// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // This file contains an implementation of a VP9 bitstream parser. The main // purpose of this parser is to support hardware decode acceleration. Some // 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; // // // 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 #include #include "base/macros.h" #include "media/base/media_export.h" #include "media/filters/vp9_raw_bits_reader.h" namespace media { const int kVp9MaxProfile = 4; const int kVp9NumRefFramesLog2 = 3; const int kVp9NumRefFrames = 1 << kVp9NumRefFramesLog2; const uint8_t kVp9MaxProb = 255; const int kVp9NumRefsPerFrame = 3; enum class Vp9ColorSpace { UNKNOWN = 0, BT_601 = 1, BT_709 = 2, SMPTE_170 = 3, SMPTE_240 = 4, BT_2020 = 5, RESERVED = 6, SRGB = 7, }; enum class Vp9InterpFilter { INTERP_FILTER_SELECT = 0, EIGHTTAP_SMOOTH = 1, EIGHTTAP = 2, EIGHTTAP_SHARP = 3, BILINEAR = 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; bool enabled; bool update_map; uint8_t tree_probs[kNumTreeProbs]; bool temporal_update; uint8_t pred_probs[kNumPredictionProbs]; bool update_data; bool abs_delta; bool feature_enabled[kNumSegments][kNumFeatures]; int8_t feature_data[kNumSegments][kNumFeatures]; }; // Members of Vp9FrameHeader will be 0-initialized by Vp9Parser::ParseFrame. struct MEDIA_EXPORT Vp9LoopFilter { static const int kNumRefDeltas = 4; static const int 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_mode_deltas[kNumModeDeltas]; int8_t mode_deltas[kNumModeDeltas]; }; // Members of Vp9FrameHeader will be 0-initialized by Vp9Parser::ParseFrame. struct MEDIA_EXPORT Vp9QuantizationParams { bool IsLossless() const { return base_qindex == 0 && y_dc_delta == 0 && uv_dc_delta == 0 && uv_ac_delta == 0; } uint8_t base_qindex; int8_t y_dc_delta; int8_t uv_dc_delta; int8_t uv_ac_delta; }; // VP9 frame header. struct MEDIA_EXPORT Vp9FrameHeader { enum FrameType { KEYFRAME = 0, INTERFRAME = 1, }; bool IsKeyframe() const { return frame_type == KEYFRAME; } uint8_t profile; bool show_existing_frame; uint8_t frame_to_show; FrameType frame_type; bool show_frame; bool error_resilient_mode; uint8_t bit_depth; Vp9ColorSpace color_space; bool yuv_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; bool intra_only; uint8_t reset_context; bool refresh_flag[kVp9NumRefFrames]; uint8_t frame_refs[kVp9NumRefsPerFrame]; bool ref_sign_biases[kVp9NumRefsPerFrame]; bool allow_high_precision_mv; Vp9InterpFilter interp_filter; bool refresh_frame_context; 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; // Size of compressed header in bytes. size_t first_partition_size; // Size of uncompressed header in bytes. size_t uncompressed_header_size; }; // A parser for VP9 bitstream. class MEDIA_EXPORT Vp9Parser { public: 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); private: // The parsing context to keep track of references. struct ReferenceSlot { uint32_t width; uint32_t height; }; 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(Vp9LoopFilter* loop_filter); void ReadQuantization(Vp9QuantizationParams* quants); void ReadSegmentationMap(Vp9Segmentation* segment); void ReadSegmentationData(Vp9Segmentation* segment); void ReadSegmentation(Vp9Segmentation* segment); void ReadTiles(Vp9FrameHeader* fhdr); bool ParseUncompressedHeader(Vp9FrameHeader* fhdr); void UpdateSlots(const Vp9FrameHeader* fhdr); // Start address of VP9 bitstream buffer. const uint8_t* stream_; // Size of |stream_| in bytes. size_t size_; // Raw bits decoder for uncompressed frame header. Vp9RawBitsReader reader_; // The parsing context to keep track of references. ReferenceSlot ref_slots_[kVp9NumRefFrames]; DISALLOW_COPY_AND_ASSIGN(Vp9Parser); }; } // namespace media #endif // MEDIA_FILTERS_VP9_PARSER_H_