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

Side by Side Diff: media/filters/ffmpeg_demuxer.cc

Issue 10581050: Ensure media's buffered ranges always have a range that includes currentTime. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 6 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
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/filters/ffmpeg_demuxer.h" 5 #include "media/filters/ffmpeg_demuxer.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 12 matching lines...) Expand all
23 #include "media/ffmpeg/ffmpeg_common.h" 23 #include "media/ffmpeg/ffmpeg_common.h"
24 #include "media/filters/bitstream_converter.h" 24 #include "media/filters/bitstream_converter.h"
25 #include "media/filters/ffmpeg_glue.h" 25 #include "media/filters/ffmpeg_glue.h"
26 #include "media/filters/ffmpeg_h264_bitstream_converter.h" 26 #include "media/filters/ffmpeg_h264_bitstream_converter.h"
27 27
28 namespace media { 28 namespace media {
29 29
30 // 30 //
31 // FFmpegDemuxerStream 31 // FFmpegDemuxerStream
32 // 32 //
33 FFmpegDemuxerStream::FFmpegDemuxerStream(FFmpegDemuxer* demuxer, 33 FFmpegDemuxerStream::FFmpegDemuxerStream(
34 AVStream* stream) 34 const NotifyBufferedCB& notify_buffered_cb,
35 : demuxer_(demuxer), 35 FFmpegDemuxer* demuxer,
36 AVStream* stream)
37 : notify_buffered_cb_(notify_buffered_cb),
38 demuxer_(demuxer),
36 stream_(stream), 39 stream_(stream),
37 type_(UNKNOWN), 40 type_(UNKNOWN),
38 discontinuous_(false), 41 discontinuous_(false),
39 stopped_(false) { 42 stopped_(false),
43 last_packet_timestamp_(kNoTimestamp()) {
40 DCHECK(demuxer_); 44 DCHECK(demuxer_);
41 45
42 // Determine our media format. 46 // Determine our media format.
43 switch (stream->codec->codec_type) { 47 switch (stream->codec->codec_type) {
44 case AVMEDIA_TYPE_AUDIO: 48 case AVMEDIA_TYPE_AUDIO:
45 type_ = AUDIO; 49 type_ = AUDIO;
46 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_); 50 AVCodecContextToAudioDecoderConfig(stream->codec, &audio_config_);
47 break; 51 break;
48 case AVMEDIA_TYPE_VIDEO: 52 case AVMEDIA_TYPE_VIDEO:
49 type_ = VIDEO; 53 type_ = VIDEO;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 } 91 }
88 92
89 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will 93 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will
90 // reference inner memory of FFmpeg. As such we should transfer the packet 94 // reference inner memory of FFmpeg. As such we should transfer the packet
91 // into memory we control. 95 // into memory we control.
92 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); 96 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size);
93 buffer->SetTimestamp(ConvertStreamTimestamp( 97 buffer->SetTimestamp(ConvertStreamTimestamp(
94 stream_->time_base, packet->pts)); 98 stream_->time_base, packet->pts));
95 buffer->SetDuration(ConvertStreamTimestamp( 99 buffer->SetDuration(ConvertStreamTimestamp(
96 stream_->time_base, packet->duration)); 100 stream_->time_base, packet->duration));
101 if (last_packet_timestamp_ != kNoTimestamp() &&
102 last_packet_timestamp_ < buffer->GetTimestamp()) {
103 notify_buffered_cb_.Run(last_packet_timestamp_, buffer->GetTimestamp());
104 }
105 last_packet_timestamp_ = buffer->GetTimestamp();
97 } 106 }
98 107
99 buffer_queue_.push_back(buffer); 108 buffer_queue_.push_back(buffer);
100 FulfillPendingRead(); 109 FulfillPendingRead();
101 return; 110 return;
102 } 111 }
103 112
104 void FFmpegDemuxerStream::FlushBuffers() { 113 void FFmpegDemuxerStream::FlushBuffers() {
105 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); 114 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop());
106 base::AutoLock auto_lock(lock_); 115 base::AutoLock auto_lock(lock_);
107 DCHECK(read_queue_.empty()) << "Read requests should be empty"; 116 DCHECK(read_queue_.empty()) << "Read requests should be empty";
108 buffer_queue_.clear(); 117 buffer_queue_.clear();
118 last_packet_timestamp_ = kNoTimestamp();
109 } 119 }
110 120
111 void FFmpegDemuxerStream::Stop() { 121 void FFmpegDemuxerStream::Stop() {
112 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop()); 122 DCHECK_EQ(MessageLoop::current(), demuxer_->message_loop());
113 base::AutoLock auto_lock(lock_); 123 base::AutoLock auto_lock(lock_);
114 buffer_queue_.clear(); 124 buffer_queue_.clear();
115 for (ReadQueue::iterator it = read_queue_.begin(); 125 for (ReadQueue::iterator it = read_queue_.begin();
116 it != read_queue_.end(); ++it) { 126 it != read_queue_.end(); ++it) {
117 it->Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer())); 127 it->Run(scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
118 } 128 }
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 482
473 // Fully initialize AVFormatContext by parsing the stream a little. 483 // Fully initialize AVFormatContext by parsing the stream a little.
474 result = avformat_find_stream_info(format_context_, NULL); 484 result = avformat_find_stream_info(format_context_, NULL);
475 if (result < 0) { 485 if (result < 0) {
476 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE); 486 status_cb.Run(DEMUXER_ERROR_COULD_NOT_PARSE);
477 return; 487 return;
478 } 488 }
479 489
480 // Create demuxer stream entries for each possible AVStream. 490 // Create demuxer stream entries for each possible AVStream.
481 streams_.resize(format_context_->nb_streams); 491 streams_.resize(format_context_->nb_streams);
492 buffered_times_.resize(streams_.size());
482 bool found_audio_stream = false; 493 bool found_audio_stream = false;
483 bool found_video_stream = false; 494 bool found_video_stream = false;
484 495
485 base::TimeDelta max_duration; 496 base::TimeDelta max_duration;
486 for (size_t i = 0; i < format_context_->nb_streams; ++i) { 497 for (size_t i = 0; i < format_context_->nb_streams; ++i) {
487 AVCodecContext* codec_context = format_context_->streams[i]->codec; 498 AVCodecContext* codec_context = format_context_->streams[i]->codec;
488 AVMediaType codec_type = codec_context->codec_type; 499 AVMediaType codec_type = codec_context->codec_type;
489 500
490 if (codec_type == AVMEDIA_TYPE_AUDIO) { 501 if (codec_type == AVMEDIA_TYPE_AUDIO) {
491 if (found_audio_stream) 502 if (found_audio_stream)
492 continue; 503 continue;
493 // Ensure the codec is supported. 504 // Ensure the codec is supported.
494 if (CodecIDToAudioCodec(codec_context->codec_id) == kUnknownAudioCodec) 505 if (CodecIDToAudioCodec(codec_context->codec_id) == kUnknownAudioCodec)
495 continue; 506 continue;
496 found_audio_stream = true; 507 found_audio_stream = true;
497 } else if (codec_type == AVMEDIA_TYPE_VIDEO) { 508 } else if (codec_type == AVMEDIA_TYPE_VIDEO) {
498 if (found_video_stream) 509 if (found_video_stream)
499 continue; 510 continue;
500 // Ensure the codec is supported. 511 // Ensure the codec is supported.
501 if (CodecIDToVideoCodec(codec_context->codec_id) == kUnknownVideoCodec) 512 if (CodecIDToVideoCodec(codec_context->codec_id) == kUnknownVideoCodec)
502 continue; 513 continue;
503 found_video_stream = true; 514 found_video_stream = true;
504 } else { 515 } else {
505 continue; 516 continue;
506 } 517 }
507 518
508 AVStream* stream = format_context_->streams[i]; 519 AVStream* stream = format_context_->streams[i];
509 scoped_refptr<FFmpegDemuxerStream> demuxer_stream( 520 scoped_refptr<FFmpegDemuxerStream> demuxer_stream(
510 new FFmpegDemuxerStream(this, stream)); 521 new FFmpegDemuxerStream(
522 base::Bind(&FFmpegDemuxer::NotifyBufferedRange, this, i),
523 this, stream));
511 524
512 streams_[i] = demuxer_stream; 525 streams_[i] = demuxer_stream;
513 max_duration = std::max(max_duration, demuxer_stream->duration()); 526 max_duration = std::max(max_duration, demuxer_stream->duration());
514 527
515 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) { 528 if (stream->first_dts != static_cast<int64_t>(AV_NOPTS_VALUE)) {
516 const base::TimeDelta first_dts = ConvertFromTimeBase( 529 const base::TimeDelta first_dts = ConvertFromTimeBase(
517 stream->time_base, stream->first_dts); 530 stream->time_base, stream->first_dts);
518 if (start_time_ == kNoTimestamp() || first_dts < start_time_) 531 if (start_time_ == kNoTimestamp() || first_dts < start_time_)
519 start_time_ = first_dts; 532 start_time_ = first_dts;
520 } 533 }
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 int FFmpegDemuxer::WaitForRead() { 713 int FFmpegDemuxer::WaitForRead() {
701 read_event_.Wait(); 714 read_event_.Wait();
702 return last_read_bytes_; 715 return last_read_bytes_;
703 } 716 }
704 717
705 void FFmpegDemuxer::SignalReadCompleted(int size) { 718 void FFmpegDemuxer::SignalReadCompleted(int size) {
706 last_read_bytes_ = size; 719 last_read_bytes_ = size;
707 read_event_.Signal(); 720 read_event_.Signal();
708 } 721 }
709 722
723 void FFmpegDemuxer::NotifyBufferedRange(
724 int stream_id, base::TimeDelta start, base::TimeDelta end) {
725 buffered_times_[stream_id].Add(start, end);
scherkus (not reviewing) 2012/06/22 06:13:51 I think each FDS stream should hold onto its own r
Ami GONE FROM CHROMIUM 2012/06/22 17:15:32 Done.
726
727 Ranges<base::TimeDelta> buffered = buffered_times_[0];
728 for (size_t i = 1; i < streams_.size(); ++i)
729 buffered = buffered.IntersectionWith(buffered_times_[i]);
730 for (size_t i = 0; i < buffered.size(); ++i)
731 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i));
732 }
733
710 } // namespace media 734 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_demuxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698