Home | History | Annotate | Download | only in vda
      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 
     99   bool FeatureEnabled(size_t seg_id, SegmentLevelFeature feature) const {
    100     return feature_enabled[seg_id][feature];
    101   }
    102 
    103   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 {
    128   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;
    195   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();
    298       bool initialized() const { return initialized_; }
    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 
    342     const Vp9SegmentationParams& segmentation() const { return segmentation_; }
    343 
    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.
    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);
    396     bool IsValid() const { return ptr != nullptr; }
    397     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