Commit fc163808 authored by Chih-Yu Huang's avatar Chih-Yu Huang Committed by Commit Bot

Reland "media/gpu: make VideoDecoderPipeline select VD implementation during Initialize()."

This reverts commit a1d47a7f.

Reason for revert: Fix build failure with target_os="chromeos"

Original change's description:
> Revert "media/gpu: make VideoDecoderPipeline select VD implementation during Initialize()."
>
> This reverts commit cae62756.
>
> Reason for revert: Breaks build with target_os="chromeos"
>
> FAILED: libmedia_gpu.so libmedia_gpu.so.TOC
> python "../../build/toolchain/gcc_solink_wrapper.py" --readelf="readelf" --nm="nm" --sofile="./libmedia_gpu.so" --tocfile="./libmedia_gpu.so.TOC" --output="./libmedia_gpu.so" -- ../../third_party/llvm-build/Release+Asserts/bin/clang++ -shared -Wl,-soname="libmedia_gpu.so" -Wl,--fatal-warnings -fPIC -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,defs -Wl,--as-needed -fuse-ld=lld -Wl,--color-diagnostics -m64 -Werror -Wl,--gdb-index -nostdlib++ --sysroot=../../build/linux/debian_sid_amd64-sysroot -L../../build/linux/debian_sid_amd64-sysroot/usr/local/lib/x86_64-linux-gnu -L../../build/linux/debian_sid_amd64-sysroot/lib/x86_64-linux-gnu -L../../build/linux/debian_sid_amd64-sysroot/usr/lib/x86_64-linux-gnu -Wl,-rpath=\$ORIGIN -Wl,-rpath=\$ORIGIN -o "./libmedia_gpu.so" @"./libmedia_gpu.so.rsp"
> ld.lld: error: undefined symbol: media::VideoDecoderPipeline::Create(scoped_refptr<base::SequencedTaskRunner>, std::__Cr::unique_ptr<media::DmabufVideoFramePool, std::__Cr::default_delete<media::DmabufVideoFramePool> >, std::__Cr::unique_ptr<media::VideoFrameConverter, std::__Cr::default_delete<media::VideoFrameConverter> >)
> >>> referenced by chromeos_video_decoder_factory.cc:54 (../../media/gpu/chromeos/chromeos_video_decoder_factory.cc:54)
> >>>               obj/media/gpu/chromeos/chromeos/chromeos_video_decoder_factory.o:(media::ChromeosVideoDecoderFactory::Create(scoped_refptr<base::SequencedTaskRunner>, std::__Cr::unique_ptr<media::DmabufVideoFramePool, std::__Cr::default_delete<media::DmabufVideoFramePool> >, std::__Cr::unique_ptr<media::VideoFrameConverter, std::__Cr::default_delete<media::VideoFrameConverter> >))
> clang: error: linker command failed with exit code 1 (use -v to see invocation)
>
> Original change's description:
> > media/gpu: make VideoDecoderPipeline select VD implementation during Initialize().
> >
> > Some devices select the video decoder implementation by the video
> > configuration (e.g. codec). VideoDecoderPipeline needs to select a
> > proper video decoder in Initialize() when a video configuration is
> > specified.
> >
> > This CL implements the mechanism of selecting VD at Initialize()
> > instead of Create() method.
> >
> > BUG=chromium:952730
> > TEST=Run video_decode_accelerator_tests on Kevin and Eve
> >
> > Change-Id: I76077df0bc1e1eeae730e618a62c6e1049e02500
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1708693
> > Reviewed-by: David Staessens <dstaessens@chromium.org>
> > Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
> > Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
> > Commit-Queue: Chih-Yu Huang <akahuang@chromium.org>
> > Cr-Commit-Position: refs/heads/master@{#691946}
>
> TBR=deanliao@chromium.org,akahuang@chromium.org,hiroh@chromium.org,acourbot@chromium.org,dstaessens@chromium.org
>
> Change-Id: I2edea554734a766fce1d61943297547159c8cbeb
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Bug: chromium:952730
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1778048
> Reviewed-by: Elly Fong-Jones <ellyjones@chromium.org>
> Reviewed-by: Vladislav Kuzkokov <vkuzkokov@chromium.org>
> Commit-Queue: Vladislav Kuzkokov <vkuzkokov@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#692035}

TBR=ellyjones@chromium.org,deanliao@chromium.org,vkuzkokov@chromium.org,akahuang@chromium.org,hiroh@chromium.org,acourbot@chromium.org,dstaessens@chromium.org

Bug: chromium:952730
Test: Run `autoninja media/gpu` with gn gargs: target_os="chromeos"
Change-Id: I34405281dbe106e3182456da154e3ceafd19f9b2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1781126Reviewed-by: default avatarChih-Yu Huang <akahuang@chromium.org>
Reviewed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Commit-Queue: Chih-Yu Huang <akahuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#692405}
parent d8ed38ab
......@@ -22,7 +22,7 @@ source_set("chromeos") {
]
if (use_vaapi || use_v4l2_codec) {
deps += [ "//media/gpu/linux:common" ]
deps += [ "//media/gpu/linux" ]
}
if (use_vaapi) {
......
......@@ -9,8 +9,12 @@
#include "base/sequenced_task_runner.h"
#include "media/base/video_decoder.h"
#include "media/gpu/buildflags.h"
#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
#include "media/gpu/linux/mailbox_video_frame_converter.h"
#include "media/gpu/linux/platform_video_frame_pool.h"
#include "media/gpu/linux/video_decoder_pipeline.h"
#endif // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_video_decoder.h"
......@@ -20,9 +24,6 @@
#include "media/gpu/v4l2/v4l2_slice_video_decoder.h"
#endif
#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
#include "media/gpu/linux/video_decoder_pipeline.h"
#endif
namespace media {
......@@ -52,29 +53,14 @@ std::unique_ptr<VideoDecoder> ChromeosVideoDecoderFactory::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter) {
if (!client_task_runner || !frame_pool || !frame_converter)
return nullptr;
std::unique_ptr<VideoDecoder> decoder;
// TODO(dstaessens@): We first try VAAPI as USE_V4L2_CODEC might also be
// set, even though initialization of V4L2SliceVideoDecoder would fail. We
// need to implement a better way to select the correct decoder.
#if BUILDFLAG(USE_VAAPI)
decoder =
VaapiVideoDecoder::Create(client_task_runner, std::move(frame_pool));
#elif BUILDFLAG(USE_V4L2_CODEC)
decoder =
V4L2SliceVideoDecoder::Create(client_task_runner, std::move(frame_pool));
#endif
#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
return std::make_unique<VideoDecoderPipeline>(std::move(client_task_runner),
std::move(decoder),
std::move(frame_converter));
#else
// TODO(akahuang): Remove ChromeosVideoDecoderFactory.
return VideoDecoderPipeline::Create(std::move(client_task_runner),
std::move(frame_pool),
std::move(frame_converter));
#endif // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
return nullptr;
#endif
}
} // namespace media
......@@ -7,6 +7,36 @@ import("//media/gpu/args.gni")
assert(use_v4l2_codec || use_vaapi)
# The source that depends on //media/gpu/{vaapi,v4l2}. It is created to avoid
# circular dependency because //media/gpu/linux:common could be depended by
# //media/gpu/{vaapi,v4l2}.
source_set("linux") {
defines = [ "MEDIA_GPU_IMPLEMENTATION" ]
sources = [
"video_decoder_pipeline.cc",
"video_decoder_pipeline.h",
]
public_deps = [
":common",
]
deps = [
"//base",
"//media",
"//media/gpu:buildflags",
"//media/gpu:common",
]
if (use_vaapi) {
deps += [ "//media/gpu/vaapi" ]
}
if (use_v4l2_codec) {
deps += [ "//media/gpu/v4l2" ]
}
}
source_set("common") {
defines = [ "MEDIA_GPU_IMPLEMENTATION" ]
sources = [
......@@ -18,8 +48,6 @@ source_set("common") {
"platform_video_frame_pool.h",
"platform_video_frame_utils.cc",
"platform_video_frame_utils.h",
"video_decoder_pipeline.cc",
"video_decoder_pipeline.h",
]
deps = [
......
......@@ -7,71 +7,154 @@
#include "base/bind.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
#include "media/base/video_decoder_config.h"
#include "base/task/task_traits.h"
#include "media/gpu/buildflags.h"
#include "media/gpu/linux/dmabuf_video_frame_pool.h"
#include "media/gpu/macros.h"
#if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_video_decoder.h"
#endif
#if BUILDFLAG(USE_V4L2_CODEC)
#include "media/gpu/v4l2/v4l2_slice_video_decoder.h"
#endif
namespace media {
// static
base::queue<VideoDecoderPipeline::CreateVDFunc>
VideoDecoderPipeline::GetCreateVDFunctions(
VideoDecoderPipeline::CreateVDFunc cur_create_vd_func) {
static constexpr VideoDecoderPipeline::CreateVDFunc kCreateVDFuncs[] = {
#if BUILDFLAG(USE_V4L2_CODEC)
&V4L2SliceVideoDecoder::Create,
#endif // BUILDFLAG(USE_V4L2_CODEC)
#if BUILDFLAG(USE_VAAPI)
&VaapiVideoDecoder::Create,
#endif // BUILDFLAG(USE_VAAPI)
};
base::queue<VideoDecoderPipeline::CreateVDFunc> ret;
for (const auto& func : kCreateVDFuncs) {
if (func != cur_create_vd_func)
ret.push(func);
}
return ret;
}
// static
std::unique_ptr<VideoDecoder> VideoDecoderPipeline::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter) {
if (!client_task_runner || !frame_pool || !frame_converter) {
VLOGF(1) << "One of arguments is nullptr.";
return nullptr;
}
if (GetCreateVDFunctions(nullptr).empty()) {
VLOGF(1) << "No available function to create video decoder.";
return nullptr;
}
return base::WrapUnique<VideoDecoder>(new VideoDecoderPipeline(
std::move(client_task_runner), std::move(frame_pool),
std::move(frame_converter)));
}
VideoDecoderPipeline::VideoDecoderPipeline(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<VideoDecoder> decoder,
std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter)
: client_task_runner_(std::move(client_task_runner)),
decoder_(std::move(decoder)),
frame_converter_(std::move(frame_converter)),
weak_this_factory_(this) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(decoder_);
decoder_task_runner_(base::CreateSingleThreadTaskRunner(
{base::ThreadPool(), base::WithBaseSyncPrimitives(),
base::TaskPriority::USER_VISIBLE},
base::SingleThreadTaskRunnerThreadMode::DEDICATED)),
frame_pool_(std::move(frame_pool)),
frame_converter_(std::move(frame_converter)) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
DCHECK(frame_pool_);
DCHECK(frame_converter_);
DCHECK(client_task_runner_);
DVLOGF(2);
weak_this_ = weak_this_factory_.GetWeakPtr();
frame_pool_->set_parent_task_runner(decoder_task_runner_);
frame_converter_->Initialize(
client_task_runner_,
base::BindRepeating(&VideoDecoderPipeline::OnFrameConverted,
weak_this_factory_.GetWeakPtr()));
base::BindRepeating(&VideoDecoderPipeline::OnFrameConverted, weak_this_));
}
VideoDecoderPipeline::~VideoDecoderPipeline() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// We have to destroy |frame_pool_| on |decoder_task_runner_|, so the
// destructor is also called on |decoder_task_runner_|.
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(3);
}
void VideoDecoderPipeline::Destroy() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(2);
weak_this_factory_.InvalidateWeakPtrs();
decoder_.reset();
used_create_vd_func_ = nullptr;
frame_converter_.reset();
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VideoDecoderPipeline::DestroyTask,
base::Unretained(this)));
}
void VideoDecoderPipeline::DestroyTask() {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(3);
// |frame_pool_| should be destroyed on |decoder_task_runner_|, which is set
// by frame_pool_->set_parent_task_runner().
frame_pool_.reset();
delete this;
}
std::string VideoDecoderPipeline::GetDisplayName() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
return decoder_->GetDisplayName();
return "VideoDecoderPipeline";
}
bool VideoDecoderPipeline::IsPlatformDecoder() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
return decoder_->IsPlatformDecoder();
return true;
}
int VideoDecoderPipeline::GetMaxDecodeRequests() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
return decoder_->GetMaxDecodeRequests();
if (!decoder_)
DVLOGF(1) << "Call before Initialize() success.";
return decoder_ ? decoder_->GetMaxDecodeRequests() : 1;
}
bool VideoDecoderPipeline::NeedsBitstreamConversion() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
return decoder_->NeedsBitstreamConversion();
if (!decoder_)
DVLOGF(1) << "Call before Initialize() success.";
return decoder_ ? decoder_->NeedsBitstreamConversion() : false;
}
bool VideoDecoderPipeline::CanReadWithoutStalling() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
return decoder_->CanReadWithoutStalling();
if (!decoder_)
DVLOGF(1) << "Call before Initialize() success.";
return decoder_ ? decoder_->CanReadWithoutStalling() : false;
}
void VideoDecoderPipeline::Initialize(const VideoDecoderConfig& config,
......@@ -80,30 +163,111 @@ void VideoDecoderPipeline::Initialize(const VideoDecoderConfig& config,
InitCB init_cb,
const OutputCB& output_cb,
const WaitingCB& waiting_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(!init_cb_);
VLOGF(2) << "config: " << config.AsHumanReadableString();
client_output_cb_ = std::move(output_cb);
init_cb_ = std::move(init_cb);
base::queue<VideoDecoderPipeline::CreateVDFunc> create_vd_funcs =
GetCreateVDFunctions(used_create_vd_func_);
if (!decoder_) {
CreateAndInitializeVD(std::move(create_vd_funcs), config, low_delay,
cdm_context, waiting_cb);
} else {
decoder_->Initialize(
config, low_delay, cdm_context,
// If it fails to re-initialize current |decoder_|, it will create
// another decoder instance by trying available VD creation functions
// again. See |OnInitializeDone| for detail.
base::BindOnce(&VideoDecoderPipeline::OnInitializeDone, weak_this_,
std::move(create_vd_funcs), config, low_delay,
cdm_context, waiting_cb),
base::BindRepeating(&VideoDecoderPipeline::OnFrameDecodedThunk,
client_task_runner_, weak_this_),
waiting_cb);
}
}
void VideoDecoderPipeline::CreateAndInitializeVD(
base::queue<VideoDecoderPipeline::CreateVDFunc> create_vd_funcs,
VideoDecoderConfig config,
bool low_delay,
CdmContext* cdm_context,
WaitingCB waiting_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(init_cb_);
DCHECK(!decoder_);
DCHECK(!used_create_vd_func_);
DVLOGF(3);
if (create_vd_funcs.empty()) {
DVLOGF(2) << "No available video decoder.";
std::move(init_cb_).Run(false);
return;
}
used_create_vd_func_ = create_vd_funcs.front();
create_vd_funcs.pop();
decoder_ = used_create_vd_func_(
client_task_runner_, decoder_task_runner_,
base::BindRepeating(&VideoDecoderPipeline::GetVideoFramePool,
base::Unretained(this)));
if (!decoder_) {
DVLOGF(2) << "Failed to create VideoDecoder.";
used_create_vd_func_ = nullptr;
return CreateAndInitializeVD(std::move(create_vd_funcs), config, low_delay,
cdm_context, std::move(waiting_cb));
}
decoder_->Initialize(
config, low_delay, cdm_context, std::move(init_cb),
config, low_delay, cdm_context,
base::BindOnce(&VideoDecoderPipeline::OnInitializeDone, weak_this_,
std::move(create_vd_funcs), config, low_delay, cdm_context,
waiting_cb),
base::BindRepeating(&VideoDecoderPipeline::OnFrameDecodedThunk,
client_task_runner_, weak_this_factory_.GetWeakPtr()),
std::move(waiting_cb));
client_task_runner_, weak_this_),
waiting_cb);
}
void VideoDecoderPipeline::OnInitializeDone(
base::queue<VideoDecoderPipeline::CreateVDFunc> create_vd_funcs,
VideoDecoderConfig config,
bool low_delay,
CdmContext* cdm_context,
WaitingCB waiting_cb,
bool success) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(init_cb_);
DVLOGF(4) << "Initialization " << (success ? "success." : "failure.");
if (success) {
DVLOGF(2) << "Initialize VD successfully.";
std::move(init_cb_).Run(true);
return;
}
DVLOGF(3) << "Reset VD, try the next create function.";
decoder_ = nullptr;
used_create_vd_func_ = nullptr;
CreateAndInitializeVD(std::move(create_vd_funcs), config, low_delay,
cdm_context, std::move(waiting_cb));
}
void VideoDecoderPipeline::Reset(base::OnceClosure closure) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(decoder_);
DCHECK(!client_reset_cb_);
DVLOGF(3);
client_reset_cb_ = std::move(closure);
decoder_->Reset(base::BindOnce(&VideoDecoderPipeline::OnResetDone,
weak_this_factory_.GetWeakPtr()));
decoder_->Reset(
base::BindOnce(&VideoDecoderPipeline::OnResetDone, weak_this_));
}
void VideoDecoderPipeline::OnResetDone() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(client_reset_cb_);
DVLOGF(3);
......@@ -116,20 +280,20 @@ void VideoDecoderPipeline::OnResetDone() {
void VideoDecoderPipeline::Decode(scoped_refptr<DecoderBuffer> buffer,
DecodeCB decode_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(decoder_);
DVLOGF(4);
bool is_flush = buffer->end_of_stream();
decoder_->Decode(std::move(buffer),
base::BindOnce(&VideoDecoderPipeline::OnDecodeDone,
weak_this_factory_.GetWeakPtr(), is_flush,
std::move(decode_cb)));
weak_this_, is_flush, std::move(decode_cb)));
}
void VideoDecoderPipeline::OnDecodeDone(bool is_flush,
DecodeCB decode_cb,
DecodeStatus status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(4) << "is_flush: " << is_flush << ", status: " << status;
if (has_error_)
......@@ -185,7 +349,7 @@ void VideoDecoderPipeline::OnFrameDecodedThunk(
}
void VideoDecoderPipeline::OnFrameDecoded(scoped_refptr<VideoFrame> frame) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(frame_converter_);
DVLOGF(4);
......@@ -193,7 +357,7 @@ void VideoDecoderPipeline::OnFrameDecoded(scoped_refptr<VideoFrame> frame) {
}
void VideoDecoderPipeline::OnFrameConverted(scoped_refptr<VideoFrame> frame) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(4);
if (!frame)
......@@ -210,7 +374,7 @@ void VideoDecoderPipeline::OnFrameConverted(scoped_refptr<VideoFrame> frame) {
}
void VideoDecoderPipeline::OnError(const std::string& msg) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
VLOGF(1) << msg;
has_error_ = true;
......@@ -218,7 +382,7 @@ void VideoDecoderPipeline::OnError(const std::string& msg) {
}
void VideoDecoderPipeline::CallFlushCbIfNeeded(DecodeStatus status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(3) << "status: " << status;
if (!client_flush_cb_)
......@@ -231,4 +395,8 @@ void VideoDecoderPipeline::CallFlushCbIfNeeded(DecodeStatus status) {
std::move(client_flush_cb_).Run(status);
}
DmabufVideoFramePool* VideoDecoderPipeline::GetVideoFramePool() const {
return frame_pool_.get();
}
} // namespace media
......@@ -7,10 +7,12 @@
#include <memory>
#include "base/containers/queue.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "media/base/video_decoder.h"
#include "media/base/video_decoder_config.h"
#include "media/gpu/media_gpu_export.h"
#include "media/gpu/video_frame_converter.h"
......@@ -20,12 +22,15 @@ class SequencedTaskRunner;
namespace media {
class DmabufVideoFramePool;
class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
public:
VideoDecoderPipeline(
static std::unique_ptr<VideoDecoder> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<VideoDecoder> decoder,
std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter);
~VideoDecoderPipeline() override;
// VideoDecoder implementation
......@@ -45,7 +50,35 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
private:
// Function signature for creating VideoDecoder.
using CreateVDFunc = std::unique_ptr<VideoDecoder> (*)(
scoped_refptr<base::SequencedTaskRunner>,
scoped_refptr<base::SequencedTaskRunner>,
base::RepeatingCallback<DmabufVideoFramePool*()>);
// Get a list of the available functions for creating VideoDeocoder.
static base::queue<CreateVDFunc> GetCreateVDFunctions(
CreateVDFunc current_func);
VideoDecoderPipeline(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter);
void Destroy() override;
void DestroyTask();
void CreateAndInitializeVD(base::queue<CreateVDFunc> create_vd_funcs,
VideoDecoderConfig config,
bool low_delay,
CdmContext* cdm_context,
WaitingCB waiting_cb);
void OnInitializeDone(base::queue<CreateVDFunc> create_vd_funcs,
VideoDecoderConfig config,
bool low_delay,
CdmContext* cdm_context,
WaitingCB waiting_cb,
bool success);
void OnDecodeDone(bool eos_buffer, DecodeCB decode_cb, DecodeStatus status);
void OnResetDone();
void OnFrameConverted(scoped_refptr<VideoFrame> frame);
......@@ -60,13 +93,34 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
// Call |client_flush_cb_| with |status| if we need.
void CallFlushCbIfNeeded(DecodeStatus status);
// Get the video frame pool without passing the ownership.
DmabufVideoFramePool* GetVideoFramePool() const;
// The client task runner and its sequence checker. All public methods should
// run on this task runner.
const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
SEQUENCE_CHECKER(client_sequence_checker_);
const std::unique_ptr<VideoDecoder> decoder_;
const std::unique_ptr<VideoFrameConverter> frame_converter_;
// The decoder task runner and its sequence checker. |decoder_| should post
// time-consuming task and call |frame_pool_|'s methods on this task runner.
const scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
SEQUENCE_CHECKER(decoder_sequence_checker_);
// The frame pool passed from the client. Destroyed on |decoder_task_runner_|.
std::unique_ptr<DmabufVideoFramePool> frame_pool_;
// The frame converter passed from the client. Destroyed on
// |client_task_runner_|.
std::unique_ptr<VideoFrameConverter> frame_converter_;
// The current video decoder implementation. Valid after initialization is
// successfully done.
std::unique_ptr<VideoDecoder> decoder_;
// The create function of |decoder_|. nullptr iff |decoder_| is nullptr.
CreateVDFunc used_create_vd_func_ = nullptr;
// Callback from the client. These callback are called on
// |client_task_runner_|.
InitCB init_cb_;
OutputCB client_output_cb_;
DecodeCB client_flush_cb_;
base::OnceClosure client_reset_cb_;
......@@ -74,9 +128,9 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
// Set to true when any unexpected error occurs.
bool has_error_ = false;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<VideoDecoderPipeline> weak_this_factory_;
// The weak pointer of this, bound to |client_task_runner_|.
base::WeakPtr<VideoDecoderPipeline> weak_this_;
base::WeakPtrFactory<VideoDecoderPipeline> weak_this_factory_{this};
};
} // namespace media
......
......@@ -71,6 +71,10 @@ source_set("v4l2") {
configs += [ "//third_party/libyuv:libyuv_config" ]
public_deps = [
"//ui/gl",
]
deps = [
"//base",
"//gpu/ipc/common",
......
......@@ -128,9 +128,10 @@ struct V4L2SliceVideoDecoder::OutputRequest {
// static
std::unique_ptr<VideoDecoder> V4L2SliceVideoDecoder::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool) {
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool_cb) {
DCHECK(client_task_runner->RunsTasksInCurrentSequence());
DCHECK(frame_pool);
DCHECK(get_pool_cb);
scoped_refptr<V4L2Device> device = V4L2Device::Create();
if (!device) {
......@@ -139,7 +140,8 @@ std::unique_ptr<VideoDecoder> V4L2SliceVideoDecoder::Create(
}
return base::WrapUnique<VideoDecoder>(new V4L2SliceVideoDecoder(
std::move(client_task_runner), std::move(device), std::move(frame_pool)));
std::move(client_task_runner), std::move(decoder_task_runner),
std::move(device), std::move(get_pool_cb)));
}
// static
......@@ -156,22 +158,19 @@ SupportedVideoDecoderConfigs V4L2SliceVideoDecoder::GetSupportedConfigs() {
V4L2SliceVideoDecoder::V4L2SliceVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
scoped_refptr<V4L2Device> device,
std::unique_ptr<DmabufVideoFramePool> frame_pool)
GetFramePoolCB get_pool_cb)
: device_(std::move(device)),
frame_pool_(std::move(frame_pool)),
get_pool_cb_(std::move(get_pool_cb)),
client_task_runner_(std::move(client_task_runner)),
decoder_task_runner_(base::CreateSequencedTaskRunner(
{base::ThreadPool(), base::WithBaseSyncPrimitives(),
base::TaskPriority::USER_VISIBLE})),
decoder_task_runner_(std::move(decoder_task_runner)),
device_poll_thread_("V4L2SliceVideoDecoderDevicePollThread"),
weak_this_factory_(this) {
DETACH_FROM_SEQUENCE(client_sequence_checker_);
DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
VLOGF(2);
weak_this_ = weak_this_factory_.GetWeakPtr();
frame_pool_->set_parent_task_runner(decoder_task_runner_);
}
V4L2SliceVideoDecoder::~V4L2SliceVideoDecoder() {
......@@ -245,6 +244,7 @@ void V4L2SliceVideoDecoder::DestroyTask() {
DCHECK(surfaces_at_device_.empty());
weak_this_factory_.InvalidateWeakPtrs();
delete this;
VLOGF(2) << "Destroyed";
}
......@@ -318,6 +318,9 @@ void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
SetState(State::kUninitialized);
}
// Setup frame pool.
frame_pool_ = get_pool_cb_.Run();
// Open V4L2 device.
VideoCodecProfile profile = config.profile();
uint32_t input_format_fourcc =
......
......@@ -38,12 +38,15 @@ class V4L2DecodeSurface;
class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder,
public V4L2DecodeSurfaceHandler {
public:
using GetFramePoolCB = base::RepeatingCallback<DmabufVideoFramePool*()>;
// Create V4L2SliceVideoDecoder instance. The success of the creation doesn't
// ensure V4L2SliceVideoDecoder is available on the device. It will be
// determined in Initialize().
static std::unique_ptr<VideoDecoder> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool);
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool_cb);
static SupportedVideoDecoderConfigs GetSupportedConfigs();
......@@ -80,8 +83,9 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder,
V4L2SliceVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
scoped_refptr<V4L2Device> device,
std::unique_ptr<DmabufVideoFramePool> frame_pool);
GetFramePoolCB get_pool_cb);
~V4L2SliceVideoDecoder() override;
void Destroy() override;
......@@ -218,7 +222,8 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder,
// V4L2 device in use.
scoped_refptr<V4L2Device> device_;
// VideoFrame manager used to allocate and recycle video frame.
std::unique_ptr<DmabufVideoFramePool> frame_pool_;
GetFramePoolCB get_pool_cb_;
DmabufVideoFramePool* frame_pool_ = nullptr;
// Video decoder used to parse stream headers by software.
std::unique_ptr<AcceleratedVideoDecoder> avd_;
......
......@@ -68,9 +68,11 @@ VaapiVideoDecoder::DecodeTask::DecodeTask(DecodeTask&&) = default;
// static
std::unique_ptr<VideoDecoder> VaapiVideoDecoder::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool) {
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool_cb) {
return base::WrapUnique<VideoDecoder>(new VaapiVideoDecoder(
std::move(client_task_runner), std::move(frame_pool)));
std::move(client_task_runner), std::move(decoder_task_runner),
std::move(get_pool_cb)));
}
// static
......@@ -81,10 +83,11 @@ SupportedVideoDecoderConfigs VaapiVideoDecoder::GetSupportedConfigs() {
VaapiVideoDecoder::VaapiVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool)
: frame_pool_(std::move(frame_pool)),
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool_cb)
: get_pool_cb_(std::move(get_pool_cb)),
client_task_runner_(std::move(client_task_runner)),
decoder_thread_("VaapiDecoderThread"),
decoder_task_runner_(std::move(decoder_task_runner)),
weak_this_factory_(this) {
DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
VLOGF(2);
......@@ -149,17 +152,7 @@ void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
return;
}
if (!decoder_thread_.IsRunning() && !decoder_thread_.Start()) {
std::move(init_cb).Run(false);
return;
}
if (!decoder_thread_task_runner_) {
decoder_thread_task_runner_ = decoder_thread_.task_runner();
frame_pool_->set_parent_task_runner(decoder_thread_task_runner_);
}
decoder_thread_task_runner_->PostTask(
decoder_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::InitializeTask, weak_this_, config,
std::move(init_cb), std::move(output_cb)));
......@@ -227,6 +220,9 @@ void VaapiVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
}
needs_bitstream_conversion_ = (config.codec() == kCodecH264);
// Get and initialize the frame pool.
frame_pool_ = get_pool_cb_.Run();
visible_rect_ = config.visible_rect();
pixel_aspect_ratio_ = config.GetPixelAspectRatio();
profile_ = profile;
......@@ -243,14 +239,8 @@ void VaapiVideoDecoder::Destroy() {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
VLOGF(2);
if (decoder_thread_task_runner_) {
decoder_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::DestroyTask, weak_this_));
decoder_thread_.Stop();
}
delete this;
VLOGF(2) << "Destroying VAAPI VD done";
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::DestroyTask, weak_this_));
}
void VaapiVideoDecoder::DestroyTask() {
......@@ -265,18 +255,17 @@ void VaapiVideoDecoder::DestroyTask() {
decoder_ = nullptr;
}
// Drop all video frame references. This will cause the frames to be
// destroyed once the decoder's client is done using them.
frame_pool_ = nullptr;
weak_this_factory_.InvalidateWeakPtrs();
delete this;
VLOGF(2) << "Destroying VAAPI VD done";
}
void VaapiVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
DecodeCB decode_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
decoder_thread_task_runner_->PostTask(
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::QueueDecodeTask, weak_this_,
std::move(buffer), std::move(decode_cb)));
}
......@@ -324,7 +313,7 @@ void VaapiVideoDecoder::ScheduleNextDecodeTask() {
*current_decode_task_->buffer_);
}
decoder_thread_task_runner_->PostTask(
decoder_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
}
......@@ -541,7 +530,7 @@ void VaapiVideoDecoder::ChangeFrameResolutionTask() {
vaapi_wrapper_->CreateContext(pic_size);
// Retry the current decode task.
decoder_thread_task_runner_->PostTask(
decoder_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
}
......@@ -570,7 +559,7 @@ void VaapiVideoDecoder::NotifyFrameAvailableTask() {
if (state_ == State::kWaitingForOutput) {
DCHECK(current_decode_task_);
SetState(State::kDecoding);
decoder_thread_task_runner_->PostTask(
decoder_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
}
......@@ -610,7 +599,7 @@ void VaapiVideoDecoder::Reset(base::OnceClosure reset_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(2);
decoder_thread_task_runner_->PostTask(
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetTask, weak_this_,
std::move(reset_cb)));
}
......@@ -632,7 +621,7 @@ void VaapiVideoDecoder::ResetTask(base::OnceClosure reset_cb) {
SetState(State::kResetting);
// Wait until any pending decode task has been aborted.
decoder_thread_task_runner_->PostTask(
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetDoneTask, weak_this_,
std::move(reset_cb)));
}
......
......@@ -39,9 +39,12 @@ class VASurface;
class VaapiVideoDecoder : public media::VideoDecoder,
public DecodeSurfaceHandler<VASurface> {
public:
using GetFramePoolCB = base::RepeatingCallback<DmabufVideoFramePool*()>;
static std::unique_ptr<VideoDecoder> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool);
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool);
static SupportedVideoDecoderConfigs GetSupportedConfigs();
......@@ -91,8 +94,10 @@ class VaapiVideoDecoder : public media::VideoDecoder,
kError, // decoder encountered an error.
};
VaapiVideoDecoder(scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool);
VaapiVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool);
~VaapiVideoDecoder() override;
// Destroy the VAAPIVideoDecoder, aborts pending decode requests and blocks
......@@ -171,7 +176,8 @@ class VaapiVideoDecoder : public media::VideoDecoder,
double pixel_aspect_ratio_ = 0.0;
// Video frame pool used to allocate and recycle video frames.
std::unique_ptr<DmabufVideoFramePool> frame_pool_;
GetFramePoolCB get_pool_cb_;
DmabufVideoFramePool* frame_pool_ = nullptr;
// The mapping between buffer id and the timestamp.
std::map<int32_t, base::TimeDelta> buffer_id_to_timestamp_;
......@@ -191,8 +197,7 @@ class VaapiVideoDecoder : public media::VideoDecoder,
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
base::Thread decoder_thread_;
scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_;
const scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
SEQUENCE_CHECKER(client_sequence_checker_);
SEQUENCE_CHECKER(decoder_sequence_checker_);
......
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