xref: /aosp_15_r20/external/libgav1/src/decoder_impl.h (revision 095378508e87ed692bf8dfeb34008b65b3735891)
1*09537850SAkhilesh Sanikop /*
2*09537850SAkhilesh Sanikop  * Copyright 2019 The libgav1 Authors
3*09537850SAkhilesh Sanikop  *
4*09537850SAkhilesh Sanikop  * Licensed under the Apache License, Version 2.0 (the "License");
5*09537850SAkhilesh Sanikop  * you may not use this file except in compliance with the License.
6*09537850SAkhilesh Sanikop  * You may obtain a copy of the License at
7*09537850SAkhilesh Sanikop  *
8*09537850SAkhilesh Sanikop  *      http://www.apache.org/licenses/LICENSE-2.0
9*09537850SAkhilesh Sanikop  *
10*09537850SAkhilesh Sanikop  * Unless required by applicable law or agreed to in writing, software
11*09537850SAkhilesh Sanikop  * distributed under the License is distributed on an "AS IS" BASIS,
12*09537850SAkhilesh Sanikop  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*09537850SAkhilesh Sanikop  * See the License for the specific language governing permissions and
14*09537850SAkhilesh Sanikop  * limitations under the License.
15*09537850SAkhilesh Sanikop  */
16*09537850SAkhilesh Sanikop 
17*09537850SAkhilesh Sanikop #ifndef LIBGAV1_SRC_DECODER_IMPL_H_
18*09537850SAkhilesh Sanikop #define LIBGAV1_SRC_DECODER_IMPL_H_
19*09537850SAkhilesh Sanikop 
20*09537850SAkhilesh Sanikop #include <array>
21*09537850SAkhilesh Sanikop #include <condition_variable>  // NOLINT (unapproved c++11 header)
22*09537850SAkhilesh Sanikop #include <cstddef>
23*09537850SAkhilesh Sanikop #include <cstdint>
24*09537850SAkhilesh Sanikop #include <memory>
25*09537850SAkhilesh Sanikop #include <mutex>  // NOLINT (unapproved c++11 header)
26*09537850SAkhilesh Sanikop 
27*09537850SAkhilesh Sanikop #include "src/buffer_pool.h"
28*09537850SAkhilesh Sanikop #include "src/decoder_state.h"
29*09537850SAkhilesh Sanikop #include "src/dsp/constants.h"
30*09537850SAkhilesh Sanikop #include "src/frame_scratch_buffer.h"
31*09537850SAkhilesh Sanikop #include "src/gav1/decoder_buffer.h"
32*09537850SAkhilesh Sanikop #include "src/gav1/decoder_settings.h"
33*09537850SAkhilesh Sanikop #include "src/gav1/status_code.h"
34*09537850SAkhilesh Sanikop #include "src/obu_parser.h"
35*09537850SAkhilesh Sanikop #include "src/quantizer.h"
36*09537850SAkhilesh Sanikop #include "src/residual_buffer_pool.h"
37*09537850SAkhilesh Sanikop #include "src/symbol_decoder_context.h"
38*09537850SAkhilesh Sanikop #include "src/tile.h"
39*09537850SAkhilesh Sanikop #include "src/utils/array_2d.h"
40*09537850SAkhilesh Sanikop #include "src/utils/block_parameters_holder.h"
41*09537850SAkhilesh Sanikop #include "src/utils/compiler_attributes.h"
42*09537850SAkhilesh Sanikop #include "src/utils/constants.h"
43*09537850SAkhilesh Sanikop #include "src/utils/memory.h"
44*09537850SAkhilesh Sanikop #include "src/utils/queue.h"
45*09537850SAkhilesh Sanikop #include "src/utils/segmentation_map.h"
46*09537850SAkhilesh Sanikop #include "src/utils/types.h"
47*09537850SAkhilesh Sanikop 
48*09537850SAkhilesh Sanikop namespace libgav1 {
49*09537850SAkhilesh Sanikop 
50*09537850SAkhilesh Sanikop struct TemporalUnit;
51*09537850SAkhilesh Sanikop 
52*09537850SAkhilesh Sanikop struct EncodedFrame {
EncodedFrameEncodedFrame53*09537850SAkhilesh Sanikop   EncodedFrame(ObuParser* const obu, const DecoderState& state,
54*09537850SAkhilesh Sanikop                const RefCountedBufferPtr& frame, int position_in_temporal_unit)
55*09537850SAkhilesh Sanikop       : sequence_header(obu->sequence_header()),
56*09537850SAkhilesh Sanikop         frame_header(obu->frame_header()),
57*09537850SAkhilesh Sanikop         state(state),
58*09537850SAkhilesh Sanikop         temporal_unit(nullptr),
59*09537850SAkhilesh Sanikop         frame(frame),
60*09537850SAkhilesh Sanikop         position_in_temporal_unit(position_in_temporal_unit) {
61*09537850SAkhilesh Sanikop     obu->MoveTileBuffers(&tile_buffers);
62*09537850SAkhilesh Sanikop     frame->MarkFrameAsStarted();
63*09537850SAkhilesh Sanikop   }
64*09537850SAkhilesh Sanikop 
65*09537850SAkhilesh Sanikop   const ObuSequenceHeader sequence_header;
66*09537850SAkhilesh Sanikop   const ObuFrameHeader frame_header;
67*09537850SAkhilesh Sanikop   Vector<TileBuffer> tile_buffers;
68*09537850SAkhilesh Sanikop   DecoderState state;
69*09537850SAkhilesh Sanikop   TemporalUnit* temporal_unit;
70*09537850SAkhilesh Sanikop   RefCountedBufferPtr frame;
71*09537850SAkhilesh Sanikop   const int position_in_temporal_unit;
72*09537850SAkhilesh Sanikop };
73*09537850SAkhilesh Sanikop 
74*09537850SAkhilesh Sanikop struct TemporalUnit : public Allocable {
75*09537850SAkhilesh Sanikop   // The default constructor is invoked by the Queue<TemporalUnit>::Init()
76*09537850SAkhilesh Sanikop   // method. Queue<> does not use the default-constructed elements, so it is
77*09537850SAkhilesh Sanikop   // safe for the default constructor to not initialize the members.
78*09537850SAkhilesh Sanikop   TemporalUnit() = default;
TemporalUnitTemporalUnit79*09537850SAkhilesh Sanikop   TemporalUnit(const uint8_t* data, size_t size, int64_t user_private_data,
80*09537850SAkhilesh Sanikop                void* buffer_private_data)
81*09537850SAkhilesh Sanikop       : data(data),
82*09537850SAkhilesh Sanikop         size(size),
83*09537850SAkhilesh Sanikop         user_private_data(user_private_data),
84*09537850SAkhilesh Sanikop         buffer_private_data(buffer_private_data),
85*09537850SAkhilesh Sanikop         decoded(false),
86*09537850SAkhilesh Sanikop         status(kStatusOk),
87*09537850SAkhilesh Sanikop         has_displayable_frame(false),
88*09537850SAkhilesh Sanikop         output_frame_position(-1),
89*09537850SAkhilesh Sanikop         decoded_count(0),
90*09537850SAkhilesh Sanikop         output_layer_count(0),
91*09537850SAkhilesh Sanikop         released_input_buffer(false) {}
92*09537850SAkhilesh Sanikop 
93*09537850SAkhilesh Sanikop   const uint8_t* data;
94*09537850SAkhilesh Sanikop   size_t size;
95*09537850SAkhilesh Sanikop   int64_t user_private_data;
96*09537850SAkhilesh Sanikop   void* buffer_private_data;
97*09537850SAkhilesh Sanikop 
98*09537850SAkhilesh Sanikop   // The following members are used only in frame parallel mode.
99*09537850SAkhilesh Sanikop   bool decoded;
100*09537850SAkhilesh Sanikop   StatusCode status;
101*09537850SAkhilesh Sanikop   bool has_displayable_frame;
102*09537850SAkhilesh Sanikop   int output_frame_position;
103*09537850SAkhilesh Sanikop 
104*09537850SAkhilesh Sanikop   Vector<EncodedFrame> frames;
105*09537850SAkhilesh Sanikop   size_t decoded_count;
106*09537850SAkhilesh Sanikop 
107*09537850SAkhilesh Sanikop   // The struct (and the counter) is used to support output of multiple layers
108*09537850SAkhilesh Sanikop   // within a single temporal unit. The decoding process will store the output
109*09537850SAkhilesh Sanikop   // frames in |output_layers| in the order they are finished decoding. At the
110*09537850SAkhilesh Sanikop   // end of the decoding process, this array will be sorted in reverse order of
111*09537850SAkhilesh Sanikop   // |position_in_temporal_unit|. DequeueFrame() will then return the frames in
112*09537850SAkhilesh Sanikop   // reverse order (so that the entire process can run with a single counter
113*09537850SAkhilesh Sanikop   // variable).
114*09537850SAkhilesh Sanikop   struct OutputLayer {
115*09537850SAkhilesh Sanikop     // Used by std::sort to sort |output_layers| in reverse order of
116*09537850SAkhilesh Sanikop     // |position_in_temporal_unit|.
117*09537850SAkhilesh Sanikop     bool operator<(const OutputLayer& rhs) const {
118*09537850SAkhilesh Sanikop       return position_in_temporal_unit > rhs.position_in_temporal_unit;
119*09537850SAkhilesh Sanikop     }
120*09537850SAkhilesh Sanikop 
121*09537850SAkhilesh Sanikop     RefCountedBufferPtr frame;
122*09537850SAkhilesh Sanikop     int position_in_temporal_unit = 0;
123*09537850SAkhilesh Sanikop   } output_layers[kMaxLayers];
124*09537850SAkhilesh Sanikop   // Number of entries in |output_layers|.
125*09537850SAkhilesh Sanikop   int output_layer_count;
126*09537850SAkhilesh Sanikop   // Flag to ensure that we release the input buffer only once if there are
127*09537850SAkhilesh Sanikop   // multiple output layers.
128*09537850SAkhilesh Sanikop   bool released_input_buffer;
129*09537850SAkhilesh Sanikop };
130*09537850SAkhilesh Sanikop 
131*09537850SAkhilesh Sanikop class DecoderImpl : public Allocable {
132*09537850SAkhilesh Sanikop  public:
133*09537850SAkhilesh Sanikop   // The constructor saves a const reference to |*settings|. Therefore
134*09537850SAkhilesh Sanikop   // |*settings| must outlive the DecoderImpl object. On success, |*output|
135*09537850SAkhilesh Sanikop   // contains a pointer to the newly-created DecoderImpl object. On failure,
136*09537850SAkhilesh Sanikop   // |*output| is not modified.
137*09537850SAkhilesh Sanikop   static StatusCode Create(const DecoderSettings* settings,
138*09537850SAkhilesh Sanikop                            std::unique_ptr<DecoderImpl>* output);
139*09537850SAkhilesh Sanikop   ~DecoderImpl();
140*09537850SAkhilesh Sanikop   StatusCode EnqueueFrame(const uint8_t* data, size_t size,
141*09537850SAkhilesh Sanikop                           int64_t user_private_data, void* buffer_private_data);
142*09537850SAkhilesh Sanikop   StatusCode DequeueFrame(const DecoderBuffer** out_ptr);
GetMaxBitdepth()143*09537850SAkhilesh Sanikop   static constexpr int GetMaxBitdepth() {
144*09537850SAkhilesh Sanikop     static_assert(LIBGAV1_MAX_BITDEPTH == 8 || LIBGAV1_MAX_BITDEPTH == 10 ||
145*09537850SAkhilesh Sanikop                       LIBGAV1_MAX_BITDEPTH == 12,
146*09537850SAkhilesh Sanikop                   "LIBGAV1_MAX_BITDEPTH must be 8, 10 or 12.");
147*09537850SAkhilesh Sanikop     return LIBGAV1_MAX_BITDEPTH;
148*09537850SAkhilesh Sanikop   }
149*09537850SAkhilesh Sanikop 
150*09537850SAkhilesh Sanikop  private:
151*09537850SAkhilesh Sanikop   explicit DecoderImpl(const DecoderSettings* settings);
152*09537850SAkhilesh Sanikop   StatusCode Init();
153*09537850SAkhilesh Sanikop   // Called when the first frame is enqueued. It does the OBU parsing for one
154*09537850SAkhilesh Sanikop   // temporal unit to retrieve the tile configuration and sets up the frame
155*09537850SAkhilesh Sanikop   // threading if frame parallel mode is allowed. It also initializes the
156*09537850SAkhilesh Sanikop   // |temporal_units_| queue based on the number of frame threads.
157*09537850SAkhilesh Sanikop   //
158*09537850SAkhilesh Sanikop   // The following are the limitations of the current implementation:
159*09537850SAkhilesh Sanikop   //  * It assumes that all frames in the video have the same tile
160*09537850SAkhilesh Sanikop   //    configuration. The frame parallel threading model will not be updated
161*09537850SAkhilesh Sanikop   //    based on tile configuration changes mid-stream.
162*09537850SAkhilesh Sanikop   //  * The above assumption holds true even when there is a new coded video
163*09537850SAkhilesh Sanikop   //    sequence (i.e.) a new sequence header.
164*09537850SAkhilesh Sanikop   StatusCode InitializeFrameThreadPoolAndTemporalUnitQueue(const uint8_t* data,
165*09537850SAkhilesh Sanikop                                                            size_t size);
166*09537850SAkhilesh Sanikop   // Used only in frame parallel mode. Signals failure and waits until the
167*09537850SAkhilesh Sanikop   // worker threads are aborted if |status| is a failure status. If |status| is
168*09537850SAkhilesh Sanikop   // equal to kStatusOk or kStatusTryAgain, this function does not do anything.
169*09537850SAkhilesh Sanikop   // Always returns the input parameter |status| as the return value.
170*09537850SAkhilesh Sanikop   //
171*09537850SAkhilesh Sanikop   // This function is called only from the application thread (from
172*09537850SAkhilesh Sanikop   // EnqueueFrame() and DequeueFrame()).
173*09537850SAkhilesh Sanikop   StatusCode SignalFailure(StatusCode status);
174*09537850SAkhilesh Sanikop 
175*09537850SAkhilesh Sanikop   void ReleaseOutputFrame();
176*09537850SAkhilesh Sanikop 
177*09537850SAkhilesh Sanikop   // Decodes all the frames contained in the given temporal unit. Used only in
178*09537850SAkhilesh Sanikop   // non frame parallel mode.
179*09537850SAkhilesh Sanikop   StatusCode DecodeTemporalUnit(const TemporalUnit& temporal_unit,
180*09537850SAkhilesh Sanikop                                 const DecoderBuffer** out_ptr);
181*09537850SAkhilesh Sanikop   // Used only in frame parallel mode. Does the OBU parsing for |data| and
182*09537850SAkhilesh Sanikop   // schedules the individual frames for decoding in the |frame_thread_pool_|.
183*09537850SAkhilesh Sanikop   StatusCode ParseAndSchedule(const uint8_t* data, size_t size,
184*09537850SAkhilesh Sanikop                               int64_t user_private_data,
185*09537850SAkhilesh Sanikop                               void* buffer_private_data);
186*09537850SAkhilesh Sanikop   // Decodes the |encoded_frame| and updates the
187*09537850SAkhilesh Sanikop   // |encoded_frame->temporal_unit|'s parameters if the decoded frame is a
188*09537850SAkhilesh Sanikop   // displayable frame. Used only in frame parallel mode.
189*09537850SAkhilesh Sanikop   StatusCode DecodeFrame(EncodedFrame* encoded_frame);
190*09537850SAkhilesh Sanikop 
191*09537850SAkhilesh Sanikop   // Populates |buffer_| with values from |frame|. Adds a reference to |frame|
192*09537850SAkhilesh Sanikop   // in |output_frame_|.
193*09537850SAkhilesh Sanikop   StatusCode CopyFrameToOutputBuffer(const RefCountedBufferPtr& frame);
194*09537850SAkhilesh Sanikop   StatusCode DecodeTiles(const ObuSequenceHeader& sequence_header,
195*09537850SAkhilesh Sanikop                          const ObuFrameHeader& frame_header,
196*09537850SAkhilesh Sanikop                          const Vector<TileBuffer>& tile_buffers,
197*09537850SAkhilesh Sanikop                          const DecoderState& state,
198*09537850SAkhilesh Sanikop                          FrameScratchBuffer* frame_scratch_buffer,
199*09537850SAkhilesh Sanikop                          RefCountedBuffer* current_frame);
200*09537850SAkhilesh Sanikop   // Applies film grain synthesis to the |displayable_frame| and stores the film
201*09537850SAkhilesh Sanikop   // grain applied frame into |film_grain_frame|. Returns kStatusOk on success.
202*09537850SAkhilesh Sanikop   StatusCode ApplyFilmGrain(const ObuSequenceHeader& sequence_header,
203*09537850SAkhilesh Sanikop                             const ObuFrameHeader& frame_header,
204*09537850SAkhilesh Sanikop                             const RefCountedBufferPtr& displayable_frame,
205*09537850SAkhilesh Sanikop                             RefCountedBufferPtr* film_grain_frame,
206*09537850SAkhilesh Sanikop                             ThreadPool* thread_pool);
207*09537850SAkhilesh Sanikop 
208*09537850SAkhilesh Sanikop   bool IsNewSequenceHeader(const ObuParser& obu);
209*09537850SAkhilesh Sanikop 
HasFailure()210*09537850SAkhilesh Sanikop   bool HasFailure() {
211*09537850SAkhilesh Sanikop     std::lock_guard<std::mutex> lock(mutex_);
212*09537850SAkhilesh Sanikop     return failure_status_ != kStatusOk;
213*09537850SAkhilesh Sanikop   }
214*09537850SAkhilesh Sanikop 
215*09537850SAkhilesh Sanikop   // Initializes the |quantizer_matrix_| if necessary and sets
216*09537850SAkhilesh Sanikop   // |quantizer_matrix_initialized_| to true.
217*09537850SAkhilesh Sanikop   bool MaybeInitializeQuantizerMatrix(const ObuFrameHeader& frame_header);
218*09537850SAkhilesh Sanikop 
219*09537850SAkhilesh Sanikop   // Allocates and generates the |wedge_masks_| if necessary and sets
220*09537850SAkhilesh Sanikop   // |wedge_masks_initialized_| to true.
221*09537850SAkhilesh Sanikop   bool MaybeInitializeWedgeMasks(FrameType frame_type);
222*09537850SAkhilesh Sanikop 
223*09537850SAkhilesh Sanikop   // Elements in this queue cannot be moved with std::move since the
224*09537850SAkhilesh Sanikop   // |EncodedFrame.temporal_unit| stores a pointer to elements in this queue.
225*09537850SAkhilesh Sanikop   Queue<TemporalUnit> temporal_units_;
226*09537850SAkhilesh Sanikop   DecoderState state_;
227*09537850SAkhilesh Sanikop 
228*09537850SAkhilesh Sanikop   DecoderBuffer buffer_ = {};
229*09537850SAkhilesh Sanikop   // |output_frame_| holds a reference to the output frame on behalf of
230*09537850SAkhilesh Sanikop   // |buffer_|.
231*09537850SAkhilesh Sanikop   RefCountedBufferPtr output_frame_;
232*09537850SAkhilesh Sanikop 
233*09537850SAkhilesh Sanikop   // Queue of output frames that are to be returned in the DequeueFrame() calls.
234*09537850SAkhilesh Sanikop   // If |settings_.output_all_layers| is false, this queue will never contain
235*09537850SAkhilesh Sanikop   // more than 1 element. This queue is used only when |is_frame_parallel_| is
236*09537850SAkhilesh Sanikop   // false.
237*09537850SAkhilesh Sanikop   Queue<RefCountedBufferPtr> output_frame_queue_;
238*09537850SAkhilesh Sanikop 
239*09537850SAkhilesh Sanikop   BufferPool buffer_pool_;
240*09537850SAkhilesh Sanikop   WedgeMaskArray wedge_masks_;
241*09537850SAkhilesh Sanikop   bool wedge_masks_initialized_ = false;
242*09537850SAkhilesh Sanikop   QuantizerMatrix quantizer_matrix_;
243*09537850SAkhilesh Sanikop   bool quantizer_matrix_initialized_ = false;
244*09537850SAkhilesh Sanikop   FrameScratchBufferPool frame_scratch_buffer_pool_;
245*09537850SAkhilesh Sanikop 
246*09537850SAkhilesh Sanikop   // Used to synchronize the accesses into |temporal_units_| in order to update
247*09537850SAkhilesh Sanikop   // the "decoded" state of an temporal unit.
248*09537850SAkhilesh Sanikop   std::mutex mutex_;
249*09537850SAkhilesh Sanikop   std::condition_variable decoded_condvar_;
250*09537850SAkhilesh Sanikop   bool is_frame_parallel_;
251*09537850SAkhilesh Sanikop   std::unique_ptr<ThreadPool> frame_thread_pool_;
252*09537850SAkhilesh Sanikop 
253*09537850SAkhilesh Sanikop   // In frame parallel mode, there are two primary points of failure:
254*09537850SAkhilesh Sanikop   //  1) ParseAndSchedule()
255*09537850SAkhilesh Sanikop   //  2) DecodeTiles()
256*09537850SAkhilesh Sanikop   // Both of these functions have to respond to the other one failing by
257*09537850SAkhilesh Sanikop   // aborting whatever they are doing. This variable is used to accomplish that.
258*09537850SAkhilesh Sanikop   // If |failure_status_| is not kStatusOk, then the two functions will try to
259*09537850SAkhilesh Sanikop   // abort as early as they can.
260*09537850SAkhilesh Sanikop   StatusCode failure_status_ = kStatusOk LIBGAV1_GUARDED_BY(mutex_);
261*09537850SAkhilesh Sanikop 
262*09537850SAkhilesh Sanikop   ObuSequenceHeader sequence_header_ = {};
263*09537850SAkhilesh Sanikop   // If true, sequence_header is valid.
264*09537850SAkhilesh Sanikop   bool has_sequence_header_ = false;
265*09537850SAkhilesh Sanikop 
266*09537850SAkhilesh Sanikop   const DecoderSettings& settings_;
267*09537850SAkhilesh Sanikop   bool seen_first_frame_ = false;
268*09537850SAkhilesh Sanikop };
269*09537850SAkhilesh Sanikop 
270*09537850SAkhilesh Sanikop }  // namespace libgav1
271*09537850SAkhilesh Sanikop 
272*09537850SAkhilesh Sanikop #endif  // LIBGAV1_SRC_DECODER_IMPL_H_
273