Skip to content

Commit 0c81ee5

Browse files
committed
Add support for version1 boxes. Add parsing of co64 box
1 parent e3a7721 commit 0c81ee5

File tree

5 files changed

+60
-22
lines changed

5 files changed

+60
-22
lines changed

lib/membrane_mp4/container/parse_helper.ex

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ defmodule Membrane.MP4.Container.ParseHelper do
6363
end
6464

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

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

8383
defp parse_field(data, {name, {type, when: condition}}, context) do
84-
{flag, key} = condition
84+
{flag_value, key, mask} = condition
85+
8586
context_object = Map.get(context, key, 0)
8687

87-
if (flag &&& context_object) == flag do
88+
if (mask &&& context_object) == flag_value do
8889
parse_field(data, {name, type}, context)
8990
else
9091
{:ok, {[], data}, context}

lib/membrane_mp4/container/schema.ex

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ defmodule Membrane.MP4.Container.Schema do
1010
"""
1111

1212
@full_box [
13-
version: :uint8,
13+
version: {:uint8, store: :version},
1414
flags: {:uint24, store: :fo_flags}
1515
]
1616

@@ -70,10 +70,13 @@ defmodule Membrane.MP4.Container.Schema do
7070
fields:
7171
@full_box ++
7272
[
73-
creation_time: :uint32,
74-
modification_time: :uint32,
73+
creation_time: {:uint32, when: {0, :version}},
74+
creation_time: {:uint64, when: {1, :version}},
75+
modification_time: {:uint32, when: {0, :version}},
76+
modification_time: {:uint64, when: {1, :version}},
7577
timescale: :uint32,
76-
duration: :uint32,
78+
duration: {:uint32, when: {0, :version}},
79+
duration: {:uint64, when: {1, :version}},
7780
rate: :fp16d16,
7881
volume: :fp8d8,
7982
reserved: <<0::size(80)>>,
@@ -101,11 +104,14 @@ defmodule Membrane.MP4.Container.Schema do
101104
fields:
102105
@full_box ++
103106
[
104-
creation_time: :uint32,
105-
modification_time: :uint32,
107+
creation_time: {:uint32, when: {0, :version}},
108+
creation_time: {:uint64, when: {1, :version}},
109+
modification_time: {:uint32, when: {0, :version}},
110+
modification_time: {:uint64, when: {1, :version}},
106111
track_id: :uint32,
107112
reserved: <<0::32>>,
108-
duration: :uint32,
113+
duration: {:uint32, when: {0, :version}},
114+
duration: {:uint64, when: {1, :version}},
109115
reserved: <<0::64>>,
110116
layer: :int16,
111117
alternate_group: :int16,
@@ -130,10 +136,13 @@ defmodule Membrane.MP4.Container.Schema do
130136
fields:
131137
@full_box ++
132138
[
133-
creation_time: :uint32,
134-
modification_time: :uint32,
139+
creation_time: {:uint32, when: {0, :version}},
140+
creation_time: {:uint64, when: {1, :version}},
141+
modification_time: {:uint32, when: {0, :version}},
142+
modification_time: {:uint64, when: {1, :version}},
135143
timescale: :uint32,
136-
duration: :uint32,
144+
duration: {:uint32, when: {0, :version}},
145+
duration: {:uint64, when: {1, :version}},
137146
reserved: <<0::1>>,
138147
language: :uint15,
139148
reserved: <<0::16>>
@@ -325,6 +334,19 @@ defmodule Membrane.MP4.Container.Schema do
325334
chunk_offset: :uint32
326335
]}
327336
]
337+
],
338+
co64: [
339+
version: 0,
340+
fields:
341+
@full_box ++
342+
[
343+
entry_count: :uint32,
344+
entry_list:
345+
{:list,
346+
[
347+
chunk_offset: :uint64
348+
]}
349+
]
328350
]
329351
]
330352
]
@@ -426,7 +448,7 @@ defmodule Membrane.MP4.Container.Schema do
426448
sample_duration: :uint32,
427449
sample_size: :uint32,
428450
sample_flags: :bin32,
429-
sample_offset: {:uint32, when: {0x800, :fo_flags}}
451+
sample_offset: {:uint32, when: {0x800, :fo_flags, 0x800}}
430452
]}
431453
]
432454
]

lib/membrane_mp4/container/schema_parser.ex

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,18 @@ defmodule Membrane.MP4.Container.Schema.Parser do
6262
{name, type}
6363
end
6464

65+
defp parse_field({name, {type, store: context_name, when: {flag, context_name, mask}}})
66+
when is_atom(name) do
67+
{name, type} = parse_field({name, type})
68+
type = {type, store: context_name, when: {flag, context_name, mask}}
69+
{name, type}
70+
end
71+
6572
defp parse_field({name, {type, store: context_name, when: {flag, context_name}}})
6673
when is_atom(name) do
6774
{name, type} = parse_field({name, type})
68-
type = {type, store: context_name, when: {flag, context_name}}
75+
default_mask = 0xFFFF_FFFF_FFFF_FFFF
76+
type = {type, store: context_name, when: {flag, context_name, default_mask}}
6977
{name, type}
7078
end
7179

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

86+
defp parse_field({name, {type, when: {flag, context_name, mask}}}) when is_atom(name) do
87+
{name, type} = parse_field({name, type})
88+
type = {type, when: {flag, context_name, mask}}
89+
{name, type}
90+
end
91+
7892
defp parse_field({name, {type, when: {flag, context_name}}}) when is_atom(name) do
7993
{name, type} = parse_field({name, type})
80-
type = {type, when: {flag, context_name}}
94+
default_mask = 0xFFFF_FFFF_FFFF_FFFF
95+
type = {type, when: {flag, context_name, default_mask}}
8196
{name, type}
8297
end
8398

lib/membrane_mp4/container/serialize_helper.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ defmodule Membrane.MP4.Container.SerializeHelper do
6565
end
6666

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

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

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

87-
if (flag &&& context_object) == flag do
87+
if (mask &&& context_object) == flag_value do
8888
serialize_field(term, type, context)
8989
else
9090
{{:ok, <<>>}, context}

lib/membrane_mp4/movie_box/sample_table_box.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ defmodule Membrane.MP4.MovieBox.SampleTableBox do
240240
sample_description: unpack_sample_description(boxes[:stsd]),
241241
sample_count: boxes[:stsz].fields.sample_count,
242242
sample_sizes: unpack_sample_sizes(boxes[:stsz]),
243-
chunk_offsets: unpack_chunk_offsets(boxes[:stco]),
243+
chunk_offsets: unpack_chunk_offsets(boxes[:stco] || boxes[:co64]),
244244
decoding_deltas: boxes[:stts].fields.entry_list,
245245
composition_offsets: get_composition_offsets(boxes),
246246
samples_per_chunk: boxes[:stsc].fields.entry_list,

0 commit comments

Comments
 (0)