Skip to content

Commit edce189

Browse files
committed
fix: Fix header sizes for MP4 boxes with 64-bit size fields
The MP4 box header depends on both whether the box is a "full" box (with version and flags) and whether the box has an extra 64-bit size field. The MP4 parser was only considering the version and flags, but not whether the extra size field was present. We already correctly parsed the 64-bit size field, but computed offsets for other fields without considering this. Groundwork for a fix for #2759 Change-Id: I48f16ef073a036954b6f7d25641ccf29828b02c8
1 parent 4b7a743 commit edce189

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

externs/shaka/mp4_parser.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
* size: number,
1818
* version: ?number,
1919
* flags: ?number,
20-
* reader: !shaka.util.DataViewReader
20+
* reader: !shaka.util.DataViewReader,
21+
* has64BitSize: boolean
2122
* }}
2223
*
2324
* @property {!shaka.util.Mp4Parser} parser
@@ -41,6 +42,9 @@
4142
* @property {!shaka.util.DataViewReader} reader
4243
* The reader for this box is only for this box. Reading or not reading to
4344
* the end will have no affect on the parser reading other sibling boxes.
45+
* @property {boolean} has64BitSize
46+
* If true, the box header had a 64-bit size field. This affects the offsets
47+
* of other fields.
4448
* @exportDoc
4549
*/
4650
shaka.extern.ParsedBox;

lib/util/mp4_parser.js

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ shaka.util.Mp4Parser = class {
114114
let size = reader.readUint32();
115115
const type = reader.readUint32();
116116
const name = shaka.util.Mp4Parser.typeToString(type);
117+
let has64BitSize = false;
117118
shaka.log.v2('Parsing MP4 box', name);
118119

119120
switch (size) {
@@ -122,6 +123,7 @@ shaka.util.Mp4Parser = class {
122123
break;
123124
case 1:
124125
size = reader.readUint64();
126+
has64BitSize = true;
125127
break;
126128
}
127129

@@ -160,11 +162,12 @@ shaka.util.Mp4Parser = class {
160162
const box = {
161163
parser: this,
162164
partialOkay: partialOkay || false,
163-
version: version,
164-
flags: flags,
165+
version,
166+
flags,
165167
reader: payloadReader,
166-
size: size,
168+
size,
167169
start: start + absStart,
170+
has64BitSize,
168171
};
169172

170173
boxDefinition(box);
@@ -190,11 +193,10 @@ shaka.util.Mp4Parser = class {
190193
*/
191194
static children(box) {
192195
// The "reader" starts at the payload, so we need to add the header to the
193-
// start position. This is either 8 or 12 bytes depending on whether this
194-
// is a full box.
195-
const header = box.flags != null ? 12 : 8;
196+
// start position. The header size varies.
197+
const headerSize = shaka.util.Mp4Parser.headerSize(box);
196198
while (box.reader.hasMoreData() && !box.parser.done_) {
197-
box.parser.parseNext(box.start + header, box.reader, box.partialOkay);
199+
box.parser.parseNext(box.start + headerSize, box.reader, box.partialOkay);
198200
}
199201
}
200202

@@ -210,13 +212,12 @@ shaka.util.Mp4Parser = class {
210212
*/
211213
static sampleDescription(box) {
212214
// The "reader" starts at the payload, so we need to add the header to the
213-
// start position. This is either 8 or 12 bytes depending on whether this
214-
// is a full box.
215-
const header = box.flags != null ? 12 : 8;
215+
// start position. The header size varies.
216+
const headerSize = shaka.util.Mp4Parser.headerSize(box);
216217
const count = box.reader.readUint32();
217218
for (const _ of shaka.util.Iterables.range(count)) {
218219
shaka.util.Functional.ignored(_);
219-
box.parser.parseNext(box.start + header, box.reader, box.partialOkay);
220+
box.parser.parseNext(box.start + headerSize, box.reader, box.partialOkay);
220221
if (box.parser.done_) {
221222
break;
222223
}
@@ -277,6 +278,20 @@ shaka.util.Mp4Parser = class {
277278
type & 0xff);
278279
return name;
279280
}
281+
282+
/**
283+
* Find the header size of the box.
284+
* Useful for modifying boxes in place or finding the exact offset of a field.
285+
*
286+
* @param {shaka.extern.ParsedBox} box
287+
* @return {number}
288+
* @export
289+
*/
290+
static headerSize(box) {
291+
return /* basic header */ 8
292+
+ /* additional 64-bit size field */ (box.has64BitSize ? 8 : 0)
293+
+ /* version and flags for a "full" box */ (box.flags != null ? 4 : 0);
294+
}
280295
};
281296

282297

0 commit comments

Comments
 (0)