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

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: more hotness 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
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 // Since the byte->time calculation is approximate, fudge the beginning & 443 // Since the byte->time calculation is approximate, fudge the beginning &
445 // ending areas to look better. 444 // ending areas to look better.
446 TimeDelta epsilon = clock_->Duration() / 100; 445 TimeDelta epsilon = clock_->Duration() / 100;
447 if (time_offset < epsilon) 446 if (time_offset < epsilon)
448 return TimeDelta(); 447 return TimeDelta();
449 if (time_offset + epsilon > clock_->Duration()) 448 if (time_offset + epsilon > clock_->Duration())
450 return clock_->Duration(); 449 return clock_->Duration();
451 return time_offset; 450 return time_offset;
452 } 451 }
453 452
454 void Pipeline::DoPause(const base::Closure& done_cb) { 453 void Pipeline::DoPause(const PipelineStatusCB& done_cb) {
455 DCHECK(message_loop_->BelongsToCurrentThread()); 454 DCHECK(message_loop_->BelongsToCurrentThread());
456 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); 455 DCHECK(!pending_callbacks_.get());
456 scoped_ptr<SerialCallbackRunner::Queue> bound_fns(
457 new SerialCallbackRunner::Queue());
457 458
458 if (audio_renderer_) 459 if (audio_renderer_)
459 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_)); 460 bound_fns->Push(base::Bind(&AudioRenderer::Pause, audio_renderer_));
460 461
461 if (video_renderer_) 462 if (video_renderer_)
462 closures->push(base::Bind(&VideoRenderer::Pause, video_renderer_)); 463 bound_fns->Push(base::Bind(&VideoRenderer::Pause, video_renderer_));
463 464
464 RunInSeries(closures.Pass(), done_cb); 465 pending_callbacks_ = SerialCallbackRunner::Run(bound_fns.Pass(), done_cb);
465 } 466 }
466 467
467 void Pipeline::DoFlush(const base::Closure& done_cb) { 468 void Pipeline::DoFlush(const PipelineStatusCB& done_cb) {
468 DCHECK(message_loop_->BelongsToCurrentThread()); 469 DCHECK(message_loop_->BelongsToCurrentThread());
469 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); 470 DCHECK(!pending_callbacks_.get());
471 scoped_ptr<SerialCallbackRunner::Queue> bound_fns(
472 new SerialCallbackRunner::Queue());
470 473
471 if (audio_renderer_) 474 if (audio_renderer_)
472 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_)); 475 bound_fns->Push(base::Bind(&AudioRenderer::Flush, audio_renderer_));
473 476
474 if (video_renderer_) 477 if (video_renderer_)
475 closures->push(base::Bind(&VideoRenderer::Flush, video_renderer_)); 478 bound_fns->Push(base::Bind(&VideoRenderer::Flush, video_renderer_));
476 479
477 RunInParallel(closures.Pass(), done_cb); 480 pending_callbacks_ = SerialCallbackRunner::Run(bound_fns.Pass(), done_cb);
478 } 481 }
479 482
480 void Pipeline::DoPlay(const base::Closure& done_cb) { 483 void Pipeline::DoPlay(const PipelineStatusCB& done_cb) {
481 DCHECK(message_loop_->BelongsToCurrentThread()); 484 DCHECK(message_loop_->BelongsToCurrentThread());
482 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); 485 DCHECK(!pending_callbacks_.get());
486 scoped_ptr<SerialCallbackRunner::Queue> bound_fns(
487 new SerialCallbackRunner::Queue());
483 488
484 if (audio_renderer_) 489 if (audio_renderer_)
485 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_)); 490 bound_fns->Push(base::Bind(&AudioRenderer::Play, audio_renderer_));
486 491
487 if (video_renderer_) 492 if (video_renderer_)
488 closures->push(base::Bind(&VideoRenderer::Play, video_renderer_)); 493 bound_fns->Push(base::Bind(&VideoRenderer::Play, video_renderer_));
489 494
490 RunInSeries(closures.Pass(), done_cb); 495 pending_callbacks_ = SerialCallbackRunner::Run(bound_fns.Pass(), done_cb);
491 } 496 }
492 497
493 void Pipeline::DoStop(const base::Closure& done_cb) { 498 void Pipeline::DoStop(const PipelineStatusCB& done_cb) {
494 DCHECK(message_loop_->BelongsToCurrentThread()); 499 DCHECK(message_loop_->BelongsToCurrentThread());
495 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>); 500 DCHECK(!pending_callbacks_.get());
501 scoped_ptr<SerialCallbackRunner::Queue> bound_fns(
502 new SerialCallbackRunner::Queue());
496 503
497 if (demuxer_) 504 if (demuxer_)
498 closures->push(base::Bind(&Demuxer::Stop, demuxer_)); 505 bound_fns->Push(base::Bind(&Demuxer::Stop, demuxer_));
499 506
500 if (audio_renderer_) 507 if (audio_renderer_)
501 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_)); 508 bound_fns->Push(base::Bind(&AudioRenderer::Stop, audio_renderer_));
502 509
503 if (video_renderer_) 510 if (video_renderer_)
504 closures->push(base::Bind(&VideoRenderer::Stop, video_renderer_)); 511 bound_fns->Push(base::Bind(&VideoRenderer::Stop, video_renderer_));
505 512
506 RunInSeries(closures.Pass(), done_cb); 513 pending_callbacks_ = SerialCallbackRunner::Run(bound_fns.Pass(), done_cb);
507 } 514 }
508 515
509 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { 516 void Pipeline::AddBufferedByteRange(int64 start, int64 end) {
510 DCHECK(IsRunning()); 517 DCHECK(IsRunning());
511 base::AutoLock auto_lock(lock_); 518 base::AutoLock auto_lock(lock_);
512 buffered_byte_ranges_.Add(start, end); 519 buffered_byte_ranges_.Add(start, end);
513 did_loading_progress_ = true; 520 did_loading_progress_ = true;
514 } 521 }
515 522
516 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, 523 void Pipeline::AddBufferedTimeRange(base::TimeDelta start,
(...skipping 21 matching lines...) Expand all
538 } 545 }
539 546
540 // Called from any thread. 547 // Called from any thread.
541 void Pipeline::OnFilterInitialize(PipelineStatus status) { 548 void Pipeline::OnFilterInitialize(PipelineStatus status) {
542 // Continue the initialize task by proceeding to the next stage. 549 // Continue the initialize task by proceeding to the next stage.
543 message_loop_->PostTask(FROM_HERE, base::Bind( 550 message_loop_->PostTask(FROM_HERE, base::Bind(
544 &Pipeline::InitializeTask, this, status)); 551 &Pipeline::InitializeTask, this, status));
545 } 552 }
546 553
547 // Called from any thread. 554 // 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 555 // This method makes the PipelineStatusCB behave like a Closure. It
555 // makes it look like a host()->SetError() call followed by a call to 556 // makes it look like a host()->SetError() call followed by a call to
556 // OnFilterStateTransition() when errors occur. 557 // OnFilterStateTransition() when errors occur.
557 // 558 //
558 // TODO: Revisit this code when SetError() is removed from FilterHost and 559 // TODO: Revisit this code when SetError() is removed from FilterHost and
559 // all the Closures are converted to PipelineStatusCB. 560 // all the Closures are converted to PipelineStatusCB.
560 void Pipeline::OnFilterStateTransitionWithStatus(PipelineStatus status) { 561 void Pipeline::OnFilterStateTransition(PipelineStatus status) {
561 if (status != PIPELINE_OK) 562 if (status != PIPELINE_OK)
562 SetError(status); 563 SetError(status);
563 OnFilterStateTransition(); 564 message_loop_->PostTask(FROM_HERE, base::Bind(
565 &Pipeline::FilterStateTransitionTask, this));
564 } 566 }
565 567
566 void Pipeline::OnTeardownStateTransition() { 568 void Pipeline::OnTeardownStateTransition(PipelineStatus status) {
569 // Ignore any errors during teardown.
567 message_loop_->PostTask(FROM_HERE, base::Bind( 570 message_loop_->PostTask(FROM_HERE, base::Bind(
568 &Pipeline::TeardownStateTransitionTask, this)); 571 &Pipeline::TeardownStateTransitionTask, this));
569 } 572 }
570 573
571 // Called from any thread. 574 // Called from any thread.
572 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { 575 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) {
573 base::AutoLock auto_lock(lock_); 576 base::AutoLock auto_lock(lock_);
574 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; 577 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded;
575 statistics_.video_bytes_decoded += stats.video_bytes_decoded; 578 statistics_.video_bytes_decoded += stats.video_bytes_decoded;
576 statistics_.video_frames_decoded += stats.video_frames_decoded; 579 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. 690 // to set the initial playback rate and volume.
688 PlaybackRateChangedTask(GetPlaybackRate()); 691 PlaybackRateChangedTask(GetPlaybackRate());
689 VolumeChangedTask(GetVolume()); 692 VolumeChangedTask(GetVolume());
690 693
691 // Fire a seek request to get the renderers to preroll. We can skip a seek 694 // 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. 695 // here as the demuxer should be at the start of the stream.
693 seek_pending_ = true; 696 seek_pending_ = true;
694 SetState(kSeeking); 697 SetState(kSeeking);
695 seek_timestamp_ = demuxer_->GetStartTime(); 698 seek_timestamp_ = demuxer_->GetStartTime();
696 DoSeek(seek_timestamp_, true, 699 DoSeek(seek_timestamp_, true,
697 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this)); 700 base::Bind(&Pipeline::OnFilterStateTransition, this));
698 } 701 }
699 } 702 }
700 703
701 // This method is called as a result of the client calling Pipeline::Stop() or 704 // This method is called as a result of the client calling Pipeline::Stop() or
702 // as the result of an error condition. 705 // as the result of an error condition.
703 // We stop the filters in the reverse order. 706 // We stop the filters in the reverse order.
704 // 707 //
705 // TODO(scherkus): beware! this can get posted multiple times since we post 708 // 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 709 // 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. 710 // 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(); 885 demuxer_->OnAudioRendererDisabled();
883 886
884 // Start clock since there is no more audio to 887 // Start clock since there is no more audio to
885 // trigger clock updates. 888 // trigger clock updates.
886 clock_->SetMaxTime(clock_->Duration()); 889 clock_->SetMaxTime(clock_->Duration());
887 StartClockIfWaitingForTimeUpdate_Locked(); 890 StartClockIfWaitingForTimeUpdate_Locked();
888 } 891 }
889 892
890 void Pipeline::FilterStateTransitionTask() { 893 void Pipeline::FilterStateTransitionTask() {
891 DCHECK(message_loop_->BelongsToCurrentThread()); 894 DCHECK(message_loop_->BelongsToCurrentThread());
895 DCHECK(pending_callbacks_.get())
896 << "Filter state transitions must be completed via pending_callbacks_";
897 pending_callbacks_.reset();
892 898
893 // No reason transitioning if we've errored or have stopped. 899 // No reason transitioning if we've errored or have stopped.
894 if (IsPipelineStopped()) { 900 if (IsPipelineStopped()) {
895 return; 901 return;
896 } 902 }
897 903
898 // If we are tearing down, don't allow any state changes. Teardown 904 // If we are tearing down, don't allow any state changes. Teardown
899 // state changes will come in via TeardownStateTransitionTask(). 905 // state changes will come in via TeardownStateTransitionTask().
900 if (IsPipelineTearingDown()) { 906 if (IsPipelineTearingDown()) {
901 return; 907 return;
(...skipping 14 matching lines...) Expand all
916 } 922 }
917 923
918 // Carry out the action for the current state. 924 // Carry out the action for the current state.
919 if (TransientState(state_)) { 925 if (TransientState(state_)) {
920 if (state_ == kPausing) { 926 if (state_ == kPausing) {
921 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); 927 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
922 } else if (state_ == kFlushing) { 928 } else if (state_ == kFlushing) {
923 DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this)); 929 DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this));
924 } else if (state_ == kSeeking) { 930 } else if (state_ == kSeeking) {
925 DoSeek(seek_timestamp_, false, 931 DoSeek(seek_timestamp_, false,
926 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this)); 932 base::Bind(&Pipeline::OnFilterStateTransition, this));
927 } else if (state_ == kStarting) { 933 } else if (state_ == kStarting) {
928 DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this)); 934 DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this));
929 } else if (state_ == kStopping) { 935 } else if (state_ == kStopping) {
930 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this)); 936 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this));
931 } else { 937 } else {
932 NOTREACHED() << "Unexpected state: " << state_; 938 NOTREACHED() << "Unexpected state: " << state_;
933 } 939 }
934 } else if (state_ == kStarted) { 940 } else if (state_ == kStarted) {
935 FinishInitialization(); 941 FinishInitialization();
936 942
(...skipping 20 matching lines...) Expand all
957 // We had a pending stop request need to be honored right now. 963 // We had a pending stop request need to be honored right now.
958 TearDownPipeline(); 964 TearDownPipeline();
959 } 965 }
960 } else { 966 } else {
961 NOTREACHED() << "Unexpected state: " << state_; 967 NOTREACHED() << "Unexpected state: " << state_;
962 } 968 }
963 } 969 }
964 970
965 void Pipeline::TeardownStateTransitionTask() { 971 void Pipeline::TeardownStateTransitionTask() {
966 DCHECK(IsPipelineTearingDown()); 972 DCHECK(IsPipelineTearingDown());
973 DCHECK(pending_callbacks_.get())
974 << "Teardown state transitions must be completed via pending_callbacks_";
975 pending_callbacks_.reset();
976
967 switch (state_) { 977 switch (state_) {
968 case kStopping: 978 case kStopping:
969 SetState(error_caused_teardown_ ? kError : kStopped); 979 SetState(error_caused_teardown_ ? kError : kStopped);
970 FinishDestroyingFiltersTask(); 980 FinishDestroyingFiltersTask();
971 break; 981 break;
972 case kPausing: 982 case kPausing:
973 SetState(kFlushing); 983 SetState(kFlushing);
974 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 984 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this));
975 break; 985 break;
976 case kFlushing: 986 case kFlushing:
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 DCHECK(message_loop_->BelongsToCurrentThread()); 1174 DCHECK(message_loop_->BelongsToCurrentThread());
1165 DCHECK_NE(kStopped, state_); 1175 DCHECK_NE(kStopped, state_);
1166 1176
1167 DCHECK(!tearing_down_ || // Teardown on Stop(). 1177 DCHECK(!tearing_down_ || // Teardown on Stop().
1168 (tearing_down_ && error_caused_teardown_) || // Teardown on error. 1178 (tearing_down_ && error_caused_teardown_) || // Teardown on error.
1169 (tearing_down_ && stop_pending_)); // Stop during teardown by error. 1179 (tearing_down_ && stop_pending_)); // Stop during teardown by error.
1170 1180
1171 // Mark that we already start tearing down operation. 1181 // Mark that we already start tearing down operation.
1172 tearing_down_ = true; 1182 tearing_down_ = true;
1173 1183
1184 // Cancel any pending operation so we can proceed with teardown.
1185 pending_callbacks_.reset();
1186
1174 switch (state_) { 1187 switch (state_) {
1175 case kCreated: 1188 case kCreated:
1176 case kError: 1189 case kError:
1177 SetState(kStopped); 1190 SetState(kStopped);
1178 // Need to put this in the message loop to make sure that it comes 1191 // Need to put this in the message loop to make sure that it comes
1179 // after any pending callback tasks that are already queued. 1192 // after any pending callback tasks that are already queued.
1180 message_loop_->PostTask(FROM_HERE, base::Bind( 1193 message_loop_->PostTask(FROM_HERE, base::Bind(
1181 &Pipeline::FinishDestroyingFiltersTask, this)); 1194 &Pipeline::FinishDestroyingFiltersTask, this));
1182 break; 1195 break;
1183 1196
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 break; 1235 break;
1223 // default: intentionally left out to force new states to cause compiler 1236 // default: intentionally left out to force new states to cause compiler
1224 // errors. 1237 // errors.
1225 }; 1238 };
1226 } 1239 }
1227 1240
1228 void Pipeline::DoSeek(base::TimeDelta seek_timestamp, 1241 void Pipeline::DoSeek(base::TimeDelta seek_timestamp,
1229 bool skip_demuxer_seek, 1242 bool skip_demuxer_seek,
1230 const PipelineStatusCB& done_cb) { 1243 const PipelineStatusCB& done_cb) {
1231 DCHECK(message_loop_->BelongsToCurrentThread()); 1244 DCHECK(message_loop_->BelongsToCurrentThread());
1232 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs( 1245 DCHECK(!pending_callbacks_.get());
1233 new std::queue<PipelineStatusCBFunc>()); 1246 scoped_ptr<SerialCallbackRunner::Queue> bound_fns(
1247 new SerialCallbackRunner::Queue());
1234 1248
1235 if (!skip_demuxer_seek) 1249 if (!skip_demuxer_seek) {
1236 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp)); 1250 bound_fns->Push(base::Bind(
1251 &Demuxer::Seek, demuxer_, seek_timestamp));
1252 }
1237 1253
1238 if (audio_renderer_) 1254 if (audio_renderer_) {
1239 status_cbs->push(base::Bind( 1255 bound_fns->Push(base::Bind(
1240 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp)); 1256 &AudioRenderer::Preroll, audio_renderer_, seek_timestamp));
1257 }
1241 1258
1242 if (video_renderer_) 1259 if (video_renderer_) {
1243 status_cbs->push(base::Bind( 1260 bound_fns->Push(base::Bind(
1244 &VideoRenderer::Preroll, video_renderer_, seek_timestamp)); 1261 &VideoRenderer::Preroll, video_renderer_, seek_timestamp));
1262 }
1245 1263
1246 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind( 1264 pending_callbacks_ = SerialCallbackRunner::Run(bound_fns.Pass(), done_cb);
1247 &Pipeline::ReportStatus, this, done_cb));
1248 } 1265 }
1249 1266
1250 void Pipeline::OnAudioUnderflow() { 1267 void Pipeline::OnAudioUnderflow() {
1251 if (!message_loop_->BelongsToCurrentThread()) { 1268 if (!message_loop_->BelongsToCurrentThread()) {
1252 message_loop_->PostTask(FROM_HERE, base::Bind( 1269 message_loop_->PostTask(FROM_HERE, base::Bind(
1253 &Pipeline::OnAudioUnderflow, this)); 1270 &Pipeline::OnAudioUnderflow, this));
1254 return; 1271 return;
1255 } 1272 }
1256 1273
1257 if (state_ != kStarted) 1274 if (state_ != kStarted)
1258 return; 1275 return;
1259 1276
1260 if (audio_renderer_) 1277 if (audio_renderer_)
1261 audio_renderer_->ResumeAfterUnderflow(true); 1278 audio_renderer_->ResumeAfterUnderflow(true);
1262 } 1279 }
1263 1280
1264 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1281 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1265 lock_.AssertAcquired(); 1282 lock_.AssertAcquired();
1266 if (!waiting_for_clock_update_) 1283 if (!waiting_for_clock_update_)
1267 return; 1284 return;
1268 1285
1269 waiting_for_clock_update_ = false; 1286 waiting_for_clock_update_ = false;
1270 clock_->Play(); 1287 clock_->Play();
1271 } 1288 }
1272 1289
1273 } // namespace media 1290 } // 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