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") { ...@@ -22,7 +22,7 @@ source_set("chromeos") {
] ]
if (use_vaapi || use_v4l2_codec) { if (use_vaapi || use_v4l2_codec) {
deps += [ "//media/gpu/linux:common" ] deps += [ "//media/gpu/linux" ]
} }
if (use_vaapi) { if (use_vaapi) {
......
...@@ -9,8 +9,12 @@ ...@@ -9,8 +9,12 @@
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "media/base/video_decoder.h" #include "media/base/video_decoder.h"
#include "media/gpu/buildflags.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/mailbox_video_frame_converter.h"
#include "media/gpu/linux/platform_video_frame_pool.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) #if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_video_decoder.h" #include "media/gpu/vaapi/vaapi_video_decoder.h"
...@@ -20,9 +24,6 @@ ...@@ -20,9 +24,6 @@
#include "media/gpu/v4l2/v4l2_slice_video_decoder.h" #include "media/gpu/v4l2/v4l2_slice_video_decoder.h"
#endif #endif
#if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
#include "media/gpu/linux/video_decoder_pipeline.h"
#endif
namespace media { namespace media {
...@@ -52,29 +53,14 @@ std::unique_ptr<VideoDecoder> ChromeosVideoDecoderFactory::Create( ...@@ -52,29 +53,14 @@ std::unique_ptr<VideoDecoder> ChromeosVideoDecoderFactory::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool, std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter) { 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) #if BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
return std::make_unique<VideoDecoderPipeline>(std::move(client_task_runner), // TODO(akahuang): Remove ChromeosVideoDecoderFactory.
std::move(decoder), return VideoDecoderPipeline::Create(std::move(client_task_runner),
std::move(frame_converter)); std::move(frame_pool),
#else std::move(frame_converter));
#endif // BUILDFLAG(USE_VAAPI) || BUILDFLAG(USE_V4L2_CODEC)
return nullptr; return nullptr;
#endif
} }
} // namespace media } // namespace media
...@@ -7,6 +7,36 @@ import("//media/gpu/args.gni") ...@@ -7,6 +7,36 @@ import("//media/gpu/args.gni")
assert(use_v4l2_codec || use_vaapi) 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") { source_set("common") {
defines = [ "MEDIA_GPU_IMPLEMENTATION" ] defines = [ "MEDIA_GPU_IMPLEMENTATION" ]
sources = [ sources = [
...@@ -18,8 +48,6 @@ source_set("common") { ...@@ -18,8 +48,6 @@ source_set("common") {
"platform_video_frame_pool.h", "platform_video_frame_pool.h",
"platform_video_frame_utils.cc", "platform_video_frame_utils.cc",
"platform_video_frame_utils.h", "platform_video_frame_utils.h",
"video_decoder_pipeline.cc",
"video_decoder_pipeline.h",
] ]
deps = [ deps = [
......
...@@ -7,71 +7,154 @@ ...@@ -7,71 +7,154 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
#include "base/task/post_task.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" #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 { 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( VideoDecoderPipeline::VideoDecoderPipeline(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<VideoDecoder> decoder, std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter) std::unique_ptr<VideoFrameConverter> frame_converter)
: client_task_runner_(std::move(client_task_runner)), : client_task_runner_(std::move(client_task_runner)),
decoder_(std::move(decoder)), decoder_task_runner_(base::CreateSingleThreadTaskRunner(
frame_converter_(std::move(frame_converter)), {base::ThreadPool(), base::WithBaseSyncPrimitives(),
weak_this_factory_(this) { base::TaskPriority::USER_VISIBLE},
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::SingleThreadTaskRunnerThreadMode::DEDICATED)),
DCHECK(decoder_); 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(frame_converter_);
DCHECK(client_task_runner_); DCHECK(client_task_runner_);
DVLOGF(2); DVLOGF(2);
weak_this_ = weak_this_factory_.GetWeakPtr();
frame_pool_->set_parent_task_runner(decoder_task_runner_);
frame_converter_->Initialize( frame_converter_->Initialize(
client_task_runner_, client_task_runner_,
base::BindRepeating(&VideoDecoderPipeline::OnFrameConverted, base::BindRepeating(&VideoDecoderPipeline::OnFrameConverted, weak_this_));
weak_this_factory_.GetWeakPtr()));
} }
VideoDecoderPipeline::~VideoDecoderPipeline() { 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); DVLOGF(3);
} }
void VideoDecoderPipeline::Destroy() { void VideoDecoderPipeline::Destroy() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(2); 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; delete this;
} }
std::string VideoDecoderPipeline::GetDisplayName() const { 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 { 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 { 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 { 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 { 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, void VideoDecoderPipeline::Initialize(const VideoDecoderConfig& config,
...@@ -80,30 +163,111 @@ void VideoDecoderPipeline::Initialize(const VideoDecoderConfig& config, ...@@ -80,30 +163,111 @@ void VideoDecoderPipeline::Initialize(const VideoDecoderConfig& config,
InitCB init_cb, InitCB init_cb,
const OutputCB& output_cb, const OutputCB& output_cb,
const WaitingCB& waiting_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(); VLOGF(2) << "config: " << config.AsHumanReadableString();
client_output_cb_ = std::move(output_cb); 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( 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, base::BindRepeating(&VideoDecoderPipeline::OnFrameDecodedThunk,
client_task_runner_, weak_this_factory_.GetWeakPtr()), client_task_runner_, weak_this_),
std::move(waiting_cb)); 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) { 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_); DCHECK(!client_reset_cb_);
DVLOGF(3); DVLOGF(3);
client_reset_cb_ = std::move(closure); client_reset_cb_ = std::move(closure);
decoder_->Reset(base::BindOnce(&VideoDecoderPipeline::OnResetDone, decoder_->Reset(
weak_this_factory_.GetWeakPtr())); base::BindOnce(&VideoDecoderPipeline::OnResetDone, weak_this_));
} }
void VideoDecoderPipeline::OnResetDone() { void VideoDecoderPipeline::OnResetDone() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(client_reset_cb_); DCHECK(client_reset_cb_);
DVLOGF(3); DVLOGF(3);
...@@ -116,20 +280,20 @@ void VideoDecoderPipeline::OnResetDone() { ...@@ -116,20 +280,20 @@ void VideoDecoderPipeline::OnResetDone() {
void VideoDecoderPipeline::Decode(scoped_refptr<DecoderBuffer> buffer, void VideoDecoderPipeline::Decode(scoped_refptr<DecoderBuffer> buffer,
DecodeCB decode_cb) { DecodeCB decode_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(decoder_);
DVLOGF(4); DVLOGF(4);
bool is_flush = buffer->end_of_stream(); bool is_flush = buffer->end_of_stream();
decoder_->Decode(std::move(buffer), decoder_->Decode(std::move(buffer),
base::BindOnce(&VideoDecoderPipeline::OnDecodeDone, base::BindOnce(&VideoDecoderPipeline::OnDecodeDone,
weak_this_factory_.GetWeakPtr(), is_flush, weak_this_, is_flush, std::move(decode_cb)));
std::move(decode_cb)));
} }
void VideoDecoderPipeline::OnDecodeDone(bool is_flush, void VideoDecoderPipeline::OnDecodeDone(bool is_flush,
DecodeCB decode_cb, DecodeCB decode_cb,
DecodeStatus status) { 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; DVLOGF(4) << "is_flush: " << is_flush << ", status: " << status;
if (has_error_) if (has_error_)
...@@ -185,7 +349,7 @@ void VideoDecoderPipeline::OnFrameDecodedThunk( ...@@ -185,7 +349,7 @@ void VideoDecoderPipeline::OnFrameDecodedThunk(
} }
void VideoDecoderPipeline::OnFrameDecoded(scoped_refptr<VideoFrame> frame) { 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_); DCHECK(frame_converter_);
DVLOGF(4); DVLOGF(4);
...@@ -193,7 +357,7 @@ void VideoDecoderPipeline::OnFrameDecoded(scoped_refptr<VideoFrame> frame) { ...@@ -193,7 +357,7 @@ void VideoDecoderPipeline::OnFrameDecoded(scoped_refptr<VideoFrame> frame) {
} }
void VideoDecoderPipeline::OnFrameConverted(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); DVLOGF(4);
if (!frame) if (!frame)
...@@ -210,7 +374,7 @@ void VideoDecoderPipeline::OnFrameConverted(scoped_refptr<VideoFrame> frame) { ...@@ -210,7 +374,7 @@ void VideoDecoderPipeline::OnFrameConverted(scoped_refptr<VideoFrame> frame) {
} }
void VideoDecoderPipeline::OnError(const std::string& msg) { 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; VLOGF(1) << msg;
has_error_ = true; has_error_ = true;
...@@ -218,7 +382,7 @@ void VideoDecoderPipeline::OnError(const std::string& msg) { ...@@ -218,7 +382,7 @@ void VideoDecoderPipeline::OnError(const std::string& msg) {
} }
void VideoDecoderPipeline::CallFlushCbIfNeeded(DecodeStatus status) { void VideoDecoderPipeline::CallFlushCbIfNeeded(DecodeStatus status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(3) << "status: " << status; DVLOGF(3) << "status: " << status;
if (!client_flush_cb_) if (!client_flush_cb_)
...@@ -231,4 +395,8 @@ void VideoDecoderPipeline::CallFlushCbIfNeeded(DecodeStatus status) { ...@@ -231,4 +395,8 @@ void VideoDecoderPipeline::CallFlushCbIfNeeded(DecodeStatus status) {
std::move(client_flush_cb_).Run(status); std::move(client_flush_cb_).Run(status);
} }
DmabufVideoFramePool* VideoDecoderPipeline::GetVideoFramePool() const {
return frame_pool_.get();
}
} // namespace media } // namespace media
...@@ -7,10 +7,12 @@ ...@@ -7,10 +7,12 @@
#include <memory> #include <memory>
#include "base/containers/queue.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "media/base/video_decoder.h" #include "media/base/video_decoder.h"
#include "media/base/video_decoder_config.h"
#include "media/gpu/media_gpu_export.h" #include "media/gpu/media_gpu_export.h"
#include "media/gpu/video_frame_converter.h" #include "media/gpu/video_frame_converter.h"
...@@ -20,12 +22,15 @@ class SequencedTaskRunner; ...@@ -20,12 +22,15 @@ class SequencedTaskRunner;
namespace media { namespace media {
class DmabufVideoFramePool;
class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder { class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
public: public:
VideoDecoderPipeline( static std::unique_ptr<VideoDecoder> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<VideoDecoder> decoder, std::unique_ptr<DmabufVideoFramePool> frame_pool,
std::unique_ptr<VideoFrameConverter> frame_converter); std::unique_ptr<VideoFrameConverter> frame_converter);
~VideoDecoderPipeline() override; ~VideoDecoderPipeline() override;
// VideoDecoder implementation // VideoDecoder implementation
...@@ -45,7 +50,35 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder { ...@@ -45,7 +50,35 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override; void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
private: 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 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 OnDecodeDone(bool eos_buffer, DecodeCB decode_cb, DecodeStatus status);
void OnResetDone(); void OnResetDone();
void OnFrameConverted(scoped_refptr<VideoFrame> frame); void OnFrameConverted(scoped_refptr<VideoFrame> frame);
...@@ -60,13 +93,34 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder { ...@@ -60,13 +93,34 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
// Call |client_flush_cb_| with |status| if we need. // Call |client_flush_cb_| with |status| if we need.
void CallFlushCbIfNeeded(DecodeStatus status); 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_; const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
SEQUENCE_CHECKER(client_sequence_checker_);
const std::unique_ptr<VideoDecoder> decoder_; // The decoder task runner and its sequence checker. |decoder_| should post
const std::unique_ptr<VideoFrameConverter> frame_converter_; // 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 // Callback from the client. These callback are called on
// |client_task_runner_|. // |client_task_runner_|.
InitCB init_cb_;
OutputCB client_output_cb_; OutputCB client_output_cb_;
DecodeCB client_flush_cb_; DecodeCB client_flush_cb_;
base::OnceClosure client_reset_cb_; base::OnceClosure client_reset_cb_;
...@@ -74,9 +128,9 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder { ...@@ -74,9 +128,9 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
// Set to true when any unexpected error occurs. // Set to true when any unexpected error occurs.
bool has_error_ = false; bool has_error_ = false;
SEQUENCE_CHECKER(sequence_checker_); // The weak pointer of this, bound to |client_task_runner_|.
base::WeakPtr<VideoDecoderPipeline> weak_this_;
base::WeakPtrFactory<VideoDecoderPipeline> weak_this_factory_; base::WeakPtrFactory<VideoDecoderPipeline> weak_this_factory_{this};
}; };
} // namespace media } // namespace media
......
...@@ -71,6 +71,10 @@ source_set("v4l2") { ...@@ -71,6 +71,10 @@ source_set("v4l2") {
configs += [ "//third_party/libyuv:libyuv_config" ] configs += [ "//third_party/libyuv:libyuv_config" ]
public_deps = [
"//ui/gl",
]
deps = [ deps = [
"//base", "//base",
"//gpu/ipc/common", "//gpu/ipc/common",
......
...@@ -128,9 +128,10 @@ struct V4L2SliceVideoDecoder::OutputRequest { ...@@ -128,9 +128,10 @@ struct V4L2SliceVideoDecoder::OutputRequest {
// static // static
std::unique_ptr<VideoDecoder> V4L2SliceVideoDecoder::Create( std::unique_ptr<VideoDecoder> V4L2SliceVideoDecoder::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, 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(client_task_runner->RunsTasksInCurrentSequence());
DCHECK(frame_pool); DCHECK(get_pool_cb);
scoped_refptr<V4L2Device> device = V4L2Device::Create(); scoped_refptr<V4L2Device> device = V4L2Device::Create();
if (!device) { if (!device) {
...@@ -139,7 +140,8 @@ std::unique_ptr<VideoDecoder> V4L2SliceVideoDecoder::Create( ...@@ -139,7 +140,8 @@ std::unique_ptr<VideoDecoder> V4L2SliceVideoDecoder::Create(
} }
return base::WrapUnique<VideoDecoder>(new V4L2SliceVideoDecoder( 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 // static
...@@ -156,22 +158,19 @@ SupportedVideoDecoderConfigs V4L2SliceVideoDecoder::GetSupportedConfigs() { ...@@ -156,22 +158,19 @@ SupportedVideoDecoderConfigs V4L2SliceVideoDecoder::GetSupportedConfigs() {
V4L2SliceVideoDecoder::V4L2SliceVideoDecoder( V4L2SliceVideoDecoder::V4L2SliceVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
scoped_refptr<V4L2Device> device, scoped_refptr<V4L2Device> device,
std::unique_ptr<DmabufVideoFramePool> frame_pool) GetFramePoolCB get_pool_cb)
: device_(std::move(device)), : 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)), client_task_runner_(std::move(client_task_runner)),
decoder_task_runner_(base::CreateSequencedTaskRunner( decoder_task_runner_(std::move(decoder_task_runner)),
{base::ThreadPool(), base::WithBaseSyncPrimitives(),
base::TaskPriority::USER_VISIBLE})),
device_poll_thread_("V4L2SliceVideoDecoderDevicePollThread"), device_poll_thread_("V4L2SliceVideoDecoderDevicePollThread"),
weak_this_factory_(this) { weak_this_factory_(this) {
DETACH_FROM_SEQUENCE(client_sequence_checker_); DETACH_FROM_SEQUENCE(client_sequence_checker_);
DETACH_FROM_SEQUENCE(decoder_sequence_checker_); DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
VLOGF(2); VLOGF(2);
weak_this_ = weak_this_factory_.GetWeakPtr(); weak_this_ = weak_this_factory_.GetWeakPtr();
frame_pool_->set_parent_task_runner(decoder_task_runner_);
} }
V4L2SliceVideoDecoder::~V4L2SliceVideoDecoder() { V4L2SliceVideoDecoder::~V4L2SliceVideoDecoder() {
...@@ -245,6 +244,7 @@ void V4L2SliceVideoDecoder::DestroyTask() { ...@@ -245,6 +244,7 @@ void V4L2SliceVideoDecoder::DestroyTask() {
DCHECK(surfaces_at_device_.empty()); DCHECK(surfaces_at_device_.empty());
weak_this_factory_.InvalidateWeakPtrs(); weak_this_factory_.InvalidateWeakPtrs();
delete this; delete this;
VLOGF(2) << "Destroyed"; VLOGF(2) << "Destroyed";
} }
...@@ -318,6 +318,9 @@ void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config, ...@@ -318,6 +318,9 @@ void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
SetState(State::kUninitialized); SetState(State::kUninitialized);
} }
// Setup frame pool.
frame_pool_ = get_pool_cb_.Run();
// Open V4L2 device. // Open V4L2 device.
VideoCodecProfile profile = config.profile(); VideoCodecProfile profile = config.profile();
uint32_t input_format_fourcc = uint32_t input_format_fourcc =
......
...@@ -38,12 +38,15 @@ class V4L2DecodeSurface; ...@@ -38,12 +38,15 @@ class V4L2DecodeSurface;
class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder, class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder,
public V4L2DecodeSurfaceHandler { public V4L2DecodeSurfaceHandler {
public: public:
using GetFramePoolCB = base::RepeatingCallback<DmabufVideoFramePool*()>;
// Create V4L2SliceVideoDecoder instance. The success of the creation doesn't // Create V4L2SliceVideoDecoder instance. The success of the creation doesn't
// ensure V4L2SliceVideoDecoder is available on the device. It will be // ensure V4L2SliceVideoDecoder is available on the device. It will be
// determined in Initialize(). // determined in Initialize().
static std::unique_ptr<VideoDecoder> Create( static std::unique_ptr<VideoDecoder> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, 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(); static SupportedVideoDecoderConfigs GetSupportedConfigs();
...@@ -80,8 +83,9 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder, ...@@ -80,8 +83,9 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder,
V4L2SliceVideoDecoder( V4L2SliceVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
scoped_refptr<V4L2Device> device, scoped_refptr<V4L2Device> device,
std::unique_ptr<DmabufVideoFramePool> frame_pool); GetFramePoolCB get_pool_cb);
~V4L2SliceVideoDecoder() override; ~V4L2SliceVideoDecoder() override;
void Destroy() override; void Destroy() override;
...@@ -218,7 +222,8 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder, ...@@ -218,7 +222,8 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder : public VideoDecoder,
// V4L2 device in use. // V4L2 device in use.
scoped_refptr<V4L2Device> device_; scoped_refptr<V4L2Device> device_;
// VideoFrame manager used to allocate and recycle video frame. // 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. // Video decoder used to parse stream headers by software.
std::unique_ptr<AcceleratedVideoDecoder> avd_; std::unique_ptr<AcceleratedVideoDecoder> avd_;
......
...@@ -68,9 +68,11 @@ VaapiVideoDecoder::DecodeTask::DecodeTask(DecodeTask&&) = default; ...@@ -68,9 +68,11 @@ VaapiVideoDecoder::DecodeTask::DecodeTask(DecodeTask&&) = default;
// static // static
std::unique_ptr<VideoDecoder> VaapiVideoDecoder::Create( std::unique_ptr<VideoDecoder> VaapiVideoDecoder::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, 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( 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 // static
...@@ -81,10 +83,11 @@ SupportedVideoDecoderConfigs VaapiVideoDecoder::GetSupportedConfigs() { ...@@ -81,10 +83,11 @@ SupportedVideoDecoderConfigs VaapiVideoDecoder::GetSupportedConfigs() {
VaapiVideoDecoder::VaapiVideoDecoder( VaapiVideoDecoder::VaapiVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, scoped_refptr<base::SequencedTaskRunner> client_task_runner,
std::unique_ptr<DmabufVideoFramePool> frame_pool) scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
: frame_pool_(std::move(frame_pool)), GetFramePoolCB get_pool_cb)
: get_pool_cb_(std::move(get_pool_cb)),
client_task_runner_(std::move(client_task_runner)), client_task_runner_(std::move(client_task_runner)),
decoder_thread_("VaapiDecoderThread"), decoder_task_runner_(std::move(decoder_task_runner)),
weak_this_factory_(this) { weak_this_factory_(this) {
DETACH_FROM_SEQUENCE(decoder_sequence_checker_); DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
VLOGF(2); VLOGF(2);
...@@ -149,17 +152,7 @@ void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config, ...@@ -149,17 +152,7 @@ void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
return; return;
} }
if (!decoder_thread_.IsRunning() && !decoder_thread_.Start()) { decoder_task_runner_->PostTask(
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(
FROM_HERE, FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::InitializeTask, weak_this_, config, base::BindOnce(&VaapiVideoDecoder::InitializeTask, weak_this_, config,
std::move(init_cb), std::move(output_cb))); std::move(init_cb), std::move(output_cb)));
...@@ -227,6 +220,9 @@ void VaapiVideoDecoder::InitializeTask(const VideoDecoderConfig& config, ...@@ -227,6 +220,9 @@ void VaapiVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
} }
needs_bitstream_conversion_ = (config.codec() == kCodecH264); needs_bitstream_conversion_ = (config.codec() == kCodecH264);
// Get and initialize the frame pool.
frame_pool_ = get_pool_cb_.Run();
visible_rect_ = config.visible_rect(); visible_rect_ = config.visible_rect();
pixel_aspect_ratio_ = config.GetPixelAspectRatio(); pixel_aspect_ratio_ = config.GetPixelAspectRatio();
profile_ = profile; profile_ = profile;
...@@ -243,14 +239,8 @@ void VaapiVideoDecoder::Destroy() { ...@@ -243,14 +239,8 @@ void VaapiVideoDecoder::Destroy() {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
VLOGF(2); VLOGF(2);
if (decoder_thread_task_runner_) { decoder_task_runner_->PostTask(
decoder_thread_task_runner_->PostTask( FROM_HERE, base::BindOnce(&VaapiVideoDecoder::DestroyTask, weak_this_));
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::DestroyTask, weak_this_));
decoder_thread_.Stop();
}
delete this;
VLOGF(2) << "Destroying VAAPI VD done";
} }
void VaapiVideoDecoder::DestroyTask() { void VaapiVideoDecoder::DestroyTask() {
...@@ -265,18 +255,17 @@ void VaapiVideoDecoder::DestroyTask() { ...@@ -265,18 +255,17 @@ void VaapiVideoDecoder::DestroyTask() {
decoder_ = nullptr; 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(); weak_this_factory_.InvalidateWeakPtrs();
delete this;
VLOGF(2) << "Destroying VAAPI VD done";
} }
void VaapiVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer, void VaapiVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
DecodeCB decode_cb) { DecodeCB decode_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); 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_, FROM_HERE, base::BindOnce(&VaapiVideoDecoder::QueueDecodeTask, weak_this_,
std::move(buffer), std::move(decode_cb))); std::move(buffer), std::move(decode_cb)));
} }
...@@ -324,7 +313,7 @@ void VaapiVideoDecoder::ScheduleNextDecodeTask() { ...@@ -324,7 +313,7 @@ void VaapiVideoDecoder::ScheduleNextDecodeTask() {
*current_decode_task_->buffer_); *current_decode_task_->buffer_);
} }
decoder_thread_task_runner_->PostTask( decoder_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_)); base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
} }
...@@ -541,7 +530,7 @@ void VaapiVideoDecoder::ChangeFrameResolutionTask() { ...@@ -541,7 +530,7 @@ void VaapiVideoDecoder::ChangeFrameResolutionTask() {
vaapi_wrapper_->CreateContext(pic_size); vaapi_wrapper_->CreateContext(pic_size);
// Retry the current decode task. // Retry the current decode task.
decoder_thread_task_runner_->PostTask( decoder_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_)); base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
} }
...@@ -570,7 +559,7 @@ void VaapiVideoDecoder::NotifyFrameAvailableTask() { ...@@ -570,7 +559,7 @@ void VaapiVideoDecoder::NotifyFrameAvailableTask() {
if (state_ == State::kWaitingForOutput) { if (state_ == State::kWaitingForOutput) {
DCHECK(current_decode_task_); DCHECK(current_decode_task_);
SetState(State::kDecoding); SetState(State::kDecoding);
decoder_thread_task_runner_->PostTask( decoder_task_runner_->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_)); base::BindOnce(&VaapiVideoDecoder::HandleDecodeTask, weak_this_));
} }
...@@ -610,7 +599,7 @@ void VaapiVideoDecoder::Reset(base::OnceClosure reset_cb) { ...@@ -610,7 +599,7 @@ void VaapiVideoDecoder::Reset(base::OnceClosure reset_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(2); DVLOGF(2);
decoder_thread_task_runner_->PostTask( decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetTask, weak_this_, FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetTask, weak_this_,
std::move(reset_cb))); std::move(reset_cb)));
} }
...@@ -632,7 +621,7 @@ void VaapiVideoDecoder::ResetTask(base::OnceClosure reset_cb) { ...@@ -632,7 +621,7 @@ void VaapiVideoDecoder::ResetTask(base::OnceClosure reset_cb) {
SetState(State::kResetting); SetState(State::kResetting);
// Wait until any pending decode task has been aborted. // 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_, FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetDoneTask, weak_this_,
std::move(reset_cb))); std::move(reset_cb)));
} }
......
...@@ -39,9 +39,12 @@ class VASurface; ...@@ -39,9 +39,12 @@ class VASurface;
class VaapiVideoDecoder : public media::VideoDecoder, class VaapiVideoDecoder : public media::VideoDecoder,
public DecodeSurfaceHandler<VASurface> { public DecodeSurfaceHandler<VASurface> {
public: public:
using GetFramePoolCB = base::RepeatingCallback<DmabufVideoFramePool*()>;
static std::unique_ptr<VideoDecoder> Create( static std::unique_ptr<VideoDecoder> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner, 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(); static SupportedVideoDecoderConfigs GetSupportedConfigs();
...@@ -91,8 +94,10 @@ class VaapiVideoDecoder : public media::VideoDecoder, ...@@ -91,8 +94,10 @@ class VaapiVideoDecoder : public media::VideoDecoder,
kError, // decoder encountered an error. kError, // decoder encountered an error.
}; };
VaapiVideoDecoder(scoped_refptr<base::SequencedTaskRunner> client_task_runner, VaapiVideoDecoder(
std::unique_ptr<DmabufVideoFramePool> frame_pool); scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool);
~VaapiVideoDecoder() override; ~VaapiVideoDecoder() override;
// Destroy the VAAPIVideoDecoder, aborts pending decode requests and blocks // Destroy the VAAPIVideoDecoder, aborts pending decode requests and blocks
...@@ -171,7 +176,8 @@ class VaapiVideoDecoder : public media::VideoDecoder, ...@@ -171,7 +176,8 @@ class VaapiVideoDecoder : public media::VideoDecoder,
double pixel_aspect_ratio_ = 0.0; double pixel_aspect_ratio_ = 0.0;
// Video frame pool used to allocate and recycle video frames. // 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. // The mapping between buffer id and the timestamp.
std::map<int32_t, base::TimeDelta> buffer_id_to_timestamp_; std::map<int32_t, base::TimeDelta> buffer_id_to_timestamp_;
...@@ -191,8 +197,7 @@ class VaapiVideoDecoder : public media::VideoDecoder, ...@@ -191,8 +197,7 @@ class VaapiVideoDecoder : public media::VideoDecoder,
scoped_refptr<VaapiWrapper> vaapi_wrapper_; scoped_refptr<VaapiWrapper> vaapi_wrapper_;
const scoped_refptr<base::SequencedTaskRunner> client_task_runner_; const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
base::Thread decoder_thread_; const scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> decoder_thread_task_runner_;
SEQUENCE_CHECKER(client_sequence_checker_); SEQUENCE_CHECKER(client_sequence_checker_);
SEQUENCE_CHECKER(decoder_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