Skip to content

Commit

Permalink
store ctts table on muxing
Browse files Browse the repository at this point in the history
  • Loading branch information
gBillal committed Jul 8, 2024
1 parent 72d38a0 commit a773a85
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 5 deletions.
2 changes: 1 addition & 1 deletion lib/membrane_mp4/demuxer/isom/samples_info.ex
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ defmodule Membrane.MP4.Demuxer.ISOM.SamplesInfo do
{dts, pts} =
case samples_info.last_dts[track_id] do
nil ->
{0, 0}
{0, scalify(sample_composition_offset, timescale)}

last_dts ->
{last_dts + scalify(delta, timescale),
Expand Down
28 changes: 28 additions & 0 deletions lib/membrane_mp4/movie_box/sample_table_box.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ defmodule Membrane.MP4.MovieBox.SampleTableBox do
}
}
] ++
maybe_sample_composition_offsets(table) ++
maybe_sample_sync ++
[
stsc: %{
Expand Down Expand Up @@ -197,6 +198,33 @@ defmodule Membrane.MP4.MovieBox.SampleTableBox do
%{sample_count: count, sample_delta: Helper.timescalify(delta, timescale)}
end)

defp maybe_sample_composition_offsets(%{composition_offsets: []}), do: []

defp maybe_sample_composition_offsets(%{composition_offsets: [%{sample_composition_offset: 0}]}),
do: []

defp maybe_sample_composition_offsets(%{
timescale: timescale,
composition_offsets: composition_offsets
}) do
composition_offsets
|> Enum.map(fn %{sample_count: count, sample_composition_offset: offset} ->
%{sample_count: count, sample_composition_offset: Helper.timescalify(offset, timescale)}
end)
|> then(
&[
ctts: %{
fields: %{
version: 0,
flags: 0,
entry_count: length(&1),
entry_list: &1
}
}
]
)
end

defp maybe_sample_sync(%{sync_samples: []}), do: []

defp maybe_sample_sync(%{sync_samples: sync_samples}) do
Expand Down
19 changes: 19 additions & 0 deletions lib/membrane_mp4/track/sample_table.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ defmodule Membrane.MP4.Track.SampleTable do
|> maybe_store_first_dts(buffer)
|> do_store_sample(buffer)
|> update_decoding_deltas(buffer)
|> update_composition_offsets(buffer)
|> maybe_store_sync_sample(buffer)
|> store_last_dts(buffer)
end
Expand Down Expand Up @@ -100,6 +101,7 @@ defmodule Membrane.MP4.Track.SampleTable do
:sync_samples,
:chunk_offsets,
:decoding_deltas,
:composition_offsets,
:samples_per_chunk
]

Expand Down Expand Up @@ -148,6 +150,23 @@ defmodule Membrane.MP4.Track.SampleTable do
end)
end

defp update_composition_offsets(sample_table, %Buffer{dts: dts, pts: pts}) do
Map.update!(sample_table, :composition_offsets, fn previous_offsets ->
new_offset = pts - dts

case previous_offsets do
[] ->
[%{sample_count: 1, sample_composition_offset: new_offset}]

[%{sample_count: count, sample_composition_offset: ^new_offset} | rest] ->
[%{sample_count: count + 1, sample_composition_offset: new_offset} | rest]

_different_delta_or_empty ->
[%{sample_count: 1, sample_composition_offset: new_offset} | previous_offsets]
end
end)
end

defp maybe_store_sync_sample(sample_table, %Buffer{metadata: %{h264: h264}})
when h264.key_frame? do
Map.update!(sample_table, :sync_samples, &[sample_table.sample_count | &1])
Expand Down
Binary file modified test/fixtures/isom/ref_two_tracks.mp4
Binary file not shown.
Binary file modified test/fixtures/isom/ref_two_tracks_fast_start.mp4
Binary file not shown.
Binary file modified test/fixtures/isom/ref_video.mp4
Binary file not shown.
Binary file modified test/fixtures/isom/ref_video_fast_start.mp4
Binary file not shown.
Binary file modified test/fixtures/isom/ref_video_hevc.mp4
Binary file not shown.
8 changes: 4 additions & 4 deletions test/membrane_mp4/muxer/isom/integration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ defmodule Membrane.MP4.Muxer.ISOM.IntegrationTest do
structure = [
child(:file, %Membrane.File.Source{location: "test/fixtures/in_video.h264"})
|> child(:parser, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {30, 1}},
generate_best_effort_timestamps: %{framerate: {30, 1}, add_dts_offset: false},
output_stream_structure: :avc1
})
|> child(:muxer, %Membrane.MP4.Muxer.ISOM{chunk_duration: Time.seconds(1)})
Expand Down Expand Up @@ -119,7 +119,7 @@ defmodule Membrane.MP4.Muxer.ISOM.IntegrationTest do
chunk_size: 2_000_048
})
|> child(:video_parser, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {30, 1}},
generate_best_effort_timestamps: %{framerate: {30, 1}, add_dts_offset: false},
output_stream_structure: :avc1
}),
child(:audio_file, %Membrane.File.Source{
Expand Down Expand Up @@ -149,7 +149,7 @@ defmodule Membrane.MP4.Muxer.ISOM.IntegrationTest do
structure = [
child(:file, %Membrane.File.Source{location: "test/fixtures/in_video.h264"})
|> child(:parser, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {30, 1}},
generate_best_effort_timestamps: %{framerate: {30, 1}, add_dts_offset: false},
output_stream_structure: :avc1
})
|> child(:muxer, %Membrane.MP4.Muxer.ISOM{
Expand Down Expand Up @@ -188,7 +188,7 @@ defmodule Membrane.MP4.Muxer.ISOM.IntegrationTest do
structure = [
child(:video_file, %Membrane.File.Source{location: "test/fixtures/in_video.h264"})
|> child(:video_parser, %Membrane.H264.Parser{
generate_best_effort_timestamps: %{framerate: {30, 1}},
generate_best_effort_timestamps: %{framerate: {30, 1}, add_dts_offset: false},
output_stream_structure: :avc1
}),
child(:audio_file, %Membrane.File.Source{location: "test/fixtures/in_audio.aac"})
Expand Down

0 comments on commit a773a85

Please sign in to comment.