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