toolkit/components/mediasniffer/mp3sniff.c

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /* MPEG format parsing */
     7 #include "mp3sniff.h"
     9 /* Maximum packet size is 320 kbits/s * 144 / 32 kHz + 1 padding byte */
    10 #define MP3_MAX_SIZE 1441
    12 typedef struct {
    13   int version;
    14   int layer;
    15   int errp;
    16   int bitrate;
    17   int freq;
    18   int pad;
    19   int priv;
    20   int mode;
    21   int modex;
    22   int copyright;
    23   int original;
    24   int emphasis;
    25 } mp3_header;
    27 /* Parse the 4-byte header in p and fill in the header struct. */
    28 static void mp3_parse(const uint8_t *p, mp3_header *header)
    29 {
    30   const int bitrates[2][16] = {
    31         /* MPEG version 1 layer 3 bitrates. */
    32 	{0,  32000,  40000,  48000,  56000,  64000,  80000,  96000,
    33          112000, 128000, 160000, 192000, 224000, 256000, 320000, 0},
    34         /* MPEG Version 2 and 2.5 layer 3 bitrates */
    35         {0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000,
    36          80000, 96000, 112000, 128000, 144000, 160000, 0} };
    37   const int samplerates[4] = {44100, 48000, 32000, 0};
    39   header->version = (p[1] & 0x18) >> 3;
    40   header->layer = 4 - ((p[1] & 0x06) >> 1);
    41   header->errp = (p[1] & 0x01);
    43   header->bitrate = bitrates[(header->version & 1) ? 0 : 1][(p[2] & 0xf0) >> 4];
    44   header->freq = samplerates[(p[2] & 0x0c) >> 2];
    45   if (header->version == 2) header->freq >>= 1;
    46   else if (header->version == 0) header->freq >>= 2;
    47   header->pad = (p[2] & 0x02) >> 1;
    48   header->priv = (p[2] & 0x01);
    50   header->mode = (p[3] & 0xc0) >> 6;
    51   header->modex = (p[3] & 0x30) >> 4;
    52   header->copyright = (p[3] & 0x08) >> 3;
    53   header->original = (p[3] & 0x04) >> 2;
    54   header->emphasis = (p[3] & 0x03);
    55 }
    57 /* calculate the size of an mp3 frame from its header */
    58 static int mp3_framesize(mp3_header *header)
    59 {
    60   int size;
    61   int scale;
    63   if ((header->version & 1) == 0) scale = 72;
    64   else scale = 144;
    65   size = header->bitrate * scale / header->freq;
    66   if (header->pad) size += 1;
    68   return size;
    69 }
    71 static int is_mp3(const uint8_t *p, long length) {
    72   /* Do we have enough room to see a 4 byte header? */
    73   if (length < 4) return 0;
    74   /* Do we have a sync pattern? */
    75   if (p[0] == 0xff && (p[1] & 0xe0) == 0xe0) {
    76     /* Do we have any illegal field values? */
    77     if (((p[1] & 0x06) >> 1) == 0) return 0;  /* No layer 4 */
    78     if (((p[2] & 0xf0) >> 4) == 15) return 0; /* Bitrate can't be 1111 */
    79     if (((p[2] & 0x0c) >> 2) == 3) return 0;  /* Samplerate can't be 11 */
    80     /* Looks like a header. */
    81     if ((4 - ((p[1] & 0x06) >> 1)) != 3) return 0; /* Only want level 3 */
    82     return 1;
    83   }
    84   return 0;
    85 }
    87 /* Identify an ID3 tag based on its header. */
    88 /* http://id3.org/id3v2.4.0-structure */
    89 static int is_id3(const uint8_t *p, long length) {
    90   /* Do we have enough room to see the header? */
    91   if (length < 10) return 0;
    92   /* Do we have a sync pattern? */
    93   if (p[0] == 'I' && p[1] == 'D' && p[2] == '3') {
    94     if (p[3] == 0xff || p[4] == 0xff) return 0; /* Illegal version. */
    95     if (p[6] & 0x80 || p[7] & 0x80 ||
    96         p[8] & 0x80) return 0; /* Bad length encoding. */
    97     /* Looks like an id3 header. */
    98     return 1;
    99   }
   100   return 0;
   101 }
   103 /* Calculate the size of an id3 tag structure from its header. */
   104 static int id3_framesize(const uint8_t *p, long length)
   105 {
   106   int size;
   108   /* Header is 10 bytes. */
   109   if (length < 10) {
   110     return 0;
   111   }
   112   /* Frame is header plus declared size. */
   113   size = 10 + (p[9] | (p[8] << 7) | (p[7] << 14) | (p[6] << 21));
   115   return size;
   116 }
   118 int mp3_sniff(const uint8_t *buf, long length)
   119 {
   120   mp3_header header;
   121   const uint8_t *p, *q;
   122   long skip;
   123   long avail;
   125   p = buf;
   126   q = p;
   127   avail = length;
   128   while (avail >= 4) {
   129     if (is_id3(p, avail)) {
   130       /* Skip over any id3 tags */
   131       skip = id3_framesize(p, avail);
   132       p += skip;
   133       avail -= skip;
   134     } else if (is_mp3(p, avail)) {
   135       mp3_parse(p, &header);
   136       skip = mp3_framesize(&header);
   137       if (skip < 4 || skip + 4 >= avail) {
   138         return 0;
   139       }
   140       p += skip;
   141       avail -= skip;
   142       /* Check for a second header at the expected offset. */
   143       if (is_mp3(p, avail)) {
   144         /* Looks like mp3. */
   145         return 1;
   146       } else {
   147         /* No second header. Not mp3. */
   148         return 0;
   149       }
   150     } else {
   151       /* No id3 tag or mp3 header. Not mp3. */
   152       return 0;
   153     }
   154   }
   156   return 0;
   157 }

mercurial