blob: 94ca0cb322290f299043116ad77523ef50a485bc [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_GPU_IPC_SERVICE_VDA_VIDEO_DECODER_H_
#define MEDIA_GPU_IPC_SERVICE_VDA_VIDEO_DECODER_H_
#include <stdint.h>
#include <map>
#include <memory>
#include "base/callback_forward.h"
#include "base/containers/mru_cache.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "media/base/video_decoder.h"
#include "media/gpu/command_buffer_helper.h"
#include "media/gpu/ipc/service/picture_buffer_manager.h"
#include "media/video/video_decode_accelerator.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_bindings.h"
namespace gpu {
class CommandBufferStub;
} // namespace gpu
namespace media {
// Implements the VideoDecoder interface backed by a VideoDecodeAccelerator.
// This class expects to run in the GPU process via MojoVideoDecoder.
class VdaVideoDecoder : public VideoDecoder,
public VideoDecodeAccelerator::Client {
public:
using GetStubCB = base::RepeatingCallback<gpu::CommandBufferStub*()>;
using AllocateShmCB =
base::RepeatingCallback<std::unique_ptr<base::SharedMemory>(size_t)>;
using CreatePictureBufferManagerCB =
base::OnceCallback<scoped_refptr<PictureBufferManager>(
PictureBufferManager::ReusePictureBufferCB)>;
using CreateCommandBufferHelperCB =
base::OnceCallback<scoped_refptr<CommandBufferHelper>()>;
using CreateVdaCB =
base::OnceCallback<std::unique_ptr<VideoDecodeAccelerator>(
scoped_refptr<CommandBufferHelper>)>;
using GetVdaCapabilitiesCB =
base::RepeatingCallback<VideoDecodeAccelerator::Capabilities()>;
// Creates a VdaVideoDecoder. The returned unique_ptr can be safely upcast to
// unique_ptr<VideoDecoder>.
//
// |get_stub_cb|: Callback to retrieve the CommandBufferStub that should be
// used for allocating textures and mailboxes. This callback will be
// called on the GPU thread.
//
// See VdaVideoDecoder() for other arguments.
static std::unique_ptr<VdaVideoDecoder, std::default_delete<VideoDecoder>>
Create(scoped_refptr<base::SingleThreadTaskRunner> parent_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
GetStubCB get_stub_cb);
// |parent_task_runner|: Task runner that |this| should operate on. All
// methods must be called on |parent_task_runner| (should be the Mojo
// MediaService task runner).
// |gpu_task_runner|: Task runner that |get_stub_cb| and GPU command buffer
// methods must be called on (should be the GPU main thread).
// |create_picture_buffer_manager_cb|: PictureBufferManager factory.
// |create_command_buffer_helper_cb|: CommandBufferHelper factory.
// |create_vda_cb|: VideoDecodeAccelerator factory.
// |get_vda_capabilities_cb|: VideDecodeAccelerator::Capabilities provider.
VdaVideoDecoder(
scoped_refptr<base::SingleThreadTaskRunner> parent_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner,
CreatePictureBufferManagerCB create_picture_buffer_manager_cb,
CreateCommandBufferHelperCB create_command_buffer_helper_cb,
CreateVdaCB create_vda_cb,
GetVdaCapabilitiesCB get_vda_capabilities_cb);
// media::VideoDecoder implementation.
std::string GetDisplayName() const override;
void Initialize(
const VideoDecoderConfig& config,
bool low_delay,
CdmContext* cdm_context,
const InitCB& init_cb,
const OutputCB& output_cb,
const WaitingForDecryptionKeyCB& waiting_for_decryption_key_cb) override;
void Decode(scoped_refptr<DecoderBuffer> buffer,
const DecodeCB& decode_cb) override;
void Reset(const base::RepeatingClosure& reset_cb) override;
bool NeedsBitstreamConversion() const override;
bool CanReadWithoutStalling() const override;
int GetMaxDecodeRequests() const override;
private:
void Destroy() override;
protected:
// Owners should call Destroy(). This is automatic via
// std::default_delete<media::VideoDecoder> when held by a
// std::unique_ptr<media::VideoDecoder>.
~VdaVideoDecoder() override;
private:
// media::VideoDecodeAccelerator::Client implementation.
void NotifyInitializationComplete(bool success) override;
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
VideoPixelFormat format,
uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override;
void DismissPictureBuffer(int32_t picture_buffer_id) override;
void PictureReady(const Picture& picture) override;
void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) override;
void NotifyFlushDone() override;
void NotifyResetDone() override;
void NotifyError(VideoDecodeAccelerator::Error error) override;
// Tasks and thread hopping.
void DestroyOnGpuThread();
void InitializeOnGpuThread();
void InitializeDone(bool status);
void DecodeOnGpuThread(BitstreamBuffer bitstream_buffer);
void PictureReadyOnParentThread(Picture picture);
void NotifyEndOfBitstreamBufferOnParentThread(int32_t bitstream_buffer_id);
void NotifyFlushDoneOnParentThread();
void NotifyResetDoneOnParentThread();
void ProvidePictureBuffersAsync(uint32_t count,
VideoPixelFormat pixel_format,
uint32_t planes,
gfx::Size texture_size,
GLenum texture_target);
void ReusePictureBuffer(int32_t picture_buffer_id);
// Error handling.
void EnterErrorState();
void DestroyCallbacks();
//
// Constant after construction, safe to read on any thread.
//
scoped_refptr<base::SingleThreadTaskRunner> parent_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
scoped_refptr<CommandBufferHelper> command_buffer_helper_;
scoped_refptr<PictureBufferManager> picture_buffer_manager_;
CreateCommandBufferHelperCB create_command_buffer_helper_cb_;
CreateVdaCB create_vda_cb_;
GetVdaCapabilitiesCB get_vda_capabilities_cb_;
//
// Parent thread state.
//
bool has_error_ = false;
InitCB init_cb_;
OutputCB output_cb_;
DecodeCB flush_cb_;
base::RepeatingClosure reset_cb_;
int32_t bitstream_buffer_id_ = 0;
std::map<int32_t, DecodeCB> decode_cbs_;
// Records timestamps so that they can be mapped to output pictures. Must be
// large enough to account for any amount of frame reordering.
base::MRUCache<int32_t, base::TimeDelta> timestamps_;
//
// GPU thread state.
//
std::unique_ptr<VideoDecodeAccelerator> vda_;
//
// Shared state.
//
VideoDecoderConfig config_;
//
// Weak pointers, prefixed by bound thread.
//
// |gpu_weak_vda_| is invalidated when the VDA has notified about an error, or
// has been destroyed. It is not valid to call VDA methods in those cases.
base::WeakPtr<VideoDecodeAccelerator> gpu_weak_vda_;
std::unique_ptr<base::WeakPtrFactory<VideoDecodeAccelerator>>
gpu_weak_vda_factory_;
// |gpu_weak_this_| is never explicitly invalidated.
// |parent_weak_this_| is invalidated when the client calls Destroy(), and
// indicates that we should not make any new client callbacks.
base::WeakPtr<VdaVideoDecoder> gpu_weak_this_;
base::WeakPtr<VdaVideoDecoder> parent_weak_this_;
base::WeakPtrFactory<VdaVideoDecoder> gpu_weak_this_factory_;
base::WeakPtrFactory<VdaVideoDecoder> parent_weak_this_factory_;
DISALLOW_COPY_AND_ASSIGN(VdaVideoDecoder);
};
} // namespace media
#endif // MEDIA_GPU_IPC_SERVICE_VDA_VIDEO_DECODER_H_