Shaka Packager SDK
mpeg1_header.cc
1 #include "packager/media/formats/mp2t/mpeg1_header.h"
2 
3 #include "packager/media/base/bit_reader.h"
4 #include "packager/media/base/bit_writer.h"
5 #include "packager/media/formats/mp2t/mp2t_common.h"
6 
7 // Parsing is done according to
8 // https://www.datavoyage.com/mpgscript/mpeghdr.htm
9 namespace {
10 const size_t kMpeg1HeaderMinSize = 4;
11 
12 const uint8_t kMpeg1V_INV = 0b01; /* Invalid version */
13 const uint8_t kMpeg1L_INV = 0b00; /* Invalid layer */
14 
15 const uint8_t kMpeg1L_3 = 0b01;
16 const uint8_t kMpeg1L_2 = 0b10;
17 const uint8_t kMpeg1L_1 = 0b11;
18 
19 const size_t kMpeg1SamplesPerFrameTable[] = {
20  // L1, L2, L3
21  384, 1152, 1152};
22 
23 const uint32_t kMpeg1SampleRateTable[][3] = {
24  // clang-format off
25  // V1, V2, V2.5
26  {44100, 22050, 11025},
27  {48000, 24000, 12000},
28  {32000, 16000, 8000}};
29  // clang-format on
30 const size_t kMpeg1SampleRateTableSize = arraysize(kMpeg1SampleRateTable);
31 
32 static inline uint32_t Mpeg1SampleRate(uint8_t sr_idx, uint8_t version) {
33  static int sr_version_indexes[] = {2, -1, 1, 0}; // {V2.5, RESERVED, V2, V1}
34  DCHECK_NE(version, 1);
35  DCHECK_LT(sr_idx, kMpeg1SampleRateTableSize);
36  return kMpeg1SampleRateTable[sr_idx][sr_version_indexes[version]];
37 }
38 
39 const uint32_t kMpeg1BitrateTable[][5] = {
40  // clang-format off
41  // V1:L1, V1:L2, V1:L3, V2:L1, V2&V2.5:L2&L3
42  { 0, 0, 0, 0, 0},
43  { 32, 32, 32, 32, 8},
44  { 64, 48, 40, 48, 16},
45  { 96, 56, 48, 56, 24},
46  { 128, 64, 56, 64, 32},
47  { 160, 80, 64, 80, 40},
48  { 192, 96, 80, 96, 48},
49  { 224, 112, 96, 112, 56},
50  { 256, 128, 112, 128, 64},
51  { 288, 160, 128, 144, 80},
52  { 320, 192, 160, 160, 96},
53  { 352, 224, 192, 176, 112},
54  { 384, 256, 224, 192, 128},
55  { 416, 320, 256, 224, 144},
56  { 448, 384, 320, 256, 160}};
57  // clang-format on
58 const size_t kMpeg1BitrateTableSize = arraysize(kMpeg1BitrateTable);
59 
60 static inline uint32_t Mpeg1BitRate(uint8_t btr_idx,
61  uint8_t version,
62  uint8_t layer) {
63  static int btr_version_indexes[] = {1, -1, 1, 0}; // {V2.5, RESERVED, V2, V1}
64  static int btr_layer_indexes[] = {-1, 2, 1, 0}; // {RESERVED, L3, L2, L1}
65 
66  DCHECK_NE(version, 1);
67  DCHECK_NE(layer, 0);
68  int vidx = btr_version_indexes[version];
69  int lidx = btr_layer_indexes[layer];
70  if (vidx == 1 && lidx > 1)
71  lidx = 1;
72 
73  DCHECK_LT(vidx * 3 + lidx, 5);
74  DCHECK_LT(btr_idx, kMpeg1BitrateTableSize);
75  return kMpeg1BitrateTable[btr_idx][vidx * 3 + lidx] * 1000;
76 }
77 
78 static inline size_t Mpeg1FrameSize(uint8_t layer,
79  uint32_t bitrate,
80  uint32_t sample_rate,
81  uint8_t padded) {
82  DCHECK_GT(sample_rate, static_cast<uint32_t>(0));
83  if (layer == kMpeg1L_1)
84  return (12 * bitrate / sample_rate + padded) * 4;
85  return 144 * bitrate / sample_rate + padded;
86 }
87 
88 } // namespace
89 
90 namespace shaka {
91 namespace media {
92 namespace mp2t {
93 
94 bool Mpeg1Header::IsSyncWord(const uint8_t* buf) const {
95  return (buf[0] == 0xff) &&
96  ((buf[1] & 0b11100000) == 0b11100000)
97  // Version 01 is reserved
98  && ((buf[1] & 0b00011000) != 0b00001000)
99  // Layer 00 is reserved
100  && ((buf[1] & 0b00000110) != 0b00000000);
101 }
102 
104  return kMpeg1HeaderMinSize + 1;
105 }
106 
108  static int spf_layer_indexes[] = {-1, 2, 1, 0}; // {RESERVED, L3, L2, L1}
109  DCHECK_NE(layer_, 0);
110  return kMpeg1SamplesPerFrameTable[spf_layer_indexes[layer_]];
111 }
112 
113 bool Mpeg1Header::Parse(const uint8_t* mpeg1_frame, size_t mpeg1_frame_size) {
114  DCHECK(mpeg1_frame);
115 
116  if (mpeg1_frame_size < kMpeg1HeaderMinSize)
117  return false;
118 
119  BitReader frame(mpeg1_frame, mpeg1_frame_size);
120  // Verify frame starts with sync bits (0x7ff).
121  uint32_t sync;
122  RCHECK(frame.ReadBits(11, &sync));
123  RCHECK(sync == 0x7ff);
124  // MPEG version and layer.
125  RCHECK(frame.ReadBits(2, &version_));
126  RCHECK(version_ != kMpeg1V_INV);
127  RCHECK(frame.ReadBits(2, &layer_));
128  RCHECK(layer_ != kMpeg1L_INV);
129  RCHECK(frame.ReadBits(1, &protection_absent_));
130 
131  uint8_t btr_idx;
132  RCHECK(frame.ReadBits(4, &btr_idx));
133  RCHECK(btr_idx > 0);
134  bitrate_ = Mpeg1BitRate(btr_idx, version_, layer_);
135 
136  uint8_t sr_idx;
137  RCHECK(frame.ReadBits(2, &sr_idx));
138  RCHECK(sr_idx < 0b11);
139  sample_rate_ = Mpeg1SampleRate(sr_idx, version_);
140 
141  RCHECK(frame.ReadBits(1, &padded_));
142  // Skip private stream bit.
143  RCHECK(frame.SkipBits(1));
144 
145  RCHECK(frame.ReadBits(2, &channel_mode_));
146  // Skip Mode extension
147  RCHECK(frame.SkipBits(2));
148  // Skip copyright, origination and emphasis info.
149  RCHECK(frame.SkipBits(4));
150 
151  return true;
152 }
153 
155  // Unlike ADTS, for MP3, the whole frame is included in the media sample, so
156  // return 0 header size.
157  return 0;
158 }
159 
161  return Mpeg1FrameSize(layer_, bitrate_, sample_rate_, padded_);
162 }
163 
164 size_t Mpeg1Header::GetFrameSizeWithoutParsing(const uint8_t* data,
165  size_t num_bytes) const {
166  DCHECK_GT(num_bytes, static_cast<size_t>(2));
167  uint8_t version = (data[1] & 0b00011000) >> 3;
168  uint8_t layer = (data[1] & 0b00000110) >> 1;
169  uint8_t btr_idx = (data[2] & 0b11110000) >> 4;
170  uint8_t sr_idx = (data[2] & 0b00001100) >> 2;
171  uint8_t padded = (data[2] & 0b00000010) >> 1;
172 
173  if ((version == kMpeg1V_INV) || (layer == kMpeg1L_INV) || (btr_idx == 0) ||
174  (sr_idx == 0b11))
175  return 0;
176 
177  uint32_t bitrate = Mpeg1BitRate(btr_idx, version, layer);
178  uint32_t samplerate = Mpeg1SampleRate(sr_idx, version);
179  return Mpeg1FrameSize(layer, bitrate, samplerate, padded);
180 }
181 
182 void Mpeg1Header::GetAudioSpecificConfig(std::vector<uint8_t>* buffer) const {
183  // The following conversion table is extracted from ISO 14496 Part 3 -
184  // Table 1.16 - Sampling Frequency Index.
185  static const size_t kConfigFrequencyTable[] = {
186  96000, 88200, 64000, 48000, 44100, 32000, 24000,
187  22050, 16000, 12000, 11025, 8000, 7350};
188  static const size_t kConfigFrequencyTableSize =
189  arraysize(kConfigFrequencyTable);
190  uint8_t cft_idx;
191 
192  for (cft_idx = 0; cft_idx < kConfigFrequencyTableSize; cft_idx++)
193  if (sample_rate_ == kConfigFrequencyTable[cft_idx])
194  break;
195 
196  DCHECK(buffer);
197  buffer->clear();
198  BitWriter config(buffer);
199 
200  // ISO/IEC 14496:3 Table 1.16 Syntax of GetAudioObjetType()
201  auto object_type = GetObjectType();
202  if (object_type <= 31) {
203  config.WriteBits(object_type, 5);
204  } else {
205  config.WriteBits(31, 5);
206  config.WriteBits(object_type - 32, 6);
207  }
208 
209  config.WriteBits(cft_idx, 4);
210  /*
211  * NOTE: Number of channels matches channel_configuration index,
212  * since mpeg1 audio has only 1 or 2 channels
213  */
214  config.WriteBits(GetNumChannels(), 4);
215  config.Flush();
216 }
217 
218 uint8_t Mpeg1Header::GetObjectType() const {
219  /*
220  * ISO14496-3:2009 Table 1.17 - Audio Object Types
221  */
222  if (layer_ == kMpeg1L_1)
223  return 32;
224  if (layer_ == kMpeg1L_2)
225  return 33;
226 
227  DCHECK_EQ(layer_, kMpeg1L_3);
228  return 34;
229 }
230 
232  return sample_rate_;
233 }
234 
236  if (channel_mode_ == 0b11)
237  return 1;
238  return 2;
239 }
240 
241 } // namespace mp2t
242 } // namespace media
243 } // namespace shaka
shaka::media::BitReader::ReadBits
bool ReadBits(size_t num_bits, T *out)
Definition: bit_reader.h:35
shaka
All the methods that are virtual are virtual for mocking.
Definition: gflags_hex_bytes.cc:11
shaka::media::mp2t::Mpeg1Header::GetObjectType
uint8_t GetObjectType() const override
Definition: mpeg1_header.cc:218
shaka::media::BitReader
A class to read bit streams.
Definition: bit_reader.h:17
shaka::media::mp2t::Mpeg1Header::GetMinFrameSize
size_t GetMinFrameSize() const override
Definition: mpeg1_header.cc:103
shaka::media::mp2t::Mpeg1Header::GetAudioSpecificConfig
void GetAudioSpecificConfig(std::vector< uint8_t > *buffer) const override
Definition: mpeg1_header.cc:182
shaka::media::mp2t::Mpeg1Header::GetNumChannels
uint8_t GetNumChannels() const override
Definition: mpeg1_header.cc:235
shaka::media::mp2t::Mpeg1Header::GetSamplesPerFrame
size_t GetSamplesPerFrame() const override
Definition: mpeg1_header.cc:107
shaka::media::mp2t::Mpeg1Header::GetFrameSizeWithoutParsing
size_t GetFrameSizeWithoutParsing(const uint8_t *data, size_t num_bytes) const override
Definition: mpeg1_header.cc:164
shaka::media::BitWriter
Definition: bit_writer.h:19
shaka::media::BitWriter::WriteBits
void WriteBits(uint32_t bits, size_t number_of_bits)
Definition: bit_writer.cc:15
shaka::media::mp2t::Mpeg1Header::IsSyncWord
bool IsSyncWord(const uint8_t *buf) const override
Definition: mpeg1_header.cc:94
shaka::media::BitReader::SkipBits
bool SkipBits(size_t num_bits)
Definition: bit_reader.cc:24
shaka::media::mp2t::Mpeg1Header::GetFrameSize
size_t GetFrameSize() const override
Definition: mpeg1_header.cc:160
shaka::media::mp2t::Mpeg1Header::Parse
bool Parse(const uint8_t *mpeg1_frame, size_t mpeg1_frame_size) override
Definition: mpeg1_header.cc:113
shaka::media::BitWriter::Flush
void Flush()
Write pending bits, and align bitstream with extra zero bits.
Definition: bit_writer.cc:31
shaka::media::mp2t::Mpeg1Header::GetSamplingFrequency
uint32_t GetSamplingFrequency() const override
Definition: mpeg1_header.cc:231
shaka::media::mp2t::Mpeg1Header::GetHeaderSize
size_t GetHeaderSize() const override
Definition: mpeg1_header.cc:154