| 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" | 
|    11 #include "base/thread_task_runner_handle.h" |    11 #include "base/thread_task_runner_handle.h" | 
|    12 #include "base/threading/thread.h" |    12 #include "base/threading/thread.h" | 
|    13 #include "media/base/android/media_codec_audio_decoder.h" |    13 #include "media/base/android/media_codec_audio_decoder.h" | 
|    14 #include "media/base/android/media_codec_video_decoder.h" |    14 #include "media/base/android/media_codec_video_decoder.h" | 
 |    15 #include "media/base/android/media_drm_bridge.h" | 
|    15 #include "media/base/android/media_player_manager.h" |    16 #include "media/base/android/media_player_manager.h" | 
|    16 #include "media/base/timestamp_constants.h" |    17 #include "media/base/timestamp_constants.h" | 
|    17  |    18  | 
|    18 #define RUN_ON_MEDIA_THREAD(METHOD, ...)                                     \ |    19 #define RUN_ON_MEDIA_THREAD(METHOD, ...)                                     \ | 
|    19   do {                                                                       \ |    20   do {                                                                       \ | 
|    20     if (!GetMediaTaskRunner()->BelongsToCurrentThread()) {                   \ |    21     if (!GetMediaTaskRunner()->BelongsToCurrentThread()) {                   \ | 
|    21       DCHECK(ui_task_runner_->BelongsToCurrentThread());                     \ |    22       DCHECK(ui_task_runner_->BelongsToCurrentThread());                     \ | 
|    22       GetMediaTaskRunner()->PostTask(                                        \ |    23       GetMediaTaskRunner()->PostTask(                                        \ | 
|    23           FROM_HERE, base::Bind(&MediaCodecPlayer::METHOD, media_weak_this_, \ |    24           FROM_HERE, base::Bind(&MediaCodecPlayer::METHOD, media_weak_this_, \ | 
|    24                                 ##__VA_ARGS__));                             \ |    25                                 ##__VA_ARGS__));                             \ | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
|    55     : MediaPlayerAndroid(player_id, |    56     : MediaPlayerAndroid(player_id, | 
|    56                          manager.get(), |    57                          manager.get(), | 
|    57                          request_media_resources_cb, |    58                          request_media_resources_cb, | 
|    58                          frame_url), |    59                          frame_url), | 
|    59       ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), |    60       ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 
|    60       demuxer_(demuxer.Pass()), |    61       demuxer_(demuxer.Pass()), | 
|    61       state_(kStatePaused), |    62       state_(kStatePaused), | 
|    62       interpolator_(&default_tick_clock_), |    63       interpolator_(&default_tick_clock_), | 
|    63       pending_start_(false), |    64       pending_start_(false), | 
|    64       pending_seek_(kNoTimestamp()), |    65       pending_seek_(kNoTimestamp()), | 
 |    66       drm_bridge_(nullptr), | 
 |    67       cdm_registration_id_(0), | 
 |    68       is_protected_surface_required_(false), | 
 |    69       key_is_required_(false), | 
 |    70       key_is_added_(false), | 
|    65       media_weak_factory_(this) { |    71       media_weak_factory_(this) { | 
|    66   DCHECK(ui_task_runner_->BelongsToCurrentThread()); |    72   DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 
|    67  |    73  | 
|    68   DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; |    74   DVLOG(1) << "MediaCodecPlayer::MediaCodecPlayer: player_id:" << player_id; | 
|    69  |    75  | 
|    70   request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); |    76   request_resources_cb_ = base::Bind(request_media_resources_cb_, player_id); | 
|    71  |    77  | 
|    72   completion_cb_ = |    78   completion_cb_ = | 
|    73       base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); |    79       base::Bind(&MediaPlayerManager::OnPlaybackComplete, manager, player_id); | 
 |    80   key_required_cb_ = base::Bind(&MediaPlayerManager::OnWaitingForDecryptionKey, | 
 |    81                                 manager, player_id); | 
|    74   seek_done_cb_ = |    82   seek_done_cb_ = | 
|    75       base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); |    83       base::Bind(&MediaPlayerManager::OnSeekComplete, manager, player_id); | 
|    76   error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id); |    84   error_cb_ = base::Bind(&MediaPlayerManager::OnError, manager, player_id); | 
|    77   attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, |    85   attach_listener_cb_ = base::Bind(&MediaPlayerAndroid::AttachListener, | 
|    78                                    WeakPtrForUIThread(), nullptr); |    86                                    WeakPtrForUIThread(), nullptr); | 
|    79   detach_listener_cb_ = |    87   detach_listener_cb_ = | 
|    80       base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); |    88       base::Bind(&MediaPlayerAndroid::DetachListener, WeakPtrForUIThread()); | 
|    81   metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, |    89   metadata_changed_cb_ = base::Bind(&MediaPlayerAndroid::OnMediaMetadataChanged, | 
|    82                                     WeakPtrForUIThread()); |    90                                     WeakPtrForUIThread()); | 
|    83   time_update_cb_ = |    91   time_update_cb_ = | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|    97  |   105  | 
|    98   // Currently the unit tests wait for the MediaCodecPlayer destruction by |   106   // Currently the unit tests wait for the MediaCodecPlayer destruction by | 
|    99   // watching the demuxer, which is destroyed as one of the member variables. |   107   // watching the demuxer, which is destroyed as one of the member variables. | 
|   100   // Release the codecs here, before any member variable is destroyed to make |   108   // Release the codecs here, before any member variable is destroyed to make | 
|   101   // the unit tests happy. |   109   // the unit tests happy. | 
|   102  |   110  | 
|   103   if (video_decoder_) |   111   if (video_decoder_) | 
|   104     video_decoder_->ReleaseDecoderResources(); |   112     video_decoder_->ReleaseDecoderResources(); | 
|   105   if (audio_decoder_) |   113   if (audio_decoder_) | 
|   106     audio_decoder_->ReleaseDecoderResources(); |   114     audio_decoder_->ReleaseDecoderResources(); | 
 |   115  | 
 |   116   if (drm_bridge_) { | 
 |   117     DCHECK(cdm_registration_id_); | 
 |   118     drm_bridge_->UnregisterPlayer(cdm_registration_id_); | 
 |   119   } | 
|   107 } |   120 } | 
|   108  |   121  | 
|   109 void MediaCodecPlayer::Initialize() { |   122 void MediaCodecPlayer::Initialize() { | 
|   110   DVLOG(1) << __FUNCTION__; |   123   DVLOG(1) << __FUNCTION__; | 
|   111   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |   124   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   112  |   125  | 
|   113   interpolator_.SetUpperBound(base::TimeDelta()); |   126   interpolator_.SetUpperBound(base::TimeDelta()); | 
|   114  |   127  | 
|   115   CreateDecoders(); |   128   CreateDecoders(); | 
|   116  |   129  | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
|   144   // Save the empty-ness before we pass the surface to the decoder. |   157   // Save the empty-ness before we pass the surface to the decoder. | 
|   145   bool surface_is_empty = surface.IsEmpty(); |   158   bool surface_is_empty = surface.IsEmpty(); | 
|   146  |   159  | 
|   147   // Apparently RemoveVideoSurface() can be called several times in a row, |   160   // Apparently RemoveVideoSurface() can be called several times in a row, | 
|   148   // ignore the second and subsequent calls. |   161   // ignore the second and subsequent calls. | 
|   149   if (surface_is_empty && !video_decoder_->HasVideoSurface()) { |   162   if (surface_is_empty && !video_decoder_->HasVideoSurface()) { | 
|   150     DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring"; |   163     DVLOG(1) << __FUNCTION__ << ": surface already removed, ignoring"; | 
|   151     return; |   164     return; | 
|   152   } |   165   } | 
|   153  |   166  | 
 |   167   // Do not set unprotected surface if we know that we need a protected one. | 
 |   168   // Empty surface means the surface removal and we always allow for it. | 
 |   169   if (!surface_is_empty && is_protected_surface_required_ && | 
 |   170       !surface.is_protected()) { | 
 |   171     DVLOG(0) << __FUNCTION__ << ": surface is not protected, ignoring"; | 
 |   172     return; | 
 |   173   } | 
 |   174  | 
|   154   video_decoder_->SetVideoSurface(surface.Pass()); |   175   video_decoder_->SetVideoSurface(surface.Pass()); | 
|   155  |   176  | 
|   156   if (surface_is_empty) { |   177   if (surface_is_empty) { | 
|   157     // Remove video surface. |   178     // Remove video surface. | 
|   158     switch (state_) { |   179     switch (state_) { | 
|   159       case kStatePlaying: |   180       case kStatePlaying: | 
|   160         if (VideoFinished()) |   181         if (VideoFinished()) | 
|   161           break; |   182           break; | 
|   162  |   183  | 
|   163         DVLOG(1) << __FUNCTION__ << ": stopping and restarting"; |   184         DVLOG(1) << __FUNCTION__ << ": stopping and restarting"; | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   216       } |   237       } | 
|   217       break; |   238       break; | 
|   218     case kStateStopping: |   239     case kStateStopping: | 
|   219     case kStateWaitingForSeek: |   240     case kStateWaitingForSeek: | 
|   220       SetPendingStart(true); |   241       SetPendingStart(true); | 
|   221       break; |   242       break; | 
|   222     case kStateWaitingForConfig: |   243     case kStateWaitingForConfig: | 
|   223     case kStatePrefetching: |   244     case kStatePrefetching: | 
|   224     case kStatePlaying: |   245     case kStatePlaying: | 
|   225     case kStateWaitingForSurface: |   246     case kStateWaitingForSurface: | 
 |   247     case kStateWaitingForKey: | 
 |   248     case kStateWaitingForCrypto: | 
|   226     case kStateError: |   249     case kStateError: | 
|   227       break;  // Ignore |   250       break;  // Ignore | 
|   228     default: |   251     default: | 
|   229       NOTREACHED(); |   252       NOTREACHED(); | 
|   230       break; |   253       break; | 
|   231   } |   254   } | 
|   232 } |   255 } | 
|   233  |   256  | 
|   234 void MediaCodecPlayer::Pause(bool is_media_related_action) { |   257 void MediaCodecPlayer::Pause(bool is_media_related_action) { | 
|   235   RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); |   258   RUN_ON_MEDIA_THREAD(Pause, is_media_related_action); | 
|   236  |   259  | 
|   237   DVLOG(1) << __FUNCTION__; |   260   DVLOG(1) << __FUNCTION__; | 
|   238  |   261  | 
|   239   SetPendingStart(false); |   262   SetPendingStart(false); | 
|   240  |   263  | 
|   241   switch (state_) { |   264   switch (state_) { | 
|   242     case kStateWaitingForConfig: |   265     case kStateWaitingForConfig: | 
|   243     case kStatePrefetching: |   266     case kStatePrefetching: | 
|   244     case kStateWaitingForSurface: |   267     case kStateWaitingForSurface: | 
 |   268     case kStateWaitingForKey: | 
 |   269     case kStateWaitingForCrypto: | 
|   245       SetState(kStatePaused); |   270       SetState(kStatePaused); | 
|   246       StopDecoders(); |   271       StopDecoders(); | 
|   247       break; |   272       break; | 
|   248     case kStatePlaying: |   273     case kStatePlaying: | 
|   249       SetState(kStateStopping); |   274       SetState(kStateStopping); | 
|   250       RequestToStopDecoders(); |   275       RequestToStopDecoders(); | 
|   251       break; |   276       break; | 
|   252     case kStatePaused: |   277     case kStatePaused: | 
|   253     case kStateStopping: |   278     case kStateStopping: | 
|   254     case kStateWaitingForSeek: |   279     case kStateWaitingForSeek: | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|   266   DVLOG(1) << __FUNCTION__ << " " << timestamp; |   291   DVLOG(1) << __FUNCTION__ << " " << timestamp; | 
|   267  |   292  | 
|   268   switch (state_) { |   293   switch (state_) { | 
|   269     case kStatePaused: |   294     case kStatePaused: | 
|   270       SetState(kStateWaitingForSeek); |   295       SetState(kStateWaitingForSeek); | 
|   271       RequestDemuxerSeek(timestamp); |   296       RequestDemuxerSeek(timestamp); | 
|   272       break; |   297       break; | 
|   273     case kStateWaitingForConfig: |   298     case kStateWaitingForConfig: | 
|   274     case kStatePrefetching: |   299     case kStatePrefetching: | 
|   275     case kStateWaitingForSurface: |   300     case kStateWaitingForSurface: | 
 |   301     case kStateWaitingForKey: | 
 |   302     case kStateWaitingForCrypto: | 
|   276       SetState(kStateWaitingForSeek); |   303       SetState(kStateWaitingForSeek); | 
|   277       StopDecoders(); |   304       StopDecoders(); | 
|   278       SetPendingStart(true); |   305       SetPendingStart(true); | 
|   279       RequestDemuxerSeek(timestamp); |   306       RequestDemuxerSeek(timestamp); | 
|   280       break; |   307       break; | 
|   281     case kStatePlaying: |   308     case kStatePlaying: | 
|   282       SetState(kStateStopping); |   309       SetState(kStateStopping); | 
|   283       RequestToStopDecoders(); |   310       RequestToStopDecoders(); | 
|   284       SetPendingStart(true); |   311       SetPendingStart(true); | 
|   285       SetPendingSeek(timestamp); |   312       SetPendingSeek(timestamp); | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|   306   // Stop decoding threads and delete MediaCodecs, but keep IPC between browser |   333   // Stop decoding threads and delete MediaCodecs, but keep IPC between browser | 
|   307   // and renderer processes going. Seek should work across and after Release(). |   334   // and renderer processes going. Seek should work across and after Release(). | 
|   308  |   335  | 
|   309   ReleaseDecoderResources(); |   336   ReleaseDecoderResources(); | 
|   310  |   337  | 
|   311   SetPendingStart(false); |   338   SetPendingStart(false); | 
|   312  |   339  | 
|   313   if (state_ != kStateWaitingForSeek) |   340   if (state_ != kStateWaitingForSeek) | 
|   314     SetState(kStatePaused); |   341     SetState(kStatePaused); | 
|   315  |   342  | 
 |   343   // Crear encryption key related flags. | 
 |   344   key_is_required_ = false; | 
 |   345   key_is_added_ = false; | 
 |   346  | 
|   316   base::TimeDelta pending_seek_time = GetPendingSeek(); |   347   base::TimeDelta pending_seek_time = GetPendingSeek(); | 
|   317   if (pending_seek_time != kNoTimestamp()) { |   348   if (pending_seek_time != kNoTimestamp()) { | 
|   318     SetPendingSeek(kNoTimestamp()); |   349     SetPendingSeek(kNoTimestamp()); | 
|   319     SetState(kStateWaitingForSeek); |   350     SetState(kStateWaitingForSeek); | 
|   320     RequestDemuxerSeek(pending_seek_time); |   351     RequestDemuxerSeek(pending_seek_time); | 
|   321   } |   352   } | 
|   322 } |   353 } | 
|   323  |   354  | 
|   324 void MediaCodecPlayer::SetVolume(double volume) { |   355 void MediaCodecPlayer::SetVolume(double volume) { | 
|   325   RUN_ON_MEDIA_THREAD(SetVolume, volume); |   356   RUN_ON_MEDIA_THREAD(SetVolume, volume); | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   375 } |   406 } | 
|   376  |   407  | 
|   377 bool MediaCodecPlayer::IsPlayerReady() { |   408 bool MediaCodecPlayer::IsPlayerReady() { | 
|   378   DCHECK(ui_task_runner_->BelongsToCurrentThread()); |   409   DCHECK(ui_task_runner_->BelongsToCurrentThread()); | 
|   379   // This method is called to check whether it's safe to release the player when |   410   // This method is called to check whether it's safe to release the player when | 
|   380   // the OS needs more resources. This class can be released at any time. |   411   // the OS needs more resources. This class can be released at any time. | 
|   381   return true; |   412   return true; | 
|   382 } |   413 } | 
|   383  |   414  | 
|   384 void MediaCodecPlayer::SetCdm(BrowserCdm* cdm) { |   415 void MediaCodecPlayer::SetCdm(BrowserCdm* cdm) { | 
|   385   DCHECK(ui_task_runner_->BelongsToCurrentThread()); |   416   RUN_ON_MEDIA_THREAD(SetCdm, cdm); | 
|   386   NOTIMPLEMENTED(); |   417  | 
 |   418   DVLOG(1) << __FUNCTION__; | 
 |   419  | 
 |   420   // Currently we don't support DRM change during the middle of playback, even | 
 |   421   // if the player is paused. There is no current plan to support it, see | 
 |   422   // http://crbug.com/253792. | 
 |   423   if (state_ != kStatePaused || GetInterpolatedTime() > base::TimeDelta()) { | 
 |   424     VLOG(0) << "Setting DRM bridge after playback has started is not supported"; | 
 |   425     return; | 
 |   426   } | 
 |   427  | 
 |   428   if (drm_bridge_) { | 
 |   429     NOTREACHED() << "Currently we do not support resetting CDM."; | 
 |   430     return; | 
 |   431   } | 
 |   432  | 
 |   433   DCHECK(cdm); | 
 |   434   drm_bridge_ = static_cast<MediaDrmBridge*>(cdm); | 
 |   435  | 
 |   436   DCHECK(drm_bridge_); | 
 |   437  | 
 |   438   cdm_registration_id_ = drm_bridge_->RegisterPlayer( | 
 |   439       base::Bind(&MediaCodecPlayer::OnKeyAdded, media_weak_this_), | 
 |   440       base::Bind(&MediaCodecPlayer::OnCdmUnset, media_weak_this_)); | 
 |   441  | 
 |   442   // We assume this property never changes so we can ask it here and use later. | 
 |   443   // TODO(timav): This value can be passed with MediaCryptoReadyCB. | 
 |   444   is_protected_surface_required_ = drm_bridge_->IsProtectedSurfaceRequired(); | 
 |   445  | 
 |   446   // If the crypto is ready by this time, OnMediaCryptoReady will be posted | 
 |   447   // right away. | 
 |   448   // drm_bridge_->SetMediaCryptoReadyCB( | 
 |   449   //    base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_)); | 
 |   450  | 
 |   451   MediaDrmBridge::MediaCryptoReadyCB cb = | 
 |   452       base::Bind(&MediaCodecPlayer::OnMediaCryptoReady, media_weak_this_); | 
 |   453  | 
 |   454   // Post back to UI thread? | 
 |   455   // TODO(timav): We need weak ptr for UI thread. | 
 |   456   ui_task_runner_->PostTask(FROM_HERE, | 
 |   457                             base::Bind(&MediaDrmBridge::SetMediaCryptoReadyCB, | 
 |   458                                        base::Unretained(drm_bridge_), cb)); | 
|   387 } |   459 } | 
|   388  |   460  | 
|   389 // Callbacks from Demuxer. |   461 // Callbacks from Demuxer. | 
|   390  |   462  | 
|   391 void MediaCodecPlayer::OnDemuxerConfigsAvailable( |   463 void MediaCodecPlayer::OnDemuxerConfigsAvailable( | 
|   392     const DemuxerConfigs& configs) { |   464     const DemuxerConfigs& configs) { | 
|   393   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |   465   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   394  |   466  | 
|   395   DVLOG(1) << __FUNCTION__; |   467   DVLOG(1) << __FUNCTION__; | 
|   396  |   468  | 
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   597     DCHECK(!internal_error_cb_.is_null()); |   669     DCHECK(!internal_error_cb_.is_null()); | 
|   598     GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |   670     GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); | 
|   599     return; |   671     return; | 
|   600   } |   672   } | 
|   601  |   673  | 
|   602   if (HasVideo() && !video_decoder_->HasVideoSurface()) { |   674   if (HasVideo() && !video_decoder_->HasVideoSurface()) { | 
|   603     SetState(kStateWaitingForSurface); |   675     SetState(kStateWaitingForSurface); | 
|   604     return; |   676     return; | 
|   605   } |   677   } | 
|   606  |   678  | 
 |   679   if (key_is_required_ && !key_is_added_) { | 
 |   680     SetState(kStateWaitingForKey); | 
 |   681     ui_task_runner_->PostTask(FROM_HERE, key_required_cb_); | 
 |   682     return; | 
 |   683   } | 
 |   684  | 
|   607   SetState(kStatePlaying); |   685   SetState(kStatePlaying); | 
|   608   StartPlaybackOrBrowserSeek(); |   686   StartPlaybackOrBrowserSeek(); | 
|   609 } |   687 } | 
|   610  |   688  | 
|   611 void MediaCodecPlayer::OnPrerollDone() { |   689 void MediaCodecPlayer::OnPrerollDone() { | 
|   612   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |   690   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   613  |   691  | 
|   614   if (state_ != kStatePlaying) { |   692   if (state_ != kStatePlaying) { | 
|   615     DVLOG(1) << __FUNCTION__ << ": in state " << AsString(state_) |   693     DVLOG(1) << __FUNCTION__ << ": in state " << AsString(state_) | 
|   616              << ", ignoring"; |   694              << ", ignoring"; | 
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   710       return; |   788       return; | 
|   711   } |   789   } | 
|   712  |   790  | 
|   713   // DetachListener to UI thread |   791   // DetachListener to UI thread | 
|   714   ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); |   792   ui_task_runner_->PostTask(FROM_HERE, detach_listener_cb_); | 
|   715  |   793  | 
|   716   if (AudioFinished() && VideoFinished()) |   794   if (AudioFinished() && VideoFinished()) | 
|   717     ui_task_runner_->PostTask(FROM_HERE, completion_cb_); |   795     ui_task_runner_->PostTask(FROM_HERE, completion_cb_); | 
|   718 } |   796 } | 
|   719  |   797  | 
 |   798 void MediaCodecPlayer::OnKeyRequired(DemuxerStream::Type type) { | 
 |   799   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
 |   800   DVLOG(1) << __FUNCTION__ << " " << type; | 
 |   801  | 
 |   802   // Request stop and restart to pick up the key. | 
 |   803   key_is_required_ = true; | 
 |   804  | 
 |   805   if (state_ == kStatePlaying) { | 
 |   806     SetState(kStateStopping); | 
 |   807     RequestToStopDecoders(); | 
 |   808     SetPendingStart(true); | 
 |   809   } | 
 |   810 } | 
 |   811  | 
|   720 void MediaCodecPlayer::OnError() { |   812 void MediaCodecPlayer::OnError() { | 
|   721   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |   813   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   722   DVLOG(1) << __FUNCTION__; |   814   DVLOG(1) << __FUNCTION__; | 
|   723  |   815  | 
|   724   // kStateError blocks all events |   816   // kStateError blocks all events | 
|   725   SetState(kStateError); |   817   SetState(kStateError); | 
|   726  |   818  | 
|   727   ReleaseDecoderResources(); |   819   ReleaseDecoderResources(); | 
|   728  |   820  | 
|   729   ui_task_runner_->PostTask(FROM_HERE, |   821   ui_task_runner_->PostTask(FROM_HERE, | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   793 void MediaCodecPlayer::OnVideoResolutionChanged(const gfx::Size& size) { |   885 void MediaCodecPlayer::OnVideoResolutionChanged(const gfx::Size& size) { | 
|   794   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |   886   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   795  |   887  | 
|   796   DVLOG(1) << __FUNCTION__ << " " << size.width() << "x" << size.height(); |   888   DVLOG(1) << __FUNCTION__ << " " << size.width() << "x" << size.height(); | 
|   797  |   889  | 
|   798   // Update cache and notify manager on UI thread |   890   // Update cache and notify manager on UI thread | 
|   799   ui_task_runner_->PostTask( |   891   ui_task_runner_->PostTask( | 
|   800       FROM_HERE, base::Bind(metadata_changed_cb_, kNoTimestamp(), size)); |   892       FROM_HERE, base::Bind(metadata_changed_cb_, kNoTimestamp(), size)); | 
|   801 } |   893 } | 
|   802  |   894  | 
 |   895 // Callbacks from DRM | 
 |   896  | 
 |   897 void MediaCodecPlayer::OnMediaCryptoReady( | 
 |   898     MediaDrmBridge::JavaObjectPtr media_crypto) { | 
 |   899   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
 |   900   DVLOG(1) << __FUNCTION__; | 
 |   901  | 
 |   902   // We receive the MediaCrypto global reference with this callback and use it | 
 |   903   // later for all subsequent configurations. This is possible only if the | 
 |   904   // MediaCrypto object remains valid until new SetCdm() is called. | 
 |   905  | 
 |   906   DCHECK(media_crypto); | 
 |   907   DCHECK(!media_crypto->is_null()); | 
 |   908  | 
 |   909   media_crypto_ = media_crypto.Pass(); | 
 |   910  | 
 |   911   if (audio_decoder_) { | 
 |   912     audio_decoder_->SetNeedsReconfigure(); | 
 |   913   } | 
 |   914  | 
 |   915   if (video_decoder_) { | 
 |   916     video_decoder_->SetNeedsReconfigure(); | 
 |   917     video_decoder_->SetProtectedSurfaceRequired(is_protected_surface_required_); | 
 |   918   } | 
 |   919  | 
 |   920   if (state_ == kStateWaitingForCrypto) { | 
 |   921     // Resume start sequence (configure, etc.) | 
 |   922     SetState(kStatePlaying); | 
 |   923     StartPlaybackOrBrowserSeek(); | 
 |   924   } | 
 |   925  | 
 |   926   DVLOG(1) << __FUNCTION__ << " end"; | 
 |   927 } | 
 |   928  | 
 |   929 void MediaCodecPlayer::OnKeyAdded() { | 
 |   930   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
 |   931   DVLOG(1) << __FUNCTION__; | 
 |   932  | 
 |   933   key_is_added_ = true; | 
 |   934  | 
 |   935   if (state_ == kStateWaitingForKey) { | 
 |   936     SetState(kStatePlaying); | 
 |   937     StartPlaybackOrBrowserSeek(); | 
 |   938   } | 
 |   939 } | 
 |   940  | 
 |   941 void MediaCodecPlayer::OnCdmUnset() { | 
 |   942   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
 |   943   DVLOG(1) << __FUNCTION__; | 
 |   944  | 
 |   945   // This comment is copied from MediaSourcePlayer::OnCdmUnset(). | 
 |   946   // TODO(xhwang): Currently this is only called during teardown. Support full | 
 |   947   // detachment of CDM during playback. This will be needed when we start to | 
 |   948   // support setMediaKeys(0) (see http://crbug.com/330324), or when we release | 
 |   949   // MediaDrm when the video is paused, or when the device goes to sleep (see | 
 |   950   // http://crbug.com/272421). | 
 |   951  | 
 |   952   if (audio_decoder_) { | 
 |   953     audio_decoder_->SetNeedsReconfigure(); | 
 |   954   } | 
 |   955  | 
 |   956   if (video_decoder_) { | 
 |   957     video_decoder_->SetProtectedSurfaceRequired(false); | 
 |   958     video_decoder_->SetNeedsReconfigure(); | 
 |   959   } | 
 |   960  | 
 |   961   cdm_registration_id_ = 0; | 
 |   962   is_protected_surface_required_ = false; | 
 |   963   drm_bridge_ = nullptr; | 
 |   964   media_crypto_.reset(); | 
 |   965 } | 
 |   966  | 
|   803 // State machine operations, called on Media thread |   967 // State machine operations, called on Media thread | 
|   804  |   968  | 
|   805 void MediaCodecPlayer::SetState(PlayerState new_state) { |   969 void MediaCodecPlayer::SetState(PlayerState new_state) { | 
|   806   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |   970   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   807  |   971  | 
|   808   DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); |   972   DVLOG(1) << "SetState:" << AsString(state_) << " -> " << AsString(new_state); | 
|   809   state_ = new_state; |   973   state_ = new_state; | 
|   810 } |   974 } | 
|   811  |   975  | 
|   812 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { |   976 void MediaCodecPlayer::SetPendingStart(bool need_to_start) { | 
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   892     video_decoder_->Prefetch(prefetch_cb); |  1056     video_decoder_->Prefetch(prefetch_cb); | 
|   893 } |  1057 } | 
|   894  |  1058  | 
|   895 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() { |  1059 void MediaCodecPlayer::StartPlaybackOrBrowserSeek() { | 
|   896   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |  1060   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   897   DVLOG(1) << __FUNCTION__; |  1061   DVLOG(1) << __FUNCTION__; | 
|   898  |  1062  | 
|   899   // TODO(timav): consider replacing this method with posting a |  1063   // TODO(timav): consider replacing this method with posting a | 
|   900   // browser seek task (i.e. generate an event) from StartPlaybackDecoders(). |  1064   // browser seek task (i.e. generate an event) from StartPlaybackDecoders(). | 
|   901  |  1065  | 
 |  1066   // Clear encryption key related flags. | 
 |  1067   key_is_required_ = false; | 
 |  1068   key_is_added_ = false; | 
 |  1069  | 
|   902   StartStatus status = StartPlaybackDecoders(); |  1070   StartStatus status = StartPlaybackDecoders(); | 
|   903  |  1071  | 
|   904   switch (status) { |  1072   switch (status) { | 
|   905     case kStartBrowserSeekRequired: |  1073     case kStartBrowserSeekRequired: | 
|   906       // Browser seek |  1074       // Browser seek | 
|   907       SetState(kStateWaitingForSeek); |  1075       SetState(kStateWaitingForSeek); | 
|   908       SetPendingStart(true); |  1076       SetPendingStart(true); | 
|   909       StopDecoders(); |  1077       StopDecoders(); | 
|   910       RequestDemuxerSeek(GetInterpolatedTime(), true); |  1078       RequestDemuxerSeek(GetInterpolatedTime(), true); | 
|   911       break; |  1079       break; | 
 |  1080     case kStartCryptoRequired: | 
 |  1081       SetState(kStateWaitingForCrypto); | 
 |  1082       break; | 
|   912     case kStartFailed: |  1083     case kStartFailed: | 
|   913       GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); |  1084       GetMediaTaskRunner()->PostTask(FROM_HERE, internal_error_cb_); | 
|   914       break; |  1085       break; | 
|   915     case kStartOk: |  1086     case kStartOk: | 
|   916       break; |  1087       break; | 
|   917   } |  1088   } | 
|   918 } |  1089 } | 
|   919  |  1090  | 
|   920 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { |  1091 MediaCodecPlayer::StartStatus MediaCodecPlayer::StartPlaybackDecoders() { | 
|   921   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |  1092   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|   939   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |  1110   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   940   DVLOG(1) << __FUNCTION__; |  1111   DVLOG(1) << __FUNCTION__; | 
|   941  |  1112  | 
|   942   const bool do_audio = !AudioFinished(); |  1113   const bool do_audio = !AudioFinished(); | 
|   943   const bool do_video = !VideoFinished(); |  1114   const bool do_video = !VideoFinished(); | 
|   944  |  1115  | 
|   945   // If there is nothing to play, the state machine should determine this at the |  1116   // If there is nothing to play, the state machine should determine this at the | 
|   946   // prefetch state and never call this method. |  1117   // prefetch state and never call this method. | 
|   947   DCHECK(do_audio || do_video); |  1118   DCHECK(do_audio || do_video); | 
|   948  |  1119  | 
|   949   // Start with video: if browser seek is required it would |  1120   bool need_crypto = (do_audio && audio_decoder_->IsContentEncrypted()) || | 
|   950   // not make sense to configure audio. |  1121                      (do_video && video_decoder_->IsContentEncrypted()); | 
|   951  |  1122  | 
|   952   if (do_video) { |  1123   // Do we need to create a local ref from the global ref? | 
|   953     MediaCodecDecoder::ConfigStatus status = video_decoder_->Configure(); |  1124   jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr; | 
|   954     switch (status) { |  1125  | 
|   955       case MediaCodecDecoder::kConfigOk: |  1126   if (need_crypto) { | 
|   956         break; |  1127     DVLOG(1) << (audio_decoder_->IsContentEncrypted() ? " audio" : "") | 
|   957       case MediaCodecDecoder::kConfigKeyFrameRequired: |  1128              << (video_decoder_->IsContentEncrypted() ? " video" : "") | 
|   958         // TODO(timav): post a task or return the status? |  1129              << " need(s) encryption"; | 
|   959         return kStartBrowserSeekRequired; |  1130     if (!media_crypto) { | 
|   960       case MediaCodecDecoder::kConfigFailure: |  1131       DVLOG(1) << __FUNCTION__ << ": MediaCrypto is not found, returning"; | 
|   961         return kStartFailed; |  1132       return kStartCryptoRequired; | 
|   962     } |  1133     } | 
|   963   } |  1134   } | 
|   964  |  1135  | 
|   965   if (do_audio) { |  1136   // Start with video: if browser seek is required it would not make sense to | 
|   966     MediaCodecDecoder::ConfigStatus status = audio_decoder_->Configure(); |  1137   // configure audio. | 
|   967     if (status != MediaCodecDecoder::kConfigOk) { |  1138  | 
 |  1139   MediaCodecDecoder::ConfigStatus status = MediaCodecDecoder::kConfigOk; | 
 |  1140   if (do_video) | 
 |  1141     status = video_decoder_->Configure(media_crypto); | 
 |  1142  | 
 |  1143   if (status == MediaCodecDecoder::kConfigOk && do_audio) | 
 |  1144     status = audio_decoder_->Configure(media_crypto); | 
 |  1145  | 
 |  1146   switch (status) { | 
 |  1147     case MediaCodecDecoder::kConfigOk: | 
 |  1148       break; | 
 |  1149     case MediaCodecDecoder::kConfigKeyFrameRequired: | 
 |  1150       return kStartBrowserSeekRequired; | 
 |  1151     case MediaCodecDecoder::kConfigNoCrypto:  // TODO: delete this | 
 |  1152       return kStartCryptoRequired; | 
 |  1153     case MediaCodecDecoder::kConfigFailure: | 
|   968       return kStartFailed; |  1154       return kStartFailed; | 
|   969     } |  | 
|   970   } |  1155   } | 
|   971  |  | 
|   972   return kStartOk; |  1156   return kStartOk; | 
|   973 } |  1157 } | 
|   974  |  1158  | 
|   975 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( |  1159 MediaCodecPlayer::StartStatus MediaCodecPlayer::MaybePrerollDecoders( | 
|   976     bool* preroll_required) { |  1160     bool* preroll_required) { | 
|   977   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); |  1161   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread()); | 
|   978  |  1162  | 
|   979   DVLOG(1) << __FUNCTION__ << " current_time:" << GetInterpolatedTime(); |  1163   DVLOG(1) << __FUNCTION__ << " current_time:" << GetInterpolatedTime(); | 
|   980  |  1164  | 
|   981   // If requested, preroll is always done in the beginning of the playback, |  1165   // If requested, preroll is always done in the beginning of the playback, | 
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1120  |  1304  | 
|  1121   audio_decoder_.reset(new MediaCodecAudioDecoder( |  1305   audio_decoder_.reset(new MediaCodecAudioDecoder( | 
|  1122       GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |  1306       GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 
|  1123                                        media_weak_this_, DemuxerStream::AUDIO), |  1307                                        media_weak_this_, DemuxerStream::AUDIO), | 
|  1124       base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |  1308       base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 
|  1125                  DemuxerStream::AUDIO), |  1309                  DemuxerStream::AUDIO), | 
|  1126       base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, |  1310       base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, | 
|  1127                  DemuxerStream::AUDIO), |  1311                  DemuxerStream::AUDIO), | 
|  1128       base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, |  1312       base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, | 
|  1129                  DemuxerStream::AUDIO), |  1313                  DemuxerStream::AUDIO), | 
 |  1314       base::Bind(&MediaCodecPlayer::OnKeyRequired, media_weak_this_, | 
 |  1315                  DemuxerStream::AUDIO), | 
|  1130       internal_error_cb_, |  1316       internal_error_cb_, | 
|  1131       base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |  1317       base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 
|  1132                  DemuxerStream::AUDIO))); |  1318                  DemuxerStream::AUDIO))); | 
|  1133  |  1319  | 
|  1134   video_decoder_.reset(new MediaCodecVideoDecoder( |  1320   video_decoder_.reset(new MediaCodecVideoDecoder( | 
|  1135       GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, |  1321       GetMediaTaskRunner(), base::Bind(&MediaCodecPlayer::RequestDemuxerData, | 
|  1136                                        media_weak_this_, DemuxerStream::VIDEO), |  1322                                        media_weak_this_, DemuxerStream::VIDEO), | 
|  1137       base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, |  1323       base::Bind(&MediaCodecPlayer::OnStarvation, media_weak_this_, | 
|  1138                  DemuxerStream::VIDEO), |  1324                  DemuxerStream::VIDEO), | 
|  1139       base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, |  1325       base::Bind(&MediaCodecPlayer::OnDecoderDrained, media_weak_this_, | 
|  1140                  DemuxerStream::VIDEO), |  1326                  DemuxerStream::VIDEO), | 
|  1141       base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, |  1327       base::Bind(&MediaCodecPlayer::OnStopDone, media_weak_this_, | 
|  1142                  DemuxerStream::VIDEO), |  1328                  DemuxerStream::VIDEO), | 
 |  1329       base::Bind(&MediaCodecPlayer::OnKeyRequired, media_weak_this_, | 
 |  1330                  DemuxerStream::VIDEO), | 
|  1143       internal_error_cb_, |  1331       internal_error_cb_, | 
|  1144       base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, |  1332       base::Bind(&MediaCodecPlayer::OnTimeIntervalUpdate, media_weak_this_, | 
|  1145                  DemuxerStream::VIDEO), |  1333                  DemuxerStream::VIDEO), | 
|  1146       base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), |  1334       base::Bind(&MediaCodecPlayer::OnVideoResolutionChanged, media_weak_this_), | 
|  1147       base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); |  1335       base::Bind(&MediaCodecPlayer::OnVideoCodecCreated, media_weak_this_))); | 
|  1148 } |  1336 } | 
|  1149  |  1337  | 
|  1150 bool MediaCodecPlayer::AudioFinished() const { |  1338 bool MediaCodecPlayer::AudioFinished() const { | 
|  1151   return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); |  1339   return audio_decoder_->IsCompleted() || !audio_decoder_->HasStream(); | 
|  1152 } |  1340 } | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|  1168     return #x; |  1356     return #x; | 
|  1169  |  1357  | 
|  1170 const char* MediaCodecPlayer::AsString(PlayerState state) { |  1358 const char* MediaCodecPlayer::AsString(PlayerState state) { | 
|  1171   switch (state) { |  1359   switch (state) { | 
|  1172     RETURN_STRING(kStatePaused); |  1360     RETURN_STRING(kStatePaused); | 
|  1173     RETURN_STRING(kStateWaitingForConfig); |  1361     RETURN_STRING(kStateWaitingForConfig); | 
|  1174     RETURN_STRING(kStatePrefetching); |  1362     RETURN_STRING(kStatePrefetching); | 
|  1175     RETURN_STRING(kStatePlaying); |  1363     RETURN_STRING(kStatePlaying); | 
|  1176     RETURN_STRING(kStateStopping); |  1364     RETURN_STRING(kStateStopping); | 
|  1177     RETURN_STRING(kStateWaitingForSurface); |  1365     RETURN_STRING(kStateWaitingForSurface); | 
 |  1366     RETURN_STRING(kStateWaitingForKey); | 
 |  1367     RETURN_STRING(kStateWaitingForCrypto); | 
|  1178     RETURN_STRING(kStateWaitingForSeek); |  1368     RETURN_STRING(kStateWaitingForSeek); | 
|  1179     RETURN_STRING(kStateError); |  1369     RETURN_STRING(kStateError); | 
|  1180   } |  1370   } | 
|  1181   return nullptr;  // crash early |  1371   return nullptr;  // crash early | 
|  1182 } |  1372 } | 
|  1183  |  1373  | 
|  1184 #undef RETURN_STRING |  1374 #undef RETURN_STRING | 
|  1185  |  1375  | 
|  1186 }  // namespace media |  1376 }  // namespace media | 
| OLD | NEW |