Skip to content

Commit

Permalink
Support AVC3 (#113)
Browse files Browse the repository at this point in the history
* support AVC3

* address CR

* Update lib/membrane_mp4/muxer/isom.ex

Co-authored-by: Łukasz Kita <[email protected]>

* bump version

---------

Co-authored-by: Łukasz Kita <[email protected]>
  • Loading branch information
mat-hek and varsill authored Aug 22, 2024
1 parent 235566f commit 2c439e6
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 40 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The package can be installed by adding `membrane_mp4_plugin` to your list of dep
```elixir
defp deps do
[
{:membrane_mp4_plugin, "~> 0.35.1"}
{:membrane_mp4_plugin, "~> 0.35.2"}
]
end
```
Expand Down
2 changes: 1 addition & 1 deletion lib/membrane_mp4/demuxer/isom.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ defmodule Membrane.MP4.Demuxer.ISOM do
any_of(
%Membrane.AAC{config: {:esds, _esds}},
%Membrane.H264{
stream_structure: {:avc1, _dcr},
stream_structure: {_avc, _dcr},
alignment: :au
},
%Membrane.H265{
Expand Down
33 changes: 23 additions & 10 deletions lib/membrane_mp4/muxer/isom.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ defmodule Membrane.MP4.Muxer.ISOM do
any_of(
%Membrane.AAC{config: {:esds, _esds}},
%Membrane.H264{
stream_structure: {:avc1, _dcr},
stream_structure: {_avc, _dcr},
alignment: :au
},
%Membrane.H265{
Expand Down Expand Up @@ -100,21 +100,34 @@ defmodule Membrane.MP4.Muxer.ISOM do
ctx,
state
) do
cond do
case {ctx.pads[pad].stream_format, stream_format} do
# Handle receiving the first stream format on the given pad
is_nil(ctx.pads[pad].stream_format) ->
{nil, new_format} ->
update_in(state, [:pad_to_track, pad_ref], fn track_id ->
Track.new(track_id, stream_format, state.chunk_duration)
Track.new(track_id, new_format, state.chunk_duration)
end)

# Handle receiving all but the first stream format on the given pad,
# when stream format is duplicated - ignore
ctx.pads[pad].stream_format == stream_format ->
# If the stream format is identical or remains H264 AVC3 or H265 HEV1,
# we can be reasonably sure that the stream can still be appended
# to the same MP4
{stream_format, stream_format} ->
state

# otherwise we can assume that output will be corrupted
true ->
raise "ISOM Muxer doesn't support variable parameters"
{%Membrane.H264{stream_structure: {:avc3, _dcr1}},
%Membrane.H264{stream_structure: {:avc3, _dcr2}}} ->
state

{%Membrane.H265{stream_structure: {:hev1, _dcr1}},
%Membrane.H265{stream_structure: {:hev1, _dcr2}}} ->
state

# Otherwise we can assume that output will be corrupted
{prev_format, new_format} ->
raise """
Unsupported stream_format change on pad #{inspect(pad_ref)}, \
previous format: #{inspect(prev_format)}
new format: #{inspect(new_format)}
"""
end
|> then(&{[], &1})
end
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Membrane.MP4.Plugin.MixProject do
use Mix.Project

@version "0.35.1"
@version "0.35.2"
@github_url "https://github.com/membraneframework/membrane_mp4_plugin"

def project do
Expand Down
Binary file added test/fixtures/isom/ref_video_vp.mp4
Binary file not shown.
45 changes: 18 additions & 27 deletions test/membrane_mp4/muxer/isom/integration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,24 @@ defmodule Membrane.MP4.Muxer.ISOM.IntegrationTest do
perform_test(pid, "video")
end

test "variable parameters H264 track" do
prepare_test("video")

structure = [
child(:file, %Membrane.File.Source{location: "test/fixtures/in_video_vp.h264"})
|> child(:parser, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {30, 1}},
output_stream_structure: :avc3
})
|> child(:muxer, %Membrane.MP4.Muxer.ISOM{chunk_duration: Time.seconds(1)})
|> child(:sink, %Membrane.File.Sink{location: out_path_for("video_vp")})
]

pid = Pipeline.start_link_supervised!(spec: structure)

perform_test(pid, "video_vp")
end

test "single H265 track" do
prepare_test("video_hevc")

Expand Down Expand Up @@ -211,33 +229,6 @@ defmodule Membrane.MP4.Muxer.ISOM.IntegrationTest do
end
end

describe "When fed a variable parameter h264 stream, Muxer.ISOM should" do
test "raise when stream format's inband_parameters are not used" do
structure = [
child(:file, %Membrane.File.Source{location: "test/fixtures/in_video_vp.h264"})
|> child(:parser, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {30, 1}},
output_stream_structure: :avc1
})
|> child(:muxer, %Membrane.MP4.Muxer.ISOM{
chunk_duration: Time.seconds(1),
fast_start: true
})
|> child(:sink, Membrane.Fake.Sink.Buffers)
]

{:ok, _supervisor_pid, pid} = Pipeline.start(spec: structure)
monitor_ref = Process.monitor(pid)

assert_receive {:DOWN, ^monitor_ref, :process, ^pid,
{:membrane_child_crash, :muxer,
{%RuntimeError{
message: "ISOM Muxer doesn't support variable parameters"
}, _stacktrace}}},
1_000
end
end

describe "ctts table" do
test "should not be stored when dts and pts values are equal" do
prepare_test("video")
Expand Down

0 comments on commit 2c439e6

Please sign in to comment.