Chromium Code Reviews| Index: media/filters/vp9_parser.h |
| diff --git a/media/filters/vp9_parser.h b/media/filters/vp9_parser.h |
| index 4d430494170f48dae739febfd283fee09750f50b..47ff4c1440c2030c65ec936842c245a8d07ca977 100644 |
| --- a/media/filters/vp9_parser.h |
| +++ b/media/filters/vp9_parser.h |
| @@ -18,9 +18,10 @@ |
| #include <deque> |
| +#include "base/callback.h" |
| #include "base/macros.h" |
| +#include "base/memory/weak_ptr.h" |
| #include "media/base/media_export.h" |
| -#include "media/filters/vp9_raw_bits_reader.h" |
| namespace media { |
| @@ -29,6 +30,9 @@ const int kVp9NumRefFramesLog2 = 3; |
| const size_t kVp9NumRefFrames = 1 << kVp9NumRefFramesLog2; |
| const uint8_t kVp9MaxProb = 255; |
| const size_t kVp9NumRefsPerFrame = 3; |
| +const size_t kVp9NumFrameContexts = 4; |
| + |
| +using Vp9Prob = uint8_t; |
| enum class Vp9ColorSpace { |
| UNKNOWN = 0, |
| @@ -41,15 +45,29 @@ enum class Vp9ColorSpace { |
| SRGB = 7, |
| }; |
| -enum Vp9InterpFilter { |
| +enum Vp9InterpolationFilter { |
| EIGHTTAP = 0, |
| EIGHTTAP_SMOOTH = 1, |
| EIGHTTAP_SHARP = 2, |
| BILINEAR = 3, |
| - SWICHABLE = 4, |
| + SWITCHABLE = 4, |
| +}; |
| + |
| +enum Vp9RefType { |
| + VP9_FRAME_INTRA = 0, |
| + VP9_FRAME_LAST = 1, |
| + VP9_FRAME_GOLDEN = 2, |
| + VP9_FRAME_ALTREF = 3, |
| + VP9_FRAME_MAX = 4, |
| +}; |
| + |
| +enum Vp9ReferenceMode { |
| + SINGLE_REFERENCE = 0, |
| + COMPOUND_REFERENCE = 1, |
| + REFERENCE_MODE_SELECT = 2, |
| }; |
| -struct MEDIA_EXPORT Vp9Segmentation { |
| +struct MEDIA_EXPORT Vp9SegmentationParams { |
| static const size_t kNumSegments = 8; |
| static const size_t kNumTreeProbs = kNumSegments - 1; |
| static const size_t kNumPredictionProbs = 3; |
| @@ -69,7 +87,7 @@ struct MEDIA_EXPORT Vp9Segmentation { |
| uint8_t pred_probs[kNumPredictionProbs]; |
| bool update_data; |
| - bool abs_delta; |
| + bool abs_or_delta_update; |
| bool feature_enabled[kNumSegments][SEG_LVL_MAX]; |
| int16_t feature_data[kNumSegments][SEG_LVL_MAX]; |
| @@ -85,41 +103,80 @@ struct MEDIA_EXPORT Vp9Segmentation { |
| } |
| }; |
| -struct MEDIA_EXPORT Vp9LoopFilter { |
| - enum Vp9FrameType { |
| - VP9_FRAME_INTRA = 0, |
| - VP9_FRAME_LAST = 1, |
| - VP9_FRAME_GOLDEN = 2, |
| - VP9_FRAME_ALTREF = 3, |
| - VP9_FRAME_MAX = 4, |
| - }; |
| - |
| +struct MEDIA_EXPORT Vp9LoopFilterParams { |
| static const size_t kNumModeDeltas = 2; |
| - uint8_t filter_level; |
| - uint8_t sharpness_level; |
| + uint8_t level; |
| + uint8_t sharpness; |
| - bool mode_ref_delta_enabled; |
| - bool mode_ref_delta_update; |
| + bool delta_enabled; |
| + bool delta_update; |
| bool update_ref_deltas[VP9_FRAME_MAX]; |
| int8_t ref_deltas[VP9_FRAME_MAX]; |
| bool update_mode_deltas[kNumModeDeltas]; |
| int8_t mode_deltas[kNumModeDeltas]; |
| - uint8_t lvl[Vp9Segmentation::kNumSegments][VP9_FRAME_MAX][kNumModeDeltas]; |
| + // Calculated from above fields. |
| + uint8_t lvl[Vp9SegmentationParams::kNumSegments][VP9_FRAME_MAX] |
| + [kNumModeDeltas]; |
| }; |
| // Members of Vp9FrameHeader will be 0-initialized by Vp9Parser::ParseNextFrame. |
| struct MEDIA_EXPORT Vp9QuantizationParams { |
| bool IsLossless() const { |
| - return base_qindex == 0 && y_dc_delta == 0 && uv_dc_delta == 0 && |
| - uv_ac_delta == 0; |
| + return base_q_idx == 0 && delta_q_y_dc == 0 && delta_q_uv_dc == 0 && |
| + delta_q_uv_ac == 0; |
| } |
| - uint8_t base_qindex; |
| - int8_t y_dc_delta; |
| - int8_t uv_dc_delta; |
| - int8_t uv_ac_delta; |
| + uint8_t base_q_idx; |
| + int8_t delta_q_y_dc; |
| + int8_t delta_q_uv_dc; |
| + int8_t delta_q_uv_ac; |
| +}; |
| + |
| +// Entropy context for frame parsing |
| +struct MEDIA_EXPORT Vp9FrameContext { |
| + Vp9Prob tx_probs_8x8[2][1]; |
| + Vp9Prob tx_probs_16x16[2][2]; |
| + Vp9Prob tx_probs_32x32[2][3]; |
| + |
| + Vp9Prob coef_probs[4][2][2][6][6][3]; |
| + Vp9Prob skip_prob[3]; |
| + Vp9Prob inter_mode_probs[7][3]; |
| + Vp9Prob interp_filter_probs[4][2]; |
| + Vp9Prob is_inter_prob[4]; |
| + |
| + Vp9Prob comp_mode_prob[5]; |
| + Vp9Prob single_ref_prob[5][2]; |
| + Vp9Prob comp_ref_prob[5]; |
| + |
| + Vp9Prob y_mode_probs[4][9]; |
| + Vp9Prob uv_mode_probs[10][9]; |
| + Vp9Prob partition_probs[16][3]; |
| + |
| + Vp9Prob mv_joint_probs[3]; |
| + Vp9Prob mv_sign_prob[2]; |
| + Vp9Prob mv_class_probs[2][10]; |
| + Vp9Prob mv_class0_bit_prob[2]; |
| + Vp9Prob mv_bits_prob[2][10]; |
| + Vp9Prob mv_class0_fr_probs[2][2][3]; |
| + Vp9Prob mv_fr_probs[2][3]; |
| + Vp9Prob mv_class0_hp_prob[2]; |
| + Vp9Prob mv_hp_prob[2]; |
| +}; |
| + |
| +struct MEDIA_EXPORT Vp9CompressedHeader { |
| + enum Vp9TxMode { |
| + ONLY_4X4 = 0, |
| + ALLOW_8X8 = 1, |
| + ALLOW_16X16 = 2, |
| + ALLOW_32X32 = 3, |
| + TX_MODE_SELECT = 4, |
| + TX_MODES = 5, |
| + }; |
| + |
| + Vp9TxMode tx_mode; |
| + Vp9ReferenceMode reference_mode; |
| }; |
| // VP9 frame header. |
| @@ -130,12 +187,15 @@ struct MEDIA_EXPORT Vp9FrameHeader { |
| }; |
| bool IsKeyframe() const; |
| - bool RefreshFlag(size_t i) const { return !!(refresh_flags & (1u << i)); } |
| + bool IsIntra() const; |
| + bool RefreshFlag(size_t i) const { |
| + return !!(refresh_frame_flags & (1u << i)); |
| + } |
| uint8_t profile; |
| bool show_existing_frame; |
| - uint8_t frame_to_show; |
| + uint8_t frame_to_show_map_idx; |
| FrameType frame_type; |
| @@ -144,32 +204,35 @@ struct MEDIA_EXPORT Vp9FrameHeader { |
| uint8_t bit_depth; |
| Vp9ColorSpace color_space; |
| - bool yuv_range; |
| + bool color_range; |
| uint8_t subsampling_x; |
| uint8_t subsampling_y; |
| - // The range of width and height is 1..2^16. |
| - uint32_t width; |
| - uint32_t height; |
| - uint32_t display_width; |
| - uint32_t display_height; |
| + // The range of frame_width and frame_height is 1..2^16. |
| + uint32_t frame_width; |
| + uint32_t frame_height; |
| + uint32_t render_width; |
| + uint32_t render_height; |
| bool intra_only; |
| - uint8_t reset_context; |
| - uint8_t refresh_flags; |
| - uint8_t frame_refs[kVp9NumRefsPerFrame]; |
| - bool ref_sign_biases[kVp9NumRefsPerFrame]; |
| + uint8_t reset_frame_context; |
| + uint8_t refresh_frame_flags; |
| + uint8_t ref_frame_idx[kVp9NumRefsPerFrame]; |
| + bool ref_frame_sign_bias[Vp9RefType::VP9_FRAME_MAX]; |
| bool allow_high_precision_mv; |
| - Vp9InterpFilter interp_filter; |
| + Vp9InterpolationFilter interpolation_filter; |
| bool refresh_frame_context; |
| bool frame_parallel_decoding_mode; |
| uint8_t frame_context_idx; |
| + // |frame_context_idx_to_save_probs| is to be used by save_probs() only, and |
| + // |frame_context_idx| otherwise. |
| + uint8_t frame_context_idx_to_save_probs; |
| Vp9QuantizationParams quant_params; |
| - uint8_t log2_tile_cols; |
| - uint8_t log2_tile_rows; |
| + uint8_t tile_cols_log2; |
| + uint8_t tile_rows_log2; |
| // Pointer to the beginning of frame data. It is a responsibility of the |
| // client of the Vp9Parser to maintain validity of this data while it is |
| @@ -180,10 +243,51 @@ struct MEDIA_EXPORT Vp9FrameHeader { |
| size_t frame_size; |
| // Size of compressed header in bytes. |
| - size_t first_partition_size; |
| + size_t header_size_in_bytes; |
| // Size of uncompressed header in bytes. |
| size_t uncompressed_header_size; |
| + |
| + Vp9CompressedHeader compressed_header; |
| + // Initial frame entropy context after load_probs2(frame_context_idx). |
| + Vp9FrameContext initial_frame_context; |
| + // Current frame entropy context after header parsing. |
| + Vp9FrameContext frame_context; |
| +}; |
| + |
| +class Vp9FrameContextManager { |
| + public: |
| + // The callback returned to parser's client if we need context update from |
| + // the client.. |
|
Pawel Osciak
2016/08/08 08:13:37
If context update is needed after decoding a frame
kcwu
2016/08/09 04:29:43
Done.
|
| + using ContextRefreshCallback = base::Callback<void(const Vp9FrameContext&)>; |
| + |
| + static bool IsValidFrameContext(const Vp9FrameContext& context); |
| + |
| + Vp9FrameContextManager(); |
| + ~Vp9FrameContextManager(); |
| + bool initialized() const { return initialized_; } |
| + bool needs_client_update() const { return needs_client_update_; } |
| + const Vp9FrameContext& frame_context() const; |
| + |
| + // Resets to uninitialized state. |
| + void Reset(); |
| + |
| + // Sets this context need update from parser's client. Returns a callback for |
| + // update. |
| + ContextRefreshCallback SetNeedsClientUpdate(); |
| + |
| + // Updates frame context. |
| + void Update(const Vp9FrameContext& frame_context); |
| + |
| + private: |
| + // Updates frame context from parser's client. |
| + void UpdateFromClient(const Vp9FrameContext& frame_context); |
| + |
| + bool initialized_; |
| + bool needs_client_update_; |
| + Vp9FrameContext frame_context_; |
| + |
| + base::WeakPtrFactory<Vp9FrameContextManager> weak_ptr_factory_; |
| }; |
| // A parser for VP9 bitstream. |
| @@ -194,9 +298,40 @@ class MEDIA_EXPORT Vp9Parser { |
| kOk, |
| kInvalidStream, |
| kEOStream, |
| + kAwaitingRefresh, |
| + }; |
| + |
| + // The parsing context to keep track of references. |
| + struct ReferenceSlot { |
| + bool initialized; |
| + uint32_t frame_width; |
| + uint32_t frame_height; |
| + uint8_t subsampling_x; |
| + uint8_t subsampling_y; |
| + uint8_t bit_depth; |
| + |
| + // More fields for consistency checking. |
| + uint8_t profile; |
| + Vp9ColorSpace color_space; |
| + }; |
| + |
| + // The parsing context that persists across frames. |
| + struct Context { |
| + void Reset(); |
| + |
| + // Segmentation and loop filter state. |
| + Vp9SegmentationParams segmentation; |
| + Vp9LoopFilterParams loop_filter; |
| + |
| + // Frame references. |
| + ReferenceSlot ref_slots[kVp9NumRefFrames]; |
| + |
| + Vp9FrameContextManager frame_context_managers[kVp9NumFrameContexts]; |
| }; |
| - Vp9Parser(); |
| + // The constructor. See ParseNextFrame() for comments for |
| + // |parsing_compressed_header|. |
| + explicit Vp9Parser(bool parsing_compressed_header); |
| ~Vp9Parser(); |
| // Set a new stream buffer to read from, starting at |stream| and of size |
| @@ -207,51 +342,54 @@ class MEDIA_EXPORT Vp9Parser { |
| // Parse the next frame in the current stream buffer, filling |fhdr| with |
| // the parsed frame header and updating current segmentation and loop filter |
| - // state. Return kOk if a frame has successfully been parsed, kEOStream if |
| - // there is no more data in the current stream buffer, or kInvalidStream |
| - // on error. |
| - Result ParseNextFrame(Vp9FrameHeader* fhdr); |
| + // state. If |parsing_compressed_header_|, this function also fills |
| + // |context_refresh_cb|, which is used to update frame context. If |
| + // |*context_refresh_cb| is null, no callback is necessary. |
| + // Return kOk if a frame has successfully been parsed, |
| + // kEOStream if there is no more data in the current stream buffer, |
| + // kAwaitingRefresh if this frame awaiting frame context update, or |
| + // kInvalidStream on error. |
| + Result ParseNextFrame( |
| + Vp9FrameHeader* fhdr, |
| + Vp9FrameContextManager::ContextRefreshCallback* context_refresh_cb); |
| // Return current segmentation state. |
| - const Vp9Segmentation& GetSegmentation() const { return segmentation_; } |
| + const Vp9SegmentationParams& GetSegmentation() const { |
| + return context_.segmentation; |
| + } |
| // Return current loop filter state. |
| - const Vp9LoopFilter& GetLoopFilter() const { return loop_filter_; } |
| + const Vp9LoopFilterParams& GetLoopFilter() const { |
| + return context_.loop_filter; |
| + } |
| // Clear parser state and return to an initialized state. |
| void Reset(); |
| private: |
| - // The parsing context to keep track of references. |
| - struct ReferenceSlot { |
| - uint32_t width; |
| - uint32_t height; |
| + class UncompressedHeaderParser; |
| + class CompressedHeaderParser; |
| + |
| + // Stores start pointer and size of each frame within the current superframe. |
| + struct FrameInfo { |
| + FrameInfo() = default; |
| + FrameInfo(const uint8_t* ptr, off_t size); |
| + bool IsValid() const { return ptr != nullptr; } |
| + void Reset() { ptr = nullptr; } |
| + |
| + // Starting address of the frame. |
| + const uint8_t* ptr = nullptr; |
| + |
| + // Size of the frame in bytes. |
| + off_t size = 0; |
| }; |
| - bool ParseSuperframe(); |
| - uint8_t ReadProfile(); |
| - bool VerifySyncCode(); |
| - bool ReadBitDepthColorSpaceSampling(Vp9FrameHeader* fhdr); |
| - void ReadFrameSize(Vp9FrameHeader* fhdr); |
| - bool ReadFrameSizeFromRefs(Vp9FrameHeader* fhdr); |
| - void ReadDisplayFrameSize(Vp9FrameHeader* fhdr); |
| - Vp9InterpFilter ReadInterpFilter(); |
| - void ReadLoopFilter(); |
| - void ReadQuantization(Vp9QuantizationParams* quants); |
| - void ReadSegmentationMap(); |
| - void ReadSegmentationData(); |
| - void ReadSegmentation(); |
| - void ReadTiles(Vp9FrameHeader* fhdr); |
| - bool ParseUncompressedHeader(const uint8_t* stream, |
| - off_t frame_size, |
| - Vp9FrameHeader* fhdr); |
| - void UpdateSlots(const Vp9FrameHeader* fhdr); |
| - |
| - void ResetLoopfilter(); |
| - void SetupPastIndependence(); |
| + std::deque<FrameInfo> ParseSuperframe(); |
| + |
| size_t GetQIndex(const Vp9QuantizationParams& quant, size_t segid) const; |
| - void SetupSegmentationDequant(const Vp9QuantizationParams& quant); |
| + void SetupSegmentationDequant(); |
| void SetupLoopFilter(); |
| + void UpdateSlots(); |
| // Current address in the bitstream buffer. |
| const uint8_t* stream_; |
| @@ -259,29 +397,15 @@ class MEDIA_EXPORT Vp9Parser { |
| // Remaining bytes in stream_. |
| off_t bytes_left_; |
| - // Stores start pointer and size of each frame within the current superframe. |
| - struct FrameInfo { |
| - FrameInfo(const uint8_t* ptr, off_t size); |
| - |
| - // Starting address of the frame. |
| - const uint8_t* ptr; |
| - |
| - // Size of the frame in bytes. |
| - off_t size; |
| - }; |
| + bool parsing_compressed_header_; |
| // FrameInfo for the remaining frames in the current superframe to be parsed. |
| std::deque<FrameInfo> frames_; |
| - // Raw bits decoder for uncompressed frame header. |
| - Vp9RawBitsReader reader_; |
| - |
| - // Segmentation and loop filter state that persists across frames. |
| - Vp9Segmentation segmentation_; |
| - Vp9LoopFilter loop_filter_; |
| + Context context_; |
| - // The parsing context to keep track of references. |
| - ReferenceSlot ref_slots_[kVp9NumRefFrames]; |
| + FrameInfo curr_frame_info_; |
| + Vp9FrameHeader curr_frame_header_; |
| DISALLOW_COPY_AND_ASSIGN(Vp9Parser); |
| }; |