| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 // Currently the unit tests wait for the MediaCodecPlayer destruction by | 92 // Currently the unit tests wait for the MediaCodecPlayer destruction by |
| 93 // 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. |
| 94 // 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 |
| 95 // the unit tests happy. | 95 // the unit tests happy. |
| 96 | 96 |
| 97 if (video_decoder_) | 97 if (video_decoder_) |
| 98 video_decoder_->ReleaseDecoderResources(); | 98 video_decoder_->ReleaseDecoderResources(); |
| 99 if (audio_decoder_) | 99 if (audio_decoder_) |
| 100 audio_decoder_->ReleaseDecoderResources(); | 100 audio_decoder_->ReleaseDecoderResources(); |
| 101 | 101 |
| 102 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 103 |
| 102 if (drm_bridge_) { | 104 if (drm_bridge_) { |
| 103 DCHECK(cdm_registration_id_); | 105 DCHECK(cdm_registration_id_); |
| 104 drm_bridge_->UnregisterPlayer(cdm_registration_id_); | 106 drm_bridge_->UnregisterPlayer(cdm_registration_id_); |
| 105 } | 107 } |
| 106 } | 108 } |
| 107 | 109 |
| 108 void MediaCodecPlayer::Initialize() { | 110 void MediaCodecPlayer::Initialize() { |
| 109 DVLOG(1) << __FUNCTION__; | 111 DVLOG(1) << __FUNCTION__; |
| 110 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 112 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 111 | 113 |
| (...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 default: | 802 default: |
| 801 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); | 803 // DVLOG(0) << __FUNCTION__ << " illegal state: " << AsString(state_); |
| 802 // NOTREACHED(); | 804 // NOTREACHED(); |
| 803 // Ignore! There can be a race condition: audio posts OnStopDone, | 805 // Ignore! There can be a race condition: audio posts OnStopDone, |
| 804 // then video posts, then first OnStopDone arrives at which point | 806 // then video posts, then first OnStopDone arrives at which point |
| 805 // both streams are already stopped, then second OnStopDone arrives. When | 807 // both streams are already stopped, then second OnStopDone arrives. When |
| 806 // the second one arrives, the state us not kStateStopping any more. | 808 // the second one arrives, the state us not kStateStopping any more. |
| 807 return; | 809 return; |
| 808 } | 810 } |
| 809 | 811 |
| 812 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 813 |
| 810 // DetachListener to UI thread | 814 // DetachListener to UI thread |
| 811 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); | 815 ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); |
| 812 | 816 |
| 813 if (AudioFinished() && VideoFinished()) | 817 if (AudioFinished() && VideoFinished()) |
| 814 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); | 818 ui_task_runner_->PostTask(FROM_HERE, completion_cb_); |
| 815 } | 819 } |
| 816 | 820 |
| 817 void MediaCodecPlayer::OnMissingKeyReported(DemuxerStream::Type type) { | 821 void MediaCodecPlayer::OnMissingKeyReported(DemuxerStream::Type type) { |
| 818 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 822 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 819 DVLOG(1) << __FUNCTION__ << " " << type; | 823 DVLOG(1) << __FUNCTION__ << " " << type; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 844 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { | 848 void MediaCodecPlayer::OnStarvation(DemuxerStream::Type type) { |
| 845 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 849 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 846 DVLOG(1) << __FUNCTION__ << " stream type:" << type; | 850 DVLOG(1) << __FUNCTION__ << " stream type:" << type; |
| 847 | 851 |
| 848 if (state_ != kStatePlaying) | 852 if (state_ != kStatePlaying) |
| 849 return; // Ignore | 853 return; // Ignore |
| 850 | 854 |
| 851 SetState(kStateStopping); | 855 SetState(kStateStopping); |
| 852 RequestToStopDecoders(); | 856 RequestToStopDecoders(); |
| 853 SetPendingStart(true); | 857 SetPendingStart(true); |
| 858 |
| 859 media_stat_->AddStarvation(); |
| 854 } | 860 } |
| 855 | 861 |
| 856 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type, | 862 void MediaCodecPlayer::OnTimeIntervalUpdate(DemuxerStream::Type type, |
| 857 base::TimeDelta now_playing, | 863 base::TimeDelta now_playing, |
| 858 base::TimeDelta last_buffered, | 864 base::TimeDelta last_buffered, |
| 859 bool postpone) { | 865 bool postpone) { |
| 860 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 866 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 861 | 867 |
| 862 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing | 868 DVLOG(2) << __FUNCTION__ << ": stream type:" << type << " [" << now_playing |
| 863 << "," << last_buffered << "]" << (postpone ? " postpone" : ""); | 869 << "," << last_buffered << "]" << (postpone ? " postpone" : ""); |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartDecoders() { | 1245 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartDecoders() { |
| 1240 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1246 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 1241 | 1247 |
| 1242 if (!interpolator_.interpolating()) | 1248 if (!interpolator_.interpolating()) |
| 1243 interpolator_.StartInterpolating(); | 1249 interpolator_.StartInterpolating(); |
| 1244 | 1250 |
| 1245 base::TimeDelta current_time = GetInterpolatedTime(); | 1251 base::TimeDelta current_time = GetInterpolatedTime(); |
| 1246 | 1252 |
| 1247 DVLOG(1) << __FUNCTION__ << " current_time:" << current_time; | 1253 DVLOG(1) << __FUNCTION__ << " current_time:" << current_time; |
| 1248 | 1254 |
| 1255 // At this point decoder threads are either not running at all or their |
| 1256 // message pumps are in the idle state after the preroll is done. |
| 1257 media_stat_->Start(current_time); |
| 1258 |
| 1249 if (!AudioFinished()) { | 1259 if (!AudioFinished()) { |
| 1250 if (!audio_decoder_->Start(current_time)) | 1260 if (!audio_decoder_->Start(current_time)) |
| 1251 return kStartFailed; | 1261 return kStartFailed; |
| 1252 | 1262 |
| 1253 // Attach listener on UI thread | 1263 // Attach listener on UI thread |
| 1254 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); | 1264 ui_task_runner_->PostTask(FROM_HERE, attach_listener_cb_); |
| 1255 } | 1265 } |
| 1256 | 1266 |
| 1257 if (!VideoFinished()) { | 1267 if (!VideoFinished()) { |
| 1258 if (!video_decoder_->Start(current_time)) | 1268 if (!video_decoder_->Start(current_time)) |
| 1259 return kStartFailed; | 1269 return kStartFailed; |
| 1260 } | 1270 } |
| 1261 | 1271 |
| 1262 return kStartOk; | 1272 return kStartOk; |
| 1263 } | 1273 } |
| 1264 | 1274 |
| 1265 void MediaCodecPlayer::StopDecoders() { | 1275 void MediaCodecPlayer::StopDecoders() { |
| 1266 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1276 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 1267 DVLOG(1) << __FUNCTION__; | 1277 DVLOG(1) << __FUNCTION__; |
| 1268 | 1278 |
| 1269 video_decoder_->SyncStop(); | 1279 video_decoder_->SyncStop(); |
| 1270 audio_decoder_->SyncStop(); | 1280 audio_decoder_->SyncStop(); |
| 1281 |
| 1282 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 1271 } | 1283 } |
| 1272 | 1284 |
| 1273 void MediaCodecPlayer::RequestToStopDecoders() { | 1285 void MediaCodecPlayer::RequestToStopDecoders() { |
| 1274 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1286 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 1275 DVLOG(1) << __FUNCTION__; | 1287 DVLOG(1) << __FUNCTION__; |
| 1276 | 1288 |
| 1277 bool do_audio = false; | 1289 bool do_audio = false; |
| 1278 bool do_video = false; | 1290 bool do_video = false; |
| 1279 | 1291 |
| 1280 if (audio_decoder_->IsPrefetchingOrPlaying()) | 1292 if (audio_decoder_->IsPrefetchingOrPlaying()) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1318 | 1330 |
| 1319 if (audio_decoder_) | 1331 if (audio_decoder_) |
| 1320 audio_decoder_->ReleaseDecoderResources(); | 1332 audio_decoder_->ReleaseDecoderResources(); |
| 1321 | 1333 |
| 1322 if (video_decoder_) | 1334 if (video_decoder_) |
| 1323 video_decoder_->ReleaseDecoderResources(); | 1335 video_decoder_->ReleaseDecoderResources(); |
| 1324 | 1336 |
| 1325 // At this point decoder threads should not be running | 1337 // At this point decoder threads should not be running |
| 1326 if (interpolator_.interpolating()) | 1338 if (interpolator_.interpolating()) |
| 1327 interpolator_.StopInterpolating(); | 1339 interpolator_.StopInterpolating(); |
| 1340 |
| 1341 media_stat_->StopAndReport(GetInterpolatedTime()); |
| 1328 } | 1342 } |
| 1329 | 1343 |
| 1330 void MediaCodecPlayer::CreateDecoders() { | 1344 void MediaCodecPlayer::CreateDecoders() { |
| 1331 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 1345 DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |
| 1332 DVLOG(1) << __FUNCTION__; | 1346 DVLOG(1) << __FUNCTION__; |
| 1333 | 1347 |
| 1334 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); | 1348 internal_error_cb_ = base::Bind(&MediaCodecPlayer::OnError, media_weak_this_); |
| 1335 | 1349 |
| 1350 media_stat_.reset(new MediaStatistics()); |
| 1351 |
| 1336 audio_decoder_.reset(new MediaCodecAudioDecoder( | 1352 audio_decoder_.reset(new MediaCodecAudioDecoder( |
| 1337 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 1353 GetMediaTaskRunner(), &media_stat_->audio_frame_stats(), |
| 1338 media_weak_this_, DemuxerStream::AUDIO), | 1354 base::Bind(&MediaCodecPlayer::RequestDemuxerData, media_weak_this_, |
| 1355 DemuxerStream::AUDIO), |
| 1339 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 1356 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
| 1340 DemuxerStream::AUDIO), | 1357 DemuxerStream::AUDIO), |
| 1341 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, | 1358 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, |
| 1342 DemuxerStream::AUDIO), | 1359 DemuxerStream::AUDIO), |
| 1343 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, | 1360 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, |
| 1344 DemuxerStream::AUDIO), | 1361 DemuxerStream::AUDIO), |
| 1345 base::Bind(&MediaCodecPlayer::OnMissingKeyReported, media_weak_this_, | 1362 base::Bind(&MediaCodecPlayer::OnMissingKeyReported, media_weak_this_, |
| 1346 DemuxerStream::AUDIO), | 1363 DemuxerStream::AUDIO), |
| 1347 internal_error_cb_, | 1364 internal_error_cb_, |
| 1348 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 1365 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
| 1349 DemuxerStream::AUDIO))); | 1366 DemuxerStream::AUDIO))); |
| 1350 | 1367 |
| 1351 video_decoder_.reset(new MediaCodecVideoDecoder( | 1368 video_decoder_.reset(new MediaCodecVideoDecoder( |
| 1352 GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 1369 GetMediaTaskRunner(), &media_stat_->video_frame_stats(), |
| 1353 media_weak_this_, DemuxerStream::VIDEO), | 1370 base::Bind(&MediaCodecPlayer::RequestDemuxerData, media_weak_this_, |
| 1371 DemuxerStream::VIDEO), |
| 1354 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 1372 base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |
| 1355 DemuxerStream::VIDEO), | 1373 DemuxerStream::VIDEO), |
| 1356 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, | 1374 base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, |
| 1357 DemuxerStream::VIDEO), | 1375 DemuxerStream::VIDEO), |
| 1358 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, | 1376 base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, |
| 1359 DemuxerStream::VIDEO), | 1377 DemuxerStream::VIDEO), |
| 1360 base::Bind(&MediaCodecPlayer::OnMissingKeyReported, media_weak_this_, | 1378 base::Bind(&MediaCodecPlayer::OnMissingKeyReported, media_weak_this_, |
| 1361 DemuxerStream::VIDEO), | 1379 DemuxerStream::VIDEO), |
| 1362 internal_error_cb_, | 1380 internal_error_cb_, |
| 1363 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 1381 base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1399 RETURN_STRING(kStateWaitingForMediaCrypto); | 1417 RETURN_STRING(kStateWaitingForMediaCrypto); |
| 1400 RETURN_STRING(kStateWaitingForSeek); | 1418 RETURN_STRING(kStateWaitingForSeek); |
| 1401 RETURN_STRING(kStateError); | 1419 RETURN_STRING(kStateError); |
| 1402 } | 1420 } |
| 1403 return nullptr; // crash early | 1421 return nullptr; // crash early |
| 1404 } | 1422 } |
| 1405 | 1423 |
| 1406 #undef RETURN_STRING | 1424 #undef RETURN_STRING |
| 1407 | 1425 |
| 1408 } // namespace media | 1426 } // namespace media |
| OLD | NEW |