190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/base/container_names.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <cctype>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <limits>
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/basictypes.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/base/bit_reader.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace media {
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace container_names {
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define TAG(a, b, c, d) \
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ((static_cast<uint32>(static_cast<uint8>(a)) << 24) | \
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     (static_cast<uint32>(static_cast<uint8>(b)) << 16) | \
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     (static_cast<uint32>(static_cast<uint8>(c)) << 8) | \
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch     (static_cast<uint32>(static_cast<uint8>(d))))
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define RCHECK(x)     \
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    do {              \
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!(x))       \
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false; \
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } while (0)
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define UTF8_BYTE_ORDER_MARK "\xef\xbb\xbf"
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Helper function to read 2 bytes (16 bits, big endian) from a buffer.
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int Read16(const uint8* p) {
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return p[0] << 8 | p[1];
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Helper function to read 3 bytes (24 bits, big endian) from a buffer.
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static uint32 Read24(const uint8* p) {
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return p[0] << 16 | p[1] << 8 | p[2];
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Helper function to read 4 bytes (32 bits, big endian) from a buffer.
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static uint32 Read32(const uint8* p) {
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Helper function to read 4 bytes (32 bits, little endian) from a buffer.
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static uint32 Read32LE(const uint8* p) {
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Helper function to do buffer comparisons with a string without going off the
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// end of the buffer.
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool StartsWith(const uint8* buffer,
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       size_t buffer_size,
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       const char* prefix) {
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t prefix_size = strlen(prefix);
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (prefix_size <= buffer_size &&
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          memcmp(buffer, prefix, prefix_size) == 0);
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Helper function to do buffer comparisons with another buffer (to allow for
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// embedded \0 in the comparison) without going off the end of the buffer.
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool StartsWith(const uint8* buffer,
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       size_t buffer_size,
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       const uint8* prefix,
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       size_t prefix_size) {
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (prefix_size <= buffer_size &&
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          memcmp(buffer, prefix, prefix_size) == 0);
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Helper function to read up to 64 bits from a bit stream.
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static uint64 ReadBits(BitReader* reader, int num_bits) {
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_GE(reader->bits_available(), num_bits);
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK((num_bits > 0) && (num_bits <= 64));
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint64 value;
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reader->ReadBits(num_bits, &value);
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return value;
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kAc3FrameSizeTable[38][3] = {
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 128, 138, 192 }, { 128, 140, 192 }, { 160, 174, 240 }, { 160, 176, 240 },
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 192, 208, 288 }, { 192, 210, 288 }, { 224, 242, 336 }, { 224, 244, 336 },
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 256, 278, 384 }, { 256, 280, 384 }, { 320, 348, 480 }, { 320, 350, 480 },
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 384, 416, 576 }, { 384, 418, 576 }, { 448, 486, 672 }, { 448, 488, 672 },
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 512, 556, 768 }, { 512, 558, 768 }, { 640, 696, 960 }, { 640, 698, 960 },
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 768, 834, 1152 }, { 768, 836, 1152 }, { 896, 974, 1344 },
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 896, 976, 1344 }, { 1024, 1114, 1536 }, { 1024, 1116, 1536 },
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 1280, 1392, 1920 }, { 1280, 1394, 1920 }, { 1536, 1670, 2304 },
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 1536, 1672, 2304 }, { 1792, 1950, 2688 }, { 1792, 1952, 2688 },
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 2048, 2228, 3072 }, { 2048, 2230, 3072 }, { 2304, 2506, 3456 },
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  { 2304, 2508, 3456 }, { 2560, 2768, 3840 }, { 2560, 2770, 3840 }
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for an ADTS AAC container.
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckAac(const uint8* buffer, int buffer_size) {
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Audio Data Transport Stream (ADTS) header is 7 or 9 bytes
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (from http://wiki.multimedia.cx/index.php?title=ADTS)
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 6);
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 6 < buffer_size) {
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 6);
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Syncword must be 0xfff.
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 12) == 0xfff);
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip MPEG version.
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1);
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Layer is always 0.
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 2) == 0);
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip protection + profile.
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1 + 2);
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Check sampling frequency index.
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 4) != 15);  // Forbidden.
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip private stream, channel configuration, originality, home,
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // copyrighted stream, and copyright_start.
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1 + 3 + 1 + 1 + 1 + 1);
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Get frame length (includes header).
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int size = ReadBits(&reader, 13);
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(size > 0);
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += size;
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const uint16 kAc3SyncWord = 0x0b77;
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for an AC3 container.
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckAc3(const uint8* buffer, int buffer_size) {
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ATSC Standard: Digital Audio Compression (AC-3, E-AC-3)
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //            Doc. A/52:2012
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (http://www.atsc.org/cms/standards/A52-2012(12-17).pdf)
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // AC3 container looks like syncinfo | bsi | audblk * 6 | aux | check.
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 6);
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 6 < buffer_size) {
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 6);
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Check syncinfo.
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 16) == kAc3SyncWord);
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip crc1.
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(16);
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify fscod.
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int sample_rate_code = ReadBits(&reader, 2);
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(sample_rate_code != 3);  // Reserved.
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify frmsizecod.
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int frame_size_code = ReadBits(&reader, 6);
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(frame_size_code < 38);  // Undefined.
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify bsid.
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 5) < 10);  // Normally 8 or 6, 16 used by EAC3.
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += kAc3FrameSizeTable[frame_size_code][sample_rate_code];
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for an EAC3 container (very similar to AC3)
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckEac3(const uint8* buffer, int buffer_size) {
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ATSC Standard: Digital Audio Compression (AC-3, E-AC-3)
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //            Doc. A/52:2012
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (http://www.atsc.org/cms/standards/A52-2012(12-17).pdf)
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // EAC3 container looks like syncinfo | bsi | audfrm | audblk* | aux | check.
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 6);
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 6 < buffer_size) {
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 6);
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Check syncinfo.
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 16) == kAc3SyncWord);
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify strmtyp.
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 2) != 3);
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip substreamid.
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(3);
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Get frmsize. Include syncinfo size and convert to bytes.
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int frame_size = (ReadBits(&reader, 11) + 1) * 2;
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(frame_size >= 7);
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip fscod, fscod2, acmod, and lfeon.
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(2 + 2 + 3 + 1);
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify bsid.
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int bit_stream_id = ReadBits(&reader, 5);
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(bit_stream_id >= 11 && bit_stream_id <= 16);
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += frame_size;
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Additional checks for a BINK container.
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckBink(const uint8* buffer, int buffer_size) {
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: http://wiki.multimedia.cx/index.php?title=Bink_Container
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size >= 44);
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify number of frames specified.
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(Read32LE(buffer + 8) > 0);
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify width in range.
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int width = Read32LE(buffer + 20);
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(width > 0 && width <= 32767);
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify height in range.
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int height = Read32LE(buffer + 24);
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(height > 0 && height <= 32767);
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify frames per second specified.
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(Read32LE(buffer + 28) > 0);
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify video frames per second specified.
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(Read32LE(buffer + 32) > 0);
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Number of audio tracks must be 256 or less.
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (Read32LE(buffer + 40) <= 256);
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Additional checks for a CAF container.
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckCaf(const uint8* buffer, int buffer_size) {
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: Apple Core Audio Format Specification 1.0
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // (https://developer.apple.com/library/mac/#documentation/MusicAudio/Reference/CAFSpec/CAF_spec/CAF_spec.html)
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size >= 52);
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BitReader reader(buffer, buffer_size);
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mFileType should be "caff".
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(ReadBits(&reader, 32) == TAG('c', 'a', 'f', 'f'));
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // mFileVersion should be 1.
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(ReadBits(&reader, 16) == 1);
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Skip mFileFlags.
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reader.SkipBits(16);
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // First chunk should be Audio Description chunk, size 32l.
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(ReadBits(&reader, 32) == TAG('d', 'e', 's', 'c'));
25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(ReadBits(&reader, 64) == 32);
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // CAFAudioFormat.mSampleRate(float64) not 0
25490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(ReadBits(&reader, 64) != 0);
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // CAFAudioFormat.mFormatID not 0
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(ReadBits(&reader, 32) != 0);
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Skip CAFAudioFormat.mBytesPerPacket and mFramesPerPacket.
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reader.SkipBits(32 + 32);
26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // CAFAudioFormat.mChannelsPerFrame not 0
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(ReadBits(&reader, 32) != 0);
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool kSamplingFrequencyValid[16] = { false, true, true, true, false,
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            false, true, true, true, false,
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            false, true, true, true, false,
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            false };
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool kExtAudioIdValid[8] = { true, false, true, false, false, false,
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    true, false };
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
27490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Additional checks for a DTS container.
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckDts(const uint8* buffer, int buffer_size) {
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ETSI TS 102 114 V1.3.1 (2011-08)
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // (http://www.etsi.org/deliver/etsi_ts/102100_102199/102114/01.03.01_60/ts_102114v010301p.pdf)
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 11);
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 11 < buffer_size) {
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 11);
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify sync word.
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 32) == 0x7ffe8001);
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip frame type and deficit sample count.
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1 + 5);
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify CRC present flag.
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 1) == 0);  // CPF must be 0.
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify number of PCM sample blocks.
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 7) >= 5);
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify primary frame byte size.
29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int frame_size = ReadBits(&reader, 14);
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(frame_size >= 95);
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip audio channel arrangement.
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(6);
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify core audio sampling frequency is an allowed value.
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(kSamplingFrequencyValid[ReadBits(&reader, 4)]);
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify transmission bit rate is valid.
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 5) <= 25);
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify reserved field is 0.
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 1) == 0);
31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip dynamic range flag, time stamp flag, auxiliary data flag, and HDCD.
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1 + 1 + 1 + 1);
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify extension audio descriptor flag is an allowed value.
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(kExtAudioIdValid[ReadBits(&reader, 3)]);
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip extended coding flag and audio sync word insertion flag.
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1 + 1);
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify low frequency effects flag is an allowed value.
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 2) != 3);
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += frame_size + 1;
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for a DV container.
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckDV(const uint8* buffer, int buffer_size) {
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: SMPTE 314M (Annex A has differences with IEC 61834).
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // (http://standards.smpte.org/content/978-1-61482-454-1/st-314-2005/SEC1.body.pdf)
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 11);
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int current_sequence_number = -1;
33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int last_block_number[6];
33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 11 < buffer_size) {
33990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 11);
34090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Decode ID data. Sections 5, 6, and 7 are reserved.
34290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int section = ReadBits(&reader, 3);
34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(section < 5);
34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Next bit must be 1.
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 1) == 1);
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip arbitrary bits.
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(4);
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int sequence_number = ReadBits(&reader, 4);
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip FSC.
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1);
35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Next 3 bits must be 1.
35790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 3) == 7);
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int block_number = ReadBits(&reader, 8);
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (section == 0) {  // Header.
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Validate the reserved bits in the next 8 bytes.
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(1);
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 1) == 0);
36590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 11) == 0x7ff);
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(4);
36790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 4) == 0xf);
36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(4);
36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 4) == 0xf);
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(4);
37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 4) == 0xf);
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(3);
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 24) == 0xffffff);
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      current_sequence_number = sequence_number;
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      for (size_t i = 0; i < arraysize(last_block_number); ++i)
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        last_block_number[i] = -1;
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Sequence number must match (this will also fail if no header seen).
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(sequence_number == current_sequence_number);
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Block number should be increasing.
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(block_number > last_block_number[section]);
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      last_block_number[section] = block_number;
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Move to next block.
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += 80;
38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for a GSM container.
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckGsm(const uint8* buffer, int buffer_size) {
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ETSI EN 300 961 V8.1.1
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // (http://www.etsi.org/deliver/etsi_en/300900_300999/300961/08.01.01_60/en_300961v080101p.pdf)
39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // also http://tools.ietf.org/html/rfc3551#page-24
39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // GSM files have a 33 byte block, only first 4 bits are fixed.
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size >= 1024);  // Need enough data to do a decent check.
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset < buffer_size) {
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // First 4 bits of each block are xD.
40390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK((buffer[offset] & 0xf0) == 0xd0);
40490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += 33;
40590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
40690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
40790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
40890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Advance to the first set of |num_bits| bits that match |start_code|. |offset|
41090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// is the current location in the buffer, and is updated. |bytes_needed| is the
41190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// number of bytes that must remain in the buffer when |start_code| is found.
41290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Returns true if start_code found (and enough space in the buffer after it),
41390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// false otherwise.
41490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool AdvanceToStartCode(const uint8* buffer,
41590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               int buffer_size,
41690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               int* offset,
41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               int bytes_needed,
41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               int num_bits,
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               uint32 start_code) {
42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_GE(bytes_needed, 3);
42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_LE(num_bits, 24);  // Only supports up to 24 bits.
42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create a mask to isolate |num_bits| bits, once shifted over.
42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint32 bits_to_shift = 24 - num_bits;
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint32 mask = (1 << num_bits) - 1;
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (*offset + bytes_needed < buffer_size) {
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint32 next = Read24(buffer + *offset);
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (((next >> bits_to_shift) & mask) == start_code)
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ++(*offset);
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for an H.261 container.
43690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckH261(const uint8* buffer, int buffer_size) {
43790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ITU-T Recommendation H.261 (03/1993)
43890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (http://www.itu.int/rec/T-REC-H.261-199303-I/en)
43990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 16);
44090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
44290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool seen_start_code = false;
44390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (true) {
44490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Advance to picture_start_code, if there is one.
44590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!AdvanceToStartCode(buffer, buffer_size, &offset, 4, 20, 0x10)) {
44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // No start code found (or off end of buffer), so success if
44790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // there was at least one valid header.
44890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return seen_start_code;
44990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
45090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Now verify the block. AdvanceToStartCode() made sure that there are
45290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // at least 4 bytes remaining in the buffer.
45390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, buffer_size - offset);
45490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 20) == 0x10);
45590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip the temporal reference and PTYPE.
45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(5 + 6);
45890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
45990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip any extra insertion information. Since this is open-ended, if we run
46090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // out of bits assume that the buffer is correctly formatted.
46190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int extra = ReadBits(&reader, 1);
46290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    while (extra == 1) {
46390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!reader.SkipBits(8))
46490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return seen_start_code;
46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!reader.ReadBits(1, &extra))
46690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return seen_start_code;
46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Next should be a Group of Blocks start code. Again, if we run out of
47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // bits, then assume that the buffer up to here is correct, and the buffer
47190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // just happened to end in the middle of a header.
47290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int next;
47390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!reader.ReadBits(16, &next))
47490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return seen_start_code;
47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(next == 1);
47690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Move to the next block.
47890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    seen_start_code = true;
47990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += 4;
48090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
48190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
48290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
48390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for an H.263 container.
48490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckH263(const uint8* buffer, int buffer_size) {
48590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ITU-T Recommendation H.263 (01/2005)
48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (http://www.itu.int/rec/T-REC-H.263-200501-I/en)
48790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // header is PSC(22b) + TR(8b) + PTYPE(8+b).
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 16);
48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool seen_start_code = false;
49290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (true) {
49390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Advance to picture_start_code, if there is one.
49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!AdvanceToStartCode(buffer, buffer_size, &offset, 9, 22, 0x20)) {
49590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // No start code found (or off end of buffer), so success if
49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // there was at least one valid header.
49790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return seen_start_code;
49890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
49990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Now verify the block. AdvanceToStartCode() made sure that there are
50190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // at least 9 bytes remaining in the buffer.
50290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 9);
50390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 22) == 0x20);
50490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip the temporal reference.
50690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(8);
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
50890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify that the first 2 bits of PTYPE are 10b.
50990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 2) == 2);
51090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip the split screen indicator, document camera indicator, and full
51290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // picture freeze release.
51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1 + 1 + 1);
51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify Source Format.
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int format = ReadBits(&reader, 3);
51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(format != 0 && format != 6);  // Forbidden or reserved.
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
51990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (format == 7) {
52090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Verify full extended PTYPE.
52190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int ufep = ReadBits(&reader, 3);
52290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (ufep == 1) {
52390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Verify the optional part of PLUSPTYPE.
52490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        format = ReadBits(&reader, 3);
52590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(format != 0 && format != 7);  // Reserved.
52690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        reader.SkipBits(11);
52790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Next 4 bits should be b1000.
52890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(ReadBits(&reader, 4) == 8);  // Not allowed.
52990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      } else {
53090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(ufep == 0);  // Only 0 and 1 allowed.
53190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
53290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Verify picture type code is not a reserved value.
53490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int picture_type_code = ReadBits(&reader, 3);
53590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(picture_type_code != 6 && picture_type_code != 7);  // Reserved.
53690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
53790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip picture resampling mode, reduced resolution mode,
53890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // and rounding type.
53990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(1 + 1 + 1);
54090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Next 3 bits should be b001.
54290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 3) == 1);  // Not allowed.
54390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
54490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
54590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Move to the next block.
54690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    seen_start_code = true;
54790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += 9;
54890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
54990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
55090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for an H.264 container.
55290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckH264(const uint8* buffer, int buffer_size) {
55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ITU-T Recommendation H.264 (01/2012)
55490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (http://www.itu.int/rec/T-REC-H.264)
55590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Section B.1: Byte stream NAL unit syntax and semantics.
55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 4);
55790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int parameter_count = 0;
56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (true) {
56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Advance to picture_start_code, if there is one.
56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!AdvanceToStartCode(buffer, buffer_size, &offset, 4, 24, 1)) {
56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // No start code found (or off end of buffer), so success if
56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // there was at least one valid header.
56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return parameter_count > 0;
56690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
56790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Now verify the block. AdvanceToStartCode() made sure that there are
56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // at least 4 bytes remaining in the buffer.
57090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 4);
57190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 24) == 1);
57290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify forbidden_zero_bit.
57490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 1) == 0);
57590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
57690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Extract nal_ref_idc and nal_unit_type.
57790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int nal_ref_idc = ReadBits(&reader, 2);
57890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int nal_unit_type = ReadBits(&reader, 5);
57990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
58090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    switch (nal_unit_type) {
58190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 5:  // Coded slice of an IDR picture.
58290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(nal_ref_idc != 0);
58390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
58490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 6:   // Supplemental enhancement information (SEI).
58590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 9:   // Access unit delimiter.
58690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 10:  // End of sequence.
58790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 11:  // End of stream.
58890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 12:  // Filler data.
58990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(nal_ref_idc == 0);
59090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
59190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 7:  // Sequence parameter set.
59290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 8:  // Picture parameter set.
59390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ++parameter_count;
59490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
59590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
59690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
59790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip the current start_code_prefix and move to the next.
59890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += 4;
59990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
60090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
60190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
60290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const char kHlsSignature[] = "#EXTM3U";
60390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const char kHls1[] = "#EXT-X-STREAM-INF:";
60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const char kHls2[] = "#EXT-X-TARGETDURATION:";
60590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const char kHls3[] = "#EXT-X-MEDIA-SEQUENCE:";
60690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
60790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Additional checks for a HLS container.
60890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckHls(const uint8* buffer, int buffer_size) {
60990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // HLS is simply a play list used for Apple HTTP Live Streaming.
61090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: Apple HTTP Live Streaming Overview
61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (http://goo.gl/MIwxj)
61290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
61390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (StartsWith(buffer, buffer_size, kHlsSignature)) {
61490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Need to find "#EXT-X-STREAM-INF:", "#EXT-X-TARGETDURATION:", or
61590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // "#EXT-X-MEDIA-SEQUENCE:" somewhere in the buffer. Other playlists (like
61690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // WinAmp) only have additional lines with #EXTINF
61790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // (http://en.wikipedia.org/wiki/M3U).
61890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int offset = strlen(kHlsSignature);
61990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    while (offset < buffer_size) {
62090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (buffer[offset] == '#') {
62190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (StartsWith(buffer + offset, buffer_size - offset, kHls1) ||
62290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            StartsWith(buffer + offset, buffer_size - offset, kHls2) ||
62390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            StartsWith(buffer + offset, buffer_size - offset, kHls3)) {
62490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          return true;
62590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
62690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
62790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ++offset;
62890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
62990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
63090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
63190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
63290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
63390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for a MJPEG stream.
63490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckMJpeg(const uint8* buffer, int buffer_size) {
63590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ISO/IEC 10918-1 : 1993(E), Annex B
63690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (http://www.w3.org/Graphics/JPEG/itu-t81.pdf)
63790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size >= 16);
63890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
63990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
64090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int last_restart = -1;
64190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int num_codes = 0;
64290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 5 < buffer_size) {
64390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Marker codes are always a two byte code with the first byte xFF.
64490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(buffer[offset] == 0xff);
64590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint8 code = buffer[offset + 1];
64690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(code >= 0xc0 || code == 1);
64790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
64890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip sequences of xFF.
64990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (code == 0xff) {
65090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ++offset;
65190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
65290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
65390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
65490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Success if the next marker code is EOI (end of image)
65590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (code == 0xd9)
65690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
65790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
65890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Check remaining codes.
65990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (code == 0xd8 || code == 1) {
66090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // SOI (start of image) / TEM (private use). No other data with header.
66190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      offset += 2;
66290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else if (code >= 0xd0 && code <= 0xd7) {
66390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // RST (restart) codes must be in sequence. No other data with header.
66490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int restart = code & 0x07;
66590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (last_restart >= 0)
66690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(restart == (last_restart + 1) % 8);
66790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      last_restart = restart;
66890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      offset += 2;
66990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
67090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // All remaining marker codes are followed by a length of the header.
67190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int length = Read16(buffer + offset + 2) + 2;
67290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
67390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Special handling of SOS (start of scan) marker since the entropy
67490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // coded data follows the SOS. Any xFF byte in the data block must be
67590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // followed by x00 in the data.
67690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (code == 0xda) {
67790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        int number_components = buffer[offset + 4];
67890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(length == 8 + 2 * number_components);
67990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
68090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Advance to the next marker.
68190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        offset += length;
68290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        while (offset + 2 < buffer_size) {
68390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          if (buffer[offset] == 0xff && buffer[offset + 1] != 0)
68490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            break;
68590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          ++offset;
68690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
68790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      } else {
68890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Skip over the marker data for the other marker codes.
68990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        offset += length;
69090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
69190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
69290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ++num_codes;
69390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
69490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (num_codes > 1);
69590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
69690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
69790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)enum Mpeg2StartCodes {
69890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PROGRAM_END_CODE = 0xb9,
69990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  PACK_START_CODE = 0xba
70090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
70190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
70290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for a MPEG2 Program Stream.
70390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckMpeg2ProgramStream(const uint8* buffer, int buffer_size) {
70490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ISO/IEC 13818-1 : 2000 (E) / ITU-T Rec. H.222.0 (2000 E).
70590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 14);
70690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
70790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
70890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 14 < buffer_size) {
70990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 14);
71090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
71190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Must start with pack_start_code.
71290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 24) == 1);
71390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 8) == PACK_START_CODE);
71490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
71590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Determine MPEG version (MPEG1 has b0010, while MPEG2 has b01).
71690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int mpeg_version = ReadBits(&reader, 2);
71790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (mpeg_version == 0) {
71890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // MPEG1, 10 byte header
71990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Validate rest of version code
72090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 2) == 2);
72190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
72290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(mpeg_version == 1);
72390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
72490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
72590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip system_clock_reference_base [32..30].
72690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(3);
72790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
72890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify marker bit.
72990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 1) == 1);
73090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
73190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip system_clock_reference_base [29..15].
73290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(15);
73390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
73490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify next marker bit.
73590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 1) == 1);
73690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
73790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip system_clock_reference_base [14..0].
73890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(15);
73990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
74090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify next marker bit.
74190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 1) == 1);
74290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
74390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (mpeg_version == 0) {
74490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Verify second marker bit.
74590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 1) == 1);
74690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
74790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip mux_rate.
74890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(22);
74990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
75090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Verify next marker bit.
75190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 1) == 1);
75290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
75390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Update offset to be after this header.
75490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      offset += 12;
75590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
75690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Must be MPEG2.
75790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip program_mux_rate.
75890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(22);
75990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
76090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Verify pair of marker bits.
76190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 2) == 3);
76290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
76390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip reserved.
76490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(5);
76590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
76690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Update offset to be after this header.
76790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int pack_stuffing_length = ReadBits(&reader, 3);
76890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      offset += 14 + pack_stuffing_length;
76990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
77090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
77190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Check for system headers and PES_packets.
77290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    while (offset + 6 < buffer_size && Read24(buffer + offset) == 1) {
77390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Next 8 bits determine stream type.
77490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int stream_id = buffer[offset + 3];
77590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
77690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Some stream types are reserved and shouldn't occur.
77790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (mpeg_version == 0)
77890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(stream_id != 0xbc && stream_id < 0xf0);
77990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      else
78090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(stream_id != 0xfc && stream_id != 0xfd && stream_id != 0xfe);
78190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
78290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Some stream types are used for pack headers.
78390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (stream_id == PACK_START_CODE)  // back to outer loop.
78490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
78590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (stream_id == PROGRAM_END_CODE)  // end of stream.
78690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return true;
78790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
78890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int pes_length = Read16(buffer + offset + 4);
78990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(pes_length > 0);
79090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      offset = offset + 6 + pes_length;
79190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
79290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
79390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Success as we are off the end of the buffer and liked everything
79490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // in the buffer.
79590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
79690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
79790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
79890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const uint8 kMpeg2SyncWord = 0x47;
79990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
80090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for a MPEG2 Transport Stream.
80190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckMpeg2TransportStream(const uint8* buffer, int buffer_size) {
80290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Spec: ISO/IEC 13818-1 : 2000 (E) / ITU-T Rec. H.222.0 (2000 E).
80390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Normal packet size is 188 bytes. However, some systems add various error
80490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // correction data at the end, resulting in packet of length 192/204/208
80590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // (https://en.wikipedia.org/wiki/MPEG_transport_stream). Determine the
80690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // length with the first packet.
80790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size >= 250);  // Want more than 1 packet to check.
80890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
80990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
81090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int packet_length = -1;
81190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (buffer[offset] != kMpeg2SyncWord && offset < 20) {
81290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip over any header in the first 20 bytes.
81390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ++offset;
81490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
81590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
81690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 6 < buffer_size) {
81790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 6);
81890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
81990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Must start with sync byte.
82090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 8) == kMpeg2SyncWord);
82190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
82290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip transport_error_indicator, payload_unit_start_indicator, and
82390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // transport_priority.
82490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(1 + 1 + 1);
82590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
82690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify the pid is not a reserved value.
82790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int pid = ReadBits(&reader, 13);
82890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(pid < 3 || pid > 15);
82990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
83090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip transport_scrambling_control.
83190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    reader.SkipBits(2);
83290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
83390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Adaptation_field_control can not be 0.
83490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int adaptation_field_control = ReadBits(&reader, 2);
83590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(adaptation_field_control != 0);
83690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
83790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // If there is an adaptation_field, verify it.
83890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (adaptation_field_control >= 2) {
83990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip continuity_counter.
84090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(4);
84190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
84290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Get adaptation_field_length and verify it.
84390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      int adaptation_field_length = ReadBits(&reader, 8);
84490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (adaptation_field_control == 2)
84590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(adaptation_field_length == 183);
84690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      else
84790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(adaptation_field_length <= 182);
84890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
84990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
85090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Attempt to determine the packet length on the first packet.
85190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (packet_length < 0) {
85290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (buffer[offset + 188] == kMpeg2SyncWord)
85390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        packet_length = 188;
85490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      else if (buffer[offset + 192] == kMpeg2SyncWord)
85590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        packet_length = 192;
85690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      else if (buffer[offset + 204] == kMpeg2SyncWord)
85790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        packet_length = 204;
85890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      else
85990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        packet_length = 208;
86090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
86190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += packet_length;
86290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
86390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
86490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
86590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
86690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)enum Mpeg4StartCodes {
86790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VISUAL_OBJECT_SEQUENCE_START_CODE = 0xb0,
86890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VISUAL_OBJECT_SEQUENCE_END_CODE = 0xb1,
86990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VISUAL_OBJECT_START_CODE = 0xb5,
87090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VOP_START_CODE = 0xb6
87190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
87290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
87390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for a raw MPEG4 bitstream container.
87490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckMpeg4BitStream(const uint8* buffer, int buffer_size) {
87590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Defined in ISO/IEC 14496-2:2001.
87690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // However, no length ... simply scan for start code values.
87790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note tags are very similar to H.264.
87890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 4);
87990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
88090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
88190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int sequence_start_count = 0;
88290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int sequence_end_count = 0;
88390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int visual_object_count = 0;
88490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int vop_count = 0;
88590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (true) {
88690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Advance to start_code, if there is one.
88790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!AdvanceToStartCode(buffer, buffer_size, &offset, 6, 24, 1)) {
88890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Not a complete sequence in memory, so return true if we've seen a
88990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // visual_object_sequence_start_code and a visual_object_start_code.
89090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return (sequence_start_count > 0 && visual_object_count > 0);
89190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
89290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
89390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Now verify the block. AdvanceToStartCode() made sure that there are
89490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // at least 6 bytes remaining in the buffer.
89590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 6);
89690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 24) == 1);
89790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
89890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int start_code = ReadBits(&reader, 8);
89990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(start_code < 0x30 || start_code > 0xaf);  // 30..AF and
90090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(start_code < 0xb7 || start_code > 0xb9);  // B7..B9 reserved
90190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
90290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    switch (start_code) {
90390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case VISUAL_OBJECT_SEQUENCE_START_CODE: {
90490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ++sequence_start_count;
90590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Verify profile in not one of many reserved values.
90690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        int profile = ReadBits(&reader, 8);
90790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile > 0);
90890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x04 || profile > 0x10);
90990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x13 || profile > 0x20);
91090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x23 || profile > 0x31);
91190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x35 || profile > 0x41);
91290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x43 || profile > 0x60);
91390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x65 || profile > 0x70);
91490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x73 || profile > 0x80);
91590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x83 || profile > 0x90);
91690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0x95 || profile > 0xa0);
91790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0xa4 || profile > 0xb0);
91890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0xb5 || profile > 0xc0);
91990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0xc3 || profile > 0xd0);
92090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(profile < 0xe4);
92190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
92290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
92490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case VISUAL_OBJECT_SEQUENCE_END_CODE:
92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(++sequence_end_count == sequence_start_count);
92690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
92790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
92890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case VISUAL_OBJECT_START_CODE: {
92990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ++visual_object_count;
93090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (ReadBits(&reader, 1) == 1) {
93190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          int visual_object_verid = ReadBits(&reader, 4);
93290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          RCHECK(visual_object_verid > 0 && visual_object_verid < 3);
93390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          RCHECK(ReadBits(&reader, 3) != 0);
93490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
93590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        int visual_object_type = ReadBits(&reader, 4);
93690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(visual_object_type > 0 && visual_object_type < 6);
93790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
93890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
93990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
94090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case VOP_START_CODE:
94190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(++vop_count <= visual_object_count);
94290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
94390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
94490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip this block.
94590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += 6;
94690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
94790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
94890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
94990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Additional checks for a MOV/QuickTime/MPEG4 container.
95090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckMov(const uint8* buffer, int buffer_size) {
95190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: ISO/IEC 14496-12:2005(E).
952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // (http://standards.iso.org/ittf/PubliclyAvailableStandards/c061988_ISO_IEC_14496-12_2012.zip)
95390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 8);
95490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
95590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
95690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 8 < buffer_size) {
9575b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    uint32 atomsize = Read32(buffer + offset);
95890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    uint32 atomtype = Read32(buffer + offset + 4);
95990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Only need to check for ones that are valid at the top level.
96090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    switch (atomtype) {
96190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('f','t','y','p'):
96290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('p','d','i','n'):
96390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('m','o','o','v'):
96490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('m','o','o','f'):
96590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('m','f','r','a'):
96690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('m','d','a','t'):
96790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('f','r','e','e'):
96890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('s','k','i','p'):
96990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('m','e','t','a'):
97090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('m','e','c','o'):
97190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('s','t','y','p'):
97290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('s','i','d','x'):
97390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('s','s','i','x'):
97490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('p','r','f','t'):
97590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TAG('b','l','o','c'):
97690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
97790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      default:
97890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
97990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
98090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (atomsize == 1) {
98190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Indicates that the length is the next 64bits.
98290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (offset + 16 > buffer_size)
98390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
98490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (Read32(buffer + offset + 8) != 0)
98590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;  // Offset is way past buffer size.
98690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      atomsize = Read32(buffer + offset + 12);
98790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
9885b892326406927b709cdaf6c384d4ababf456332Ben Murdoch    if (atomsize == 0 || atomsize > static_cast<size_t>(buffer_size))
989a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      break;  // Indicates the last atom or length too big.
99090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += atomsize;
99190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
99290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
99390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
99490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
99590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)enum MPEGVersion {
99690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VERSION_25 = 0,
99790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VERSION_RESERVED,
99890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VERSION_2,
99990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VERSION_1
100090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
100190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)enum MPEGLayer {
100290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  L_RESERVED = 0,
100390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LAYER_3,
100490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LAYER_2,
100590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LAYER_1
100690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
100790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
100890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int kSampleRateTable[4][4] = { { 11025, 12000, 8000, 0 },   // v2.5
100990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      { 0, 0, 0, 0 },              // not used
101090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      { 22050, 24000, 16000, 0 },  // v2
101190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      { 44100, 48000, 32000, 0 }   // v1
101290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
101390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
101490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int kBitRateTableV1L1[16] = { 0, 32, 64, 96, 128, 160, 192, 224, 256,
101590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     288, 320, 352, 384, 416, 448, 0 };
101690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int kBitRateTableV1L2[16] = { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160,
101790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     192, 224, 256, 320, 384, 0 };
101890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int kBitRateTableV1L3[16] = { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128,
101990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     160, 192, 224, 256, 320, 0 };
102090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int kBitRateTableV2L1[16] = { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144,
102190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     160, 176, 192, 224, 256, 0 };
102290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int kBitRateTableV2L23[16] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,
102390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      112, 128, 144, 160, 0 };
102490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
102590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool ValidMpegAudioFrameHeader(const uint8* header,
102690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int header_size,
102790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                      int* framesize) {
102890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm.
102990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_GE(header_size, 4);
103090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *framesize = 0;
103190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BitReader reader(header, 4);  // Header can only be 4 bytes long.
103290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
103390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify frame sync (11 bits) are all set.
103490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(ReadBits(&reader, 11) == 0x7ff);
103590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
103690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify MPEG audio version id.
103790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int version = ReadBits(&reader, 2);
103890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(version != 1);  // Reserved.
103990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
104090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify layer.
104190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int layer = ReadBits(&reader, 2);
104290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(layer != 0);
104390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
104490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Skip protection bit.
104590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  reader.SkipBits(1);
104690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
104790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify bitrate index.
104890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int bitrate_index = ReadBits(&reader, 4);
104990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(bitrate_index != 0xf);
105090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
105190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify sampling rate frequency index.
105290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int sampling_index = ReadBits(&reader, 2);
105390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(sampling_index != 3);
105490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
105590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Get padding bit.
105690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int padding = ReadBits(&reader, 1);
105790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
105890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Frame size:
105990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // For Layer I files = (12 * BitRate / SampleRate + Padding) * 4
106090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // For others = 144 * BitRate / SampleRate + Padding
106190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unfortunately, BitRate and SampleRate are coded.
106290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int sampling_rate = kSampleRateTable[version][sampling_index];
106390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int bitrate;
106490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (version == VERSION_1) {
106590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (layer == LAYER_1)
106690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bitrate = kBitRateTableV1L1[bitrate_index];
106790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else if (layer == LAYER_2)
106890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bitrate = kBitRateTableV1L2[bitrate_index];
106990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else
107090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bitrate = kBitRateTableV1L3[bitrate_index];
107190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
107290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (layer == LAYER_1)
107390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bitrate = kBitRateTableV2L1[bitrate_index];
107490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else
107590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      bitrate = kBitRateTableV2L23[bitrate_index];
107690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
107790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (layer == LAYER_1)
107890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *framesize = ((12000 * bitrate) / sampling_rate + padding) * 4;
107990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else
108090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *framesize = (144000 * bitrate) / sampling_rate + padding;
108190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (bitrate > 0 && sampling_rate > 0);
108290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
108390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
108490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Extract a size encoded the MP3 way.
108590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int GetMp3HeaderSize(const uint8* buffer, int buffer_size) {
108690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_GE(buffer_size, 9);
108790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int size = ((buffer[6] & 0x7f) << 21) + ((buffer[7] & 0x7f) << 14) +
108890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)             ((buffer[8] & 0x7f) << 7) + (buffer[9] & 0x7f) + 10;
108990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (buffer[5] & 0x10)  // Footer added?
109090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size += 10;
109190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return size;
109290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
109390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
109490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Additional checks for a MP3 container.
109590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckMp3(const uint8* buffer, int buffer_size, bool seenHeader) {
109690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size >= 10);  // Must be enough to read the initial header.
109790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
109890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int framesize;
109990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int numSeen = 0;
110090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
110190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (seenHeader) {
110290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset = GetMp3HeaderSize(buffer, buffer_size);
110390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
110490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Skip over leading 0's.
110590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    while (offset < buffer_size && buffer[offset] == 0)
110690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ++offset;
110790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
110890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
110990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (offset + 3 < buffer_size) {
111090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ValidMpegAudioFrameHeader(
111190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        buffer + offset, buffer_size - offset, &framesize));
111290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
111390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Have we seen enough valid headers?
111490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (++numSeen > 10)
111590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;
111690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += framesize;
111790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
111890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Off the end of the buffer, return success if a few valid headers seen.
111990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return numSeen > 2;
112090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
112190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
112290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Check that the next characters in |buffer| represent a number. The format
112390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// accepted is optional whitespace followed by 1 or more digits. |max_digits|
112490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// specifies the maximum number of digits to process. Returns true if a valid
112590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// number is found, false otherwise.
112690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool VerifyNumber(const uint8* buffer,
112790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         int buffer_size,
112890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         int* offset,
112990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         int max_digits) {
113090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(*offset < buffer_size);
113190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
113290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Skip over any leading space.
113390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (isspace(buffer[*offset])) {
113490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ++(*offset);
113590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(*offset < buffer_size);
113690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
113790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
113890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Need to process up to max_digits digits.
113990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int numSeen = 0;
114090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (--max_digits >= 0 && isdigit(buffer[*offset])) {
114190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ++numSeen;
114290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ++(*offset);
114390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (*offset >= buffer_size)
114490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return true;  // Out of space but seen a digit.
114590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
114690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
114790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Success if at least one digit seen.
114890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (numSeen > 0);
114990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
115090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
115190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Check that the next character in |buffer| is one of |c1| or |c2|. |c2| is
115290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// optional. Returns true if there is a match, false if no match or out of
115390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// space.
115490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static inline bool VerifyCharacters(const uint8* buffer,
115590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    int buffer_size,
115690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    int* offset,
115790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    char c1,
115890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    char c2) {
115990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(*offset < buffer_size);
116090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  char c = static_cast<char>(buffer[(*offset)++]);
116190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (c == c1 || (c == c2 && c2 != 0));
116290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
116390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
116490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for a SRT container.
116590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckSrt(const uint8* buffer, int buffer_size) {
116690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: http://en.wikipedia.org/wiki/SubRip
116790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 20);
116890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
116990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // First line should just be the subtitle sequence number.
117090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = StartsWith(buffer, buffer_size, UTF8_BYTE_ORDER_MARK) ? 3 : 0;
117190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 100));
117290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, '\n', '\r'));
117390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
117490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Skip any additional \n\r.
117590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (VerifyCharacters(buffer, buffer_size, &offset, '\n', '\r')) {}
117690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  --offset;  // Since VerifyCharacters() gobbled up the next non-CR/LF.
117790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
117890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Second line should look like the following:
117990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //   00:00:10,500 --> 00:00:13,000
118090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Units separator can be , or .
118190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 100));
118290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ':', 0));
118390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 2));
118490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ':', 0));
118590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 2));
118690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ',', '.'));
118790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 3));
118890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ' ', 0));
118990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, '-', 0));
119090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, '-', 0));
119190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, '>', 0));
119290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ' ', 0));
119390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 100));
119490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ':', 0));
119590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 2));
119690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ':', 0));
119790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 2));
119890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyCharacters(buffer, buffer_size, &offset, ',', '.'));
119990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(VerifyNumber(buffer, buffer_size, &offset, 3));
120090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
120190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
120290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
120390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Read a Matroska Element Id.
120490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int GetElementId(BitReader* reader) {
120590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Element ID is coded with the leading zero bits (max 3) determining size.
120690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If it is an invalid encoding or the end of the buffer is reached,
120790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // return -1 as a tag that won't be expected.
120890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (reader->bits_available() >= 8) {
120990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int num_bits_to_read = 0;
121090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    static int prefix[] = { 0x80, 0x4000, 0x200000, 0x10000000 };
121190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (int i = 0; i < 4; ++i) {
121290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      num_bits_to_read += 7;
121390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (ReadBits(reader, 1) == 1) {
121490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (reader->bits_available() < num_bits_to_read)
121590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          break;
121690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // prefix[] adds back the bits read individually.
121790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return ReadBits(reader, num_bits_to_read) | prefix[i];
121890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
121990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
122090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
122190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Invalid encoding, return something not expected.
122290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return -1;
122390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
122490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
122590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Read a Matroska Unsigned Integer (VINT).
122690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static uint64 GetVint(BitReader* reader) {
122790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Values are coded with the leading zero bits (max 7) determining size.
122890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If it is an invalid coding or the end of the buffer is reached,
122990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // return something that will go off the end of the buffer.
123090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (reader->bits_available() >= 8) {
123190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int num_bits_to_read = 0;
123290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (int i = 0; i < 8; ++i) {
123390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      num_bits_to_read += 7;
123490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (ReadBits(reader, 1) == 1) {
123590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (reader->bits_available() < num_bits_to_read)
123690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          break;
123790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return ReadBits(reader, num_bits_to_read);
123890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
123990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
124090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
124190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Incorrect format (more than 7 leading 0's) or off the end of the buffer.
124290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Since the return value is used as a byte size, return a value that will
124390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // cause a failure when used.
124490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (reader->bits_available() / 8) + 2;
124590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
124690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
124790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Additional checks for a WEBM container.
124890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckWebm(const uint8* buffer, int buffer_size) {
124990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: http://www.matroska.org/technical/specs/index.html
125090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size > 12);
125190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
125290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  BitReader reader(buffer, buffer_size);
125390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
125490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Verify starting Element Id.
125590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(GetElementId(&reader) == 0x1a45dfa3);
125690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
125790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Get the header size, and ensure there are enough bits to check.
125890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int header_size = GetVint(&reader);
125990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(reader.bits_available() / 8 >= header_size);
126090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
126190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Loop through the header.
126290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (reader.bits_available() > 0) {
126390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int tag = GetElementId(&reader);
126490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int tagsize = GetVint(&reader);
126590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    switch (tag) {
126690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0x4286:  // EBMLVersion
126790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0x42f7:  // EBMLReadVersion
126890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0x42f2:  // EBMLMaxIdLength
126990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0x42f3:  // EBMLMaxSizeLength
127090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0x4287:  // DocTypeVersion
127190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0x4285:  // DocTypeReadVersion
127290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0xec:    // void
127390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0xbf:    // CRC32
127490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(reader.SkipBits(tagsize * 8));
127590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
127690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
127790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case 0x4282:  // EBMLDocType
127890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Need to see "webm" or "matroska" next.
127990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        switch (ReadBits(&reader, 32)) {
128090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          case TAG('w', 'e', 'b', 'm') :
128190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return true;
128290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          case TAG('m', 'a', 't', 'r') :
128390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return (ReadBits(&reader, 32) == TAG('o', 's', 'k', 'a'));
128490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
128590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
128690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
128790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      default:  // Unrecognized tag
128890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
128990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
129090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
129190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
129290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
129390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
129490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)enum VC1StartCodes {
129590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VC1_FRAME_START_CODE = 0x0d,
129690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VC1_ENTRY_POINT_START_CODE = 0x0e,
129790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  VC1_SEQUENCE_START_CODE = 0x0f
129890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
129990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
130090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Checks for a VC1 bitstream container.
130190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static bool CheckVC1(const uint8* buffer, int buffer_size) {
130290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Reference: SMPTE 421M
1303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // (http://standards.smpte.org/content/978-1-61482-555-5/st-421-2006/SEC1.body.pdf)
130490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // However, no length ... simply scan for start code values.
130590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Expect to see SEQ | [ [ ENTRY ] PIC* ]*
130690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Note tags are very similar to H.264.
130790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
130890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RCHECK(buffer_size >= 24);
130990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
131090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // First check for Bitstream Metadata Serialization (Annex L)
131190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (buffer[0] == 0xc5 &&
131290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Read32(buffer + 4) == 0x04 &&
131390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Read32(buffer + 20) == 0x0c) {
131490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Verify settings in STRUCT_C and STRUCT_A
131590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + 8, 12);
131690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
131790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int profile = ReadBits(&reader, 4);
131890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (profile == 0 || profile == 4) {  // simple or main
131990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip FRMRTQ_POSTPROC, BITRTQ_POSTPROC, and LOOPFILTER.
132090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(3 + 5 + 1);
132190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
132290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Next bit must be 0.
132390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 1) == 0);
132490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
132590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip MULTIRES.
132690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(1);
132790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
132890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Next bit must be 1.
132990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 1) == 1);
133090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
133190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip FASTUVMC, EXTENDED_MV, DQUANT, and VSTRANSFORM.
133290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(1 + 1 + 2 + 1);
133390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
133490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Next bit must be 0.
133590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 1) == 0);
133690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
133790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Skip OVERLAP, SYNCMARKER, RANGERED, MAXBFRAMES, QUANTIZER, and
133890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // FINTERPFLAG.
133990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      reader.SkipBits(1 + 1 + 1 + 3 + 2 + 1);
134090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
134190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Next bit must be 1.
134290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 1) == 1);
134390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
134490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
134590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(profile == 12);  // Other profile values not allowed.
134690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RCHECK(ReadBits(&reader, 28) == 0);
134790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
134890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
134990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Now check HORIZ_SIZE and VERT_SIZE, which must be 8192 or less.
135090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 32) <= 8192);
135190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 32) <= 8192);
135290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return true;
135390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
135490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
135590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Buffer isn't Bitstream Metadata, so scan for start codes.
135690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 0;
135790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int sequence_start_code = 0;
135890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int frame_start_code = 0;
135990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (true) {
136090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Advance to start_code, if there is one.
136190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!AdvanceToStartCode(buffer, buffer_size, &offset, 5, 24, 1)) {
136290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Not a complete sequence in memory, so return true if we've seen a
136390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // sequence start and a frame start (not checking entry points since
136490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // they only occur in advanced profiles).
136590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return (sequence_start_code > 0 && frame_start_code > 0);
136690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
136790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
136890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Now verify the block. AdvanceToStartCode() made sure that there are
136990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // at least 5 bytes remaining in the buffer.
137090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BitReader reader(buffer + offset, 5);
137190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RCHECK(ReadBits(&reader, 24) == 1);
137290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
137390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Keep track of the number of certain types received.
137490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    switch (ReadBits(&reader, 8)) {
137590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case VC1_SEQUENCE_START_CODE: {
137690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ++sequence_start_code;
137790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        switch (ReadBits(&reader, 2)) {
137890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          case 0:  // simple
137990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          case 1:  // main
138090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            RCHECK(ReadBits(&reader, 2) == 0);
138190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            break;
138290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          case 2:  // complex
138390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return false;
138490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          case 3:  // advanced
138590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            RCHECK(ReadBits(&reader, 3) <= 4);  // Verify level = 0..4
138690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            RCHECK(ReadBits(&reader, 2) == 1);  // Verify colordiff_format = 1
138790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            break;
138890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        }
138990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
139090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
139190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
139290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case VC1_ENTRY_POINT_START_CODE:
139390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // No fields in entry data to check. However, it must occur after
139490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // sequence header.
139590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        RCHECK(sequence_start_code > 0);
139690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
139790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
139890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case VC1_FRAME_START_CODE:
139990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ++frame_start_code;
140090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
140190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
140290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    offset += 5;
140390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
140490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
140590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
140690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// For some formats the signature is a bunch of characters. They are defined
140790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// below. Note that the first 4 characters of the string may be used as a TAG
140890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// in LookupContainerByFirst4. For signatures that contain embedded \0, use
140990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// uint8[].
141090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const char kAmrSignature[] = "#!AMR";
141190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const uint8 kAsfSignature[] = { 0x30, 0x26, 0xb2, 0x75, 0x8e, 0x66, 0xcf,
141290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62,
141390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       0xce, 0x6c };
141490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const char kAssSignature[] = "[Script Info]";
141590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const char kAssBomSignature[] = UTF8_BYTE_ORDER_MARK "[Script Info]";
141690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static const uint8 kWtvSignature[] = { 0xb7, 0xd8, 0x00, 0x20, 0x37, 0x49, 0xda,
141790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       0x11, 0xa6, 0x4e, 0x00, 0x07, 0xe9, 0x5e,
141890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                       0xad, 0x8d };
141990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
142090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Attempt to determine the container type from the buffer provided. This is
142190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// a simple pass, that uses the first 4 bytes of the buffer as an index to get
142290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// a rough idea of the container format.
142390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static MediaContainerName LookupContainerByFirst4(const uint8* buffer,
142490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                  int buffer_size) {
142590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Minimum size that the code expects to exist without checking size.
142690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (buffer_size < 12)
142790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_UNKNOWN;
142890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
142990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint32 first4 = Read32(buffer);
143090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (first4) {
143190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x1a45dfa3:
143290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckWebm(buffer, buffer_size))
143390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_WEBM;
143490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
143590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
143690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x3026b275:
143790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (StartsWith(buffer,
143890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     buffer_size,
143990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     kAsfSignature,
144090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     sizeof(kAsfSignature))) {
144190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_ASF;
144290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
144390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
144490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
144590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('#','!','A','M'):
144690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (StartsWith(buffer, buffer_size, kAmrSignature))
144790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_AMR;
144890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
144990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
145090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('#','E','X','T'):
145190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckHls(buffer, buffer_size))
145290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_HLS;
145390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
145490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
145590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('.','R','M','F'):
145690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (buffer[4] == 0 && buffer[5] == 0)
145790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_RM;
145890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
145990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
146090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('.','r','a','\xfd'):
146190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return CONTAINER_RM;
146290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
146390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('B','I','K','b'):
146490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('B','I','K','d'):
146590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('B','I','K','f'):
146690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('B','I','K','g'):
146790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('B','I','K','h'):
146890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('B','I','K','i'):
146990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckBink(buffer, buffer_size))
147090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_BINK;
147190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
147290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
147390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('c','a','f','f'):
147490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckCaf(buffer, buffer_size))
147590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_CAF;
147690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
147790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
147890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('D','E','X','A'):
147990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (buffer_size > 15 &&
148090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          Read16(buffer + 11) <= 2048 &&
148190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          Read16(buffer + 13) <= 2048) {
148290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_DXA;
148390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
148490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
148590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
148690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('D','T','S','H'):
148790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (Read32(buffer + 4) == TAG('D','H','D','R'))
148890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_DTSHD;
148990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
149090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
149190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x64a30100:
149290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x64a30200:
149390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x64a30300:
149490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x64a30400:
149590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x0001a364:
149690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x0002a364:
149790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x0003a364:
149890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (Read32(buffer + 4) != 0 && Read32(buffer + 8) != 0)
149990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_IRCAM;
150090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
150190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
150290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('f','L','a','C'):
150390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return CONTAINER_FLAC;
150490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
150590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('F','L','V',0):
150690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('F','L','V',1):
150790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('F','L','V',2):
150890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('F','L','V',3):
150990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('F','L','V',4):
151090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (buffer[5] == 0 && Read32(buffer + 5) > 8)
151190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_FLV;
151290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
151390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
151490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('F','O','R','M'):
151590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      switch (Read32(buffer + 8)) {
151690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case TAG('A','I','F','F'):
151790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case TAG('A','I','F','C'):
151890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          return CONTAINER_AIFF;
151990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
152090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
152190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
152290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('M','A','C',' '):
152390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return CONTAINER_APE;
152490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
152590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('O','N','2',' '):
152690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (Read32(buffer + 8) == TAG('O','N','2','f'))
152790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_AVI;
152890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
152990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
153090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('O','g','g','S'):
153190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (buffer[5] <= 7)
153290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_OGG;
153390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
153490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
153590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('R','F','6','4'):
153690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (buffer_size > 16 && Read32(buffer + 12) == TAG('d','s','6','4'))
153790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_WAV;
153890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
153990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
154090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('R','I','F','F'):
154190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      switch (Read32(buffer + 8)) {
154290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case TAG('A','V','I',' '):
154390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case TAG('A','V','I','X'):
154490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case TAG('A','V','I','\x19'):
154590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case TAG('A','M','V',' '):
154690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          return CONTAINER_AVI;
154790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        case TAG('W','A','V','E'):
154890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          return CONTAINER_WAV;
154990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
155090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
155190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
155290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('[','S','c','r'):
155390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (StartsWith(buffer, buffer_size, kAssSignature))
155490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_ASS;
155590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
155690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
155790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('\xef','\xbb','\xbf','['):
155890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (StartsWith(buffer, buffer_size, kAssBomSignature))
155990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_ASS;
156090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
156190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
156290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x7ffe8001:
156390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0xfe7f0180:
156490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0x1fffe800:
156590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0xff1f00e8:
156690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckDts(buffer, buffer_size))
156790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_DTS;
156890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
156990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
157090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0xb7d80020:
157190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (StartsWith(buffer,
157290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     buffer_size,
157390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     kWtvSignature,
157490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     sizeof(kWtvSignature))) {
157590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_WTV;
157690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
157790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
157890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
157990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
158090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Now try a few different ones that look at something other
158190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // than the first 4 bytes.
158290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint32 first3 = first4 & 0xffffff00;
158390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (first3) {
158490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('C','W','S',0):
158590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('F','W','S',0):
158690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return CONTAINER_SWF;
158790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
158890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TAG('I','D','3',0):
158990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckMp3(buffer, buffer_size, true))
159090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_MP3;
159190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
159290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
159390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
159490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Maybe the first 2 characters are something we can use.
159590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uint32 first2 = Read16(buffer);
159690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (first2) {
159790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kAc3SyncWord:
159890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckAc3(buffer, buffer_size))
159990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_AC3;
160090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckEac3(buffer, buffer_size))
160190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_EAC3;
160290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
160390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
160490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0xfff0:
160590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0xfff1:
160690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0xfff8:
160790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case 0xfff9:
160890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (CheckAac(buffer, buffer_size))
160990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return CONTAINER_AAC;
161090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
161190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
161290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
161390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check if the file is in MP3 format without the header.
161490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckMp3(buffer, buffer_size, false))
161590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_MP3;
161690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
161790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return CONTAINER_UNKNOWN;
161890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
161990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
162090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Attempt to determine the container name from the buffer provided.
162190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)MediaContainerName DetermineContainer(const uint8* buffer, int buffer_size) {
162290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(buffer);
162390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
162490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Since MOV/QuickTime/MPEG4 streams are common, check for them first.
162590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckMov(buffer, buffer_size))
162690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_MOV;
162790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
162890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Next attempt the simple checks, that typically look at just the
162990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // first few bytes of the file.
163090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MediaContainerName result = LookupContainerByFirst4(buffer, buffer_size);
163190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (result != CONTAINER_UNKNOWN)
163290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return result;
163390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
163490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Additional checks that may scan a portion of the buffer.
163590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckMpeg2ProgramStream(buffer, buffer_size))
163690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_MPEG2PS;
163790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckMpeg2TransportStream(buffer, buffer_size))
163890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_MPEG2TS;
163990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckMJpeg(buffer, buffer_size))
164090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_MJPEG;
164190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckDV(buffer, buffer_size))
164290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_DV;
164390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckH261(buffer, buffer_size))
164490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_H261;
164590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckH263(buffer, buffer_size))
164690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_H263;
164790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckH264(buffer, buffer_size))
164890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_H264;
164990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckMpeg4BitStream(buffer, buffer_size))
165090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_MPEG4BS;
165190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckVC1(buffer, buffer_size))
165290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_VC1;
165390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckSrt(buffer, buffer_size))
165490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_SRT;
165590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (CheckGsm(buffer, buffer_size))
165690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return CONTAINER_GSM;
165790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
165890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // AC3/EAC3 might not start at the beginning of the stream,
165990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // so scan for a start code.
166090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int offset = 1;  // No need to start at byte 0 due to First4 check.
166190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (AdvanceToStartCode(buffer, buffer_size, &offset, 4, 16, kAc3SyncWord)) {
166290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (CheckAc3(buffer + offset, buffer_size - offset))
166390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return CONTAINER_AC3;
166490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (CheckEac3(buffer + offset, buffer_size - offset))
166590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return CONTAINER_EAC3;
166690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
166790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
166890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return CONTAINER_UNKNOWN;
166990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
167090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
167190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace container_names
167290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
167390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace media
1674