| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/formats/mp2t/mp2t_stream_parser.h" | 5 #include "media/formats/mp2t/mp2t_stream_parser.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 } | 150 } |
| 151 | 151 |
| 152 Mp2tStreamParser::BufferQueueWithConfig::~BufferQueueWithConfig() { | 152 Mp2tStreamParser::BufferQueueWithConfig::~BufferQueueWithConfig() { |
| 153 } | 153 } |
| 154 | 154 |
| 155 Mp2tStreamParser::Mp2tStreamParser(bool sbr_in_mimetype) | 155 Mp2tStreamParser::Mp2tStreamParser(bool sbr_in_mimetype) |
| 156 : sbr_in_mimetype_(sbr_in_mimetype), | 156 : sbr_in_mimetype_(sbr_in_mimetype), |
| 157 selected_audio_pid_(-1), | 157 selected_audio_pid_(-1), |
| 158 selected_video_pid_(-1), | 158 selected_video_pid_(-1), |
| 159 is_initialized_(false), | 159 is_initialized_(false), |
| 160 segment_started_(false), | 160 segment_started_(false) { |
| 161 first_video_frame_in_segment_(true) { | |
| 162 } | 161 } |
| 163 | 162 |
| 164 Mp2tStreamParser::~Mp2tStreamParser() { | 163 Mp2tStreamParser::~Mp2tStreamParser() { |
| 165 STLDeleteValues(&pids_); | 164 STLDeleteValues(&pids_); |
| 166 } | 165 } |
| 167 | 166 |
| 168 void Mp2tStreamParser::Init( | 167 void Mp2tStreamParser::Init( |
| 169 const InitCB& init_cb, | 168 const InitCB& init_cb, |
| 170 const NewConfigCB& config_cb, | 169 const NewConfigCB& config_cb, |
| 171 const NewBuffersCB& new_buffers_cb, | 170 const NewBuffersCB& new_buffers_cb, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 delete pid_state; | 202 delete pid_state; |
| 204 } | 203 } |
| 205 pids_.clear(); | 204 pids_.clear(); |
| 206 EmitRemainingBuffers(); | 205 EmitRemainingBuffers(); |
| 207 buffer_queue_chain_.clear(); | 206 buffer_queue_chain_.clear(); |
| 208 | 207 |
| 209 // End of the segment. | 208 // End of the segment. |
| 210 // Note: does not need to invoke |end_of_segment_cb_| since flushing the | 209 // Note: does not need to invoke |end_of_segment_cb_| since flushing the |
| 211 // stream parser already involves the end of the current segment. | 210 // stream parser already involves the end of the current segment. |
| 212 segment_started_ = false; | 211 segment_started_ = false; |
| 213 first_video_frame_in_segment_ = true; | |
| 214 discarded_frames_dts_.clear(); | |
| 215 | 212 |
| 216 // Remove any bytes left in the TS buffer. | 213 // Remove any bytes left in the TS buffer. |
| 217 // (i.e. any partial TS packet => less than 188 bytes). | 214 // (i.e. any partial TS packet => less than 188 bytes). |
| 218 ts_byte_queue_.Reset(); | 215 ts_byte_queue_.Reset(); |
| 219 | 216 |
| 220 // Reset the selected PIDs. | 217 // Reset the selected PIDs. |
| 221 selected_audio_pid_ = -1; | 218 selected_audio_pid_ = -1; |
| 222 selected_video_pid_ = -1; | 219 selected_video_pid_ = -1; |
| 223 } | 220 } |
| 224 | 221 |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 scoped_refptr<StreamParserBuffer> stream_parser_buffer) { | 495 scoped_refptr<StreamParserBuffer> stream_parser_buffer) { |
| 499 DCHECK_EQ(pes_pid, selected_audio_pid_); | 496 DCHECK_EQ(pes_pid, selected_audio_pid_); |
| 500 | 497 |
| 501 DVLOG(LOG_LEVEL_ES) | 498 DVLOG(LOG_LEVEL_ES) |
| 502 << "OnEmitAudioBuffer: " | 499 << "OnEmitAudioBuffer: " |
| 503 << " size=" | 500 << " size=" |
| 504 << stream_parser_buffer->data_size() | 501 << stream_parser_buffer->data_size() |
| 505 << " dts=" | 502 << " dts=" |
| 506 << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds() | 503 << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds() |
| 507 << " pts=" | 504 << " pts=" |
| 508 << stream_parser_buffer->timestamp().InMilliseconds(); | 505 << stream_parser_buffer->timestamp().InMilliseconds() |
| 506 << " dur=" |
| 507 << stream_parser_buffer->duration().InMilliseconds(); |
| 509 stream_parser_buffer->set_timestamp( | 508 stream_parser_buffer->set_timestamp( |
| 510 stream_parser_buffer->timestamp() - time_offset_); | 509 stream_parser_buffer->timestamp() - time_offset_); |
| 511 stream_parser_buffer->SetDecodeTimestamp( | 510 stream_parser_buffer->SetDecodeTimestamp( |
| 512 stream_parser_buffer->GetDecodeTimestamp() - time_offset_); | 511 stream_parser_buffer->GetDecodeTimestamp() - time_offset_); |
| 513 | 512 |
| 514 // Ignore the incoming buffer if it is not associated with any config. | 513 // Ignore the incoming buffer if it is not associated with any config. |
| 515 if (buffer_queue_chain_.empty()) { | 514 if (buffer_queue_chain_.empty()) { |
| 516 DVLOG(1) << "Ignoring audio buffer with no corresponding audio config"; | 515 NOTREACHED() << "Cannot provide buffers before configs"; |
| 517 return; | 516 return; |
| 518 } | 517 } |
| 519 | 518 |
| 520 buffer_queue_chain_.back().audio_queue.push_back(stream_parser_buffer); | 519 buffer_queue_chain_.back().audio_queue.push_back(stream_parser_buffer); |
| 521 } | 520 } |
| 522 | 521 |
| 523 void Mp2tStreamParser::OnEmitVideoBuffer( | 522 void Mp2tStreamParser::OnEmitVideoBuffer( |
| 524 int pes_pid, | 523 int pes_pid, |
| 525 scoped_refptr<StreamParserBuffer> stream_parser_buffer) { | 524 scoped_refptr<StreamParserBuffer> stream_parser_buffer) { |
| 526 DCHECK_EQ(pes_pid, selected_video_pid_); | 525 DCHECK_EQ(pes_pid, selected_video_pid_); |
| 527 | 526 |
| 528 DVLOG(LOG_LEVEL_ES) | 527 DVLOG(LOG_LEVEL_ES) |
| 529 << "OnEmitVideoBuffer" | 528 << "OnEmitVideoBuffer" |
| 530 << " size=" | 529 << " size=" |
| 531 << stream_parser_buffer->data_size() | 530 << stream_parser_buffer->data_size() |
| 532 << " dts=" | 531 << " dts=" |
| 533 << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds() | 532 << stream_parser_buffer->GetDecodeTimestamp().InMilliseconds() |
| 534 << " pts=" | 533 << " pts=" |
| 535 << stream_parser_buffer->timestamp().InMilliseconds() | 534 << stream_parser_buffer->timestamp().InMilliseconds() |
| 535 << " dur=" |
| 536 << stream_parser_buffer->duration().InMilliseconds() |
| 536 << " IsKeyframe=" | 537 << " IsKeyframe=" |
| 537 << stream_parser_buffer->IsKeyframe(); | 538 << stream_parser_buffer->IsKeyframe(); |
| 538 stream_parser_buffer->set_timestamp( | 539 stream_parser_buffer->set_timestamp( |
| 539 stream_parser_buffer->timestamp() - time_offset_); | 540 stream_parser_buffer->timestamp() - time_offset_); |
| 540 stream_parser_buffer->SetDecodeTimestamp( | 541 stream_parser_buffer->SetDecodeTimestamp( |
| 541 stream_parser_buffer->GetDecodeTimestamp() - time_offset_); | 542 stream_parser_buffer->GetDecodeTimestamp() - time_offset_); |
| 542 | 543 |
| 543 // Discard the incoming buffer: | 544 // Ignore the incoming buffer if it is not associated with any config. |
| 544 // - if it is not associated with any config, | 545 if (buffer_queue_chain_.empty()) { |
| 545 // - or if only non-key frames have been added to a new segment. | 546 NOTREACHED() << "Cannot provide buffers before configs"; |
| 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; | 547 return; |
| 559 } | 548 } |
| 560 | 549 |
| 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); | 550 buffer_queue_chain_.back().video_queue.push_back(stream_parser_buffer); |
| 567 } | 551 } |
| 568 | 552 |
| 569 bool Mp2tStreamParser::EmitRemainingBuffers() { | 553 bool Mp2tStreamParser::EmitRemainingBuffers() { |
| 570 DVLOG(LOG_LEVEL_ES) << "Mp2tStreamParser::EmitRemainingBuffers"; | 554 DVLOG(LOG_LEVEL_ES) << "Mp2tStreamParser::EmitRemainingBuffers"; |
| 571 | 555 |
| 572 // No buffer should be sent until fully initialized. | 556 // No buffer should be sent until fully initialized. |
| 573 if (!is_initialized_) | 557 if (!is_initialized_) |
| 574 return true; | 558 return true; |
| 575 | 559 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 | 607 |
| 624 // Push an empty queue with the last audio/video config | 608 // Push an empty queue with the last audio/video config |
| 625 // so that buffers with the same config can be added later on. | 609 // so that buffers with the same config can be added later on. |
| 626 BufferQueueWithConfig queue_with_config( | 610 BufferQueueWithConfig queue_with_config( |
| 627 true, last_audio_config, last_video_config); | 611 true, last_audio_config, last_video_config); |
| 628 buffer_queue_chain_.push_back(queue_with_config); | 612 buffer_queue_chain_.push_back(queue_with_config); |
| 629 | 613 |
| 630 return true; | 614 return true; |
| 631 } | 615 } |
| 632 | 616 |
| 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 | 617 } // namespace mp2t |
| 662 } // namespace media | 618 } // namespace media |
| OLD | NEW |