| 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/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 // Finish initializaton on Media thread | 80 // Finish initializaton on Media thread |
| 81 GetMediaTaskRunner()->PostTask( | 81 GetMediaTaskRunner()->PostTask( |
| 82 FROM_HERE, base::Bind(&MediaCodecPlayer::Initialize, media_weak_this_)); | 82 FROM_HERE, base::Bind(&MediaCodecPlayer::Initialize, media_weak_this_)); |
| 83 } | 83 } |
| 84 | 84 |
| 85 MediaCodecPlayer::~MediaCodecPlayer() | 85 MediaCodecPlayer::~MediaCodecPlayer() |
| 86 { | 86 { |
| 87 DVLOG(1) << "MediaCodecPlayer::~MediaCodecPlayer"; | 87 DVLOG(1) << "MediaCodecPlayer::~MediaCodecPlayer"; |
| 88 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 88 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 89 | 89 |
| 90 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 91 |
| 90 // Currently the unit tests wait for the MediaCodecPlayer destruction by | 92 // Currently the unit tests wait for the MediaCodecPlayer destruction by |
| 91 // watching the demuxer, which is destroyed as one of the member variables. | 93 // watching the demuxer, which is destroyed as one of the member variables. |
| 92 // Release the codecs here, before any member variable is destroyed to make | 94 // Release the codecs here, before any member variable is destroyed to make |
| 93 // the unit tests happy. | 95 // the unit tests happy. |
| 94 | 96 |
| 95 if (video_decoder_) | 97 if (video_decoder_) |
| 96 video_decoder_->ReleaseDecoderResources(); | 98 video_decoder_->ReleaseDecoderResources(); |
| 97 if (audio_decoder_) | 99 if (audio_decoder_) |
| 98 audio_decoder_->ReleaseDecoderResources(); | 100 audio_decoder_->ReleaseDecoderResources(); |
| 99 | 101 |
| 100 media_stat_->StopAndReport(GetInterpolatedTime()); | |
| 101 | |
| 102 if (cdm_) { | 102 if (cdm_) { |
| 103 DCHECK(cdm_registration_id_); | 103 DCHECK(cdm_registration_id_); |
| 104 static_cast<MediaDrmBridge*>(cdm_.get()) | 104 static_cast<MediaDrmBridge*>(cdm_.get()) |
| 105 ->UnregisterPlayer(cdm_registration_id_); | 105 ->UnregisterPlayer(cdm_registration_id_); |
| 106 } | 106 } |
| 107 } | 107 } |
| 108 | 108 |
| 109 void MediaCodecPlayer::Initialize() { | 109 void MediaCodecPlayer::Initialize() { |
| 110 DVLOG(1) << __FUNCTION__; | 110 DVLOG(1) << __FUNCTION__; |
| 111 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 111 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 NOTREACHED(); | 240 NOTREACHED(); |
| 241 break; | 241 break; |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 | 244 |
| 245 void MediaCodecPlayer::Pause(bool is_media_related_action) { | 245 void MediaCodecPlayer::Pause(bool is_media_related_action) { |
| 246 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); | 246 RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); |
| 247 | 247 |
| 248 DVLOG(1) << __FUNCTION__; | 248 DVLOG(1) << __FUNCTION__; |
| 249 | 249 |
| 250 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 251 |
| 250 SetPendingStart(false); | 252 SetPendingStart(false); |
| 251 | 253 |
| 252 switch (state_) { | 254 switch (state_) { |
| 253 case kStateWaitingForConfig: | 255 case kStateWaitingForConfig: |
| 254 case kStateWaitingForPermission: | 256 case kStateWaitingForPermission: |
| 255 case kStatePrefetching: | 257 case kStatePrefetching: |
| 256 case kStateWaitingForSurface: | 258 case kStateWaitingForSurface: |
| 257 case kStateWaitingForKey: | 259 case kStateWaitingForKey: |
| 258 case kStateWaitingForMediaCrypto: | 260 case kStateWaitingForMediaCrypto: |
| 259 SetState(kStatePaused); | 261 SetState(kStatePaused); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 272 NOTREACHED(); | 274 NOTREACHED(); |
| 273 break; | 275 break; |
| 274 } | 276 } |
| 275 } | 277 } |
| 276 | 278 |
| 277 void MediaCodecPlayer::SeekTo(base::TimeDelta timestamp) { | 279 void MediaCodecPlayer::SeekTo(base::TimeDelta timestamp) { |
| 278 RUN_ON_MEDIA_THREAD(SeekTo, timestamp); | 280 RUN_ON_MEDIA_THREAD(SeekTo, timestamp); |
| 279 | 281 |
| 280 DVLOG(1) << __FUNCTION__ << " " << timestamp; | 282 DVLOG(1) << __FUNCTION__ << " " << timestamp; |
| 281 | 283 |
| 284 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 285 |
| 282 switch (state_) { | 286 switch (state_) { |
| 283 case kStatePaused: | 287 case kStatePaused: |
| 284 SetState(kStateWaitingForSeek); | 288 SetState(kStateWaitingForSeek); |
| 285 RequestDemuxerSeek(timestamp); | 289 RequestDemuxerSeek(timestamp); |
| 286 break; | 290 break; |
| 287 case kStateWaitingForConfig: | 291 case kStateWaitingForConfig: |
| 288 case kStateWaitingForPermission: | 292 case kStateWaitingForPermission: |
| 289 case kStatePrefetching: | 293 case kStatePrefetching: |
| 290 case kStateWaitingForSurface: | 294 case kStateWaitingForSurface: |
| 291 case kStateWaitingForKey: | 295 case kStateWaitingForKey: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 322 // track the active players. We should pass | 326 // track the active players. We should pass |
| 323 // MediaThrottler::OnDecodeRequestFinished() to this class in the ctor, but | 327 // MediaThrottler::OnDecodeRequestFinished() to this class in the ctor, but |
| 324 // also need a way for BrowserMediaPlayerManager to track active players. | 328 // also need a way for BrowserMediaPlayerManager to track active players. |
| 325 if (ui_task_runner_->BelongsToCurrentThread()) | 329 if (ui_task_runner_->BelongsToCurrentThread()) |
| 326 on_decoder_resources_released_cb_.Run(player_id()); | 330 on_decoder_resources_released_cb_.Run(player_id()); |
| 327 | 331 |
| 328 RUN_ON_MEDIA_THREAD(Release); | 332 RUN_ON_MEDIA_THREAD(Release); |
| 329 | 333 |
| 330 DVLOG(1) << __FUNCTION__; | 334 DVLOG(1) << __FUNCTION__; |
| 331 | 335 |
| 336 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 337 |
| 332 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser | 338 // Stop decoding threads and delete MediaCodecs, but keep IPC between browser |
| 333 // and renderer processes going. Seek should work across and after Release(). | 339 // and renderer processes going. Seek should work across and after Release(). |
| 334 | 340 |
| 335 ReleaseDecoderResources(); | 341 ReleaseDecoderResources(); |
| 336 | 342 |
| 337 SetPendingStart(false); | 343 SetPendingStart(false); |
| 338 | 344 |
| 339 if (state_ != kStateWaitingForSeek) | 345 if (state_ != kStateWaitingForSeek) |
| 340 SetState(kStatePaused); | 346 SetState(kStatePaused); |
| 341 | 347 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 default: | 821 default: |
| 816 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); | 822 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); |
| 817 // NOTREACHED(); | 823 // NOTREACHED(); |
| 818 // Ignore! There can be a race condition: audio posts OnStopDone, | 824 // Ignore! There can be a race condition: audio posts OnStopDone, |
| 819 // then video posts, then first OnStopDone arrives at which point | 825 // then video posts, then first OnStopDone arrives at which point |
| 820 // both streams are already stopped, then second OnStopDone arrives. When | 826 // both streams are already stopped, then second OnStopDone arrives. When |
| 821 // the second one arrives, the state us not kStateStopping any more. | 827 // the second one arrives, the state us not kStateStopping any more. |
| 822 return; | 828 return; |
| 823 } | 829 } |
| 824 | 830 |
| 825 media_stat_->StopAndReport(GetInterpolatedTime()); | |
| 826 | |
| 827 // DetachListener to UI thread | 831 // DetachListener to UI thread |
| 828 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); | 832 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); |
| 829 | 833 |
| 830 if (AudioFinished() && VideoFinished()) | 834 if (AudioFinished() && VideoFinished()) { |
| 835 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 831 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); | 836 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); |
| 837 } |
| 832 } | 838 } |
| 833 | 839 |
| 834 void MediaCodecPlayer::OnMissingKeyReported(DemuxerStream::Type type) { | 840 void MediaCodecPlayer::OnMissingKeyReported(DemuxerStream::Type type) { |
| 835 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 841 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 836 DVLOG(1) << __FUNCTION__ << " " << type; | 842 DVLOG(1) << __FUNCTION__ << " " << type; |
| 837 | 843 |
| 838 // Request stop and restart to pick up the key. | 844 // Request stop and restart to pick up the key. |
| 839 key_is_required_ = true; | 845 key_is_required_ = true; |
| 840 | 846 |
| 841 if (state_ == kStatePlaying) { | 847 if (state_ == kStatePlaying) { |
| 848 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 849 |
| 842 SetState(kStateStopping); | 850 SetState(kStateStopping); |
| 843 RequestToStopDecoders(); | 851 RequestToStopDecoders(); |
| 844 SetPendingStart(true); | 852 SetPendingStart(true); |
| 845 } | 853 } |
| 846 } | 854 } |
| 847 | 855 |
| 848 void MediaCodecPlayer::OnError() { | 856 void MediaCodecPlayer::OnError() { |
| 849 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 857 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 850 DVLOG(1) << __FUNCTION__; | 858 DVLOG(1) << __FUNCTION__; |
| 851 | 859 |
| 860 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 861 |
| 852 // kStateError blocks all events | 862 // kStateError blocks all events |
| 853 SetState(kStateError); | 863 SetState(kStateError); |
| 854 | 864 |
| 855 ReleaseDecoderResources(); | 865 ReleaseDecoderResources(); |
| 856 | 866 |
| 857 ui_task_runner_->PostTask(FROM_HERE, | 867 ui_task_runner_->PostTask(FROM_HERE, |
| 858 base::Bind(error_cb_, MEDIA_ERROR_DECODE)); | 868 base::Bind(error_cb_, MEDIA_ERROR_DECODE)); |
| 859 } | 869 } |
| 860 | 870 |
| 861 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { | 871 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1236 | 1246 |
| 1237 if (!interpolator_.interpolating()) | 1247 if (!interpolator_.interpolating()) |
| 1238 interpolator_.StartInterpolating(); | 1248 interpolator_.StartInterpolating(); |
| 1239 | 1249 |
| 1240 base::TimeDelta current_time = GetInterpolatedTime(); | 1250 base::TimeDelta current_time = GetInterpolatedTime(); |
| 1241 | 1251 |
| 1242 DVLOG(1) << __FUNCTION__ << " current_time:" << current_time; | 1252 DVLOG(1) << __FUNCTION__ << " current_time:" << current_time; |
| 1243 | 1253 |
| 1244 // At this point decoder threads are either not running at all or their | 1254 // At this point decoder threads are either not running at all or their |
| 1245 // message pumps are in the idle state after the preroll is done. | 1255 // message pumps are in the idle state after the preroll is done. |
| 1246 media_stat_->Start(current_time); | |
| 1247 | 1256 |
| 1248 if (!AudioFinished()) { | 1257 if (!AudioFinished()) { |
| 1249 if (!audio_decoder_->Start(current_time)) | 1258 if (!audio_decoder_->Start(current_time)) |
| 1250 return kStartFailed; | 1259 return kStartFailed; |
| 1251 | 1260 |
| 1252 // Attach listener on UI thread | 1261 // Attach listener on UI thread |
| 1253 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); | 1262 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); |
| 1254 } | 1263 } |
| 1255 | 1264 |
| 1256 if (!VideoFinished()) { | 1265 if (!VideoFinished()) { |
| 1257 if (!video_decoder_->Start(current_time)) | 1266 if (!video_decoder_->Start(current_time)) |
| 1258 return kStartFailed; | 1267 return kStartFailed; |
| 1259 } | 1268 } |
| 1260 | 1269 |
| 1270 media_stat_->Start(current_time); |
| 1271 |
| 1261 return kStartOk; | 1272 return kStartOk; |
| 1262 } | 1273 } |
| 1263 | 1274 |
| 1264 void MediaCodecPlayer::StopDecoders() { | 1275 void MediaCodecPlayer::StopDecoders() { |
| 1265 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1276 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 1266 DVLOG(1) << __FUNCTION__; | 1277 DVLOG(1) << __FUNCTION__; |
| 1267 | 1278 |
| 1268 video_decoder_->SyncStop(); | 1279 video_decoder_->SyncStop(); |
| 1269 audio_decoder_->SyncStop(); | 1280 audio_decoder_->SyncStop(); |
| 1270 | |
| 1271 media_stat_->StopAndReport(GetInterpolatedTime()); | |
| 1272 } | 1281 } |
| 1273 | 1282 |
| 1274 void MediaCodecPlayer::RequestToStopDecoders() { | 1283 void MediaCodecPlayer::RequestToStopDecoders() { |
| 1275 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1284 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 1276 DVLOG(1) << __FUNCTION__; | 1285 DVLOG(1) << __FUNCTION__; |
| 1277 | 1286 |
| 1278 bool do_audio = false; | 1287 bool do_audio = false; |
| 1279 bool do_video = false; | 1288 bool do_video = false; |
| 1280 | 1289 |
| 1281 if (audio_decoder_->IsPrefetchingOrPlaying()) | 1290 if (audio_decoder_->IsPrefetchingOrPlaying()) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 | 1328 |
| 1320 if (audio_decoder_) | 1329 if (audio_decoder_) |
| 1321 audio_decoder_->ReleaseDecoderResources(); | 1330 audio_decoder_->ReleaseDecoderResources(); |
| 1322 | 1331 |
| 1323 if (video_decoder_) | 1332 if (video_decoder_) |
| 1324 video_decoder_->ReleaseDecoderResources(); | 1333 video_decoder_->ReleaseDecoderResources(); |
| 1325 | 1334 |
| 1326 // At this point decoder threads should not be running | 1335 // At this point decoder threads should not be running |
| 1327 if (interpolator_.interpolating()) | 1336 if (interpolator_.interpolating()) |
| 1328 interpolator_.StopInterpolating(); | 1337 interpolator_.StopInterpolating(); |
| 1329 | |
| 1330 media_stat_->StopAndReport(GetInterpolatedTime()); | |
| 1331 } | 1338 } |
| 1332 | 1339 |
| 1333 void MediaCodecPlayer::CreateDecoders() { | 1340 void MediaCodecPlayer::CreateDecoders() { |
| 1334 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1341 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 1335 DVLOG(1) << __FUNCTION__; | 1342 DVLOG(1) << __FUNCTION__; |
| 1336 | 1343 |
| 1337 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); | 1344 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); |
| 1338 | 1345 |
| 1339 media_stat_.reset(new MediaStatistics()); | 1346 media_stat_.reset(new MediaStatistics()); |
| 1340 | 1347 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 RETURN_STRING(kStateWaitingForMediaCrypto); | 1413 RETURN_STRING(kStateWaitingForMediaCrypto); |
| 1407 RETURN_STRING(kStateWaitingForSeek); | 1414 RETURN_STRING(kStateWaitingForSeek); |
| 1408 RETURN_STRING(kStateError); | 1415 RETURN_STRING(kStateError); |
| 1409 } | 1416 } |
| 1410 return nullptr; // crash early | 1417 return nullptr; // crash early |
| 1411 } | 1418 } |
| 1412 | 1419 |
| 1413 #undef RETURN_STRING | 1420 #undef RETURN_STRING |
| 1414 | 1421 |
| 1415 } // namespace media | 1422 } // namespace media |
| OLD | NEW |