2
0
Ficheiros
rocm-systems/projects/rocdecode/src/parser/avc_parser.cpp
T

1347 linhas
65 KiB
C++
Em bruto Vista normal Histórico

2024-01-16 20:57:40 -05:00
/*
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.
*/
#include "avc_parser.h"
AvcVideoParser::AvcVideoParser() {
prev_has_mmco_5_ = 0;
curr_has_mmco_5_ = 0;
prev_ref_pic_bottom_field_ = 0;
curr_ref_pic_bottom_field_ = 0;
}
AvcVideoParser::~AvcVideoParser() {
}
rocDecStatus AvcVideoParser::Initialize(RocdecParserParams *p_params) {
return RocVideoParser::Initialize(p_params);
}
rocDecStatus AvcVideoParser::UnInitialize() {
return ROCDEC_SUCCESS;
2024-01-16 20:57:40 -05:00
}
rocDecStatus AvcVideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) {
if (p_data->payload && p_data->payload_size) {
if (ParsePictureData(p_data->payload, p_data->payload_size) != PARSER_OK) {
ERR(STR("Parser failed!"));
return ROCDEC_RUNTIME_ERROR;
}
// Init Roc decoder for the first time or reconfigure the existing decoder
if (new_sps_activated_) {
if (NotifyNewSps(&sps_list_[active_sps_id_]) != PARSER_OK) {
2024-01-16 20:57:40 -05:00
return ROCDEC_RUNTIME_ERROR;
}
new_sps_activated_ = false;
}
pic_count_++;
} else if (!(p_data->flags & ROCDEC_PKT_ENDOFSTREAM)) {
// If no payload and EOS is not set, treated as invalid.
return ROCDEC_INVALID_PARAMETER;
}
return ROCDEC_SUCCESS;
}
ParserResult AvcVideoParser::ParsePictureData(const uint8_t *p_stream, uint32_t pic_data_size) {
ParserResult ret = PARSER_OK;
pic_data_buffer_ptr_ = (uint8_t*)p_stream;
pic_data_size_ = pic_data_size;
curr_byte_offset_ = 0;
start_code_num_ = 0;
curr_start_code_offset_ = 0;
next_start_code_offset_ = 0;
slice_num_ = 0;
sei_message_count_ = 0;
sei_payload_size_ = 0;
do {
ret = GetNalUnit();
if (ret == PARSER_NOT_FOUND) {
ERR(STR("Error: no start code found in the frame data."));
return ret;
}
// Parse the NAL unit
if (nal_unit_size_) {
// start code + NAL unit header = 4 bytes
int ebsp_size = nal_unit_size_ - 4 > RBSP_BUF_SIZE ? RBSP_BUF_SIZE : nal_unit_size_ - 4; // only copy enough bytes for header parsing
nal_unit_header_ = ParseNalUnitHeader(pic_data_buffer_ptr_[curr_start_code_offset_ + 3]);
switch (nal_unit_header_.nal_unit_type) {
case kAvcNalTypeSeq_Parameter_Set: {
memcpy(rbsp_buf_, (pic_data_buffer_ptr_ + curr_start_code_offset_ + 4), ebsp_size);
rbsp_size_ = EbspToRbsp(rbsp_buf_, 0, ebsp_size);
ParseSps(rbsp_buf_, rbsp_size_);
break;
}
case kAvcNalTypePic_Parameter_Set: {
memcpy(rbsp_buf_, (pic_data_buffer_ptr_ + curr_start_code_offset_ + 4), ebsp_size);
rbsp_size_ = EbspToRbsp(rbsp_buf_, 0, ebsp_size);
ParsePps(rbsp_buf_, rbsp_size_);
break;
}
case kAvcNalTypeSlice_IDR:
case kAvcNalTypeSlice_Non_IDR:
case kAvcNalTypeSlice_Data_Partition_A:
case kAvcNalTypeSlice_Data_Partition_B:
case kAvcNalTypeSlice_Data_Partition_C: {
memcpy(rbsp_buf_, (pic_data_buffer_ptr_ + curr_start_code_offset_ + 4), ebsp_size);
rbsp_size_ = EbspToRbsp(rbsp_buf_, 0, ebsp_size);
// For each picture, only parse the first slice header
if (slice_num_ == 0) {
// Save slice NAL unit header
slice_nal_unit_header_ = nal_unit_header_;
// Use the data directly from demuxer without copying
pic_stream_data_ptr_ = pic_data_buffer_ptr_ + curr_start_code_offset_;
// Picture stream data size is calculated as the diff between the frame end and the first slice offset.
// This is to consider the possibility of non-slice NAL units between slices.
pic_stream_data_size_ = pic_data_size - curr_start_code_offset_;
ParseSliceHeader(rbsp_buf_, rbsp_size_, &slice_header_0_);
// Start decode process
// Todo
}
slice_num_++;
break;
}
case kAvcNalTypeSEI_Info: {
if (pfn_get_sei_message_cb_) {
// Todo
}
break;
}
case kAvcNalTypeEnd_Of_Seq: {
break;
}
case kAvcNalTypeEnd_Of_Stream: {
pic_count_ = 0;
break;
}
default:
break;
}
}
// Break if this is the last NAL unit
if (ret == PARSER_EOF) {
break;
}
} while (1);
return PARSER_OK;
}
ParserResult AvcVideoParser::NotifyNewSps(AvcSeqParameterSet *p_sps) {
video_format_params_.codec = rocDecVideoCodec_H264;
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_sps->bit_depth_luma_minus8;
video_format_params_.bit_depth_chroma_minus8 = p_sps->bit_depth_chroma_minus8;
video_format_params_.progressive_sequence = p_sps->frame_mbs_only_flag ? 1 : 0;
video_format_params_.min_num_decode_surfaces = dpb_buffer_.dpb_size;
video_format_params_.coded_width = pic_width_;
video_format_params_.coded_height = pic_height_;
video_format_params_.chroma_format = static_cast<rocDecVideoChromaFormat>(p_sps->chroma_format_idc);
// Table 6-1
int sub_width_c, sub_height_c;
switch (video_format_params_.chroma_format) {
case rocDecVideoChromaFormat_Monochrome: {
sub_width_c = 0; // not defined
sub_height_c = 0; // not defined
break;
}
case rocDecVideoChromaFormat_420: {
sub_width_c = 2;
sub_height_c = 2;
break;
}
case rocDecVideoChromaFormat_422: {
sub_width_c = 2;
sub_height_c = 1;
break;
}
case rocDecVideoChromaFormat_444: {
if (p_sps->separate_colour_plane_flag) {
sub_width_c = 0; // not defined
sub_height_c = 0; // not defined
} else {
sub_width_c = 1;
sub_height_c = 1;
}
break;
}
default:
ERR(STR("Error: Sequence Callback function - Chroma Format is not supported"));
return PARSER_FAIL;
}
int chroma_array_type = p_sps->separate_colour_plane_flag ? 0 : p_sps->chroma_format_idc;
int crop_unit_x, crop_unit_y;
if (chroma_array_type == 0) {
crop_unit_x = 1; // (7-19)
crop_unit_y = 2 - p_sps->frame_mbs_only_flag; // (7-20)
} else {
crop_unit_x = sub_width_c; // (7-21)
crop_unit_y = sub_height_c * (2 - p_sps->frame_mbs_only_flag); // (7-22)
}
if (p_sps->frame_cropping_flag) {
video_format_params_.display_area.left = crop_unit_x * p_sps->frame_crop_left_offset;
video_format_params_.display_area.top = crop_unit_y * p_sps->frame_crop_top_offset;
video_format_params_.display_area.right = pic_width_ - (crop_unit_x * p_sps->frame_crop_right_offset);
video_format_params_.display_area.bottom = pic_height_ - (crop_unit_y * p_sps->frame_crop_bottom_offset);
} else { // default values
video_format_params_.display_area.left = 0;
video_format_params_.display_area.top = 0;
video_format_params_.display_area.right = pic_width_;
video_format_params_.display_area.bottom = pic_height_;
}
video_format_params_.bitrate = 0;
if (p_sps->vui_parameters_present_flag) {
if (p_sps->vui_seq_parameters.aspect_ratio_info_present_flag) {
video_format_params_.display_aspect_ratio.x = p_sps->vui_seq_parameters.sar_width;
video_format_params_.display_aspect_ratio.y = p_sps->vui_seq_parameters.sar_height;
} else { // default values
video_format_params_.display_aspect_ratio.x = 0;
video_format_params_.display_aspect_ratio.y = 0;
}
}
if (p_sps->vui_parameters_present_flag) {
video_format_params_.video_signal_description.video_format = p_sps->vui_seq_parameters.video_format;
video_format_params_.video_signal_description.video_full_range_flag = p_sps->vui_seq_parameters.video_full_range_flag;
video_format_params_.video_signal_description.color_primaries = p_sps->vui_seq_parameters.colour_primaries;
video_format_params_.video_signal_description.transfer_characteristics = p_sps->vui_seq_parameters.transfer_characteristics;
video_format_params_.video_signal_description.matrix_coefficients = p_sps->vui_seq_parameters.matrix_coefficients;
video_format_params_.video_signal_description.reserved_zero_bits = 0;
}
video_format_params_.seqhdr_data_length = 0;
// callback function with RocdecVideoFormat params filled out
if (pfn_sequece_cb_(parser_params_.pUserData, &video_format_params_) == 0) {
ERR("Sequence callback function failed.");
return PARSER_FAIL;
} else {
return PARSER_OK;
}
}
2024-01-16 20:57:40 -05:00
AvcNalUnitHeader AvcVideoParser::ParseNalUnitHeader(uint8_t header_byte) {
size_t bit_offset = 0;
AvcNalUnitHeader nal_header;
nal_header.forbidden_zero_bit = Parser::GetBit(&header_byte, bit_offset);
nal_header.nal_ref_idc = Parser::ReadBits(&header_byte, bit_offset, 2);
nal_header.nal_unit_type = Parser::ReadBits(&header_byte, bit_offset, 5);
return nal_header;
}
const int Flat_4x4_16[16] = {
16,16,16,16,
16,16,16,16,
16,16,16,16,
16,16,16,16
};
const int Flat_8x8_16[64] = {
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16,
16,16,16,16,16,16,16,16
};
const int Default_4x4_Intra[16] = {
6, 13, 13, 20,
20, 20, 28, 28,
28, 28, 32, 32,
32, 37, 37, 42
};
const int Default_4x4_Inter[16] = {
10, 14, 14, 20,
20, 20, 24, 24,
24, 24, 27, 27,
27, 30, 30, 34
};
const int Default_8x8_Intra[64] = {
6, 10, 10, 13, 11, 13, 16, 16,
16, 16, 18, 18, 18, 18, 18, 23,
23, 23, 23, 23, 23, 25, 25, 25,
25, 25, 25, 25, 27, 27, 27, 27,
27, 27, 27, 27, 29, 29, 29, 29,
29, 29, 29, 31, 31, 31, 31, 31,
31, 33, 33, 33, 33, 33, 36, 36,
36, 36, 38, 38, 38, 40, 40, 42
};
const int Default_8x8_Inter[64] = {
9, 13, 13, 15, 13, 15, 17, 17,
17, 17, 19, 19, 19, 19, 19, 21,
21, 21, 21, 21, 21, 22, 22, 22,
22, 22, 22, 22, 24, 24, 24, 24,
24, 24, 24, 24, 25, 25, 25, 25,
25, 25, 25, 27, 27, 27, 27, 27,
27, 28, 28, 28, 28, 28, 30, 30,
30, 30, 32, 32, 32, 33, 33, 35
};
void AvcVideoParser::ParseSps(uint8_t *p_stream, size_t size) {
size_t offset = 0; // current bit offset
AvcSeqParameterSet *p_sps = nullptr;
// Parse and temporarily store till set id
uint32_t profile_idc = Parser::ReadBits(p_stream, offset, 8);
uint32_t constraint_set0_flag = Parser::GetBit(p_stream, offset);
uint32_t constraint_set1_flag = Parser::GetBit(p_stream, offset);
uint32_t constraint_set2_flag = Parser::GetBit(p_stream, offset);
uint32_t constraint_set3_flag = Parser::GetBit(p_stream, offset);
uint32_t constraint_set4_flag = Parser::GetBit(p_stream, offset);
uint32_t constraint_set5_flag = Parser::GetBit(p_stream, offset);
uint32_t reserved_zero_2bits = Parser::ReadBits(p_stream, offset, 2);
uint32_t level_idc = Parser::ReadBits(p_stream, offset, 8);
uint32_t seq_parameter_set_id = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps = &sps_list_[seq_parameter_set_id];
memset(p_sps, 0, sizeof(AvcSeqParameterSet));
p_sps->profile_idc = profile_idc;
p_sps->constraint_set0_flag = constraint_set0_flag;
p_sps->constraint_set1_flag = constraint_set1_flag;
p_sps->constraint_set2_flag = constraint_set2_flag;
p_sps->constraint_set3_flag = constraint_set3_flag;
p_sps->constraint_set4_flag = constraint_set4_flag;
p_sps->constraint_set5_flag = constraint_set5_flag;
p_sps->reserved_zero_2bits = reserved_zero_2bits;
p_sps->level_idc = level_idc;
p_sps->seq_parameter_set_id = seq_parameter_set_id;
if (p_sps->profile_idc == 100 ||
p_sps->profile_idc == 110 ||
p_sps->profile_idc == 122 ||
p_sps->profile_idc == 244 ||
p_sps->profile_idc == 44 ||
p_sps->profile_idc == 83 ||
p_sps->profile_idc == 86 ||
p_sps->profile_idc == 118 ||
p_sps->profile_idc == 128 ||
p_sps->profile_idc == 138 ||
p_sps->profile_idc == 139 ||
p_sps->profile_idc == 134 ||
p_sps->profile_idc == 135) {
p_sps->chroma_format_idc = Parser::ExpGolomb::ReadUe(p_stream, offset);
if (p_sps->chroma_format_idc == 3) {
p_sps->separate_colour_plane_flag = Parser::GetBit(p_stream, offset);
}
p_sps->bit_depth_luma_minus8 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->bit_depth_chroma_minus8 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->qpprime_y_zero_transform_bypass_flag = Parser::GetBit(p_stream, offset);
p_sps->seq_scaling_matrix_present_flag = Parser::GetBit(p_stream, offset);
if (p_sps->seq_scaling_matrix_present_flag == 1) {
for (int i = 0; i < ((p_sps->chroma_format_idc != 3) ? 8 : 12); i++) {
p_sps->seq_scaling_list_present_flag[i] = Parser::GetBit(p_stream, offset);
if (p_sps->seq_scaling_list_present_flag[i] == 1) {
if ( i < 6 ) {
GetScalingList(p_stream, offset, p_sps->scaling_list_4x4[i], 16, &p_sps->use_default_scaling_matrix_4x4_flag[i]);
} else {
GetScalingList(p_stream, offset, p_sps->scaling_list_8x8[i - 6], 64, &p_sps->use_default_scaling_matrix_8x8_flag[i - 6]);
}
}
}
}
} else {
p_sps->chroma_format_idc = 1;
}
// Setup default scaling list if needed
if (p_sps->seq_scaling_matrix_present_flag == 0) {
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 16; j++) {
p_sps->scaling_list_4x4[i][j] = Flat_4x4_16[j];
}
}
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 64; j++) {
p_sps->scaling_list_8x8[i][j] = Flat_8x8_16[j];
}
}
} else {
// 4 x 4
for (int i = 0; i < 6; i++) {
if (!p_sps->seq_scaling_list_present_flag[i]) { // fall back rule set A
if (i == 0) {
for (int j = 0; j < 16; j++) {
p_sps->scaling_list_4x4[i][j] = Default_4x4_Intra[j];
}
} else if (i == 3) {
for (int j = 0; j < 16; j++) {
p_sps->scaling_list_4x4[i][j] = Default_4x4_Inter[j];
}
} else {
for (int j = 0; j < 16; j++) {
p_sps->scaling_list_4x4[i][j] = p_sps->scaling_list_4x4[i - 1][j];
}
}
} else {
if (p_sps->use_default_scaling_matrix_4x4_flag[i]) {
if (i < 3) {
for (int j = 0; j < 16; j++) {
p_sps->scaling_list_4x4[i][j] = Default_4x4_Intra[j];
}
} else {
for (int j = 0; j < 16; j++) {
p_sps->scaling_list_4x4[i][j] = Default_4x4_Inter[j];
}
}
}
}
}
// 8 x 8
for (int i = 0; i < 6; i++) {
if(!p_sps->seq_scaling_list_present_flag[i + 6]) { // fall back rule set A
if (i == 0) {
for (int j = 0; j < 64; j++) {
p_sps->scaling_list_8x8[i][j] = Default_8x8_Intra[j];
}
} else if (i == 1) {
for (int j = 0; j < 64; j++) {
p_sps->scaling_list_8x8[i][j] = Default_8x8_Inter[j];
}
} else {
for (int j = 0; j < 64; j++) {
p_sps->scaling_list_8x8[i][j] = p_sps->scaling_list_8x8[i - 2][j];
}
}
} else {
if (p_sps->use_default_scaling_matrix_8x8_flag[i]) {
if (i % 2 == 0) {
for (int j = 0; j < 64; j++) {
p_sps->scaling_list_8x8[i][j] = Default_8x8_Intra[j];
}
} else {
for (int j = 0; j < 64; j++) {
p_sps->scaling_list_8x8[i][j] = Default_8x8_Inter[j];
}
}
}
}
}
}
p_sps->log2_max_frame_num_minus4 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->pic_order_cnt_type = Parser::ExpGolomb::ReadUe(p_stream, offset);
if (p_sps->pic_order_cnt_type == 0 ) {
p_sps->log2_max_pic_order_cnt_lsb_minus4 = Parser::ExpGolomb::ReadUe(p_stream, offset);
//MaxPicOrderCntLsb = pow(2, p_sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
} else if (p_sps->pic_order_cnt_type == 1) {
p_sps->delta_pic_order_always_zero_flag = Parser::GetBit(p_stream, offset);
p_sps->offset_for_non_ref_pic = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_sps->offset_for_top_to_bottom_field = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_sps->num_ref_frames_in_pic_order_cnt_cycle = Parser::ExpGolomb::ReadUe(p_stream, offset);
for (int i = 0; i < p_sps->num_ref_frames_in_pic_order_cnt_cycle; i++) {
p_sps->offset_for_ref_frame[i] = Parser::ExpGolomb::ReadSe(p_stream, offset);
}
}
p_sps->max_num_ref_frames = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->gaps_in_frame_num_value_allowed_flag = Parser::GetBit(p_stream, offset);
p_sps->pic_width_in_mbs_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->pic_height_in_map_units_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->frame_mbs_only_flag = Parser::GetBit(p_stream, offset);
if (!p_sps->frame_mbs_only_flag) {
p_sps->mb_adaptive_frame_field_flag = Parser::GetBit(p_stream, offset);
}
p_sps->direct_8x8_inference_flag = Parser::GetBit(p_stream, offset);
p_sps->frame_cropping_flag = Parser::GetBit(p_stream, offset);
if (p_sps->frame_cropping_flag) {
p_sps->frame_crop_left_offset = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->frame_crop_right_offset = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->frame_crop_top_offset = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps->frame_crop_bottom_offset = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
p_sps->vui_parameters_present_flag = Parser::GetBit(p_stream, offset);
if (p_sps->vui_parameters_present_flag == 1) {
GetVuiParameters(p_stream, offset, &p_sps->vui_seq_parameters);
}
p_sps->is_received = 1; // confirm SPS with seq_parameter_set_id received (but not activated)
#if DBGINFO
PrintSps(p_sps);
#endif // DBGINFO
}
void AvcVideoParser::ParsePps(uint8_t *p_stream, size_t stream_size_in_byte) {
AvcSeqParameterSet *p_sps = nullptr;
AvcPicParameterSet *p_pps = nullptr;
size_t offset = 0; // current bit offset
// Parse and temporarily store
uint32_t pic_parameter_set_id = Parser::ExpGolomb::ReadUe(p_stream, offset);
uint32_t seq_parameter_set_id = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_sps = &sps_list_[seq_parameter_set_id];
p_pps = &pps_list_[pic_parameter_set_id];
memset(p_pps, 0, sizeof(AvcPicParameterSet));
p_pps->pic_parameter_set_id = pic_parameter_set_id;
p_pps->seq_parameter_set_id = seq_parameter_set_id;
p_pps->entropy_coding_mode_flag = Parser::GetBit(p_stream, offset);
p_pps->bottom_field_pic_order_in_frame_present_flag = Parser::GetBit(p_stream, offset);
p_pps->num_slice_groups_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
if (p_pps->num_slice_groups_minus1 > 0) {
p_pps->slice_group_map_type = Parser::ExpGolomb::ReadUe(p_stream, offset);
if (p_pps->slice_group_map_type == 0) {
for (int i_group = 0; i_group <= p_pps->num_slice_groups_minus1; i_group++) {
p_pps->run_length_minus1[i_group] = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
} else if (p_pps->slice_group_map_type == 2) {
for (int i_group = 0; i_group < p_pps->num_slice_groups_minus1; i_group++ ) {
p_pps->top_left[i_group] = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_pps->bottom_right[i_group] = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
} else if (p_pps->slice_group_map_type == 3 || p_pps->slice_group_map_type == 4 || p_pps->slice_group_map_type == 5) {
p_pps->slice_group_change_direction_flag = Parser::GetBit(p_stream, offset);
p_pps->slice_group_change_rate_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
} else if (p_pps->slice_group_map_type == 6) {
p_pps->pic_size_in_map_units_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
int slice_group_id_size = ceil(log2(p_pps->num_slice_groups_minus1 + 1));
for (int i = 0; i <= p_pps->pic_size_in_map_units_minus1; i++) {
//p_pps->slice_group_id[i] = Parser::ReadBits(p_stream, offset, slice_group_id_size);
int temp = Parser::ReadBits(p_stream, offset, slice_group_id_size);
ERR("AVC PPS parsing: slice_group_id memory not allocaed!");
}
}
}
p_pps->num_ref_idx_l0_default_active_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_pps->num_ref_idx_l1_default_active_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_pps->weighted_pred_flag = Parser::GetBit(p_stream, offset);
p_pps->weighted_bipred_idc = Parser::ReadBits(p_stream, offset, 2);
p_pps->pic_init_qp_minus26 = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_pps->pic_init_qs_minus26 = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_pps->chroma_qp_index_offset = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_pps->deblocking_filter_control_present_flag = Parser::GetBit(p_stream, offset);
p_pps->constrained_intra_pred_flag = Parser::GetBit(p_stream, offset);
p_pps->redundant_pic_cnt_present_flag = Parser::GetBit(p_stream, offset);
if (MoreRbspData(p_stream, stream_size_in_byte, offset)) {
p_pps->transform_8x8_mode_flag = Parser::GetBit(p_stream, offset);
p_pps->pic_scaling_matrix_present_flag = Parser::GetBit(p_stream, offset);
if (p_pps->pic_scaling_matrix_present_flag == 1) {
int count = p_sps->chroma_format_idc != 3 ? 2 : 6;
for (int i = 0; i < 6 + count * p_pps->transform_8x8_mode_flag; i++) {
p_pps->pic_scaling_list_present_flag [i] = Parser::GetBit(p_stream, offset);
if (p_pps->pic_scaling_list_present_flag[i] == 1) {
if ( i < 6 ) {
GetScalingList(p_stream, offset, p_pps->scaling_list_4x4[i], 16, &p_pps->use_default_scaling_matrix_4x4_flag[i]);
} else {
GetScalingList(p_stream, offset, p_pps->scaling_list_8x8[i - 6], 64, &p_pps->use_default_scaling_matrix_8x8_flag[i - 6]);
}
}
}
}
p_pps->second_chroma_qp_index_offset = Parser::ExpGolomb::ReadSe(p_stream, offset);
} else {
/// When second_chroma_qp_index_offset is not present, it shall be inferred to be equal to chroma_qp_index_offset.
p_pps->second_chroma_qp_index_offset = p_pps->chroma_qp_index_offset;
}
// Setup default scaling list if needed
if (p_pps->pic_scaling_matrix_present_flag == 0) {
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 16; j++) {
p_pps->scaling_list_4x4[i][j] = p_sps->scaling_list_4x4[i][j];
}
}
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 64; j++) {
p_pps->scaling_list_8x8[i][j] = p_sps->scaling_list_8x8[i][j];
}
}
} else {
// 4 x 4
for (int i = 0; i < 6; i++) {
if (p_pps->pic_scaling_list_present_flag[i] == 0) {
if (i == 0) {
if ( p_sps->seq_scaling_matrix_present_flag == 0) { // fall back rule set A
for (int j = 0; j < 16; j++) {
p_pps->scaling_list_4x4[i][j] = Default_4x4_Intra[j];
}
} else { // fall back rule set B
for (int j = 0; j < 16; j++) {
p_pps->scaling_list_4x4[i][j] = p_sps->scaling_list_4x4[i][j];
}
}
} else if (i == 3) {
if (p_sps->seq_scaling_matrix_present_flag == 0) { // fall back rule set A
for (int j = 0; j < 16; j++) {
p_pps->scaling_list_4x4[i][j] = Default_4x4_Inter[j];
}
} else { // fall back rule set B
for (int j = 0; j < 16; j++) {
p_pps->scaling_list_4x4[i][j] = p_sps->scaling_list_4x4[i][j];
}
}
} else {
for (int j = 0; j < 16; j++) {
p_pps->scaling_list_4x4[i][j] = p_pps->scaling_list_4x4[i - 1][j];
}
}
} else {
if (p_pps->use_default_scaling_matrix_4x4_flag[i]) {
if( i < 3 ) {
for (int j = 0; j < 16; j++) {
p_pps->scaling_list_4x4[i][j] = Default_4x4_Intra[j];
}
} else {
for (int j = 0; j < 16; j++) {
p_pps->scaling_list_4x4[i][j] = Default_4x4_Inter[j];
}
}
}
}
}
// 8 x 8
for (int i = 0; i < 6; i++) {
if (p_pps->pic_scaling_list_present_flag[i + 6] == 0) {
if (i == 0) {
if ( p_sps->seq_scaling_matrix_present_flag == 0) { // fall back rule set A
for (int j = 0; j < 64; j++) {
p_pps->scaling_list_8x8[i][j] = Default_8x8_Intra[j];
}
} else { // fall back rule set B
for (int j = 0; j < 64; j++) {
p_pps->scaling_list_8x8[i][j] = p_sps->scaling_list_8x8[i][j];
}
}
} else if (i == 1) {
if ( p_sps->seq_scaling_matrix_present_flag == 0) { // fall back rule set A
for (int j = 0; j < 64; j++) {
p_pps->scaling_list_8x8[i][j] = Default_8x8_Inter[j];
}
} else { // fall back rule set B
for (int j = 0; j < 64; j++) {
p_pps->scaling_list_8x8[i][j] = p_sps->scaling_list_8x8[i][j];
}
}
} else {
for (int j = 0; j < 64; j++) {
p_pps->scaling_list_8x8[i][j] = p_pps->scaling_list_8x8[i - 2][j];
}
}
} else {
if (p_pps->use_default_scaling_matrix_8x8_flag[i]) {
if ( i % 2 == 0) {
for (int j = 0; j < 64; j++) {
p_pps->scaling_list_8x8[i][j] = Default_8x8_Intra[j];
}
} else {
for (int j = 0; j < 64; j++) {
p_pps->scaling_list_8x8[i][j] = Default_8x8_Inter[j];
}
}
}
}
}
}
p_pps->is_received = 1; // confirm PPS with pic_parameter_set_id received (but not activated)
#if DBGINFO
PrintPps(p_pps);
#endif // DBGINFO
}
ParserResult AvcVideoParser::ParseSliceHeader(uint8_t *p_stream, size_t stream_size_in_byte, AvcSliceHeader *p_slice_header) {
int i;
size_t offset = 0; // current bit offset
AvcSeqParameterSet *p_sps = nullptr;
AvcPicParameterSet *p_pps = nullptr;
curr_has_mmco_5_ = 0;
memset(p_slice_header, 0, sizeof(AvcSliceHeader));
p_slice_header->first_mb_in_slice = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_slice_header->slice_type = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_slice_header->pic_parameter_set_id = Parser::ExpGolomb::ReadUe(p_stream, offset);
// Set active SPS and PPS for the current slice
active_pps_id_ = p_slice_header->pic_parameter_set_id;
p_pps = &pps_list_[active_pps_id_];
if (active_sps_id_ != p_pps->seq_parameter_set_id) {
active_sps_id_ = p_pps->seq_parameter_set_id;
p_sps = &sps_list_[active_sps_id_];
// Re-set DPB size.
dpb_buffer_.dpb_size = p_sps->max_num_ref_frames + 1;
dpb_buffer_.dpb_size = dpb_buffer_.dpb_size > AVC_MAX_DPB_FRAMES ? AVC_MAX_DPB_FRAMES : dpb_buffer_.dpb_size;
new_sps_activated_ = true; // Note: clear this flag after the actions are taken.
}
p_sps = &sps_list_[active_sps_id_];
// Check video dimension change
uint32_t curr_pic_width = (p_sps->pic_width_in_mbs_minus1 + 1) * AVC_MACRO_BLOCK_SIZE;
uint32_t curr_pic_height = (2 - p_sps->frame_mbs_only_flag) * (p_sps->pic_height_in_map_units_minus1 + 1) * AVC_MACRO_BLOCK_SIZE;
if ( pic_width_ != curr_pic_width || pic_height_ != curr_pic_height) {
pic_width_ = curr_pic_width;
pic_height_ = curr_pic_height;
// Take care of the case where a new SPS replaces the old SPS with the same id but with different dimensions
// Re-set DPB size.
dpb_buffer_.dpb_size = p_sps->max_num_ref_frames + 1;
dpb_buffer_.dpb_size = dpb_buffer_.dpb_size > AVC_MAX_DPB_FRAMES ? AVC_MAX_DPB_FRAMES : dpb_buffer_.dpb_size;
new_sps_activated_ = true; // Note: clear this flag after the actions are taken.
}
if (p_sps->separate_colour_plane_flag == 1) {
p_slice_header->colour_plane_id = Parser::ReadBits(p_stream, offset, 2);
}
p_slice_header->frame_num = Parser::ReadBits(p_stream, offset, p_sps->log2_max_frame_num_minus4 + 4);
if (p_sps->frame_mbs_only_flag != 1) {
p_slice_header->field_pic_flag = Parser::GetBit(p_stream, offset);
if (p_slice_header->field_pic_flag == 1)
{
p_slice_header->bottom_field_flag = Parser::GetBit(p_stream, offset);
}
} else {
p_slice_header->field_pic_flag = 0;
p_slice_header->bottom_field_flag = 0;
}
if ( nal_unit_header_.nal_ref_idc ) {
curr_ref_pic_bottom_field_ = p_slice_header->bottom_field_flag;
}
if (nal_unit_header_.nal_unit_type == kAvcNalTypeSlice_IDR) {
p_slice_header->idr_pic_id = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
if (p_sps->pic_order_cnt_type == 0) {
p_slice_header->pic_order_cnt_lsb = Parser::ReadBits(p_stream, offset, p_sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
if (p_pps->bottom_field_pic_order_in_frame_present_flag == 1 && p_slice_header->field_pic_flag != 1 ) {
p_slice_header->delta_pic_order_cnt_bottom = Parser::ExpGolomb::ReadSe(p_stream, offset);
}
}
if (p_sps->pic_order_cnt_type == 1 && p_sps->delta_pic_order_always_zero_flag != 1) {
p_slice_header->delta_pic_order_cnt[0] = Parser::ExpGolomb::ReadSe(p_stream, offset);
if (p_pps->bottom_field_pic_order_in_frame_present_flag == 1 && p_slice_header->field_pic_flag != 1) {
p_slice_header->delta_pic_order_cnt[1] = Parser::ExpGolomb::ReadSe(p_stream, offset);
}
}
if (p_pps->redundant_pic_cnt_present_flag == 1) {
p_slice_header->redundant_pic_cnt = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
if (p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6 ) { // B-Slice
p_slice_header->direct_spatial_mv_pred_flag = Parser::GetBit(p_stream, offset);
}
if (p_slice_header->slice_type == kAvcSliceTypeP || p_slice_header->slice_type == kAvcSliceTypeP_5 ||
p_slice_header->slice_type == kAvcSliceTypeSP || p_slice_header->slice_type == kAvcSliceTypeSP_8 ||
p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6) {
p_slice_header->num_ref_idx_active_override_flag = Parser::GetBit(p_stream, offset);
if (p_slice_header->num_ref_idx_active_override_flag == 1) {
p_slice_header->num_ref_idx_l0_active_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
if (p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6) {
p_slice_header->num_ref_idx_l1_active_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
} else {
p_slice_header->num_ref_idx_l0_active_minus1 = p_pps->num_ref_idx_l0_default_active_minus1;
p_slice_header->num_ref_idx_l1_active_minus1 = p_pps->num_ref_idx_l1_default_active_minus1;
}
}
// Bail out for NAL unit type 20/21
if ( nal_unit_header_.nal_unit_type == 21 || nal_unit_header_.nal_unit_type == 21) {
return PARSER_NOT_SUPPORTED;
}
// Ref picture list modification
int modification_of_pic_nums_idc;
if (p_slice_header->slice_type != kAvcSliceTypeI && p_slice_header->slice_type != kAvcSliceTypeSI &&
p_slice_header->slice_type != kAvcSliceTypeI_7 && p_slice_header->slice_type != kAvcSliceTypeSI_9) {
p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l0 = Parser::GetBit(p_stream, offset);
if (p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l0 == 1) {
i = 0;
do {
modification_of_pic_nums_idc = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_slice_header->ref_pic_list.modification_l0[i].modification_of_pic_nums_idc = modification_of_pic_nums_idc;
if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) {
p_slice_header->ref_pic_list.modification_l0[i].abs_diff_pic_num_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
} else if (modification_of_pic_nums_idc == 2) {
p_slice_header->ref_pic_list.modification_l0[i].long_term_pic_num = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
i++;
} while (modification_of_pic_nums_idc != 3);
}
}
if (p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6) {
p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l1 = Parser::GetBit(p_stream, offset);
if (p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l1 == 1) {
i = 0;
do {
modification_of_pic_nums_idc = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_slice_header->ref_pic_list.modification_l1[i].modification_of_pic_nums_idc = modification_of_pic_nums_idc;
if (modification_of_pic_nums_idc == 0 || modification_of_pic_nums_idc == 1) {
p_slice_header->ref_pic_list.modification_l1[i].abs_diff_pic_num_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
} else if(modification_of_pic_nums_idc == 2) {
p_slice_header->ref_pic_list.modification_l1[i].long_term_pic_num = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
i++;
} while (modification_of_pic_nums_idc != 3);
}
}
// Prediction weight table
if ((p_pps->weighted_pred_flag == 1 &&
((p_slice_header->slice_type == kAvcSliceTypeP || p_slice_header->slice_type == kAvcSliceTypeP_5) ||
(p_slice_header->slice_type == kAvcSliceTypeSP || p_slice_header->slice_type == kAvcSliceTypeSP_8))) ||
(p_pps->weighted_bipred_idc == 1 &&
(p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6))) {
p_slice_header->pred_weight_table.luma_log2_weight_denom = Parser::ExpGolomb::ReadUe(p_stream, offset);
int ChromaArrayType = p_sps->separate_colour_plane_flag == 0 ? p_sps->chroma_format_idc : 0;
if (ChromaArrayType != 0) {
p_slice_header->pred_weight_table.chroma_log2_weight_denom = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
for (i = 0; i <= p_slice_header->num_ref_idx_l0_active_minus1; i++) {
p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l0_flag = Parser::GetBit(p_stream, offset);
if (p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l0_flag == 1) {
p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l0 = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_slice_header->pred_weight_table.weight_factor[i].luma_offset_l0 = Parser::ExpGolomb::ReadSe(p_stream, offset);
} else {
p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l0 = 1 << p_slice_header->pred_weight_table.luma_log2_weight_denom;
p_slice_header->pred_weight_table.weight_factor[i].luma_offset_l0 = 0;
}
if (ChromaArrayType != 0) {
p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l0_flag = Parser::GetBit(p_stream, offset);
if (p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l0_flag == 1) {
for (int j = 0; j < 2; j++) {
p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l0[j] = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_slice_header->pred_weight_table.weight_factor[i].chroma_offset_l0[j] = Parser::ExpGolomb::ReadSe(p_stream, offset);
}
} else {
for (int j = 0; j < 2; j++) {
p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l0[j] = 1 << p_slice_header->pred_weight_table.chroma_log2_weight_denom;
p_slice_header->pred_weight_table.weight_factor[i].chroma_offset_l0[j] = 0;
}
}
}
}
if (p_slice_header->slice_type == kAvcSliceTypeB || p_slice_header->slice_type == kAvcSliceTypeB_6) {
for (int i = 0; i <= p_slice_header->num_ref_idx_l1_active_minus1; i++) {
p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l1_flag = Parser::GetBit(p_stream, offset);
if (p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l1_flag == 1) {
p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l1 = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_slice_header->pred_weight_table.weight_factor[i].luma_offset_l1 = Parser::ExpGolomb::ReadSe(p_stream, offset);
} else {
p_slice_header->pred_weight_table.weight_factor[i].luma_weight_l1 = 1 << p_slice_header->pred_weight_table.luma_log2_weight_denom;
p_slice_header->pred_weight_table.weight_factor[i].luma_offset_l1 = 0;
}
if (ChromaArrayType != 0 ) {
p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l1_flag = Parser::GetBit(p_stream, offset);
if (p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l1_flag == 1) {
for (int j = 0; j < 2; j++) {
p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l1[j] = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_slice_header->pred_weight_table.weight_factor[i].chroma_offset_l1[j] = Parser::ExpGolomb::ReadSe(p_stream, offset);
}
} else {
for (int j = 0; j < 2; j++) {
p_slice_header->pred_weight_table.weight_factor[i].chroma_weight_l1[j] = 1 << p_slice_header->pred_weight_table.chroma_log2_weight_denom;
p_slice_header->pred_weight_table.weight_factor[i].chroma_offset_l1[j] = 0;
}
}
}
}
}
}
// Decoded reference picture marking.
int memory_management_control_operation;
if (nal_unit_header_.nal_ref_idc != 0) {
if (nal_unit_header_.nal_unit_type == kAvcNalTypeSlice_IDR) {
p_slice_header->dec_ref_pic_marking.no_output_of_prior_pics_flag = Parser::GetBit(p_stream, offset);
p_slice_header->dec_ref_pic_marking.long_term_reference_flag = Parser::GetBit(p_stream, offset);
} else {
p_slice_header->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = Parser::GetBit(p_stream, offset);
if (p_slice_header->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag == 1) {
i = 0;
do {
memory_management_control_operation = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_slice_header->dec_ref_pic_marking.mmco[i].memory_management_control_operation = memory_management_control_operation;
if (memory_management_control_operation == 1 || memory_management_control_operation == 3) {
p_slice_header->dec_ref_pic_marking.mmco[i].difference_of_pic_nums_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
if (memory_management_control_operation == 2) {
p_slice_header->dec_ref_pic_marking.mmco[i].long_term_pic_num = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
if (memory_management_control_operation == 3 || memory_management_control_operation == 6) {
p_slice_header->dec_ref_pic_marking.mmco[i].long_term_frame_idx = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
if (memory_management_control_operation == 4) {
p_slice_header->dec_ref_pic_marking.mmco[i].max_long_term_frame_idx_plus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
if ( memory_management_control_operation == 5) {
curr_has_mmco_5_ = 1;
}
i++;
} while (memory_management_control_operation != 0);
p_slice_header->dec_ref_pic_marking.mmco_count = i - 1;
}
}
}
if (p_pps->entropy_coding_mode_flag == 1 &&
p_slice_header->slice_type != kAvcSliceTypeI && p_slice_header->slice_type != kAvcSliceTypeSI &&
p_slice_header->slice_type != kAvcSliceTypeI_7 && p_slice_header->slice_type != kAvcSliceTypeSI_9) {
p_slice_header->cabac_init_idc = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
p_slice_header->slice_qp_delta = Parser::ExpGolomb::ReadSe(p_stream, offset);
if (p_slice_header->slice_type == kAvcSliceTypeSP || p_slice_header->slice_type == kAvcSliceTypeSI ||
p_slice_header->slice_type == kAvcSliceTypeSP_8 || p_slice_header->slice_type == kAvcSliceTypeSI_9) {
if (p_slice_header->slice_type == kAvcSliceTypeSP || p_slice_header->slice_type == kAvcSliceTypeSP_8) {
p_slice_header->sp_for_switch_flag = Parser::GetBit(p_stream, offset);
}
p_slice_header->slice_qs_delta = Parser::ExpGolomb::ReadSe(p_stream, offset);
}
if (p_pps->deblocking_filter_control_present_flag == 1) {
p_slice_header->disable_deblocking_filter_idc = Parser::ExpGolomb::ReadUe(p_stream, offset);
if (p_slice_header->disable_deblocking_filter_idc != 1) {
p_slice_header->slice_alpha_c0_offset_div2 = Parser::ExpGolomb::ReadSe(p_stream, offset);
p_slice_header->slice_beta_offset_div2 = Parser::ExpGolomb::ReadSe(p_stream, offset);
}
}
if (p_pps->num_slice_groups_minus1 > 0 && p_pps->slice_group_map_type >= 3 && p_pps->slice_group_map_type <= 5) {
int size = ceil(log2((double)(p_sps->pic_height_in_map_units_minus1+1) / (double)(p_pps->slice_group_change_rate_minus1+1) + 1));
p_slice_header->slice_group_change_cycle = Parser::ReadBits(p_stream, offset, size);
}
#if DBGINFO
PrintSliceHeader(p_slice_header);
#endif // DBGINFO
return PARSER_OK;
}
void AvcVideoParser::GetScalingList(uint8_t *p_stream, size_t &offset, uint32_t *scaling_list, uint32_t list_size, uint32_t *use_default_scaling_matrix_flag) {
int32_t last_scale, next_scale, delta_scale;
last_scale = 8;
next_scale = 8;
for (int j = 0; j < list_size; j++) {
if (next_scale != 0) {
delta_scale = Parser::ExpGolomb::ReadSe(p_stream, offset);
next_scale = (last_scale + delta_scale + 256) % 256;
*use_default_scaling_matrix_flag = (j == 0 && next_scale == 0);
}
scaling_list[j] = (next_scale == 0) ? last_scale : next_scale;
last_scale = scaling_list[j];
}
}
void AvcVideoParser::GetVuiParameters(uint8_t *p_stream, size_t &offset, AvcVuiSeqParameters *p_vui_params) {
p_vui_params->aspect_ratio_info_present_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->aspect_ratio_info_present_flag == 1) {
p_vui_params->aspect_ratio_idc = Parser::ReadBits(p_stream, offset, 8);
if (p_vui_params->aspect_ratio_idc == 255 /*Extended_SAR*/) {
p_vui_params->sar_width = Parser::ReadBits(p_stream, offset, 16);
p_vui_params->sar_height = Parser::ReadBits(p_stream, offset, 16);
}
}
p_vui_params->overscan_info_present_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->overscan_info_present_flag == 1) {
p_vui_params->overscan_appropriate_flag = Parser::GetBit(p_stream, offset);
}
p_vui_params->video_signal_type_present_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->video_signal_type_present_flag == 1) {
p_vui_params->video_format = Parser::ReadBits(p_stream, offset, 3);
p_vui_params->video_full_range_flag = Parser::GetBit(p_stream, offset);
p_vui_params->colour_description_present_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->colour_description_present_flag == 1) {
p_vui_params->colour_primaries = Parser::ReadBits(p_stream, offset, 8);
p_vui_params->transfer_characteristics = Parser::ReadBits(p_stream, offset, 8);
p_vui_params->matrix_coefficients = Parser::ReadBits(p_stream, offset, 8);
}
}
p_vui_params->chroma_loc_info_present_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->chroma_loc_info_present_flag == 1) {
p_vui_params->chroma_sample_loc_type_top_field = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->chroma_sample_loc_type_bottom_field = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
p_vui_params->timing_info_present_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->timing_info_present_flag == 1) {
p_vui_params->num_units_in_tick = Parser::ReadBits(p_stream, offset, 32);
p_vui_params->time_scale = Parser::ReadBits(p_stream, offset, 32);
p_vui_params->fixed_frame_rate_flag = Parser::GetBit(p_stream, offset);
}
p_vui_params->nal_hrd_parameters_present_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->nal_hrd_parameters_present_flag == 1 ) {
p_vui_params->nal_hrd_parameters.cpb_cnt_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->nal_hrd_parameters.bit_rate_scale = Parser::ReadBits(p_stream, offset, 4);
p_vui_params->nal_hrd_parameters.cpb_size_scale = Parser::ReadBits(p_stream, offset, 4);
for (int SchedSelIdx = 0; SchedSelIdx <= p_vui_params->nal_hrd_parameters.cpb_cnt_minus1; SchedSelIdx ++) {
p_vui_params->nal_hrd_parameters.bit_rate_value_minus1[SchedSelIdx] = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->nal_hrd_parameters.cpb_size_value_minus1[SchedSelIdx] = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->nal_hrd_parameters.cbr_flag[SchedSelIdx] = Parser::ReadBits(p_stream, offset, 1);
}
p_vui_params->nal_hrd_parameters.initial_cpb_removal_delay_length_minus1 = Parser::ReadBits(p_stream, offset, 5);
p_vui_params->nal_hrd_parameters.cpb_removal_delay_length_minus1 = Parser::ReadBits(p_stream, offset, 5);
p_vui_params->nal_hrd_parameters.dpb_output_delay_length_minus1 = Parser::ReadBits(p_stream, offset, 5);
p_vui_params->nal_hrd_parameters.time_offset_length = Parser::ReadBits(p_stream, offset, 5);
}
p_vui_params->vcl_hrd_parameters_present_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->vcl_hrd_parameters_present_flag == 1) {
p_vui_params->vcl_hrd_parameters.cpb_cnt_minus1 = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->vcl_hrd_parameters.bit_rate_scale = Parser::ReadBits(p_stream, offset, 4);
p_vui_params->vcl_hrd_parameters.cpb_size_scale = Parser::ReadBits(p_stream, offset, 4);
for (int SchedSelIdx = 0; SchedSelIdx <= p_vui_params->vcl_hrd_parameters.cpb_cnt_minus1; SchedSelIdx ++) {
p_vui_params->vcl_hrd_parameters.bit_rate_value_minus1[SchedSelIdx] = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->vcl_hrd_parameters.cpb_size_value_minus1[SchedSelIdx] = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->vcl_hrd_parameters.cbr_flag[SchedSelIdx] = Parser::GetBit(p_stream, offset);
}
p_vui_params->vcl_hrd_parameters.initial_cpb_removal_delay_length_minus1 = Parser::ReadBits(p_stream, offset, 5);
p_vui_params->vcl_hrd_parameters.cpb_removal_delay_length_minus1 = Parser::ReadBits(p_stream, offset, 5);
p_vui_params->vcl_hrd_parameters.dpb_output_delay_length_minus1 = Parser::ReadBits(p_stream, offset, 5);
p_vui_params->vcl_hrd_parameters.time_offset_length = Parser::ReadBits(p_stream, offset, 5);
}
if (p_vui_params->nal_hrd_parameters_present_flag == 1 || p_vui_params->vcl_hrd_parameters_present_flag == 1) {
p_vui_params->low_delay_hrd_flag = Parser::GetBit(p_stream, offset);
}
p_vui_params->pic_struct_present_flag = Parser::GetBit(p_stream, offset);
p_vui_params->bitstream_restriction_flag = Parser::GetBit(p_stream, offset);
if (p_vui_params->bitstream_restriction_flag) {
p_vui_params->motion_vectors_over_pic_boundaries_flag = Parser::GetBit(p_stream, offset);
p_vui_params->max_bytes_per_pic_denom = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->max_bits_per_mb_denom = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->log2_max_mv_length_horizontal = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->log2_max_mv_length_vertical = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->num_reorder_frames = Parser::ExpGolomb::ReadUe(p_stream, offset);
p_vui_params->max_dec_frame_buffering = Parser::ExpGolomb::ReadUe(p_stream, offset);
}
}
bool AvcVideoParser::MoreRbspData(uint8_t *p_stream, size_t stream_size_in_byte, size_t bit_offset) {
bool more_rbsp_bits = false;
uint8_t curr_byte = p_stream[bit_offset >> 3];
uint8_t next_bytes[3];
uint32_t next_byte_offset = (bit_offset + 7) >> 3;
int bit_offset_in_byte = bit_offset % 8;
/// If the following bytes are not start code, we have more RBSP data. If we don't have enough bytes
/// in the stream, pad with 0.
next_bytes[0] = next_byte_offset < stream_size_in_byte ? p_stream[next_byte_offset] : 0;
next_bytes[1] = (next_byte_offset + 1) < stream_size_in_byte ? p_stream[next_byte_offset + 1] : 0;
next_bytes[2] = (next_byte_offset + 2) < stream_size_in_byte ? p_stream[next_byte_offset + 2] : 0;
if ( (next_bytes[0] == 0x00 && next_bytes[1] == 0x00 && next_bytes[2] == 0x00) || // padding zero bytes
(next_bytes[0] == 0x00 && next_bytes[1] == 0x00 && next_bytes[2] == 0x01) ) { // start code
/// Continue checking the existence of the trailing bits in the current byte.
} else {
return true;
}
/// Check if RBSP trailing bits immediately follow
if ((bit_offset_in_byte) == 0) {
if (curr_byte == 0x80) { // RBSP trailing bits
more_rbsp_bits = false;
} else {
more_rbsp_bits = true;
}
} else {
uint8_t curr_bit = curr_byte & (0x80 >> bit_offset_in_byte);
if ( curr_bit == 0 ) {
more_rbsp_bits = true; // rbsp_stop_one_bit has to be 1.
} else {
/// If this is the last bit, need to grab the next byte
if ( bit_offset_in_byte == 7 ) {
if ( next_bytes[0] != 0 ) {
more_rbsp_bits = true;
} else {
more_rbsp_bits = false;
}
} else {
bit_offset_in_byte++;
for (int i = bit_offset_in_byte; i < 8; i++) {
curr_bit = curr_byte & (0x80 >> i);
if ( curr_bit ) {
more_rbsp_bits = true;
break;
}
}
}
}
}
return more_rbsp_bits;
}
#if DBGINFO
void AvcVideoParser::PrintSps(AvcSeqParameterSet *p_sps) {
uint32_t i, j;
MSG("=======================");
MSG("Sequence parameter set: ");
MSG("=======================");
MSG("profile_idc = " << p_sps->profile_idc);
MSG("level_idc = " << p_sps->level_idc);
MSG("chroma_format_idc = " << p_sps->chroma_format_idc);
MSG("separate_colour_plane_flag = " << p_sps->separate_colour_plane_flag);
MSG("bit_depth_luma_minus8 = " << p_sps->bit_depth_luma_minus8);
MSG("bit_depth_chroma_minus8 = " << p_sps->bit_depth_chroma_minus8);
MSG("qpprime_y_zero_transform_bypass_flag = " << p_sps->qpprime_y_zero_transform_bypass_flag);
MSG("seq_scaling_matrix_present_flag = " << p_sps->seq_scaling_matrix_present_flag);
MSG_NO_NEWLINE("seq_scaling_list_present_flag[12]: ");
for (i = 0; i < 12; i++) {
MSG_NO_NEWLINE(" " << p_sps->seq_scaling_list_present_flag[i]);
}
MSG("");
MSG("scaling_list_4x4[6][16]:");
for (i = 0; i < 6; i++) {
for (j = 0; j < 16; j++) {
MSG_NO_NEWLINE(" " << p_sps->scaling_list_4x4[i][j]);
}
MSG("");
}
MSG("");
MSG("scaling_list_8x8[6][64]:");
for (i = 0; i < 6; i++) {
for (j = 0; j < 64; j++) {
MSG_NO_NEWLINE(" " << p_sps->scaling_list_8x8[i][j]);
}
MSG("");
}
MSG("");
MSG_NO_NEWLINE("use_default_scaling_matrix_4x4_flag[6]: ");
for (i = 0; i < 6; i++) {
MSG_NO_NEWLINE(" " << p_sps->use_default_scaling_matrix_4x4_flag[i]);
}
MSG("");
MSG_NO_NEWLINE("use_default_scaling_matrix_8x8_flag[6]: ");
for (i = 0; i < 6; i++) {
MSG_NO_NEWLINE(" " << p_sps->use_default_scaling_matrix_8x8_flag[i]);
}
MSG("");
MSG("log2_max_frame_num_minus4 = " << p_sps->log2_max_frame_num_minus4);
MSG("pic_order_cnt_type = " << p_sps->pic_order_cnt_type);
MSG("log2_max_pic_order_cnt_lsb_minus4 = " << p_sps->log2_max_pic_order_cnt_lsb_minus4);
MSG("delta_pic_order_always_zero_flag = " << p_sps->delta_pic_order_always_zero_flag);
MSG("offset_for_non_ref_pic = " << p_sps->offset_for_non_ref_pic);
MSG("offset_for_top_to_bottom_field = " << p_sps->offset_for_top_to_bottom_field);
MSG("num_ref_frames_in_pic_order_cnt_cycle = " << p_sps->num_ref_frames_in_pic_order_cnt_cycle);
MSG("offset_for_ref_frame[]: ....");
MSG("max_num_ref_frames = " << p_sps->max_num_ref_frames);
MSG("gaps_in_frame_num_value_allowed_flag = " << p_sps->gaps_in_frame_num_value_allowed_flag);
MSG("pic_width_in_mbs_minus1 = " << p_sps->pic_width_in_mbs_minus1);
MSG("pic_height_in_map_units_minus1 = " << p_sps->pic_height_in_map_units_minus1);
MSG("frame_mbs_only_flag = " << p_sps->frame_mbs_only_flag);
MSG("mb_adaptive_frame_field_flag = " << p_sps->mb_adaptive_frame_field_flag);
MSG("direct_8x8_inference_flag = " << p_sps->direct_8x8_inference_flag);
MSG("frame_cropping_flag = " << p_sps->frame_cropping_flag);
MSG("frame_crop_left_offset = " << p_sps->frame_crop_left_offset);
MSG("frame_crop_right_offset = " << p_sps->frame_crop_right_offset);
MSG("frame_crop_top_offset = " << p_sps->frame_crop_top_offset);
MSG("frame_crop_bottom_offset = " << p_sps->frame_crop_bottom_offset);
MSG("vui_parameters_present_flag = " << p_sps->vui_parameters_present_flag);
MSG("vui_seq_parameters: ....");
MSG("");
}
void AvcVideoParser::PrintPps(AvcPicParameterSet *p_pps) {
uint32_t i, j;
MSG("=======================");
MSG("Picture parameter set: ");
MSG("=======================");
MSG("pic_parameter_set_id = " << p_pps->pic_parameter_set_id);
MSG("seq_parameter_set_id = " << p_pps->seq_parameter_set_id);
MSG("entropy_coding_mode_flag = " << p_pps->entropy_coding_mode_flag);
MSG("bottom_field_pic_order_in_frame_present_flag = " << p_pps->bottom_field_pic_order_in_frame_present_flag);
MSG("num_slice_groups_minus1 = " << p_pps->num_slice_groups_minus1);
MSG("slice_group_map_type = " << p_pps->slice_group_map_type);
MSG("run_length_minus1[]: ....");
MSG("top_left[]: ....");
MSG("bottom_right[]: ....");
MSG("slice_group_change_direction_flag = " << p_pps->slice_group_change_direction_flag);
MSG("slice_group_change_rate_minus1 = " << p_pps->slice_group_change_rate_minus1);
MSG("pic_size_in_map_units_minus1 = " << p_pps->pic_size_in_map_units_minus1);
MSG("slice_group_id[]: ....");
MSG("num_ref_idx_l0_default_active_minus1 = " << p_pps->num_ref_idx_l0_default_active_minus1);
MSG("num_ref_idx_l1_default_active_minus1 = " << p_pps->num_ref_idx_l1_default_active_minus1);
MSG("weighted_pred_flag = " << p_pps->weighted_pred_flag);
MSG("weighted_bipred_idc = " << p_pps->weighted_bipred_idc);
MSG("pic_init_qp_minus26 = " << p_pps->pic_init_qp_minus26);
MSG("pic_init_qs_minus26 = " << p_pps->pic_init_qs_minus26);
MSG("chroma_qp_index_offset = " << p_pps->chroma_qp_index_offset);
MSG("deblocking_filter_control_present_flag = " << p_pps->deblocking_filter_control_present_flag);
MSG("constrained_intra_pred_flag = " << p_pps->constrained_intra_pred_flag);
MSG("redundant_pic_cnt_present_flag = " << p_pps->redundant_pic_cnt_present_flag);
MSG("transform_8x8_mode_flag = " << p_pps->transform_8x8_mode_flag);
MSG("pic_scaling_matrix_present_flag = " << p_pps->pic_scaling_matrix_present_flag);
MSG_NO_NEWLINE("pic_scaling_list_present_flag[12]: ");
for (i = 0; i < 12; i++) {
MSG_NO_NEWLINE(" " << p_pps->pic_scaling_list_present_flag[i]);
}
MSG("");
MSG("scaling_list_4x4[6][16]:");
for (i = 0; i < 6; i++) {
for (j = 0; j < 16; j++) {
MSG_NO_NEWLINE(" " << p_pps->scaling_list_4x4[i][j]);
}
MSG("");
}
MSG("");
MSG("scaling_list_8x8[6][64]:");
for (i = 0; i < 6; i++) {
for (j = 0; j < 64; j++) {
MSG_NO_NEWLINE(" " << p_pps->scaling_list_8x8[i][j]);
}
MSG("");
}
MSG("");
MSG_NO_NEWLINE("use_default_scaling_matrix_4x4_flag[6]: ");
for (i = 0; i < 6; i++) {
MSG_NO_NEWLINE(" " << p_pps->use_default_scaling_matrix_4x4_flag[i]);
}
MSG("");
MSG_NO_NEWLINE("use_default_scaling_matrix_8x8_flag[6]: ");
for (i = 0; i < 6; i++) {
MSG_NO_NEWLINE(" " << p_pps->use_default_scaling_matrix_8x8_flag[i]);
}
MSG("");
MSG("second_chroma_qp_index_offset = " << p_pps->second_chroma_qp_index_offset);
MSG("");
}
void AvcVideoParser::PrintSliceHeader(AvcSliceHeader *p_slice_header) {
uint32_t i, j;
MSG("======================");
MSG("Slice header");
MSG("======================");
MSG("first_mb_in_slice = " << p_slice_header->first_mb_in_slice);
MSG("slice_type = " << p_slice_header->slice_type);
MSG("pic_parameter_set_id = " << p_slice_header->pic_parameter_set_id);
MSG("frame_num = " << p_slice_header->frame_num);
MSG("field_pic_flag = " << p_slice_header->field_pic_flag);
MSG("bottom_field_flag = " << p_slice_header->bottom_field_flag);
MSG("idr_pic_id = " << p_slice_header->idr_pic_id);
MSG("pic_order_cnt_lsb = " << p_slice_header->pic_order_cnt_lsb);
MSG("delta_pic_order_cnt_bottom = " << p_slice_header->delta_pic_order_cnt_bottom);
MSG("delta_pic_order_cnt[2] = " << p_slice_header->delta_pic_order_cnt[0] << ", " << p_slice_header->delta_pic_order_cnt[1]);
MSG("redundant_pic_cnt = " << p_slice_header->redundant_pic_cnt);
MSG("direct_spatial_mv_pred_flag = " << p_slice_header->direct_spatial_mv_pred_flag);
MSG("num_ref_idx_active_override_flag = " << p_slice_header->num_ref_idx_active_override_flag);
MSG("num_ref_idx_l0_active_minus1 = " << p_slice_header->num_ref_idx_l0_active_minus1);
MSG("num_ref_idx_l1_active_minus1 = " << p_slice_header->num_ref_idx_l1_active_minus1);
MSG("Reference picture list modification:");
MSG("ref_pic_list_modification_flag_l0 = " << p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l0);
if ( p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l0 ){
MSG("Modification operations for list 0: ");
for (j = 0; j < AVC_MAX_REF_PICTURE_NUM; j++) {
MSG_NO_NEWLINE("(" << p_slice_header->ref_pic_list.modification_l0[j].modification_of_pic_nums_idc << ", " << p_slice_header->ref_pic_list.modification_l0[j].abs_diff_pic_num_minus1 << ", " << p_slice_header->ref_pic_list.modification_l0[j].long_term_pic_num << ") ");
}
MSG("");
}
MSG("ref_pic_list_modification_flag_l1 = " << p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l1);
if ( p_slice_header->ref_pic_list.ref_pic_list_modification_flag_l1 ) {
MSG("Modification operations for list 1: ");
for (j = 0; j < AVC_MAX_REF_PICTURE_NUM; j++) {
MSG_NO_NEWLINE("(" << p_slice_header->ref_pic_list.modification_l1[j].modification_of_pic_nums_idc << ", " << p_slice_header->ref_pic_list.modification_l1[j].abs_diff_pic_num_minus1 << ", " << p_slice_header->ref_pic_list.modification_l1[j].long_term_pic_num << ") ");
}
MSG("");
}
MSG("pred_weight_table: ....");
MSG("Decoded reference picture marking:");
AvcDecRefPicMarking *refMarking = &(p_slice_header->dec_ref_pic_marking);
MSG("no_output_of_prior_pics_flag = " << refMarking->no_output_of_prior_pics_flag);
MSG("long_term_reference_flag = " << refMarking->long_term_reference_flag);
MSG("adaptive_ref_pic_marking_mode_flag = " << refMarking->adaptive_ref_pic_marking_mode_flag);
if ( refMarking->adaptive_ref_pic_marking_mode_flag ) {
MSG("mmco_count = " << refMarking->mmco_count);
for (j = 0; j < AVC_MAX_REF_PICTURE_NUM; j++) {
MSG_NO_NEWLINE("(" << refMarking->mmco[j].memory_management_control_operation << ", " << refMarking->mmco[j].difference_of_pic_nums_minus1 << ", " << refMarking->mmco[j].long_term_pic_num << ", " << refMarking->mmco[j].long_term_frame_idx << ", " << refMarking->mmco[j].max_long_term_frame_idx_plus1 << ") ");
}
}
MSG("cabac_init_idc = " << p_slice_header->cabac_init_idc);
MSG("slice_qp_delta = " << p_slice_header->slice_qp_delta);
MSG("sp_for_switch_flag = " << p_slice_header->sp_for_switch_flag);
MSG("slice_qs_delta = " << p_slice_header->slice_qs_delta);
MSG("disable_deblocking_filter_idc = " << p_slice_header->disable_deblocking_filter_idc);
MSG("slice_alpha_c0_offset_div2 = " << p_slice_header->slice_alpha_c0_offset_div2);
MSG("slice_beta_offset_div2 = " << p_slice_header->slice_beta_offset_div2);
MSG("slice_group_change_cycle = " << p_slice_header->slice_group_change_cycle);
}
#endif // DBGINFO