Skip to content

Commit

Permalink
Add image sequence encoding support using SVT-AV1
Browse files Browse the repository at this point in the history
  • Loading branch information
tongyuantongyu authored and joedrago committed Apr 14, 2021
1 parent 86ace0a commit 0f8b684
Showing 1 changed file with 65 additions and 55 deletions.
120 changes: 65 additions & 55 deletions src/codec_svt.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ static avifResult svtCodecEncodeImage(avifCodec * codec,
{
avifResult result = AVIF_RESULT_UNKNOWN_ERROR;
EbColorFormat color_format = EB_YUV420;

if (!(addImageFlags & AVIF_ADD_IMAGE_FLAG_SINGLE)) {
return AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION;
}
EbBufferHeaderType * input_buffer = NULL;
EbErrorType res = EB_ErrorNone;

int y_shift = 0;
// EbColorRange svt_range;
Expand All @@ -63,60 +61,72 @@ static avifResult svtCodecEncodeImage(avifCodec * codec,
}
}

EbSvtAv1EncConfiguration * svt_config = avifAlloc(sizeof(EbSvtAv1EncConfiguration));
if (!svt_config)
return AVIF_RESULT_UNKNOWN_ERROR;
codec->internal->svt_config = svt_config;

svt_av1_enc_init_handle(&codec->internal->svt_encoder, NULL, svt_config);
svt_config->encoder_color_format = color_format;
svt_config->encoder_bit_depth = (uint8_t)image->depth;
svt_config->high_dynamic_range_input = image->depth > 8 ? AVIF_TRUE : AVIF_FALSE;
if (codec->internal->svt_encoder == NULL) {

svt_config->source_width = image->width;
svt_config->source_height = image->height;
svt_config->logical_processors = encoder->maxThreads;
svt_config->enable_adaptive_quantization = AVIF_FALSE;
// disable 2-pass
svt_config->rc_firstpass_stats_out = AVIF_FALSE;
svt_config->rc_twopass_stats_in = (SvtAv1FixedBuf) { NULL, 0 };
EbSvtAv1EncConfiguration * svt_config = avifAlloc(sizeof(EbSvtAv1EncConfiguration));
if (!svt_config)
return AVIF_RESULT_UNKNOWN_ERROR;
memset(svt_config, 0, sizeof(EbSvtAv1EncConfiguration));
codec->internal->svt_config = svt_config;

if (alpha) {
svt_config->min_qp_allowed = AVIF_CLAMP(encoder->minQuantizerAlpha, 0, 63);
svt_config->max_qp_allowed = AVIF_CLAMP(encoder->maxQuantizerAlpha, 0, 63);
} else {
svt_config->min_qp_allowed = AVIF_CLAMP(encoder->minQuantizer, 0, 63);
svt_config->qp = AVIF_CLAMP(encoder->maxQuantizer, 0, 63);
}
res = svt_av1_enc_init_handle(&codec->internal->svt_encoder, NULL, svt_config);
if (res != EB_ErrorNone || codec->internal->svt_encoder == NULL) {
goto cleanup;
}
svt_config->encoder_color_format = color_format;
svt_config->encoder_bit_depth = (uint8_t)image->depth;
svt_config->is_16bit_pipeline = image->depth > 8 ? AVIF_TRUE : AVIF_FALSE;

// Follow comment in svt header: set if input is HDR10 BT2020 using SMPTE ST2084.
svt_config->high_dynamic_range_input = (image->depth == 10 && image->matrixCoefficients == AVIF_MATRIX_COEFFICIENTS_BT2020_NCL &&
image->transferCharacteristics == AVIF_TRANSFER_CHARACTERISTICS_SMPTE2084)
? AVIF_TRUE
: AVIF_FALSE;

svt_config->source_width = image->width;
svt_config->source_height = image->height;
svt_config->logical_processors = encoder->maxThreads;
svt_config->enable_adaptive_quantization = AVIF_FALSE;
// disable 2-pass
svt_config->rc_firstpass_stats_out = AVIF_FALSE;
svt_config->rc_twopass_stats_in = (SvtAv1FixedBuf) { NULL, 0 };

if (alpha) {
svt_config->min_qp_allowed = AVIF_CLAMP(encoder->minQuantizerAlpha, 0, 63);
svt_config->max_qp_allowed = AVIF_CLAMP(encoder->maxQuantizerAlpha, 0, 63);
} else {
svt_config->min_qp_allowed = AVIF_CLAMP(encoder->minQuantizer, 0, 63);
svt_config->qp = AVIF_CLAMP(encoder->maxQuantizer, 0, 63);
}

if (encoder->tileRowsLog2 != 0) {
int tileRowsLog2 = AVIF_CLAMP(encoder->tileRowsLog2, 0, 6);
svt_config->tile_rows = 1 << tileRowsLog2;
}
if (encoder->tileColsLog2 != 0) {
int tileColsLog2 = AVIF_CLAMP(encoder->tileColsLog2, 0, 6);
svt_config->tile_columns = 1 << tileColsLog2;
}
if (encoder->speed != AVIF_SPEED_DEFAULT) {
int speed = AVIF_CLAMP(encoder->speed, 0, 8);
svt_config->enc_mode = (int8_t)speed;
}
if (encoder->tileRowsLog2 != 0) {
int tileRowsLog2 = AVIF_CLAMP(encoder->tileRowsLog2, 0, 6);
svt_config->tile_rows = 1 << tileRowsLog2;
}
if (encoder->tileColsLog2 != 0) {
int tileColsLog2 = AVIF_CLAMP(encoder->tileColsLog2, 0, 6);
svt_config->tile_columns = 1 << tileColsLog2;
}
if (encoder->speed != AVIF_SPEED_DEFAULT) {
int speed = AVIF_CLAMP(encoder->speed, 0, 8);
svt_config->enc_mode = (int8_t)speed;
}

if (color_format == EB_YUV422 || image->depth > 10) {
svt_config->profile = PROFESSIONAL_PROFILE;
} else if (color_format == EB_YUV444) {
svt_config->profile = HIGH_PROFILE;
}
if (color_format == EB_YUV422 || image->depth > 10) {
svt_config->profile = PROFESSIONAL_PROFILE;
} else if (color_format == EB_YUV444) {
svt_config->profile = HIGH_PROFILE;
}

EbErrorType res = svt_av1_enc_set_parameter(codec->internal->svt_encoder, svt_config);
EbBufferHeaderType * input_buffer = NULL;
if (res == EB_ErrorBadParameter) {
goto cleanup;
}
res = svt_av1_enc_set_parameter(codec->internal->svt_encoder, svt_config);
if (res == EB_ErrorBadParameter) {
goto cleanup;
}

res = svt_av1_enc_init(codec->internal->svt_encoder);
if (res != EB_ErrorNone) {
goto cleanup;
res = svt_av1_enc_init(codec->internal->svt_encoder);
if (res != EB_ErrorNone) {
goto cleanup;
}
}

allocate_svt_buffers(&input_buffer);
Expand Down Expand Up @@ -157,8 +167,9 @@ static avifResult svtCodecEncodeImage(avifCodec * codec,
result = dequeue_frame(codec, output, AVIF_FALSE);
cleanup:
if (input_buffer) {
avifFree(input_buffer->p_buffer);
input_buffer->p_buffer = NULL;
if (input_buffer->p_buffer) {
avifFree(input_buffer->p_buffer);
}
avifFree(input_buffer);
input_buffer = NULL;
}
Expand Down Expand Up @@ -215,7 +226,6 @@ avifCodec * avifCodecCreateSvt(void)

codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(avifCodecInternal));
memset(codec->internal, 0, sizeof(struct avifCodecInternal));
codec->internal->svt_encoder = (EbComponentType *)avifAlloc(sizeof(EbComponentType));
return codec;
}

Expand Down

0 comments on commit 0f8b684

Please sign in to comment.