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

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

Issue 206103004: Remove HasAudio(), HasVideo(), GetInitialNaturalSize() from media::Pipeline. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 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
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"
(...skipping 27 matching lines...) Expand all
38 : task_runner_(task_runner), 38 : task_runner_(task_runner),
39 media_log_(media_log), 39 media_log_(media_log),
40 running_(false), 40 running_(false),
41 did_loading_progress_(false), 41 did_loading_progress_(false),
42 total_bytes_(0), 42 total_bytes_(0),
43 volume_(1.0f), 43 volume_(1.0f),
44 playback_rate_(0.0f), 44 playback_rate_(0.0f),
45 clock_(new Clock(&default_tick_clock_)), 45 clock_(new Clock(&default_tick_clock_)),
46 waiting_for_clock_update_(false), 46 waiting_for_clock_update_(false),
47 status_(PIPELINE_OK), 47 status_(PIPELINE_OK),
48 has_audio_(false),
49 has_video_(false),
50 state_(kCreated), 48 state_(kCreated),
51 audio_ended_(false), 49 audio_ended_(false),
52 video_ended_(false), 50 video_ended_(false),
53 text_ended_(false), 51 text_ended_(false),
54 audio_disabled_(false), 52 audio_disabled_(false),
55 demuxer_(NULL), 53 demuxer_(NULL),
56 creation_time_(default_tick_clock_.NowTicks()) { 54 creation_time_(default_tick_clock_.NowTicks()) {
57 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); 55 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
58 media_log_->AddEvent( 56 media_log_->AddEvent(
59 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); 57 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED));
60 } 58 }
61 59
62 Pipeline::~Pipeline() { 60 Pipeline::~Pipeline() {
63 DCHECK(thread_checker_.CalledOnValidThread()) 61 DCHECK(thread_checker_.CalledOnValidThread())
64 << "Pipeline must be destroyed on same thread that created it"; 62 << "Pipeline must be destroyed on same thread that created it";
65 DCHECK(!running_) << "Stop() must complete before destroying object"; 63 DCHECK(!running_) << "Stop() must complete before destroying object";
66 DCHECK(stop_cb_.is_null()); 64 DCHECK(stop_cb_.is_null());
67 DCHECK(seek_cb_.is_null()); 65 DCHECK(seek_cb_.is_null());
68 66
69 media_log_->AddEvent( 67 media_log_->AddEvent(
70 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); 68 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED));
71 } 69 }
72 70
73 void Pipeline::Start(scoped_ptr<FilterCollection> collection, 71 void Pipeline::Start(scoped_ptr<FilterCollection> collection,
74 const base::Closure& ended_cb, 72 const base::Closure& ended_cb,
75 const PipelineStatusCB& error_cb, 73 const PipelineStatusCB& error_cb,
76 const PipelineStatusCB& seek_cb, 74 const PipelineStatusCB& seek_cb,
75 const HasTrackCB& has_track_cb,
77 const BufferingStateCB& buffering_state_cb, 76 const BufferingStateCB& buffering_state_cb,
78 const base::Closure& duration_change_cb) { 77 const base::Closure& duration_change_cb) {
79 base::AutoLock auto_lock(lock_); 78 base::AutoLock auto_lock(lock_);
80 CHECK(!running_) << "Media pipeline is already running"; 79 CHECK(!running_) << "Media pipeline is already running";
81 DCHECK(!buffering_state_cb.is_null()); 80 DCHECK(!buffering_state_cb.is_null());
82 81
82 filter_collection_ = collection.Pass();
83 ended_cb_ = ended_cb;
84 error_cb_ = error_cb;
85 seek_cb_ = seek_cb;
86 has_track_cb_ = has_track_cb;
87 buffering_state_cb_ = buffering_state_cb;
88 duration_change_cb_ = duration_change_cb;
89
83 running_ = true; 90 running_ = true;
84 task_runner_->PostTask(FROM_HERE, base::Bind( 91 task_runner_->PostTask(
85 &Pipeline::StartTask, base::Unretained(this), base::Passed(&collection), 92 FROM_HERE, base::Bind(&Pipeline::StartTask, base::Unretained(this)));
86 ended_cb, error_cb, seek_cb, buffering_state_cb, duration_change_cb));
87 } 93 }
88 94
89 void Pipeline::Stop(const base::Closure& stop_cb) { 95 void Pipeline::Stop(const base::Closure& stop_cb) {
90 base::AutoLock auto_lock(lock_); 96 base::AutoLock auto_lock(lock_);
91 task_runner_->PostTask(FROM_HERE, base::Bind( 97 task_runner_->PostTask(FROM_HERE, base::Bind(
92 &Pipeline::StopTask, base::Unretained(this), stop_cb)); 98 &Pipeline::StopTask, base::Unretained(this), stop_cb));
93 } 99 }
94 100
95 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { 101 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
96 base::AutoLock auto_lock(lock_); 102 base::AutoLock auto_lock(lock_);
97 if (!running_) { 103 if (!running_) {
98 NOTREACHED() << "Media pipeline isn't running"; 104 NOTREACHED() << "Media pipeline isn't running";
99 return; 105 return;
100 } 106 }
101 107
102 task_runner_->PostTask(FROM_HERE, base::Bind( 108 task_runner_->PostTask(FROM_HERE, base::Bind(
103 &Pipeline::SeekTask, base::Unretained(this), time, seek_cb)); 109 &Pipeline::SeekTask, base::Unretained(this), time, seek_cb));
104 } 110 }
105 111
106 bool Pipeline::IsRunning() const { 112 bool Pipeline::IsRunning() const {
107 base::AutoLock auto_lock(lock_); 113 base::AutoLock auto_lock(lock_);
108 return running_; 114 return running_;
109 } 115 }
110 116
111 bool Pipeline::HasAudio() const {
112 base::AutoLock auto_lock(lock_);
113 return has_audio_;
114 }
115
116 bool Pipeline::HasVideo() const {
117 base::AutoLock auto_lock(lock_);
118 return has_video_;
119 }
120
121 float Pipeline::GetPlaybackRate() const { 117 float Pipeline::GetPlaybackRate() const {
122 base::AutoLock auto_lock(lock_); 118 base::AutoLock auto_lock(lock_);
123 return playback_rate_; 119 return playback_rate_;
124 } 120 }
125 121
126 void Pipeline::SetPlaybackRate(float playback_rate) { 122 void Pipeline::SetPlaybackRate(float playback_rate) {
127 if (playback_rate < 0.0f) 123 if (playback_rate < 0.0f)
128 return; 124 return;
129 125
130 base::AutoLock auto_lock(lock_); 126 base::AutoLock auto_lock(lock_);
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 &Pipeline::AudioDisabledTask, base::Unretained(this))); 322 &Pipeline::AudioDisabledTask, base::Unretained(this)));
327 media_log_->AddEvent( 323 media_log_->AddEvent(
328 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); 324 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED));
329 } 325 }
330 326
331 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { 327 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) {
332 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); 328 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds());
333 DCHECK(IsRunning()); 329 DCHECK(IsRunning());
334 base::AutoLock auto_lock(lock_); 330 base::AutoLock auto_lock(lock_);
335 331
336 if (!has_audio_) 332 if (audio_renderer_ == NULL || audio_disabled_)
337 return; 333 return;
334
338 if (waiting_for_clock_update_ && time < clock_->Elapsed()) 335 if (waiting_for_clock_update_ && time < clock_->Elapsed())
339 return; 336 return;
340 337
341 // TODO(scherkus): |state_| should only be accessed on pipeline thread, see 338 // TODO(scherkus): |state_| should only be accessed on pipeline thread, see
342 // http://crbug.com/137973 339 // http://crbug.com/137973
343 if (state_ == kSeeking) 340 if (state_ == kSeeking)
344 return; 341 return;
345 342
346 clock_->SetTime(time, max_time); 343 clock_->SetTime(time, max_time);
347 StartClockIfWaitingForTimeUpdate_Locked(); 344 StartClockIfWaitingForTimeUpdate_Locked();
348 } 345 }
349 346
350 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { 347 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) {
351 DCHECK(IsRunning()); 348 DCHECK(IsRunning());
352 base::AutoLock auto_lock(lock_); 349 base::AutoLock auto_lock(lock_);
353 350
354 if (has_audio_) 351 if (audio_renderer_ != NULL && !audio_disabled_)
355 return; 352 return;
356 353
357 // TODO(scherkus): |state_| should only be accessed on pipeline thread, see 354 // TODO(scherkus): |state_| should only be accessed on pipeline thread, see
358 // http://crbug.com/137973 355 // http://crbug.com/137973
359 if (state_ == kSeeking) 356 if (state_ == kSeeking)
360 return; 357 return;
361 358
362 DCHECK(!waiting_for_clock_update_); 359 DCHECK(!waiting_for_clock_update_);
363 clock_->SetMaxTime(max_time); 360 clock_->SetMaxTime(max_time);
364 } 361 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 case kInitVideoRenderer: 452 case kInitVideoRenderer:
456 return InitializeVideoRenderer(done_cb); 453 return InitializeVideoRenderer(done_cb);
457 454
458 case kInitPrerolling: 455 case kInitPrerolling:
459 filter_collection_.reset(); 456 filter_collection_.reset();
460 { 457 {
461 base::AutoLock l(lock_); 458 base::AutoLock l(lock_);
462 // We do not want to start the clock running. We only want to set the 459 // We do not want to start the clock running. We only want to set the
463 // base media time so our timestamp calculations will be correct. 460 // base media time so our timestamp calculations will be correct.
464 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); 461 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime());
465
466 // TODO(scherkus): |has_audio_| should be true no matter what --
467 // otherwise people with muted/disabled sound cards will make our
468 // default controls look as if every video doesn't contain an audio
469 // track.
470 has_audio_ = audio_renderer_ != NULL && !audio_disabled_;
471 has_video_ = video_renderer_ != NULL;
472 } 462 }
473 if (!audio_renderer_ && !video_renderer_) { 463 if (!audio_renderer_ && !video_renderer_) {
474 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER); 464 done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER);
475 return; 465 return;
476 } 466 }
477 467
478 buffering_state_cb_.Run(kHaveMetadata); 468 buffering_state_cb_.Run(kHaveMetadata);
479 469
480 return DoInitialPreroll(done_cb); 470 return DoInitialPreroll(done_cb);
481 471
482 case kStarting: 472 case kStarting:
483 return DoPlay(done_cb); 473 return DoPlay(done_cb);
484 474
485 case kStarted: 475 case kStarted:
486 { 476 {
487 base::AutoLock l(lock_); 477 base::AutoLock l(lock_);
488 // We use audio stream to update the clock. So if there is such a 478 // We use audio stream to update the clock. So if there is such a
489 // stream, we pause the clock until we receive a valid timestamp. 479 // stream, we pause the clock until we receive a valid timestamp.
490 waiting_for_clock_update_ = true; 480 waiting_for_clock_update_ = true;
491 if (!has_audio_) { 481 if (audio_renderer_ == NULL || audio_disabled_) {
492 clock_->SetMaxTime(clock_->Duration()); 482 clock_->SetMaxTime(clock_->Duration());
493 StartClockIfWaitingForTimeUpdate_Locked(); 483 StartClockIfWaitingForTimeUpdate_Locked();
494 } 484 }
495 } 485 }
496 486
497 DCHECK(!seek_cb_.is_null()); 487 DCHECK(!seek_cb_.is_null());
498 DCHECK_EQ(status_, PIPELINE_OK); 488 DCHECK_EQ(status_, PIPELINE_OK);
499 489
500 // Fire canplaythrough immediately after playback begins because of 490 // Fire canplaythrough immediately after playback begins because of
501 // crbug.com/106480. 491 // crbug.com/106480.
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 714
725 // Called from any thread. 715 // Called from any thread.
726 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { 716 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) {
727 base::AutoLock auto_lock(lock_); 717 base::AutoLock auto_lock(lock_);
728 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; 718 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded;
729 statistics_.video_bytes_decoded += stats.video_bytes_decoded; 719 statistics_.video_bytes_decoded += stats.video_bytes_decoded;
730 statistics_.video_frames_decoded += stats.video_frames_decoded; 720 statistics_.video_frames_decoded += stats.video_frames_decoded;
731 statistics_.video_frames_dropped += stats.video_frames_dropped; 721 statistics_.video_frames_dropped += stats.video_frames_dropped;
732 } 722 }
733 723
734 void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, 724 void Pipeline::StartTask() {
735 const base::Closure& ended_cb,
736 const PipelineStatusCB& error_cb,
737 const PipelineStatusCB& seek_cb,
738 const BufferingStateCB& buffering_state_cb,
739 const base::Closure& duration_change_cb) {
740 DCHECK(task_runner_->BelongsToCurrentThread()); 725 DCHECK(task_runner_->BelongsToCurrentThread());
741 CHECK_EQ(kCreated, state_) 726 CHECK_EQ(kCreated, state_)
742 << "Media pipeline cannot be started more than once"; 727 << "Media pipeline cannot be started more than once";
743 728
744 filter_collection_ = filter_collection.Pass();
745 ended_cb_ = ended_cb;
746 error_cb_ = error_cb;
747 seek_cb_ = seek_cb;
748 buffering_state_cb_ = buffering_state_cb;
749 duration_change_cb_ = duration_change_cb;
750
751 text_renderer_ = filter_collection_->GetTextRenderer(); 729 text_renderer_ = filter_collection_->GetTextRenderer();
752
753 if (text_renderer_) { 730 if (text_renderer_) {
754 text_renderer_->Initialize( 731 text_renderer_->Initialize(
755 base::Bind(&Pipeline::OnTextRendererEnded, base::Unretained(this))); 732 base::Bind(&Pipeline::OnTextRendererEnded, base::Unretained(this)));
756 } 733 }
757 734
758 StateTransitionTask(PIPELINE_OK); 735 StateTransitionTask(PIPELINE_OK);
759 } 736 }
760 737
761 void Pipeline::StopTask(const base::Closure& stop_cb) { 738 void Pipeline::StopTask(const base::Closure& stop_cb) {
762 DCHECK(task_runner_->BelongsToCurrentThread()); 739 DCHECK(task_runner_->BelongsToCurrentThread());
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 } 895 }
919 896
920 DCHECK_EQ(status_, PIPELINE_OK); 897 DCHECK_EQ(status_, PIPELINE_OK);
921 ended_cb_.Run(); 898 ended_cb_.Run();
922 } 899 }
923 900
924 void Pipeline::AudioDisabledTask() { 901 void Pipeline::AudioDisabledTask() {
925 DCHECK(task_runner_->BelongsToCurrentThread()); 902 DCHECK(task_runner_->BelongsToCurrentThread());
926 903
927 base::AutoLock auto_lock(lock_); 904 base::AutoLock auto_lock(lock_);
928 has_audio_ = false;
929 audio_disabled_ = true; 905 audio_disabled_ = true;
930 906
931 // Notify our demuxer that we're no longer rendering audio. 907 // Notify our demuxer that we're no longer rendering audio.
932 demuxer_->OnAudioRendererDisabled(); 908 demuxer_->OnAudioRendererDisabled();
933 909
934 // Start clock since there is no more audio to trigger clock updates. 910 // Start clock since there is no more audio to trigger clock updates.
935 clock_->SetMaxTime(clock_->Duration()); 911 clock_->SetMaxTime(clock_->Duration());
936 StartClockIfWaitingForTimeUpdate_Locked(); 912 StartClockIfWaitingForTimeUpdate_Locked();
937 } 913 }
938 914
(...skipping 23 matching lines...) Expand all
962 audio_renderer_ = filter_collection_->GetAudioRenderer(); 938 audio_renderer_ = filter_collection_->GetAudioRenderer();
963 audio_renderer_->Initialize( 939 audio_renderer_->Initialize(
964 demuxer_->GetStream(DemuxerStream::AUDIO), 940 demuxer_->GetStream(DemuxerStream::AUDIO),
965 done_cb, 941 done_cb,
966 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), 942 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
967 base::Bind(&Pipeline::OnAudioUnderflow, base::Unretained(this)), 943 base::Bind(&Pipeline::OnAudioUnderflow, base::Unretained(this)),
968 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)), 944 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)),
969 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)), 945 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)),
970 base::Bind(&Pipeline::OnAudioDisabled, base::Unretained(this)), 946 base::Bind(&Pipeline::OnAudioDisabled, base::Unretained(this)),
971 base::Bind(&Pipeline::SetError, base::Unretained(this))); 947 base::Bind(&Pipeline::SetError, base::Unretained(this)));
948
949 if (!has_track_cb_.is_null())
950 has_track_cb_.Run(AUDIO);
972 } 951 }
973 952
974 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) { 953 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) {
975 DCHECK(task_runner_->BelongsToCurrentThread()); 954 DCHECK(task_runner_->BelongsToCurrentThread());
976 955
977 // Get an initial natural size so we have something when we signal 956 // Get an initial natural size so we have something when we signal
978 // the kHaveMetadata buffering state. 957 // the kHaveMetadata buffering state.
979 // 958 //
980 // TODO(acolwell): We have to query demuxer outside of the lock to prevent a 959 // TODO(acolwell): We have to query demuxer outside of the lock to prevent a
981 // deadlock between ChunkDemuxer and Pipeline. See http://crbug.com/334325 for 960 // deadlock between ChunkDemuxer and Pipeline. See http://crbug.com/334325 for
982 // ideas on removing locking from ChunkDemuxer. 961 // ideas on removing locking from ChunkDemuxer.
983 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO); 962 DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
984 gfx::Size initial_natural_size = 963 gfx::Size initial_natural_size =
985 stream->video_decoder_config().natural_size(); 964 stream->video_decoder_config().natural_size();
986 { 965 {
987 base::AutoLock l(lock_); 966 base::AutoLock l(lock_);
988 initial_natural_size_ = initial_natural_size; 967 initial_natural_size_ = initial_natural_size;
989 } 968 }
990 969
991 video_renderer_ = filter_collection_->GetVideoRenderer(); 970 video_renderer_ = filter_collection_->GetVideoRenderer();
992 video_renderer_->Initialize( 971 video_renderer_->Initialize(
993 stream, 972 stream,
994 done_cb, 973 done_cb,
995 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), 974 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
996 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)), 975 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)),
997 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)), 976 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)),
998 base::Bind(&Pipeline::SetError, base::Unretained(this)), 977 base::Bind(&Pipeline::SetError, base::Unretained(this)),
999 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)), 978 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)),
1000 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this))); 979 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this)));
980
981 if (!has_track_cb_.is_null())
982 has_track_cb_.Run(VIDEO);
1001 } 983 }
1002 984
1003 void Pipeline::OnAudioUnderflow() { 985 void Pipeline::OnAudioUnderflow() {
1004 if (!task_runner_->BelongsToCurrentThread()) { 986 if (!task_runner_->BelongsToCurrentThread()) {
1005 task_runner_->PostTask(FROM_HERE, base::Bind( 987 task_runner_->PostTask(FROM_HERE, base::Bind(
1006 &Pipeline::OnAudioUnderflow, base::Unretained(this))); 988 &Pipeline::OnAudioUnderflow, base::Unretained(this)));
1007 return; 989 return;
1008 } 990 }
1009 991
1010 if (state_ != kStarted) 992 if (state_ != kStarted)
1011 return; 993 return;
1012 994
1013 if (audio_renderer_) 995 if (audio_renderer_)
1014 audio_renderer_->ResumeAfterUnderflow(); 996 audio_renderer_->ResumeAfterUnderflow();
1015 } 997 }
1016 998
1017 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 999 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1018 lock_.AssertAcquired(); 1000 lock_.AssertAcquired();
1019 if (!waiting_for_clock_update_) 1001 if (!waiting_for_clock_update_)
1020 return; 1002 return;
1021 1003
1022 waiting_for_clock_update_ = false; 1004 waiting_for_clock_update_ = false;
1023 clock_->Play(); 1005 clock_->Play();
1024 } 1006 }
1025 1007
1026 } // namespace media 1008 } // namespace media
OLDNEW
« content/renderer/media/webmediaplayer_impl.cc ('K') | « media/base/pipeline.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698