X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Flibkvazaar.c;h=e58405d27e4f7efc3f0a2360b64f4a3d2bf0d0ee;hb=51a3e525935efc60d8d23050f0daafeb82a3df57;hp=3000f6ac6e7045568a997e8e98e2816b0db9c41a;hpb=470204218f37e361da02d75845f9db9793a4ee53;p=ffmpeg diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index 3000f6ac6e7..e58405d27e4 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -24,10 +24,13 @@ #include #include "libavutil/avassert.h" -#include "libavutil/imgutils.h" #include "libavutil/dict.h" -#include "libavutil/opt.h" +#include "libavutil/error.h" +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" #include "libavutil/pixdesc.h" +#include "libavutil/opt.h" + #include "avcodec.h" #include "internal.h" @@ -43,39 +46,39 @@ typedef struct LibkvazaarContext { static av_cold int libkvazaar_init(AVCodecContext *avctx) { - int retval = 0; + LibkvazaarContext *const ctx = avctx->priv_data; + const kvz_api *const api = ctx->api = kvz_api_get(8); kvz_config *cfg = NULL; kvz_encoder *enc = NULL; - const kvz_api *const api = kvz_api_get(8); - - LibkvazaarContext *const ctx = avctx->priv_data; - // Kvazaar requires width and height to be multiples of eight. + /* Kvazaar requires width and height to be multiples of eight. */ if (avctx->width % 8 || avctx->height % 8) { - av_log(avctx, AV_LOG_ERROR, "Video dimensions are not a multiple of 8.\n"); - retval = AVERROR_INVALIDDATA; - goto done; + av_log(avctx, AV_LOG_ERROR, + "Video dimensions are not a multiple of 8 (%dx%d).\n", + avctx->width, avctx->height); + return AVERROR(ENOSYS); } - cfg = api->config_alloc(); + ctx->config = cfg = api->config_alloc(); if (!cfg) { - av_log(avctx, AV_LOG_ERROR, "Could not allocate kvazaar config structure.\n"); - retval = AVERROR(ENOMEM); - goto done; + av_log(avctx, AV_LOG_ERROR, + "Could not allocate kvazaar config structure.\n"); + return AVERROR(ENOMEM); } if (!api->config_init(cfg)) { - av_log(avctx, AV_LOG_ERROR, "Could not initialize kvazaar config structure.\n"); - retval = AVERROR_EXTERNAL; - goto done; + av_log(avctx, AV_LOG_ERROR, + "Could not initialize kvazaar config structure.\n"); + return AVERROR_BUG; } - cfg->width = avctx->width; + cfg->width = avctx->width; cfg->height = avctx->height; + cfg->framerate = avctx->time_base.den / (double)(avctx->time_base.num * avctx->ticks_per_frame); cfg->target_bitrate = avctx->bit_rate; - cfg->vui.sar_width = avctx->sample_aspect_ratio.num; + cfg->vui.sar_width = avctx->sample_aspect_ratio.num; cfg->vui.sar_height = avctx->sample_aspect_ratio.den; if (ctx->kvz_params) { @@ -84,8 +87,7 @@ static av_cold int libkvazaar_init(AVCodecContext *avctx) AVDictionaryEntry *entry = NULL; while ((entry = av_dict_get(dict, "", entry, AV_DICT_IGNORE_SUFFIX))) { if (!api->config_parse(cfg, entry->key, entry->value)) { - av_log(avctx, AV_LOG_WARNING, - "Invalid option: %s=%s.\n", + av_log(avctx, AV_LOG_WARNING, "Invalid option: %s=%s.\n", entry->key, entry->value); } } @@ -93,40 +95,51 @@ static av_cold int libkvazaar_init(AVCodecContext *avctx) } } - enc = api->encoder_open(cfg); + ctx->encoder = enc = api->encoder_open(cfg); if (!enc) { av_log(avctx, AV_LOG_ERROR, "Could not open kvazaar encoder.\n"); - retval = AVERROR_EXTERNAL; - goto done; + return AVERROR_BUG; } - ctx->api = api; - ctx->encoder = enc; - ctx->config = cfg; - enc = NULL; - cfg = NULL; + if (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) { + kvz_data_chunk *data_out = NULL; + kvz_data_chunk *chunk = NULL; + uint32_t len_out; + uint8_t *p; -done: - api->config_destroy(cfg); - api->encoder_close(enc); + if (!api->encoder_headers(enc, &data_out, &len_out)) + return AVERROR(ENOMEM); - return retval; + avctx->extradata = p = av_mallocz(len_out + AV_INPUT_BUFFER_PADDING_SIZE); + if (!p) { + ctx->api->chunk_free(data_out); + return AVERROR(ENOMEM); + } + + avctx->extradata_size = len_out; + + for (chunk = data_out; chunk != NULL; chunk = chunk->next) { + memcpy(p, chunk->data, chunk->len); + p += chunk->len; + } + + ctx->api->chunk_free(data_out); + } + + return 0; } static av_cold int libkvazaar_close(AVCodecContext *avctx) { LibkvazaarContext *ctx = avctx->priv_data; - if (!ctx->api) return 0; - if (ctx->encoder) { - ctx->api->encoder_close(ctx->encoder); - ctx->encoder = NULL; + if (ctx->api) { + ctx->api->encoder_close(ctx->encoder); + ctx->api->config_destroy(ctx->config); } - if (ctx->config) { - ctx->api->config_destroy(ctx->config); - ctx->config = NULL; - } + if (avctx->extradata) + av_freep(&avctx->extradata); return 0; } @@ -136,15 +149,13 @@ static int libkvazaar_encode(AVCodecContext *avctx, const AVFrame *frame, int *got_packet_ptr) { - int retval = 0; - kvz_picture *img_in = NULL; - - kvz_data_chunk *data_out = NULL; - uint32_t len_out = 0; + LibkvazaarContext *ctx = avctx->priv_data; + kvz_picture *input_pic = NULL; kvz_picture *recon_pic = NULL; kvz_frame_info frame_info; - - LibkvazaarContext *ctx = avctx->priv_data; + kvz_data_chunk *data_out = NULL; + uint32_t len_out = 0; + int retval = 0; *got_packet_ptr = 0; @@ -171,14 +182,14 @@ static int libkvazaar_encode(AVCodecContext *avctx, } // Allocate input picture for kvazaar. - img_in = ctx->api->picture_alloc(frame->width, frame->height); - if (!img_in) { + input_pic = ctx->api->picture_alloc(frame->width, frame->height); + if (!input_pic) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate picture.\n"); retval = AVERROR(ENOMEM); goto done; } - // Copy pixels from frame to img_in. + // Copy pixels from frame to input_pic. { int dst_linesizes[4] = { frame->width, @@ -186,22 +197,26 @@ static int libkvazaar_encode(AVCodecContext *avctx, frame->width / 2, 0 }; - av_image_copy(img_in->data, dst_linesizes, + av_image_copy(input_pic->data, dst_linesizes, frame->data, frame->linesize, frame->format, frame->width, frame->height); } - img_in->pts = frame->pts; + input_pic->pts = frame->pts; } - if (!ctx->api->encoder_encode(ctx->encoder, img_in, - &data_out, &len_out, - &recon_pic, NULL, - &frame_info)) { + retval = ctx->api->encoder_encode(ctx->encoder, + input_pic, + &data_out, &len_out, + &recon_pic, NULL, + &frame_info); + if (!retval) { av_log(avctx, AV_LOG_ERROR, "Failed to encode frame.\n"); - retval = AVERROR_EXTERNAL; + retval = AVERROR_INVALIDDATA; goto done; } + else + retval = 0; /* kvazaar returns 1 on success */ if (data_out) { kvz_data_chunk *chunk = NULL; @@ -218,14 +233,9 @@ static int libkvazaar_encode(AVCodecContext *avctx, memcpy(avpkt->data + written, chunk->data, chunk->len); written += chunk->len; } - *got_packet_ptr = 1; - - ctx->api->chunk_free(data_out); - data_out = NULL; avpkt->pts = recon_pic->pts; avpkt->dts = recon_pic->dts; - avpkt->flags = 0; // IRAP VCL NAL unit types span the range // [BLA_W_LP (16), RSV_IRAP_VCL23 (23)]. @@ -233,10 +243,12 @@ static int libkvazaar_encode(AVCodecContext *avctx, frame_info.nal_unit_type <= KVZ_NAL_RSV_IRAP_VCL23) { avpkt->flags |= AV_PKT_FLAG_KEY; } + + *got_packet_ptr = 1; } done: - ctx->api->picture_free(img_in); + ctx->api->picture_free(input_pic); ctx->api->picture_free(recon_pic); ctx->api->chunk_free(data_out); return retval; @@ -247,10 +259,11 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE }; +#define OFFSET(x) offsetof(LibkvazaarContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "kvazaar-params", "Set kvazaar parameters as a comma-separated list of name=value pairs.", - offsetof(LibkvazaarContext, kvz_params), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, - AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM }, + { "kvazaar-params", "Set kvazaar parameters as a comma-separated list of key=value pairs.", + OFFSET(kvz_params), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VE }, { NULL }, }; @@ -281,4 +294,6 @@ AVCodec ff_libkvazaar_encoder = { .init = libkvazaar_init, .encode2 = libkvazaar_encode, .close = libkvazaar_close, + + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, };