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

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, 7 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 (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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 109
108 void Pipeline::Stop(const base::Closure& stop_cb) { 110 void Pipeline::Stop(const base::Closure& stop_cb) {
109 base::AutoLock auto_lock(lock_); 111 base::AutoLock auto_lock(lock_);
110 CHECK(running_) << "Media pipeline isn't running"; 112 CHECK(running_) << "Media pipeline isn't running";
111 113
112 // Stop the pipeline, which will set |running_| to false on our behalf. 114 // Stop the pipeline, which will set |running_| to false on our behalf.
113 message_loop_->PostTask(FROM_HERE, base::Bind( 115 message_loop_->PostTask(FROM_HERE, base::Bind(
114 &Pipeline::StopTask, this, stop_cb)); 116 &Pipeline::StopTask, this, stop_cb));
115 } 117 }
116 118
117 void Pipeline::Seek(base::TimeDelta time, 119 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
118 const PipelineStatusCB& seek_cb) {
119 base::AutoLock auto_lock(lock_); 120 base::AutoLock auto_lock(lock_);
120 CHECK(running_) << "Media pipeline isn't running"; 121 CHECK(running_) << "Media pipeline isn't running";
121 122
122 message_loop_->PostTask(FROM_HERE, base::Bind( 123 message_loop_->PostTask(FROM_HERE, base::Bind(
123 &Pipeline::SeekTask, this, time, seek_cb)); 124 &Pipeline::SeekTask, this, time, seek_cb));
124 } 125 }
125 126
126 bool Pipeline::IsRunning() const { 127 bool Pipeline::IsRunning() const {
127 base::AutoLock auto_lock(lock_); 128 base::AutoLock auto_lock(lock_);
128 return running_; 129 return running_;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 return; 184 return;
184 185
185 base::AutoLock auto_lock(lock_); 186 base::AutoLock auto_lock(lock_);
186 volume_ = volume; 187 volume_ = volume;
187 if (running_ && !tearing_down_) { 188 if (running_ && !tearing_down_) {
188 message_loop_->PostTask(FROM_HERE, base::Bind( 189 message_loop_->PostTask(FROM_HERE, base::Bind(
189 &Pipeline::VolumeChangedTask, this, volume)); 190 &Pipeline::VolumeChangedTask, this, volume));
190 } 191 }
191 } 192 }
192 193
193 base::TimeDelta Pipeline::GetCurrentTime() const { 194 TimeDelta Pipeline::GetCurrentTime() const {
194 base::AutoLock auto_lock(lock_); 195 base::AutoLock auto_lock(lock_);
195 return GetCurrentTime_Locked(); 196 return GetCurrentTime_Locked();
196 } 197 }
197 198
198 base::TimeDelta Pipeline::GetCurrentTime_Locked() const { 199 TimeDelta Pipeline::GetCurrentTime_Locked() const {
199 lock_.AssertAcquired(); 200 lock_.AssertAcquired();
200 return clock_->Elapsed(); 201 return clock_->Elapsed();
201 } 202 }
202 203
203 Ranges<base::TimeDelta> Pipeline::GetBufferedTimeRanges() { 204 Ranges<TimeDelta> Pipeline::GetBufferedTimeRanges() {
204 base::AutoLock auto_lock(lock_); 205 base::AutoLock auto_lock(lock_);
205 return buffered_time_ranges_; 206 return buffered_time_ranges_;
scherkus (not reviewing) 2012/05/29 18:13:29 would it be simpler to compute buffered_time_range
Ami GONE FROM CHROMIUM 2012/05/29 20:45:44 Hmm; that does indeed simplify the code. There is
206 } 207 }
207 208
208 base::TimeDelta Pipeline::GetMediaDuration() const { 209 TimeDelta Pipeline::GetMediaDuration() const {
209 base::AutoLock auto_lock(lock_); 210 base::AutoLock auto_lock(lock_);
210 return clock_->Duration(); 211 return clock_->Duration();
211 } 212 }
212 213
213 int64 Pipeline::GetBufferedBytes() const { 214 int64 Pipeline::GetBufferedBytes() const {
214 base::AutoLock auto_lock(lock_); 215 base::AutoLock auto_lock(lock_);
215 return buffered_bytes_; 216 int64 ret = 0;
217 for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i)
218 ret += buffered_byte_ranges_.end(i) - buffered_byte_ranges_.start(i);
219 return ret;
216 } 220 }
217 221
218 int64 Pipeline::GetTotalBytes() const { 222 int64 Pipeline::GetTotalBytes() const {
219 base::AutoLock auto_lock(lock_); 223 base::AutoLock auto_lock(lock_);
220 return total_bytes_; 224 return total_bytes_;
221 } 225 }
222 226
223 void Pipeline::GetNaturalVideoSize(gfx::Size* out_size) const { 227 void Pipeline::GetNaturalVideoSize(gfx::Size* out_size) const {
224 CHECK(out_size); 228 CHECK(out_size);
225 base::AutoLock auto_lock(lock_); 229 base::AutoLock auto_lock(lock_);
226 *out_size = natural_size_; 230 *out_size = natural_size_;
227 } 231 }
228 232
229 PipelineStatistics Pipeline::GetStatistics() const { 233 PipelineStatistics Pipeline::GetStatistics() const {
230 base::AutoLock auto_lock(lock_); 234 base::AutoLock auto_lock(lock_);
231 return statistics_; 235 return statistics_;
232 } 236 }
233 237
234 void Pipeline::SetClockForTesting(Clock* clock) { 238 void Pipeline::SetClockForTesting(Clock* clock) {
235 clock_.reset(clock); 239 clock_.reset(clock);
236 } 240 }
237 241
238 void Pipeline::SetCurrentReadPosition(int64 offset) { 242 void Pipeline::SetCurrentReadPosition(int64 offset) {
scherkus (not reviewing) 2012/05/29 18:13:29 AFAIK this is still called by FFDemuxer but I can'
Ami GONE FROM CHROMIUM 2012/05/29 20:45:44 Hahahahahahahahaha. current_bytes_ is (was) a writ
239 base::AutoLock auto_lock(lock_); 243 base::AutoLock auto_lock(lock_);
240 244
241 // The current read position should never be ahead of the buffered byte 245 // The current read position should never be ahead of the buffered byte
242 // position but threading issues between BufferedDataSource::DoneRead_Locked() 246 // position but threading issues between BufferedDataSource::DoneRead_Locked()
243 // and BufferedDataSource::NetworkEventCallback() can cause them to be 247 // and BufferedDataSource::NetworkEventCallback() can cause them to be
244 // temporarily out of sync. The easiest fix for this is to cap both 248 // 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 249 // buffered_byte_ranges_ and current_bytes_ to always be legal values in
scherkus (not reviewing) 2012/05/29 18:13:29 |var|
Ami GONE FROM CHROMIUM 2012/05/29 20:45:44 Done.
246 // SetCurrentReadPosition() and in SetBufferedBytes(). 250 // SetCurrentReadPosition() and in AddBufferedByteRange().
247 if (offset > buffered_bytes_)
248 buffered_bytes_ = offset;
249 current_bytes_ = offset; 251 current_bytes_ = offset;
252 if (!buffered_byte_ranges_.size()) {
253 buffered_byte_ranges_.Add(0, offset);
254 return;
255 }
256 int64 start = buffered_byte_ranges_.start(buffered_byte_ranges_.size() - 1);
257 int64 end = buffered_byte_ranges_.end(buffered_byte_ranges_.size() - 1);
258 if (end < offset)
259 buffered_byte_ranges_.Add(start, offset);
250 } 260 }
251 261
252 void Pipeline::ResetState() { 262 void Pipeline::ResetState() {
253 base::AutoLock auto_lock(lock_); 263 base::AutoLock auto_lock(lock_);
254 const base::TimeDelta kZero; 264 const TimeDelta kZero;
255 running_ = false; 265 running_ = false;
256 stop_pending_ = false; 266 stop_pending_ = false;
257 seek_pending_ = false; 267 seek_pending_ = false;
258 tearing_down_ = false; 268 tearing_down_ = false;
259 error_caused_teardown_ = false; 269 error_caused_teardown_ = false;
260 playback_rate_change_pending_ = false; 270 playback_rate_change_pending_ = false;
261 buffered_bytes_ = 0; 271 buffered_byte_ranges_.clear();
262 buffered_time_ranges_.clear(); 272 buffered_time_ranges_.clear();
263 total_bytes_ = 0; 273 total_bytes_ = 0;
264 natural_size_.SetSize(0, 0); 274 natural_size_.SetSize(0, 0);
265 volume_ = 1.0f; 275 volume_ = 1.0f;
266 playback_rate_ = 0.0f; 276 playback_rate_ = 0.0f;
267 pending_playback_rate_ = 0.0f; 277 pending_playback_rate_ = 0.0f;
268 status_ = PIPELINE_OK; 278 status_ = PIPELINE_OK;
269 has_audio_ = false; 279 has_audio_ = false;
270 has_video_ = false; 280 has_video_ = false;
271 waiting_for_clock_update_ = false; 281 waiting_for_clock_update_ = false;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 DCHECK(IsRunning()); 381 DCHECK(IsRunning());
372 DCHECK_NE(PIPELINE_OK, error); 382 DCHECK_NE(PIPELINE_OK, error);
373 VLOG(1) << "Media pipeline error: " << error; 383 VLOG(1) << "Media pipeline error: " << error;
374 384
375 message_loop_->PostTask(FROM_HERE, base::Bind( 385 message_loop_->PostTask(FROM_HERE, base::Bind(
376 &Pipeline::ErrorChangedTask, this, error)); 386 &Pipeline::ErrorChangedTask, this, error));
377 387
378 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error)); 388 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
379 } 389 }
380 390
381 base::TimeDelta Pipeline::GetTime() const { 391 TimeDelta Pipeline::GetTime() const {
382 DCHECK(IsRunning()); 392 DCHECK(IsRunning());
383 return GetCurrentTime(); 393 return GetCurrentTime();
384 } 394 }
385 395
386 base::TimeDelta Pipeline::GetDuration() const { 396 TimeDelta Pipeline::GetDuration() const {
387 DCHECK(IsRunning()); 397 DCHECK(IsRunning());
388 return GetMediaDuration(); 398 return GetMediaDuration();
389 } 399 }
390 400
391 void Pipeline::OnAudioTimeUpdate(base::TimeDelta time, 401 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) {
392 base::TimeDelta max_time) {
393 DCHECK(time <= max_time); 402 DCHECK(time <= max_time);
394 DCHECK(IsRunning()); 403 DCHECK(IsRunning());
395 base::AutoLock auto_lock(lock_); 404 base::AutoLock auto_lock(lock_);
396 405
397 if (!has_audio_) 406 if (!has_audio_)
398 return; 407 return;
399 if (waiting_for_clock_update_ && time < clock_->Elapsed()) 408 if (waiting_for_clock_update_ && time < clock_->Elapsed())
400 return; 409 return;
401 410
402 clock_->SetTime(time, max_time); 411 clock_->SetTime(time, max_time);
403 StartClockIfWaitingForTimeUpdate_Locked(); 412 StartClockIfWaitingForTimeUpdate_Locked();
404 } 413 }
405 414
406 void Pipeline::OnVideoTimeUpdate(base::TimeDelta max_time) { 415 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) {
407 DCHECK(IsRunning()); 416 DCHECK(IsRunning());
408 base::AutoLock auto_lock(lock_); 417 base::AutoLock auto_lock(lock_);
409 418
410 if (has_audio_) 419 if (has_audio_)
411 return; 420 return;
412 421
413 DCHECK(!waiting_for_clock_update_); 422 DCHECK(!waiting_for_clock_update_);
414 clock_->SetMaxTime(max_time); 423 clock_->SetMaxTime(max_time);
415 } 424 }
416 425
417 void Pipeline::SetDuration(base::TimeDelta duration) { 426 void Pipeline::SetDuration(TimeDelta duration) {
418 DCHECK(IsRunning()); 427 DCHECK(IsRunning());
419 media_log_->AddEvent( 428 media_log_->AddEvent(
420 media_log_->CreateTimeEvent( 429 media_log_->CreateTimeEvent(
421 MediaLogEvent::DURATION_SET, "duration", duration)); 430 MediaLogEvent::DURATION_SET, "duration", duration));
422 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration); 431 UMA_HISTOGRAM_LONG_TIMES("Media.Duration", duration);
423 432
424 base::AutoLock auto_lock(lock_); 433 base::AutoLock auto_lock(lock_);
425 clock_->SetDuration(duration); 434 clock_->SetDuration(duration);
426 UpdateBufferedTimeRanges_Locked(); 435
436 if (total_bytes_ == 0)
437 return;
438 buffered_time_ranges_.clear();
439 for (size_t i = 0; i < buffered_byte_ranges_.size(); ++i) {
440 TimeDelta start = TimeForByteOffset_Locked(buffered_byte_ranges_.start(i));
441 TimeDelta end = TimeForByteOffset_Locked(buffered_byte_ranges_.end(i));
442 // Cap approximated buffered time at the length of the video.
443 end = std::min(end, clock_->Duration());
444 // Make sure buffered time is at least the current time.
445 end = std::max(end, GetCurrentTime_Locked());
446 buffered_time_ranges_.Add(start, end);
447 }
427 } 448 }
428 449
429 void Pipeline::SetTotalBytes(int64 total_bytes) { 450 void Pipeline::SetTotalBytes(int64 total_bytes) {
430 DCHECK(IsRunning()); 451 DCHECK(IsRunning());
431 media_log_->AddEvent( 452 media_log_->AddEvent(
432 media_log_->CreateIntegerEvent( 453 media_log_->CreateIntegerEvent(
433 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes)); 454 MediaLogEvent::TOTAL_BYTES_SET, "total_bytes", total_bytes));
434 int64 total_mbytes = total_bytes >> 20; 455 int64 total_mbytes = total_bytes >> 20;
435 if (total_mbytes > kint32max) 456 if (total_mbytes > kint32max)
436 total_mbytes = kint32max; 457 total_mbytes = kint32max;
437 UMA_HISTOGRAM_CUSTOM_COUNTS( 458 UMA_HISTOGRAM_CUSTOM_COUNTS(
438 "Media.TotalMBytes", static_cast<int32>(total_mbytes), 1, kint32max, 50); 459 "Media.TotalMBytes", static_cast<int32>(total_mbytes), 1, kint32max, 50);
439 460
440 base::AutoLock auto_lock(lock_); 461 base::AutoLock auto_lock(lock_);
441 total_bytes_ = total_bytes; 462 total_bytes_ = total_bytes;
442 } 463 }
443 464
444 void Pipeline::SetBufferedBytes(int64 buffered_bytes) { 465 TimeDelta Pipeline::TimeForByteOffset_Locked(int64 byte_offset) const {
466 lock_.AssertAcquired();
467 TimeDelta time_offset = byte_offset * clock_->Duration() / total_bytes_;
468 // Since the byte->time calculation is approximate, fudge the beginning &
469 // ending areas to look better.
470 TimeDelta epsilon = clock_->Duration() / 100;
471 if (time_offset < epsilon)
472 return TimeDelta();
473 if (time_offset + epsilon > clock_->Duration())
474 return clock_->Duration();
475 return time_offset;
476 }
477
478 void Pipeline::AddBufferedByteRange(int64 start, int64 end) {
445 DCHECK(IsRunning()); 479 DCHECK(IsRunning());
446 base::AutoLock auto_lock(lock_); 480 base::AutoLock auto_lock(lock_);
447 // See comments in SetCurrentReadPosition() about capping. 481 // See comments in SetCurrentReadPosition() about capping.
448 if (buffered_bytes < current_bytes_) 482 if (end < current_bytes_)
449 current_bytes_ = buffered_bytes; 483 current_bytes_ = end;
450 buffered_bytes_ = buffered_bytes; 484 buffered_byte_ranges_.Add(start, end);
451 UpdateBufferedTimeRanges_Locked();
452 }
453 485
454 void Pipeline::UpdateBufferedTimeRanges_Locked() {
455 lock_.AssertAcquired();
456 if (total_bytes_ == 0) 486 if (total_bytes_ == 0)
457 return; 487 return;
458 base::TimeDelta buffered_time = 488 buffered_time_ranges_.Add(TimeForByteOffset_Locked(start),
459 clock_->Duration() * buffered_bytes_ / total_bytes_; 489 TimeForByteOffset_Locked(end));
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 } 490 }
468 491
469 void Pipeline::SetNaturalVideoSize(const gfx::Size& size) { 492 void Pipeline::SetNaturalVideoSize(const gfx::Size& size) {
470 DCHECK(IsRunning()); 493 DCHECK(IsRunning());
471 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( 494 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
472 size.width(), size.height())); 495 size.width(), size.height()));
473 496
474 base::AutoLock auto_lock(lock_); 497 base::AutoLock auto_lock(lock_);
475 natural_size_ = size; 498 natural_size_ = size;
476 } 499 }
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 798
776 void Pipeline::VolumeChangedTask(float volume) { 799 void Pipeline::VolumeChangedTask(float volume) {
777 DCHECK(message_loop_->BelongsToCurrentThread()); 800 DCHECK(message_loop_->BelongsToCurrentThread());
778 if (!running_ || tearing_down_) 801 if (!running_ || tearing_down_)
779 return; 802 return;
780 803
781 if (audio_renderer_) 804 if (audio_renderer_)
782 audio_renderer_->SetVolume(volume); 805 audio_renderer_->SetVolume(volume);
783 } 806 }
784 807
785 void Pipeline::SeekTask(base::TimeDelta time, 808 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) {
786 const PipelineStatusCB& seek_cb) {
787 DCHECK(message_loop_->BelongsToCurrentThread()); 809 DCHECK(message_loop_->BelongsToCurrentThread());
788 DCHECK(!IsPipelineStopPending()); 810 DCHECK(!IsPipelineStopPending());
789 811
790 // Suppress seeking if we're not fully started. 812 // Suppress seeking if we're not fully started.
791 if (state_ != kStarted && state_ != kEnded) { 813 if (state_ != kStarted && state_ != kEnded) {
792 // TODO(scherkus): should we run the callback? I'm tempted to say the API 814 // TODO(scherkus): should we run the callback? I'm tempted to say the API
793 // will only execute the first Seek() request. 815 // will only execute the first Seek() request.
794 DVLOG(1) << "Media pipeline has not started, ignoring seek to " 816 DVLOG(1) << "Media pipeline has not started, ignoring seek to "
795 << time.InMicroseconds() << " (current state: " << state_ << ")"; 817 << time.InMicroseconds() << " (current state: " << state_ << ")";
796 return; 818 return;
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 } 1275 }
1254 1276
1255 if (pipeline_filter_) { 1277 if (pipeline_filter_) {
1256 pipeline_filter_->Stop(callback); 1278 pipeline_filter_->Stop(callback);
1257 return; 1279 return;
1258 } 1280 }
1259 1281
1260 callback.Run(); 1282 callback.Run();
1261 } 1283 }
1262 1284
1263 void Pipeline::DoSeek(base::TimeDelta seek_timestamp) { 1285 void Pipeline::DoSeek(TimeDelta seek_timestamp) {
1264 // TODO(acolwell): We might be able to convert this if (demuxer_) into a 1286 // 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 1287 // DCHECK(). Further investigation is needed to make sure this won't introduce
1266 // a bug. 1288 // a bug.
1267 if (demuxer_) { 1289 if (demuxer_) {
1268 demuxer_->Seek(seek_timestamp, base::Bind( 1290 demuxer_->Seek(seek_timestamp, base::Bind(
1269 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp)); 1291 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp));
1270 return; 1292 return;
1271 } 1293 }
1272 1294
1273 OnDemuxerSeekDone(seek_timestamp, PIPELINE_OK); 1295 OnDemuxerSeekDone(seek_timestamp, PIPELINE_OK);
1274 } 1296 }
1275 1297
1276 void Pipeline::OnDemuxerSeekDone(base::TimeDelta seek_timestamp, 1298 void Pipeline::OnDemuxerSeekDone(TimeDelta seek_timestamp,
1277 PipelineStatus status) { 1299 PipelineStatus status) {
1278 if (!message_loop_->BelongsToCurrentThread()) { 1300 if (!message_loop_->BelongsToCurrentThread()) {
1279 message_loop_->PostTask(FROM_HERE, base::Bind( 1301 message_loop_->PostTask(FROM_HERE, base::Bind(
1280 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status)); 1302 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status));
1281 return; 1303 return;
1282 } 1304 }
1283 1305
1284 PipelineStatusCB done_cb = 1306 PipelineStatusCB done_cb =
1285 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this); 1307 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this);
1286 1308
(...skipping 22 matching lines...) Expand all
1309 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1331 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1310 lock_.AssertAcquired(); 1332 lock_.AssertAcquired();
1311 if (!waiting_for_clock_update_) 1333 if (!waiting_for_clock_update_)
1312 return; 1334 return;
1313 1335
1314 waiting_for_clock_update_ = false; 1336 waiting_for_clock_update_ = false;
1315 clock_->Play(); 1337 clock_->Play();
1316 } 1338 }
1317 1339
1318 } // namespace media 1340 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698