Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / offloading_video_decoder.h
1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef MEDIA_FILTERS_OFFLOADING_VIDEO_DECODER_H_
6 #define MEDIA_FILTERS_OFFLOADING_VIDEO_DECODER_H_
7
8 #include "base/callback_forward.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/sequence_checker.h"
11 #include "media/base/video_codecs.h"
12 #include "media/base/video_decoder.h"
13 #include "media/base/video_decoder_config.h"
14
15 namespace base {
16 class SequencedTaskRunner;
17 }  // namespace base
18
19 namespace media {
20 class CancellationHelper;
21
22 // OffloadableVideoDecoder implementations must have synchronous execution of
23 // Reset() and Decode() (true for all current software decoders); this allows
24 // for serializing these operations on the offloading sequence. With
25 // serializing, multiple Decode() events can be queued on the offload thread,
26 // and Reset() does not need to wait for |reset_cb| to return.
27 class MEDIA_EXPORT OffloadableVideoDecoder : public VideoDecoder {
28  public:
29   enum class OffloadState {
30     kOffloaded,  // Indicates the VideoDecoder is being used with
31                  // OffloadingVideoDecoder and that callbacks provided to
32                  // VideoDecoder methods should not be bound to the current
33                  // loop.
34
35     kNormal,  // Indicates the VideoDecoder is being used as a normal
36               // VideoDecoder, meaning callbacks should always be asynchronous.
37   };
38
39   ~OffloadableVideoDecoder() override {}
40
41   // Called by the OffloadingVideoDecoder when closing the decoder and switching
42   // task runners. Will be called on the task runner that Initialize() was
43   // called on. Upon completion of this method implementing decoders must be
44   // ready to be Initialized() on another thread.
45   virtual void Detach() = 0;
46 };
47
48 // Wrapper for OffloadableVideoDecoder implementations that runs the wrapped
49 // decoder on a task pool other than the caller's thread.
50 //
51 // Offloading allows us to avoid blocking the media sequence for Decode() when
52 // it's known that decoding may take a long time; e.g., high-resolution VP9
53 // decodes may occasionally take upwards of > 100ms per frame, which is enough
54 // to exhaust the audio buffer and lead to underflow in some circumstances.
55 //
56 // Offloading also allows better pipelining of Decode() calls. The normal decode
57 // sequence is Decode(buffer) -> DecodeComplete() -> WaitFor(buffer)-> (repeat);
58 // this sequence generally involves thread hops as well. When offloading we can
59 // take advantage of the serialization of operations on the offloading sequence
60 // to make this Decode(buffer) -> DecodeComplete() -> Decode(buffer) by queuing
61 // the next Decode(buffer) before the previous one completes.
62 //
63 // I.e., we are no longer wasting cycles waiting for the recipient of the
64 // decoded frame to acknowledge that receipt, request the next muxed buffer, and
65 // then queue the next decode. Those operations now happen in parallel with the
66 // decoding of the previous buffer on the offloading sequence. Improving the
67 // total throughput that a decode can achieve.
68 //
69 // E.g., without parallel offloading, over 4000 frames, a 4K60 VP9 clip spent
70 // ~11.7 seconds of aggregate time just waiting for frames. With parallel
71 // offloading the same clip spent only ~3.4 seconds.
72 //
73 // Optionally decoders which are aware of the wrapping may choose to not rebind
74 // callbacks to the offloaded thread since they will already be bound by the
75 // OffloadingVideoDecoder; this simply avoids extra hops for completed tasks.
76 class MEDIA_EXPORT OffloadingVideoDecoder : public VideoDecoder {
77  public:
78   // Offloads |decoder| for VideoDecoderConfigs provided to Initialize() using
79   // |supported_codecs| with a coded width >= |min_offloading_width|.
80   //
81   // E.g. if a width of 1024 is specified, and VideoDecoderConfig has a coded
82   // size of 1280x720 we will use offloading. Conversely if the width was
83   // 640x480, we would not use offloading.
84   OffloadingVideoDecoder(int min_offloading_width,
85                          std::vector<VideoCodec> supported_codecs,
86                          std::unique_ptr<OffloadableVideoDecoder> decoder);
87
88   OffloadingVideoDecoder(const OffloadingVideoDecoder&) = delete;
89   OffloadingVideoDecoder& operator=(const OffloadingVideoDecoder&) = delete;
90
91   ~OffloadingVideoDecoder() override;
92
93   // VideoDecoder implementation.
94   VideoDecoderType GetDecoderType() const override;
95   void Initialize(const VideoDecoderConfig& config,
96                   bool low_delay,
97                   CdmContext* cdm_context,
98                   InitCB init_cb,
99                   const OutputCB& output_cb,
100                   const WaitingCB& waiting_cb) override;
101   void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
102   void Reset(base::OnceClosure reset_cb) override;
103   int GetMaxDecodeRequests() const override;
104
105  private:
106   // VideoDecoderConfigs given to Initialize() with a coded size that has width
107   // greater than or equal to this value will be offloaded.
108   const int min_offloading_width_;
109
110   // Codecs supported for offloading.
111   const std::vector<VideoCodec> supported_codecs_;
112
113   // Indicates if Initialize() has been called.
114   bool initialized_ = false;
115
116   SEQUENCE_CHECKER(sequence_checker_);
117
118   // A helper class for managing Decode() and Reset() calls to the offloaded
119   // decoder; it owns the given OffloadableVideoDecoder and is always destructed
120   // on |offload_task_runner_| when used.
121   std::unique_ptr<CancellationHelper> helper_;
122
123   // High resolution decodes may block the media thread for too long, in such
124   // cases offload the decoding to a task pool.
125   scoped_refptr<base::SequencedTaskRunner> offload_task_runner_;
126
127   // NOTE: Weak pointers must be invalidated before all other member variables.
128   base::WeakPtrFactory<OffloadingVideoDecoder> weak_factory_{this};
129 };
130
131 }  // namespace media
132
133 #endif  // MEDIA_FILTERS_OFFLOADING_VIDEO_DECODER_H_