From 8111fa9fcd9a9c747e1e358e8632faca02853a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 11:49:33 +0200 Subject: [PATCH 01/14] Add simple usage example --- .formatter.exs | 2 +- .gitignore | 1 + README.md | 13 +++++++++-- examples/parse_and_fill.exs | 46 +++++++++++++++++++++++++++++++++++++ lib/membrane/aac/filler.ex | 2 +- 5 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 examples/parse_and_fill.exs diff --git a/.formatter.exs b/.formatter.exs index 4c3febe..e88289c 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,6 +1,6 @@ [ inputs: [ - "{lib,test,config}/**/*.{ex,exs}", + "{lib,test,config,examples}/**/*.{ex,exs}", ".formatter.exs", "*.exs" ], diff --git a/.gitignore b/.gitignore index 94bafe2..44d62b6 100644 --- a/.gitignore +++ b/.gitignore @@ -174,4 +174,5 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk +output.aac # End of https://www.gitignore.io/api/c,vim,linux,macos,elixir,windows,visualstudiocode diff --git a/README.md b/README.md index cdee74c..e06ce41 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,19 @@ end ``` ## Usage example +You can find examples of usage in the `examples/` directory. -TODO +To see how to fill the gaps in AAC audio stream with silent frames, run: +``` +elixir examples/parse_and_fill.exs +``` + +When the script terminates, you can play the result with the following command: +``` +ffplay output.mp4 +``` -The docs can be found at [Hex Docs](https://hexdocs.pm/membrane_aac_plugin). +The documentation can be found at [Hex Docs](https://hexdocs.pm/membrane_aac_plugin). ## Copyright and License diff --git a/examples/parse_and_fill.exs b/examples/parse_and_fill.exs new file mode 100644 index 0000000..971eab1 --- /dev/null +++ b/examples/parse_and_fill.exs @@ -0,0 +1,46 @@ +Mix.install([ + :membrane_hackney_plugin, + :membrane_mp4_plugin, + :membrane_file_plugin, + {:membrane_aac_plugin, path: Path.expand("./"), override: true} +]) + +defmodule FillingWithSilencePipeline do + use Membrane.Pipeline + + alias Membrane.{AAC, File, Hackney} + + @impl true + def handle_init(_ctx, _opts) do + spec = + child(:source, %Hackney.Source{ + location: + "https://raw.githubusercontent.com/membraneframework/static/gh-pages/samples/test-audio.aac", + hackney_opts: [follow_redirect: true] + }) + |> child(:parser, %AAC.Parser{out_encapsulation: :ADTS}) + |> child(:filler, AAC.Filler) + |> child(:sink, %File.Sink{location: "output.aac"}) + + {[spec: spec], %{}} + end + + # When end of stream arrives, terminate the pipeline + @impl + def handle_element_end_of_stream(:sink, _pad, _ctx, state) do + {[terminate: :normal], state} + end + + @impl true + def handle_element_end_of_stream(_child, _pad, _ctx, state) do + {[], state} + end +end + +{:ok, _supervisor, pid} = Membrane.Pipeline.start_link(FillingWithSilencePipeline) +monitor_ref = Process.monitor(pid) + +receive do + {:DOWN, ^monitor_ref, :process, _pid, _reason} -> + :ok +end diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index 8419715..1894e43 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -70,7 +70,7 @@ defmodule Membrane.AAC.Filler do def handle_buffer(:input, buffer, _ctx, state) do use Numbers, overload_operators: true, comparison: true - %{timestamp: current_timestamp} = buffer.metadata + current_timestamp = buffer.pts %{expected_timestamp: expected_timestamp, frame_duration: frame_duration} = state expected_timestamp = expected_timestamp || current_timestamp From 490fee46384ec65cacad74c4c2291ecc9a7be6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 12:12:43 +0200 Subject: [PATCH 02/14] Adjust tests to timestamps in pts field of the buffer --- test/membrane/aac/filler_test.exs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/membrane/aac/filler_test.exs b/test/membrane/aac/filler_test.exs index 24c1f85..d100017 100644 --- a/test/membrane/aac/filler_test.exs +++ b/test/membrane/aac/filler_test.exs @@ -19,7 +19,7 @@ defmodule Membrane.AAC.FillerTest do state: state, current_timestamp: current_timestamp } do - current_buffer = %Buffer{metadata: %{timestamp: current_timestamp}, payload: ""} + current_buffer = %Buffer{pts: current_timestamp, payload: ""} assert {actions, new_state} = Filler.handle_buffer(:input, current_buffer, nil, state) @@ -35,7 +35,7 @@ defmodule Membrane.AAC.FillerTest do skipped_frames = 10 current_buffer = %Buffer{ - metadata: %{timestamp: current_timestamp + skipped_frames}, + pts: current_timestamp + skipped_frames, payload: "" } @@ -64,7 +64,7 @@ defmodule Membrane.AAC.FillerTest do |> Enum.map( &%Membrane.Buffer{ payload: &1, - metadata: %{timestamp: &1} + pts: &1 } ) @@ -118,7 +118,7 @@ defmodule Membrane.AAC.FillerTest do state = %{state | channels: channels} buffer = %Buffer{ - metadata: %{timestamp: current_timestamp + skipped_frames}, + pts: current_timestamp + skipped_frames, payload: "" } From cdf7804a03b4041e033eb6d59c398db3ad88cf6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 12:14:26 +0200 Subject: [PATCH 03/14] Use pts field in output buffer --- lib/membrane/aac/filler.ex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index 1894e43..76d886e 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -82,8 +82,7 @@ defmodule Membrane.AAC.Filler do buffers = Enum.map(silent_frames_timestamps, fn timestamp -> - %Buffer{buffer | payload: silent_frame_payload} - |> Bunch.Struct.put_in([:metadata, :timestamp], timestamp) + %Buffer{buffer | payload: silent_frame_payload, pts: timestamp} end) ++ [buffer] expected_timestamp = expected_timestamp + length(buffers) * frame_duration From e9440ccf78ab863ef461b523ac793e2c83b1da4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 12:15:43 +0200 Subject: [PATCH 04/14] Use dts if pts are missing --- lib/membrane/aac/filler.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index 76d886e..048ced0 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -70,7 +70,7 @@ defmodule Membrane.AAC.Filler do def handle_buffer(:input, buffer, _ctx, state) do use Numbers, overload_operators: true, comparison: true - current_timestamp = buffer.pts + current_timestamp = buffer.pts || buffer.dts %{expected_timestamp: expected_timestamp, frame_duration: frame_duration} = state expected_timestamp = expected_timestamp || current_timestamp @@ -82,7 +82,7 @@ defmodule Membrane.AAC.Filler do buffers = Enum.map(silent_frames_timestamps, fn timestamp -> - %Buffer{buffer | payload: silent_frame_payload, pts: timestamp} + %Buffer{buffer | payload: silent_frame_payload, pts: timestamp, dts: timestamp} end) ++ [buffer] expected_timestamp = expected_timestamp + length(buffers) * frame_duration From 04190dd99190f729252526e7efa0bc4e50fa89e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 12:16:40 +0200 Subject: [PATCH 05/14] Update credo --- mix.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mix.lock b/mix.lock index 997e5bb..23c1d2f 100644 --- a/mix.lock +++ b/mix.lock @@ -1,15 +1,15 @@ %{ "bimap": {:hex, :bimap, "1.3.0", "3ea4832e58dc83a9b5b407c6731e7bae87458aa618e6d11d8e12114a17afa4b3", [:mix], [], "hexpm", "bf5a2b078528465aa705f405a5c638becd63e41d280ada41e0f77e6d255a10b4"}, "bunch": {:hex, :bunch, "1.6.0", "4775f8cdf5e801c06beed3913b0bd53fceec9d63380cdcccbda6be125a6cfd54", [:mix], [], "hexpm", "ef4e9abf83f0299d599daed3764d19e8eac5d27a5237e5e4d5e2c129cfeb9a22"}, - "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, + "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, - "credo": {:hex, :credo, "1.7.1", "6e26bbcc9e22eefbff7e43188e69924e78818e2fe6282487d0703652bc20fd62", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "e9871c6095a4c0381c89b6aa98bc6260a8ba6addccf7f6a53da8849c748a58a2"}, + "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, "dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"}, "earmark_parser": {:hex, :earmark_parser, "1.4.38", "b42252eddf63bda05554ba8be93a1262dc0920c721f1aaf989f5de0f73a2e367", [:mix], [], "hexpm", "2cd0907795aaef0c7e8442e376633c5b3bd6edc8dbbdc539b22f095501c1cdb6"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, - "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, - "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, + "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, + "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, From 2350c1a27b913064df39c65c240d76421737153a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 16:33:56 +0200 Subject: [PATCH 06/14] Add silence filling example --- examples/parse_and_fill.exs | 39 ++++++++++++++++++++++++++++++++++++- lib/membrane/aac/filler.ex | 13 ++++++++++--- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/examples/parse_and_fill.exs b/examples/parse_and_fill.exs index 971eab1..fb3f7a8 100644 --- a/examples/parse_and_fill.exs +++ b/examples/parse_and_fill.exs @@ -5,6 +5,40 @@ Mix.install([ {:membrane_aac_plugin, path: Path.expand("./"), override: true} ]) +defmodule TimestampsGapGenerator do + use Membrane.Filter + + def_input_pad :input, accepted_format: _any + def_output_pad :output, accepted_format: _any + + def_options gap_duration: [ + spec: Membrane.Time.t(), + default: Membrane.Time.seconds(5), + description: """ + Specifies the duration of the timestamps gap. + """ + ], + gap_start_time: [ + spec: Membrane.Time.t(), + default: Membrane.Time.seconds(0), + description: """ + Specifies when the timestamps gap should start. + """ + ] + + @impl true + def handle_buffer(:input, buffer, _ctx, state) do + buffer = + if buffer.pts > state.gap_start_time do + %{buffer | pts: buffer.pts + state.gap_duration} + else + buffer + end + + {[buffer: {:output, buffer}], state} + end +end + defmodule FillingWithSilencePipeline do use Membrane.Pipeline @@ -12,14 +46,17 @@ defmodule FillingWithSilencePipeline do @impl true def handle_init(_ctx, _opts) do + # child(%File.Source{location: "out.aac"}) spec = child(:source, %Hackney.Source{ location: "https://raw.githubusercontent.com/membraneframework/static/gh-pages/samples/test-audio.aac", hackney_opts: [follow_redirect: true] }) - |> child(:parser, %AAC.Parser{out_encapsulation: :ADTS}) + |> child(:parser, %AAC.Parser{out_encapsulation: :none}) + |> child(:timestamps_gap_generator, TimestampsGapGenerator) |> child(:filler, AAC.Filler) + |> child(:parser2, %AAC.Parser{out_encapsulation: :ADTS}) |> child(:sink, %File.Sink{location: "output.aac"}) {[spec: spec], %{}} diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index 048ced0..da6fa78 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -7,7 +7,7 @@ defmodule Membrane.AAC.Filler do # Silence frame per channel configuration @silent_frames %{ - 1 => <<222, 2, 0, 76, 97, 118, 99, 53, 56, 46, 53, 52, 46, 49, 48, 48, 0, 2, 48, 64, 14>>, + 1 => <<222, 2, 0, 76, 97, 118, 99, 54, 48, 46, 51, 49, 46, 49, 48, 50, 0, 2, 48, 64, 14>>, 2 => <<255, 241, 80, 128, 3, 223, 252, 222, 2, 0, 76, 97, 118, 99, 53, 56, 46, 57, 49, 46, 49, 48, 48, 0, 66, 32, 8, 193, 24, 56>> @@ -60,7 +60,9 @@ defmodule Membrane.AAC.Filler do @impl true def handle_stream_format(:input, stream_format, _ctx, state) do - new_duration = stream_format.samples_per_frame / stream_format.sample_rate * Time.second() + new_duration = + stream_format.samples_per_frame / stream_format.sample_rate * Time.second() + state = %State{state | frame_duration: new_duration, channels: stream_format.channels} {[forward: stream_format], state} @@ -82,7 +84,12 @@ defmodule Membrane.AAC.Filler do buffers = Enum.map(silent_frames_timestamps, fn timestamp -> - %Buffer{buffer | payload: silent_frame_payload, pts: timestamp, dts: timestamp} + %Buffer{ + buffer + | payload: silent_frame_payload, + pts: round(timestamp), + dts: round(timestamp) + } end) ++ [buffer] expected_timestamp = expected_timestamp + length(buffers) * frame_duration From 481e5dda7acfb44a1e23b1dc6e5cff1f1ff58faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 16:40:03 +0200 Subject: [PATCH 07/14] Remove parse_and_fill example. Add parsing and MP4 payloading example --- .gitignore | 2 +- README.md | 6 +++--- .../{parse_and_fill.exs => parse_and_put_in_mp4.exs} | 12 ++++-------- 3 files changed, 8 insertions(+), 12 deletions(-) rename examples/{parse_and_fill.exs => parse_and_put_in_mp4.exs} (83%) diff --git a/.gitignore b/.gitignore index 44d62b6..54358c6 100644 --- a/.gitignore +++ b/.gitignore @@ -174,5 +174,5 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk -output.aac +output.mp4 # End of https://www.gitignore.io/api/c,vim,linux,macos,elixir,windows,visualstudiocode diff --git a/README.md b/README.md index e06ce41..cc7f831 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,12 @@ end ## Usage example You can find examples of usage in the `examples/` directory. -To see how to fill the gaps in AAC audio stream with silent frames, run: +To see how the parser can be used to payload AAC stream so that it can be put in the MP4 container, run: ``` -elixir examples/parse_and_fill.exs +elixir examples/add_and_put_in_mp4.exs ``` -When the script terminates, you can play the result with the following command: +When the script terminates, you can play the result .mp4 file with the following command: ``` ffplay output.mp4 ``` diff --git a/examples/parse_and_fill.exs b/examples/parse_and_put_in_mp4.exs similarity index 83% rename from examples/parse_and_fill.exs rename to examples/parse_and_put_in_mp4.exs index fb3f7a8..ceb568d 100644 --- a/examples/parse_and_fill.exs +++ b/examples/parse_and_put_in_mp4.exs @@ -26,7 +26,6 @@ defmodule TimestampsGapGenerator do """ ] - @impl true def handle_buffer(:input, buffer, _ctx, state) do buffer = if buffer.pts > state.gap_start_time do @@ -42,22 +41,19 @@ end defmodule FillingWithSilencePipeline do use Membrane.Pipeline - alias Membrane.{AAC, File, Hackney} + alias Membrane.{AAC, File, Hackney, MP4} @impl true def handle_init(_ctx, _opts) do - # child(%File.Source{location: "out.aac"}) spec = child(:source, %Hackney.Source{ location: "https://raw.githubusercontent.com/membraneframework/static/gh-pages/samples/test-audio.aac", hackney_opts: [follow_redirect: true] }) - |> child(:parser, %AAC.Parser{out_encapsulation: :none}) - |> child(:timestamps_gap_generator, TimestampsGapGenerator) - |> child(:filler, AAC.Filler) - |> child(:parser2, %AAC.Parser{out_encapsulation: :ADTS}) - |> child(:sink, %File.Sink{location: "output.aac"}) + |> child(:parser, %AAC.Parser{out_encapsulation: :none, output_config: :esds}) + |> child(:muxer, %Membrane.MP4.Muxer.ISOM{}) + |> child(:sink, %File.Sink{location: "output.mp4"}) {[spec: spec], %{}} end From 3f700da779812dd332523734bc655e3af75a0cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 16:55:08 +0200 Subject: [PATCH 08/14] Deprecate Filler --- lib/membrane/aac/filler.ex | 11 +++++++++++ mix.lock | 10 +++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index da6fa78..4c4a1f7 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -1,9 +1,14 @@ defmodule Membrane.AAC.Filler do @moduledoc """ + ** Warning: This element is deprecated. ** + + ** Please use `Membrane.AudioFiller` from the `:membrane_audio_filler_plugin` to fill gaps in raw audio stream with silence. ** + Element that fills gaps in AAC stream with silent frames. """ use Membrane.Filter alias Membrane.{Buffer, Time} + require Membrane.Logger # Silence frame per channel configuration @silent_frames %{ @@ -46,10 +51,16 @@ defmodule Membrane.AAC.Filler do Returns a silent AAC frame that this element uses to fill gaps in the stream. """ @spec silent_frame(integer()) :: binary() + @deprecated "This function is no longer supported" def silent_frame(channels), do: Map.fetch!(@silent_frames, channels) @impl true def handle_init(_ctx, _opts) do + Membrane.Logger.warning(""" + `#{__MODULE__}` element is deprecated now. + Please use `Membrane.AudioFiller` from the `:membrane_audio_filler_plugin` to fill gaps in raw audio stream with silence. + """) + {[], %State{frame_duration: nil}} end diff --git a/mix.lock b/mix.lock index 23c1d2f..1ba9389 100644 --- a/mix.lock +++ b/mix.lock @@ -5,14 +5,14 @@ "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, "dialyxir": {:hex, :dialyxir, "1.4.2", "764a6e8e7a354f0ba95d58418178d486065ead1f69ad89782817c296d0d746a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "516603d8067b2fd585319e4b13d3674ad4f314a5902ba8130cd97dc902ce6bbd"}, - "earmark_parser": {:hex, :earmark_parser, "1.4.38", "b42252eddf63bda05554ba8be93a1262dc0920c721f1aaf989f5de0f73a2e367", [:mix], [], "hexpm", "2cd0907795aaef0c7e8442e376633c5b3bd6edc8dbbdc539b22f095501c1cdb6"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, - "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, + "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"}, "file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, - "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, - "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, + "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, + "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"}, "membrane_aac_format": {:hex, :membrane_aac_format, "0.8.0", "515631eabd6e584e0e9af2cea80471fee6246484dbbefc4726c1d93ece8e0838", [:mix], [{:bimap, "~> 1.1", [hex: :bimap, repo: "hexpm", optional: false]}], "hexpm", "a30176a94491033ed32be45e51d509fc70a5ee6e751f12fd6c0d60bd637013f6"}, "membrane_core": {:hex, :membrane_core, "1.0.0", "1b543aefd952283be1f2a215a1db213aa4d91222722ba03cd35280622f1905ee", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 3.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "352c90fd0a29942143c4bf7a727cc05c632e323f50a1a4e99321b1e8982f1533"}, "membrane_file_plugin": {:hex, :membrane_file_plugin, "0.16.0", "7917f6682c22b9bcfc2ca20ed960eee0f7d03ad31fd5f59ed850f1fe3ddd545a", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "b0727998f75a9b4dab8a2baefdfc13c3eac00a04e061ab1b0e61dc5566927acc"}, From fe08e78457a44c4607f0e6728b11bc819dc4a45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 16:57:41 +0200 Subject: [PATCH 09/14] Remove unused code from the example --- examples/parse_and_put_in_mp4.exs | 39 +++---------------------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/examples/parse_and_put_in_mp4.exs b/examples/parse_and_put_in_mp4.exs index ceb568d..8ed7c2b 100644 --- a/examples/parse_and_put_in_mp4.exs +++ b/examples/parse_and_put_in_mp4.exs @@ -5,40 +5,7 @@ Mix.install([ {:membrane_aac_plugin, path: Path.expand("./"), override: true} ]) -defmodule TimestampsGapGenerator do - use Membrane.Filter - - def_input_pad :input, accepted_format: _any - def_output_pad :output, accepted_format: _any - - def_options gap_duration: [ - spec: Membrane.Time.t(), - default: Membrane.Time.seconds(5), - description: """ - Specifies the duration of the timestamps gap. - """ - ], - gap_start_time: [ - spec: Membrane.Time.t(), - default: Membrane.Time.seconds(0), - description: """ - Specifies when the timestamps gap should start. - """ - ] - - def handle_buffer(:input, buffer, _ctx, state) do - buffer = - if buffer.pts > state.gap_start_time do - %{buffer | pts: buffer.pts + state.gap_duration} - else - buffer - end - - {[buffer: {:output, buffer}], state} - end -end - -defmodule FillingWithSilencePipeline do +defmodule MP4MuxingPipeline do use Membrane.Pipeline alias Membrane.{AAC, File, Hackney, MP4} @@ -52,7 +19,7 @@ defmodule FillingWithSilencePipeline do hackney_opts: [follow_redirect: true] }) |> child(:parser, %AAC.Parser{out_encapsulation: :none, output_config: :esds}) - |> child(:muxer, %Membrane.MP4.Muxer.ISOM{}) + |> child(:muxer, %MP4.Muxer.ISOM{}) |> child(:sink, %File.Sink{location: "output.mp4"}) {[spec: spec], %{}} @@ -70,7 +37,7 @@ defmodule FillingWithSilencePipeline do end end -{:ok, _supervisor, pid} = Membrane.Pipeline.start_link(FillingWithSilencePipeline) +{:ok, _supervisor, pid} = Membrane.Pipeline.start_link(MP4MuxingPipeline) monitor_ref = Process.monitor(pid) receive do From 553d90718ff897e29f0bd52c0b0e3940e928b111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 16:58:16 +0200 Subject: [PATCH 10/14] Bump to v0.18.2 --- README.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cc7f831..8035099 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ The package can be installed by adding `membrane_aac_plugin` to your list of dep ```elixir def deps do [ - {:membrane_aac_plugin, "~> 0.18.1"} + {:membrane_aac_plugin, "~> 0.18.2"} ] end ``` diff --git a/mix.exs b/mix.exs index 99ad6b3..2375fad 100644 --- a/mix.exs +++ b/mix.exs @@ -1,7 +1,7 @@ defmodule Membrane.AAC.MixProject do use Mix.Project - @version "0.18.1" + @version "0.18.2" @github_url "https://github.com/membraneframework/membrane_aac_plugin" def project do From e906435ec1a7e2596141343f4cdfc80404bb2ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 16:59:44 +0200 Subject: [PATCH 11/14] Fix credo warning --- lib/membrane/aac/filler.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index 4c4a1f7..6796921 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -7,8 +7,8 @@ defmodule Membrane.AAC.Filler do Element that fills gaps in AAC stream with silent frames. """ use Membrane.Filter - alias Membrane.{Buffer, Time} require Membrane.Logger + alias Membrane.{Buffer, Time} # Silence frame per channel configuration @silent_frames %{ From 1fca7ca81d6e3cfa8b28be0813764e6884cfb2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Thu, 19 Sep 2024 17:00:40 +0200 Subject: [PATCH 12/14] Remove deprecation of the silent_frame/1 function --- lib/membrane/aac/filler.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index 6796921..52dbd40 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -51,7 +51,6 @@ defmodule Membrane.AAC.Filler do Returns a silent AAC frame that this element uses to fill gaps in the stream. """ @spec silent_frame(integer()) :: binary() - @deprecated "This function is no longer supported" def silent_frame(channels), do: Map.fetch!(@silent_frames, channels) @impl true From beeaba8e2f66988331eec2a27bb552f9fe0a3c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Fri, 20 Sep 2024 16:41:50 +0200 Subject: [PATCH 13/14] Update lib/membrane/aac/filler.ex Co-authored-by: Mateusz Front --- lib/membrane/aac/filler.ex | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index 52dbd40..3e795e6 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -1,8 +1,6 @@ defmodule Membrane.AAC.Filler do + @moduledoc deprecated: "Please use `Membrane.AudioFiller` from the `:membrane_audio_filler_plugin` to fill gaps in raw audio stream with silence." @moduledoc """ - ** Warning: This element is deprecated. ** - - ** Please use `Membrane.AudioFiller` from the `:membrane_audio_filler_plugin` to fill gaps in raw audio stream with silence. ** Element that fills gaps in AAC stream with silent frames. """ From 8c28ed71ff3969713ad3e9dc551b253580b19390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Kita?= Date: Fri, 20 Sep 2024 17:08:42 +0200 Subject: [PATCH 14/14] Perform formatting --- lib/membrane/aac/filler.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/membrane/aac/filler.ex b/lib/membrane/aac/filler.ex index 3e795e6..539e702 100644 --- a/lib/membrane/aac/filler.ex +++ b/lib/membrane/aac/filler.ex @@ -1,5 +1,6 @@ defmodule Membrane.AAC.Filler do - @moduledoc deprecated: "Please use `Membrane.AudioFiller` from the `:membrane_audio_filler_plugin` to fill gaps in raw audio stream with silence." + @moduledoc deprecated: + "Please use `Membrane.AudioFiller` from the `:membrane_audio_filler_plugin` to fill gaps in raw audio stream with silence." @moduledoc """ Element that fills gaps in AAC stream with silent frames.