2024-03-26 15:59:15 -07:00
|
|
|
/*
|
|
|
|
|
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include "av1_parser.h"
|
|
|
|
|
|
|
|
|
|
Av1VideoParser::Av1VideoParser() {
|
|
|
|
|
//todo: add constructor code
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Av1VideoParser::~Av1VideoParser() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rocDecStatus Av1VideoParser::Initialize(RocdecParserParams *p_params) {
|
|
|
|
|
return RocVideoParser::Initialize(p_params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rocDecStatus Av1VideoParser::UnInitialize() {
|
|
|
|
|
return ROCDEC_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rocDecStatus Av1VideoParser::ParseVideoData(RocdecSourceDataPacket *p_data) {
|
|
|
|
|
//to be implemented
|
|
|
|
|
return ROCDEC_NOT_IMPLEMENTED;
|
2024-04-03 15:04:18 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::ParseSequenceHeader(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);
|
|
|
|
|
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) {
|
|
|
|
|
p_seq_header->timing_info_present_flag = 0;
|
|
|
|
|
p_seq_header->decoder_model_info_present_flag = 0;
|
|
|
|
|
p_seq_header->initial_display_delay_present_flag = 0;
|
|
|
|
|
p_seq_header->operating_points_cnt_minus_1 = 0;
|
|
|
|
|
p_seq_header->operating_point_idc[0] = 0;
|
|
|
|
|
p_seq_header->seq_level_idx[0] = Parser::ReadBits(p_stream, offset, 5);
|
|
|
|
|
p_seq_header->seq_tier[0] = 0;
|
|
|
|
|
p_seq_header->decoder_model_present_for_this_op[0] = 0;
|
|
|
|
|
p_seq_header->initial_display_delay_present_for_this_op[0] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->timing_info_present_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
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);
|
|
|
|
|
p_seq_header->timing_info.time_scale = Parser::ReadBits(p_stream, offset, 32);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_seq_header->decoder_model_info_present_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->decoder_model_info_present_flag) {
|
|
|
|
|
p_seq_header->decoder_model_info.buffer_delay_length_minus_1 = Parser::ReadBits(p_stream, offset, 5);
|
|
|
|
|
p_seq_header->decoder_model_info.num_units_in_decoding_tick = Parser::ReadBits(p_stream, offset, 32);
|
|
|
|
|
p_seq_header->decoder_model_info.buffer_removal_time_length_minus_1 = Parser::ReadBits(p_stream, offset, 5);
|
|
|
|
|
p_seq_header->decoder_model_info.frame_presentation_time_length_minus_1 = Parser::ReadBits(p_stream, offset, 5);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->decoder_model_info_present_flag = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_seq_header->initial_display_delay_present_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->seq_tier[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->decoder_model_info_present_flag) {
|
|
|
|
|
p_seq_header->decoder_model_present_for_this_op[i] = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->decoder_model_present_for_this_op[i]) {
|
|
|
|
|
p_seq_header->operating_parameters_info[i].decoder_buffer_delay = Parser::ReadBits(p_stream, offset, p_seq_header->decoder_model_info.buffer_delay_length_minus_1 + 1);
|
|
|
|
|
p_seq_header->operating_parameters_info[i].encoder_buffer_delay = Parser::ReadBits(p_stream, offset, p_seq_header->decoder_model_info.buffer_delay_length_minus_1 + 1);
|
|
|
|
|
p_seq_header->operating_parameters_info[i].low_delay_mode_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->decoder_model_present_for_this_op[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->initial_display_delay_present_flag) {
|
|
|
|
|
p_seq_header->initial_display_delay_present_for_this_op[i] = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->initial_display_delay_present_for_this_op[i]) {
|
|
|
|
|
p_seq_header->initial_display_delay_minus_1[i] = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Todo: Choose operating point.
|
|
|
|
|
|
|
|
|
|
p_seq_header->frame_width_bits_minus_1 = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
p_seq_header->frame_height_bits_minus_1 = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
p_seq_header->max_frame_width_minus_1 = Parser::ReadBits(p_stream, offset, p_seq_header->frame_width_bits_minus_1 + 1);
|
|
|
|
|
p_seq_header->max_frame_height_minus_1 = Parser::ReadBits(p_stream, offset, p_seq_header->frame_height_bits_minus_1 + 1);
|
|
|
|
|
if (p_seq_header->reduced_still_picture_header) {
|
|
|
|
|
p_seq_header->frame_id_numbers_present_flag = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->frame_id_numbers_present_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
if (p_seq_header->frame_id_numbers_present_flag) {
|
|
|
|
|
p_seq_header->delta_frame_id_length_minus_2 = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
p_seq_header->additional_frame_id_length_minus_1 = Parser::ReadBits(p_stream, offset, 3);
|
|
|
|
|
}
|
|
|
|
|
p_seq_header->use_128x128_superblock = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_filter_intra = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_intra_edge_filter = Parser::GetBit(p_stream, offset);
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->reduced_still_picture_header) {
|
|
|
|
|
p_seq_header->enable_interintra_compound = 0;
|
|
|
|
|
p_seq_header->enable_masked_compound = 0;
|
|
|
|
|
p_seq_header->enable_warped_motion = 0;
|
|
|
|
|
p_seq_header->enable_dual_filter = 0;
|
|
|
|
|
p_seq_header->enable_order_hint = 0;
|
|
|
|
|
p_seq_header->enable_jnt_comp = 0;
|
|
|
|
|
p_seq_header->enable_ref_frame_mvs = 0;
|
|
|
|
|
p_seq_header->seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS;
|
|
|
|
|
p_seq_header->seq_force_integer_mv = SELECT_INTEGER_MV;
|
|
|
|
|
p_seq_header->order_hint_bits = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->enable_interintra_compound = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_masked_compound = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_warped_motion = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_dual_filter = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_order_hint = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->enable_order_hint) {
|
|
|
|
|
p_seq_header->enable_jnt_comp = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_ref_frame_mvs = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->enable_jnt_comp = 0;
|
|
|
|
|
p_seq_header->enable_ref_frame_mvs = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_seq_header->seq_choose_screen_content_tools = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->seq_choose_screen_content_tools) {
|
|
|
|
|
p_seq_header->seq_force_screen_content_tools = SELECT_SCREEN_CONTENT_TOOLS;
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->seq_force_screen_content_tools = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
if (p_seq_header->seq_force_screen_content_tools > 0) {
|
|
|
|
|
p_seq_header->seq_choose_integer_mv = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->seq_choose_integer_mv) {
|
|
|
|
|
p_seq_header->seq_force_integer_mv = SELECT_INTEGER_MV;
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->seq_force_integer_mv = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->seq_force_integer_mv = SELECT_INTEGER_MV;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->enable_order_hint) {
|
|
|
|
|
p_seq_header->order_hint_bits_minus_1 = Parser::ReadBits(p_stream, offset, 3);
|
|
|
|
|
p_seq_header->order_hint_bits = p_seq_header->order_hint_bits_minus_1 + 1;
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->order_hint_bits = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_seq_header->enable_superres = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_cdef = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->enable_restoration = Parser::GetBit(p_stream, offset);
|
|
|
|
|
|
|
|
|
|
ParseColorConfig(p_stream, offset, p_seq_header);
|
|
|
|
|
|
|
|
|
|
p_seq_header->film_grain_params_present = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-11 09:01:54 -04:00
|
|
|
ParserResult Av1VideoParser::ParseUncompressedHeader(uint8_t *p_stream, size_t size) {
|
|
|
|
|
size_t offset = 0; // current bit offset
|
|
|
|
|
Av1SequenceHeader *p_seq_header = &seq_header_;
|
|
|
|
|
Av1FrameHeader *p_frame_header = &frame_header_;
|
|
|
|
|
uint32_t frame_id_len = 0;
|
|
|
|
|
uint32_t all_frames = (1 << NUM_REF_FRAMES) - 1;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
memset(p_frame_header, 0, sizeof(Av1FrameHeader));
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->frame_id_numbers_present_flag) {
|
|
|
|
|
frame_id_len = p_seq_header->additional_frame_id_length_minus_1 + p_seq_header-> delta_frame_id_length_minus_2 + 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->reduced_still_picture_header) {
|
|
|
|
|
p_frame_header->show_existing_frame = 0;
|
|
|
|
|
p_frame_header->frame_type = kKeyFrame;
|
|
|
|
|
p_frame_header->frame_is_intra = 1;
|
|
|
|
|
p_frame_header->show_frame = 1;
|
|
|
|
|
p_frame_header->showable_frame = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->show_existing_frame = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->show_existing_frame == 1) {
|
|
|
|
|
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()
|
|
|
|
|
p_frame_header->temporal_point_info.frame_presentation_time = Parser::ReadBits(p_stream, offset, p_seq_header->decoder_model_info.frame_presentation_time_length_minus_1 + 1);
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->refresh_frame_flags = 0;
|
|
|
|
|
if (p_seq_header->frame_id_numbers_present_flag) {
|
|
|
|
|
p_frame_header->display_frame_id = Parser::ReadBits(p_stream, offset, frame_id_len);
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->frame_type = ref_frame_type_[p_frame_header->frame_to_show_map_idx];
|
|
|
|
|
if (p_frame_header->frame_type == kKeyFrame) {
|
|
|
|
|
p_frame_header->refresh_frame_flags = all_frames;
|
|
|
|
|
}
|
|
|
|
|
if (p_seq_header->film_grain_params_present) {
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Film grain param loading not implemented.\n");
|
|
|
|
|
// load_grain_params(p_frame_header->frame_to_show_map_idx);
|
|
|
|
|
return PARSER_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return PARSER_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->frame_type = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
p_frame_header->frame_is_intra = (p_frame_header->frame_type == kIntraOnlyFrame) || (p_frame_header->frame_type == kKeyFrame);
|
|
|
|
|
p_frame_header->show_frame = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->show_frame && p_seq_header->decoder_model_info_present_flag && !p_seq_header->timing_info.equal_picture_interval) {
|
|
|
|
|
// temporal_point_info()
|
|
|
|
|
p_frame_header->temporal_point_info.frame_presentation_time = Parser::ReadBits(p_stream, offset, p_seq_header->decoder_model_info.frame_presentation_time_length_minus_1 + 1);
|
|
|
|
|
}
|
|
|
|
|
if (p_frame_header->show_frame) {
|
|
|
|
|
p_frame_header->showable_frame = p_frame_header->frame_type != kKeyFrame;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->showable_frame = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
if (p_frame_header->frame_type == kSwitchFrame || (p_frame_header->frame_type == kKeyFrame && p_frame_header->show_frame)) {
|
|
|
|
|
p_frame_header->error_resilient_mode = 1;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->error_resilient_mode = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->frame_type == kKeyFrame && p_frame_header->show_frame) {
|
|
|
|
|
for (i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
ref_valid_[i] = 0;
|
|
|
|
|
ref_order_hint_[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
p_frame_header->order_hints[kLastFrame + i] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->disable_cdf_update = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->seq_force_screen_content_tools == SELECT_SCREEN_CONTENT_TOOLS) {
|
|
|
|
|
p_frame_header->allow_screen_content_tools = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->allow_screen_content_tools = p_seq_header->seq_force_screen_content_tools;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->allow_screen_content_tools) {
|
|
|
|
|
if (p_seq_header->seq_force_integer_mv == SELECT_INTEGER_MV) {
|
|
|
|
|
p_frame_header->force_integer_mv = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->force_integer_mv = p_seq_header->seq_force_integer_mv;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->force_integer_mv = 0;
|
|
|
|
|
}
|
|
|
|
|
if (p_frame_header->frame_is_intra) {
|
|
|
|
|
p_frame_header->force_integer_mv = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->frame_id_numbers_present_flag) {
|
|
|
|
|
p_frame_header->prev_frame_id = p_frame_header->current_frame_id;
|
|
|
|
|
p_frame_header->current_frame_id = Parser::ReadBits(p_stream, offset, frame_id_len);
|
|
|
|
|
MarkRefFrames(p_seq_header, p_frame_header, frame_id_len);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->current_frame_id = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->frame_type == kSwitchFrame) {
|
|
|
|
|
p_frame_header->frame_size_override_flag = 1;
|
|
|
|
|
} else if (p_seq_header->reduced_still_picture_header) {
|
|
|
|
|
p_frame_header->frame_size_override_flag = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->frame_size_override_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->order_hint = Parser::ReadBits(p_stream, offset, p_seq_header->order_hint_bits);
|
|
|
|
|
if (p_frame_header->frame_is_intra || p_frame_header->error_resilient_mode) {
|
|
|
|
|
p_frame_header->primary_ref_frame = PRIMARY_REF_NONE;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->primary_ref_frame = Parser::ReadBits(p_stream, offset, 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->decoder_model_info_present_flag) {
|
|
|
|
|
p_frame_header->buffer_removal_time_present_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->buffer_removal_time_present_flag) {
|
|
|
|
|
for (int op_num = 0; op_num <= p_seq_header->operating_points_cnt_minus_1; op_num++) {
|
|
|
|
|
if (p_seq_header->decoder_model_present_for_this_op[op_num]) {
|
|
|
|
|
uint32_t op_pt_idc = p_seq_header->operating_point_idc[op_num];
|
|
|
|
|
uint32_t in_temporal_layer = (op_pt_idc >> temporal_id_) & 1;
|
|
|
|
|
uint32_t in_spatial_layer = (op_pt_idc >> (spatial_id_ + 8)) & 1;
|
|
|
|
|
if (op_pt_idc == 0 || (in_temporal_layer && in_spatial_layer)) {
|
|
|
|
|
p_frame_header->buffer_removal_time[op_num] = Parser::ReadBits(p_stream, offset, p_seq_header->decoder_model_info.buffer_removal_time_length_minus_1 + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->allow_high_precision_mv = 0;
|
|
|
|
|
p_frame_header->use_ref_frame_mvs = 0;
|
|
|
|
|
p_frame_header->allow_intrabc = 0;
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->frame_type == kSwitchFrame || (p_frame_header->frame_type == kKeyFrame && p_frame_header->show_frame)) {
|
|
|
|
|
p_frame_header->refresh_frame_flags = all_frames;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->refresh_frame_flags = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
}
|
|
|
|
|
// Clear reference list for kKeyFrame
|
|
|
|
|
if (p_frame_header->frame_type == kKeyFrame) {
|
|
|
|
|
for (i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
ref_pictures_[i].index = INVALID_INDEX;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
|
for (i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
p_frame_header->ref_order_hint[i] = Parser::ReadBits(p_stream, offset, p_seq_header->order_hint_bits);
|
|
|
|
|
if (p_frame_header->ref_order_hint[i] != ref_order_hint_[i]) {
|
|
|
|
|
ref_valid_[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->frame_is_intra) {
|
|
|
|
|
FrameSize(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!p_seq_header->enable_order_hint) {
|
|
|
|
|
p_frame_header->frame_refs_short_signaling = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->frame_refs_short_signaling = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->frame_refs_short_signaling) {
|
|
|
|
|
p_frame_header->last_frame_idx = Parser::ReadBits(p_stream, offset, 3);
|
|
|
|
|
p_frame_header->gold_frame_idx = Parser::ReadBits(p_stream, offset, 3);
|
|
|
|
|
// 7.8. Set frame refs process
|
|
|
|
|
SetFrameRefs(p_seq_header, p_frame_header);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
if (!p_frame_header->frame_refs_short_signaling) {
|
|
|
|
|
p_frame_header->ref_frame_idx[i] = Parser::ReadBits(p_stream, offset, 3);
|
|
|
|
|
}
|
|
|
|
|
if (p_seq_header->frame_id_numbers_present_flag) {
|
|
|
|
|
p_frame_header->delta_frame_id_minus_1 = Parser::ReadBits(p_stream, offset, p_seq_header->delta_frame_id_length_minus_2 + 2);
|
|
|
|
|
uint32_t delta_frame_id = p_frame_header->delta_frame_id_minus_1 + 1;
|
|
|
|
|
p_frame_header->expected_frame_id[i] = ((p_frame_header->current_frame_id + (1 << frame_id_len) - delta_frame_id ) % (1 << frame_id_len));
|
|
|
|
|
if (p_frame_header->expected_frame_id[i] != ref_frame_id_[p_frame_header->ref_frame_idx[i]] || ref_valid_[p_frame_header->ref_frame_idx[i]] == 0) {
|
|
|
|
|
ERR("Syntax Error: Reference buffer frame ID mismatch.\n");
|
|
|
|
|
return PARSER_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
RenderSize(p_stream, offset, p_frame_header);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->force_integer_mv) {
|
|
|
|
|
p_frame_header->allow_high_precision_mv = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->allow_high_precision_mv = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// read_interpolation_filter()
|
|
|
|
|
p_frame_header->is_filter_switchable = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->is_filter_switchable == 1) {
|
|
|
|
|
p_frame_header->interpolation_filter = kSwitchable;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->interpolation_filter = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->is_motion_mode_switchable = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->error_resilient_mode || !p_seq_header->enable_ref_frame_mvs) {
|
|
|
|
|
p_frame_header->use_ref_frame_mvs = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->use_ref_frame_mvs = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
uint32_t ref_frame = kLastFrame + i;
|
|
|
|
|
uint32_t hint = ref_order_hint_[p_frame_header->ref_frame_idx[i]];
|
|
|
|
|
p_frame_header->order_hints[ref_frame] = hint;
|
|
|
|
|
if (!p_seq_header->enable_order_hint) {
|
|
|
|
|
p_frame_header->ref_frame_sign_bias[ref_frame] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->ref_frame_sign_bias[ref_frame] = GetRelativeDist(p_seq_header, hint, p_frame_header->order_hint) > 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Generate reference map for the next picture
|
|
|
|
|
int ref_index = 0;
|
|
|
|
|
for (int mask = p_frame_header->refresh_frame_flags; mask; mask >>= 1) {
|
|
|
|
|
if (mask & 1) {
|
|
|
|
|
ref_pic_map_next_[ref_index] = new_fb_index_;
|
|
|
|
|
} else {
|
|
|
|
|
ref_pic_map_next_[ref_index] = ref_pic_map_[ref_index];
|
|
|
|
|
}
|
|
|
|
|
++ref_index;
|
|
|
|
|
}
|
|
|
|
|
for (; ref_index < NUM_REF_FRAMES; ++ref_index) {
|
|
|
|
|
ref_pic_map_next_[ref_index] = ref_pic_map_[ref_index];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->reduced_still_picture_header || p_frame_header->disable_cdf_update) {
|
|
|
|
|
p_frame_header->disable_frame_end_update_cdf = 1;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->disable_frame_end_update_cdf = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->primary_ref_frame == PRIMARY_REF_NONE) {
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Warning: need to implement init_non_coeff_cdfs()\n");
|
|
|
|
|
|
|
|
|
|
SetupPastIndependence(p_frame_header);
|
|
|
|
|
} else {
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Warning: need to implement load_cdfs()\n");
|
|
|
|
|
ERR("Warning: need to implement load_previous()\n");
|
|
|
|
|
return PARSER_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->use_ref_frame_mvs == 1) {
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Warning: need to implement motion_field_estimation()\n");
|
|
|
|
|
return PARSER_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TileInfo(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
|
|
|
|
|
QuantizationParams(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
|
|
|
|
|
SegmentationParams(p_stream, offset, p_frame_header);
|
|
|
|
|
|
|
|
|
|
DeltaQParams(p_stream, offset, p_frame_header);
|
|
|
|
|
|
|
|
|
|
DeltaLFParams(p_stream, offset, p_frame_header);
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->primary_ref_frame == PRIMARY_REF_NONE) {
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Warning: Need to implement init_coeff_cdfs()\n");
|
|
|
|
|
} else {
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Warning: Need to implement load_previous_segment_ids()\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->coded_lossless = 1;
|
|
|
|
|
for (int segment_id = 0; segment_id < MAX_SEGMENTS; segment_id++) {
|
|
|
|
|
// Todo int qindex = get_qindex( 1, segment_id );
|
|
|
|
|
ERR("Warning: Need to implement get_qindex()\n");
|
|
|
|
|
int qindex = 1;
|
|
|
|
|
p_frame_header->lossless_array[segment_id] = qindex == 0 && p_frame_header->quantization_params.delta_q_y_dc == 0 && p_frame_header->quantization_params.delta_q_u_ac == 0 && p_frame_header->quantization_params.delta_q_u_dc == 0 && p_frame_header->quantization_params.delta_q_v_ac == 0 && p_frame_header->quantization_params.delta_q_v_dc == 0;
|
|
|
|
|
if (!p_frame_header->lossless_array[segment_id]) {
|
|
|
|
|
p_frame_header->coded_lossless = 0;
|
|
|
|
|
}
|
|
|
|
|
if (p_frame_header->quantization_params.using_qmatrix) {
|
|
|
|
|
if (p_frame_header->lossless_array[segment_id]) {
|
|
|
|
|
p_frame_header->seg_qm_level[0][segment_id] = 15;
|
|
|
|
|
p_frame_header->seg_qm_level[1][segment_id] = 15;
|
|
|
|
|
p_frame_header->seg_qm_level[2][segment_id] = 15;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->seg_qm_level[0][segment_id] = p_frame_header->quantization_params.qm_y;
|
|
|
|
|
p_frame_header->seg_qm_level[1][segment_id] = p_frame_header->quantization_params.qm_u;
|
|
|
|
|
p_frame_header->seg_qm_level[2][segment_id] = p_frame_header->quantization_params.qm_v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->all_lossless = p_frame_header->coded_lossless && (p_frame_header->frame_size.frame_width == p_frame_header->frame_size.upscaled_width);
|
|
|
|
|
|
|
|
|
|
LoopFilterParams(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
|
|
|
|
|
CdefParams(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
|
|
|
|
|
LrParams(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
|
|
|
|
|
ReadTxMode(p_stream, offset, p_frame_header);
|
|
|
|
|
|
|
|
|
|
// frame_reference_mode()
|
|
|
|
|
if (p_frame_header->frame_is_intra) {
|
|
|
|
|
p_frame_header->frame_reference_mode.reference_select = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->frame_reference_mode.reference_select = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SkipModeParams(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->frame_is_intra || p_frame_header->error_resilient_mode || !p_seq_header->enable_warped_motion) {
|
|
|
|
|
p_frame_header->allow_warped_motion = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->allow_warped_motion = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
return PARSER_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::ParseTileGroupInfo(uint8_t *p_stream, size_t size) {
|
|
|
|
|
size_t offset = 0; // current bit offset
|
|
|
|
|
Av1SequenceHeader *p_seq_header = &seq_header_;
|
|
|
|
|
Av1FrameHeader *p_frame_header = &frame_header_;
|
|
|
|
|
Av1TileGroupDataInfo *p_tile_group = &tile_group_data_;
|
|
|
|
|
uint32_t num_tiles;
|
|
|
|
|
uint32_t tile_start_and_end_present_flag = 0;
|
|
|
|
|
uint32_t tg_start, tg_end;
|
|
|
|
|
uint32_t header_types = 0;
|
|
|
|
|
uint32_t tile_cols = p_frame_header->tile_info.tile_cols;
|
|
|
|
|
uint32_t tile_rows = p_frame_header->tile_info.tile_rows;
|
|
|
|
|
uint8_t *p_tg_buf = p_stream;
|
|
|
|
|
uint32_t tg_size = size;
|
|
|
|
|
|
|
|
|
|
memset(p_tile_group, 0, sizeof(Av1TileGroupDataInfo));
|
|
|
|
|
p_tile_group->buffer_ptr = p_tg_buf;
|
|
|
|
|
p_tile_group->buffer_size = tg_size;
|
|
|
|
|
|
|
|
|
|
// First parse the header
|
|
|
|
|
num_tiles = tile_cols * tile_rows;
|
|
|
|
|
if (num_tiles > 1) {
|
|
|
|
|
tile_start_and_end_present_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
if (num_tiles == 1 || !tile_start_and_end_present_flag) {
|
|
|
|
|
tg_start = 0;
|
|
|
|
|
tg_end = num_tiles - 1;
|
|
|
|
|
} else {
|
|
|
|
|
uint32_t tile_bits = p_frame_header->tile_info.tile_cols_log2 + p_frame_header->tile_info.tile_rows_log2;
|
|
|
|
|
tg_start = Parser::ReadBits(p_stream, offset, tile_bits);
|
|
|
|
|
tg_end = Parser::ReadBits(p_stream, offset, tile_bits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
header_types = ((offset + 7) >> 3);
|
|
|
|
|
p_tg_buf += header_types;
|
|
|
|
|
tg_size -= header_types;
|
|
|
|
|
for (int tile_num = tg_start; tile_num <= tg_end; tile_num++) {
|
|
|
|
|
int tile_row = tile_num / tile_cols;
|
|
|
|
|
int tile_col = tile_num % tile_cols;
|
|
|
|
|
int last_tile = tile_num == tg_end;
|
|
|
|
|
if (last_tile) {
|
|
|
|
|
p_tile_group->tile_data_info[tile_row][tile_col].size = tg_size;
|
|
|
|
|
p_tile_group->tile_data_info[tile_row][tile_col].offset = p_tg_buf - p_tile_group->buffer_ptr;
|
|
|
|
|
} else {
|
|
|
|
|
uint32_t tile_size_bytes = p_frame_header->tile_info.tile_size_bytes_minus_1 + 1;
|
|
|
|
|
uint32_t tile_size = ReadLeBytes(p_tg_buf, tile_size_bytes) + 1;
|
|
|
|
|
p_tile_group->tile_data_info[tile_row][tile_col].size = tile_size;
|
|
|
|
|
p_tile_group->tile_data_info[tile_row][tile_col].offset = p_tg_buf + tile_size_bytes - p_tile_group->buffer_ptr;
|
|
|
|
|
tg_size -= tile_size + tile_size_bytes;
|
|
|
|
|
p_tg_buf += tile_size + tile_size_bytes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-03 15:04:18 -04:00
|
|
|
void Av1VideoParser::ParseColorConfig(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header) {
|
|
|
|
|
p_seq_header->color_config.bit_depth = 8;
|
|
|
|
|
|
|
|
|
|
p_seq_header->color_config.high_bitdepth = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->seq_profile == 2 && p_seq_header->color_config.high_bitdepth) {
|
|
|
|
|
p_seq_header->color_config.twelve_bit = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->color_config.bit_depth = p_seq_header->color_config.twelve_bit ? 12 : 10;
|
|
|
|
|
} else if (p_seq_header->seq_profile <= 2) {
|
|
|
|
|
p_seq_header->color_config.bit_depth = p_seq_header->color_config.high_bitdepth ? 10 : 8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->seq_profile == 1) {
|
|
|
|
|
p_seq_header->color_config.mono_chrome = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->color_config.mono_chrome = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
p_seq_header->color_config.num_planes = p_seq_header->color_config.mono_chrome ? 1 : 3;
|
|
|
|
|
|
|
|
|
|
p_seq_header->color_config.color_description_present_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->color_config.color_description_present_flag) {
|
|
|
|
|
p_seq_header->color_config.color_primaries = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
p_seq_header->color_config.transfer_characteristics = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
p_seq_header->color_config.matrix_coefficients = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->color_config.color_primaries = CP_UNSPECIFIED;
|
|
|
|
|
p_seq_header->color_config.transfer_characteristics = TC_UNSPECIFIED;
|
|
|
|
|
p_seq_header->color_config.matrix_coefficients = MC_UNSPECIFIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->color_config.mono_chrome) {
|
|
|
|
|
p_seq_header->color_config.color_range = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_seq_header->color_config.subsampling_x = 1;
|
|
|
|
|
p_seq_header->color_config.subsampling_y = 1;
|
|
|
|
|
p_seq_header->color_config.chroma_sample_position = CSP_UNKNOWN;
|
|
|
|
|
p_seq_header->color_config.separate_uv_delta_q = 0;
|
|
|
|
|
return;
|
|
|
|
|
} else if (p_seq_header->color_config.color_primaries == CP_BT_709 && p_seq_header->color_config.transfer_characteristics == TC_SRGB && p_seq_header->color_config.matrix_coefficients == MC_IDENTITY) {
|
|
|
|
|
p_seq_header->color_config.color_range = 1;
|
|
|
|
|
p_seq_header->color_config.subsampling_x = 0;
|
|
|
|
|
p_seq_header->color_config.subsampling_y = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->color_config.color_range = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->seq_profile == 0) {
|
|
|
|
|
p_seq_header->color_config.subsampling_x = 1;
|
|
|
|
|
p_seq_header->color_config.subsampling_y = 1;
|
|
|
|
|
} else if (p_seq_header->seq_profile == 1) {
|
|
|
|
|
p_seq_header->color_config.subsampling_x = 0;
|
|
|
|
|
p_seq_header->color_config.subsampling_y = 0;
|
|
|
|
|
} else {
|
|
|
|
|
if (p_seq_header->color_config.bit_depth == 12) {
|
|
|
|
|
p_seq_header->color_config.subsampling_x = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_seq_header->color_config.subsampling_x) {
|
|
|
|
|
p_seq_header->color_config.subsampling_y = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->color_config.subsampling_y = 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
p_seq_header->color_config.subsampling_x = 1;
|
|
|
|
|
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);
|
|
|
|
|
}
|
2024-04-11 09:01:54 -04:00
|
|
|
|
|
|
|
|
void Av1VideoParser::MarkRefFrames(Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header, uint32_t id_len) {
|
|
|
|
|
int diff_len = p_seq_header->delta_frame_id_length_minus_2 + 2;
|
|
|
|
|
for (int i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
if (p_frame_header->frame_type == kKeyFrame && p_frame_header->show_frame) {
|
|
|
|
|
ref_valid_[i] = 0;
|
|
|
|
|
} else if (p_frame_header->current_frame_id > (1 << diff_len)) {
|
|
|
|
|
if (ref_frame_id_[i] > p_frame_header->current_frame_id || ref_frame_id_[i] < (p_frame_header->current_frame_id - (1 << diff_len))) {
|
|
|
|
|
ref_valid_[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (ref_frame_id_[i] > p_frame_header->current_frame_id && ref_frame_id_[i] < ((1 << id_len) + p_frame_header->current_frame_id - (1 << diff_len))) {
|
|
|
|
|
ref_valid_[ i ] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void 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);
|
|
|
|
|
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);
|
|
|
|
|
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 = p_seq_header->max_frame_width_minus_1 + 1;
|
|
|
|
|
p_frame_header->frame_size.frame_height = p_seq_header->max_frame_height_minus_1 + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SuperResParams(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
ComputeImageSize(p_frame_header);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::SuperResParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
uint32_t super_res_denom;
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->enable_superres) {
|
|
|
|
|
p_frame_header->frame_size.superres_params.use_superres = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->frame_size.superres_params.use_superres = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->frame_size.superres_params.use_superres) {
|
|
|
|
|
p_frame_header->frame_size.superres_params.coded_denom = Parser::ReadBits(p_stream, offset, SUPERRES_DENOM_BITS);
|
|
|
|
|
super_res_denom = p_frame_header->frame_size.superres_params.coded_denom + SUPERRES_DENOM_MIN;
|
|
|
|
|
} else {
|
|
|
|
|
super_res_denom = SUPERRES_NUM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->frame_size.upscaled_width = p_frame_header->frame_size.frame_width;
|
|
|
|
|
p_frame_header->frame_size.frame_width = (p_frame_header->frame_size.upscaled_width * SUPERRES_NUM + (super_res_denom / 2)) / super_res_denom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::ComputeImageSize(Av1FrameHeader *p_frame_header) {
|
|
|
|
|
p_frame_header->frame_size.mi_cols = 2 * ((p_frame_header->frame_size.frame_width + 7) >> 3);
|
|
|
|
|
p_frame_header->frame_size.mi_rows = 2 * ((p_frame_header->frame_size.frame_height + 7) >> 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::RenderSize(const uint8_t *p_stream, size_t &offset, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
p_frame_header->render_size.render_and_frame_size_different = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->render_size.render_and_frame_size_different) {
|
|
|
|
|
p_frame_header->render_size.render_width_minus_1 = Parser::ReadBits(p_stream, offset, 16);
|
|
|
|
|
p_frame_header->render_size.render_height_minus_1 = Parser::ReadBits(p_stream, offset, 16);
|
|
|
|
|
p_frame_header->render_size.render_width = p_frame_header->render_size.render_width_minus_1 + 1;
|
|
|
|
|
p_frame_header->render_size.render_height = p_frame_header->render_size.render_height_minus_1 + 1;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->render_size.render_width = p_frame_header->frame_size.upscaled_width;
|
|
|
|
|
p_frame_header->render_size.render_height = p_frame_header->frame_size.frame_height;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::SetFrameRefs(Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
int i;
|
|
|
|
|
int used_frame[NUM_REF_FRAMES];
|
|
|
|
|
int curr_frame_hint;
|
|
|
|
|
int shifted_order_hints[NUM_REF_FRAMES];
|
|
|
|
|
int ref;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
p_frame_header->ref_frame_idx[i] = -1;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->ref_frame_idx[kLastFrame - kLastFrame] = p_frame_header->last_frame_idx;
|
|
|
|
|
p_frame_header->ref_frame_idx[kGoldenFrame - kLastFrame] = p_frame_header->gold_frame_idx;
|
|
|
|
|
for (i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
used_frame[ i ] = 0;
|
|
|
|
|
}
|
|
|
|
|
used_frame[p_frame_header->last_frame_idx] = 1;
|
|
|
|
|
used_frame[p_frame_header->gold_frame_idx ] = 1;
|
|
|
|
|
|
|
|
|
|
curr_frame_hint = 1 << (p_seq_header->order_hint_bits - 1);
|
|
|
|
|
for (i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
shifted_order_hints[i] = curr_frame_hint + GetRelativeDist(p_seq_header, ref_order_hint_[i], p_frame_header->order_hint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The kAltRefFrame reference is set to be a backward reference to the frame with highest output order.
|
|
|
|
|
ref = FindLatestBackward(shifted_order_hints, used_frame, curr_frame_hint);
|
|
|
|
|
if (ref >= 0) {
|
|
|
|
|
p_frame_header->ref_frame_idx[kAltRefFrame - kLastFrame] = ref;
|
|
|
|
|
used_frame[ref] = 1;
|
|
|
|
|
}
|
|
|
|
|
// The kBwdRefFrame reference is set to be a backward reference to the closest frame.
|
|
|
|
|
ref = FindEarliestBackward(shifted_order_hints, used_frame, curr_frame_hint);
|
|
|
|
|
if ( ref >= 0 )
|
|
|
|
|
{
|
|
|
|
|
p_frame_header->ref_frame_idx[kBwdRefFrame - kLastFrame] = ref;
|
|
|
|
|
used_frame[ref] = 1;
|
|
|
|
|
}
|
|
|
|
|
// The kAltRef2Frame reference is set to the next closest backward reference.
|
|
|
|
|
ref = FindEarliestBackward(shifted_order_hints, used_frame, curr_frame_hint);
|
|
|
|
|
if ( ref >= 0 )
|
|
|
|
|
{
|
|
|
|
|
p_frame_header->ref_frame_idx[kAltRef2Frame - kLastFrame] = ref;
|
|
|
|
|
used_frame[ref] = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The remaining references are set to be forward references in anti-chronological order.
|
|
|
|
|
int ref_frame_list[REFS_PER_FRAME - 2] = {kLast2Frame, kLast3Frame, kBwdRefFrame, kAltRef2Frame, kAltRefFrame};
|
|
|
|
|
for (i = 0; i < REFS_PER_FRAME - 2; i++) {
|
|
|
|
|
int refFrame = ref_frame_list[i];
|
|
|
|
|
if (p_frame_header->ref_frame_idx[refFrame - kLastFrame] < 0) {
|
|
|
|
|
ref = FindLatestForward(shifted_order_hints, used_frame, curr_frame_hint);
|
|
|
|
|
if (ref >= 0) {
|
|
|
|
|
p_frame_header->ref_frame_idx[refFrame - kLastFrame] = ref;
|
|
|
|
|
used_frame[ref] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Finally, any remaining references are set to the reference frame with smallest output order.
|
|
|
|
|
ref = -1;
|
|
|
|
|
for (i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
int earliest_order_hint = 9999;
|
|
|
|
|
int hint = shifted_order_hints[i];
|
|
|
|
|
if (ref < 0 || hint < earliest_order_hint) {
|
|
|
|
|
ref = i;
|
|
|
|
|
earliest_order_hint = hint;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
if (p_frame_header->ref_frame_idx[i] < 0) {
|
|
|
|
|
p_frame_header->ref_frame_idx[i] = ref;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Av1VideoParser::GetRelativeDist(Av1SequenceHeader *p_seq_header, int a, int b) {
|
|
|
|
|
if (!p_seq_header->enable_order_hint) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int diff = a - b;
|
|
|
|
|
int m = 1 << (p_seq_header->order_hint_bits - 1);
|
|
|
|
|
diff = (diff & (m - 1)) - (diff & m);
|
|
|
|
|
return diff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Av1VideoParser::FindLatestBackward(int *shifted_order_hints, int *used_frame, int curr_frame_hint) {
|
|
|
|
|
int ref = -1;
|
|
|
|
|
int hint;
|
|
|
|
|
int latest_order_hint = -9999;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
hint = shifted_order_hints[i];
|
|
|
|
|
if (!used_frame[i] && hint >= curr_frame_hint && (ref < 0 || hint >= latest_order_hint)) {
|
|
|
|
|
ref = i;
|
|
|
|
|
latest_order_hint = hint;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ref;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Av1VideoParser::FindEarliestBackward(int *shifted_order_hints, int *used_frame, int curr_frame_hint) {
|
|
|
|
|
int ref = -1;
|
|
|
|
|
int hint;
|
|
|
|
|
int earliest_order_hint = 9999;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
hint = shifted_order_hints[i];
|
|
|
|
|
if (!used_frame[i] && hint >= curr_frame_hint && (ref < 0 || hint < earliest_order_hint)) {
|
|
|
|
|
ref = i;
|
|
|
|
|
earliest_order_hint = hint;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ref;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Av1VideoParser::FindLatestForward(int *shifted_order_hints, int *used_frame, int curr_frame_hint) {
|
|
|
|
|
int ref = -1;
|
|
|
|
|
int hint;
|
|
|
|
|
int latest_order_hint = -9999;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_REF_FRAMES; i++) {
|
|
|
|
|
hint = shifted_order_hints[i];
|
|
|
|
|
if (!used_frame[i] && hint < curr_frame_hint && (ref < 0 || hint >= latest_order_hint)) {
|
|
|
|
|
ref = i;
|
|
|
|
|
latest_order_hint = hint;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ref;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::FrameSizeWithRefs(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
for (int i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
p_frame_header->found_ref = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->found_ref) {
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Warning: Need to implement! found_ref == 1 case.\n");
|
|
|
|
|
#if 0
|
|
|
|
|
UpscaledWidth = RefUpscaledWidth[ ref_frame_idx[ i ] ]
|
|
|
|
|
FrameWidth = UpscaledWidth
|
|
|
|
|
FrameHeight = RefFrameHeight[ ref_frame_idx[ i ] ]
|
|
|
|
|
RenderWidth = RefRenderWidth[ ref_frame_idx[ i ] ]
|
|
|
|
|
RenderHeight = RefRenderHeight[ ref_frame_idx[ i ] ]
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->found_ref == 0) {
|
|
|
|
|
FrameSize(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
RenderSize(p_stream, offset, p_frame_header);
|
|
|
|
|
} else {
|
|
|
|
|
SuperResParams(p_stream, offset, p_seq_header, p_frame_header);
|
|
|
|
|
ComputeImageSize(p_frame_header);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::SetupPastIndependence(Av1FrameHeader *p_frame_header) {
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_delta_enabled = 1;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_delta_update = 1;
|
|
|
|
|
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Need to implement the rest of SetupPastIndependence");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void 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;
|
|
|
|
|
int32_t sb_size;
|
|
|
|
|
int32_t max_tile_width_sb;
|
|
|
|
|
int32_t max_tile_height_sb;
|
|
|
|
|
int32_t max_tile_area_sb;
|
|
|
|
|
int32_t min_log2_tile_cols;
|
|
|
|
|
int32_t min_log2_tile_rows;
|
|
|
|
|
int32_t max_log2_tile_cols;
|
|
|
|
|
int32_t max_log2_tile_rows;
|
|
|
|
|
int32_t min_log2_tiles;
|
|
|
|
|
int32_t tile_width_sb;
|
|
|
|
|
int32_t tile_height_sb;
|
|
|
|
|
int32_t max_width;
|
|
|
|
|
int32_t max_height;
|
|
|
|
|
int32_t size_sb;
|
|
|
|
|
int start_sb;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
sb_cols = p_seq_header->use_128x128_superblock ? ((p_frame_header->frame_size.mi_cols + 31) >> 5) : ((p_frame_header->frame_size.mi_cols + 15) >> 4);
|
|
|
|
|
sb_rows = p_seq_header->use_128x128_superblock ? ((p_frame_header->frame_size.mi_rows + 31) >> 5) : ((p_frame_header->frame_size.mi_rows + 15 ) >> 4);
|
|
|
|
|
sb_shift = p_seq_header->use_128x128_superblock ? 5 : 4;
|
|
|
|
|
sb_size = sb_shift + 2;
|
|
|
|
|
max_tile_width_sb = MAX_TILE_WIDTH >> sb_size;
|
|
|
|
|
max_tile_area_sb = MAX_TILE_AREA >> (2 * sb_size);
|
|
|
|
|
min_log2_tile_cols = TileLog2(max_tile_width_sb, sb_cols);
|
|
|
|
|
max_log2_tile_cols = TileLog2(1, std::min(sb_cols, MAX_TILE_COLS));
|
|
|
|
|
max_log2_tile_rows = TileLog2(1, std::min(sb_rows, MAX_TILE_ROWS));
|
|
|
|
|
min_log2_tiles = std::max(min_log2_tile_cols, static_cast<int>(TileLog2(max_tile_area_sb, sb_rows * sb_cols)));
|
|
|
|
|
|
|
|
|
|
p_frame_header->tile_info.uniform_tile_spacing_flag = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->tile_info.uniform_tile_spacing_flag) {
|
|
|
|
|
p_frame_header->tile_info.tile_cols_log2 = min_log2_tile_cols;
|
|
|
|
|
while (p_frame_header->tile_info.tile_cols_log2 < max_log2_tile_cols) {
|
|
|
|
|
p_frame_header->tile_info.increment_tile_cols_log2 = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->tile_info.increment_tile_cols_log2 == 1) {
|
|
|
|
|
p_frame_header->tile_info.tile_cols_log2++;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tile_width_sb = (sb_cols + (1 << p_frame_header->tile_info.tile_cols_log2) - 1) >> p_frame_header->tile_info.tile_cols_log2;
|
|
|
|
|
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;
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->tile_info.mi_col_starts[i] = p_frame_header->frame_size.mi_cols;
|
|
|
|
|
p_frame_header->tile_info.tile_cols = i;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
while (p_frame_header->tile_info.tile_rows_log2 < max_log2_tile_rows) {
|
|
|
|
|
p_frame_header->tile_info.increment_tile_rows_log2 = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->tile_info.increment_tile_rows_log2 == 1) {
|
|
|
|
|
p_frame_header->tile_info.tile_rows_log2++;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tile_height_sb = (sb_rows + (1 << p_frame_header->tile_info.tile_rows_log2) - 1) >> p_frame_header->tile_info.tile_rows_log2;
|
|
|
|
|
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;
|
|
|
|
|
i += 1;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->tile_info.mi_row_starts[i] = p_frame_header->frame_size.mi_rows;
|
|
|
|
|
p_frame_header->tile_info.tile_rows = i;
|
|
|
|
|
} else {
|
|
|
|
|
int widest_tile_sb = 0;
|
|
|
|
|
start_sb = 0;
|
|
|
|
|
for (i = 0; start_sb < sb_cols; i++) {
|
|
|
|
|
p_frame_header->tile_info.mi_col_starts[i] = start_sb << sb_shift;
|
|
|
|
|
max_width = std::min(sb_cols - start_sb, max_tile_width_sb);
|
|
|
|
|
p_frame_header->tile_info.width_in_sbs_minus_1 = ReadUnsignedNonSymmetic(p_stream, offset, max_width);
|
|
|
|
|
size_sb = p_frame_header->tile_info.width_in_sbs_minus_1 + 1;
|
|
|
|
|
widest_tile_sb = std::max(size_sb, widest_tile_sb);
|
|
|
|
|
start_sb += size_sb;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->tile_info.mi_col_starts[i] = p_frame_header->frame_size.mi_cols;
|
|
|
|
|
p_frame_header->tile_info.tile_cols = i;
|
|
|
|
|
p_frame_header->tile_info.tile_cols_log2 = TileLog2(1, p_frame_header->tile_info.tile_cols);
|
|
|
|
|
|
|
|
|
|
if (min_log2_tiles > 0) {
|
|
|
|
|
max_tile_area_sb = (sb_rows * sb_cols) >> (min_log2_tiles + 1);
|
|
|
|
|
} else {
|
|
|
|
|
max_tile_area_sb = sb_rows * sb_cols;
|
|
|
|
|
}
|
|
|
|
|
max_tile_height_sb = std::max(max_tile_area_sb / widest_tile_sb, static_cast<int>(1));
|
|
|
|
|
|
|
|
|
|
start_sb = 0;
|
|
|
|
|
for (i = 0; start_sb < sb_rows; i++) {
|
|
|
|
|
p_frame_header->tile_info.mi_row_starts[i] = start_sb << sb_shift;
|
|
|
|
|
max_height = std::min(sb_rows - start_sb, max_tile_height_sb);
|
|
|
|
|
p_frame_header->tile_info.height_in_sbs_minus_1 = ReadUnsignedNonSymmetic(p_stream, offset, max_height);
|
|
|
|
|
size_sb = p_frame_header->tile_info.height_in_sbs_minus_1 + 1;
|
|
|
|
|
start_sb += size_sb;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->tile_info.mi_row_starts[ i ] = p_frame_header->frame_size.mi_rows;
|
|
|
|
|
p_frame_header->tile_info.tile_rows = i;
|
|
|
|
|
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);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t Av1VideoParser::TileLog2(uint32_t blk_size, uint32_t target) {
|
|
|
|
|
uint32_t k;
|
|
|
|
|
for (k = 0; (blk_size << k) < target; k++ ) {
|
|
|
|
|
}
|
|
|
|
|
return k;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::QuantizationParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
p_frame_header->quantization_params.base_q_idx = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
p_frame_header->quantization_params.delta_q_y_dc = ReadDeltaQ(p_stream, offset, p_frame_header);
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->color_config.num_planes > 1) {
|
|
|
|
|
if (p_seq_header->color_config.separate_uv_delta_q) {
|
|
|
|
|
p_frame_header->quantization_params.diff_uv_delta = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->quantization_params.diff_uv_delta = 0;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->quantization_params.delta_q_u_dc = ReadDeltaQ(p_stream, offset, p_frame_header);
|
|
|
|
|
p_frame_header->quantization_params.delta_q_u_ac = ReadDeltaQ(p_stream, offset, p_frame_header);
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->quantization_params.diff_uv_delta) {
|
|
|
|
|
p_frame_header->quantization_params.delta_q_v_dc = ReadDeltaQ(p_stream, offset, p_frame_header);
|
|
|
|
|
p_frame_header->quantization_params.delta_q_v_ac = ReadDeltaQ(p_stream, offset, p_frame_header);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->quantization_params.delta_q_v_dc = p_frame_header->quantization_params.delta_q_u_dc;
|
|
|
|
|
p_frame_header->quantization_params.delta_q_v_ac = p_frame_header->quantization_params.delta_q_u_ac;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->quantization_params.delta_q_u_dc = 0;
|
|
|
|
|
p_frame_header->quantization_params.delta_q_u_ac = 0;
|
|
|
|
|
p_frame_header->quantization_params.delta_q_v_dc = 0;
|
|
|
|
|
p_frame_header->quantization_params.delta_q_v_ac = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->quantization_params.using_qmatrix = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->quantization_params.using_qmatrix) {
|
|
|
|
|
p_frame_header->quantization_params.qm_y = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
p_frame_header->quantization_params.qm_u = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
if (!p_seq_header->color_config.separate_uv_delta_q) {
|
|
|
|
|
p_frame_header->quantization_params.qm_v = p_frame_header->quantization_params.qm_u;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->quantization_params.qm_v = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t Av1VideoParser::ReadDeltaQ(const uint8_t *p_stream, size_t &offset, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
p_frame_header->quantization_params.delta_coded = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->quantization_params.delta_coded) {
|
|
|
|
|
p_frame_header->quantization_params.delta_q = ReadSigned(p_stream, offset, 1 + 6);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->quantization_params.delta_q = 0;
|
|
|
|
|
}
|
|
|
|
|
return p_frame_header->quantization_params.delta_q;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::SegmentationParams(const uint8_t *p_stream, size_t &offset, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
int i, j;
|
|
|
|
|
int clipped_value;
|
|
|
|
|
uint32_t bits_to_read;
|
|
|
|
|
uint32_t segmentation_feature_bits[SEG_LVL_MAX] = {8,6,6,6,6,3,0,0};
|
|
|
|
|
uint32_t segmentation_feature_signed[SEG_LVL_MAX] = { 1, 1, 1, 1, 1, 0, 0, 0 };
|
|
|
|
|
uint32_t segmentation_feature_max[SEG_LVL_MAX] = {255, MAX_LOOP_FILTER, MAX_LOOP_FILTER, MAX_LOOP_FILTER, MAX_LOOP_FILTER, 7, 0, 0 };
|
|
|
|
|
|
|
|
|
|
p_frame_header->segmentation_params.segmentation_enabled = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->segmentation_params.segmentation_enabled == 1) {
|
|
|
|
|
if (p_frame_header->primary_ref_frame == PRIMARY_REF_NONE) {
|
|
|
|
|
p_frame_header->segmentation_params.segmentation_update_map = 1;
|
|
|
|
|
p_frame_header->segmentation_params.segmentation_temporal_update = 0;
|
|
|
|
|
p_frame_header->segmentation_params.segmentation_update_data = 1;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->segmentation_params.segmentation_update_map = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->segmentation_params.segmentation_update_map == 1) {
|
|
|
|
|
p_frame_header->segmentation_params.segmentation_temporal_update = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->segmentation_params.segmentation_update_data = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->segmentation_params.segmentation_update_data == 1) {
|
|
|
|
|
for (i = 0; i < MAX_SEGMENTS; i++) {
|
|
|
|
|
for (j = 0; j < SEG_LVL_MAX; j++) {
|
|
|
|
|
p_frame_header->segmentation_params.feature_value = 0;
|
|
|
|
|
p_frame_header->segmentation_params.feature_enabled = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_frame_header->segmentation_params.feature_enabled_flags[i][j] = p_frame_header->segmentation_params.feature_enabled;
|
|
|
|
|
clipped_value = 0;
|
|
|
|
|
if (p_frame_header->segmentation_params.feature_enabled == 1) {
|
|
|
|
|
bits_to_read = segmentation_feature_bits[j];
|
|
|
|
|
int limit = segmentation_feature_max[j];
|
|
|
|
|
if (segmentation_feature_signed[j] == 1) {
|
|
|
|
|
p_frame_header->segmentation_params.feature_value = ReadSigned(p_stream, offset, 1 + bits_to_read);
|
|
|
|
|
clipped_value = std::clamp(static_cast<int>(p_frame_header->segmentation_params.feature_value), -limit, limit);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->segmentation_params.feature_value = Parser::ReadBits(p_stream, offset, bits_to_read);
|
|
|
|
|
clipped_value = std::clamp(static_cast<int>(p_frame_header->segmentation_params.feature_value), 0, limit);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->segmentation_params.feature_data[i][j] = clipped_value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (i = 0; i < MAX_SEGMENTS; i++) {
|
|
|
|
|
for (j = 0; j < SEG_LVL_MAX; j++) {
|
|
|
|
|
p_frame_header->segmentation_params.feature_enabled_flags[i][j] = 0;
|
|
|
|
|
p_frame_header->segmentation_params.feature_data[i][j] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->segmentation_params.seg_id_pre_skip = 0;
|
|
|
|
|
p_frame_header->segmentation_params.last_active_seg_id = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_SEGMENTS; i++) {
|
|
|
|
|
for (j = 0; j < SEG_LVL_MAX; j++) {
|
|
|
|
|
if (p_frame_header->segmentation_params.feature_enabled_flags[i][j]) {
|
|
|
|
|
p_frame_header->segmentation_params.last_active_seg_id = i;
|
|
|
|
|
if (j >= SEG_LVL_REF_FRAME) {
|
|
|
|
|
p_frame_header->segmentation_params.seg_id_pre_skip = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::DeltaQParams(const uint8_t *p_stream, size_t &offset, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
p_frame_header->delta_q_params.delta_q_res = 0;
|
|
|
|
|
p_frame_header->delta_q_params.delta_q_present = 0;
|
|
|
|
|
if ( p_frame_header->quantization_params.base_q_idx > 0 )
|
|
|
|
|
{
|
|
|
|
|
p_frame_header->delta_q_params.delta_q_present = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
if ( p_frame_header->delta_q_params.delta_q_present )
|
|
|
|
|
{
|
|
|
|
|
p_frame_header->delta_q_params.delta_q_res = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::DeltaLFParams(const uint8_t *p_stream, size_t &offset, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
p_frame_header->delta_lf_params.delta_lf_present = 0;
|
|
|
|
|
p_frame_header->delta_lf_params.delta_lf_res = 0;
|
|
|
|
|
p_frame_header->delta_lf_params.delta_lf_multi = 0;
|
|
|
|
|
if (p_frame_header->delta_q_params.delta_q_present) {
|
|
|
|
|
if (!p_frame_header->allow_intrabc) {
|
|
|
|
|
p_frame_header->delta_lf_params.delta_lf_present = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
if (p_frame_header->delta_lf_params.delta_lf_present) {
|
|
|
|
|
p_frame_header->delta_lf_params.delta_lf_res = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
p_frame_header->delta_lf_params.delta_lf_multi = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::LoopFilterParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->coded_lossless || p_frame_header->allow_intrabc) {
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_level[0] = 0;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_level[1] = 0;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[kIntraFrame] = 1;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[kLastFrame] = 0;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[kLast2Frame] = 0;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[kLast3Frame] = 0;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[kBwdRefFrame] = 0;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[kGoldenFrame] = -1;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[kAltRefFrame] = -1;
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[kAltRef2Frame] = -1;
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_mode_deltas[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_level[0] = Parser::ReadBits(p_stream, offset, 6);
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_level[1] = Parser::ReadBits(p_stream, offset, 6);
|
|
|
|
|
if (p_seq_header->color_config.num_planes > 1) {
|
|
|
|
|
if (p_frame_header->loop_filter_params.loop_filter_level[0] || p_frame_header->loop_filter_params.loop_filter_level[1]) {
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_level[2] = Parser::ReadBits(p_stream, offset, 6);
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_level[3] = Parser::ReadBits(p_stream, offset, 6);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_sharpness = Parser::ReadBits(p_stream, offset, 3);
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_delta_enabled = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->loop_filter_params.loop_filter_delta_enabled == 1) {
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_delta_update = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->loop_filter_params.loop_filter_delta_update == 1) {
|
|
|
|
|
for (i = 0; i < TOTAL_REFS_PER_FRAME; i++) {
|
|
|
|
|
p_frame_header->loop_filter_params.update_ref_delta = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->loop_filter_params.update_ref_delta == 1) {
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_ref_deltas[i] = ReadSigned(p_stream, offset, 1 + 6);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
|
p_frame_header->loop_filter_params.update_mode_delta = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if ( p_frame_header->loop_filter_params.update_mode_delta == 1 )
|
|
|
|
|
{
|
|
|
|
|
p_frame_header->loop_filter_params.loop_filter_mode_deltas[i] = ReadSigned(p_stream, offset, 1 + 6);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::CdefParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
if (p_frame_header->coded_lossless || p_frame_header->allow_intrabc ||!p_seq_header->enable_cdef) {
|
|
|
|
|
p_frame_header->cdef_params.cdef_bits = 0;
|
|
|
|
|
p_frame_header->cdef_params.cdef_y_pri_strength[0] = 0;
|
|
|
|
|
p_frame_header->cdef_params.cdef_y_sec_strength[0] = 0;
|
|
|
|
|
p_frame_header->cdef_params.cdef_uv_pri_strength[0] = 0;
|
|
|
|
|
p_frame_header->cdef_params.cdef_uv_sec_strength[0] = 0;
|
|
|
|
|
p_frame_header->cdef_params.cdef_damping = 3;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->cdef_params.cdef_damping_minus_3 = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
p_frame_header->cdef_params.cdef_damping = p_frame_header->cdef_params.cdef_damping_minus_3 + 3;
|
|
|
|
|
p_frame_header->cdef_params.cdef_bits = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
for (int i = 0; i < (1 << p_frame_header->cdef_params.cdef_bits); i++) {
|
|
|
|
|
p_frame_header->cdef_params.cdef_y_pri_strength[i] = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
p_frame_header->cdef_params.cdef_y_sec_strength[i] = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
if (p_frame_header->cdef_params.cdef_y_sec_strength[i] == 3) {
|
|
|
|
|
p_frame_header->cdef_params.cdef_y_sec_strength[i] += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->color_config.num_planes > 1) {
|
|
|
|
|
p_frame_header->cdef_params.cdef_uv_pri_strength[i] = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
p_frame_header->cdef_params.cdef_uv_sec_strength[i] = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
if (p_frame_header->cdef_params.cdef_uv_sec_strength[i] == 3) {
|
|
|
|
|
p_frame_header->cdef_params.cdef_uv_sec_strength[i] += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::LrParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
uint32_t remap_lr_type[4] = {kRestoreNone, kRestoreSwitchable, kRestoreWiener, kRestoreSgrproj};
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->all_lossless || p_frame_header->allow_intrabc || !p_seq_header->enable_restoration) {
|
|
|
|
|
p_frame_header->lr_params.frame_restoration_type[0] = kRestoreNone;
|
|
|
|
|
p_frame_header->lr_params.frame_restoration_type[1] = kRestoreNone;
|
|
|
|
|
p_frame_header->lr_params.frame_restoration_type[2] = kRestoreNone;
|
|
|
|
|
p_frame_header->lr_params.uses_lr = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->lr_params.uses_lr = 0;
|
|
|
|
|
uint32_t uses_chroma_lr = 0;
|
|
|
|
|
for (int i = 0; i < p_seq_header->color_config.num_planes; i++) {
|
|
|
|
|
p_frame_header->lr_params.lr_type = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
p_frame_header->lr_params.frame_restoration_type[i] = remap_lr_type[p_frame_header->lr_params.lr_type];
|
|
|
|
|
if (p_frame_header->lr_params.frame_restoration_type[i] != kRestoreNone) {
|
|
|
|
|
p_frame_header->lr_params.uses_lr = 1;
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
uses_chroma_lr = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->lr_params.uses_lr) {
|
|
|
|
|
if (p_seq_header->use_128x128_superblock) {
|
|
|
|
|
p_frame_header->lr_params.lr_unit_shift = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_frame_header->lr_params.lr_unit_shift++;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->lr_params.lr_unit_shift = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->lr_params.lr_unit_shift) {
|
|
|
|
|
p_frame_header->lr_params.lr_unit_extra_shift = Parser::GetBit(p_stream, offset);
|
|
|
|
|
p_frame_header->lr_params.lr_unit_shift += p_frame_header->lr_params.lr_unit_extra_shift;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->lr_params.loop_restoration_size[0] = RESTORATION_TILESIZE_MAX >> (2 - p_frame_header->lr_params.lr_unit_shift);
|
|
|
|
|
if (p_seq_header->color_config.subsampling_x && p_seq_header->color_config.subsampling_y && uses_chroma_lr) {
|
|
|
|
|
p_frame_header->lr_params.lr_uv_shift = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->lr_params.lr_uv_shift = 0;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->lr_params.loop_restoration_size[1] = p_frame_header->lr_params.loop_restoration_size[0] >> p_frame_header->lr_params.lr_uv_shift;
|
|
|
|
|
p_frame_header->lr_params.loop_restoration_size[2] = p_frame_header->lr_params.loop_restoration_size[0] >> p_frame_header->lr_params.lr_uv_shift;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::ReadTxMode(const uint8_t *p_stream, size_t &offset, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
if (p_frame_header->coded_lossless == 1) {
|
|
|
|
|
p_frame_header->tx_mode.tx_mode = kOnly4x4;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->tx_mode.tx_mode_select = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->tx_mode.tx_mode_select) {
|
|
|
|
|
p_frame_header->tx_mode.tx_mode = kTxModeSelect;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->tx_mode.tx_mode = kTxModeSelect;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::SkipModeParams(const uint8_t *p_stream, size_t &offset, Av1SequenceHeader *p_seq_header, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
uint32_t skip_mode_allowed;
|
|
|
|
|
int forward_idx, backward_idx;
|
|
|
|
|
int forward_hint, backward_hint;
|
|
|
|
|
int second_forward_idx, second_forward_hint;
|
|
|
|
|
uint32_t ref_hint;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->frame_is_intra || !p_frame_header->frame_reference_mode.reference_select || !p_seq_header->enable_order_hint) {
|
|
|
|
|
skip_mode_allowed = 0;
|
|
|
|
|
} else {
|
|
|
|
|
forward_idx = -1;
|
|
|
|
|
backward_idx = -1;
|
|
|
|
|
forward_hint = ref_order_hint_[0]; // init value. No effect.
|
|
|
|
|
backward_hint = ref_order_hint_[1]; // init value. No effect.
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
ref_hint = ref_order_hint_[p_frame_header->ref_frame_idx[i]];
|
|
|
|
|
if (GetRelativeDist(p_seq_header, ref_hint, p_frame_header->order_hint ) < 0) {
|
|
|
|
|
if (forward_idx < 0 || GetRelativeDist(p_seq_header, ref_hint, forward_hint) > 0) {
|
|
|
|
|
forward_idx = i;
|
|
|
|
|
forward_hint = ref_hint;
|
|
|
|
|
}
|
|
|
|
|
} else if (GetRelativeDist(p_seq_header, ref_hint, p_frame_header->order_hint) > 0) {
|
|
|
|
|
if (backward_idx < 0 || GetRelativeDist(p_seq_header, ref_hint, backward_hint) < 0 ) {
|
|
|
|
|
backward_idx = i;
|
|
|
|
|
backward_hint = ref_hint;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (forward_idx < 0) {
|
|
|
|
|
skip_mode_allowed = 0;
|
|
|
|
|
} else if (backward_idx >= 0) {
|
|
|
|
|
skip_mode_allowed = 1;
|
|
|
|
|
p_frame_header->skip_mode_params.skip_mode_frame[0] = kLastFrame + std::min(forward_idx, backward_idx);
|
|
|
|
|
p_frame_header->skip_mode_params.skip_mode_frame[1] = kLastFrame + std::max(forward_idx, backward_idx);
|
|
|
|
|
} else {
|
|
|
|
|
second_forward_idx = -1;
|
|
|
|
|
second_forward_hint = ref_order_hint_[0]; // init value. No effect.
|
|
|
|
|
for (i = 0; i < REFS_PER_FRAME; i++) {
|
|
|
|
|
ref_hint = ref_order_hint_[p_frame_header->ref_frame_idx[i]];
|
|
|
|
|
if (GetRelativeDist(p_seq_header, ref_hint, forward_hint ) < 0) {
|
|
|
|
|
if (second_forward_idx < 0 || GetRelativeDist(p_seq_header, ref_hint, second_forward_hint ) > 0) {
|
|
|
|
|
second_forward_idx = i;
|
|
|
|
|
second_forward_hint = ref_hint;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (second_forward_idx < 0) {
|
|
|
|
|
skip_mode_allowed = 0;
|
|
|
|
|
} else {
|
|
|
|
|
skip_mode_allowed = 1;
|
|
|
|
|
p_frame_header->skip_mode_params.skip_mode_frame[0] = kLastFrame + std::min(forward_idx, second_forward_idx);
|
|
|
|
|
p_frame_header->skip_mode_params.skip_mode_frame[1] = kLastFrame + std::max(forward_idx, second_forward_idx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (skip_mode_allowed ) {
|
|
|
|
|
p_frame_header->skip_mode_params.skip_mode_present = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->skip_mode_params.skip_mode_present = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::GlobalMotionParams(const uint8_t *p_stream, size_t &offset, Av1FrameHeader *p_frame_header) {
|
|
|
|
|
int ref;
|
|
|
|
|
int type;
|
|
|
|
|
|
|
|
|
|
for (ref = kLastFrame; ref <= kAltRefFrame; ref++) {
|
|
|
|
|
p_frame_header->global_motion_params.gm_type[ref] = kIdentity;
|
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
|
p_frame_header->global_motion_params.gm_params[ref][i] = ( ( i % 3 == 2 ) ? 1 << WARPEDMODEL_PREC_BITS : 0 );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->frame_is_intra) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (ref = kLastFrame; ref <= kAltRefFrame; ref++) {
|
|
|
|
|
p_frame_header->global_motion_params.is_global = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->global_motion_params.is_global) {
|
|
|
|
|
p_frame_header->global_motion_params.is_rot_zoom = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (p_frame_header->global_motion_params.is_rot_zoom) {
|
|
|
|
|
type = kRotZoom;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->global_motion_params.is_translation = Parser::GetBit(p_stream, offset);
|
|
|
|
|
type = p_frame_header->global_motion_params.is_translation ? kTranslation : kAffine;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
type = kIdentity;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->global_motion_params.gm_type[ref] = type;
|
|
|
|
|
|
|
|
|
|
if (type >= kRotZoom) {
|
|
|
|
|
ReadGlobalParam(p_stream, offset, p_frame_header, type, ref, 2);
|
|
|
|
|
ReadGlobalParam(p_stream, offset, p_frame_header, type, ref, 3);
|
|
|
|
|
if (type == kAffine) {
|
|
|
|
|
ReadGlobalParam(p_stream, offset, p_frame_header, type, ref, 4);
|
|
|
|
|
ReadGlobalParam(p_stream, offset, p_frame_header, type, ref, 5);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->global_motion_params.gm_params[ref][4] = -p_frame_header->global_motion_params.gm_params[ref][3];
|
|
|
|
|
p_frame_header->global_motion_params.gm_params[ref][5] = p_frame_header->global_motion_params.gm_params[ref][2];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( type >= kTranslation ) {
|
|
|
|
|
ReadGlobalParam(p_stream, offset, p_frame_header, type, ref, 0);
|
|
|
|
|
ReadGlobalParam(p_stream, offset, p_frame_header, type, ref, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Av1VideoParser::ReadGlobalParam(const uint8_t *p_stream, size_t &offset, Av1FrameHeader *p_frame_header, int type, int ref, int idx) {
|
|
|
|
|
int abs_bits = GM_ABS_ALPHA_BITS;
|
|
|
|
|
int prec_bits = GM_ALPHA_PREC_BITS;
|
|
|
|
|
|
|
|
|
|
if (idx < 2) {
|
|
|
|
|
if (type == kTranslation) {
|
|
|
|
|
abs_bits = GM_ABS_TRANS_ONLY_BITS - !p_frame_header->allow_high_precision_mv;
|
|
|
|
|
prec_bits = GM_TRANS_ONLY_PREC_BITS - !p_frame_header->allow_high_precision_mv;
|
|
|
|
|
} else {
|
|
|
|
|
abs_bits = GM_ABS_TRANS_BITS;
|
|
|
|
|
prec_bits = GM_TRANS_PREC_BITS;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int prec_diff = WARPEDMODEL_PREC_BITS - prec_bits;
|
|
|
|
|
int round = (idx % 3) == 2 ? (1 << WARPEDMODEL_PREC_BITS) : 0;
|
|
|
|
|
int sub = (idx % 3) == 2 ? (1 << prec_bits) : 0;
|
|
|
|
|
int mx = (1 << abs_bits);
|
|
|
|
|
// Todo:
|
|
|
|
|
ERR("Error: PrevGmParams is calculated in SetupPastIndependence() (setup_past_independence()) function, which is not implemented yet.\n");
|
|
|
|
|
int r = (p_frame_header->global_motion_params.prev_gm_params[ref][idx] >> prec_diff) - sub;
|
|
|
|
|
p_frame_header->global_motion_params.gm_params[ref][idx] = (DecodeSignedSubexpWithRef(p_stream, offset, -mx, mx + 1, r) << prec_diff) + round;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Av1VideoParser::DecodeSignedSubexpWithRef(const uint8_t *p_stream, size_t &offset, int low, int high, int r) {
|
|
|
|
|
int x = DecodeUnsignedSubexpWithRef(p_stream, offset, high - low, r - low);
|
|
|
|
|
return x + low;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Av1VideoParser::DecodeUnsignedSubexpWithRef(const uint8_t *p_stream, size_t &offset, int mx, int r) {
|
|
|
|
|
int v = DecodeSubexp(p_stream, offset, mx);
|
|
|
|
|
if ((r << 1) <= mx) {
|
|
|
|
|
return InverseRecenter(r, v);
|
|
|
|
|
} else {
|
|
|
|
|
return mx - 1 - InverseRecenter(mx - 1 - r, v);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Av1VideoParser::DecodeSubexp(const uint8_t *p_stream, size_t &offset, int num_syms) {
|
|
|
|
|
int i = 0;
|
|
|
|
|
int mk = 0;
|
|
|
|
|
int k = 3;
|
|
|
|
|
while (1) {
|
|
|
|
|
int b2 = i ? k + i - 1 : k;
|
|
|
|
|
int a = 1 << b2;
|
|
|
|
|
if (num_syms <= mk + 3 * a) {
|
|
|
|
|
int subexp_final_bits = ReadUnsignedNonSymmetic(p_stream, offset, num_syms - mk);
|
|
|
|
|
return subexp_final_bits + mk;
|
|
|
|
|
} else {
|
|
|
|
|
int subexp_more_bits = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if (subexp_more_bits) {
|
|
|
|
|
i++;
|
|
|
|
|
mk += a;
|
|
|
|
|
} else {
|
|
|
|
|
int subexp_bits = Parser::ReadBits(p_stream, offset, b2);
|
|
|
|
|
return subexp_bits + mk;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Av1VideoParser::InverseRecenter(int r, int v) {
|
|
|
|
|
if (v > 2 * r) {
|
|
|
|
|
return v;
|
|
|
|
|
} else if (v & 1) {
|
|
|
|
|
return r - ((v + 1) >> 1);
|
|
|
|
|
} else {
|
|
|
|
|
return r + (v >> 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void 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;
|
|
|
|
|
}
|
|
|
|
|
p_frame_header->film_grain_params.apply_grain = Parser::GetBit(p_stream, offset);
|
|
|
|
|
if ( !p_frame_header->film_grain_params.apply_grain )
|
|
|
|
|
{
|
|
|
|
|
// reset_grain_params()
|
|
|
|
|
memset(&p_frame_header->film_grain_params, 0, sizeof(Av1FilmGrainParams));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->film_grain_params.grain_seed = Parser::ReadBits(p_stream, offset, 16);
|
|
|
|
|
if (p_frame_header->frame_type == kInterFrame) {
|
|
|
|
|
p_frame_header->film_grain_params.update_grain = Parser::GetBit(p_stream, offset);
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->film_grain_params.update_grain = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!p_frame_header->film_grain_params.update_grain) {
|
|
|
|
|
p_frame_header->film_grain_params.film_grain_params_ref_idx = Parser::ReadBits(p_stream, offset, 3);
|
|
|
|
|
int temp_grain_seed = p_frame_header->film_grain_params.grain_seed;
|
|
|
|
|
//load_grain_params( film_grain_params_ref_idx );
|
|
|
|
|
// Todo
|
|
|
|
|
ERR("Warning: need to implement film grain param loading load_grain_params( film_grain_params_ref_idx ).\n");
|
|
|
|
|
p_frame_header->film_grain_params.grain_seed = temp_grain_seed;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->film_grain_params.num_y_points = Parser::ReadBits(p_stream, offset, 4);
|
|
|
|
|
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);
|
|
|
|
|
p_frame_header->film_grain_params.point_y_scaling[i] = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->color_config.mono_chrome) {
|
|
|
|
|
p_frame_header->film_grain_params.chroma_scaling_from_luma = 0;
|
|
|
|
|
} else {
|
|
|
|
|
p_frame_header->film_grain_params.chroma_scaling_from_luma = Parser::GetBit(p_stream, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_seq_header->color_config.mono_chrome || p_frame_header->film_grain_params.chroma_scaling_from_luma || (p_seq_header->color_config.subsampling_x == 1 && p_seq_header->color_config.subsampling_y == 1 && p_frame_header->film_grain_params.num_y_points == 0)) {
|
|
|
|
|
p_frame_header->film_grain_params.num_cb_points = 0;
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
p_frame_header->film_grain_params.point_cr_scaling[i] = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->film_grain_params.grain_scaling_minus_8 = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
p_frame_header->film_grain_params.ar_coeff_lag = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
uint32_t num_pos_luma = 2 * p_frame_header->film_grain_params.ar_coeff_lag * (p_frame_header->film_grain_params.ar_coeff_lag + 1);
|
|
|
|
|
uint32_t num_pos_chroma;
|
|
|
|
|
if (p_frame_header->film_grain_params.num_y_points) {
|
|
|
|
|
num_pos_chroma = num_pos_luma + 1;
|
|
|
|
|
for (i = 0; i < num_pos_luma; i++) {
|
|
|
|
|
p_frame_header->film_grain_params.ar_coeffs_y_plus_128[i] = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
num_pos_chroma = num_pos_luma;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->film_grain_params.chroma_scaling_from_luma || p_frame_header->film_grain_params.num_cb_points) {
|
|
|
|
|
for (i = 0; i < num_pos_chroma; i++) {
|
|
|
|
|
p_frame_header->film_grain_params.ar_coeffs_cb_plus_128[i] = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->film_grain_params.chroma_scaling_from_luma || p_frame_header->film_grain_params.num_cr_points) {
|
|
|
|
|
for (i = 0; i < num_pos_chroma; i++) {
|
|
|
|
|
p_frame_header->film_grain_params.ar_coeffs_cr_plus_128[i] = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p_frame_header->film_grain_params.ar_coeff_shift_minus_6 = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
p_frame_header->film_grain_params.grain_scale_shift = Parser::ReadBits(p_stream, offset, 2);
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->film_grain_params.num_cb_points) {
|
|
|
|
|
p_frame_header->film_grain_params.cb_mult = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
p_frame_header->film_grain_params.cb_luma_mult = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
p_frame_header->film_grain_params.cb_offset = Parser::ReadBits(p_stream, offset, 9);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (p_frame_header->film_grain_params.num_cr_points) {
|
|
|
|
|
p_frame_header->film_grain_params.cr_mult = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
p_frame_header->film_grain_params.cr_luma_mult = Parser::ReadBits(p_stream, offset, 8);
|
|
|
|
|
p_frame_header->film_grain_params.cr_offset = Parser::ReadBits(p_stream, offset, 9);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|