diff --git a/api/rocdecode.h b/api/rocdecode.h index a5971e4c54..d3506e1ec5 100644 --- a/api/rocdecode.h +++ b/api/rocdecode.h @@ -394,7 +394,7 @@ typedef struct _RocdecVc1PicParams { } RocdecVc1PicParams; /***********************************************************/ -//! \struct RocdecAvcPicParams placeholder +//! \struct RocdecAvcPicParams //! \ingroup group_amd_rocdecode //! AVC picture parameters //! This structure is used in RocdecAvcPicParams structure @@ -454,7 +454,7 @@ typedef struct _RocdecAvcPicParams { } RocdecAvcPicParams; /***********************************************************/ -//! \struct RocdecAvcSliceParams placeholder +//! \struct RocdecAvcSliceParams //! \ingroup group_amd_rocdecode //! AVC slice parameter buffer //! This structure is configured to be the same as VA-API VASliceParameterBufferH264 structure @@ -504,7 +504,7 @@ typedef struct _RocdecAvcSliceParams { } RocdecAvcSliceParams; /***********************************************************/ -//! \struct RocdecAvcIQMatrix placeholder +//! \struct RocdecAvcIQMatrix //! \ingroup group_amd_rocdecode //! AVC Inverse Quantization Matrix //! This structure is configured to be the same as VA-API VAIQMatrixBufferH264 structure @@ -776,6 +776,242 @@ typedef struct _RocdecHevcIQMatrix { uint32_t reserved[4]; } RocdecHevcIQMatrix; +/***********************************************************/ +//! \struct RocdecVp9PicParams +//! \ingroup group_amd_rocdecode +//! VP9 picture parameters +//! This structure is configured to be the same as VA-API VADecPictureParameterBufferVP9 structure. +/***********************************************************/ +typedef struct _RocdecVp9PicParams { + /** \brief picture width + * Picture original resolution. The value may not be multiple of 8. + */ + uint16_t frame_width; + /** \brief picture height + * Picture original resolution. The value may not be multiple of 8. + */ + uint16_t frame_height; + + /** \brief Surface indices of reference frames in DPB. + * + * Each entry of the list specifies the surface index of the picture + * that is referred by current picture or will be referred by any future + * picture. + * Application who calls this API should update this list based on the + * refreshing information from VP9 bitstream. + */ + uint32_t reference_frames[8]; + + union { + struct { + /** \brief flags for current picture + * same syntax and semantic as those in VP9 code + */ + uint32_t subsampling_x : 1; + uint32_t subsampling_y : 1; + uint32_t frame_type : 1; + uint32_t show_frame : 1; + uint32_t error_resilient_mode : 1; + uint32_t intra_only : 1; + uint32_t allow_high_precision_mv : 1; + uint32_t mcomp_filter_type : 3; + uint32_t frame_parallel_decoding_mode : 1; + uint32_t reset_frame_context : 2; + uint32_t refresh_frame_context : 1; + uint32_t frame_context_idx : 2; + uint32_t segmentation_enabled : 1; + + /** \brief corresponds to variable temporal_update in VP9 code. + */ + uint32_t segmentation_temporal_update : 1; + /** \brief corresponds to variable update_mb_segmentation_map + * in VP9 code. + */ + uint32_t segmentation_update_map : 1; + + /** \brief Index of reference_frames[] and points to the + * LAST reference frame. + * It corresponds to active_ref_idx[0] in VP9 code. + */ + uint32_t last_ref_frame : 3; + /** \brief Sign Bias of the LAST reference frame. + * It corresponds to ref_frame_sign_bias[LAST_FRAME] in VP9 code. + */ + uint32_t last_ref_frame_sign_bias : 1; + /** \brief Index of reference_frames[] and points to the + * GOLDERN reference frame. + * It corresponds to active_ref_idx[1] in VP9 code. + */ + uint32_t golden_ref_frame : 3; + /** \brief Sign Bias of the GOLDERN reference frame. + * Corresponds to ref_frame_sign_bias[GOLDERN_FRAME] in VP9 code. + */ + uint32_t golden_ref_frame_sign_bias : 1; + /** \brief Index of reference_frames[] and points to the + * ALTERNATE reference frame. + * Corresponds to active_ref_idx[2] in VP9 code. + */ + uint32_t alt_ref_frame : 3; + /** \brief Sign Bias of the ALTERNATE reference frame. + * Corresponds to ref_frame_sign_bias[ALTREF_FRAME] in VP9 code. + */ + uint32_t alt_ref_frame_sign_bias : 1; + /** \brief Lossless Mode + * LosslessFlag = base_qindex == 0 && + * y_dc_delta_q == 0 && + * uv_dc_delta_q == 0 && + * uv_ac_delta_q == 0; + * Where base_qindex, y_dc_delta_q, uv_dc_delta_q and uv_ac_delta_q + * are all variables in VP9 code. + */ + uint32_t lossless_flag : 1; + } bits; + uint32_t value; + } pic_fields; + + /* following parameters have same syntax with those in VP9 code */ + uint8_t filter_level; + uint8_t sharpness_level; + + /** \brief number of tile rows specified by (1 << log2_tile_rows). + * It corresponds the variable with same name in VP9 code. + */ + uint8_t log2_tile_rows; + /** \brief number of tile columns specified by (1 << log2_tile_columns). + * It corresponds the variable with same name in VP9 code. + */ + uint8_t log2_tile_columns; + /** \brief Number of bytes taken up by the uncompressed frame header, + * which corresponds to byte length of function + * read_uncompressed_header() in VP9 code. + * Specifically, it is the byte count from bit stream buffer start to + * the last byte of uncompressed frame header. + * If there are other meta data in the buffer before uncompressed header, + * its size should be also included here. + */ + uint8_t frame_header_length_in_bytes; + + /** \brief The byte count of compressed header the bitstream buffer, + * which corresponds to syntax first_partition_size in code. + */ + uint16_t first_partition_size; + + /** These values are segment probabilities with same names in VP9 + * function setup_segmentation(). They should be parsed directly from + * bitstream by application. + */ + uint8_t mb_segment_tree_probs[7]; + uint8_t segment_pred_probs[3]; + + /** \brief VP9 Profile definition + * value range [0..3]. + */ + uint8_t profile; + + /** \brief VP9 bit depth per sample + * same for both luma and chroma samples. + */ + uint8_t bit_depth; + + /** \brief Reserved bytes for future use, must be zero */ + uint32_t va_reserved[8]; + +} RocdecVp9PicParams; + +/** + * \brief VP9 Segmentation Parameter Data Structure + * This structure is configured to be the same as VA-API VASegmentParameterVP9 structure. + */ +typedef struct _RocdecVp9SegmentParameter { + union { + struct { + /** \brief Indicates if per segment reference frame indicator + * is enabled. + * Corresponding to variable feature_enabled when + * j == SEG_LVL_REF_FRAME in function setup_segmentation() VP9 code. + */ + uint16_t segment_reference_enabled : 1; + /** \brief Specifies per segment reference indication. + * 0: reserved + * 1: Last ref + * 2: golden + * 3: altref + * Value can be derived from variable data when + * j == SEG_LVL_REF_FRAME in function setup_segmentation() VP9 code. + */ + uint16_t segment_reference : 2; + /** \brief Indicates if per segment skip feature is enabled. + * Corresponding to variable feature_enabled when + * j == SEG_LVL_SKIP in function setup_segmentation() VP9 code. + */ + uint16_t segment_reference_skipped : 1; + } fields; + uint16_t value; + } segment_flags; + + /** \brief Specifies the filter level information per segment. + * The value corresponds to variable lfi->lvl[seg][ref][mode] in VP9 code, + * where m is [ref], and n is [mode] in FilterLevel[m][n]. + */ + uint8_t filter_level[4][2]; + /** \brief Specifies per segment Luma AC quantization scale. + * Corresponding to y_dequant[qindex][1] in vp9_mb_init_quantizer() + * function of VP9 code. + */ + int16_t luma_ac_quant_scale; + /** \brief Specifies per segment Luma DC quantization scale. + * Corresponding to y_dequant[qindex][0] in vp9_mb_init_quantizer() + * function of VP9 code. + */ + int16_t luma_dc_quant_scale; + /** \brief Specifies per segment Chroma AC quantization scale. + * Corresponding to uv_dequant[qindex][1] in vp9_mb_init_quantizer() + * function of VP9 code. + */ + int16_t chroma_ac_quant_scale; + /** \brief Specifies per segment Chroma DC quantization scale. + * Corresponding to uv_dequant[qindex][0] in vp9_mb_init_quantizer() + * function of VP9 code. + */ + int16_t chroma_dc_quant_scale; + + /** \brief Reserved bytes for future use, must be zero */ + uint32_t va_reserved[4]; + +} RocdecVp9SegmentParameter; + +/***********************************************************/ +//! \struct RocdecVp9SliceParams +//! \ingroup group_amd_rocdecode +//! VP9 slice parameter buffer +//! This structure is configured to be the same as VA-API VASliceParameterBufferVP9 structure. +/***********************************************************/ +typedef struct _RocdecVp9SliceParams { + /** \brief The byte count of current frame in the bitstream buffer, + * starting from first byte of the buffer. + * It uses the name slice_data_size to be consitent with other codec, + * but actually means frame_data_size. + */ + uint32_t slice_data_size; + /** + * offset to the first byte of partition data (control partition) + */ + uint32_t slice_data_offset; + /** + * see VA_SLICE_DATA_FLAG_XXX definitions + */ + uint32_t slice_data_flag; + + /** + * \brief per segment information + */ + RocdecVp9SegmentParameter seg_param[8]; + + /** \brief Reserved bytes for future use, must be zero */ + uint32_t va_reserved[4]; + +} RocdecVp9SliceParams; + /** \brief Segmentation Information for AV1 */ typedef struct _RocdecAv1SegmentationStruct { @@ -1320,7 +1556,7 @@ typedef struct _RocdecAV1PicParams { } RocdecAv1PicParams; /***********************************************************/ -//! \struct RocdecAv1SliceParams placeholder +//! \struct RocdecAv1SliceParams //! \ingroup group_amd_rocdecode //! AV1 slice parameter buffer //! This structure is configured to be the same as VA-API VASliceParameterBufferAV1 structure. @@ -1397,6 +1633,7 @@ typedef struct _RocdecPicParams { RocdecHevcPicParams hevc; RocdecVc1PicParams vc1; RocdecJPEGPicParams jpeg; + RocdecVp9PicParams vp9; RocdecAv1PicParams av1; uint32_t codec_reserved[256]; } pic_params; @@ -1407,6 +1644,7 @@ typedef struct _RocdecPicParams { // Todo: Add slice params defines for other codecs. RocdecAvcSliceParams *avc; RocdecHevcSliceParams *hevc; + RocdecVp9SliceParams *vp9; RocdecAv1SliceParams *av1; } slice_params; diff --git a/src/parser/parser_handle.h b/src/parser/parser_handle.h index d623a71e71..0e7e50e717 100644 --- a/src/parser/parser_handle.h +++ b/src/parser/parser_handle.h @@ -28,6 +28,7 @@ THE SOFTWARE. #include "avc_parser.h" #include "av1_parser.h" #include "hevc_parser.h" +#include "vp9_parser.h" class RocParserHandle { public: @@ -51,6 +52,9 @@ private: case rocDecVideoCodec_HEVC: roc_parser_ = std::make_shared(); break; + case rocDecVideoCodec_VP9: + roc_parser_ = std::make_shared(); + break; case rocDecVideoCodec_AV1: roc_parser_ = std::make_shared(); break; diff --git a/src/parser/rocparser_api.cpp b/src/parser/rocparser_api.cpp index 2fa51f596c..c0bd9c9dec 100644 --- a/src/parser/rocparser_api.cpp +++ b/src/parser/rocparser_api.cpp @@ -36,6 +36,7 @@ rocDecCreateVideoParser(RocdecVideoParser *parser_handle, RocdecParserParams *pa if (parser_params->codec_type != rocDecVideoCodec_HEVC && parser_params->codec_type != rocDecVideoCodec_AVC && + parser_params->codec_type != rocDecVideoCodec_VP9 && parser_params->codec_type != rocDecVideoCodec_AV1) { ERR("The current version of rocDecode officially supports only the H.265 (HEVC), H.264 (AVC) and AV1 codecs."); return ROCDEC_NOT_IMPLEMENTED; diff --git a/src/parser/vp9_defines.h b/src/parser/vp9_defines.h new file mode 100644 index 0000000000..f895ce90d2 --- /dev/null +++ b/src/parser/vp9_defines.h @@ -0,0 +1,182 @@ +/* +Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#pragma once + +#include + +#define VP9_REFS_PER_FRAME 3 // Each inter frame can use up to 3 frames for reference +#define VP9_NUM_REF_FRAMES 8 // Number of frames that can be stored for future reference +#define VP9_MAX_REF_FRAMES 4 // Number of values that can be derived for ref_frame +#define VP9_MAX_SEGMENTS 8 // Number of segments allowed in segmentation map +#define VP9_SEG_LVL_ALT_Q 0 // Index for quantizer segment feature +#define VP9_SEG_LVL_ALT_L 1 // Index for loop filter segment feature +#define VP9_SEG_LVL_REF_FRAME 2 // Index for reference frame segment feature +#define VP9_SEG_LVL_SKIP 3 // Index for skip segment feature +#define VP9_SEG_LVL_MAX 4 // Number of segment features +#define MIN_TILE_WIDTH_B64 4 // Minimum width of a tile in units of superblocks (although tiles on the right hand edge can be narrower) +#define MAX_TILE_WIDTH_B64 64 // Maximum width of a tile in units of superblocks +#define MAX_MODE_LF_DELTAS 2 // Number of different mode types for loop filtering +#define VP9_MAX_LOOP_FILTER 63 // Maximum value used for loop filtering + +typedef enum { + kVp9KeyFrame = 0, + kVp9NonKeyFrame = 1, +} Vp9FrameType; + +typedef enum { + CS_UNKNOWN = 0, // Unknown (in this case the color space must be signaled outside the VP9 bitstream). + CS_BT_601 = 1, // Rec. ITU-R BT.601-7 + CS_BT_709 = 2, // Rec. ITU-R BT.709-6 + CS_SMPTE_170 = 3, // SMPTE-170 + CS_SMPTE_240 = 4, // SMPTE-240 + CS_BT_2020 = 5, // Rec. ITU-R BT.2020-2 + CS_RESERVED = 6, // Reserved + CS_RGB = 7, // sRGB (IEC 61966-2-1) +} Vp9ColorSpace; + +typedef enum { + kStudioSwing = 0, // Studio video range + kFullSwing = 1, // Full video range +} Vp9ColorRange; + +typedef enum { + kVp9IntraFrame = 0, + kVp9LastFrame = 1, + kVp9GoldenFrame = 2, + kVp9AltRefFrame = 3, +} Vp9RefFrame; + +typedef enum { + kVp9EightTap = 0, + kVp9EightTapSmooth = 1, + kVp9EightTapSharp = 2, + kVp9Bilinear = 3, + kVp9Switchable = 4, +} Vp9InterpolotionFilterType; + +typedef struct { + uint8_t frame_sync_byte_0; + uint8_t frame_sync_byte_1; + uint8_t frame_sync_byte_2; +} Vp9FrameSyncCode; + +typedef struct { + uint8_t ten_or_twelve_bit; + uint8_t bit_depth; + uint8_t color_space; + uint8_t color_range; + uint8_t subsampling_x; + uint8_t subsampling_y; + uint8_t reserved_zero; +} Vp9ColorConfig; + +typedef struct { + uint16_t frame_width_minus_1; + uint16_t frame_height_minus_1; + uint32_t frame_width; + uint32_t frame_height; + uint16_t mi_cols; + uint16_t mi_rows; + uint16_t sb64_cols; + uint16_t sb64_rows; +} Vp9FrameSize; + +typedef struct { + uint8_t render_and_frame_size_different; + uint16_t render_width_minus_1; + uint16_t render_height_minus_1; + uint32_t render_width; + uint32_t render_height; +} Vp9RenderSize; + +typedef struct { + uint8_t loop_filter_level; + uint8_t loop_filter_sharpness; + uint8_t loop_filter_delta_enabled; + uint8_t loop_filter_delta_update; + uint8_t update_ref_delta[4]; + int8_t loop_filter_ref_deltas[4]; + uint8_t update_mode_delta[2]; + int8_t loop_filter_mode_deltas[2]; +} Vp9LoopFilterParams; + +typedef struct { + uint8_t base_q_idx; + int8_t delta_q_y_dc; + int8_t delta_q_uv_dc; + int8_t delta_q_uv_ac; + uint8_t lossless; +} Vp9QuantizationParams; + +typedef struct { + uint8_t segmentation_enabled; + uint8_t segmentation_update_map; + uint8_t segmentation_tree_probs[7]; + uint8_t segmentation_temporal_update; + uint8_t segmentation_pred_prob[3]; + uint8_t segmentation_update_data; + uint8_t segmentation_abs_or_delta_update; + uint8_t feature_enabled[VP9_MAX_SEGMENTS][VP9_SEG_LVL_MAX]; + int16_t feature_data[VP9_MAX_SEGMENTS][VP9_SEG_LVL_MAX]; +} Vp9SegmentationParams; + +typedef struct { + uint16_t min_log2_tile_cols; // minLog2TileCols + uint16_t max_log2_tile_cols; // maxLog2TileCols + uint8_t tile_cols_log2; + uint8_t tile_rows_log2; +} Vp9TileInfo; + +typedef struct { + uint8_t frame_marker; + uint8_t profile_low_bit; + uint8_t profile_high_bit; + uint8_t profile; + uint8_t reserved_zero; + uint8_t show_existing_frame; + uint8_t frame_to_show_map_idx; + uint8_t frame_type; + uint8_t show_frame; + uint8_t error_resilient_mode; + uint8_t intra_only; + uint8_t reset_frame_context; + Vp9FrameSyncCode frame_sync_code; + Vp9ColorConfig color_config; + Vp9FrameSize frame_size; + Vp9RenderSize render_size; + uint8_t refresh_frame_flags; + uint8_t ref_frame_idx[VP9_REFS_PER_FRAME]; + uint8_t ref_frame_sign_bias[VP9_MAX_REF_FRAMES]; + uint8_t allow_high_precision_mv; + uint8_t is_filter_switchable; + uint8_t raw_interpolation_filter; + uint8_t interpolation_filter; + uint8_t refresh_frame_context; + uint8_t frame_parallel_decoding_mode; + uint8_t frame_context_idx; + Vp9LoopFilterParams loop_filter_params; + Vp9QuantizationParams quantization_params; + Vp9SegmentationParams segmentation_params; + Vp9TileInfo tile_info; + uint16_t header_size_in_bytes; +} Vp9UncompressedHeader; \ No newline at end of file diff --git a/src/parser/vp9_parser.cpp b/src/parser/vp9_parser.cpp new file mode 100644 index 0000000000..2ffdc6fa95 --- /dev/null +++ b/src/parser/vp9_parser.cpp @@ -0,0 +1,840 @@ +/* +Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include +#include "vp9_parser.h" + +Vp9VideoParser::Vp9VideoParser() { + memset(&curr_pic_, 0, sizeof(Vp9Picture)); + memset(&dpb_buffer_, 0, sizeof(DecodedPictureBuffer)); + memset(&uncompressed_header_, 0, sizeof(Vp9UncompressedHeader)); + uncomp_header_size_ = 0; + memset(&tile_params_, 0, sizeof(RocdecVp9SliceParams)); + InitDpb(); +} + +Vp9VideoParser::~Vp9VideoParser() { +} + +rocDecStatus Vp9VideoParser::Initialize(RocdecParserParams *p_params) { + rocDecStatus ret; + if ((ret = RocVideoParser::Initialize(p_params)) != ROCDEC_SUCCESS) { + return ret; + } + // Set display delay to at least DECODE_BUF_POOL_EXTENSION (2) to prevent synchronous submission + if (parser_params_.max_display_delay < DECODE_BUF_POOL_EXTENSION) { + parser_params_.max_display_delay = DECODE_BUF_POOL_EXTENSION; + } + CheckAndAdjustDecBufPoolSize(VP9_NUM_REF_FRAMES); + return ROCDEC_SUCCESS; +} + +rocDecStatus Vp9VideoParser::UnInitialize() { + return ROCDEC_SUCCESS; +} + +rocDecStatus Vp9VideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) { + if (p_data->payload && p_data->payload_size) { + curr_pts_ = p_data->pts; + if (ParsePictureData(p_data->payload, p_data->payload_size) != PARSER_OK) { + ERR(STR("Parser failed!")); + return ROCDEC_RUNTIME_ERROR; + } + } else if (!(p_data->flags & ROCDEC_PKT_ENDOFSTREAM)) { + // If no payload and EOS is not set, treated as invalid. + return ROCDEC_INVALID_PARAMETER; + } + if (p_data->flags & ROCDEC_PKT_ENDOFSTREAM) { + if (FlushDpb() != PARSER_OK) { + return ROCDEC_RUNTIME_ERROR; + } + } + return ROCDEC_SUCCESS; +} + +ParserResult Vp9VideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t pic_data_size) { + ParserResult ret = PARSER_OK; + printf("Frame %d: pic_data_size = %d.................\n", pic_count_, pic_data_size); // Jefftest + if ((ret = ParseUncompressedHeader(const_cast(p_stream), pic_data_size)) != PARSER_OK) { + return ret; + } + // Init Roc decoder for the first time or reconfigure the existing decoder + if (new_seq_activated_) { + if ((ret = NotifyNewSequence(&uncompressed_header_)) != PARSER_OK) { + return ret; + } + new_seq_activated_ = false; + } + pic_stream_data_ptr_ = const_cast(p_stream); + pic_stream_data_size_ = pic_data_size; + num_slices_ = 1; + + // Decode the picture + if ((ret = SendPicForDecode()) != PARSER_OK) { + ERR(STR("Failed to decode!")); + return ret; + } + pic_count_++; + + return PARSER_OK; +} + +ParserResult Vp9VideoParser::NotifyNewSequence(Vp9UncompressedHeader *p_uncomp_header) { + video_format_params_.codec = rocDecVideoCodec_VP9; + video_format_params_.frame_rate.numerator = frame_rate_.numerator; + video_format_params_.frame_rate.denominator = frame_rate_.denominator; + video_format_params_.bit_depth_luma_minus8 = p_uncomp_header->color_config.bit_depth - 8; + video_format_params_.bit_depth_chroma_minus8 = p_uncomp_header->color_config.bit_depth - 8; + video_format_params_.progressive_sequence = 1; + video_format_params_.min_num_decode_surfaces = dec_buf_pool_size_; + video_format_params_.coded_width = pic_width_; + video_format_params_.coded_height = pic_height_; + + // 7.2.2. Color config semantics + if (p_uncomp_header->color_config.subsampling_x == 1 && p_uncomp_header->color_config.subsampling_y == 1) { + video_format_params_.chroma_format = rocDecVideoChromaFormat_420; + } else if (p_uncomp_header->color_config.subsampling_x == 1 && p_uncomp_header->color_config.subsampling_y == 0) { + video_format_params_.chroma_format = rocDecVideoChromaFormat_422; + } else if (p_uncomp_header->color_config.subsampling_x == 0 && p_uncomp_header->color_config.subsampling_y == 0) { + video_format_params_.chroma_format = rocDecVideoChromaFormat_444; + } else { + ERR("Unsupported chroma format."); + return PARSER_INVALID_FORMAT; + } + + video_format_params_.display_area.left = 0; + video_format_params_.display_area.top = 0; + video_format_params_.display_area.right = p_uncomp_header->render_size.render_width; + video_format_params_.display_area.bottom = p_uncomp_header->render_size.render_height; + video_format_params_.bitrate = 0; + + // Dispaly aspect ratio + int disp_width = (video_format_params_.display_area.right - video_format_params_.display_area.left); + int disp_height = (video_format_params_.display_area.bottom - video_format_params_.display_area.top); + int gcd = std::__gcd(disp_width, disp_height); // greatest common divisor + video_format_params_.display_aspect_ratio.x = disp_width / gcd; + video_format_params_.display_aspect_ratio.y = disp_height / gcd; + + video_format_params_.video_signal_description = {0}; + video_format_params_.seqhdr_data_length = 0; + + // callback function with RocdecVideoFormat params filled out + if (pfn_sequece_cb_(parser_params_.user_data, &video_format_params_) == 0) { + ERR("Sequence callback function failed."); + return PARSER_FAIL; + } else { + return PARSER_OK; + } + + return PARSER_OK; +} + +ParserResult Vp9VideoParser::SendPicForDecode() { + Vp9UncompressedHeader *p_uncomp_header = &uncompressed_header_; + dec_pic_params_ = {0}; + + dec_pic_params_.pic_width = pic_width_; + dec_pic_params_.pic_height = pic_height_; + dec_pic_params_.curr_pic_idx = curr_pic_.dec_buf_idx; + dec_pic_params_.field_pic_flag = 0; + dec_pic_params_.bottom_field_flag = 0; + dec_pic_params_.second_field = 0; + + dec_pic_params_.bitstream_data_len = pic_stream_data_size_; + dec_pic_params_.bitstream_data = pic_stream_data_ptr_; + dec_pic_params_.num_slices = num_slices_; + + dec_pic_params_.ref_pic_flag = 1; + dec_pic_params_.intra_pic_flag = frame_is_intra_; + + // Set up the picture parameter buffer + RocdecVp9PicParams *p_pic_param = &dec_pic_params_.pic_params.vp9; + p_pic_param->frame_width = pic_width_; + p_pic_param->frame_height = pic_height_; + p_pic_param->pic_fields.bits.subsampling_x = p_uncomp_header->color_config.subsampling_x; + p_pic_param->pic_fields.bits.subsampling_y = p_uncomp_header->color_config.subsampling_y; + p_pic_param->pic_fields.bits.frame_type = p_uncomp_header->frame_type; + p_pic_param->pic_fields.bits.show_frame = p_uncomp_header->show_frame; + p_pic_param->pic_fields.bits.error_resilient_mode = p_uncomp_header->error_resilient_mode; + p_pic_param->pic_fields.bits.intra_only = p_uncomp_header->intra_only; + p_pic_param->pic_fields.bits.allow_high_precision_mv = p_uncomp_header->allow_high_precision_mv; + p_pic_param->pic_fields.bits.mcomp_filter_type = p_uncomp_header->interpolation_filter ^ (p_uncomp_header->interpolation_filter <= 1); + p_pic_param->pic_fields.bits.frame_parallel_decoding_mode = p_uncomp_header->frame_parallel_decoding_mode; + p_pic_param->pic_fields.bits.reset_frame_context = p_uncomp_header->reset_frame_context; + p_pic_param->pic_fields.bits.refresh_frame_context = p_uncomp_header->refresh_frame_context; + p_pic_param->pic_fields.bits.frame_context_idx = p_uncomp_header->frame_context_idx; + p_pic_param->pic_fields.bits.segmentation_enabled = p_uncomp_header->segmentation_params.segmentation_enabled; + p_pic_param->pic_fields.bits.segmentation_temporal_update = p_uncomp_header->segmentation_params.segmentation_temporal_update; + p_pic_param->pic_fields.bits.segmentation_update_map = p_uncomp_header->segmentation_params.segmentation_update_map; + p_pic_param->pic_fields.bits.last_ref_frame = p_uncomp_header->ref_frame_idx[kVp9LastFrame - kVp9LastFrame]; + p_pic_param->pic_fields.bits.last_ref_frame_sign_bias = p_uncomp_header->ref_frame_sign_bias[kVp9LastFrame]; + p_pic_param->pic_fields.bits.golden_ref_frame = p_uncomp_header->ref_frame_idx[kVp9GoldenFrame - kVp9LastFrame]; + p_pic_param->pic_fields.bits.golden_ref_frame_sign_bias = p_uncomp_header->ref_frame_sign_bias[kVp9GoldenFrame]; + p_pic_param->pic_fields.bits.alt_ref_frame = p_uncomp_header->ref_frame_idx[kVp9AltRefFrame - kVp9LastFrame]; + p_pic_param->pic_fields.bits.alt_ref_frame_sign_bias = p_uncomp_header->ref_frame_sign_bias[kVp9AltRefFrame]; + p_pic_param->pic_fields.bits.lossless_flag = p_uncomp_header->quantization_params.lossless; + + p_pic_param->filter_level = p_uncomp_header->loop_filter_params.loop_filter_level; + p_pic_param->sharpness_level = p_uncomp_header->loop_filter_params.loop_filter_sharpness; + p_pic_param->log2_tile_rows = p_uncomp_header->tile_info.tile_rows_log2; + p_pic_param->log2_tile_columns = p_uncomp_header->tile_info.tile_cols_log2; + p_pic_param->frame_header_length_in_bytes = uncomp_header_size_; + p_pic_param->first_partition_size = p_uncomp_header->header_size_in_bytes; + for (int i = 0; i < 7; i++) { + p_pic_param->mb_segment_tree_probs[i] = p_uncomp_header->segmentation_params.segmentation_tree_probs[i]; + } + for (int i = 0; i < 3; i++) { + p_pic_param->segment_pred_probs[i] = p_uncomp_header->segmentation_params.segmentation_pred_prob[i]; + } + p_pic_param->profile = p_uncomp_header->profile; + p_pic_param->bit_depth = p_uncomp_header->color_config.bit_depth; + + // Todo + for (int i = 0; i < VP9_NUM_REF_FRAMES; i++) + p_pic_param->reference_frames[i] = 0; + + + RocdecVp9SliceParams *p_tile_params = &tile_params_; + p_tile_params->slice_data_offset = 0; // Todo + p_tile_params->slice_data_size = pic_stream_data_size_; // Todo + p_tile_params->slice_data_flag = 0; // VA_SLICE_DATA_FLAG_ALL; + for (int i = 0; i < VP9_MAX_SEGMENTS; i++) { + p_tile_params->seg_param[i].segment_flags.fields.segment_reference_enabled = p_uncomp_header->segmentation_params.feature_enabled[i][VP9_SEG_LVL_REF_FRAME]; + p_tile_params->seg_param[i].segment_flags.fields.segment_reference = p_uncomp_header->segmentation_params.feature_data[i][VP9_SEG_LVL_REF_FRAME]; + p_tile_params->seg_param[i].segment_flags.fields.segment_reference_skipped = p_uncomp_header->segmentation_params.feature_enabled[i][VP9_SEG_LVL_SKIP]; + p_tile_params->seg_param[i].luma_dc_quant_scale = y_dequant_[i][0]; + p_tile_params->seg_param[i].luma_ac_quant_scale = y_dequant_[i][1]; + p_tile_params->seg_param[i].chroma_dc_quant_scale = uv_dequant_[i][0]; + p_tile_params->seg_param[i].chroma_ac_quant_scale = uv_dequant_[i][1]; + memcpy(p_tile_params->seg_param[i].filter_level, lvl_lookup_[i], VP9_MAX_REF_FRAMES * MAX_MODE_LF_DELTAS * sizeof(uint8_t)); + } + dec_pic_params_.slice_params.vp9 = p_tile_params; + + if (pfn_decode_picture_cb_(parser_params_.user_data, &dec_pic_params_) == 0) { + ERR("Decode error occurred."); + return PARSER_FAIL; + } else { + return PARSER_OK; + } +} + +void Vp9VideoParser::InitDpb() { + int i; + memset(&dpb_buffer_, 0, sizeof(DecodedPictureBuffer)); + for (i = 0; i < VP9_NUM_REF_FRAMES; i++) { + dpb_buffer_.frame_store[i].pic_idx = i; + dpb_buffer_.frame_store[i].use_status = kNotUsed; + } +} + +ParserResult Vp9VideoParser::FlushDpb() { + if (pfn_display_picture_cb_ && num_output_pics_ > 0) { + if (OutputDecodedPictures(true) != PARSER_OK) { + return PARSER_FAIL; + } + } + return PARSER_OK; +} + +ParserResult Vp9VideoParser::FindFreeInDecBufPool() { + int dec_buf_index; + // Find a free buffer in decode/display buffer pool to store the decoded image + for (dec_buf_index = 0; dec_buf_index < dec_buf_pool_size_; dec_buf_index++) { + if (decode_buffer_pool_[dec_buf_index].use_status == kNotUsed) { + break; + } + } + if (dec_buf_index == dec_buf_pool_size_) { + ERR("Could not find a free buffer in decode buffer pool for decoded image."); + return PARSER_NOT_FOUND; + } + curr_pic_.dec_buf_idx = dec_buf_index; + decode_buffer_pool_[dec_buf_index].use_status |= kFrameUsedForDecode; + // Todo decode_buffer_pool_[dec_buf_index].pic_order_cnt = curr_pic_.order_hint; + decode_buffer_pool_[dec_buf_index].pts = curr_pts_; + return PARSER_OK; +} + +ParserResult Vp9VideoParser::FindFreeInDpbAndMark() { + int i; + /*Todo*/ + + return PARSER_OK; +} + +ParserResult Vp9VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t size) { + ParserResult ret = PARSER_OK; + size_t offset = 0; // current bit offset + Vp9UncompressedHeader *p_uncomp_header = &uncompressed_header_; + + // memset(p_uncomp_header, 0, sizeof(Vp9UncompressedHeader)); + p_uncomp_header->frame_marker = Parser::ReadBits(p_stream, offset, 2); + p_uncomp_header->profile_low_bit = Parser::GetBit(p_stream, offset); + p_uncomp_header->profile_high_bit = Parser::GetBit(p_stream, offset); + p_uncomp_header->profile = (p_uncomp_header->profile_high_bit << 1) + p_uncomp_header->profile_low_bit; + if (p_uncomp_header->profile == 3) { + p_uncomp_header->reserved_zero = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->reserved_zero) { + ERR("Syntax error: reserved_zero in Uncompressed header is not 0 when Profile is 3"); + return PARSER_INVALID_ARG; + } + } + p_uncomp_header->show_existing_frame = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->show_existing_frame) { + p_uncomp_header->frame_to_show_map_idx = Parser::ReadBits(p_stream, offset, 3); + p_uncomp_header->header_size_in_bytes = 0; + p_uncomp_header->refresh_frame_flags = 0; + p_uncomp_header->loop_filter_params.loop_filter_level = 0; + return PARSER_OK; + } + last_frame_type_ = p_uncomp_header->frame_type; + p_uncomp_header->frame_type = Parser::GetBit(p_stream, offset); + p_uncomp_header->show_frame = Parser::GetBit(p_stream, offset); + p_uncomp_header->error_resilient_mode = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->frame_type == kVp9KeyFrame) { + if ((ret = FrameSyncCode(p_stream, offset, p_uncomp_header)) != PARSER_OK) { + return ret; + } + if ((ret = ColorConfig(p_stream, offset, p_uncomp_header)) != PARSER_OK) { + return ret; + } + FrameSize(p_stream, offset, p_uncomp_header); + RenderSize(p_stream, offset, p_uncomp_header); + p_uncomp_header->refresh_frame_flags = 0xFF; + frame_is_intra_ = 1; + } else { + if (p_uncomp_header->show_frame == 0) { + p_uncomp_header->intra_only = Parser::GetBit(p_stream, offset); + } else { + p_uncomp_header->intra_only = 0; + } + frame_is_intra_ = p_uncomp_header->intra_only; + if (p_uncomp_header->error_resilient_mode == 0) { + p_uncomp_header->reset_frame_context = Parser::ReadBits(p_stream, offset, 2); + } else { + p_uncomp_header->reset_frame_context = 0; + } + if (p_uncomp_header->intra_only == 1) { + if ((ret = FrameSyncCode(p_stream, offset, p_uncomp_header)) != PARSER_OK) { + return ret; + } + if (p_uncomp_header->profile > 0) { + if ((ret = ColorConfig(p_stream, offset, p_uncomp_header)) != PARSER_OK) { + return ret; + } + } else { + p_uncomp_header->color_config.color_space = CS_BT_601; + p_uncomp_header->color_config.subsampling_x = 1; + p_uncomp_header->color_config.subsampling_y = 1; + p_uncomp_header->color_config.bit_depth = 8; + } + p_uncomp_header->refresh_frame_flags = Parser::ReadBits(p_stream, offset, 8); + FrameSize(p_stream, offset, p_uncomp_header); + RenderSize(p_stream, offset, p_uncomp_header); + } else { + p_uncomp_header->refresh_frame_flags = Parser::ReadBits(p_stream, offset, 8); + for (int i = 0; i < VP9_REFS_PER_FRAME; i++) { + p_uncomp_header->ref_frame_idx[i] = Parser::ReadBits(p_stream, offset, 3); + p_uncomp_header->ref_frame_sign_bias[kVp9LastFrame + i] = Parser::GetBit(p_stream, offset); + } + FrameSizeWithRefs(p_stream, offset, p_uncomp_header); + p_uncomp_header->allow_high_precision_mv = Parser::GetBit(p_stream, offset); + // read_interpolation_filter() + uint8_t literal_to_type[4] = {kVp9EightTapSmooth, kVp9EightTap, kVp9EightTapSharp, kVp9Bilinear}; + p_uncomp_header->is_filter_switchable = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->is_filter_switchable) { + p_uncomp_header->interpolation_filter = kVp9Switchable; + } else { + p_uncomp_header->raw_interpolation_filter = Parser::ReadBits(p_stream, offset, 2); + p_uncomp_header->interpolation_filter = literal_to_type[p_uncomp_header->raw_interpolation_filter]; + } + } + } + if (p_uncomp_header->error_resilient_mode == 0) { + p_uncomp_header->refresh_frame_context = Parser::GetBit(p_stream, offset); + p_uncomp_header->frame_parallel_decoding_mode = Parser::GetBit(p_stream, offset); + } else { + p_uncomp_header->refresh_frame_context = 0; + p_uncomp_header->frame_parallel_decoding_mode = 1; + } + p_uncomp_header->frame_context_idx = Parser::ReadBits(p_stream, offset, 2); + if (frame_is_intra_ || p_uncomp_header->error_resilient_mode) { + // Todo: setup_past_independence() + if (p_uncomp_header->frame_type == kVp9KeyFrame || p_uncomp_header->error_resilient_mode == 1 || p_uncomp_header->reset_frame_context == 3) { + for (int i = 0; i < 4; i++) { + // Todo: save_probs( i ) + } + } else if (p_uncomp_header->reset_frame_context == 2) { + // Todo: save_probs(p_uncomp_header->frame_context_idx) + } + p_uncomp_header->frame_context_idx = 0; + } + LoopFilterParams(p_stream, offset, p_uncomp_header); + QuantizationParams(p_stream, offset, p_uncomp_header); + SegmentationParams(p_stream, offset, p_uncomp_header); + SetupSegDequant(p_uncomp_header); + LoopFilterFrameInit(p_uncomp_header); + TileInfo(p_stream, offset, p_uncomp_header); + + p_uncomp_header->header_size_in_bytes = Parser::ReadBits(p_stream, offset, 16); + + if (pic_width_ != p_uncomp_header->frame_size.frame_width || pic_height_ != p_uncomp_header->frame_size.frame_height) { + pic_width_ = p_uncomp_header->frame_size.frame_width; + pic_height_ = p_uncomp_header->frame_size.frame_height; + new_seq_activated_ = true; + } + + uncomp_header_size_ = (offset + 7) >> 3; + return PARSER_OK; +} + +ParserResult Vp9VideoParser::FrameSyncCode(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + p_uncomp_header->frame_sync_code.frame_sync_byte_0 = Parser::ReadBits(p_stream, offset, 8); + if (p_uncomp_header->frame_sync_code.frame_sync_byte_0 != 0x49) { + ERR("Syntax error: frame_sync_byte_0 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_0) + " but shall be equal to 0x49."); + return PARSER_INVALID_ARG; + } + p_uncomp_header->frame_sync_code.frame_sync_byte_1 = Parser::ReadBits(p_stream, offset, 8); + if (p_uncomp_header->frame_sync_code.frame_sync_byte_1 != 0x83) { + ERR("Syntax error: frame_sync_byte_1 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_1) + " but shall be equal to 0x83."); + return PARSER_INVALID_ARG; + } + p_uncomp_header->frame_sync_code.frame_sync_byte_2 = Parser::ReadBits(p_stream, offset, 8); + if (p_uncomp_header->frame_sync_code.frame_sync_byte_2 != 0x42) { + ERR("Syntax error: frame_sync_byte_2 is " + TOSTR(p_uncomp_header->frame_sync_code.frame_sync_byte_2) + " but shall be equal to 0x42."); + return PARSER_INVALID_ARG; + } + return PARSER_OK; +} + +ParserResult Vp9VideoParser::ColorConfig(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + if (p_uncomp_header->profile >= 2) { + p_uncomp_header->color_config.ten_or_twelve_bit = Parser::GetBit(p_stream, offset); + p_uncomp_header->color_config.bit_depth = p_uncomp_header->color_config.ten_or_twelve_bit ? 12 : 10; + } else { + p_uncomp_header->color_config.bit_depth = 8; + } + p_uncomp_header->color_config.color_space = Parser::ReadBits(p_stream, offset, 3); + if (p_uncomp_header->color_config.color_space != CS_RGB) { + p_uncomp_header->color_config.color_range = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->profile == 1 || p_uncomp_header->profile == 3) { + p_uncomp_header->color_config.subsampling_x = Parser::GetBit(p_stream, offset); + p_uncomp_header->color_config.subsampling_y = Parser::GetBit(p_stream, offset); + p_uncomp_header->color_config.reserved_zero = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->color_config.reserved_zero) { + ERR("Syntax error: reserved_zero in color config is not 0 when Profile is 1 or 3"); + return PARSER_INVALID_ARG; + } + } else { + p_uncomp_header->color_config.subsampling_x = 1; + p_uncomp_header->color_config.subsampling_y = 1; + } + } else { + p_uncomp_header->color_config.color_range = 1; + if (p_uncomp_header->profile == 1 || p_uncomp_header->profile == 3) { + p_uncomp_header->color_config.subsampling_x = 0; + p_uncomp_header->color_config.subsampling_y = 0; + p_uncomp_header->color_config.reserved_zero = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->color_config.reserved_zero) { + ERR("Syntax error: reserved_zero in color config is not 0 when Profile is 1 or 3"); + return PARSER_INVALID_ARG; + } + } + } + return PARSER_OK; +} + +void Vp9VideoParser::FrameSize(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + p_uncomp_header->frame_size.frame_width_minus_1 = Parser::ReadBits(p_stream, offset, 16); + p_uncomp_header->frame_size.frame_height_minus_1 = Parser::ReadBits(p_stream, offset, 16); + p_uncomp_header->frame_size.frame_width = p_uncomp_header->frame_size.frame_width_minus_1 + 1; + p_uncomp_header->frame_size.frame_height = p_uncomp_header->frame_size.frame_height_minus_1 + 1; + ComputeImageSize(p_uncomp_header); +} + +void Vp9VideoParser::RenderSize(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + p_uncomp_header->render_size.render_and_frame_size_different = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->render_size.render_and_frame_size_different) { + p_uncomp_header->render_size.render_width_minus_1 = Parser::ReadBits(p_stream, offset, 16); + p_uncomp_header->render_size.render_height_minus_1 = Parser::ReadBits(p_stream, offset, 16); + p_uncomp_header->render_size.render_width = p_uncomp_header->render_size.render_width_minus_1 + 1; + p_uncomp_header->render_size.render_height = p_uncomp_header->render_size.render_height_minus_1 + 1; + } else { + p_uncomp_header->render_size.render_width_minus_1 = p_uncomp_header->frame_size.frame_width_minus_1; + p_uncomp_header->render_size.render_height_minus_1 = p_uncomp_header->frame_size.frame_height_minus_1; + p_uncomp_header->render_size.render_width = p_uncomp_header->frame_size.frame_width; + p_uncomp_header->render_size.render_height = p_uncomp_header->frame_size.frame_height; + } +} + +void Vp9VideoParser::FrameSizeWithRefs(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + uint8_t found_ref; + for (int i = 0; i < 3; i++) { + found_ref = Parser::GetBit(p_stream, offset); + if (found_ref) { + p_uncomp_header->frame_size.frame_width = dpb_buffer_.ref_frame_width[p_uncomp_header->ref_frame_idx[i]]; + p_uncomp_header->frame_size.frame_height = dpb_buffer_.ref_frame_height[p_uncomp_header->ref_frame_idx[i]]; + break; + } + } + if (found_ref == 0) { + FrameSize(p_stream, offset, p_uncomp_header); + } else { + ComputeImageSize(p_uncomp_header); + } + RenderSize(p_stream, offset, p_uncomp_header); +} + +void Vp9VideoParser::ComputeImageSize(Vp9UncompressedHeader *p_uncomp_header) { + p_uncomp_header->frame_size.mi_cols = (p_uncomp_header->frame_size.frame_width + 7) >> 3; + p_uncomp_header->frame_size.mi_rows = (p_uncomp_header->frame_size.frame_height + 7) >> 3; + p_uncomp_header->frame_size.sb64_cols = (p_uncomp_header->frame_size.mi_cols + 7) >> 3; + p_uncomp_header->frame_size.sb64_rows = (p_uncomp_header->frame_size.mi_rows + 7) >> 3; + // Todo steps in 7.2.6 +} + +void Vp9VideoParser::LoopFilterParams(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + p_uncomp_header->loop_filter_params.loop_filter_level = Parser::ReadBits(p_stream, offset, 6); + p_uncomp_header->loop_filter_params.loop_filter_sharpness = Parser::ReadBits(p_stream, offset, 3); + p_uncomp_header->loop_filter_params.loop_filter_delta_enabled = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->loop_filter_params.loop_filter_delta_enabled) { + p_uncomp_header->loop_filter_params.loop_filter_delta_update = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->loop_filter_params.loop_filter_delta_update) { + for (int i = 0; i < 4; i++) { + p_uncomp_header->loop_filter_params.update_ref_delta[i] = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->loop_filter_params.update_ref_delta[i]) { + p_uncomp_header->loop_filter_params.loop_filter_ref_deltas[i] = ReadSigned(p_stream, offset, 6); + } + } + for (int i = 0; i < 2; i++) { + p_uncomp_header->loop_filter_params.update_mode_delta[i] = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->loop_filter_params.update_mode_delta[i]) { + p_uncomp_header->loop_filter_params.loop_filter_mode_deltas[i] = ReadSigned(p_stream, offset, 6); + } + } + } + } +} + +void Vp9VideoParser::QuantizationParams(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + p_uncomp_header->quantization_params.base_q_idx = Parser::ReadBits(p_stream, offset, 8); + p_uncomp_header->quantization_params.delta_q_y_dc = ReadDeltaQ(p_stream, offset); + p_uncomp_header->quantization_params.delta_q_uv_dc = ReadDeltaQ(p_stream, offset); + p_uncomp_header->quantization_params.delta_q_uv_ac = ReadDeltaQ(p_stream, offset); + p_uncomp_header->quantization_params.lossless = p_uncomp_header->quantization_params.base_q_idx == 0 && p_uncomp_header->quantization_params.delta_q_y_dc == 0 && p_uncomp_header->quantization_params.delta_q_uv_dc == 0 && p_uncomp_header->quantization_params.delta_q_uv_ac == 0; +} + +int8_t Vp9VideoParser::ReadDeltaQ(const uint8_t *p_stream, size_t &offset) { + uint8_t delta_coded; + int8_t delta_q; + delta_coded = Parser::GetBit(p_stream, offset); + if (delta_coded) { + delta_q = ReadSigned(p_stream, offset, 4); + } else { + delta_q = 0; + } + return delta_q; +} + +void Vp9VideoParser::SegmentationParams(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + const uint8_t segmentation_feature_bits[VP9_SEG_LVL_MAX] = {8, 6, 2, 0}; + const uint8_t segmentation_feature_signed[VP9_SEG_LVL_MAX] = {1, 1, 0, 0}; + p_uncomp_header->segmentation_params.segmentation_enabled = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->segmentation_params.segmentation_enabled) { + p_uncomp_header->segmentation_params.segmentation_update_map = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->segmentation_params.segmentation_update_map) { + for (int i = 0; i < 7; i++) { + p_uncomp_header->segmentation_params.segmentation_tree_probs[i] = ReadProb(p_stream, offset); + } + p_uncomp_header->segmentation_params.segmentation_temporal_update = Parser::GetBit(p_stream, offset); + for (int i = 0; i < 3; i++) { + p_uncomp_header->segmentation_params.segmentation_pred_prob[i] = p_uncomp_header->segmentation_params.segmentation_temporal_update ? ReadProb(p_stream, offset) : 255; + } + } + p_uncomp_header->segmentation_params.segmentation_update_data = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->segmentation_params.segmentation_update_data) { + p_uncomp_header->segmentation_params.segmentation_abs_or_delta_update = Parser::GetBit(p_stream, offset); + for (int i = 0; i < VP9_MAX_SEGMENTS; i++) { + for (int j = 0; j < VP9_SEG_LVL_MAX; j++) { + int feature_value = 0; + p_uncomp_header->segmentation_params.feature_enabled[i][j] = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->segmentation_params.feature_enabled[i][j]) { + int bits_to_read = segmentation_feature_bits[j]; + if (bits_to_read) { + feature_value = Parser::ReadBits(p_stream, offset, bits_to_read); + } + if (segmentation_feature_signed[j] == 1) { + uint8_t feature_sign = Parser::GetBit(p_stream, offset); + if (feature_sign) { + feature_value *= -1; + } + } + } + p_uncomp_header->segmentation_params.feature_data[i][j] = feature_value; + } + } + } + } else { + p_uncomp_header->segmentation_params.segmentation_update_map = 0; + p_uncomp_header->segmentation_params.segmentation_temporal_update = 0; + } +} + +uint8_t Vp9VideoParser::ReadProb(const uint8_t *p_stream, size_t &offset) { + uint8_t prob_coded; + uint8_t prob = 255; + prob_coded = Parser::GetBit(p_stream, offset); + if (prob_coded) { + prob = Parser::ReadBits(p_stream, offset, 8); + } + return prob; +} + +void Vp9VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header) { + // calc_min_log2_tile_cols() + int min_log2 = 0; + while ((MAX_TILE_WIDTH_B64 << min_log2) < p_uncomp_header->frame_size.sb64_cols) { + min_log2++; + } + p_uncomp_header->tile_info.min_log2_tile_cols = min_log2; + // calc_max_log2_tile_cols() + int max_log2 = 1; + while ((p_uncomp_header->frame_size.sb64_cols >> max_log2) >= MIN_TILE_WIDTH_B64) { + max_log2++; + } + p_uncomp_header->tile_info.max_log2_tile_cols = max_log2 - 1; + p_uncomp_header->tile_info.tile_cols_log2 = p_uncomp_header->tile_info.min_log2_tile_cols; + while (p_uncomp_header->tile_info.tile_cols_log2 < p_uncomp_header->tile_info.max_log2_tile_cols) { + if (Parser::GetBit(p_stream, offset)) { // increment_tile_cols_log2 + p_uncomp_header->tile_info.tile_cols_log2++; + } else { + break; + } + } + p_uncomp_header->tile_info.tile_rows_log2 = Parser::GetBit(p_stream, offset); + if (p_uncomp_header->tile_info.tile_rows_log2) { + uint8_t increment_tile_rows_log2 = Parser::GetBit(p_stream, offset); + p_uncomp_header->tile_info.tile_rows_log2 += increment_tile_rows_log2; + } +} + +static const int16_t dc_qlookup[3][256] = { + {4, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, + 19, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 29, 30, + 31, 32, 32, 33, 34, 35, 36, 37, 38, 38, 39, 40, 41, 42, + 43, 43, 44, 45, 46, 47, 48, 48, 49, 50, 51, 52, 53, 53, + 54, 55, 56, 57, 57, 58, 59, 60, 61, 62, 62, 63, 64, 65, + 66, 66, 67, 68, 69, 70, 70, 71, 72, 73, 74, 74, 75, 76, + 77, 78, 78, 79, 80, 81, 81, 82, 83, 84, 85, 85, 87, 88, + 90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 108, 110, + 111, 113, 114, 116, 117, 118, 120, 121, 123, 125, 127, 129, 131, 134, + 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 161, 164, + 166, 169, 172, 174, 177, 180, 182, 185, 187, 190, 192, 195, 199, 202, + 205, 208, 211, 214, 217, 220, 223, 226, 230, 233, 237, 240, 243, 247, + 250, 253, 257, 261, 265, 269, 272, 276, 280, 284, 288, 292, 296, 300, + 304, 309, 313, 317, 322, 326, 330, 335, 340, 344, 349, 354, 359, 364, + 369, 374, 379, 384, 389, 395, 400, 406, 411, 417, 423, 429, 435, 441, + 447, 454, 461, 467, 475, 482, 489, 497, 505, 513, 522, 530, 539, 549, + 559, 569, 579, 590, 602, 614, 626, 640, 654, 668, 684, 700, 717, 736, + 755, 775, 796, 819, 843, 869, 896, 925, 955, 988, 1022, 1058, 1098, 1139, + 1184, 1232, 1282, 1336,}, + {4, 9, 10, 13, 15, 17, 20, 22, 25, 28, 31, 34, 37, + 40, 43, 47, 50, 53, 57, 60, 64, 68, 71, 75, 78, 82, + 86, 90, 93, 97, 101, 105, 109, 113, 116, 120, 124, 128, 132, + 136, 140, 143, 147, 151, 155, 159, 163, 166, 170, 174, 178, 182, + 185, 189, 193, 197, 200, 204, 208, 212, 215, 219, 223, 226, 230, + 233, 237, 241, 244, 248, 251, 255, 259, 262, 266, 269, 273, 276, + 280, 283, 287, 290, 293, 297, 300, 304, 307, 310, 314, 317, 321, + 324, 327, 331, 334, 337, 343, 350, 356, 362, 369, 375, 381, 387, + 394, 400, 406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466, + 472, 478, 484, 490, 499, 507, 516, 525, 533, 542, 550, 559, 567, + 576, 584, 592, 601, 609, 617, 625, 634, 644, 655, 666, 676, 687, + 698, 708, 718, 729, 739, 749, 759, 770, 782, 795, 807, 819, 831, + 844, 856, 868, 880, 891, 906, 920, 933, 947, 961, 975, 988, 1001, + 1015, 1030, 1045, 1061, 1076, 1090, 1105, 1120, 1137, 1153, 1170, 1186, 1202, + 1218, 1236, 1253, 1271, 1288, 1306, 1323, 1342, 1361, 1379, 1398, 1416, 1436, + 1456, 1476, 1496, 1516, 1537, 1559, 1580, 1601, 1624, 1647, 1670, 1692, 1717, + 1741, 1766, 1791, 1817, 1844, 1871, 1900, 1929, 1958, 1990, 2021, 2054, 2088, + 2123, 2159, 2197, 2236, 2276, 2319, 2363, 2410, 2458, 2508, 2561, 2616, 2675, + 2737, 2802, 2871, 2944, 3020, 3102, 3188, 3280, 3375, 3478, 3586, 3702, 3823, + 3953, 4089, 4236, 4394, 4559, 4737, 4929, 5130, 5347,}, + {4, 12, 18, 25, 33, 41, 50, 60, 70, 80, 91, + 103, 115, 127, 140, 153, 166, 180, 194, 208, 222, 237, + 251, 266, 281, 296, 312, 327, 343, 358, 374, 390, 405, + 421, 437, 453, 469, 484, 500, 516, 532, 548, 564, 580, + 596, 611, 627, 643, 659, 674, 690, 706, 721, 737, 752, + 768, 783, 798, 814, 829, 844, 859, 874, 889, 904, 919, + 934, 949, 964, 978, 993, 1008, 1022, 1037, 1051, 1065, 1080, + 1094, 1108, 1122, 1136, 1151, 1165, 1179, 1192, 1206, 1220, 1234, + 1248, 1261, 1275, 1288, 1302, 1315, 1329, 1342, 1368, 1393, 1419, + 1444, 1469, 1494, 1519, 1544, 1569, 1594, 1618, 1643, 1668, 1692, + 1717, 1741, 1765, 1789, 1814, 1838, 1862, 1885, 1909, 1933, 1957, + 1992, 2027, 2061, 2096, 2130, 2165, 2199, 2233, 2267, 2300, 2334, + 2367, 2400, 2434, 2467, 2499, 2532, 2575, 2618, 2661, 2704, 2746, + 2788, 2830, 2872, 2913, 2954, 2995, 3036, 3076, 3127, 3177, 3226, + 3275, 3324, 3373, 3421, 3469, 3517, 3565, 3621, 3677, 3733, 3788, + 3843, 3897, 3951, 4005, 4058, 4119, 4181, 4241, 4301, 4361, 4420, + 4479, 4546, 4612, 4677, 4742, 4807, 4871, 4942, 5013, 5083, 5153, + 5222, 5291, 5367, 5442, 5517, 5591, 5665, 5745, 5825, 5905, 5984, + 6063, 6149, 6234, 6319, 6404, 6495, 6587, 6678, 6769, 6867, 6966, + 7064, 7163, 7269, 7376, 7483, 7599, 7715, 7832, 7958, 8085, 8214, + 8352, 8492, 8635, 8788, 8945, 9104, 9275, 9450, 9639, 9832, 10031, + 10245, 10465, 10702, 10946, 11210, 11482, 11776, 12081, 12409, 12750, 13118, + 13501, 13913, 14343, 14807, 15290, 15812, 16356, 16943, 17575, 18237, 18949, + 19718, 20521, 21387,} +}; +static const int16_t ac_qlookup[3][256] = { + {4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + 98, 99, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118, + 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, + 146, 148, 150, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, + 182, 185, 188, 191, 194, 197, 200, 203, 207, 211, 215, 219, 223, + 227, 231, 235, 239, 243, 247, 251, 255, 260, 265, 270, 275, 280, + 285, 290, 295, 300, 305, 311, 317, 323, 329, 335, 341, 347, 353, + 359, 366, 373, 380, 387, 394, 401, 408, 416, 424, 432, 440, 448, + 456, 465, 474, 483, 492, 501, 510, 520, 530, 540, 550, 560, 571, + 582, 593, 604, 615, 627, 639, 651, 663, 676, 689, 702, 715, 729, + 743, 757, 771, 786, 801, 816, 832, 848, 864, 881, 898, 915, 933, + 951, 969, 988, 1007, 1026, 1046, 1066, 1087, 1108, 1129, 1151, 1173, 1196, + 1219, 1243, 1267, 1292, 1317, 1343, 1369, 1396, 1423, 1451, 1479, 1508, 1537, + 1567, 1597, 1628, 1660, 1692, 1725, 1759, 1793, 1828,}, + {4, 9, 11, 13, 16, 18, 21, 24, 27, 30, 33, 37, 40, + 44, 48, 51, 55, 59, 63, 67, 71, 75, 79, 83, 88, 92, + 96, 100, 105, 109, 114, 118, 122, 127, 131, 136, 140, 145, 149, + 154, 158, 163, 168, 172, 177, 181, 186, 190, 195, 199, 204, 208, + 213, 217, 222, 226, 231, 235, 240, 244, 249, 253, 258, 262, 267, + 271, 275, 280, 284, 289, 293, 297, 302, 306, 311, 315, 319, 324, + 328, 332, 337, 341, 345, 349, 354, 358, 362, 367, 371, 375, 379, + 384, 388, 392, 396, 401, 409, 417, 425, 433, 441, 449, 458, 466, + 474, 482, 490, 498, 506, 514, 523, 531, 539, 547, 555, 563, 571, + 579, 588, 596, 604, 616, 628, 640, 652, 664, 676, 688, 700, 713, + 725, 737, 749, 761, 773, 785, 797, 809, 825, 841, 857, 873, 889, + 905, 922, 938, 954, 970, 986, 1002, 1018, 1038, 1058, 1078, 1098, 1118, + 1138, 1158, 1178, 1198, 1218, 1242, 1266, 1290, 1314, 1338, 1362, 1386, 1411, + 1435, 1463, 1491, 1519, 1547, 1575, 1603, 1631, 1663, 1695, 1727, 1759, 1791, + 1823, 1859, 1895, 1931, 1967, 2003, 2039, 2079, 2119, 2159, 2199, 2239, 2283, + 2327, 2371, 2415, 2459, 2507, 2555, 2603, 2651, 2703, 2755, 2807, 2859, 2915, + 2971, 3027, 3083, 3143, 3203, 3263, 3327, 3391, 3455, 3523, 3591, 3659, 3731, + 3803, 3876, 3952, 4028, 4104, 4184, 4264, 4348, 4432, 4516, 4604, 4692, 4784, + 4876, 4972, 5068, 5168, 5268, 5372, 5476, 5584, 5692, 5804, 5916, 6032, 6148, + 6268, 6388, 6512, 6640, 6768, 6900, 7036, 7172, 7312,}, + {4, 13, 19, 27, 35, 44, 54, 64, 75, 87, 99, + 112, 126, 139, 154, 168, 183, 199, 214, 230, 247, 263, + 280, 297, 314, 331, 349, 366, 384, 402, 420, 438, 456, + 475, 493, 511, 530, 548, 567, 586, 604, 623, 642, 660, + 679, 698, 716, 735, 753, 772, 791, 809, 828, 846, 865, + 884, 902, 920, 939, 957, 976, 994, 1012, 1030, 1049, 1067, + 1085, 1103, 1121, 1139, 1157, 1175, 1193, 1211, 1229, 1246, 1264, + 1282, 1299, 1317, 1335, 1352, 1370, 1387, 1405, 1422, 1440, 1457, + 1474, 1491, 1509, 1526, 1543, 1560, 1577, 1595, 1627, 1660, 1693, + 1725, 1758, 1791, 1824, 1856, 1889, 1922, 1954, 1987, 2020, 2052, + 2085, 2118, 2150, 2183, 2216, 2248, 2281, 2313, 2346, 2378, 2411, + 2459, 2508, 2556, 2605, 2653, 2701, 2750, 2798, 2847, 2895, 2943, + 2992, 3040, 3088, 3137, 3185, 3234, 3298, 3362, 3426, 3491, 3555, + 3619, 3684, 3748, 3812, 3876, 3941, 4005, 4069, 4149, 4230, 4310, + 4390, 4470, 4550, 4631, 4711, 4791, 4871, 4967, 5064, 5160, 5256, + 5352, 5448, 5544, 5641, 5737, 5849, 5961, 6073, 6185, 6297, 6410, + 6522, 6650, 6778, 6906, 7034, 7162, 7290, 7435, 7579, 7723, 7867, + 8011, 8155, 8315, 8475, 8635, 8795, 8956, 9132, 9308, 9484, 9660, + 9836, 10028, 10220, 10412, 10604, 10812, 11020, 11228, 11437, 11661, 11885, + 12109, 12333, 12573, 12813, 13053, 13309, 13565, 13821, 14093, 14365, 14637, + 14925, 15213, 15502, 15806, 16110, 16414, 16734, 17054, 17390, 17726, 18062, + 18414, 18766, 19134, 19502, 19886, 20270, 20670, 21070, 21486, 21902, 22334, + 22766, 23214, 23662, 24126, 24590, 25070, 25551, 26047, 26559, 27071, 27599, + 28143, 28687, 29247,} +}; + +int Vp9VideoParser::DcQ(int bit_depth, int index) { + return dc_qlookup[(bit_depth - 8) >> 1][std::clamp(index, 0, 255)]; +} + +int Vp9VideoParser::AcQ(int bit_depth, int index) { + return ac_qlookup[(bit_depth - 8) >> 1][std::clamp(index, 0, 255)]; +} + +int Vp9VideoParser::GetQIndex(Vp9UncompressedHeader *p_uncomp_header, int seg_id) { + int value = 0; + if (p_uncomp_header->segmentation_params.segmentation_enabled && p_uncomp_header->segmentation_params.feature_enabled[seg_id][VP9_SEG_LVL_ALT_Q]) { + value = p_uncomp_header->segmentation_params.feature_data[seg_id][VP9_SEG_LVL_ALT_Q]; + if (p_uncomp_header->segmentation_params.segmentation_abs_or_delta_update == 0) { + value += p_uncomp_header->quantization_params.base_q_idx; + value = std::clamp(value, 0, 255); + } + } else { + value = p_uncomp_header->quantization_params.base_q_idx; + } + return value; +} + +void Vp9VideoParser::SetupSegDequant(Vp9UncompressedHeader *p_uncomp_header) { + int q_index; + if (p_uncomp_header->segmentation_params.segmentation_enabled) { + for (int i = 0; i < VP9_MAX_SEGMENTS; i++) { + q_index = GetQIndex(p_uncomp_header, i); + y_dequant_[i][0] = DcQ(p_uncomp_header->color_config.bit_depth, q_index + p_uncomp_header->quantization_params.delta_q_y_dc); + y_dequant_[i][1] = AcQ(p_uncomp_header->color_config.bit_depth, q_index); + uv_dequant_[i][0] = DcQ(p_uncomp_header->color_config.bit_depth, q_index + p_uncomp_header->quantization_params.delta_q_uv_dc); + uv_dequant_[i][1] = AcQ(p_uncomp_header->color_config.bit_depth, q_index + p_uncomp_header->quantization_params.delta_q_uv_ac); + } + } else { + // When segmentation is disabled, only the first value is used. + q_index = p_uncomp_header->quantization_params.base_q_idx; + y_dequant_[0][0] = DcQ(p_uncomp_header->color_config.bit_depth, q_index + p_uncomp_header->quantization_params.delta_q_y_dc); + y_dequant_[0][1] = AcQ(p_uncomp_header->color_config.bit_depth, q_index); + uv_dequant_[0][0] = DcQ(p_uncomp_header->color_config.bit_depth, q_index + p_uncomp_header->quantization_params.delta_q_uv_dc); + uv_dequant_[0][1] = AcQ(p_uncomp_header->color_config.bit_depth, q_index + p_uncomp_header->quantization_params.delta_q_uv_ac); + } +} + +void Vp9VideoParser::LoopFilterFrameInit(Vp9UncompressedHeader *p_uncomp_header) { + int n_shift = p_uncomp_header->loop_filter_params.loop_filter_level >> 5; + for (int seg_id = 0; seg_id < VP9_MAX_SEGMENTS; seg_id++) { + uint8_t lvl_seg = p_uncomp_header->loop_filter_params.loop_filter_level; + if (p_uncomp_header->segmentation_params.feature_enabled[seg_id][VP9_SEG_LVL_ALT_L]) { + if (p_uncomp_header->segmentation_params.segmentation_abs_or_delta_update) { + lvl_seg = p_uncomp_header->segmentation_params.feature_data[seg_id][VP9_SEG_LVL_ALT_L]; + } else { + lvl_seg += p_uncomp_header->segmentation_params.feature_data[seg_id][VP9_SEG_LVL_ALT_L]; + } + lvl_seg = std::clamp(static_cast(lvl_seg), 0, VP9_MAX_LOOP_FILTER); + } + if (p_uncomp_header->loop_filter_params.loop_filter_delta_update == 0) { + memset(lvl_lookup_[seg_id], lvl_seg, VP9_MAX_REF_FRAMES * MAX_MODE_LF_DELTAS * sizeof(uint8_t)); + } else { + uint8_t intra_lvl = lvl_seg + (p_uncomp_header->loop_filter_params.loop_filter_ref_deltas[kVp9IntraFrame] << n_shift); + lvl_lookup_[seg_id][kVp9IntraFrame][0] = std::clamp(static_cast(intra_lvl), 0, VP9_MAX_LOOP_FILTER); + for (int ref = kVp9LastFrame; ref < VP9_MAX_REF_FRAMES; ref++) { + for (int mode = 0; mode < MAX_MODE_LF_DELTAS; mode++) { + uint8_t inter_lvl = lvl_seg + (p_uncomp_header->loop_filter_params.loop_filter_ref_deltas[ref] << n_shift) + + (p_uncomp_header->loop_filter_params.loop_filter_mode_deltas[mode] << n_shift); + lvl_lookup_[seg_id][ref][mode] = std::clamp(static_cast(inter_lvl), 0, VP9_MAX_LOOP_FILTER); + } + } + } + } +} diff --git a/src/parser/vp9_parser.h b/src/parser/vp9_parser.h new file mode 100644 index 0000000000..79e07d5f01 --- /dev/null +++ b/src/parser/vp9_parser.h @@ -0,0 +1,262 @@ +/* +Copyright (c) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#pragma once + +#include "vp9_defines.h" +#include "roc_video_parser.h" + +class Vp9VideoParser : public RocVideoParser { +public: + /*! \brief Vp9VideoParser constructor + */ + Vp9VideoParser(); + + /*! \brief Vp9VideoParser destructor + */ + virtual ~Vp9VideoParser(); + + /*! \brief Function to Initialize the parser + * \param [in] p_params Input of RocdecParserParams with codec type to initialize parser. + * \return rocDecStatus Returns success on completion, else error code for failure + */ + virtual rocDecStatus Initialize(RocdecParserParams *p_params); + + /*! \brief Function to Parse video data: Typically called from application when a demuxed picture is ready to be parsed + * \param [in] p_data Pointer to picture data of type RocdecSourceDataPacket + * @return rocDecStatus Returns success on completion, else error_code for failure + */ + virtual rocDecStatus ParseVideoData(RocdecSourceDataPacket *p_data); + + /*! \brief function to uninitialize AV1 parser + * @return rocDecStatus + */ + virtual rocDecStatus UnInitialize(); // derived method + +protected: + typedef struct { + int pic_idx; + int dec_buf_idx; // frame index in decode/display buffer pool + uint32_t use_status; // refer to FrameBufUseStatus + } Vp9Picture; + + /*! \brief Decoded picture buffer + */ + typedef struct { + Vp9Picture frame_store[VP9_NUM_REF_FRAMES]; // BufferPool + uint32_t ref_frame_width[VP9_NUM_REF_FRAMES]; // RefFrameWidth + uint32_t ref_frame_height[VP9_NUM_REF_FRAMES]; // RefFrameHeight + } DecodedPictureBuffer; + + Vp9UncompressedHeader uncompressed_header_; + uint32_t uncomp_header_size_; + uint8_t last_frame_type_; // LastFrameType + uint8_t frame_is_intra_; + RocdecVp9SliceParams tile_params_; + int16_t y_dequant_[VP9_MAX_SEGMENTS][2]; + int16_t uv_dequant_[VP9_MAX_SEGMENTS][2]; + uint8_t lvl_lookup_[VP9_MAX_SEGMENTS][VP9_MAX_REF_FRAMES][MAX_MODE_LF_DELTAS]; + + DecodedPictureBuffer dpb_buffer_; + Vp9Picture curr_pic_; + + /*! \brief Function to parse one picture bit stream received from the demuxer. + * \param [in] p_stream A pointer of uint8_t for the input stream to be parsed + * \param [in] pic_data_size Size of the input stream + * \return ParserResult + */ + ParserResult ParsePictureData(const uint8_t *p_stream, uint32_t pic_data_size); + + /*! \brief Function to notify decoder about new sequence format through callback + * \return ParserResult + */ + ParserResult NotifyNewSequence(Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to fill the decode parameters and call back decoder to decode a picture + * \return ParserResult + */ + ParserResult SendPicForDecode(); + + /*! Function to initialize the local DPB (BufferPool) + * \return None + */ + void InitDpb(); + + /*! \brief Function to send out the remaining pictures that need for output in decode frame buffer. + * \return ParserResult + */ + ParserResult FlushDpb(); + + /*! \brief Function to find a free buffer in the decode buffer pool + * \return ParserResult + */ + ParserResult FindFreeInDecBufPool(); + + /*! \brief Function to find a free buffer in DPB for the current picture and mark it. + * \return ParserResult + */ + ParserResult FindFreeInDpbAndMark(); + + /*! \brief Function to parse an uncompressed header (uncompressed_header(), 6.2) + * \param [in] p_stream Pointer to the bit stream + * \param [in] size Byte size of the stream + * \return ParserResult + */ + ParserResult ParseUncompressedHeader(uint8_t *p_stream, size_t size); + + /*! \brief Function to parse frame sync syntax (frame_sync_code(), 6.2.1) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return ParserResult + */ + ParserResult FrameSyncCode(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to parse color config syntax (color_config(), 6.2.2) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return ParserResult + */ + ParserResult ColorConfig(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to parse frame size syntax (frame_size(), 6.2.3) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void FrameSize(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to parse render size syntax (frame_size(), 6.2.4) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void RenderSize(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to parse frame size with refs syntax (frame_size_with_refs(), 6.2.5) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void FrameSizeWithRefs(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to calculate 8x8 and 64x64 block columns and rows of the frame (compute_image_size(), 6.2.6) + * \param [inout] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void ComputeImageSize(Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to parse loop filter params syntax (loop_filter_params(), 6.2.8) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void LoopFilterParams(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to parse quantization params syntax (quantization_params(), 6.2.9) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void QuantizationParams(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to parse delta quantizer syntax (read_delta_q(), 6.2.10) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \return int8_t + */ + int8_t ReadDeltaQ(const uint8_t *p_stream, size_t &offset); + + /*! \brief Function to parse segmentation params syntax (segmentation_params(), 6.2.11) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void SegmentationParams(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to parse probability syntax (read_delta_q(), 6.2.12) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \return uint8_t + */ + uint8_t ReadProb(const uint8_t *p_stream, size_t &offset); + + /*! \brief Function to parse tile info syntax (tile_info(), 6.2.13) + * \param [in] p_stream Pointer to the bit stream + * \param [inout] offset Bit offset + * \param [out] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void TileInfo(const uint8_t *p_stream, size_t &offset, Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to set up Y and UV dequantization values based on segmentation parameters. 8.6.1. + * \param [in] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void SetupSegDequant(Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to return the quantizer index for the current block. + * \param [in] p_uncomp_header Pointer to uncompressed header struct + * \param [in] seg_id Segment id + * \return quantizer index + */ + int GetQIndex(Vp9UncompressedHeader *p_uncomp_header, int seg_id); + + /*! \brief Function to get DC quantization parameter + * \param [in] bit_depth Bit depth + * \param [in] seg_id index Quantization parameter index + * \return DC quantization parameter + */ + int DcQ(int bit_depth, int index); + + /*! \brief Function to get AC quantization parameter + * \param [in] bit_depth Bit depth + * \param [in] seg_id index Quantization parameter index + * \return AC quantization parameter + */ + int AcQ(int bit_depth, int index); + + /*! \brief Function to prepare a filter strength lookup table once per frame. 8.8.1. + * \param [in] p_uncomp_header Pointer to uncompressed header struct + * \return None + */ + void LoopFilterFrameInit(Vp9UncompressedHeader *p_uncomp_header); + + /*! \brief Function to read igned integer using n bits for the value and 1 bit for a sign flag 4.10.6. su(n). + * \param [in] p_stream Bit stream pointer + * \param [in] bit_offset Starting bit offset + * \param [out] bit_offset Updated bit offset + * \param [in] num_bits Number of bits to read + * \return The signed value + */ + inline int32_t ReadSigned(const uint8_t *p_stream, size_t &bit_offset, int num_bits) { + uint32_t u_value = Parser::ReadBits(p_stream, bit_offset, num_bits); + uint8_t sign = Parser::GetBit(p_stream, bit_offset); + return sign ? -u_value : u_value; + } +}; \ No newline at end of file diff --git a/src/rocdecode/roc_decoder_caps.h b/src/rocdecode/roc_decoder_caps.h index 36641c3d1c..4acb84f363 100644 --- a/src/rocdecode/roc_decoder_caps.h +++ b/src/rocdecode/roc_decoder_caps.h @@ -120,17 +120,19 @@ private: // , vcn_instances_for_gcn_arch_name1}}, // av1 is available only on VCN3.0 and above vcn_spec_table = { - {"gfx908",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2160, 64, 64}}}, 2}}, - {"gfx90a",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2160, 64, 64}}}, 2}}, - {"gfx942",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 3}}, - {"gfx1030",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, - {"gfx1031",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, - {"gfx1032",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, - {"gfx1100",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, - {"gfx1101",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 1}}, - {"gfx1102",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, - {"gfx1200",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, - {"gfx1201",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, + {"gfx908",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2160, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}}, 2}}, + {"gfx90a",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2160, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}}, 2}}, + {"gfx940",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 3}}, + {"gfx941",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 4}}, + {"gfx942",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 3}}, + {"gfx1030",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, + {"gfx1031",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, + {"gfx1032",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, + {"gfx1100",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, + {"gfx1101",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 1}}, + {"gfx1102",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, + {"gfx1200",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, + {"gfx1201",{{{rocDecVideoCodec_HEVC, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 7680, 4320, 64, 64}}, {rocDecVideoCodec_AVC, {{rocDecVideoChromaFormat_420}, {0}, 1, 4096, 2176, 64, 64}}, {rocDecVideoCodec_VP9, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}, {rocDecVideoCodec_AV1, {{rocDecVideoChromaFormat_420}, {0, 2}, 3, 8192, 4352, 64, 64}}}, 2}}, }; } RocDecVcnCodecSpec(const RocDecVcnCodecSpec&) = delete; diff --git a/src/rocdecode/vaapi/vaapi_videodecoder.cpp b/src/rocdecode/vaapi/vaapi_videodecoder.cpp index d95434fb6b..fdc9e92f9f 100644 --- a/src/rocdecode/vaapi/vaapi_videodecoder.cpp +++ b/src/rocdecode/vaapi/vaapi_videodecoder.cpp @@ -150,6 +150,13 @@ rocDecStatus VaapiVideoDecoder::CreateDecoderConfig() { case rocDecVideoCodec_AVC: va_profile_ = VAProfileH264Main; break; + case rocDecVideoCodec_VP9: + if (decoder_create_info_.bit_depth_minus_8 == 0) { + va_profile_ = VAProfileVP9Profile0; + } else if (decoder_create_info_.bit_depth_minus_8 == 2) { + va_profile_ = VAProfileVP9Profile2; + } + break; case rocDecVideoCodec_AV1: #if VA_CHECK_VERSION(1,6,0) va_profile_ = VAProfileAV1Profile0; @@ -315,6 +322,28 @@ rocDecStatus VaapiVideoDecoder::SubmitDecode(RocdecPicParams *pPicParams) { } break; } + + case rocDecVideoCodec_VP9: { + for (int i = 0; i < 8; i++) { + if (pPicParams->pic_params.vp9.reference_frames[i] != 0xFF) { + if (pPicParams->pic_params.vp9.reference_frames[i] >= va_surface_ids_.size()) { + ERR("Reference frame index exceeded the VAAPI surface pool limit."); + return ROCDEC_INVALID_PARAMETER; + } + pPicParams->pic_params.vp9.reference_frames[i] = va_surface_ids_[pPicParams->pic_params.vp9.reference_frames[i]]; + } + } + pic_params_ptr = (void*)&pPicParams->pic_params.vp9; + pic_params_size = sizeof(RocdecVp9PicParams); + slice_params_ptr = (void*)pPicParams->slice_params.vp9; + slice_params_size = sizeof(RocdecVp9SliceParams); + if ((pic_params_size != sizeof(VADecPictureParameterBufferVP9)) || (slice_params_size != sizeof(VASliceParameterBufferVP9))) { + ERR("VP9 data_buffer parameter_size not matching vaapi parameter buffer size."); + return ROCDEC_RUNTIME_ERROR; + } + break; + } + case rocDecVideoCodec_AV1: { pPicParams->pic_params.av1.current_frame = curr_surface_id;