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