Home | History | Annotate | Download | only in mp2t
      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/mp2t/mp2t_stream_parser.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/callback_helpers.h"
      9 #include "base/memory/scoped_ptr.h"
     10 #include "base/stl_util.h"
     11 #include "media/base/audio_decoder_config.h"
     12 #include "media/base/buffers.h"
     13 #include "media/base/stream_parser_buffer.h"
     14 #include "media/base/text_track_config.h"
     15 #include "media/base/video_decoder_config.h"
     16 #include "media/formats/mp2t/es_parser.h"
     17 #include "media/formats/mp2t/es_parser_adts.h"
     18 #include "media/formats/mp2t/es_parser_h264.h"
     19 #include "media/formats/mp2t/mp2t_common.h"
     20 #include "media/formats/mp2t/ts_packet.h"
     21 #include "media/formats/mp2t/ts_section.h"
     22 #include "media/formats/mp2t/ts_section_pat.h"
     23 #include "media/formats/mp2t/ts_section_pes.h"
     24 #include "media/formats/mp2t/ts_section_pmt.h"
     25 
     26 namespace media {
     27 namespace mp2t {
     28 
     29 enum StreamType {
     30   // ISO-13818.1 / ITU H.222 Table 2.34 "Stream type assignments"
     31   kStreamTypeMpeg1Audio = 0x3,
     32   kStreamTypeAAC = 0xf,
     33   kStreamTypeAVC = 0x1b,
     34 };
     35 
     36 class PidState {
     37  public:
     38   enum PidType {
     39     kPidPat,
     40     kPidPmt,
     41     kPidAudioPes,
     42     kPidVideoPes,
     43   };
     44 
     45   PidState(int pid, PidType pid_tyoe,
     46            scoped_ptr<TsSection> section_parser);
     47 
     48   // Extract the content of the TS packet and parse it.
     49   // Return true if successful.
     50   bool PushTsPacket(const TsPacket& ts_packet);
     51 
     52   // Flush the PID state (possibly emitting some pending frames)
     53   // and reset its state.
     54   void Flush();
     55 
     56   // Enable/disable the PID.
     57   // Disabling a PID will reset its state and ignore any further incoming TS
     58   // packets.
     59   void Enable();
     60   void Disable();
     61   bool IsEnabled() const;
     62 
     63   PidType pid_type() const { return pid_type_; }
     64 
     65  private:
     66   void ResetState();
     67 
     68   int pid_;
     69   PidType pid_type_;
     70   scoped_ptr<TsSection> section_parser_;
     71 
     72   bool enable_;
     73 
     74   int continuity_counter_;
     75 };
     76 
     77 PidState::PidState(int pid, PidType pid_type,
     78                    scoped_ptr<TsSection> section_parser)
     79   : pid_(pid),
     80     pid_type_(pid_type),
     81     section_parser_(section_parser.Pass()),
     82     enable_(false),
     83     continuity_counter_(-1) {
     84   DCHECK(section_parser_);
     85 }
     86 
     87 bool PidState::PushTsPacket(const TsPacket& ts_packet) {
     88   DCHECK_EQ(ts_packet.pid(), pid_);
     89 
     90   // The current PID is not part of the PID filter,
     91   // just discard the incoming TS packet.
     92   if (!enable_)
     93     return true;
     94 
     95   int expected_continuity_counter = (continuity_counter_ + 1) % 16;
     96   if (continuity_counter_ >= 0 &&
     97       ts_packet.continuity_counter() != expected_continuity_counter) {
     98     DVLOG(1) << "TS discontinuity detected for pid: " << pid_;
     99     return false;
    100   }
    101 
    102   bool status = section_parser_->Parse(
    103       ts_packet.payload_unit_start_indicator(),
    104       ts_packet.payload(),
    105       ts_packet.payload_size());
    106 
    107   // At the minimum, when parsing failed, auto reset the section parser.
    108   // Components that use the StreamParser can take further action if needed.
    109   if (!status) {
    110     DVLOG(1) << "Parsing failed for pid = " << pid_;
    111     ResetState();
    112   }
    113 
    114   return status;
    115 }
    116 
    117 void PidState::Flush() {
    118   section_parser_->Flush();
    119   ResetState();
    120 }
    121 
    122 void PidState::Enable() {
    123   enable_ = true;
    124 }
    125 
    126 void PidState::Disable() {
    127   if (!enable_)
    128     return;
    129 
    130   ResetState();
    131   enable_ = false;
    132 }
    133 
    134 bool PidState::IsEnabled() const {
    135   return enable_;
    136 }
    137 
    138 void PidState::ResetState() {
    139   section_parser_->Reset();
    140   continuity_counter_ = -1;
    141 }
    142 
    143 Mp2tStreamParser::BufferQueueWithConfig::BufferQueueWithConfig(
    144     bool is_cfg_sent,
    145     const AudioDecoderConfig& audio_cfg,
    146     const VideoDecoderConfig& video_cfg)
    147   : is_config_sent(is_cfg_sent),
    148     audio_config(audio_cfg),
    149     video_config(video_cfg) {
    150 }
    151 
    152 Mp2tStreamParser::BufferQueueWithConfig::~BufferQueueWithConfig() {
    153 }
    154 
    155 Mp2tStreamParser::Mp2tStreamParser(bool sbr_in_mimetype)
    156   : sbr_in_mimetype_(sbr_in_mimetype),
    157     selected_audio_pid_(-1),
    158     selected_video_pid_(-1),
    159     is_initialized_(false),
    160     segment_started_(false),
    161     first_video_frame_in_segment_(true) {
    162 }
    163 
    164 Mp2tStreamParser::~Mp2tStreamParser() {
    165   STLDeleteValues(&pids_);
    166 }
    167 
    168 void Mp2tStreamParser::Init(
    169     const InitCB& init_cb,
    170     const NewConfigCB& config_cb,
    171     const NewBuffersCB& new_buffers_cb,
    172     bool /* ignore_text_tracks */ ,
    173     const NeedKeyCB& need_key_cb,
    174     const NewMediaSegmentCB& new_segment_cb,
    175     const base::Closure& end_of_segment_cb,
    176     const LogCB& log_cb) {
    177   DCHECK(!is_initialized_);
    178   DCHECK(init_cb_.is_null());
    179   DCHECK(!init_cb.is_null());
    180   DCHECK(!config_cb.is_null());
    181   DCHECK(!new_buffers_cb.is_null());
    182   DCHECK(!need_key_cb.is_null());
    183   DCHECK(!end_of_segment_cb.is_null());
    184 
    185   init_cb_ = init_cb;
    186   config_cb_ = config_cb;
    187   new_buffers_cb_ = new_buffers_cb;
    188   need_key_cb_ = need_key_cb;
    189   new_segment_cb_ = new_segment_cb;
    190   end_of_segment_cb_ = end_of_segment_cb;
    191   log_cb_ = log_cb;
    192 }
    193 
    194 void Mp2tStreamParser::Flush() {
    195   DVLOG(1) << "Mp2tStreamParser::Flush";
    196 
    197   // Flush the buffers and reset the pids.
    198   for (std::map<int, PidState*>::iterator it = pids_.begin();
    199        it != pids_.end(); ++it) {
    200     DVLOG(1) << "Flushing PID: " << it->first;
    201     PidState* pid_state = it->second;
    202     pid_state->Flush();
    203     delete pid_state;
    204   }
    205   pids_.clear();
    206   EmitRemainingBuffers();
    207   buffer_queue_chain_.clear();
    208 
    209   // End of the segment.
    210   // Note: does not need to invoke |end_of_segment_cb_| since flushing the
    211   // stream parser already involves the end of the current segment.
    212   segment_started_ = false;
    213   first_video_frame_in_segment_ = true;
    214   discarded_frames_dts_.clear();
    215 
    216   // Remove any bytes left in the TS buffer.
    217   // (i.e. any partial TS packet => less than 188 bytes).
    218   ts_byte_queue_.Reset();
    219 
    220   // Reset the selected PIDs.
    221   selected_audio_pid_ = -1;
    222   selected_video_pid_ = -1;
    223 }
    224 
    225 bool Mp2tStreamParser::Parse(const uint8* buf, int size) {
    226   DVLOG(1) << "Mp2tStreamParser::Parse size=" << size;
    227 
    228   // Add the data to the parser state.
    229   ts_byte_queue_.Push(buf, size);
    230 
    231   while (true) {
    232     const uint8* ts_buffer;
    233     int ts_buffer_size;
    234     ts_byte_queue_.Peek(&ts_buffer, &ts_buffer_size);
    235     if (ts_buffer_size < TsPacket::kPacketSize)
    236       break;
    237 
    238     // Synchronization.
    239     int skipped_bytes = TsPacket::Sync(ts_buffer, ts_buffer_size);
    240     if (skipped_bytes > 0) {
    241       DVLOG(1) << "Packet not aligned on a TS syncword:"
    242                << " skipped_bytes=" << skipped_bytes;
    243       ts_byte_queue_.Pop(skipped_bytes);
    244       continue;
    245     }
    246 
    247     // Parse the TS header, skipping 1 byte if the header is invalid.
    248     scoped_ptr<TsPacket> ts_packet(TsPacket::Parse(ts_buffer, ts_buffer_size));
    249     if (!ts_packet) {
    250       DVLOG(1) << "Error: invalid TS packet";
    251       ts_byte_queue_.Pop(1);
    252       continue;
    253     }
    254     DVLOG(LOG_LEVEL_TS)
    255         << "Processing PID=" << ts_packet->pid()
    256         << " start_unit=" << ts_packet->payload_unit_start_indicator();
    257 
    258     // Parse the section.
    259     std::map<int, PidState*>::iterator it = pids_.find(ts_packet->pid());
    260     if (it == pids_.end() &&
    261         ts_packet->pid() == TsSection::kPidPat) {
    262       // Create the PAT state here if needed.
    263       scoped_ptr<TsSection> pat_section_parser(
    264           new TsSectionPat(
    265               base::Bind(&Mp2tStreamParser::RegisterPmt,
    266                          base::Unretained(this))));
    267       scoped_ptr<PidState> pat_pid_state(
    268           new PidState(ts_packet->pid(), PidState::kPidPat,
    269                        pat_section_parser.Pass()));
    270       pat_pid_state->Enable();
    271       it = pids_.insert(
    272           std::pair<int, PidState*>(ts_packet->pid(),
    273                                     pat_pid_state.release())).first;
    274     }
    275 
    276     if (it != pids_.end()) {
    277       if (!it->second->PushTsPacket(*ts_packet))
    278         return false;
    279     } else {
    280       DVLOG(LOG_LEVEL_TS) << "Ignoring TS packet for pid: " << ts_packet->pid();
    281     }
    282 
    283     // Go to the next packet.
    284     ts_byte_queue_.Pop(TsPacket::kPacketSize);
    285   }
    286 
    287   RCHECK(FinishInitializationIfNeeded());
    288 
    289   // Emit the A/V buffers that kept accumulating during TS parsing.
    290   return EmitRemainingBuffers();
    291 }
    292 
    293 void Mp2tStreamParser::RegisterPmt(int program_number, int pmt_pid) {
    294   DVLOG(1) << "RegisterPmt:"
    295            << " program_number=" << program_number
    296            << " pmt_pid=" << pmt_pid;
    297 
    298   // Only one TS program is allowed. Ignore the incoming program map table,
    299   // if there is already one registered.
    300   for (std::map<int, PidState*>::iterator it = pids_.begin();
    301        it != pids_.end(); ++it) {
    302     PidState* pid_state = it->second;
    303     if (pid_state->pid_type() == PidState::kPidPmt) {
    304       DVLOG_IF(1, pmt_pid != it->first) << "More than one program is defined";
    305       return;
    306     }
    307   }
    308 
    309   // Create the PMT state here if needed.
    310   DVLOG(1) << "Create a new PMT parser";
    311   scoped_ptr<TsSection> pmt_section_parser(
    312       new TsSectionPmt(
    313           base::Bind(&Mp2tStreamParser::RegisterPes,
    314                      base::Unretained(this), pmt_pid)));
    315   scoped_ptr<PidState> pmt_pid_state(
    316       new PidState(pmt_pid, PidState::kPidPmt, pmt_section_parser.Pass()));
    317   pmt_pid_state->Enable();
    318   pids_.insert(std::pair<int, PidState*>(pmt_pid, pmt_pid_state.release()));
    319 }
    320 
    321 void Mp2tStreamParser::RegisterPes(int pmt_pid,
    322                                    int pes_pid,
    323                                    int stream_type) {
    324   // TODO(damienv): check there is no mismatch if the entry already exists.
    325   DVLOG(1) << "RegisterPes:"
    326            << " pes_pid=" << pes_pid
    327            << " stream_type=" << std::hex << stream_type << std::dec;
    328   std::map<int, PidState*>::iterator it = pids_.find(pes_pid);
    329   if (it != pids_.end())
    330     return;
    331 
    332   // Create a stream parser corresponding to the stream type.
    333   bool is_audio = false;
    334   scoped_ptr<EsParser> es_parser;
    335   if (stream_type == kStreamTypeAVC) {
    336     es_parser.reset(
    337         new EsParserH264(
    338             base::Bind(&Mp2tStreamParser::OnVideoConfigChanged,
    339                        base::Unretained(this),
    340                        pes_pid),
    341             base::Bind(&Mp2tStreamParser::OnEmitVideoBuffer,
    342                        base::Unretained(this),
    343                        pes_pid)));
    344   } else if (stream_type == kStreamTypeAAC) {
    345     es_parser.reset(
    346         new EsParserAdts(
    347             base::Bind(&Mp2tStreamParser::OnAudioConfigChanged,
    348                        base::Unretained(this),
    349                        pes_pid),
    350             base::Bind(&Mp2tStreamParser::OnEmitAudioBuffer,
    351                        base::Unretained(this),
    352                        pes_pid),
    353             sbr_in_mimetype_));
    354     is_audio = true;
    355   } else {
    356     return;
    357   }
    358 
    359   // Create the PES state here.
    360   DVLOG(1) << "Create a new PES state";
    361   scoped_ptr<TsSection> pes_section_parser(
    362       new TsSectionPes(es_parser.Pass()));
    363   PidState::PidType pid_type =
    364       is_audio ? PidState::kPidAudioPes : PidState::kPidVideoPes;
    365   scoped_ptr<PidState> pes_pid_state(
    366       new PidState(pes_pid, pid_type, pes_section_parser.Pass()));
    367   pids_.insert(std::pair<int, PidState*>(pes_pid, pes_pid_state.release()));
    368 
    369   // A new PES pid has been added, the PID filter might change.
    370   UpdatePidFilter();
    371 }
    372 
    373 void Mp2tStreamParser::UpdatePidFilter() {
    374   // Applies the HLS rule to select the default audio/video PIDs:
    375   // select the audio/video streams with the lowest PID.
    376   // TODO(damienv): this can be changed when the StreamParser interface
    377   // supports multiple audio/video streams.
    378   PidMap::iterator lowest_audio_pid = pids_.end();
    379   PidMap::iterator lowest_video_pid = pids_.end();
    380   for (PidMap::iterator it = pids_.begin(); it != pids_.end(); ++it) {
    381     int pid = it->first;
    382     PidState* pid_state = it->second;
    383     if (pid_state->pid_type() == PidState::kPidAudioPes &&
    384         (lowest_audio_pid == pids_.end() || pid < lowest_audio_pid->first))
    385       lowest_audio_pid = it;
    386     if (pid_state->pid_type() == PidState::kPidVideoPes &&
    387         (lowest_video_pid == pids_.end() || pid < lowest_video_pid->first))
    388       lowest_video_pid = it;
    389   }
    390 
    391   // Enable both the lowest audio and video PIDs.
    392   if (lowest_audio_pid != pids_.end()) {
    393     DVLOG(1) << "Enable audio pid: " << lowest_audio_pid->first;
    394     lowest_audio_pid->second->Enable();
    395     selected_audio_pid_ = lowest_audio_pid->first;
    396   }
    397   if (lowest_video_pid != pids_.end()) {
    398     DVLOG(1) << "Enable video pid: " << lowest_video_pid->first;
    399     lowest_video_pid->second->Enable();
    400     selected_video_pid_ = lowest_video_pid->first;
    401   }
    402 
    403   // Disable all the other audio and video PIDs.
    404   for (PidMap::iterator it = pids_.begin(); it != pids_.end(); ++it) {
    405     PidState* pid_state = it->second;
    406     if (it != lowest_audio_pid && it != lowest_video_pid &&
    407         (pid_state->pid_type() == PidState::kPidAudioPes ||
    408          pid_state->pid_type() == PidState::kPidVideoPes))
    409       pid_state->Disable();
    410   }
    411 }
    412 
    413 void Mp2tStreamParser::OnVideoConfigChanged(
    414     int pes_pid,
    415     const VideoDecoderConfig& video_decoder_config) {
    416   DVLOG(1) << "OnVideoConfigChanged for pid=" << pes_pid;
    417   DCHECK_EQ(pes_pid, selected_video_pid_);
    418   DCHECK(video_decoder_config.IsValidConfig());
    419 
    420   // Create a new entry in |buffer_queue_chain_| with the updated configs.
    421   BufferQueueWithConfig buffer_queue_with_config(
    422       false,
    423       buffer_queue_chain_.empty()
    424       ? AudioDecoderConfig() : buffer_queue_chain_.back().audio_config,
    425       video_decoder_config);
    426   buffer_queue_chain_.push_back(buffer_queue_with_config);
    427 
    428   // Replace any non valid config with the 1st valid entry.
    429   // This might happen if there was no available config before.
    430   for (std::list<BufferQueueWithConfig>::iterator it =
    431        buffer_queue_chain_.begin(); it != buffer_queue_chain_.end(); ++it) {
    432     if (it->video_config.IsValidConfig())
    433       break;
    434     it->video_config = video_decoder_config;
    435   }
    436 }
    437 
    438 void Mp2tStreamParser::OnAudioConfigChanged(
    439     int pes_pid,
    440     const AudioDecoderConfig& audio_decoder_config) {
    441   DVLOG(1) << "OnAudioConfigChanged for pid=" << pes_pid;
    442   DCHECK_EQ(pes_pid, selected_audio_pid_);
    443   DCHECK(audio_decoder_config.IsValidConfig());
    444 
    445   // Create a new entry in |buffer_queue_chain_| with the updated configs.
    446   BufferQueueWithConfig buffer_queue_with_config(
    447       false,
    448       audio_decoder_config,
    449       buffer_queue_chain_.empty()
    450       ? VideoDecoderConfig() : buffer_queue_chain_.back().video_config);
    451   buffer_queue_chain_.push_back(buffer_queue_with_config);
    452 
    453   // Replace any non valid config with the 1st valid entry.
    454   // This might happen if there was no available config before.
    455   for (std::list<BufferQueueWithConfig>::iterator it =
    456        buffer_queue_chain_.begin(); it != buffer_queue_chain_.end(); ++it) {
    457     if (it->audio_config.IsValidConfig())
    458       break;
    459     it->audio_config = audio_decoder_config;
    460   }
    461 }
    462 
    463 bool Mp2tStreamParser::FinishInitializationIfNeeded() {
    464   // Nothing to be done if already initialized.
    465   if (is_initialized_)
    466     return true;
    467 
    468   // Wait for more data to come to finish initialization.
    469   if (buffer_queue_chain_.empty())
    470     return true;
    471 
    472   // Wait for more data to come if one of the config is not available.
    473   BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
    474   if (selected_audio_pid_ > 0 &&
    475       !queue_with_config.audio_config.IsValidConfig())
    476     return true;
    477   if (selected_video_pid_ > 0 &&
    478       !queue_with_config.video_config.IsValidConfig())
    479     return true;
    480 
    481   // Pass the config before invoking the initialization callback.
    482   RCHECK(config_cb_.Run(queue_with_config.audio_config,
    483                         queue_with_config.video_config,
    484                         TextTrackConfigMap()));
    485   queue_with_config.is_config_sent = true;
    486 
    487   // For Mpeg2 TS, the duration is not known.
    488   DVLOG(1) << "Mpeg2TS stream parser initialization done";
    489   base::ResetAndReturn(&init_cb_)
    490       .Run(true, InitParameters(kInfiniteDuration()));
    491   is_initialized_ = true;
    492 
    493   return true;
    494 }
    495 
    496 void Mp2tStreamParser::OnEmitAudioBuffer(
    497     int pes_pid,
    498     scoped_refptr<StreamParserBuffer> stream_parser_buffer) {
    499   DCHECK_EQ(pes_pid, selected_audio_pid_);
    500 
    501   DVLOG(LOG_LEVEL_ES)
    502       << "OnEmitAudioBuffer: "
    503       << " size="
    504       << stream_parser_buffer->data_size()
    505       << " dts="
    506       << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds()
    507       << " pts="
    508       << stream_parser_buffer->timestamp().InMilliseconds();
    509   stream_parser_buffer->set_timestamp(
    510       stream_parser_buffer->timestamp() - time_offset_);
    511   stream_parser_buffer->SetDecodeTimestamp(
    512       stream_parser_buffer->GetDecodeTimestamp() - time_offset_);
    513 
    514   // Ignore the incoming buffer if it is not associated with any config.
    515   if (buffer_queue_chain_.empty()) {
    516     DVLOG(1) << "Ignoring audio buffer with no corresponding audio config";
    517     return;
    518   }
    519 
    520   buffer_queue_chain_.back().audio_queue.push_back(stream_parser_buffer);
    521 }
    522 
    523 void Mp2tStreamParser::OnEmitVideoBuffer(
    524     int pes_pid,
    525     scoped_refptr<StreamParserBuffer> stream_parser_buffer) {
    526   DCHECK_EQ(pes_pid, selected_video_pid_);
    527 
    528   DVLOG(LOG_LEVEL_ES)
    529       << "OnEmitVideoBuffer"
    530       << " size="
    531       << stream_parser_buffer->data_size()
    532       << " dts="
    533       << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds()
    534       << " pts="
    535       << stream_parser_buffer->timestamp().InMilliseconds()
    536       << " IsKeyframe="
    537       << stream_parser_buffer->IsKeyframe();
    538   stream_parser_buffer->set_timestamp(
    539       stream_parser_buffer->timestamp() - time_offset_);
    540   stream_parser_buffer->SetDecodeTimestamp(
    541       stream_parser_buffer->GetDecodeTimestamp() - time_offset_);
    542 
    543   // Discard the incoming buffer:
    544   // - if it is not associated with any config,
    545   // - or if only non-key frames have been added to a new segment.
    546   if (buffer_queue_chain_.empty() ||
    547       (first_video_frame_in_segment_ && !stream_parser_buffer->IsKeyframe())) {
    548     DVLOG(1) << "Discard video buffer:"
    549              << " keyframe=" << stream_parser_buffer->IsKeyframe()
    550              << " dts="
    551              << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds();
    552     if (discarded_frames_dts_.empty() ||
    553         discarded_frames_min_pts_ > stream_parser_buffer->timestamp()) {
    554       discarded_frames_min_pts_ = stream_parser_buffer->timestamp();
    555     }
    556     discarded_frames_dts_.push_back(
    557         stream_parser_buffer->GetDecodeTimestamp());
    558     return;
    559   }
    560 
    561   // Fill the gap created by frames that have been discarded.
    562   if (!discarded_frames_dts_.empty())
    563     FillVideoGap(stream_parser_buffer);
    564 
    565   first_video_frame_in_segment_ = false;
    566   buffer_queue_chain_.back().video_queue.push_back(stream_parser_buffer);
    567 }
    568 
    569 bool Mp2tStreamParser::EmitRemainingBuffers() {
    570   DVLOG(LOG_LEVEL_ES) << "Mp2tStreamParser::EmitRemainingBuffers";
    571 
    572   // No buffer should be sent until fully initialized.
    573   if (!is_initialized_)
    574     return true;
    575 
    576   if (buffer_queue_chain_.empty())
    577     return true;
    578 
    579   // Keep track of the last audio and video config sent.
    580   AudioDecoderConfig last_audio_config =
    581       buffer_queue_chain_.back().audio_config;
    582   VideoDecoderConfig last_video_config =
    583       buffer_queue_chain_.back().video_config;
    584 
    585   // Do not have all the configs, need more data.
    586   if (selected_audio_pid_ >= 0 && !last_audio_config.IsValidConfig())
    587     return true;
    588   if (selected_video_pid_ >= 0 && !last_video_config.IsValidConfig())
    589     return true;
    590 
    591   // Buffer emission.
    592   while (!buffer_queue_chain_.empty()) {
    593     // Start a segment if needed.
    594     if (!segment_started_) {
    595       DVLOG(1) << "Starting a new segment";
    596       segment_started_ = true;
    597       new_segment_cb_.Run();
    598     }
    599 
    600     // Update the audio and video config if needed.
    601     BufferQueueWithConfig& queue_with_config = buffer_queue_chain_.front();
    602     if (!queue_with_config.is_config_sent) {
    603       if (!config_cb_.Run(queue_with_config.audio_config,
    604                           queue_with_config.video_config,
    605                           TextTrackConfigMap()))
    606         return false;
    607       queue_with_config.is_config_sent = true;
    608     }
    609 
    610     // Add buffers.
    611     TextBufferQueueMap empty_text_map;
    612     if (!queue_with_config.audio_queue.empty() ||
    613         !queue_with_config.video_queue.empty()) {
    614       if (!new_buffers_cb_.Run(queue_with_config.audio_queue,
    615                                queue_with_config.video_queue,
    616                                empty_text_map)) {
    617         return false;
    618       }
    619     }
    620 
    621     buffer_queue_chain_.pop_front();
    622   }
    623 
    624   // Push an empty queue with the last audio/video config
    625   // so that buffers with the same config can be added later on.
    626   BufferQueueWithConfig queue_with_config(
    627       true, last_audio_config, last_video_config);
    628   buffer_queue_chain_.push_back(queue_with_config);
    629 
    630   return true;
    631 }
    632 
    633 void Mp2tStreamParser::FillVideoGap(
    634     const scoped_refptr<StreamParserBuffer>& stream_parser_buffer) {
    635   DCHECK(!buffer_queue_chain_.empty());
    636   DCHECK(!discarded_frames_dts_.empty());
    637   DCHECK(stream_parser_buffer->IsKeyframe());
    638 
    639   // PTS is interpolated between the min PTS of discarded frames
    640   // and the PTS of the first valid buffer.
    641   base::TimeDelta pts = discarded_frames_min_pts_;
    642   base::TimeDelta pts_delta =
    643       (stream_parser_buffer->timestamp() - pts) / discarded_frames_dts_.size();
    644 
    645   while (!discarded_frames_dts_.empty()) {
    646     scoped_refptr<StreamParserBuffer> frame =
    647         StreamParserBuffer::CopyFrom(
    648             stream_parser_buffer->data(),
    649             stream_parser_buffer->data_size(),
    650             stream_parser_buffer->IsKeyframe(),
    651             stream_parser_buffer->type(),
    652             stream_parser_buffer->track_id());
    653     frame->SetDecodeTimestamp(discarded_frames_dts_.front());
    654     frame->set_timestamp(pts);
    655     buffer_queue_chain_.back().video_queue.push_back(frame);
    656     pts += pts_delta;
    657     discarded_frames_dts_.pop_front();
    658   }
    659 }
    660 
    661 }  // namespace mp2t
    662 }  // namespace media
    663