Home | History | Annotate | Download | only in mpeg
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/formats/mpeg/mpeg_audio_stream_parser_base.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback_helpers.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "media/base/buffers.h"
     11 #include "media/base/stream_parser_buffer.h"
     12 #include "media/base/text_track_config.h"
     13 #include "media/base/video_decoder_config.h"
     14 
     15 namespace media {
     16 
     17 static const uint32 kICYStartCode = 0x49435920; // 'ICY '
     18 
     19 // Arbitrary upper bound on the size of an IceCast header before it
     20 // triggers an error.
     21 static const int kMaxIcecastHeaderSize = 4096;
     22 
     23 static const uint32 kID3StartCodeMask = 0xffffff00;
     24 static const uint32 kID3v1StartCode = 0x54414700; // 'TAG\0'
     25 static const int kID3v1Size = 128;
     26 static const int kID3v1ExtendedSize = 227;
     27 static const uint32 kID3v2StartCode = 0x49443300; // 'ID3\0'
     28 
     29 static int LocateEndOfHeaders(const uint8_t* buf, int buf_len, int i) {
     30   bool was_lf = false;
     31   char last_c = '\0';
     32   for (; i < buf_len; ++i) {
     33     char c = buf[i];
     34     if (c == '\n') {
     35       if (was_lf)
     36         return i + 1;
     37       was_lf = true;
     38     } else if (c != '\r' || last_c != '\n') {
     39       was_lf = false;
     40     }
     41     last_c = c;
     42   }
     43   return -1;
     44 }
     45 
     46 MPEGAudioStreamParserBase::MPEGAudioStreamParserBase(uint32 start_code_mask,
     47                                                      AudioCodec audio_codec,
     48                                                      int codec_delay)
     49     : state_(UNINITIALIZED),
     50       in_media_segment_(false),
     51       start_code_mask_(start_code_mask),
     52       audio_codec_(audio_codec),
     53       codec_delay_(codec_delay) {}
     54 
     55 MPEGAudioStreamParserBase::~MPEGAudioStreamParserBase() {}
     56 
     57 void MPEGAudioStreamParserBase::Init(const InitCB& init_cb,
     58                                      const NewConfigCB& config_cb,
     59                                      const NewBuffersCB& new_buffers_cb,
     60                                      bool ignore_text_tracks,
     61                                      const NeedKeyCB& need_key_cb,
     62                                      const NewMediaSegmentCB& new_segment_cb,
     63                                      const base::Closure& end_of_segment_cb,
     64                                      const LogCB& log_cb) {
     65   DVLOG(1) << __FUNCTION__;
     66   DCHECK_EQ(state_, UNINITIALIZED);
     67   init_cb_ = init_cb;
     68   config_cb_ = config_cb;
     69   new_buffers_cb_ = new_buffers_cb;
     70   new_segment_cb_ = new_segment_cb;
     71   end_of_segment_cb_ = end_of_segment_cb;
     72   log_cb_ = log_cb;
     73 
     74   ChangeState(INITIALIZED);
     75 }
     76 
     77 void MPEGAudioStreamParserBase::Flush() {
     78   DVLOG(1) << __FUNCTION__;
     79   DCHECK_NE(state_, UNINITIALIZED);
     80   queue_.Reset();
     81   timestamp_helper_->SetBaseTimestamp(base::TimeDelta());
     82   in_media_segment_ = false;
     83 }
     84 
     85 bool MPEGAudioStreamParserBase::Parse(const uint8* buf, int size) {
     86   DVLOG(1) << __FUNCTION__ << "(" << size << ")";
     87   DCHECK(buf);
     88   DCHECK_GT(size, 0);
     89   DCHECK_NE(state_, UNINITIALIZED);
     90 
     91   if (state_ == PARSE_ERROR)
     92     return false;
     93 
     94   DCHECK_EQ(state_, INITIALIZED);
     95 
     96   queue_.Push(buf, size);
     97 
     98   bool end_of_segment = true;
     99   BufferQueue buffers;
    100   for (;;) {
    101     const uint8* data;
    102     int data_size;
    103     queue_.Peek(&data, &data_size);
    104 
    105     if (data_size < 4)
    106       break;
    107 
    108     uint32 start_code = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
    109     int bytes_read = 0;
    110     bool parsed_metadata = true;
    111     if ((start_code & start_code_mask_) == start_code_mask_) {
    112       bytes_read = ParseFrame(data, data_size, &buffers);
    113 
    114       // Only allow the current segment to end if a full frame has been parsed.
    115       end_of_segment = bytes_read > 0;
    116       parsed_metadata = false;
    117     } else if (start_code == kICYStartCode) {
    118       bytes_read = ParseIcecastHeader(data, data_size);
    119     } else if ((start_code & kID3StartCodeMask) == kID3v1StartCode) {
    120       bytes_read = ParseID3v1(data, data_size);
    121     } else if ((start_code & kID3StartCodeMask) == kID3v2StartCode) {
    122       bytes_read = ParseID3v2(data, data_size);
    123     } else {
    124       bytes_read = FindNextValidStartCode(data, data_size);
    125 
    126       if (bytes_read > 0) {
    127         DVLOG(1) << "Unexpected start code 0x" << std::hex << start_code;
    128         DVLOG(1) << "SKIPPING " << bytes_read << " bytes of garbage.";
    129       }
    130     }
    131 
    132     CHECK_LE(bytes_read, data_size);
    133 
    134     if (bytes_read < 0) {
    135       ChangeState(PARSE_ERROR);
    136       return false;
    137     } else if (bytes_read == 0) {
    138       // Need more data.
    139       break;
    140     }
    141 
    142     // Send pending buffers if we have encountered metadata.
    143     if (parsed_metadata && !buffers.empty() && !SendBuffers(&buffers, true))
    144       return false;
    145 
    146     queue_.Pop(bytes_read);
    147     end_of_segment = true;
    148   }
    149 
    150   if (buffers.empty())
    151     return true;
    152 
    153   // Send buffers collected in this append that haven't been sent yet.
    154   return SendBuffers(&buffers, end_of_segment);
    155 }
    156 
    157 void MPEGAudioStreamParserBase::ChangeState(State state) {
    158   DVLOG(1) << __FUNCTION__ << "() : " << state_ << " -> " << state;
    159   state_ = state;
    160 }
    161 
    162 int MPEGAudioStreamParserBase::ParseFrame(const uint8* data,
    163                                           int size,
    164                                           BufferQueue* buffers) {
    165   DVLOG(2) << __FUNCTION__ << "(" << size << ")";
    166 
    167   int sample_rate;
    168   ChannelLayout channel_layout;
    169   int frame_size;
    170   int sample_count;
    171   bool metadata_frame = false;
    172   int bytes_read = ParseFrameHeader(data,
    173                                     size,
    174                                     &frame_size,
    175                                     &sample_rate,
    176                                     &channel_layout,
    177                                     &sample_count,
    178                                     &metadata_frame);
    179 
    180   if (bytes_read <= 0)
    181     return bytes_read;
    182 
    183   // Make sure data contains the entire frame.
    184   if (size < frame_size)
    185     return 0;
    186 
    187   DVLOG(2) << " sample_rate " << sample_rate
    188            << " channel_layout " << channel_layout
    189            << " frame_size " << frame_size
    190            << " sample_count " << sample_count;
    191 
    192   if (config_.IsValidConfig() &&
    193       (config_.samples_per_second() != sample_rate ||
    194        config_.channel_layout() != channel_layout)) {
    195     // Clear config data so that a config change is initiated.
    196     config_ = AudioDecoderConfig();
    197 
    198     // Send all buffers associated with the previous config.
    199     if (!buffers->empty() && !SendBuffers(buffers, true))
    200       return -1;
    201   }
    202 
    203   if (!config_.IsValidConfig()) {
    204     config_.Initialize(audio_codec_,
    205                        kSampleFormatF32,
    206                        channel_layout,
    207                        sample_rate,
    208                        NULL,
    209                        0,
    210                        false,
    211                        false,
    212                        base::TimeDelta(),
    213                        codec_delay_);
    214 
    215     base::TimeDelta base_timestamp;
    216     if (timestamp_helper_)
    217       base_timestamp = timestamp_helper_->GetTimestamp();
    218 
    219     timestamp_helper_.reset(new AudioTimestampHelper(sample_rate));
    220     timestamp_helper_->SetBaseTimestamp(base_timestamp);
    221 
    222     VideoDecoderConfig video_config;
    223     bool success = config_cb_.Run(config_, video_config, TextTrackConfigMap());
    224 
    225     if (!init_cb_.is_null()) {
    226       InitParameters params(kInfiniteDuration());
    227       params.auto_update_timestamp_offset = true;
    228       base::ResetAndReturn(&init_cb_).Run(success, params);
    229     }
    230 
    231     if (!success)
    232       return -1;
    233   }
    234 
    235   if (metadata_frame)
    236     return frame_size;
    237 
    238   // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId
    239   // type and allow multiple audio tracks, if applicable. See
    240   // https://crbug.com/341581.
    241   scoped_refptr<StreamParserBuffer> buffer =
    242       StreamParserBuffer::CopyFrom(data, frame_size, true,
    243                                    DemuxerStream::AUDIO, 0);
    244   buffer->set_timestamp(timestamp_helper_->GetTimestamp());
    245   buffer->set_duration(timestamp_helper_->GetFrameDuration(sample_count));
    246   buffers->push_back(buffer);
    247 
    248   timestamp_helper_->AddFrames(sample_count);
    249 
    250   return frame_size;
    251 }
    252 
    253 int MPEGAudioStreamParserBase::ParseIcecastHeader(const uint8* data, int size) {
    254   DVLOG(1) << __FUNCTION__ << "(" << size << ")";
    255 
    256   if (size < 4)
    257     return 0;
    258 
    259   if (memcmp("ICY ", data, 4))
    260     return -1;
    261 
    262   int locate_size = std::min(size, kMaxIcecastHeaderSize);
    263   int offset = LocateEndOfHeaders(data, locate_size, 4);
    264   if (offset < 0) {
    265     if (locate_size == kMaxIcecastHeaderSize) {
    266       MEDIA_LOG(log_cb_) << "Icecast header is too large.";
    267       return -1;
    268     }
    269 
    270     return 0;
    271   }
    272 
    273   return offset;
    274 }
    275 
    276 int MPEGAudioStreamParserBase::ParseID3v1(const uint8* data, int size) {
    277   DVLOG(1) << __FUNCTION__ << "(" << size << ")";
    278 
    279   if (size < kID3v1Size)
    280     return 0;
    281 
    282   // TODO(acolwell): Add code to actually validate ID3v1 data and
    283   // expose it as a metadata text track.
    284   return !memcmp(data, "TAG+", 4) ? kID3v1ExtendedSize : kID3v1Size;
    285 }
    286 
    287 int MPEGAudioStreamParserBase::ParseID3v2(const uint8* data, int size) {
    288   DVLOG(1) << __FUNCTION__ << "(" << size << ")";
    289 
    290   if (size < 10)
    291     return 0;
    292 
    293   BitReader reader(data, size);
    294   int32 id;
    295   int version;
    296   uint8 flags;
    297   int32 id3_size;
    298 
    299   if (!reader.ReadBits(24, &id) ||
    300       !reader.ReadBits(16, &version) ||
    301       !reader.ReadBits(8, &flags) ||
    302       !ParseSyncSafeInt(&reader, &id3_size)) {
    303     return -1;
    304   }
    305 
    306   int32 actual_tag_size = 10 + id3_size;
    307 
    308   // Increment size if 'Footer present' flag is set.
    309   if (flags & 0x10)
    310     actual_tag_size += 10;
    311 
    312   // Make sure we have the entire tag.
    313   if (size < actual_tag_size)
    314     return 0;
    315 
    316   // TODO(acolwell): Add code to actually validate ID3v2 data and
    317   // expose it as a metadata text track.
    318   return actual_tag_size;
    319 }
    320 
    321 bool MPEGAudioStreamParserBase::ParseSyncSafeInt(BitReader* reader,
    322                                                  int32* value) {
    323   *value = 0;
    324   for (int i = 0; i < 4; ++i) {
    325     uint8 tmp;
    326     if (!reader->ReadBits(1, &tmp) || tmp != 0) {
    327       MEDIA_LOG(log_cb_) << "ID3 syncsafe integer byte MSb is not 0!";
    328       return false;
    329     }
    330 
    331     if (!reader->ReadBits(7, &tmp))
    332       return false;
    333 
    334     *value <<= 7;
    335     *value += tmp;
    336   }
    337 
    338   return true;
    339 }
    340 
    341 int MPEGAudioStreamParserBase::FindNextValidStartCode(const uint8* data,
    342                                                       int size) const {
    343   const uint8* start = data;
    344   const uint8* end = data + size;
    345 
    346   while (start < end) {
    347     int bytes_left = end - start;
    348     const uint8* candidate_start_code =
    349         static_cast<const uint8*>(memchr(start, 0xff, bytes_left));
    350 
    351     if (!candidate_start_code)
    352       return 0;
    353 
    354     bool parse_header_failed = false;
    355     const uint8* sync = candidate_start_code;
    356     // Try to find 3 valid frames in a row. 3 was selected to decrease
    357     // the probability of false positives.
    358     for (int i = 0; i < 3; ++i) {
    359       int sync_size = end - sync;
    360       int frame_size;
    361       int sync_bytes = ParseFrameHeader(
    362           sync, sync_size, &frame_size, NULL, NULL, NULL, NULL);
    363 
    364       if (sync_bytes == 0)
    365         return 0;
    366 
    367       if (sync_bytes > 0) {
    368         DCHECK_LT(sync_bytes, sync_size);
    369 
    370         // Skip over this frame so we can check the next one.
    371         sync += frame_size;
    372 
    373         // Make sure the next frame starts inside the buffer.
    374         if (sync >= end)
    375           return 0;
    376       } else {
    377         DVLOG(1) << "ParseFrameHeader() " << i << " failed @" << (sync - data);
    378         parse_header_failed = true;
    379         break;
    380       }
    381     }
    382 
    383     if (parse_header_failed) {
    384       // One of the frame header parses failed so |candidate_start_code|
    385       // did not point to the start of a real frame. Move |start| forward
    386       // so we can find the next candidate.
    387       start = candidate_start_code + 1;
    388       continue;
    389     }
    390 
    391     return candidate_start_code - data;
    392   }
    393 
    394   return 0;
    395 }
    396 
    397 bool MPEGAudioStreamParserBase::SendBuffers(BufferQueue* buffers,
    398                                             bool end_of_segment) {
    399   DCHECK(!buffers->empty());
    400 
    401   if (!in_media_segment_) {
    402     in_media_segment_ = true;
    403     new_segment_cb_.Run();
    404   }
    405 
    406   BufferQueue empty_video_buffers;
    407   TextBufferQueueMap empty_text_map;
    408   if (!new_buffers_cb_.Run(*buffers, empty_video_buffers, empty_text_map))
    409     return false;
    410   buffers->clear();
    411 
    412   if (end_of_segment) {
    413     in_media_segment_ = false;
    414     end_of_segment_cb_.Run();
    415   }
    416 
    417   timestamp_helper_->SetBaseTimestamp(base::TimeDelta());
    418   return true;
    419 }
    420 
    421 }  // namespace media
    422