Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1584)

Unified Diff: media/gpu/android_video_decode_accelerator.cc

Issue 2692863011: Add ContentVideoViewOverlay to AVDA. (Closed)
Patch Set: make DequeueOutput require NO_ERROR from setsurface Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}

Powered by Google App Engine
This is Rietveld 408576698