Files
rocm-systems/src/parser/vp9_parser.cpp
T
jeffqjiangNew 9c113d5ee9 * rocDecode/VP9: Increased DPB buffer size to handle streams with the maximum number of the reference frames allowed. (#488)
- DPB buffer size was set to NUM_REF_FRAMES(8) which can not handle streams with 8 reference frames. We increase DPB size from 8 to 10 (same strategy as AV1) to be able to handle these streams.
2025-01-07 20:43:49 -05:00

1138 строки
60 KiB
C++

/*
Copyright (c) 2024 - 2025 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));
memset(y_dequant_, 0, sizeof(y_dequant_));
memset(uv_dequant_, 0, sizeof(uv_dequant_));
memset(lvl_lookup_, 0, sizeof(lvl_lookup_));
InitDpb();
num_frames_in_chunck_ = 1;
frame_sizes_.assign(1, 0);
}
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_BUFFER_POOL_MAX_SIZE);
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;
CheckSuperframe(p_stream, pic_data_size);
uint8_t *pic_data_ptr = const_cast<uint8_t*>(p_stream);
for (int frame_index = 0; frame_index < num_frames_in_chunck_; frame_index++) {
if ((ret = ParseUncompressedHeader(pic_data_ptr, frame_sizes_[frame_index])) != 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;
}
if (uncompressed_header_.show_existing_frame) {
int disp_idx = dpb_buffer_.virtual_buffer_index[uncompressed_header_.frame_to_show_map_idx];
if (disp_idx == INVALID_INDEX) {
ERR("Invalid existing frame index to show.");
return PARSER_INVALID_ARG;
}
if (pfn_display_picture_cb_) {
disp_idx = dpb_buffer_.frame_store[disp_idx].dec_buf_idx;
decode_buffer_pool_[disp_idx].use_status |= kFrameUsedForDisplay;
decode_buffer_pool_[disp_idx].pts = curr_pts_;
// Insert into output/display picture list
if (num_output_pics_ < dec_buf_pool_size_) {
output_pic_list_[num_output_pics_] = disp_idx;
num_output_pics_++;
} else {
ERR("Display list size larger than decode buffer pool size!");
return PARSER_OUT_OF_RANGE;
}
}
#if DBGINFO
PrintDpb();
#endif // DBGINFO
} else {
pic_stream_data_ptr_ = pic_data_ptr;
pic_stream_data_size_ = frame_sizes_[frame_index];
num_slices_ = 1;
if ((ret = FindFreeInDecBufPool()) != PARSER_OK) {
return ret;
}
if ((ret = FindFreeInDpbAndMark()) != PARSER_OK) {
return ret;
}
if ((ret = SendPicForDecode()) != PARSER_OK) {
ERR(STR("Failed to decode!"));
return ret;
}
#if DBGINFO
PrintDpb();
#endif // DBGINFO
// Output decoded pictures from DPB if any are ready
if (pfn_display_picture_cb_ && num_output_pics_ > 0) {
if ((ret = OutputDecodedPictures(false)) != PARSER_OK) {
return ret;
}
}
UpdateRefFrames();
pic_count_++;
dpb_buffer_.dec_ref_count[curr_pic_.pic_idx]--;
CheckAndUpdateDecStatus();
}
pic_data_ptr += frame_sizes_[frame_index];
}
return PARSER_OK;
}
void Vp9VideoParser::CheckSuperframe(const uint8_t *p_stream, uint32_t chunk_data_size) {
const uint32_t superframe_marker = 6; // 0b110
bool is_superframe = false;
int num_frames = 1;
int size_index = 0;
int size_bytes = 0;
uint8_t last_byte = p_stream[chunk_data_size - 1];
if ((last_byte >> 5) == superframe_marker) {
size_bytes = ((last_byte >> 3) & 0x3) + 1;
num_frames = (last_byte & 0x7) + 1;
size_index = 2 + num_frames * size_bytes;
// Check if the first byte and the last byte match
if (chunk_data_size >= size_index && p_stream[chunk_data_size - size_index] == last_byte) {
is_superframe = true;
}
}
if (is_superframe) {
if (num_frames > frame_sizes_.size()) {
frame_sizes_.resize(num_frames);
}
int offset = chunk_data_size - size_index + 1;
for (int i = 0; i < num_frames; i++) {
int count = 0;
frame_sizes_[i] = 0;
do {
frame_sizes_[i] = (p_stream[offset++] << (8 * count)) + frame_sizes_[i];
count++;
} while (count < size_bytes);
}
num_frames_in_chunck_ = num_frames;
} else {
num_frames_in_chunck_ = 1;
frame_sizes_[0] = chunk_data_size;
}
}
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_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;
for (int i = 0; i < VP9_NUM_REF_FRAMES; i++) {
p_pic_param->reference_frames[i] = 0xFF;
if (dpb_buffer_.virtual_buffer_index[i] != INVALID_INDEX) {
p_pic_param->reference_frames[i] = dpb_buffer_.frame_store[dpb_buffer_.virtual_buffer_index[i]].dec_buf_idx;
}
}
RocdecVp9SliceParams *p_tile_params = &tile_params_;
p_tile_params->slice_data_offset = 0;
p_tile_params->slice_data_size = pic_stream_data_size_;
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 DBGINFO
PrintVaapiParams();
#endif // DBGINFO
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::UpdateRefFrames() {
for (int i = 0; i < VP9_NUM_REF_FRAMES; i++) {
if ((uncompressed_header_.refresh_frame_flags >> i) & 1) {
dpb_buffer_.ref_frame_width[i] = uncompressed_header_.frame_size.frame_width;
dpb_buffer_.ref_frame_height[i] = uncompressed_header_.frame_size.frame_height;
dpb_buffer_.ref_subsampling_x[i] = uncompressed_header_.color_config.subsampling_x;
dpb_buffer_.ref_subsampling_y[i] = uncompressed_header_.color_config.subsampling_y;
dpb_buffer_.ref_bit_depth[i] = uncompressed_header_.color_config.bit_depth;
if (dpb_buffer_.virtual_buffer_index[i] != INVALID_INDEX) {
dpb_buffer_.dec_ref_count[dpb_buffer_.virtual_buffer_index[i]]--;
}
dpb_buffer_.virtual_buffer_index[i] = curr_pic_.pic_idx;
dpb_buffer_.dec_ref_count[curr_pic_.pic_idx]++;
}
}
}
void Vp9VideoParser::InitDpb() {
int i;
memset(&dpb_buffer_, 0, sizeof(DecodedPictureBuffer));
for (i = 0; i < VP9_BUFFER_POOL_MAX_SIZE; i++) {
dpb_buffer_.frame_store[i].pic_idx = i;
dpb_buffer_.frame_store[i].use_status = kNotUsed;
dpb_buffer_.dec_ref_count[i] = 0;
}
for (i = 0; i < VP9_NUM_REF_FRAMES; i++) {
dpb_buffer_.virtual_buffer_index[i] = INVALID_INDEX;
}
}
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;
decode_buffer_pool_[dec_buf_index].pts = curr_pts_;
return PARSER_OK;
}
ParserResult Vp9VideoParser::FindFreeInDpbAndMark() {
int i;
for (i = 0; i < VP9_BUFFER_POOL_MAX_SIZE; i++ ) {
if (dpb_buffer_.dec_ref_count[i] == 0) {
break;
}
}
if (i == VP9_BUFFER_POOL_MAX_SIZE) {
ERR("DPB buffer overflow!");
return PARSER_NOT_FOUND;
}
curr_pic_.pic_idx = i;
curr_pic_.use_status = kFrameUsedForDecode;
dpb_buffer_.frame_store[curr_pic_.pic_idx] = curr_pic_;
dpb_buffer_.dec_ref_count[curr_pic_.pic_idx]++;
// Mark as used in decode/display buffer pool
if (pfn_display_picture_cb_ && uncompressed_header_.show_frame) {
int disp_idx = curr_pic_.dec_buf_idx;
decode_buffer_pool_[disp_idx].use_status |= kFrameUsedForDisplay;
decode_buffer_pool_[disp_idx].pts = curr_pts_;
// Insert into output/display picture list
if (num_output_pics_ < dec_buf_pool_size_) {
output_pic_list_[num_output_pics_] = disp_idx;
num_output_pics_++;
} else {
ERR("Display list size larger than decode buffer pool size!");
return PARSER_OUT_OF_RANGE;
}
}
return PARSER_OK;
}
void Vp9VideoParser::CheckAndUpdateDecStatus() {
for (int i = 0; i < VP9_BUFFER_POOL_MAX_SIZE; i++) {
if (dpb_buffer_.frame_store[i].use_status != kNotUsed && dpb_buffer_.dec_ref_count[i] == 0) {
dpb_buffer_.frame_store[i].use_status = kNotUsed;
decode_buffer_pool_[dpb_buffer_.frame_store[i].dec_buf_idx].use_status &= ~kFrameUsedForDecode;
}
}
}
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) {
SetupPastIndependence(p_uncomp_header);
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++) {
// save_probs( i )
}
} else if (p_uncomp_header->reset_frame_context == 2) {
// 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;
// steps in 7.2.6
}
void Vp9VideoParser::SetupPastIndependence(Vp9UncompressedHeader *p_uncomp_header) {
for (int i = 0; i < VP9_MAX_SEGMENTS; i++) {
for (int j = 0; j < VP9_SEG_LVL_MAX; j++) {
p_uncomp_header->segmentation_params.feature_data[i][j] = 0;
p_uncomp_header->segmentation_params.feature_enabled[i][j] = 0;
}
}
p_uncomp_header->segmentation_params.segmentation_abs_or_delta_update = 0;
// At block level, PrevSegmentIds[ row ][ col ] is set equal to 0 for row = 0..MiRows-1 and col = 0..MiCols-1
p_uncomp_header->loop_filter_params.loop_filter_delta_enabled = 1;
p_uncomp_header->loop_filter_params.loop_filter_ref_deltas[kVp9IntraFrame] = 1;
p_uncomp_header->loop_filter_params.loop_filter_ref_deltas[kVp9LastFrame] = 0;
p_uncomp_header->loop_filter_params.loop_filter_ref_deltas[kVp9GoldenFrame] = -1;
p_uncomp_header->loop_filter_params.loop_filter_ref_deltas[kVp9AltRefFrame] = -1;
p_uncomp_header->loop_filter_params.loop_filter_mode_deltas[0] = 0;
p_uncomp_header->loop_filter_params.loop_filter_mode_deltas[1] = 0;
for (int i = 0; i < VP9_MAX_REF_FRAMES; i++) {
p_uncomp_header->ref_frame_sign_bias[i] = 0;
}
}
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));
}
if (p_uncomp_header->loop_filter_params.loop_filter_delta_enabled) {
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);
}
}
}
}
}
#if DBGINFO
void Vp9VideoParser::PrintVaapiParams() {
int i;
MSG("=======================");
MSG("VAAPI parameter Info: ");
MSG("=======================");
MSG("pic_width = " << dec_pic_params_.pic_width);
MSG("pic_height = " << dec_pic_params_.pic_height);
MSG("curr_pic_idx = " << dec_pic_params_.curr_pic_idx);
MSG("field_pic_flag = " << dec_pic_params_.field_pic_flag);
MSG("bottom_field_flag = " << dec_pic_params_.bottom_field_flag);
MSG("second_field = " << dec_pic_params_.second_field);
MSG("bitstream_data_len = " << dec_pic_params_.bitstream_data_len);
MSG("num_slices = " << dec_pic_params_.num_slices);
MSG("ref_pic_flag = " << dec_pic_params_.ref_pic_flag);
MSG("intra_pic_flag = " << dec_pic_params_.intra_pic_flag);
MSG("=======================");
MSG("Picture parameter Info:");
MSG("=======================");
RocdecVp9PicParams *p_pic_param = &dec_pic_params_.pic_params.vp9;
MSG("frame_width = " << p_pic_param->frame_width);
MSG("frame_height = " << p_pic_param->frame_height);
MSG_NO_NEWLINE("reference_frames[]:");
for (i = 0; i < VP9_NUM_REF_FRAMES; i++) {
MSG_NO_NEWLINE(" " << p_pic_param->reference_frames[i]);
}
MSG("");
MSG("subsampling_x = " << p_pic_param->pic_fields.bits.subsampling_x);
MSG("subsampling_y = " << p_pic_param->pic_fields.bits.subsampling_y);
MSG("frame_type = " << p_pic_param->pic_fields.bits.frame_type);
MSG("show_frame = " << p_pic_param->pic_fields.bits.show_frame);
MSG("error_resilient_mode = " << p_pic_param->pic_fields.bits.error_resilient_mode);
MSG("intra_only = " << p_pic_param->pic_fields.bits.intra_only);
MSG("allow_high_precision_mv = " << p_pic_param->pic_fields.bits.allow_high_precision_mv);
MSG("mcomp_filter_type = " << p_pic_param->pic_fields.bits.mcomp_filter_type);
MSG("frame_parallel_decoding_mode = " << p_pic_param->pic_fields.bits.frame_parallel_decoding_mode);
MSG("reset_frame_context = " << p_pic_param->pic_fields.bits.reset_frame_context);
MSG("refresh_frame_context = " << p_pic_param->pic_fields.bits.refresh_frame_context);
MSG("frame_context_idx = " << p_pic_param->pic_fields.bits.frame_context_idx);
MSG("segmentation_enabled = " << p_pic_param->pic_fields.bits.segmentation_enabled);
MSG("segmentation_temporal_update = " << p_pic_param->pic_fields.bits.segmentation_temporal_update);
MSG("segmentation_update_map = " << p_pic_param->pic_fields.bits.segmentation_update_map);
MSG("last_ref_frame = " << p_pic_param->pic_fields.bits.last_ref_frame);
MSG("last_ref_frame_sign_bias = " << p_pic_param->pic_fields.bits.last_ref_frame_sign_bias);
MSG("golden_ref_frame = " << p_pic_param->pic_fields.bits.golden_ref_frame);
MSG("golden_ref_frame_sign_bias = " << p_pic_param->pic_fields.bits.golden_ref_frame_sign_bias);
MSG("alt_ref_frame = " << p_pic_param->pic_fields.bits.alt_ref_frame);
MSG("alt_ref_frame_sign_bias = " << p_pic_param->pic_fields.bits.alt_ref_frame_sign_bias);
MSG("lossless_flag = " << p_pic_param->pic_fields.bits.lossless_flag);
MSG("filter_level = " << static_cast<uint32_t>(p_pic_param->filter_level));
MSG("sharpness_level = " << static_cast<uint32_t>(p_pic_param->sharpness_level));
MSG("log2_tile_rows = " << static_cast<uint32_t>(p_pic_param->log2_tile_rows));
MSG("log2_tile_columns = " << static_cast<uint32_t>(p_pic_param->log2_tile_columns));
MSG("frame_header_length_in_bytes = " << static_cast<uint32_t>(p_pic_param->frame_header_length_in_bytes));
MSG("first_partition_size = " << p_pic_param->first_partition_size);
MSG_NO_NEWLINE("mb_segment_tree_probs[]:");
for (i = 0; i < 7; i++) {
MSG_NO_NEWLINE(" " << static_cast<uint32_t>(p_pic_param->mb_segment_tree_probs[i]));
}
MSG("");
MSG_NO_NEWLINE("segment_pred_probs[]:");
for (i = 0; i < 3; i++) {
MSG_NO_NEWLINE(" " << static_cast<uint32_t>(p_pic_param->segment_pred_probs[i]));
}
MSG("");
MSG("profile = " << static_cast<uint32_t>(p_pic_param->profile));
MSG("bit_depth = " << static_cast<uint32_t>(p_pic_param->bit_depth));
MSG("=======================");
MSG("Tile parameter Info: ");
MSG("=======================");
RocdecVp9SliceParams *p_tile_param = dec_pic_params_.slice_params.vp9;
MSG("slice_data_size = " << p_tile_param->slice_data_size);
MSG("slice_data_offset = " << p_tile_param->slice_data_offset);
MSG("slice_data_flag = " << p_tile_param->slice_data_flag);
for (i = 0; i < 8; i++) {
RocdecVp9SegmentParameter *p_seg_param = &p_tile_param->seg_param[i];
MSG("Segment " << i << ":");
MSG("segment_reference_enabled = " << p_seg_param->segment_flags.fields.segment_reference_enabled);
MSG("segment_reference = " << p_seg_param->segment_flags.fields.segment_reference);
MSG("segment_reference_skipped = " << p_seg_param->segment_flags.fields.segment_reference_skipped);
MSG_NO_NEWLINE("filter_level[4][2]: ");
for (int j = 0; j < 4; j++) {
MSG_NO_NEWLINE("(" << static_cast<uint32_t>(p_seg_param->filter_level[j][0]) << " " << static_cast<uint32_t>(p_seg_param->filter_level[j][1]) << ") ");
}
MSG("");
MSG("luma_ac_quant_scale = " << p_seg_param->luma_ac_quant_scale);
MSG("luma_dc_quant_scale = " << p_seg_param->luma_dc_quant_scale);
MSG("chroma_ac_quant_scale = " << p_seg_param->chroma_ac_quant_scale);
MSG("chroma_dc_quant_scale = " << p_seg_param->chroma_dc_quant_scale);
}
}
void Vp9VideoParser::PrintDpb() {
uint32_t i;
MSG("=======================");
MSG("DPB buffer content: ");
MSG("=======================");
MSG("Current frame: pic_idx = " << curr_pic_.pic_idx << ", dec_buf_idx = " << curr_pic_.dec_buf_idx);
for (i = 0; i < VP9_BUFFER_POOL_MAX_SIZE; i++) {
MSG("Frame store " << i << ": " << "dec_ref_count = " << dpb_buffer_.dec_ref_count[i] << ", pic_idx = " << dpb_buffer_.frame_store[i].pic_idx << ", dec_buf_idx = " << dpb_buffer_.frame_store[i].dec_buf_idx << ", use_status = " << dpb_buffer_.frame_store[i].use_status);
}
MSG_NO_NEWLINE("virtual_buffer_index[] =");
for (i = 0; i < VP9_NUM_REF_FRAMES; i++) {
MSG_NO_NEWLINE(" " << dpb_buffer_.virtual_buffer_index[i]);
}
MSG("");
MSG("Decode buffer pool:");
for(i = 0; i < dec_buf_pool_size_; i++) {
DecodeFrameBuffer *p_dec_buf = &decode_buffer_pool_[i];
MSG("Decode buffer " << i << ": use_status = " << p_dec_buf->use_status << ", pts = " << p_dec_buf->pts);
}
MSG("num_output_pics_ = " << num_output_pics_);
if (num_output_pics_) {
MSG_NO_NEWLINE("output_pic_list:");
for (i = 0; i < num_output_pics_; i++) {
MSG_NO_NEWLINE(" " << output_pic_list_[i]);
}
MSG("");
}
}
#endif // DBGINFO