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

Unified Diff: media/gpu/android_video_decode_accelerator.cc

Issue 2296513003: Delete AVDACopyingBackingStrategy and rename AVDADeferredRenderingBackingStrategy (Closed)
Patch Set: Undelete & fix unittest Created 4 years, 4 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 fcc40220d0614ba6bfa9abe098c8e49196f02977..8ea23a0a7c0c285f80fc62f52460a889e758c16c 100644
--- a/media/gpu/android_video_decode_accelerator.cc
+++ b/media/gpu/android_video_decode_accelerator.cc
@@ -33,9 +33,7 @@
#include "media/base/media.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_decoder_config.h"
-#include "media/gpu/android_copying_backing_strategy.h"
-#include "media/gpu/android_deferred_rendering_backing_strategy.h"
-#include "media/gpu/avda_return_on_failure.h"
+#include "media/gpu/avda_picture_buffer_manager.h"
#include "media/gpu/shared_memory_region.h"
#include "media/video/picture.h"
#include "ui/gl/android/scoped_java_surface.h"
@@ -126,57 +124,6 @@ inline void RecordFormatChangedMetric(FormatChangedValue value) {
} // namespace
-// Handle OnFrameAvailable callbacks safely. Since they occur asynchronously,
-// we take care that the AVDA that wants them still exists. A WeakPtr to
-// the AVDA would be preferable, except that OnFrameAvailable callbacks can
-// occur off the gpu main thread. We also can't guarantee when the
-// SurfaceTexture will quit sending callbacks to coordinate with the
-// destruction of the AVDA, so we have a separate object that the cb can own.
-class AndroidVideoDecodeAccelerator::OnFrameAvailableHandler
- : public base::RefCountedThreadSafe<OnFrameAvailableHandler> {
- public:
- // We do not retain ownership of |owner|. It must remain valid until
- // after ClearOwner() is called. This will register with
- // |surface_texture| to receive OnFrameAvailable callbacks.
- OnFrameAvailableHandler(
- AndroidVideoDecodeAccelerator* owner,
- const scoped_refptr<gl::SurfaceTexture>& surface_texture)
- : owner_(owner) {
- // Note that the callback owns a strong ref to us.
- surface_texture->SetFrameAvailableCallbackOnAnyThread(
- base::Bind(&OnFrameAvailableHandler::OnFrameAvailable,
- scoped_refptr<OnFrameAvailableHandler>(this)));
- }
-
- // Forget about our owner, which is required before one deletes it.
- // No further callbacks will happen once this completes.
- void ClearOwner() {
- base::AutoLock lock(lock_);
- // No callback can happen until we release the lock.
- owner_ = nullptr;
- }
-
- // Call back into our owner if it hasn't been deleted.
- void OnFrameAvailable() {
- base::AutoLock auto_lock(lock_);
- // |owner_| can't be deleted while we have the lock.
- if (owner_)
- owner_->OnFrameAvailable();
- }
-
- private:
- friend class base::RefCountedThreadSafe<OnFrameAvailableHandler>;
- virtual ~OnFrameAvailableHandler() {}
-
- // Protects changes to owner_.
- base::Lock lock_;
-
- // AVDA that wants the OnFrameAvailable callback.
- AndroidVideoDecodeAccelerator* owner_;
-
- DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler);
-};
-
// AVDAManager manages shared resources for a number of AVDA instances.
// Its responsibilities include:
// - Starting and stopping a shared "construction" thread for instantiating and
@@ -552,17 +499,6 @@ bool AndroidVideoDecodeAccelerator::Initialize(const Config& config,
return false;
}
- const gpu::GpuPreferences& gpu_preferences =
- gles_decoder->GetContextGroup()->gpu_preferences();
-
- if (UseDeferredRenderingStrategy(gpu_preferences)) {
- DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy.";
- strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this));
- } else {
- DVLOG(1) << __FUNCTION__ << ", using copy back strategy.";
- strategy_.reset(new AndroidCopyingBackingStrategy(this));
- }
-
if (!make_context_current_cb_.Run()) {
LOG(ERROR) << "Failed to make this decoder's GL context current.";
return false;
@@ -570,7 +506,7 @@ bool AndroidVideoDecodeAccelerator::Initialize(const Config& config,
if (g_avda_manager.Get().AllocateSurface(config_.surface_id, this)) {
// We have succesfully owned the surface, so finish initialization now.
- return InitializeStrategy();
+ return InitializePictureBufferManager();
}
// We have to wait for some other AVDA instance to free up the surface.
@@ -581,19 +517,17 @@ bool AndroidVideoDecodeAccelerator::Initialize(const Config& config,
void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) {
DCHECK(deferred_initialization_pending_);
- if (!success || !InitializeStrategy()) {
+ if (!success || !InitializePictureBufferManager()) {
NotifyInitializationComplete(false);
deferred_initialization_pending_ = false;
}
}
-bool AndroidVideoDecodeAccelerator::InitializeStrategy() {
- codec_config_->surface_ = strategy_->Initialize(config_.surface_id);
- if (codec_config_->surface_.IsEmpty()) {
- LOG(ERROR) << "Failed to initialize the backing strategy. The returned "
- "Java surface is empty.";
+bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() {
+ codec_config_->surface_ =
+ picture_buffer_manager_.Initialize(this, config_.surface_id);
+ if (codec_config_->surface_.IsEmpty())
return false;
- }
on_destroying_surface_cb_ =
base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface,
@@ -601,14 +535,6 @@ bool AndroidVideoDecodeAccelerator::InitializeStrategy() {
AVDASurfaceTracker::GetInstance()->RegisterOnDestroyingSurfaceCallback(
on_destroying_surface_cb_);
- // TODO(watk,liberato): move this into the strategy.
- scoped_refptr<gl::SurfaceTexture> surface_texture =
- strategy_->GetSurfaceTexture();
- if (surface_texture) {
- on_frame_available_handler_ =
- new OnFrameAvailableHandler(this, surface_texture);
- }
-
if (!g_avda_manager.Get().StartThread(this))
return false;
@@ -640,7 +566,7 @@ void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) {
return;
}
- strategy_->MaybeRenderEarly();
+ picture_buffer_manager_.MaybeRenderEarly();
bool did_work = false, did_input = false, did_output = false;
do {
did_input = QueueInput();
@@ -953,22 +879,19 @@ void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient(
free_picture_ids_.pop();
TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size());
- const auto& i = output_picture_buffers_.find(picture_buffer_id);
- if (i == output_picture_buffers_.end()) {
+ const auto it = output_picture_buffers_.find(picture_buffer_id);
+ if (it == output_picture_buffers_.end()) {
POST_ERROR(PLATFORM_FAILURE,
"Can't find PictureBuffer id: " << picture_buffer_id);
return;
}
- bool size_changed = false;
- if (i->second.size() != size_) {
- // Size may have changed due to resolution change since the last time this
- // PictureBuffer was used.
- strategy_->UpdatePictureBufferSize(&i->second, size_);
- size_changed = true;
- }
+ PictureBuffer& picture_buffer = it->second;
+ const bool size_changed = picture_buffer.size() != size_;
+ if (size_changed)
+ picture_buffer.set_size(size_);
- const bool allow_overlay = strategy_->ArePicturesOverlayable();
+ const bool allow_overlay = picture_buffer_manager_.ArePicturesOverlayable();
UMA_HISTOGRAM_BOOLEAN("Media.AVDA.FrameSentAsOverlay", allow_overlay);
Picture picture(picture_buffer_id, bitstream_id, gfx::Rect(size_),
allow_overlay);
@@ -980,9 +903,9 @@ void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient(
// called, so it is safe to do this.
NotifyPictureReady(picture);
- // Connect the PictureBuffer to the decoded frame, via whatever mechanism the
- // strategy likes.
- strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second);
+ // Connect the PictureBuffer to the decoded frame.
+ picture_buffer_manager_.UseCodecBufferForPictureBuffer(codec_buffer_index,
+ picture_buffer);
}
void AndroidVideoDecodeAccelerator::Decode(
@@ -1026,9 +949,10 @@ void AndroidVideoDecodeAccelerator::DecodeBuffer(
void AndroidVideoDecodeAccelerator::RequestPictureBuffers() {
if (client_) {
- client_->ProvidePictureBuffers(kNumPictureBuffers, PIXEL_FORMAT_UNKNOWN, 1,
- strategy_->GetPictureBufferSize(),
- strategy_->GetTextureTarget());
+ client_->ProvidePictureBuffers(
+ kNumPictureBuffers, PIXEL_FORMAT_UNKNOWN, 1,
+ picture_buffer_manager_.GetPictureBufferSize(),
+ picture_buffer_manager_.GetTextureTarget());
}
}
@@ -1048,7 +972,7 @@ void AndroidVideoDecodeAccelerator::AssignPictureBuffers(
<< "Failed to make GL context current for Assign, continuing.";
for (size_t i = 0; i < buffers.size(); ++i) {
- if (buffers[i].size() != strategy_->GetPictureBufferSize()) {
+ if (buffers[i].size() != picture_buffer_manager_.GetPictureBufferSize()) {
POST_ERROR(INVALID_ARGUMENT,
"Invalid picture buffer size assigned. Wanted "
<< size_.ToString() << ", but got "
@@ -1059,7 +983,7 @@ void AndroidVideoDecodeAccelerator::AssignPictureBuffers(
output_picture_buffers_.insert(std::make_pair(id, buffers[i]));
free_picture_ids_.push(id);
- strategy_->AssignOnePictureBuffer(buffers[i], have_context);
+ picture_buffer_manager_.AssignOnePictureBuffer(buffers[i], have_context);
}
TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size());
DoIOTask(true);
@@ -1072,15 +996,14 @@ void AndroidVideoDecodeAccelerator::ReusePictureBuffer(
free_picture_ids_.push(picture_buffer_id);
TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size());
- OutputBufferMap::const_iterator i =
- output_picture_buffers_.find(picture_buffer_id);
- if (i == output_picture_buffers_.end()) {
+ auto it = output_picture_buffers_.find(picture_buffer_id);
+ if (it == output_picture_buffers_.end()) {
POST_ERROR(PLATFORM_FAILURE, "Can't find PictureBuffer id "
<< picture_buffer_id);
return;
}
- strategy_->ReuseOnePictureBuffer(i->second);
+ picture_buffer_manager_.ReuseOnePictureBuffer(it->second);
DoIOTask(true);
}
@@ -1105,14 +1028,14 @@ void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() {
state_ = WAITING_FOR_CODEC;
- // Tell the strategy that we're changing codecs. The codec itself could be
- // used normally, since we don't replace it until we're back on the main
- // thread. However, if we're using an output surface, then the incoming codec
- // might access that surface while the main thread is drawing. Telling the
- // strategy to forget the codec avoids this.
+ // Tell the picture buffer manager that we're changing codecs. The codec
+ // itself could be used normally, since we don't replace it until we're back
+ // on the main thread. However, if we're using an output surface, then the
+ // incoming codec might access that surface while the main thread is drawing.
+ // Telling the manager to forget the codec avoids this.
if (media_codec_) {
ReleaseMediaCodec();
- strategy_->CodecChanged(nullptr);
+ picture_buffer_manager_.CodecChanged(nullptr);
}
// Choose whether to autodetect the codec type. Note that we do this after
@@ -1205,7 +1128,7 @@ void AndroidVideoDecodeAccelerator::OnCodecConfigured(
DCHECK(!media_codec_);
media_codec_ = std::move(media_codec);
- strategy_->CodecChanged(media_codec_.get());
+ picture_buffer_manager_.CodecChanged(media_codec_.get());
if (!media_codec_) {
POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec.");
return;
@@ -1324,7 +1247,7 @@ void AndroidVideoDecodeAccelerator::ResetCodecState() {
media_codec_->Flush();
// Since we just flushed all the output buffers, make sure that nothing is
// using them.
- strategy_->CodecChanged(media_codec_.get());
+ picture_buffer_manager_.CodecChanged(media_codec_.get());
} else {
DVLOG(3) << __FUNCTION__
<< " Deleting the MediaCodec and creating a new one.";
@@ -1356,8 +1279,7 @@ void AndroidVideoDecodeAccelerator::Reset() {
// Any error that is waiting to post can be ignored.
error_sequence_token_++;
- DCHECK(strategy_);
- strategy_->ReleaseCodecBuffers(output_picture_buffers_);
+ picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_);
// Some VP8 files require complete MediaCodec drain before we can call
// MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963.
@@ -1377,29 +1299,18 @@ void AndroidVideoDecodeAccelerator::Destroy() {
DVLOG(1) << __FUNCTION__;
DCHECK(thread_checker_.CalledOnValidThread());
- bool have_context = make_context_current_cb_.Run();
- if (!have_context)
- LOG(WARNING) << "Failed make GL context current for Destroy, continuing.";
-
- if (strategy_)
- strategy_->BeginCleanup(have_context, output_picture_buffers_);
-
- // If we have an OnFrameAvailable handler, tell it that we're going away.
- if (on_frame_available_handler_) {
- on_frame_available_handler_->ClearOwner();
- on_frame_available_handler_ = nullptr;
- }
+ picture_buffer_manager_.Destroy(output_picture_buffers_);
client_ = nullptr;
- // Some VP8 files require complete MediaCodec drain before we can call
- // MediaCodec.flush() or MediaCodec.reset(). http://crbug.com/598963.
+ // Some VP8 files require a complete MediaCodec drain before we can call
+ // MediaCodec.flush() or MediaCodec.release(). http://crbug.com/598963. In
+ // that case, postpone ActualDestroy() until after the drain.
if (media_codec_ && codec_config_->codec_ == kCodecVP8) {
- // Clear pending_bitstream_records_.
+ // Clear |pending_bitstream_records_|.
while (!pending_bitstream_records_.empty())
pending_bitstream_records_.pop();
- // Postpone ActualDestroy after the drain.
StartCodecDrain(DRAIN_FOR_DESTROY);
} else {
ActualDestroy();
@@ -1415,9 +1326,6 @@ void AndroidVideoDecodeAccelerator::ActualDestroy() {
on_destroying_surface_cb_);
}
- if (strategy_)
- strategy_->EndCleanup();
-
// 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.
g_avda_manager.Get().DeallocateSurface(config_.surface_id, this);
@@ -1430,6 +1338,7 @@ void AndroidVideoDecodeAccelerator::ActualDestroy() {
g_avda_manager.Get().StopTimer(this);
ReleaseMediaCodec();
}
+
delete this;
}
@@ -1443,66 +1352,11 @@ const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const {
return size_;
}
-const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker()
- const {
- return thread_checker_;
-}
-
base::WeakPtr<gpu::gles2::GLES2Decoder>
AndroidVideoDecodeAccelerator::GetGlDecoder() const {
return get_gles2_decoder_cb_.Run();
}
-gpu::gles2::TextureRef* AndroidVideoDecodeAccelerator::GetTextureForPicture(
- const PictureBuffer& picture_buffer) {
- auto gles_decoder = GetGlDecoder();
- RETURN_ON_FAILURE(this, gles_decoder, "Failed to get GL decoder",
- ILLEGAL_STATE, nullptr);
- RETURN_ON_FAILURE(this, gles_decoder->GetContextGroup(),
- "Null gles_decoder->GetContextGroup()", ILLEGAL_STATE,
- nullptr);
- gpu::gles2::TextureManager* texture_manager =
- gles_decoder->GetContextGroup()->texture_manager();
- RETURN_ON_FAILURE(this, texture_manager, "Null texture_manager",
- ILLEGAL_STATE, nullptr);
-
- DCHECK_LE(1u, picture_buffer.internal_texture_ids().size());
- gpu::gles2::TextureRef* texture_ref =
- texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]);
- RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE,
- nullptr);
-
- return texture_ref;
-}
-
-scoped_refptr<gl::SurfaceTexture>
-AndroidVideoDecodeAccelerator::CreateAttachedSurfaceTexture(
- GLuint* service_id) {
- GLuint texture_id;
- glGenTextures(1, &texture_id);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- auto gl_decoder = GetGlDecoder();
- gl_decoder->RestoreTextureUnitBindings(0);
- gl_decoder->RestoreActiveTexture();
- DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
-
- *service_id = texture_id;
- // Previously, to reduce context switching, we used to create an unattached
- // SurfaceTexture and attach it lazily in the compositor's context. But that
- // was flaky because SurfaceTexture#detachFromGLContext() is buggy on a lot of
- // devices. Now we attach it to the current context, which means we might have
- // to context switch later to call updateTexImage(). Fortunately, if virtual
- // contexts are in use, we won't have to context switch.
- return gl::SurfaceTexture::Create(texture_id);
-}
-
void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("media", "AVDA::OnDestroyingSurface");
@@ -1517,7 +1371,7 @@ void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) {
state_ = SURFACE_DESTROYED;
if (media_codec_) {
ReleaseMediaCodec();
- strategy_->CodecChanged(media_codec_.get());
+ picture_buffer_manager_.CodecChanged(media_codec_.get());
}
// If we're draining, signal completion now because the drain can no longer
// proceed.
@@ -1525,12 +1379,6 @@ void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) {
OnDrainCompleted();
}
-void AndroidVideoDecodeAccelerator::OnFrameAvailable() {
- // Remember: this may be on any thread.
- DCHECK(strategy_);
- strategy_->OnFrameAvailable();
-}
-
void AndroidVideoDecodeAccelerator::PostError(
const ::tracked_objects::Location& from_here,
VideoDecodeAccelerator::Error error) {
@@ -1693,12 +1541,6 @@ void AndroidVideoDecodeAccelerator::ReleaseMediaCodec() {
}
// static
-bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy(
- const gpu::GpuPreferences& gpu_preferences) {
- return true;
-}
-
-// static
VideoDecodeAccelerator::Capabilities
AndroidVideoDecodeAccelerator::GetCapabilities(
const gpu::GpuPreferences& gpu_preferences) {
@@ -1759,20 +1601,18 @@ AndroidVideoDecodeAccelerator::GetCapabilities(
capabilities.flags =
VideoDecodeAccelerator::Capabilities::SUPPORTS_DEFERRED_INITIALIZATION;
- if (UseDeferredRenderingStrategy(gpu_preferences)) {
- capabilities.flags |= VideoDecodeAccelerator::Capabilities::
- NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE;
+ capabilities.flags |=
+ VideoDecodeAccelerator::Capabilities::NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE;
- // If we're using threaded texture mailboxes the COPY_REQUIRED flag must be
- // set on deferred strategy frames (http://crbug.com/582170), and
- // SurfaceView output is disabled (http://crbug.com/582170).
- if (gpu_preferences.enable_threaded_texture_mailboxes) {
- capabilities.flags |=
- media::VideoDecodeAccelerator::Capabilities::REQUIRES_TEXTURE_COPY;
- } else if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) {
- capabilities.flags |= media::VideoDecodeAccelerator::Capabilities::
- SUPPORTS_EXTERNAL_OUTPUT_SURFACE;
- }
+ // If we're using threaded texture mailboxes the COPY_REQUIRED flag must be
+ // set on the video frames (http://crbug.com/582170), and SurfaceView output
+ // is disabled (http://crbug.com/582170).
+ if (gpu_preferences.enable_threaded_texture_mailboxes) {
+ capabilities.flags |=
+ media::VideoDecodeAccelerator::Capabilities::REQUIRES_TEXTURE_COPY;
+ } else if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) {
+ capabilities.flags |= media::VideoDecodeAccelerator::Capabilities::
+ SUPPORTS_EXTERNAL_OUTPUT_SURFACE;
}
return capabilities;
« no previous file with comments | « media/gpu/android_video_decode_accelerator.h ('k') | media/gpu/android_video_decode_accelerator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698