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

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

Issue 11420070: Remove locking from FFmpegDemuxerStream and associated TODOs from media code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 8 years, 1 month 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_video_decoder.h » ('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 17 matching lines...) Expand all
28 28
29 namespace media { 29 namespace media {
30 30
31 // 31 //
32 // FFmpegDemuxerStream 32 // FFmpegDemuxerStream
33 // 33 //
34 FFmpegDemuxerStream::FFmpegDemuxerStream( 34 FFmpegDemuxerStream::FFmpegDemuxerStream(
35 FFmpegDemuxer* demuxer, 35 FFmpegDemuxer* demuxer,
36 AVStream* stream) 36 AVStream* stream)
37 : demuxer_(demuxer), 37 : demuxer_(demuxer),
38 message_loop_(base::MessageLoopProxy::current()),
38 stream_(stream), 39 stream_(stream),
39 type_(UNKNOWN), 40 type_(UNKNOWN),
40 stopped_(false), 41 stopped_(false),
41 last_packet_timestamp_(kNoTimestamp()), 42 last_packet_timestamp_(kNoTimestamp()),
42 bitstream_converter_enabled_(false) { 43 bitstream_converter_enabled_(false) {
43 DCHECK(demuxer_); 44 DCHECK(demuxer_);
44 45
45 // Determine our media format. 46 // Determine our media format.
46 switch (stream->codec->codec_type) { 47 switch (stream->codec->codec_type) {
47 case AVMEDIA_TYPE_AUDIO: 48 case AVMEDIA_TYPE_AUDIO:
(...skipping 12 matching lines...) Expand all
60 // Calculate the duration. 61 // Calculate the duration.
61 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration); 62 duration_ = ConvertStreamTimestamp(stream->time_base, stream->duration);
62 63
63 if (stream_->codec->codec_id == CODEC_ID_H264) { 64 if (stream_->codec->codec_id == CODEC_ID_H264) {
64 bitstream_converter_.reset( 65 bitstream_converter_.reset(
65 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec)); 66 new FFmpegH264ToAnnexBBitstreamConverter(stream_->codec));
66 } 67 }
67 } 68 }
68 69
69 bool FFmpegDemuxerStream::HasPendingReads() { 70 bool FFmpegDemuxerStream::HasPendingReads() {
70 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread()); 71 DCHECK(message_loop_->BelongsToCurrentThread());
71 base::AutoLock auto_lock(lock_);
72 DCHECK(!stopped_ || read_queue_.empty()) 72 DCHECK(!stopped_ || read_queue_.empty())
73 << "Read queue should have been emptied if demuxing stream is stopped"; 73 << "Read queue should have been emptied if demuxing stream is stopped";
74 return !read_queue_.empty(); 74 return !read_queue_.empty();
75 } 75 }
76 76
77 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { 77 void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) {
78 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread()); 78 DCHECK(message_loop_->BelongsToCurrentThread());
79 79
80 base::AutoLock auto_lock(lock_);
81 if (stopped_) { 80 if (stopped_) {
82 NOTREACHED() << "Attempted to enqueue packet on a stopped stream"; 81 NOTREACHED() << "Attempted to enqueue packet on a stopped stream";
83 return; 82 return;
84 } 83 }
85 84
86 scoped_refptr<DecoderBuffer> buffer; 85 scoped_refptr<DecoderBuffer> buffer;
87 if (!packet.get()) { 86 if (!packet.get()) {
88 buffer = DecoderBuffer::CreateEOSBuffer(); 87 buffer = DecoderBuffer::CreateEOSBuffer();
89 } else { 88 } else {
90 // Convert the packet if there is a bitstream filter. 89 // Convert the packet if there is a bitstream filter.
91 if (packet->data && bitstream_converter_enabled_ && 90 if (packet->data && bitstream_converter_enabled_ &&
92 !bitstream_converter_->ConvertPacket(packet.get())) { 91 !bitstream_converter_->ConvertPacket(packet.get())) {
93 LOG(ERROR) << "Format converstion failed."; 92 LOG(ERROR) << "Format converstion failed.";
94 } 93 }
95 94
96 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will 95 // If a packet is returned by FFmpeg's av_parser_parse2() the packet will
97 // reference inner memory of FFmpeg. As such we should transfer the packet 96 // reference inner memory of FFmpeg. As such we should transfer the packet
98 // into memory we control. 97 // into memory we control.
99 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size); 98 buffer = DecoderBuffer::CopyFrom(packet->data, packet->size);
100 buffer->SetTimestamp(ConvertStreamTimestamp( 99 buffer->SetTimestamp(ConvertStreamTimestamp(
101 stream_->time_base, packet->pts)); 100 stream_->time_base, packet->pts));
102 buffer->SetDuration(ConvertStreamTimestamp( 101 buffer->SetDuration(ConvertStreamTimestamp(
103 stream_->time_base, packet->duration)); 102 stream_->time_base, packet->duration));
104 if (buffer->GetTimestamp() != kNoTimestamp() && 103 if (buffer->GetTimestamp() != kNoTimestamp() &&
105 last_packet_timestamp_ != kNoTimestamp() && 104 last_packet_timestamp_ != kNoTimestamp() &&
106 last_packet_timestamp_ < buffer->GetTimestamp()) { 105 last_packet_timestamp_ < buffer->GetTimestamp()) {
107 buffered_ranges_.Add(last_packet_timestamp_, buffer->GetTimestamp()); 106 buffered_ranges_.Add(last_packet_timestamp_, buffer->GetTimestamp());
108 demuxer_->message_loop()->PostTask(FROM_HERE, base::Bind( 107 demuxer_->NotifyBufferingChanged();
109 &FFmpegDemuxer::NotifyBufferingChanged, demuxer_));
110 } 108 }
111 last_packet_timestamp_ = buffer->GetTimestamp(); 109 last_packet_timestamp_ = buffer->GetTimestamp();
112 } 110 }
113 111
114 buffer_queue_.push_back(buffer); 112 buffer_queue_.push_back(buffer);
115 FulfillPendingRead(); 113 SatisfyPendingReads();
116 return;
117 } 114 }
118 115
119 void FFmpegDemuxerStream::FlushBuffers() { 116 void FFmpegDemuxerStream::FlushBuffers() {
120 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread()); 117 DCHECK(message_loop_->BelongsToCurrentThread());
121 base::AutoLock auto_lock(lock_);
122 DCHECK(read_queue_.empty()) << "Read requests should be empty"; 118 DCHECK(read_queue_.empty()) << "Read requests should be empty";
123 buffer_queue_.clear(); 119 buffer_queue_.clear();
124 last_packet_timestamp_ = kNoTimestamp(); 120 last_packet_timestamp_ = kNoTimestamp();
125 } 121 }
126 122
127 void FFmpegDemuxerStream::Stop() { 123 void FFmpegDemuxerStream::Stop() {
128 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread()); 124 DCHECK(message_loop_->BelongsToCurrentThread());
129 base::AutoLock auto_lock(lock_);
130 buffer_queue_.clear(); 125 buffer_queue_.clear();
131 for (ReadQueue::iterator it = read_queue_.begin(); 126 for (ReadQueue::iterator it = read_queue_.begin();
132 it != read_queue_.end(); ++it) { 127 it != read_queue_.end(); ++it) {
133 it->Run(DemuxerStream::kOk, 128 it->Run(DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer());
134 scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
135 } 129 }
136 read_queue_.clear(); 130 read_queue_.clear();
137 stopped_ = true; 131 stopped_ = true;
138 } 132 }
139 133
140 base::TimeDelta FFmpegDemuxerStream::duration() { 134 base::TimeDelta FFmpegDemuxerStream::duration() {
141 return duration_; 135 return duration_;
142 } 136 }
143 137
144 DemuxerStream::Type FFmpegDemuxerStream::type() { 138 DemuxerStream::Type FFmpegDemuxerStream::type() {
145 return type_; 139 return type_;
146 } 140 }
147 141
148 void FFmpegDemuxerStream::Read(const ReadCB& read_cb) { 142 void FFmpegDemuxerStream::Read(const ReadCB& read_cb) {
149 DCHECK(!read_cb.is_null()); 143 if (!message_loop_->BelongsToCurrentThread()) {
150 144 message_loop_->PostTask(FROM_HERE, base::Bind(
151 base::AutoLock auto_lock(lock_); 145 &FFmpegDemuxerStream::Read, this, read_cb));
152 // Don't accept any additional reads if we've been told to stop.
153 // The demuxer_ may have been destroyed in the pipleine thread.
154 //
155 // TODO(scherkus): it would be cleaner if we replied with an error message.
156 if (stopped_) {
157 read_cb.Run(DemuxerStream::kOk,
158 scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
159 return; 146 return;
160 } 147 }
161 148
162 // Buffers are only queued when there are no pending reads. 149 // Don't accept any additional reads if we've been told to stop.
163 DCHECK(buffer_queue_.empty() || read_queue_.empty()); 150 // The |demuxer_| may have been destroyed in the pipeline thread.
164 151 //
165 if (buffer_queue_.empty()) { 152 // TODO(scherkus): it would be cleaner to reply with an error message.
166 demuxer_->message_loop()->PostTask(FROM_HERE, base::Bind( 153 if (stopped_) {
167 &FFmpegDemuxerStream::ReadTask, this, read_cb)); 154 read_cb.Run(DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer());
168 return; 155 return;
169 } 156 }
170 157
171 // Send the oldest buffer back.
172 scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
173 buffer_queue_.pop_front();
174 read_cb.Run(DemuxerStream::kOk, buffer);
175 }
176
177 void FFmpegDemuxerStream::ReadTask(const ReadCB& read_cb) {
178 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread());
179
180 base::AutoLock auto_lock(lock_);
181 // Don't accept any additional reads if we've been told to stop.
182 //
183 // TODO(scherkus): it would be cleaner if we replied with an error message.
184 if (stopped_) {
185 read_cb.Run(DemuxerStream::kOk,
186 scoped_refptr<DecoderBuffer>(DecoderBuffer::CreateEOSBuffer()));
187 return;
188 }
189
190 // Enqueue the callback and attempt to satisfy it immediately.
191 read_queue_.push_back(read_cb); 158 read_queue_.push_back(read_cb);
192 FulfillPendingRead(); 159 SatisfyPendingReads();
193
194 // Check if there are still pending reads, demux some more.
195 if (!read_queue_.empty()) {
196 demuxer_->PostDemuxTask();
197 }
198 }
199
200 void FFmpegDemuxerStream::FulfillPendingRead() {
201 DCHECK(demuxer_->message_loop()->BelongsToCurrentThread());
202 lock_.AssertAcquired();
203 if (buffer_queue_.empty() || read_queue_.empty()) {
204 return;
205 }
206
207 // Dequeue a buffer and pending read pair.
208 scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
209 ReadCB read_cb(read_queue_.front());
210 buffer_queue_.pop_front();
211 read_queue_.pop_front();
212
213 // Execute the callback.
214 read_cb.Run(DemuxerStream::kOk, buffer);
215 } 160 }
216 161
217 void FFmpegDemuxerStream::EnableBitstreamConverter() { 162 void FFmpegDemuxerStream::EnableBitstreamConverter() {
218 base::AutoLock auto_lock(lock_); 163 if (!message_loop_->BelongsToCurrentThread()) {
164 message_loop_->PostTask(FROM_HERE, base::Bind(
165 &FFmpegDemuxerStream::EnableBitstreamConverter, this));
166 return;
167 }
219 CHECK(bitstream_converter_.get()); 168 CHECK(bitstream_converter_.get());
220 bitstream_converter_enabled_ = true; 169 bitstream_converter_enabled_ = true;
221 } 170 }
222 171
223 const AudioDecoderConfig& FFmpegDemuxerStream::audio_decoder_config() { 172 const AudioDecoderConfig& FFmpegDemuxerStream::audio_decoder_config() {
224 CHECK_EQ(type_, AUDIO); 173 CHECK_EQ(type_, AUDIO);
225 return audio_config_; 174 return audio_config_;
226 } 175 }
227 176
228 const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() { 177 const VideoDecoderConfig& FFmpegDemuxerStream::video_decoder_config() {
229 CHECK_EQ(type_, VIDEO); 178 CHECK_EQ(type_, VIDEO);
230 return video_config_; 179 return video_config_;
231 } 180 }
232 181
233 FFmpegDemuxerStream::~FFmpegDemuxerStream() { 182 FFmpegDemuxerStream::~FFmpegDemuxerStream() {
234 base::AutoLock auto_lock(lock_);
235 DCHECK(stopped_); 183 DCHECK(stopped_);
236 DCHECK(read_queue_.empty()); 184 DCHECK(read_queue_.empty());
237 DCHECK(buffer_queue_.empty()); 185 DCHECK(buffer_queue_.empty());
238 } 186 }
239 187
240 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const { 188 base::TimeDelta FFmpegDemuxerStream::GetElapsedTime() const {
241 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts); 189 return ConvertStreamTimestamp(stream_->time_base, stream_->cur_dts);
242 } 190 }
243 191
244 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const { 192 Ranges<base::TimeDelta> FFmpegDemuxerStream::GetBufferedRanges() const {
245 base::AutoLock auto_lock(lock_);
246 return buffered_ranges_; 193 return buffered_ranges_;
247 } 194 }
248 195
196 void FFmpegDemuxerStream::SatisfyPendingReads() {
197 DCHECK(message_loop_->BelongsToCurrentThread());
198 while (!read_queue_.empty() && !buffer_queue_.empty()) {
199 ReadCB read_cb = read_queue_.front();
200 read_queue_.pop_front();
201
202 // Send earliest buffer back on a new execution stack to avoid recursing.
203 scoped_refptr<DecoderBuffer> buffer = buffer_queue_.front();
204 buffer_queue_.pop_front();
205 message_loop_->PostTask(FROM_HERE, base::Bind(
206 read_cb, DemuxerStream::kOk, buffer));
207 }
208
209 // No buffers but pending reads? Ask for more!
210 if (!read_queue_.empty() && buffer_queue_.empty()) {
211 demuxer_->NotifyHasPendingRead();
212 }
213 }
214
249 // static 215 // static
250 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp( 216 base::TimeDelta FFmpegDemuxerStream::ConvertStreamTimestamp(
251 const AVRational& time_base, int64 timestamp) { 217 const AVRational& time_base, int64 timestamp) {
252 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE)) 218 if (timestamp == static_cast<int64>(AV_NOPTS_VALUE))
253 return kNoTimestamp(); 219 return kNoTimestamp();
254 220
255 return ConvertFromTimeBase(time_base, timestamp); 221 return ConvertFromTimeBase(time_base, timestamp);
256 } 222 }
257 223
258 // 224 //
(...skipping 11 matching lines...) Expand all
270 audio_disabled_(false), 236 audio_disabled_(false),
271 duration_known_(false), 237 duration_known_(false),
272 url_protocol_(data_source, BindToLoop(message_loop_, base::Bind( 238 url_protocol_(data_source, BindToLoop(message_loop_, base::Bind(
273 &FFmpegDemuxer::OnDataSourceError, base::Unretained(this)))) { 239 &FFmpegDemuxer::OnDataSourceError, base::Unretained(this)))) {
274 DCHECK(message_loop_); 240 DCHECK(message_loop_);
275 DCHECK(data_source_); 241 DCHECK(data_source_);
276 } 242 }
277 243
278 FFmpegDemuxer::~FFmpegDemuxer() {} 244 FFmpegDemuxer::~FFmpegDemuxer() {}
279 245
280 void FFmpegDemuxer::PostDemuxTask() {
281 message_loop_->PostTask(FROM_HERE,
282 base::Bind(&FFmpegDemuxer::DemuxTask, this));
283 }
284
285 void FFmpegDemuxer::Stop(const base::Closure& callback) { 246 void FFmpegDemuxer::Stop(const base::Closure& callback) {
286 // Post a task to notify the streams to stop as well. 247 // Post a task to notify the streams to stop as well.
287 message_loop_->PostTask(FROM_HERE, 248 message_loop_->PostTask(FROM_HERE,
288 base::Bind(&FFmpegDemuxer::StopTask, this, callback)); 249 base::Bind(&FFmpegDemuxer::StopTask, this, callback));
289 } 250 }
290 251
291 void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) { 252 void FFmpegDemuxer::Seek(base::TimeDelta time, const PipelineStatusCB& cb) {
292 message_loop_->PostTask(FROM_HERE, 253 message_loop_->PostTask(FROM_HERE,
293 base::Bind(&FFmpegDemuxer::SeekTask, this, time, cb)); 254 base::Bind(&FFmpegDemuxer::SeekTask, this, time, cb));
294 } 255 }
(...skipping 27 matching lines...) Expand all
322 return *iter; 283 return *iter;
323 } 284 }
324 } 285 }
325 return NULL; 286 return NULL;
326 } 287 }
327 288
328 base::TimeDelta FFmpegDemuxer::GetStartTime() const { 289 base::TimeDelta FFmpegDemuxer::GetStartTime() const {
329 return start_time_; 290 return start_time_;
330 } 291 }
331 292
332 scoped_refptr<base::MessageLoopProxy> FFmpegDemuxer::message_loop() {
333 return message_loop_;
334 }
335
336 // Helper for calculating the bitrate of the media based on information stored 293 // Helper for calculating the bitrate of the media based on information stored
337 // in |format_context| or failing that the size and duration of the media. 294 // in |format_context| or failing that the size and duration of the media.
338 // 295 //
339 // Returns 0 if a bitrate could not be determined. 296 // Returns 0 if a bitrate could not be determined.
340 static int CalculateBitrate( 297 static int CalculateBitrate(
341 AVFormatContext* format_context, 298 AVFormatContext* format_context,
342 const base::TimeDelta& duration, 299 const base::TimeDelta& duration,
343 int64 filesize_in_bytes) { 300 int64 filesize_in_bytes) {
344 // If there is a bitrate set on the container, use it. 301 // If there is a bitrate set on the container, use it.
345 if (format_context->bit_rate > 0) 302 if (format_context->bit_rate > 0)
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 } 550 }
594 } 551 }
595 } 552 }
596 // If we have reached the end of stream, tell the downstream filters about 553 // If we have reached the end of stream, tell the downstream filters about
597 // the event. 554 // the event.
598 StreamHasEnded(); 555 StreamHasEnded();
599 return; 556 return;
600 } 557 }
601 558
602 // Queue the packet with the appropriate stream. 559 // Queue the packet with the appropriate stream.
603 // TODO(scherkus): should we post this back to the pipeline thread? I'm
604 // worried about downstream filters (i.e., decoders) executing on this
605 // thread.
606 DCHECK_GE(packet->stream_index, 0); 560 DCHECK_GE(packet->stream_index, 0);
607 DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size())); 561 DCHECK_LT(packet->stream_index, static_cast<int>(streams_.size()));
608 562
609 // Defend against ffmpeg giving us a bad stream index. 563 // Defend against ffmpeg giving us a bad stream index.
610 if (packet->stream_index >= 0 && 564 if (packet->stream_index >= 0 &&
611 packet->stream_index < static_cast<int>(streams_.size()) && 565 packet->stream_index < static_cast<int>(streams_.size()) &&
612 streams_[packet->stream_index] && 566 streams_[packet->stream_index] &&
613 (!audio_disabled_ || 567 (!audio_disabled_ ||
614 streams_[packet->stream_index]->type() != DemuxerStream::AUDIO)) { 568 streams_[packet->stream_index]->type() != DemuxerStream::AUDIO)) {
615 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index]; 569 FFmpegDemuxerStream* demuxer_stream = streams_[packet->stream_index];
616 demuxer_stream->EnqueuePacket(packet.Pass()); 570 demuxer_stream->EnqueuePacket(packet.Pass());
617 } 571 }
618 572
619 // Create a loop by posting another task. This allows seek and message loop 573 // Create a loop by posting another task. This allows seek and message loop
620 // quit tasks to get processed. 574 // quit tasks to get processed.
621 if (StreamsHavePendingReads()) { 575 if (StreamsHavePendingReads()) {
622 PostDemuxTask(); 576 message_loop_->PostTask(FROM_HERE, base::Bind(
577 &FFmpegDemuxer::DemuxTask, this));
623 } 578 }
624 } 579 }
625 580
626 void FFmpegDemuxer::StopTask(const base::Closure& callback) { 581 void FFmpegDemuxer::StopTask(const base::Closure& callback) {
627 DCHECK(message_loop_->BelongsToCurrentThread()); 582 DCHECK(message_loop_->BelongsToCurrentThread());
628 url_protocol_.Abort(); 583 url_protocol_.Abort();
629 data_source_->Stop(BindToLoop(message_loop_, base::Bind( 584 data_source_->Stop(BindToLoop(message_loop_, base::Bind(
630 &FFmpegDemuxer::OnDataSourceStopped, this, callback))); 585 &FFmpegDemuxer::OnDataSourceStopped, this, callback)));
631 } 586 }
632 587
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 StreamVector::iterator iter; 629 StreamVector::iterator iter;
675 for (iter = streams_.begin(); iter != streams_.end(); ++iter) { 630 for (iter = streams_.begin(); iter != streams_.end(); ++iter) {
676 if (!*iter || 631 if (!*iter ||
677 (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) { 632 (audio_disabled_ && (*iter)->type() == DemuxerStream::AUDIO)) {
678 continue; 633 continue;
679 } 634 }
680 (*iter)->EnqueuePacket(ScopedAVPacket()); 635 (*iter)->EnqueuePacket(ScopedAVPacket());
681 } 636 }
682 } 637 }
683 638
639 void FFmpegDemuxer::NotifyHasPendingRead() {
640 DCHECK(message_loop_->BelongsToCurrentThread());
641 DemuxTask();
642 }
643
684 void FFmpegDemuxer::NotifyBufferingChanged() { 644 void FFmpegDemuxer::NotifyBufferingChanged() {
685 DCHECK(message_loop_->BelongsToCurrentThread()); 645 DCHECK(message_loop_->BelongsToCurrentThread());
686 Ranges<base::TimeDelta> buffered; 646 Ranges<base::TimeDelta> buffered;
687 scoped_refptr<FFmpegDemuxerStream> audio = 647 scoped_refptr<FFmpegDemuxerStream> audio =
688 audio_disabled_ ? NULL : GetFFmpegStream(DemuxerStream::AUDIO); 648 audio_disabled_ ? NULL : GetFFmpegStream(DemuxerStream::AUDIO);
689 scoped_refptr<FFmpegDemuxerStream> video = 649 scoped_refptr<FFmpegDemuxerStream> video =
690 GetFFmpegStream(DemuxerStream::VIDEO); 650 GetFFmpegStream(DemuxerStream::VIDEO);
691 if (audio && video) { 651 if (audio && video) {
692 buffered = audio->GetBufferedRanges().IntersectionWith( 652 buffered = audio->GetBufferedRanges().IntersectionWith(
693 video->GetBufferedRanges()); 653 video->GetBufferedRanges());
694 } else if (audio) { 654 } else if (audio) {
695 buffered = audio->GetBufferedRanges(); 655 buffered = audio->GetBufferedRanges();
696 } else if (video) { 656 } else if (video) {
697 buffered = video->GetBufferedRanges(); 657 buffered = video->GetBufferedRanges();
698 } 658 }
699 for (size_t i = 0; i < buffered.size(); ++i) 659 for (size_t i = 0; i < buffered.size(); ++i)
700 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i)); 660 host_->AddBufferedTimeRange(buffered.start(i), buffered.end(i));
701 } 661 }
702 662
703 void FFmpegDemuxer::OnDataSourceError() { 663 void FFmpegDemuxer::OnDataSourceError() {
704 host_->OnDemuxerError(PIPELINE_ERROR_READ); 664 host_->OnDemuxerError(PIPELINE_ERROR_READ);
705 } 665 }
706 666
707 } // namespace media 667 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer.h ('k') | media/filters/ffmpeg_video_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698