* [FFmpeg-devel] [PATCH 1/2] avcodec/ffv1: split off and share frame header parsing code
@ 2025-02-03 2:16 James Almer
2025-02-03 2:16 ` [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser James Almer
2025-02-06 15:49 ` [FFmpeg-devel] [PATCH 1/2] avcodec/ffv1: split off and share frame header parsing code Michael Niedermayer
0 siblings, 2 replies; 7+ messages in thread
From: James Almer @ 2025-02-03 2:16 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavcodec/Makefile | 4 +-
libavcodec/ffv1.c | 14 +-
libavcodec/ffv1.h | 35 ++-
libavcodec/ffv1_parse.c | 410 +++++++++++++++++++++++++++++++++++
libavcodec/ffv1dec.c | 459 +++-------------------------------------
libavcodec/ffv1enc.c | 14 +-
6 files changed, 491 insertions(+), 445 deletions(-)
create mode 100644 libavcodec/ffv1_parse.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index a3ef11a258..44bb34182a 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -368,8 +368,8 @@ OBJS-$(CONFIG_EVRC_DECODER) += evrcdec.o acelp_vectors.o lsp.o
OBJS-$(CONFIG_EXR_DECODER) += exr.o exrdsp.o half2float.o
OBJS-$(CONFIG_EXR_ENCODER) += exrenc.o float2half.o
OBJS-$(CONFIG_FASTAUDIO_DECODER) += fastaudio.o
-OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1.o
-OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o
+OBJS-$(CONFIG_FFV1_DECODER) += ffv1dec.o ffv1_parse.o ffv1.o
+OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1_parse.o ffv1.o
OBJS-$(CONFIG_FFV1_VULKAN_ENCODER) += ffv1enc.o ffv1.o ffv1enc_vulkan.o
OBJS-$(CONFIG_FFWAVESYNTH_DECODER) += ffwavesynth.o
OBJS-$(CONFIG_FIC_DECODER) += fic.o
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index f303ed769f..54c2e7a8c6 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -33,10 +33,8 @@
#include "ffv1.h"
#include "libavutil/refstruct.h"
-av_cold int ff_ffv1_common_init(AVCodecContext *avctx)
+av_cold int ff_ffv1_common_init(AVCodecContext *avctx, FFV1Context *s)
{
- FFV1Context *s = avctx->priv_data;
-
if (!avctx->width || !avctx->height)
return AVERROR_INVALIDDATA;
@@ -221,10 +219,13 @@ void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1SliceContext *sc)
}
}
+int ff_ffv1_get_symbol(RangeCoder *c, uint8_t *state, int is_signed)
+{
+ return get_symbol_inline(c, state, is_signed);
+}
-av_cold int ff_ffv1_close(AVCodecContext *avctx)
+av_cold void ff_ffv1_close(FFV1Context *s)
{
- FFV1Context *s = avctx->priv_data;
int i, j;
for (j = 0; j < s->max_slice_count; j++) {
@@ -238,7 +239,6 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
av_refstruct_unref(&s->slice_damaged);
- av_freep(&avctx->stats_out);
for (j = 0; j < s->quant_table_count; j++) {
av_freep(&s->initial_states[j]);
for (i = 0; i < s->max_slice_count; i++) {
@@ -249,6 +249,4 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
}
av_freep(&s->slices);
-
- return 0;
}
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 419c53093f..583696a36e 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -28,6 +28,7 @@
* FF Video Codec 1 (a lossless codec)
*/
+#include "libavutil/attributes.h"
#include "avcodec.h"
#include "get_bits.h"
#include "mathops.h"
@@ -169,15 +170,20 @@ typedef struct FFV1Context {
uint8_t frame_damaged;
} FFV1Context;
-int ff_ffv1_common_init(AVCodecContext *avctx);
+int ff_ffv1_common_init(AVCodecContext *avctx, FFV1Context *s);
int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1SliceContext *sc);
int ff_ffv1_init_slices_state(FFV1Context *f);
int ff_ffv1_init_slice_contexts(FFV1Context *f);
PlaneContext *ff_ffv1_planes_alloc(void);
int ff_ffv1_allocate_initial_states(FFV1Context *f);
void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1SliceContext *sc);
-int ff_ffv1_close(AVCodecContext *avctx);
+void ff_ffv1_close(FFV1Context *s);
int ff_need_new_slices(int width, int num_h_slices, int chroma_shift);
+int ff_ffv1_parse_header(FFV1Context *f, RangeCoder *c, uint8_t *state);
+int ff_ffv1_read_extra_header(FFV1Context *f);
+int ff_ffv1_read_quant_tables(RangeCoder *c,
+ int16_t quant_table[MAX_CONTEXT_INPUTS][256]);
+int ff_ffv1_get_symbol(RangeCoder *c, uint8_t *state, int is_signed);
/**
* This is intended for both width and height
@@ -223,4 +229,29 @@ static inline void update_vlc_state(VlcState *const state, const int v)
state->count = count;
}
+
+static inline av_flatten int get_symbol_inline(RangeCoder *c, uint8_t *state,
+ int is_signed)
+{
+ if (get_rac(c, state + 0))
+ return 0;
+ else {
+ int e;
+ unsigned a;
+ e = 0;
+ while (get_rac(c, state + 1 + FFMIN(e, 9))) { // 1..10
+ e++;
+ if (e > 31)
+ return AVERROR_INVALIDDATA;
+ }
+
+ a = 1;
+ for (int i = e - 1; i >= 0; i--)
+ a += a + get_rac(c, state + 22 + FFMIN(i, 9)); // 22..31
+
+ e = -(is_signed && get_rac(c, state + 11 + FFMIN(e, 10))); // 11..21
+ return (a ^ e) - e;
+ }
+}
+
#endif /* AVCODEC_FFV1_H */
diff --git a/libavcodec/ffv1_parse.c b/libavcodec/ffv1_parse.c
new file mode 100644
index 0000000000..81224df214
--- /dev/null
+++ b/libavcodec/ffv1_parse.c
@@ -0,0 +1,410 @@
+/*
+ * 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 "libavutil/crc.h"
+#include "libavutil/mem.h"
+#include "libavutil/pixdesc.h"
+#include "rangecoder.h"
+#include "ffv1.h"
+
+static int read_quant_table(RangeCoder *c, int16_t *quant_table, int scale)
+{
+ int v;
+ int i = 0;
+ uint8_t state[CONTEXT_SIZE];
+
+ memset(state, 128, sizeof(state));
+
+ for (v = 0; i < 128; v++) {
+ unsigned len = ff_ffv1_get_symbol(c, state, 0) + 1U;
+
+ if (len > 128 - i || !len)
+ return AVERROR_INVALIDDATA;
+
+ while (len--) {
+ quant_table[i] = scale * v;
+ i++;
+ }
+ }
+
+ for (i = 1; i < 128; i++)
+ quant_table[256 - i] = -quant_table[i];
+ quant_table[128] = -quant_table[127];
+
+ return 2 * v - 1;
+}
+
+int ff_ffv1_read_quant_tables(RangeCoder *c,
+ int16_t quant_table[MAX_CONTEXT_INPUTS][256])
+{
+ int i;
+ int context_count = 1;
+
+ for (i = 0; i < 5; i++) {
+ int ret = read_quant_table(c, quant_table[i], context_count);
+ if (ret < 0)
+ return ret;
+ context_count *= ret;
+ if (context_count > 32768U) {
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ return (context_count + 1) / 2;
+}
+
+int ff_ffv1_read_extra_header(FFV1Context *f)
+{
+ RangeCoder c;
+ uint8_t state[CONTEXT_SIZE];
+ int ret;
+ uint8_t state2[32][CONTEXT_SIZE];
+ unsigned crc = 0;
+
+ memset(state2, 128, sizeof(state2));
+ memset(state, 128, sizeof(state));
+
+ ff_init_range_decoder(&c, f->avctx->extradata, f->avctx->extradata_size);
+ ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
+
+ f->version = ff_ffv1_get_symbol(&c, state, 0);
+ if (f->version < 2) {
+ av_log(f->avctx, AV_LOG_ERROR, "Invalid version in global header\n");
+ return AVERROR_INVALIDDATA;
+ }
+ if (f->version > 4) {
+ av_log(f->avctx, AV_LOG_ERROR, "unsupported version %d\n",
+ f->version);
+ return AVERROR_PATCHWELCOME;
+ }
+ f->combined_version = f->version << 16;
+ if (f->version > 2) {
+ c.bytestream_end -= 4;
+ f->micro_version = ff_ffv1_get_symbol(&c, state, 0);
+ if (f->micro_version < 0 || f->micro_version > 65535)
+ return AVERROR_INVALIDDATA;
+ f->combined_version += f->micro_version;
+ }
+ f->ac = ff_ffv1_get_symbol(&c, state, 0);
+
+ if (f->ac == AC_RANGE_CUSTOM_TAB) {
+ for (int i = 1; i < 256; i++)
+ f->state_transition[i] = ff_ffv1_get_symbol(&c, state, 1) + c.one_state[i];
+ }
+
+ f->colorspace = ff_ffv1_get_symbol(&c, state, 0); //YUV cs type
+ f->avctx->bits_per_raw_sample = ff_ffv1_get_symbol(&c, state, 0);
+ f->chroma_planes = get_rac(&c, state);
+ f->chroma_h_shift = ff_ffv1_get_symbol(&c, state, 0);
+ f->chroma_v_shift = ff_ffv1_get_symbol(&c, state, 0);
+ f->transparency = get_rac(&c, state);
+ f->plane_count = 1 + (f->chroma_planes || f->version<4) + f->transparency;
+ f->num_h_slices = 1 + ff_ffv1_get_symbol(&c, state, 0);
+ f->num_v_slices = 1 + ff_ffv1_get_symbol(&c, state, 0);
+
+ if (f->chroma_h_shift > 4U || f->chroma_v_shift > 4U) {
+ av_log(f->avctx, AV_LOG_ERROR, "chroma shift parameters %d %d are invalid\n",
+ f->chroma_h_shift, f->chroma_v_shift);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (f->num_h_slices > (unsigned)f->width || !f->num_h_slices ||
+ f->num_v_slices > (unsigned)f->height || !f->num_v_slices
+ ) {
+ av_log(f->avctx, AV_LOG_ERROR, "slice count invalid\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (f->num_h_slices > MAX_SLICES / f->num_v_slices) {
+ av_log(f->avctx, AV_LOG_ERROR, "slice count unsupported\n");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ f->quant_table_count = ff_ffv1_get_symbol(&c, state, 0);
+ if (f->quant_table_count > (unsigned)MAX_QUANT_TABLES || !f->quant_table_count) {
+ av_log(f->avctx, AV_LOG_ERROR, "quant table count %d is invalid\n", f->quant_table_count);
+ f->quant_table_count = 0;
+ return AVERROR_INVALIDDATA;
+ }
+
+ for (int i = 0; i < f->quant_table_count; i++) {
+ f->context_count[i] = ff_ffv1_read_quant_tables(&c, f->quant_tables[i]);
+ if (f->context_count[i] < 0) {
+ av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ if ((ret = ff_ffv1_allocate_initial_states(f)) < 0)
+ return ret;
+
+ for (int i = 0; i < f->quant_table_count; i++)
+ if (get_rac(&c, state)) {
+ for (int j = 0; j < f->context_count[i]; j++)
+ for (int k = 0; k < CONTEXT_SIZE; k++) {
+ int pred = j ? f->initial_states[i][j - 1][k] : 128;
+ f->initial_states[i][j][k] =
+ (pred + ff_ffv1_get_symbol(&c, state2[k], 1)) & 0xFF;
+ }
+ }
+
+ if (f->version > 2) {
+ f->ec = ff_ffv1_get_symbol(&c, state, 0);
+ if (f->ec >= 2)
+ f->crcref = 0x7a8c4079;
+ if (f->combined_version >= 0x30003)
+ f->intra = ff_ffv1_get_symbol(&c, state, 0);
+ }
+
+ if (f->version > 2) {
+ unsigned v;
+ v = av_crc(av_crc_get_table(AV_CRC_32_IEEE), f->crcref,
+ f->avctx->extradata, f->avctx->extradata_size);
+ if (v != f->crcref || f->avctx->extradata_size < 4) {
+ av_log(f->avctx, AV_LOG_ERROR, "CRC mismatch %X!\n", v);
+ return AVERROR_INVALIDDATA;
+ }
+ crc = AV_RB32(f->avctx->extradata + f->avctx->extradata_size - 4);
+ }
+
+ if (f->avctx->debug & FF_DEBUG_PICT_INFO)
+ av_log(f->avctx, AV_LOG_DEBUG,
+ "global: ver:%d.%d, coder:%d, colorspace: %d bpr:%d chroma:%d(%d:%d), alpha:%d slices:%dx%d qtabs:%d ec:%d intra:%d CRC:0x%08X\n",
+ f->version, f->micro_version,
+ f->ac,
+ f->colorspace,
+ f->avctx->bits_per_raw_sample,
+ f->chroma_planes, f->chroma_h_shift, f->chroma_v_shift,
+ f->transparency,
+ f->num_h_slices, f->num_v_slices,
+ f->quant_table_count,
+ f->ec,
+ f->intra,
+ crc
+ );
+ return 0;
+}
+
+int ff_ffv1_parse_header(FFV1Context *f, RangeCoder *c, uint8_t *state)
+{
+ if (f->version < 2) {
+ int chroma_planes, chroma_h_shift, chroma_v_shift, transparency, colorspace, bits_per_raw_sample;
+ unsigned v= ff_ffv1_get_symbol(c, state, 0);
+ if (v >= 2) {
+ av_log(f->avctx, AV_LOG_ERROR, "invalid version %d in ver01 header\n", v);
+ return AVERROR_INVALIDDATA;
+ }
+ f->version = v;
+ f->ac = ff_ffv1_get_symbol(c, state, 0);
+
+ if (f->ac == AC_RANGE_CUSTOM_TAB) {
+ for (int i = 1; i < 256; i++) {
+ int st = ff_ffv1_get_symbol(c, state, 1) + c->one_state[i];
+ if (st < 1 || st > 255) {
+ av_log(f->avctx, AV_LOG_ERROR, "invalid state transition %d\n", st);
+ return AVERROR_INVALIDDATA;
+ }
+ f->state_transition[i] = st;
+ }
+ }
+
+ colorspace = ff_ffv1_get_symbol(c, state, 0); //YUV cs type
+ bits_per_raw_sample = f->version > 0 ? ff_ffv1_get_symbol(c, state, 0) : f->avctx->bits_per_raw_sample;
+ chroma_planes = get_rac(c, state);
+ chroma_h_shift = ff_ffv1_get_symbol(c, state, 0);
+ chroma_v_shift = ff_ffv1_get_symbol(c, state, 0);
+ transparency = get_rac(c, state);
+ if (colorspace == 0 && f->avctx->skip_alpha)
+ transparency = 0;
+
+ if (f->plane_count) {
+ if (colorspace != f->colorspace ||
+ bits_per_raw_sample != f->avctx->bits_per_raw_sample ||
+ chroma_planes != f->chroma_planes ||
+ chroma_h_shift != f->chroma_h_shift ||
+ chroma_v_shift != f->chroma_v_shift ||
+ transparency != f->transparency) {
+ av_log(f->avctx, AV_LOG_ERROR, "Invalid change of global parameters\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ if (chroma_h_shift > 4U || chroma_v_shift > 4U) {
+ av_log(f->avctx, AV_LOG_ERROR, "chroma shift parameters %d %d are invalid\n",
+ chroma_h_shift, chroma_v_shift);
+ return AVERROR_INVALIDDATA;
+ }
+
+ f->colorspace = colorspace;
+ f->avctx->bits_per_raw_sample = bits_per_raw_sample;
+ f->chroma_planes = chroma_planes;
+ f->chroma_h_shift = chroma_h_shift;
+ f->chroma_v_shift = chroma_v_shift;
+ f->transparency = transparency;
+
+ f->plane_count = 2 + f->transparency;
+ }
+
+ if (f->colorspace == 0) {
+ if (!f->transparency && !f->chroma_planes) {
+ if (f->avctx->bits_per_raw_sample <= 8)
+ f->pix_fmt = AV_PIX_FMT_GRAY8;
+ else if (f->avctx->bits_per_raw_sample == 9) {
+ f->packed_at_lsb = 1;
+ f->pix_fmt = AV_PIX_FMT_GRAY9;
+ } else if (f->avctx->bits_per_raw_sample == 10) {
+ f->packed_at_lsb = 1;
+ f->pix_fmt = AV_PIX_FMT_GRAY10;
+ } else if (f->avctx->bits_per_raw_sample == 12) {
+ f->packed_at_lsb = 1;
+ f->pix_fmt = AV_PIX_FMT_GRAY12;
+ } else if (f->avctx->bits_per_raw_sample == 14) {
+ f->packed_at_lsb = 1;
+ f->pix_fmt = AV_PIX_FMT_GRAY14;
+ } else if (f->avctx->bits_per_raw_sample == 16) {
+ f->packed_at_lsb = 1;
+ f->pix_fmt = AV_PIX_FMT_GRAY16;
+ } else if (f->avctx->bits_per_raw_sample < 16) {
+ f->pix_fmt = AV_PIX_FMT_GRAY16;
+ } else
+ return AVERROR(ENOSYS);
+ } else if (f->transparency && !f->chroma_planes) {
+ if (f->avctx->bits_per_raw_sample <= 8)
+ f->pix_fmt = AV_PIX_FMT_YA8;
+ else
+ return AVERROR(ENOSYS);
+ } else if (f->avctx->bits_per_raw_sample<=8 && !f->transparency) {
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P; break;
+ case 0x01: f->pix_fmt = AV_PIX_FMT_YUV440P; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P; break;
+ case 0x20: f->pix_fmt = AV_PIX_FMT_YUV411P; break;
+ case 0x22: f->pix_fmt = AV_PIX_FMT_YUV410P; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample <= 8 && f->transparency) {
+ switch(16*f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUVA420P; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 9 && !f->transparency) {
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P9; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P9; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P9; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 9 && f->transparency) {
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P9; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P9; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUVA420P9; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 10 && !f->transparency) {
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P10; break;
+ case 0x01: f->pix_fmt = AV_PIX_FMT_YUV440P10; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P10; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P10; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 10 && f->transparency) {
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P10; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P10; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUVA420P10; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 12 && !f->transparency) {
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P12; break;
+ case 0x01: f->pix_fmt = AV_PIX_FMT_YUV440P12; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P12; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P12; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 12 && f->transparency) {
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P12; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P12; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 14 && !f->transparency) {
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P14; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P14; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P14; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 16 && !f->transparency){
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P16; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P16; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P16; break;
+ }
+ } else if (f->avctx->bits_per_raw_sample == 16 && f->transparency){
+ f->packed_at_lsb = 1;
+ switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
+ case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P16; break;
+ case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P16; break;
+ case 0x11: f->pix_fmt = AV_PIX_FMT_YUVA420P16; break;
+ }
+ }
+ } else if (f->colorspace == 1) {
+ if (f->chroma_h_shift || f->chroma_v_shift) {
+ av_log(f->avctx, AV_LOG_ERROR,
+ "chroma subsampling not supported in this colorspace\n");
+ return AVERROR(ENOSYS);
+ }
+ if ( f->avctx->bits_per_raw_sample <= 8 && !f->transparency)
+ f->pix_fmt = AV_PIX_FMT_0RGB32;
+ else if (f->avctx->bits_per_raw_sample <= 8 && f->transparency)
+ f->pix_fmt = AV_PIX_FMT_RGB32;
+ else if (f->avctx->bits_per_raw_sample == 9 && !f->transparency)
+ f->pix_fmt = AV_PIX_FMT_GBRP9;
+ else if (f->avctx->bits_per_raw_sample == 10 && !f->transparency)
+ f->pix_fmt = AV_PIX_FMT_GBRP10;
+ else if (f->avctx->bits_per_raw_sample == 10 && f->transparency)
+ f->pix_fmt = AV_PIX_FMT_GBRAP10;
+ else if (f->avctx->bits_per_raw_sample == 12 && !f->transparency)
+ f->pix_fmt = AV_PIX_FMT_GBRP12;
+ else if (f->avctx->bits_per_raw_sample == 12 && f->transparency)
+ f->pix_fmt = AV_PIX_FMT_GBRAP12;
+ else if (f->avctx->bits_per_raw_sample == 14 && !f->transparency)
+ f->pix_fmt = AV_PIX_FMT_GBRP14;
+ else if (f->avctx->bits_per_raw_sample == 14 && f->transparency)
+ f->pix_fmt = AV_PIX_FMT_GBRAP14;
+ else if (f->avctx->bits_per_raw_sample == 16 && !f->transparency) {
+ f->pix_fmt = AV_PIX_FMT_GBRP16;
+ f->use32bit = 1;
+ } else if (f->avctx->bits_per_raw_sample == 16 && f->transparency) {
+ f->pix_fmt = AV_PIX_FMT_GBRAP16;
+ f->use32bit = 1;
+ }
+ } else {
+ av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
+ return AVERROR(ENOSYS);
+ }
+ if (f->pix_fmt == AV_PIX_FMT_NONE) {
+ av_log(f->avctx, AV_LOG_ERROR, "format not supported\n");
+ return AVERROR(ENOSYS);
+ }
+
+ return 0;
+}
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index fcf3d525ac..22ff0b04f0 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -42,35 +42,6 @@
#include "thread.h"
#include "decode.h"
-static inline av_flatten int get_symbol_inline(RangeCoder *c, uint8_t *state,
- int is_signed)
-{
- if (get_rac(c, state + 0))
- return 0;
- else {
- int e;
- unsigned a;
- e = 0;
- while (get_rac(c, state + 1 + FFMIN(e, 9))) { // 1..10
- e++;
- if (e > 31)
- return AVERROR_INVALIDDATA;
- }
-
- a = 1;
- for (int i = e - 1; i >= 0; i--)
- a += a + get_rac(c, state + 22 + FFMIN(i, 9)); // 22..31
-
- e = -(is_signed && get_rac(c, state + 11 + FFMIN(e, 10))); // 11..21
- return (a ^ e) - e;
- }
-}
-
-static av_noinline int get_symbol(RangeCoder *c, uint8_t *state, int is_signed)
-{
- return get_symbol_inline(c, state, is_signed);
-}
-
static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state,
int bits)
{
@@ -174,10 +145,10 @@ static int decode_slice_header(const FFV1Context *f,
int sx, sy, sw, sh;
memset(state, 128, sizeof(state));
- sx = get_symbol(c, state, 0);
- sy = get_symbol(c, state, 0);
- sw = get_symbol(c, state, 0) + 1U;
- sh = get_symbol(c, state, 0) + 1U;
+ sx = ff_ffv1_get_symbol(c, state, 0);
+ sy = ff_ffv1_get_symbol(c, state, 0);
+ sw = ff_ffv1_get_symbol(c, state, 0) + 1U;
+ sh = ff_ffv1_get_symbol(c, state, 0) + 1U;
av_assert0(f->version > 2);
@@ -202,7 +173,7 @@ static int decode_slice_header(const FFV1Context *f,
for (unsigned i = 0; i < f->plane_count; i++) {
PlaneContext * const p = &sc->plane[i];
- int idx = get_symbol(c, state, 0);
+ int idx = ff_ffv1_get_symbol(c, state, 0);
if (idx >= (unsigned)f->quant_table_count) {
av_log(f->avctx, AV_LOG_ERROR, "quant_table_index out of range\n");
return -1;
@@ -217,7 +188,7 @@ static int decode_slice_header(const FFV1Context *f,
p->context_count = context_count;
}
- ps = get_symbol(c, state, 0);
+ ps = ff_ffv1_get_symbol(c, state, 0);
if (ps == 1) {
frame->flags |= AV_FRAME_FLAG_INTERLACED;
frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
@@ -227,8 +198,8 @@ static int decode_slice_header(const FFV1Context *f,
} else if (ps == 3) {
frame->flags &= ~AV_FRAME_FLAG_INTERLACED;
}
- frame->sample_aspect_ratio.num = get_symbol(c, state, 0);
- frame->sample_aspect_ratio.den = get_symbol(c, state, 0);
+ frame->sample_aspect_ratio.num = ff_ffv1_get_symbol(c, state, 0);
+ frame->sample_aspect_ratio.den = ff_ffv1_get_symbol(c, state, 0);
if (av_image_check_sar(f->width, f->height,
frame->sample_aspect_ratio) < 0) {
@@ -240,10 +211,10 @@ static int decode_slice_header(const FFV1Context *f,
if (f->version > 3) {
sc->slice_reset_contexts = get_rac(c, state);
- sc->slice_coding_mode = get_symbol(c, state, 0);
+ sc->slice_coding_mode = ff_ffv1_get_symbol(c, state, 0);
if (sc->slice_coding_mode != 1 && f->colorspace == 1) {
- sc->slice_rct_by_coef = get_symbol(c, state, 0);
- sc->slice_rct_ry_coef = get_symbol(c, state, 0);
+ sc->slice_rct_by_coef = ff_ffv1_get_symbol(c, state, 0);
+ sc->slice_rct_ry_coef = ff_ffv1_get_symbol(c, state, 0);
if ((uint64_t)sc->slice_rct_by_coef + (uint64_t)sc->slice_rct_ry_coef > 4) {
av_log(f->avctx, AV_LOG_ERROR, "slice_rct_y_coef out of range\n");
return AVERROR_INVALIDDATA;
@@ -364,182 +335,6 @@ static int decode_slice(AVCodecContext *c, void *arg)
return 0;
}
-static int read_quant_table(RangeCoder *c, int16_t *quant_table, int scale)
-{
- int v;
- int i = 0;
- uint8_t state[CONTEXT_SIZE];
-
- memset(state, 128, sizeof(state));
-
- for (v = 0; i < 128; v++) {
- unsigned len = get_symbol(c, state, 0) + 1U;
-
- if (len > 128 - i || !len)
- return AVERROR_INVALIDDATA;
-
- while (len--) {
- quant_table[i] = scale * v;
- i++;
- }
- }
-
- for (i = 1; i < 128; i++)
- quant_table[256 - i] = -quant_table[i];
- quant_table[128] = -quant_table[127];
-
- return 2 * v - 1;
-}
-
-static int read_quant_tables(RangeCoder *c,
- int16_t quant_table[MAX_CONTEXT_INPUTS][256])
-{
- int i;
- int context_count = 1;
-
- for (i = 0; i < 5; i++) {
- int ret = read_quant_table(c, quant_table[i], context_count);
- if (ret < 0)
- return ret;
- context_count *= ret;
- if (context_count > 32768U) {
- return AVERROR_INVALIDDATA;
- }
- }
- return (context_count + 1) / 2;
-}
-
-static int read_extra_header(FFV1Context *f)
-{
- RangeCoder c;
- uint8_t state[CONTEXT_SIZE];
- int ret;
- uint8_t state2[32][CONTEXT_SIZE];
- unsigned crc = 0;
-
- memset(state2, 128, sizeof(state2));
- memset(state, 128, sizeof(state));
-
- ff_init_range_decoder(&c, f->avctx->extradata, f->avctx->extradata_size);
- ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
-
- f->version = get_symbol(&c, state, 0);
- if (f->version < 2) {
- av_log(f->avctx, AV_LOG_ERROR, "Invalid version in global header\n");
- return AVERROR_INVALIDDATA;
- }
- if (f->version > 4) {
- av_log(f->avctx, AV_LOG_ERROR, "unsupported version %d\n",
- f->version);
- return AVERROR_PATCHWELCOME;
- }
- f->combined_version = f->version << 16;
- if (f->version > 2) {
- c.bytestream_end -= 4;
- f->micro_version = get_symbol(&c, state, 0);
- if (f->micro_version < 0 || f->micro_version > 65535)
- return AVERROR_INVALIDDATA;
- f->combined_version += f->micro_version;
- }
- f->ac = get_symbol(&c, state, 0);
-
- if (f->ac == AC_RANGE_CUSTOM_TAB) {
- for (int i = 1; i < 256; i++)
- f->state_transition[i] = get_symbol(&c, state, 1) + c.one_state[i];
- }
-
- f->colorspace = get_symbol(&c, state, 0); //YUV cs type
- f->avctx->bits_per_raw_sample = get_symbol(&c, state, 0);
- f->chroma_planes = get_rac(&c, state);
- f->chroma_h_shift = get_symbol(&c, state, 0);
- f->chroma_v_shift = get_symbol(&c, state, 0);
- f->transparency = get_rac(&c, state);
- f->plane_count = 1 + (f->chroma_planes || f->version<4) + f->transparency;
- f->num_h_slices = 1 + get_symbol(&c, state, 0);
- f->num_v_slices = 1 + get_symbol(&c, state, 0);
-
- if (f->chroma_h_shift > 4U || f->chroma_v_shift > 4U) {
- av_log(f->avctx, AV_LOG_ERROR, "chroma shift parameters %d %d are invalid\n",
- f->chroma_h_shift, f->chroma_v_shift);
- return AVERROR_INVALIDDATA;
- }
-
- if (f->num_h_slices > (unsigned)f->width || !f->num_h_slices ||
- f->num_v_slices > (unsigned)f->height || !f->num_v_slices
- ) {
- av_log(f->avctx, AV_LOG_ERROR, "slice count invalid\n");
- return AVERROR_INVALIDDATA;
- }
-
- if (f->num_h_slices > MAX_SLICES / f->num_v_slices) {
- av_log(f->avctx, AV_LOG_ERROR, "slice count unsupported\n");
- return AVERROR_PATCHWELCOME;
- }
-
- f->quant_table_count = get_symbol(&c, state, 0);
- if (f->quant_table_count > (unsigned)MAX_QUANT_TABLES || !f->quant_table_count) {
- av_log(f->avctx, AV_LOG_ERROR, "quant table count %d is invalid\n", f->quant_table_count);
- f->quant_table_count = 0;
- return AVERROR_INVALIDDATA;
- }
-
- for (int i = 0; i < f->quant_table_count; i++) {
- f->context_count[i] = read_quant_tables(&c, f->quant_tables[i]);
- if (f->context_count[i] < 0) {
- av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n");
- return AVERROR_INVALIDDATA;
- }
- }
- if ((ret = ff_ffv1_allocate_initial_states(f)) < 0)
- return ret;
-
- for (int i = 0; i < f->quant_table_count; i++)
- if (get_rac(&c, state)) {
- for (int j = 0; j < f->context_count[i]; j++)
- for (int k = 0; k < CONTEXT_SIZE; k++) {
- int pred = j ? f->initial_states[i][j - 1][k] : 128;
- f->initial_states[i][j][k] =
- (pred + get_symbol(&c, state2[k], 1)) & 0xFF;
- }
- }
-
- if (f->version > 2) {
- f->ec = get_symbol(&c, state, 0);
- if (f->ec >= 2)
- f->crcref = 0x7a8c4079;
- if (f->combined_version >= 0x30003)
- f->intra = get_symbol(&c, state, 0);
- }
-
- if (f->version > 2) {
- unsigned v;
- v = av_crc(av_crc_get_table(AV_CRC_32_IEEE), f->crcref,
- f->avctx->extradata, f->avctx->extradata_size);
- if (v != f->crcref || f->avctx->extradata_size < 4) {
- av_log(f->avctx, AV_LOG_ERROR, "CRC mismatch %X!\n", v);
- return AVERROR_INVALIDDATA;
- }
- crc = AV_RB32(f->avctx->extradata + f->avctx->extradata_size - 4);
- }
-
- if (f->avctx->debug & FF_DEBUG_PICT_INFO)
- av_log(f->avctx, AV_LOG_DEBUG,
- "global: ver:%d.%d, coder:%d, colorspace: %d bpr:%d chroma:%d(%d:%d), alpha:%d slices:%dx%d qtabs:%d ec:%d intra:%d CRC:0x%08X\n",
- f->version, f->micro_version,
- f->ac,
- f->colorspace,
- f->avctx->bits_per_raw_sample,
- f->chroma_planes, f->chroma_h_shift, f->chroma_v_shift,
- f->transparency,
- f->num_h_slices, f->num_v_slices,
- f->quant_table_count,
- f->ec,
- f->intra,
- crc
- );
- return 0;
-}
-
static enum AVPixelFormat get_pixel_format(FFV1Context *f)
{
enum AVPixelFormat pix_fmts[] = {
@@ -554,214 +349,13 @@ static int read_header(FFV1Context *f, RangeCoder *c)
{
uint8_t state[CONTEXT_SIZE];
int context_count = -1; //-1 to avoid warning
+ int ret;
memset(state, 128, sizeof(state));
- if (f->version < 2) {
- int chroma_planes, chroma_h_shift, chroma_v_shift, transparency, colorspace, bits_per_raw_sample;
- unsigned v= get_symbol(c, state, 0);
- if (v >= 2) {
- av_log(f->avctx, AV_LOG_ERROR, "invalid version %d in ver01 header\n", v);
- return AVERROR_INVALIDDATA;
- }
- f->version = v;
- f->ac = get_symbol(c, state, 0);
-
- if (f->ac == AC_RANGE_CUSTOM_TAB) {
- for (int i = 1; i < 256; i++) {
- int st = get_symbol(c, state, 1) + c->one_state[i];
- if (st < 1 || st > 255) {
- av_log(f->avctx, AV_LOG_ERROR, "invalid state transition %d\n", st);
- return AVERROR_INVALIDDATA;
- }
- f->state_transition[i] = st;
- }
- }
-
- colorspace = get_symbol(c, state, 0); //YUV cs type
- bits_per_raw_sample = f->version > 0 ? get_symbol(c, state, 0) : f->avctx->bits_per_raw_sample;
- chroma_planes = get_rac(c, state);
- chroma_h_shift = get_symbol(c, state, 0);
- chroma_v_shift = get_symbol(c, state, 0);
- transparency = get_rac(c, state);
- if (colorspace == 0 && f->avctx->skip_alpha)
- transparency = 0;
-
- if (f->plane_count) {
- if (colorspace != f->colorspace ||
- bits_per_raw_sample != f->avctx->bits_per_raw_sample ||
- chroma_planes != f->chroma_planes ||
- chroma_h_shift != f->chroma_h_shift ||
- chroma_v_shift != f->chroma_v_shift ||
- transparency != f->transparency) {
- av_log(f->avctx, AV_LOG_ERROR, "Invalid change of global parameters\n");
- return AVERROR_INVALIDDATA;
- }
- }
-
- if (chroma_h_shift > 4U || chroma_v_shift > 4U) {
- av_log(f->avctx, AV_LOG_ERROR, "chroma shift parameters %d %d are invalid\n",
- chroma_h_shift, chroma_v_shift);
- return AVERROR_INVALIDDATA;
- }
-
- f->colorspace = colorspace;
- f->avctx->bits_per_raw_sample = bits_per_raw_sample;
- f->chroma_planes = chroma_planes;
- f->chroma_h_shift = chroma_h_shift;
- f->chroma_v_shift = chroma_v_shift;
- f->transparency = transparency;
-
- f->plane_count = 2 + f->transparency;
- }
-
- if (f->colorspace == 0) {
- if (!f->transparency && !f->chroma_planes) {
- if (f->avctx->bits_per_raw_sample <= 8)
- f->pix_fmt = AV_PIX_FMT_GRAY8;
- else if (f->avctx->bits_per_raw_sample == 9) {
- f->packed_at_lsb = 1;
- f->pix_fmt = AV_PIX_FMT_GRAY9;
- } else if (f->avctx->bits_per_raw_sample == 10) {
- f->packed_at_lsb = 1;
- f->pix_fmt = AV_PIX_FMT_GRAY10;
- } else if (f->avctx->bits_per_raw_sample == 12) {
- f->packed_at_lsb = 1;
- f->pix_fmt = AV_PIX_FMT_GRAY12;
- } else if (f->avctx->bits_per_raw_sample == 14) {
- f->packed_at_lsb = 1;
- f->pix_fmt = AV_PIX_FMT_GRAY14;
- } else if (f->avctx->bits_per_raw_sample == 16) {
- f->packed_at_lsb = 1;
- f->pix_fmt = AV_PIX_FMT_GRAY16;
- } else if (f->avctx->bits_per_raw_sample < 16) {
- f->pix_fmt = AV_PIX_FMT_GRAY16;
- } else
- return AVERROR(ENOSYS);
- } else if (f->transparency && !f->chroma_planes) {
- if (f->avctx->bits_per_raw_sample <= 8)
- f->pix_fmt = AV_PIX_FMT_YA8;
- else
- return AVERROR(ENOSYS);
- } else if (f->avctx->bits_per_raw_sample<=8 && !f->transparency) {
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P; break;
- case 0x01: f->pix_fmt = AV_PIX_FMT_YUV440P; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P; break;
- case 0x20: f->pix_fmt = AV_PIX_FMT_YUV411P; break;
- case 0x22: f->pix_fmt = AV_PIX_FMT_YUV410P; break;
- }
- } else if (f->avctx->bits_per_raw_sample <= 8 && f->transparency) {
- switch(16*f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUVA420P; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 9 && !f->transparency) {
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P9; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P9; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P9; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 9 && f->transparency) {
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P9; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P9; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUVA420P9; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 10 && !f->transparency) {
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P10; break;
- case 0x01: f->pix_fmt = AV_PIX_FMT_YUV440P10; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P10; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P10; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 10 && f->transparency) {
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P10; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P10; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUVA420P10; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 12 && !f->transparency) {
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P12; break;
- case 0x01: f->pix_fmt = AV_PIX_FMT_YUV440P12; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P12; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P12; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 12 && f->transparency) {
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P12; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P12; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 14 && !f->transparency) {
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P14; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P14; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P14; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 16 && !f->transparency){
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUV444P16; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUV422P16; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUV420P16; break;
- }
- } else if (f->avctx->bits_per_raw_sample == 16 && f->transparency){
- f->packed_at_lsb = 1;
- switch(16 * f->chroma_h_shift + f->chroma_v_shift) {
- case 0x00: f->pix_fmt = AV_PIX_FMT_YUVA444P16; break;
- case 0x10: f->pix_fmt = AV_PIX_FMT_YUVA422P16; break;
- case 0x11: f->pix_fmt = AV_PIX_FMT_YUVA420P16; break;
- }
- }
- } else if (f->colorspace == 1) {
- if (f->chroma_h_shift || f->chroma_v_shift) {
- av_log(f->avctx, AV_LOG_ERROR,
- "chroma subsampling not supported in this colorspace\n");
- return AVERROR(ENOSYS);
- }
- if ( f->avctx->bits_per_raw_sample <= 8 && !f->transparency)
- f->pix_fmt = AV_PIX_FMT_0RGB32;
- else if (f->avctx->bits_per_raw_sample <= 8 && f->transparency)
- f->pix_fmt = AV_PIX_FMT_RGB32;
- else if (f->avctx->bits_per_raw_sample == 9 && !f->transparency)
- f->pix_fmt = AV_PIX_FMT_GBRP9;
- else if (f->avctx->bits_per_raw_sample == 10 && !f->transparency)
- f->pix_fmt = AV_PIX_FMT_GBRP10;
- else if (f->avctx->bits_per_raw_sample == 10 && f->transparency)
- f->pix_fmt = AV_PIX_FMT_GBRAP10;
- else if (f->avctx->bits_per_raw_sample == 12 && !f->transparency)
- f->pix_fmt = AV_PIX_FMT_GBRP12;
- else if (f->avctx->bits_per_raw_sample == 12 && f->transparency)
- f->pix_fmt = AV_PIX_FMT_GBRAP12;
- else if (f->avctx->bits_per_raw_sample == 14 && !f->transparency)
- f->pix_fmt = AV_PIX_FMT_GBRP14;
- else if (f->avctx->bits_per_raw_sample == 14 && f->transparency)
- f->pix_fmt = AV_PIX_FMT_GBRAP14;
- else if (f->avctx->bits_per_raw_sample == 16 && !f->transparency) {
- f->pix_fmt = AV_PIX_FMT_GBRP16;
- f->use32bit = 1;
- } else if (f->avctx->bits_per_raw_sample == 16 && f->transparency) {
- f->pix_fmt = AV_PIX_FMT_GBRAP16;
- f->use32bit = 1;
- }
- } else {
- av_log(f->avctx, AV_LOG_ERROR, "colorspace not supported\n");
- return AVERROR(ENOSYS);
- }
- if (f->pix_fmt == AV_PIX_FMT_NONE) {
- av_log(f->avctx, AV_LOG_ERROR, "format not supported\n");
- return AVERROR(ENOSYS);
- }
+ ret = ff_ffv1_parse_header(f, c, state);
+ if (ret < 0)
+ return ret;
f->avctx->pix_fmt = get_pixel_format(f);
if (f->avctx->pix_fmt < 0)
@@ -770,14 +364,14 @@ static int read_header(FFV1Context *f, RangeCoder *c)
ff_dlog(f->avctx, "%d %d %d\n",
f->chroma_h_shift, f->chroma_v_shift, f->pix_fmt);
if (f->version < 2) {
- context_count = read_quant_tables(c, f->quant_tables[0]);
+ context_count = ff_ffv1_read_quant_tables(c, f->quant_tables[0]);
if (context_count < 0) {
av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n");
return AVERROR_INVALIDDATA;
}
f->slice_count = f->max_slice_count;
} else if (f->version < 3) {
- f->slice_count = get_symbol(c, state, 0);
+ f->slice_count = ff_ffv1_get_symbol(c, state, 0);
} else {
const uint8_t *p = c->bytestream_end;
for (f->slice_count = 0;
@@ -804,10 +398,10 @@ static int read_header(FFV1Context *f, RangeCoder *c)
FFV1SliceContext *sc = &f->slices[j];
if (f->version == 2) {
- int sx = get_symbol(c, state, 0);
- int sy = get_symbol(c, state, 0);
- int sw = get_symbol(c, state, 0) + 1U;
- int sh = get_symbol(c, state, 0) + 1U;
+ int sx = ff_ffv1_get_symbol(c, state, 0);
+ int sy = ff_ffv1_get_symbol(c, state, 0);
+ int sw = ff_ffv1_get_symbol(c, state, 0) + 1U;
+ int sh = ff_ffv1_get_symbol(c, state, 0) + 1U;
if (sx < 0 || sy < 0 || sw <= 0 || sh <= 0)
return AVERROR_INVALIDDATA;
@@ -834,7 +428,7 @@ static int read_header(FFV1Context *f, RangeCoder *c)
PlaneContext *const p = &sc->plane[i];
if (f->version == 2) {
- int idx = get_symbol(c, state, 0);
+ int idx = ff_ffv1_get_symbol(c, state, 0);
if (idx >= (unsigned)f->quant_table_count) {
av_log(f->avctx, AV_LOG_ERROR,
"quant_table_index out of range\n");
@@ -858,10 +452,10 @@ static av_cold int decode_init(AVCodecContext *avctx)
FFV1Context *f = avctx->priv_data;
int ret;
- if ((ret = ff_ffv1_common_init(avctx)) < 0)
+ if ((ret = ff_ffv1_common_init(avctx, f)) < 0)
return ret;
- if (avctx->extradata_size > 0 && (ret = read_extra_header(f)) < 0)
+ if (avctx->extradata_size > 0 && (ret = ff_ffv1_read_extra_header(f)) < 0)
return ret;
if ((ret = ff_ffv1_init_slice_contexts(f)) < 0)
@@ -1160,8 +754,11 @@ static av_cold int ffv1_decode_close(AVCodecContext *avctx)
ff_progress_frame_unref(&s->picture);
ff_progress_frame_unref(&s->last_picture);
+ av_freep(&avctx->stats_out);
+
+ ff_ffv1_close(s);
- return ff_ffv1_close(avctx);
+ return 0;
}
const FFCodec ff_ffv1_decoder = {
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index e44316f86a..2e3262db54 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -894,7 +894,7 @@ static int encode_init_internal(AVCodecContext *avctx)
int ret;
FFV1Context *s = avctx->priv_data;
- if ((ret = ff_ffv1_common_init(avctx)) < 0)
+ if ((ret = ff_ffv1_common_init(avctx, s)) < 0)
return ret;
if (s->ac == 1) // Compatbility with common command line usage
@@ -1334,6 +1334,16 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
return 0;
}
+static av_cold int encode_close(AVCodecContext *avctx)
+{
+ FFV1Context *const s = avctx->priv_data;
+
+ av_freep(&avctx->stats_out);
+ ff_ffv1_close(s);
+
+ return 0;
+}
+
#define OFFSET(x) offsetof(FFV1Context, x)
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
@@ -1380,7 +1390,7 @@ const FFCodec ff_ffv1_encoder = {
.priv_data_size = sizeof(FFV1Context),
.init = encode_init_internal,
FF_CODEC_ENCODE_CB(encode_frame),
- .close = ff_ffv1_close,
+ .close = encode_close,
.p.pix_fmts = (const enum AVPixelFormat[]) {
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV444P,
AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV411P,
--
2.48.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] 7+ messages in thread
* [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser
2025-02-03 2:16 [FFmpeg-devel] [PATCH 1/2] avcodec/ffv1: split off and share frame header parsing code James Almer
@ 2025-02-03 2:16 ` James Almer
2025-02-03 5:42 ` Lynne
2025-02-06 15:52 ` Michael Niedermayer
2025-02-06 15:49 ` [FFmpeg-devel] [PATCH 1/2] avcodec/ffv1: split off and share frame header parsing code Michael Niedermayer
1 sibling, 2 replies; 7+ messages in thread
From: James Almer @ 2025-02-03 2:16 UTC (permalink / raw)
To: ffmpeg-devel
Only setting frame and stream properties. No packetization is performed.
Signed-off-by: James Almer <jamrial@gmail.com>
---
configure | 1 +
libavcodec/Makefile | 1 +
libavcodec/ffv1_parser.c | 86 ++++++++++++++++++++++++++++++++++++++++
libavcodec/parsers.c | 1 +
4 files changed, 89 insertions(+)
create mode 100644 libavcodec/ffv1_parser.c
diff --git a/configure b/configure
index 06f641ead0..f09faaf505 100755
--- a/configure
+++ b/configure
@@ -3469,6 +3469,7 @@ vvc_qsv_decoder_select="vvc_mp4toannexb_bsf qsvdec"
aac_parser_select="adts_header mpeg4audio"
av1_parser_select="cbs_av1"
evc_parser_select="evcparse"
+ffv1_parser_select="rangecoder"
ftr_parser_select="adts_header mpeg4audio"
h264_parser_select="golomb h264dsp h264parse h264_sei"
hevc_parser_select="hevcparse hevc_sei"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 44bb34182a..973e2c45d6 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -1207,6 +1207,7 @@ OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o
OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o
OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o
OBJS-$(CONFIG_EVC_PARSER) += evc_parser.o
+OBJS-$(CONFIG_FFV1_PARSER) += ffv1_parser.o ffv1_parse.o ffv1.o
OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o
OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o
OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o
diff --git a/libavcodec/ffv1_parser.c b/libavcodec/ffv1_parser.c
new file mode 100644
index 0000000000..d0b396b693
--- /dev/null
+++ b/libavcodec/ffv1_parser.c
@@ -0,0 +1,86 @@
+/*
+ * 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 "avcodec.h"
+#include "ffv1.h"
+#include "rangecoder.h"
+
+typedef struct FFV1ParseContext {
+ FFV1Context f;
+ int got_first;
+} FFV1ParseContext;
+
+static int parse(AVCodecParserContext *s,
+ AVCodecContext *avctx,
+ const uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size)
+{
+ FFV1ParseContext *p = s->priv_data;
+ FFV1Context *f = &p->f;
+ RangeCoder c;
+ uint8_t keystate = 128;
+
+ *poutbuf = buf;
+ *poutbuf_size = buf_size;
+
+ if (!p->got_first) {
+ int ret = ff_ffv1_common_init(avctx, f);
+ p->got_first = 1;
+ if (ret < 0)
+ return buf_size;
+
+ if (avctx->extradata_size > 0 && (ret = ff_ffv1_read_extra_header(f)) < 0)
+ return buf_size;
+ }
+
+ ff_init_range_decoder(&c, buf, buf_size);
+ ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
+
+ f->avctx = avctx;
+ s->key_frame = get_rac(&c, &keystate);
+ s->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P, see ffv1dec.c
+ s->field_order = AV_FIELD_UNKNOWN;
+ s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
+
+ if (s->key_frame) {
+ uint8_t state[CONTEXT_SIZE];
+ memset(state, 128, sizeof(state));
+ ff_ffv1_parse_header(f, &c, state);
+ }
+
+ s->width = f->width;
+ s->height = f->height;
+ s->format = f->pix_fmt;
+
+ return buf_size;
+}
+
+static void close(AVCodecParserContext *s)
+{
+ FFV1ParseContext *p = s->priv_data;
+
+ p->f.avctx = NULL;
+ ff_ffv1_close(&p->f);
+}
+
+const AVCodecParser ff_ffv1_parser = {
+ .codec_ids = { AV_CODEC_ID_FFV1 },
+ .priv_data_size = sizeof(FFV1ParseContext),
+ .parser_parse = parse,
+ .parser_close = close,
+};
diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c
index 8bfd2dbce0..5387351fd0 100644
--- a/libavcodec/parsers.c
+++ b/libavcodec/parsers.c
@@ -45,6 +45,7 @@ extern const AVCodecParser ff_dvd_nav_parser;
extern const AVCodecParser ff_evc_parser;
extern const AVCodecParser ff_flac_parser;
extern const AVCodecParser ff_ftr_parser;
+extern const AVCodecParser ff_ffv1_parser;
extern const AVCodecParser ff_g723_1_parser;
extern const AVCodecParser ff_g729_parser;
extern const AVCodecParser ff_gif_parser;
--
2.48.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] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser
2025-02-03 2:16 ` [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser James Almer
@ 2025-02-03 5:42 ` Lynne
2025-02-03 13:00 ` James Almer
2025-02-06 15:52 ` Michael Niedermayer
1 sibling, 1 reply; 7+ messages in thread
From: Lynne @ 2025-02-03 5:42 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1.1.1.1: Type: text/plain, Size: 4626 bytes --]
On 03/02/2025 03:16, James Almer wrote:
> Only setting frame and stream properties. No packetization is performed.
>
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> configure | 1 +
> libavcodec/Makefile | 1 +
> libavcodec/ffv1_parser.c | 86 ++++++++++++++++++++++++++++++++++++++++
> libavcodec/parsers.c | 1 +
> 4 files changed, 89 insertions(+)
> create mode 100644 libavcodec/ffv1_parser.c
>
> diff --git a/configure b/configure
> index 06f641ead0..f09faaf505 100755
> --- a/configure
> +++ b/configure
> @@ -3469,6 +3469,7 @@ vvc_qsv_decoder_select="vvc_mp4toannexb_bsf qsvdec"
> aac_parser_select="adts_header mpeg4audio"
> av1_parser_select="cbs_av1"
> evc_parser_select="evcparse"
> +ffv1_parser_select="rangecoder"
> ftr_parser_select="adts_header mpeg4audio"
> h264_parser_select="golomb h264dsp h264parse h264_sei"
> hevc_parser_select="hevcparse hevc_sei"
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 44bb34182a..973e2c45d6 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -1207,6 +1207,7 @@ OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o
> OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o
> OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o
> OBJS-$(CONFIG_EVC_PARSER) += evc_parser.o
> +OBJS-$(CONFIG_FFV1_PARSER) += ffv1_parser.o ffv1_parse.o ffv1.o
> OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o
> OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o
> OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o
> diff --git a/libavcodec/ffv1_parser.c b/libavcodec/ffv1_parser.c
> new file mode 100644
> index 0000000000..d0b396b693
> --- /dev/null
> +++ b/libavcodec/ffv1_parser.c
> @@ -0,0 +1,86 @@
> +/*
> + * 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 "avcodec.h"
> +#include "ffv1.h"
> +#include "rangecoder.h"
> +
> +typedef struct FFV1ParseContext {
> + FFV1Context f;
> + int got_first;
> +} FFV1ParseContext;
> +
> +static int parse(AVCodecParserContext *s,
> + AVCodecContext *avctx,
> + const uint8_t **poutbuf, int *poutbuf_size,
> + const uint8_t *buf, int buf_size)
> +{
> + FFV1ParseContext *p = s->priv_data;
> + FFV1Context *f = &p->f;
> + RangeCoder c;
> + uint8_t keystate = 128;
> +
> + *poutbuf = buf;
> + *poutbuf_size = buf_size;
> +
> + if (!p->got_first) {
> + int ret = ff_ffv1_common_init(avctx, f);
> + p->got_first = 1;
> + if (ret < 0)
> + return buf_size;
> +
> + if (avctx->extradata_size > 0 && (ret = ff_ffv1_read_extra_header(f)) < 0)
> + return buf_size;
> + }
> +
> + ff_init_range_decoder(&c, buf, buf_size);
> + ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
> +
> + f->avctx = avctx;
> + s->key_frame = get_rac(&c, &keystate);
> + s->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P, see ffv1dec.c
> + s->field_order = AV_FIELD_UNKNOWN;
> + s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
> +
> + if (s->key_frame) {
> + uint8_t state[CONTEXT_SIZE];
> + memset(state, 128, sizeof(state));
> + ff_ffv1_parse_header(f, &c, state);
> + }
> +
> + s->width = f->width;
> + s->height = f->height;
> + s->format = f->pix_fmt;
> +
> + return buf_size;
> +}
> +
> +static void close(AVCodecParserContext *s)
> +{
> + FFV1ParseContext *p = s->priv_data;
> +
> + p->f.avctx = NULL;
Since avctx looks like is only used for logging now in parse_header, you
could cast AVCodecParserContext and avoid av_log(NULL)s on error.
Other than that, patchset looks good to me, thanks.
[-- Attachment #1.1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 637 bytes --]
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 236 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser
2025-02-03 5:42 ` Lynne
@ 2025-02-03 13:00 ` James Almer
0 siblings, 0 replies; 7+ messages in thread
From: James Almer @ 2025-02-03 13:00 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1.1.1: Type: text/plain, Size: 5363 bytes --]
On 2/3/2025 2:42 AM, Lynne wrote:
> On 03/02/2025 03:16, James Almer wrote:
>> Only setting frame and stream properties. No packetization is performed.
>>
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>> configure | 1 +
>> libavcodec/Makefile | 1 +
>> libavcodec/ffv1_parser.c | 86 ++++++++++++++++++++++++++++++++++++++++
>> libavcodec/parsers.c | 1 +
>> 4 files changed, 89 insertions(+)
>> create mode 100644 libavcodec/ffv1_parser.c
>>
>> diff --git a/configure b/configure
>> index 06f641ead0..f09faaf505 100755
>> --- a/configure
>> +++ b/configure
>> @@ -3469,6 +3469,7 @@ vvc_qsv_decoder_select="vvc_mp4toannexb_bsf qsvdec"
>> aac_parser_select="adts_header mpeg4audio"
>> av1_parser_select="cbs_av1"
>> evc_parser_select="evcparse"
>> +ffv1_parser_select="rangecoder"
>> ftr_parser_select="adts_header mpeg4audio"
>> h264_parser_select="golomb h264dsp h264parse h264_sei"
>> hevc_parser_select="hevcparse hevc_sei"
>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>> index 44bb34182a..973e2c45d6 100644
>> --- a/libavcodec/Makefile
>> +++ b/libavcodec/Makefile
>> @@ -1207,6 +1207,7 @@ OBJS-$(CONFIG_DVBSUB_PARSER) +=
>> dvbsub_parser.o
>> OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o
>> OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o
>> OBJS-$(CONFIG_EVC_PARSER) += evc_parser.o
>> +OBJS-$(CONFIG_FFV1_PARSER) += ffv1_parser.o ffv1_parse.o
>> ffv1.o
>> OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o
>> flac.o
>> OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o
>> OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o
>> diff --git a/libavcodec/ffv1_parser.c b/libavcodec/ffv1_parser.c
>> new file mode 100644
>> index 0000000000..d0b396b693
>> --- /dev/null
>> +++ b/libavcodec/ffv1_parser.c
>> @@ -0,0 +1,86 @@
>> +/*
>> + * 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 "avcodec.h"
>> +#include "ffv1.h"
>> +#include "rangecoder.h"
>> +
>> +typedef struct FFV1ParseContext {
>> + FFV1Context f;
>> + int got_first;
>> +} FFV1ParseContext;
>> +
>> +static int parse(AVCodecParserContext *s,
>> + AVCodecContext *avctx,
>> + const uint8_t **poutbuf, int *poutbuf_size,
>> + const uint8_t *buf, int buf_size)
>> +{
>> + FFV1ParseContext *p = s->priv_data;
>> + FFV1Context *f = &p->f;
>> + RangeCoder c;
>> + uint8_t keystate = 128;
>> +
>> + *poutbuf = buf;
>> + *poutbuf_size = buf_size;
>> +
>> + if (!p->got_first) {
>> + int ret = ff_ffv1_common_init(avctx, f);
>> + p->got_first = 1;
>> + if (ret < 0)
>> + return buf_size;
>> +
>> + if (avctx->extradata_size > 0 && (ret =
>> ff_ffv1_read_extra_header(f)) < 0)
>> + return buf_size;
>> + }
>> +
>> + ff_init_range_decoder(&c, buf, buf_size);
>> + ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
>> +
>> + f->avctx = avctx;
>> + s->key_frame = get_rac(&c, &keystate);
>> + s->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P, see ffv1dec.c
>> + s->field_order = AV_FIELD_UNKNOWN;
>> + s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
>> +
>> + if (s->key_frame) {
>> + uint8_t state[CONTEXT_SIZE];
>> + memset(state, 128, sizeof(state));
>> + ff_ffv1_parse_header(f, &c, state);
>> + }
>> +
>> + s->width = f->width;
>> + s->height = f->height;
>> + s->format = f->pix_fmt;
>> +
>> + return buf_size;
>> +}
>> +
>> +static void close(AVCodecParserContext *s)
>> +{
>> + FFV1ParseContext *p = s->priv_data;
>> +
>> + p->f.avctx = NULL;
>
> Since avctx looks like is only used for logging now in parse_header, you
> could cast AVCodecParserContext and avoid av_log(NULL)s on error.
parse_header also sets and reads bits_per_raw_sample in avctx, so it's
not just a log context. And avctx being set to null here is only a
precaution, because ff_ffv1_close() doesn't currently access it.
>
> Other than that, patchset looks good to me, thanks.
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH 1/2] avcodec/ffv1: split off and share frame header parsing code
2025-02-03 2:16 [FFmpeg-devel] [PATCH 1/2] avcodec/ffv1: split off and share frame header parsing code James Almer
2025-02-03 2:16 ` [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser James Almer
@ 2025-02-06 15:49 ` Michael Niedermayer
1 sibling, 0 replies; 7+ messages in thread
From: Michael Niedermayer @ 2025-02-06 15:49 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 767 bytes --]
On Sun, Feb 02, 2025 at 11:16:02PM -0300, James Almer wrote:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> libavcodec/Makefile | 4 +-
> libavcodec/ffv1.c | 14 +-
> libavcodec/ffv1.h | 35 ++-
> libavcodec/ffv1_parse.c | 410 +++++++++++++++++++++++++++++++++++
> libavcodec/ffv1dec.c | 459 +++-------------------------------------
> libavcodec/ffv1enc.c | 14 +-
> 6 files changed, 491 insertions(+), 445 deletions(-)
> create mode 100644 libavcodec/ffv1_parse.c
probably ok
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
"Nothing to hide" only works if the folks in power share the values of
you and everyone you know entirely and always will -- Tom Scott
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser
2025-02-03 2:16 ` [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser James Almer
2025-02-03 5:42 ` Lynne
@ 2025-02-06 15:52 ` Michael Niedermayer
2025-02-06 17:10 ` James Almer
1 sibling, 1 reply; 7+ messages in thread
From: Michael Niedermayer @ 2025-02-06 15:52 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 4406 bytes --]
On Sun, Feb 02, 2025 at 11:16:03PM -0300, James Almer wrote:
> Only setting frame and stream properties. No packetization is performed.
>
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
> configure | 1 +
> libavcodec/Makefile | 1 +
> libavcodec/ffv1_parser.c | 86 ++++++++++++++++++++++++++++++++++++++++
> libavcodec/parsers.c | 1 +
> 4 files changed, 89 insertions(+)
> create mode 100644 libavcodec/ffv1_parser.c
>
> diff --git a/configure b/configure
> index 06f641ead0..f09faaf505 100755
> --- a/configure
> +++ b/configure
> @@ -3469,6 +3469,7 @@ vvc_qsv_decoder_select="vvc_mp4toannexb_bsf qsvdec"
> aac_parser_select="adts_header mpeg4audio"
> av1_parser_select="cbs_av1"
> evc_parser_select="evcparse"
> +ffv1_parser_select="rangecoder"
> ftr_parser_select="adts_header mpeg4audio"
> h264_parser_select="golomb h264dsp h264parse h264_sei"
> hevc_parser_select="hevcparse hevc_sei"
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 44bb34182a..973e2c45d6 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -1207,6 +1207,7 @@ OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o
> OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o
> OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o
> OBJS-$(CONFIG_EVC_PARSER) += evc_parser.o
> +OBJS-$(CONFIG_FFV1_PARSER) += ffv1_parser.o ffv1_parse.o ffv1.o
> OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o
> OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o
> OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o
> diff --git a/libavcodec/ffv1_parser.c b/libavcodec/ffv1_parser.c
> new file mode 100644
> index 0000000000..d0b396b693
> --- /dev/null
> +++ b/libavcodec/ffv1_parser.c
> @@ -0,0 +1,86 @@
> +/*
> + * 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 "avcodec.h"
> +#include "ffv1.h"
> +#include "rangecoder.h"
> +
> +typedef struct FFV1ParseContext {
> + FFV1Context f;
> + int got_first;
> +} FFV1ParseContext;
> +
> +static int parse(AVCodecParserContext *s,
> + AVCodecContext *avctx,
> + const uint8_t **poutbuf, int *poutbuf_size,
> + const uint8_t *buf, int buf_size)
> +{
> + FFV1ParseContext *p = s->priv_data;
> + FFV1Context *f = &p->f;
> + RangeCoder c;
> + uint8_t keystate = 128;
> +
> + *poutbuf = buf;
> + *poutbuf_size = buf_size;
> +
> + if (!p->got_first) {
> + int ret = ff_ffv1_common_init(avctx, f);
> + p->got_first = 1;
> + if (ret < 0)
> + return buf_size;
> +
> + if (avctx->extradata_size > 0 && (ret = ff_ffv1_read_extra_header(f)) < 0)
> + return buf_size;
> + }
> +
> + ff_init_range_decoder(&c, buf, buf_size);
> + ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
> +
> + f->avctx = avctx;
> + s->key_frame = get_rac(&c, &keystate);
> + s->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P, see ffv1dec.c
id remove the comment, also in ffv1dec.c
patch should be ok
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Modern terrorism, a quick summary: Need oil, start war with country that
has oil, kill hundread thousand in war. Let country fall into chaos,
be surprised about raise of fundamantalists. Drop more bombs, kill more
people, be surprised about them taking revenge and drop even more bombs
and strip your own citizens of their rights and freedoms. to be continued
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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] 7+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser
2025-02-06 15:52 ` Michael Niedermayer
@ 2025-02-06 17:10 ` James Almer
0 siblings, 0 replies; 7+ messages in thread
From: James Almer @ 2025-02-06 17:10 UTC (permalink / raw)
To: ffmpeg-devel
[-- Attachment #1.1.1: Type: text/plain, Size: 4161 bytes --]
On 2/6/2025 12:52 PM, Michael Niedermayer wrote:
> On Sun, Feb 02, 2025 at 11:16:03PM -0300, James Almer wrote:
>> Only setting frame and stream properties. No packetization is performed.
>>
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>> configure | 1 +
>> libavcodec/Makefile | 1 +
>> libavcodec/ffv1_parser.c | 86 ++++++++++++++++++++++++++++++++++++++++
>> libavcodec/parsers.c | 1 +
>> 4 files changed, 89 insertions(+)
>> create mode 100644 libavcodec/ffv1_parser.c
>>
>> diff --git a/configure b/configure
>> index 06f641ead0..f09faaf505 100755
>> --- a/configure
>> +++ b/configure
>> @@ -3469,6 +3469,7 @@ vvc_qsv_decoder_select="vvc_mp4toannexb_bsf qsvdec"
>> aac_parser_select="adts_header mpeg4audio"
>> av1_parser_select="cbs_av1"
>> evc_parser_select="evcparse"
>> +ffv1_parser_select="rangecoder"
>> ftr_parser_select="adts_header mpeg4audio"
>> h264_parser_select="golomb h264dsp h264parse h264_sei"
>> hevc_parser_select="hevcparse hevc_sei"
>> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
>> index 44bb34182a..973e2c45d6 100644
>> --- a/libavcodec/Makefile
>> +++ b/libavcodec/Makefile
>> @@ -1207,6 +1207,7 @@ OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o
>> OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o
>> OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o
>> OBJS-$(CONFIG_EVC_PARSER) += evc_parser.o
>> +OBJS-$(CONFIG_FFV1_PARSER) += ffv1_parser.o ffv1_parse.o ffv1.o
>> OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o
>> OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o
>> OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o
>> diff --git a/libavcodec/ffv1_parser.c b/libavcodec/ffv1_parser.c
>> new file mode 100644
>> index 0000000000..d0b396b693
>> --- /dev/null
>> +++ b/libavcodec/ffv1_parser.c
>> @@ -0,0 +1,86 @@
>> +/*
>> + * 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 "avcodec.h"
>> +#include "ffv1.h"
>> +#include "rangecoder.h"
>> +
>> +typedef struct FFV1ParseContext {
>> + FFV1Context f;
>> + int got_first;
>> +} FFV1ParseContext;
>> +
>> +static int parse(AVCodecParserContext *s,
>> + AVCodecContext *avctx,
>> + const uint8_t **poutbuf, int *poutbuf_size,
>> + const uint8_t *buf, int buf_size)
>> +{
>> + FFV1ParseContext *p = s->priv_data;
>> + FFV1Context *f = &p->f;
>> + RangeCoder c;
>> + uint8_t keystate = 128;
>> +
>> + *poutbuf = buf;
>> + *poutbuf_size = buf_size;
>> +
>> + if (!p->got_first) {
>> + int ret = ff_ffv1_common_init(avctx, f);
>> + p->got_first = 1;
>> + if (ret < 0)
>> + return buf_size;
>> +
>> + if (avctx->extradata_size > 0 && (ret = ff_ffv1_read_extra_header(f)) < 0)
>> + return buf_size;
>> + }
>> +
>> + ff_init_range_decoder(&c, buf, buf_size);
>> + ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
>> +
>> + f->avctx = avctx;
>> + s->key_frame = get_rac(&c, &keystate);
>> + s->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P, see ffv1dec.c
>
> id remove the comment, also in ffv1dec.c
>
> patch should be ok
>
Applied with that change. Thanks.
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
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] 7+ messages in thread
end of thread, other threads:[~2025-02-06 17:10 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-03 2:16 [FFmpeg-devel] [PATCH 1/2] avcodec/ffv1: split off and share frame header parsing code James Almer
2025-02-03 2:16 ` [FFmpeg-devel] [PATCH v2 2/2] avcodec: add a ffv1 parser James Almer
2025-02-03 5:42 ` Lynne
2025-02-03 13:00 ` James Almer
2025-02-06 15:52 ` Michael Niedermayer
2025-02-06 17:10 ` James Almer
2025-02-06 15:49 ` [FFmpeg-devel] [PATCH 1/2] avcodec/ffv1: split off and share frame header parsing code Michael Niedermayer
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