Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions av2/av2_cx_iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,58 @@ static avm_codec_err_t validate_config(avm_codec_alg_priv_t *ctx,
RANGE_CHECK_HI(extra_cfg, crop_win_right_offset, 65535);
RANGE_CHECK_HI(extra_cfg, crop_win_top_offset, 65535);
RANGE_CHECK_HI(extra_cfg, crop_win_bottom_offset, 65535);
if (extra_cfg->enable_cropping_window) {
// The decoder validates the conformance window in
// av2_validate_seq_conformance_window() and
// av2_validate_frame_level_conformance(), rejecting the stream with
// AVM_CODEC_UNSUP_BITSTREAM. Apply the same constraints here so an
// undecodable configuration is refused rather than producing a bitstream
// the reference decoder cannot decode.
const int left = extra_cfg->crop_win_left_offset;
const int right = extra_cfg->crop_win_right_offset;
const int top = extra_cfg->crop_win_top_offset;
const int bottom = extra_cfg->crop_win_bottom_offset;
const int max_width = cfg->g_forced_max_frame_width
? (int)cfg->g_forced_max_frame_width
: (int)cfg->g_w;
const int max_height = cfg->g_forced_max_frame_height
? (int)cfg->g_forced_max_frame_height
: (int)cfg->g_h;
// Mirrors av2_validate_seq_conformance_window() in the decoder: each offset
// must be less than the sequence maximum. The left+right and top+bottom
// terms additionally keep conformance requirements 3 and 4 satisfied at
// every coded frame size, which the checks below can only cover for g_w and
// g_h.
if (left >= max_width || right >= max_width || left + right >= max_width) {
ERROR(
"crop_win_left_offset and crop_win_right_offset must each be less "
"than the frame width, and must not together span it");
}
if (top >= max_height || bottom >= max_height ||
top + bottom >= max_height) {
ERROR(
"crop_win_top_offset and crop_win_bottom_offset must each be less "
"than the frame height, and must not together span it");
}
const int LeftPosX = (left * (int)cfg->g_w) / max_width;
const int RightPosX =
(int)cfg->g_w - 1 - ((right * (int)cfg->g_w) / max_width);
const int TopPosY = (top * (int)cfg->g_h) / max_height;
const int BottomPosY =
(int)cfg->g_h - 1 - ((bottom * (int)cfg->g_h) / max_height);
// Conformance requirement 3: LeftPosX<= RightPosX
if (LeftPosX > RightPosX) {
ERROR(
"crop_win_left_offset and crop_win_right_offset leave no samples in "
"the frame");
}
// Conformance requirement 4: TopPosY <= BottomPosY
if (TopPosY > BottomPosY) {
ERROR(
"crop_win_top_offset and crop_win_bottom_offset leave no samples in "
"the frame");
}
}

RANGE_CHECK_HI(extra_cfg, sharpness, 7);
RANGE_CHECK_HI(extra_cfg, arnr_max_frames, 15);
Expand Down Expand Up @@ -3341,6 +3393,12 @@ static avm_codec_err_t encoder_encode(avm_codec_alg_priv_t *ctx,
av2_check_initial_width(cpi_lap, subsampling_x, subsampling_y);
}

// The coded subsampling is only settled by av2_check_initial_width()
// above, so the cropping window's chroma alignment can only be checked
// from here on.
av2_validate_crop_window_chroma_alignment(cpi, cpi->common.width,
cpi->common.height);

// Store the original flags in to the frame buffer. Will extract the
// key frame flag when we actually encode this frame.
if (av2_receive_raw_frame(cpi, flags | ctx->next_frame_flags, &sd,
Expand Down
37 changes: 37 additions & 0 deletions av2/encoder/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -2501,6 +2501,40 @@ static void init_ref_frame_bufs(AV2_COMP *cpi) {
}
}

void av2_validate_crop_window_chroma_alignment(AV2_COMP *cpi, int frame_width,
int frame_height) {
AV2_COMMON *const cm = &cpi->common;
const SequenceHeader *const seq_params = &cm->seq_params;
const struct CropWindow *const conf = &seq_params->conf;
if (!conf->conf_win_enabled_flag) return;

const int SubX = seq_params->subsampling_x + 1;
const int SubY = seq_params->subsampling_y + 1;
const int LeftPosX =
(conf->conf_win_left_offset * frame_width) / seq_params->max_frame_width;
const int TopPosY =
(conf->conf_win_top_offset * frame_height) / seq_params->max_frame_height;

// Conformance requirement 1: LeftPosX == SubX * (LeftPosX/Subx)
if (!seq_params->monochrome && SubX > 1 &&
LeftPosX != SubX * (LeftPosX / SubX)) {
avm_internal_error(&cm->error, AVM_CODEC_INVALID_PARAM,
"crop_win_left_offset puts the conformance window left "
"position %d off the chroma grid at coded width %d: it "
"must be a multiple of SubX=%d",
LeftPosX, frame_width, SubX);
}
// Conformance requirement 2: TopPosY == SubY * (TopPosY / SubY)
if (!seq_params->monochrome && SubY > 1 &&
TopPosY != SubY * (TopPosY / SubY)) {
avm_internal_error(&cm->error, AVM_CODEC_INVALID_PARAM,
"crop_win_top_offset puts the conformance window top "
"position %d off the chroma grid at coded height %d: it "
"must be a multiple of SubY=%d",
TopPosY, frame_height, SubY);
}
}

void av2_check_initial_width(AV2_COMP *cpi, int subsampling_x,
int subsampling_y) {
AV2_COMMON *const cm = &cpi->common;
Expand Down Expand Up @@ -2616,6 +2650,9 @@ void av2_set_frame_size(AV2_COMP *cpi, int width, int height) {

av2_noise_estimate_init(&cpi->noise_estimate, cm->width, cm->height);
}

av2_validate_crop_window_chroma_alignment(cpi, cm->width, cm->height);

if (cm->bridge_frame_info.is_bridge_frame) {
cm->bridge_frame_info.bridge_frame_max_height = cm->height;
cm->bridge_frame_info.bridge_frame_max_width = cm->width;
Expand Down
3 changes: 3 additions & 0 deletions av2/encoder/encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3123,6 +3123,9 @@ void av2_change_config(AV2_COMP *cpi, const AV2EncoderConfig *oxcf);
void av2_check_initial_width(AV2_COMP *cpi, int subsampling_x,
int subsampling_y);

void av2_validate_crop_window_chroma_alignment(AV2_COMP *cpi, int frame_width,
int frame_height);

void av2_init_seq_coding_tools(AV2_COMP *cpi, SequenceHeader *seq,
AV2_COMMON *cm, const AV2EncoderConfig *oxcf);

Expand Down