LCOV - code coverage report
Current view: top level - toolkit/components/mediasniffer - mp3sniff.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 66 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source 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/. */
       4             : 
       5             : /* MPEG format parsing */
       6             : 
       7             : #include "mp3sniff.h"
       8             : 
       9             : /* Maximum packet size is 320 kbits/s * 144 / 32 kHz + 1 padding byte */
      10             : #define MP3_MAX_SIZE 1441
      11             : 
      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;
      26             : 
      27             : /* Parse the 4-byte header in p and fill in the header struct. */
      28           0 : static void mp3_parse(const uint8_t *p, mp3_header *header)
      29             : {
      30           0 :   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           0 :   const int samplerates[4] = {44100, 48000, 32000, 0};
      38             : 
      39           0 :   header->version = (p[1] & 0x18) >> 3;
      40           0 :   header->layer = 4 - ((p[1] & 0x06) >> 1);
      41           0 :   header->errp = (p[1] & 0x01);
      42             : 
      43           0 :   header->bitrate = bitrates[(header->version & 1) ? 0 : 1][(p[2] & 0xf0) >> 4];
      44           0 :   header->freq = samplerates[(p[2] & 0x0c) >> 2];
      45           0 :   if (header->version == 2) header->freq >>= 1;
      46           0 :   else if (header->version == 0) header->freq >>= 2;
      47           0 :   header->pad = (p[2] & 0x02) >> 1;
      48           0 :   header->priv = (p[2] & 0x01);
      49             : 
      50           0 :   header->mode = (p[3] & 0xc0) >> 6;
      51           0 :   header->modex = (p[3] & 0x30) >> 4;
      52           0 :   header->copyright = (p[3] & 0x08) >> 3;
      53           0 :   header->original = (p[3] & 0x04) >> 2;
      54           0 :   header->emphasis = (p[3] & 0x03);
      55           0 : }
      56             : 
      57             : /* calculate the size of an mp3 frame from its header */
      58           0 : static int mp3_framesize(mp3_header *header)
      59             : {
      60             :   int size;
      61             :   int scale;
      62             : 
      63           0 :   if ((header->version & 1) == 0) scale = 72;
      64           0 :   else scale = 144;
      65           0 :   size = header->bitrate * scale / header->freq;
      66           0 :   if (header->pad) size += 1;
      67             : 
      68           0 :   return size;
      69             : }
      70             : 
      71           0 : static int is_mp3(const uint8_t *p, long length) {
      72             :   /* Do we have enough room to see a 4 byte header? */
      73           0 :   if (length < 4) return 0;
      74             :   /* Do we have a sync pattern? */
      75           0 :   if (p[0] == 0xff && (p[1] & 0xe0) == 0xe0) {
      76             :     /* Do we have any illegal field values? */
      77           0 :     if (((p[1] & 0x06) >> 1) == 0) return 0;  /* No layer 4 */
      78           0 :     if (((p[2] & 0xf0) >> 4) == 15) return 0; /* Bitrate can't be 1111 */
      79           0 :     if (((p[2] & 0x0c) >> 2) == 3) return 0;  /* Samplerate can't be 11 */
      80             :     /* Looks like a header. */
      81           0 :     if ((4 - ((p[1] & 0x06) >> 1)) != 3) return 0; /* Only want level 3 */
      82           0 :     return 1;
      83             :   }
      84           0 :   return 0;
      85             : }
      86             : 
      87             : /* Identify an ID3 tag based on its header. */
      88             : /* http://id3.org/id3v2.4.0-structure */
      89           0 : static int is_id3(const uint8_t *p, long length) {
      90             :   /* Do we have enough room to see the header? */
      91           0 :   if (length < 10) return 0;
      92             :   /* Do we have a sync pattern? */
      93           0 :   if (p[0] == 'I' && p[1] == 'D' && p[2] == '3') {
      94           0 :     if (p[3] == 0xff || p[4] == 0xff) return 0; /* Illegal version. */
      95           0 :     if (p[6] & 0x80 || p[7] & 0x80 ||
      96           0 :         p[8] & 0x80) return 0; /* Bad length encoding. */
      97             :     /* Looks like an id3 header. */
      98           0 :     return 1;
      99             :   }
     100           0 :   return 0;
     101             : }
     102             : 
     103             : /* Calculate the size of an id3 tag structure from its header. */
     104           0 : static int id3_framesize(const uint8_t *p, long length)
     105             : {
     106             :   int size;
     107             : 
     108             :   /* Header is 10 bytes. */
     109           0 :   if (length < 10) {
     110           0 :     return 0;
     111             :   }
     112             :   /* Frame is header plus declared size. */
     113           0 :   size = 10 + (p[9] | (p[8] << 7) | (p[7] << 14) | (p[6] << 21));
     114             : 
     115           0 :   return size;
     116             : }
     117             : 
     118           0 : int mp3_sniff(const uint8_t *buf, long length)
     119             : {
     120             :   mp3_header header;
     121             :   const uint8_t *p;
     122             :   long skip;
     123             :   long avail;
     124             : 
     125           0 :   p = buf;
     126           0 :   avail = length;
     127           0 :   while (avail >= 4) {
     128           0 :     if (is_id3(p, avail)) {
     129             :       /* Skip over any id3 tags */
     130           0 :       skip = id3_framesize(p, avail);
     131           0 :       p += skip;
     132           0 :       avail -= skip;
     133           0 :     } else if (is_mp3(p, avail)) {
     134           0 :       mp3_parse(p, &header);
     135           0 :       skip = mp3_framesize(&header);
     136           0 :       if (skip < 4 || skip + 4 >= avail) {
     137           0 :         return 0;
     138             :       }
     139           0 :       p += skip;
     140           0 :       avail -= skip;
     141             :       /* Check for a second header at the expected offset. */
     142           0 :       if (is_mp3(p, avail)) {
     143             :         /* Looks like mp3. */
     144           0 :         return 1;
     145             :       } else {
     146             :         /* No second header. Not mp3. */
     147           0 :         return 0;
     148             :       }
     149             :     } else {
     150             :       /* No id3 tag or mp3 header. Not mp3. */
     151           0 :       return 0;
     152             :     }
     153             :   }
     154             : 
     155           0 :   return 0;
     156             : }

Generated by: LCOV version 1.13