| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/android/media_codec_player.h" | 5 #include "media/base/android/media_codec_player.h" |
| 6 | 6 |
| 7 #include "base/barrier_closure.h" | 7 #include "base/barrier_closure.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 base::WeakPtr<MediaPlayerManager> manager, | 51 base::WeakPtr<MediaPlayerManager> manager, |
| 52 const RequestMediaResourcesCB& request_media_resources_cb, | 52 const RequestMediaResourcesCB& request_media_resources_cb, |
| 53 scoped_ptr<DemuxerAndroid> demuxer, | 53 scoped_ptr<DemuxerAndroid> demuxer, |
| 54 const GURL& frame_url) | 54 const GURL& frame_url) |
| 55 : MediaPlayerAndroid(player_id, | 55 : MediaPlayerAndroid(player_id, |
| 56 manager.get(), | 56 manager.get(), |
| 57 request_media_resources_cb, | 57 request_media_resources_cb, |
| 58 frame_url), | 58 frame_url), |
| 59 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 59 ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 60 demuxer_(demuxer.Pass()), | 60 demuxer_(demuxer.Pass()), |
| 61 state_(STATE_PAUSED), | 61 state_(kStatePaused), |
| 62 interpolator_(&default_tick_clock_), | 62 interpolator_(&default_tick_clock_), |
| 63 pending_start_(false), | 63 pending_start_(false), |
| 64 pending_seek_(kNoTimestamp()), | 64 pending_seek_(kNoTimestamp()), |
| 65 media_weak_factory_(this) { | 65 media_weak_factory_(this) { |
| 66 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 66 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 67 | 67 |
| 68 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; | 68 DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; |
| 69 | 69 |
| 70 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); | 70 request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); |
| 71 | 71 |
| 72 completion_cb_ = | 72 completion_cb_ = |
| 73 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); | 73 base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); |
| 74 seek_done_cb_ = | 74 seek_done_cb_ = |
| 75 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); | 75 base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); |
| 76 error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id); |
| 76 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, | 77 attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, |
| 77 WeakPtrForUIThread(), nullptr); | 78 WeakPtrForUIThread(), nullptr); |
| 78 detach_listener_cb_ = | 79 detach_listener_cb_ = |
| 79 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); | 80 base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); |
| 80 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, | 81 metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, |
| 81 WeakPtrForUIThread()); | 82 WeakPtrForUIThread()); |
| 82 time_update_cb_ = | 83 time_update_cb_ = |
| 83 base::Bind(&MediaPlayerAndroid::OnTimeUpdate, WeakPtrForUIThread()); | 84 base::Bind(&MediaPlayerAndroid::OnTimeUpdate, WeakPtrForUIThread()); |
| 84 | 85 |
| 85 media_weak_this_ = media_weak_factory_.GetWeakPtr(); | 86 media_weak_this_ = media_weak_factory_.GetWeakPtr(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 | 124 |
| 124 // Post deletion onto Media thread | 125 // Post deletion onto Media thread |
| 125 GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this); | 126 GetMediaTaskRunner()->DeleteSoon(FROM_HERE, this); |
| 126 } | 127 } |
| 127 | 128 |
| 128 void MediaCodecPlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { | 129 void MediaCodecPlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
| 129 RUN_ON_MEDIA_THREAD(SetVideoSurface, base::Passed(&surface)); | 130 RUN_ON_MEDIA_THREAD(SetVideoSurface, base::Passed(&surface)); |
| 130 | 131 |
| 131 DVLOG(1) << __FUNCTION__ << (surface.IsEmpty() ? " empty" : " non-empty"); | 132 DVLOG(1) << __FUNCTION__ << (surface.IsEmpty() ? " empty" : " non-empty"); |
| 132 | 133 |
| 133 // I assume that if video decoder already has the surface, | 134 // Save the empty-ness before we pass the surface to the decoder. |
| 134 // there will be two calls: | 135 bool surface_is_empty = surface.IsEmpty(); |
| 135 // (1) SetVideoSurface(0) | |
| 136 // (2) SetVideoSurface(new_surface) | |
| 137 video_decoder_->SetPendingSurface(surface.Pass()); | |
| 138 | 136 |
| 139 if (video_decoder_->HasPendingSurface() && | 137 // Apparently RemoveVideoSurface() can be called several times in a row, |
| 140 state_ == STATE_WAITING_FOR_SURFACE) { | 138 // ignore the second and subsequent calls. |
| 141 SetState(STATE_PLAYING); | 139 if (surface_is_empty && !video_decoder_->HasVideoSurface()) { |
| 142 StartPlaybackDecoders(); | 140 DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring"; |
| 141 return; |
| 142 } |
| 143 |
| 144 video_decoder_->SetVideoSurface(surface.Pass()); |
| 145 |
| 146 if (surface_is_empty) { |
| 147 // Remove video surface. |
| 148 switch (state_) { |
| 149 case kStatePlaying: |
| 150 if (VideoFinished()) |
| 151 break; |
| 152 |
| 153 DVLOG(1) << __FUNCTION__ << ": stopping and restarting"; |
| 154 // Stop decoders as quickly as possible. |
| 155 StopDecoders(); // synchronous stop |
| 156 |
| 157 // Prefetch or wait for initial configuration. |
| 158 if (HasAudio() || HasVideo()) { |
| 159 SetState(kStatePrefetching); |
| 160 StartPrefetchDecoders(); |
| 161 } else { |
| 162 SetState(kStateWaitingForConfig); |
| 163 } |
| 164 break; |
| 165 |
| 166 default: |
| 167 break; // ignore |
| 168 } |
| 169 } else { |
| 170 // Replace video surface. |
| 171 switch (state_) { |
| 172 case kStateWaitingForSurface: |
| 173 SetState(kStatePlaying); |
| 174 StartPlaybackOrBrowserSeek(); |
| 175 break; |
| 176 |
| 177 case kStatePlaying: |
| 178 if (VideoFinished()) |
| 179 break; |
| 180 |
| 181 DVLOG(1) << __FUNCTION__ << ": requesting to stop and restart"; |
| 182 SetState(kStateStopping); |
| 183 RequestToStopDecoders(); |
| 184 SetPendingStart(true); |
| 185 break; |
| 186 |
| 187 default: |
| 188 break; // ignore |
| 189 } |
| 143 } | 190 } |
| 144 } | 191 } |
| 145 | 192 |
| 146 void MediaCodecPlayer::Start() { | 193 void MediaCodecPlayer::Start() { |
| 147 RUN_ON_MEDIA_THREAD(Start); | 194 RUN_ON_MEDIA_THREAD(Start); |
| 148 | 195 |
| 149 DVLOG(1) << __FUNCTION__; | 196 DVLOG(1) << __FUNCTION__; |
| 150 | 197 |
| 151 switch (state_) { | 198 switch (state_) { |
| 152 case STATE_PAUSED: | 199 case kStatePaused: |
| 153 // Prefetch or wait for initial configuration. | 200 // Prefetch or wait for initial configuration. |
| 154 if (HasAudio() || HasVideo()) { | 201 if (HasAudio() || HasVideo()) { |
| 155 SetState(STATE_PREFETCHING); | 202 SetState(kStatePrefetching); |
| 156 StartPrefetchDecoders(); | 203 StartPrefetchDecoders(); |
| 157 } else { | 204 } else { |
| 158 SetState(STATE_WAITING_FOR_CONFIG); | 205 SetState(kStateWaitingForConfig); |
| 159 } | 206 } |
| 160 break; | 207 break; |
| 161 case STATE_STOPPING: | 208 case kStateStopping: |
| 162 case STATE_WAITING_FOR_SEEK: | 209 case kStateWaitingForSeek: |
| 163 SetPendingStart(true); | 210 SetPendingStart(true); |
| 164 break; | 211 break; |
| 165 case STATE_WAITING_FOR_CONFIG: | 212 case kStateWaitingForConfig: |
| 166 case STATE_PREFETCHING: | 213 case kStatePrefetching: |
| 167 case STATE_PLAYING: | 214 case kStatePlaying: |
| 168 case STATE_WAITING_FOR_SURFACE: | 215 case kStateWaitingForSurface: |
| 169 case STATE_ERROR: | 216 case kStateError: |
| 170 break; // Ignore | 217 break; // Ignore |
| 171 default: | 218 default: |
| 172 NOTREACHED(); | 219 NOTREACHED(); |
| 173 break; | 220 break; |
| 174 } | 221 } |
| 175 } | 222 } |
| 176 | 223 |
| 177 void MediaCodecPlayer::Pause(bool is_media_related_action) { | 224 void MediaCodecPlayer::Pause(bool is_media_related_action) { |
| 178 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); | 225 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); |
| 179 | 226 |
| 180 DVLOG(1) << __FUNCTION__; | 227 DVLOG(1) << __FUNCTION__; |
| 181 | 228 |
| 182 SetPendingStart(false); | 229 SetPendingStart(false); |
| 183 | 230 |
| 184 switch (state_) { | 231 switch (state_) { |
| 185 case STATE_WAITING_FOR_CONFIG: | 232 case kStateWaitingForConfig: |
| 186 case STATE_PREFETCHING: | 233 case kStatePrefetching: |
| 187 case STATE_WAITING_FOR_SURFACE: | 234 case kStateWaitingForSurface: |
| 188 SetState(STATE_PAUSED); | 235 SetState(kStatePaused); |
| 189 StopDecoders(); | 236 StopDecoders(); |
| 190 break; | 237 break; |
| 191 case STATE_PLAYING: | 238 case kStatePlaying: |
| 192 SetState(STATE_STOPPING); | 239 SetState(kStateStopping); |
| 193 RequestToStopDecoders(); | 240 RequestToStopDecoders(); |
| 194 break; | 241 break; |
| 195 case STATE_PAUSED: | 242 case kStatePaused: |
| 196 case STATE_STOPPING: | 243 case kStateStopping: |
| 197 case STATE_WAITING_FOR_SEEK: | 244 case kStateWaitingForSeek: |
| 198 case STATE_ERROR: | 245 case kStateError: |
| 199 break; // Ignore | 246 break; // Ignore |
| 200 default: | 247 default: |
| 201 NOTREACHED(); | 248 NOTREACHED(); |
| 202 break; | 249 break; |
| 203 } | 250 } |
| 204 } | 251 } |
| 205 | 252 |
| 206 void MediaCodecPlayer::SeekTo(base::TimeDelta timestamp) { | 253 void MediaCodecPlayer::SeekTo(base::TimeDelta timestamp) { |
| 207 RUN_ON_MEDIA_THREAD(SeekTo, timestamp); | 254 RUN_ON_MEDIA_THREAD(SeekTo, timestamp); |
| 208 | 255 |
| 209 DVLOG(1) << __FUNCTION__ << " " << timestamp; | 256 DVLOG(1) << __FUNCTION__ << " " << timestamp; |
| 210 | 257 |
| 211 switch (state_) { | 258 switch (state_) { |
| 212 case STATE_PAUSED: | 259 case kStatePaused: |
| 213 SetState(STATE_WAITING_FOR_SEEK); | 260 SetState(kStateWaitingForSeek); |
| 214 RequestDemuxerSeek(timestamp); | 261 RequestDemuxerSeek(timestamp); |
| 215 break; | 262 break; |
| 216 case STATE_WAITING_FOR_CONFIG: | 263 case kStateWaitingForConfig: |
| 217 case STATE_PREFETCHING: | 264 case kStatePrefetching: |
| 218 case STATE_WAITING_FOR_SURFACE: | 265 case kStateWaitingForSurface: |
| 219 SetState(STATE_WAITING_FOR_SEEK); | 266 SetState(kStateWaitingForSeek); |
| 220 StopDecoders(); | 267 StopDecoders(); |
| 221 SetPendingStart(true); | 268 SetPendingStart(true); |
| 222 RequestDemuxerSeek(timestamp); | 269 RequestDemuxerSeek(timestamp); |
| 223 break; | 270 break; |
| 224 case STATE_PLAYING: | 271 case kStatePlaying: |
| 225 SetState(STATE_STOPPING); | 272 SetState(kStateStopping); |
| 226 RequestToStopDecoders(); | 273 RequestToStopDecoders(); |
| 227 SetPendingStart(true); | 274 SetPendingStart(true); |
| 228 SetPendingSeek(timestamp); | 275 SetPendingSeek(timestamp); |
| 229 break; | 276 break; |
| 230 case STATE_STOPPING: | 277 case kStateStopping: |
| 231 SetPendingSeek(timestamp); | 278 SetPendingSeek(timestamp); |
| 232 break; | 279 break; |
| 233 case STATE_WAITING_FOR_SEEK: | 280 case kStateWaitingForSeek: |
| 234 SetPendingSeek(timestamp); | 281 SetPendingSeek(timestamp); |
| 235 break; | 282 break; |
| 236 case STATE_ERROR: | 283 case kStateError: |
| 237 break; // ignore | 284 break; // ignore |
| 238 default: | 285 default: |
| 239 NOTREACHED(); | 286 NOTREACHED(); |
| 240 break; | 287 break; |
| 241 } | 288 } |
| 242 } | 289 } |
| 243 | 290 |
| 244 void MediaCodecPlayer::Release() { | 291 void MediaCodecPlayer::Release() { |
| 245 RUN_ON_MEDIA_THREAD(Release); | 292 RUN_ON_MEDIA_THREAD(Release); |
| 246 | 293 |
| 247 DVLOG(1) << __FUNCTION__; | 294 DVLOG(1) << __FUNCTION__; |
| 248 | 295 |
| 249 SetState(STATE_PAUSED); | 296 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser |
| 297 // and renderer processes going. Seek should work across and after Release(). |
| 298 |
| 250 ReleaseDecoderResources(); | 299 ReleaseDecoderResources(); |
| 300 |
| 301 SetPendingStart(false); |
| 302 |
| 303 if (state_ != kStateWaitingForSeek) |
| 304 SetState(kStatePaused); |
| 305 |
| 306 base::TimeDelta pending_seek_time = GetPendingSeek(); |
| 307 if (pending_seek_time != kNoTimestamp()) { |
| 308 SetPendingSeek(kNoTimestamp()); |
| 309 SetState(kStateWaitingForSeek); |
| 310 RequestDemuxerSeek(pending_seek_time); |
| 311 } |
| 251 } | 312 } |
| 252 | 313 |
| 253 void MediaCodecPlayer::SetVolume(double volume) { | 314 void MediaCodecPlayer::SetVolume(double volume) { |
| 254 RUN_ON_MEDIA_THREAD(SetVolume, volume); | 315 RUN_ON_MEDIA_THREAD(SetVolume, volume); |
| 255 | 316 |
| 256 DVLOG(1) << __FUNCTION__ << " " << volume; | 317 DVLOG(1) << __FUNCTION__ << " " << volume; |
| 257 audio_decoder_->SetVolume(volume); | 318 audio_decoder_->SetVolume(volume); |
| 258 } | 319 } |
| 259 | 320 |
| 260 int MediaCodecPlayer::GetVideoWidth() { | 321 int MediaCodecPlayer::GetVideoWidth() { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 275 base::TimeDelta MediaCodecPlayer::GetDuration() { | 336 base::TimeDelta MediaCodecPlayer::GetDuration() { |
| 276 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 337 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 277 return metadata_cache_.duration; | 338 return metadata_cache_.duration; |
| 278 } | 339 } |
| 279 | 340 |
| 280 bool MediaCodecPlayer::IsPlaying() { | 341 bool MediaCodecPlayer::IsPlaying() { |
| 281 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 342 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 282 | 343 |
| 283 // TODO(timav): Use another variable since |state_| should only be accessed on | 344 // TODO(timav): Use another variable since |state_| should only be accessed on |
| 284 // Media thread. | 345 // Media thread. |
| 285 return state_ == STATE_PLAYING || state_ == STATE_STOPPING; | 346 return state_ == kStatePlaying || state_ == kStateStopping; |
| 286 } | 347 } |
| 287 | 348 |
| 288 bool MediaCodecPlayer::CanPause() { | 349 bool MediaCodecPlayer::CanPause() { |
| 289 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 350 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 290 NOTIMPLEMENTED(); | 351 NOTIMPLEMENTED(); |
| 291 return false; | 352 return false; |
| 292 } | 353 } |
| 293 | 354 |
| 294 bool MediaCodecPlayer::CanSeekForward() { | 355 bool MediaCodecPlayer::CanSeekForward() { |
| 295 DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 356 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 if (data.type == DemuxerStream::VIDEO) | 408 if (data.type == DemuxerStream::VIDEO) |
| 348 video_decoder_->OnDemuxerDataAvailable(data); | 409 video_decoder_->OnDemuxerDataAvailable(data); |
| 349 } | 410 } |
| 350 | 411 |
| 351 void MediaCodecPlayer::OnDemuxerSeekDone( | 412 void MediaCodecPlayer::OnDemuxerSeekDone( |
| 352 base::TimeDelta actual_browser_seek_time) { | 413 base::TimeDelta actual_browser_seek_time) { |
| 353 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 414 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 354 | 415 |
| 355 DVLOG(1) << __FUNCTION__ << " actual_time:" << actual_browser_seek_time; | 416 DVLOG(1) << __FUNCTION__ << " actual_time:" << actual_browser_seek_time; |
| 356 | 417 |
| 357 if (state_ != STATE_WAITING_FOR_SEEK) | |
| 358 return; // ignore | |
| 359 | |
| 360 DCHECK(seek_info_.get()); | 418 DCHECK(seek_info_.get()); |
| 361 DCHECK(seek_info_->seek_time != kNoTimestamp()); | 419 DCHECK(seek_info_->seek_time != kNoTimestamp()); |
| 362 | 420 |
| 363 // A browser seek must not jump into the past. Ideally, it seeks to the | 421 // A browser seek must not jump into the past. Ideally, it seeks to the |
| 364 // requested time, but it might jump into the future. | 422 // requested time, but it might jump into the future. |
| 365 DCHECK(!seek_info_->is_browser_seek || | 423 DCHECK(!seek_info_->is_browser_seek || |
| 366 seek_info_->seek_time <= actual_browser_seek_time); | 424 seek_info_->seek_time <= actual_browser_seek_time); |
| 367 | 425 |
| 368 // Restrict the current time to be equal to seek_time | 426 // Restrict the current time to be equal to seek_time |
| 369 // for the next StartPlaybackDecoders() call. | 427 // for the next StartPlaybackDecoders() call. |
| 370 | 428 |
| 371 base::TimeDelta seek_time = seek_info_->is_browser_seek | 429 base::TimeDelta seek_time = seek_info_->is_browser_seek |
| 372 ? actual_browser_seek_time | 430 ? actual_browser_seek_time |
| 373 : seek_info_->seek_time; | 431 : seek_info_->seek_time; |
| 374 | 432 |
| 375 interpolator_.SetBounds(seek_time, seek_time); | 433 interpolator_.SetBounds(seek_time, seek_time); |
| 376 audio_decoder_->SetBaseTimestamp(seek_time); | 434 audio_decoder_->SetBaseTimestamp(seek_time); |
| 377 | 435 |
| 436 // The Flush() might set the state to kStateError. |
| 437 if (state_ == kStateError) { |
| 438 // Notify the Renderer. |
| 439 if (!seek_info_->is_browser_seek) |
| 440 ui_task_runner_->PostTask(FROM_HERE, |
| 441 base::Bind(seek_done_cb_, seek_time)); |
| 442 |
| 443 seek_info_.reset(); |
| 444 return; |
| 445 } |
| 446 |
| 447 DCHECK_EQ(kStateWaitingForSeek, state_); |
| 448 |
| 378 base::TimeDelta pending_seek_time = GetPendingSeek(); | 449 base::TimeDelta pending_seek_time = GetPendingSeek(); |
| 379 if (pending_seek_time != kNoTimestamp()) { | 450 if (pending_seek_time != kNoTimestamp()) { |
| 380 // Keep STATE_WAITING_FOR_SEEK | 451 // Keep kStateWaitingForSeek |
| 381 SetPendingSeek(kNoTimestamp()); | 452 SetPendingSeek(kNoTimestamp()); |
| 382 RequestDemuxerSeek(pending_seek_time); | 453 RequestDemuxerSeek(pending_seek_time); |
| 383 return; | 454 return; |
| 384 } | 455 } |
| 385 | 456 |
| 386 if (HasPendingStart()) { | 457 if (HasPendingStart()) { |
| 387 SetPendingStart(false); | 458 SetPendingStart(false); |
| 388 // Prefetch or wait for initial configuration. | 459 // Prefetch or wait for initial configuration. |
| 389 if (HasAudio() || HasVideo()) { | 460 if (HasAudio() || HasVideo()) { |
| 390 SetState(STATE_PREFETCHING); | 461 SetState(kStatePrefetching); |
| 391 StartPrefetchDecoders(); | 462 StartPrefetchDecoders(); |
| 392 } else { | 463 } else { |
| 393 SetState(STATE_WAITING_FOR_CONFIG); | 464 SetState(kStateWaitingForConfig); |
| 394 } | 465 } |
| 395 } else { | 466 } else { |
| 396 SetState(STATE_PAUSED); | 467 SetState(kStatePaused); |
| 397 } | 468 } |
| 398 | 469 |
| 399 // Notify the Renderer. | 470 // Notify the Renderer. |
| 400 if (!seek_info_->is_browser_seek) | 471 if (!seek_info_->is_browser_seek) |
| 401 ui_task_runner_->PostTask(FROM_HERE, base::Bind(seek_done_cb_, seek_time)); | 472 ui_task_runner_->PostTask(FROM_HERE, base::Bind(seek_done_cb_, seek_time)); |
| 402 | 473 |
| 403 seek_info_.reset(); | 474 seek_info_.reset(); |
| 404 } | 475 } |
| 405 | 476 |
| 406 void MediaCodecPlayer::OnDemuxerDurationChanged( | 477 void MediaCodecPlayer::OnDemuxerDurationChanged( |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 // 4. RequestDemuxerData is processed by the media thread queue. Since the | 522 // 4. RequestDemuxerData is processed by the media thread queue. Since the |
| 452 // weak_ptr was invalidated in (3), this is a no-op. If we used | 523 // weak_ptr was invalidated in (3), this is a no-op. If we used |
| 453 // DemuxerAndroid::RequestDemuxerData() it would arrive and will try to | 524 // DemuxerAndroid::RequestDemuxerData() it would arrive and will try to |
| 454 // call the client, but the client (i.e. this player) would not exist. | 525 // call the client, but the client (i.e. this player) would not exist. |
| 455 demuxer_->RequestDemuxerData(stream_type); | 526 demuxer_->RequestDemuxerData(stream_type); |
| 456 } | 527 } |
| 457 | 528 |
| 458 void MediaCodecPlayer::OnPrefetchDone() { | 529 void MediaCodecPlayer::OnPrefetchDone() { |
| 459 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 530 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 460 | 531 |
| 461 if (state_ != STATE_PREFETCHING) { | 532 if (state_ != kStatePrefetching) { |
| 462 DVLOG(1) << __FUNCTION__ << " wrong state " << AsString(state_) | 533 DVLOG(1) << __FUNCTION__ << " wrong state " << AsString(state_) |
| 463 << " ignoring"; | 534 << " ignoring"; |
| 464 return; // Ignore | 535 return; // Ignore |
| 465 } | 536 } |
| 466 | 537 |
| 467 DVLOG(1) << __FUNCTION__; | 538 DVLOG(1) << __FUNCTION__; |
| 468 | 539 |
| 469 if (!HasAudio() && !HasVideo()) { | 540 if (!HasAudio() && !HasVideo()) { |
| 470 // No configuration at all after prefetching. | 541 // No configuration at all after prefetching. |
| 471 // This is an error, initial configuration is expected | 542 // This is an error, initial configuration is expected |
| 472 // before the first data chunk. | 543 // before the first data chunk. |
| 473 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | 544 DCHECK(!internal_error_cb_.is_null()); |
| 545 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
| 474 return; | 546 return; |
| 475 } | 547 } |
| 476 | 548 |
| 477 if (HasVideo() && !HasPendingSurface()) { | 549 if (HasVideo() && !video_decoder_->HasVideoSurface()) { |
| 478 SetState(STATE_WAITING_FOR_SURFACE); | 550 SetState(kStateWaitingForSurface); |
| 479 return; | 551 return; |
| 480 } | 552 } |
| 481 | 553 |
| 482 SetState(STATE_PLAYING); | 554 SetState(kStatePlaying); |
| 483 StartPlaybackDecoders(); | 555 StartPlaybackOrBrowserSeek(); |
| 484 } | 556 } |
| 485 | 557 |
| 486 void MediaCodecPlayer::OnStopDone() { | 558 void MediaCodecPlayer::OnStopDone() { |
| 487 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 559 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 488 DVLOG(1) << __FUNCTION__; | 560 DVLOG(1) << __FUNCTION__; |
| 489 | 561 |
| 490 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) | 562 if (!(audio_decoder_->IsStopped() && video_decoder_->IsStopped())) |
| 491 return; // Wait until other stream is stopped | 563 return; // Wait until other stream is stopped |
| 492 | 564 |
| 493 // At this point decoder threads should not be running | 565 // At this point decoder threads should not be running |
| 494 if (interpolator_.interpolating()) | 566 if (interpolator_.interpolating()) |
| 495 interpolator_.StopInterpolating(); | 567 interpolator_.StopInterpolating(); |
| 496 | 568 |
| 497 base::TimeDelta seek_time; | 569 base::TimeDelta seek_time; |
| 498 switch (state_) { | 570 switch (state_) { |
| 499 case STATE_STOPPING: { | 571 case kStateStopping: { |
| 500 base::TimeDelta seek_time = GetPendingSeek(); | 572 base::TimeDelta seek_time = GetPendingSeek(); |
| 501 if (seek_time != kNoTimestamp()) { | 573 if (seek_time != kNoTimestamp()) { |
| 502 SetState(STATE_WAITING_FOR_SEEK); | 574 SetState(kStateWaitingForSeek); |
| 503 SetPendingSeek(kNoTimestamp()); | 575 SetPendingSeek(kNoTimestamp()); |
| 504 RequestDemuxerSeek(seek_time); | 576 RequestDemuxerSeek(seek_time); |
| 505 } else if (HasPendingStart()) { | 577 } else if (HasPendingStart()) { |
| 506 SetPendingStart(false); | 578 SetPendingStart(false); |
| 507 SetState(STATE_PREFETCHING); | 579 SetState(kStatePrefetching); |
| 508 StartPrefetchDecoders(); | 580 StartPrefetchDecoders(); |
| 509 } else { | 581 } else { |
| 510 SetState(STATE_PAUSED); | 582 SetState(kStatePaused); |
| 511 } | 583 } |
| 512 } break; | 584 } break; |
| 513 case STATE_PLAYING: | 585 case kStatePlaying: |
| 514 // Unexpected stop means completion | 586 // Unexpected stop means completion |
| 515 SetState(STATE_PAUSED); | 587 SetState(kStatePaused); |
| 516 break; | 588 break; |
| 517 default: | 589 default: |
| 518 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); | 590 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); |
| 519 // NOTREACHED(); | 591 // NOTREACHED(); |
| 520 // Ignore! There can be a race condition: audio posts OnStopDone, | 592 // Ignore! There can be a race condition: audio posts OnStopDone, |
| 521 // then video posts, then first OnStopDone arrives at which point | 593 // then video posts, then first OnStopDone arrives at which point |
| 522 // both streams are already stopped, then second OnStopDone arrives. When | 594 // both streams are already stopped, then second OnStopDone arrives. When |
| 523 // the second one arrives, the state us not STATE_STOPPING any more. | 595 // the second one arrives, the state us not kStateStopping any more. |
| 524 break; | 596 break; |
| 525 } | 597 } |
| 526 | 598 |
| 527 // DetachListener to UI thread | 599 // DetachListener to UI thread |
| 528 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); | 600 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); |
| 529 | 601 |
| 530 if (AudioFinished() && VideoFinished()) | 602 if (AudioFinished() && VideoFinished()) |
| 531 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); | 603 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); |
| 532 } | 604 } |
| 533 | 605 |
| 534 void MediaCodecPlayer::OnError() { | 606 void MediaCodecPlayer::OnError() { |
| 535 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 607 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 536 DVLOG(1) << __FUNCTION__; | 608 DVLOG(1) << __FUNCTION__; |
| 537 | 609 |
| 538 // STATE_ERROR blocks all events | 610 // kStateError blocks all events |
| 539 SetState(STATE_ERROR); | 611 SetState(kStateError); |
| 540 | 612 |
| 541 ReleaseDecoderResources(); | 613 ReleaseDecoderResources(); |
| 614 |
| 615 ui_task_runner_->PostTask(FROM_HERE, |
| 616 base::Bind(error_cb_, MEDIA_ERROR_DECODE)); |
| 542 } | 617 } |
| 543 | 618 |
| 544 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { | 619 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { |
| 545 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 620 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 546 DVLOG(1) << __FUNCTION__ << " stream type:" << type; | 621 DVLOG(1) << __FUNCTION__ << " stream type:" << type; |
| 547 | 622 |
| 548 if (state_ != STATE_PLAYING) | 623 if (state_ != kStatePlaying) |
| 549 return; // Ignore | 624 return; // Ignore |
| 550 | 625 |
| 551 SetState(STATE_STOPPING); | 626 SetState(kStateStopping); |
| 552 RequestToStopDecoders(); | 627 RequestToStopDecoders(); |
| 553 SetPendingStart(true); | 628 SetPendingStart(true); |
| 554 } | 629 } |
| 555 | 630 |
| 556 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type, | 631 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type, |
| 557 base::TimeDelta now_playing, | 632 base::TimeDelta now_playing, |
| 558 base::TimeDelta last_buffered) { | 633 base::TimeDelta last_buffered) { |
| 559 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 634 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 560 | 635 |
| 561 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing | 636 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 598 | 673 |
| 599 // State machine operations, called on Media thread | 674 // State machine operations, called on Media thread |
| 600 | 675 |
| 601 void MediaCodecPlayer::SetState(PlayerState new_state) { | 676 void MediaCodecPlayer::SetState(PlayerState new_state) { |
| 602 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 677 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 603 | 678 |
| 604 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); | 679 DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); |
| 605 state_ = new_state; | 680 state_ = new_state; |
| 606 } | 681 } |
| 607 | 682 |
| 608 void MediaCodecPlayer::SetPendingSurface(gfx::ScopedJavaSurface surface) { | |
| 609 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | |
| 610 DVLOG(1) << __FUNCTION__; | |
| 611 | |
| 612 video_decoder_->SetPendingSurface(surface.Pass()); | |
| 613 } | |
| 614 | |
| 615 bool MediaCodecPlayer::HasPendingSurface() const { | |
| 616 return video_decoder_->HasPendingSurface(); | |
| 617 } | |
| 618 | |
| 619 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { | 683 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { |
| 620 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 684 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 621 DVLOG(1) << __FUNCTION__ << ": " << need_to_start; | 685 DVLOG(1) << __FUNCTION__ << ": " << need_to_start; |
| 622 pending_start_ = need_to_start; | 686 pending_start_ = need_to_start; |
| 623 } | 687 } |
| 624 | 688 |
| 625 bool MediaCodecPlayer::HasPendingStart() const { | 689 bool MediaCodecPlayer::HasPendingStart() const { |
| 626 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 690 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 627 return pending_start_; | 691 return pending_start_; |
| 628 } | 692 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 658 // At least one valid codec must be present. | 722 // At least one valid codec must be present. |
| 659 DCHECK(configs.audio_codec != kUnknownAudioCodec || | 723 DCHECK(configs.audio_codec != kUnknownAudioCodec || |
| 660 configs.video_codec != kUnknownVideoCodec); | 724 configs.video_codec != kUnknownVideoCodec); |
| 661 | 725 |
| 662 if (configs.audio_codec != kUnknownAudioCodec) | 726 if (configs.audio_codec != kUnknownAudioCodec) |
| 663 audio_decoder_->SetDemuxerConfigs(configs); | 727 audio_decoder_->SetDemuxerConfigs(configs); |
| 664 | 728 |
| 665 if (configs.video_codec != kUnknownVideoCodec) | 729 if (configs.video_codec != kUnknownVideoCodec) |
| 666 video_decoder_->SetDemuxerConfigs(configs); | 730 video_decoder_->SetDemuxerConfigs(configs); |
| 667 | 731 |
| 668 if (state_ == STATE_WAITING_FOR_CONFIG) { | 732 if (state_ == kStateWaitingForConfig) { |
| 669 SetState(STATE_PREFETCHING); | 733 SetState(kStatePrefetching); |
| 670 StartPrefetchDecoders(); | 734 StartPrefetchDecoders(); |
| 671 } | 735 } |
| 672 } | 736 } |
| 673 | 737 |
| 674 void MediaCodecPlayer::StartPrefetchDecoders() { | 738 void MediaCodecPlayer::StartPrefetchDecoders() { |
| 675 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 739 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 676 DVLOG(1) << __FUNCTION__; | 740 DVLOG(1) << __FUNCTION__; |
| 677 | 741 |
| 678 bool do_audio = false; | 742 bool do_audio = false; |
| 679 bool do_video = false; | 743 bool do_video = false; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 692 base::Closure prefetch_cb = base::BarrierClosure( | 756 base::Closure prefetch_cb = base::BarrierClosure( |
| 693 count, base::Bind(&MediaCodecPlayer::OnPrefetchDone, media_weak_this_)); | 757 count, base::Bind(&MediaCodecPlayer::OnPrefetchDone, media_weak_this_)); |
| 694 | 758 |
| 695 if (do_audio) | 759 if (do_audio) |
| 696 audio_decoder_->Prefetch(prefetch_cb); | 760 audio_decoder_->Prefetch(prefetch_cb); |
| 697 | 761 |
| 698 if (do_video) | 762 if (do_video) |
| 699 video_decoder_->Prefetch(prefetch_cb); | 763 video_decoder_->Prefetch(prefetch_cb); |
| 700 } | 764 } |
| 701 | 765 |
| 702 void MediaCodecPlayer::StartPlaybackDecoders() { | 766 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() { |
| 703 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 767 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 704 DVLOG(1) << __FUNCTION__; | 768 DVLOG(1) << __FUNCTION__; |
| 705 | 769 |
| 706 // Configure all streams before the start since | 770 // TODO(timav): consider replacing this method with posting a |
| 707 // we may discover that browser seek is required. | 771 // browser seek task (i.e. generate an event) from StartPlaybackDecoders(). |
| 772 |
| 773 StartStatus status = StartPlaybackDecoders(); |
| 774 |
| 775 switch (status) { |
| 776 case kStartBrowserSeekRequired: |
| 777 // Browser seek |
| 778 SetState(kStateWaitingForSeek); |
| 779 SetPendingStart(true); |
| 780 StopDecoders(); |
| 781 RequestDemuxerSeek(GetInterpolatedTime(), true); |
| 782 break; |
| 783 case kStartFailed: |
| 784 GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |
| 785 break; |
| 786 case kStartOk: |
| 787 break; |
| 788 } |
| 789 } |
| 790 |
| 791 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { |
| 792 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 793 DVLOG(1) << __FUNCTION__; |
| 708 | 794 |
| 709 bool do_audio = !AudioFinished(); | 795 bool do_audio = !AudioFinished(); |
| 710 bool do_video = !VideoFinished(); | 796 bool do_video = !VideoFinished(); |
| 711 | 797 |
| 712 // If there is nothing to play, the state machine should determine | 798 // If there is nothing to play, the state machine should determine this at the |
| 713 // this at the prefetch state and never call this method. | 799 // prefetch state and never call this method. |
| 714 DCHECK(do_audio || do_video); | 800 DCHECK(do_audio || do_video); |
| 715 | 801 |
| 802 // Configure all streams before the start since we may discover that browser |
| 803 // seek is required. Start with video: if browser seek is required it would |
| 804 // not make sense to configure audio. |
| 805 |
| 806 if (do_video) { |
| 807 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); |
| 808 switch (status) { |
| 809 case MediaCodecDecoder::kConfigOk: |
| 810 break; |
| 811 case MediaCodecDecoder::kConfigKeyFrameRequired: |
| 812 // TODO(timav): post a task or return the status? |
| 813 return kStartBrowserSeekRequired; |
| 814 case MediaCodecDecoder::kConfigFailure: |
| 815 return kStartFailed; |
| 816 } |
| 817 } |
| 818 |
| 716 if (do_audio) { | 819 if (do_audio) { |
| 717 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); | 820 MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); |
| 718 if (status != MediaCodecDecoder::CONFIG_OK) { | 821 if (status != MediaCodecDecoder::kConfigOk) { |
| 719 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | 822 return kStartFailed; |
| 720 return; | |
| 721 } | 823 } |
| 722 } | 824 } |
| 723 | 825 |
| 724 if (do_video) { | |
| 725 MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); | |
| 726 if (status != MediaCodecDecoder::CONFIG_OK) { | |
| 727 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | |
| 728 return; | |
| 729 } | |
| 730 } | |
| 731 | |
| 732 // At this point decoder threads should not be running. | 826 // At this point decoder threads should not be running. |
| 733 if (!interpolator_.interpolating()) | 827 if (!interpolator_.interpolating()) |
| 734 interpolator_.StartInterpolating(); | 828 interpolator_.StartInterpolating(); |
| 735 | 829 |
| 736 base::TimeDelta current_time = GetInterpolatedTime(); | 830 base::TimeDelta current_time = GetInterpolatedTime(); |
| 737 | 831 |
| 738 if (do_audio) { | 832 if (do_audio) { |
| 739 if (!audio_decoder_->Start(current_time)) { | 833 if (!audio_decoder_->Start(current_time)) { |
| 740 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | 834 return kStartFailed; |
| 741 return; | |
| 742 } | 835 } |
| 743 | 836 |
| 744 // Attach listener on UI thread | 837 // Attach listener on UI thread |
| 745 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); | 838 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); |
| 746 } | 839 } |
| 747 | 840 |
| 748 if (do_video) { | 841 if (do_video) { |
| 749 if (!video_decoder_->Start(current_time)) { | 842 if (!video_decoder_->Start(current_time)) { |
| 750 GetMediaTaskRunner()->PostTask(FROM_HERE, error_cb_); | 843 return kStartFailed; |
| 751 return; | |
| 752 } | 844 } |
| 753 } | 845 } |
| 846 |
| 847 return kStartOk; |
| 754 } | 848 } |
| 755 | 849 |
| 756 void MediaCodecPlayer::StopDecoders() { | 850 void MediaCodecPlayer::StopDecoders() { |
| 757 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 851 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 758 DVLOG(1) << __FUNCTION__; | 852 DVLOG(1) << __FUNCTION__; |
| 759 | 853 |
| 854 video_decoder_->SyncStop(); |
| 760 audio_decoder_->SyncStop(); | 855 audio_decoder_->SyncStop(); |
| 761 video_decoder_->SyncStop(); | |
| 762 } | 856 } |
| 763 | 857 |
| 764 void MediaCodecPlayer::RequestToStopDecoders() { | 858 void MediaCodecPlayer::RequestToStopDecoders() { |
| 765 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 859 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 766 DVLOG(1) << __FUNCTION__; | 860 DVLOG(1) << __FUNCTION__; |
| 767 | 861 |
| 768 bool do_audio = false; | 862 bool do_audio = false; |
| 769 bool do_video = false; | 863 bool do_video = false; |
| 770 | 864 |
| 771 if (audio_decoder_->IsPrefetchingOrPlaying()) | 865 if (audio_decoder_->IsPrefetchingOrPlaying()) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 782 if (do_audio) | 876 if (do_audio) |
| 783 audio_decoder_->RequestToStop(); | 877 audio_decoder_->RequestToStop(); |
| 784 if (do_video) | 878 if (do_video) |
| 785 video_decoder_->RequestToStop(); | 879 video_decoder_->RequestToStop(); |
| 786 } | 880 } |
| 787 | 881 |
| 788 void MediaCodecPlayer::RequestDemuxerSeek(base::TimeDelta seek_time, | 882 void MediaCodecPlayer::RequestDemuxerSeek(base::TimeDelta seek_time, |
| 789 bool is_browser_seek) { | 883 bool is_browser_seek) { |
| 790 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 884 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 791 DVLOG(1) << __FUNCTION__ << " " << seek_time | 885 DVLOG(1) << __FUNCTION__ << " " << seek_time |
| 792 << (is_browser_seek ? " browser_seek" : ""); | 886 << (is_browser_seek ? " BROWSER_SEEK" : ""); |
| 793 | 887 |
| 794 // Flush decoders before requesting demuxer. | 888 // Flush decoders before requesting demuxer. |
| 795 audio_decoder_->Flush(); | 889 audio_decoder_->Flush(); |
| 796 video_decoder_->Flush(); | 890 video_decoder_->Flush(); |
| 797 | 891 |
| 798 // Save active seek data. Logically it is attached to STATE_WAITING_FOR_SEEK. | 892 // Save active seek data. Logically it is attached to kStateWaitingForSeek. |
| 799 DCHECK(state_ == STATE_WAITING_FOR_SEEK); | 893 DCHECK_EQ(kStateWaitingForSeek, state_); |
| 800 seek_info_.reset(new SeekInfo(seek_time, is_browser_seek)); | 894 seek_info_.reset(new SeekInfo(seek_time, is_browser_seek)); |
| 801 | 895 |
| 802 demuxer_->RequestDemuxerSeek(seek_time, is_browser_seek); | 896 demuxer_->RequestDemuxerSeek(seek_time, is_browser_seek); |
| 803 } | 897 } |
| 804 | 898 |
| 805 void MediaCodecPlayer::ReleaseDecoderResources() { | 899 void MediaCodecPlayer::ReleaseDecoderResources() { |
| 806 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 900 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 807 DVLOG(1) << __FUNCTION__; | 901 DVLOG(1) << __FUNCTION__; |
| 808 | 902 |
| 809 if (audio_decoder_) | 903 if (audio_decoder_) |
| 810 audio_decoder_->ReleaseDecoderResources(); | 904 audio_decoder_->ReleaseDecoderResources(); |
| 811 | 905 |
| 812 if (video_decoder_) | 906 if (video_decoder_) |
| 813 video_decoder_->ReleaseDecoderResources(); | 907 video_decoder_->ReleaseDecoderResources(); |
| 814 | 908 |
| 815 // At this point decoder threads should not be running | 909 // At this point decoder threads should not be running |
| 816 if (interpolator_.interpolating()) | 910 if (interpolator_.interpolating()) |
| 817 interpolator_.StopInterpolating(); | 911 interpolator_.StopInterpolating(); |
| 818 } | 912 } |
| 819 | 913 |
| 820 void MediaCodecPlayer::CreateDecoders() { | 914 void MediaCodecPlayer::CreateDecoders() { |
| 821 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 915 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 822 DVLOG(1) << __FUNCTION__; | 916 DVLOG(1) << __FUNCTION__; |
| 823 | 917 |
| 824 error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); | 918 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); |
| 825 | 919 |
| 826 audio_decoder_.reset(new MediaCodecAudioDecoder( | 920 audio_decoder_.reset(new MediaCodecAudioDecoder( |
| 827 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 921 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |
| 828 media_weak_this_, DemuxerStream::AUDIO), | 922 media_weak_this_, DemuxerStream::AUDIO), |
| 829 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 923 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
| 830 DemuxerStream::AUDIO), | 924 DemuxerStream::AUDIO), |
| 831 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), error_cb_, | 925 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), |
| 926 internal_error_cb_, |
| 832 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 927 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
| 833 DemuxerStream::AUDIO))); | 928 DemuxerStream::AUDIO))); |
| 834 | 929 |
| 835 video_decoder_.reset(new MediaCodecVideoDecoder( | 930 video_decoder_.reset(new MediaCodecVideoDecoder( |
| 836 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 931 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |
| 837 media_weak_this_, DemuxerStream::VIDEO), | 932 media_weak_this_, DemuxerStream::VIDEO), |
| 838 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 933 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
| 839 DemuxerStream::VIDEO), | 934 DemuxerStream::VIDEO), |
| 840 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), error_cb_, | 935 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_), |
| 936 internal_error_cb_, |
| 841 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 937 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
| 842 DemuxerStream::VIDEO), | 938 DemuxerStream::VIDEO), |
| 843 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), | 939 base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), |
| 844 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); | 940 base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); |
| 845 } | 941 } |
| 846 | 942 |
| 847 bool MediaCodecPlayer::AudioFinished() const { | 943 bool MediaCodecPlayer::AudioFinished() const { |
| 848 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); | 944 return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); |
| 849 } | 945 } |
| 850 | 946 |
| 851 bool MediaCodecPlayer::VideoFinished() const { | 947 bool MediaCodecPlayer::VideoFinished() const { |
| 852 return video_decoder_->IsCompleted() || !video_decoder_->HasStream(); | 948 return video_decoder_->IsCompleted() || !video_decoder_->HasStream(); |
| 853 } | 949 } |
| 854 | 950 |
| 855 base::TimeDelta MediaCodecPlayer::GetInterpolatedTime() { | 951 base::TimeDelta MediaCodecPlayer::GetInterpolatedTime() { |
| 856 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 952 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 857 | 953 |
| 858 base::TimeDelta interpolated_time = interpolator_.GetInterpolatedTime(); | 954 base::TimeDelta interpolated_time = interpolator_.GetInterpolatedTime(); |
| 859 return std::min(interpolated_time, duration_); | 955 return std::min(interpolated_time, duration_); |
| 860 } | 956 } |
| 861 | 957 |
| 862 #undef RETURN_STRING | 958 #undef RETURN_STRING |
| 863 #define RETURN_STRING(x) \ | 959 #define RETURN_STRING(x) \ |
| 864 case x: \ | 960 case x: \ |
| 865 return #x; | 961 return #x; |
| 866 | 962 |
| 867 const char* MediaCodecPlayer::AsString(PlayerState state) { | 963 const char* MediaCodecPlayer::AsString(PlayerState state) { |
| 868 switch (state) { | 964 switch (state) { |
| 869 RETURN_STRING(STATE_PAUSED); | 965 RETURN_STRING(kStatePaused); |
| 870 RETURN_STRING(STATE_WAITING_FOR_CONFIG); | 966 RETURN_STRING(kStateWaitingForConfig); |
| 871 RETURN_STRING(STATE_PREFETCHING); | 967 RETURN_STRING(kStatePrefetching); |
| 872 RETURN_STRING(STATE_PLAYING); | 968 RETURN_STRING(kStatePlaying); |
| 873 RETURN_STRING(STATE_STOPPING); | 969 RETURN_STRING(kStateStopping); |
| 874 RETURN_STRING(STATE_WAITING_FOR_SURFACE); | 970 RETURN_STRING(kStateWaitingForSurface); |
| 875 RETURN_STRING(STATE_WAITING_FOR_SEEK); | 971 RETURN_STRING(kStateWaitingForSeek); |
| 876 RETURN_STRING(STATE_ERROR); | 972 RETURN_STRING(kStateError); |
| 877 } | 973 } |
| 878 return nullptr; // crash early | 974 return nullptr; // crash early |
| 879 } | 975 } |
| 880 | 976 |
| 881 #undef RETURN_STRING | 977 #undef RETURN_STRING |
| 882 | 978 |
| 883 } // namespace media | 979 } // namespace media |
| OLD | NEW |