> -----Original Message----- > From: ffmpeg-devel <ffmpeg-devel-boun...@ffmpeg.org> On Behalf Of James > Almer > Sent: środa, 30 kwietnia 2025 02:40 > To: ffmpeg-devel@ffmpeg.org > Subject: [FFmpeg-devel] [PATCH] avcodec: add APV encoder using liboapv > > From: Dawid Kozinski <d.kozin...@samsung.com> > > Co-authored-by: James Almer <jamr...@gmail.com> > Signed-off-by: James Almer <jamr...@gmail.com> > --- > Touched up Dawid's patch to fix several issues. The most important one being > the image rescaling code that's out of place in an encoder. > liboapv does not seem to properly support 12bit content yet (Which is why the > scaling code was added, to reduce the input to 10bit), so i removed it > altogether. Same with all the references to GRAY, 420P, A444P, and Y210, which > are also not supported. > Thank you for the review and your changes. We are aware that the encoder is not the best place for data rescaling. However, the oapve_encode() function requires data which size is a multiple of 16. Any suggestions for resolving this problem? A bit off-topic. I am still working on the implementation of the MOV muxer. The patch should be submitted soon. > Also removed the ad-hock atomics. If the library needs the reference counting > to be atomic, it needs to handle it itself. Their own CLI implementation doesn't > even bother with it. > > configure | 4 + > doc/encoders.texi | 41 ++++ > libavcodec/Makefile | 1 + > libavcodec/allcodecs.c | 2 + > libavcodec/liboapvenc.c | 490 ++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 538 insertions(+) > create mode 100644 libavcodec/liboapvenc.c > > diff --git a/configure b/configure > index e285061742..4717836aff 100755 > --- a/configure > +++ b/configure > @@ -250,6 +250,7 @@ External library support: > --enable-liblensfun enable lensfun lens correction [no] > --enable-libmodplug enable ModPlug via libmodplug [no] > --enable-libmp3lame enable MP3 encoding via libmp3lame [no] > + --enable-liboapv enable APV encoding/decoding via liboapv [no] > --enable-libopencore-amrnb enable AMR-NB de/encoding via libopencore- > amrnb [no] > --enable-libopencore-amrwb enable AMR-WB decoding via libopencore- > amrwb [no] > --enable-libopencv enable video filtering via libopencv [no] > @@ -1951,6 +1952,7 @@ EXTERNAL_LIBRARY_LIST=" > libmodplug > libmp3lame > libmysofa > + liboapv > libopencv > libopenh264 > libopenjpeg > @@ -3590,6 +3592,7 @@ liblc3_encoder_select="audio_frame_queue" > libmodplug_demuxer_deps="libmodplug" > libmp3lame_encoder_deps="libmp3lame" > libmp3lame_encoder_select="audio_frame_queue mpegaudioheader" > +liboapv_encoder_deps="liboapv" > libopencore_amrnb_decoder_deps="libopencore_amrnb" > libopencore_amrnb_encoder_deps="libopencore_amrnb" > libopencore_amrnb_encoder_select="audio_frame_queue" > @@ -6930,6 +6933,7 @@ enabled jni && { [ $target_os = "android" ] && > check_headers jni.h > enabled ladspa && require_headers "ladspa.h dlfcn.h" > enabled lcms2 && require_pkg_config lcms2 "lcms2 >= 2.13" lcms2.h > cmsCreateContext > enabled libaom && require_pkg_config libaom "aom >= 2.0.0" > aom/aom_codec.h aom_codec_version > +enabled liboapv && require_pkg_config liboapv "oapv >= 0.1.13" > "oapv/oapv.h" oapve_encode > enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" > "aribb24/aribb24.h" arib_instance_new || > { enabled gpl && require_pkg_config libaribb24 aribb24 > "aribb24/aribb24.h" arib_instance_new; } || > die "ERROR: libaribb24 requires version higher than 1.0.3 or -- > enable-gpl."; } diff --git a/doc/encoders.texi b/doc/encoders.texi index > 128e81a2e7..f5d6d69246 100644 > --- a/doc/encoders.texi > +++ b/doc/encoders.texi > @@ -1889,6 +1889,47 @@ ffmpeg -i input -c:v libaom-av1 -b:v 500K -aom- > params tune=psnr:enable-tpl-model > > @end table > > +@section liboapv > + > +Advanced Professional Video codec encoder wrapper. > + > +This encoder requires the presence of the liboapv headers and library > +during configuration. You need to explicitly configure the build with > +@option{--enable-liboapv}. > + > +@float NOTE > +Many liboapv encoder options are mapped to FFmpeg global codec options, > +while unique encoder options are provided through private options. > +Additionally the apv-params private options allows one to pass a list > +of key=value tuples as accepted by the liboapv @code{parse_apv_params} > function. > +@end float > + > +The apv project website is at > @url{https://protect2.fireeye.com/v1/url?k=0ac15afb-6bbaf073-0ac0d1b4- > 74fe4860018a-8320254a0f21174c&q=1&e=b2c8d30c-5c3a-4ef3-af4f- > bd15f74e89f9&u=https%3A%2F%2Fgithub.com%2FAcademySoftwareFoundatio > n%2Fopenapv%257D. > + > +@subsection Options > + > +The following options are supported by the liboapv wrapper. > +The apv-equivalent options or values are listed in parentheses for easy > migration. > + > +@float NOTE > +To reduce the duplication of documentation, only the private options > +and some others requiring special attention are documented here. For > +the documentation of the undocumented generic options, see > +@ref{codec-options,,the Codec Options chapter}. > +@end float > + > +@float NOTE > +To get a more accurate and extensive documentation of the liboapv > +options, invoke the command @code{apv_app_enc --help} or consult the > liboapv documentation. > +@end float > + > +@table @option > +@item b (@emph{bitrate}) > +Set target video bitrate in bits/s. > +Note that FFmpeg's b option is expressed in bits/s, while apv's bitrate is in > kilobits/s. > + > +@end table > + > @section libsvtav1 > > SVT-AV1 encoder wrapper. > diff --git a/libavcodec/Makefile b/libavcodec/Makefile index > cc142bbae2..cae8f3a9f1 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -1151,6 +1151,7 @@ OBJS-$(CONFIG_LIBKVAZAAR_ENCODER) += > libkvazaar.o > OBJS-$(CONFIG_LIBLC3_ENCODER) += liblc3enc.o > OBJS-$(CONFIG_LIBLC3_DECODER) += liblc3dec.o > OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o > +OBJS-$(CONFIG_LIBOAPV_ENCODER) += liboapvenc.o > OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o > OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o > OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o diff > --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index > 09f06c71d6..3cb04a2462 100644 > --- a/libavcodec/allcodecs.c > +++ b/libavcodec/allcodecs.c > @@ -764,6 +764,7 @@ extern const FFCodec ff_pcm_mulaw_at_decoder; > extern const FFCodec ff_qdmc_at_decoder; extern const FFCodec > ff_qdm2_at_decoder; extern FFCodec ff_libaom_av1_encoder; > + > /* preferred over libaribb24 */ > extern const FFCodec ff_libaribcaption_decoder; extern const FFCodec > ff_libaribb24_decoder; @@ -787,6 +788,7 @@ extern const FFCodec > ff_libjxl_encoder; extern const FFCodec ff_liblc3_encoder; extern const > FFCodec ff_liblc3_decoder; extern const FFCodec ff_libmp3lame_encoder; > +extern const FFCodec ff_liboapv_encoder; > extern const FFCodec ff_libopencore_amrnb_encoder; extern const FFCodec > ff_libopencore_amrnb_decoder; extern const FFCodec > ff_libopencore_amrwb_decoder; diff --git a/libavcodec/liboapvenc.c > b/libavcodec/liboapvenc.c new file mode 100644 index 0000000000..01fb20ecff > --- /dev/null > +++ b/libavcodec/liboapvenc.c > @@ -0,0 +1,490 @@ > +/* > + * liboapv encoder > + * Advanced Professional Video codec library > + * > + * Copyright (C) 2025 Dawid Kozinski <d.kozin...@samsung.com> > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > +02110-1301 USA */ > + > +#include <stdint.h> > +#include <stdlib.h> > + > +#include <oapv/oapv.h> > + > +#include "libavutil/opt.h" > +#include "libavutil/pixdesc.h" > +#include "libavutil/pixfmt.h" > +#include "libavutil/mem.h" > +#include "libavutil/avassert.h" > +#include "libavutil/imgutils.h" > + > +#include "avcodec.h" > +#include "packet_internal.h" > +#include "codec_internal.h" > +#include "encode.h" > + > +#define MAX_BS_BUF (128 * 1024 * 1024) > +#define MAX_NUM_FRMS (1) // supports only 1-frame in an access unit > +#define FRM_IDX (0) // supports only 1-frame in an access unit > +#define MAX_NUM_CC (OAPV_MAX_CC) // Max number of color componets > (upto 4:4:4:4) > + > +/** > + * The structure stores all the states associated with the instance of > +APV encoder */ typedef struct ApvEncContext { > + const AVClass *class; > + > + oapve_t id; // APV instance identifier > + oapvm_t mid; > + oapve_cdesc_t cdsc; // coding parameters i.e profile, width & height of > input frame, num of therads, frame rate ... > + oapv_bitb_t bitb; // bitstream buffer (output) > + oapve_stat_t stat; // encoding status (output) > + > + oapv_frms_t ifrms; // frames for input > + > + int num_frames; // number of frames in an access unit > + > + int preset_id; // preset of apv ( fastest, fast, medium, slow, placebo) > + > + int qp; // quantization parameter (QP) [0,51] > + > + AVDictionary *oapv_params; > +} ApvEncContext; > + > +static int apv_imgb_release(oapv_imgb_t *imgb) { > + int refcnt = --imgb->refcnt; > + if (refcnt == 0) { > + for (int i = 0; i < imgb->np; i++) > + av_freep(&imgb->baddr[i]); > + av_free(imgb); > + } > + > + return refcnt; > +} > + > +static int apv_imgb_addref(oapv_imgb_t * imgb) { > + int refcnt = ++imgb->refcnt; > + return refcnt; > +} > + > +static int apv_imgb_getref(oapv_imgb_t * imgb) { > + return imgb->refcnt; > +} > + > +static oapv_imgb_t *apv_imgb_create(int w, int h, int cs, void *logctx) > +{ > + oapv_imgb_t *imgb; > + int i, bd; > + > + imgb = av_mallocz(sizeof(oapv_imgb_t)); > + if (!imgb) > + goto fail; > + > + bd = OAPV_CS_GET_BYTE_DEPTH(cs); /* byte unit */ > + > + imgb->w[0] = w; > + imgb->h[0] = h; > + switch(OAPV_CS_GET_FORMAT(cs)) { > + case OAPV_CF_YCBCR422: > + imgb->w[1] = imgb->w[2] = (w + 1) >> 1; > + imgb->h[1] = imgb->h[2] = h; > + imgb->np = 3; > + break; > + case OAPV_CF_YCBCR444: > + imgb->w[1] = imgb->w[2] = w; > + imgb->h[1] = imgb->h[2] = h; > + imgb->np = 3; > + break; > + default: > + av_log(logctx, AV_LOG_ERROR, "unsupported color format\n"); > + goto fail; > + } > + > + for (i = 0; i < imgb->np; i++) { > + imgb->aw[i] = FFALIGN(imgb->w[i], OAPV_MB_W); > + imgb->s[i] = imgb->aw[i] * bd; > + imgb->ah[i] = FFALIGN(imgb->h[i], OAPV_MB_H); > + imgb->e[i] = imgb->ah[i]; > + > + imgb->bsize[i] = imgb->s[i] * imgb->e[i]; > + imgb->a[i] = imgb->baddr[i] = av_mallocz(imgb->bsize[i]); > + if (imgb->a[i] == NULL) > + goto fail; > + } > + imgb->cs = cs; > + imgb->addref = apv_imgb_addref; > + imgb->getref = apv_imgb_getref; > + imgb->release = apv_imgb_release; > + > + imgb->refcnt = 1; > + > + return imgb; > +fail: > + av_log(logctx, AV_LOG_ERROR, "cannot create image buffer\n"); > + if (imgb) { > + for (int i = 0; i < imgb->np; i++) > + av_freep(&imgb->a[i]); > + } > + av_freep(&imgb); > + return NULL; > +} > + > +/** > + * Convert FFmpeg pixel format (AVPixelFormat) into APV pre-defined > +color format > + * > + * @return APV pre-defined color format (@see oapv.h) on success, > +OAPV_CF_UNKNOWN on failure */ static inline int get_color_format(enum > +AVPixelFormat pix_fmt) { > + int cf = OAPV_CF_UNKNOWN; > + > + switch (pix_fmt) { > + case AV_PIX_FMT_YUV422P10: > + cf = OAPV_CF_YCBCR422; > + break; > + case AV_PIX_FMT_YUV444P10: > + cf = OAPV_CF_YCBCR444; > + break; > + default: > + break; > + } > + > + return cf; > +} > + > +/** > + * The function returns a pointer to the object of the oapve_cdesc_t type. > + * oapve_cdesc_t contains all encoder parameters that should be initialized > before the encoder is used. > + * > + * The field values of the oapve_cdesc_t structure are populated based on: > + * - the corresponding field values of the AvCodecConetxt structure, > + * - the apv encoder specific option values, > + * > + * The order of processing input data and populating the apve_cdsc > +structure > + * 1) first, the fields of the AVCodecContext structure corresponding to the > provided input options are processed, > + * (i.e -pix_fmt yuv422p -s:v 1920x1080 -r 30 -profile:v 0) > + * 2) then apve-specific options added as AVOption to the apv AVCodec > implementation > + * (i.e -preset 0) > + * > + * Keep in mind that, there are options that can be set in different ways. > + * In this case, please follow the above-mentioned order of processing. > + * The most recent assignments overwrite the previous values. > + * > + * @param[in] avctx codec context (AVCodecContext) > + * @param[out] cdsc contains all APV encoder encoder parameters that > +should be initialized before the encoder is use > + * > + * @return 0 on success, negative error code on failure */ static int > +get_conf(AVCodecContext *avctx, oapve_cdesc_t *cdsc) { > + ApvEncContext *apv = avctx->priv_data; > + > + /* initialize apv_param struct with default values */ > + int ret = oapve_param_default(&cdsc->param[FRM_IDX]); > + if (OAPV_FAILED(ret)) { > + av_log(avctx, AV_LOG_ERROR, "Cannot set default parameter\n"); > + return AVERROR_EXTERNAL; > + } > + > + /* read options from AVCodecContext */ > + if (avctx->width > 0) > + cdsc->param[FRM_IDX].w = avctx->width; > + > + if (avctx->height > 0) > + cdsc->param[FRM_IDX].h = avctx->height; > + > + if (avctx->framerate.num > 0) { > + cdsc->param[FRM_IDX].fps_num = avctx->framerate.num; > + cdsc->param[FRM_IDX].fps_den = avctx->framerate.den; > + } else if (avctx->time_base.num > 0) { > + cdsc->param[FRM_IDX].fps_num = avctx->time_base.den; > + cdsc->param[FRM_IDX].fps_den = avctx->time_base.num; > + } > + > + cdsc->param[FRM_IDX].preset = apv->preset_id; > + cdsc->param[FRM_IDX].qp = apv->qp; > + if (avctx->bit_rate / 1000 > INT_MAX || avctx->rc_max_rate / 1000 > > INT_MAX) { > + av_log(avctx, AV_LOG_ERROR, "Not supported bitrate bit_rate and > rc_max_rate > %d000\n", INT_MAX); > + return AVERROR(EINVAL); > + } > + cdsc->param[FRM_IDX].bitrate = (int)(avctx->bit_rate / 1000); > + if (cdsc->param[FRM_IDX].bitrate) { > + if (cdsc->param[FRM_IDX].qp) { > + av_log(avctx, AV_LOG_WARNING, "You cannot set both the bitrate and > the QP parameter at the same time.\n" > + "If the bitrate is set, the rate control type is set to ABR, > which means that the QP value is ignored.\n"); > + } > + cdsc->param[FRM_IDX].rc_type = OAPV_RC_ABR; > + } > + > + cdsc->threads = avctx->thread_count; > + > + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) > + cdsc->param[FRM_IDX].color_primaries = avctx->color_primaries; > + > + if (avctx->color_trc != AVCOL_TRC_UNSPECIFIED) > + cdsc->param[FRM_IDX].transfer_characteristics = > + avctx->color_trc; > + > + if (avctx->colorspace != AVCOL_SPC_UNSPECIFIED) > + cdsc->param[FRM_IDX].matrix_coefficients = avctx->colorspace; > + > + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED) > + cdsc->param[FRM_IDX].full_range_flag = (avctx->color_range == > + AVCOL_RANGE_JPEG); > + > + cdsc->max_bs_buf_size = MAX_BS_BUF; /* maximum bitstream buffer size > */ > + cdsc->max_num_frms = MAX_NUM_FRMS; > + > + return 0; > +} > + > +static int get_bit_depth(enum AVPixelFormat pixel_format) { > + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixel_format); > + av_assert0(desc); > + return desc->comp[0].depth; > +} > + > +/** > + * @brief Initialize APV codec > + * Create an encoder instance and allocate all the needed resources > + * > + * @param avctx codec context > + * @return 0 on success, negative error code on failure */ static > +av_cold int liboapve_init(AVCodecContext *avctx) { > + ApvEncContext *apv = avctx->priv_data; > + oapve_cdesc_t *cdsc = &apv->cdsc; > + unsigned char *bs_buf; > + int input_depth; > + int cfmt; // color format > + int ret; > + > + apv->id = NULL; > + apv->mid = NULL; > + apv->bitb.addr = NULL; > + > + /* allocate bitstream buffer */ > + bs_buf = (unsigned char *)av_malloc(MAX_BS_BUF); > + if (bs_buf == NULL) { > + av_log(avctx, AV_LOG_ERROR, "Cannot allocate bitstream buffer, > size=%d\n", MAX_BS_BUF); > + return AVERROR(ENOMEM); > + } > + apv->bitb.addr = bs_buf; > + apv->bitb.bsize = MAX_BS_BUF; > + > + /* read configurations and set values for created descriptor (APV_CDSC) */ > + ret = get_conf(avctx, cdsc); > + if (ret < 0) { > + av_log(avctx, AV_LOG_ERROR, "Cannot get OAPV configuration\n"); > + return ret; > + } > + > + const AVDictionaryEntry *en = NULL; > + while (en = av_dict_iterate(apv->oapv_params, en)) { > + ret = oapve_param_parse(&cdsc->param[FRM_IDX], en->key, en->value); > + if (ret < 0) > + av_log(avctx, AV_LOG_WARNING, "Error parsing option '%s = %s'.\n", > en->key, en->value); > + } > + > + /* create encoder */ > + apv->id = oapve_create(cdsc, &ret); > + if (apv->id == NULL) { > + av_log(avctx, AV_LOG_ERROR, "Cannot create OAPV encoder\n"); > + if (ret == OAPV_ERR_INVALID_LEVEL) > + av_log(avctx, AV_LOG_ERROR, "Invalid level idc: %d\n", cdsc- > >param[0].level_idc); > + return AVERROR_EXTERNAL; > + } > + > + /* create metadata handler */ > + apv->mid = oapvm_create(&ret); > + if (apv->mid == NULL || OAPV_FAILED(ret)) { > + av_log(avctx, AV_LOG_ERROR, "cannot create OAPV metadata > handler\n"); > + return AVERROR_EXTERNAL; > + } > + > + input_depth = get_bit_depth(avctx->pix_fmt); > + cfmt = get_color_format(avctx->pix_fmt); > + > + apv->ifrms.frm[FRM_IDX].imgb = apv_imgb_create(avctx->width, avctx- > >height, > + OAPV_CS_SET(cfmt, input_depth, > AV_HAVE_BIGENDIAN), avctx); > + if (apv->ifrms.frm[FRM_IDX].imgb == NULL) > + return AVERROR(ENOMEM); > + apv->ifrms.num_frms++; > + > + /* color description values */ > + if (cdsc->param[FRM_IDX].color_description_present_flag) { > + avctx->color_primaries = cdsc->param[FRM_IDX].color_primaries; > + avctx->color_trc = cdsc->param[FRM_IDX].transfer_characteristics; > + avctx->colorspace = cdsc->param[FRM_IDX].matrix_coefficients; > + avctx->color_range = (cdsc->param[FRM_IDX].full_range_flag) ? > AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; > + } > + > + return 0; > +} > + > +/** > + * Encode raw data frame into APV packet > + * > + * @param[in] avctx codec context > + * @param[out] avpkt output AVPacket containing encoded data > + * @param[in] frame AVFrame containing the raw data to be encoded > + * @param[out] got_packet encoder sets to 0 or 1 to indicate that a > + * non-empty packet was returned in pkt > + * > + * @return 0 on success, negative error code on failure > + */ > +static int liboapve_encode(AVCodecContext *avctx, AVPacket *avpkt, > + const AVFrame *frame, int *got_packet) { > + ApvEncContext *apv = avctx->priv_data; > + oapv_frm_t *frm = &apv->ifrms.frm[FRM_IDX]; > + oapv_imgb_t *imgb = frm->imgb; > + int ret; > + > + if (avctx->width != frame->width || avctx->height != frame->height || avctx- > >pix_fmt != frame->format) { > + av_log(avctx, AV_LOG_ERROR, "Dimension change is not supported\n"); > + return AVERROR(EINVAL); > + } > + > + av_image_copy((uint8_t **)imgb->a, imgb->s, (const uint8_t **)frame- > >data, frame->linesize, > + frame->format, frame->width, frame->height); > + > + imgb->ts[0] = frame->pts; > + > + frm->group_id = 1; // @todo FIX-ME : need to set properly in case of multi- > frame > + frm->pbu_type = OAPV_PBU_TYPE_PRIMARY_FRAME; > + > + ret = oapve_encode(apv->id, &apv->ifrms, apv->mid, &apv->bitb, &apv- > >stat, NULL); > + if (OAPV_FAILED(ret)) { > + av_log(avctx, AV_LOG_ERROR, "oapve_encode() failed\n"); > + return AVERROR_EXTERNAL; > + } > + > + /* store bitstream */ > + if (OAPV_SUCCEEDED(ret) && apv->stat.write > 0) { > + ret = ff_get_encode_buffer(avctx, avpkt, apv->stat.write - 4, 0); > + if (ret < 0) > + return ret; > + > + // The encoder returns a "Raw bitstream" formated AU, including au_size. > + // Discard it as we only need the access_unit() structure. > + memcpy(avpkt->data, (uint8_t *)apv->bitb.addr + 4, > + apv->stat.write - 4); > + > + avpkt->time_base.num = apv->cdsc.param->fps_num; > + avpkt->time_base.den = apv->cdsc.param->fps_den; > + > + avpkt->pts = avpkt->dts = frame->pts; > + avpkt->flags |= AV_PKT_FLAG_KEY; > + > + ff_side_data_set_encoder_stats(avpkt, apv->qp * FF_QP2LAMBDA, > + NULL, 0, AV_PICTURE_TYPE_I); > + > + *got_packet = 1; > + } > + > + return 0; > +} > + > +/** > + * Destroy the encoder and release all the allocated resources > + * > + * @param avctx codec context > + * @return 0 on success, negative error code on failure */ static > +av_cold int liboapve_close(AVCodecContext *avctx) { > + ApvEncContext *apv = avctx->priv_data; > + > + for (int i = 0; i < apv->num_frames; i++) { > + if (apv->ifrms.frm[i].imgb != NULL) > + apv->ifrms.frm[i].imgb->release(apv->ifrms.frm[i].imgb); > + apv->ifrms.frm[i].imgb = NULL; > + } > + > + if (apv->mid) { > + oapvm_rem_all(apv->mid); > + } > + > + if (apv->id) { > + oapve_delete(apv->id); > + apv->id = NULL; > + } > + > + if (apv->mid) { > + oapvm_delete(apv->mid); > + apv->mid = NULL; > + } > + > + av_freep(&apv->bitb.addr); /* release bitstream buffer */ > + > + return 0; > +} > + > +#define OFFSET(x) offsetof(ApvEncContext, x) #define VE > +AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM > + > +static const enum AVPixelFormat supported_pixel_formats[] = { > + AV_PIX_FMT_YUV422P10, > + AV_PIX_FMT_YUV444P10, > + AV_PIX_FMT_NONE > +}; > + > +static const AVOption liboapv_options[] = { > + { "preset", "Encoding preset for setting encoding speed (optimization level > control)", OFFSET(preset_id), AV_OPT_TYPE_INT, { .i64 = > OAPV_PRESET_DEFAULT }, OAPV_PRESET_FASTEST, OAPV_PRESET_PLACEBO, > VE, .unit = "preset" }, > + { "fastest", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_FASTEST > }, INT_MIN, INT_MAX, VE, .unit = "preset" }, > + { "fast", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_FAST }, > INT_MIN, INT_MAX, VE, .unit = "preset" }, > + { "medium", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = > OAPV_PRESET_MEDIUM }, INT_MIN, INT_MAX, VE, .unit = "preset" }, > + { "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_SLOW }, > INT_MIN, INT_MAX, VE, .unit = "preset" }, > + { "placebo", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = > OAPV_PRESET_PLACEBO }, INT_MIN, INT_MAX, VE, .unit = "preset" }, > + { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = > +OAPV_PRESET_DEFAULT }, INT_MIN, INT_MAX, VE, .unit = "preset" }, > + > + { "qp", "Quantization parameter value for CQP rate control mode", > OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 51, VE }, > + { "oapv-params", "Override the apv configuration using a :-separated list of > key=value parameters", OFFSET(oapv_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, > VE }, > + { NULL } > +}; > + > +static const AVClass liboapve_class = { > + .class_name = "liboapv", > + .item_name = av_default_item_name, > + .option = liboapv_options, > + .version = LIBAVUTIL_VERSION_INT, > +}; > + > +static const FFCodecDefault liboapve_defaults[] = { > + { "b", "0" }, // bitrate in terms of kilo-bits per second (support for bit-rates > from a few hundred Mbps to a few Gbps for 2K, 4K and 8K resolution content) > + { NULL }, > +}; > + > +const FFCodec ff_liboapv_encoder = { > + .p.name = "liboapv", > + .p.long_name = NULL_IF_CONFIG_SMALL("liboapv APV"), > + .p.type = AVMEDIA_TYPE_VIDEO, > + .p.id = AV_CODEC_ID_APV, > + .init = liboapve_init, > + FF_CODEC_ENCODE_CB(liboapve_encode), > + .close = liboapve_close, > + .priv_data_size = sizeof(ApvEncContext), > + .p.priv_class = &liboapve_class, > + .defaults = liboapve_defaults, > + .p.capabilities = AV_CODEC_CAP_OTHER_THREADS | > AV_CODEC_CAP_DR1, > + .p.wrapper_name = "liboapv", > + .p.pix_fmts = supported_pixel_formats, > + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | > FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_NOT_INIT_THREADSAFE, > +}; > -- > 2.49.0 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://protect2.fireeye.com/v1/url?k=c2a62f8e-a3dd8506-c2a7a4c1- > 74fe4860018a-499384c6081a622b&q=1&e=b2c8d30c-5c3a-4ef3-af4f- > bd15f74e89f9&u=https%3A%2F%2Fffmpeg.org%2Fmailman%2Flistinfo%2Fffmp > eg-devel > > To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org > with subject "unsubscribe". _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".
Re: [FFmpeg-devel] [PATCH] avcodec: add APV encoder using liboapv
Dawid Kozinski/Multimedia (PLT) /SRPOL/Staff Engineer/Samsung Electronics Wed, 30 Apr 2025 07:04:40 -0700