Index: media/gpu/android_video_decode_accelerator.cc |
diff --git a/media/gpu/android_video_decode_accelerator.cc b/media/gpu/android_video_decode_accelerator.cc |
index c3a3aaa52964d9f3aaca4bf670f511e2b730ad72..615da5a8519f018e061bfe728b18d50a26cad7b4 100644 |
--- a/media/gpu/android_video_decode_accelerator.cc |
+++ b/media/gpu/android_video_decode_accelerator.cc |
@@ -35,6 +35,7 @@ |
#include "media/base/timestamp_constants.h" |
#include "media/base/video_decoder_config.h" |
#include "media/gpu/avda_picture_buffer_manager.h" |
+#include "media/gpu/content_video_view_overlay.h" |
#include "media/gpu/shared_memory_region.h" |
#include "media/video/picture.h" |
#include "ui/gl/android/scoped_java_surface.h" |
@@ -364,6 +365,13 @@ void AndroidVideoDecodeAccelerator::StartSurfaceCreation() { |
// afterwards (::Decode, for deferred surface init, UpdateSurface). |
DCHECK(incoming_bundle_); |
+ // We should not yet have an overlay. |
+ DCHECK(!incoming_bundle_->overlay); |
+ |
+ // Note that we don't enforce that for any SurfaceTexture or its Surface, |
+ // since there might be a codec that's using them. They'll get cleared |
+ // later, in InitializePictureBufferManager. |
+ |
// If surface creation is deferred, then do nothing except signal that init |
// is complete, if needed. We might still fail to get a surface or codec, |
// which would normally be an init error. Since we're deferring init until a |
@@ -377,34 +385,50 @@ void AndroidVideoDecodeAccelerator::StartSurfaceCreation() { |
return; |
} |
- if (!codec_allocator_->AllocateSurface(this, incoming_bundle_->surface_id)) { |
+ if (incoming_bundle_->surface_id != SurfaceManager::kNoSurfaceID) { |
+ // Create the overlay. Note that it will never call us back immediately. |
+ // It will post when the surface is available. |
+ AndroidOverlay::Config overlay_config; |
+ // We use weak ptrs here since |overlay| can outlive us, if we send it for |
+ // async codec config. |
+ overlay_config.ready_cb = |
+ base::Bind(&AndroidVideoDecodeAccelerator::OnOverlayReady, |
+ weak_this_factory_.GetWeakPtr()); |
+ overlay_config.failed_cb = |
+ base::Bind(&AndroidVideoDecodeAccelerator::OnOverlayFailed, |
+ weak_this_factory_.GetWeakPtr()); |
+ overlay_config.destroyed_cb = |
+ base::Bind(&AndroidVideoDecodeAccelerator::OnSurfaceDestroyed, |
+ weak_this_factory_.GetWeakPtr()); |
+ incoming_bundle_->overlay = base::MakeUnique<ContentVideoViewOverlay>( |
+ codec_allocator_, incoming_bundle_->surface_id, overlay_config); |
// We have to wait for some other AVDA instance to free up the surface. |
- // OnSurfaceAvailable will be called when it's available. |
+ // OnOverlayReady will be called when it's available. |
// Note that if we aren't deferring init, then we'll signal success, and |
// if we fail later then it will fail decoding instead. However, since |
// nobody that provides a SurfaceView requires sync init, it doesn't matter. |
+ // Also remember that ContentVideoViewOverlay will not call OnOverlayReady |
+ // before it returns. |
state_ = WAITING_FOR_SURFACE; |
return; |
} |
- // We now own the surface, so finish initialization. |
+ // We're creating a SurfaceTexture. |
InitializePictureBufferManager(); |
} |
-void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) { |
+void AndroidVideoDecodeAccelerator::OnOverlayReady() { |
DCHECK(!defer_surface_creation_); |
DCHECK_EQ(state_, WAITING_FOR_SURFACE); |
DCHECK(incoming_bundle_); |
- if (!success) { |
- NOTIFY_ERROR(PLATFORM_FAILURE, "Surface is not available"); |
- incoming_bundle_ = nullptr; |
- return; |
- } |
- |
InitializePictureBufferManager(); |
} |
+void AndroidVideoDecodeAccelerator::OnOverlayFailed() { |
+ NOTIFY_ERROR(PLATFORM_FAILURE, "Surface is not available"); |
+} |
+ |
void AndroidVideoDecodeAccelerator::InitializePictureBufferManager() { |
DCHECK(!defer_surface_creation_); |
DCHECK(incoming_bundle_); |
@@ -418,9 +442,19 @@ void AndroidVideoDecodeAccelerator::InitializePictureBufferManager() { |
// Move |incoming_bundle_| to |codec_config_|. Our caller must set up an |
// incoming bundle properly, since we don't want to accidentally overwrite |
// |surface_bundle| for a codec that's being released elsewhere. |
- incoming_bundle_->surface = picture_buffer_manager_.Initialize(surface_id()); |
- incoming_bundle_->surface_texture = picture_buffer_manager_.surface_texture(); |
- if (incoming_bundle_->surface.IsEmpty()) { |
+ // TODO(liberato): it doesn't make sense anymore for the PictureBufferManager |
+ // to create the surface texture. We can probably make an overlay impl out |
+ // of it, and provide the surface texture to |picture_buffer_manager_|. |
+ if (incoming_bundle_->overlay) { |
+ picture_buffer_manager_.InitializeForOverlay(); |
+ } else { |
+ incoming_bundle_->surface_texture_surface = |
+ picture_buffer_manager_.InitializeForSurfaceTexture(); |
+ incoming_bundle_->surface_texture = |
+ picture_buffer_manager_.surface_texture(); |
+ } |
+ |
+ if (incoming_bundle_->j_surface().is_null()) { |
NOTIFY_ERROR(PLATFORM_FAILURE, "Codec surface is empty"); |
incoming_bundle_ = nullptr; |
return; |
@@ -431,8 +465,7 @@ void AndroidVideoDecodeAccelerator::InitializePictureBufferManager() { |
// If we get here with a codec, then we must setSurface. |
if (media_codec_) { |
// TODO(liberato): fail on api check? |
- if (!media_codec_->SetSurface( |
- incoming_bundle_->surface.j_surface().obj())) { |
+ if (!media_codec_->SetSurface(incoming_bundle_->j_surface().obj())) { |
NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces."); |
// We're not going to use |incoming_bundle_|. |
} else { |
@@ -655,7 +688,7 @@ bool AndroidVideoDecodeAccelerator::DequeueOutput() { |
if (!UpdateSurface()) |
return false; |
// If we can't allocate the incoming surface yet, then stop here. |
- if (state_ == WAITING_FOR_SURFACE) |
+ if (state_ != NO_ERROR) |
return false; |
} |
@@ -1014,7 +1047,6 @@ void AndroidVideoDecodeAccelerator::OnCodecConfigured( |
std::unique_ptr<MediaCodecBridge> media_codec) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); |
- |
// If we are supposed to notify that initialization is complete, then do so |
// before returning. Otherwise, this is a reconfiguration. |
@@ -1158,6 +1190,10 @@ void AndroidVideoDecodeAccelerator::ResetCodecState() { |
} else { |
DVLOG(3) << __func__ << " Deleting the MediaCodec and creating a new one."; |
GetManager()->StopTimer(this); |
+ // Note that this will release the codec, then allocate a new one. It will |
+ // not wait for the old one to finish up with the surface, which is bad. |
+ // It works (usually) because it ends up allocating the codec on the same |
+ // thread as is used to release the old one, so it's serialized anyway. |
ConfigureMediaCodecAsynchronously(); |
} |
} |
@@ -1234,10 +1270,6 @@ void AndroidVideoDecodeAccelerator::ActualDestroy() { |
GetManager()->StopTimer(this); |
ReleaseCodec(); |
- // We no longer care about |surface_id|, in case we did before. It's okay |
- // if we have no surface and/or weren't the owner or a waiter. |
- codec_allocator_->DeallocateSurface(this, surface_id()); |
liberato (no reviews please)
2017/03/08 22:48:59
one difference with this CL is that, if codec rele
|
- |
delete this; |
} |
@@ -1559,7 +1591,6 @@ bool AndroidVideoDecodeAccelerator::UpdateSurface() { |
DCHECK(surface_id() == SurfaceManager::kNoSurfaceID || |
pending_surface_id_.value() == SurfaceManager::kNoSurfaceID); |
- const int previous_surface_id = surface_id(); |
const int new_surface_id = pending_surface_id_.value(); |
pending_surface_id_.reset(); |
@@ -1584,19 +1615,7 @@ bool AndroidVideoDecodeAccelerator::UpdateSurface() { |
// should have been dropped. |
DCHECK(!incoming_bundle_); |
ReleaseCodec(); |
- // We no longer own the new surface. |
- codec_allocator_->DeallocateSurface(this, new_surface_id); |
- } |
- |
- // Regardless of whether we succeeded, we no longer own the previous surface. |
- // This is the only case where we start a new incoming bundle, and we maintain |
- // the property that |incoming_bundle_| is the one that we own, as documented |
- // for surface_id(). |
- // It would be nice if the outgoing surface bundle did this. |
- // TODO(liberato): It could, but the CVV implementation of AndroidOverlay |
- // will do it too when the bundle holding it is dropped. We'll do it this way |
- // until then, just to minimize changes. |
- codec_allocator_->DeallocateSurface(this, previous_surface_id); |
+ } |
return state_ != ERROR; |
} |