Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release membrane_h264_plugin v0.9.0 #52

Merged
merged 5 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The package can be installed by adding `membrane_h264_plugin` to your list of de
```elixir
def deps do
[
{:membrane_h264_plugin, "~> 0.8.1"}
{:membrane_h264_plugin, "~> 0.9.0"}
]
end
```
Expand All @@ -39,13 +39,13 @@ defmodule Decoding.Pipeline do

@impl true
def handle_init(_ctx, _opts) do
structure =
spec =
child(:source, %File.Source{location: "test/fixtures/input-10-720p-main.h264"})
|> child(:parser, H264.Parser)
|> child(:decoder, H264.FFmpeg.Decoder)
|> child(:sink, %File.Sink{location: "output.raw"})

{[spec: structure], nil}
{[spec: spec], nil}
end

@impl true
Expand Down
7 changes: 3 additions & 4 deletions lib/membrane_h264_plugin/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,11 @@ defmodule Membrane.H264.Parser do
@nalu_length_size 4

def_input_pad :input,
demand_unit: :buffers,
demand_mode: :auto,
flow_control: :auto,
accepted_format: any_of(%RemoteStream{type: :bytestream}, H264)

def_output_pad :output,
demand_mode: :auto,
flow_control: :auto,
accepted_format:
%H264{alignment: alignment, nalu_in_metadata?: true} when alignment in [:nalu, :au]

Expand Down Expand Up @@ -277,7 +276,7 @@ defmodule Membrane.H264.Parser do
end

@impl true
def handle_process(:input, %Membrane.Buffer{} = buffer, ctx, state) do
def handle_buffer(:input, %Membrane.Buffer{} = buffer, ctx, state) do
{payload, state} =
case state.frame_prefix do
<<>> -> {buffer.payload, state}
Expand Down
8 changes: 4 additions & 4 deletions mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Membrane.H264.Plugin.Mixfile do
use Mix.Project

@version "0.8.1"
@version "0.9.0"
@github_url "https://github.com/membraneframework-labs/membrane_h264_plugin"

def project do
Expand Down Expand Up @@ -37,11 +37,11 @@ defmodule Membrane.H264.Plugin.Mixfile do

defp deps do
[
{:membrane_core, "~> 0.12.7"},
{:membrane_core, "~> 1.0"},
{:membrane_h264_format, "~> 0.6.0"},
{:bunch, "~> 1.4"},
{:membrane_stream_plugin, "~> 0.3.1", only: :test},
{:membrane_file_plugin, "~> 0.14.0", only: :test},
{:membrane_stream_plugin, "~> 0.4.0", only: :test},
{:membrane_file_plugin, "~> 0.16.0", only: :test},
{:ex_doc, ">= 0.0.0", only: :dev, runtime: false},
{:dialyxir, ">= 0.0.0", only: :dev, runtime: false},
{:credo, ">= 0.0.0", only: :dev, runtime: false}
Expand Down
8 changes: 4 additions & 4 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
"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"},
"membrane_core": {:hex, :membrane_core, "0.12.9", "b80239deacf98f24cfd2e0703b632e92ddded8b989227cd6e724140f433b0aac", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "389b4b22da0e35d5b053ec2fa87bf36882e0ab88f8fb841af895982fb4abe504"},
"membrane_file_plugin": {:hex, :membrane_file_plugin, "0.14.0", "87f19f5f5afbfbaf2219b8f1d8496534cb9ad01fca74687910bf3f7aa866e244", [:mix], [{:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "28956f8d5d87735d499c57f1c24f62aeab71e0211863759e7e695ead966eb433"},
"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"},
"membrane_h264_format": {:hex, :membrane_h264_format, "0.6.1", "44836cd9de0abe989b146df1e114507787efc0cf0da2368f17a10c47b4e0738c", [:mix], [], "hexpm", "4b79be56465a876d2eac2c3af99e115374bbdc03eb1dea4f696ee9a8033cd4b0"},
"membrane_stream_plugin": {:hex, :membrane_stream_plugin, "0.3.1", "265f327dad815a8ef18f8872bdebc6c1aa1fea3d059446c937b76ff067c166e6", [:mix], [{:membrane_core, "~> 0.12.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "b504296b9f5a78b43c0d46ad66202a1f0f93d4c122949c27ad4c04f67f3c5907"},
"membrane_stream_plugin": {:hex, :membrane_stream_plugin, "0.4.0", "0c4ab72a4e13bf0faa0f1166fbaf68d2e34167dbec345aedb74ce1eb7497bdda", [:mix], [{:membrane_core, "~> 1.0", [hex: :membrane_core, repo: "hexpm", optional: false]}], "hexpm", "5a9a9c17783e18ad740e6ddfed364581bdb7ebdab8e61ba2c19a1830356f7eb8"},
"nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"},
"numbers": {:hex, :numbers, "5.2.4", "f123d5bb7f6acc366f8f445e10a32bd403c8469bdbce8ce049e1f0972b607080", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "eeccf5c61d5f4922198395bf87a465b6f980b8b862dd22d28198c5e6fab38582"},
"qex": {:hex, :qex, "0.5.1", "0d82c0f008551d24fffb99d97f8299afcb8ea9cf99582b770bd004ed5af63fd6", [:mix], [], "hexpm", "935a39fdaf2445834b95951456559e9dc2063d0a055742c558a99987b38d6bab"},
"ratio": {:hex, :ratio, "2.4.2", "c8518f3536d49b1b00d88dd20d49f8b11abb7819638093314a6348139f14f9f9", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "441ef6f73172a3503de65ccf1769030997b0d533b1039422f1e5e0e0b4cbf89e"},
"ratio": {:hex, :ratio, "3.0.2", "60a5976872a4dc3d873ecc57eed1738589e99d1094834b9c935b118231297cfb", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "3a13ed5a30ad0bfd7e4a86bf86d93d2b5a06f5904417d38d3f3ea6406cdfc7bb"},
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
}
24 changes: 12 additions & 12 deletions test/integration/modes_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ defmodule Membrane.H264.ModesTest do

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
structure: [
spec: [
child(:source, %TestSource{mode: mode})
|> child(:parser, Parser)
|> child(:sink, Sink)
]
)

assert_pipeline_play(pid)
assert_sink_playing(pid, :sink)
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

Expand All @@ -37,7 +37,7 @@ defmodule Membrane.H264.ModesTest do
assert_sink_buffer(pid, :sink, %Buffer{payload: ^payload, pts: nil, dts: nil})
end)

Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end

test "if the pts and dts are rewritten properly in :nalu_aligned mode" do
Expand All @@ -47,14 +47,14 @@ defmodule Membrane.H264.ModesTest do

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
structure: [
spec: [
child(:source, %TestSource{mode: mode})
|> child(:parser, Parser)
|> child(:sink, Sink)
]
)

assert_pipeline_play(pid)
assert_sink_playing(pid, :sink)
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

Expand All @@ -67,7 +67,7 @@ defmodule Membrane.H264.ModesTest do
assert_sink_buffer(pid, :sink, %Buffer{payload: ^payload, pts: ^pts, dts: ^dts})
end)

Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end

test "if the pts and dts are rewritten properly in :au_aligned mode" do
Expand All @@ -77,14 +77,14 @@ defmodule Membrane.H264.ModesTest do

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
structure: [
spec: [
child(:source, %TestSource{mode: mode})
|> child(:parser, Parser)
|> child(:sink, Sink)
]
)

assert_pipeline_play(pid)
assert_sink_playing(pid, :sink)
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

Expand All @@ -97,20 +97,20 @@ defmodule Membrane.H264.ModesTest do
assert dts == buf.dts
end)

Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end

test "if single NAL unit is sent per buffer with `output_alignment: :nalu`" do
{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
structure: [
spec: [
child(:source, %Membrane.File.Source{location: @h264_input_file})
|> child(:parser, %Parser{output_alignment: :nalu})
|> child(:sink, Sink)
]
)

assert_pipeline_play(pid)
assert_sink_playing(pid, :sink)
assert_sink_stream_format(pid, :sink, %Membrane.H264{alignment: :nalu})

binary = File.read!(@h264_input_file)
Expand All @@ -123,6 +123,6 @@ defmodule Membrane.H264.ModesTest do
end)

assert_end_of_stream(pid, :sink)
Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end
end
12 changes: 6 additions & 6 deletions test/integration/timestamp_generation_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ defmodule Membrane.H264.TimestampGenerationTest do

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
structure: [
spec: [
child(:source, %TestSource{mode: mode})
|> child(:parser, Parser)
|> child(:sink, Sink)
]
)

assert_pipeline_play(pid)
assert_sink_playing(pid, :sink)
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

Expand All @@ -71,7 +71,7 @@ defmodule Membrane.H264.TimestampGenerationTest do
assert_sink_buffer(pid, :sink, %Buffer{payload: ^payload, pts: nil, dts: nil})
end)

Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end

Enum.map(
Expand All @@ -93,7 +93,7 @@ defmodule Membrane.H264.TimestampGenerationTest do

{:ok, _supervisor_pid, pid} =
Pipeline.start_supervised(
structure: [
spec: [
child(:source, %TestSource{mode: mode})
|> child(:parser, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: framerate}
Expand All @@ -102,7 +102,7 @@ defmodule Membrane.H264.TimestampGenerationTest do
]
)

assert_pipeline_play(pid)
assert_sink_playing(pid, :sink)
send_buffers_actions = for buffer <- input_buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, send_buffers_actions ++ [end_of_stream: :output])

Expand All @@ -118,7 +118,7 @@ defmodule Membrane.H264.TimestampGenerationTest do
Membrane.Time.as_milliseconds(dts, :round)}
end)

Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end
end
)
Expand Down
7 changes: 3 additions & 4 deletions test/parser/process_all_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,20 @@ defmodule Membrane.H264.ProcessAllTest do
@prefix <<1::32>>

defp make_pipeline(in_path, out_path, spss, ppss) do
structure = [
spec = [
child(:file_src, %Membrane.File.Source{chunk_size: 40_960, location: in_path})
|> child(:parser, %H264.Parser{spss: spss, ppss: ppss})
|> child(:sink, %Membrane.File.Sink{location: out_path})
]

Pipeline.start_link_supervised(structure: structure)
Pipeline.start_link_supervised(spec: spec)
end

defp perform_test(filename, tmp_dir, timeout, spss \\ [], ppss \\ []) do
in_path = "../fixtures/input-#{filename}.h264" |> Path.expand(__DIR__)
out_path = Path.join(tmp_dir, "output-all-#{filename}.h264")

assert {:ok, _supervisor_pid, pid} = make_pipeline(in_path, out_path, spss, ppss)
assert_pipeline_play(pid)
assert_end_of_stream(pid, :sink, :input, timeout)

expected =
Expand All @@ -36,7 +35,7 @@ defmodule Membrane.H264.ProcessAllTest do

assert File.read!(out_path) == expected

Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end

describe "ProcessAllPipeline should" do
Expand Down
12 changes: 6 additions & 6 deletions test/parser/repeat_parameter_sets_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ defmodule Membrane.H264.RepeatParameterSetsTest do
34, 192>>

defp make_pipeline(source, spss \\ [], ppss \\ [], output_stream_structure \\ :annexb) do
structure =
spec =
child(:source, source)
|> child(:parser, %H264.Parser{
spss: spss,
Expand All @@ -32,7 +32,7 @@ defmodule Membrane.H264.RepeatParameterSetsTest do
})
|> child(:sink, Sink)

Pipeline.start_link_supervised!(structure: structure)
Pipeline.start_link_supervised!(spec: spec)
end

defp perform_test(
Expand All @@ -44,7 +44,7 @@ defmodule Membrane.H264.RepeatParameterSetsTest do
) do
buffers = prepare_buffers(data, mode, parser_input_stream_structure)

assert_pipeline_play(pipeline_pid)
assert_sink_playing(pipeline_pid, :sink)
actions = for buffer <- buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pipeline_pid, :source, actions ++ [end_of_stream: :output])

Expand All @@ -61,7 +61,7 @@ defmodule Membrane.H264.RepeatParameterSetsTest do
end)

assert_end_of_stream(pipeline_pid, :sink, :input, 3_000)
Pipeline.terminate(pipeline_pid, blocking?: true)
Pipeline.terminate(pipeline_pid)
end

defp split_access_unit(access_unit) do
Expand Down Expand Up @@ -103,7 +103,7 @@ defmodule Membrane.H264.RepeatParameterSetsTest do

buffers = prepare_buffers(File.read!(in_path), :bytestream)

assert_pipeline_play(pid)
assert_sink_playing(pid, :sink)
actions = for buffer <- buffers, do: {:buffer, {:output, buffer}}
Pipeline.message_child(pid, :source, actions ++ [end_of_stream: :output])

Expand All @@ -115,7 +115,7 @@ defmodule Membrane.H264.RepeatParameterSetsTest do
end)

assert_end_of_stream(pid, :sink, :input, 3_000)
Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end
end
end
16 changes: 6 additions & 10 deletions test/parser/skip_until_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ defmodule Membrane.H264.SkipUntilTest do
alias Membrane.Testing.Pipeline

defp make_pipeline(in_path, out_path, skip_until_keyframe) do
structure = [
spec = [
child(:file_src, %Membrane.File.Source{chunk_size: 40_960, location: in_path})
|> child(:parser, %H264.Parser{skip_until_keyframe: skip_until_keyframe})
|> child(:sink, %Membrane.File.Sink{location: out_path})
]

Pipeline.start_link_supervised(structure: structure)
Pipeline.start_link_supervised(spec: spec)
end

describe "The parser should" do
Expand All @@ -26,11 +26,10 @@ defmodule Membrane.H264.SkipUntilTest do
out_path = Path.join(ctx.tmp_dir, "output-all-#{filename}.h264")

assert {:ok, _supervisor_pid, pid} = make_pipeline(in_path, out_path, false)
assert_pipeline_play(pid)
assert_end_of_stream(pid, :parser)
refute_sink_buffer(pid, :sink, _, 500)

Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end

test "skip until AU with IDR frame is provided, when `skip_until_keyframe: true`", ctx do
Expand All @@ -39,10 +38,9 @@ defmodule Membrane.H264.SkipUntilTest do
out_path = Path.join(ctx.tmp_dir, "output-#{filename}.h264")
ref_path = "test/fixtures/reference-#{filename}.h264"
assert {:ok, _supervisor_pid, pid} = make_pipeline(in_path, out_path, true)
assert_pipeline_play(pid)
assert_end_of_stream(pid, :sink)
assert File.read(out_path) == File.read(ref_path)
Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end

test "skip until AU with parameters is provided, no matter if it contains keyframe, when `skip_until_keyframe: false`",
Expand All @@ -52,10 +50,9 @@ defmodule Membrane.H264.SkipUntilTest do
out_path = Path.join(ctx.tmp_dir, "output-#{filename}.h264")
ref_path = "test/fixtures/reference-#{filename}.h264"
assert {:ok, _supervisor_pid, pid} = make_pipeline(in_path, out_path, false)
assert_pipeline_play(pid)
assert_end_of_stream(pid, :sink)
assert File.read(out_path) == File.read(ref_path)
Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end

test "skip until AU with parameters and IDR is provided, when `skip_until_keyframe: true`",
Expand All @@ -64,10 +61,9 @@ defmodule Membrane.H264.SkipUntilTest do
in_path = "../fixtures/input-#{filename}.h264" |> Path.expand(__DIR__)
out_path = Path.join(ctx.tmp_dir, "output-#{filename}.h264")
assert {:ok, _supervisor_pid, pid} = make_pipeline(in_path, out_path, true)
assert_pipeline_play(pid)
assert_end_of_stream(pid, :parser)
refute_sink_buffer(pid, :sink, _, 500)
Pipeline.terminate(pid, blocking?: true)
Pipeline.terminate(pid)
end
end
end
Loading