Added initial code for VP9 support. (#442)
* * rocDecode/VP9: Initial code for VP9. - Added structures for VA-API. - Added defines for uncompressed header and parsing functions. * * rocDecode/VP9: Added decode frame call to VA-API. * * rocDecode/VP9: Added new sequence notification function. * * rocDecode/VP9: Intra decode started to work. * * rocDecode/VP9: Minor changes based on review comments. --------- Co-authored-by: Kiriti Gowda <kiritigowda@gmail.com>
Tá an tiomantas seo le fáil i:
tiomanta ag
GitHub
tuismitheoir
b3f8fec41b
tiomantas
3eb6bc2192
+242
-4
@@ -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;
|
||||
|
||||
|
||||
@@ -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<HevcVideoParser>();
|
||||
break;
|
||||
case rocDecVideoCodec_VP9:
|
||||
roc_parser_ = std::make_shared<Vp9VideoParser>();
|
||||
break;
|
||||
case rocDecVideoCodec_AV1:
|
||||
roc_parser_ = std::make_shared<Av1VideoParser>();
|
||||
break;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
|
||||
#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;
|
||||
@@ -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 <algorithm>
|
||||
#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<uint8_t*>(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<uint8_t*>(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<int>(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<int>(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<int>(inter_lvl), 0, VP9_MAX_LOOP_FILTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <tt>RocdecParserParams</tt> with codec type to initialize parser.
|
||||
* \return <tt>rocDecStatus</tt> 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 <tt>RocdecSourceDataPacket</tt>
|
||||
* @return <tt>rocDecStatus</tt> 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 <tt>uint8_t</tt> for the input stream to be parsed
|
||||
* \param [in] pic_data_size Size of the input stream
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
ParserResult ParsePictureData(const uint8_t *p_stream, uint32_t pic_data_size);
|
||||
|
||||
/*! \brief Function to notify decoder about new sequence format through callback
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
ParserResult NotifyNewSequence(Vp9UncompressedHeader *p_uncomp_header);
|
||||
|
||||
/*! \brief Function to fill the decode parameters and call back decoder to decode a picture
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
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 <tt>ParserResult</tt>
|
||||
*/
|
||||
ParserResult FlushDpb();
|
||||
|
||||
/*! \brief Function to find a free buffer in the decode buffer pool
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
ParserResult FindFreeInDecBufPool();
|
||||
|
||||
/*! \brief Function to find a free buffer in DPB for the current picture and mark it.
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
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 <tt>ParserResult</tt>
|
||||
*/
|
||||
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 <tt>ParserResult</tt>
|
||||
*/
|
||||
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 <tt>ParserResult</tt>
|
||||
*/
|
||||
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 <tt>int8_t</tt>
|
||||
*/
|
||||
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 <tt>uint8_t</tt>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Tagairt in Eagrán Nua
Cuir bac ar úsáideoir