Chromium Code Reviews| Index: media/filters/vp9_parser.h |
| diff --git a/media/filters/vp9_parser.h b/media/filters/vp9_parser.h |
| index 877043179096747e3cc30ba2aaa7bac9117d5df2..57c93b0c9539bcb6b908b5e0e3b9a8d8810d156b 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, |
|
kcwu
2015/08/31 09:58:35
ah, sorry for the bug
Pawel Osciak
2015/09/08 06:43:49
No worries.
|
| 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 && |
| @@ -118,6 +129,7 @@ struct MEDIA_EXPORT Vp9FrameHeader { |
| }; |
| bool IsKeyframe() const { return frame_type == KEYFRAME; } |
| + bool RefreshFlag(size_t i) const { return refresh_flags & (1u << i); } |
|
kcwu
2015/08/31 09:58:35
|reader_| is big endian and MSB first inside integ
Pawel Osciak
2015/09/08 06:43:49
Yes, I was surprised too, but spec and libvpx both
|
| 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,33 @@ 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(); |
| - // 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); |
| + // 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); |
| + |
| + // Return current segmentation state. |
| + const Vp9Segmentation& GetSegmentation() const { return segmentation_; } |
| + |
| + // Return current loop filter state. |
| + const Vp9LoopFilter& GetLoopFilter() const { return loop_filter_; } |
| private: |
| // The parsing context to keep track of references. |
| @@ -184,6 +223,7 @@ class MEDIA_EXPORT Vp9Parser { |
| uint32_t height; |
| }; |
| + bool ParseSuperframe(); |
| uint8_t ReadProfile(); |
| bool VerifySyncCode(); |
| bool ReadBitDepthColorSpaceSampling(Vp9FrameHeader* fhdr); |
| @@ -191,24 +231,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]; |