| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, | 5 // TODO(scherkus): clean up PipelineImpl... too many crazy function names, |
| 6 // potential deadlocks, etc... | 6 // potential deadlocks, etc... |
| 7 | 7 |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 PipelineImpl::PipelineImpl(MessageLoop* message_loop) | 28 PipelineImpl::PipelineImpl(MessageLoop* message_loop) |
| 29 : message_loop_(message_loop), | 29 : message_loop_(message_loop), |
| 30 clock_(new ClockImpl(&base::Time::Now)), | 30 clock_(new ClockImpl(&base::Time::Now)), |
| 31 waiting_for_clock_update_(false), | 31 waiting_for_clock_update_(false), |
| 32 state_(kCreated), | 32 state_(kCreated), |
| 33 current_bytes_(0) { | 33 current_bytes_(0) { |
| 34 ResetState(); | 34 ResetState(); |
| 35 } | 35 } |
| 36 | 36 |
| 37 PipelineImpl::~PipelineImpl() { | 37 PipelineImpl::~PipelineImpl() { |
| 38 AutoLock auto_lock(lock_); | 38 base::AutoLock auto_lock(lock_); |
| 39 DCHECK(!running_) << "Stop() must complete before destroying object"; | 39 DCHECK(!running_) << "Stop() must complete before destroying object"; |
| 40 DCHECK(!stop_pending_); | 40 DCHECK(!stop_pending_); |
| 41 DCHECK(!seek_pending_); | 41 DCHECK(!seek_pending_); |
| 42 } | 42 } |
| 43 | 43 |
| 44 void PipelineImpl::Init(PipelineCallback* ended_callback, | 44 void PipelineImpl::Init(PipelineCallback* ended_callback, |
| 45 PipelineCallback* error_callback, | 45 PipelineCallback* error_callback, |
| 46 PipelineCallback* network_callback) { | 46 PipelineCallback* network_callback) { |
| 47 DCHECK(!IsRunning()) | 47 DCHECK(!IsRunning()) |
| 48 << "Init() should be called before the pipeline has started"; | 48 << "Init() should be called before the pipeline has started"; |
| 49 ended_callback_.reset(ended_callback); | 49 ended_callback_.reset(ended_callback); |
| 50 error_callback_.reset(error_callback); | 50 error_callback_.reset(error_callback); |
| 51 network_callback_.reset(network_callback); | 51 network_callback_.reset(network_callback); |
| 52 } | 52 } |
| 53 | 53 |
| 54 // Creates the PipelineInternal and calls it's start method. | 54 // Creates the PipelineInternal and calls it's start method. |
| 55 bool PipelineImpl::Start(FilterCollection* collection, | 55 bool PipelineImpl::Start(FilterCollection* collection, |
| 56 const std::string& url, | 56 const std::string& url, |
| 57 PipelineCallback* start_callback) { | 57 PipelineCallback* start_callback) { |
| 58 AutoLock auto_lock(lock_); | 58 base::AutoLock auto_lock(lock_); |
| 59 scoped_ptr<PipelineCallback> callback(start_callback); | 59 scoped_ptr<PipelineCallback> callback(start_callback); |
| 60 scoped_ptr<FilterCollection> filter_collection(collection); | 60 scoped_ptr<FilterCollection> filter_collection(collection); |
| 61 | 61 |
| 62 if (running_) { | 62 if (running_) { |
| 63 VLOG(1) << "Media pipeline is already running"; | 63 VLOG(1) << "Media pipeline is already running"; |
| 64 return false; | 64 return false; |
| 65 } | 65 } |
| 66 | 66 |
| 67 if (collection->IsEmpty()) { | 67 if (collection->IsEmpty()) { |
| 68 return false; | 68 return false; |
| 69 } | 69 } |
| 70 | 70 |
| 71 // Kick off initialization! | 71 // Kick off initialization! |
| 72 running_ = true; | 72 running_ = true; |
| 73 message_loop_->PostTask( | 73 message_loop_->PostTask( |
| 74 FROM_HERE, | 74 FROM_HERE, |
| 75 NewRunnableMethod(this, | 75 NewRunnableMethod(this, |
| 76 &PipelineImpl::StartTask, | 76 &PipelineImpl::StartTask, |
| 77 filter_collection.release(), | 77 filter_collection.release(), |
| 78 url, | 78 url, |
| 79 callback.release())); | 79 callback.release())); |
| 80 return true; | 80 return true; |
| 81 } | 81 } |
| 82 | 82 |
| 83 void PipelineImpl::Stop(PipelineCallback* stop_callback) { | 83 void PipelineImpl::Stop(PipelineCallback* stop_callback) { |
| 84 AutoLock auto_lock(lock_); | 84 base::AutoLock auto_lock(lock_); |
| 85 scoped_ptr<PipelineCallback> callback(stop_callback); | 85 scoped_ptr<PipelineCallback> callback(stop_callback); |
| 86 if (!running_) { | 86 if (!running_) { |
| 87 VLOG(1) << "Media pipeline has already stopped"; | 87 VLOG(1) << "Media pipeline has already stopped"; |
| 88 return; | 88 return; |
| 89 } | 89 } |
| 90 | 90 |
| 91 // Stop the pipeline, which will set |running_| to false on behalf. | 91 // Stop the pipeline, which will set |running_| to false on behalf. |
| 92 message_loop_->PostTask(FROM_HERE, | 92 message_loop_->PostTask(FROM_HERE, |
| 93 NewRunnableMethod(this, &PipelineImpl::StopTask, callback.release())); | 93 NewRunnableMethod(this, &PipelineImpl::StopTask, callback.release())); |
| 94 } | 94 } |
| 95 | 95 |
| 96 void PipelineImpl::Seek(base::TimeDelta time, | 96 void PipelineImpl::Seek(base::TimeDelta time, |
| 97 PipelineCallback* seek_callback) { | 97 PipelineCallback* seek_callback) { |
| 98 AutoLock auto_lock(lock_); | 98 base::AutoLock auto_lock(lock_); |
| 99 scoped_ptr<PipelineCallback> callback(seek_callback); | 99 scoped_ptr<PipelineCallback> callback(seek_callback); |
| 100 if (!running_) { | 100 if (!running_) { |
| 101 VLOG(1) << "Media pipeline must be running"; | 101 VLOG(1) << "Media pipeline must be running"; |
| 102 return; | 102 return; |
| 103 } | 103 } |
| 104 | 104 |
| 105 message_loop_->PostTask(FROM_HERE, | 105 message_loop_->PostTask(FROM_HERE, |
| 106 NewRunnableMethod(this, &PipelineImpl::SeekTask, time, | 106 NewRunnableMethod(this, &PipelineImpl::SeekTask, time, |
| 107 callback.release())); | 107 callback.release())); |
| 108 } | 108 } |
| 109 | 109 |
| 110 bool PipelineImpl::IsRunning() const { | 110 bool PipelineImpl::IsRunning() const { |
| 111 AutoLock auto_lock(lock_); | 111 base::AutoLock auto_lock(lock_); |
| 112 return running_; | 112 return running_; |
| 113 } | 113 } |
| 114 | 114 |
| 115 bool PipelineImpl::IsInitialized() const { | 115 bool PipelineImpl::IsInitialized() const { |
| 116 // TODO(scherkus): perhaps replace this with a bool that is set/get under the | 116 // TODO(scherkus): perhaps replace this with a bool that is set/get under the |
| 117 // lock, because this is breaching the contract that |state_| is only accessed | 117 // lock, because this is breaching the contract that |state_| is only accessed |
| 118 // on |message_loop_|. | 118 // on |message_loop_|. |
| 119 AutoLock auto_lock(lock_); | 119 base::AutoLock auto_lock(lock_); |
| 120 switch (state_) { | 120 switch (state_) { |
| 121 case kPausing: | 121 case kPausing: |
| 122 case kFlushing: | 122 case kFlushing: |
| 123 case kSeeking: | 123 case kSeeking: |
| 124 case kStarting: | 124 case kStarting: |
| 125 case kStarted: | 125 case kStarted: |
| 126 case kEnded: | 126 case kEnded: |
| 127 return true; | 127 return true; |
| 128 default: | 128 default: |
| 129 return false; | 129 return false; |
| 130 } | 130 } |
| 131 } | 131 } |
| 132 | 132 |
| 133 bool PipelineImpl::IsNetworkActive() const { | 133 bool PipelineImpl::IsNetworkActive() const { |
| 134 AutoLock auto_lock(lock_); | 134 base::AutoLock auto_lock(lock_); |
| 135 return network_activity_; | 135 return network_activity_; |
| 136 } | 136 } |
| 137 | 137 |
| 138 bool PipelineImpl::IsRendered(const std::string& major_mime_type) const { | 138 bool PipelineImpl::IsRendered(const std::string& major_mime_type) const { |
| 139 AutoLock auto_lock(lock_); | 139 base::AutoLock auto_lock(lock_); |
| 140 bool is_rendered = (rendered_mime_types_.find(major_mime_type) != | 140 bool is_rendered = (rendered_mime_types_.find(major_mime_type) != |
| 141 rendered_mime_types_.end()); | 141 rendered_mime_types_.end()); |
| 142 return is_rendered; | 142 return is_rendered; |
| 143 } | 143 } |
| 144 | 144 |
| 145 float PipelineImpl::GetPlaybackRate() const { | 145 float PipelineImpl::GetPlaybackRate() const { |
| 146 AutoLock auto_lock(lock_); | 146 base::AutoLock auto_lock(lock_); |
| 147 return playback_rate_; | 147 return playback_rate_; |
| 148 } | 148 } |
| 149 | 149 |
| 150 void PipelineImpl::SetPlaybackRate(float playback_rate) { | 150 void PipelineImpl::SetPlaybackRate(float playback_rate) { |
| 151 if (playback_rate < 0.0f) { | 151 if (playback_rate < 0.0f) { |
| 152 return; | 152 return; |
| 153 } | 153 } |
| 154 | 154 |
| 155 AutoLock auto_lock(lock_); | 155 base::AutoLock auto_lock(lock_); |
| 156 playback_rate_ = playback_rate; | 156 playback_rate_ = playback_rate; |
| 157 if (running_) { | 157 if (running_) { |
| 158 message_loop_->PostTask(FROM_HERE, | 158 message_loop_->PostTask(FROM_HERE, |
| 159 NewRunnableMethod(this, &PipelineImpl::PlaybackRateChangedTask, | 159 NewRunnableMethod(this, &PipelineImpl::PlaybackRateChangedTask, |
| 160 playback_rate)); | 160 playback_rate)); |
| 161 } | 161 } |
| 162 } | 162 } |
| 163 | 163 |
| 164 float PipelineImpl::GetVolume() const { | 164 float PipelineImpl::GetVolume() const { |
| 165 AutoLock auto_lock(lock_); | 165 base::AutoLock auto_lock(lock_); |
| 166 return volume_; | 166 return volume_; |
| 167 } | 167 } |
| 168 | 168 |
| 169 void PipelineImpl::SetVolume(float volume) { | 169 void PipelineImpl::SetVolume(float volume) { |
| 170 if (volume < 0.0f || volume > 1.0f) { | 170 if (volume < 0.0f || volume > 1.0f) { |
| 171 return; | 171 return; |
| 172 } | 172 } |
| 173 | 173 |
| 174 AutoLock auto_lock(lock_); | 174 base::AutoLock auto_lock(lock_); |
| 175 volume_ = volume; | 175 volume_ = volume; |
| 176 if (running_) { | 176 if (running_) { |
| 177 message_loop_->PostTask(FROM_HERE, | 177 message_loop_->PostTask(FROM_HERE, |
| 178 NewRunnableMethod(this, &PipelineImpl::VolumeChangedTask, | 178 NewRunnableMethod(this, &PipelineImpl::VolumeChangedTask, |
| 179 volume)); | 179 volume)); |
| 180 } | 180 } |
| 181 } | 181 } |
| 182 | 182 |
| 183 base::TimeDelta PipelineImpl::GetCurrentTime() const { | 183 base::TimeDelta PipelineImpl::GetCurrentTime() const { |
| 184 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that | 184 // TODO(scherkus): perhaps replace checking state_ == kEnded with a bool that |
| 185 // is set/get under the lock, because this is breaching the contract that | 185 // is set/get under the lock, because this is breaching the contract that |
| 186 // |state_| is only accessed on |message_loop_|. | 186 // |state_| is only accessed on |message_loop_|. |
| 187 AutoLock auto_lock(lock_); | 187 base::AutoLock auto_lock(lock_); |
| 188 return GetCurrentTime_Locked(); | 188 return GetCurrentTime_Locked(); |
| 189 } | 189 } |
| 190 | 190 |
| 191 base::TimeDelta PipelineImpl::GetCurrentTime_Locked() const { | 191 base::TimeDelta PipelineImpl::GetCurrentTime_Locked() const { |
| 192 base::TimeDelta elapsed = clock_->Elapsed(); | 192 base::TimeDelta elapsed = clock_->Elapsed(); |
| 193 if (state_ == kEnded || elapsed > duration_) { | 193 if (state_ == kEnded || elapsed > duration_) { |
| 194 return duration_; | 194 return duration_; |
| 195 } | 195 } |
| 196 return elapsed; | 196 return elapsed; |
| 197 } | 197 } |
| 198 | 198 |
| 199 base::TimeDelta PipelineImpl::GetBufferedTime() { | 199 base::TimeDelta PipelineImpl::GetBufferedTime() { |
| 200 AutoLock auto_lock(lock_); | 200 base::AutoLock auto_lock(lock_); |
| 201 | 201 |
| 202 // If media is fully loaded, then return duration. | 202 // If media is fully loaded, then return duration. |
| 203 if (loaded_ || total_bytes_ == buffered_bytes_) { | 203 if (loaded_ || total_bytes_ == buffered_bytes_) { |
| 204 max_buffered_time_ = duration_; | 204 max_buffered_time_ = duration_; |
| 205 return duration_; | 205 return duration_; |
| 206 } | 206 } |
| 207 | 207 |
| 208 base::TimeDelta current_time = GetCurrentTime_Locked(); | 208 base::TimeDelta current_time = GetCurrentTime_Locked(); |
| 209 | 209 |
| 210 // If buffered time was set, we report that value directly. | 210 // If buffered time was set, we report that value directly. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 230 // Make sure buffered_time is at least the current time | 230 // Make sure buffered_time is at least the current time |
| 231 buffered_time = std::max(buffered_time, current_time); | 231 buffered_time = std::max(buffered_time, current_time); |
| 232 | 232 |
| 233 // Only print the max buffered time for smooth buffering. | 233 // Only print the max buffered time for smooth buffering. |
| 234 max_buffered_time_ = std::max(buffered_time, max_buffered_time_); | 234 max_buffered_time_ = std::max(buffered_time, max_buffered_time_); |
| 235 | 235 |
| 236 return max_buffered_time_; | 236 return max_buffered_time_; |
| 237 } | 237 } |
| 238 | 238 |
| 239 base::TimeDelta PipelineImpl::GetMediaDuration() const { | 239 base::TimeDelta PipelineImpl::GetMediaDuration() const { |
| 240 AutoLock auto_lock(lock_); | 240 base::AutoLock auto_lock(lock_); |
| 241 return duration_; | 241 return duration_; |
| 242 } | 242 } |
| 243 | 243 |
| 244 int64 PipelineImpl::GetBufferedBytes() const { | 244 int64 PipelineImpl::GetBufferedBytes() const { |
| 245 AutoLock auto_lock(lock_); | 245 base::AutoLock auto_lock(lock_); |
| 246 return buffered_bytes_; | 246 return buffered_bytes_; |
| 247 } | 247 } |
| 248 | 248 |
| 249 int64 PipelineImpl::GetTotalBytes() const { | 249 int64 PipelineImpl::GetTotalBytes() const { |
| 250 AutoLock auto_lock(lock_); | 250 base::AutoLock auto_lock(lock_); |
| 251 return total_bytes_; | 251 return total_bytes_; |
| 252 } | 252 } |
| 253 | 253 |
| 254 void PipelineImpl::GetVideoSize(size_t* width_out, size_t* height_out) const { | 254 void PipelineImpl::GetVideoSize(size_t* width_out, size_t* height_out) const { |
| 255 CHECK(width_out); | 255 CHECK(width_out); |
| 256 CHECK(height_out); | 256 CHECK(height_out); |
| 257 AutoLock auto_lock(lock_); | 257 base::AutoLock auto_lock(lock_); |
| 258 *width_out = video_width_; | 258 *width_out = video_width_; |
| 259 *height_out = video_height_; | 259 *height_out = video_height_; |
| 260 } | 260 } |
| 261 | 261 |
| 262 bool PipelineImpl::IsStreaming() const { | 262 bool PipelineImpl::IsStreaming() const { |
| 263 AutoLock auto_lock(lock_); | 263 base::AutoLock auto_lock(lock_); |
| 264 return streaming_; | 264 return streaming_; |
| 265 } | 265 } |
| 266 | 266 |
| 267 bool PipelineImpl::IsLoaded() const { | 267 bool PipelineImpl::IsLoaded() const { |
| 268 AutoLock auto_lock(lock_); | 268 base::AutoLock auto_lock(lock_); |
| 269 return loaded_; | 269 return loaded_; |
| 270 } | 270 } |
| 271 | 271 |
| 272 PipelineError PipelineImpl::GetError() const { | 272 PipelineError PipelineImpl::GetError() const { |
| 273 AutoLock auto_lock(lock_); | 273 base::AutoLock auto_lock(lock_); |
| 274 return error_; | 274 return error_; |
| 275 } | 275 } |
| 276 | 276 |
| 277 void PipelineImpl::SetCurrentReadPosition(int64 offset) { | 277 void PipelineImpl::SetCurrentReadPosition(int64 offset) { |
| 278 AutoLock auto_lock(lock_); | 278 base::AutoLock auto_lock(lock_); |
| 279 | 279 |
| 280 // The current read position should never be ahead of the buffered byte | 280 // The current read position should never be ahead of the buffered byte |
| 281 // position but threading issues between BufferedDataSource::DoneRead_Locked() | 281 // position but threading issues between BufferedDataSource::DoneRead_Locked() |
| 282 // and BufferedDataSource::NetworkEventCallback() can cause them to be | 282 // and BufferedDataSource::NetworkEventCallback() can cause them to be |
| 283 // temporarily out of sync. The easiest fix for this is to cap both | 283 // temporarily out of sync. The easiest fix for this is to cap both |
| 284 // buffered_bytes_ and current_bytes_ to always be legal values in | 284 // buffered_bytes_ and current_bytes_ to always be legal values in |
| 285 // SetCurrentReadPosition() and in SetBufferedBytes(). | 285 // SetCurrentReadPosition() and in SetBufferedBytes(). |
| 286 if (offset > buffered_bytes_) | 286 if (offset > buffered_bytes_) |
| 287 buffered_bytes_ = offset; | 287 buffered_bytes_ = offset; |
| 288 current_bytes_ = offset; | 288 current_bytes_ = offset; |
| 289 } | 289 } |
| 290 | 290 |
| 291 int64 PipelineImpl::GetCurrentReadPosition() { | 291 int64 PipelineImpl::GetCurrentReadPosition() { |
| 292 AutoLock auto_lock(lock_); | 292 base::AutoLock auto_lock(lock_); |
| 293 return current_bytes_; | 293 return current_bytes_; |
| 294 } | 294 } |
| 295 | 295 |
| 296 void PipelineImpl::ResetState() { | 296 void PipelineImpl::ResetState() { |
| 297 AutoLock auto_lock(lock_); | 297 base::AutoLock auto_lock(lock_); |
| 298 const base::TimeDelta kZero; | 298 const base::TimeDelta kZero; |
| 299 running_ = false; | 299 running_ = false; |
| 300 stop_pending_ = false; | 300 stop_pending_ = false; |
| 301 seek_pending_ = false; | 301 seek_pending_ = false; |
| 302 tearing_down_ = false; | 302 tearing_down_ = false; |
| 303 duration_ = kZero; | 303 duration_ = kZero; |
| 304 buffered_time_ = kZero; | 304 buffered_time_ = kZero; |
| 305 buffered_bytes_ = 0; | 305 buffered_bytes_ = 0; |
| 306 streaming_ = false; | 306 streaming_ = false; |
| 307 loaded_ = false; | 307 loaded_ = false; |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 return GetCurrentTime(); | 413 return GetCurrentTime(); |
| 414 } | 414 } |
| 415 | 415 |
| 416 base::TimeDelta PipelineImpl::GetDuration() const { | 416 base::TimeDelta PipelineImpl::GetDuration() const { |
| 417 DCHECK(IsRunning()); | 417 DCHECK(IsRunning()); |
| 418 return GetMediaDuration(); | 418 return GetMediaDuration(); |
| 419 } | 419 } |
| 420 | 420 |
| 421 void PipelineImpl::SetTime(base::TimeDelta time) { | 421 void PipelineImpl::SetTime(base::TimeDelta time) { |
| 422 DCHECK(IsRunning()); | 422 DCHECK(IsRunning()); |
| 423 AutoLock auto_lock(lock_); | 423 base::AutoLock auto_lock(lock_); |
| 424 | 424 |
| 425 // If we were waiting for a valid timestamp and such timestamp arrives, we | 425 // If we were waiting for a valid timestamp and such timestamp arrives, we |
| 426 // need to clear the flag for waiting and start the clock. | 426 // need to clear the flag for waiting and start the clock. |
| 427 if (waiting_for_clock_update_) { | 427 if (waiting_for_clock_update_) { |
| 428 if (time < clock_->Elapsed()) | 428 if (time < clock_->Elapsed()) |
| 429 return; | 429 return; |
| 430 waiting_for_clock_update_ = false; | 430 waiting_for_clock_update_ = false; |
| 431 clock_->SetTime(time); | 431 clock_->SetTime(time); |
| 432 clock_->Play(); | 432 clock_->Play(); |
| 433 return; | 433 return; |
| 434 } | 434 } |
| 435 clock_->SetTime(time); | 435 clock_->SetTime(time); |
| 436 } | 436 } |
| 437 | 437 |
| 438 void PipelineImpl::SetDuration(base::TimeDelta duration) { | 438 void PipelineImpl::SetDuration(base::TimeDelta duration) { |
| 439 DCHECK(IsRunning()); | 439 DCHECK(IsRunning()); |
| 440 AutoLock auto_lock(lock_); | 440 base::AutoLock auto_lock(lock_); |
| 441 duration_ = duration; | 441 duration_ = duration; |
| 442 } | 442 } |
| 443 | 443 |
| 444 void PipelineImpl::SetBufferedTime(base::TimeDelta buffered_time) { | 444 void PipelineImpl::SetBufferedTime(base::TimeDelta buffered_time) { |
| 445 DCHECK(IsRunning()); | 445 DCHECK(IsRunning()); |
| 446 AutoLock auto_lock(lock_); | 446 base::AutoLock auto_lock(lock_); |
| 447 buffered_time_ = buffered_time; | 447 buffered_time_ = buffered_time; |
| 448 } | 448 } |
| 449 | 449 |
| 450 void PipelineImpl::SetTotalBytes(int64 total_bytes) { | 450 void PipelineImpl::SetTotalBytes(int64 total_bytes) { |
| 451 DCHECK(IsRunning()); | 451 DCHECK(IsRunning()); |
| 452 AutoLock auto_lock(lock_); | 452 base::AutoLock auto_lock(lock_); |
| 453 total_bytes_ = total_bytes; | 453 total_bytes_ = total_bytes; |
| 454 } | 454 } |
| 455 | 455 |
| 456 void PipelineImpl::SetBufferedBytes(int64 buffered_bytes) { | 456 void PipelineImpl::SetBufferedBytes(int64 buffered_bytes) { |
| 457 DCHECK(IsRunning()); | 457 DCHECK(IsRunning()); |
| 458 AutoLock auto_lock(lock_); | 458 base::AutoLock auto_lock(lock_); |
| 459 | 459 |
| 460 // See comments in SetCurrentReadPosition() about capping. | 460 // See comments in SetCurrentReadPosition() about capping. |
| 461 if (buffered_bytes < current_bytes_) | 461 if (buffered_bytes < current_bytes_) |
| 462 current_bytes_ = buffered_bytes; | 462 current_bytes_ = buffered_bytes; |
| 463 buffered_bytes_ = buffered_bytes; | 463 buffered_bytes_ = buffered_bytes; |
| 464 } | 464 } |
| 465 | 465 |
| 466 void PipelineImpl::SetVideoSize(size_t width, size_t height) { | 466 void PipelineImpl::SetVideoSize(size_t width, size_t height) { |
| 467 DCHECK(IsRunning()); | 467 DCHECK(IsRunning()); |
| 468 AutoLock auto_lock(lock_); | 468 base::AutoLock auto_lock(lock_); |
| 469 video_width_ = width; | 469 video_width_ = width; |
| 470 video_height_ = height; | 470 video_height_ = height; |
| 471 } | 471 } |
| 472 | 472 |
| 473 void PipelineImpl::SetStreaming(bool streaming) { | 473 void PipelineImpl::SetStreaming(bool streaming) { |
| 474 DCHECK(IsRunning()); | 474 DCHECK(IsRunning()); |
| 475 AutoLock auto_lock(lock_); | 475 base::AutoLock auto_lock(lock_); |
| 476 streaming_ = streaming; | 476 streaming_ = streaming; |
| 477 } | 477 } |
| 478 | 478 |
| 479 void PipelineImpl::NotifyEnded() { | 479 void PipelineImpl::NotifyEnded() { |
| 480 DCHECK(IsRunning()); | 480 DCHECK(IsRunning()); |
| 481 message_loop_->PostTask(FROM_HERE, | 481 message_loop_->PostTask(FROM_HERE, |
| 482 NewRunnableMethod(this, &PipelineImpl::NotifyEndedTask)); | 482 NewRunnableMethod(this, &PipelineImpl::NotifyEndedTask)); |
| 483 } | 483 } |
| 484 | 484 |
| 485 void PipelineImpl::SetLoaded(bool loaded) { | 485 void PipelineImpl::SetLoaded(bool loaded) { |
| 486 DCHECK(IsRunning()); | 486 DCHECK(IsRunning()); |
| 487 AutoLock auto_lock(lock_); | 487 base::AutoLock auto_lock(lock_); |
| 488 loaded_ = loaded; | 488 loaded_ = loaded; |
| 489 } | 489 } |
| 490 | 490 |
| 491 void PipelineImpl::SetNetworkActivity(bool network_activity) { | 491 void PipelineImpl::SetNetworkActivity(bool network_activity) { |
| 492 DCHECK(IsRunning()); | 492 DCHECK(IsRunning()); |
| 493 { | 493 { |
| 494 AutoLock auto_lock(lock_); | 494 base::AutoLock auto_lock(lock_); |
| 495 network_activity_ = network_activity; | 495 network_activity_ = network_activity; |
| 496 } | 496 } |
| 497 message_loop_->PostTask(FROM_HERE, | 497 message_loop_->PostTask(FROM_HERE, |
| 498 NewRunnableMethod(this, &PipelineImpl::NotifyNetworkEventTask)); | 498 NewRunnableMethod(this, &PipelineImpl::NotifyNetworkEventTask)); |
| 499 } | 499 } |
| 500 | 500 |
| 501 void PipelineImpl::DisableAudioRenderer() { | 501 void PipelineImpl::DisableAudioRenderer() { |
| 502 DCHECK(IsRunning()); | 502 DCHECK(IsRunning()); |
| 503 | 503 |
| 504 // Disable renderer on the message loop. | 504 // Disable renderer on the message loop. |
| 505 message_loop_->PostTask(FROM_HERE, | 505 message_loop_->PostTask(FROM_HERE, |
| 506 NewRunnableMethod(this, &PipelineImpl::DisableAudioRendererTask)); | 506 NewRunnableMethod(this, &PipelineImpl::DisableAudioRendererTask)); |
| 507 } | 507 } |
| 508 | 508 |
| 509 void PipelineImpl::InsertRenderedMimeType(const std::string& major_mime_type) { | 509 void PipelineImpl::InsertRenderedMimeType(const std::string& major_mime_type) { |
| 510 DCHECK(IsRunning()); | 510 DCHECK(IsRunning()); |
| 511 AutoLock auto_lock(lock_); | 511 base::AutoLock auto_lock(lock_); |
| 512 rendered_mime_types_.insert(major_mime_type); | 512 rendered_mime_types_.insert(major_mime_type); |
| 513 } | 513 } |
| 514 | 514 |
| 515 bool PipelineImpl::HasRenderedMimeTypes() const { | 515 bool PipelineImpl::HasRenderedMimeTypes() const { |
| 516 DCHECK(IsRunning()); | 516 DCHECK(IsRunning()); |
| 517 AutoLock auto_lock(lock_); | 517 base::AutoLock auto_lock(lock_); |
| 518 return !rendered_mime_types_.empty(); | 518 return !rendered_mime_types_.empty(); |
| 519 } | 519 } |
| 520 | 520 |
| 521 // Called from any thread. | 521 // Called from any thread. |
| 522 void PipelineImpl::OnFilterInitialize() { | 522 void PipelineImpl::OnFilterInitialize() { |
| 523 // Continue the initialize task by proceeding to the next stage. | 523 // Continue the initialize task by proceeding to the next stage. |
| 524 message_loop_->PostTask(FROM_HERE, | 524 message_loop_->PostTask(FROM_HERE, |
| 525 NewRunnableMethod(this, &PipelineImpl::InitializeTask)); | 525 NewRunnableMethod(this, &PipelineImpl::InitializeTask)); |
| 526 } | 526 } |
| 527 | 527 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 PipelineError error = GetError(); | 673 PipelineError error = GetError(); |
| 674 | 674 |
| 675 if (state_ == kStopped || (IsPipelineStopPending() && error == PIPELINE_OK)) { | 675 if (state_ == kStopped || (IsPipelineStopPending() && error == PIPELINE_OK)) { |
| 676 // If we are already stopped or stopping normally, return immediately. | 676 // If we are already stopped or stopping normally, return immediately. |
| 677 delete stop_callback; | 677 delete stop_callback; |
| 678 return; | 678 return; |
| 679 } else if (state_ == kError || | 679 } else if (state_ == kError || |
| 680 (IsPipelineStopPending() && error != PIPELINE_OK)) { | 680 (IsPipelineStopPending() && error != PIPELINE_OK)) { |
| 681 // If we are stopping due to SetError(), stop normally instead of | 681 // If we are stopping due to SetError(), stop normally instead of |
| 682 // going to error state. | 682 // going to error state. |
| 683 AutoLock auto_lock(lock_); | 683 base::AutoLock auto_lock(lock_); |
| 684 error_ = PIPELINE_OK; | 684 error_ = PIPELINE_OK; |
| 685 } | 685 } |
| 686 | 686 |
| 687 stop_callback_.reset(stop_callback); | 687 stop_callback_.reset(stop_callback); |
| 688 | 688 |
| 689 stop_pending_ = true; | 689 stop_pending_ = true; |
| 690 if (!IsPipelineSeeking()) { | 690 if (!IsPipelineSeeking()) { |
| 691 // We will tear down pipeline immediately when there is no seek operation | 691 // We will tear down pipeline immediately when there is no seek operation |
| 692 // pending. This should include the case where we are partially initialized. | 692 // pending. This should include the case where we are partially initialized. |
| 693 // Ideally this case should use SetError() rather than Stop() to tear down. | 693 // Ideally this case should use SetError() rather than Stop() to tear down. |
| 694 DCHECK(!IsPipelineTearingDown()); | 694 DCHECK(!IsPipelineTearingDown()); |
| 695 TearDownPipeline(); | 695 TearDownPipeline(); |
| 696 } | 696 } |
| 697 } | 697 } |
| 698 | 698 |
| 699 void PipelineImpl::ErrorChangedTask(PipelineError error) { | 699 void PipelineImpl::ErrorChangedTask(PipelineError error) { |
| 700 DCHECK_EQ(MessageLoop::current(), message_loop_); | 700 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 701 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; | 701 DCHECK_NE(PIPELINE_OK, error) << "PIPELINE_OK isn't an error!"; |
| 702 | 702 |
| 703 // Suppress executing additional error logic. Note that if we are currently | 703 // Suppress executing additional error logic. Note that if we are currently |
| 704 // performing a normal stop, then we return immediately and continue the | 704 // performing a normal stop, then we return immediately and continue the |
| 705 // normal stop. | 705 // normal stop. |
| 706 if (IsPipelineStopped() || IsPipelineTearingDown()) { | 706 if (IsPipelineStopped() || IsPipelineTearingDown()) { |
| 707 return; | 707 return; |
| 708 } | 708 } |
| 709 | 709 |
| 710 AutoLock auto_lock(lock_); | 710 base::AutoLock auto_lock(lock_); |
| 711 error_ = error; | 711 error_ = error; |
| 712 | 712 |
| 713 TearDownPipeline(); | 713 TearDownPipeline(); |
| 714 } | 714 } |
| 715 | 715 |
| 716 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { | 716 void PipelineImpl::PlaybackRateChangedTask(float playback_rate) { |
| 717 DCHECK_EQ(MessageLoop::current(), message_loop_); | 717 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 718 { | 718 { |
| 719 AutoLock auto_lock(lock_); | 719 base::AutoLock auto_lock(lock_); |
| 720 clock_->SetPlaybackRate(playback_rate); | 720 clock_->SetPlaybackRate(playback_rate); |
| 721 } | 721 } |
| 722 | 722 |
| 723 // Notify |pipeline_filter_| if it has been initialized. If initialization | 723 // Notify |pipeline_filter_| if it has been initialized. If initialization |
| 724 // hasn't completed yet, the playback rate will be set when initialization | 724 // hasn't completed yet, the playback rate will be set when initialization |
| 725 // completes. | 725 // completes. |
| 726 if (pipeline_filter_) { | 726 if (pipeline_filter_) { |
| 727 pipeline_filter_->SetPlaybackRate(playback_rate); | 727 pipeline_filter_->SetPlaybackRate(playback_rate); |
| 728 } | 728 } |
| 729 } | 729 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 760 // kPausing (for each filter) | 760 // kPausing (for each filter) |
| 761 // kSeeking (for each filter) | 761 // kSeeking (for each filter) |
| 762 // kStarting (for each filter) | 762 // kStarting (for each filter) |
| 763 // kStarted | 763 // kStarted |
| 764 set_state(kPausing); | 764 set_state(kPausing); |
| 765 seek_timestamp_ = time; | 765 seek_timestamp_ = time; |
| 766 seek_callback_.reset(seek_callback); | 766 seek_callback_.reset(seek_callback); |
| 767 | 767 |
| 768 // Kick off seeking! | 768 // Kick off seeking! |
| 769 { | 769 { |
| 770 AutoLock auto_lock(lock_); | 770 base::AutoLock auto_lock(lock_); |
| 771 // If we are waiting for a clock update, the clock hasn't been played yet. | 771 // If we are waiting for a clock update, the clock hasn't been played yet. |
| 772 if (!waiting_for_clock_update_) | 772 if (!waiting_for_clock_update_) |
| 773 clock_->Pause(); | 773 clock_->Pause(); |
| 774 } | 774 } |
| 775 pipeline_filter_->Pause( | 775 pipeline_filter_->Pause( |
| 776 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 776 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 777 } | 777 } |
| 778 | 778 |
| 779 void PipelineImpl::NotifyEndedTask() { | 779 void PipelineImpl::NotifyEndedTask() { |
| 780 DCHECK_EQ(MessageLoop::current(), message_loop_); | 780 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 if (network_callback_.get()) { | 816 if (network_callback_.get()) { |
| 817 network_callback_->Run(); | 817 network_callback_->Run(); |
| 818 } | 818 } |
| 819 } | 819 } |
| 820 | 820 |
| 821 void PipelineImpl::DisableAudioRendererTask() { | 821 void PipelineImpl::DisableAudioRendererTask() { |
| 822 DCHECK_EQ(MessageLoop::current(), message_loop_); | 822 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 823 | 823 |
| 824 // |rendered_mime_types_| is read through public methods so we need to lock | 824 // |rendered_mime_types_| is read through public methods so we need to lock |
| 825 // this variable. | 825 // this variable. |
| 826 AutoLock auto_lock(lock_); | 826 base::AutoLock auto_lock(lock_); |
| 827 rendered_mime_types_.erase(mime_type::kMajorTypeAudio); | 827 rendered_mime_types_.erase(mime_type::kMajorTypeAudio); |
| 828 | 828 |
| 829 audio_disabled_ = true; | 829 audio_disabled_ = true; |
| 830 | 830 |
| 831 // Notify all filters of disabled audio renderer. If the filter isn't | 831 // Notify all filters of disabled audio renderer. If the filter isn't |
| 832 // initialized yet, OnAudioRendererDisabled() will be called when | 832 // initialized yet, OnAudioRendererDisabled() will be called when |
| 833 // initialization is complete. | 833 // initialization is complete. |
| 834 if (pipeline_filter_) { | 834 if (pipeline_filter_) { |
| 835 pipeline_filter_->OnAudioRendererDisabled(); | 835 pipeline_filter_->OnAudioRendererDisabled(); |
| 836 } | 836 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 847 if (!TransientState(state_)) { | 847 if (!TransientState(state_)) { |
| 848 NOTREACHED() << "Invalid current state: " << state_; | 848 NOTREACHED() << "Invalid current state: " << state_; |
| 849 SetError(PIPELINE_ERROR_ABORT); | 849 SetError(PIPELINE_ERROR_ABORT); |
| 850 return; | 850 return; |
| 851 } | 851 } |
| 852 | 852 |
| 853 // Decrement the number of remaining transitions, making sure to transition | 853 // Decrement the number of remaining transitions, making sure to transition |
| 854 // to the next state if needed. | 854 // to the next state if needed. |
| 855 set_state(FindNextState(state_)); | 855 set_state(FindNextState(state_)); |
| 856 if (state_ == kSeeking) { | 856 if (state_ == kSeeking) { |
| 857 AutoLock auto_lock(lock_); | 857 base::AutoLock auto_lock(lock_); |
| 858 clock_->SetTime(seek_timestamp_); | 858 clock_->SetTime(seek_timestamp_); |
| 859 } | 859 } |
| 860 | 860 |
| 861 // Carry out the action for the current state. | 861 // Carry out the action for the current state. |
| 862 if (TransientState(state_)) { | 862 if (TransientState(state_)) { |
| 863 if (state_ == kPausing) { | 863 if (state_ == kPausing) { |
| 864 pipeline_filter_->Pause( | 864 pipeline_filter_->Pause( |
| 865 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); | 865 NewCallback(this, &PipelineImpl::OnFilterStateTransition)); |
| 866 } else if (state_ == kFlushing) { | 866 } else if (state_ == kFlushing) { |
| 867 pipeline_filter_->Flush( | 867 pipeline_filter_->Flush( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 878 } else { | 878 } else { |
| 879 NOTREACHED() << "Unexpected state: " << state_; | 879 NOTREACHED() << "Unexpected state: " << state_; |
| 880 } | 880 } |
| 881 } else if (state_ == kStarted) { | 881 } else if (state_ == kStarted) { |
| 882 FinishInitialization(); | 882 FinishInitialization(); |
| 883 | 883 |
| 884 // Finally, reset our seeking timestamp back to zero. | 884 // Finally, reset our seeking timestamp back to zero. |
| 885 seek_timestamp_ = base::TimeDelta(); | 885 seek_timestamp_ = base::TimeDelta(); |
| 886 seek_pending_ = false; | 886 seek_pending_ = false; |
| 887 | 887 |
| 888 AutoLock auto_lock(lock_); | 888 base::AutoLock auto_lock(lock_); |
| 889 // We use audio stream to update the clock. So if there is such a stream, | 889 // We use audio stream to update the clock. So if there is such a stream, |
| 890 // we pause the clock until we receive a valid timestamp. | 890 // we pause the clock until we receive a valid timestamp. |
| 891 waiting_for_clock_update_ = | 891 waiting_for_clock_update_ = |
| 892 rendered_mime_types_.find(mime_type::kMajorTypeAudio) != | 892 rendered_mime_types_.find(mime_type::kMajorTypeAudio) != |
| 893 rendered_mime_types_.end(); | 893 rendered_mime_types_.end(); |
| 894 if (!waiting_for_clock_update_) | 894 if (!waiting_for_clock_update_) |
| 895 clock_->Play(); | 895 clock_->Play(); |
| 896 | 896 |
| 897 if (IsPipelineStopPending()) { | 897 if (IsPipelineStopPending()) { |
| 898 // We had a pending stop request need to be honored right now. | 898 // We had a pending stop request need to be honored right now. |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 pipeline_filter_->Pause(NewCallback( | 1134 pipeline_filter_->Pause(NewCallback( |
| 1135 this, &PipelineImpl::OnFilterStateTransition)); | 1135 this, &PipelineImpl::OnFilterStateTransition)); |
| 1136 } else { | 1136 } else { |
| 1137 set_state(kStopped); | 1137 set_state(kStopped); |
| 1138 message_loop_->PostTask(FROM_HERE, | 1138 message_loop_->PostTask(FROM_HERE, |
| 1139 NewRunnableMethod(this, &PipelineImpl::FinishDestroyingFiltersTask)); | 1139 NewRunnableMethod(this, &PipelineImpl::FinishDestroyingFiltersTask)); |
| 1140 } | 1140 } |
| 1141 } | 1141 } |
| 1142 | 1142 |
| 1143 } // namespace media | 1143 } // namespace media |
| OLD | NEW |