* [FFmpeg-devel] [PATCH v1 8/8] avcodec/apv_decoder: Provided support for APV decoder
[not found] <CGME20250423141345eucas1p1784ac4af60429d8d8dbc0c7018fd9fc0@eucas1p1.samsung.com>
@ 2025-04-23 14:13 ` Dawid Kozinski
2025-04-24 19:23 ` Mark Thompson
0 siblings, 1 reply; 2+ messages in thread
From: Dawid Kozinski @ 2025-04-23 14:13 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Dawid Kozinski
- Added APV decoder wrapper
- Changes in project configuration file and libavcodec Makefile
- Added documentation for APV decoder wrapper
Signed-off-by: Dawid Kozinski <d.kozinski@samsung.com>
---
configure | 1 +
doc/decoders.texi | 27 ++
libavcodec/Makefile | 1 +
libavcodec/libapvdec.c | 560 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 589 insertions(+)
create mode 100644 libavcodec/libapvdec.c
diff --git a/configure b/configure
index fa125d383d..8c4a829035 100755
--- a/configure
+++ b/configure
@@ -3562,6 +3562,7 @@ libaom_av1_decoder_deps="libaom"
libaom_av1_encoder_deps="libaom"
libaom_av1_encoder_select="extract_extradata_bsf dovi_rpuenc"
libapv_encoder_deps="liboapv"
+libapv_decoder_deps="liboapv"
libaribb24_decoder_deps="libaribb24"
libaribcaption_decoder_deps="libaribcaption"
libcelt_decoder_deps="libcelt"
diff --git a/doc/decoders.texi b/doc/decoders.texi
index 17bb361ffa..ffe576db77 100644
--- a/doc/decoders.texi
+++ b/doc/decoders.texi
@@ -397,6 +397,33 @@ without this library.
@chapter Subtitles Decoders
@c man begin SUBTILES DECODERS
+@section liboapv
+
+Advanced Professional Video codec decoder wrapper.
+
+This decoder 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 decoder options are mapped to FFmpeg global codec options,
+while unique decoder 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://github.com/AcademySoftwareFoundation/openapv}.
+
+@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 get a more accurate and extensive documentation of the liboapv options,
+invoke the command @code{apv_app_dec --help} or consult the liboapv documentation.
+@end float
+
@section libaribb24
ARIB STD-B24 caption decoder.
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 7350f4ce07..d172e554ae 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1130,6 +1130,7 @@ OBJS-$(CONFIG_PCM_MULAW_AT_ENCODER) += audiotoolboxenc.o
OBJS-$(CONFIG_LIBAOM_AV1_DECODER) += libaomdec.o libaom.o
OBJS-$(CONFIG_LIBAOM_AV1_ENCODER) += libaomenc.o libaom.o
OBJS-$(CONFIG_LIBAPV_ENCODER) += libapvenc.o apv_imgb.o
+OBJS-$(CONFIG_LIBAPV_DECODER) += libapvdec.o apv_imgb.o
OBJS-$(CONFIG_LIBARIBB24_DECODER) += libaribb24.o ass.o
OBJS-$(CONFIG_LIBARIBCAPTION_DECODER) += libaribcaption.o ass.o
OBJS-$(CONFIG_LIBCELT_DECODER) += libcelt_dec.o
diff --git a/libavcodec/libapvdec.c b/libavcodec/libapvdec.c
new file mode 100644
index 0000000000..8bf2a12605
--- /dev/null
+++ b/libavcodec/libapvdec.c
@@ -0,0 +1,560 @@
+/*
+ * APV (Advanced Professional Video codec) decoding using APV codec library (liboapv)
+ *
+ * Copyright (C) 2025 Dawid Kozinski <d.kozinski@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 <float.h>
+#include <stdlib.h>
+
+
+#include <oapv/oapv.h>
+
+#include "libavutil/internal.h"
+#include "libavutil/common.h"
+#include "libavutil/opt.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/pixfmt.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/cpu.h"
+#include "libavutil/container_fifo.h"
+
+#include "avcodec.h"
+#include "internal.h"
+#include "packet_internal.h"
+#include "codec_internal.h"
+#include "profiles.h"
+#include "decode.h"
+#include "apv.h"
+#include "apv_imgb.h"
+
+/**
+ * The structure stores all the states associated with the instance of APV decoder
+ */
+typedef struct ApvDecContext {
+ const AVClass *class;
+
+ oapvd_t id; // apvd instance identifier @see apvd_t.h
+ oapvd_cdesc_t cdsc; // decoding parameters @see apvd_t.h
+
+ oapvm_t mid; // OAPV metadata container
+
+ int hash; // embed picture signature (HASH) for conformance checking in decoding
+
+ int output_depth;
+ int output_csp;
+
+ struct AVContainerFifo *output_fifo;
+ AVFrame* frames[OAPV_MAX_NUM_FRAMES];
+
+ int frames_count;
+ int total_frames_count;
+ int au_count;
+
+ AVPacket *pkt; // frame data
+} ApvDecContext;
+
+/**
+ * The function populates the apvd_cdsc structure.
+ * apvd_cdsc contains all decoder parameters that should be initialized before its use.
+ *
+ * @param[in] avctx codec context
+ * @param[out] cdsc contains all decoder parameters that should be initialized before its use
+ *
+ */
+static void get_conf(AVCodecContext *avctx, oapvd_cdesc_t *cdsc)
+{
+ /* clear apvd_cdsc structure */
+ memset(cdsc, 0, sizeof(oapvd_cdesc_t));
+
+ /* init apvd_cdsc structure */
+ cdsc->threads = OAPV_CDESC_THREADS_AUTO;
+}
+
+static int set_extra_config(AVCodecContext *avctx, oapvd_t id, ApvDecContext *ctx)
+{
+ int ret = 0, size, value;
+
+ if(ctx->hash) {
+ size = 4;
+ value = 1;
+ ret = oapvd_config(id, OAPV_CFG_SET_USE_FRM_HASH, &value, &size);
+ if (OAPV_FAILED(ret)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set config for using frame hash\n");
+ return AVERROR_EXTERNAL;
+ }
+ }
+ return ret;
+}
+
+/**
+ * @param[in] info the structure that stores information of bitstream
+ * @param[out] avctx codec context
+ * @return 0 on success, negative value on failure
+ */
+static int export_stream_params(const oapv_au_info_t* aui, AVCodecContext *avctx)
+{
+ avctx->width = aui->frm_info->w;
+ avctx->height = aui->frm_info->h;
+
+ switch(aui->frm_info->cs) {
+ case OAPV_CS_SET(OAPV_CF_YCBCR422, 10, 0): // profile 33
+ avctx->pix_fmt = AV_PIX_FMT_YUV422P10LE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR422, 10, 1):
+ avctx->pix_fmt = AV_PIX_FMT_YUV422P10BE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR422, 12, 0): // profile 44
+ avctx->pix_fmt = AV_PIX_FMT_YUV422P12LE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR422, 12, 1):
+ avctx->pix_fmt = AV_PIX_FMT_YUV422P12BE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR444, 10, 0): // profile 55
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P10LE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR444, 10, 1):
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P10BE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR444, 12, 0): // profile 66
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P12LE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR444, 12, 1):
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P12BE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR4444, 10, 0): // profile 77
+ avctx->pix_fmt = AV_PIX_FMT_YUVA444P10LE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR4444, 10, 1):
+ avctx->pix_fmt = AV_PIX_FMT_YUVA444P10BE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR4444, 12, 0): // profile 88
+ avctx->pix_fmt = AV_PIX_FMT_YUVA444P12LE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR4444, 12, 1):
+ avctx->pix_fmt = AV_PIX_FMT_YUVA444P12BE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR400, 10, 0): // profile 99
+ avctx->pix_fmt = AV_PIX_FMT_GRAY10LE;
+ break;
+ case OAPV_CS_SET(OAPV_CF_YCBCR400, 10, 1):
+ avctx->pix_fmt = AV_PIX_FMT_GRAY10BE;
+ break;
+ default:
+ av_log(avctx, AV_LOG_ERROR, "Unknown color space\n");
+ avctx->pix_fmt = AV_PIX_FMT_NONE;
+ return AVERROR_INVALIDDATA;
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Copy image in imgb to frame.
+ *
+ * @param avctx codec context
+ * @param[in] imgb
+ * @param[out] frame
+ * @return 0 on success, negative value on failure
+ */
+static int libapvd_image_copy(struct AVCodecContext *avctx, oapv_imgb_t *imgb, struct AVFrame *frame)
+{
+ int ret;
+
+ if (imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR422, 10, 0) && // profile 33
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR422, 10, 1) && // profile 33
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR422, 12, 0) && // profile 44
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR422, 12, 1) && // profile 44
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR444, 10, 0) && // profile 55
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR444, 10, 1) && // profile 55
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR444, 12, 0) && // profile 66
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR444, 12, 1) && // profile 66
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR4444, 10, 0) && // profile 77
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR4444, 10, 1) && // profile 77
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR4444, 12, 0) && // profile 88
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR4444, 12, 1) && // profile 88
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR400, 10, 0) && // profile 99
+ imgb->cs != OAPV_CS_SET(OAPV_CF_YCBCR400, 10, 1)) { // profile 99
+ av_log(avctx, AV_LOG_ERROR, "Not supported pixel format: %s\n", av_get_pix_fmt_name(avctx->pix_fmt));
+
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (imgb->w[0] != avctx->width || imgb->h[0] != avctx->height) { // stream resolution changed
+ if (ff_set_dimensions(avctx, imgb->w[0], imgb->h[0]) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot set new dimension\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ if (ret = ff_get_buffer(avctx, frame, 0) < 0)
+ return ret;
+
+ av_image_copy(frame->data, frame->linesize, (const uint8_t **)imgb->a,
+ imgb->s, avctx->pix_fmt,
+ imgb->w[0], imgb->h[0]);
+
+ return 0;
+}
+
+/**
+ * Initialize decoder
+ * Create a decoder instance and allocate all the needed resources
+ *
+ * @param avctx codec context
+ * @return 0 on success, negative error code on failure
+ */
+static av_cold int libapvd_init(AVCodecContext *avctx)
+{
+ ApvDecContext *apvctx = avctx->priv_data;
+ oapvd_cdesc_t *cdsc = &(apvctx->cdsc);
+ int ret = 0;
+
+ /* read configurations from AVCodecContext and populate the apvd_cdsc structure */
+ get_conf(avctx, cdsc);
+
+ /* create decoder instance */
+ apvctx->id = oapvd_create(&(apvctx->cdsc), NULL);
+ if (apvctx->id == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot create apvd decoder\n");
+ return AVERROR_EXTERNAL;
+ }
+
+ /* create metadata container */
+ apvctx->mid = oapvm_create(&ret);
+ if(OAPV_FAILED(ret)) {
+ av_log(avctx, AV_LOG_ERROR, "ERROR: cannot create OAPV metadata container (err=%d)\n", ret);
+ return AVERROR_EXTERNAL;
+ }
+
+ if ((ret = set_extra_config(avctx, apvctx->id, apvctx)) != 0) {
+ av_log(avctx, AV_LOG_ERROR, "Cannot set extra configuration\n");
+ return AVERROR(EINVAL);
+ }
+
+ apvctx->pkt = av_packet_alloc();
+
+ // Allocate an AVContainerFifo instance for AVFrames
+ apvctx->output_fifo = av_container_fifo_alloc_avframe(0);
+ if (!apvctx->output_fifo)
+ return AVERROR(ENOMEM);
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(apvctx->frames); i++) {
+ apvctx->frames[i] = NULL;
+ }
+
+ apvctx->frames_count = 0;
+ apvctx->total_frames_count = 0;
+ apvctx->au_count = 0;
+
+ return 0;
+}
+
+/**
+ * Decode frame with decoupled packet/frame dataflow
+ *
+ * @param avctx codec context
+ * @param[out] frame decoded frame
+ *
+ * @return 0 on success, negative error code on failure
+ */
+static int libapvd_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+ ApvDecContext *apvctx = avctx->priv_data;
+ AVPacket *pkt = apvctx->pkt;
+ int ret = 0;
+
+ uint8_t *bs_buf = NULL;
+ uint32_t bs_buf_size = 0;
+
+ oapvd_stat_t stat;
+ oapv_bitb_t bitb;
+ oapv_frms_t ofrms;
+ oapv_imgb_t *imgb_w = NULL;
+ oapv_imgb_t *imgb_o = NULL;
+ oapv_frm_t *frm = NULL;
+
+ oapv_au_info_t aui;
+ oapv_frm_info_t *finfo = NULL;
+
+ AVPacket* pkt_fd; // encoded frame data
+
+ if (av_container_fifo_can_read(apvctx->output_fifo))
+ goto do_output;
+
+ for(int i =0; i<apvctx->frames_count;i++ ) {
+ av_frame_unref(apvctx->frames[i]);
+ apvctx->frames_count = 0;
+ }
+
+ // frame data (input data)
+ ret = ff_decode_get_packet(avctx, pkt);
+ if (ret < 0 && ret != AVERROR_EOF) {
+ av_packet_unref(pkt);
+ return ret;
+ }
+
+ if (pkt->size <= 0) {
+ av_packet_unref(pkt);
+ return ret;
+ }
+
+ memset(&ofrms, 0, sizeof(oapv_frms_t));
+ memset(&aui, 0, sizeof(oapv_au_info_t));
+
+ pkt_fd = av_packet_clone(pkt);
+ av_packet_unref(pkt);
+
+ bs_buf = pkt_fd->data + APV_AU_SIZE_PREFIX_LENGTH;
+ bs_buf_size = pkt_fd->size - APV_AU_SIZE_PREFIX_LENGTH;
+
+ if (OAPV_FAILED(oapvd_info(bs_buf, bs_buf_size, &aui)))
+ {
+ av_log(avctx, AV_LOG_ERROR, "Invalid bitstream\n");
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+
+ if ((ret = export_stream_params(&aui, avctx)) != 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to export stream params\n");
+ goto end;
+ }
+
+ /* create decoding frame buffers */
+ ofrms.num_frms = aui.num_frms;
+ for(int i = 0; i < ofrms.num_frms; i++) {
+
+ finfo = &aui.frm_info[i];
+
+ if(apvctx->output_csp == 1) {
+ ofrms.frm[i].imgb = apv_imgb_create(finfo->w, finfo->h, OAPV_CS_SET(OAPV_CF_PLANAR2, 10, 0), avctx);
+ } else {
+ ofrms.frm[i].imgb = apv_imgb_create(finfo->w, finfo->h, finfo->cs, avctx);
+ }
+
+ if(ofrms.frm[i].imgb == NULL) {
+ av_log(avctx, AV_LOG_ERROR, "cannot allocate image buffer (w:%d, h:%d, cs:%d)\n",
+ finfo->w, finfo->h, finfo->cs);
+
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+ }
+
+ if(apvctx->output_depth == 0) {
+ apvctx->output_depth = OAPV_CS_GET_BIT_DEPTH(finfo->cs);
+ }
+
+ /* main decoding block */
+ bitb.addr = bs_buf;
+ bitb.ssize = bs_buf_size;
+ memset(&stat, 0, sizeof(oapvd_stat_t));
+
+ ret = oapvd_decode(apvctx->id, &bitb, &ofrms, apvctx->mid, &stat);
+ if(OAPV_FAILED(ret)) {
+ av_log(avctx, AV_LOG_ERROR,"failed to decode bitstream\n");
+
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+ if(stat.read != bs_buf_size) {
+ av_log(avctx, AV_LOG_ERROR,"\t=> different reading of bitstream (in:%d, read:%d)\n",
+ bs_buf_size, stat.read);
+ }
+
+ /* Testing of metadata reading */
+ if(apvctx->mid) {
+ oapvm_payload_t *pld = NULL; // metadata payload
+ int num_plds = 0; // number of metadata payload
+
+ ret = oapvm_get_all(apvctx->mid, NULL, &num_plds);
+
+ if(OAPV_FAILED(ret)) {
+ av_log(avctx, AV_LOG_ERROR,"failed to read metadata\n");
+
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+ if(num_plds > 0) {
+ pld = malloc(sizeof(oapvm_payload_t) * num_plds);
+ ret = oapvm_get_all(apvctx->mid, pld, &num_plds);
+ if(OAPV_FAILED(ret)) {
+ av_log(avctx, AV_LOG_ERROR,"failed to read metadata\n");
+
+ if(pld != NULL)
+ free(pld);
+
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+ }
+ if(pld != NULL)
+ free(pld);
+ }
+
+ /* Write decoded frames into AVFrame objects */
+ for(int i = 0; i < ofrms.num_frms; i++) {
+ frm = &ofrms.frm[i];
+ if(OAPV_CS_GET_BIT_DEPTH(frm->imgb->cs) != apvctx->output_depth) {
+ if(imgb_w == NULL) {
+ imgb_w = apv_imgb_create(frm->imgb->w[0], frm->imgb->h[0],
+ OAPV_CS_SET(OAPV_CS_GET_FORMAT(frm->imgb->cs), apvctx->output_depth, 0), avctx);
+ if(imgb_w == NULL) {
+ av_log(avctx, AV_LOG_ERROR,"cannot allocate image buffer (w:%d, h:%d, cs:%d)\n",
+ frm->imgb->w[0], frm->imgb->h[0], frm->imgb->cs);
+
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+ }
+ apv_imgb_cpy(imgb_w, frm->imgb, avctx);
+
+ imgb_o = imgb_w;
+ }
+ else {
+ imgb_o = frm->imgb;
+ }
+
+ if(apvctx->frames[i] == NULL) {
+ apvctx->frames[i] = av_frame_alloc();
+ }
+
+ /* Copy decoded image into AVFrame object */
+ ret = libapvd_image_copy(avctx, imgb_o, apvctx->frames[i]);
+ if(ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Image copying error\n");
+ av_frame_unref(apvctx->frames[i]);
+
+ goto end;
+ }
+
+ /* Use ff_decode_frame_props_from_pkt() to fill frame properties */
+ ret = ff_decode_frame_props_from_pkt(avctx, apvctx->frames[i], pkt_fd);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "ff_decode_frame_props_from_pkt error\n");
+ av_frame_unref(apvctx->frames[i]);
+
+ goto end;
+ }
+
+ if (pkt_fd->flags & AV_PKT_FLAG_KEY) {
+ apvctx->frames[i]->pict_type = AV_PICTURE_TYPE_I;
+ apvctx->frames[i]->flags |= AV_FRAME_FLAG_KEY;
+ }
+
+ apvctx->frames_count++;
+
+ /* Write the AVFrame data to the FIFO */
+ ret = av_container_fifo_write(apvctx->output_fifo, apvctx->frames[i], AV_CONTAINER_FIFO_FLAG_REF);
+ }
+ apvctx->total_frames_count += apvctx->frames_count;
+ apvctx->au_count++;
+
+end:
+ av_packet_unref(pkt_fd);
+
+ for(int i = 0; i < ofrms.num_frms; i++) {
+ if(ofrms.frm[i].imgb != NULL) {
+ ofrms.frm[i].imgb->release(ofrms.frm[i].imgb);
+ ofrms.frm[i].imgb = NULL;
+ }
+ }
+ if (imgb_w) {
+ imgb_w->release(imgb_w);
+ imgb_w = NULL;
+ }
+
+ imgb_o = NULL;
+
+ if (av_container_fifo_can_read(apvctx->output_fifo))
+ goto do_output;
+
+ return AVERROR(EAGAIN);
+
+do_output:
+ /* Read the next available object from the FIFO into frame */
+ if (av_container_fifo_read(apvctx->output_fifo, frame, 0) >= 0) {
+ return 0;
+ }
+ return 0;
+}
+
+/**
+ * Destroy decoder
+ *
+ * @param avctx codec context
+ * @return 0 on success
+ */
+static av_cold int libapvd_close(AVCodecContext *avctx)
+{
+ ApvDecContext *apvctx = avctx->priv_data;
+ if (apvctx->id) {
+ oapvd_delete(apvctx->id);
+ apvctx->id = NULL;
+ }
+
+ if (apvctx->mid) {
+ oapvm_rem_all(apvctx->mid);
+ oapvm_delete(apvctx->mid);
+ apvctx->mid = NULL;
+ }
+
+ av_packet_free(&apvctx->pkt);
+
+ av_container_fifo_free(&apvctx->output_fifo);
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(apvctx->frames); i++) {
+ av_frame_free(&apvctx->frames[i]);
+ }
+
+ return 0;
+}
+
+#define OFFSET(x) offsetof(ApvDecContext, x)
+#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+
+// Consider using following options (./ffmpeg --help encoder=liboapv)
+//
+static const AVOption libapvd_options[] = {
+ { "output_csp", "Color space", OFFSET(output_csp),AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD },
+ { "output_depth", "Color space", OFFSET(output_depth),AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD },
+ { NULL }
+};
+
+static const AVClass libapvd_class = {
+ .class_name = "libapvd",
+ .item_name = av_default_item_name,
+ .option = libapvd_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+const FFCodec ff_libapv_decoder = {
+ .p.name = "apv",
+ .p.long_name = NULL_IF_CONFIG_SMALL("APV / Advanced Professional Video"),
+ .p.type = AVMEDIA_TYPE_VIDEO,
+ .p.id = AV_CODEC_ID_APV,
+ .init = libapvd_init,
+ FF_CODEC_RECEIVE_FRAME_CB(libapvd_receive_frame),
+ .close = libapvd_close,
+ .priv_data_size = sizeof(ApvDecContext),
+ .p.priv_class = &libapvd_class,
+ .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_AVOID_PROBING,
+ .p.wrapper_name = "libapvd",
+ .p.profiles = NULL_IF_CONFIG_SMALL(ff_apv_profiles),
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_NOT_INIT_THREADSAFE | FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_SETS_FRAME_PROPS
+};
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [FFmpeg-devel] [PATCH v1 8/8] avcodec/apv_decoder: Provided support for APV decoder
2025-04-23 14:13 ` [FFmpeg-devel] [PATCH v1 8/8] avcodec/apv_decoder: Provided support for APV decoder Dawid Kozinski
@ 2025-04-24 19:23 ` Mark Thompson
0 siblings, 0 replies; 2+ messages in thread
From: Mark Thompson @ 2025-04-24 19:23 UTC (permalink / raw)
To: ffmpeg-devel
On 23/04/2025 15:13, Dawid Kozinski wrote:
> - Added APV decoder wrapper
> - Changes in project configuration file and libavcodec Makefile
> - Added documentation for APV decoder wrapper
>
> Signed-off-by: Dawid Kozinski <d.kozinski@samsung.com>
> ---
> configure | 1 +
> doc/decoders.texi | 27 ++
> libavcodec/Makefile | 1 +
> libavcodec/libapvdec.c | 560 +++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 589 insertions(+)
> create mode 100644 libavcodec/libapvdec.c
>
> ...
This is asking the decoder library to decode all of the frames (primary/non-primary/preview/depth/alpha) found in the access unit, putting the resulting frames in a fifo, and then outputting them one at a time to receive_frame.
What is the aim there and what does the user need to do to achieve it? For typical existing lavc users (such as the ffmpeg utility) this seems likely to be very confusing, as all of the frames will be bunched together in the same stream even though they don't have the same meaning or (likely) the same properties.
For my decoder implementation I am currently outputting only the primary frame, and would appreciate if you have any thoughts on what the right thing to do if there are multiple frames in the access unit is.
I considered decoding an alpha frame and merging it with the primary frame to form a YUVA422P10 frame, but this seemed fragile as the specification places no constraints on the alpha frame (e.g. no requirement that it is 4:0:0 and has the same dimensions as the primary frame) so I decided against including it.
For the other types I have no thoughts on what might be useful and therefore currently ignore them.
Thanks,
- Mark
PS: Are there any official samples with multiple frames? Examples which I didn't make myself would be appreciated for test purposes.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2025-04-24 19:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <CGME20250423141345eucas1p1784ac4af60429d8d8dbc0c7018fd9fc0@eucas1p1.samsung.com>
2025-04-23 14:13 ` [FFmpeg-devel] [PATCH v1 8/8] avcodec/apv_decoder: Provided support for APV decoder Dawid Kozinski
2025-04-24 19:23 ` Mark Thompson
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git