109 if (data.
size() < 8) {
110 if (error) *error =
"Data too small for MP4";
115 fl::size moovPos = findBox(data, 0, data.
size(),
"moov");
116 if (moovPos == fl::size(-1)) {
117 if (error) *error =
"No moov box found";
122 fl::u32 moovSize = readU32BE(data, moovPos, ok);
124 if (error) *error =
"Invalid moov box size";
127 fl::size moovEnd = moovPos + moovSize;
128 if (moovEnd > data.
size()) moovEnd = data.
size();
129 fl::size moovBody = moovPos + 8;
132 fl::size trakPos = findBox(data, moovBody, moovEnd,
"trak");
133 if (trakPos == fl::size(-1)) {
134 if (error) *error =
"No trak box found";
138 fl::u32 trakSize = readU32BE(data, trakPos, ok);
140 if (error) *error =
"Invalid trak box size";
143 fl::size trakEnd = trakPos + trakSize;
144 if (trakEnd > moovEnd) trakEnd = moovEnd;
145 fl::size trakBody = trakPos + 8;
148 fl::size mdiaPos = findBox(data, trakBody, trakEnd,
"mdia");
149 if (mdiaPos == fl::size(-1)) {
150 if (error) *error =
"No mdia box found";
154 fl::u32 mdiaSize = readU32BE(data, mdiaPos, ok);
156 if (error) *error =
"Invalid mdia box size";
159 fl::size mdiaEnd = mdiaPos + mdiaSize;
160 if (mdiaEnd > trakEnd) mdiaEnd = trakEnd;
161 fl::size mdiaBody = mdiaPos + 8;
164 fl::size minfPos = findBox(data, mdiaBody, mdiaEnd,
"minf");
165 if (minfPos == fl::size(-1)) {
166 if (error) *error =
"No minf box found";
170 fl::u32 minfSize = readU32BE(data, minfPos, ok);
172 if (error) *error =
"Invalid minf box size";
175 fl::size minfEnd = minfPos + minfSize;
176 if (minfEnd > mdiaEnd) minfEnd = mdiaEnd;
177 fl::size minfBody = minfPos + 8;
180 fl::size stblPos = findBox(data, minfBody, minfEnd,
"stbl");
181 if (stblPos == fl::size(-1)) {
182 if (error) *error =
"No stbl box found";
186 fl::u32 stblSize = readU32BE(data, stblPos, ok);
188 if (error) *error =
"Invalid stbl box size";
191 fl::size stblEnd = stblPos + stblSize;
192 if (stblEnd > minfEnd) stblEnd = minfEnd;
193 fl::size stblBody = stblPos + 8;
196 fl::size stsdPos = findBox(data, stblBody, stblEnd,
"stsd");
197 if (stsdPos == fl::size(-1)) {
198 if (error) *error =
"No stsd box found";
202 fl::u32 stsdSize = readU32BE(data, stsdPos, ok);
204 if (error) *error =
"Invalid stsd box size";
207 fl::size stsdEnd = stsdPos + stsdSize;
208 if (stsdEnd > stblEnd) stsdEnd = stblEnd;
211 fl::size stsdBody = stsdPos + 8 + 4 + 4;
212 if (stsdBody > stsdEnd) {
213 if (error) *error =
"stsd box too small";
218 fl::size avc1Pos = findBox(data, stsdBody, stsdEnd,
"avc1");
219 if (avc1Pos == fl::size(-1)) {
220 if (error) *error =
"No avc1 sample entry found (not H.264)";
224 fl::u32 avc1Size = readU32BE(data, avc1Pos, ok);
226 if (error) *error =
"Invalid avc1 box size";
229 fl::size avc1End = avc1Pos + avc1Size;
230 if (avc1End > stsdEnd) avc1End = stsdEnd;
242 fl::size avc1Body = avc1Pos + 8 + 6 + 2 + 2 + 2 + 12;
243 if (avc1Body + 4 > avc1End) {
244 if (error) *error =
"avc1 box too small for dimensions";
248 info.
width = readU16BE(data, avc1Body, ok);
249 info.
height = readU16BE(data, avc1Body + 2, ok);
251 if (error) *error =
"Failed to read dimensions from avc1";
257 fl::size subBoxStart = avc1Body + 4 + 4 + 4 + 4 + 2 + 32 + 2 + 2;
260 fl::size avcCPos = findBox(data, subBoxStart, avc1End,
"avcC");
261 if (avcCPos == fl::size(-1)) {
262 if (error) *error =
"No avcC box found inside avc1";
266 fl::u32 avcCSize = readU32BE(data, avcCPos, ok);
268 if (error) *error =
"Invalid avcC box size";
271 fl::size avcCEnd = avcCPos + avcCSize;
272 if (avcCEnd > avc1End) avcCEnd = avc1End;
274 if (!parseAvcC(data, avcCPos, avcCEnd, info)) {
275 if (error) *error =
"Failed to parse avcC configuration record";