Skip to content

Commit

Permalink
Add support for version1 boxes. Add parsing of co64 box
Browse files Browse the repository at this point in the history
  • Loading branch information
varsill committed Apr 18, 2024
1 parent e3a7721 commit 0c81ee5
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 22 deletions.
9 changes: 5 additions & 4 deletions lib/membrane_mp4/container/parse_helper.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ defmodule Membrane.MP4.Container.ParseHelper do
end

defp parse_field(data, {name, {type, store: context_name, when: condition}}, context) do
{flag, key} = condition
{flag_value, key, mask} = condition
context_object = Map.get(context, key, 0)

if (flag &&& context_object) == flag do
if (mask &&& context_object) == flag_value do
parse_field(data, {name, {type, store: context_name}}, context)
else
{:ok, {[], data}, context}
Expand All @@ -81,10 +81,11 @@ defmodule Membrane.MP4.Container.ParseHelper do
end

defp parse_field(data, {name, {type, when: condition}}, context) do
{flag, key} = condition
{flag_value, key, mask} = condition

context_object = Map.get(context, key, 0)

if (flag &&& context_object) == flag do
if (mask &&& context_object) == flag_value do
parse_field(data, {name, type}, context)
else
{:ok, {[], data}, context}
Expand Down
44 changes: 33 additions & 11 deletions lib/membrane_mp4/container/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ defmodule Membrane.MP4.Container.Schema do
"""

@full_box [
version: :uint8,
version: {:uint8, store: :version},
flags: {:uint24, store: :fo_flags}
]

Expand Down Expand Up @@ -70,10 +70,13 @@ defmodule Membrane.MP4.Container.Schema do
fields:
@full_box ++
[
creation_time: :uint32,
modification_time: :uint32,
creation_time: {:uint32, when: {0, :version}},
creation_time: {:uint64, when: {1, :version}},
modification_time: {:uint32, when: {0, :version}},
modification_time: {:uint64, when: {1, :version}},
timescale: :uint32,
duration: :uint32,
duration: {:uint32, when: {0, :version}},
duration: {:uint64, when: {1, :version}},
rate: :fp16d16,
volume: :fp8d8,
reserved: <<0::size(80)>>,
Expand Down Expand Up @@ -101,11 +104,14 @@ defmodule Membrane.MP4.Container.Schema do
fields:
@full_box ++
[
creation_time: :uint32,
modification_time: :uint32,
creation_time: {:uint32, when: {0, :version}},
creation_time: {:uint64, when: {1, :version}},
modification_time: {:uint32, when: {0, :version}},
modification_time: {:uint64, when: {1, :version}},
track_id: :uint32,
reserved: <<0::32>>,
duration: :uint32,
duration: {:uint32, when: {0, :version}},
duration: {:uint64, when: {1, :version}},
reserved: <<0::64>>,
layer: :int16,
alternate_group: :int16,
Expand All @@ -130,10 +136,13 @@ defmodule Membrane.MP4.Container.Schema do
fields:
@full_box ++
[
creation_time: :uint32,
modification_time: :uint32,
creation_time: {:uint32, when: {0, :version}},
creation_time: {:uint64, when: {1, :version}},
modification_time: {:uint32, when: {0, :version}},
modification_time: {:uint64, when: {1, :version}},
timescale: :uint32,
duration: :uint32,
duration: {:uint32, when: {0, :version}},
duration: {:uint64, when: {1, :version}},
reserved: <<0::1>>,
language: :uint15,
reserved: <<0::16>>
Expand Down Expand Up @@ -325,6 +334,19 @@ defmodule Membrane.MP4.Container.Schema do
chunk_offset: :uint32
]}
]
],
co64: [
version: 0,
fields:
@full_box ++
[
entry_count: :uint32,
entry_list:
{:list,
[
chunk_offset: :uint64
]}
]
]
]
]
Expand Down Expand Up @@ -426,7 +448,7 @@ defmodule Membrane.MP4.Container.Schema do
sample_duration: :uint32,
sample_size: :uint32,
sample_flags: :bin32,
sample_offset: {:uint32, when: {0x800, :fo_flags}}
sample_offset: {:uint32, when: {0x800, :fo_flags, 0x800}}
]}
]
]
Expand Down
19 changes: 17 additions & 2 deletions lib/membrane_mp4/container/schema_parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,18 @@ defmodule Membrane.MP4.Container.Schema.Parser do
{name, type}
end

defp parse_field({name, {type, store: context_name, when: {flag, context_name, mask}}})
when is_atom(name) do
{name, type} = parse_field({name, type})
type = {type, store: context_name, when: {flag, context_name, mask}}
{name, type}
end

defp parse_field({name, {type, store: context_name, when: {flag, context_name}}})
when is_atom(name) do
{name, type} = parse_field({name, type})
type = {type, store: context_name, when: {flag, context_name}}
default_mask = 0xFFFF_FFFF_FFFF_FFFF
type = {type, store: context_name, when: {flag, context_name, default_mask}}
{name, type}
end

Expand All @@ -75,9 +83,16 @@ defmodule Membrane.MP4.Container.Schema.Parser do
{name, type}
end

defp parse_field({name, {type, when: {flag, context_name, mask}}}) when is_atom(name) do
{name, type} = parse_field({name, type})
type = {type, when: {flag, context_name, mask}}
{name, type}
end

defp parse_field({name, {type, when: {flag, context_name}}}) when is_atom(name) do
{name, type} = parse_field({name, type})
type = {type, when: {flag, context_name}}
default_mask = 0xFFFF_FFFF_FFFF_FFFF
type = {type, when: {flag, context_name, default_mask}}
{name, type}
end

Expand Down
8 changes: 4 additions & 4 deletions lib/membrane_mp4/container/serialize_helper.ex
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ defmodule Membrane.MP4.Container.SerializeHelper do
end

defp serialize_field(term, {type, store: context_name, when: condition}, context) do
{flag, key} = condition
{flag_value, key, mask} = condition
context_object = Map.get(context, key)

if context_object != nil and (flag &&& context_object) == flag do
if context_object != nil and (mask &&& context_object) == flag_value do
serialize_field(term, {type, store: context_name}, context)
else
{{:ok, <<>>}, context}
Expand All @@ -81,10 +81,10 @@ defmodule Membrane.MP4.Container.SerializeHelper do
end

defp serialize_field(term, {type, when: condition}, context) do
{flag, key} = condition
{flag_value, key, mask} = condition
context_object = Map.get(context, key, 0)

if (flag &&& context_object) == flag do
if (mask &&& context_object) == flag_value do
serialize_field(term, type, context)
else
{{:ok, <<>>}, context}
Expand Down
2 changes: 1 addition & 1 deletion lib/membrane_mp4/movie_box/sample_table_box.ex
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ defmodule Membrane.MP4.MovieBox.SampleTableBox do
sample_description: unpack_sample_description(boxes[:stsd]),
sample_count: boxes[:stsz].fields.sample_count,
sample_sizes: unpack_sample_sizes(boxes[:stsz]),
chunk_offsets: unpack_chunk_offsets(boxes[:stco]),
chunk_offsets: unpack_chunk_offsets(boxes[:stco] || boxes[:co64]),
decoding_deltas: boxes[:stts].fields.entry_list,
composition_offsets: get_composition_offsets(boxes),
samples_per_chunk: boxes[:stsc].fields.entry_list,
Expand Down

0 comments on commit 0c81ee5

Please sign in to comment.