Skip to content

Commit

Permalink
Replace use of Embedded with nested "data" field
Browse files Browse the repository at this point in the history
This is by no means ideal. It would be much preferred to be embedded, but the maintainer of construct has stated there is no workaround and nesting is the only option.

This means when building boxes we must now nest the data in `data` container. This also means grabbing a fields value must now specify `.data` first, e.g., `tenc_box.data.is_encrypted`. See changes with the tests. Not ideal at all.
  • Loading branch information
rlaphoenix committed Apr 17, 2023
1 parent f3033ac commit f38276c
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 56 deletions.
12 changes: 6 additions & 6 deletions src/pymp4/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,10 @@
"color_table_id" / Default(Int16sb, -1),
"avc_data" / Prefixed(Int32ub, Struct(
"type" / PaddedString(4, "ascii"),
Embedded(Switch(this.type, {
"data" / Switch(this.type, {
"avcC": AAVC,
"hvcC": HVCC,
}, Struct("data" / GreedyBytes)))
}, GreedyBytes)
), includelength=True),
"sample_info" / LazyBound(lambda _: GreedyRange(Box))
)
Expand All @@ -292,13 +292,13 @@
"format" / PaddedString(4, "ascii"),
Padding(6, pattern=b"\x00"),
"data_reference_index" / Default(Int16ub, 1),
Embedded(Switch(this.format, {
"data" / Switch(this.format, {
"ec-3": MP4ASampleEntryBox,
"mp4a": MP4ASampleEntryBox,
"enca": MP4ASampleEntryBox,
"avc1": AVC1SampleEntryBox,
"encv": AVC1SampleEntryBox
}, Struct("data" / GreedyBytes)))
}, GreedyBytes)
), includelength=True)

BitRateBox = Struct(
Expand Down Expand Up @@ -614,7 +614,7 @@
Box = Prefixed(Int32ub, Struct(
"offset" / Tell,
"type" / PaddedString(4, "ascii"),
Embedded(Switch(this.type, {
"data" / Switch(this.type, {
"ftyp": FileTypeBox,
"styp": SegmentTypeBox,
"mvhd": MovieHeaderBox,
Expand Down Expand Up @@ -668,7 +668,7 @@
"abst": HDSSegmentBox,
"asrt": HDSSegmentRunBox,
"afrt": HDSFragmentRunBox
}, default=RawBox)),
}, default=RawBox),
"end" / TellPlusSizeOf(Int32ub)
), includelength=True)

Expand Down
103 changes: 62 additions & 41 deletions tests/test_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ def test_ftyp_parse(self):
Container(
offset=0,
type="ftyp",
major_brand="iso5",
minor_version=1,
compatible_brands=["iso5", "avc1"],
data=Container(
major_brand="iso5",
minor_version=1,
compatible_brands=["iso5", "avc1"]
),
end=24
)
)
Expand All @@ -41,9 +43,12 @@ def test_ftyp_build(self):
self.assertEqual(
Box.build(dict(
type="ftyp",
major_brand="iso5",
minor_version=1,
compatible_brands=["iso5", "avc1"])),
data=dict(
major_brand="iso5",
minor_version=1,
compatible_brands=["iso5", "avc1"]
)
)),
b'\x00\x00\x00\x18ftypiso5\x00\x00\x00\x01iso5avc1')

def test_mdhd_parse(self):
Expand All @@ -52,50 +57,56 @@ def test_mdhd_parse(self):
Container(
offset=0,
type="mdhd",
version=0,
flags=0,
creation_time=0,
modification_time=0,
timescale=1000000,
duration=0,
language="und",
data=Container(
version=0,
flags=0,
creation_time=0,
modification_time=0,
timescale=1000000,
duration=0,
language="und"
),
end=32
)
)

def test_mdhd_build(self):
mdhd_data = Box.build(dict(
type="mdhd",
creation_time=0,
modification_time=0,
timescale=1000000,
duration=0,
language=u"und"))
data=dict(
creation_time=0,
modification_time=0,
timescale=1000000,
duration=0,
language="und"
)))
self.assertEqual(len(mdhd_data), 32)
self.assertEqual(mdhd_data,
b'\x00\x00\x00\x20mdhd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0fB@\x00\x00\x00\x00U\xc4\x00\x00')

mdhd_data64 = Box.build(dict(
type="mdhd",
version=1,
creation_time=0,
modification_time=0,
timescale=1000000,
duration=0,
language=u"und"))
data=dict(
version=1,
creation_time=0,
modification_time=0,
timescale=1000000,
duration=0,
language="und"
)))
self.assertEqual(len(mdhd_data64), 44)
self.assertEqual(mdhd_data64,
b'\x00\x00\x00,mdhd\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0fB@\x00\x00\x00\x00\x00\x00\x00\x00U\xc4\x00\x00')

def test_moov_build(self):
moov = \
Container(type="moov", children=ListContainer([ # 96 bytes
Container(type="mvex", children=ListContainer([ # 88 bytes
Container(type="mehd", version=0, flags=0, fragment_duration=0), # 16 bytes
Container(type="trex", track_ID=1), # 32 bytes
Container(type="trex", track_ID=2), # 32 bytes
]))
]))
Container(type="moov", data=Container(children=ListContainer([ # 96 bytes
Container(type="mvex", data=Container(children=ListContainer([ # 88 bytes
Container(type="mehd", data=Container(version=0, flags=0, fragment_duration=0)), # 16 bytes
Container(type="trex", data=Container(track_ID=1)), # 32 bytes
Container(type="trex", data=Container(track_ID=2)), # 32 bytes
])))
])))

moov_data = Box.build(moov)

Expand All @@ -116,18 +127,22 @@ def test_smhd_parse(self):
Container(
offset=0,
type="smhd",
version=0,
flags=0,
balance=0,
reserved=0,
data=Container(
version=0,
flags=0,
balance=0,
reserved=0
),
end=len(in_bytes)
)
)

def test_smhd_build(self):
smhd_data = Box.build(dict(
type="smhd",
balance=0))
data=dict(
balance=0
)))
self.assertEqual(len(smhd_data), 16),
self.assertEqual(smhd_data, b'\x00\x00\x00\x10smhd\x00\x00\x00\x00\x00\x00\x00\x00')

Expand All @@ -139,11 +154,17 @@ def test_stsd_parse(self):
Container(
offset=0,
type="stsd",
version=0,
flags=0,
entries=ListContainer([
Container(format='tx3g', data_reference_index=1, data=tx3g_data)
]),
data=Container(
version=0,
flags=0,
entries=ListContainer([
Container(
format="tx3g",
data_reference_index=1,
data=tx3g_data
)
])
),
end=len(in_bytes)
)
)
23 changes: 14 additions & 9 deletions tests/test_dashboxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ def test_tenc_parse(self):
Container(
offset=0,
type="tenc",
version=0,
flags=0,
is_encrypted=1,
iv_size=8,
key_ID=UUID('337b9643-21b6-4355-9e59-3eccb46c7ef7'),
constant_iv=None,
data=Container(
version=0,
flags=0,
is_encrypted=1,
iv_size=8,
key_ID=UUID('337b9643-21b6-4355-9e59-3eccb46c7ef7'),
constant_iv=None
),
end=32
)
)
Expand All @@ -45,7 +47,10 @@ def test_tenc_build(self):
self.assertEqual(
Box.build(dict(
type="tenc",
key_ID=UUID('337b9643-21b6-4355-9e59-3eccb46c7ef7'),
iv_size=8,
is_encrypted=1)),
data=dict(
key_ID=UUID('337b9643-21b6-4355-9e59-3eccb46c7ef7'),
iv_size=8,
is_encrypted=1
)
)),
b'\x00\x00\x00 tenc\x00\x00\x00\x00\x00\x00\x01\x083{\x96C!\xb6CU\x9eY>\xcc\xb4l~\xf7')

0 comments on commit f38276c

Please sign in to comment.