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 // 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 |
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 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 |
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 |