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

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

Issue 10854151: Allow transitioning to HAVE_METADATA before pipeline initialization completes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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
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/buffers.h" 20 #include "media/base/buffers.h"
21 #include "media/base/clock.h" 21 #include "media/base/clock.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_decoder_config.h"
25 #include "media/base/video_renderer.h" 26 #include "media/base/video_renderer.h"
26 27
27 using base::TimeDelta; 28 using base::TimeDelta;
28 29
29 namespace media { 30 namespace media {
30 31
31 PipelineStatusNotification::PipelineStatusNotification() 32 PipelineStatusNotification::PipelineStatusNotification()
32 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) { 33 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) {
33 } 34 }
34 35
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 DCHECK(stop_cb_.is_null()); 101 DCHECK(stop_cb_.is_null());
101 DCHECK(!seek_pending_); 102 DCHECK(!seek_pending_);
102 103
103 media_log_->AddEvent( 104 media_log_->AddEvent(
104 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); 105 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED));
105 } 106 }
106 107
107 void Pipeline::Start(scoped_ptr<FilterCollection> collection, 108 void Pipeline::Start(scoped_ptr<FilterCollection> collection,
108 const PipelineStatusCB& ended_cb, 109 const PipelineStatusCB& ended_cb,
109 const PipelineStatusCB& error_cb, 110 const PipelineStatusCB& error_cb,
110 const PipelineStatusCB& start_cb) { 111 const PipelineStatusCB& start_cb,
112 const ReadyStateCB& ready_state_cb) {
111 base::AutoLock auto_lock(lock_); 113 base::AutoLock auto_lock(lock_);
112 CHECK(!running_) << "Media pipeline is already running"; 114 CHECK(!running_) << "Media pipeline is already running";
113 115
114 running_ = true; 116 running_ = true;
115 message_loop_->PostTask(FROM_HERE, base::Bind( 117 message_loop_->PostTask(FROM_HERE, base::Bind(
116 &Pipeline::StartTask, this, base::Passed(&collection), 118 &Pipeline::StartTask, this, base::Passed(&collection),
117 ended_cb, error_cb, start_cb)); 119 ended_cb, error_cb, start_cb, ready_state_cb));
118 } 120 }
119 121
120 void Pipeline::Stop(const base::Closure& stop_cb) { 122 void Pipeline::Stop(const base::Closure& stop_cb) {
121 base::AutoLock auto_lock(lock_); 123 base::AutoLock auto_lock(lock_);
122 message_loop_->PostTask(FROM_HERE, base::Bind( 124 message_loop_->PostTask(FROM_HERE, base::Bind(
123 &Pipeline::StopTask, this, stop_cb)); 125 &Pipeline::StopTask, this, stop_cb));
124 } 126 }
125 127
126 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) { 128 void Pipeline::Seek(TimeDelta time, const PipelineStatusCB& seek_cb) {
127 base::AutoLock auto_lock(lock_); 129 base::AutoLock auto_lock(lock_);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 if (cb.is_null()) 274 if (cb.is_null())
273 return; 275 return;
274 cb.Run(status); 276 cb.Run(status);
275 // Prevent double-reporting of errors to clients. 277 // Prevent double-reporting of errors to clients.
276 if (status != PIPELINE_OK) 278 if (status != PIPELINE_OK)
277 error_cb_.Reset(); 279 error_cb_.Reset();
278 } 280 }
279 281
280 void Pipeline::FinishInitialization() { 282 void Pipeline::FinishInitialization() {
281 DCHECK(message_loop_->BelongsToCurrentThread()); 283 DCHECK(message_loop_->BelongsToCurrentThread());
284 if (!ready_state_cb_.is_null())
285 ready_state_cb_.Run(HaveEnoughData);
scherkus (not reviewing) 2012/08/15 19:53:43 fix indent
acolwell GONE FROM CHROMIUM 2012/08/15 23:21:15 Done.
286
282 // Execute the seek callback, if present. Note that this might be the 287 // Execute the seek callback, if present. Note that this might be the
283 // initial callback passed into Start(). 288 // initial callback passed into Start().
284 ReportStatus(seek_cb_, status_); 289 ReportStatus(seek_cb_, status_);
285 seek_timestamp_ = kNoTimestamp(); 290 seek_timestamp_ = kNoTimestamp();
286 seek_cb_.Reset(); 291 seek_cb_.Reset();
287 } 292 }
288 293
289 // static 294 // static
290 bool Pipeline::TransientState(State state) { 295 bool Pipeline::TransientState(State state) {
291 return state == kPausing || 296 return state == kPausing ||
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 base::AutoLock auto_lock(lock_); 545 base::AutoLock auto_lock(lock_);
541 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; 546 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded;
542 statistics_.video_bytes_decoded += stats.video_bytes_decoded; 547 statistics_.video_bytes_decoded += stats.video_bytes_decoded;
543 statistics_.video_frames_decoded += stats.video_frames_decoded; 548 statistics_.video_frames_decoded += stats.video_frames_decoded;
544 statistics_.video_frames_dropped += stats.video_frames_dropped; 549 statistics_.video_frames_dropped += stats.video_frames_dropped;
545 } 550 }
546 551
547 void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, 552 void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection,
548 const PipelineStatusCB& ended_cb, 553 const PipelineStatusCB& ended_cb,
549 const PipelineStatusCB& error_cb, 554 const PipelineStatusCB& error_cb,
550 const PipelineStatusCB& start_cb) { 555 const PipelineStatusCB& start_cb,
Ami GONE FROM CHROMIUM 2012/08/15 18:00:08 AFAICT start_cb.Run() is always called with OK (el
scherkus (not reviewing) 2012/08/15 19:53:43 start_cb is set as seek_cb, meaning it will get ca
acolwell GONE FROM CHROMIUM 2012/08/15 23:21:15 So I've kept the callback for now, but I've rename
556 const ReadyStateCB& ready_state_cb) {
551 DCHECK(message_loop_->BelongsToCurrentThread()); 557 DCHECK(message_loop_->BelongsToCurrentThread());
552 DCHECK_EQ(kCreated, state_); 558 DCHECK_EQ(kCreated, state_);
553 filter_collection_ = filter_collection.Pass(); 559 filter_collection_ = filter_collection.Pass();
554 ended_cb_ = ended_cb; 560 ended_cb_ = ended_cb;
555 error_cb_ = error_cb; 561 error_cb_ = error_cb;
556 seek_cb_ = start_cb; 562 seek_cb_ = start_cb;
563 ready_state_cb_ = ready_state_cb;
557 564
558 // Kick off initialization. 565 // Kick off initialization.
559 pipeline_init_state_.reset(new PipelineInitState()); 566 pipeline_init_state_.reset(new PipelineInitState());
560 567
561 SetState(kInitDemuxer); 568 SetState(kInitDemuxer);
562 InitializeDemuxer(); 569 InitializeDemuxer();
563 } 570 }
564 571
565 // Main initialization method called on the pipeline thread. This code attempts 572 // Main initialization method called on the pipeline thread. This code attempts
566 // to use the specified filter factory to build a pipeline. 573 // to use the specified filter factory to build a pipeline.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) { 619 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) {
613 base::AutoLock auto_lock(lock_); 620 base::AutoLock auto_lock(lock_);
614 has_audio_ = true; 621 has_audio_ = true;
615 return; 622 return;
616 } 623 }
617 } 624 }
618 625
619 // Assuming audio renderer was created, create video renderer. 626 // Assuming audio renderer was created, create video renderer.
620 if (state_ == kInitAudioRenderer) { 627 if (state_ == kInitAudioRenderer) {
621 SetState(kInitVideoRenderer); 628 SetState(kInitVideoRenderer);
622 if (InitializeVideoRenderer(demuxer_->GetStream(DemuxerStream::VIDEO))) { 629 scoped_refptr<DemuxerStream> video_stream =
630 demuxer_->GetStream(DemuxerStream::VIDEO);
631 if (InitializeVideoRenderer(video_stream)) {
623 base::AutoLock auto_lock(lock_); 632 base::AutoLock auto_lock(lock_);
624 has_video_ = true; 633 has_video_ = true;
634
635 // Get an initial natural size so we have something when we signal
636 // the HaveMetadata ready state.
637 natural_size_ = video_stream->video_decoder_config().natural_size();
625 return; 638 return;
626 } 639 }
627 } 640 }
628 641
629 if (state_ == kInitVideoRenderer) { 642 if (state_ == kInitVideoRenderer) {
630 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { 643 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) {
631 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); 644 SetError(PIPELINE_ERROR_COULD_NOT_RENDER);
632 return; 645 return;
633 } 646 }
634 647
635 // Clear initialization state now that we're done. 648 // Clear initialization state now that we're done.
636 filter_collection_.reset(); 649 filter_collection_.reset();
637 pipeline_init_state_.reset(); 650 pipeline_init_state_.reset();
638 651
639 // Initialization was successful, we are now considered paused, so it's safe 652 // Initialization was successful, we are now considered paused, so it's safe
640 // to set the initial playback rate and volume. 653 // to set the initial playback rate and volume.
641 PlaybackRateChangedTask(GetPlaybackRate()); 654 PlaybackRateChangedTask(GetPlaybackRate());
642 VolumeChangedTask(GetVolume()); 655 VolumeChangedTask(GetVolume());
643 656
657 if (!ready_state_cb_.is_null())
658 ready_state_cb_.Run(HaveMetadata);
659
644 // Fire a seek request to get the renderers to preroll. We can skip a seek 660 // Fire a seek request to get the renderers to preroll. We can skip a seek
645 // here as the demuxer should be at the start of the stream. 661 // here as the demuxer should be at the start of the stream.
646 seek_pending_ = true; 662 seek_pending_ = true;
647 SetState(kSeeking); 663 SetState(kSeeking);
648 seek_timestamp_ = demuxer_->GetStartTime(); 664 seek_timestamp_ = demuxer_->GetStartTime();
649 DoSeek(seek_timestamp_, true, 665 DoSeek(seek_timestamp_, true,
650 base::Bind(&Pipeline::OnFilterStateTransition, this)); 666 base::Bind(&Pipeline::OnFilterStateTransition, this));
651 } 667 }
652 } 668 }
653 669
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1226 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1211 lock_.AssertAcquired(); 1227 lock_.AssertAcquired();
1212 if (!waiting_for_clock_update_) 1228 if (!waiting_for_clock_update_)
1213 return; 1229 return;
1214 1230
1215 waiting_for_clock_update_ = false; 1231 waiting_for_clock_update_ = false;
1216 clock_->Play(); 1232 clock_->Play();
1217 } 1233 }
1218 1234
1219 } // namespace media 1235 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698