Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Dawid Kozinski <d.kozinski@samsung.com>
To: ffmpeg-devel@ffmpeg.org
Cc: Dawid Kozinski <d.kozinski@samsung.com>
Subject: [FFmpeg-devel] [PATCH v1 2/8] avcodec/apv_parser: Added parser implementation for APV format
Date: Wed, 23 Apr 2025 16:12:26 +0200
Message-ID: <20250423141226.1857892-1-d.kozinski@samsung.com> (raw)
In-Reply-To: <CGME20250423141230eucas1p1962c2698d09aced37fa5551493a693b8@eucas1p1.samsung.com>

- Added constants definitions for APV parser
- Provided parsing following APV RFC
- APV parser registration

Signed-off-by: Dawid Kozinski <d.kozinski@samsung.com>
---
 configure               |   2 +
 libavcodec/Makefile     |   2 +
 libavcodec/apv.h        |  93 ++++++++
 libavcodec/apv_parse.c  |  32 +++
 libavcodec/apv_parse.h  |  81 +++++++
 libavcodec/apv_parser.c | 141 +++++++++++
 libavcodec/apv_ps.c     | 503 ++++++++++++++++++++++++++++++++++++++++
 libavcodec/apv_ps.h     | 188 +++++++++++++++
 libavcodec/parsers.c    |   1 +
 9 files changed, 1043 insertions(+)
 create mode 100644 libavcodec/apv.h
 create mode 100644 libavcodec/apv_parse.c
 create mode 100644 libavcodec/apv_parse.h
 create mode 100644 libavcodec/apv_parser.c
 create mode 100644 libavcodec/apv_ps.c
 create mode 100644 libavcodec/apv_ps.h

diff --git a/configure b/configure
index c94b8eac43..294f7e4a9d 100755
--- a/configure
+++ b/configure
@@ -2555,6 +2555,7 @@ CONFIG_EXTRA="
     aandcttables
     ac3dsp
     adts_header
+    apvparse
     atsc_a53
     audio_frame_queue
     audiodsp
@@ -3481,6 +3482,7 @@ vvc_qsv_decoder_select="vvc_mp4toannexb_bsf qsvdec"
 
 # parsers
 aac_parser_select="adts_header mpeg4audio"
+apv_parser_select="apvparse"
 av1_parser_select="cbs_av1"
 evc_parser_select="evcparse"
 ffv1_parser_select="rangecoder"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 7bd1dbec9a..3ae6dd17ea 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -76,6 +76,7 @@ OBJS-$(CONFIG_AANDCTTABLES)            += aandcttab.o
 OBJS-$(CONFIG_AC3DSP)                  += ac3dsp.o ac3.o ac3tab.o
 OBJS-$(CONFIG_ADTS_HEADER)             += adts_header.o mpeg4audio_sample_rates.o
 OBJS-$(CONFIG_AMF)                     += amfenc.o amfdec.o
+OBJS-$(CONFIG_APVPARSE)                += apv_parse.o apv_ps.o
 OBJS-$(CONFIG_AUDIO_FRAME_QUEUE)       += audio_frame_queue.o
 OBJS-$(CONFIG_ATSC_A53)                += atsc_a53.o
 OBJS-$(CONFIG_AUDIODSP)                += audiodsp.o
@@ -1196,6 +1197,7 @@ OBJS-$(CONFIG_AC3_PARSER)              += aac_ac3_parser.o ac3tab.o \
                                           ac3_channel_layout_tab.o
 OBJS-$(CONFIG_ADX_PARSER)              += adx_parser.o
 OBJS-$(CONFIG_AMR_PARSER)              += amr_parser.o
+OBJS-$(CONFIG_APV_PARSER)              += apv_parser.o
 OBJS-$(CONFIG_AV1_PARSER)              += av1_parser.o av1_parse.o
 OBJS-$(CONFIG_AVS2_PARSER)             += avs2.o avs2_parser.o
 OBJS-$(CONFIG_AVS3_PARSER)             += avs3_parser.o
diff --git a/libavcodec/apv.h b/libavcodec/apv.h
new file mode 100644
index 0000000000..f40515440b
--- /dev/null
+++ b/libavcodec/apv.h
@@ -0,0 +1,93 @@
+/*
+ * APV definitions and enums
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_APV_H
+#define AVCODEC_APV_H
+
+// The length field that indicates the length in bytes of the following Frame Data is configured to be of 4 bytes
+// A four-byte length Frame Data Size syntax element, which indicates the size of the Frame Data in bytes, may precede the Frame Data, depending on the application.
+#define APV_AU_SIZE_PREFIX_LENGTH           (4)  /* byte */
+#define APV_PBU_SIZE_PREFIX_LENGTH          (4)  /* byte */
+#define APV_SIGNATURE_LENGTH                (4)  /* byte */
+
+// @deprecated
+#define APV_FRAME_DATA_SIZE_PREFIX_LENGTH   (4)  /* byte */
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-5.3.3
+#define APV_PBU_HEADER_SIZE                 (4)  /* byte */
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-5.3.6
+#define APV_FRAME_INFO_SIZE                 (14)  /* byte */
+
+/* size of macroblock */
+#define APV_LOG2_MB                     (4)
+#define APV_MB                          (1<<APV_LOG2_MB)
+#define APV_MB_W                        (1<<APV_LOG2_MB)
+#define APV_MB_H                        (1<<APV_LOG2_MB)
+#define APV_MB_D                        (APV_MB_W * APV_MB_H)
+
+/* size of block */
+#define APV_LOG2_BLOCK                  (3)
+#define APV_BLOCK                       (1<<APV_LOG2_BLOCK)
+#define APV_BLOCK_W                     (1<<APV_LOG2_BLOCK)
+#define APV_BLOCK_H                     (1<<APV_LOG2_BLOCK)
+#define APV_BLOCK_D                     (APV_BLOCK_W * APV_BLOCK_H)
+
+/* @see WD1 APV spec section 7.3.2.2*/
+#define APV_PREV_DC_DIFF 40
+
+/* size of macroblock */
+enum {
+    APV_MB_WIDTH    = 16,
+    APV_MB_HEIGHT   = 16,
+};
+
+/* Color components */
+enum { 
+    APV_COLOR_COMP_Y    = 0,    /* Y luma */
+    APV_COLOR_COMP_U    = 1,    /* Cb Chroma */
+    APV_COLOR_COMP_V    = 2,    /* Cr Chroma */
+    APV_COLOR_COMP_A    = 3,    /* Alpha */
+    APV_COLOR_COMP_NUM  = 4     /* number of color component */
+};
+
+/* size of block */
+#define LOG2_BLK                   (3)
+#define LOG2_BLK_W                 (3)
+#define LOG2_BLK_H                 (3)
+#define BLK_W                      (1 << LOG2_BLK)
+#define BLK_H                      (1 << LOG2_BLK)
+#define BLK_D                      (BLK_W * BLK_H)
+
+const static uint16_t ScanOrder[BLK_D] =
+{
+    0,    1,    8,   16,    9,    2,    3,   10,
+    17,   24,   32,   25,   18,   11,    4,    5,
+    12,   19,   26,   33,   40,   48,   41,   34,
+    27,   20,   13,    6,    7,   14,   21,   28,
+    35,   42,   49,   56,   57,   50,   43,   36,
+    29,   22,   15,   23,   30,   37,   44,   51,
+    58,   59,   52,   45,   38,   31,   39,   46,
+    53,   60,   61,   54,   47,   55,   62,   63,
+};
+
+#endif // AVCODEC_APV_H
diff --git a/libavcodec/apv_parse.c b/libavcodec/apv_parse.c
new file mode 100644
index 0000000000..c6b16679d9
--- /dev/null
+++ b/libavcodec/apv_parse.c
@@ -0,0 +1,32 @@
+/*
+ * 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 "parser.h"
+
+#include "apv.h"
+#include "apv_parse.h"
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-frame
+int ff_apv_parse_frame_data(GetBitContext *gb, APVFrameData *fd)
+{
+    ff_apv_parse_frame_header(gb, &fd->frame_data_header);
+
+    return 0;
+}
diff --git a/libavcodec/apv_parse.h b/libavcodec/apv_parse.h
new file mode 100644
index 0000000000..78af9d8f89
--- /dev/null
+++ b/libavcodec/apv_parse.h
@@ -0,0 +1,81 @@
+/*
+ * 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
+ */
+
+/**
+ * @file
+ * APV decoder/parser shared code
+ */
+
+#ifndef AVCODEC_APV_PARSE_H
+#define AVCODEC_APV_PARSE_H
+
+#include <stdint.h>
+
+#include "libavutil/log.h"
+#include "apv.h"
+#include "apv_ps.h"
+
+static inline uint32_t apv_read_frame_data_size(const uint8_t *bits, int bits_size, void *logctx)
+{
+    uint32_t frame_data_size = 0;
+
+    if (bits_size < APV_FRAME_DATA_SIZE_PREFIX_LENGTH) {
+        av_log(logctx, AV_LOG_ERROR, "Can't read Frame Data size\n");
+        return 0;
+    }
+
+    frame_data_size = AV_RB32(bits);
+
+    return frame_data_size;
+}
+
+// @see 12.1. Raw bitstream format [https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-12.1]
+static inline uint32_t apv_read_au_size(const uint8_t *bits, int bits_size, void *logctx)
+{
+    uint32_t au_size = 0;
+
+    if (bits_size < APV_AU_SIZE_PREFIX_LENGTH) {
+        av_log(logctx, AV_LOG_ERROR, "Can't read Access Unit size\n");
+        return 0;
+    }
+
+    au_size = AV_RB32(bits);
+
+    return au_size;
+}
+
+static inline uint32_t apv_read_pbu_size(const uint8_t *bits, int bits_size, void *logctx)
+{
+    uint32_t pbu_size = 0;
+
+    if (bits_size < APV_PBU_SIZE_PREFIX_LENGTH) {
+        av_log(logctx, AV_LOG_ERROR, "Can't read PBU (primitive bitstream unit) size\n");
+        return 0;
+    }
+
+    pbu_size = AV_RB32(bits);
+
+    return pbu_size;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-frame
+int ff_apv_parse_frame_data(GetBitContext *gb, APVFrameData *fd);
+
+#endif /* AVCODEC_APV_PARSE_H */
diff --git a/libavcodec/apv_parser.c b/libavcodec/apv_parser.c
new file mode 100644
index 0000000000..cc5b59e205
--- /dev/null
+++ b/libavcodec/apv_parser.c
@@ -0,0 +1,141 @@
+/*
+ * APV format parser
+ *
+ * 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 "parser.h"
+#include "bytestream.h"
+#include "apv.h"
+#include "apv_parse.h"
+
+typedef struct APVParserContext {
+    APVParamSets ps;
+
+    int parsed_extradata;
+} APVParserContext;
+
+/**
+ * @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-12.1
+ * 
+ * Parse APV bitstream
+ *
+ * @param s codec parser context
+ * @param avctx codec context
+ * @param buf buffer with field/frame data
+ * @param buf_size size of the buffer
+ */
+static int parse_apv_bitstream(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t *buf, int buf_size)
+{
+    const uint8_t *data = buf;
+    int data_size = buf_size;
+
+    if (data_size > 0) {
+        int au_size = 0;
+        
+        // Buffer size is not enough for buffer to store Frame Data 4-bytes prefix (length)
+        if (data_size < APV_AU_SIZE_PREFIX_LENGTH)
+            return AVERROR_INVALIDDATA;
+
+        au_size = apv_read_au_size(data, APV_AU_SIZE_PREFIX_LENGTH, avctx);
+
+        if (!au_size || au_size > INT_MAX)
+            return AVERROR_INVALIDDATA;
+
+        data += APV_AU_SIZE_PREFIX_LENGTH;
+        data_size -= APV_AU_SIZE_PREFIX_LENGTH;
+
+        if (data_size < au_size)
+            return AVERROR_INVALIDDATA;
+    }
+    return 0;
+}
+
+// Decoding Frame Data from apvC (APVDecoderConfigurationRecord)
+static int decode_extradata(AVCodecParserContext *s, AVCodecContext *avctx)
+{
+    const uint8_t *data = avctx->extradata;
+    int size = avctx->extradata_size;
+    int ret = 0;
+    if (!data || size <= 0)
+        return -1;
+    
+    return ret;
+}
+
+static int apv_parse(AVCodecParserContext *s, AVCodecContext *avctx,
+                     const uint8_t **poutbuf, int *poutbuf_size,
+                     const uint8_t *buf, int buf_size)
+{
+    int next;
+    int ret;
+    APVParserContext *ctx = s->priv_data;
+
+    s->picture_structure = AV_PICTURE_STRUCTURE_FRAME;
+    s->key_frame = 1;
+
+    if (avctx->extradata && !ctx->parsed_extradata) {
+        decode_extradata(s, avctx);
+        ctx->parsed_extradata = 1;
+    }
+
+    next = buf_size;
+
+    ret = parse_apv_bitstream(s, avctx, buf, buf_size);
+    if(ret < 0) {
+        *poutbuf      = NULL;
+        *poutbuf_size = 0;
+        return buf_size;
+    }
+
+    // poutbuf contains just one Access Unit
+    *poutbuf      = buf;
+    *poutbuf_size = buf_size;
+
+    return next;
+}
+
+static void apv_parser_close(AVCodecParserContext *s)
+{
+    APVParserContext *ctx = s->priv_data;
+
+    if(ctx->ps.frame_data.frame_data_header.tile_info.ColStarts) {
+        free(ctx->ps.frame_data.frame_data_header.tile_info.ColStarts);
+        ctx->ps.frame_data.frame_data_header.tile_info.ColStarts = NULL;
+    }
+
+    if(ctx->ps.frame_data.frame_data_header.tile_info.RowStarts) {
+        free(ctx->ps.frame_data.frame_data_header.tile_info.RowStarts);
+        ctx->ps.frame_data.frame_data_header.tile_info.RowStarts = NULL;
+    }
+    
+    if(ctx->ps.frame_data.frame_data_header.tile_info.tile_size_in_fh) {
+        free(ctx->ps.frame_data.frame_data_header.tile_info.tile_size_in_fh);
+        ctx->ps.frame_data.frame_data_header.tile_info.tile_size_in_fh = NULL;
+    }
+
+    ff_apv_ps_free(&ctx->ps);
+}
+
+const AVCodecParser ff_apv_parser = {
+    .codec_ids      = { AV_CODEC_ID_APV },
+    .priv_data_size = sizeof(APVParserContext),
+    .parser_parse   = apv_parse,
+    .parser_close   = apv_parser_close,
+};
diff --git a/libavcodec/apv_ps.c b/libavcodec/apv_ps.c
new file mode 100644
index 0000000000..a9fa0c8030
--- /dev/null
+++ b/libavcodec/apv_ps.c
@@ -0,0 +1,503 @@
+/*
+ * 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 "golomb.h"
+#include "parser.h"
+#include "apv.h"
+#include "apv_ps.h"
+
+#define ffapv_max(a,b)             \
+({                           \
+    __typeof__ (a) _a = (a); \
+    __typeof__ (b) _b = (b); \
+    _a > _b ? _a : _b;       \
+})
+
+#define ffapv_min(a,b)             \
+({                           \
+    __typeof__ (a) _a = (a); \
+    __typeof__ (b) _b = (b); \
+    _a < _b ? _a : _b;       \
+})
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-arithmetic-operators
+#define ffapv_clip3(min, max, val) ffapv_max( (min), ffapv_min((max), (val)) )
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-5.3.3
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-primitive-bitstream-unit-he
+int ff_apv_parse_pbu_header(GetBitContext *gb, APVPBUHeader *pbuh)
+{
+    pbuh->pbu_type                      = get_bits(gb, 8);
+    pbuh->group_id                      = get_bits(gb, 16);
+    pbuh->reserved_zer_8bits            = get_bits(gb, 8);
+        
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-tile-info
+int ff_apv_tile_info(GetBitContext *gb, const APVFrameDataHeader *fdh, APVTileInfo *ti)
+{
+    // @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-source-decoded-and-output-f
+    int MbWidth = APV_MB_WIDTH;
+    int MbHeight = APV_MB_HEIGHT;
+
+    int FrameWidthInSamplesY;
+    int FrameHeightInSamplesY;
+    int FrameWidthInMbsY;
+    int FrameHeightInMbsY;
+
+    int startMb = 0;
+    int i = 0;
+
+    ti->tile_width_in_mbs = get_bits(gb, 20);
+    ti->tile_height_in_mbs = get_bits(gb, 20);
+
+    FrameWidthInSamplesY = fdh->frame_info.frame_width;
+    FrameHeightInSamplesY = fdh->frame_info.frame_height;
+    FrameWidthInMbsY = ceil( FrameWidthInSamplesY / MbWidth );
+    FrameHeightInMbsY = ceil( FrameHeightInSamplesY / MbHeight );
+
+    if(!ti->ColStarts)
+        free(ti->ColStarts);
+
+    // @todo remember to free it
+    ti->ColStarts = malloc(sizeof(int) * FrameWidthInMbsY);
+
+    for( i = 0; startMb < FrameWidthInMbsY; i++ ) {
+        ti->ColStarts[ i ] = startMb * MbWidth;
+        startMb += ti->tile_width_in_mbs;
+    }
+
+    ti->ColStarts[ i ] = FrameWidthInMbsY * MbWidth;
+    ti->TileCols = i;
+
+    startMb = 0;
+
+    if(!ti->RowStarts)
+        free(ti->RowStarts);
+
+    // @todo remember to free it
+    ti->RowStarts = malloc(sizeof(int) * FrameHeightInMbsY);
+
+    for( i = 0; startMb < FrameHeightInMbsY; i++ ) {
+        ti->RowStarts[ i ] = startMb * MbHeight;
+        startMb += ti->tile_height_in_mbs + 1;
+    }
+
+    ti->RowStarts[ i ] = FrameHeightInMbsY * MbHeight;
+    ti->TileRows = i;
+    ti->NumTiles = ti->TileCols * ti->TileRows;
+
+    if(!ti->tile_size_in_fh)
+        free(ti->tile_size_in_fh);
+
+    // @todo remember to free it
+    ti->tile_size_in_fh = malloc(sizeof(uint32_t) * ti->NumTiles);
+
+    for( i = 0; i < ti->NumTiles ; i++ )
+        ti->tile_size_in_fh[i] = get_bits(gb, 32);
+
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-byte_aligned
+// byte_aligned( ) is specified as follows:
+// — If the current position in the bitstream is on a byte boundary, i.e., the next bit in the bitstream is the first bit in a byte, the return value of byte_aligned( ) is equal to TRUE.
+// — Otherwise, the return value of byte_aligned( ) is equal to FALSE.
+//
+static int byte_aligned(GetBitContext *gb)
+{
+    int bits_count = get_bits_count(gb);
+    if (bits_count % 8)
+        return 1;
+    else
+        return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-byte-alignment
+int ff_apv_byte_alignment(GetBitContext *gb, APVByteAlignemnt *ba)
+{
+    while(!byte_aligned(gb))
+        ba->alignment_bit_equal_to_zero = get_bits1(gb);
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-quantization-matrix
+int ff_apv_quantization_matrix(GetBitContext *gb, int num_comp, APVQuantizationMatrix *qm)
+{
+    for( int cIdx = 0; cIdx < num_comp; cIdx ++ ) {
+        for( int y = 0; y < 8; y ++ ) {
+            for( int x = 0; x < 8; x ++ )
+                qm->q_matrix[ cIdx ][ x ][ y ] = get_bits(gb, 8);
+        }
+    }
+    return 0;
+}
+
+// https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-frame-information
+int ff_apv_parse_frame_info(GetBitContext *gb, APVFrameInfo *frame_info)
+{
+    frame_info->profile_idc                    = get_bits(gb, 8);
+    frame_info->level_idc                      = get_bits(gb, 8);
+    frame_info->band_idc                       = get_bits(gb, 3);
+    frame_info->reserved_zero_5bits            = get_bits(gb, 5);
+    frame_info->frame_width                    = get_bits(gb, 24);
+    frame_info->frame_height                   = get_bits(gb, 24);
+    frame_info->chroma_format_idc              = get_bits(gb, 4);
+    frame_info->bit_depth_minus8               = get_bits(gb, 4);
+    frame_info->capture_time_distance          = get_bits(gb, 8);
+    frame_info->reserved_zero_8bits            = get_bits(gb, 8);
+    
+    return 0;
+}
+
+static int num_component(int chroma_format_idc) {
+    int NumComps = 0;
+    
+    switch (chroma_format_idc)
+    {
+    case 0:
+        NumComps = 1;
+        break;
+    case 2:
+    case 3:
+        NumComps = 3;
+        break;
+    case 4:
+        NumComps = 4;
+        break;
+    
+    default:
+        break;
+    }
+    return NumComps;
+}
+
+static int sub_width_c(int chroma_format_idc) {
+    int SubWidthC = 0;
+    
+    switch (chroma_format_idc)
+    {
+    case 0:
+        SubWidthC = 1;
+        break;
+    case 2:
+        SubWidthC = 2;
+        break;
+    case 3:
+        SubWidthC = 1;
+        break;
+    case 4:
+        SubWidthC = 1;
+        break;
+    
+    default:
+        break;
+    }
+    return SubWidthC;
+}
+
+static int apv_parse_pbu_header(GetBitContext *gb, APVPBUHeader *pbuh)
+{
+    pbuh->pbu_type                      = get_bits(gb, 8);
+    pbuh->group_id                      = get_bits(gb, 16);
+    pbuh->reserved_zer_8bits            = get_bits(gb, 8);
+        
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-frame-header
+
+int ff_apv_parse_frame_header(GetBitContext *gb, APVFrameDataHeader *frame_header)
+{
+    int ret = 0;
+    int NumComps = APV_COLOR_COMP_NUM;
+
+    ret = ff_apv_parse_frame_info(gb, &frame_header->frame_info);
+    
+    frame_header->reserved_zero_8bits = get_bits(gb, 8);
+    frame_header->color_description_present_flag = get_bits(gb, 1);
+
+    if(frame_header->color_description_present_flag) {
+        frame_header->color_primaries = get_bits(gb, 8);
+        frame_header->transfer_characteristics = get_bits(gb, 8);
+        frame_header->matrix_coefficients = get_bits(gb, 8);
+    }
+    
+    frame_header->use_q_matrix = get_bits(gb, 1);
+
+    NumComps = num_component(frame_header->frame_info.chroma_format_idc);
+    if(NumComps == 0) {
+        return -1;
+    }
+    
+    if(frame_header->use_q_matrix)
+        ret = ff_apv_quantization_matrix(gb, NumComps, &frame_header->quantization_matrix);
+
+    ff_apv_tile_info(gb, frame_header, &frame_header->tile_info);
+    frame_header->reserved_zero_8bits_2 = get_bits(gb, 8);
+
+    ff_apv_byte_alignment(gb, &frame_header->byte_alignent);
+
+    return ret;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-process-for-variable-length-
+static int read_vlc(GetBitContext *gb, uint32_t kParam)
+{
+
+    uint32_t symbolValue = 0;
+    uint8_t parseExpGolomb = 1;
+    uint32_t k = kParam;
+    uint32_t stopLoop = 0;
+
+    if( get_bits(gb, 1) == 1 )
+        parseExpGolomb = 0;
+    else {
+        if( get_bits(gb, 1) == 0 ) {
+            symbolValue += ( 1 << k );
+            parseExpGolomb = 0;
+        } else {
+            symbolValue += ( 2 << k );
+            parseExpGolomb = 1;
+        }
+    }
+
+    if( parseExpGolomb ) {
+        do {
+            if( get_bits(gb, 1) == 1 )
+                stopLoop = 1;
+            else {
+                symbolValue += ( 1 << k );
+                k++;
+            }
+        } while( !stopLoop );
+    }
+
+    if( k > 0 )
+        symbolValue += get_bits(gb, k);
+
+    return symbolValue;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-ac-coefficient-coding
+static void ac_coeff_coding( GetBitContext *gb, uint32_t Prev1stAcLevel, int32_t TransCoeff[APV_COLOR_COMP_NUM][APV_MB_WIDTH][APV_MB_HEIGHT], uint32_t x0, uint32_t y0, int log2BlkWidth, int log2BlkHeight, int cIdx )
+{
+    int scanPos = 1;
+    int firstAC = 1;
+    int PrevLevel = Prev1stAcLevel;
+    int PrevRun = 0;
+
+    do {
+        int kParam = ffapv_clip3( 0, 2, PrevRun >> 2 );
+        int coeff_zero_run = read_vlc(gb, kParam); // h(v)
+
+        for( int i = 0; i < coeff_zero_run; i++ ) {
+            int blkPos = ScanOrder[ scanPos ];
+            int xC = blkPos & ( ( 1 << log2BlkWidth ) - 1 );
+            int yC = blkPos >> log2BlkWidth;
+            TransCoeff[ cIdx ][ x0 + xC ][ y0 + yC ] = 0;
+            scanPos++;
+        }
+        PrevRun = coeff_zero_run;
+        if( scanPos < ( 1 << ( log2BlkWidth + log2BlkHeight ) ) ) {
+            int kParam = ffapv_clip3( 0, 4, PrevLevel >> 2 );
+            int abs_ac_coeff_minus1 = read_vlc(gb, kParam);
+
+            uint8_t sign_ac_coeff = get_bits1(gb);
+            int level = ( abs_ac_coeff_minus1 + 1 ) * ( 1 - 2 * sign_ac_coeff );
+            uint16_t blkPos = ScanOrder[ scanPos ];
+            int xC = blkPos & ( ( 1 << log2BlkWidth ) - 1 );
+            int yC = blkPos >> log2BlkWidth;
+            TransCoeff[ cIdx ][ x0 + xC ][ y0 + yC ] = level;
+            scanPos++;
+            PrevLevel = abs_ac_coeff_minus1 + 1;
+            if( firstAC == 1 ) {
+                firstAC = 0;
+                Prev1stAcLevel = PrevLevel;
+            }
+        }
+    } while ( scanPos < ( 1 << ( log2BlkWidth + log2BlkHeight ) ) );
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-macroblock-layer
+static int macroblock_layer( GetBitContext *gb, const APVFrameDataHeader *fdh, uint32_t Prev1stAcLevel,  uint32_t xMb, uint32_t yMb, uint32_t cIdx )
+{
+
+    uint32_t MbWidth = APV_MB_WIDTH;
+    uint32_t MbHeight = APV_MB_HEIGHT;
+
+    // @see 6.2 Source, decoded and output frame formats
+    // @see Table 2 — SubWidthC and SubHeightC values derived from chroma_format_idc
+    uint32_t SubWidthC = (fdh->frame_info.chroma_format_idc == 2) ? 2 : 1;
+    uint32_t SubHeightC = 1;
+
+    // @see 6.2 Source, decoded and output frame formats
+    uint32_t MbWidthC = MbWidth / SubWidthC;
+    uint32_t MbHeightC = MbHeight / SubHeightC;
+
+    uint32_t subW = ( cIdx == 0 ) ? 1 : SubWidthC;
+    uint32_t subH = ( cIdx == 0 ) ? 1 : SubHeightC;
+    uint32_t blkWidth = ( cIdx == 0 ) ? MbWidth : MbWidthC;
+    uint32_t blkHeight = ( cIdx == 0 ) ? MbHeight : MbHeightC;
+
+    uint32_t TrSize = 8;
+
+    // moved from tile_data
+    uint32_t PrevDC = 0;
+    uint32_t PrevDcDiff = APV_PREV_DC_DIFF;
+
+    int32_t TransCoeff[APV_COLOR_COMP_NUM][APV_MB_WIDTH][APV_MB_HEIGHT];
+
+    for( int y = 0; y < blkHeight; y += TrSize ) {
+        for( int x = 0; x < blkWidth; x += TrSize ) {
+
+            int kParam = ffapv_clip3( 0, 5, PrevDcDiff >> 2 );
+            int abs_dc_coeff_diff = read_vlc(gb, kParam); //  h(v)
+            int sign_dc_coeff_diff; // u(1)
+
+            if( abs_dc_coeff_diff )
+                sign_dc_coeff_diff = get_bits1(gb); // u(1)
+
+            TransCoeff[ cIdx ][ xMb / subW + x ][ yMb / subH + y ] = PrevDC + abs_dc_coeff_diff * ( 1 - 2 * sign_dc_coeff_diff );
+            PrevDC = TransCoeff[ cIdx ][ xMb / subW + x ][ yMb / subH + y ];
+            PrevDcDiff = abs_dc_coeff_diff;
+            ac_coeff_coding( gb, Prev1stAcLevel, TransCoeff, xMb / subW + x, yMb / subH + y, log2( TrSize ), log2( TrSize ), cIdx );
+        }
+    }
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-tile-header
+static int tile_header(GetBitContext *gb,  const APVFrameDataHeader *fdh, APVTileHeader *th)
+{
+    int NumComps = num_component(fdh->frame_info.chroma_format_idc);
+    
+    th->tile_header_size = get_bits(gb, 16);
+    th->tile_index = get_bits(gb, 16);
+    
+    for(int i=0; i<NumComps; i++) {
+        th->tile_data_size[i] = get_bits(gb, 32);
+    }
+    
+    for(int i=0; i<NumComps; i++) {
+        th->tile_qp[i] = get_bits(gb, 8);
+    }
+
+    th->reserved_zero_8bits = get_bits(gb, 8);
+    
+    ff_apv_byte_alignment(gb, &th->byte_alignent);
+
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-tile-data
+
+// @param cIdx specifying the color component of the current block,
+static int tile_data(GetBitContext *gb, const APVFrameDataHeader *fdh, APVTile *tile, uint8_t tileIdx, uint8_t cIdx)
+{
+    int MbWidth = APV_MB_WIDTH;
+    int MbHeight = APV_MB_HEIGHT;
+
+    uint32_t x0 = fdh->tile_info.ColStarts[ tileIdx % fdh->tile_info.TileCols ];
+    uint32_t y0 = fdh->tile_info.RowStarts[ tileIdx / fdh->tile_info.TileCols ];
+
+    uint32_t numMbColsInTile = ( fdh->tile_info.ColStarts[ tileIdx % fdh->tile_info.TileCols + 1 ]
+                                 - fdh->tile_info.ColStarts[ tileIdx % fdh->tile_info.TileCols ] ) / MbWidth;
+
+    uint32_t numMbRowsInTile = ( fdh->tile_info.RowStarts[ tileIdx / fdh->tile_info.TileCols + 1 ]
+                                 - fdh->tile_info.RowStarts[ tileIdx / fdh->tile_info.TileCols] ) / MbHeight;
+
+    uint32_t numMbsInTile = numMbColsInTile * numMbRowsInTile;
+
+    uint32_t Prev1stAcLevel = 0;
+    for( int i = 0; i < numMbsInTile; i++ ) {
+        uint32_t xMb = x0 + ( i % numMbColsInTile ) * MbWidth;
+        uint32_t yMb = y0 + ( i / numMbColsInTile ) * MbHeight;
+        macroblock_layer( gb, fdh, Prev1stAcLevel, xMb, yMb, cIdx );
+    }
+    ff_apv_byte_alignment(gb, &tile->tile_data->byte_alignent);
+
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-tile
+int ff_apv_parse_tile(GetBitContext *gb, const APVFrameDataHeader *fdh, APVTile *tile, uint8_t tileIdx)
+{
+    int ret = 0;
+    int NumComps = num_component(fdh->frame_info.chroma_format_idc);
+
+    tile_header(gb, fdh, &tile->tile_header);
+
+    for(int i=0; i<NumComps; i++) {
+        tile_data(gb, fdh, tile, tileIdx, i);
+    }
+
+    return ret;
+}
+
+void ff_apv_ps_free(APVParamSets *ps)
+{
+    APVFrameData* fd = &ps->frame_data;
+    int num_tiles = fd->frame_data_header.tile_info.NumTiles;
+
+    for( int i = 0; i < num_tiles; i++ )
+        free(fd->tiles[i]);
+
+    free(fd->tiles);
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-metadata-payload-syntax
+static int metadata_payload( GetBitContext *gb, uint32_t metadataSize )
+{
+    do {
+        uint16_t size;
+
+        skip_bits(gb, 16);          // u(16)
+
+        size = get_bits(gb, 16);    // u(16)
+
+        skip_bits(gb, size * 8);    // value u(size*8);
+
+    } while (get_bits(gb, 16) != 0xFFFF);
+
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-metadata
+int ff_apv_parse_metadata(GetBitContext *gb, APVFrameData *fd)
+{
+    uint16_t metadata_num = get_bits(gb, 16); // u(16)
+    for(int i = 0; i < metadata_num; i++ ) {
+        uint32_t metadata_size_minus1 = get_bits_long(gb, 32); // u(32)
+        metadata_payload( gb, metadata_size_minus1 + 1 );
+    }
+    return 0;
+}
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-filler
+int ff_apv_parse_filler_data(GetBitContext *gb, APVFrameData *fd)
+{
+    uint8_t ff_byte = 0;
+    while(  get_bits(gb, 8) == 0xFF )
+        ff_byte = 0xff; // equal to 0xFF
+
+    return ff_byte;
+}
diff --git a/libavcodec/apv_ps.h b/libavcodec/apv_ps.h
new file mode 100644
index 0000000000..17809dd6bf
--- /dev/null
+++ b/libavcodec/apv_ps.h
@@ -0,0 +1,188 @@
+/*
+ * 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
+ */
+
+/**
+ * @file
+ * APV decoder/parser shared code
+ */
+
+#ifndef AVCODEC_APV_PS_H
+#define AVCODEC_APV_PS_H
+
+#include <stdint.h>
+
+#include "apv.h"
+#include "get_bits.h"
+
+/* size of block */
+#define APV_LOG2_BLOCK                  (3)
+#define APV_BLOCK                       (1<<APV_LOG2_BLOCK)
+#define APV_BLOCK_W                     (1<<APV_LOG2_BLOCK)
+#define APV_BLOCK_H                     (1<<APV_LOG2_BLOCK)
+#define APV_BLOCK_D                     (APV_BLOCK_W * APV_BLOCK_H)
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-5.3.17
+typedef struct APVByteAlignemnt {
+    uint8_t alignment_bit_equal_to_zero; /* equal to 0*/ // f(1)
+} APVByteAlignemnt;
+
+// The sturcture reflects Tile Header layout
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-5.3.13
+
+// The following descriptors specify the parsing process of each element
+// u(n) - unsigned integer using n bits
+// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first
+typedef struct APVTileHeader {
+    uint16_t tile_header_size;                          // u(16)
+    uint16_t tile_index;                                // u(16)
+
+    uint32_t tile_data_size[APV_COLOR_COMP_NUM];        // u(32)
+
+
+    uint8_t tile_qp[APV_COLOR_COMP_NUM];                // u(8)
+    uint8_t reserved_zero_8bits;                        // u(8)
+    
+    APVByteAlignemnt byte_alignent;
+
+} APVTileHeader;
+
+// The sturcture reflects Tile Info sturcture layout
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-5.3.8
+//
+// The following descriptors specify the parsing process of each element
+// u(n) - unsigned integer using n bits
+// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first
+typedef struct APVTileInfo {
+    uint32_t tile_width_in_mbs;                     // u(20)
+    uint32_t tile_height_in_mbs;                    // u(20)
+    uint8_t  tile_size_present_in_fh_flag;          // u(1)
+    uint32_t *tile_size_in_fh;                      // table of size NumTiles; elements of u(32) type
+
+    uint32_t *ColStarts; // table of size FrameWidthInMbsY
+    uint32_t *RowStarts; // table of size FrameHeightInMbsY
+    uint32_t TileCols;
+    uint32_t TileRows;
+    uint32_t NumTiles;
+
+} APVTileInfo;
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-quantization-matrix
+typedef struct APVQuantizationMatrix {
+    uint8_t q_matrix[3][8][8];
+} APVQuantizationMatrix;
+
+// @see  https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-frame-information
+// 5.3.6. Frame information
+typedef struct APVFrameInfo {
+    uint8_t profile_idc;                             // u(8)
+    uint8_t level_idc;                               // u(8)
+    uint8_t band_idc;                                // u(3)
+    uint8_t reserved_zero_5bits;                     // u(5)
+    uint32_t frame_width;                            // u(24)
+    uint32_t frame_height;                           // u(24)
+    uint8_t chroma_format_idc;                       // u(4)
+    uint8_t bit_depth_minus8;                        // u(4)
+    uint8_t capture_time_distance;                   // u(8)
+    uint16_t reserved_zero_8bits;                    // u(8)
+} APVFrameInfo;
+
+typedef struct APVFrameDataHeader {
+    
+    struct APVFrameInfo frame_info;
+    uint8_t reserved_zero_8bits;                    // u(8)
+
+    uint8_t color_description_present_flag;         // u(1)
+    uint8_t color_primaries;                        // u(8)
+    uint8_t transfer_characteristics;               // u(8)
+    uint8_t matrix_coefficients;                    // u(8)
+
+    uint8_t use_q_matrix;                           // u(1)
+
+    APVQuantizationMatrix quantization_matrix;
+    APVTileInfo tile_info;
+
+    uint8_t reserved_zero_8bits_2;                  // u(8)
+
+    APVByteAlignemnt byte_alignent;
+
+} APVFrameDataHeader;
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#section-5.3.3
+typedef struct APVPBUHeader {
+    uint8_t pbu_type;                               // u(8)
+    uint8_t group_id;                               // u(16)
+    uint8_t reserved_zer_8bits;                     // u(8)
+} APVPBUHeader;
+
+typedef struct APVTileData {
+    uint32_t PrevDc;
+    uint32_t PrevDcDiff;
+    uint32_t numMbColsInTile;
+    uint32_t numMbRowsInTile;
+    uint32_t numMbsInTile;
+    uint32_t Prev1stAcLevel;
+
+    APVByteAlignemnt byte_alignent;
+} APVTileData;
+
+typedef struct APVTile {
+    APVTileHeader tile_header;
+    APVTileData tile_data[3];
+} APVTile;
+
+typedef struct APVFrameData {
+    APVFrameDataHeader frame_data_header;
+    APVTile **tiles; // table of pointers to elements of type APVTile; the size of table is NumTiles
+} APVFrameData;
+
+typedef struct APVParamSets {
+    APVFrameData frame_data;
+} APVParamSets;
+
+// https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-primitive-bitstream-unit-he
+int ff_apv_parse_pbu_header(GetBitContext *gb, APVPBUHeader *fdh);
+
+// https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-frame-header
+int ff_apv_parse_frame_header(GetBitContext *gb, APVFrameDataHeader *fdh);
+
+// https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-frame-information
+int ff_apv_parse_frame_info(GetBitContext *gb, APVFrameInfo *frame_info);
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-frame-information
+int ff_apv_tile_info(GetBitContext *gb, const APVFrameDataHeader *fdh, APVTileInfo *ti);
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-tile
+int ff_apv_parse_tile(GetBitContext *gb, const APVFrameDataHeader *fdh, APVTile *tile, uint8_t tileIdx);
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-byte-alignment
+int ff_apv_byte_alignment(GetBitContext *gb, APVByteAlignemnt *ba);
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-quantization-matrix
+int ff_apv_quantization_matrix(GetBitContext *gb, int num_comp, APVQuantizationMatrix *qm);
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-metadata
+int ff_apv_parse_metadata(GetBitContext *gb, APVFrameData *fd);
+
+// @see https://www.ietf.org/archive/id/draft-lim-apv-04.html#name-filler
+int ff_apv_parse_filler_data(GetBitContext *gb, APVFrameData *fd);
+
+void ff_apv_ps_free(APVParamSets *ps);
+
+#endif /* AVCODEC_APV_PS_H */
diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c
index 5387351fd0..21164f3751 100644
--- a/libavcodec/parsers.c
+++ b/libavcodec/parsers.c
@@ -25,6 +25,7 @@ extern const AVCodecParser ff_aac_latm_parser;
 extern const AVCodecParser ff_ac3_parser;
 extern const AVCodecParser ff_adx_parser;
 extern const AVCodecParser ff_amr_parser;
+extern const AVCodecParser ff_apv_parser;
 extern const AVCodecParser ff_av1_parser;
 extern const AVCodecParser ff_avs2_parser;
 extern const AVCodecParser ff_avs3_parser;
-- 
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".

       reply	other threads:[~2025-04-23 14:12 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20250423141230eucas1p1962c2698d09aced37fa5551493a693b8@eucas1p1.samsung.com>
2025-04-23 14:12 ` Dawid Kozinski [this message]
2025-04-23 14:27   ` James Almer
2025-04-23 21:14   ` Mark Thompson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250423141226.1857892-1-d.kozinski@samsung.com \
    --to=d.kozinski@samsung.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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