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