Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: media/formats/mp2t/mp2t_stream_parser.cc

Issue 364823008: Mpeg2TS - estimate duration for video frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address CR comments. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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 DVLOG(1) << "Ignoring audio buffer with no corresponding audio config";
wolenetz 2014/07/10 17:57:23 If there has been no init segment prior to media s
damienv1 2014/07/10 18:34:51 True. With the updated code, there should always b
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 DVLOG(1) << "Ignoring video buffer with no corresponding video config";
wolenetz 2014/07/10 17:57:23 If there has been no init segment prior to media s
damienv1 2014/07/10 18:34:52 ditto.
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698