Index: media/filters/vp9_parser.h |
diff --git a/media/filters/vp9_parser.h b/media/filters/vp9_parser.h |
index 4d430494170f48dae739febfd283fee09750f50b..acb88d7e76a443cfc12ac6ff20238ecc1699fd53 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: |
+ // If context update is needed after decoding a frame, the client must |
+ // execute this callback, passing the updated context state. |
+ 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_ = false; |
+ bool needs_client_update_ = false; |
+ 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); |
}; |