Index: media/filters/vp9_parser.h |
diff --git a/media/filters/vp9_parser.h b/media/filters/vp9_parser.h |
index 877043179096747e3cc30ba2aaa7bac9117d5df2..5724ae91498b4f4a63df6d43701027a4150726b8 100644 |
--- a/media/filters/vp9_parser.h |
+++ b/media/filters/vp9_parser.h |
@@ -7,29 +7,16 @@ |
// accelerators, e.g. libva which implements VA-API, require the caller |
// (chrome) to feed them parsed VP9 frame header. |
// |
-// Example usage: |
-// { |
-// Vp9Parser parser; |
-// uint8_t* frame_stream; |
-// size_t frame_size; |
+// See content::VP9Decoder for example usage. |
// |
-// // Get frames from, say, WebM parser or IVF parser. |
-// while (GetVp9Frame(&frame_stream, &frame_size)) { |
-// Vp9FrameHeader header; |
-// if (!parser.ParseFrame(frame_stream, frame_size, &header)) { |
-// // Parse failed. |
-// return false; |
-// } |
-// // Got a frame parsed successfully. |
-// } |
-// } |
- |
#ifndef MEDIA_FILTERS_VP9_PARSER_H_ |
#define MEDIA_FILTERS_VP9_PARSER_H_ |
#include <stddef.h> |
#include <stdint.h> |
+#include <deque> |
+ |
#include "base/macros.h" |
#include "media/base/media_export.h" |
#include "media/filters/vp9_raw_bits_reader.h" |
@@ -38,9 +25,9 @@ namespace media { |
const int kVp9MaxProfile = 4; |
const int kVp9NumRefFramesLog2 = 3; |
-const int kVp9NumRefFrames = 1 << kVp9NumRefFramesLog2; |
+const size_t kVp9NumRefFrames = 1 << kVp9NumRefFramesLog2; |
const uint8_t kVp9MaxProb = 255; |
-const int kVp9NumRefsPerFrame = 3; |
+const size_t kVp9NumRefsPerFrame = 3; |
enum class Vp9ColorSpace { |
UNKNOWN = 0, |
@@ -53,20 +40,25 @@ enum class Vp9ColorSpace { |
SRGB = 7, |
}; |
-enum class Vp9InterpFilter { |
- INTERP_FILTER_SELECT = 0, |
+enum Vp9InterpFilter { |
+ EIGHTTAP = 0, |
EIGHTTAP_SMOOTH = 1, |
- EIGHTTAP = 2, |
- EIGHTTAP_SHARP = 3, |
- BILINEAR = 4, |
+ EIGHTTAP_SHARP = 2, |
+ BILINEAR = 3, |
+ SWICHABLE = 4, |
}; |
-// Members of Vp9FrameHeader will be 0-initialized by Vp9Parser::ParseFrame. |
struct MEDIA_EXPORT Vp9Segmentation { |
- static const int kNumSegments = 8; |
- static const int kNumTreeProbs = kNumSegments - 1; |
- static const int kNumPredictionProbs = 3; |
- static const int kNumFeatures = 4; |
+ static const size_t kNumSegments = 8; |
+ static const size_t kNumTreeProbs = kNumSegments - 1; |
+ static const size_t kNumPredictionProbs = 3; |
+ enum SegmentLevelFeature { |
+ SEG_LVL_ALT_Q = 0, |
+ SEG_LVL_ALT_LF = 1, |
+ SEG_LVL_REF_FRAME = 2, |
+ SEG_LVL_SKIP = 3, |
+ SEG_LVL_MAX |
+ }; |
bool enabled; |
@@ -77,27 +69,46 @@ struct MEDIA_EXPORT Vp9Segmentation { |
bool update_data; |
bool abs_delta; |
- bool feature_enabled[kNumSegments][kNumFeatures]; |
- int8_t feature_data[kNumSegments][kNumFeatures]; |
+ bool feature_enabled[kNumSegments][SEG_LVL_MAX]; |
+ int8_t feature_data[kNumSegments][SEG_LVL_MAX]; |
+ |
+ int16_t y_dequant[kNumSegments][2]; |
+ int16_t uv_dequant[kNumSegments][2]; |
+ |
+ bool FeatureEnabled(size_t seg_id, SegmentLevelFeature feature) const { |
+ return feature_enabled[seg_id][feature]; |
+ } |
+ |
+ int8_t FeatureData(size_t seg_id, SegmentLevelFeature feature) const { |
+ return feature_data[seg_id][feature]; |
+ } |
}; |
-// Members of Vp9FrameHeader will be 0-initialized by Vp9Parser::ParseFrame. |
struct MEDIA_EXPORT Vp9LoopFilter { |
- static const int kNumRefDeltas = 4; |
- static const int kNumModeDeltas = 2; |
+ enum Vp9FrameType { |
+ VP9_FRAME_INTRA = 0, |
+ VP9_FRAME_LAST = 1, |
+ VP9_FRAME_GOLDEN = 2, |
+ VP9_FRAME_ALTREF = 3, |
+ VP9_FRAME_MAX = 4, |
+ }; |
+ |
+ static const size_t kNumModeDeltas = 2; |
uint8_t filter_level; |
uint8_t sharpness_level; |
bool mode_ref_delta_enabled; |
bool mode_ref_delta_update; |
- bool update_ref_deltas[kNumRefDeltas]; |
- int8_t ref_deltas[kNumRefDeltas]; |
+ 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]; |
}; |
-// Members of Vp9FrameHeader will be 0-initialized by Vp9Parser::ParseFrame. |
+// 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 && |
@@ -117,7 +128,8 @@ struct MEDIA_EXPORT Vp9FrameHeader { |
INTERFRAME = 1, |
}; |
- bool IsKeyframe() const { return frame_type == KEYFRAME; } |
+ bool IsKeyframe() const; |
+ bool RefreshFlag(size_t i) const { return !!(refresh_flags & (1u << i)); } |
uint8_t profile; |
@@ -143,7 +155,7 @@ struct MEDIA_EXPORT Vp9FrameHeader { |
bool intra_only; |
uint8_t reset_context; |
- bool refresh_flag[kVp9NumRefFrames]; |
+ uint8_t refresh_flags; |
uint8_t frame_refs[kVp9NumRefsPerFrame]; |
bool ref_sign_biases[kVp9NumRefsPerFrame]; |
bool allow_high_precision_mv; |
@@ -153,13 +165,19 @@ struct MEDIA_EXPORT Vp9FrameHeader { |
bool frame_parallel_decoding_mode; |
uint8_t frame_context_idx; |
- Vp9LoopFilter loop_filter; |
Vp9QuantizationParams quant_params; |
- Vp9Segmentation segment; |
uint8_t log2_tile_cols; |
uint8_t log2_tile_rows; |
+ // 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 |
+ // being used outside of that class. |
+ const uint8_t* data; |
+ |
+ // Size of |data| in bytes. |
+ size_t frame_size; |
+ |
// Size of compressed header in bytes. |
size_t first_partition_size; |
@@ -170,12 +188,37 @@ struct MEDIA_EXPORT Vp9FrameHeader { |
// A parser for VP9 bitstream. |
class MEDIA_EXPORT Vp9Parser { |
public: |
+ // ParseNextFrame() return values. See documentation for ParseNextFrame(). |
+ enum Result { |
+ kOk, |
+ kInvalidStream, |
+ kEOStream, |
+ }; |
+ |
Vp9Parser(); |
+ ~Vp9Parser(); |
+ |
+ // Set a new stream buffer to read from, starting at |stream| and of size |
+ // |stream_size| in bytes. |stream| must point to the beginning of a single |
+ // frame or a single superframe, is owned by caller and must remain valid |
+ // until the next call to SetStream(). |
+ void SetStream(const uint8_t* stream, off_t stream_size); |
+ |
+ // 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); |
- // Parses one frame and fills parsing result to |fhdr|. Returns true on |
- // success, false otherwise. |
- // |stream| is the address of VP9 bitstream with |size|. |
- bool ParseFrame(const uint8_t* stream, size_t size, Vp9FrameHeader* fhdr); |
+ // Return current segmentation state. |
+ const Vp9Segmentation& GetSegmentation() const { return segmentation_; } |
+ |
+ // Return current loop filter state. |
+ const Vp9LoopFilter& GetLoopFilter() const { return loop_filter_; } |
+ |
+ // Clear parser state and return to an initialized state. |
+ void Reset(); |
private: |
// The parsing context to keep track of references. |
@@ -184,6 +227,7 @@ class MEDIA_EXPORT Vp9Parser { |
uint32_t height; |
}; |
+ bool ParseSuperframe(); |
uint8_t ReadProfile(); |
bool VerifySyncCode(); |
bool ReadBitDepthColorSpaceSampling(Vp9FrameHeader* fhdr); |
@@ -191,24 +235,50 @@ class MEDIA_EXPORT Vp9Parser { |
bool ReadFrameSizeFromRefs(Vp9FrameHeader* fhdr); |
void ReadDisplayFrameSize(Vp9FrameHeader* fhdr); |
Vp9InterpFilter ReadInterpFilter(); |
- void ReadLoopFilter(Vp9LoopFilter* loop_filter); |
+ void ReadLoopFilter(); |
void ReadQuantization(Vp9QuantizationParams* quants); |
- void ReadSegmentationMap(Vp9Segmentation* segment); |
- void ReadSegmentationData(Vp9Segmentation* segment); |
- void ReadSegmentation(Vp9Segmentation* segment); |
+ void ReadSegmentationMap(); |
+ void ReadSegmentationData(); |
+ void ReadSegmentation(); |
void ReadTiles(Vp9FrameHeader* fhdr); |
- bool ParseUncompressedHeader(Vp9FrameHeader* fhdr); |
+ bool ParseUncompressedHeader(const uint8_t* stream, |
+ off_t frame_size, |
+ Vp9FrameHeader* fhdr); |
void UpdateSlots(const Vp9FrameHeader* fhdr); |
- // Start address of VP9 bitstream buffer. |
+ void ResetLoopfilter(); |
+ void SetupPastIndependence(); |
+ size_t GetQIndex(const Vp9QuantizationParams& quant, size_t segid) const; |
+ void SetupSegmentationDequant(const Vp9QuantizationParams& quant); |
+ void SetupLoopFilter(); |
+ |
+ // Current address in the bitstream buffer. |
const uint8_t* stream_; |
- // Size of |stream_| in bytes. |
- size_t size_; |
+ // 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; |
+ }; |
+ |
+ // 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_; |
+ |
// The parsing context to keep track of references. |
ReferenceSlot ref_slots_[kVp9NumRefFrames]; |