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

media/gpu/linux: Make VideoDecoderPipeline delegate VD tasks to decoder thread.

Originally, VideoDecoderPipeline delegates VD tasks to the client
thread. Each VD implementation then post the tasks to decoder thread.
Then VD implementations post the callback back to the client thread
when the task is done. In the future, ImageProcessor will also operate
on the decoder thread. We will pass the task and output frames by:

  VDPipeline (client)
  -> VD (client -> decoder -> client)
  -> VDPipeline (client)
  -> IP (client -> decoder -> client)
  -> VDPipeline (client)
  -> Converter (client -> GPU -> client)
  -> VDPipeline (client)
  Total 6 thread hopping.

This CL now posts the VD task on the decoder thread. We don't need to
hop thread inside each VD implementation. With this CL, we could save
2 thread hopping.

  VDPipeline (client -> decoder)
  -> VD (decoder)
  -> VDPipeline (decoder)
  -> IP (decoder)
  -> VDPipeline (decoder)
  -> Converter (decoder -> GPU -> decoder)
  -> VDPipeline (decoder -> client)
  Total 4 thread hopping.

BUG=chromium:998413
TEST=run video_decode_accelerator_tests on Eve and Kevin
     with dcheck_always_on = true

Change-Id: I7367663258adfd0f46ddca25493faff4633ae034
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1777449
Commit-Queue: Chih-Yu Huang <akahuang@chromium.org>
Reviewed-by: default avatarDavid Staessens <dstaessens@chromium.org>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarAlexandre Courbot <acourbot@chromium.org>
Cr-Commit-Position: refs/heads/master@{#707704}
parent 105403f9
This diff is collapsed.
......@@ -86,7 +86,6 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
// Function signature for creating VideoDecoder.
using CreateVDFunc = std::unique_ptr<DecoderInterface> (*)(
scoped_refptr<base::SequencedTaskRunner>,
scoped_refptr<base::SequencedTaskRunner>,
base::RepeatingCallback<DmabufVideoFramePool*()>);
using GetCreateVDFunctionsCB =
......@@ -129,6 +128,12 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
void Destroy() override;
void DestroyTask();
void InitializeTask(const VideoDecoderConfig& config,
InitCB init_cb,
const OutputCB& output_cb);
void ResetTask(base::OnceClosure closure);
void DecodeTask(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb);
void CreateAndInitializeVD(base::queue<CreateVDFunc> create_vd_funcs,
VideoDecoderConfig config);
void OnInitializeDone(base::queue<CreateVDFunc> create_vd_funcs,
......@@ -140,10 +145,6 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
void OnFrameConverted(scoped_refptr<VideoFrame> frame);
void OnError(const std::string& msg);
static void OnFrameDecodedThunk(
scoped_refptr<base::SequencedTaskRunner> task_runner,
base::Optional<base::WeakPtr<VideoDecoderPipeline>> pipeline,
scoped_refptr<VideoFrame> frame);
void OnFrameDecoded(scoped_refptr<VideoFrame> frame);
// Call |client_flush_cb_| with |status| if we need.
......@@ -157,8 +158,8 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
SEQUENCE_CHECKER(client_sequence_checker_);
// The decoder task runner and its sequence checker. |decoder_| should post
// time-consuming task and call |frame_pool_|'s methods on this task runner.
// The decoder task runner and its sequence checker. Call |decoder_|'s,
// |frame_pool_|'s, and |frame_converter_|'s methods on this task runner.
const scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
SEQUENCE_CHECKER(decoder_sequence_checker_);
......@@ -190,9 +191,13 @@ class MEDIA_GPU_EXPORT VideoDecoderPipeline : public VideoDecoder {
// Set to true when any unexpected error occurs.
bool has_error_ = false;
base::WeakPtr<VideoDecoderPipeline> client_weak_this_;
base::WeakPtr<VideoDecoderPipeline> decoder_weak_this_;
// The weak pointer of this, bound to |client_task_runner_|.
base::WeakPtr<VideoDecoderPipeline> weak_this_;
base::WeakPtrFactory<VideoDecoderPipeline> weak_this_factory_{this};
base::WeakPtrFactory<VideoDecoderPipeline> client_weak_this_factory_{this};
// The weak pointer of this, bound to |decoder_task_runner_|.
base::WeakPtrFactory<VideoDecoderPipeline> decoder_weak_this_factory_{this};
};
} // namespace media
......
......@@ -42,10 +42,9 @@ constexpr uint32_t kSupportedInputFourccs[] = {
// static
std::unique_ptr<VideoDecoderPipeline::DecoderInterface>
V4L2SliceVideoDecoder::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool_cb) {
DCHECK(client_task_runner->RunsTasksInCurrentSequence());
DCHECK(decoder_task_runner->RunsTasksInCurrentSequence());
DCHECK(get_pool_cb);
scoped_refptr<V4L2Device> device = V4L2Device::Create();
......@@ -55,8 +54,7 @@ V4L2SliceVideoDecoder::Create(
}
return base::WrapUnique<VideoDecoderPipeline::DecoderInterface>(
new V4L2SliceVideoDecoder(std::move(client_task_runner),
std::move(decoder_task_runner),
new V4L2SliceVideoDecoder(std::move(decoder_task_runner),
std::move(device), std::move(get_pool_cb)));
}
......@@ -73,36 +71,20 @@ SupportedVideoDecoderConfigs V4L2SliceVideoDecoder::GetSupportedConfigs() {
}
V4L2SliceVideoDecoder::V4L2SliceVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
scoped_refptr<V4L2Device> device,
GetFramePoolCB get_pool_cb)
: device_(std::move(device)),
get_pool_cb_(std::move(get_pool_cb)),
client_task_runner_(std::move(client_task_runner)),
decoder_task_runner_(std::move(decoder_task_runner)),
weak_this_factory_(this) {
DETACH_FROM_SEQUENCE(client_sequence_checker_);
DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
VLOGF(2);
weak_this_ = weak_this_factory_.GetWeakPtr();
}
V4L2SliceVideoDecoder::~V4L2SliceVideoDecoder() {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
VLOGF(2);
// We need this event to synchronously destroy this instance.
// TODO(akahuang): Remove this event by manipulating this instance only on one
// sequence.
base::WaitableEvent event;
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&V4L2SliceVideoDecoder::DestroyTask, weak_this_,
base::Unretained(&event)));
event.Wait();
}
void V4L2SliceVideoDecoder::DestroyTask(base::WaitableEvent* event) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(2);
......@@ -124,34 +106,20 @@ void V4L2SliceVideoDecoder::DestroyTask(base::WaitableEvent* event) {
}
weak_this_factory_.InvalidateWeakPtrs();
event->Signal();
}
void V4L2SliceVideoDecoder::Initialize(const VideoDecoderConfig& config,
InitCB init_cb,
const OutputCB& output_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(config.IsValidConfig());
decoder_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&V4L2SliceVideoDecoder::InitializeTask, weak_this_, config,
std::move(init_cb), std::move(output_cb)));
}
void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
InitCB init_cb,
const OutputCB& output_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DCHECK(config.IsValidConfig());
DCHECK(state_ == State::kUninitialized || state_ == State::kDecoding);
DVLOGF(3);
// Reset V4L2 device and queue if reinitializing decoder.
if (state_ != State::kUninitialized) {
if (!StopStreamV4L2Queue()) {
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
......@@ -163,8 +131,7 @@ void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
device_ = V4L2Device::Create();
if (!device_) {
VLOGF(1) << "Failed to create V4L2 device.";
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
......@@ -185,8 +152,7 @@ void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
!device_->Open(V4L2Device::Type::kDecoder, input_format_fourcc)) {
VLOGF(1) << "Failed to open device for profile: " << profile
<< " fourcc: " << FourccToString(input_format_fourcc);
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
......@@ -196,8 +162,7 @@ void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
(caps.capabilities & kCapsRequired) != kCapsRequired) {
VLOGF(1) << "ioctl() failed: VIDIOC_QUERYCAP, "
<< "caps check failed: 0x" << std::hex << caps.capabilities;
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
......@@ -208,8 +173,7 @@ void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
output_queue_ = device_->GetQueue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
if (!input_queue_ || !output_queue_) {
VLOGF(1) << "Failed to create V4L2 queue.";
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
......@@ -217,46 +181,40 @@ void V4L2SliceVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
backend_ = std::make_unique<V4L2StatelessVideoDecoderBackend>(
this, device_, frame_pool_, profile, decoder_task_runner_);
if (!backend_->Initialize()) {
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
// Setup input format.
if (!SetupInputFormat(input_format_fourcc)) {
VLOGF(1) << "Failed to setup input format.";
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
if (!SetCodedSizeOnInputQueue(config.coded_size())) {
VLOGF(1) << "Failed to set coded size on input queue";
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
// Setup output format.
if (!SetupOutputFormat(config.coded_size(), config.visible_rect())) {
VLOGF(1) << "Failed to setup output format.";
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
if (input_queue_->AllocateBuffers(kNumInputBuffers, V4L2_MEMORY_MMAP) == 0) {
VLOGF(1) << "Failed to allocate input buffer.";
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
// Call init_cb
output_cb_ = output_cb;
SetState(State::kDecoding);
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), true));
std::move(init_cb).Run(true);
}
bool V4L2SliceVideoDecoder::SetupInputFormat(uint32_t input_format_fourcc) {
......@@ -377,15 +335,6 @@ V4L2SliceVideoDecoder::UpdateVideoFramePoolFormat(
}
void V4L2SliceVideoDecoder::Reset(base::OnceClosure closure) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(3);
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&V4L2SliceVideoDecoder::ResetTask, weak_this_,
std::move(closure)));
}
void V4L2SliceVideoDecoder::ResetTask(base::OnceClosure closure) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(3);
......@@ -404,22 +353,11 @@ void V4L2SliceVideoDecoder::ResetTask(base::OnceClosure closure) {
return;
}
client_task_runner_->PostTask(FROM_HERE, std::move(closure));
std::move(closure).Run();
}
void V4L2SliceVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
DecodeCB decode_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
decoder_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&V4L2SliceVideoDecoder::EnqueueDecodeTask, weak_this_,
std::move(buffer), std::move(decode_cb)));
}
void V4L2SliceVideoDecoder::EnqueueDecodeTask(
scoped_refptr<DecoderBuffer> buffer,
V4L2SliceVideoDecoder::DecodeCB decode_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DCHECK_NE(state_, State::kUninitialized);
......@@ -584,13 +522,6 @@ void V4L2SliceVideoDecoder::ServiceDeviceTask(bool /* event */) {
}
}
void V4L2SliceVideoDecoder::RunDecodeCB(DecodeCB cb, DecodeStatus status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(cb), status));
}
void V4L2SliceVideoDecoder::OutputFrame(scoped_refptr<VideoFrame> frame,
const gfx::Rect& visible_rect,
base::TimeDelta timestamp) {
......@@ -614,9 +545,7 @@ void V4L2SliceVideoDecoder::OutputFrame(scoped_refptr<VideoFrame> frame,
frame = std::move(wrapped_frame);
}
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(output_cb_, std::move(frame)));
output_cb_.Run(std::move(frame));
}
void V4L2SliceVideoDecoder::SetState(State new_state) {
......
......@@ -21,7 +21,6 @@
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "media/base/video_frame_layout.h"
......@@ -46,7 +45,6 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder
// ensure V4L2SliceVideoDecoder is available on the device. It will be
// determined in Initialize().
static std::unique_ptr<VideoDecoderPipeline::DecoderInterface> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool_cb);
......@@ -67,7 +65,6 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder
bool ChangeResolution(gfx::Size pic_size,
gfx::Rect visible_rect,
size_t num_output_frames) override;
void RunDecodeCB(DecodeCB cb, DecodeStatus status) override;
void OutputFrame(scoped_refptr<VideoFrame> frame,
const gfx::Rect& visible_rect,
base::TimeDelta timestamp) override;
......@@ -76,7 +73,6 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder
friend class V4L2SliceVideoDecoderTest;
V4L2SliceVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
scoped_refptr<V4L2Device> device,
GetFramePoolCB get_pool_cb);
......@@ -110,10 +106,6 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder
SEQUENCE_CHECKER(sequence_checker_);
};
// Initialize on decoder thread.
void InitializeTask(const VideoDecoderConfig& config,
InitCB init_cb,
const OutputCB& output_cb);
// Setup format for input queue.
bool SetupInputFormat(uint32_t input_format_fourcc);
......@@ -137,15 +129,6 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder
const gfx::Size& size,
const gfx::Rect& visible_rect);
// Destroy on decoder thread.
void DestroyTask(base::WaitableEvent* event);
// Reset on decoder thread.
void ResetTask(base::OnceClosure closure);
// Enqueue |buffer| to be decoded. |decode_cb| will be called once |buffer|
// is no longer used.
void EnqueueDecodeTask(scoped_refptr<DecoderBuffer> buffer,
V4L2SliceVideoDecoder::DecodeCB decode_cb);
// Start streaming V4L2 input and output queues. Attempt to start
// |device_poll_thread_| before starting streaming.
bool StartStreamV4L2Queue();
......@@ -168,11 +151,8 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder
GetFramePoolCB get_pool_cb_;
DmabufVideoFramePool* frame_pool_ = nullptr;
// Client task runner. All public methods of
// Decoder task runner. All public methods of
// VideoDecoderPipeline::DecoderInterface are executed at this task runner.
const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
// Thread to communicate with the device on. Most of internal methods and data
// members are manipulated on this thread.
const scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
// State of the instance.
......@@ -192,7 +172,6 @@ class MEDIA_GPU_EXPORT V4L2SliceVideoDecoder
BitstreamIdGenerator bitstream_id_generator_;
SEQUENCE_CHECKER(client_sequence_checker_);
SEQUENCE_CHECKER(decoder_sequence_checker_);
// |weak_this_| must be dereferenced and invalidated on
......
......@@ -51,9 +51,6 @@ class V4L2VideoDecoderBackend {
virtual bool ChangeResolution(gfx::Size pic_size,
gfx::Rect visible_rect,
size_t num_output_frames) = 0;
// Call the decode callback and count the number of pending callbacks.
virtual void RunDecodeCB(VideoDecoder::DecodeCB cb,
DecodeStatus status) = 0;
// Convert the frame and call the output callback.
virtual void OutputFrame(scoped_refptr<VideoFrame> frame,
const gfx::Rect& visible_rect,
......@@ -65,8 +62,7 @@ class V4L2VideoDecoderBackend {
virtual bool Initialize() = 0;
// Schedule |buffer| to be processed, with bitstream ID |bitstream_id|.
// The backend must call V4L2SliceVideoDecoder::RunDecodeCB() with |decode_cb|
// as argument once the buffer is not used anymore.
// The backend must call |decode_cb| once the buffer is not used anymore.
virtual void EnqueueDecodeTask(scoped_refptr<DecoderBuffer> buffer,
VideoDecoder::DecodeCB decode_cb,
int32_t bitstream_id) = 0;
......
......@@ -396,8 +396,7 @@ bool V4L2StatelessVideoDecoderBackend::PumpDecodeTask() {
// Current decode request is finished processing.
if (current_decode_request_) {
DCHECK(current_decode_request_->decode_cb);
client_->RunDecodeCB(std::move(current_decode_request_->decode_cb),
DecodeStatus::OK);
std::move(current_decode_request_->decode_cb).Run(DecodeStatus::OK);
current_decode_request_ = base::nullopt;
}
......@@ -469,7 +468,7 @@ void V4L2StatelessVideoDecoderBackend::PumpOutputSurfaces() {
case OutputRequest::kFlushFence:
DCHECK(output_request_queue_.empty());
DVLOGF(2) << "Flush finished.";
client_->RunDecodeCB(std::move(flush_cb_), DecodeStatus::OK);
std::move(flush_cb_).Run(DecodeStatus::OK);
resume_decode = true;
break;
......@@ -539,18 +538,18 @@ void V4L2StatelessVideoDecoderBackend::ClearPendingRequests(
output_request_queue_.pop();
if (flush_cb_)
client_->RunDecodeCB(std::move(flush_cb_), status);
std::move(flush_cb_).Run(status);
// Clear current_decode_request_ and decode_request_queue_.
if (current_decode_request_) {
client_->RunDecodeCB(std::move(current_decode_request_->decode_cb), status);
std::move(current_decode_request_->decode_cb).Run(status);
current_decode_request_ = base::nullopt;
}
while (!decode_request_queue_.empty()) {
auto request = std::move(decode_request_queue_.front());
decode_request_queue_.pop();
client_->RunDecodeCB(std::move(request.decode_cb), status);
std::move(request.decode_cb).Run(status);
}
}
......
......@@ -65,12 +65,10 @@ VaapiVideoDecoder::DecodeTask::DecodeTask(DecodeTask&&) = default;
// static
std::unique_ptr<VideoDecoderPipeline::DecoderInterface>
VaapiVideoDecoder::Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool_cb) {
return base::WrapUnique<VideoDecoderPipeline::DecoderInterface>(
new VaapiVideoDecoder(std::move(client_task_runner),
std::move(decoder_task_runner),
new VaapiVideoDecoder(std::move(decoder_task_runner),
std::move(get_pool_cb)));
}
......@@ -81,37 +79,21 @@ SupportedVideoDecoderConfigs VaapiVideoDecoder::GetSupportedConfigs() {
}
VaapiVideoDecoder::VaapiVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool_cb)
: get_pool_cb_(std::move(get_pool_cb)),
buffer_id_to_timestamp_(kTimestampCacheSize),
client_task_runner_(std::move(client_task_runner)),
decoder_task_runner_(std::move(decoder_task_runner)),
weak_this_factory_(this) {
DETACH_FROM_SEQUENCE(decoder_sequence_checker_);
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
VLOGF(2);
weak_this_ = weak_this_factory_.GetWeakPtr();
}
VaapiVideoDecoder::~VaapiVideoDecoder() {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
VLOGF(2);
// We need this event to synchronously destroy this instance.
// TODO(akahuang): Remove this event by manipulating this instance only on one
// sequence.
base::WaitableEvent event;
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::DestroyTask, weak_this_,
base::Unretained(&event)));
event.Wait();
}
void VaapiVideoDecoder::DestroyTask(base::WaitableEvent* event) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(2);
VLOGF(2);
// Abort all currently scheduled decode tasks.
ClearDecodeTaskQueue(DecodeStatus::ABORTED);
......@@ -122,34 +104,20 @@ void VaapiVideoDecoder::DestroyTask(base::WaitableEvent* event) {
}
weak_this_factory_.InvalidateWeakPtrs();
event->Signal();
}
void VaapiVideoDecoder::Initialize(const VideoDecoderConfig& config,
InitCB init_cb,
const OutputCB& output_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DCHECK(config.IsValidConfig());
decoder_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VaapiVideoDecoder::InitializeTask, weak_this_, config,
std::move(init_cb), std::move(output_cb)));
}
void VaapiVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
InitCB init_cb,
OutputCB output_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DCHECK(config.IsValidConfig());
DCHECK(state_ == State::kUninitialized || state_ == State::kWaitingForInput);
DVLOGF(3);
// Reinitializing the decoder is allowed if there are no pending decodes.
if (current_decode_task_ || !decode_task_queue_.empty()) {
VLOGF(1) << "Don't call Initialize() while there are pending decode tasks";
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
......@@ -175,8 +143,7 @@ void VaapiVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
if (!vaapi_wrapper_.get()) {
VLOGF(1) << "Failed initializing VAAPI for profile "
<< GetProfileName(profile);
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
......@@ -194,8 +161,7 @@ void VaapiVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
config.color_space_info()));
} else {
VLOGF(1) << "Unsupported profile " << GetProfileName(profile);
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), false));
std::move(init_cb).Run(false);
return;
}
......@@ -209,28 +175,18 @@ void VaapiVideoDecoder::InitializeTask(const VideoDecoderConfig& config,
SetState(State::kWaitingForInput);
// Notify client initialization was successful.
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(init_cb), true));
std::move(init_cb).Run(true);
}
void VaapiVideoDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
DecodeCB decode_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::QueueDecodeTask, weak_this_,
std::move(buffer), std::move(decode_cb)));
}
void VaapiVideoDecoder::QueueDecodeTask(scoped_refptr<DecoderBuffer> buffer,
DecodeCB decode_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(4) << "Queuing input buffer, id: " << next_buffer_id_ << ", size: "
<< (buffer->end_of_stream() ? 0 : buffer->data_size());
// If we're in the error state, immediately fail the decode task.
if (state_ == State::kError) {
RunDecodeCB(std::move(decode_cb), DecodeStatus::DECODE_ERROR);
std::move(decode_cb).Run(DecodeStatus::DECODE_ERROR);
return;
}
......@@ -291,8 +247,7 @@ void VaapiVideoDecoder::HandleDecodeTask() {
case AcceleratedVideoDecoder::kRanOutOfStreamData:
// Decoding was successful, notify client and try to schedule the next
// task. Switch to the idle state if we ran out of buffers to decode.
RunDecodeCB(std::move(current_decode_task_->decode_done_cb_),
DecodeStatus::OK);
std::move(current_decode_task_->decode_done_cb_).Run(DecodeStatus::OK);
current_decode_task_ = base::nullopt;
if (!decode_task_queue_.empty()) {
ScheduleNextDecodeTask();
......@@ -330,12 +285,12 @@ void VaapiVideoDecoder::ClearDecodeTaskQueue(DecodeStatus status) {
DVLOGF(4);
if (current_decode_task_) {
RunDecodeCB(std::move(current_decode_task_->decode_done_cb_), status);
std::move(current_decode_task_->decode_done_cb_).Run(status);
current_decode_task_ = base::nullopt;
}
while (!decode_task_queue_.empty()) {
RunDecodeCB(std::move(decode_task_queue_.front().decode_done_cb_), status);
std::move(decode_task_queue_.front().decode_done_cb_).Run(status);
decode_task_queue_.pop();
}
}
......@@ -439,8 +394,7 @@ void VaapiVideoDecoder::OutputFrameTask(scoped_refptr<VideoFrame> video_frame,
video_frame = std::move(wrapped_frame);
}
client_task_runner_->PostTask(
FROM_HERE, base::BindOnce(output_cb_, std::move(video_frame)));
output_cb_.Run(std::move(video_frame));
}
void VaapiVideoDecoder::ChangeFrameResolutionTask() {
......@@ -522,8 +476,7 @@ void VaapiVideoDecoder::FlushTask() {
DCHECK(output_frames_.empty());
// Notify the client flushing is done.
RunDecodeCB(std::move(current_decode_task_->decode_done_cb_),
DecodeStatus::OK);
std::move(current_decode_task_->decode_done_cb_).Run(DecodeStatus::OK);
current_decode_task_ = base::nullopt;
// Wait for new decodes, no decode tasks should be queued while flushing.
......@@ -531,21 +484,12 @@ void VaapiVideoDecoder::FlushTask() {
}
void VaapiVideoDecoder::Reset(base::OnceClosure reset_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
DVLOGF(2);
decoder_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VaapiVideoDecoder::ResetTask, weak_this_,
std::move(reset_cb)));
}
void VaapiVideoDecoder::ResetTask(base::OnceClosure reset_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(2);
// If we encountered an error, skip reset and notify client.
if (state_ == State::kError) {
client_task_runner_->PostTask(FROM_HERE, std::move(reset_cb));
std::move(reset_cb).Run();
return;
}
......@@ -568,17 +512,10 @@ void VaapiVideoDecoder::ResetDoneTask(base::OnceClosure reset_cb) {
DCHECK(decode_task_queue_.empty());
DVLOGF(2);
client_task_runner_->PostTask(FROM_HERE, std::move(reset_cb));
std::move(reset_cb).Run();
SetState(State::kWaitingForInput);
}
void VaapiVideoDecoder::RunDecodeCB(DecodeCB cb, DecodeStatus status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
client_task_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(cb), status));
}
void VaapiVideoDecoder::SetState(State state) {
DCHECK_CALLED_ON_VALID_SEQUENCE(decoder_sequence_checker_);
DVLOGF(4) << static_cast<int>(state)
......
......@@ -20,7 +20,6 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/sequence_checker.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "media/base/video_codecs.h"
......@@ -45,7 +44,6 @@ class VaapiVideoDecoder : public VideoDecoderPipeline::DecoderInterface,
using GetFramePoolCB = base::RepeatingCallback<DmabufVideoFramePool*()>;
static std::unique_ptr<VideoDecoderPipeline::DecoderInterface> Create(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool);
......@@ -90,21 +88,10 @@ class VaapiVideoDecoder : public VideoDecoderPipeline::DecoderInterface,
};
VaapiVideoDecoder(
scoped_refptr<base::SequencedTaskRunner> client_task_runner,
scoped_refptr<base::SequencedTaskRunner> decoder_task_runner,
GetFramePoolCB get_pool);
~VaapiVideoDecoder() override;
// Initialize the VAAPI video decoder on the decoder thread.
void InitializeTask(const VideoDecoderConfig& config,
InitCB init_cb,
OutputCB output_cb);
// Destroy the VAAPI video decoder on the decoder thread.
void DestroyTask(base::WaitableEvent* event);
// Queue a decode task on the decoder thread. If the decoder is currently
// waiting for input buffers decoding will be started.
void QueueDecodeTask(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb);
// Schedule the next decode task in the queue to be executed.
void ScheduleNextDecodeTask();
// Try to decode a single input buffer on the decoder thread.
......@@ -138,15 +125,9 @@ class VaapiVideoDecoder : public VideoDecoderPipeline::DecoderInterface,
// tasks have been executed and all frames have been output.
void FlushTask();
// Reset the decoder on the decoder thread. This will abort any pending decode
// task. The |reset_cb| will be passed to ResetDoneTask() and called when
// resetting has completed.
void ResetTask(base::OnceClosure reset_cb);
// Called on the decoder thread once resetting is done. Executes |reset_cb|.
// Called when resetting the decoder is done, executes |reset_cb|.
void ResetDoneTask(base::OnceClosure reset_cb);
// Called on decoder thread to schedule |decode_cb| on the client task runner.
void RunDecodeCB(DecodeCB decode_cb, DecodeStatus status);
// Change the current |state_| to the specified |state| on the decoder thread.
void SetState(State state);
......@@ -188,10 +169,8 @@ class VaapiVideoDecoder : public VideoDecoderPipeline::DecoderInterface,
std::unique_ptr<AcceleratedVideoDecoder> decoder_;
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
const scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
const scoped_refptr<base::SequencedTaskRunner> decoder_task_runner_;
SEQUENCE_CHECKER(client_sequence_checker_);
SEQUENCE_CHECKER(decoder_sequence_checker_);
base::WeakPtr<VaapiVideoDecoder> weak_this_;
......
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