Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // This file contains an implementation of a VP9 bitstream parser. The main | 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 | 6 // purpose of this parser is to support hardware decode acceleration. Some |
| 7 // accelerators, e.g. libva which implements VA-API, require the caller | 7 // accelerators, e.g. libva which implements VA-API, require the caller |
| 8 // (chrome) to feed them parsed VP9 frame header. | 8 // (chrome) to feed them parsed VP9 frame header. |
| 9 // | 9 // |
| 10 // See media::VP9Decoder for example usage. | 10 // See media::VP9Decoder for example usage. |
| 11 // | 11 // |
| 12 #ifndef MEDIA_FILTERS_VP9_PARSER_H_ | 12 #ifndef MEDIA_FILTERS_VP9_PARSER_H_ |
| 13 #define MEDIA_FILTERS_VP9_PARSER_H_ | 13 #define MEDIA_FILTERS_VP9_PARSER_H_ |
| 14 | 14 |
| 15 #include <stddef.h> | 15 #include <stddef.h> |
| 16 #include <stdint.h> | 16 #include <stdint.h> |
| 17 #include <sys/types.h> | 17 #include <sys/types.h> |
| 18 | 18 |
| 19 #include <deque> | 19 #include <deque> |
| 20 #include <memory> | |
| 20 | 21 |
| 21 #include "base/callback.h" | 22 #include "base/callback.h" |
| 22 #include "base/macros.h" | 23 #include "base/macros.h" |
| 23 #include "base/memory/weak_ptr.h" | 24 #include "base/memory/weak_ptr.h" |
| 24 #include "media/base/media_export.h" | 25 #include "media/base/media_export.h" |
| 25 | 26 |
| 26 namespace media { | 27 namespace media { |
| 27 | 28 |
| 28 const int kVp9MaxProfile = 4; | 29 const int kVp9MaxProfile = 4; |
| 29 const int kVp9NumRefFramesLog2 = 3; | 30 const int kVp9NumRefFramesLog2 = 3; |
| 30 const size_t kVp9NumRefFrames = 1 << kVp9NumRefFramesLog2; | 31 const size_t kVp9NumRefFrames = 1 << kVp9NumRefFramesLog2; |
| 31 const uint8_t kVp9MaxProb = 255; | 32 const uint8_t kVp9MaxProb = 255; |
| 32 const size_t kVp9NumRefsPerFrame = 3; | 33 const size_t kVp9NumRefsPerFrame = 3; |
| 33 const size_t kVp9NumFrameContexts = 4; | 34 const size_t kVp9NumFrameContextsLog2 = 2; |
| 35 const size_t kVp9NumFrameContexts = 1 << kVp9NumFrameContextsLog2; | |
| 34 | 36 |
| 35 using Vp9Prob = uint8_t; | 37 using Vp9Prob = uint8_t; |
| 36 | 38 |
| 37 enum class Vp9ColorSpace { | 39 enum class Vp9ColorSpace { |
| 38 UNKNOWN = 0, | 40 UNKNOWN = 0, |
| 39 BT_601 = 1, | 41 BT_601 = 1, |
| 40 BT_709 = 2, | 42 BT_709 = 2, |
| 41 SMPTE_170 = 3, | 43 SMPTE_170 = 3, |
| 42 SMPTE_240 = 4, | 44 SMPTE_240 = 4, |
| 43 BT_2020 = 5, | 45 BT_2020 = 5, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 129 } | 131 } |
| 130 | 132 |
| 131 uint8_t base_q_idx; | 133 uint8_t base_q_idx; |
| 132 int8_t delta_q_y_dc; | 134 int8_t delta_q_y_dc; |
| 133 int8_t delta_q_uv_dc; | 135 int8_t delta_q_uv_dc; |
| 134 int8_t delta_q_uv_ac; | 136 int8_t delta_q_uv_ac; |
| 135 }; | 137 }; |
| 136 | 138 |
| 137 // Entropy context for frame parsing | 139 // Entropy context for frame parsing |
| 138 struct MEDIA_EXPORT Vp9FrameContext { | 140 struct MEDIA_EXPORT Vp9FrameContext { |
| 141 bool IsValid() const; | |
| 142 | |
| 139 Vp9Prob tx_probs_8x8[2][1]; | 143 Vp9Prob tx_probs_8x8[2][1]; |
| 140 Vp9Prob tx_probs_16x16[2][2]; | 144 Vp9Prob tx_probs_16x16[2][2]; |
| 141 Vp9Prob tx_probs_32x32[2][3]; | 145 Vp9Prob tx_probs_32x32[2][3]; |
| 142 | 146 |
| 143 Vp9Prob coef_probs[4][2][2][6][6][3]; | 147 Vp9Prob coef_probs[4][2][2][6][6][3]; |
| 144 Vp9Prob skip_prob[3]; | 148 Vp9Prob skip_prob[3]; |
| 145 Vp9Prob inter_mode_probs[7][3]; | 149 Vp9Prob inter_mode_probs[7][3]; |
| 146 Vp9Prob interp_filter_probs[4][2]; | 150 Vp9Prob interp_filter_probs[4][2]; |
| 147 Vp9Prob is_inter_prob[4]; | 151 Vp9Prob is_inter_prob[4]; |
| 148 | 152 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 // Size of uncompressed header in bytes. | 252 // Size of uncompressed header in bytes. |
| 249 size_t uncompressed_header_size; | 253 size_t uncompressed_header_size; |
| 250 | 254 |
| 251 Vp9CompressedHeader compressed_header; | 255 Vp9CompressedHeader compressed_header; |
| 252 // Initial frame entropy context after load_probs2(frame_context_idx). | 256 // Initial frame entropy context after load_probs2(frame_context_idx). |
| 253 Vp9FrameContext initial_frame_context; | 257 Vp9FrameContext initial_frame_context; |
| 254 // Current frame entropy context after header parsing. | 258 // Current frame entropy context after header parsing. |
| 255 Vp9FrameContext frame_context; | 259 Vp9FrameContext frame_context; |
| 256 }; | 260 }; |
| 257 | 261 |
| 258 class Vp9FrameContextManager { | 262 // A parser for VP9 bitstream. |
| 263 class MEDIA_EXPORT Vp9Parser { | |
| 259 public: | 264 public: |
| 260 // If context update is needed after decoding a frame, the client must | 265 // If context update is needed after decoding a frame, the client must |
| 261 // execute this callback, passing the updated context state. | 266 // execute this callback, passing the updated context state. |
| 262 using ContextRefreshCallback = base::Callback<void(const Vp9FrameContext&)>; | 267 using ContextRefreshCallback = base::Callback<void(const Vp9FrameContext&)>; |
| 263 | 268 |
| 264 static bool IsValidFrameContext(const Vp9FrameContext& context); | |
| 265 | |
| 266 Vp9FrameContextManager(); | |
| 267 ~Vp9FrameContextManager(); | |
| 268 bool initialized() const { return initialized_; } | |
| 269 bool needs_client_update() const { return needs_client_update_; } | |
| 270 const Vp9FrameContext& frame_context() const; | |
| 271 | |
| 272 // Resets to uninitialized state. | |
| 273 void Reset(); | |
| 274 | |
| 275 // Sets this context need update from parser's client. Returns a callback for | |
| 276 // update. | |
| 277 ContextRefreshCallback SetNeedsClientUpdate(); | |
| 278 | |
| 279 // Updates frame context. | |
| 280 void Update(const Vp9FrameContext& frame_context); | |
| 281 | |
| 282 private: | |
| 283 // Updates frame context from parser's client. | |
| 284 void UpdateFromClient(const Vp9FrameContext& frame_context); | |
| 285 | |
| 286 bool initialized_ = false; | |
| 287 bool needs_client_update_ = false; | |
| 288 Vp9FrameContext frame_context_; | |
| 289 | |
| 290 base::WeakPtrFactory<Vp9FrameContextManager> weak_ptr_factory_; | |
| 291 }; | |
| 292 | |
| 293 // A parser for VP9 bitstream. | |
| 294 class MEDIA_EXPORT Vp9Parser { | |
| 295 public: | |
| 296 // ParseNextFrame() return values. See documentation for ParseNextFrame(). | 269 // ParseNextFrame() return values. See documentation for ParseNextFrame(). |
| 297 enum Result { | 270 enum Result { |
| 298 kOk, | 271 kOk, |
| 299 kInvalidStream, | 272 kInvalidStream, |
| 300 kEOStream, | 273 kEOStream, |
| 301 kAwaitingRefresh, | 274 kAwaitingRefresh, |
| 302 }; | 275 }; |
| 303 | 276 |
| 304 // The parsing context to keep track of references. | 277 // The parsing context to keep track of references. |
| 305 struct ReferenceSlot { | 278 struct ReferenceSlot { |
| 306 bool initialized; | 279 bool initialized; |
| 307 uint32_t frame_width; | 280 uint32_t frame_width; |
| 308 uint32_t frame_height; | 281 uint32_t frame_height; |
| 309 uint8_t subsampling_x; | 282 uint8_t subsampling_x; |
| 310 uint8_t subsampling_y; | 283 uint8_t subsampling_y; |
| 311 uint8_t bit_depth; | 284 uint8_t bit_depth; |
| 312 | 285 |
| 313 // More fields for consistency checking. | 286 // More fields for consistency checking. |
| 314 uint8_t profile; | 287 uint8_t profile; |
| 315 Vp9ColorSpace color_space; | 288 Vp9ColorSpace color_space; |
| 316 }; | 289 }; |
| 317 | 290 |
| 318 // The parsing context that persists across frames. | 291 // The parsing context that persists across frames. |
| 319 struct Context { | 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 // Return a callback to update frame context at a later time with. | |
|
kcwu
2016/08/17 04:06:09
s/Return/Returns/
Pawel Osciak
2016/08/19 08:22:43
Done.
| |
| 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 | |
| 320 void Reset(); | 325 void Reset(); |
| 321 | 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 of |ref_type|. | |
| 336 const ReferenceSlot& GetRefSlot(size_t ref_type) const; | |
|
kcwu
2016/08/17 04:06:09
ref_idx or ref_frame_idx?
"size_t ref_type" looks
Pawel Osciak
2016/08/19 08:22:43
Done.
| |
| 337 | |
| 338 // Update contents of ReferenceSlot for |ref_type| with the contents of | |
| 339 // |ref_slot|. | |
| 340 void UpdateRefSlot(size_t ref_type, 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 | |
| 322 // Segmentation and loop filter state. | 350 // Segmentation and loop filter state. |
| 323 Vp9SegmentationParams segmentation; | 351 Vp9SegmentationParams segmentation_; |
| 324 Vp9LoopFilterParams loop_filter; | 352 Vp9LoopFilterParams loop_filter_; |
| 325 | 353 |
| 326 // Frame references. | 354 // Frame references. |
| 327 ReferenceSlot ref_slots[kVp9NumRefFrames]; | 355 ReferenceSlot ref_slots_[kVp9NumRefFrames]; |
| 328 | 356 |
| 329 Vp9FrameContextManager frame_context_managers[kVp9NumFrameContexts]; | 357 Vp9FrameContextManager frame_context_managers_[kVp9NumFrameContexts]; |
| 330 }; | 358 }; |
| 331 | 359 |
| 332 // The constructor. See ParseNextFrame() for comments for | 360 // The constructor. See ParseNextFrame() for comments for |
| 333 // |parsing_compressed_header|. | 361 // |parsing_compressed_header|. |
| 334 explicit Vp9Parser(bool parsing_compressed_header); | 362 explicit Vp9Parser(bool parsing_compressed_header); |
| 335 ~Vp9Parser(); | 363 ~Vp9Parser(); |
| 336 | 364 |
| 337 // Set a new stream buffer to read from, starting at |stream| and of size | 365 // Set a new stream buffer to read from, starting at |stream| and of size |
| 338 // |stream_size| in bytes. |stream| must point to the beginning of a single | 366 // |stream_size| in bytes. |stream| must point to the beginning of a single |
| 339 // frame or a single superframe, is owned by caller and must remain valid | 367 // frame or a single superframe, is owned by caller and must remain valid |
| 340 // until the next call to SetStream(). | 368 // until the next call to SetStream(). |
| 341 void SetStream(const uint8_t* stream, off_t stream_size); | 369 void SetStream(const uint8_t* stream, off_t stream_size); |
| 342 | 370 |
| 343 // Parse the next frame in the current stream buffer, filling |fhdr| with | 371 // Parse the next frame in the current stream buffer, filling |fhdr| with |
| 344 // the parsed frame header and updating current segmentation and loop filter | 372 // the parsed frame header and updating current segmentation and loop filter |
| 345 // state. If |parsing_compressed_header_|, this function also fills | 373 // state. |
| 346 // |context_refresh_cb|, which is used to update frame context. If | |
| 347 // |*context_refresh_cb| is null, no callback is necessary. | |
| 348 // Return kOk if a frame has successfully been parsed, | 374 // Return kOk if a frame has successfully been parsed, |
| 349 // kEOStream if there is no more data in the current stream buffer, | 375 // kEOStream if there is no more data in the current stream buffer, |
| 350 // kAwaitingRefresh if this frame awaiting frame context update, or | 376 // kAwaitingRefresh if this frame awaiting frame context update, or |
| 351 // kInvalidStream on error. | 377 // kInvalidStream on error. |
| 352 Result ParseNextFrame( | 378 Result ParseNextFrame(Vp9FrameHeader* fhdr); |
| 353 Vp9FrameHeader* fhdr, | |
| 354 Vp9FrameContextManager::ContextRefreshCallback* context_refresh_cb); | |
| 355 | 379 |
| 356 // Return current segmentation state. | 380 // Return current parsing context. |
| 357 const Vp9SegmentationParams& GetSegmentation() const { | 381 const Context& context() const { return context_; } |
| 358 return context_.segmentation; | |
| 359 } | |
| 360 | 382 |
| 361 // Return current loop filter state. | 383 // Return a ContextRefreshCallback, which, if not null, has to be called with |
| 362 const Vp9LoopFilterParams& GetLoopFilter() const { | 384 // the new context state after the frame associated with |frame_context_idx| |
| 363 return context_.loop_filter; | 385 // is decoded. |
| 364 } | 386 ContextRefreshCallback GetContextRefreshCb(size_t frame_context_idx); |
| 365 | 387 |
| 366 // Clear parser state and return to an initialized state. | 388 // Clear parser state and return to an initialized state. |
| 367 void Reset(); | 389 void Reset(); |
| 368 | 390 |
| 369 private: | 391 private: |
| 370 class UncompressedHeaderParser; | |
| 371 class CompressedHeaderParser; | |
| 372 | |
| 373 // Stores start pointer and size of each frame within the current superframe. | 392 // Stores start pointer and size of each frame within the current superframe. |
| 374 struct FrameInfo { | 393 struct FrameInfo { |
| 375 FrameInfo() = default; | 394 FrameInfo() = default; |
| 376 FrameInfo(const uint8_t* ptr, off_t size); | 395 FrameInfo(const uint8_t* ptr, off_t size); |
| 377 bool IsValid() const { return ptr != nullptr; } | 396 bool IsValid() const { return ptr != nullptr; } |
| 378 void Reset() { ptr = nullptr; } | 397 void Reset() { ptr = nullptr; } |
| 379 | 398 |
| 380 // Starting address of the frame. | 399 // Starting address of the frame. |
| 381 const uint8_t* ptr = nullptr; | 400 const uint8_t* ptr = nullptr; |
| 382 | 401 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 406 | 425 |
| 407 FrameInfo curr_frame_info_; | 426 FrameInfo curr_frame_info_; |
| 408 Vp9FrameHeader curr_frame_header_; | 427 Vp9FrameHeader curr_frame_header_; |
| 409 | 428 |
| 410 DISALLOW_COPY_AND_ASSIGN(Vp9Parser); | 429 DISALLOW_COPY_AND_ASSIGN(Vp9Parser); |
| 411 }; | 430 }; |
| 412 | 431 |
| 413 } // namespace media | 432 } // namespace media |
| 414 | 433 |
| 415 #endif // MEDIA_FILTERS_VP9_PARSER_H_ | 434 #endif // MEDIA_FILTERS_VP9_PARSER_H_ |
| OLD | NEW |