X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fcbs_av1_syntax_template.c;h=6fe6e9a4f356182bb8350813883a48d9d963f130;hb=7c4287b27628346321981b2529bff028f119c870;hp=48f4fab514a51596872bc421e5b012f3f0fc2fe9;hpb=409e684e79b6ee0c511292326f09b13fe230e58e;p=ffmpeg diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index 48f4fab514a..6fe6e9a4f35 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -19,8 +19,8 @@ static int FUNC(obu_header)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawOBUHeader *current) { + CodedBitstreamAV1Context *priv = ctx->priv_data; int err; - av_unused int zero = 0; HEADER("OBU header"); @@ -36,8 +36,14 @@ static int FUNC(obu_header)(CodedBitstreamContext *ctx, RWContext *rw, fb(3, temporal_id); fb(2, spatial_id); fc(3, extension_header_reserved_3bits, 0, 0); + } else { + infer(temporal_id, 0); + infer(spatial_id, 0); } + priv->temporal_id = current->temporal_id; + priv->spatial_id = current->spatial_id; + return 0; } @@ -268,7 +274,7 @@ static int FUNC(sequence_header_obu)(CodedBitstreamContext *ctx, RWContext *rw, flag(enable_intra_edge_filter); if (current->reduced_still_picture_header) { - infer(enable_intraintra_compound, 0); + infer(enable_interintra_compound, 0); infer(enable_masked_compound, 0); infer(enable_warped_motion, 0); infer(enable_dual_filter, 0); @@ -281,7 +287,7 @@ static int FUNC(sequence_header_obu)(CodedBitstreamContext *ctx, RWContext *rw, infer(seq_force_integer_mv, AV1_SELECT_INTEGER_MV); } else { - flag(enable_intraintra_compound); + flag(enable_interintra_compound); flag(enable_masked_compound); flag(enable_warped_motion); flag(enable_dual_filter); @@ -339,6 +345,117 @@ static int FUNC(temporal_delimiter_obu)(CodedBitstreamContext *ctx, RWContext *r return 0; } +static int FUNC(set_frame_refs)(CodedBitstreamContext *ctx, RWContext *rw, + AV1RawFrameHeader *current) +{ + CodedBitstreamAV1Context *priv = ctx->priv_data; + const AV1RawSequenceHeader *seq = priv->sequence_header; + static const uint8_t ref_frame_list[AV1_NUM_REF_FRAMES - 2] = { + AV1_REF_FRAME_LAST2, AV1_REF_FRAME_LAST3, AV1_REF_FRAME_BWDREF, + AV1_REF_FRAME_ALTREF2, AV1_REF_FRAME_ALTREF + }; + int8_t ref_frame_idx[AV1_REFS_PER_FRAME], used_frame[AV1_NUM_REF_FRAMES]; + int8_t shifted_order_hints[AV1_NUM_REF_FRAMES]; + int cur_frame_hint, latest_order_hint, earliest_order_hint, ref; + int i, j; + + for (i = 0; i < AV1_REFS_PER_FRAME; i++) + ref_frame_idx[i] = -1; + ref_frame_idx[AV1_REF_FRAME_LAST - AV1_REF_FRAME_LAST] = current->last_frame_idx; + ref_frame_idx[AV1_REF_FRAME_GOLDEN - AV1_REF_FRAME_LAST] = current->golden_frame_idx; + + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) + used_frame[i] = 0; + used_frame[current->last_frame_idx] = 1; + used_frame[current->golden_frame_idx] = 1; + + cur_frame_hint = 1 << (seq->order_hint_bits_minus_1); + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) + shifted_order_hints[i] = cur_frame_hint + + cbs_av1_get_relative_dist(seq, priv->ref[i].order_hint, + priv->order_hint); + + latest_order_hint = shifted_order_hints[current->last_frame_idx]; + earliest_order_hint = shifted_order_hints[current->golden_frame_idx]; + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + int hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint >= latest_order_hint)) { + ref = i; + latest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_ALTREF - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + int hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint < earliest_order_hint)) { + ref = i; + earliest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_BWDREF - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + int hint = shifted_order_hints[i]; + if (!used_frame[i] && hint >= cur_frame_hint && + (ref < 0 || hint < earliest_order_hint)) { + ref = i; + earliest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[AV1_REF_FRAME_ALTREF2 - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + + for (i = 0; i < AV1_REFS_PER_FRAME - 2; i++) { + int ref_frame = ref_frame_list[i]; + if (ref_frame_idx[ref_frame - AV1_REF_FRAME_LAST] < 0 ) { + ref = -1; + for (j = 0; j < AV1_NUM_REF_FRAMES; j++) { + int hint = shifted_order_hints[j]; + if (!used_frame[j] && hint < cur_frame_hint && + (ref < 0 || hint >= latest_order_hint)) { + ref = j; + latest_order_hint = hint; + } + } + if (ref >= 0) { + ref_frame_idx[ref_frame - AV1_REF_FRAME_LAST] = ref; + used_frame[ref] = 1; + } + } + } + + ref = -1; + for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { + int hint = shifted_order_hints[i]; + if (ref < 0 || hint < earliest_order_hint) { + ref = i; + earliest_order_hint = hint; + } + } + for (i = 0; i < AV1_REFS_PER_FRAME; i++) { + if (ref_frame_idx[i] < 0) + ref_frame_idx[i] = ref; + infer(ref_frame_idx[i], ref_frame_idx[i]); + } + + return 0; +} + static int FUNC(superres_params)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawFrameHeader *current) { @@ -375,14 +492,14 @@ static int FUNC(frame_size)(CodedBitstreamContext *ctx, RWContext *rw, if (current->frame_size_override_flag) { fb(seq->frame_width_bits_minus_1 + 1, frame_width_minus_1); fb(seq->frame_height_bits_minus_1 + 1, frame_height_minus_1); - - priv->frame_width = current->frame_width_minus_1 + 1; - priv->frame_height = current->frame_height_minus_1 + 1; } else { - priv->frame_width = seq->max_frame_width_minus_1 + 1; - priv->frame_height = seq->max_frame_height_minus_1 + 1; + infer(frame_width_minus_1, seq->max_frame_width_minus_1); + infer(frame_height_minus_1, seq->max_frame_height_minus_1); } + priv->frame_width = current->frame_width_minus_1 + 1; + priv->frame_height = current->frame_height_minus_1 + 1; + CHECK(FUNC(superres_params)(ctx, rw, current)); return 0; @@ -399,14 +516,14 @@ static int FUNC(render_size)(CodedBitstreamContext *ctx, RWContext *rw, if (current->render_and_frame_size_different) { fb(16, render_width_minus_1); fb(16, render_height_minus_1); - - priv->render_width = current->render_width_minus_1 + 1; - priv->render_height = current->render_height_minus_1 + 1; } else { - priv->render_width = priv->upscaled_width; - priv->render_height = priv->frame_height; + infer(render_width_minus_1, current->frame_width_minus_1); + infer(render_height_minus_1, current->frame_height_minus_1); } + priv->render_width = current->render_width_minus_1 + 1; + priv->render_height = current->render_height_minus_1 + 1; + return 0; } @@ -430,8 +547,13 @@ static int FUNC(frame_size_with_refs)(CodedBitstreamContext *ctx, RWContext *rw, return AVERROR_INVALIDDATA; } + infer(frame_width_minus_1, ref->upscaled_width - 1); + infer(frame_height_minus_1, ref->frame_height - 1); + infer(render_width_minus_1, ref->render_width - 1); + infer(render_height_minus_1, ref->render_height - 1); + priv->upscaled_width = ref->upscaled_width; - priv->frame_width = ref->frame_width; + priv->frame_width = priv->upscaled_width; priv->frame_height = ref->frame_height; priv->render_width = ref->render_width; priv->render_height = ref->render_height; @@ -514,6 +636,15 @@ static int FUNC(tile_info)(CodedBitstreamContext *ctx, RWContext *rw, current->tile_rows_log2; current->tile_rows = (sb_rows + tile_height_sb - 1) / tile_height_sb; + for (i = 0; i < current->tile_cols - 1; i++) + infer(width_in_sbs_minus_1[i], tile_width_sb - 1); + infer(width_in_sbs_minus_1[i], + sb_cols - (current->tile_cols - 1) * tile_width_sb - 1); + for (i = 0; i < current->tile_rows - 1; i++) + infer(height_in_sbs_minus_1[i], tile_height_sb - 1); + infer(height_in_sbs_minus_1[i], + sb_rows - (current->tile_rows - 1) * tile_height_sb - 1); + } else { int widest_tile_sb, start_sb, size_sb, max_width, max_height; @@ -612,8 +743,11 @@ static int FUNC(quantization_params)(CodedBitstreamContext *ctx, RWContext *rw, static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawFrameHeader *current) { + CodedBitstreamAV1Context *priv = ctx->priv_data; static const uint8_t bits[AV1_SEG_LVL_MAX] = { 8, 6, 6, 6, 6, 3, 0, 0 }; static const uint8_t sign[AV1_SEG_LVL_MAX] = { 1, 1, 1, 1, 1, 0, 0, 0 }; + static const uint8_t default_feature_enabled[AV1_SEG_LVL_MAX] = { 0 }; + static const int16_t default_feature_value[AV1_SEG_LVL_MAX] = { 0 }; int i, j, err; flag(segmentation_enabled); @@ -632,9 +766,22 @@ static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw, flag(segmentation_update_data); } - if (current->segmentation_update_data) { - for (i = 0; i < AV1_MAX_SEGMENTS; i++) { - for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + for (i = 0; i < AV1_MAX_SEGMENTS; i++) { + const uint8_t *ref_feature_enabled; + const int16_t *ref_feature_value; + + if (current->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + ref_feature_enabled = default_feature_enabled; + ref_feature_value = default_feature_value; + } else { + ref_feature_enabled = + priv->ref[current->ref_frame_idx[current->primary_ref_frame]].feature_enabled[i]; + ref_feature_value = + priv->ref[current->ref_frame_idx[current->primary_ref_frame]].feature_value[i]; + } + + for (j = 0; j < AV1_SEG_LVL_MAX; j++) { + if (current->segmentation_update_data) { flags(feature_enabled[i][j], 2, i, j); if (current->feature_enabled[i][j] && bits[j] > 0) { @@ -645,6 +792,9 @@ static int FUNC(segmentation_params)(CodedBitstreamContext *ctx, RWContext *rw, } else { infer(feature_value[i][j], 0); } + } else { + infer(feature_enabled[i][j], ref_feature_enabled[j]); + infer(feature_value[i][j], ref_feature_value[j]); } } } @@ -706,6 +856,9 @@ static int FUNC(loop_filter_params)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawFrameHeader *current) { CodedBitstreamAV1Context *priv = ctx->priv_data; + static const int8_t default_loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME] = + { 1, 0, 0, 0, -1, 0, -1, -1 }; + static const int8_t default_loop_filter_mode_deltas[2] = { 0, 0 }; int i, err; if (priv->coded_lossless || current->allow_intrabc) { @@ -739,19 +892,44 @@ static int FUNC(loop_filter_params)(CodedBitstreamContext *ctx, RWContext *rw, flag(loop_filter_delta_enabled); if (current->loop_filter_delta_enabled) { + const int8_t *ref_loop_filter_ref_deltas, *ref_loop_filter_mode_deltas; + + if (current->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + ref_loop_filter_ref_deltas = default_loop_filter_ref_deltas; + ref_loop_filter_mode_deltas = default_loop_filter_mode_deltas; + } else { + ref_loop_filter_ref_deltas = + priv->ref[current->ref_frame_idx[current->primary_ref_frame]].loop_filter_ref_deltas; + ref_loop_filter_mode_deltas = + priv->ref[current->ref_frame_idx[current->primary_ref_frame]].loop_filter_mode_deltas; + } + flag(loop_filter_delta_update); - if (current->loop_filter_delta_update) { - for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) { + for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) { + if (current->loop_filter_delta_update) flags(update_ref_delta[i], 1, i); - if (current->update_ref_delta[i]) - sus(1 + 6, loop_filter_ref_deltas[i], 1, i); - } - for (i = 0; i < 2; i++) { + else + infer(update_ref_delta[i], 0); + if (current->update_ref_delta[i]) + sus(1 + 6, loop_filter_ref_deltas[i], 1, i); + else + infer(loop_filter_ref_deltas[i], ref_loop_filter_ref_deltas[i]); + } + for (i = 0; i < 2; i++) { + if (current->loop_filter_delta_update) flags(update_mode_delta[i], 1, i); - if (current->update_mode_delta[i]) - sus(1 + 6, loop_filter_mode_deltas[i], 1, i); - } + else + infer(update_mode_delta[i], 0); + if (current->update_mode_delta[i]) + sus(1 + 6, loop_filter_mode_deltas[i], 1, i); + else + infer(loop_filter_mode_deltas[i], ref_loop_filter_mode_deltas[i]); } + } else { + for (i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) + infer(loop_filter_ref_deltas[i], default_loop_filter_ref_deltas[i]); + for (i = 0; i < 2; i++) + infer(loop_filter_mode_deltas[i], default_loop_filter_mode_deltas[i]); } return 0; @@ -809,7 +987,7 @@ static int FUNC(lr_params)(CodedBitstreamContext *ctx, RWContext *rw, for (i = 0; i < priv->num_planes; i++) { fbs(2, lr_type[i], 1, i); - if (current->lr_type[i] != 0) { + if (current->lr_type[i] != AV1_RESTORE_NONE) { uses_lr = 1; if (i > 0) uses_chroma_lr = 1; @@ -881,9 +1059,9 @@ static int FUNC(skip_mode_params)(CodedBitstreamContext *ctx, RWContext *rw, forward_idx = -1; backward_idx = -1; for (i = 0; i < AV1_REFS_PER_FRAME; i++) { - ref_hint = priv->ref[i].order_hint; + ref_hint = priv->ref[current->ref_frame_idx[i]].order_hint; dist = cbs_av1_get_relative_dist(seq, ref_hint, - current->order_hint); + priv->order_hint); if (dist < 0) { if (forward_idx < 0 || cbs_av1_get_relative_dist(seq, ref_hint, @@ -912,7 +1090,7 @@ static int FUNC(skip_mode_params)(CodedBitstreamContext *ctx, RWContext *rw, second_forward_idx = -1; for (i = 0; i < AV1_REFS_PER_FRAME; i++) { - ref_hint = priv->ref[i].order_hint; + ref_hint = priv->ref[current->ref_frame_idx[i]].order_hint; if (cbs_av1_get_relative_dist(seq, ref_hint, forward_hint) < 0) { if (second_forward_idx < 0 || @@ -1016,7 +1194,8 @@ static int FUNC(global_motion_params)(CodedBitstreamContext *ctx, RWContext *rw, } static int FUNC(film_grain_params)(CodedBitstreamContext *ctx, RWContext *rw, - AV1RawFrameHeader *current) + AV1RawFilmGrainParams *current, + AV1RawFrameHeader *frame_header) { CodedBitstreamAV1Context *priv = ctx->priv_data; const AV1RawSequenceHeader *seq = priv->sequence_header; @@ -1024,7 +1203,7 @@ static int FUNC(film_grain_params)(CodedBitstreamContext *ctx, RWContext *rw, int i, err; if (!seq->film_grain_params_present || - (!current->show_frame && !current->showable_frame)) + (!frame_header->show_frame && !frame_header->showable_frame)) return 0; flag(apply_grain); @@ -1034,7 +1213,7 @@ static int FUNC(film_grain_params)(CodedBitstreamContext *ctx, RWContext *rw, fb(16, grain_seed); - if (current->frame_type == AV1_FRAME_INTER) + if (frame_header->frame_type == AV1_FRAME_INTER) flag(update_grain); else infer(update_grain, 1); @@ -1044,9 +1223,12 @@ static int FUNC(film_grain_params)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } - fb(4, num_y_points); + fc(4, num_y_points, 0, 14); for (i = 0; i < current->num_y_points; i++) { - fbs(8, point_y_value[i], 1, i); + fcs(8, point_y_value[i], + i ? current->point_y_value[i - 1] + 1 : 0, + MAX_UINT_BITS(8) - (current->num_y_points - i - 1), + 1, i); fbs(8, point_y_scaling[i], 1, i); } @@ -1063,14 +1245,20 @@ static int FUNC(film_grain_params)(CodedBitstreamContext *ctx, RWContext *rw, infer(num_cb_points, 0); infer(num_cr_points, 0); } else { - fb(4, num_cb_points); + fc(4, num_cb_points, 0, 10); for (i = 0; i < current->num_cb_points; i++) { - fbs(8, point_cb_value[i], 1, i); + fcs(8, point_cb_value[i], + i ? current->point_cb_value[i - 1] + 1 : 0, + MAX_UINT_BITS(8) - (current->num_cb_points - i - 1), + 1, i); fbs(8, point_cb_scaling[i], 1, i); } - fb(4, num_cr_points); + fc(4, num_cr_points, 0, 10); for (i = 0; i < current->num_cr_points; i++) { - fbs(8, point_cr_value[i], 1, i); + fcs(8, point_cr_value[i], + i ? current->point_cr_value[i - 1] + 1 : 0, + MAX_UINT_BITS(8) - (current->num_cr_points - i - 1), + 1, i); fbs(8, point_cr_scaling[i], 1, i); } } @@ -1142,10 +1330,17 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, flag(show_existing_frame); if (current->show_existing_frame) { - AV1ReferenceFrameState *frame; + AV1ReferenceFrameState *ref; fb(3, frame_to_show_map_idx); - frame = &priv->ref[current->frame_to_show_map_idx]; + ref = &priv->ref[current->frame_to_show_map_idx]; + + if (!ref->valid) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Missing reference frame needed for " + "show_existing_frame (frame_to_show_map_idx = %d).\n", + current->frame_to_show_map_idx); + return AVERROR_INVALIDDATA; + } if (seq->decoder_model_info_present_flag && !seq->timing_info.equal_picture_interval) { @@ -1156,12 +1351,29 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, if (seq->frame_id_numbers_present_flag) fb(id_len, display_frame_id); - if (frame->frame_type == AV1_FRAME_KEY) + infer(frame_type, ref->frame_type); + if (current->frame_type == AV1_FRAME_KEY) { infer(refresh_frame_flags, all_frames); - else + + // Section 7.21 + infer(current_frame_id, ref->frame_id); + priv->upscaled_width = ref->upscaled_width; + priv->frame_width = ref->frame_width; + priv->frame_height = ref->frame_height; + priv->render_width = ref->render_width; + priv->render_height = ref->render_height; + priv->bit_depth = ref->bit_depth; + priv->order_hint = ref->order_hint; + } else infer(refresh_frame_flags, 0); - return 0; + infer(frame_width_minus_1, ref->upscaled_width - 1); + infer(frame_height_minus_1, ref->frame_height - 1); + infer(render_width_minus_1, ref->render_width - 1); + infer(render_height_minus_1, ref->render_height - 1); + + // Section 7.20 + goto update_refs; } fb(2, frame_type); @@ -1247,6 +1459,7 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, fb(order_hint_bits, order_hint); else infer(order_hint, 0); + priv->order_hint = current->order_hint; if (frame_is_intra || current->error_resilient_mode) infer(primary_ref_frame, AV1_PRIMARY_REF_NONE); @@ -1262,7 +1475,7 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, int in_temporal_layer = (op_pt_idc >> priv->temporal_id ) & 1; int in_spatial_layer = (op_pt_idc >> (priv->spatial_id + 8)) & 1; if (seq->operating_point_idc[i] == 0 || - in_temporal_layer || in_spatial_layer) { + (in_temporal_layer && in_spatial_layer)) { fbs(seq->decoder_model_info.buffer_removal_time_length_minus_1 + 1, buffer_removal_time[i], 1, i); } @@ -1278,9 +1491,12 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, fb(8, refresh_frame_flags); if (!frame_is_intra || current->refresh_frame_flags != all_frames) { - if (current->error_resilient_mode && seq->enable_order_hint) { + if (seq->enable_order_hint) { for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { - fbs(order_hint_bits, ref_order_hint[i], 1, i); + if (current->error_resilient_mode) + fbs(order_hint_bits, ref_order_hint[i], 1, i); + else + infer(ref_order_hint[i], priv->ref[i].order_hint); if (current->ref_order_hint[i] != priv->ref[i].order_hint) priv->ref[i].valid = 0; } @@ -1306,16 +1522,7 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, if (current->frame_refs_short_signaling) { fb(3, last_frame_idx); fb(3, golden_frame_idx); - - for (i = 0; i < AV1_REFS_PER_FRAME; i++) { - if (i == 0) - infer(ref_frame_idx[i], current->last_frame_idx); - else if (i == AV1_REF_FRAME_GOLDEN - - AV1_REF_FRAME_LAST) - infer(ref_frame_idx[i], current->golden_frame_idx); - else - infer(ref_frame_idx[i], -1); - } + CHECK(FUNC(set_frame_refs)(ctx, rw, current)); } } @@ -1429,8 +1636,18 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, CHECK(FUNC(global_motion_params)(ctx, rw, current)); - CHECK(FUNC(film_grain_params)(ctx, rw, current)); + CHECK(FUNC(film_grain_params)(ctx, rw, ¤t->film_grain, current)); + + av_log(ctx->log_ctx, AV_LOG_DEBUG, "Frame %d: size %dx%d " + "upscaled %d render %dx%d subsample %dx%d " + "bitdepth %d tiles %dx%d.\n", priv->order_hint, + priv->frame_width, priv->frame_height, priv->upscaled_width, + priv->render_width, priv->render_height, + seq->color_config.subsampling_x + 1, + seq->color_config.subsampling_y + 1, priv->bit_depth, + priv->tile_rows, priv->tile_cols); +update_refs: for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { if (current->refresh_frame_flags & (1 << i)) { priv->ref[i] = (AV1ReferenceFrameState) { @@ -1445,20 +1662,19 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, .subsampling_x = seq->color_config.subsampling_x, .subsampling_y = seq->color_config.subsampling_y, .bit_depth = priv->bit_depth, - .order_hint = current->order_hint, + .order_hint = priv->order_hint, }; + memcpy(priv->ref[i].loop_filter_ref_deltas, current->loop_filter_ref_deltas, + sizeof(current->loop_filter_ref_deltas)); + memcpy(priv->ref[i].loop_filter_mode_deltas, current->loop_filter_mode_deltas, + sizeof(current->loop_filter_mode_deltas)); + memcpy(priv->ref[i].feature_enabled, current->feature_enabled, + sizeof(current->feature_enabled)); + memcpy(priv->ref[i].feature_value, current->feature_value, + sizeof(current->feature_value)); } } - av_log(ctx->log_ctx, AV_LOG_DEBUG, "Frame %d: size %dx%d " - "upscaled %d render %dx%d subsample %dx%d " - "bitdepth %d tiles %dx%d.\n", current->order_hint, - priv->frame_width, priv->frame_height, priv->upscaled_width, - priv->render_width, priv->render_height, - seq->color_config.subsampling_x + 1, - seq->color_config.subsampling_y + 1, priv->bit_depth, - priv->tile_rows, priv->tile_cols); - return 0; } @@ -1499,8 +1715,6 @@ static int FUNC(frame_header_obu)(CodedBitstreamContext *ctx, RWContext *rw, else HEADER("Frame Header"); - priv->seen_frame_header = 1; - #ifdef READ start_pos = get_bits_count(rw); #else @@ -1509,6 +1723,8 @@ static int FUNC(frame_header_obu)(CodedBitstreamContext *ctx, RWContext *rw, CHECK(FUNC(uncompressed_header)(ctx, rw, current)); + priv->tile_num = 0; + if (current->show_existing_frame) { priv->seen_frame_header = 0; } else { @@ -1574,10 +1790,12 @@ static int FUNC(tile_group_obu)(CodedBitstreamContext *ctx, RWContext *rw, } else { tile_bits = cbs_av1_tile_log2(1, priv->tile_cols) + cbs_av1_tile_log2(1, priv->tile_rows); - fb(tile_bits, tg_start); - fb(tile_bits, tg_end); + fc(tile_bits, tg_start, priv->tile_num, num_tiles - 1); + fc(tile_bits, tg_end, current->tg_start, num_tiles - 1); } + priv->tile_num = current->tg_end + 1; + CHECK(FUNC(byte_alignment)(ctx, rw)); // Reset header for next frame. @@ -1637,15 +1855,65 @@ static int FUNC(metadata_hdr_mdcv)(CodedBitstreamContext *ctx, RWContext *rw, int err, i; for (i = 0; i < 3; i++) { - fcs(16, primary_chromaticity_x[i], 0, 50000, 1, i); - fcs(16, primary_chromaticity_y[i], 0, 50000, 1, i); + fbs(16, primary_chromaticity_x[i], 1, i); + fbs(16, primary_chromaticity_y[i], 1, i); } - fc(16, white_point_chromaticity_x, 0, 50000); - fc(16, white_point_chromaticity_y, 0, 50000); + fb(16, white_point_chromaticity_x); + fb(16, white_point_chromaticity_y); fc(32, luminance_max, 1, MAX_UINT_BITS(32)); - fc(32, luminance_min, 0, current->luminance_max >> 6); + // luminance_min must be lower than luminance_max. Convert luminance_max from + // 24.8 fixed point to 18.14 fixed point in order to compare them. + fc(32, luminance_min, 0, FFMIN(((uint64_t)current->luminance_max << 6) - 1, + MAX_UINT_BITS(32))); + + return 0; +} + +static int FUNC(scalability_structure)(CodedBitstreamContext *ctx, RWContext *rw, + AV1RawMetadataScalability *current) +{ + CodedBitstreamAV1Context *priv = ctx->priv_data; + const AV1RawSequenceHeader *seq; + int err, i, j; + + if (!priv->sequence_header) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "No sequence header available: " + "unable to parse scalability metadata.\n"); + return AVERROR_INVALIDDATA; + } + seq = priv->sequence_header; + + fb(2, spatial_layers_cnt_minus_1); + flag(spatial_layer_dimensions_present_flag); + flag(spatial_layer_description_present_flag); + flag(temporal_group_description_present_flag); + fc(3, scalability_structure_reserved_3bits, 0, 0); + if (current->spatial_layer_dimensions_present_flag) { + for (i = 0; i <= current->spatial_layers_cnt_minus_1; i++) { + fcs(16, spatial_layer_max_width[i], + 0, seq->max_frame_width_minus_1 + 1, 1, i); + fcs(16, spatial_layer_max_height[i], + 0, seq->max_frame_height_minus_1 + 1, 1, i); + } + } + if (current->spatial_layer_description_present_flag) { + for (i = 0; i <= current->spatial_layers_cnt_minus_1; i++) + fbs(8, spatial_layer_ref_id[i], 1, i); + } + if (current->temporal_group_description_present_flag) { + fb(8, temporal_group_size); + for (i = 0; i < current->temporal_group_size; i++) { + fbs(3, temporal_group_temporal_id[i], 1, i); + flags(temporal_group_temporal_switching_up_point_flag[i], 1, i); + flags(temporal_group_spatial_switching_up_point_flag[i], 1, i); + fbs(3, temporal_group_ref_cnt[i], 1, i); + for (j = 0; j < current->temporal_group_ref_cnt[i]; j++) { + fbs(8, temporal_group_ref_pic_diff[i][j], 2, i, j); + } + } + } return 0; } @@ -1653,9 +1921,14 @@ static int FUNC(metadata_hdr_mdcv)(CodedBitstreamContext *ctx, RWContext *rw, static int FUNC(metadata_scalability)(CodedBitstreamContext *ctx, RWContext *rw, AV1RawMetadataScalability *current) { - // TODO: scalability metadata. + int err; - return AVERROR_PATCHWELCOME; + fb(8, scalability_mode_idc); + + if (current->scalability_mode_idc == AV1_SCALABILITY_SS) + CHECK(FUNC(scalability_structure)(ctx, rw, current)); + + return 0; } static int FUNC(metadata_itut_t35)(CodedBitstreamContext *ctx, RWContext *rw, @@ -1671,15 +1944,7 @@ static int FUNC(metadata_itut_t35)(CodedBitstreamContext *ctx, RWContext *rw, #ifdef READ // The payload runs up to the start of the trailing bits, but there might // be arbitrarily many trailing zeroes so we need to read through twice. - { - GetBitContext tmp = *rw; - current->payload_size = 0; - for (i = 0; get_bits_left(rw) >= 8; i++) { - if (get_bits(rw, 8)) - current->payload_size = i; - } - *rw = tmp; - } + current->payload_size = cbs_av1_get_payload_bytes_left(rw); current->payload_ref = av_buffer_alloc(current->payload_size); if (!current->payload_ref) @@ -1706,19 +1971,19 @@ static int FUNC(metadata_timecode)(CodedBitstreamContext *ctx, RWContext *rw, fb(9, n_frames); if (current->full_timestamp_flag) { - fb(6, seconds_value); - fb(6, minutes_value); - fb(5, hours_value); + fc(6, seconds_value, 0, 59); + fc(6, minutes_value, 0, 59); + fc(5, hours_value, 0, 23); } else { flag(seconds_flag); if (current->seconds_flag) { - fb(6, seconds_value); + fc(6, seconds_value, 0, 59); flag(minutes_flag); if (current->minutes_flag) { - fb(6, minutes_value); + fc(6, minutes_value, 0, 59); flag(hours_flag); if (current->hours_flag) - fb(5, hours_value); + fc(5, hours_value, 0, 23); } } } @@ -1726,6 +1991,8 @@ static int FUNC(metadata_timecode)(CodedBitstreamContext *ctx, RWContext *rw, fb(5, time_offset_length); if (current->time_offset_length > 0) fb(current->time_offset_length, time_offset_value); + else + infer(time_offset_length, 0); return 0; } @@ -1760,3 +2027,27 @@ static int FUNC(metadata_obu)(CodedBitstreamContext *ctx, RWContext *rw, return 0; } + +static int FUNC(padding_obu)(CodedBitstreamContext *ctx, RWContext *rw, + AV1RawPadding *current) +{ + int i, err; + + HEADER("Padding"); + +#ifdef READ + // The payload runs up to the start of the trailing bits, but there might + // be arbitrarily many trailing zeroes so we need to read through twice. + current->payload_size = cbs_av1_get_payload_bytes_left(rw); + + current->payload_ref = av_buffer_alloc(current->payload_size); + if (!current->payload_ref) + return AVERROR(ENOMEM); + current->payload = current->payload_ref->data; +#endif + + for (i = 0; i < current->payload_size; i++) + xf(8, obu_padding_byte[i], current->payload[i], 0x00, 0xff, 1, i); + + return 0; +}