#include "media/gpu/android/maybe_render_early_manager.h"
#include <vector>
#include "base/containers/contains.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequence_bound.h"
#include "media/gpu/android/codec_image_group.h"
#include "media/gpu/android/codec_surface_bundle.h"
namespace media {
class GpuMaybeRenderEarlyImpl {
public:
GpuMaybeRenderEarlyImpl() {}
GpuMaybeRenderEarlyImpl(const GpuMaybeRenderEarlyImpl&) = delete;
GpuMaybeRenderEarlyImpl& operator=(const GpuMaybeRenderEarlyImpl&) = delete;
~GpuMaybeRenderEarlyImpl() = default;
void SetCodecImageGroup(scoped_refptr<CodecImageGroup> image_group) {
image_group_ = std::move(image_group);
}
void AddCodecImage(scoped_refptr<CodecImageHolder> codec_image_holder) {
codec_image_holder->codec_image_raw()->AddUnusedCB(base::BindOnce(
&GpuMaybeRenderEarlyImpl::OnImageUnused, weak_factory_.GetWeakPtr()));
DCHECK(!base::Contains(images_, codec_image_holder->codec_image_raw()));
images_.push_back(codec_image_holder->codec_image_raw());
image_group_->AddCodecImage(codec_image_holder->codec_image_raw());
}
void MaybeRenderEarly(scoped_refptr<gpu::RefCountedLock> drdc_lock) {
base::AutoLockMaybe auto_lock(drdc_lock ? drdc_lock->GetDrDcLockPtr()
: nullptr);
internal::MaybeRenderEarly(&images_);
}
private:
void OnImageUnused(CodecImage* image) {
DCHECK(base::Contains(images_, image));
std::erase(images_, image);
internal::MaybeRenderEarly(&images_);
}
std::vector<raw_ptr<CodecImage, VectorExperimental>> images_;
scoped_refptr<CodecImageGroup> image_group_;
base::WeakPtrFactory<GpuMaybeRenderEarlyImpl> weak_factory_{this};
};
class MaybeRenderEarlyManagerImpl : public MaybeRenderEarlyManager,
public gpu::RefCountedLockHelperDrDc {
public:
MaybeRenderEarlyManagerImpl(
scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
scoped_refptr<gpu::RefCountedLock> drdc_lock)
: gpu::RefCountedLockHelperDrDc(std::move(drdc_lock)),
gpu_task_runner_(gpu_task_runner),
gpu_impl_(std::move(gpu_task_runner)) {}
MaybeRenderEarlyManagerImpl(const MaybeRenderEarlyManagerImpl&) = delete;
MaybeRenderEarlyManagerImpl& operator=(const MaybeRenderEarlyManagerImpl&) =
delete;
~MaybeRenderEarlyManagerImpl() override = default;
void SetSurfaceBundle(
scoped_refptr<CodecSurfaceBundle> surface_bundle) override {
auto image_group = base::MakeRefCounted<CodecImageGroup>(
gpu_task_runner_, std::move(surface_bundle), GetDrDcLock());
gpu_impl_.AsyncCall(&GpuMaybeRenderEarlyImpl::SetCodecImageGroup)
.WithArgs(std::move(image_group));
}
void AddCodecImage(
scoped_refptr<CodecImageHolder> codec_image_holder) override {
gpu_impl_.AsyncCall(&GpuMaybeRenderEarlyImpl::AddCodecImage)
.WithArgs(std::move(codec_image_holder));
}
void MaybeRenderEarly() override {
gpu_impl_.AsyncCall(&GpuMaybeRenderEarlyImpl::MaybeRenderEarly)
.WithArgs(GetDrDcLock());
}
private:
scoped_refptr<base::SequencedTaskRunner> gpu_task_runner_;
base::SequenceBound<GpuMaybeRenderEarlyImpl> gpu_impl_;
};
std::unique_ptr<MaybeRenderEarlyManager> MaybeRenderEarlyManager::Create(
scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<gpu::RefCountedLock> lock) {
return std::make_unique<MaybeRenderEarlyManagerImpl>(std::move(task_runner),
std::move(lock));
}
}