• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // This file contains an implementation of a VP9 bitstream parser. The main
6 // purpose of this parser is to support hardware decode acceleration. Some
7 // accelerators, e.g. libva which implements VA-API, require the caller
8 // (chrome) to feed them parsed VP9 frame header.
9 //
10 // See media::VP9Decoder for example usage.
11 //
12 #ifndef VP9_PARSER_H_
13 #define VP9_PARSER_H_
14 
15 #include <stddef.h>
16 #include <stdint.h>
17 #include <sys/types.h>
18 
19 #include <deque>
20 #include <memory>
21 
22 #include "base/callback.h"
23 #include "base/macros.h"
24 #include "base/memory/weak_ptr.h"
25 
26 namespace media {
27 
28 const int kVp9MaxProfile = 4;
29 const int kVp9NumRefFramesLog2 = 3;
30 const size_t kVp9NumRefFrames = 1 << kVp9NumRefFramesLog2;
31 const uint8_t kVp9MaxProb = 255;
32 const size_t kVp9NumRefsPerFrame = 3;
33 const size_t kVp9NumFrameContextsLog2 = 2;
34 const size_t kVp9NumFrameContexts = 1 << kVp9NumFrameContextsLog2;
35 
36 using Vp9Prob = uint8_t;
37 
38 enum class Vp9ColorSpace {
39   UNKNOWN = 0,
40   BT_601 = 1,
41   BT_709 = 2,
42   SMPTE_170 = 3,
43   SMPTE_240 = 4,
44   BT_2020 = 5,
45   RESERVED = 6,
46   SRGB = 7,
47 };
48 
49 enum Vp9InterpolationFilter {
50   EIGHTTAP = 0,
51   EIGHTTAP_SMOOTH = 1,
52   EIGHTTAP_SHARP = 2,
53   BILINEAR = 3,
54   SWITCHABLE = 4,
55 };
56 
57 enum Vp9RefType {
58   VP9_FRAME_INTRA = 0,
59   VP9_FRAME_LAST = 1,
60   VP9_FRAME_GOLDEN = 2,
61   VP9_FRAME_ALTREF = 3,
62   VP9_FRAME_MAX = 4,
63 };
64 
65 enum Vp9ReferenceMode {
66   SINGLE_REFERENCE = 0,
67   COMPOUND_REFERENCE = 1,
68   REFERENCE_MODE_SELECT = 2,
69 };
70 
71 struct Vp9SegmentationParams {
72   static const size_t kNumSegments = 8;
73   static const size_t kNumTreeProbs = kNumSegments - 1;
74   static const size_t kNumPredictionProbs = 3;
75   enum SegmentLevelFeature {
76     SEG_LVL_ALT_Q = 0,
77     SEG_LVL_ALT_LF = 1,
78     SEG_LVL_REF_FRAME = 2,
79     SEG_LVL_SKIP = 3,
80     SEG_LVL_MAX
81   };
82 
83   bool enabled;
84 
85   bool update_map;
86   uint8_t tree_probs[kNumTreeProbs];
87   bool temporal_update;
88   uint8_t pred_probs[kNumPredictionProbs];
89 
90   bool update_data;
91   bool abs_or_delta_update;
92   bool feature_enabled[kNumSegments][SEG_LVL_MAX];
93   int16_t feature_data[kNumSegments][SEG_LVL_MAX];
94 
95   int16_t y_dequant[kNumSegments][2];
96   int16_t uv_dequant[kNumSegments][2];
97 
FeatureEnabledVp9SegmentationParams98   bool FeatureEnabled(size_t seg_id, SegmentLevelFeature feature) const {
99     return feature_enabled[seg_id][feature];
100   }
101 
FeatureDataVp9SegmentationParams102   int16_t FeatureData(size_t seg_id, SegmentLevelFeature feature) const {
103     return feature_data[seg_id][feature];
104   }
105 };
106 
107 struct Vp9LoopFilterParams {
108   static const size_t kNumModeDeltas = 2;
109 
110   uint8_t level;
111   uint8_t sharpness;
112 
113   bool delta_enabled;
114   bool delta_update;
115   bool update_ref_deltas[VP9_FRAME_MAX];
116   int8_t ref_deltas[VP9_FRAME_MAX];
117   bool update_mode_deltas[kNumModeDeltas];
118   int8_t mode_deltas[kNumModeDeltas];
119 
120   // Calculated from above fields.
121   uint8_t lvl[Vp9SegmentationParams::kNumSegments][VP9_FRAME_MAX]
122              [kNumModeDeltas];
123 };
124 
125 // Members of Vp9FrameHeader will be 0-initialized by Vp9Parser::ParseNextFrame.
126 struct Vp9QuantizationParams {
IsLosslessVp9QuantizationParams127   bool IsLossless() const {
128     return base_q_idx == 0 && delta_q_y_dc == 0 && delta_q_uv_dc == 0 &&
129            delta_q_uv_ac == 0;
130   }
131 
132   uint8_t base_q_idx;
133   int8_t delta_q_y_dc;
134   int8_t delta_q_uv_dc;
135   int8_t delta_q_uv_ac;
136 };
137 
138 // Entropy context for frame parsing
139 struct Vp9FrameContext {
140   bool IsValid() const;
141 
142   Vp9Prob tx_probs_8x8[2][1];
143   Vp9Prob tx_probs_16x16[2][2];
144   Vp9Prob tx_probs_32x32[2][3];
145 
146   Vp9Prob coef_probs[4][2][2][6][6][3];
147   Vp9Prob skip_prob[3];
148   Vp9Prob inter_mode_probs[7][3];
149   Vp9Prob interp_filter_probs[4][2];
150   Vp9Prob is_inter_prob[4];
151 
152   Vp9Prob comp_mode_prob[5];
153   Vp9Prob single_ref_prob[5][2];
154   Vp9Prob comp_ref_prob[5];
155 
156   Vp9Prob y_mode_probs[4][9];
157   Vp9Prob uv_mode_probs[10][9];
158   Vp9Prob partition_probs[16][3];
159 
160   Vp9Prob mv_joint_probs[3];
161   Vp9Prob mv_sign_prob[2];
162   Vp9Prob mv_class_probs[2][10];
163   Vp9Prob mv_class0_bit_prob[2];
164   Vp9Prob mv_bits_prob[2][10];
165   Vp9Prob mv_class0_fr_probs[2][2][3];
166   Vp9Prob mv_fr_probs[2][3];
167   Vp9Prob mv_class0_hp_prob[2];
168   Vp9Prob mv_hp_prob[2];
169 };
170 
171 struct Vp9CompressedHeader {
172   enum Vp9TxMode {
173     ONLY_4X4 = 0,
174     ALLOW_8X8 = 1,
175     ALLOW_16X16 = 2,
176     ALLOW_32X32 = 3,
177     TX_MODE_SELECT = 4,
178     TX_MODES = 5,
179   };
180 
181   Vp9TxMode tx_mode;
182   Vp9ReferenceMode reference_mode;
183 };
184 
185 // VP9 frame header.
186 struct Vp9FrameHeader {
187   enum FrameType {
188     KEYFRAME = 0,
189     INTERFRAME = 1,
190   };
191 
192   bool IsKeyframe() const;
193   bool IsIntra() const;
RefreshFlagVp9FrameHeader194   bool RefreshFlag(size_t i) const {
195     return !!(refresh_frame_flags & (1u << i));
196   }
197 
198   uint8_t profile;
199 
200   bool show_existing_frame;
201   uint8_t frame_to_show_map_idx;
202 
203   FrameType frame_type;
204 
205   bool show_frame;
206   bool error_resilient_mode;
207 
208   uint8_t bit_depth;
209   Vp9ColorSpace color_space;
210   bool color_range;
211   uint8_t subsampling_x;
212   uint8_t subsampling_y;
213 
214   // The range of frame_width and frame_height is 1..2^16.
215   uint32_t frame_width;
216   uint32_t frame_height;
217   uint32_t render_width;
218   uint32_t render_height;
219 
220   bool intra_only;
221   uint8_t reset_frame_context;
222   uint8_t refresh_frame_flags;
223   uint8_t ref_frame_idx[kVp9NumRefsPerFrame];
224   bool ref_frame_sign_bias[Vp9RefType::VP9_FRAME_MAX];
225   bool allow_high_precision_mv;
226   Vp9InterpolationFilter interpolation_filter;
227 
228   bool refresh_frame_context;
229   bool frame_parallel_decoding_mode;
230   uint8_t frame_context_idx;
231   // |frame_context_idx_to_save_probs| is to be used by save_probs() only, and
232   // |frame_context_idx| otherwise.
233   uint8_t frame_context_idx_to_save_probs;
234 
235   Vp9QuantizationParams quant_params;
236 
237   uint8_t tile_cols_log2;
238   uint8_t tile_rows_log2;
239 
240   // Pointer to the beginning of frame data. It is a responsibility of the
241   // client of the Vp9Parser to maintain validity of this data while it is
242   // being used outside of that class.
243   const uint8_t* data;
244 
245   // Size of |data| in bytes.
246   size_t frame_size;
247 
248   // Size of compressed header in bytes.
249   size_t header_size_in_bytes;
250 
251   // Size of uncompressed header in bytes.
252   size_t uncompressed_header_size;
253 
254   Vp9CompressedHeader compressed_header;
255   // Initial frame entropy context after load_probs2(frame_context_idx).
256   Vp9FrameContext initial_frame_context;
257   // Current frame entropy context after header parsing.
258   Vp9FrameContext frame_context;
259 };
260 
261 // A parser for VP9 bitstream.
262 class Vp9Parser {
263  public:
264   // If context update is needed after decoding a frame, the client must
265   // execute this callback, passing the updated context state.
266   using ContextRefreshCallback = base::Callback<void(const Vp9FrameContext&)>;
267 
268   // ParseNextFrame() return values. See documentation for ParseNextFrame().
269   enum Result {
270     kOk,
271     kInvalidStream,
272     kEOStream,
273     kAwaitingRefresh,
274   };
275 
276   // The parsing context to keep track of references.
277   struct ReferenceSlot {
278     bool initialized;
279     uint32_t frame_width;
280     uint32_t frame_height;
281     uint8_t subsampling_x;
282     uint8_t subsampling_y;
283     uint8_t bit_depth;
284 
285     // More fields for consistency checking.
286     uint8_t profile;
287     Vp9ColorSpace color_space;
288   };
289 
290   // The parsing context that persists across frames.
291   class Context {
292    public:
293     class Vp9FrameContextManager {
294      public:
295       Vp9FrameContextManager();
296       ~Vp9FrameContextManager();
initialized()297       bool initialized() const { return initialized_; }
needs_client_update()298       bool needs_client_update() const { return needs_client_update_; }
299       const Vp9FrameContext& frame_context() const;
300 
301       // Resets to uninitialized state.
302       void Reset();
303 
304       // Marks this context as requiring an update from parser's client.
305       void SetNeedsClientUpdate();
306 
307       // Updates frame context.
308       void Update(const Vp9FrameContext& frame_context);
309 
310       // Returns a callback to update frame context at a later time with.
311       ContextRefreshCallback GetUpdateCb();
312 
313      private:
314       // Updates frame context from parser's client.
315       void UpdateFromClient(const Vp9FrameContext& frame_context);
316 
317       bool initialized_ = false;
318       bool needs_client_update_ = false;
319       Vp9FrameContext frame_context_;
320 
321       base::WeakPtrFactory<Vp9FrameContextManager> weak_ptr_factory_;
322     };
323 
324     void Reset();
325 
326     // Mark |frame_context_idx| as requiring update from the client.
327     void MarkFrameContextForUpdate(size_t frame_context_idx);
328 
329     // Update frame context at |frame_context_idx| with the contents of
330     // |frame_context|.
331     void UpdateFrameContext(size_t frame_context_idx,
332                             const Vp9FrameContext& frame_context);
333 
334     // Return ReferenceSlot for frame at |ref_idx|.
335     const ReferenceSlot& GetRefSlot(size_t ref_idx) const;
336 
337     // Update contents of ReferenceSlot at |ref_idx| with the contents of
338     // |ref_slot|.
339     void UpdateRefSlot(size_t ref_idx, const ReferenceSlot& ref_slot);
340 
segmentation()341     const Vp9SegmentationParams& segmentation() const { return segmentation_; }
342 
loop_filter()343     const Vp9LoopFilterParams& loop_filter() const { return loop_filter_; }
344 
345    private:
346     friend class Vp9UncompressedHeaderParser;
347     friend class Vp9Parser;
348 
349     // Segmentation and loop filter state.
350     Vp9SegmentationParams segmentation_;
351     Vp9LoopFilterParams loop_filter_;
352 
353     // Frame references.
354     ReferenceSlot ref_slots_[kVp9NumRefFrames];
355 
356     Vp9FrameContextManager frame_context_managers_[kVp9NumFrameContexts];
357   };
358 
359   // The constructor. See ParseNextFrame() for comments for
360   // |parsing_compressed_header|.
361   explicit Vp9Parser(bool parsing_compressed_header);
362   ~Vp9Parser();
363 
364   // Set a new stream buffer to read from, starting at |stream| and of size
365   // |stream_size| in bytes. |stream| must point to the beginning of a single
366   // frame or a single superframe, is owned by caller and must remain valid
367   // until the next call to SetStream().
368   void SetStream(const uint8_t* stream, off_t stream_size);
369 
370   // Parse the next frame in the current stream buffer, filling |fhdr| with
371   // the parsed frame header and updating current segmentation and loop filter
372   // state.
373   // Return kOk if a frame has successfully been parsed,
374   //        kEOStream if there is no more data in the current stream buffer,
375   //        kAwaitingRefresh if this frame awaiting frame context update, or
376   //        kInvalidStream on error.
377   Result ParseNextFrame(Vp9FrameHeader* fhdr);
378 
379   // Return current parsing context.
context()380   const Context& context() const { return context_; }
381 
382   // Return a ContextRefreshCallback, which, if not null, has to be called with
383   // the new context state after the frame associated with |frame_context_idx|
384   // is decoded.
385   ContextRefreshCallback GetContextRefreshCb(size_t frame_context_idx);
386 
387   // Clear parser state and return to an initialized state.
388   void Reset();
389 
390  private:
391   // Stores start pointer and size of each frame within the current superframe.
392   struct FrameInfo {
393     FrameInfo() = default;
394     FrameInfo(const uint8_t* ptr, off_t size);
IsValidFrameInfo395     bool IsValid() const { return ptr != nullptr; }
ResetFrameInfo396     void Reset() { ptr = nullptr; }
397 
398     // Starting address of the frame.
399     const uint8_t* ptr = nullptr;
400 
401     // Size of the frame in bytes.
402     off_t size = 0;
403   };
404 
405   std::deque<FrameInfo> ParseSuperframe();
406 
407   size_t GetQIndex(const Vp9QuantizationParams& quant, size_t segid) const;
408   void SetupSegmentationDequant();
409   void SetupLoopFilter();
410   void UpdateSlots();
411 
412   // Current address in the bitstream buffer.
413   const uint8_t* stream_;
414 
415   // Remaining bytes in stream_.
416   off_t bytes_left_;
417 
418   bool parsing_compressed_header_;
419 
420   // FrameInfo for the remaining frames in the current superframe to be parsed.
421   std::deque<FrameInfo> frames_;
422 
423   Context context_;
424 
425   FrameInfo curr_frame_info_;
426   Vp9FrameHeader curr_frame_header_;
427 
428   DISALLOW_COPY_AND_ASSIGN(Vp9Parser);
429 };
430 
431 }  // namespace media
432 
433 #endif  // VP9_PARSER_H_
434