Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/mediasniffer/mp3sniff.c
Line
Count
Source (jump to first uncovered line)
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
static void mp3_parse(const uint8_t *p, mp3_header *header)
29
0
{
30
0
  const int bitrates[2][16] = {
31
0
        /* MPEG version 1 layer 3 bitrates. */
32
0
  {0,  32000,  40000,  48000,  56000,  64000,  80000,  96000,
33
0
         112000, 128000, 160000, 192000, 224000, 256000, 320000, 0},
34
0
        /* MPEG Version 2 and 2.5 layer 3 bitrates */
35
0
        {0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000,
36
0
         80000, 96000, 112000, 128000, 144000, 160000, 0} };
37
0
  const int samplerates[4] = {44100, 48000, 32000, 0};
38
0
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
0
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
0
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
static int mp3_framesize(mp3_header *header)
59
0
{
60
0
  int size;
61
0
  int scale;
62
0
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
0
68
0
  return size;
69
0
}
70
71
0
static int is_mp3(const uint8_t *p, long length) {
72
0
  /* Do we have enough room to see a 4 byte header? */
73
0
  if (length < 4) return 0;
74
0
  /* Do we have a sync pattern? */
75
0
  if (p[0] == 0xff && (p[1] & 0xe0) == 0xe0) {
76
0
    /* 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
0
    /* Looks like a header. */
81
0
    if ((4 - ((p[1] & 0x06) >> 1)) != 3) return 0; /* Only want level 3 */
82
0
    return 1;
83
0
  }
84
0
  return 0;
85
0
}
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
0
  /* Do we have enough room to see the header? */
91
0
  if (length < 10) return 0;
92
0
  /* 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
0
    /* Looks like an id3 header. */
98
0
    return 1;
99
0
  }
100
0
  return 0;
101
0
}
102
103
/* Calculate the size of an id3 tag structure from its header. */
104
static int id3_framesize(const uint8_t *p, long length)
105
0
{
106
0
  int size;
107
0
108
0
  /* Header is 10 bytes. */
109
0
  if (length < 10) {
110
0
    return 0;
111
0
  }
112
0
  /* Frame is header plus declared size. */
113
0
  size = 10 + (p[9] | (p[8] << 7) | (p[7] << 14) | (p[6] << 21));
114
0
115
0
  return size;
116
0
}
117
118
int mp3_sniff(const uint8_t *buf, long length)
119
0
{
120
0
  mp3_header header;
121
0
  const uint8_t *p;
122
0
  long skip;
123
0
  long avail;
124
0
125
0
  p = buf;
126
0
  avail = length;
127
0
  while (avail >= 4) {
128
0
    if (is_id3(p, avail)) {
129
0
      /* 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
0
      }
139
0
      p += skip;
140
0
      avail -= skip;
141
0
      /* Check for a second header at the expected offset. */
142
0
      if (is_mp3(p, avail)) {
143
0
        /* Looks like mp3. */
144
0
        return 1;
145
0
      } else {
146
0
        /* No second header. Not mp3. */
147
0
        return 0;
148
0
      }
149
0
    } else {
150
0
      /* No id3 tag or mp3 header. Not mp3. */
151
0
      return 0;
152
0
    }
153
0
  }
154
0
155
0
  return 0;
156
0
}