Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1107)

Side by Side Diff: media/base/container_names.cc

Issue 14495010: Add UMA stats for audio/video containers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/base/container_names.h"
6
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "base/metrics/sparse_histogram.h"
10
11 namespace media {
12
13 #define TAG(a, b, c, d) \
14 ((static_cast<uint8_t>(a) << 24) | (static_cast<uint8_t>(b) << 16) | \
15 (static_cast<uint8_t>(c) << 8) | (static_cast<uint8_t>(d)))
16
17 // Helper function to read 2 bytes (16 bits, big endian) from a buffer.
18 static uint32_t Read16(const uint8_t* p) {
19 return p[0] << 8 | p[1];
20 }
21
22 // Helper function to read 3 bytes (24 bits, big endian) from a buffer.
23 static uint32_t Read24(const uint8_t* p) {
24 return p[0] << 16 | p[1] << 8 | p[2];
25 }
26
27 // Helper function to read 4 bytes (32 bits, big endian) from a buffer.
28 static uint32_t Read32(const uint8_t* p) {
29 return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
30 }
31
32 // Helper function to do buffer comparisons without going off the end
33 // of the buffer.
34 static bool CompareEqual(const uint8_t* buffer,
xhwang 2013/05/03 19:59:06 This function is checking that "search" is a prefi
jrummell 2013/05/03 23:56:21 Done.
35 size_t buffer_size,
36 const char* search,
37 size_t search_size) {
38 return (search_size <= buffer_size &&
39 memcmp(buffer, search, search_size) == 0);
40 }
41
42 // Comparison function used by lower_bound which returns true
43 // if the first argument is less than the second.
xhwang 2013/05/03 19:59:06 s/less than the second/less than the second in lex
jrummell 2013/05/03 23:56:21 Done.
44 static bool ContainerNameMappingComparer(const ContainerNameMapping& a,
45 const char* b) {
46 return strcasecmp(a.name, b) < 0;
47 }
48
49 // Output a container value to the histogram.
50 static void LogContainerToHistogram(FFmpegContainerName container,
51 bool is_guess) {
52 int metric = 2 * container;
53 if (is_guess)
54 ++metric;
55
56 UMA_HISTOGRAM_SPARSE_SLOWLY("Media.DetectedContainer", metric);
57 }
58
59 // For some formats the signature is a bunch of characters. They are defined
60 // below. Note that the first 4 characters of the string may be used as a TAG
61 // in LookupContainerByFirst4.
62 #define BYTE_ORDER_MARK "\xef\xbb\xbf"
63
64 static const char kAmrSignature[] = "#!AMR";
65 static const char kApcSignature[] = "CRYO_APC";
66 static const char kAsfSignature[] =
67 "\x30\x26\xb2\x75\x8e\x66\xcf\x11\xa6\xd9\x00\xaa\x00\x62\xce\x6c";
68 static const char kAssSignature[] = "[Script Info]";
69 static const char kAssBomSignature[] = BYTE_ORDER_MARK "[Script Info]";
70 static const char kConcatSignature[] = "ffconcat version 1.0";
71 static const char kDnxhdSignature[] = "\x00\x00\x02\x80\x01";
72 static const char kFfSignature[] = ";FFMETADATA";
73 static const char kHlsSignature[] = "#EXTM3U";
74 static const char kIdfSignature[] =
75 "\x04\x31\x2e\x34\x00\x00\x00\x00\x4f\x00\x15\x00";
76 static const char kIlbcSignature[] = "#!iLBC";
77 static const char kIssSignature[] = "IMA_ADPCM_Sound";
78 static const char kIv8Signature[] = "\x01\x01\x03\xb8\x80\x60";
79 static const char kJvSignature[] = " Compression by John M Phillips Copyright "
80 "(C) 1995 The Bitmap Brothers Ltd.";
81 static const char kLibnutSignature[] = "nut/multimedia container";
82 static const char kLxfSignature[] = "LEITCH\x00\x00";
83 static const char kNuv1Signature[] = "NuppelVideo";
84 static const char kNuv2Signature[] = "MythTVVideo";
85 static const char kPafSignature[] =
86 "Packed Animation File V1.0\n(c) 1992-96 Amazing Studio\x0a\x1a";
87 static const char kRealSignature[] = "<window";
88 static const char kRealBomSignature[] = BYTE_ORDER_MARK "<window";
89 static const char kRplSignature[] = "ARMovie\x0A";
90 static const char kSamiSignature[] = "<SAMI>";
91 static const char kSamiBomSignature[] = BYTE_ORDER_MARK "<SAMI>";
92 static const char kSmjpegSignature[] = "\x00\x0aSMJPEG";
93 static const char kVivoSignature[] = "\r\nVersion:Vivo/";
94 static const char kVobsubSignature[] = "# VobSub index file,";
95 static const char kVocSignature[] = "Creative Voice File\x1A";
96 static const char kW64Signature[] =
97 "riff\x2e\x91\xcf\x11\xa5\xd6\x28\xdb\x04\xc1\x00\x00";
98 static const char kW64Signature2[] =
99 "wave\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a";
100 static const char kWebvttSignature[] = "WEBVTT";
101 static const char kWebvttBomSignature[] = BYTE_ORDER_MARK "WEBVTT";
102 static const char kWtvSignature[] =
103 "\xb7\xd8\x00\x20\x37\x49\xda\x11\xa6\x4e\x00\x07\xe9\x5e\xad\x8d";
104 static const char kYuv4Signature[] = "YUV4MPEG2";
105
106 const uint16_t ac3_frame_size_table[38][3] = {
xhwang 2013/05/03 19:59:06 use kCamelCase for consts?
jrummell 2013/05/03 23:56:21 Done.
107 { 128, 138, 192 }, { 128, 140, 192 }, { 160, 174, 240 }, { 160, 176, 240 },
108 { 192, 208, 288 }, { 192, 210, 288 }, { 224, 242, 336 }, { 224, 244, 336 },
109 { 256, 278, 384 }, { 256, 280, 384 }, { 320, 348, 480 }, { 320, 350, 480 },
110 { 384, 416, 576 }, { 384, 418, 576 }, { 448, 486, 672 }, { 448, 488, 672 },
111 { 512, 556, 768 }, { 512, 558, 768 }, { 640, 696, 960 }, { 640, 698, 960 },
112 { 768, 834, 1152 }, { 768, 836, 1152 }, { 896, 974, 1344 },
113 { 896, 976, 1344 }, { 1024, 1114, 1536 }, { 1024, 1116, 1536 },
114 { 1280, 1392, 1920 }, { 1280, 1394, 1920 }, { 1536, 1670, 2304 },
115 { 1536, 1672, 2304 }, { 1792, 1950, 2688 }, { 1792, 1952, 2688 },
116 { 2048, 2228, 3072 }, { 2048, 2230, 3072 }, { 2304, 2506, 3456 },
117 { 2304, 2508, 3456 }, { 2560, 2768, 3840 }, { 2560, 2770, 3840 },
118 };
119
120 // Checks for an ADTS AAC container.
121 static bool check_aac(const uint8_t buffer[], size_t buffer_size) {
xhwang 2013/05/03 19:59:06 use const uint8_t* and int?
jrummell 2013/05/03 23:56:21 Done.
122 // ADTS header is 7 or 9 bytes
123 // (from http://wiki.multimedia.cx/index.php?title=ADTS)
124 size_t offset = 0;
125 while (offset + 5 < buffer_size) {
126 uint32_t syncword = (Read16(buffer + offset) >> 4) & 0xfff;
xhwang 2013/05/03 19:59:06 we are using uint32_t in this function even for 16
jrummell 2013/05/03 23:56:21 Done.
127 uint32_t layer = (buffer[offset + 1] >> 1) & 0x3;
128 uint32_t frequency_index = (buffer[offset + 2] >> 2) & 0xf;
129 uint32_t size = (Read24(buffer + offset + 3) >> 5) & 0x1fff;
130 if (syncword != 0xfff || layer != 0 || frequency_index == 15)
131 return false;
132 offset += size;
133 }
134 return true;
xhwang 2013/05/03 19:59:06 So if buffer_size is <= 5, we return true here. Is
jrummell 2013/05/03 23:56:21 Done.
135 }
136
137 // Checks for an AC3 container.
138 static bool check_ac3(const uint8_t buffer[], size_t buffer_size) {
139 // AC3 container looks like syncinfo | bsi | audblk * 6 | aux | check.
140 // from spec @ http://www.atsc.org/cms/standards/A52-2012(12-17).pdf
141 size_t offset = 0;
142
143 while (offset + 6 < buffer_size) {
144 // Verify syncinfo (5 bytes)
145 if (Read16(buffer + offset) != 0x0b77)
146 return false;
147 int sample_rate_code = (buffer[offset + 4] >> 6) & 0x03;
148 if (sample_rate_code == 3) // reserved
149 return false;
150 int frame_size_code = buffer[offset + 4] & 0x3f;
151 if (frame_size_code >= 38)
152 return false;
153
154 // Verify bsi (no fixed alignment)
155 int bit_stream_id = (buffer[offset + 5] >> 3) & 0x1f;
156 if (bit_stream_id >= 10) // normally 8 or 6
157 return false;
158
159 offset += ac3_frame_size_table[frame_size_code][sample_rate_code];
160 }
161 return true;
xhwang 2013/05/03 19:59:06 ditto
jrummell 2013/05/03 23:56:21 Done.
162 }
163
164 // Checks for an EAC3 container (very similar to AC3)
165 static bool check_eac3(const uint8_t buffer[], size_t buffer_size) {
166 // EAC3 container looks like syncinfo | bsi | audfrm | audblk* | aux | check.
167 // from spec @ http://www.atsc.org/cms/standards/A52-2012(12-17).pdf
168 size_t offset = 0;
169
170 while (offset + 6 < buffer_size) {
171 // Verify syncinfo (5 bytes)
172 if (Read16(buffer + offset) != 0x0b77)
173 return false;
174
175 // Verify bsi (no fixed alignment)
176 int stream_type = (buffer[offset + 2] > 6) & 0x3;
177 if (stream_type == 3)
178 return false;
179 int frame_size = ((Read16(buffer + offset + 2) & 0x7ff) + 1) * 2;
180 if (frame_size < 7)
181 return false;
182 int bit_stream_id = (buffer[offset + 5] >> 3) & 0x1f;
183 if (bit_stream_id != 16)
184 return false;
185
186 offset += frame_size;
187 }
188 return true;
xhwang 2013/05/03 19:59:06 ditto
jrummell 2013/05/03 23:56:21 Done.
189 }
190
191 // Additional checks for an ACT container.
192 static bool check_act(const uint8_t buffer[], size_t buffer_size) {
193 if (buffer_size < 512 || Read32(buffer + 16) != 16)
194 return false;
195 // Most of the first 512 bytes should be 0.
196 for (int i = 44; i < 256; ++i)
197 if (buffer[i] != 0)
198 return false;
199 if (buffer[256] != 0x84)
200 return false;
201 for (int i = 264; i < 512; ++i)
202 if (buffer[i] != 0)
203 return false;
204 return true;
205 }
206
207 // Additional checks for an AEA container.
208 static bool check_aea(const uint8_t buffer[], size_t buffer_size) {
209 if (buffer_size < 2260)
210 return false;
211 int channels = buffer[264];
212 return ((channels == 1 || channels == 2) &&
213 buffer[2048] == buffer[2259] &&
214 buffer[2049] == buffer[2258]);
215 }
216
217 // Additional checks for a BINK container.
218 static bool check_bink(const uint8_t buffer[], size_t buffer_size) {
219 if (buffer_size < 36)
220 return false;
221 uint32_t frames = Read32(buffer + 8);
222 uint32_t width = Read32(buffer + 20);
223 uint32_t height = Read32(buffer + 24);
224 uint32_t fps = Read32(buffer + 28);
225 uint32_t den = Read32(buffer + 32);
226 return (frames > 0 && fps > 0 && den > 0 &&
227 (width > 0 && width <= 7680) &&
228 (height > 0 && height <= 4800));
229 }
230
231 // Additional checks for a C93 container.
232 static bool check_c93(const uint8_t buffer[], size_t buffer_size) {
233 uint16_t index = 1;
234 if (buffer_size < 20)
235 return false;
236 for (int i = 0; i < 16; i += 4) {
237 if (Read16(buffer + i) != index || !buffer[i + 2] || !buffer[i + 3])
238 return false;
239 index += buffer[i + 2];
xhwang 2013/05/03 19:59:06 just double check, so we are not using buffer[i +
jrummell 2013/05/03 23:56:21 This is what is in ffmpeg (https://code.google.com
xhwang 2013/05/06 23:51:27 ok, thanks for the link.
Ilya Sherman 2013/05/07 00:10:51 Just double-checking: Is it consistent with ffmpeg
240 }
xhwang 2013/05/03 19:59:06 indent
jrummell 2013/05/03 23:56:21 Done.
241 return true;
242 }
243
244 // Additional checks for a CDXL container.
245 static bool check_cdxl(const uint8_t buffer[], size_t buffer_size) {
246 if (buffer_size < 32)
247 return false;
248 uint8_t type = buffer[0];
249 uint32_t current_size = Read32(buffer + 2);
250 uint32_t width = Read16(buffer + 14);
251 uint32_t height = Read16(buffer + 16);
252 uint8_t plane1 = buffer[18];
253 uint8_t plane2 = buffer[19];
254 uint32_t palette_size = Read16(buffer + 20);
255 uint32_t audio_size = Read16(buffer + 22);
256 uint32_t image_size = width * height * plane2 / 8;
257 return (type == 1 &&
258 palette_size <= 512 &&
259 plane1 != 0 &&
260 plane2 != 0 &&
261 width != 0 &&
262 height != 0 &&
263 current_size >= audio_size + palette_size + image_size + 32 &&
264 Read32(buffer + 24) == 0 &&
265 Read32(buffer + 28) == 0 &&
266 Read16(buffer + 10) == 0);
267 }
268
269 // Additional checks for a DNXHD container.
270 static bool check_dnxhd(const uint8_t buffer[], size_t buffer_size) {
271 if (buffer_size < 42)
272 return false;
273 uint32_t height = Read16(buffer + 24);
274 uint32_t width = Read16(buffer + 26);
275 uint32_t compression = Read16(buffer + 40);
276 return (CompareEqual(buffer,
277 buffer_size,
278 kDnxhdSignature,
279 sizeof(kDnxhdSignature) - 1) &&
280 height > 0 && width > 0 && compression >= 1235 &&
281 compression <= 1253);
282 }
283
284 // Additional checks for a DSICIN container.
285 static bool check_dsicin(const uint8_t buffer[], size_t buffer_size) {
286 return (buffer_size > 17 &&
287 Read32(buffer + 12) == 22050 &&
288 buffer[16] == 16 &&
289 buffer[17] == 0);
290 }
291
292 // Additional checks for an IDCIN container.
293 static bool check_idcin(const uint8_t buffer[], size_t buffer_size) {
294 if (buffer_size < 20)
xhwang 2013/05/03 19:59:06 s/</<=/ ? It seems we only need 20 bytes.
jrummell 2013/05/03 23:56:21 Correct. If we have 20 bytes we can test. If it's
295 return false;
296 uint32_t width = Read32(buffer);
297 uint32_t height = Read32(buffer + 4);
298 uint32_t rate = Read32(buffer + 8);
299 uint32_t bytes = Read32(buffer + 12);
300 uint32_t channels = Read32(buffer + 16);
301 return (width > 0 && width <= 1024 &&
302 height > 0 && height <= 1024 &&
303 rate >= 8000 && rate <= 48000 &&
304 bytes <= 2 &&
305 channels <= 2);
306 }
307
308 #define HLS1 "#EXT-X-STREAM-INF:"
309 #define HLS2 "#EXT-X-TARGETDURATION:"
310 #define HLS3 "#EXT-X-MEDIA-SEQUENCE:"
xhwang 2013/05/03 19:59:06 here and 359-362: use const instead of macro?
311
312 // Additional checks for a HLS container.
313 static bool check_hls(const uint8_t buffer[], size_t buffer_size) {
314 if (CompareEqual(buffer,
315 buffer_size,
316 kHlsSignature,
317 sizeof(kHlsSignature) - 1)) {
318 // Need to find "#EXT-X-STREAM-INF:", "#EXT-X-TARGETDURATION:",
319 // or "#EXT-X-MEDIA-SEQUENCE:" somewhere in the buffer
320 size_t offset = sizeof(kHlsSignature) - 1;
321 while (offset < buffer_size) {
322 if (buffer[offset] == '#') {
323 if (CompareEqual(buffer + offset,
324 buffer_size - offset,
325 HLS1,
326 strlen(HLS1)) ||
327 CompareEqual(buffer + offset,
328 buffer_size - offset,
329 HLS2,
330 strlen(HLS2)) ||
331 CompareEqual(buffer + offset,
332 buffer_size - offset,
333 HLS3,
334 strlen(HLS3)))
335 return true;
336 }
337 ++offset;
338 }
339 }
340 return false;
341 }
342
343 // Checks for a LOAS container.
344 static bool check_loas(const uint8_t buffer[], size_t buffer_size) {
345 // LOAS header is 3 bytes.
346 // (from ISO/IEC 14496-3:2005, page 51)
347 size_t offset = 0;
348 while (offset + 3 < buffer_size) {
349 uint32_t header = Read24(buffer);
350 uint32_t syncword = (header >> 13) & 0x7ff;
351 uint32_t audio_length = (header & 0x1fff);
352 if (syncword != 0x2b7 || audio_length < 4)
353 return false;
354 offset += audio_length + 3 /* header */;
355 }
356 return true;
xhwang 2013/05/03 19:59:06 ditto about buffer_size check
jrummell 2013/05/03 23:56:21 Done.
357 }
358
359 #define VISUAL_OBJECT_SEQUENCE_START_CODE 0xb0
360 #define VISUAL_OBJECT_SEQUENCE_END_CODE 0xb1
361 #define VISUAL_OBJECT_START_CODE 0xb5
362 #define VOP_START_CODE 0xb6
363
364 // Checks for a M4V (raw MPEG4) container.
365 static bool check_m4v(const uint8_t buffer[], size_t buffer_size) {
366 // Defined in ISO/IEC 14496-2:2001.
367 // However, no length ... simply scan for start code values
368 // Expect to see SEQ | VO1 | VOL* | VO2 ...
369 size_t offset = 0;
370 int sequence_start_count = 0;
371 int sequence_end_count = 0;
372 int visual_object_count = 0;
373 int vop_count = 0;
374 while (offset + 4 < buffer_size) {
375 uint32_t start_code = Read24(buffer + offset);
376 if (start_code == 1) {
377 // Fail if it is a reserved value.
378 if (buffer[offset] >= 0x30 && buffer[offset] <= 0xaf)
379 return false;
380 if (buffer[offset] >= 0xb7 && buffer[offset] <= 0xb9)
381 return false;
382
383 switch (buffer[offset]) {
384 case VISUAL_OBJECT_SEQUENCE_START_CODE:
385 ++sequence_start_count;
386 break;
387 case VISUAL_OBJECT_SEQUENCE_END_CODE:
388 if (++sequence_end_count > sequence_start_count)
389 return false;
390 break;
391 case VISUAL_OBJECT_START_CODE:
392 ++visual_object_count;
393 break;
394 case VOP_START_CODE:
395 if (++vop_count > visual_object_count)
396 return false;
397 break;
398 }
399 offset += 4;
400 }
401 else {
402 // Start codes can start on any byte boundary
403 ++offset;
404 }
405 }
406 // Not a complete sequence in memory, so return true if we've seen a
407 // visual_object_sequence_start_code and a visual_object_start_code.
408 return (sequence_start_count > 0 && visual_object_count > 0);
409 }
410
411 // Additional checks for a MM container.
412 static bool check_mm(const uint8_t buffer[], size_t buffer_size) {
413 if (buffer_size < 16)
414 return false;
415 uint32_t length = Read32(buffer + 2);
416 uint32_t fps = Read16(buffer + 8);
417 uint32_t width = Read16(buffer + 12);
418 uint32_t height = Read16(buffer + 14);
419 uint32_t type = (length + 2 < buffer_size) ? Read16(buffer + length) : 0;
xhwang 2013/05/03 19:59:06 here, length looks like type_offset.. then on line
jrummell 2013/05/03 23:56:21 Done.
420 return ((length == 22 || length == 24) &&
421 fps > 0 && fps <= 60 &&
422 width > 0 && width <= 2048 &&
423 height > 0 && height <= 2048 &&
424 type > 0 && type < 50);
425 }
426
427 // Additional checks for a MOV container.
428 static bool check_mov(const uint8_t buffer[], size_t buffer_size) {
xhwang 2013/05/03 19:59:06 ditto, shall we check buffer_size?
jrummell 2013/05/03 23:56:21 Done.
429 size_t offset = 0;
430 while (offset + 16 < buffer_size) {
431 uint32_t atomsize = Read32(buffer + offset);
432 uint32_t atomtype = Read32(buffer + offset + 4);
433 // Valid atoms from http://www.mp4ra.org/atoms.html
434 switch (atomtype) {
435 case TAG('a','i','n','f'):
436 case TAG('a','v','c','n'):
437 case TAG('b','l','o','c'):
438 case TAG('b','p','c','c'):
439 case TAG('b','u','f','f'):
440 case TAG('b','x','m','l'):
441 case TAG('c','c','i','d'):
442 case TAG('c','d','e','f'):
443 case TAG('c','m','a','p'):
444 case TAG('c','o','6','4'):
445 case TAG('c','o','l','r'):
446 case TAG('c','r','h','d'):
447 case TAG('c','s','l','g'):
448 case TAG('c','t','t','s'):
449 case TAG('c','v','r','u'):
450 case TAG('d','i','n','f'):
451 case TAG('d','r','e','f'):
452 case TAG('d','s','g','d'):
453 case TAG('d','s','t','g'):
454 case TAG('e','d','t','s'):
455 case TAG('e','l','s','t'):
456 case TAG('f','e','c','i'):
457 case TAG('f','e','c','r'):
458 case TAG('f','i','i','n'):
459 case TAG('f','i','r','e'):
460 case TAG('f','p','a','r'):
461 case TAG('f','r','e','e'):
462 case TAG('f','r','m','a'):
463 case TAG('f','t','y','p'):
464 case TAG('g','i','t','n'):
465 case TAG('g','r','p','i'):
466 case TAG('h','d','l','r'):
467 case TAG('h','m','h','d'):
468 case TAG('h','p','i','x'):
469 case TAG('i','c','n','u'):
470 case TAG('I','D','3','2'):
471 case TAG('i','d','a','t'):
472 case TAG('i','h','d','r'):
473 case TAG('i','i','n','f'):
474 case TAG('i','l','o','c'):
475 case TAG('i','m','i','f'):
476 case TAG('i','n','f','u'):
477 case TAG('i','o','d','s'):
478 case TAG('i','p','h','d'):
479 case TAG('i','p','m','c'):
480 case TAG('i','p','r','o'):
481 case TAG('i','r','e','f'):
482 case TAG('j','P',' ',' '):
483 case TAG('j','p','2','c'):
484 case TAG('j','p','2','h'):
485 case TAG('j','p','2','i'):
486 case TAG('l','r','c','u'):
487 case TAG('m','7','h','d'):
488 case TAG('m','d','a','t'):
489 case TAG('m','d','h','d'):
490 case TAG('m','d','i','a'):
491 case TAG('m','d','r','i'):
492 case TAG('m','e','c','o'):
493 case TAG('m','e','h','d'):
494 case TAG('m','e','r','e'):
495 case TAG('m','e','t','a'):
496 case TAG('m','f','h','d'):
497 case TAG('m','f','r','a'):
498 case TAG('m','f','r','o'):
499 case TAG('m','i','n','f'):
500 case TAG('m','j','h','d'):
501 case TAG('m','o','o','f'):
502 case TAG('m','o','o','v'):
503 case TAG('m','v','c','g'):
504 case TAG('m','v','c','i'):
505 case TAG('m','v','e','x'):
506 case TAG('m','v','h','d'):
507 case TAG('m','v','r','a'):
508 case TAG('n','m','h','d'):
509 case TAG('o','c','h','d'):
510 case TAG('o','d','a','f'):
511 case TAG('o','d','d','a'):
512 case TAG('o','d','h','d'):
513 case TAG('o','d','h','e'):
514 case TAG('o','d','r','b'):
515 case TAG('o','d','r','m'):
516 case TAG('o','d','t','t'):
517 case TAG('o','h','d','r'):
518 case TAG('p','a','d','b'):
519 case TAG('p','a','e','n'):
520 case TAG('p','c','l','r'):
521 case TAG('p','d','i','n'):
522 case TAG('p','i','t','m'):
523 case TAG('r','e','s',' '):
524 case TAG('r','e','s','c'):
525 case TAG('r','e','s','d'):
526 case TAG('s','b','g','p'):
527 case TAG('s','c','h','i'):
528 case TAG('s','c','h','m'):
529 case TAG('s','d','e','p'):
530 case TAG('s','d','h','d'):
531 case TAG('s','d','t','p'):
532 case TAG('s','d','v','p'):
533 case TAG('s','e','g','r'):
534 case TAG('s','e','n','c'):
535 case TAG('s','g','p','d'):
536 case TAG('s','i','d','x'):
537 case TAG('s','i','n','f'):
538 case TAG('s','k','i','p'):
539 case TAG('s','m','h','d'):
540 case TAG('s','r','m','b'):
541 case TAG('s','r','m','c'):
542 case TAG('s','r','p','p'):
543 case TAG('s','t','b','l'):
544 case TAG('s','t','c','o'):
545 case TAG('s','t','d','p'):
546 case TAG('s','t','h','d'):
547 case TAG('s','t','s','c'):
548 case TAG('s','t','s','d'):
549 case TAG('s','t','s','h'):
550 case TAG('s','t','s','s'):
551 case TAG('s','t','s','z'):
552 case TAG('s','t','t','s'):
553 case TAG('s','t','y','p'):
554 case TAG('s','t','z','2'):
555 case TAG('s','u','b','s'):
556 case TAG('s','w','t','c'):
557 case TAG('t','f','a','d'):
558 case TAG('t','f','h','d'):
559 case TAG('t','f','m','a'):
560 case TAG('t','f','r','a'):
561 case TAG('t','i','b','r'):
562 case TAG('t','i','r','i'):
563 case TAG('t','k','h','d'):
564 case TAG('t','r','a','f'):
565 case TAG('t','r','a','k'):
566 case TAG('t','r','e','f'):
567 case TAG('t','r','e','x'):
568 case TAG('t','r','g','r'):
569 case TAG('t','r','i','k'):
570 case TAG('t','r','u','n'):
571 case TAG('u','d','t','a'):
572 case TAG('u','i','n','f'):
573 case TAG('U','I','T','S'):
574 case TAG('u','l','s','t'):
575 case TAG('u','r','l',' '):
576 case TAG('u','u','i','d'):
577 case TAG('v','m','h','d'):
578 case TAG('v','w','d','i'):
579 case TAG('x','m','l',' '):
580 case TAG('C','o','d','e'):
581 case TAG('a','l','b','m'):
582 case TAG('a','n','g','l'):
583 case TAG('a','u','t','h'):
584 case TAG('c','l','f','n'):
585 case TAG('c','l','i','d'):
586 case TAG('c','l','s','f'):
587 case TAG('c','m','i','d'):
588 case TAG('c','m','n','m'):
589 case TAG('c','o','l','l'):
590 case TAG('c','p','r','t'):
591 case TAG('d','a','t','e'):
592 case TAG('d','s','c','p'):
593 case TAG('g','n','r','e'):
594 case TAG('h','n','t','i'):
595 case TAG('k','y','w','d'):
596 case TAG('l','o','c','i'):
597 case TAG('m','a','n','u'):
598 case TAG('m','o','d','l'):
599 case TAG('p','e','r','f'):
600 case TAG('r','e','e','l'):
601 case TAG('r','t','n','g'):
602 case TAG('s','c','e','n'):
603 case TAG('s','h','o','t'):
604 case TAG('s','l','n','o'):
605 case TAG('s','t','r','k'):
606 case TAG('t','h','m','b'):
607 case TAG('t','s','e','l'):
608 case TAG('t','i','t','l'):
609 case TAG('u','r','a','t'):
610 case TAG('y','r','r','c'):
611 case TAG('c','l','i','p'):
612 case TAG('c','r','g','n'):
613 case TAG('c','t','a','b'):
614 case TAG('d','c','f','D'):
615 case TAG('e','l','n','g'):
616 case TAG('i','m','a','p'):
617 case TAG('k','m','a','t'):
618 case TAG('l','o','a','d'):
619 case TAG('m','a','t','t'):
620 case TAG('p','n','o','t'):
621 case TAG('w','i','d','e'):
622 break;
623 default:
624 return false;
625 }
626 if (atomsize == 0)
627 break; // indicates the last atom
628 if (atomsize == 1) {
629 // Indicates that the length is the next 64bits.
630 if (Read32(buffer + offset + 8) != 0)
631 break; // offset is way past buffer size
632 atomsize = Read32(buffer + offset + 12);
633 }
634 offset += atomsize;
635 }
636 return true;
637 }
638
639 enum MPEGVersion {
640 Version25 = 0,
641 v_reserved,
642 Version2,
643 Version1
644 };
645 enum MPEGlayer {
646 l_reserved = 0,
647 Layer3,
648 Layer2,
649 Layer1
650 };
651
652 static int Sample_Rate_Table[4][4] = {
653 { 11025, 12000, 8000, 0 }, // v2.5
654 { 0, 0, 0, 0 }, // not used
655 { 22050, 24000, 16000, 0 }, // v2
656 { 44100, 48000, 32000, 0 } // v1
657 };
658
659 static int Bit_Rate_Table_v1_l1[16] =
660 { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 };
xhwang 2013/05/03 19:59:06 here and below, 4 space indentation.
jrummell 2013/05/03 23:56:21 Reformatted to what clang-format does.
661 static int Bit_Rate_Table_v1_l2[16] =
662 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 };
663 static int Bit_Rate_Table_v1_l3[16] =
664 { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 };
665 static int Bit_Rate_Table_v2_l1[16] =
666 { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 };
667 static int Bit_Rate_Table_v2_l23[16] =
668 { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 };
669
670 static bool valid_mpeg_audio_frame_header(uint32_t header, size_t* framesize) {
671 *framesize = 0;
672 // first 11 bits must be all set
673 if ((header & 0xffe00000) != 0xffe00000)
674 return false;
675 // version (bits 20-19) can not be 01
676 int version = (header >> 19) & 0x3;
677 if (version == 1)
678 return false;
679 // layer (bits 18-17) can not be 00
680 int layer = (header >> 17) & 0x3;
681 if (layer == 0)
682 return false;
683 // bitrate (bits 15-12) can not be 1111
684 int bitrate_index = (header >> 12) & 0xf;
685 if (bitrate_index == 0xf)
686 return false;
687 // sampling (bits 11-10) can not be 11
688 int sampling_index = (header >> 10) & 0x3;
689 if (sampling_index == 3)
690 return false;
691
692 // Frame size:
693 // For Layer I files = (12 * BitRate / SampleRate + Padding) * 4
694 // For others = 144 * BitRate / SampleRate + Padding
695 // Unfortunately, BitRate and SampleRate are coded
696 int padding = (header >> 9) & 0x1;
697 int sampling_rate = Sample_Rate_Table[version][sampling_index];
698 int bitrate;
699 if (version == Version1) {
700 if (layer == Layer1)
701 bitrate = Bit_Rate_Table_v1_l1[bitrate_index];
702 else if (layer == Layer2)
703 bitrate = Bit_Rate_Table_v1_l2[bitrate_index];
704 else
705 bitrate = Bit_Rate_Table_v1_l3[bitrate_index];
706 }
707 else {
708 if (layer == Layer1)
709 bitrate = Bit_Rate_Table_v2_l1[bitrate_index];
710 else
711 bitrate = Bit_Rate_Table_v2_l23[bitrate_index];
712 }
713 if (layer == Layer1)
714 *framesize = ((12000 * bitrate) / sampling_rate + padding) * 4;
715 else
716 *framesize = (144000 * bitrate) / sampling_rate + padding;
717 return (bitrate > 0 && sampling_rate > 0);
718 }
719
720 // Extract a size encoded the MP3 way
721 static uint32_t get_mp3_header_size(const uint8_t buffer[]) {
722 uint32_t size = ((buffer[6] & 0x7f) << 21) +
723 ((buffer[7] & 0x7f) << 14) +
724 ((buffer[8] & 0x7f) << 7) +
725 (buffer[9] & 0x7f) +
xhwang 2013/05/03 19:59:06 indent
jrummell 2013/05/03 23:56:21 Done.
726 10;
727 if (buffer[5] & 0x10) // footer added?
728 size += 10;
729 return size;
730 }
731
732 // Additional checks for a MP3 container.
733 static bool check_mp3(const uint8_t buffer[],
734 size_t buffer_size,
735 bool seenHeader) {
xhwang 2013/05/03 19:59:06 ditto, check buffer_size?
jrummell 2013/05/03 23:56:21 Not sure why? We only return true if we see at lea
736 size_t framesize;
737 size_t numSeen = 0;
738 size_t offset = 0;
739 if (seenHeader)
740 offset = get_mp3_header_size(buffer);
741 while (offset + 3 <= buffer_size &&
742 valid_mpeg_audio_frame_header(Read32(buffer + offset), &framesize)) {
743 ++numSeen;
744 offset += framesize;
745 }
746 return (numSeen > 10 || offset >= buffer_size);
747 }
748
749 // Extract an encoded MPC size, returning the value and
750 // the number of characters used by the size.
751 static int64_t get_mpc8_header_size(const uint8_t* b, size_t* count) {
xhwang 2013/05/03 19:59:06 s/b/buffer and s/count/buffer_size to be consisten
jrummell 2013/05/03 23:56:21 Done s/b/buffer. However, the second is the number
752 int64_t size = 0;
753 uint8_t c;
754 *count = 0;
755 do {
756 c = *b++;
757 if (++(*count) > 10)
758 return -1;
759 size = (size << 7) | (c & 0x7f);
760 } while (c & 0x80);
761 return size;
762 }
763
764 // Additional checks for a MPC8 container.
765 static bool check_mpc8(const uint8_t buffer[], size_t buffer_size) {
766 size_t offset = 4;
767 while (offset < buffer_size - 14) {
xhwang 2013/05/03 19:59:06 size_t -14 is dangerous.
jrummell 2013/05/03 23:56:21 Done.
768 if (!isupper(buffer[offset]) || !isupper(buffer[offset + 1]))
xhwang 2013/05/03 19:59:06 include what you use, add #include <cctype> ?
jrummell 2013/05/03 23:56:21 Done.
769 return false;
770
771 size_t size_characters;
772 int64_t size = get_mpc8_header_size(buffer + offset, &size_characters);
773 if (size < 2)
774 return false;
775 if (buffer[offset] == 'S' && buffer[offset + 1] == 'H') {
776 return (size >= 11 && size <= 28 &&
777 Read32(buffer + offset + size_characters + 2) != 0);
778 }
779 offset = offset + size + size_characters;
780 }
781 return false;
782 }
783
784 // Additional checks for a MSNWCTCP container.
785 static bool check_msnwctcp(const uint8_t buffer[], size_t buffer_size) {
786 // The FFmpeg probe scans through the complete buffer looking for
787 // a matching header. This code only looks for it at the beginning
788 // of the buffer.
789 uint32_t width = Read16(buffer + 2);
xhwang 2013/05/03 19:59:06 check buffer_size before starting to read?
jrummell 2013/05/03 23:56:21 All the checks tagged with "Additional" are only c
790 uint32_t height = Read16(buffer + 4);
791 if (!(width == 320 && height == 240) && !(width == 160 && height == 120))
792 return false;
793 return (buffer_size > 16 && Read32(buffer + 12) != TAG('M','L','2','0'));
794 }
795
796 // Additional checks for a MTV container.
797 static bool check_mtv(const uint8_t buffer[], size_t buffer_size) {
798 if (buffer_size < 58)
799 return false;
800 uint32_t bpp = Read16(buffer + 50);
801 if (bpp != 16)
802 return false;
803 uint32_t width = Read16(buffer + 52);
804 uint32_t height = Read16(buffer + 54);
805 uint32_t segment_size = Read16(buffer + 56);
806 return ((width != 0 && height != 0) || (segment_size != 0));
807 }
808
809 // Additional checks for a NC container.
810 static bool check_nc(const uint8_t buffer[], size_t buffer_size) {
811 uint32_t size = Read16(buffer + 5);
xhwang 2013/05/03 19:59:06 check buffer_size before reading?
jrummell 2013/05/03 23:56:21 Done.
812 return (size + 20 < buffer_size && Read32(buffer + size + 16) == 0x1a5);
813 }
814
815 // Additional checks for a NSV container, only if the header isn't
816 // at the start of the file.
817 static bool check_nsv(const uint8_t buffer[], size_t buffer_size) {
818 // Get the chunk size and check if at the end we are getting 0xBEEF
819 if (buffer_size < 24)
820 return false;
821 size_t vsize = Read24(buffer + 19) >> 4;
822 size_t asize = Read16(buffer + 22);
823 size_t offset = 24 + asize + vsize;
824 return (offset + 2 <= buffer_size && Read16(buffer + offset) == 0xbeef);
825 }
826
827 // Additional checks for an OMA container.
828 static bool check_oma(const uint8_t buffer[], size_t buffer_size) {
829 if (buffer[4] != 0)
xhwang 2013/05/03 19:59:06 check buffer_size before read?
jrummell 2013/05/03 23:56:21 Done.
830 return false;
831 uint32_t tag_len = get_mp3_header_size(buffer);
832 if (tag_len > buffer_size - 6)
833 return false;
834 return (Read24(buffer + tag_len) == TAG(0,'E','A','3') &&
835 buffer[tag_len + 4] == 0 && buffer[tag_len + 5] == 96);
836 }
837
838 // Additional checks for a PJS container.
839 static bool check_pjs(const uint8_t buffer[], size_t buffer_size) {
840 size_t offset = 0;
841 while (buffer[offset] != '"' && offset < buffer_size - 2)
842 ++offset;
843 ++offset;
844 while (buffer[offset] != '"' && offset < buffer_size) {
845 if (buffer[offset] == '\n' || buffer[offset] == '\r')
846 return false;
847 ++offset;
848 }
849 return true;
850 }
851
852 // Additional checks for a PVA container.
853 static bool check_pva(const uint8_t buffer[], size_t buffer_size) {
854 uint32_t length = Read16(buffer + 6);
855 if (buffer[4] != 0x55 || (buffer[5] & 0xe0) != 0 || length > 6136)
856 return false;
857 if (buffer_size < length + 8)
858 return false;
859 return (buffer[length] == 'A' &&
860 buffer[length + 1] == 'V' &&
861 (buffer[length + 2] == 1 || buffer[length + 2] == 2) &&
862 buffer[length + 4] == 0x55 &&
863 (buffer[5] & 0xe0) == 0 &&
864 Read16(buffer + length + 6) <= 6136);
865 }
866
867 // Additional checks for a TIERTEXSEQ container.
868 static bool check_tiertexseq(const uint8_t buffer[], size_t buffer_size) {
869 // No real header, but first 256 bytes are always 0
870 if (buffer_size < 257)
871 return false;
872 for (int i = 0; i < 256; ++i)
873 if (buffer[i] != 0)
874 return false;
875 return (buffer[256] != 0 && buffer[257] != 0);
876 }
877
878 // Additional checks for a TMV container.
879 static bool check_tmv(const uint8_t buffer[], size_t buffer_size) {
880 return (Read16(buffer + 4) >= 5000 && // sample rate
881 Read16(buffer + 6) >= 41 && // audio size
882 buffer[8] == 0 && // compression method
883 buffer[9] != 0 && // width
884 buffer[10] != 0); // height
885 }
886
887 // Additional checks for a VIVO container.
888 static bool check_vivo(const uint8_t buffer[], size_t buffer_size) {
889 if (buffer[0] != 0)
890 return false;
891 uint32_t length = buffer[1] & 0x7f;
892 size_t offset = 2;
893 if ((buffer[1] & 0x80) != 0) {
894 if (buffer[2] & 0x80)
895 return false;
896 length = (length << 7) + (buffer[2] & 0x7f);
897 offset = 3;
898 }
899 if (length < 21 || length > 1024 || offset + 16 > buffer_size)
900 return false;
901 return (CompareEqual(buffer + offset,
902 buffer_size - offset,
903 kVivoSignature,
904 sizeof(kVivoSignature) - 1) &&
905 buffer[offset + 16] >= '0' && buffer[offset + 16] <= '2');
906 }
907
908 // Additional checks for a VMD container.
909 static bool check_vmd(const uint8_t buffer[], size_t buffer_size) {
910 if (buffer_size < 16)
911 return false;
912 uint32_t width = Read16(buffer + 12);
913 uint32_t height = Read16(buffer + 14);
914 return (width > 0 && width <= 2048 && height > 0 && height <= 2048);
915 }
916
917 // Additional checks for a VQF container.
918 static bool check_vqf(const uint8_t buffer[], size_t buffer_size) {
919 return (CompareEqual(buffer + 4, buffer_size - 4, "97012000", 8) ||
920 CompareEqual(buffer + 4, buffer_size - 4, "00052200", 8));
921 }
922
923 // Read a Matroska TAG, updating offset to point past it.
924 static int get_vtag(const uint8_t buffer[], size_t* offset) {
925 // Size of the tag is determined the same way as VINT,
926 // but the bit is not removed. Maximum of 4 bytes.
927 int result = buffer[*offset];
928 if ((result & 0x80) != 0) {
929 // It is a one byte tag
930 ++*offset;
931 }
932 else if ((result & 0x40) != 0) {
933 // It is a 2 byte tag
934 result = Read16(buffer + *offset);
935 *offset += 2;
936 }
937 else if ((result & 0x20) != 0) {
938 // It is a 3 byte tag
939 result = Read24(buffer + *offset);
940 *offset += 3;
941 }
942 else {
943 // It is a 4 byte tag
944 result = Read32(buffer + *offset);
945 *offset += 4;
946 }
947 return result;
948 }
949
950 // Read a Matroska VINT, updating offset to point past it.
951 static int get_vint(const uint8_t buffer[], size_t* offset) {
952 // Length = 1 + [number_of_leading_zero_bits].
953 int size = 1;
954 int mask = 0x80;
955 uint8_t b = buffer[*offset];
956 while (mask > 0 && (b & mask) == 0) {
957 ++size;
958 mask = mask >> 1;
959 }
960
961 // Now that we know the size, use the remaining bits plus
962 // following bytes to get the value.
963 int result = buffer[(*offset)++] & (mask - 1);
964 while (--size > 0)
965 result = (result << 8) | buffer[(*offset)++];
966 return result;
967 }
968
969 // Additional checks for a WEBM container.
970 static bool check_webm(const uint8_t buffer[], size_t buffer_size) {
971 size_t offset = 4;
972 int header_size = get_vint(buffer, &offset);
973 size_t lastoffset = offset + header_size;
974 if (lastoffset > buffer_size)
975 return false;
976 while (offset < lastoffset) {
977 int tag = get_vtag(buffer, &offset);
978 int tagsize = get_vint(buffer, &offset);
979 switch (tag) {
980 case 0x4286: // EBMLVersion
981 case 0x42f7: // EBMLReadVersion
982 case 0x42f2: // EBMLMaxIdLength
983 case 0x42f3: // EBMLMaxSizeLength
984 case 0x4287: // DocTypeVersion
985 case 0x4285: // DocTypeReadVersion
986 case 0xec: // void
987 case 0xbf: // CRC32
988 offset += tagsize;
989 break;
990 case 0x4282: // EBMLDocType
991 return (
992 (tagsize >= 4 &&
993 CompareEqual(buffer + offset, buffer_size - offset, "webm", 4)) ||
994 (tagsize >= 8 &&
995 CompareEqual(
996 buffer + offset, buffer_size - offset, "matroska", 8)));
997 default:
998 // Unrecognized tag
999 return false;
1000 }
1001 }
1002 return false;
1003 }
1004
1005 // Additional checks for a WSAUD container.
1006 static bool check_wsaud(const uint8_t buffer[], size_t buffer_size) {
1007 uint32_t sample_rate = Read16(buffer);
1008 if (sample_rate < 8000 || sample_rate > 48000)
1009 return false;
1010 if ((buffer[10] & 0xfc) != 0 || (buffer[11] != 1 && buffer[11] != 99))
1011 return false;
1012 return (buffer_size > 20 && Read32(buffer + 16) == 0x0000deaf);
1013 }
1014
1015 // Additional checks for a XA container.
1016 static bool check_xa(const uint8_t buffer[], size_t buffer_size) {
1017 if (buffer_size < 14)
1018 return false;
1019 uint32_t channels = Read16(buffer + 10);
1020 if (channels < 1 || channels > 8)
1021 return false;
1022 uint32_t srate = Read16(buffer + 12);
1023 if (srate < 1 || srate > 192000)
1024 return false;
1025 uint32_t bits_per_sample = Read16(buffer + 10);
1026 return (bits_per_sample >= 4 || bits_per_sample <= 32);
1027 }
1028
1029 // Additional checks for a XBIN container.
1030 static bool check_xbin(const uint8_t buffer[], size_t buffer_size) {
1031 uint32_t x = Read16(buffer + 5);
1032 return (buffer[4] == 0x1a &&
1033 x > 0 && x <= 160 &&
1034 buffer[9] > 0 && buffer[9] <= 32);
1035 }
1036
1037 // Additional checks for a XMV container.
1038 static bool check_xmv(const uint8_t buffer[], size_t buffer_size) {
1039 if (buffer_size < 18)
1040 return false;
1041 uint32_t version = Read16(buffer + 16);
1042 return (Read32(buffer + 12) == TAG('x','o','b','X') &&
1043 version > 0 && version <= 4);
1044 }
1045
1046 // Additional checks for a YOP container.
1047 static bool check_yop(const uint8_t buffer[], size_t buffer_size) {
1048 return (buffer_size > 20 &&
1049 buffer[2] < 10 &&
1050 buffer[3] < 10 &&
1051 buffer[6] != 0 &&
1052 buffer[7] != 0 &&
1053 (buffer[8] & 1) == 0 &&
1054 (buffer[10] & 1) == 0 &&
1055 Read16(buffer + 18) >= 920 &&
1056 Read16(buffer + 18) <
1057 static_cast<uint32_t>(buffer[12] * 3 + 4 + buffer[7] * 2048));
1058 }
1059
1060 // Attempt to determine the container type from the buffer provided. This is
1061 // a simple pass, that uses the first 4 bytes of the buffer as an index to get
1062 // a rough idea of the container format. It covers the following containers
1063 // (those with * are not fully covered):
1064 // 4xm, act, aea, aiff, amr, anm, apc, ape, aqtitle, asf, ass, ast, au, avi,
1065 // avr, avs, bethsoftvid, bfi, bink, bit, brstm, c93, caff, cdxl, concat,
1066 // dfa, dnxhd, dsicin, dtshd, dxa, ea, epaf, ffm, ffmetadata, file_cpk, flac,
1067 // flic, flv, frm, gif, gxf, hls, ico, idf, iff, ilbc, ircam, iss, iv8, ivf,
1068 // jv, libnut, lmlm4, lvf, lxf, mgsts, mm, mmf, mov, mp3*, mpc, mpc8,
1069 // msnwctcp*, mtv, mv, nc, nistsphere, nsv*, nut, nuv, ogg, oma, paf, pmp,
1070 // pva, pvf, qcp, r3d, realtext, rl2, rm, roq, rpl, sami, siff, smjpeg, smk,
1071 // smush, sol, sox, swf, tak, thp, tiertexseq, tmv, tta, txd, vc1test, vivo,
1072 // vmd, vobsub, voc, vqf, w64, wav, wc3movie, webm, webvtt, wsaud, wsvqa,
1073 // wtv, wv, xa, xbin, xmv, xwma, yop, yuv4mpegpipe
1074 static FFmpegContainerName LookupContainerByFirst4(const uint8 buffer[],
1075 size_t buffer_size) {
1076 // Minimum size that the code expects to exist without checking size.
1077 if (buffer_size < 12)
1078 return CONTAINER_UNKNOWN;
1079
1080 uint32_t first4 = Read32(buffer);
1081 uint32_t second4 = Read32(buffer + 4);
1082 uint32_t third4 = Read32(buffer + 8);
1083 uint32_t next;
1084
1085 switch (first4) {
1086 case 0:
1087 if (buffer_size > 16 &&
1088 Read16(buffer + 4) == 0x1bc &&
1089 Read32(buffer + 10) == 0 &&
1090 Read16(buffer + 14) == 0xe1e2)
1091 return CONTAINER_GXF;
1092 if (check_mm(buffer, buffer_size))
1093 return CONTAINER_MM;
1094 if (second4 > 0 && second4 <= 1024 * 1024 && Read24(buffer + 8) == 1)
1095 return CONTAINER_LMLM4;
1096 if (check_tiertexseq(buffer, buffer_size))
1097 return CONTAINER_TIERTEXSEQ;
1098 break;
1099 case 1:
1100 if (second4 > 0 && second4 <= 1024 * 1024 && Read24(buffer + 8) == 1)
1101 return CONTAINER_LMLM4;
1102 if (Read16(buffer + 4) != 0)
1103 return CONTAINER_ICO;
1104 break;
1105 case 2:
1106 if (second4 > 0 && second4 <= 1024 * 1024 && Read24(buffer + 8) == 1)
1107 return CONTAINER_LMLM4;
1108 break;
1109 case 4:
1110 if (second4 > 0 && second4 <= 1024 * 1024 &&
1111 (Read16(buffer + 8) & 0xfffe) == 0xfffc)
1112 return CONTAINER_LMLM4;
1113 break;
1114 case 0xe:
1115 if (buffer_size > 16 && second4 == 0x50 && Read32(buffer + 12) == 0x34)
1116 return CONTAINER_MGSTS;
1117 break;
1118 case 0x16:
1119 if (third4 == 0x1803ffff || third4 == 0x1003ffff)
1120 return CONTAINER_TXD;
1121 break;
1122 case 0x1a5:
1123 if (check_nc(buffer, buffer_size))
1124 return CONTAINER_NC;
1125 break;
1126 case TAG('\x00','\x00','\x02','\x80'):
1127 if (check_dnxhd(buffer, buffer_size))
1128 return CONTAINER_DNXHD;
1129 break;
1130 case 0x800:
1131 if (check_aea(buffer, buffer_size))
1132 return CONTAINER_AEA;
1133 break;
1134 case 0x001800a0:
1135 case 0x00180140:
1136 if (check_msnwctcp(buffer, buffer_size))
1137 return CONTAINER_MSNWCTCP;
1138 break;
1139 case TAG('\x00','\x0a','S','M'):
1140 if (CompareEqual(buffer,
1141 buffer_size,
1142 kSmjpegSignature,
1143 sizeof(kSmjpegSignature) - 1))
1144 return CONTAINER_SMJPEG;
1145 break;
1146 case 0x1084ffff:
1147 if (Read16(buffer + 4) == 0xffff)
1148 return CONTAINER_ROQ;
1149 break;
1150 case TAG('\x01','\x01','\x03','\xb8'):
1151 if (CompareEqual(buffer,
1152 buffer_size,
1153 kIv8Signature,
1154 sizeof(kIv8Signature) - 1))
1155 return CONTAINER_IV8;
1156 break;
1157 case TAG('\x04','\x31','\x2e','\x34'):
1158 if (CompareEqual(buffer,
1159 buffer_size,
1160 kIdfSignature,
1161 sizeof(kIdfSignature) - 1))
1162 return CONTAINER_IDF;
1163 break;
1164 case TAG('\x0b','\x8d','S','O'):
1165 case TAG('\x0c','\x0d','S','O'):
1166 case TAG('\x0c','\x8d','S','O'):
1167 if (buffer[4] == 'L' && buffer[5] == 0)
1168 return CONTAINER_SOL;
1169 break;
1170 case 0x1a45dfa3:
1171 if (check_webm(buffer, buffer_size))
1172 return CONTAINER_WEBM;
1173 break;
1174 case TAG('.','s','n','d'):
1175 return CONTAINER_AU;
1176 case TAG('\x30','\x26','\xB2','\x75'):
1177 if (CompareEqual(buffer,
1178 buffer_size,
1179 kAsfSignature,
1180 sizeof(kAsfSignature) - 1))
1181 return CONTAINER_ASF;
1182 break;
1183 case TAG(' ','p','a','f'):
1184 if (buffer_size > 24 &&
1185 second4 == 0 && third4 == 0 &&
1186 Read32(buffer + 12) != 0 &&
1187 Read32(buffer + 20) != 0)
1188 return CONTAINER_EPAF;
1189 break;
1190 case TAG('#','!','A','M'):
1191 if (CompareEqual(buffer,
1192 buffer_size,
1193 kAmrSignature,
1194 sizeof(kAmrSignature) - 1))
1195 return CONTAINER_AMR;
1196 break;
1197 case TAG('#','!','i','L'):
1198 if (CompareEqual(buffer,
1199 buffer_size,
1200 kIlbcSignature,
1201 sizeof(kIlbcSignature) - 1))
1202 return CONTAINER_ILBC;
1203 break;
1204 case TAG('#','E','X','T'):
1205 if (check_hls(buffer, buffer_size))
1206 return CONTAINER_HLS;
1207 break;
1208 case TAG('#',' ','V','o'):
1209 if (CompareEqual(buffer,
1210 buffer_size,
1211 kVobsubSignature,
1212 sizeof(kVobsubSignature) - 1))
1213 return CONTAINER_VOBSUB;
1214 break;
1215 case TAG('.','R','M','F'):
1216 if (buffer[4] == 0 && buffer[5] == 0)
1217 return CONTAINER_RM;
1218 break;
1219 case TAG('.','r','a','\xfd'):
1220 return CONTAINER_RM;
1221 case TAG('.','S','o','X'):
1222 case TAG('X','o','S','.'):
1223 return CONTAINER_SOX;
1224 case TAG('1','S','N','h'):
1225 case TAG('S','C','H','l'):
1226 case TAG('S','E','A','D'):
1227 case TAG('S','H','E','N'):
1228 case TAG('k','V','G','T'):
1229 case TAG('M','A','D','k'):
1230 case TAG('M','P','C','h'):
1231 case TAG('M','V','h','d'):
1232 if ((second4 > 0x0fffff) && ((second4 & 0x0f0ff) != 0))
1233 return CONTAINER_EA;
1234 break;
1235 case TAG('2','B','I','T'):
1236 return CONTAINER_AVR;
1237 case TAG('A','N','I','M'):
1238 if (third4 == TAG('A','H','D','R'))
1239 return CONTAINER_SMUSH;
1240 break;
1241 case TAG('A','R','M','o'):
1242 if (CompareEqual(buffer,
1243 buffer_size,
1244 kRplSignature,
1245 sizeof(kRplSignature) - 1))
1246 return CONTAINER_RPL;
1247 break;
1248 case TAG('B','B','C','D'):
1249 return CONTAINER_DIRAC;
1250 case TAG('B','F','&','I'):
1251 return CONTAINER_BFI;
1252 case TAG(';','F','F','M'):
1253 if (CompareEqual(buffer,
1254 buffer_size,
1255 kFfSignature,
1256 sizeof(kFfSignature) - 1))
1257 return CONTAINER_FFMETADATA;
1258 break;
1259 case TAG('B','I','K','b'):
1260 case TAG('B','I','K','f'):
1261 case TAG('B','I','K','g'):
1262 case TAG('B','I','K','h'):
1263 case TAG('B','I','K','i'):
1264 if (check_bink(buffer, buffer_size))
1265 return CONTAINER_BINK;
1266 break;
1267 case TAG('c','a','f','f'):
1268 if (Read16(buffer + 4) == 1)
1269 return CONTAINER_CAF;
1270 break;
1271 case TAG('C','r','e','a'):
1272 if (CompareEqual(buffer,
1273 buffer_size,
1274 kVocSignature,
1275 sizeof(kVocSignature) - 1))
1276 return CONTAINER_VOC;
1277 break;
1278 case TAG('C','R','Y','O'):
1279 if (CompareEqual(buffer,
1280 buffer_size,
1281 kApcSignature,
1282 sizeof(kApcSignature) - 1))
1283 return CONTAINER_APC;
1284 break;
1285 case TAG('D','E','X','A'):
1286 if (buffer_size > 15 &&
1287 Read16(buffer + 11) <= 2048 &&
1288 Read16(buffer + 13) <= 2048)
1289 return CONTAINER_DXA;
1290 break;
1291 case TAG('D','K','I','F'):
1292 if (second4 == 32)
1293 return CONTAINER_IVF;
1294 break;
1295 case TAG('D','T','S','H'):
1296 if (second4 == TAG('D','H','D','R'))
1297 return CONTAINER_DTSHD;
1298 break;
1299 case TAG('D','F','I','A'):
1300 return CONTAINER_DFA;
1301 case TAG('\x64','\xa3','\x01','\x00'):
1302 case TAG('\x64','\xa3','\x02','\x00'):
1303 case TAG('\x64','\xa3','\x03','\x00'):
1304 case TAG('\x64','\xa3','\x04','\x00'):
1305 case TAG('\x00','\x01','\xa3','\x64'):
1306 case TAG('\x00','\x02','\xa3','\x64'):
1307 case TAG('\x00','\x03','\xa3','\x64'):
1308 if (second4 != 0 && third4 != 0)
1309 return CONTAINER_IRCAM;
1310 break;
1311 case TAG('e','a','3','\x03'):
1312 if (check_oma(buffer, buffer_size))
1313 return CONTAINER_OMA;
1314 break;
1315 case TAG('f','a','p',' '):
1316 if (buffer_size > 24 &&
1317 second4 == 0 && third4 == 1 &&
1318 Read32(buffer + 12) != 0 &&
1319 Read32(buffer + 20) != 0)
1320 return CONTAINER_EPAF;
1321 break;
1322 case TAG('f','f','c','o'):
1323 if (CompareEqual(buffer,
1324 buffer_size,
1325 kConcatSignature,
1326 sizeof(kConcatSignature) - 1))
1327 return CONTAINER_CONCAT;
1328 break;
1329 case TAG('F','F','M','1'):
1330 case TAG('F','F','M','2'):
1331 return CONTAINER_FFM;
1332 case TAG('F','I','L','M'):
1333 return CONTAINER_FILM_CPK;
1334 case TAG('f','L','a','C'):
1335 return CONTAINER_FLAC;
1336 case TAG('F','L','V','\x00'):
1337 case TAG('F','L','V','\x01'):
1338 case TAG('F','L','V','\x02'):
1339 case TAG('F','L','V','\x03'):
1340 case TAG('F','L','V','\x04'):
1341 if (buffer[5] == 0 && Read32(buffer + 5) > 8)
1342 return CONTAINER_FLV;
1343 break;
1344 case TAG('F','O','R','M'):
1345 switch (third4) {
1346 case TAG('A','I','F','F'):
1347 case TAG('A','I','F','C'):
1348 return CONTAINER_AIFF;
1349 case TAG('8','S','V','X'):
1350 case TAG('1','6','S','V'):
1351 case TAG('M','A','U','D'):
1352 case TAG('P','B','M',' '):
1353 case TAG('A','C','B','M'):
1354 case TAG('D','E','E','P'):
1355 case TAG('I','L','B','M'):
1356 case TAG('R','G','B','8'):
1357 case TAG('R','G','B','N'):
1358 return CONTAINER_IFF;
1359 case TAG('M','O','V','E'):
1360 return CONTAINER_WC3MOVIE;
1361 case TAG('R','L','V','2'):
1362 case TAG('R','L','V','3'):
1363 return CONTAINER_RL2;
1364 case TAG('W','V','Q','A'):
1365 return CONTAINER_WSVQA;
1366 }
1367 break;
1368 case TAG('G','I','F','8'):
1369 if ((buffer[4] == '7' || buffer[4] == '9') &&
1370 buffer[5] == 'a' &&
1371 Read16(buffer + 6) != 0 &&
1372 Read16(buffer + 8) != 0)
1373 return CONTAINER_GIF;
1374 break;
1375 case TAG('I','M','A','_'):
1376 if (CompareEqual(buffer,
1377 buffer_size,
1378 kIssSignature,
1379 sizeof(kIssSignature) - 1))
1380 return CONTAINER_ISS;
1381 break;
1382 case TAG('k','!','\x00','\x40'):
1383 case TAG('k','!','\x00','\x50'):
1384 return CONTAINER_BIT;
1385 case TAG('L','E','I','T'):
1386 if (CompareEqual(buffer,
1387 buffer_size,
1388 kLxfSignature,
1389 sizeof(kLxfSignature) - 1))
1390 return CONTAINER_LXF;
1391 break;
1392 case TAG('L','P','F',' '):
1393 if (buffer_size > 24 &&
1394 Read32(buffer + 16) == TAG('A','N','I','M') &&
1395 Read16(buffer + 20) != 0 &&
1396 Read16(buffer + 22) != 0)
1397 return CONTAINER_ANM;
1398 break;
1399 case TAG('L','V','F','F'):
1400 return CONTAINER_LVF;
1401 case TAG('M','A','C',' '):
1402 return CONTAINER_APE;
1403 case TAG('M','M','M','D'):
1404 if (third4 == TAG('C','N','T','I'))
1405 return CONTAINER_MMF;
1406 break;
1407 case TAG('M','O','V','I'):
1408 if (Read16(buffer + 4) < 3)
1409 return CONTAINER_MV;
1410 break;
1411 case TAG('M','P','+','\x07'):
1412 case TAG('M','P','+','\x17'):
1413 return CONTAINER_MPC;
1414 case TAG('M','P','C','K'):
1415 if (check_mpc8(buffer, buffer_size))
1416 return CONTAINER_MPC8;
1417 break;
1418 case TAG('N','I','S','T'):
1419 if (second4 == TAG('_','1','A','\x0a'))
1420 return CONTAINER_NISTSPHERE;
1421 break;
1422 case TAG('N','M','\x7a','\x56'):
1423 if (second4 == TAG('\x1F','\x5F','\x04','\xAD'))
1424 return CONTAINER_NUT;
1425 break;
1426 case TAG('N','S','V','f'):
1427 case TAG('N','S','V','s'):
1428 return CONTAINER_NSV;
1429 case TAG('n','u','t','/'):
1430 if (CompareEqual(buffer,
1431 buffer_size,
1432 kLibnutSignature,
1433 sizeof(kLibnutSignature) - 1))
1434 return CONTAINER_LIBNUT;
1435 break;
1436 case TAG('N','u','p','p'):
1437 if (CompareEqual(buffer,
1438 buffer_size,
1439 kNuv1Signature,
1440 sizeof(kNuv1Signature) - 1))
1441 return CONTAINER_NUV;
1442 break;
1443 case TAG('M','y','t','h'):
1444 if (CompareEqual(buffer,
1445 buffer_size,
1446 kNuv2Signature,
1447 sizeof(kNuv2Signature) - 1))
1448 return CONTAINER_NUV;
1449 break;
1450 case TAG('O','N','2',' '):
1451 if (third4 == TAG('O','N','2','f'))
1452 return CONTAINER_AVI;
1453 case TAG('O','g','g','S'):
1454 if (buffer[5] <= 7)
1455 return CONTAINER_OGG;
1456 break;
1457 case TAG('P','a','c','k'):
1458 if (CompareEqual(buffer,
1459 buffer_size,
1460 kPafSignature,
1461 sizeof(kPafSignature) - 1))
1462 return CONTAINER_PAF;
1463 break;
1464 case TAG('p','m','p','m'):
1465 if (Read32(buffer + 4) == 1)
1466 return CONTAINER_PMP;
1467 break;
1468 case TAG('P','V','F','1'):
1469 if (buffer[4] == '\n')
1470 return CONTAINER_PVF;
1471 break;
1472 case TAG('R','F','6','4'):
1473 if (buffer_size > 16 && Read32(buffer + 12) == TAG('d','s','6','4'))
1474 return CONTAINER_WAV;
1475 break;
1476 case TAG('r','i','f','f'):
1477 if (CompareEqual(buffer,
1478 buffer_size,
1479 kW64Signature,
1480 sizeof(kW64Signature) - 1) &&
1481 CompareEqual(buffer + 24,
1482 buffer_size - 24,
1483 kW64Signature2,
1484 sizeof(kW64Signature2) - 1))
1485 return CONTAINER_W64;
1486 break;
1487 case TAG('R','I','F','F'):
1488 switch (third4) {
1489 case TAG('4','X','M','V'):
1490 return CONTAINER_4XM;
1491 case TAG('A','V','I',' '):
1492 case TAG('A','V','I','X'):
1493 case TAG('A','V','I','\x19'):
1494 case TAG('A','M','V',' '):
1495 return CONTAINER_AVI;
1496 case TAG('Q','L','C','M'):
1497 if (buffer_size > 16 && Read32(buffer + 12) == TAG('f','m','t',' '))
1498 return CONTAINER_QCP;
1499 break;
1500 case TAG('W','A','V','E'):
1501 // possibly ACT or WAV
1502 return (check_act(buffer, buffer_size)) ?
1503 CONTAINER_ACT : CONTAINER_WAV;
1504 case TAG('X','W','M','A'):
1505 return CONTAINER_XWMA;
1506 }
1507 break;
1508 case TAG('R','S','T','M'):
1509 next = Read16(buffer + 4);
1510 if (next == 0xfffe || next == 0xfeff)
1511 return CONTAINER_BRSTM;
1512 break;
1513 case TAG('S','A','N','M'):
1514 if (third4 == TAG('S','H','D','R'))
1515 return CONTAINER_SMUSH;
1516 break;
1517 case TAG('S','I','F','F'):
1518 if (third4 == TAG('V','B','V','1') || third4 == TAG('S','O','U','N'))
1519 return CONTAINER_SIFF;
1520 break;
1521 case TAG('S','M','K','2'):
1522 case TAG('S','M','K','4'):
1523 return CONTAINER_SMK;
1524 case TAG('S','T','R','M'):
1525 if (buffer_size > 18 && Read16(buffer + 10) && Read16(buffer + 12) &&
1526 Read16(buffer + 16))
1527 return CONTAINER_AST;
1528 break;
1529 case TAG('t','B','a','K'):
1530 return CONTAINER_TAK;
1531 case TAG('T','H','P','\x00'):
1532 return CONTAINER_THP;
1533 case TAG('T','M','A','V'):
1534 if (check_tmv(buffer, buffer_size))
1535 return CONTAINER_TMV;
1536 break;
1537 case TAG('T','T','A','1'):
1538 return CONTAINER_TTA;
1539 case TAG('\x55','\xaa','\x00','\x00'):
1540 if (check_dsicin(buffer, buffer_size))
1541 return CONTAINER_DSICIN;
1542 break;
1543 case TAG('T','W','I','N'):
1544 if (check_vqf(buffer, buffer_size))
1545 return CONTAINER_VQF;
1546 break;
1547 case TAG('V','I','D','\x00'):
1548 return CONTAINER_BETHSOFTVID;
1549 case TAG('w','W','\x10','\x00'):
1550 return CONTAINER_AVS;
1551 case TAG('w','v','p','k'):
1552 return CONTAINER_WV;
1553 case TAG('X','A','\x00','\x00'):
1554 case TAG('X','A','I','\x00'):
1555 case TAG('X','A','J','\x00'):
1556 if (check_xa(buffer, buffer_size))
1557 return CONTAINER_XA;
1558 break;
1559 case TAG('X','B','I','N'):
1560 if (check_xbin(buffer, buffer_size))
1561 return CONTAINER_XBIN;
1562 break;
1563 case TAG('Y','U','V','4'):
1564 if (CompareEqual(buffer,
1565 buffer_size,
1566 kYuv4Signature,
1567 sizeof(kYuv4Signature) - 1))
1568 return CONTAINER_YUV4MPEGPIPE;
1569 break;
1570 case TAG('W','E','B','V'):
1571 if (CompareEqual(buffer,
1572 buffer_size,
1573 kWebvttSignature,
1574 sizeof(kWebvttSignature) - 1))
1575 return CONTAINER_WEBVTT;
1576 break;
1577 case TAG('\xef','\xbb','\xbf','W'):
1578 if (CompareEqual(buffer,
1579 buffer_size,
1580 kWebvttBomSignature,
1581 sizeof(kWebvttBomSignature) - 1))
1582 return CONTAINER_WEBVTT;
1583 break;
1584 case TAG('[','S','c','r'):
1585 if (CompareEqual(buffer,
1586 buffer_size,
1587 kAssSignature,
1588 sizeof(kAssSignature) - 1))
1589 return CONTAINER_ASS;
1590 break;
1591 case TAG('\xef','\xbb','\xbf','['):
1592 if (CompareEqual(buffer,
1593 buffer_size,
1594 kAssBomSignature,
1595 sizeof(kAssBomSignature) - 1))
1596 return CONTAINER_ASS;
1597 break;
1598 case TAG('<','w','i','n'):
1599 if (CompareEqual(buffer,
1600 buffer_size,
1601 kRealSignature,
1602 sizeof(kRealSignature) - 1))
1603 return CONTAINER_REALTEXT;
1604 break;
1605 case TAG('<','S','A','M'):
1606 if (CompareEqual(buffer,
1607 buffer_size,
1608 kSamiSignature,
1609 sizeof(kSamiSignature) - 1))
1610 return CONTAINER_SAMI;
1611 break;
1612 case TAG('\xef','\xbb','\xbf','<'):
1613 if (CompareEqual(buffer,
1614 buffer_size,
1615 kRealBomSignature,
1616 sizeof(kRealBomSignature) - 1))
1617 return CONTAINER_REALTEXT;
1618 if (CompareEqual(buffer,
1619 buffer_size,
1620 kSamiBomSignature,
1621 sizeof(kSamiBomSignature) - 1))
1622 return CONTAINER_SAMI;
1623 break;
1624 case TAG('\xb7','\xd8','\x00','\x20'):
1625 if (CompareEqual(buffer,
1626 buffer_size,
1627 kWtvSignature,
1628 sizeof(kWtvSignature) - 1))
1629 return CONTAINER_WTV;
1630 break;
1631 }
1632
1633 // Now try a few different ones that look at something other
1634 // than the first 4 bytes
1635 uint32_t first3 = first4 & 0xffffff00;
1636 switch (first3) {
1637 case TAG('A','M','V',0):
1638 if (check_mtv(buffer, buffer_size))
1639 return CONTAINER_MTV;
1640 break;
1641 case TAG('C','W','S',0):
1642 case TAG('F','W','S',0):
1643 return CONTAINER_SWF;
1644 case TAG('F','R','M',0):
1645 if (Read16(buffer + 4) != 0 && Read16(buffer + 6) != 0)
1646 return CONTAINER_FRM;
1647 break;
1648 case TAG('A','V','\x01',0):
1649 case TAG('A','V','\x02',0):
1650 if (check_pva(buffer, buffer_size))
1651 return CONTAINER_PVA;
1652 break;
1653 case TAG('I','D','3',0):
1654 if (check_mp3(buffer, buffer_size, true))
1655 return CONTAINER_MP3;
1656 break;
1657 }
1658
1659 // Maybe the first 2 characters are something we can use.
1660 uint32_t first2 = first4 & 0xffff0000;
1661 switch (first2) {
1662 case 0x032e0000:
1663 if (check_vmd(buffer, buffer_size))
1664 return CONTAINER_VMD;
1665 break;
1666 case 0x04000000:
1667 case 0x04040000:
1668 case 0x040c0000:
1669 case 0x04140000:
1670 return CONTAINER_EA_CDATA;
1671 case TAG('J','V',0,0):
1672 if (CompareEqual(buffer + 4,
1673 buffer_size - 4,
1674 kJvSignature,
1675 sizeof(kJvSignature) - 1))
1676 return CONTAINER_JV;
1677 break;
1678 case 0x0b770000:
1679 if (check_ac3(buffer, buffer_size))
1680 return CONTAINER_AC3;
1681 if (check_eac3(buffer, buffer_size))
1682 return CONTAINER_EAC3;
1683 break;
1684 case TAG('Y','O',0,0):
1685 if (check_yop(buffer, buffer_size))
1686 return CONTAINER_JV;
1687 break;
1688 case 0xfff00000:
1689 case 0xfff10000:
1690 case 0xfff80000:
1691 case 0xfff90000:
1692 if (check_aac(buffer, buffer_size))
1693 return CONTAINER_AAC;
1694 break;
1695 }
1696
1697 // Now try the second set of 4 characters.
1698 switch (second4) {
1699 case 4:
1700 if (buffer_size > 24 && buffer[3] == 0xc5 && Read32(buffer + 20) == 0xc)
1701 return CONTAINER_VC1TEST;
1702 break;
1703 case TAG('R','E','D','1'):
1704 return CONTAINER_R3D;
1705 }
1706
1707 switch (Read16(buffer + 4)) {
1708 case 0xaf11:
1709 case 0xaf12:
1710 case 0xaf13:
1711 if (buffer_size > 20 &&
1712 third4 <= 4096 &&
1713 Read16(buffer + 10) <= 4096 &&
1714 (Read16(buffer + 16) == 0xf1fa || Read32(buffer + 16) <= 2000))
1715 return CONTAINER_FLIC;
1716 break;
1717 }
1718
1719 // Lastly, there are some that are other simple checks but don't fit
1720 // the above case statements.
1721 if (check_c93(buffer, buffer_size))
1722 return CONTAINER_C93;
1723 if (check_cdxl(buffer, buffer_size))
1724 return CONTAINER_CDXL;
1725 if (check_idcin(buffer, buffer_size))
1726 return CONTAINER_IDCIN;
1727 if (check_loas(buffer, buffer_size))
1728 return CONTAINER_LOAS;
1729 if (check_m4v(buffer, buffer_size))
1730 return CONTAINER_M4V;
1731 if (check_mov(buffer, buffer_size))
1732 return CONTAINER_MOV;
1733 if (check_vivo(buffer, buffer_size))
1734 return CONTAINER_VIVO;
1735 if (check_wsaud(buffer, buffer_size))
1736 return CONTAINER_WSAUD;
1737 if (check_xmv(buffer, buffer_size))
1738 return CONTAINER_XMV;
1739 // Check if the file is in MP3 format without the header
1740 if (check_mp3(buffer, buffer_size, false))
1741 return CONTAINER_MP3;
1742
1743 // skip over starting 0's, and see if it is MP3/AC3/EAC3
1744 if (buffer[0] == 0) {
1745 size_t offset = 1;
1746 size_t remaining = buffer_size - 1;
1747 while (remaining > 0 && buffer[offset] == 0) {
1748 ++offset;
1749 --remaining;
1750 }
1751 if (remaining > 32) {
1752 // not worth trying if only a small number of bytes left
1753 if (Read16(buffer + offset) == 0x0b77) {
1754 if (check_ac3(buffer + offset, remaining))
1755 return CONTAINER_AC3;
1756 if (check_eac3(buffer + offset, remaining))
1757 return CONTAINER_EAC3;
1758 }
1759 else if (check_mp3(buffer + offset, remaining, false))
1760 return CONTAINER_MP3;
1761 }
1762 }
1763
1764 return CONTAINER_UNKNOWN;
1765 }
1766
1767 static const char ipm_string[] = "Interplay MVE File\x1A\0\x1A";
1768 static const char mxf_string[] =
1769 "\x06\x0e\x2b\x34\x02\x05\x01\x01\x0d\x01\x02\x01\x01\x02";
1770 static const char sub1_string[] = "******** START SCRIPT ********";
1771
1772 // Attempt to determine the container type by scanning for a set of strings,
1773 // character by character. It covers the following containers:
1774 // ipmovie, mxf, subviewer1
1775 static FFmpegContainerName LookupContainerByStringScan(const uint8 buffer[],
1776 size_t buffer_size) {
1777 size_t offset = 0;
1778 size_t remaining = buffer_size;
1779 while (offset + 4 < buffer_size) {
1780 uint32_t tag = Read32(buffer + offset);
1781 switch (tag) {
1782 case TAG('I','n','t','e'):
1783 if (CompareEqual(buffer + offset,
1784 remaining,
1785 ipm_string,
1786 sizeof(ipm_string) - 1))
1787 return CONTAINER_IPMOVIE;
1788 break;
1789 case 0x060e2b34:
1790 if (CompareEqual(buffer + offset,
1791 remaining,
1792 mxf_string,
1793 sizeof(mxf_string) - 1))
1794 return CONTAINER_MXF;
1795 break;
1796 case TAG('*','*','*','*'):
1797 if (CompareEqual(buffer + offset,
1798 remaining,
1799 sub1_string,
1800 sizeof(sub1_string) - 1))
1801 return CONTAINER_SUBVIEWER1;
1802 break;
1803 case TAG('N','S','V','s'):
1804 if (check_nsv(buffer + offset, remaining))
1805 return CONTAINER_NSV;
1806 break;
1807 case 0x001800a0:
1808 case 0x00180140:
1809 if (check_msnwctcp(buffer + offset, remaining))
1810 return CONTAINER_MSNWCTCP;
1811 break;
1812 }
1813
1814 // Not found, move forward to next character.
1815 ++offset;
1816 --remaining;
1817 }
1818
1819 // didn't find a string match for any of the formats
1820 return CONTAINER_UNKNOWN;
1821 }
1822
1823 // Helper function to do limited scanf functionality without going off
1824 // the end of the buffer.
1825 static bool SaferScanf(const uint8_t* buffer,
1826 size_t buffer_size,
1827 const char* format) {
1828 // This function only supports the following items in the format string:
1829 // %<maxlength>d -- integer (can start with +/-, maxlength is optional)
1830 // %<maxlength>u -- unsigned integer (only digits, maxlength is optional)
1831 // %c -- any single character
1832 // %[<characters>] -- character must be one of the set
1833 // -- everything else is a literal
1834 // This code assumes that format is correct.
1835 size_t offset = 0;
1836 while (offset < buffer_size) {
1837 // Determine next format item.
1838 if (*format == '\0') {
1839 // End of format string, success.
1840 return true;
1841 } else if (*format != '%') {
1842 // Not a specifier, so it must match exactly
1843 if (buffer[offset] != *format)
1844 return false;
1845 ++offset;
1846 } else {
1847 ++format;
1848 int maxLength = 0;
1849 int numSeen = 0;
1850 while (isdigit(*format)) {
1851 maxLength = maxLength * 10 + (*format - '0');
1852 ++format;
1853 }
1854 if (maxLength < 1) // If not specified set it to 100 to simplify below
1855 maxLength = 100;
1856 switch (*format) {
1857 case 'c':
1858 ++offset; // Don't care what the character is
1859 break;
1860 case 'd':
1861 if (buffer[offset] == '+' || buffer[offset] == '-')
1862 ++offset;
1863 case 'u':
1864 // need to process up to maxLength digits
1865 while (offset < buffer_size &&
1866 --maxLength >= 0 &&
1867 isdigit(buffer[offset])) {
1868 ++numSeen;
1869 ++offset;
1870 }
1871 if (numSeen == 0) // No digits, so it is not a match for %d/%u
1872 return false;
1873 break;
1874 case '[':
1875 ++format; // Skip [
1876 while (*format != ']') {
1877 if (buffer[offset] == *format) {
1878 ++numSeen;
1879 }
1880 ++format;
1881 }
1882 if (numSeen == 0) // No character match
1883 return false;
1884 ++offset; // Skip the character matched
1885 break;
1886 default:
1887 NOTREACHED();
1888 }
1889 }
1890 // Move to the next format specification.
1891 ++format;
1892 }
1893 // Out of buffer, so it doesn't match
1894 return false;
1895 }
1896
1897 // Attempt to determine the container type by scanning for a set of strings,
1898 // line by line. It covers the following containers:
1899 // microdvd, mpl2, mpsub, pjs, sdp, srt, subviewer, vplayer
1900 static FFmpegContainerName LookupContainerByStringLine(const uint8 buffer[],
1901 size_t buffer_size) {
1902 size_t offset = CompareEqual(buffer, buffer_size, BYTE_ORDER_MARK, 3) ? 3 : 0;
1903 size_t lines = 0;
1904
1905 // PJS is a scan from the beginning only.
1906 if (SaferScanf(buffer, buffer_size, "%d,%d,%c"))
1907 if (check_pjs(buffer, buffer_size))
1908 return CONTAINER_PJS;
1909
1910 // Same for VPLAYER.
1911 if (SaferScanf(buffer, buffer_size, "%d:%d:%d.%d%[: =]"))
1912 return CONTAINER_VPLAYER;
1913
1914 // Same for AQTITLE
1915 if (SaferScanf(buffer, buffer_size, "-->> %d"))
1916 return CONTAINER_AQTITLE;
1917
1918 while (offset < buffer_size) {
1919 const uint8_t* ptr = buffer + offset;
1920 size_t remaining = buffer_size - offset;;
1921
1922 if (*ptr == '{' && lines < 3) {
1923 if (SaferScanf(ptr, remaining, "{%d}{}%c") ||
1924 SaferScanf(ptr, remaining, "{%d}{%d}%c") ||
1925 SaferScanf(ptr, remaining, "{DEFAULT}{}%c"))
1926 return CONTAINER_MICRODVD;
1927 }
1928
1929 if (*ptr == '[' && lines < 3) {
1930 if (SaferScanf(ptr, remaining, "[%64d][%64d]%c") ||
1931 SaferScanf(ptr, remaining, "[%64d][]%c"))
1932 return CONTAINER_MPL2;
1933 }
1934
1935 if (*ptr == 'F') {
1936 if (SaferScanf(ptr, remaining, "FORMAT=%d") ||
1937 SaferScanf(ptr, remaining, "FORMAT=TIME"))
1938 return CONTAINER_MPSUB;
1939 }
1940
1941 if (*ptr == 'c') {
1942 if (CompareEqual(ptr, remaining, "c=IN IP", 7))
1943 return CONTAINER_SDP;
1944 }
1945
1946 if (isdigit(*ptr) && lines < 3) {
1947 if (SaferScanf(
1948 ptr, remaining, "%d:%2d:%2d%[,.]%3d --> %d:%2d:%2d%[,.]%3d"))
1949 return CONTAINER_SRT;
1950 }
1951
1952 if (isdigit(*ptr) && lines < 1) {
1953 if (SaferScanf(ptr, remaining, "%u:%u:%u.%u,%u:%u:%u.%u%c") ||
1954 CompareEqual(ptr, remaining, "[INFORMATION]", 13))
1955 return CONTAINER_SUBVIEWER;
1956 }
1957
1958 // Find the end of the line.
1959 while (buffer[offset] != '\n' && buffer[offset] != '\r' &&
1960 offset < buffer_size)
1961 ++offset;
1962
1963 // Skip the \n\r.
1964 while ((buffer[offset] == '\n' || buffer[offset] == '\r') &&
1965 offset < buffer_size)
1966 ++offset;
1967 ++lines;
1968 }
1969
1970 // Didn't find a string match for any of the formats.
1971 return CONTAINER_UNKNOWN;
1972 }
1973
1974 // The strings in the list below are the ones returned by FFmpeg.
1975 // This would be the string from AVInputFormat.name. The list is
1976 // sorted by string alphabetically, so that we can use a binary
1977 // search when looking for a container by name.
1978 const ContainerNameMapping ContainerNames::container_name_mapping[] = {
1979 { CONTAINER_4XM, "4xm" },
1980 { CONTAINER_AAC, "aac" },
1981 { CONTAINER_AC3, "ac3" },
1982 { CONTAINER_ACT, "act" },
1983 { CONTAINER_ADF, "adf" },
1984 { CONTAINER_ADX, "adx" },
1985 { CONTAINER_AEA, "aea" },
1986 { CONTAINER_AFC, "afc" },
1987 { CONTAINER_AIFF, "aiff" },
1988 { CONTAINER_ALAW, "alaw" },
1989 { CONTAINER_ALSA, "alsa" },
1990 { CONTAINER_AMR, "amr" },
1991 { CONTAINER_ANM, "anm" },
1992 { CONTAINER_APC, "apc" },
1993 { CONTAINER_APE, "ape" },
1994 { CONTAINER_AQTITLE, "aqtitle" },
1995 { CONTAINER_ASF, "asf" },
1996 { CONTAINER_ASS, "ass" },
1997 { CONTAINER_AST, "ast" },
1998 { CONTAINER_AU, "au" },
1999 { CONTAINER_AVI, "avi" },
2000 { CONTAINER_AVISYNTH, "avisynth" },
2001 { CONTAINER_AVR, "avr" },
2002 { CONTAINER_AVS, "avs" },
2003 { CONTAINER_BETHSOFTVID, "bethsoftvid" },
2004 { CONTAINER_BFI, "bfi" },
2005 { CONTAINER_BIN, "bin" },
2006 { CONTAINER_BINK, "bink" },
2007 { CONTAINER_BIT, "bit" },
2008 { CONTAINER_BKTR, "bktr" },
2009 { CONTAINER_BMV, "bmv" },
2010 { CONTAINER_BRSTM, "brstm" },
2011 { CONTAINER_C93, "c93" },
2012 { CONTAINER_CAF, "caf" },
2013 { CONTAINER_CAVSVIDEO, "cavsvideo" },
2014 { CONTAINER_CDG, "cdg" },
2015 { CONTAINER_CDXL, "cdxl" },
2016 { CONTAINER_CONCAT, "concat" },
2017 { CONTAINER_DAUD, "daud" },
2018 { CONTAINER_DFA, "dfa" },
2019 { CONTAINER_DIRAC, "dirac" },
2020 { CONTAINER_DNXHD, "dnxhd" },
2021 { CONTAINER_DSHOW, "dshow" },
2022 { CONTAINER_DSICIN, "dsicin" },
2023 { CONTAINER_DTS, "dts" },
2024 { CONTAINER_DTSHD, "dtshd" },
2025 { CONTAINER_DV, "dv" },
2026 { CONTAINER_DV1394, "dv1394" },
2027 { CONTAINER_DXA, "dxa" },
2028 { CONTAINER_EA, "ea" },
2029 { CONTAINER_EA_CDATA, "ea_cdata" },
2030 { CONTAINER_EAC3, "eac3" },
2031 { CONTAINER_EPAF, "epaf" },
2032 { CONTAINER_F32BE, "f32be" },
2033 { CONTAINER_F32LE, "f32le" },
2034 { CONTAINER_F64BE, "f64be" },
2035 { CONTAINER_F64LE, "f64le" },
2036 { CONTAINER_FBDEV, "fbdev" },
2037 { CONTAINER_FFM, "ffm" },
2038 { CONTAINER_FFMETADATA, "ffmetadata" },
2039 { CONTAINER_FILM_CPK, "film_cpk" },
2040 { CONTAINER_FILMSTRIP, "filmstrip" },
2041 { CONTAINER_FLAC, "flac" },
2042 { CONTAINER_FLIC, "flic" },
2043 { CONTAINER_FLV, "flv" },
2044 { CONTAINER_FRM, "frm" },
2045 { CONTAINER_G722, "g722" },
2046 { CONTAINER_G723_1, "g723_1" },
2047 { CONTAINER_G729, "g729" },
2048 { CONTAINER_GIF, "gif" },
2049 { CONTAINER_GSM, "gsm" },
2050 { CONTAINER_GXF, "gxf" },
2051 { CONTAINER_H261, "h261" },
2052 { CONTAINER_H263, "h263" },
2053 { CONTAINER_H264, "h264" },
2054 { CONTAINER_HLS, "hls,applehttp" },
2055 { CONTAINER_ICO, "ico" },
2056 { CONTAINER_IDCIN, "idcin" },
2057 { CONTAINER_IDF, "idf" },
2058 { CONTAINER_IEC61883, "iec61883" },
2059 { CONTAINER_IFF, "iff" },
2060 { CONTAINER_ILBC, "ilbc" },
2061 { CONTAINER_IMAGE2, "image2" },
2062 { CONTAINER_IMAGE2PIPE, "image2pipe" },
2063 { CONTAINER_INGENIENT, "ingenient" },
2064 { CONTAINER_IPMOVIE, "ipmovie" },
2065 { CONTAINER_IRCAM, "ircam" },
2066 { CONTAINER_ISS, "iss" },
2067 { CONTAINER_IV8, "iv8" },
2068 { CONTAINER_IVF, "ivf" },
2069 { CONTAINER_JACK, "jack" },
2070 { CONTAINER_JACOSUB, "jacosub" },
2071 { CONTAINER_JV, "jv" },
2072 { CONTAINER_LATM, "latm" },
2073 { CONTAINER_LAVFI, "lavfi" },
2074 { CONTAINER_LIBCDIO, "libcdio" },
2075 { CONTAINER_LIBDC1394, "libdc1394" },
2076 { CONTAINER_LIBMODPLUG, "libmodplug" },
2077 { CONTAINER_LIBNUT, "libnut" },
2078 { CONTAINER_LMLM4, "lmlm4" },
2079 { CONTAINER_LOAS, "loas" },
2080 { CONTAINER_LVF, "lvf" },
2081 { CONTAINER_LXF, "lxf" },
2082 { CONTAINER_M4V, "m4v" },
2083 { CONTAINER_WEBM, "matroska,webm" },
2084 { CONTAINER_MGSTS, "mgsts" },
2085 { CONTAINER_MICRODVD, "microdvd" },
2086 { CONTAINER_MJPEG, "mjpeg" },
2087 { CONTAINER_MLP, "mlp" },
2088 { CONTAINER_MM, "mm" },
2089 { CONTAINER_MMF, "mmf" },
2090 { CONTAINER_MOV, "mov,mp4,m4a,3gp,3g2,mj2" },
2091 { CONTAINER_MP3, "mp3" },
2092 { CONTAINER_MPC, "mpc" },
2093 { CONTAINER_MPC8, "mpc8" },
2094 { CONTAINER_MPEG, "mpeg" },
2095 { CONTAINER_MPEGTS, "mpegts" },
2096 { CONTAINER_MPEGTSRAW, "mpegtsraw" },
2097 { CONTAINER_MPEGVIDEO, "mpegvideo" },
2098 { CONTAINER_MPL2, "mpl2" },
2099 { CONTAINER_MPSUB, "mpsub" },
2100 { CONTAINER_MSNWCTCP, "msnwctcp" },
2101 { CONTAINER_MTV, "mtv" },
2102 { CONTAINER_MULAW, "mulaw" },
2103 { CONTAINER_MV, "mv" },
2104 { CONTAINER_MVI, "mvi" },
2105 { CONTAINER_MXF, "mxf" },
2106 { CONTAINER_MXG, "mxg" },
2107 { CONTAINER_NC, "nc" },
2108 { CONTAINER_NISTSPHERE, "nistsphere" },
2109 { CONTAINER_NSV, "nsv" },
2110 { CONTAINER_NUT, "nut" },
2111 { CONTAINER_NUV, "nuv" },
2112 { CONTAINER_OGG, "ogg" },
2113 { CONTAINER_OMA, "oma" },
2114 { CONTAINER_OPENAL, "openal" },
2115 { CONTAINER_OSS, "oss" },
2116 { CONTAINER_PAF, "paf" },
2117 { CONTAINER_PJS, "pjs" },
2118 { CONTAINER_PMP, "pmp" },
2119 { CONTAINER_PSXSTR, "psxstr" },
2120 { CONTAINER_PULSE, "pulse" },
2121 { CONTAINER_PVA, "pva" },
2122 { CONTAINER_PVF, "pvf" },
2123 { CONTAINER_QCP, "qcp" },
2124 { CONTAINER_R3D, "r3d" },
2125 { CONTAINER_RAWVIDEO, "rawvideo" },
2126 { CONTAINER_RDT, "rdt" },
2127 { CONTAINER_REALTEXT, "realtext" },
2128 { CONTAINER_RL2, "rl2" },
2129 { CONTAINER_RM, "rm" },
2130 { CONTAINER_ROQ, "roq" },
2131 { CONTAINER_RPL, "rpl" },
2132 { CONTAINER_RSO, "rso" },
2133 { CONTAINER_RTP, "rtp" },
2134 { CONTAINER_RTSP, "rtsp" },
2135 { CONTAINER_S16BE, "s16be" },
2136 { CONTAINER_S16LE, "s16le" },
2137 { CONTAINER_S24BE, "s24be" },
2138 { CONTAINER_S24LE, "s24le" },
2139 { CONTAINER_S32BE, "s32be" },
2140 { CONTAINER_S32LE, "s32le" },
2141 { CONTAINER_S8, "s8" },
2142 { CONTAINER_SAMI, "sami" },
2143 { CONTAINER_SAP, "sap" },
2144 { CONTAINER_SBG, "sbg" },
2145 { CONTAINER_SDP, "sdp" },
2146 { CONTAINER_SHN, "shn" },
2147 { CONTAINER_SIFF, "siff" },
2148 { CONTAINER_SMJPEG, "smjpeg" },
2149 { CONTAINER_SMK, "smk" },
2150 { CONTAINER_SMUSH, "smush" },
2151 { CONTAINER_SNDIO, "sndio" },
2152 { CONTAINER_SOL, "sol" },
2153 { CONTAINER_SOX, "sox" },
2154 { CONTAINER_SPDIF, "spdif" },
2155 { CONTAINER_SRT, "srt" },
2156 { CONTAINER_SUBVIEWER, "subviewer" },
2157 { CONTAINER_SUBVIEWER1, "subviewer1" },
2158 { CONTAINER_SWF, "swf" },
2159 { CONTAINER_TAK, "tak" },
2160 { CONTAINER_TEDCAPTIONS, "tedcaptions" },
2161 { CONTAINER_THP, "thp" },
2162 { CONTAINER_TIERTEXSEQ, "tiertexseq" },
2163 { CONTAINER_TMV, "tmv" },
2164 { CONTAINER_TRUEHD, "truehd" },
2165 { CONTAINER_TTA, "tta" },
2166 { CONTAINER_TTY, "tty" },
2167 { CONTAINER_TXD, "txd" },
2168 { CONTAINER_VC1, "vc1" },
2169 { CONTAINER_VC1TEST, "vc1test" },
2170 { CONTAINER_VFWCAP, "vfwcap" },
2171 { CONTAINER_V4L, "video4linux,v4l" },
2172 { CONTAINER_V4L2, "video4linux2,v4l2" },
2173 { CONTAINER_VIVO, "vivo" },
2174 { CONTAINER_VMD, "vmd" },
2175 { CONTAINER_VOBSUB, "vobsub" },
2176 { CONTAINER_VOC, "voc" },
2177 { CONTAINER_VPLAYER, "vplayer" },
2178 { CONTAINER_VQF, "vqf" },
2179 { CONTAINER_W64, "w64" },
2180 { CONTAINER_WAV, "wav" },
2181 { CONTAINER_WC3MOVIE, "wc3movie" },
2182 { CONTAINER_WEBVTT, "webvtt" },
2183 { CONTAINER_WSAUD, "wsaud" },
2184 { CONTAINER_WSVQA, "wsvqa" },
2185 { CONTAINER_WTV, "wtv" },
2186 { CONTAINER_WV, "wv" },
2187 { CONTAINER_X11GRAB, "x11grab" },
2188 { CONTAINER_XA, "xa" },
2189 { CONTAINER_XBIN, "xbin" },
2190 { CONTAINER_XMV, "xmv" },
2191 { CONTAINER_XWMA, "xwma" },
2192 { CONTAINER_YOP, "yop" },
2193 { CONTAINER_YUV4MPEGPIPE, "yuv4mpegpipe" }
2194 };
2195
2196 // Returns the number of elements in container_name_mapping.
2197 const int ContainerNames::ContainerNameMappingSize() {
2198 return arraysize(container_name_mapping);
2199 }
2200
2201 // Lookup a container name using the list above (container_name_mapping)
2202 // to determine the container enum. If not found (recent addition to
2203 // FFmpeg or a name change), return CONTAINER_UNKNOWN.
2204 FFmpegContainerName ContainerNames::LookupContainer(
2205 const char* container_name) {
2206 DCHECK(container_name);
2207 const ContainerNameMapping* found =
2208 std::lower_bound(container_name_mapping,
2209 container_name_mapping + ContainerNameMappingSize() - 1,
2210 container_name,
2211 ContainerNameMappingComparer);
2212 return (strcasecmp(found->name, container_name) == 0) ? found->id
2213 : CONTAINER_UNKNOWN;
2214 }
2215
2216 // Attempt to determine the container name from the buffer provided.
2217 FFmpegContainerName ContainerNames::DetermineContainer(const uint8 buffer[],
2218 size_t buffer_size) {
2219 // TODO(jrummell): The following formats are not scanned for
2220 // cavsvideo, dts, dv, h261, h263, h264, jacosub,
2221 // mpeg, mpegts, mpegvideo, psxstr, sbg, spdif, tedcaptions
2222
2223 // First attempt the simple checks, that typically look at just the
2224 // first few bytes of the file.
2225 FFmpegContainerName result = LookupContainerByFirst4(buffer, buffer_size);
2226 if (result != CONTAINER_UNKNOWN)
2227 return result;
2228
2229 // No success with simple test, so attempt to determine the container by
2230 // looking for strings in the buffer.
2231 result = LookupContainerByStringScan(buffer, buffer_size);
2232 if (result != CONTAINER_UNKNOWN)
2233 return result;
2234 return LookupContainerByStringLine(buffer, buffer_size);
2235 }
2236
2237 // Log the container based on the name returned by FFmpeg.
2238 void ContainerNames::LogContainer(const char* container_name) {
2239 FFmpegContainerName container = LookupContainer(container_name);
2240 LogContainerToHistogram(container, false);
2241 }
2242
2243 // Log the container by examining the first part of the stream.
2244 void ContainerNames::LogContainer(const uint8 buffer[], size_t buffer_size) {
2245 FFmpegContainerName container = DetermineContainer(buffer, buffer_size);
2246 LogContainerToHistogram(container, true);
2247 }
2248
2249 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698