Commit 4b2ccc21 authored by watk's avatar watk Committed by Commit bot

Delete AVDACopyingBackingStrategy and rename AVDADeferredRenderingBackingStrategy

AVDACopyingBackingStrategy is unused so it's now deleted. Since we only have a single
strategy left, it's renamed to AVDAPictureBufferManager, since its role is mostly
to associate PictureBuffers with MediaCodec buffers.

BUG=637463

Review-Url: https://codereview.chromium.org/2296513003
Cr-Commit-Position: refs/heads/master@{#415803}
parent 54d6d7be
...@@ -207,15 +207,12 @@ component("gpu") { ...@@ -207,15 +207,12 @@ component("gpu") {
if (is_android) { if (is_android) {
sources += [ sources += [
"android_copying_backing_strategy.cc",
"android_copying_backing_strategy.h",
"android_deferred_rendering_backing_strategy.cc",
"android_deferred_rendering_backing_strategy.h",
"android_video_decode_accelerator.cc", "android_video_decode_accelerator.cc",
"android_video_decode_accelerator.h", "android_video_decode_accelerator.h",
"avda_codec_image.cc", "avda_codec_image.cc",
"avda_codec_image.h", "avda_codec_image.h",
"avda_return_on_failure.h", "avda_picture_buffer_manager.cc",
"avda_picture_buffer_manager.h",
"avda_shared_state.cc", "avda_shared_state.cc",
"avda_shared_state.h", "avda_shared_state.h",
"avda_state_provider.h", "avda_state_provider.h",
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/android_copying_backing_strategy.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "media/base/limits.h"
#include "media/gpu/avda_return_on_failure.h"
#include "media/video/picture.h"
#include "ui/gl/android/surface_texture.h"
#include "ui/gl/gl_bindings.h"
namespace media {
AndroidCopyingBackingStrategy::AndroidCopyingBackingStrategy(
AVDAStateProvider* state_provider)
: state_provider_(state_provider),
surface_texture_id_(0),
media_codec_(nullptr) {}
AndroidCopyingBackingStrategy::~AndroidCopyingBackingStrategy() {}
gl::ScopedJavaSurface AndroidCopyingBackingStrategy::Initialize(
int surface_view_id) {
if (surface_view_id != VideoDecodeAccelerator::Config::kNoSurfaceID) {
LOG(ERROR) << "The copying strategy should not be initialized with a "
"surface id.";
return gl::ScopedJavaSurface();
}
surface_texture_ =
state_provider_->CreateAttachedSurfaceTexture(&surface_texture_id_);
return gl::ScopedJavaSurface(surface_texture_.get());
}
void AndroidCopyingBackingStrategy::BeginCleanup(
bool have_context,
const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) {
DCHECK(state_provider_->ThreadChecker().CalledOnValidThread());
if (copier_)
copier_->Destroy();
if (surface_texture_id_ && have_context)
glDeleteTextures(1, &surface_texture_id_);
}
void AndroidCopyingBackingStrategy::EndCleanup() {}
scoped_refptr<gl::SurfaceTexture>
AndroidCopyingBackingStrategy::GetSurfaceTexture() const {
return surface_texture_;
}
uint32_t AndroidCopyingBackingStrategy::GetTextureTarget() const {
return GL_TEXTURE_2D;
}
gfx::Size AndroidCopyingBackingStrategy::GetPictureBufferSize() const {
return state_provider_->GetSize();
}
void AndroidCopyingBackingStrategy::UseCodecBufferForPictureBuffer(
int32_t codec_buf_index,
const PictureBuffer& picture_buffer) {
// Make sure that the decoder is available.
RETURN_ON_FAILURE(state_provider_, state_provider_->GetGlDecoder().get(),
"Failed to get gles2 decoder instance.", ILLEGAL_STATE);
// Render the codec buffer into |surface_texture_|, and switch it to be
// the front buffer.
// This ignores the emitted ByteBuffer and instead relies on rendering to
// the codec's SurfaceTexture and then copying from that texture to the
// client's PictureBuffer's texture. This means that each picture's data
// is written three times: once to the ByteBuffer, once to the
// SurfaceTexture, and once to the client's texture. It would be nicer to
// either:
// 1) Render directly to the client's texture from MediaCodec (one write);
// or
// 2) Upload the ByteBuffer to the client's texture (two writes).
// Unfortunately neither is possible:
// 1) MediaCodec's use of SurfaceTexture is a singleton, and the texture
// written to can't change during the codec's lifetime. b/11990461
// 2) The ByteBuffer is likely to contain the pixels in a vendor-specific,
// opaque/non-standard format. It's not possible to negotiate the
// decoder to emit a specific colorspace, even using HW CSC. b/10706245
// So, we live with these two extra copies per picture :(
{
TRACE_EVENT0("media", "AVDA::ReleaseOutputBuffer");
media_codec_->ReleaseOutputBuffer(codec_buf_index, true);
}
{
TRACE_EVENT0("media", "AVDA::UpdateTexImage");
surface_texture_->UpdateTexImage();
}
float transform_matrix[16];
surface_texture_->GetTransformMatrix(transform_matrix);
DCHECK_LE(1u, picture_buffer.texture_ids().size());
uint32_t picture_buffer_texture_id = picture_buffer.texture_ids()[0];
// Defer initializing the CopyTextureCHROMIUMResourceManager until it is
// needed because it takes 10s of milliseconds to initialize.
if (!copier_) {
copier_.reset(new gpu::CopyTextureCHROMIUMResourceManager());
copier_->Initialize(state_provider_->GetGlDecoder().get(),
state_provider_->GetGlDecoder()
->GetContextGroup()
->feature_info()
->feature_flags());
}
// Here, we copy |surface_texture_id_| to the picture buffer instead of
// setting new texture to |surface_texture_| by calling attachToGLContext()
// because:
// 1. Once we call detachFrameGLContext(), it deletes the texture previously
// attached.
// 2. SurfaceTexture requires us to apply a transform matrix when we show
// the texture.
copier_->DoCopyTextureWithTransform(
state_provider_->GetGlDecoder().get(), GL_TEXTURE_EXTERNAL_OES,
surface_texture_id_, GL_TEXTURE_2D, picture_buffer_texture_id,
state_provider_->GetSize().width(), state_provider_->GetSize().height(),
true, false, false, transform_matrix);
}
void AndroidCopyingBackingStrategy::CodecChanged(VideoCodecBridge* codec) {
media_codec_ = codec;
}
void AndroidCopyingBackingStrategy::OnFrameAvailable() {
// TODO(liberato): crbug.com/574948 . The OnFrameAvailable logic can be
// moved into AVDA, and we should wait for it before doing the copy.
// Because there were some test failures, we don't do this now but
// instead preserve the old behavior.
}
bool AndroidCopyingBackingStrategy::ArePicturesOverlayable() {
return false;
}
void AndroidCopyingBackingStrategy::UpdatePictureBufferSize(
PictureBuffer* picture_buffer,
const gfx::Size& new_size) {
// This strategy uses 2D textures who's allocated memory is dependent on the
// size. To update size in all places, we must:
// 1) Update the PictureBuffer meta-data
picture_buffer->set_size(new_size);
// 2) Update the GL texture via glTexImage2D. This step assumes the caller
// has made our GL context current.
DCHECK_LE(1u, picture_buffer->texture_ids().size());
glBindTexture(GL_TEXTURE_2D, picture_buffer->texture_ids()[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, new_size.width(), new_size.height(),
0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
state_provider_->GetGlDecoder()->RestoreActiveTextureUnitBinding(
GL_TEXTURE_2D);
// 3) Update the CHROMIUM Texture's size.
gpu::gles2::TextureRef* texture_ref =
state_provider_->GetTextureForPicture(*picture_buffer);
RETURN_IF_NULL(texture_ref);
gpu::gles2::TextureManager* texture_manager =
state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager();
RETURN_IF_NULL(texture_manager);
texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA,
new_size.width(), new_size.height(), 1, 0,
GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(new_size));
}
} // namespace media
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_ANDROID_COPYING_BACKING_STRATEGY_H_
#define MEDIA_GPU_ANDROID_COPYING_BACKING_STRATEGY_H_
#include <stdint.h>
#include <memory>
#include "base/compiler_specific.h"
#include "media/gpu/android_video_decode_accelerator.h"
#include "media/gpu/media_gpu_export.h"
namespace gpu {
class CopyTextureCHROMIUMResourceManager;
}
namespace media {
class PictureBuffer;
}
namespace media {
class AVDAStateProvider;
// A BackingStrategy implementation that copies images to PictureBuffer
// textures via gpu texture copy.
class MEDIA_GPU_EXPORT AndroidCopyingBackingStrategy
: public AndroidVideoDecodeAccelerator::BackingStrategy {
public:
explicit AndroidCopyingBackingStrategy(AVDAStateProvider* state_provider);
~AndroidCopyingBackingStrategy() override;
// AndroidVideoDecodeAccelerator::BackingStrategy
gl::ScopedJavaSurface Initialize(int surface_view_id) override;
void BeginCleanup(
bool have_context,
const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) override;
void EndCleanup() override;
scoped_refptr<gl::SurfaceTexture> GetSurfaceTexture() const override;
uint32_t GetTextureTarget() const override;
gfx::Size GetPictureBufferSize() const override;
void UseCodecBufferForPictureBuffer(
int32_t codec_buffer_index,
const PictureBuffer& picture_buffer) override;
void CodecChanged(VideoCodecBridge* codec) override;
void OnFrameAvailable() override;
bool ArePicturesOverlayable() override;
void UpdatePictureBufferSize(PictureBuffer* picture_buffer,
const gfx::Size& new_size) override;
private:
// Used for copy the texture from surface texture to picture buffers.
std::unique_ptr<gpu::CopyTextureCHROMIUMResourceManager> copier_;
AVDAStateProvider* state_provider_;
// A container of texture. Used to set a texture to |media_codec_|.
scoped_refptr<gl::SurfaceTexture> surface_texture_;
// The texture id which is set to |surface_texture_|.
uint32_t surface_texture_id_;
VideoCodecBridge* media_codec_;
};
} // namespace media
#endif // MEDIA_GPU_ANDROID_COPYING_BACKING_STRATEGY_H_
...@@ -9,9 +9,7 @@ ...@@ -9,9 +9,7 @@
#include <list> #include <list>
#include <map> #include <map>
#include <memory>
#include <queue> #include <queue>
#include <string>
#include <vector> #include <vector>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
...@@ -22,6 +20,7 @@ ...@@ -22,6 +20,7 @@
#include "media/base/android/media_drm_bridge_cdm_context.h" #include "media/base/android/media_drm_bridge_cdm_context.h"
#include "media/base/android/sdk_media_codec_bridge.h" #include "media/base/android/sdk_media_codec_bridge.h"
#include "media/base/media_keys.h" #include "media/base/media_keys.h"
#include "media/gpu/avda_picture_buffer_manager.h"
#include "media/gpu/avda_state_provider.h" #include "media/gpu/avda_state_provider.h"
#include "media/gpu/avda_surface_tracker.h" #include "media/gpu/avda_surface_tracker.h"
#include "media/gpu/gpu_video_decode_accelerator_helpers.h" #include "media/gpu/gpu_video_decode_accelerator_helpers.h"
...@@ -34,92 +33,16 @@ class SurfaceTexture; ...@@ -34,92 +33,16 @@ class SurfaceTexture;
} }
namespace media { namespace media {
class SharedMemoryRegion; class SharedMemoryRegion;
// A VideoDecodeAccelerator implementation for Android. // A VideoDecodeAccelerator implementation for Android. This class decodes the
// This class decodes the input encoded stream by using Android's MediaCodec // encded input stream using Android's MediaCodec. It handles the work of
// class. http://developer.android.com/reference/android/media/MediaCodec.html // transferring data to and from MediaCodec, and delegates attaching MediaCodec
// It delegates attaching pictures to PictureBuffers to a BackingStrategy, but // output buffers to PictureBuffers to AVDAPictureBufferManager.
// otherwise handles the work of transferring data to / from MediaCodec.
class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator
: public VideoDecodeAccelerator, : public VideoDecodeAccelerator,
public AVDAStateProvider { public AVDAStateProvider {
public: public:
using OutputBufferMap = std::map<int32_t, PictureBuffer>;
// A BackingStrategy is responsible for making a PictureBuffer's texture
// contain the image that a MediaCodec decoder buffer tells it to.
class BackingStrategy {
public:
virtual ~BackingStrategy() {}
// Must be called before anything else. If surface_view_id is not equal to
// |kNoSurfaceID| it refers to a SurfaceView that the strategy must render
// to.
// Returns the Java surface to configure MediaCodec with.
virtual gl::ScopedJavaSurface Initialize(int surface_view_id) = 0;
// Called before the AVDA does any Destroy() work. The strategy should
// release any pending codec buffers, for example.
virtual void BeginCleanup(bool have_context,
const OutputBufferMap& buffer_map) = 0;
// Called before the AVDA closes up entirely. This will be
// the last call that the BackingStrategy receives.
virtual void EndCleanup() = 0;
// This returns the SurfaceTexture created by Initialize, or nullptr if
// the strategy was initialized with a SurfaceView.
virtual scoped_refptr<gl::SurfaceTexture> GetSurfaceTexture() const = 0;
// Return the GL texture target that the PictureBuffer textures use.
virtual uint32_t GetTextureTarget() const = 0;
// Return the size to use when requesting picture buffers.
virtual gfx::Size GetPictureBufferSize() const = 0;
// Make the provided PictureBuffer draw the image that is represented by
// the decoded output buffer at codec_buffer_index.
virtual void UseCodecBufferForPictureBuffer(
int32_t codec_buffer_index,
const PictureBuffer& picture_buffer) = 0;
// Notify strategy that a picture buffer has been assigned.
virtual void AssignOnePictureBuffer(const PictureBuffer& picture_buffer,
bool have_context) {}
// Notify strategy that a picture buffer has been reused.
virtual void ReuseOnePictureBuffer(const PictureBuffer& picture_buffer) {}
// Release MediaCodec buffers.
virtual void ReleaseCodecBuffers(
const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) {}
// Attempts to free up codec output buffers by rendering early.
virtual void MaybeRenderEarly() {}
// Notify strategy that we have a new android MediaCodec instance. This
// happens when we're starting up or re-configuring mid-stream. Any
// previously provided codec should no longer be referenced.
virtual void CodecChanged(VideoCodecBridge* codec) = 0;
// Notify the strategy that a frame is available. This callback can happen
// on any thread at any time.
virtual void OnFrameAvailable() = 0;
// Whether the pictures produced by this backing strategy are overlayable.
virtual bool ArePicturesOverlayable() = 0;
// Size may have changed due to resolution change since the last time this
// PictureBuffer was used. Update the size of the picture buffer to
// |new_size| and also update any size-dependent state (e.g. size of
// associated texture). Callers should set the correct GL context prior to
// calling.
virtual void UpdatePictureBufferSize(PictureBuffer* picture_buffer,
const gfx::Size& new_size) = 0;
};
AndroidVideoDecodeAccelerator( AndroidVideoDecodeAccelerator(
const MakeGLContextCurrentCallback& make_context_current_cb, const MakeGLContextCurrentCallback& make_context_current_cb,
const GetGLES2DecoderCallback& get_gles2_decoder_cb); const GetGLES2DecoderCallback& get_gles2_decoder_cb);
...@@ -141,22 +64,13 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator ...@@ -141,22 +64,13 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator
// AVDAStateProvider implementation: // AVDAStateProvider implementation:
const gfx::Size& GetSize() const override; const gfx::Size& GetSize() const override;
const base::ThreadChecker& ThreadChecker() const override;
base::WeakPtr<gpu::gles2::GLES2Decoder> GetGlDecoder() const override; base::WeakPtr<gpu::gles2::GLES2Decoder> GetGlDecoder() const override;
gpu::gles2::TextureRef* GetTextureForPicture(
const PictureBuffer& picture_buffer) override;
scoped_refptr<gl::SurfaceTexture> CreateAttachedSurfaceTexture(
GLuint* service_id) override;
void PostError(const ::tracked_objects::Location& from_here, void PostError(const ::tracked_objects::Location& from_here,
VideoDecodeAccelerator::Error error) override; VideoDecodeAccelerator::Error error) override;
static VideoDecodeAccelerator::Capabilities GetCapabilities( static VideoDecodeAccelerator::Capabilities GetCapabilities(
const gpu::GpuPreferences& gpu_preferences); const gpu::GpuPreferences& gpu_preferences);
// Notifies about SurfaceTexture::OnFrameAvailable. This can happen on any
// thread at any time!
void OnFrameAvailable();
private: private:
friend class AVDAManager; friend class AVDAManager;
...@@ -195,8 +109,7 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator ...@@ -195,8 +109,7 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator
// Whether encryption scheme requires to use protected surface. // Whether encryption scheme requires to use protected surface.
bool needs_protected_surface_ = false; bool needs_protected_surface_ = false;
// The surface that MediaCodec is configured to output to. It's created by // The surface that MediaCodec is configured to output to.
// the backing strategy.
gl::ScopedJavaSurface surface_; gl::ScopedJavaSurface surface_;
// The MediaCrypto object is used in the MediaCodec.configure() in case of // The MediaCrypto object is used in the MediaCodec.configure() in case of
...@@ -225,12 +138,12 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator ...@@ -225,12 +138,12 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator
// if initialization should stop. // if initialization should stop.
void OnSurfaceAvailable(bool success); void OnSurfaceAvailable(bool success);
// Finish initialization of the strategy. This is to be called when the // Initialize of the picture buffer manager. This is to be called when the
// SurfaceView in |surface_id_|, if any, is no longer busy. It will return // SurfaceView in |surface_id_|, if any, is no longer busy. It will return
// false on failure, and true if initialization was successful. This includes // false on failure, and true if initialization was successful. This includes
// synchronous and asynchronous init; the AVDA might not yet have a codec on // synchronous and asynchronous init; the AVDA might not yet have a codec on
// success, but async init will at least be in progress. // success, but async init will at least be in progress.
bool InitializeStrategy(); bool InitializePictureBufferManager();
// A part of destruction process that is sometimes postponed after the drain. // A part of destruction process that is sometimes postponed after the drain.
void ActualDestroy(); void ActualDestroy();
...@@ -355,10 +268,6 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator ...@@ -355,10 +268,6 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator
// this. // this.
void OnDestroyingSurface(int surface_id); void OnDestroyingSurface(int surface_id);
// Returns true if and only if we should use deferred rendering.
static bool UseDeferredRenderingStrategy(
const gpu::GpuPreferences& gpu_preferences);
// Indicates if MediaCodec should not be used for software decoding since we // Indicates if MediaCodec should not be used for software decoding since we
// have safer versions elsewhere. // have safer versions elsewhere.
bool IsMediaCodecSoftwareDecodingForbidden() const; bool IsMediaCodecSoftwareDecodingForbidden() const;
...@@ -379,9 +288,8 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator ...@@ -379,9 +288,8 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator
// error state. // error state.
State state_; State state_;
// This map maintains the picture buffers passed to the client for decoding. // The assigned picture buffers by picture buffer id.
// The key is the picture buffer id. AVDAPictureBufferManager::PictureBufferMap output_picture_buffers_;
OutputBufferMap output_picture_buffers_;
// This keeps the free picture buffer ids which can be used for sending // This keeps the free picture buffer ids which can be used for sending
// decoded frames to the client. // decoded frames to the client.
...@@ -424,12 +332,7 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator ...@@ -424,12 +332,7 @@ class MEDIA_GPU_EXPORT AndroidVideoDecodeAccelerator
// NotifyEndOfBitstreamBuffer() before getting output from the bitstream. // NotifyEndOfBitstreamBuffer() before getting output from the bitstream.
std::list<int32_t> bitstreams_notified_in_advance_; std::list<int32_t> bitstreams_notified_in_advance_;
// Backing strategy that we'll use to connect PictureBuffers to frames. AVDAPictureBufferManager picture_buffer_manager_;
std::unique_ptr<BackingStrategy> strategy_;
// Helper class that manages asynchronous OnFrameAvailable callbacks.
class OnFrameAvailableHandler;
scoped_refptr<OnFrameAvailableHandler> on_frame_available_handler_;
// Time at which we last did useful work on io_timer_. // Time at which we last did useful work on io_timer_.
base::TimeTicks most_recent_work_; base::TimeTicks most_recent_work_;
......
...@@ -15,20 +15,21 @@ ...@@ -15,20 +15,21 @@
#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
#include "media/base/android/media_codec_util.h" #include "media/base/android/media_codec_util.h"
#include "media/base/android/media_jni_registrar.h" #include "media/base/android/media_jni_registrar.h"
#include "media/gpu/android_copying_backing_strategy.h"
#include "media/gpu/android_video_decode_accelerator.h" #include "media/gpu/android_video_decode_accelerator.h"
#include "media/video/picture.h" #include "media/video/picture.h"
#include "media/video/video_decode_accelerator.h" #include "media/video/video_decode_accelerator.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/android/surface_texture.h" #include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/init/gl_factory.h"
namespace { namespace {
bool MockMakeContextCurrent() { bool MakeContextCurrent() {
return true; return true;
} }
static base::WeakPtr<gpu::gles2::GLES2Decoder> MockGetGLES2Decoder( base::WeakPtr<gpu::gles2::GLES2Decoder> GetGLES2Decoder(
const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder) { const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder) {
return decoder; return decoder;
} }
...@@ -65,43 +66,48 @@ class AndroidVideoDecodeAcceleratorTest : public testing::Test { ...@@ -65,43 +66,48 @@ class AndroidVideoDecodeAcceleratorTest : public testing::Test {
JNIEnv* env = base::android::AttachCurrentThread(); JNIEnv* env = base::android::AttachCurrentThread();
RegisterJni(env); RegisterJni(env);
// Start message loop because gl::init::ClearGLBindings();
// AndroidVideoDecodeAccelerator::ConfigureMediaCodec() starts a timer task. ASSERT_TRUE(gl::init::InitializeGLOneOff());
surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size(1024, 1024));
context_ = gl::init::CreateGLContext(nullptr, surface_.get(),
gl::PreferDiscreteGpu);
context_->MakeCurrent(surface_.get());
// Start a message loop because AVDA starts a timer task.
message_loop_.reset(new base::MessageLoop()); message_loop_.reset(new base::MessageLoop());
gl_decoder_.reset(new testing::NiceMock<gpu::gles2::MockGLES2Decoder>());
client_.reset(new MockVideoDecodeAcceleratorClient());
std::unique_ptr<gpu::gles2::MockGLES2Decoder> decoder( vda_.reset(new AndroidVideoDecodeAccelerator(
new gpu::gles2::MockGLES2Decoder()); base::Bind(&MakeContextCurrent),
std::unique_ptr<MockVideoDecodeAcceleratorClient> client( base::Bind(&GetGLES2Decoder, gl_decoder_->AsWeakPtr())));
new MockVideoDecodeAcceleratorClient());
accelerator_.reset(new AndroidVideoDecodeAccelerator(
base::Bind(&MockMakeContextCurrent),
base::Bind(&MockGetGLES2Decoder, decoder->AsWeakPtr())));
} }
bool Configure(VideoCodec codec) { bool Initialize(VideoCodecProfile profile) {
AndroidVideoDecodeAccelerator* accelerator = return vda_->Initialize(VideoDecodeAccelerator::Config(profile),
static_cast<AndroidVideoDecodeAccelerator*>(accelerator_.get()); client_.get());
scoped_refptr<gl::SurfaceTexture> surface_texture =
gl::SurfaceTexture::Create(0);
accelerator->codec_config_->surface_ =
gl::ScopedJavaSurface(surface_texture.get());
accelerator->codec_config_->codec_ = codec;
return accelerator->ConfigureMediaCodecSynchronously();
} }
private: private:
std::unique_ptr<VideoDecodeAccelerator> accelerator_;
std::unique_ptr<base::MessageLoop> message_loop_; std::unique_ptr<base::MessageLoop> message_loop_;
scoped_refptr<gl::GLSurface> surface_;
scoped_refptr<gl::GLContext> context_;
std::unique_ptr<gpu::gles2::MockGLES2Decoder> gl_decoder_;
std::unique_ptr<MockVideoDecodeAcceleratorClient> client_;
// This must be a unique pointer to a VDA and not an AVDA to ensure the
// the default_delete specialization that calls Destroy() will be used.
std::unique_ptr<VideoDecodeAccelerator> vda_;
}; };
TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureUnsupportedCodec) { TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureUnsupportedCodec) {
EXPECT_FALSE(Configure(kUnknownVideoCodec)); ASSERT_FALSE(Initialize(VIDEO_CODEC_PROFILE_UNKNOWN));
} }
TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureSupportedCodec) { TEST_F(AndroidVideoDecodeAcceleratorTest, ConfigureSupportedCodec) {
if (!MediaCodecUtil::IsMediaCodecAvailable()) if (!MediaCodecUtil::IsMediaCodecAvailable())
return; return;
EXPECT_TRUE(Configure(kCodecVP8)); ASSERT_TRUE(Initialize(VP8PROFILE_ANY));
} }
} // namespace media } // namespace media
......
...@@ -2,71 +2,93 @@ ...@@ -2,71 +2,93 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef MEDIA_GPU_ANDROID_DEFERRED_RENDERING_BACKING_STRATEGY_H_ #ifndef MEDIA_GPU_AVDA_PICTURE_BUFFER_MANAGER_H_
#define MEDIA_GPU_ANDROID_DEFERRED_RENDERING_BACKING_STRATEGY_H_ #define MEDIA_GPU_AVDA_PICTURE_BUFFER_MANAGER_H_
#include <stdint.h> #include <stdint.h>
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "media/gpu/android_video_decode_accelerator.h" #include "media/gpu/avda_state_provider.h"
#include "media/gpu/media_gpu_export.h" #include "media/gpu/media_gpu_export.h"
namespace gl {
class GLImage;
}
namespace gpu { namespace gpu {
namespace gles2 { namespace gles2 {
class GLStreamTextureImage; class GLStreamTextureImage;
class TextureRef;
} }
} }
namespace media { namespace gl {
class ScopedJavaSurface;
class SurfaceTexture;
}
class AVDACodecImage; namespace media {
class AVDASharedState; class AVDASharedState;
class VideoCodecBridge;
// A BackingStrategy implementation that defers releasing codec buffers until
// a PictureBuffer's texture is used to draw, then draws using the surface // AVDAPictureBufferManager is used by AVDA to associate its PictureBuffers with
// texture's front buffer rather than a copy. To do this, it uses a GLImage // MediaCodec output buffers. It attaches AVDACodecImages to the PictureBuffer
// implementation to talk to MediaCodec. // textures so that when they're used to draw the AVDACodecImage can release the
class MEDIA_GPU_EXPORT AndroidDeferredRenderingBackingStrategy // MediaCodec buffer to the backing Surface. If the Surface is a SurfaceTexture,
: public AndroidVideoDecodeAccelerator::BackingStrategy { // the front buffer can then be used to draw without needing to copy the pixels.
// If the Surface is a SurfaceView, the release causes the frame to be displayed
// immediately.
class MEDIA_GPU_EXPORT AVDAPictureBufferManager {
public: public:
explicit AndroidDeferredRenderingBackingStrategy( using PictureBufferMap = std::map<int32_t, PictureBuffer>;
AVDAStateProvider* state_provider);
~AndroidDeferredRenderingBackingStrategy() override; AVDAPictureBufferManager();
virtual ~AVDAPictureBufferManager();
// AndroidVideoDecodeAccelerator::BackingStrategy
gl::ScopedJavaSurface Initialize(int surface_view_id) override; // Must be called before anything else. If |surface_view_id| is |kNoSurfaceID|
void BeginCleanup( // then a new SurfaceTexture will be returned. Otherwise, the corresponding
bool have_context, // SurfaceView will be returned.
const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) override; gl::ScopedJavaSurface Initialize(AVDAStateProvider* state_provider,
void EndCleanup() override; int surface_view_id);
scoped_refptr<gl::SurfaceTexture> GetSurfaceTexture() const override;
uint32_t GetTextureTarget() const override; void Destroy(const PictureBufferMap& buffers);
gfx::Size GetPictureBufferSize() const override;
void UseCodecBufferForPictureBuffer( // Returns the GL texture target that the PictureBuffer textures use.
int32_t codec_buffer_index, uint32_t GetTextureTarget() const;
const PictureBuffer& picture_buffer) override;
void AssignOnePictureBuffer(const PictureBuffer&, bool) override; // Returns the size to use when requesting picture buffers.
void ReuseOnePictureBuffer(const PictureBuffer& picture_buffer) override; gfx::Size GetPictureBufferSize() const;
void MaybeRenderEarly() override;
void CodecChanged(VideoCodecBridge* codec) override; // Sets up |picture_buffer| so that its texture will refer to the image that
void ReleaseCodecBuffers( // is represented by the decoded output buffer at codec_buffer_index.
const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) override; void UseCodecBufferForPictureBuffer(int32_t codec_buffer_index,
void OnFrameAvailable() override; const PictureBuffer& picture_buffer);
bool ArePicturesOverlayable() override;
void UpdatePictureBufferSize(PictureBuffer* picture_buffer, // Assigns a picture buffer and attaches an image to its texture.
const gfx::Size& new_size) override; void AssignOnePictureBuffer(const PictureBuffer& picture_buffer,
bool have_context);
// Reuses a picture buffer to hold a new frame.
void ReuseOnePictureBuffer(const PictureBuffer& picture_buffer);
// Release MediaCodec buffers.
void ReleaseCodecBuffers(const PictureBufferMap& buffers);
// Attempts to free up codec output buffers by rendering early.
void MaybeRenderEarly();
// Called when the MediaCodec instance changes. If |codec| is nullptr the
// MediaCodec is being destroyed. Previously provided codecs should no longer
// be referenced.
void CodecChanged(VideoCodecBridge* codec);
// Whether the pictures buffers are overlayable.
bool ArePicturesOverlayable();
private: private:
// Release any codec buffer that is associated with the given picture buffer // Release any codec buffer that is associated with the given picture buffer
// back to the codec. It is okay if there is no such buffer. // back to the codec. It is okay if there is no such buffer.
void ReleaseCodecBufferForPicture(const PictureBuffer& picture_buffer); void ReleaseCodecBufferForPicture(const PictureBuffer& picture_buffer);
gpu::gles2::TextureRef* GetTextureForPicture(
const PictureBuffer& picture_buffer);
// Sets up the texture references (as found by |picture_buffer|), for the // Sets up the texture references (as found by |picture_buffer|), for the
// specified |image|. If |image| is null, clears any ref on the texture // specified |image|. If |image| is null, clears any ref on the texture
// associated with |picture_buffer|. // associated with |picture_buffer|.
...@@ -74,17 +96,6 @@ class MEDIA_GPU_EXPORT AndroidDeferredRenderingBackingStrategy ...@@ -74,17 +96,6 @@ class MEDIA_GPU_EXPORT AndroidDeferredRenderingBackingStrategy
const PictureBuffer& picture_buffer, const PictureBuffer& picture_buffer,
const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image); const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image);
// Make a copy of the SurfaceTexture's front buffer and associate all given
// picture buffer textures with it. The picture buffer textures will not
// dependend on |this|, the SurfaceTexture, the MediaCodec or the VDA, so it's
// used to back the picture buffers when the VDA is being destroyed.
void CopySurfaceTextureToPictures(
const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers);
// Return true if and only if CopySurfaceTextureToPictures is expected to work
// on this device.
bool ShouldCopyPictures() const;
scoped_refptr<AVDASharedState> shared_state_; scoped_refptr<AVDASharedState> shared_state_;
AVDAStateProvider* state_provider_; AVDAStateProvider* state_provider_;
...@@ -93,15 +104,18 @@ class MEDIA_GPU_EXPORT AndroidDeferredRenderingBackingStrategy ...@@ -93,15 +104,18 @@ class MEDIA_GPU_EXPORT AndroidDeferredRenderingBackingStrategy
// we're not rendering to a SurfaceView. // we're not rendering to a SurfaceView.
scoped_refptr<gl::SurfaceTexture> surface_texture_; scoped_refptr<gl::SurfaceTexture> surface_texture_;
class OnFrameAvailableHandler;
scoped_refptr<OnFrameAvailableHandler> on_frame_available_handler_;
VideoCodecBridge* media_codec_; VideoCodecBridge* media_codec_;
// Picture buffer IDs that are out for display. Stored in order of frames as // Picture buffer IDs that are out for display. Stored in order of frames as
// they are returned from the decoder. // they are returned from the decoder.
std::vector<int32_t> pictures_out_for_display_; std::vector<int32_t> pictures_out_for_display_;
DISALLOW_COPY_AND_ASSIGN(AndroidDeferredRenderingBackingStrategy); DISALLOW_COPY_AND_ASSIGN(AVDAPictureBufferManager);
}; };
} // namespace media } // namespace media
#endif // MEDIA_GPU_ANDROID_DEFERRED_RENDERING_BACKING_STRATEGY_H_ #endif // MEDIA_GPU_AVDA_PICTURE_BUFFER_MANAGER_H_
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_AVDA_RETURN_ON_FAILURE_H_
#define MEDIA_GPU_AVDA_RETURN_ON_FAILURE_H_
#include "media/video/video_decode_accelerator.h"
// Helper macros for dealing with failure. If |result| evaluates false, emit
// |log| to ERROR, register |error| with the decoder, and return. This will
// also transition to the error state, stopping further decoding.
// This is meant to be used only within AndroidVideoDecoder and the various
// backing strategies. |provider| must support PostError. The varargs
// can be used for the return value.
#define RETURN_ON_FAILURE(provider, result, log, error, ...) \
do { \
if (!(result)) { \
DLOG(ERROR) << log; \
provider->PostError(FROM_HERE, VideoDecodeAccelerator::error); \
return __VA_ARGS__; \
} \
} while (0)
// Similar to the above, with some handy boilerplate savings. The varargs
// can be used for the return value.
#define RETURN_IF_NULL(ptr, ...) \
RETURN_ON_FAILURE(state_provider_, ptr, "Got null for " << #ptr, \
ILLEGAL_STATE, ##__VA_ARGS__);
// Return null if !ptr.
#define RETURN_NULL_IF_NULL(ptr) RETURN_IF_NULL(ptr, 0)
#endif // MEDIA_GPU_AVDA_RETURN_ON_FAILURE_H_
...@@ -10,10 +10,6 @@ ...@@ -10,10 +10,6 @@
#include "gpu/command_buffer/service/texture_manager.h" #include "gpu/command_buffer/service/texture_manager.h"
#include "media/video/video_decode_accelerator.h" #include "media/video/video_decode_accelerator.h"
namespace gl {
class SurfaceTexture;
}
namespace gpu { namespace gpu {
namespace gles2 { namespace gles2 {
class GLES2Decoder; class GLES2Decoder;
...@@ -22,21 +18,13 @@ class GLES2Decoder; ...@@ -22,21 +18,13 @@ class GLES2Decoder;
namespace media { namespace media {
// Helper class that provides the BackingStrategy with enough state // Helper class that provides AVDAPictureBufferManager with enough state
// to do useful work. // to do useful work.
class AVDAStateProvider { class AVDAStateProvider {
public: public:
// Various handy getters. // Various handy getters.
virtual const gfx::Size& GetSize() const = 0; virtual const gfx::Size& GetSize() const = 0;
virtual const base::ThreadChecker& ThreadChecker() const = 0;
virtual base::WeakPtr<gpu::gles2::GLES2Decoder> GetGlDecoder() const = 0; virtual base::WeakPtr<gpu::gles2::GLES2Decoder> GetGlDecoder() const = 0;
virtual gpu::gles2::TextureRef* GetTextureForPicture(
const PictureBuffer& picture_buffer) = 0;
// Create a SurfaceTexture and attach a new gl texture to it. |*service_id|
// is set to the created texture id.
virtual scoped_refptr<gl::SurfaceTexture> CreateAttachedSurfaceTexture(
GLuint* service_id) = 0;
// Helper function to report an error condition and stop decoding. // Helper function to report an error condition and stop decoding.
// This will post NotifyError(), and transition to the error state. // This will post NotifyError(), and transition to the error state.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment