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

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

Issue 10830146: Replace RunInSeries() and RunInParallel() with CallbackSeries helper class. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: comments Created 8 years, 4 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
« media/base/callback_util.cc ('K') | « media/base/pipeline.h ('k') | no next file » | 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/callback_util.h"
21 #include "media/base/clock.h" 20 #include "media/base/clock.h"
22 #include "media/base/filter_collection.h" 21 #include "media/base/filter_collection.h"
23 #include "media/base/media_log.h" 22 #include "media/base/media_log.h"
24 #include "media/base/video_decoder.h" 23 #include "media/base/video_decoder.h"
25 #include "media/base/video_renderer.h" 24 #include "media/base/video_renderer.h"
26 25
27 using base::TimeDelta; 26 using base::TimeDelta;
28 27
29 namespace media { 28 namespace media {
30 29
30 // Used to convert a callback to a function accepting a Closure into a callback
Ami GONE FROM CHROMIUM 2012/08/03 19:29:01 s/callback to a /bound/ twice
scherkus (not reviewing) 2012/08/03 20:19:04 Done.
31 // to a function accepting a PipelineStatusCB. Since closures have no way of
32 // reporting a status |status_cb| is executed with PIPELINE_OK.
33 typedef base::Callback<void(const base::Closure&)> ClosureFunc;
34 void RunClosureFunc(const ClosureFunc& closure,
35 const PipelineStatusCB& status_cb) {
36 closure.Run(base::Bind(status_cb, PIPELINE_OK));
37 }
38
31 PipelineStatusNotification::PipelineStatusNotification() 39 PipelineStatusNotification::PipelineStatusNotification()
32 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) { 40 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) {
33 } 41 }
34 42
35 PipelineStatusNotification::~PipelineStatusNotification() { 43 PipelineStatusNotification::~PipelineStatusNotification() {
36 DCHECK(notified_); 44 DCHECK(notified_);
37 } 45 }
38 46
39 PipelineStatusCB PipelineStatusNotification::Callback() { 47 PipelineStatusCB PipelineStatusNotification::Callback() {
40 return base::Bind(&PipelineStatusNotification::Notify, 48 return base::Bind(&PipelineStatusNotification::Notify,
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 // Since the byte->time calculation is approximate, fudge the beginning & 452 // Since the byte->time calculation is approximate, fudge the beginning &
445 // ending areas to look better. 453 // ending areas to look better.
446 TimeDelta epsilon = clock_->Duration() / 100; 454 TimeDelta epsilon = clock_->Duration() / 100;
447 if (time_offset < epsilon) 455 if (time_offset < epsilon)
448 return TimeDelta(); 456 return TimeDelta();
449 if (time_offset + epsilon > clock_->Duration()) 457 if (time_offset + epsilon > clock_->Duration())
450 return clock_->Duration(); 458 return clock_->Duration();
451 return time_offset; 459 return time_offset;
452 } 460 }
453 461
454 void Pipeline::DoPause(const base::Closure& done_cb) { 462 void Pipeline::DoPause(const PipelineStatusCB& done_cb) {
455 DCHECK(message_loop_->BelongsToCurrentThread()); 463 DCHECK(message_loop_->BelongsToCurrentThread());
456 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); 464 DCHECK(!pending_callbacks_.get());
465 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs(
466 new std::queue<PipelineStatusCBFunc>());
457 467
458 if (audio_renderer_) 468 if (audio_renderer_) {
459 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); 469 status_cbs->push(base::Bind(
470 &RunClosureFunc, base::Bind(&AudioRenderer::Pause, audio_renderer_)));
471 }
460 472
461 if (video_renderer_) 473 if (video_renderer_) {
462 closures->push(base::Bind(&VideoRenderer::Pause, video_renderer_)); 474 status_cbs->push(base::Bind(
475 &RunClosureFunc, base::Bind(&VideoRenderer::Pause, video_renderer_)));
476 }
463 477
464 RunInSeries(closures.Pass(), done_cb); 478 pending_callbacks_ = SerialCallbackRunner::Run(status_cbs.Pass(), done_cb);
465 } 479 }
466 480
467 void Pipeline::DoFlush(const base::Closure& done_cb) { 481 void Pipeline::DoFlush(const PipelineStatusCB& done_cb) {
468 DCHECK(message_loop_->BelongsToCurrentThread()); 482 DCHECK(message_loop_->BelongsToCurrentThread());
469 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); 483 DCHECK(!pending_callbacks_.get());
484 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs(
485 new std::queue<PipelineStatusCBFunc>());
470 486
471 if (audio_renderer_) 487 if (audio_renderer_) {
472 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); 488 status_cbs->push(base::Bind(
489 &RunClosureFunc, base::Bind(&AudioRenderer::Flush, audio_renderer_)));
490 }
473 491
474 if (video_renderer_) 492 if (video_renderer_) {
475 closures->push(base::Bind(&VideoRenderer::Flush, video_renderer_)); 493 status_cbs->push(base::Bind(
494 &RunClosureFunc, base::Bind(&VideoRenderer::Flush, video_renderer_)));
495 }
476 496
477 RunInParallel(closures.Pass(), done_cb); 497 pending_callbacks_ = SerialCallbackRunner::Run(status_cbs.Pass(), done_cb);
478 } 498 }
479 499
480 void Pipeline::DoPlay(const base::Closure& done_cb) { 500 void Pipeline::DoPlay(const PipelineStatusCB& done_cb) {
481 DCHECK(message_loop_->BelongsToCurrentThread()); 501 DCHECK(message_loop_->BelongsToCurrentThread());
482 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); 502 DCHECK(!pending_callbacks_.get());
503 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs(
504 new std::queue<PipelineStatusCBFunc>());
483 505
484 if (audio_renderer_) 506 if (audio_renderer_) {
485 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); 507 status_cbs->push(base::Bind(
508 &RunClosureFunc, base::Bind(&AudioRenderer::Play, audio_renderer_)));
509 }
486 510
487 if (video_renderer_) 511 if (video_renderer_) {
488 closures->push(base::Bind(&VideoRenderer::Play, video_renderer_)); 512 status_cbs->push(base::Bind(
513 &RunClosureFunc, base::Bind(&VideoRenderer::Play, video_renderer_)));
514 }
489 515
490 RunInSeries(closures.Pass(), done_cb); 516 pending_callbacks_ = SerialCallbackRunner::Run(status_cbs.Pass(), done_cb);
491 } 517 }
492 518
493 void Pipeline::DoStop(const base::Closure& done_cb) { 519 void Pipeline::DoStop(const PipelineStatusCB& done_cb) {
494 DCHECK(message_loop_->BelongsToCurrentThread()); 520 DCHECK(message_loop_->BelongsToCurrentThread());
495 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); 521 DCHECK(!pending_callbacks_.get());
522 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs(
523 new std::queue<PipelineStatusCBFunc>());
496 524
497 if (demuxer_) 525 if (demuxer_) {
498 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); 526 status_cbs->push(base::Bind(
527 &RunClosureFunc, base::Bind(&Demuxer::Stop, demuxer_)));
528 }
499 529
500 if (audio_renderer_) 530 if (audio_renderer_) {
501 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); 531 status_cbs->push(base::Bind(
532 &RunClosureFunc, base::Bind(&AudioRenderer::Stop, audio_renderer_)));
533 }
502 534
503 if (video_renderer_) 535 if (video_renderer_) {
504 closures->push(base::Bind(&VideoRenderer::Stop, video_renderer_)); 536 status_cbs->push(base::Bind(
537 &RunClosureFunc, base::Bind(&VideoRenderer::Stop, video_renderer_)));
538 }
505 539
506 RunInSeries(closures.Pass(), done_cb); 540 pending_callbacks_ = SerialCallbackRunner::Run(status_cbs.Pass(), done_cb);
507 } 541 }
508 542
509 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { 543 void Pipeline::AddBufferedByteRange(int64 start, int64 end) {
510 DCHECK(IsRunning()); 544 DCHECK(IsRunning());
511 base::AutoLock auto_lock(lock_); 545 base::AutoLock auto_lock(lock_);
512 buffered_byte_ranges_.Add(start, end); 546 buffered_byte_ranges_.Add(start, end);
513 did_loading_progress_ = true; 547 did_loading_progress_ = true;
514 } 548 }
515 549
516 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, 550 void Pipeline::AddBufferedTimeRange(base::TimeDelta start,
(...skipping 21 matching lines...) Expand all
538 } 572 }
539 573
540 // Called from any thread. 574 // Called from any thread.
541 void Pipeline::OnFilterInitialize(PipelineStatus status) { 575 void Pipeline::OnFilterInitialize(PipelineStatus status) {
542 // Continue the initialize task by proceeding to the next stage. 576 // Continue the initialize task by proceeding to the next stage.
543 message_loop_->PostTask(FROM_HERE, base::Bind( 577 message_loop_->PostTask(FROM_HERE, base::Bind(
544 &Pipeline::InitializeTask, this, status)); 578 &Pipeline::InitializeTask, this, status));
545 } 579 }
546 580
547 // Called from any thread. 581 // Called from any thread.
548 void Pipeline::OnFilterStateTransition() {
549 message_loop_->PostTask(FROM_HERE, base::Bind(
550 &Pipeline::FilterStateTransitionTask, this));
551 }
552
553 // Called from any thread.
554 // This method makes the PipelineStatusCB behave like a Closure. It 582 // This method makes the PipelineStatusCB behave like a Closure. It
555 // makes it look like a host()->SetError() call followed by a call to 583 // makes it look like a host()->SetError() call followed by a call to
556 // OnFilterStateTransition() when errors occur. 584 // OnFilterStateTransition() when errors occur.
557 // 585 //
558 // TODO: Revisit this code when SetError() is removed from FilterHost and 586 // TODO: Revisit this code when SetError() is removed from FilterHost and
559 // all the Closures are converted to PipelineStatusCB. 587 // all the Closures are converted to PipelineStatusCB.
560 void Pipeline::OnFilterStateTransitionWithStatus(PipelineStatus status) { 588 void Pipeline::OnFilterStateTransition(PipelineStatus status) {
561 if (status != PIPELINE_OK) 589 if (status != PIPELINE_OK)
562 SetError(status); 590 SetError(status);
563 OnFilterStateTransition(); 591 message_loop_->PostTask(FROM_HERE, base::Bind(
592 &Pipeline::FilterStateTransitionTask, this));
564 } 593 }
565 594
566 void Pipeline::OnTeardownStateTransition() { 595 void Pipeline::OnTeardownStateTransition(PipelineStatus status) {
596 // Ignore any errors during teardown.
567 message_loop_->PostTask(FROM_HERE, base::Bind( 597 message_loop_->PostTask(FROM_HERE, base::Bind(
568 &Pipeline::TeardownStateTransitionTask, this)); 598 &Pipeline::TeardownStateTransitionTask, this));
569 } 599 }
570 600
571 // Called from any thread. 601 // Called from any thread.
572 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { 602 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) {
573 base::AutoLock auto_lock(lock_); 603 base::AutoLock auto_lock(lock_);
574 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; 604 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded;
575 statistics_.video_bytes_decoded += stats.video_bytes_decoded; 605 statistics_.video_bytes_decoded += stats.video_bytes_decoded;
576 statistics_.video_frames_decoded += stats.video_frames_decoded; 606 statistics_.video_frames_decoded += stats.video_frames_decoded;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 // to set the initial playback rate and volume. 717 // to set the initial playback rate and volume.
688 PlaybackRateChangedTask(GetPlaybackRate()); 718 PlaybackRateChangedTask(GetPlaybackRate());
689 VolumeChangedTask(GetVolume()); 719 VolumeChangedTask(GetVolume());
690 720
691 // Fire a seek request to get the renderers to preroll. We can skip a seek 721 // Fire a seek request to get the renderers to preroll. We can skip a seek
692 // here as the demuxer should be at the start of the stream. 722 // here as the demuxer should be at the start of the stream.
693 seek_pending_ = true; 723 seek_pending_ = true;
694 SetState(kSeeking); 724 SetState(kSeeking);
695 seek_timestamp_ = demuxer_->GetStartTime(); 725 seek_timestamp_ = demuxer_->GetStartTime();
696 DoSeek(seek_timestamp_, true, 726 DoSeek(seek_timestamp_, true,
697 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this)); 727 base::Bind(&Pipeline::OnFilterStateTransition, this));
698 } 728 }
699 } 729 }
700 730
701 // This method is called as a result of the client calling Pipeline::Stop() or 731 // This method is called as a result of the client calling Pipeline::Stop() or
702 // as the result of an error condition. 732 // as the result of an error condition.
703 // We stop the filters in the reverse order. 733 // We stop the filters in the reverse order.
704 // 734 //
705 // TODO(scherkus): beware! this can get posted multiple times since we post 735 // TODO(scherkus): beware! this can get posted multiple times since we post
706 // Stop() tasks even if we've already stopped. Perhaps this should no-op for 736 // Stop() tasks even if we've already stopped. Perhaps this should no-op for
707 // additional calls, however most of this logic will be changing. 737 // additional calls, however most of this logic will be changing.
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
882 demuxer_->OnAudioRendererDisabled(); 912 demuxer_->OnAudioRendererDisabled();
883 913
884 // Start clock since there is no more audio to 914 // Start clock since there is no more audio to
885 // trigger clock updates. 915 // trigger clock updates.
886 clock_->SetMaxTime(clock_->Duration()); 916 clock_->SetMaxTime(clock_->Duration());
887 StartClockIfWaitingForTimeUpdate_Locked(); 917 StartClockIfWaitingForTimeUpdate_Locked();
888 } 918 }
889 919
890 void Pipeline::FilterStateTransitionTask() { 920 void Pipeline::FilterStateTransitionTask() {
891 DCHECK(message_loop_->BelongsToCurrentThread()); 921 DCHECK(message_loop_->BelongsToCurrentThread());
922 DCHECK(pending_callbacks_.get())
923 << "Filter state transitions must be completed via pending_callbacks_";
924 pending_callbacks_.reset();
892 925
893 // No reason transitioning if we've errored or have stopped. 926 // No reason transitioning if we've errored or have stopped.
894 if (IsPipelineStopped()) { 927 if (IsPipelineStopped()) {
895 return; 928 return;
896 } 929 }
897 930
898 // If we are tearing down, don't allow any state changes. Teardown 931 // If we are tearing down, don't allow any state changes. Teardown
899 // state changes will come in via TeardownStateTransitionTask(). 932 // state changes will come in via TeardownStateTransitionTask().
900 if (IsPipelineTearingDown()) { 933 if (IsPipelineTearingDown()) {
901 return; 934 return;
(...skipping 14 matching lines...) Expand all
916 } 949 }
917 950
918 // Carry out the action for the current state. 951 // Carry out the action for the current state.
919 if (TransientState(state_)) { 952 if (TransientState(state_)) {
920 if (state_ == kPausing) { 953 if (state_ == kPausing) {
921 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); 954 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
922 } else if (state_ == kFlushing) { 955 } else if (state_ == kFlushing) {
923 DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this)); 956 DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this));
924 } else if (state_ == kSeeking) { 957 } else if (state_ == kSeeking) {
925 DoSeek(seek_timestamp_, false, 958 DoSeek(seek_timestamp_, false,
926 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this)); 959 base::Bind(&Pipeline::OnFilterStateTransition, this));
927 } else if (state_ == kStarting) { 960 } else if (state_ == kStarting) {
928 DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this)); 961 DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this));
929 } else if (state_ == kStopping) { 962 } else if (state_ == kStopping) {
930 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this)); 963 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this));
931 } else { 964 } else {
932 NOTREACHED() << "Unexpected state: " << state_; 965 NOTREACHED() << "Unexpected state: " << state_;
933 } 966 }
934 } else if (state_ == kStarted) { 967 } else if (state_ == kStarted) {
935 FinishInitialization(); 968 FinishInitialization();
936 969
(...skipping 20 matching lines...) Expand all
957 // We had a pending stop request need to be honored right now. 990 // We had a pending stop request need to be honored right now.
958 TearDownPipeline(); 991 TearDownPipeline();
959 } 992 }
960 } else { 993 } else {
961 NOTREACHED() << "Unexpected state: " << state_; 994 NOTREACHED() << "Unexpected state: " << state_;
962 } 995 }
963 } 996 }
964 997
965 void Pipeline::TeardownStateTransitionTask() { 998 void Pipeline::TeardownStateTransitionTask() {
966 DCHECK(IsPipelineTearingDown()); 999 DCHECK(IsPipelineTearingDown());
1000 DCHECK(pending_callbacks_.get())
1001 << "Teardown state transitions must be completed via pending_callbacks_";
1002 pending_callbacks_.reset();
1003
967 switch (state_) { 1004 switch (state_) {
968 case kStopping: 1005 case kStopping:
969 SetState(error_caused_teardown_ ? kError : kStopped); 1006 SetState(error_caused_teardown_ ? kError : kStopped);
970 FinishDestroyingFiltersTask(); 1007 FinishDestroyingFiltersTask();
971 break; 1008 break;
972 case kPausing: 1009 case kPausing:
973 SetState(kFlushing); 1010 SetState(kFlushing);
974 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 1011 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this));
975 break; 1012 break;
976 case kFlushing: 1013 case kFlushing:
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 DCHECK(message_loop_->BelongsToCurrentThread()); 1201 DCHECK(message_loop_->BelongsToCurrentThread());
1165 DCHECK_NE(kStopped, state_); 1202 DCHECK_NE(kStopped, state_);
1166 1203
1167 DCHECK(!tearing_down_ || // Teardown on Stop(). 1204 DCHECK(!tearing_down_ || // Teardown on Stop().
1168 (tearing_down_ && error_caused_teardown_) || // Teardown on error. 1205 (tearing_down_ && error_caused_teardown_) || // Teardown on error.
1169 (tearing_down_ && stop_pending_)); // Stop during teardown by error. 1206 (tearing_down_ && stop_pending_)); // Stop during teardown by error.
1170 1207
1171 // Mark that we already start tearing down operation. 1208 // Mark that we already start tearing down operation.
1172 tearing_down_ = true; 1209 tearing_down_ = true;
1173 1210
1211 // Cancel any pending operation so we can proceed with teardown.
1212 pending_callbacks_.reset();
1213
1174 switch (state_) { 1214 switch (state_) {
1175 case kCreated: 1215 case kCreated:
1176 case kError: 1216 case kError:
1177 SetState(kStopped); 1217 SetState(kStopped);
1178 // Need to put this in the message loop to make sure that it comes 1218 // Need to put this in the message loop to make sure that it comes
1179 // after any pending callback tasks that are already queued. 1219 // after any pending callback tasks that are already queued.
1180 message_loop_->PostTask(FROM_HERE, base::Bind( 1220 message_loop_->PostTask(FROM_HERE, base::Bind(
1181 &Pipeline::FinishDestroyingFiltersTask, this)); 1221 &Pipeline::FinishDestroyingFiltersTask, this));
1182 break; 1222 break;
1183 1223
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 break; 1262 break;
1223 // default: intentionally left out to force new states to cause compiler 1263 // default: intentionally left out to force new states to cause compiler
1224 // errors. 1264 // errors.
1225 }; 1265 };
1226 } 1266 }
1227 1267
1228 void Pipeline::DoSeek(base::TimeDelta seek_timestamp, 1268 void Pipeline::DoSeek(base::TimeDelta seek_timestamp,
1229 bool skip_demuxer_seek, 1269 bool skip_demuxer_seek,
1230 const PipelineStatusCB& done_cb) { 1270 const PipelineStatusCB& done_cb) {
1231 DCHECK(message_loop_->BelongsToCurrentThread()); 1271 DCHECK(message_loop_->BelongsToCurrentThread());
1272 DCHECK(!pending_callbacks_.get());
1232 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs( 1273 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs(
1233 new std::queue<PipelineStatusCBFunc>()); 1274 new std::queue<PipelineStatusCBFunc>());
1234 1275
1235 if (!skip_demuxer_seek) 1276 if (!skip_demuxer_seek) {
1236 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp)); 1277 status_cbs->push(base::Bind(
1278 &Demuxer::Seek, demuxer_, seek_timestamp));
1279 }
1237 1280
1238 if (audio_renderer_) 1281 if (audio_renderer_) {
1239 status_cbs->push(base::Bind( 1282 status_cbs->push(base::Bind(
1240 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp)); 1283 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp));
1284 }
1241 1285
1242 if (video_renderer_) 1286 if (video_renderer_) {
1243 status_cbs->push(base::Bind( 1287 status_cbs->push(base::Bind(
1244 &VideoRenderer::Preroll, video_renderer_, seek_timestamp)); 1288 &VideoRenderer::Preroll, video_renderer_, seek_timestamp));
1289 }
1245 1290
1246 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind( 1291 pending_callbacks_ = SerialCallbackRunner::Run(status_cbs.Pass(), done_cb);
1247 &Pipeline::ReportStatus, this, done_cb));
1248 } 1292 }
1249 1293
1250 void Pipeline::OnAudioUnderflow() { 1294 void Pipeline::OnAudioUnderflow() {
1251 if (!message_loop_->BelongsToCurrentThread()) { 1295 if (!message_loop_->BelongsToCurrentThread()) {
1252 message_loop_->PostTask(FROM_HERE, base::Bind( 1296 message_loop_->PostTask(FROM_HERE, base::Bind(
1253 &Pipeline::OnAudioUnderflow, this)); 1297 &Pipeline::OnAudioUnderflow, this));
1254 return; 1298 return;
1255 } 1299 }
1256 1300
1257 if (state_ != kStarted) 1301 if (state_ != kStarted)
1258 return; 1302 return;
1259 1303
1260 if (audio_renderer_) 1304 if (audio_renderer_)
1261 audio_renderer_->ResumeAfterUnderflow(true); 1305 audio_renderer_->ResumeAfterUnderflow(true);
1262 } 1306 }
1263 1307
1264 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1308 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1265 lock_.AssertAcquired(); 1309 lock_.AssertAcquired();
1266 if (!waiting_for_clock_update_) 1310 if (!waiting_for_clock_update_)
1267 return; 1311 return;
1268 1312
1269 waiting_for_clock_update_ = false; 1313 waiting_for_clock_update_ = false;
1270 clock_->Play(); 1314 clock_->Play();
1271 } 1315 }
1272 1316
1273 } // namespace media 1317 } // namespace media
OLDNEW
« media/base/callback_util.cc ('K') | « media/base/pipeline.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698