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

Side by Side Diff: media/base/pipeline.cc

Issue 10451049: Track buffered byte ranges correctly in media::Pipeline. (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/base/pipeline.h ('k') | media/base/pipeline_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/base/pipeline.h" 5 #include "media/base/pipeline.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/synchronization/condition_variable.h" 17 #include "base/synchronization/condition_variable.h"
18 #include "media/base/audio_decoder.h" 18 #include "media/base/audio_decoder.h"
19 #include "media/base/audio_renderer.h" 19 #include "media/base/audio_renderer.h"
20 #include "media/base/clock.h" 20 #include "media/base/clock.h"
21 #include "media/base/composite_filter.h" 21 #include "media/base/composite_filter.h"
22 #include "media/base/filter_collection.h" 22 #include "media/base/filter_collection.h"
23 #include "media/base/media_log.h" 23 #include "media/base/media_log.h"
24 #include "media/base/video_decoder.h" 24 #include "media/base/video_decoder.h"
25 #include "media/base/video_renderer.h" 25 #include "media/base/video_renderer.h"
26 26
27 using base::TimeDelta;
28
27 namespace media { 29 namespace media {
28 30
29 PipelineStatusNotification::PipelineStatusNotification() 31 PipelineStatusNotification::PipelineStatusNotification()
30 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) { 32 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) {
31 } 33 }
32 34
33 PipelineStatusNotification::~PipelineStatusNotification() { 35 PipelineStatusNotification::~PipelineStatusNotification() {
34 DCHECK(notified_); 36 DCHECK(notified_);
35 } 37 }
36 38
(...skipping 29 matching lines...) Expand all
66 scoped_refptr<VideoRenderer> video_renderer; 68 scoped_refptr<VideoRenderer> video_renderer;
67 scoped_refptr<CompositeFilter> composite; 69 scoped_refptr<CompositeFilter> composite;
68 }; 70 };
69 71
70 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) 72 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log)
71 : message_loop_(message_loop->message_loop_proxy()), 73 : message_loop_(message_loop->message_loop_proxy()),
72 media_log_(media_log), 74 media_log_(media_log),
73 clock_(new Clock(&base::Time::Now)), 75 clock_(new Clock(&base::Time::Now)),
74 waiting_for_clock_update_(false), 76 waiting_for_clock_update_(false),
75 state_(kCreated), 77 state_(kCreated),
76 current_bytes_(0),
77 creation_time_(base::Time::Now()) { 78 creation_time_(base::Time::Now()) {
78 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); 79 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
79 ResetState(); 80 ResetState();
80 media_log_->AddEvent( 81 media_log_->AddEvent(
81 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); 82 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED));
82 } 83 }
83 84
84 Pipeline::~Pipeline() { 85 Pipeline::~Pipeline() {
85 base::AutoLock auto_lock(lock_); 86 base::AutoLock auto_lock(lock_);
86 DCHECK(!running_) << "Stop() must complete before destroying object"; 87 DCHECK(!running_) << "Stop() must complete before destroying object";
(...skipping 20 matching lines...) Expand all
107 108
108 void Pipeline::Stop(const base::Closure& stop_cb) { 109 void Pipeline::Stop(const base::Closure& stop_cb) {
109 base::AutoLock auto_lock(lock_); 110 base::AutoLock auto_lock(lock_);
110 CHECK(running_) << "Media pipeline isn't running"; 111 CHECK(running_) << "Media pipeline isn't running";
111 112
112 // Stop the pipeline, which will set |running_| to false on our behalf. 113 // Stop the pipeline, which will set |running_| to false on our behalf.
113 message_loop_->PostTask(FROM_HERE, base::Bind( 114 message_loop_->PostTask(FROM_HERE, base::Bind(
114 &Pipeline::StopTask, this, stop_cb)); 115 &Pipeline::StopTask, this, stop_cb));
115 } 116 }
116 117
117 void Pipeline::Seek(base::TimeDelta time, 118 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
118 const PipelineStatusCB& seek_cb) {
119 base::AutoLock auto_lock(lock_); 119 base::AutoLock auto_lock(lock_);
120 CHECK(running_) << "Media pipeline isn't running"; 120 CHECK(running_) << "Media pipeline isn't running";
121 121
122 message_loop_->PostTask(FROM_HERE, base::Bind( 122 message_loop_->PostTask(FROM_HERE, base::Bind(
123 &Pipeline::SeekTask, this, time, seek_cb)); 123 &Pipeline::SeekTask, this, time, seek_cb));
124 } 124 }
125 125
126 bool Pipeline::IsRunning() const { 126 bool Pipeline::IsRunning() const {
127 base::AutoLock auto_lock(lock_); 127 base::AutoLock auto_lock(lock_);
128 return running_; 128 return running_;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 return; 183 return;
184 184
185 base::AutoLock auto_lock(lock_); 185 base::AutoLock auto_lock(lock_);
186 volume_ = volume; 186 volume_ = volume;
187 if (running_ && !tearing_down_) { 187 if (running_ && !tearing_down_) {
188 message_loop_->PostTask(FROM_HERE, base::Bind( 188 message_loop_->PostTask(FROM_HERE, base::Bind(
189 &Pipeline::VolumeChangedTask, this, volume)); 189 &Pipeline::VolumeChangedTask, this, volume));
190 } 190 }
191 } 191 }
192 192
193 base::TimeDelta Pipeline::GetCurrentTime() const { 193 TimeDelta Pipeline::GetCurrentTime() const {
194 base::AutoLock auto_lock(lock_); 194 base::AutoLock auto_lock(lock_);
195 return GetCurrentTime_Locked(); 195 return GetCurrentTime_Locked();
196 } 196 }
197 197
198 base::TimeDelta Pipeline::GetCurrentTime_Locked() const { 198 TimeDelta Pipeline::GetCurrentTime_Locked() const {
199 lock_.AssertAcquired(); 199 lock_.AssertAcquired();
200 return clock_->Elapsed(); 200 return clock_->Elapsed();
201 } 201 }
202 202
203 Ranges<base::TimeDelta> Pipeline::GetBufferedTimeRanges() { 203 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() {
204 base::AutoLock auto_lock(lock_); 204 base::AutoLock auto_lock(lock_);
205 return buffered_time_ranges_; 205 Ranges<base::TimeDelta> time_ranges;
scherkus (not reviewing) 2012/05/29 21:01:48 s/base:://
Ami GONE FROM CHROMIUM 2012/05/29 21:08:37 Done.
206 if (clock_->Duration() == TimeDelta() || total_bytes_ == 0)
207 return time_ranges;
208 for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i) {
209 TimeDelta start = TimeForByteOffset_Locked(buffered_byte_ranges_.start(i));
210 TimeDelta end = TimeForByteOffset_Locked(buffered_byte_ranges_.end(i));
211 // Cap approximated buffered time at the length of the video.
212 end = std::min(end, clock_->Duration());
213 time_ranges.Add(start, end);
214 }
215
216 return time_ranges;
206 } 217 }
207 218
208 base::TimeDelta Pipeline::GetMediaDuration() const { 219 TimeDelta Pipeline::GetMediaDuration() const {
209 base::AutoLock auto_lock(lock_); 220 base::AutoLock auto_lock(lock_);
210 return clock_->Duration(); 221 return clock_->Duration();
211 } 222 }
212 223
213 int64 Pipeline::GetBufferedBytes() const { 224 int64 Pipeline::GetBufferedBytes() const {
214 base::AutoLock auto_lock(lock_); 225 base::AutoLock auto_lock(lock_);
215 return buffered_bytes_; 226 int64 ret = 0;
227 for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i)
228 ret += buffered_byte_ranges_.end(i) - buffered_byte_ranges_.start(i);
229 return ret;
216 } 230 }
217 231
218 int64 Pipeline::GetTotalBytes() const { 232 int64 Pipeline::GetTotalBytes() const {
219 base::AutoLock auto_lock(lock_); 233 base::AutoLock auto_lock(lock_);
220 return total_bytes_; 234 return total_bytes_;
221 } 235 }
222 236
223 void Pipeline::GetNaturalVideoSize(gfx::Size* out_size) const { 237 void Pipeline::GetNaturalVideoSize(gfx::Size* out_size) const {
224 CHECK(out_size); 238 CHECK(out_size);
225 base::AutoLock auto_lock(lock_); 239 base::AutoLock auto_lock(lock_);
226 *out_size = natural_size_; 240 *out_size = natural_size_;
227 } 241 }
228 242
229 PipelineStatistics Pipeline::GetStatistics() const { 243 PipelineStatistics Pipeline::GetStatistics() const {
230 base::AutoLock auto_lock(lock_); 244 base::AutoLock auto_lock(lock_);
231 return statistics_; 245 return statistics_;
232 } 246 }
233 247
234 void Pipeline::SetClockForTesting(Clock* clock) { 248 void Pipeline::SetClockForTesting(Clock* clock) {
235 clock_.reset(clock); 249 clock_.reset(clock);
236 } 250 }
237 251
238 void Pipeline::SetCurrentReadPosition(int64 offset) {
239 base::AutoLock auto_lock(lock_);
240
241 // The current read position should never be ahead of the buffered byte
242 // position but threading issues between BufferedDataSource::DoneRead_Locked()
243 // and BufferedDataSource::NetworkEventCallback() can cause them to be
244 // temporarily out of sync. The easiest fix for this is to cap both
245 // buffered_bytes_ and current_bytes_ to always be legal values in
246 // SetCurrentReadPosition() and in SetBufferedBytes().
247 if (offset > buffered_bytes_)
248 buffered_bytes_ = offset;
249 current_bytes_ = offset;
250 }
251
252 void Pipeline::ResetState() { 252 void Pipeline::ResetState() {
253 base::AutoLock auto_lock(lock_); 253 base::AutoLock auto_lock(lock_);
254 const base::TimeDelta kZero; 254 const TimeDelta kZero;
255 running_ = false; 255 running_ = false;
256 stop_pending_ = false; 256 stop_pending_ = false;
257 seek_pending_ = false; 257 seek_pending_ = false;
258 tearing_down_ = false; 258 tearing_down_ = false;
259 error_caused_teardown_ = false; 259 error_caused_teardown_ = false;
260 playback_rate_change_pending_ = false; 260 playback_rate_change_pending_ = false;
261 buffered_bytes_ = 0; 261 buffered_byte_ranges_.clear();
262 buffered_time_ranges_.clear();
263 total_bytes_ = 0; 262 total_bytes_ = 0;
264 natural_size_.SetSize(0, 0); 263 natural_size_.SetSize(0, 0);
265 volume_ = 1.0f; 264 volume_ = 1.0f;
266 playback_rate_ = 0.0f; 265 playback_rate_ = 0.0f;
267 pending_playback_rate_ = 0.0f; 266 pending_playback_rate_ = 0.0f;
268 status_ = PIPELINE_OK; 267 status_ = PIPELINE_OK;
269 has_audio_ = false; 268 has_audio_ = false;
270 has_video_ = false; 269 has_video_ = false;
271 waiting_for_clock_update_ = false; 270 waiting_for_clock_update_ = false;
272 audio_disabled_ = false; 271 audio_disabled_ = false;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 DCHECK(IsRunning()); 370 DCHECK(IsRunning());
372 DCHECK_NE(PIPELINE_OK, error); 371 DCHECK_NE(PIPELINE_OK, error);
373 VLOG(1) << "Media pipeline error: " << error; 372 VLOG(1) << "Media pipeline error: " << error;
374 373
375 message_loop_->PostTask(FROM_HERE, base::Bind( 374 message_loop_->PostTask(FROM_HERE, base::Bind(
376 &Pipeline::ErrorChangedTask, this, error)); 375 &Pipeline::ErrorChangedTask, this, error));
377 376
378 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); 377 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
379 } 378 }
380 379
381 base::TimeDelta Pipeline::GetTime() const { 380 TimeDelta Pipeline::GetTime() const {
382 DCHECK(IsRunning()); 381 DCHECK(IsRunning());
383 return GetCurrentTime(); 382 return GetCurrentTime();
384 } 383 }
385 384
386 base::TimeDelta Pipeline::GetDuration() const { 385 TimeDelta Pipeline::GetDuration() const {
387 DCHECK(IsRunning()); 386 DCHECK(IsRunning());
388 return GetMediaDuration(); 387 return GetMediaDuration();
389 } 388 }
390 389
391 void Pipeline::OnAudioTimeUpdate(base::TimeDelta time, 390 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) {
392 base::TimeDelta max_time) {
393 DCHECK(time <= max_time); 391 DCHECK(time <= max_time);
394 DCHECK(IsRunning()); 392 DCHECK(IsRunning());
395 base::AutoLock auto_lock(lock_); 393 base::AutoLock auto_lock(lock_);
396 394
397 if (!has_audio_) 395 if (!has_audio_)
398 return; 396 return;
399 if (waiting_for_clock_update_ && time < clock_->Elapsed()) 397 if (waiting_for_clock_update_ && time < clock_->Elapsed())
400 return; 398 return;
401 399
402 clock_->SetTime(time, max_time); 400 clock_->SetTime(time, max_time);
403 StartClockIfWaitingForTimeUpdate_Locked(); 401 StartClockIfWaitingForTimeUpdate_Locked();
404 } 402 }
405 403
406 void Pipeline::OnVideoTimeUpdate(base::TimeDelta max_time) { 404 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) {
407 DCHECK(IsRunning()); 405 DCHECK(IsRunning());
408 base::AutoLock auto_lock(lock_); 406 base::AutoLock auto_lock(lock_);
409 407
410 if (has_audio_) 408 if (has_audio_)
411 return; 409 return;
412 410
413 DCHECK(!waiting_for_clock_update_); 411 DCHECK(!waiting_for_clock_update_);
414 clock_->SetMaxTime(max_time); 412 clock_->SetMaxTime(max_time);
415 } 413 }
416 414
417 void Pipeline::SetDuration(base::TimeDelta duration) { 415 void Pipeline::SetDuration(TimeDelta duration) {
418 DCHECK(IsRunning()); 416 DCHECK(IsRunning());
419 media_log_->AddEvent( 417 media_log_->AddEvent(
420 media_log_->CreateTimeEvent( 418 media_log_->CreateTimeEvent(
421 MediaLogEvent::DURATION_SET, "duration", duration)); 419 MediaLogEvent::DURATION_SET, "duration", duration));
422 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); 420 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration);
423 421
424 base::AutoLock auto_lock(lock_); 422 base::AutoLock auto_lock(lock_);
425 clock_->SetDuration(duration); 423 clock_->SetDuration(duration);
426 UpdateBufferedTimeRanges_Locked();
427 } 424 }
428 425
429 void Pipeline::SetTotalBytes(int64 total_bytes) { 426 void Pipeline::SetTotalBytes(int64 total_bytes) {
430 DCHECK(IsRunning()); 427 DCHECK(IsRunning());
431 media_log_->AddEvent( 428 media_log_->AddEvent(
432 media_log_->CreateIntegerEvent( 429 media_log_->CreateIntegerEvent(
433 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes)); 430 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes));
434 int64 total_mbytes = total_bytes >> 20; 431 int64 total_mbytes = total_bytes >> 20;
435 if (total_mbytes > kint32max) 432 if (total_mbytes > kint32max)
436 total_mbytes = kint32max; 433 total_mbytes = kint32max;
437 UMA_HISTOGRAM_CUSTOM_COUNTS( 434 UMA_HISTOGRAM_CUSTOM_COUNTS(
438 "Media.TotalMBytes", static_cast<int32>(total_mbytes), 1, kint32max, 50); 435 "Media.TotalMBytes", static_cast<int32>(total_mbytes), 1, kint32max, 50);
439 436
440 base::AutoLock auto_lock(lock_); 437 base::AutoLock auto_lock(lock_);
441 total_bytes_ = total_bytes; 438 total_bytes_ = total_bytes;
442 } 439 }
443 440
444 void Pipeline::SetBufferedBytes(int64 buffered_bytes) { 441 TimeDelta Pipeline::TimeForByteOffset_Locked(int64 byte_offset) const {
442 lock_.AssertAcquired();
443 TimeDelta time_offset = byte_offset * clock_->Duration() / total_bytes_;
444 // Since the byte->time calculation is approximate, fudge the beginning &
445 // ending areas to look better.
446 TimeDelta epsilon = clock_->Duration() / 100;
447 if (time_offset < epsilon)
448 return TimeDelta();
449 if (time_offset + epsilon > clock_->Duration())
450 return clock_->Duration();
451 return time_offset;
452 }
453
454 void Pipeline::AddBufferedByteRange(int64 start, int64 end) {
445 DCHECK(IsRunning()); 455 DCHECK(IsRunning());
446 base::AutoLock auto_lock(lock_); 456 base::AutoLock auto_lock(lock_);
447 // See comments in SetCurrentReadPosition() about capping. 457 buffered_byte_ranges_.Add(start, end);
448 if (buffered_bytes < current_bytes_)
449 current_bytes_ = buffered_bytes;
450 buffered_bytes_ = buffered_bytes;
451 UpdateBufferedTimeRanges_Locked();
452 }
453
454 void Pipeline::UpdateBufferedTimeRanges_Locked() {
455 lock_.AssertAcquired();
456 if (total_bytes_ == 0)
457 return;
458 base::TimeDelta buffered_time =
459 clock_->Duration() * buffered_bytes_ / total_bytes_;
460 // Cap approximated buffered time at the length of the video.
461 buffered_time = std::min(buffered_time, clock_->Duration());
462 // Make sure buffered_time is at least the current time and at least the
463 // current seek target.
464 buffered_time = std::max(buffered_time, GetCurrentTime_Locked());
465 buffered_time = std::max(buffered_time, seek_timestamp_);
466 buffered_time_ranges_.Add(seek_timestamp_, buffered_time);
467 } 458 }
468 459
469 void Pipeline::SetNaturalVideoSize(const gfx::Size& size) { 460 void Pipeline::SetNaturalVideoSize(const gfx::Size& size) {
470 DCHECK(IsRunning()); 461 DCHECK(IsRunning());
471 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( 462 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
472 size.width(), size.height())); 463 size.width(), size.height()));
473 464
474 base::AutoLock auto_lock(lock_); 465 base::AutoLock auto_lock(lock_);
475 natural_size_ = size; 466 natural_size_ = size;
476 } 467 }
477 468
478 void Pipeline::NotifyEnded() { 469 void Pipeline::NotifyEnded() {
479 DCHECK(IsRunning()); 470 DCHECK(IsRunning());
480 message_loop_->PostTask(FROM_HERE, base::Bind( 471 message_loop_->PostTask(FROM_HERE, base::Bind(
481 &Pipeline::NotifyEndedTask, this)); 472 &Pipeline::NotifyEndedTask, this));
482 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); 473 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED));
483 } 474 }
484 475
485 void Pipeline::SetNetworkActivity(bool is_downloading_data) { 476 void Pipeline::SetNetworkActivity(bool is_downloading_data) {
scherkus (not reviewing) 2012/05/29 21:01:48 hmm... how soon until this + network_cb_ can go aw
Ami GONE FROM CHROMIUM 2012/05/29 21:08:37 What is this I don't even. Pretty soon, I'm guessi
Ami GONE FROM CHROMIUM 2012/06/10 21:05:27 This is now https://chromiumcodereview.appspot.com
486 DCHECK(IsRunning()); 477 DCHECK(IsRunning());
487 478
488 NetworkEvent type = DOWNLOAD_PAUSED; 479 NetworkEvent type = DOWNLOAD_PAUSED;
489 if (is_downloading_data) 480 if (is_downloading_data)
490 type = DOWNLOAD_CONTINUED; 481 type = DOWNLOAD_CONTINUED;
491 482
492 message_loop_->PostTask(FROM_HERE, base::Bind( 483 message_loop_->PostTask(FROM_HERE, base::Bind(
493 &Pipeline::NotifyNetworkEventTask, this, type)); 484 &Pipeline::NotifyNetworkEventTask, this, type));
494 media_log_->AddEvent( 485 media_log_->AddEvent(
495 media_log_->CreateBooleanEvent( 486 media_log_->CreateBooleanEvent(
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 766
776 void Pipeline::VolumeChangedTask(float volume) { 767 void Pipeline::VolumeChangedTask(float volume) {
777 DCHECK(message_loop_->BelongsToCurrentThread()); 768 DCHECK(message_loop_->BelongsToCurrentThread());
778 if (!running_ || tearing_down_) 769 if (!running_ || tearing_down_)
779 return; 770 return;
780 771
781 if (audio_renderer_) 772 if (audio_renderer_)
782 audio_renderer_->SetVolume(volume); 773 audio_renderer_->SetVolume(volume);
783 } 774 }
784 775
785 void Pipeline::SeekTask(base::TimeDelta time, 776 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) {
786 const PipelineStatusCB& seek_cb) {
787 DCHECK(message_loop_->BelongsToCurrentThread()); 777 DCHECK(message_loop_->BelongsToCurrentThread());
788 DCHECK(!IsPipelineStopPending()); 778 DCHECK(!IsPipelineStopPending());
789 779
790 // Suppress seeking if we're not fully started. 780 // Suppress seeking if we're not fully started.
791 if (state_ != kStarted && state_ != kEnded) { 781 if (state_ != kStarted && state_ != kEnded) {
792 // TODO(scherkus): should we run the callback? I'm tempted to say the API 782 // TODO(scherkus): should we run the callback? I'm tempted to say the API
793 // will only execute the first Seek() request. 783 // will only execute the first Seek() request.
794 DVLOG(1) << "Media pipeline has not started, ignoring seek to " 784 DVLOG(1) << "Media pipeline has not started, ignoring seek to "
795 << time.InMicroseconds() << " (current state: " << state_ << ")"; 785 << time.InMicroseconds() << " (current state: " << state_ << ")";
796 return; 786 return;
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 } 1243 }
1254 1244
1255 if (pipeline_filter_) { 1245 if (pipeline_filter_) {
1256 pipeline_filter_->Stop(callback); 1246 pipeline_filter_->Stop(callback);
1257 return; 1247 return;
1258 } 1248 }
1259 1249
1260 callback.Run(); 1250 callback.Run();
1261 } 1251 }
1262 1252
1263 void Pipeline::DoSeek(base::TimeDelta seek_timestamp) { 1253 void Pipeline::DoSeek(TimeDelta seek_timestamp) {
1264 // TODO(acolwell): We might be able to convert this if (demuxer_) into a 1254 // TODO(acolwell): We might be able to convert this if (demuxer_) into a
1265 // DCHECK(). Further investigation is needed to make sure this won't introduce 1255 // DCHECK(). Further investigation is needed to make sure this won't introduce
1266 // a bug. 1256 // a bug.
1267 if (demuxer_) { 1257 if (demuxer_) {
1268 demuxer_->Seek(seek_timestamp, base::Bind( 1258 demuxer_->Seek(seek_timestamp, base::Bind(
1269 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp)); 1259 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp));
1270 return; 1260 return;
1271 } 1261 }
1272 1262
1273 OnDemuxerSeekDone(seek_timestamp, PIPELINE_OK); 1263 OnDemuxerSeekDone(seek_timestamp, PIPELINE_OK);
1274 } 1264 }
1275 1265
1276 void Pipeline::OnDemuxerSeekDone(base::TimeDelta seek_timestamp, 1266 void Pipeline::OnDemuxerSeekDone(TimeDelta seek_timestamp,
1277 PipelineStatus status) { 1267 PipelineStatus status) {
1278 if (!message_loop_->BelongsToCurrentThread()) { 1268 if (!message_loop_->BelongsToCurrentThread()) {
1279 message_loop_->PostTask(FROM_HERE, base::Bind( 1269 message_loop_->PostTask(FROM_HERE, base::Bind(
1280 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status)); 1270 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status));
1281 return; 1271 return;
1282 } 1272 }
1283 1273
1284 PipelineStatusCB done_cb = 1274 PipelineStatusCB done_cb =
1285 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this); 1275 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this);
1286 1276
(...skipping 22 matching lines...) Expand all
1309 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1299 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1310 lock_.AssertAcquired(); 1300 lock_.AssertAcquired();
1311 if (!waiting_for_clock_update_) 1301 if (!waiting_for_clock_update_)
1312 return; 1302 return;
1313 1303
1314 waiting_for_clock_update_ = false; 1304 waiting_for_clock_update_ = false;
1315 clock_->Play(); 1305 clock_->Play();
1316 } 1306 }
1317 1307
1318 } // namespace media 1308 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline.h ('k') | media/base/pipeline_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698