summaryrefslogtreecommitdiff
path: root/chromium/media/gpu/android
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/gpu/android')
-rw-r--r--chromium/media/gpu/android/codec_image.cc34
-rw-r--r--chromium/media/gpu/android/codec_image.h22
-rw-r--r--chromium/media/gpu/android/codec_image_unittest.cc8
-rw-r--r--chromium/media/gpu/android/frame_info_helper.cc229
-rw-r--r--chromium/media/gpu/android/frame_info_helper.h21
-rw-r--r--chromium/media/gpu/android/media_codec_video_decoder.cc76
-rw-r--r--chromium/media/gpu/android/media_codec_video_decoder.h37
-rw-r--r--chromium/media/gpu/android/media_codec_video_decoder_unittest.cc46
-rw-r--r--chromium/media/gpu/android/video_frame_factory_impl.cc65
-rw-r--r--chromium/media/gpu/android/video_frame_factory_impl.h16
-rw-r--r--chromium/media/gpu/android/video_frame_factory_impl_unittest.cc120
11 files changed, 310 insertions, 364 deletions
diff --git a/chromium/media/gpu/android/codec_image.cc b/chromium/media/gpu/android/codec_image.cc
index ae3a90da5c9..1a0b7d93184 100644
--- a/chromium/media/gpu/android/codec_image.cc
+++ b/chromium/media/gpu/android/codec_image.cc
@@ -25,11 +25,11 @@ CodecImage::~CodecImage() {
void CodecImage::Initialize(
std::unique_ptr<CodecOutputBufferRenderer> output_buffer_renderer,
- scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
+ bool is_texture_owner_backed,
PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb) {
DCHECK(output_buffer_renderer);
output_buffer_renderer_ = std::move(output_buffer_renderer);
- codec_buffer_wait_coordinator_ = std::move(codec_buffer_wait_coordinator);
+ is_texture_owner_backed_ = is_texture_owner_backed;
promotion_hint_cb_ = std::move(promotion_hint_cb);
}
@@ -42,7 +42,6 @@ void CodecImage::NotifyUnused() {
// our reference to the TextureOwner (if any). In other words, undo anything
// that we did in Initialize.
ReleaseCodecBuffer();
- codec_buffer_wait_coordinator_.reset();
promotion_hint_cb_ = base::NullCallback();
for (auto& cb : unused_cbs_)
@@ -65,7 +64,7 @@ unsigned CodecImage::GetDataType() {
CodecImage::BindOrCopy CodecImage::ShouldBindOrCopy() {
// If we're using an overlay, then pretend it's bound. That way, we'll get
// calls to ScheduleOverlayPlane. Otherwise, CopyTexImage needs to be called.
- return !codec_buffer_wait_coordinator_ ? BIND : COPY;
+ return is_texture_owner_backed_ ? COPY : BIND;
}
bool CodecImage::BindTexImage(unsigned target) {
@@ -82,16 +81,17 @@ bool CodecImage::CopyTexImage(unsigned target) {
if (target != GL_TEXTURE_EXTERNAL_OES)
return false;
+ if (!output_buffer_renderer_)
+ return true;
+
GLint bound_service_id = 0;
glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
// The currently bound texture should be the texture owner's texture.
if (bound_service_id !=
static_cast<GLint>(
- codec_buffer_wait_coordinator_->texture_owner()->GetTextureId()))
+ output_buffer_renderer_->texture_owner()->GetTextureId()))
return false;
- if (!output_buffer_renderer_)
- return true;
output_buffer_renderer_->RenderToTextureOwnerFrontBuffer(
BindingsMode::kEnsureTexImageBound);
@@ -113,7 +113,7 @@ bool CodecImage::ScheduleOverlayPlane(
bool enable_blend,
std::unique_ptr<gfx::GpuFence> gpu_fence) {
TRACE_EVENT0("media", "CodecImage::ScheduleOverlayPlane");
- if (codec_buffer_wait_coordinator_) {
+ if (is_texture_owner_backed_) {
DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is "
"TextureOwner backed.";
return false;
@@ -131,7 +131,7 @@ void CodecImage::NotifyOverlayPromotion(bool promotion,
if (!promotion_hint_cb_)
return;
- if (!codec_buffer_wait_coordinator_ && promotion) {
+ if (!is_texture_owner_backed_ && promotion) {
// When |CodecImage| is already backed by SurfaceView, and it should be used
// as overlay.
@@ -157,16 +157,6 @@ void CodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
uint64_t process_tracing_id,
const std::string& dump_name) {}
-void CodecImage::GetTextureMatrix(float matrix[16]) {
- static constexpr float kIdentity[16]{
- 1, 0, 0, 0, //
- 0, 1, 0, 0, //
- 0, 0, 1, 0, //
- 0, 0, 0, 1 //
- };
- memcpy(matrix, kIdentity, sizeof(kIdentity));
-}
-
void CodecImage::NotifyPromotionHint(bool promotion_hint,
int display_x,
int display_y,
@@ -174,7 +164,7 @@ void CodecImage::NotifyPromotionHint(bool promotion_hint,
int display_height) {
// TODO(crbug.com/1004859): Add back early skip due to suspecting affecting
// video smoothness.
- if (promotion_hint && !codec_buffer_wait_coordinator_)
+ if (promotion_hint && !is_texture_owner_backed_)
return;
NotifyOverlayPromotion(
@@ -241,11 +231,11 @@ CodecImage::GetAHardwareBuffer() {
// as free when viz is still using us for drawing. This can happen if the
// renderer crashes before receiving returns. It's hard to catch elsewhere,
// so just handle it gracefully here.
- if (!codec_buffer_wait_coordinator_)
+ if (!output_buffer_renderer_)
return nullptr;
RenderToTextureOwnerFrontBuffer(BindingsMode::kDontRestoreIfBound);
- return codec_buffer_wait_coordinator_->texture_owner()->GetAHardwareBuffer();
+ return output_buffer_renderer_->texture_owner()->GetAHardwareBuffer();
}
gfx::Rect CodecImage::GetCropRect() {
diff --git a/chromium/media/gpu/android/codec_image.h b/chromium/media/gpu/android/codec_image.h
index 8693118f918..c765e24dbfe 100644
--- a/chromium/media/gpu/android/codec_image.h
+++ b/chromium/media/gpu/android/codec_image.h
@@ -15,7 +15,6 @@
#include "base/memory/ref_counted_delete_on_sequence.h"
#include "gpu/command_buffer/service/gl_stream_texture_image.h"
#include "gpu/command_buffer/service/stream_texture_shared_image_interface.h"
-#include "media/gpu/android/codec_buffer_wait_coordinator.h"
#include "media/gpu/android/codec_output_buffer_renderer.h"
#include "media/gpu/android/promotion_hint_aggregator.h"
#include "media/gpu/media_gpu_export.h"
@@ -54,7 +53,7 @@ class MEDIA_GPU_EXPORT CodecImage
// not in use.
void Initialize(
std::unique_ptr<CodecOutputBufferRenderer> output_buffer_renderer,
- scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
+ bool is_texture_owner_backed,
PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb);
// Add a callback that will be called when we're marked as unused. Does not
@@ -91,7 +90,6 @@ class MEDIA_GPU_EXPORT CodecImage
GetAHardwareBuffer() override;
gfx::Rect GetCropRect() override;
// gpu::gles2::GLStreamTextureMatrix implementation
- void GetTextureMatrix(float xform[16]) override;
// Currently this API is implemented by the NotifyOverlayPromotion, since this
// API is expected to be removed.
void NotifyPromotionHint(bool promotion_hint,
@@ -129,18 +127,11 @@ class MEDIA_GPU_EXPORT CodecImage
// Whether this image is backed by a texture owner.
- // We want to check for texture_owner owned by
- // |codec_buffer_wait_coordinator_| and hence only checking for
- // |codec_buffer_wait_coordinator_| is enough here.
- // TODO(vikassoni): Update the method name in future refactorings.
- bool is_texture_owner_backed() const {
- return !!codec_buffer_wait_coordinator_;
- }
+ bool is_texture_owner_backed() const { return is_texture_owner_backed_; }
scoped_refptr<gpu::TextureOwner> texture_owner() const {
- return codec_buffer_wait_coordinator_
- ? codec_buffer_wait_coordinator_->texture_owner()
- : nullptr;
+ return output_buffer_renderer_ ? output_buffer_renderer_->texture_owner()
+ : nullptr;
}
// Renders this image to the front buffer of its backing surface.
@@ -180,9 +171,8 @@ class MEDIA_GPU_EXPORT CodecImage
// frame available event before calling UpdateTexImage().
bool RenderToTextureOwnerFrontBuffer(BindingsMode bindings_mode);
- // The CodecBufferWaitCoordinator that |output_buffer_| will be rendered to.
- // Or null, if this image is backed by an overlay.
- scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator_;
+ // Whether this image is texture_owner or overlay backed.
+ bool is_texture_owner_backed_ = false;
// The bounds last sent to the overlay.
gfx::Rect most_recent_bounds_;
diff --git a/chromium/media/gpu/android/codec_image_unittest.cc b/chromium/media/gpu/android/codec_image_unittest.cc
index 7fcd7eeba13..87496e335c9 100644
--- a/chromium/media/gpu/android/codec_image_unittest.cc
+++ b/chromium/media/gpu/android/codec_image_unittest.cc
@@ -94,7 +94,7 @@ class CodecImageTest : public testing::Test {
scoped_refptr<CodecImage> image = new CodecImage(buffer_renderer->size());
image->Initialize(
- std::move(buffer_renderer), codec_buffer_wait_coordinator,
+ std::move(buffer_renderer), kind == kTextureOwner,
base::BindRepeating(&PromotionHintReceiver::OnPromotionHint,
base::Unretained(&promotion_hint_receiver_)));
@@ -144,7 +144,7 @@ TEST_F(CodecImageTest, UnusedCBRunsOnNotifyUnused) {
base::MockCallback<CodecImage::UnusedCB> cb_2;
auto i = NewImage(kTextureOwner);
ASSERT_TRUE(i->get_codec_output_buffer_for_testing());
- ASSERT_TRUE(i->is_texture_owner_backed());
+ ASSERT_TRUE(i->HasTextureOwner());
i->AddUnusedCB(cb_1.Get());
i->AddUnusedCB(cb_2.Get());
EXPECT_CALL(cb_1, Run(i.get()));
@@ -153,7 +153,7 @@ TEST_F(CodecImageTest, UnusedCBRunsOnNotifyUnused) {
// Also verify that the output buffer and texture owner are released.
i->NotifyUnused();
EXPECT_FALSE(i->get_codec_output_buffer_for_testing());
- EXPECT_FALSE(i->is_texture_owner_backed());
+ EXPECT_FALSE(i->HasTextureOwner());
// Verify that an additional call doesn't crash. It should do nothing.
i->NotifyUnused();
@@ -391,7 +391,7 @@ TEST_F(CodecImageTest, CodedSizeVsVisibleSize) {
std::make_unique<CodecOutputBufferRenderer>(std::move(buffer), nullptr);
scoped_refptr<CodecImage> image = new CodecImage(coded_size);
- image->Initialize(std::move(buffer_renderer), nullptr,
+ image->Initialize(std::move(buffer_renderer), false,
PromotionHintAggregator::NotifyPromotionHintCB());
// Verify that CodecImage::GetSize returns coded_size and not visible_size
diff --git a/chromium/media/gpu/android/frame_info_helper.cc b/chromium/media/gpu/android/frame_info_helper.cc
index efe1873cb1c..b3cf5299aa7 100644
--- a/chromium/media/gpu/android/frame_info_helper.cc
+++ b/chromium/media/gpu/android/frame_info_helper.cc
@@ -4,10 +4,13 @@
#include "media/gpu/android/frame_info_helper.h"
+#include "base/threading/sequence_bound.h"
#include "gpu/command_buffer/service/shared_image_video.h"
#include "gpu/ipc/service/command_buffer_stub.h"
#include "gpu/ipc/service/gpu_channel.h"
#include "gpu/ipc/service/gpu_channel_manager.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/gpu/android/codec_output_buffer_renderer.h"
namespace media {
@@ -21,100 +24,188 @@ FrameInfoHelper::FrameInfo& FrameInfoHelper::FrameInfo::operator=(
// Concrete implementation of FrameInfoHelper that renders output buffers and
// gets the FrameInfo they need.
-class FrameInfoHelperImpl : public FrameInfoHelper,
- public gpu::CommandBufferStub::DestructionObserver {
+class FrameInfoHelperImpl : public FrameInfoHelper {
public:
- FrameInfoHelperImpl(SharedImageVideoProvider::GetStubCB get_stub_cb) {
- stub_ = get_stub_cb.Run();
- if (stub_)
- stub_->AddDestructionObserver(this);
+ FrameInfoHelperImpl(scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
+ SharedImageVideoProvider::GetStubCB get_stub_cb) {
+ on_gpu_ = base::SequenceBound<OnGpu>(std::move(gpu_task_runner),
+ std::move(get_stub_cb));
}
- ~FrameInfoHelperImpl() override {
- if (stub_)
- stub_->RemoveDestructionObserver(this);
+ ~FrameInfoHelperImpl() override = default;
+
+ void GetFrameInfo(std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
+ FrameInfoReadyCB callback) override {
+ Request request = {.buffer_renderer = std::move(buffer_renderer),
+ .callback = std::move(callback)};
+ requests_.push(std::move(request));
+ // If there were no pending requests start processing queue now.
+ if (requests_.size() == 1)
+ ProcessRequestsQueue();
}
- void GetFrameInfo(
- std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
- base::OnceCallback<
- void(std::unique_ptr<CodecOutputBufferRenderer>, FrameInfo, bool)> cb)
- override {
- if (!buffer_renderer) {
- std::move(cb).Run(nullptr, FrameInfo(), false);
- return;
+ private:
+ struct Request {
+ std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer;
+ FrameInfoReadyCB callback;
+ };
+
+ class OnGpu : public gpu::CommandBufferStub::DestructionObserver {
+ public:
+ OnGpu(SharedImageVideoProvider::GetStubCB get_stub_cb) {
+ stub_ = get_stub_cb.Run();
+ if (stub_)
+ stub_->AddDestructionObserver(this);
}
- auto texture_owner = buffer_renderer->texture_owner();
+ ~OnGpu() override {
+ if (stub_)
+ stub_->RemoveDestructionObserver(this);
+ }
- FrameInfo info;
+ void OnWillDestroyStub(bool have_context) override {
+ DCHECK(stub_);
+ stub_ = nullptr;
+ }
- // Indicates that the FrameInfo is reliable and can be cached by caller.
- // It's true if we either return cached values or we attempted to render
- // frame and succeeded.
- bool success = true;
-
- // We default to visible size if if we can't get real size
- info.coded_size = buffer_renderer->size();
- info.visible_rect = gfx::Rect(info.coded_size);
-
- if (texture_owner) {
- if (visible_size_ == buffer_renderer->size()) {
- info = frame_info_;
- } else if (buffer_renderer->RenderToTextureOwnerFrontBuffer(
- CodecOutputBufferRenderer::BindingsMode::
- kDontRestoreIfBound)) {
- visible_size_ = buffer_renderer->size();
- texture_owner->GetCodedSizeAndVisibleRect(
- visible_size_, &frame_info_.coded_size, &frame_info_.visible_rect);
-
- frame_info_.ycbcr_info = GetYCbCrInfo(texture_owner.get());
- info = frame_info_;
- } else {
- // We attempted to render frame and failed, mark request as failed so
- // caller won't cache best-guess values.
- success = false;
+ void GetFrameInfo(
+ std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
+ base::OnceCallback<void(std::unique_ptr<CodecOutputBufferRenderer>,
+ base::Optional<FrameInfo>)> cb) {
+ DCHECK(buffer_renderer);
+
+ auto texture_owner = buffer_renderer->texture_owner();
+ DCHECK(texture_owner);
+
+ base::Optional<FrameInfo> info;
+
+ if (buffer_renderer->RenderToTextureOwnerFrontBuffer(
+ CodecOutputBufferRenderer::BindingsMode::kDontRestoreIfBound)) {
+ gfx::Size coded_size;
+ gfx::Rect visible_rect;
+ if (texture_owner->GetCodedSizeAndVisibleRect(
+ buffer_renderer->size(), &coded_size, &visible_rect)) {
+ info.emplace();
+ info->coded_size = coded_size;
+ info->visible_rect = visible_rect;
+ info->ycbcr_info = GetYCbCrInfo(texture_owner.get());
+ }
}
+
+ std::move(cb).Run(std::move(buffer_renderer), info);
+ }
+
+ private:
+ // Gets YCbCrInfo from last rendered frame.
+ base::Optional<gpu::VulkanYCbCrInfo> GetYCbCrInfo(
+ gpu::TextureOwner* texture_owner) {
+ gpu::ContextResult result;
+
+ if (!stub_)
+ return base::nullopt;
+
+ auto shared_context =
+ stub_->channel()->gpu_channel_manager()->GetSharedContextState(
+ &result);
+ auto context_provider =
+ (result == gpu::ContextResult::kSuccess) ? shared_context : nullptr;
+ if (!context_provider)
+ return base::nullopt;
+
+ return gpu::SharedImageVideo::GetYcbcrInfo(texture_owner,
+ context_provider);
}
- std::move(cb).Run(std::move(buffer_renderer), frame_info_, success);
+ gpu::CommandBufferStub* stub_ = nullptr;
+ };
+
+ FrameInfo GetFrameInfoWithVisibleSize(const gfx::Size& visible_size) {
+ FrameInfo info;
+ info.coded_size = visible_size;
+ info.visible_rect = gfx::Rect(visible_size);
+ return info;
}
- void OnWillDestroyStub(bool have_context) override {
- DCHECK(stub_);
- stub_ = nullptr;
+ void OnFrameInfoReady(
+ std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
+ base::Optional<FrameInfo> frame_info) {
+ DCHECK(buffer_renderer);
+ DCHECK(!requests_.empty());
+
+ auto& request = requests_.front();
+
+ if (frame_info) {
+ visible_size_ = buffer_renderer->size();
+ frame_info_ = *frame_info;
+ std::move(request.callback).Run(std::move(buffer_renderer), frame_info_);
+ } else {
+ // It's possible that we will fail to render frame and so weren't able to
+ // obtain FrameInfo. In this case we don't cache new values and complete
+ // current request with visible size, we will attempt to render next frame
+ // with next request.
+ auto info = GetFrameInfoWithVisibleSize(buffer_renderer->size());
+ std::move(request.callback)
+ .Run(std::move(buffer_renderer), std::move(info));
+ }
+ requests_.pop();
+ ProcessRequestsQueue();
}
- private:
- // Gets YCbCrInfo from last rendered frame.
- base::Optional<gpu::VulkanYCbCrInfo> GetYCbCrInfo(
- gpu::TextureOwner* texture_owner) {
- gpu::ContextResult result;
- if (!stub_)
- return base::nullopt;
-
- auto shared_context =
- stub_->channel()->gpu_channel_manager()->GetSharedContextState(&result);
- auto context_provider =
- (result == gpu::ContextResult::kSuccess) ? shared_context : nullptr;
- if (!context_provider)
- return base::nullopt;
-
- return gpu::SharedImageVideo::GetYcbcrInfo(texture_owner, context_provider);
+ void ProcessRequestsQueue() {
+ while (!requests_.empty()) {
+ auto& request = requests_.front();
+
+ if (!request.buffer_renderer) {
+ // If we don't have buffer_renderer we can Run callback immediately.
+ std::move(request.callback).Run(nullptr, FrameInfo());
+ } else if (!request.buffer_renderer->texture_owner()) {
+ // If there is no texture_owner (SurfaceView case), we can't render
+ // frame and get proper size. But as Display Compositor won't render
+ // this frame the actual size is not important, assume coded_size =
+ // visible_size.
+ auto info =
+ GetFrameInfoWithVisibleSize(request.buffer_renderer->size());
+ std::move(request.callback)
+ .Run(std::move(request.buffer_renderer), std::move(info));
+ } else if (visible_size_ == request.buffer_renderer->size()) {
+ // We have cached the results of last frame info request with the same
+ // size. We assume that coded_size doesn't change if the visible_size
+ // stays the same.
+ std::move(request.callback)
+ .Run(std::move(request.buffer_renderer), frame_info_);
+ } else {
+ // We have texture_owner and we don't have cached value, so we need to
+ // hop to GPU thread and render the frame to get proper size.
+ auto cb = BindToCurrentLoop(
+ base::BindOnce(&FrameInfoHelperImpl::OnFrameInfoReady,
+ weak_factory_.GetWeakPtr()));
+
+ on_gpu_.Post(FROM_HERE, &OnGpu::GetFrameInfo,
+ std::move(request.buffer_renderer), std::move(cb));
+ // We didn't complete this request quite yet, so we can't process queue
+ // any further.
+ break;
+ }
+ requests_.pop();
+ }
}
- gpu::CommandBufferStub* stub_ = nullptr;
+ base::SequenceBound<OnGpu> on_gpu_;
+ std::queue<Request> requests_;
+ // Cached values.
FrameInfo frame_info_;
gfx::Size visible_size_;
+
+ base::WeakPtrFactory<FrameInfoHelperImpl> weak_factory_{this};
};
// static
-base::SequenceBound<FrameInfoHelper> FrameInfoHelper::Create(
+std::unique_ptr<FrameInfoHelper> FrameInfoHelper::Create(
scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
SharedImageVideoProvider::GetStubCB get_stub_cb) {
- return base::SequenceBound<FrameInfoHelperImpl>(std::move(gpu_task_runner),
- std::move(get_stub_cb));
+ return std::make_unique<FrameInfoHelperImpl>(std::move(gpu_task_runner),
+ std::move(get_stub_cb));
}
-} // namespace media
+} // namespace media \ No newline at end of file
diff --git a/chromium/media/gpu/android/frame_info_helper.h b/chromium/media/gpu/android/frame_info_helper.h
index 5fc4ffca328..1f60bceb094 100644
--- a/chromium/media/gpu/android/frame_info_helper.h
+++ b/chromium/media/gpu/android/frame_info_helper.h
@@ -6,12 +6,11 @@
#define MEDIA_GPU_ANDROID_FRAME_INFO_HELPER_H_
#include "base/optional.h"
-#include "base/threading/sequence_bound.h"
-#include "media/gpu/android/codec_image.h"
#include "media/gpu/android/shared_image_video_provider.h"
#include "media/gpu/media_gpu_export.h"
namespace media {
+class CodecOutputBufferRenderer;
// Helper class to fetch YCbCrInfo for Vulkan from a CodecImage.
class MEDIA_GPU_EXPORT FrameInfoHelper {
@@ -29,7 +28,11 @@ class MEDIA_GPU_EXPORT FrameInfoHelper {
base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info;
};
- static base::SequenceBound<FrameInfoHelper> Create(
+ using FrameInfoReadyCB =
+ base::OnceCallback<void(std::unique_ptr<CodecOutputBufferRenderer>,
+ FrameInfo)>;
+
+ static std::unique_ptr<FrameInfoHelper> Create(
scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
SharedImageVideoProvider::GetStubCB get_stub_cb);
@@ -40,9 +43,11 @@ class MEDIA_GPU_EXPORT FrameInfoHelper {
// attempt to get YCbCrInfo and cache it. If all necessary info is cached the
// call will leave buffer_renderer intact and it can be rendered later.
// Rendering can fail for reasons. This function will make best efforts to
- // fill FrameInfo which can be used to create VideoFrame, but shouldn't be
- // cached by caller. Last parameter in |cb| is bool that indicates that info
- // is reliable.
+ // fill FrameInfo which can be used to create VideoFrame.
+ //
+ // Callbacks will be executed and on callers sequence and guaranteed to be
+ // called in order of GetFrameInfo calls. Callback can be called before this
+ // function returns if all necessary info is available right away.
//
// While this API might seem to be out of its Vulkan mind, it's this
// complicated to (a) prevent rendering frames out of order to the front
@@ -50,9 +55,7 @@ class MEDIA_GPU_EXPORT FrameInfoHelper {
// can't get a YCbCrInfo from a CodecImage due to timeouts.
virtual void GetFrameInfo(
std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
- base::OnceCallback<void(std::unique_ptr<CodecOutputBufferRenderer>,
- FrameInfo,
- bool)> cb) = 0;
+ FrameInfoReadyCB callback) = 0;
protected:
FrameInfoHelper() = default;
diff --git a/chromium/media/gpu/android/media_codec_video_decoder.cc b/chromium/media/gpu/android/media_codec_video_decoder.cc
index 6e127512fc2..848983075f6 100644
--- a/chromium/media/gpu/android/media_codec_video_decoder.cc
+++ b/chromium/media/gpu/android/media_codec_video_decoder.cc
@@ -19,6 +19,7 @@
#include "base/trace_event/trace_event.h"
#include "media/base/android/media_codec_bridge_impl.h"
#include "media/base/android/media_codec_util.h"
+#include "media/base/async_destroy_video_decoder.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/cdm_context.h"
#include "media/base/decoder_buffer.h"
@@ -227,7 +228,9 @@ MediaCodecVideoDecoder::MediaCodecVideoDecoder(
overlay_factory_cb_(std::move(overlay_factory_cb)),
device_info_(device_info),
enable_threaded_texture_mailboxes_(
- gpu_preferences.enable_threaded_texture_mailboxes) {
+ gpu_preferences.enable_threaded_texture_mailboxes),
+ allow_nonsecure_overlays_(
+ base::FeatureList::IsEnabled(media::kAllowNonSecureOverlays)) {
DVLOG(2) << __func__;
surface_chooser_helper_.chooser()->SetClientCallbacks(
base::Bind(&MediaCodecVideoDecoder::OnSurfaceChosen,
@@ -236,44 +239,69 @@ MediaCodecVideoDecoder::MediaCodecVideoDecoder(
weak_factory_.GetWeakPtr(), nullptr));
}
+std::unique_ptr<VideoDecoder> MediaCodecVideoDecoder::Create(
+ const gpu::GpuPreferences& gpu_preferences,
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ std::unique_ptr<MediaLog> media_log,
+ DeviceInfo* device_info,
+ CodecAllocator* codec_allocator,
+ std::unique_ptr<AndroidVideoSurfaceChooser> surface_chooser,
+ AndroidOverlayMojoFactoryCB overlay_factory_cb,
+ RequestOverlayInfoCB request_overlay_info_cb,
+ std::unique_ptr<VideoFrameFactory> video_frame_factory) {
+ auto* decoder = new MediaCodecVideoDecoder(
+ gpu_preferences, gpu_feature_info, std::move(media_log), device_info,
+ codec_allocator, std::move(surface_chooser),
+ std::move(overlay_factory_cb), std::move(request_overlay_info_cb),
+ std::move(video_frame_factory));
+ return std::make_unique<AsyncDestroyVideoDecoder<MediaCodecVideoDecoder>>(
+ base::WrapUnique(decoder));
+}
+
MediaCodecVideoDecoder::~MediaCodecVideoDecoder() {
DVLOG(2) << __func__;
TRACE_EVENT0("media", "MediaCodecVideoDecoder::~MediaCodecVideoDecoder");
ReleaseCodec();
}
-void MediaCodecVideoDecoder::Destroy() {
+void MediaCodecVideoDecoder::DestroyAsync(
+ std::unique_ptr<MediaCodecVideoDecoder> decoder) {
DVLOG(1) << __func__;
TRACE_EVENT0("media", "MediaCodecVideoDecoder::Destroy");
+ DCHECK(decoder);
+
+ // This will be destroyed by a call to |DeleteSoon|
+ // in |OnCodecDrained|.
+ auto* self = decoder.release();
// Cancel pending callbacks.
//
// WARNING: This will lose the callback we've given to MediaCodecBridge for
// asynchronous notifications; so we must not leave this function with any
// work necessary from StartTimerOrPumpCodec().
- weak_factory_.InvalidateWeakPtrs();
+ self->weak_factory_.InvalidateWeakPtrs();
- if (media_crypto_context_) {
+ if (self->media_crypto_context_) {
// Cancel previously registered callback (if any).
- media_crypto_context_->SetMediaCryptoReadyCB(base::NullCallback());
- if (cdm_registration_id_)
- media_crypto_context_->UnregisterPlayer(cdm_registration_id_);
- media_crypto_context_ = nullptr;
- cdm_registration_id_ = 0;
+ self->media_crypto_context_->SetMediaCryptoReadyCB(base::NullCallback());
+ if (self->cdm_registration_id_)
+ self->media_crypto_context_->UnregisterPlayer(self->cdm_registration_id_);
+ self->media_crypto_context_ = nullptr;
+ self->cdm_registration_id_ = 0;
}
// Mojo callbacks require that they're run before destruction.
- if (reset_cb_)
- std::move(reset_cb_).Run();
+ if (self->reset_cb_)
+ std::move(self->reset_cb_).Run();
// Cancel callbacks we no longer want.
- codec_allocator_weak_factory_.InvalidateWeakPtrs();
- CancelPendingDecodes(DecodeStatus::ABORTED);
- StartDrainingCodec(DrainType::kForDestroy);
+ self->codec_allocator_weak_factory_.InvalidateWeakPtrs();
+ self->CancelPendingDecodes(DecodeStatus::ABORTED);
+ self->StartDrainingCodec(DrainType::kForDestroy);
// Per the WARNING above. Validate that no draining work remains.
- if (using_async_api_)
- DCHECK(!drain_type_.has_value());
+ if (self->using_async_api_)
+ DCHECK(!self->drain_type_.has_value());
}
void MediaCodecVideoDecoder::Initialize(const VideoDecoderConfig& config,
@@ -471,6 +499,12 @@ void MediaCodecVideoDecoder::StartLazyInit() {
overlay_mode = VideoFrameFactory::OverlayMode::kRequestPromotionHints;
}
+ // Regardless of whether we're using SurfaceControl or Dialog overlays, don't
+ // allow any overlays in A/B power testing mode, unless this requires a
+ // secure surface. Don't fail the playback for power testing.
+ if (!requires_secure_codec_ && !allow_nonsecure_overlays_)
+ overlay_mode = VideoFrameFactory::OverlayMode::kDontRequestPromotionHints;
+
video_frame_factory_->Initialize(
overlay_mode,
base::Bind(&MediaCodecVideoDecoder::OnVideoFrameFactoryInitialized,
@@ -488,10 +522,16 @@ void MediaCodecVideoDecoder::OnVideoFrameFactoryInitialized(
}
texture_owner_bundle_ = new CodecSurfaceBundle(std::move(texture_owner));
+ // This is for A/B power testing only. Turn off Dialog-based overlays in
+ // power testing mode, unless we need them for L1 content.
+ // See https://crbug.com/1081346 .
+ const bool allowed_for_experiment =
+ requires_secure_codec_ || allow_nonsecure_overlays_;
+
// Overlays are disabled when |enable_threaded_texture_mailboxes| is true
// (http://crbug.com/582170).
if (enable_threaded_texture_mailboxes_ ||
- !device_info_->SupportsOverlaySurfaces()) {
+ !device_info_->SupportsOverlaySurfaces() || !allowed_for_experiment) {
OnSurfaceChosen(nullptr);
return;
}
@@ -975,7 +1015,7 @@ void MediaCodecVideoDecoder::ForwardVideoFrame(
if (reset_generation == reset_generation_) {
// TODO(liberato): We might actually have a SW decoder. Consider setting
// this to false if so, especially for higher bitrates.
- frame->metadata()->SetBoolean(VideoFrameMetadata::POWER_EFFICIENT, true);
+ frame->metadata()->power_efficient = true;
output_cb_.Run(std::move(frame));
}
}
diff --git a/chromium/media/gpu/android/media_codec_video_decoder.h b/chromium/media/gpu/android/media_codec_video_decoder.h
index 59055e4d359..7e87139ae32 100644
--- a/chromium/media/gpu/android/media_codec_video_decoder.h
+++ b/chromium/media/gpu/android/media_codec_video_decoder.h
@@ -58,11 +58,14 @@ struct PendingDecode {
// playbacks that need them.
// TODO: Lazy initialization should be handled at a higher layer of the media
// stack for both simplicity and cross platform support.
-class MEDIA_GPU_EXPORT MediaCodecVideoDecoder : public VideoDecoder {
+class MEDIA_GPU_EXPORT MediaCodecVideoDecoder final : public VideoDecoder {
public:
static std::vector<SupportedVideoDecoderConfig> GetSupportedConfigs();
- MediaCodecVideoDecoder(
+ ~MediaCodecVideoDecoder() override;
+ static void DestroyAsync(std::unique_ptr<MediaCodecVideoDecoder>);
+
+ static std::unique_ptr<VideoDecoder> Create(
const gpu::GpuPreferences& gpu_preferences,
const gpu::GpuFeatureInfo& gpu_feature_info,
std::unique_ptr<MediaLog> media_log,
@@ -87,9 +90,20 @@ class MEDIA_GPU_EXPORT MediaCodecVideoDecoder : public VideoDecoder {
bool CanReadWithoutStalling() const override;
int GetMaxDecodeRequests() const override;
- protected:
- // Protected for testing.
- ~MediaCodecVideoDecoder() override;
+ private:
+ // The test has access for PumpCodec() and the constructor.
+ friend class MediaCodecVideoDecoderTest;
+
+ MediaCodecVideoDecoder(
+ const gpu::GpuPreferences& gpu_preferences,
+ const gpu::GpuFeatureInfo& gpu_feature_info,
+ std::unique_ptr<MediaLog> media_log,
+ DeviceInfo* device_info,
+ CodecAllocator* codec_allocator,
+ std::unique_ptr<AndroidVideoSurfaceChooser> surface_chooser,
+ AndroidOverlayMojoFactoryCB overlay_factory_cb,
+ RequestOverlayInfoCB request_overlay_info_cb,
+ std::unique_ptr<VideoFrameFactory> video_frame_factory);
// Set up |cdm_context| as part of initialization. Guarantees that |init_cb|
// will be called depending on the outcome, though not necessarily before this
@@ -102,11 +116,6 @@ class MEDIA_GPU_EXPORT MediaCodecVideoDecoder : public VideoDecoder {
JavaObjectPtr media_crypto,
bool requires_secure_video_codec);
- private:
- // The test has access for PumpCodec().
- friend class MediaCodecVideoDecoderTest;
- friend class base::DeleteHelper<MediaCodecVideoDecoder>;
-
enum class State {
// Initializing resources required to create a codec.
kInitializing,
@@ -124,9 +133,6 @@ class MEDIA_GPU_EXPORT MediaCodecVideoDecoder : public VideoDecoder {
enum class DrainType { kForReset, kForDestroy };
- // Starts teardown.
- void Destroy() override;
-
// Finishes initialization.
void StartLazyInit();
void OnVideoFrameFactoryInitialized(
@@ -327,6 +333,11 @@ class MEDIA_GPU_EXPORT MediaCodecVideoDecoder : public VideoDecoder {
// Optional crypto object from the Cdm.
base::android::ScopedJavaGlobalRef<jobject> media_crypto_;
+ // For A/B power testing, this causes all non-L1 content to avoid overlays.
+ // This is only for A/B power testing, and can be removed after that.
+ // See https://crbug.com/1081346 .
+ bool allow_nonsecure_overlays_ = true;
+
base::WeakPtrFactory<MediaCodecVideoDecoder> weak_factory_{this};
base::WeakPtrFactory<MediaCodecVideoDecoder> codec_allocator_weak_factory_{
this};
diff --git a/chromium/media/gpu/android/media_codec_video_decoder_unittest.cc b/chromium/media/gpu/android/media_codec_video_decoder_unittest.cc
index 61d4c13f3ed..16f3a5f4871 100644
--- a/chromium/media/gpu/android/media_codec_video_decoder_unittest.cc
+++ b/chromium/media/gpu/android/media_codec_video_decoder_unittest.cc
@@ -17,6 +17,7 @@
#include "media/base/android/media_codec_util.h"
#include "media/base/android/mock_android_overlay.h"
#include "media/base/android/mock_media_crypto_context.h"
+#include "media/base/async_destroy_video_decoder.h"
#include "media/base/decoder_buffer.h"
#include "media/base/media_util.h"
#include "media/base/test_helpers.h"
@@ -52,12 +53,6 @@ std::unique_ptr<AndroidOverlay> CreateAndroidOverlayCb(
return nullptr;
}
-// Make MCVD's destruction observable for teardown tests.
-struct DestructionObservableMCVD : public DestructionObservable,
- public MediaCodecVideoDecoder {
- using MediaCodecVideoDecoder::MediaCodecVideoDecoder;
-};
-
} // namespace
class MockVideoFrameFactory : public VideoFrameFactory {
@@ -149,18 +144,16 @@ class MediaCodecVideoDecoderTest : public testing::TestWithParam<VideoCodec> {
ON_CALL(*video_frame_factory_, Initialize(ExpectedOverlayMode(), _))
.WillByDefault(RunCallback<1>(texture_owner));
- auto* observable_mcvd = new DestructionObservableMCVD(
+ auto* mcvd = new MediaCodecVideoDecoder(
gpu_preferences_, gpu_feature_info_, std::make_unique<NullMediaLog>(),
device_info_.get(), codec_allocator_.get(), std::move(surface_chooser),
base::BindRepeating(&CreateAndroidOverlayCb),
base::BindRepeating(&MediaCodecVideoDecoderTest::RequestOverlayInfoCb,
base::Unretained(this)),
std::move(video_frame_factory));
- mcvd_.reset(observable_mcvd);
- mcvd_raw_ = observable_mcvd;
- destruction_observer_ = observable_mcvd->CreateDestructionObserver();
- // Ensure MCVD doesn't leak by default.
- destruction_observer_->ExpectDestruction();
+ mcvd_ = std::make_unique<AsyncDestroyVideoDecoder<MediaCodecVideoDecoder>>(
+ base::WrapUnique(mcvd));
+ mcvd_raw_ = mcvd;
}
VideoFrameFactory::OverlayMode ExpectedOverlayMode() const {
@@ -291,7 +284,6 @@ class MediaCodecVideoDecoderTest : public testing::TestWithParam<VideoCodec> {
gpu::MockTextureOwner* texture_owner_;
MockVideoFrameFactory* video_frame_factory_;
NiceMock<base::MockCallback<VideoDecoder::DecodeCB>> decode_cb_;
- std::unique_ptr<DestructionObserver> destruction_observer_;
ProvideOverlayInfoCB provide_overlay_info_cb_;
bool restart_for_transitions_;
gpu::GpuPreferences gpu_preferences_;
@@ -308,7 +300,7 @@ class MediaCodecVideoDecoderTest : public testing::TestWithParam<VideoCodec> {
// |mcvd_raw_| lets us call PumpCodec() even after |mcvd_| is dropped, for
// testing the teardown path.
MediaCodecVideoDecoder* mcvd_raw_;
- std::unique_ptr<MediaCodecVideoDecoder> mcvd_;
+ std::unique_ptr<VideoDecoder> mcvd_;
};
// Tests which only work for a single codec.
@@ -687,9 +679,6 @@ TEST_P(MediaCodecVideoDecoderVp8Test, UnregisterPlayerBeforeAsyncDestruction) {
// before the decoder is actually destructed, asynchronously.
EXPECT_CALL(*cdm_, UnregisterPlayer(MockMediaCryptoContext::kRegistrationId));
mcvd_.reset();
-
- // Make sure the decoder has not been destroyed yet.
- destruction_observer_->DoNotAllowDestruction();
}
// A reference test for UnregisterPlayerBeforeAsyncDestruction.
@@ -704,9 +693,6 @@ TEST_P(MediaCodecVideoDecoderVp8Test, UnregisterPlayerBeforeSyncDestruction) {
// When |mcvd_| is reset, expect that it will unregister itself immediately.
EXPECT_CALL(*cdm_, UnregisterPlayer(MockMediaCryptoContext::kRegistrationId));
mcvd_.reset();
-
- // Make sure the decoder is now destroyed.
- destruction_observer_->ExpectDestruction();
}
TEST_P(MediaCodecVideoDecoderVp8Test, ResetDoesNotDrainVp8WithAsyncApi) {
@@ -818,18 +804,9 @@ TEST_P(MediaCodecVideoDecoderTest, EosDecodeCbIsRunAfterEosIsDequeued) {
std::move(video_frame_factory_->last_closure_).Run();
}
-TEST_P(MediaCodecVideoDecoderTest, TeardownBeforeInitWorks) {
- // Since we assert that MCVD is destructed by default, this test verifies that
- // MCVD is destructed safely before Initialize().
-}
-
TEST_P(MediaCodecVideoDecoderTest, TeardownInvalidatesCodecCreationWeakPtr) {
InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
- destruction_observer_->DoNotAllowDestruction();
mcvd_.reset();
- // DeleteSoon() is now pending. Ensure it's safe if the codec creation
- // completes before it runs.
- destruction_observer_->ExpectDestruction();
EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(NotNull()));
ASSERT_TRUE(codec_allocator_->ProvideMockCodecAsync());
}
@@ -837,11 +814,7 @@ TEST_P(MediaCodecVideoDecoderTest, TeardownInvalidatesCodecCreationWeakPtr) {
TEST_P(MediaCodecVideoDecoderTest,
TeardownInvalidatesCodecCreationWeakPtrButDoesNotCallReleaseMediaCodec) {
InitializeWithTextureOwner_OneDecodePending(TestVideoConfig::Large(codec_));
- destruction_observer_->DoNotAllowDestruction();
mcvd_.reset();
- // DeleteSoon() is now pending. Ensure it's safe if the codec creation
- // completes before it runs.
- destruction_observer_->ExpectDestruction();
// A null codec should not be released via ReleaseMediaCodec().
EXPECT_CALL(*codec_allocator_, MockReleaseMediaCodec(_)).Times(0);
@@ -880,7 +853,6 @@ TEST_P(MediaCodecVideoDecoderVp8Test,
PumpCodec();
// MCVD should not be destructed immediately.
- destruction_observer_->DoNotAllowDestruction();
mcvd_.reset();
base::RunLoop().RunUntilIdle();
@@ -888,7 +860,6 @@ TEST_P(MediaCodecVideoDecoderVp8Test,
codec->AcceptOneInput(MockMediaCodecBridge::kEos);
codec->ProduceOneOutput(MockMediaCodecBridge::kEos);
EXPECT_CALL(*codec, Flush()).Times(0);
- destruction_observer_->ExpectDestruction();
PumpCodec();
base::RunLoop().RunUntilIdle();
}
@@ -1000,10 +971,7 @@ TEST_P(MediaCodecVideoDecoderTest, VideoFramesArePowerEfficient) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(!!most_recent_frame_);
- bool power_efficient = false;
- EXPECT_TRUE(most_recent_frame_->metadata()->GetBoolean(
- VideoFrameMetadata::POWER_EFFICIENT, &power_efficient));
- EXPECT_TRUE(power_efficient);
+ EXPECT_TRUE(most_recent_frame_->metadata()->power_efficient);
}
TEST_P(MediaCodecVideoDecoderH264Test, CsdIsIncludedInCodecConfig) {
diff --git a/chromium/media/gpu/android/video_frame_factory_impl.cc b/chromium/media/gpu/android/video_frame_factory_impl.cc
index b7c768bae0c..1132f5995de 100644
--- a/chromium/media/gpu/android/video_frame_factory_impl.cc
+++ b/chromium/media/gpu/android/video_frame_factory_impl.cc
@@ -81,7 +81,7 @@ VideoFrameFactoryImpl::VideoFrameFactoryImpl(
const gpu::GpuPreferences& gpu_preferences,
std::unique_ptr<SharedImageVideoProvider> image_provider,
std::unique_ptr<MaybeRenderEarlyManager> mre_manager,
- base::SequenceBound<FrameInfoHelper> frame_info_helper)
+ std::unique_ptr<FrameInfoHelper> frame_info_helper)
: image_provider_(std::move(image_provider)),
gpu_task_runner_(std::move(gpu_task_runner)),
enable_threaded_texture_mailboxes_(
@@ -171,7 +171,7 @@ void VideoFrameFactoryImpl::CreateVideoFrame(
auto image_ready_cb =
base::BindOnce(&VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady,
weak_factory_.GetWeakPtr(), std::move(output_cb),
- timestamp, natural_size, codec_buffer_wait_coordinator_,
+ timestamp, natural_size, !!codec_buffer_wait_coordinator_,
std::move(promotion_hint_cb), pixel_format, overlay_mode_,
enable_threaded_texture_mailboxes_, gpu_task_runner_);
@@ -181,48 +181,20 @@ void VideoFrameFactoryImpl::CreateVideoFrame(
void VideoFrameFactoryImpl::RequestImage(
std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
ImageWithInfoReadyCB image_ready_cb) {
- if (buffer_renderer && visible_size_ == buffer_renderer->size()) {
- auto cb = base::BindOnce(std::move(image_ready_cb),
- std::move(buffer_renderer), frame_info_);
-
- image_provider_->RequestImage(
- std::move(cb), image_spec_,
- codec_buffer_wait_coordinator_
- ? codec_buffer_wait_coordinator_->texture_owner()
- : nullptr);
- return;
- }
-
- // We need to reset size to make sure VFFI pipeline is still ordered.
- // e.g: CreateVideoFrame is called with new size. We post task to GPU thread
- // to get new frame info. While we wait CreateVideoFrame might be called with
- // old size again and if we don't reset size here we will skip GPU hop and new
- // frame will be created earlier than first one.
- visible_size_ = gfx::Size();
-
- auto info_cb = BindToCurrentLoop(
+ auto info_cb =
base::BindOnce(&VideoFrameFactoryImpl::CreateVideoFrame_OnFrameInfoReady,
weak_factory_.GetWeakPtr(), std::move(image_ready_cb),
- codec_buffer_wait_coordinator_));
+ codec_buffer_wait_coordinator_);
- frame_info_helper_.Post(FROM_HERE, &FrameInfoHelper::GetFrameInfo,
- std::move(buffer_renderer), std::move(info_cb));
+ frame_info_helper_->GetFrameInfo(std::move(buffer_renderer),
+ std::move(info_cb));
}
void VideoFrameFactoryImpl::CreateVideoFrame_OnFrameInfoReady(
ImageWithInfoReadyCB image_ready_cb,
scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
std::unique_ptr<CodecOutputBufferRenderer> output_buffer_renderer,
- FrameInfoHelper::FrameInfo frame_info,
- bool success) {
- // To get frame info we need to render frame which might fail for variety of
- // reason. FrameInfoHelper will provide best values we can proceed with, but
- // we should not cache it and attempt to get info for next frame.
- if (success) {
- frame_info_ = frame_info;
- visible_size_ = output_buffer_renderer->size();
- }
-
+ FrameInfoHelper::FrameInfo frame_info) {
// If we don't have output buffer here we can't rely on reply from
// FrameInfoHelper as there might be not cached value and we can't render
// nothing. But in this case call comes from RunAfterPendingVideoFrames and we
@@ -246,7 +218,7 @@ void VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady(
OnceOutputCB output_cb,
base::TimeDelta timestamp,
gfx::Size natural_size,
- scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
+ bool is_texture_owner_backed,
PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb,
VideoPixelFormat pixel_format,
OverlayMode overlay_mode,
@@ -268,7 +240,7 @@ void VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady(
// When we remove the output buffer management from CodecImage, then that's
// what we'd have a reference to here rather than CodecImage.
record.codec_image_holder->codec_image_raw()->Initialize(
- std::move(output_buffer_renderer), codec_buffer_wait_coordinator,
+ std::move(output_buffer_renderer), is_texture_owner_backed,
std::move(promotion_hint_cb));
// Send the CodecImage (via holder, since we can't touch the refcount here) to
@@ -301,7 +273,7 @@ void VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady(
// The frames must be copied when threaded texture mailboxes are in use
// (http://crbug.com/582170).
if (enable_threaded_texture_mailboxes)
- frame->metadata()->SetBoolean(VideoFrameMetadata::COPY_REQUIRED, true);
+ frame->metadata()->copy_required = true;
const bool is_surface_control =
overlay_mode == OverlayMode::kSurfaceControlSecure ||
@@ -309,25 +281,20 @@ void VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady(
const bool wants_promotion_hints =
overlay_mode == OverlayMode::kRequestPromotionHints;
- // Remember that we can't access |codec_buffer_wait_coordinator|, but we can
- // check if we have one here.
bool allow_overlay = false;
if (is_surface_control) {
- DCHECK(codec_buffer_wait_coordinator);
+ DCHECK(is_texture_owner_backed);
allow_overlay = true;
} else {
// We unconditionally mark the picture as overlayable, even if
- // |!codec_buffer_wait_coordinator|, if we want to get hints. It's
+ // |!is_texture_owner_backed|, if we want to get hints. It's
// required, else we won't get hints.
- allow_overlay = !codec_buffer_wait_coordinator || wants_promotion_hints;
+ allow_overlay = !is_texture_owner_backed || wants_promotion_hints;
}
- frame->metadata()->SetBoolean(VideoFrameMetadata::ALLOW_OVERLAY,
- allow_overlay);
- frame->metadata()->SetBoolean(VideoFrameMetadata::WANTS_PROMOTION_HINT,
- wants_promotion_hints);
- frame->metadata()->SetBoolean(VideoFrameMetadata::TEXTURE_OWNER,
- !!codec_buffer_wait_coordinator);
+ frame->metadata()->allow_overlay = allow_overlay;
+ frame->metadata()->wants_promotion_hint = wants_promotion_hints;
+ frame->metadata()->texture_owner = is_texture_owner_backed;
// TODO(liberato): if this is run via being dropped, then it would be nice
// to find that out rather than treating the image as unused. If the renderer
diff --git a/chromium/media/gpu/android/video_frame_factory_impl.h b/chromium/media/gpu/android/video_frame_factory_impl.h
index 624d7d2b650..489149eb765 100644
--- a/chromium/media/gpu/android/video_frame_factory_impl.h
+++ b/chromium/media/gpu/android/video_frame_factory_impl.h
@@ -10,7 +10,6 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
-#include "base/threading/sequence_bound.h"
#include "gpu/config/gpu_preferences.h"
#include "media/base/video_frame.h"
#include "media/gpu/android/codec_buffer_wait_coordinator.h"
@@ -52,7 +51,7 @@ class MEDIA_GPU_EXPORT VideoFrameFactoryImpl : public VideoFrameFactory {
const gpu::GpuPreferences& gpu_preferences,
std::unique_ptr<SharedImageVideoProvider> image_provider,
std::unique_ptr<MaybeRenderEarlyManager> mre_manager,
- base::SequenceBound<FrameInfoHelper> frame_info_helper);
+ std::unique_ptr<FrameInfoHelper> frame_info_helper);
~VideoFrameFactoryImpl() override;
void Initialize(OverlayMode overlay_mode, InitCB init_cb) override;
@@ -91,7 +90,7 @@ class MEDIA_GPU_EXPORT VideoFrameFactoryImpl : public VideoFrameFactory {
OnceOutputCB output_cb,
base::TimeDelta timestamp,
gfx::Size natural_size,
- scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
+ bool is_texture_owner_backed,
PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb,
VideoPixelFormat pixel_format,
OverlayMode overlay_mode,
@@ -105,8 +104,7 @@ class MEDIA_GPU_EXPORT VideoFrameFactoryImpl : public VideoFrameFactory {
ImageWithInfoReadyCB image_ready_cb,
scoped_refptr<CodecBufferWaitCoordinator> codec_buffer_wait_coordinator,
std::unique_ptr<CodecOutputBufferRenderer> output_buffer_renderer,
- FrameInfoHelper::FrameInfo frame_info,
- bool success);
+ FrameInfoHelper::FrameInfo frame_info);
MaybeRenderEarlyManager* mre_manager() const { return mre_manager_.get(); }
@@ -128,12 +126,8 @@ class MEDIA_GPU_EXPORT VideoFrameFactoryImpl : public VideoFrameFactory {
std::unique_ptr<MaybeRenderEarlyManager> mre_manager_;
- // Caches FrameInfo and visible size it was cached for.
- gfx::Size visible_size_;
- FrameInfoHelper::FrameInfo frame_info_;
-
- // Optional helper to get the Vulkan YCbCrInfo.
- base::SequenceBound<FrameInfoHelper> frame_info_helper_;
+ // Helper to get coded_size and optional Vulkan YCbCrInfo.
+ std::unique_ptr<FrameInfoHelper> frame_info_helper_;
// The current image spec that we'll use to request images.
SharedImageVideoProvider::ImageSpec image_spec_;
diff --git a/chromium/media/gpu/android/video_frame_factory_impl_unittest.cc b/chromium/media/gpu/android/video_frame_factory_impl_unittest.cc
index ade0a27c05d..13231efe252 100644
--- a/chromium/media/gpu/android/video_frame_factory_impl_unittest.cc
+++ b/chromium/media/gpu/android/video_frame_factory_impl_unittest.cc
@@ -44,46 +44,14 @@ class MockMaybeRenderEarlyManager : public MaybeRenderEarlyManager {
class MockFrameInfoHelper : public FrameInfoHelper,
public DestructionObservable {
public:
- MockFrameInfoHelper(MockFrameInfoHelper** thiz) { *thiz = this; }
-
- void GetFrameInfo(
- std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
- base::OnceCallback<
- void(std::unique_ptr<CodecOutputBufferRenderer>, FrameInfo, bool)> cb)
- override {
- MockGetFrameInfo(buffer_renderer.get());
- cb_ = std::move(cb);
- buffer_renderer_ = std::move(buffer_renderer);
-
- if (run_callback_automatically_) {
- RunWithYcbCrInfo(true);
- base::RunLoop().RunUntilIdle();
- }
- }
-
- void RunWithYcbCrInfo(bool success) {
- DCHECK(buffer_renderer_);
-
+ void GetFrameInfo(std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer,
+ FrameInfoReadyCB cb) override {
FrameInfo info;
- info.coded_size = buffer_renderer_->size();
+ info.coded_size = buffer_renderer->size();
info.visible_rect = gfx::Rect(info.coded_size);
- std::move(cb_).Run(std::move(buffer_renderer_), info, success);
- }
-
- void set_run_callback_automatically(bool run_callback_automatically) {
- run_callback_automatically_ = run_callback_automatically;
+ std::move(cb).Run(std::move(buffer_renderer), info);
}
-
- MOCK_METHOD1(MockGetFrameInfo,
- void(CodecOutputBufferRenderer* buffer_renderer));
-
- private:
- bool run_callback_automatically_ = true;
- base::OnceCallback<
- void(std::unique_ptr<CodecOutputBufferRenderer>, FrameInfo, bool)>
- cb_;
- std::unique_ptr<CodecOutputBufferRenderer> buffer_renderer_;
};
class VideoFrameFactoryImplTest : public testing::Test {
@@ -96,15 +64,11 @@ class VideoFrameFactoryImplTest : public testing::Test {
auto mre_manager = std::make_unique<MockMaybeRenderEarlyManager>();
mre_manager_raw_ = mre_manager.get();
- auto ycbcr_helper = base::SequenceBound<MockFrameInfoHelper>(
- task_runner_, &ycbcr_helper_raw_);
- base::RunLoop().RunUntilIdle(); // Init |ycbcr_helper_raw_|.
- ycbcr_destruction_observer_ =
- ycbcr_helper_raw_->CreateDestructionObserver();
+ auto info_helper = std::make_unique<MockFrameInfoHelper>();
impl_ = std::make_unique<VideoFrameFactoryImpl>(
task_runner_, gpu_preferences_, std::move(image_provider),
- std::move(mre_manager), std::move(ycbcr_helper));
+ std::move(mre_manager), std::move(info_helper));
auto texture_owner = base::MakeRefCounted<NiceMock<gpu::MockTextureOwner>>(
0, nullptr, nullptr, true);
auto codec_buffer_wait_coordinator =
@@ -177,7 +141,6 @@ class VideoFrameFactoryImplTest : public testing::Test {
// Sent to |impl_| by RequestVideoFrame..
base::MockCallback<VideoFrameFactory::OnceOutputCB> output_cb_;
- MockFrameInfoHelper* ycbcr_helper_raw_ = nullptr;
std::unique_ptr<DestructionObserver> ycbcr_destruction_observer_;
gpu::GpuPreferences gpu_preferences_;
@@ -272,75 +235,4 @@ TEST_F(VideoFrameFactoryImplTest,
impl_ = nullptr;
base::RunLoop().RunUntilIdle();
}
-
-TEST_F(VideoFrameFactoryImplTest, DoesCallFrameInfoHelperIfVulkan) {
- // We will be driving callback by ourselves in this test.
- ycbcr_helper_raw_->set_run_callback_automatically(false);
- // Expect call to get info for the first frame.
- EXPECT_CALL(*ycbcr_helper_raw_, MockGetFrameInfo(_)).Times(1);
-
- RequestVideoFrame();
-
- // Provide info. It should send image request.
- ycbcr_helper_raw_->RunWithYcbCrInfo(true);
- base::RunLoop().RunUntilIdle();
-
- testing::Mock::VerifyAndClearExpectations(ycbcr_helper_raw_);
-
- // Fulfilling image request should provide video frame.
- EXPECT_CALL(output_cb_, Run(_)).Times(1);
-
- auto image_record = MakeImageRecord();
- image_provider_raw_->ProvideOneRequestedImage(&image_record);
- base::RunLoop().RunUntilIdle();
-
- // Verify that no more calls happen, since we don't want thread hops on every
- // frame. Note that multiple could be dispatched before now. It should still
- // send along a VideoFrame, though.
- EXPECT_CALL(*ycbcr_helper_raw_, MockGetFrameInfo(_)).Times(0);
- EXPECT_CALL(output_cb_, Run(_)).Times(1);
-
- RequestVideoFrame();
- auto other_image_record = MakeImageRecord();
- // If the helper hasn't been destroyed, then we don't expect it to be called.
- image_provider_raw_->ProvideOneRequestedImage(&other_image_record);
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(VideoFrameFactoryImplTest, NullYCbCrInfoDoesntCrash) {
- // We will be driving callback by ourselves in this test.
- ycbcr_helper_raw_->set_run_callback_automatically(false);
-
- // Expect call to get info for the first frame.
- EXPECT_CALL(*ycbcr_helper_raw_, MockGetFrameInfo(_)).Times(1);
-
- RequestVideoFrame();
-
- // Provide info. It should send image request.
- ycbcr_helper_raw_->RunWithYcbCrInfo(false);
- base::RunLoop().RunUntilIdle();
-
- testing::Mock::VerifyAndClearExpectations(ycbcr_helper_raw_);
-
- // Fulfilling image request should provide video frame.
- EXPECT_CALL(output_cb_, Run(_)).Times(1);
-
- auto image_record = MakeImageRecord();
- image_provider_raw_->ProvideOneRequestedImage(&image_record);
- base::RunLoop().RunUntilIdle();
-
- // Verify that we will get call to GetFrameInfo as previous one failed.
- EXPECT_CALL(*ycbcr_helper_raw_, MockGetFrameInfo(_)).Times(1);
- EXPECT_CALL(output_cb_, Run(_)).Times(1);
-
- RequestVideoFrame();
- ycbcr_helper_raw_->RunWithYcbCrInfo(true);
- base::RunLoop().RunUntilIdle();
-
- auto other_image_record = MakeImageRecord();
- // If the helper hasn't been destroyed, then we don't expect it to be called.
- image_provider_raw_->ProvideOneRequestedImage(&other_image_record);
- base::RunLoop().RunUntilIdle();
-}
-
} // namespace media