#include "media/gpu/android/codec_image.h"
#include <string.h>
#include <memory>
#include "base/android/scoped_hardware_buffer_fence_sync.h"
#include "base/debug/dump_without_crashing.h"
#include "base/functional/callback_helpers.h"
#include "base/task/sequenced_task_runner.h"
namespace media {
CodecImage::CodecImage(const gfx::Size& coded_size,
scoped_refptr<gpu::RefCountedLock> drdc_lock)
: RefCountedLockHelperDrDc(std::move(drdc_lock)), coded_size_(coded_size) {}
CodecImage::~CodecImage() {
DCHECK_CALLED_ON_VALID_THREAD(gpu_main_thread_checker_);
AssertAcquiredDrDcLock();
NotifyUnused();
}
void CodecImage::Initialize(
std::unique_ptr<CodecOutputBufferRenderer> output_buffer_renderer,
bool is_texture_owner_backed,
PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb) {
DCHECK(output_buffer_renderer);
output_buffer_renderer_ = std::move(output_buffer_renderer);
is_texture_owner_backed_ = is_texture_owner_backed;
promotion_hint_cb_ = std::move(promotion_hint_cb);
}
void CodecImage::AddUnusedCB(UnusedCB unused_cb) {
DCHECK_CALLED_ON_VALID_THREAD(gpu_main_thread_checker_);
unused_cbs_.push_back(std::move(unused_cb));
}
void CodecImage::NotifyUnused() {
DCHECK_CALLED_ON_VALID_THREAD(gpu_main_thread_checker_);
AssertAcquiredDrDcLock();
ReleaseCodecBuffer();
promotion_hint_cb_ = base::NullCallback();
for (auto& cb : unused_cbs_)
std::move(cb).Run(this);
unused_cbs_.clear();
}
void CodecImage::NotifyOverlayPromotion(bool promotion,
const gfx::Rect& bounds) {
AssertAcquiredDrDcLock();
if (!promotion_hint_cb_)
return;
if (!is_texture_owner_backed_ && promotion) {
if (most_recent_bounds_ != bounds) {
most_recent_bounds_ = bounds;
promotion_hint_cb_.Run(PromotionHintAggregator::Hint(bounds, promotion));
}
} else {
promotion_hint_cb_.Run(PromotionHintAggregator::Hint(bounds, promotion));
}
}
void CodecImage::ReleaseResources() {
DCHECK_CALLED_ON_VALID_THREAD(gpu_main_thread_checker_);
ReleaseCodecBuffer();
}
bool CodecImage::HasTextureOwner() const {
return !!texture_owner();
}
bool CodecImage::RenderToFrontBuffer() {
DCHECK_CALLED_ON_VALID_THREAD(gpu_main_thread_checker_);
AssertAcquiredDrDcLock();
if (!output_buffer_renderer_)
return false;
return output_buffer_renderer_->RenderToFrontBuffer();
}
bool CodecImage::RenderToTextureOwnerBackBuffer() {
DCHECK_CALLED_ON_VALID_THREAD(gpu_main_thread_checker_);
AssertAcquiredDrDcLock();
if (!output_buffer_renderer_)
return false;
return output_buffer_renderer_->RenderToTextureOwnerBackBuffer();
}
bool CodecImage::RenderToTextureOwnerFrontBuffer() {
AssertAcquiredDrDcLock();
if (!output_buffer_renderer_)
return false;
return output_buffer_renderer_->RenderToTextureOwnerFrontBuffer();
}
bool CodecImage::RenderToOverlay() {
AssertAcquiredDrDcLock();
if (!output_buffer_renderer_)
return false;
return output_buffer_renderer_->RenderToOverlay();
}
void CodecImage::ReleaseCodecBuffer() {
DCHECK_CALLED_ON_VALID_THREAD(gpu_main_thread_checker_);
AssertAcquiredDrDcLock();
output_buffer_renderer_.reset();
}
std::unique_ptr<base::android::ScopedHardwareBufferFenceSync>
CodecImage::GetAHardwareBuffer() {
AssertAcquiredDrDcLock();
if (!output_buffer_renderer_)
return nullptr;
RenderToTextureOwnerFrontBuffer();
return output_buffer_renderer_->texture_owner()->GetAHardwareBuffer();
}
CodecImageHolder::CodecImageHolder(
scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<CodecImage> codec_image,
scoped_refptr<gpu::RefCountedLock> drdc_lock)
: base::RefCountedDeleteOnSequence<CodecImageHolder>(
std::move(task_runner)),
gpu::RefCountedLockHelperDrDc(std::move(drdc_lock)),
codec_image_(std::move(codec_image)) {}
CodecImageHolder::~CodecImageHolder() {
{
auto scoped_lock = GetScopedDrDcLock();
codec_image_.reset();
}
}
}