1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_DECODER_BROKER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_DECODER_BROKER_H_
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "media/base/decoder_status.h"
#include "media/base/video_decoder.h"
#include "media/base/video_frame.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webcodecs/hardware_preference.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace base {
class SequencedTaskRunner;
} // namespace base
namespace blink {
// Implementation detail of VideoDecoderBroker. Helps safely perform decoder
// tasks on the media thread.
class MediaVideoTaskWrapper;
// Client interface for MediaVideoTaskWrapper. Implementation detail of
// VideoDecoderBroker, but we need to define it here to implement it below.
//
// This avoids having pass-through callbacks from main->media task sequence,
// which is unsafe because the public callers of broker APIs may be broken if
// their callback is destructed on another thread.
//
// An int "cb_id" is used for those that are traditionally OnceCallbacks to
// lookup the correct public callback.
class CrossThreadVideoDecoderClient {
public:
struct DecoderDetails {
media::VideoDecoderType decoder_id;
bool is_platform_decoder;
bool needs_bitstream_conversion;
int max_decode_requests;
};
virtual void OnInitialize(media::DecoderStatus status,
std::optional<DecoderDetails> details) = 0;
virtual void OnDecodeDone(int cb_id, media::DecoderStatus status) = 0;
virtual void OnDecodeOutput(scoped_refptr<media::VideoFrame> frame,
bool can_read_without_stalling) = 0;
virtual void OnReset(int cb_id) = 0;
};
// This class brokers the connection between WebCodecs and an underlying
// media::VideoDecoder. It abstracts away details of construction and selection
// of the media/ decoder. It also handles thread-hopping as required by
// underlying APIS.
//
// A new underlying decoder is selected anytime Initialize() is called.
// TODO(chcunningham): Elide re-selection if the config has not significantly
// changed.
//
// All API calls and callbacks must occur on the main thread.
class MODULES_EXPORT VideoDecoderBroker : public media::VideoDecoder,
public CrossThreadVideoDecoderClient {
public:
// |gpu_factories| may be null when GPU accelerated decoding is not available.
explicit VideoDecoderBroker(
ExecutionContext& execution_context,
media::GpuVideoAcceleratorFactories* gpu_factories,
media::MediaLog* media_log);
~VideoDecoderBroker() override;
// Disallow copy and assign.
VideoDecoderBroker(const VideoDecoderBroker&) = delete;
VideoDecoderBroker& operator=(const VideoDecoderBroker&) = delete;
// VideoDecoder implementation.
media::VideoDecoderType GetDecoderType() const override;
bool IsPlatformDecoder() const override;
void Initialize(const media::VideoDecoderConfig& config,
bool low_delay,
media::CdmContext* cdm_context,
InitCB init_cb,
const OutputCB& output_cb,
const media::WaitingCB& waiting_cb) override;
void Decode(scoped_refptr<media::DecoderBuffer> buffer,
DecodeCB decode_cb) override;
void Reset(base::OnceClosure reset_cb) override;
bool NeedsBitstreamConversion() const override;
bool CanReadWithoutStalling() const override;
int GetMaxDecodeRequests() const override;
void SetHardwarePreference(HardwarePreference hardware_preference);
private:
// Creates a new (incremented) callback ID from |last_callback_id_| for
// mapping in |pending_decode_cb_map_|.
int CreateCallbackId();
// MediaVideoTaskWrapper::CrossThreadVideoDecoderClient
void OnInitialize(media::DecoderStatus status,
std::optional<DecoderDetails> details) override;
void OnDecodeDone(int cb_id, media::DecoderStatus status) override;
void OnDecodeOutput(scoped_refptr<media::VideoFrame> frame,
bool can_read_without_stalling) override;
void OnReset(int cb_id) override;
// When media::GpuVideoAcceleratorFactories is provided, its API requires
// that we use its TaskRunner (the media thread). When not provided, this task
// runner will still be used to reduce contention on the main thread.
// TODO(chcunningham): Try to eliminate the Post(). Most of the
// underlying::VideoDecoders already offload their work, so this just adds
// overhead.
scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
// Owner of state and methods to be used on media_task_runner_;
std::unique_ptr<MediaVideoTaskWrapper> media_tasks_;
// Wrapper state for GetDecoderType(), IsPlatformDecoder() and others.
std::optional<DecoderDetails> decoder_details_;
// Set to match the underlying decoder's answer at every OnDecodeOutput().
bool can_read_without_stalling_ = true;
// Holds the last key for callbacks in the map below. Incremented for each
// usage via CreateCallbackId().
uint32_t last_callback_id_ = 0;
// Maps a callback ID to pending Decode(). See CrossThreadVideoDecoderClient.
HashMap<int, DecodeCB> pending_decode_cb_map_;
// Maps a callback ID to pending Reset(). See CrossThreadVideoDecoderClient.
HashMap<int, base::OnceClosure> pending_reset_cb_map_;
// Pending InitCB saved from the last call to Initialize();
InitCB init_cb_;
// OutputCB saved from last call to Initialize().
OutputCB output_cb_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<VideoDecoderBroker> weak_factory_{this};
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_DECODER_BROKER_H_
|