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