* AV1 error resilience: Added invalid stream syntax element checks in various places. (#582)
- Added checks for allowed values for various stream syntax elements, according to AV1 specification.
This commit is contained in:
+109
-15
@@ -748,14 +748,19 @@ ParserResult Av1VideoParser::ReadObuHeaderAndSize() {
|
||||
}
|
||||
}
|
||||
|
||||
void Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t size) {
|
||||
ParserResult Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t size) {
|
||||
Av1SequenceHeader *p_seq_header = &seq_header_;
|
||||
size_t offset = 0; // current bit offset
|
||||
|
||||
memset(p_seq_header, 0, sizeof(Av1SequenceHeader));
|
||||
p_seq_header->seq_profile = Parser::ReadBits(p_stream, offset, 3);
|
||||
CHECK_ALLOWED_MAX("seq_profile", p_seq_header->seq_profile, 2);
|
||||
p_seq_header->still_picture = Parser::GetBit(p_stream, offset);
|
||||
p_seq_header->reduced_still_picture_header = Parser::GetBit(p_stream, offset);
|
||||
if (p_seq_header->reduced_still_picture_header == 1 && p_seq_header->still_picture != 1) {
|
||||
ERR("If reduced_still_picture_header is 1, still_picture is required to be 1.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (p_seq_header->reduced_still_picture_header) {
|
||||
p_seq_header->timing_info_present_flag = 0;
|
||||
@@ -772,7 +777,15 @@ void Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t size) {
|
||||
if (p_seq_header->timing_info_present_flag) {
|
||||
// timing_info()
|
||||
p_seq_header->timing_info.num_units_in_display_tick = Parser::ReadBits(p_stream, offset, 32);
|
||||
if (p_seq_header->timing_info.num_units_in_display_tick == 0) {
|
||||
ERR("num_units_in_display_tick is 0.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
p_seq_header->timing_info.time_scale = Parser::ReadBits(p_stream, offset, 32);
|
||||
if (p_seq_header->timing_info.time_scale == 0) {
|
||||
ERR("time_scale is 0.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
p_seq_header->timing_info.equal_picture_interval = Parser::GetBit(p_stream, offset);
|
||||
if (p_seq_header->timing_info.equal_picture_interval) {
|
||||
p_seq_header->timing_info.num_ticks_per_picture_minus_1 = ReadUVLC(p_stream, offset);
|
||||
@@ -793,6 +806,18 @@ void Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t size) {
|
||||
p_seq_header->operating_points_cnt_minus_1 = Parser::ReadBits(p_stream, offset, 5);
|
||||
for (int i = 0; i < p_seq_header->operating_points_cnt_minus_1 + 1; i++) {
|
||||
p_seq_header->operating_point_idc[i] = Parser::ReadBits(p_stream, offset, 12);
|
||||
if (i > 0) {
|
||||
for (int j = 0; j < i - 1; j++) {
|
||||
if (p_seq_header->operating_point_idc[i] == p_seq_header->operating_point_idc[j]) {
|
||||
ERR("operating_point_idc[" + TOSTR(i) + "] is equal to operating_point_idc[" + TOSTR(j) + "]");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p_seq_header->operating_point_idc[i] && obu_header_.obu_extension_flag != 1) {
|
||||
ERR("When operating_point_idc is not 0, obu_extension_flag is required to be 1.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
p_seq_header->seq_level_idx[i] = Parser::ReadBits(p_stream, offset, 5);
|
||||
if (p_seq_header->seq_level_idx[i] > 7) {
|
||||
p_seq_header->seq_tier[i] = Parser::GetBit(p_stream, offset);
|
||||
@@ -901,6 +926,7 @@ void Av1VideoParser::ParseSequenceHeaderObu(uint8_t *p_stream, size_t size) {
|
||||
CheckAndAdjustDecBufPoolSize(BUFFER_POOL_MAX_SIZE * 2);
|
||||
}
|
||||
p_seq_header->is_received = 1;
|
||||
return PARSER_OK;
|
||||
}
|
||||
|
||||
ParserResult Av1VideoParser::ParseFrameHeaderObu(uint8_t *p_stream, size_t size, int *p_bytes_parsed) {
|
||||
@@ -926,6 +952,7 @@ ParserResult Av1VideoParser::ParseFrameHeaderObu(uint8_t *p_stream, size_t size,
|
||||
}
|
||||
|
||||
ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t size, int *p_bytes_parsed) {
|
||||
ParserResult ret = PARSER_OK;
|
||||
size_t offset = 0; // current bit offset
|
||||
Av1SequenceHeader *p_seq_header = &seq_header_;
|
||||
Av1FrameHeader *p_frame_header = &frame_header_;
|
||||
@@ -952,6 +979,10 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s
|
||||
} else {
|
||||
p_frame_header->show_existing_frame = Parser::GetBit(p_stream, offset);
|
||||
if (p_frame_header->show_existing_frame == 1) {
|
||||
if (obu_header_.obu_type == kObuFrame) {
|
||||
ERR("show_existing_frame is 1 when obu_type is equal to OBU_FRAME.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
p_frame_header->frame_to_show_map_idx = Parser::ReadBits(p_stream, offset, 3);
|
||||
if (p_seq_header->decoder_model_info_present_flag && !p_seq_header->timing_info.equal_picture_interval) {
|
||||
// temporal_point_info()
|
||||
@@ -959,6 +990,7 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s
|
||||
}
|
||||
p_frame_header->refresh_frame_flags = 0;
|
||||
if (p_seq_header->frame_id_numbers_present_flag) {
|
||||
CHECK_ALLOWED_MAX("display_frame_id length", frame_id_len, 16);
|
||||
p_frame_header->display_frame_id = Parser::ReadBits(p_stream, offset, frame_id_len);
|
||||
}
|
||||
p_frame_header->frame_type = dpb_buffer_.ref_frame_type[p_frame_header->frame_to_show_map_idx];
|
||||
@@ -1067,6 +1099,10 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s
|
||||
p_frame_header->refresh_frame_flags = all_frames;
|
||||
} else {
|
||||
p_frame_header->refresh_frame_flags = Parser::ReadBits(p_stream, offset, 8);
|
||||
if (p_frame_header->frame_type == kIntraOnlyFrame && p_frame_header->refresh_frame_flags == 0xFF) {
|
||||
ERR("When frame_type is equal to INTRA_ONLY_FRAME, it is a requirement of bitstream conformance that refresh_frame_flags is not equal to 0xff.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
}
|
||||
if (!p_frame_header->frame_is_intra || p_frame_header->refresh_frame_flags != all_frames) {
|
||||
if (p_frame_header->error_resilient_mode && p_seq_header->enable_order_hint) {
|
||||
@@ -1080,7 +1116,9 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s
|
||||
}
|
||||
|
||||
if (p_frame_header->frame_is_intra) {
|
||||
FrameSize(p_stream, offset, p_seq_header, p_frame_header);
|
||||
if ((ret = FrameSize(p_stream, offset, p_seq_header, p_frame_header)) != PARSER_OK) {
|
||||
return ret;
|
||||
}
|
||||
RenderSize(p_stream, offset, p_frame_header);
|
||||
if (p_frame_header->allow_screen_content_tools && p_frame_header->frame_size.upscaled_width == p_frame_header->frame_size.frame_width) {
|
||||
p_frame_header->allow_intrabc = Parser::GetBit(p_stream, offset);
|
||||
@@ -1116,7 +1154,9 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s
|
||||
if (p_frame_header->frame_size_override_flag && !p_frame_header->error_resilient_mode) {
|
||||
FrameSizeWithRefs(p_stream, offset, p_seq_header, p_frame_header);
|
||||
} else {
|
||||
FrameSize(p_stream, offset, p_seq_header, p_frame_header);
|
||||
if ((ret = FrameSize(p_stream, offset, p_seq_header, p_frame_header)) != PARSER_OK) {
|
||||
return ret;
|
||||
}
|
||||
RenderSize(p_stream, offset, p_frame_header);
|
||||
}
|
||||
|
||||
@@ -1179,7 +1219,9 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s
|
||||
//motion_field_estimation());
|
||||
}
|
||||
|
||||
TileInfo(p_stream, offset, p_seq_header, p_frame_header);
|
||||
if ((ret = TileInfo(p_stream, offset, p_seq_header, p_frame_header)) != PARSER_OK) {
|
||||
return ret;
|
||||
}
|
||||
QuantizationParams(p_stream, offset, p_seq_header, p_frame_header);
|
||||
SegmentationParams(p_stream, offset, p_frame_header);
|
||||
DeltaQParams(p_stream, offset, p_frame_header);
|
||||
@@ -1212,6 +1254,10 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p_frame_header->coded_lossless == 1 && p_frame_header->delta_q_params.delta_q_present == 1) {
|
||||
ERR("It is a requirement of bitstream conformance that delta_q_present is equal to 0 when CodedLossless is equal to 1.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
|
||||
p_frame_header->all_lossless = p_frame_header->coded_lossless && (p_frame_header->frame_size.frame_width == p_frame_header->frame_size.upscaled_width);
|
||||
|
||||
@@ -1238,7 +1284,9 @@ ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t s
|
||||
p_frame_header->reduced_tx_set = Parser::GetBit(p_stream, offset);
|
||||
|
||||
GlobalMotionParams(p_stream, offset, p_frame_header);
|
||||
FilmGrainParams(p_stream, offset, p_seq_header, p_frame_header);
|
||||
if ((ret = FilmGrainParams(p_stream, offset, p_seq_header, p_frame_header)) != PARSER_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*p_bytes_parsed = (offset + 7) >> 3;
|
||||
p_frame_header->is_received = 1;
|
||||
@@ -1269,6 +1317,10 @@ ParserResult Av1VideoParser::ParseTileGroupObu(uint8_t *p_stream, size_t size) {
|
||||
p_tile_group->num_tiles = tile_cols * tile_rows;
|
||||
if (p_tile_group->num_tiles > 1) {
|
||||
tile_start_and_end_present_flag = Parser::GetBit(p_stream, offset);
|
||||
if (obu_header_.obu_type == kObuFrame && tile_start_and_end_present_flag != 0) {
|
||||
ERR("If obu_type is equal to OBU_FRAME, it is a requirement of bitstream conformance that the value of tile_start_and_end_present_flag is equal to 0.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
}
|
||||
if (p_tile_group->num_tiles == 1 || !tile_start_and_end_present_flag) {
|
||||
p_tile_group->tg_start = 0;
|
||||
@@ -1276,7 +1328,15 @@ ParserResult Av1VideoParser::ParseTileGroupObu(uint8_t *p_stream, size_t size) {
|
||||
} else {
|
||||
uint32_t tile_bits = p_frame_header->tile_info.tile_cols_log2 + p_frame_header->tile_info.tile_rows_log2;
|
||||
p_tile_group->tg_start = Parser::ReadBits(p_stream, offset, tile_bits);
|
||||
if (p_tile_group->tg_start != p_tile_group->num_tiles_parsed) {
|
||||
ERR("It is a requirement of bitstream conformance that the value of tg_start (" + TOSTR(p_tile_group->tg_start) + ") is equal to the value of TileNum (" + TOSTR(p_tile_group->num_tiles_parsed) + ") at the point that tile_group_obu is invoked.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
p_tile_group->tg_end = Parser::ReadBits(p_stream, offset, tile_bits);
|
||||
if (p_tile_group->tg_end < p_tile_group->tg_start) {
|
||||
ERR("It is a requirement of bitstream conformance that the value of tg_end (" + TOSTR(p_tile_group->tg_end) + ") is greater than or equal to tg_start (" + TOSTR(p_tile_group->tg_start) + ").");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
header_bytes = ((offset + 7) >> 3);
|
||||
@@ -1379,12 +1439,10 @@ void Av1VideoParser::ParseColorConfig(const uint8_t *p_stream, size_t &offset, A
|
||||
p_seq_header->color_config.subsampling_y = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (p_seq_header->color_config.subsampling_x && p_seq_header->color_config.subsampling_y) {
|
||||
p_seq_header->color_config.chroma_sample_position = Parser::ReadBits(p_stream, offset, 2);
|
||||
}
|
||||
}
|
||||
|
||||
p_seq_header->color_config.separate_uv_delta_q = Parser::GetBit(p_stream, offset);
|
||||
}
|
||||
|
||||
@@ -1405,11 +1463,13 @@ void Av1VideoParser::MarkRefFrames(Av1SequenceHeader *p_seq_header, Av1FrameHead
|
||||
}
|
||||
}
|
||||
|
||||
void Av1VideoParser::FrameSize(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
||||
ParserResult Av1VideoParser::FrameSize(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
||||
if (p_frame_header->frame_size_override_flag) {
|
||||
p_frame_header->frame_size.frame_width_minus_1 = Parser::ReadBits(p_stream, offset, p_seq_header->frame_width_bits_minus_1 + 1);
|
||||
CHECK_ALLOWED_MAX("frame_width_minus_1", p_frame_header->frame_size.frame_width_minus_1, p_seq_header->max_frame_width_minus_1);
|
||||
p_frame_header->frame_size.frame_width = p_frame_header->frame_size.frame_width_minus_1 + 1;
|
||||
p_frame_header->frame_size.frame_height_minus_1 = Parser::ReadBits(p_stream, offset, p_seq_header->frame_height_bits_minus_1 + 1);
|
||||
CHECK_ALLOWED_MAX("frame_height_minus_1", p_frame_header->frame_size.frame_height_minus_1, p_seq_header->max_frame_height_minus_1);
|
||||
p_frame_header->frame_size.frame_height = p_frame_header->frame_size.frame_height_minus_1 + 1;
|
||||
} else {
|
||||
p_frame_header->frame_size.frame_width_minus_1 = p_seq_header->max_frame_width_minus_1;
|
||||
@@ -1419,6 +1479,7 @@ void Av1VideoParser::FrameSize(const uint8_t *p_stream, size_t &offset, Av1Seque
|
||||
}
|
||||
SuperResParams(p_stream, offset, p_seq_header, p_frame_header);
|
||||
ComputeImageSize(p_frame_header);
|
||||
return PARSER_OK;
|
||||
}
|
||||
|
||||
void Av1VideoParser::SuperResParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
||||
@@ -1655,7 +1716,7 @@ void Av1VideoParser::LoadPrevious(Av1FrameHeader *p_frame_header) {
|
||||
}
|
||||
}
|
||||
|
||||
void Av1VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
||||
ParserResult Av1VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
||||
int32_t sb_cols;
|
||||
int32_t sb_rows;
|
||||
int32_t sb_shift;
|
||||
@@ -1699,6 +1760,7 @@ void Av1VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Av1Sequen
|
||||
}
|
||||
}
|
||||
tile_width_sb = (sb_cols + (1 << p_frame_header->tile_info.tile_cols_log2) - 1) >> p_frame_header->tile_info.tile_cols_log2;
|
||||
CHECK_ALLOWED_MAX("tileWidthSb", tile_width_sb, max_tile_width_sb);
|
||||
i = 0;
|
||||
for (start_sb = 0; start_sb < sb_cols; start_sb += tile_width_sb) {
|
||||
p_frame_header->tile_info.mi_col_starts[i] = start_sb << sb_shift;
|
||||
@@ -1706,6 +1768,7 @@ void Av1VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Av1Sequen
|
||||
}
|
||||
p_frame_header->tile_info.mi_col_starts[i] = p_frame_header->frame_size.mi_cols;
|
||||
p_frame_header->tile_info.tile_cols = i;
|
||||
CHECK_ALLOWED_MAX("TileCols", p_frame_header->tile_info.tile_cols, MAX_TILE_COLS);
|
||||
|
||||
min_log2_tile_rows = std::max(min_log2_tiles - p_frame_header->tile_info.tile_cols_log2, 0);
|
||||
p_frame_header->tile_info.tile_rows_log2 = min_log2_tile_rows;
|
||||
@@ -1718,6 +1781,7 @@ void Av1VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Av1Sequen
|
||||
}
|
||||
}
|
||||
tile_height_sb = (sb_rows + (1 << p_frame_header->tile_info.tile_rows_log2) - 1) >> p_frame_header->tile_info.tile_rows_log2;
|
||||
CHECK_ALLOWED_MAX("tileWidthSb * tileHeightSb", tile_width_sb * tile_height_sb, max_tile_area_sb);
|
||||
i = 0;
|
||||
for (start_sb = 0; start_sb < sb_rows; start_sb += tile_height_sb ) {
|
||||
p_frame_header->tile_info.mi_row_starts[i] = start_sb << sb_shift;
|
||||
@@ -1725,6 +1789,7 @@ void Av1VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Av1Sequen
|
||||
}
|
||||
p_frame_header->tile_info.mi_row_starts[i] = p_frame_header->frame_size.mi_rows;
|
||||
p_frame_header->tile_info.tile_rows = i;
|
||||
CHECK_ALLOWED_MAX("TileRows", p_frame_header->tile_info.tile_rows, MAX_TILE_ROWS);
|
||||
|
||||
for (i = 0; i < p_frame_header->tile_info.tile_cols - 1; i++) {
|
||||
p_frame_header->tile_info.width_in_sbs_minus_1[i] = tile_width_sb - 1;
|
||||
@@ -1747,6 +1812,7 @@ void Av1VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Av1Sequen
|
||||
}
|
||||
p_frame_header->tile_info.mi_col_starts[i] = p_frame_header->frame_size.mi_cols;
|
||||
p_frame_header->tile_info.tile_cols = i;
|
||||
CHECK_ALLOWED_MAX("TileCols", p_frame_header->tile_info.tile_cols, MAX_TILE_COLS);
|
||||
p_frame_header->tile_info.tile_cols_log2 = TileLog2(1, p_frame_header->tile_info.tile_cols);
|
||||
|
||||
if (min_log2_tiles > 0) {
|
||||
@@ -1766,15 +1832,18 @@ void Av1VideoParser::TileInfo(const uint8_t *p_stream, size_t &offset, Av1Sequen
|
||||
}
|
||||
p_frame_header->tile_info.mi_row_starts[ i ] = p_frame_header->frame_size.mi_rows;
|
||||
p_frame_header->tile_info.tile_rows = i;
|
||||
CHECK_ALLOWED_MAX("TileRows", p_frame_header->tile_info.tile_rows, MAX_TILE_ROWS);
|
||||
p_frame_header->tile_info.tile_rows_log2 = TileLog2(1, p_frame_header->tile_info.tile_rows);
|
||||
}
|
||||
|
||||
if (p_frame_header->tile_info.tile_cols_log2 > 0 || p_frame_header->tile_info.tile_rows_log2 > 0) {
|
||||
p_frame_header->tile_info.context_update_tile_id = Parser::ReadBits(p_stream, offset, p_frame_header->tile_info.tile_rows_log2 + p_frame_header->tile_info.tile_cols_log2);
|
||||
CHECK_ALLOWED_MAX("context_update_tile_id", p_frame_header->tile_info.context_update_tile_id, p_frame_header->tile_info.tile_cols * p_frame_header->tile_info.tile_rows);
|
||||
p_frame_header->tile_info.tile_size_bytes_minus_1 = Parser::ReadBits(p_stream, offset, 2);
|
||||
} else {
|
||||
p_frame_header->tile_info.context_update_tile_id = 0;
|
||||
}
|
||||
return PARSER_OK;
|
||||
}
|
||||
|
||||
uint32_t Av1VideoParser::TileLog2(uint32_t blk_size, uint32_t target) {
|
||||
@@ -2338,20 +2407,19 @@ void Av1VideoParser::ResolveDivisor(int d, int *div_shift, int *div_factor) {
|
||||
}
|
||||
}
|
||||
|
||||
void Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
||||
ParserResult Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
||||
int i;
|
||||
|
||||
if (!p_seq_header->film_grain_params_present || (!p_frame_header->show_frame && !p_frame_header->showable_frame)) {
|
||||
// reset_grain_params()
|
||||
memset(&p_frame_header->film_grain_params, 0, sizeof(Av1FilmGrainParams));
|
||||
return;
|
||||
return PARSER_OK;
|
||||
}
|
||||
p_frame_header->film_grain_params.apply_grain = Parser::GetBit(p_stream, offset);
|
||||
if ( !p_frame_header->film_grain_params.apply_grain )
|
||||
{
|
||||
if (!p_frame_header->film_grain_params.apply_grain) {
|
||||
// reset_grain_params()
|
||||
memset(&p_frame_header->film_grain_params, 0, sizeof(Av1FilmGrainParams));
|
||||
return;
|
||||
return PARSER_OK;
|
||||
}
|
||||
|
||||
p_frame_header->film_grain_params.grain_seed = Parser::ReadBits(p_stream, offset, 16);
|
||||
@@ -2366,12 +2434,17 @@ void Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &offset, Av
|
||||
int temp_grain_seed = p_frame_header->film_grain_params.grain_seed;
|
||||
p_frame_header->film_grain_params = dpb_buffer_.saved_film_grain_params[p_frame_header->film_grain_params.film_grain_params_ref_idx]; // load_grain_params()
|
||||
p_frame_header->film_grain_params.grain_seed = temp_grain_seed;
|
||||
return;
|
||||
return PARSER_OK;
|
||||
}
|
||||
|
||||
p_frame_header->film_grain_params.num_y_points = Parser::ReadBits(p_stream, offset, 4);
|
||||
CHECK_ALLOWED_MAX("num_y_points", p_frame_header->film_grain_params.num_y_points, 14);
|
||||
for (i = 0; i < p_frame_header->film_grain_params.num_y_points; i++) {
|
||||
p_frame_header->film_grain_params.point_y_value[i] = Parser::ReadBits(p_stream, offset, 8);
|
||||
if (i > 0 && p_frame_header->film_grain_params.point_y_value[i] <= p_frame_header->film_grain_params.point_y_value[i - 1]) {
|
||||
ERR("point_y_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_y_value[i]) + ") should be greater than point_y_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_y_value[i - 1]) + ")");
|
||||
return PARSER_INVALID_ARG;
|
||||
}
|
||||
p_frame_header->film_grain_params.point_y_scaling[i] = Parser::ReadBits(p_stream, offset, 8);
|
||||
}
|
||||
|
||||
@@ -2386,14 +2459,34 @@ void Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &offset, Av
|
||||
p_frame_header->film_grain_params.num_cr_points = 0;
|
||||
} else {
|
||||
p_frame_header->film_grain_params.num_cb_points = Parser::ReadBits(p_stream, offset, 4);
|
||||
CHECK_ALLOWED_MAX("num_cb_points", p_frame_header->film_grain_params.num_cb_points, 10);
|
||||
for (i = 0; i < p_frame_header->film_grain_params.num_cb_points; i++) {
|
||||
p_frame_header->film_grain_params.point_cb_value[i] = Parser::ReadBits(p_stream, offset, 8);
|
||||
if (i > 0 && p_frame_header->film_grain_params.point_cb_value[i] <= p_frame_header->film_grain_params.point_cb_value[i - 1]) {
|
||||
ERR("point_cb_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cb_value[i]) + ") should be greater than point_cb_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cb_value[i - 1]) + ")");
|
||||
return PARSER_INVALID_ARG;
|
||||
}
|
||||
p_frame_header->film_grain_params.point_cb_scaling[i] = Parser::ReadBits(p_stream, offset, 8);
|
||||
}
|
||||
p_frame_header->film_grain_params.num_cr_points = Parser::ReadBits(p_stream, offset, 4);
|
||||
CHECK_ALLOWED_MAX("num_cr_points", p_frame_header->film_grain_params.num_cr_points, 10);
|
||||
if (p_seq_header->color_config.subsampling_x == 1 && p_seq_header->color_config.subsampling_y == 1) {
|
||||
if (p_frame_header->film_grain_params.num_cb_points == 0 && p_frame_header->film_grain_params.num_cr_points != 0) {
|
||||
ERR("If subsampling_x is equal to 1 and subsampling_y is equal to 1 and num_cb_points is equal to 0, it is a requirement of bitstream conformance that num_cr_points is equal to 0.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
if (p_frame_header->film_grain_params.num_cb_points != 0 && p_frame_header->film_grain_params.num_cr_points == 0) {
|
||||
ERR("If subsampling_x is equal to 1 and subsampling_y is equal to 1 and num_cb_points is not equal to 0, it is a requirement of bitstream conformance that num_cr_points is not equal to 0.");
|
||||
return PARSER_WRONG_STATE;
|
||||
}
|
||||
}
|
||||
for ( i = 0; i < p_frame_header->film_grain_params.num_cr_points; i++ )
|
||||
{
|
||||
p_frame_header->film_grain_params.point_cr_value[i] = Parser::ReadBits(p_stream, offset, 8);
|
||||
if (i > 0 && p_frame_header->film_grain_params.point_cr_value[i] <= p_frame_header->film_grain_params.point_cr_value[i - 1]) {
|
||||
ERR("point_cr_value["+ TOSTR(i) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cr_value[i]) + ") should be greater than point_cr_value[" + TOSTR(i - 1) + "] (" + TOSTR(p_frame_header->film_grain_params.point_cr_value[i - 1]) + ")");
|
||||
return PARSER_INVALID_ARG;
|
||||
}
|
||||
p_frame_header->film_grain_params.point_cr_scaling[i] = Parser::ReadBits(p_stream, offset, 8);
|
||||
}
|
||||
}
|
||||
@@ -2440,6 +2533,7 @@ void Av1VideoParser::FilmGrainParams(const uint8_t *p_stream, size_t &offset, Av
|
||||
|
||||
p_frame_header->film_grain_params.overlap_flag = Parser::GetBit(p_stream, offset);
|
||||
p_frame_header->film_grain_params.clip_to_restricted_range = Parser::GetBit(p_stream, offset);
|
||||
return PARSER_OK;
|
||||
}
|
||||
|
||||
#if DBGINFO
|
||||
|
||||
@@ -203,9 +203,9 @@ protected:
|
||||
/*! \brief Function to parse a sequence header OBU. 5.5.
|
||||
* \param [in] p_stream Pointer to the bit stream
|
||||
* \param [in] size Byte size of the stream
|
||||
* \return None
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
void ParseSequenceHeaderObu(uint8_t *p_stream, size_t size);
|
||||
ParserResult ParseSequenceHeaderObu(uint8_t *p_stream, size_t size);
|
||||
|
||||
/*! \brief Function to parse a frame header OBU. 5.9.
|
||||
* \param [in] p_stream Pointer to the bit stream
|
||||
@@ -252,9 +252,9 @@ protected:
|
||||
* \param [out] offset Updated bit offset
|
||||
* \param [in] p_seq_header Pointer to sequence header struct
|
||||
* \param [out] p_frame_header Pointer to frame header struct
|
||||
* \return None
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
void FrameSize(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header);
|
||||
ParserResult FrameSize(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header);
|
||||
|
||||
/*! \brief Function to parse super res parameters
|
||||
* \param [in] p_stream Pointer to the bit stream
|
||||
@@ -350,9 +350,9 @@ protected:
|
||||
* \param [out] offset Updated bit offset
|
||||
* \param [in] p_seq_header Pointer to sequence header struct
|
||||
* \param [out] p_frame_header Pointer to frame header struct
|
||||
* \return None
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
void TileInfo(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header);
|
||||
ParserResult TileInfo(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header);
|
||||
|
||||
/*! \brief Function to calculate the smallest value for k such that blk_size << k is greater than or equal to target.
|
||||
* \param [in] blk_size Block size
|
||||
@@ -522,9 +522,9 @@ protected:
|
||||
* \param [out] offset Updated bit offset
|
||||
* \param [in] p_seq_header Pointer to sequence header struct
|
||||
* \param [out] p_frame_header Pointer to frame header struct
|
||||
* \return None
|
||||
* \return <tt>ParserResult</tt>
|
||||
*/
|
||||
void FilmGrainParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header);
|
||||
ParserResult FilmGrainParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header);
|
||||
|
||||
/*! \brief Function to round a number to 2^n
|
||||
* \param [in] x The number to be rounded
|
||||
|
||||
Reference in New Issue
Block a user