* [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2
@ 2024-07-16 17:11 Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 02/39] lavc/ffv1dec: declare loop variables in the loop where possible Anton Khirnov
` (38 more replies)
0 siblings, 39 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
tests/fate/vcodec.mak | 3 ++-
tests/ref/vsynth/vsynth1-ffv1-v2 | 4 ++++
tests/ref/vsynth/vsynth2-ffv1-v2 | 4 ++++
tests/ref/vsynth/vsynth3-ffv1-v2 | 4 ++++
tests/ref/vsynth/vsynth_lena-ffv1-v2 | 4 ++++
5 files changed, 18 insertions(+), 1 deletion(-)
create mode 100644 tests/ref/vsynth/vsynth1-ffv1-v2
create mode 100644 tests/ref/vsynth/vsynth2-ffv1-v2
create mode 100644 tests/ref/vsynth/vsynth3-ffv1-v2
create mode 100644 tests/ref/vsynth/vsynth_lena-ffv1-v2
diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak
index abdc481f8a..b9829be027 100644
--- a/tests/fate/vcodec.mak
+++ b/tests/fate/vcodec.mak
@@ -154,13 +154,14 @@ $(FATE_VCODEC_DV:%=fate-vsynth\%-%): CODEC = dvvideo
$(FATE_VCODEC_DV:%=fate-vsynth\%-%): FMT = dv
$(FATE_VCODEC_DV:%=fate-vsynth\%-%): DECOPTS += $(DEFAULT_SIZE)
-FATE_VCODEC-$(call ENCDEC, FFV1, AVI) += ffv1 ffv1-v0 \
+FATE_VCODEC-$(call ENCDEC, FFV1, AVI) += ffv1 ffv1-v0 ffv1-v2 \
ffv1-v3-yuv420p \
ffv1-2pass
FATE_VCODEC_SCALE-$(call ENCDEC, FFV1, AVI) += ffv1-v3-yuv422p10 ffv1-v3-yuv444p16 \
ffv1-v3-bgr0 ffv1-v3-rgb48
fate-vsynth%-ffv1: ENCOPTS = -slices 4
fate-vsynth%-ffv1-v0: CODEC = ffv1
+fate-vsynth%-ffv1-v2: ENCOPTS = -level 2 -strict experimental
fate-vsynth%-ffv1-v3-yuv420p: ENCOPTS = -level 3 -pix_fmt yuv420p
fate-vsynth%-ffv1-v3-yuv422p10: ENCOPTS = -level 3 -pix_fmt yuv422p10 \
-sws_flags neighbor+bitexact
diff --git a/tests/ref/vsynth/vsynth1-ffv1-v2 b/tests/ref/vsynth/vsynth1-ffv1-v2
new file mode 100644
index 0000000000..69536fb390
--- /dev/null
+++ b/tests/ref/vsynth/vsynth1-ffv1-v2
@@ -0,0 +1,4 @@
+0f9298229cf53ce257648ccec70c893f *tests/data/fate/vsynth1-ffv1-v2.avi
+2689724 tests/data/fate/vsynth1-ffv1-v2.avi
+c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-ffv1-v2.out.rawvideo
+stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200
diff --git a/tests/ref/vsynth/vsynth2-ffv1-v2 b/tests/ref/vsynth/vsynth2-ffv1-v2
new file mode 100644
index 0000000000..0b3f288f8f
--- /dev/null
+++ b/tests/ref/vsynth/vsynth2-ffv1-v2
@@ -0,0 +1,4 @@
+3144d06b9af1af98d072ccf05ff116ba *tests/data/fate/vsynth2-ffv1-v2.avi
+3716500 tests/data/fate/vsynth2-ffv1-v2.avi
+36d7ca943916e1743cefa609eba0205c *tests/data/fate/vsynth2-ffv1-v2.out.rawvideo
+stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200
diff --git a/tests/ref/vsynth/vsynth3-ffv1-v2 b/tests/ref/vsynth/vsynth3-ffv1-v2
new file mode 100644
index 0000000000..3b0397ec02
--- /dev/null
+++ b/tests/ref/vsynth/vsynth3-ffv1-v2
@@ -0,0 +1,4 @@
+72f1126e9e270f019d90f74959bcf0cb *tests/data/fate/vsynth3-ffv1-v2.avi
+60648 tests/data/fate/vsynth3-ffv1-v2.avi
+a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-ffv1-v2.out.rawvideo
+stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700
diff --git a/tests/ref/vsynth/vsynth_lena-ffv1-v2 b/tests/ref/vsynth/vsynth_lena-ffv1-v2
new file mode 100644
index 0000000000..5f180462b5
--- /dev/null
+++ b/tests/ref/vsynth/vsynth_lena-ffv1-v2
@@ -0,0 +1,4 @@
+4a0dbd5b50fa68fc7d5a8d6d64bd695a *tests/data/fate/vsynth_lena-ffv1-v2.avi
+3546264 tests/data/fate/vsynth_lena-ffv1-v2.avi
+dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth_lena-ffv1-v2.out.rawvideo
+stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 02/39] lavc/ffv1dec: declare loop variables in the loop where possible
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 18:22 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 03/39] lavc/ffv1dec: simplify slice index calculation Anton Khirnov
` (37 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1dec.c | 45 ++++++++++++++++++++++----------------------
1 file changed, 22 insertions(+), 23 deletions(-)
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 7a0d1909aa..5c515e97b6 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -46,7 +46,7 @@ static inline av_flatten int get_symbol_inline(RangeCoder *c, uint8_t *state,
if (get_rac(c, state + 0))
return 0;
else {
- int i, e;
+ int e;
unsigned a;
e = 0;
while (get_rac(c, state + 1 + FFMIN(e, 9))) { // 1..10
@@ -56,7 +56,7 @@ static inline av_flatten int get_symbol_inline(RangeCoder *c, uint8_t *state,
}
a = 1;
- for (i = e - 1; i >= 0; i--)
+ 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
@@ -167,7 +167,7 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs)
{
RangeCoder *c = &fs->c;
uint8_t state[CONTEXT_SIZE];
- unsigned ps, i, context_count;
+ unsigned ps, context_count;
int sx, sy, sw, sh;
memset(state, 128, sizeof(state));
@@ -197,7 +197,7 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs)
if (fs->ac == AC_GOLOMB_RICE && fs->slice_width >= (1<<23))
return AVERROR_INVALIDDATA;
- for (i = 0; i < f->plane_count; i++) {
+ for (unsigned i = 0; i < f->plane_count; i++) {
PlaneContext * const p = &fs->plane[i];
int idx = get_symbol(c, state, 0);
if (idx >= (unsigned)f->quant_table_count) {
@@ -259,7 +259,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
int width, height, x, y, ret;
const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step;
AVFrame * const p = f->cur;
- int i, si;
+ int si;
for( si=0; fs != f->slice_context[si]; si ++)
;
@@ -276,7 +276,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
if (!(p->flags & AV_FRAME_FLAG_KEY))
fsdst->slice_damaged |= fssrc->slice_damaged;
- for (i = 0; i < f->plane_count; i++) {
+ for (int i = 0; i < f->plane_count; i++) {
PlaneContext *psrc = &fssrc->plane[i];
PlaneContext *pdst = &fsdst->plane[i];
@@ -424,7 +424,7 @@ static int read_extra_header(FFV1Context *f)
{
RangeCoder *const c = &f->c;
uint8_t state[CONTEXT_SIZE];
- int i, j, k, ret;
+ int ret;
uint8_t state2[32][CONTEXT_SIZE];
unsigned crc = 0;
@@ -453,7 +453,7 @@ static int read_extra_header(FFV1Context *f)
f->ac = get_symbol(c, state, 0);
if (f->ac == AC_RANGE_CUSTOM_TAB) {
- for (i = 1; i < 256; i++)
+ for (int i = 1; i < 256; i++)
f->state_transition[i] = get_symbol(c, state, 1) + c->one_state[i];
}
@@ -492,7 +492,7 @@ static int read_extra_header(FFV1Context *f)
return AVERROR_INVALIDDATA;
}
- for (i = 0; i < f->quant_table_count; i++) {
+ 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");
@@ -502,10 +502,10 @@ static int read_extra_header(FFV1Context *f)
if ((ret = ff_ffv1_allocate_initial_states(f)) < 0)
return ret;
- for (i = 0; i < f->quant_table_count; i++)
+ for (int i = 0; i < f->quant_table_count; i++)
if (get_rac(c, state)) {
- for (j = 0; j < f->context_count[i]; j++)
- for (k = 0; k < CONTEXT_SIZE; k++) {
+ 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;
@@ -550,7 +550,7 @@ static int read_extra_header(FFV1Context *f)
static int read_header(FFV1Context *f)
{
uint8_t state[CONTEXT_SIZE];
- int i, j, context_count = -1; //-1 to avoid warning
+ int context_count = -1; //-1 to avoid warning
RangeCoder *const c = &f->slice_context[0]->c;
memset(state, 128, sizeof(state));
@@ -566,7 +566,7 @@ static int read_header(FFV1Context *f)
f->ac = get_symbol(c, state, 0);
if (f->ac == AC_RANGE_CUSTOM_TAB) {
- for (i = 1; i < 256; i++) {
+ 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);
@@ -790,7 +790,7 @@ static int read_header(FFV1Context *f)
return AVERROR_INVALIDDATA;
}
- for (j = 0; j < f->slice_count; j++) {
+ for (int j = 0; j < f->slice_count; j++) {
FFV1Context *fs = f->slice_context[j];
fs->ac = f->ac;
fs->packed_at_lsb = f->packed_at_lsb;
@@ -819,7 +819,7 @@ static int read_header(FFV1Context *f)
&& (unsigned)fs->slice_y + (uint64_t)fs->slice_height <= f->height);
}
- for (i = 0; i < f->plane_count; i++) {
+ for (int i = 0; i < f->plane_count; i++) {
PlaneContext *const p = &fs->plane[i];
if (f->version == 2) {
@@ -874,7 +874,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
int buf_size = avpkt->size;
FFV1Context *f = avctx->priv_data;
RangeCoder *const c = &f->slice_context[0]->c;
- int i, ret, key_frame;
+ int ret, key_frame;
uint8_t keystate = 128;
uint8_t *buf_p;
AVFrame *p;
@@ -908,6 +908,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
} else {
int w = avctx->width;
int s = 1 + w / (1<<23);
+ int i;
w /= s;
@@ -941,7 +942,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
ff_thread_finish_setup(avctx);
buf_p = buf + buf_size;
- for (i = f->slice_count - 1; i >= 0; i--) {
+ for (int i = f->slice_count - 1; i >= 0; i--) {
FFV1Context *fs = f->slice_context[i];
int trailer = 3 + 5*!!f->ec;
int v;
@@ -991,15 +992,14 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
f->slice_count,
sizeof(void*));
- for (i = f->slice_count - 1; i >= 0; i--) {
+ for (int i = f->slice_count - 1; i >= 0; i--) {
FFV1Context *fs = f->slice_context[i];
- int j;
if (fs->slice_damaged && f->last_picture.f) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
const uint8_t *src[4];
uint8_t *dst[4];
ff_progress_frame_await(&f->last_picture, INT_MAX);
- for (j = 0; j < desc->nb_components; j++) {
+ for (int j = 0; j < desc->nb_components; j++) {
int pixshift = desc->comp[j].depth > 8;
int sh = (j == 1 || j == 2) ? f->chroma_h_shift : 0;
int sv = (j == 1 || j == 2) ? f->chroma_v_shift : 0;
@@ -1064,7 +1064,6 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
{
FFV1Context *fsrc = src->priv_data;
FFV1Context *fdst = dst->priv_data;
- int i;
if (dst == src)
return 0;
@@ -1075,7 +1074,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
sizeof(fdst->state_transition));
memcpy(fdst->quant_table, fsrc->quant_table, sizeof(fsrc->quant_table));
- for (i = 0; i < fdst->num_h_slices * fdst->num_v_slices; i++) {
+ for (int i = 0; i < fdst->num_h_slices * fdst->num_v_slices; i++) {
FFV1Context *fssrc = fsrc->slice_context[i];
FFV1Context *fsdst = fdst->slice_context[i];
copy_fields(fsdst, fssrc, fsrc);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 03/39] lavc/ffv1dec: simplify slice index calculation
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 02/39] lavc/ffv1dec: declare loop variables in the loop where possible Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 18:24 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 04/39] lavc/ffv1dec: drop FFV1Context.cur Anton Khirnov
` (36 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1dec.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 5c515e97b6..7066146477 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -259,10 +259,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
int width, height, x, y, ret;
const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step;
AVFrame * const p = f->cur;
- int si;
-
- for( si=0; fs != f->slice_context[si]; si ++)
- ;
+ const int si = (FFV1Context**)arg - f->slice_context;
if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
ff_progress_frame_await(&f->last_picture, si);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 04/39] lavc/ffv1dec: drop FFV1Context.cur
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 02/39] lavc/ffv1dec: declare loop variables in the loop where possible Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 03/39] lavc/ffv1dec: simplify slice index calculation Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 18:27 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 05/39] lavc/ffv1dec: drop a pointless variable in decode_slice() Anton Khirnov
` (35 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
It is merely a pointer to FFV1Context.picture.f, which can just as well
be used directly.
---
libavcodec/ffv1.h | 1 -
libavcodec/ffv1dec.c | 33 +++++++++++++++++----------------
2 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index acec22e83e..d99367ce81 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -89,7 +89,6 @@ typedef struct FFV1Context {
ProgressFrame picture, last_picture;
struct FFV1Context *fsrc;
- AVFrame *cur;
const AVFrame *cur_enc_frame;
int plane_count;
int ac; ///< 1=range coder <-> 0=golomb rice
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 7066146477..60d04f04b9 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -163,7 +163,8 @@ static int decode_plane(FFV1Context *s, uint8_t *src,
return 0;
}
-static int decode_slice_header(const FFV1Context *f, FFV1Context *fs)
+static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
+ AVFrame *frame)
{
RangeCoder *c = &fs->c;
uint8_t state[CONTEXT_SIZE];
@@ -217,23 +218,23 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs)
ps = get_symbol(c, state, 0);
if (ps == 1) {
- f->cur->flags |= AV_FRAME_FLAG_INTERLACED;
- f->cur->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
+ frame->flags |= AV_FRAME_FLAG_INTERLACED;
+ frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;
} else if (ps == 2) {
- f->cur->flags |= AV_FRAME_FLAG_INTERLACED;
- f->cur->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST;
+ frame->flags |= AV_FRAME_FLAG_INTERLACED;
+ frame->flags &= ~AV_FRAME_FLAG_TOP_FIELD_FIRST;
} else if (ps == 3) {
- f->cur->flags &= ~AV_FRAME_FLAG_INTERLACED;
+ frame->flags &= ~AV_FRAME_FLAG_INTERLACED;
}
- f->cur->sample_aspect_ratio.num = get_symbol(c, state, 0);
- f->cur->sample_aspect_ratio.den = get_symbol(c, state, 0);
+ frame->sample_aspect_ratio.num = get_symbol(c, state, 0);
+ frame->sample_aspect_ratio.den = get_symbol(c, state, 0);
if (av_image_check_sar(f->width, f->height,
- f->cur->sample_aspect_ratio) < 0) {
+ frame->sample_aspect_ratio) < 0) {
av_log(f->avctx, AV_LOG_WARNING, "ignoring invalid SAR: %u/%u\n",
- f->cur->sample_aspect_ratio.num,
- f->cur->sample_aspect_ratio.den);
- f->cur->sample_aspect_ratio = (AVRational){ 0, 1 };
+ frame->sample_aspect_ratio.num,
+ frame->sample_aspect_ratio.den);
+ frame->sample_aspect_ratio = (AVRational){ 0, 1 };
}
if (fs->version > 3) {
@@ -258,7 +259,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
FFV1Context *f = fs->avctx->priv_data;
int width, height, x, y, ret;
const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step;
- AVFrame * const p = f->cur;
+ AVFrame * const p = f->picture.f;
const int si = (FFV1Context**)arg - f->slice_context;
if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
@@ -299,7 +300,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
if (f->version > 2) {
if (ff_ffv1_init_slice_state(f, fs) < 0)
return AVERROR(ENOMEM);
- if (decode_slice_header(f, fs) < 0) {
+ if (decode_slice_header(f, fs, p) < 0) {
fs->slice_x = fs->slice_y = fs->slice_height = fs->slice_width = 0;
fs->slice_damaged = 1;
return AVERROR_INVALIDDATA;
@@ -307,7 +308,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
}
if ((ret = ff_ffv1_init_slice_state(f, fs)) < 0)
return ret;
- if ((f->cur->flags & AV_FRAME_FLAG_KEY) || fs->slice_reset_contexts) {
+ if ((p->flags & AV_FRAME_FLAG_KEY) || fs->slice_reset_contexts) {
ff_ffv1_clear_slice_state(f, fs);
} else if (fs->slice_damaged) {
return AVERROR_INVALIDDATA;
@@ -920,7 +921,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
if (ret < 0)
return ret;
- f->cur = p = f->picture.f;
+ p = f->picture.f;
p->pict_type = AV_PICTURE_TYPE_I; //FIXME I vs. P
p->flags = (p->flags & ~AV_FRAME_FLAG_KEY) | key_frame;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 05/39] lavc/ffv1dec: drop a pointless variable in decode_slice()
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (2 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 04/39] lavc/ffv1dec: drop FFV1Context.cur Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 18:58 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 06/39] lavc/ffv1dec: move copy_fields() under HAVE_THREADS Anton Khirnov
` (34 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
fsdst is by construction always equal to fs, there is even an
av_assert1() checking that. Just use fs directly.
---
libavcodec/ffv1dec.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 60d04f04b9..dbb7e082a3 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -267,16 +267,14 @@ static int decode_slice(AVCodecContext *c, void *arg)
if(f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY)) {
FFV1Context *fssrc = f->fsrc->slice_context[si];
- FFV1Context *fsdst = f->slice_context[si];
- av_assert1(fsdst->plane_count == fssrc->plane_count);
- av_assert1(fsdst == fs);
+ av_assert1(fs->plane_count == fssrc->plane_count);
if (!(p->flags & AV_FRAME_FLAG_KEY))
- fsdst->slice_damaged |= fssrc->slice_damaged;
+ fs->slice_damaged |= fssrc->slice_damaged;
for (int i = 0; i < f->plane_count; i++) {
PlaneContext *psrc = &fssrc->plane[i];
- PlaneContext *pdst = &fsdst->plane[i];
+ PlaneContext *pdst = &fs->plane[i];
av_free(pdst->state);
av_free(pdst->vlc_state);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 06/39] lavc/ffv1dec: move copy_fields() under HAVE_THREADS
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (3 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 05/39] lavc/ffv1dec: drop a pointless variable in decode_slice() Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 18:58 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 07/39] lavc/ffv1: add a per-slice context Anton Khirnov
` (33 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
It is unused otherwise
---
libavcodec/ffv1dec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index dbb7e082a3..6d59355c23 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -1027,6 +1027,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
return buf_size;
}
+#if HAVE_THREADS
static void copy_fields(FFV1Context *fsdst, const FFV1Context *fssrc,
const FFV1Context *fsrc)
{
@@ -1055,7 +1056,6 @@ static void copy_fields(FFV1Context *fsdst, const FFV1Context *fssrc,
}
}
-#if HAVE_THREADS
static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
{
FFV1Context *fsrc = src->priv_data;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 07/39] lavc/ffv1: add a per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (4 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 06/39] lavc/ffv1dec: move copy_fields() under HAVE_THREADS Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:01 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 08/39] lavc/ffv1: move sample_buffer to the " Anton Khirnov
` (32 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
FFV1 decoder and encoder currently use the same struct - FFV1Context -
both as codec private data and per-slice context. For this purpose
FFV1Context contains an array of pointers to per-slice FFV1Context
instances.
This pattern is highly confusing, as it is not clear which fields are
per-slice and which per-codec.
Address this by adding a new struct storing only per-slice data. Start
by moving slice_{x,y,width,height} to it.
---
libavcodec/ffv1.c | 15 ++++++---
libavcodec/ffv1.h | 13 +++++---
libavcodec/ffv1dec.c | 76 ++++++++++++++++++++++++--------------------
libavcodec/ffv1enc.c | 25 ++++++++-------
4 files changed, 76 insertions(+), 53 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 6ec24fed4a..25f28287c0 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -108,7 +108,12 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
av_assert0(max_slice_count > 0);
+ f->slices = av_calloc(max_slice_count, sizeof(*f->slices));
+ if (!f->slices)
+ return AVERROR(ENOMEM);
+
for (i = 0; i < max_slice_count;) {
+ FFV1SliceContext *sc = &f->slices[i];
int sx = i % f->num_h_slices;
int sy = i / f->num_h_slices;
int sxs = f->avctx->width * sx / f->num_h_slices;
@@ -124,10 +129,10 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
memcpy(fs, f, sizeof(*fs));
memset(fs->rc_stat2, 0, sizeof(fs->rc_stat2));
- fs->slice_width = sxe - sxs;
- fs->slice_height = sye - sys;
- fs->slice_x = sxs;
- fs->slice_y = sys;
+ sc->slice_width = sxe - sxs;
+ sc->slice_height = sye - sys;
+ sc->slice_x = sxs;
+ sc->slice_y = sys;
fs->sample_buffer = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
sizeof(*fs->sample_buffer));
@@ -217,5 +222,7 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
for (i = 0; i < s->max_slice_count; i++)
av_freep(&s->slice_context[i]);
+ av_freep(&s->slices);
+
return 0;
}
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index d99367ce81..256904b283 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -69,6 +69,13 @@ typedef struct PlaneContext {
#define MAX_SLICES 1024
+typedef struct FFV1SliceContext {
+ int slice_width;
+ int slice_height;
+ int slice_x;
+ int slice_y;
+} FFV1SliceContext;
+
typedef struct FFV1Context {
AVClass *class;
AVCodecContext *avctx;
@@ -123,14 +130,12 @@ typedef struct FFV1Context {
int max_slice_count;
int num_v_slices;
int num_h_slices;
- int slice_width;
- int slice_height;
- int slice_x;
- int slice_y;
int slice_reset_contexts;
int slice_coding_mode;
int slice_rct_by_coef;
int slice_rct_ry_coef;
+
+ FFV1SliceContext *slices;
} FFV1Context;
int ff_ffv1_common_init(AVCodecContext *avctx);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 6d59355c23..28e4a05b21 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -164,7 +164,7 @@ static int decode_plane(FFV1Context *s, uint8_t *src,
}
static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
- AVFrame *frame)
+ FFV1SliceContext *sc, AVFrame *frame)
{
RangeCoder *c = &fs->c;
uint8_t state[CONTEXT_SIZE];
@@ -185,17 +185,17 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
if (sx > f->num_h_slices - sw || sy > f->num_v_slices - sh)
return AVERROR_INVALIDDATA;
- fs->slice_x = sx * (int64_t)f->width / f->num_h_slices;
- fs->slice_y = sy * (int64_t)f->height / f->num_v_slices;
- fs->slice_width = (sx + sw) * (int64_t)f->width / f->num_h_slices - fs->slice_x;
- fs->slice_height = (sy + sh) * (int64_t)f->height / f->num_v_slices - fs->slice_y;
+ sc->slice_x = sx * (int64_t)f->width / f->num_h_slices;
+ sc->slice_y = sy * (int64_t)f->height / f->num_v_slices;
+ sc->slice_width = (sx + sw) * (int64_t)f->width / f->num_h_slices - sc->slice_x;
+ sc->slice_height = (sy + sh) * (int64_t)f->height / f->num_v_slices - sc->slice_y;
- av_assert0((unsigned)fs->slice_width <= f->width &&
- (unsigned)fs->slice_height <= f->height);
- av_assert0 ( (unsigned)fs->slice_x + (uint64_t)fs->slice_width <= f->width
- && (unsigned)fs->slice_y + (uint64_t)fs->slice_height <= f->height);
+ av_assert0((unsigned)sc->slice_width <= f->width &&
+ (unsigned)sc->slice_height <= f->height);
+ av_assert0 ( (unsigned)sc->slice_x + (uint64_t)sc->slice_width <= f->width
+ && (unsigned)sc->slice_y + (uint64_t)sc->slice_height <= f->height);
- if (fs->ac == AC_GOLOMB_RICE && fs->slice_width >= (1<<23))
+ if (fs->ac == AC_GOLOMB_RICE && sc->slice_width >= (1<<23))
return AVERROR_INVALIDDATA;
for (unsigned i = 0; i < f->plane_count; i++) {
@@ -261,6 +261,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step;
AVFrame * const p = f->picture.f;
const int si = (FFV1Context**)arg - f->slice_context;
+ FFV1SliceContext *sc = &f->slices[si];
if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
ff_progress_frame_await(&f->last_picture, si);
@@ -298,8 +299,8 @@ static int decode_slice(AVCodecContext *c, void *arg)
if (f->version > 2) {
if (ff_ffv1_init_slice_state(f, fs) < 0)
return AVERROR(ENOMEM);
- if (decode_slice_header(f, fs, p) < 0) {
- fs->slice_x = fs->slice_y = fs->slice_height = fs->slice_width = 0;
+ if (decode_slice_header(f, fs, sc, p) < 0) {
+ sc->slice_x = sc->slice_y = sc->slice_height = sc->slice_width = 0;
fs->slice_damaged = 1;
return AVERROR_INVALIDDATA;
}
@@ -312,10 +313,10 @@ static int decode_slice(AVCodecContext *c, void *arg)
return AVERROR_INVALIDDATA;
}
- width = fs->slice_width;
- height = fs->slice_height;
- x = fs->slice_x;
- y = fs->slice_y;
+ width = sc->slice_width;
+ height = sc->slice_height;
+ x = sc->slice_x;
+ y = sc->slice_y;
if (fs->ac == AC_GOLOMB_RICE) {
if (f->version == 3 && f->micro_version > 1 || f->version > 3)
@@ -788,6 +789,7 @@ static int read_header(FFV1Context *f)
for (int j = 0; j < f->slice_count; j++) {
FFV1Context *fs = f->slice_context[j];
+ FFV1SliceContext *sc = &f->slices[j];
fs->ac = f->ac;
fs->packed_at_lsb = f->packed_at_lsb;
@@ -804,15 +806,15 @@ static int read_header(FFV1Context *f)
if (sx > f->num_h_slices - sw || sy > f->num_v_slices - sh)
return AVERROR_INVALIDDATA;
- fs->slice_x = sx * (int64_t)f->width / f->num_h_slices;
- fs->slice_y = sy * (int64_t)f->height / f->num_v_slices;
- fs->slice_width = (sx + sw) * (int64_t)f->width / f->num_h_slices - fs->slice_x;
- fs->slice_height = (sy + sh) * (int64_t)f->height / f->num_v_slices - fs->slice_y;
+ sc->slice_x = sx * (int64_t)f->width / f->num_h_slices;
+ sc->slice_y = sy * (int64_t)f->height / f->num_v_slices;
+ sc->slice_width = (sx + sw) * (int64_t)f->width / f->num_h_slices - sc->slice_x;
+ sc->slice_height = (sy + sh) * (int64_t)f->height / f->num_v_slices - sc->slice_y;
- av_assert0((unsigned)fs->slice_width <= f->width &&
- (unsigned)fs->slice_height <= f->height);
- av_assert0 ( (unsigned)fs->slice_x + (uint64_t)fs->slice_width <= f->width
- && (unsigned)fs->slice_y + (uint64_t)fs->slice_height <= f->height);
+ av_assert0((unsigned)sc->slice_width <= f->width &&
+ (unsigned)sc->slice_height <= f->height);
+ av_assert0 ( (unsigned)sc->slice_x + (uint64_t)sc->slice_width <= f->width
+ && (unsigned)sc->slice_y + (uint64_t)sc->slice_height <= f->height);
}
for (int i = 0; i < f->plane_count; i++) {
@@ -990,6 +992,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
for (int i = f->slice_count - 1; i >= 0; i--) {
FFV1Context *fs = f->slice_context[i];
+ FFV1SliceContext *sc = &f->slices[i];
if (fs->slice_damaged && f->last_picture.f) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
const uint8_t *src[4];
@@ -1000,9 +1003,9 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
int sh = (j == 1 || j == 2) ? f->chroma_h_shift : 0;
int sv = (j == 1 || j == 2) ? f->chroma_v_shift : 0;
dst[j] = p->data[j] + p->linesize[j] *
- (fs->slice_y >> sv) + ((fs->slice_x >> sh) << pixshift);
+ (sc->slice_y >> sv) + ((sc->slice_x >> sh) << pixshift);
src[j] = f->last_picture.f->data[j] + f->last_picture.f->linesize[j] *
- (fs->slice_y >> sv) + ((fs->slice_x >> sh) << pixshift);
+ (sc->slice_y >> sv) + ((sc->slice_x >> sh) << pixshift);
}
if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
@@ -1012,8 +1015,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
av_image_copy(dst, p->linesize, src,
f->last_picture.f->linesize,
avctx->pix_fmt,
- fs->slice_width,
- fs->slice_height);
+ sc->slice_width,
+ sc->slice_height);
}
}
ff_progress_frame_report(&f->picture, INT_MAX);
@@ -1048,12 +1051,6 @@ static void copy_fields(FFV1Context *fsdst, const FFV1Context *fssrc,
fsdst->packed_at_lsb = fsrc->packed_at_lsb;
fsdst->slice_count = fsrc->slice_count;
- if (fsrc->version<3){
- fsdst->slice_x = fssrc->slice_x;
- fsdst->slice_y = fssrc->slice_y;
- fsdst->slice_width = fssrc->slice_width;
- fsdst->slice_height = fssrc->slice_height;
- }
}
static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
@@ -1073,7 +1070,18 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
for (int i = 0; i < fdst->num_h_slices * fdst->num_v_slices; i++) {
FFV1Context *fssrc = fsrc->slice_context[i];
FFV1Context *fsdst = fdst->slice_context[i];
+
+ FFV1SliceContext *sc = &fdst->slices[i];
+ const FFV1SliceContext *sc0 = &fsrc->slices[i];
+
copy_fields(fsdst, fssrc, fsrc);
+
+ if (fsrc->version < 3) {
+ sc->slice_x = sc0->slice_x;
+ sc->slice_y = sc0->slice_y;
+ sc->slice_width = sc0->slice_width;
+ sc->slice_height = sc0->slice_height;
+ }
}
av_assert0(!fdst->plane[0].state);
av_assert0(!fdst->sample_buffer);
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 94d9215acd..c46df15b0c 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -370,7 +370,7 @@ static void write_header(FFV1Context *f)
} else if (f->version < 3) {
put_symbol(c, state, f->slice_count, 0);
for (i = 0; i < f->slice_count; i++) {
- FFV1Context *fs = f->slice_context[i];
+ FFV1SliceContext *fs = &f->slices[i];
put_symbol(c, state,
(fs->slice_x + 1) * f->num_h_slices / f->width, 0);
put_symbol(c, state,
@@ -904,17 +904,18 @@ slices_ok:
return 0;
}
-static void encode_slice_header(FFV1Context *f, FFV1Context *fs)
+static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
+ FFV1SliceContext *sc)
{
RangeCoder *c = &fs->c;
uint8_t state[CONTEXT_SIZE];
int j;
memset(state, 128, sizeof(state));
- put_symbol(c, state, (fs->slice_x +1)*f->num_h_slices / f->width , 0);
- put_symbol(c, state, (fs->slice_y +1)*f->num_v_slices / f->height , 0);
- put_symbol(c, state, (fs->slice_width +1)*f->num_h_slices / f->width -1, 0);
- put_symbol(c, state, (fs->slice_height+1)*f->num_v_slices / f->height-1, 0);
+ put_symbol(c, state, (sc->slice_x +1)*f->num_h_slices / f->width , 0);
+ put_symbol(c, state, (sc->slice_y +1)*f->num_v_slices / f->height , 0);
+ put_symbol(c, state, (sc->slice_width +1)*f->num_h_slices / f->width -1, 0);
+ put_symbol(c, state, (sc->slice_height+1)*f->num_v_slices / f->height-1, 0);
for (j=0; j<f->plane_count; j++) {
put_symbol(c, state, f->plane[j].quant_table_index, 0);
av_assert0(f->plane[j].quant_table_index == f->context_model);
@@ -1023,10 +1024,12 @@ static int encode_slice(AVCodecContext *c, void *arg)
{
FFV1Context *fs = *(void **)arg;
FFV1Context *f = fs->avctx->priv_data;
- int width = fs->slice_width;
- int height = fs->slice_height;
- int x = fs->slice_x;
- int y = fs->slice_y;
+ const int si = (FFV1Context**)arg - f->slice_context;
+ FFV1SliceContext *sc = &f->slices[si];
+ int width = sc->slice_width;
+ int height = sc->slice_height;
+ int x = sc->slice_x;
+ int y = sc->slice_y;
const AVFrame *const p = f->cur_enc_frame;
const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step;
int ret;
@@ -1048,7 +1051,7 @@ retry:
if (f->key_frame)
ff_ffv1_clear_slice_state(f, fs);
if (f->version > 2) {
- encode_slice_header(f, fs);
+ encode_slice_header(f, fs, sc);
}
if (fs->ac == AC_GOLOMB_RICE) {
fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&fs->c, f->version > 2) : 0;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 08/39] lavc/ffv1: move sample_buffer to the per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (5 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 07/39] lavc/ffv1: add a per-slice context Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:04 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 09/39] lavc/ffv1: move run_index " Anton Khirnov
` (31 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.c | 35 ++++++++++++++++++++---------------
libavcodec/ffv1.h | 5 +++--
libavcodec/ffv1dec.c | 27 +++++++++++++--------------
libavcodec/ffv1dec_template.c | 9 +++++----
libavcodec/ffv1enc.c | 30 ++++++++++++++++--------------
libavcodec/ffv1enc_template.c | 9 +++++----
6 files changed, 62 insertions(+), 53 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 25f28287c0..a102425596 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -112,6 +112,8 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
if (!f->slices)
return AVERROR(ENOMEM);
+ f->max_slice_count = max_slice_count;
+
for (i = 0; i < max_slice_count;) {
FFV1SliceContext *sc = &f->slices[i];
int sx = i % f->num_h_slices;
@@ -123,7 +125,7 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
FFV1Context *fs = av_mallocz(sizeof(*fs));
if (!fs)
- goto memfail;
+ return AVERROR(ENOMEM);
f->slice_context[i++] = fs;
memcpy(fs, f, sizeof(*fs));
@@ -134,19 +136,15 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
sc->slice_x = sxs;
sc->slice_y = sys;
- fs->sample_buffer = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
- sizeof(*fs->sample_buffer));
- fs->sample_buffer32 = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
- sizeof(*fs->sample_buffer32));
- if (!fs->sample_buffer || !fs->sample_buffer32)
- goto memfail;
+ sc->sample_buffer = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
+ sizeof(*sc->sample_buffer));
+ sc->sample_buffer32 = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
+ sizeof(*sc->sample_buffer32));
+ if (!sc->sample_buffer || !sc->sample_buffer32)
+ return AVERROR(ENOMEM);
}
- f->max_slice_count = max_slice_count;
- return 0;
-memfail:
- f->max_slice_count = i;
- return AVERROR(ENOMEM);
+ return 0;
}
int ff_ffv1_allocate_initial_states(FFV1Context *f)
@@ -199,14 +197,20 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
for (j = 0; j < s->max_slice_count; j++) {
FFV1Context *fs = s->slice_context[j];
+ FFV1SliceContext *sc = &s->slices[j];
+
+ av_freep(&sc->sample_buffer);
+ av_freep(&sc->sample_buffer32);
+
+ if (!fs)
+ continue;
+
for (i = 0; i < s->plane_count; i++) {
PlaneContext *p = &fs->plane[i];
av_freep(&p->state);
av_freep(&p->vlc_state);
}
- av_freep(&fs->sample_buffer);
- av_freep(&fs->sample_buffer32);
}
av_freep(&avctx->stats_out);
@@ -214,7 +218,8 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
av_freep(&s->initial_states[j]);
for (i = 0; i < s->max_slice_count; i++) {
FFV1Context *sf = s->slice_context[i];
- av_freep(&sf->rc_stat2[j]);
+ if (sf)
+ av_freep(&sf->rc_stat2[j]);
}
av_freep(&s->rc_stat2[j]);
}
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 256904b283..ccb510a483 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -70,6 +70,9 @@ typedef struct PlaneContext {
#define MAX_SLICES 1024
typedef struct FFV1SliceContext {
+ int16_t *sample_buffer;
+ int32_t *sample_buffer32;
+
int slice_width;
int slice_height;
int slice_x;
@@ -108,8 +111,6 @@ typedef struct FFV1Context {
uint8_t (*initial_states[MAX_QUANT_TABLES])[32];
int run_index;
int colorspace;
- int16_t *sample_buffer;
- int32_t *sample_buffer32;
int use32bit;
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 28e4a05b21..fcf8977a36 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -117,18 +117,18 @@ static int is_input_end(FFV1Context *s)
#define RENAME(name) name ## 32
#include "ffv1dec_template.c"
-static int decode_plane(FFV1Context *s, uint8_t *src,
- int w, int h, int stride, int plane_index,
+static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
+ uint8_t *src, int w, int h, int stride, int plane_index,
int pixel_stride)
{
int x, y;
int16_t *sample[2];
- sample[0] = s->sample_buffer + 3;
- sample[1] = s->sample_buffer + w + 6 + 3;
+ sample[0] = sc->sample_buffer + 3;
+ sample[1] = sc->sample_buffer + w + 6 + 3;
s->run_index = 0;
- memset(s->sample_buffer, 0, 2 * (w + 6) * sizeof(*s->sample_buffer));
+ memset(sc->sample_buffer, 0, 2 * (w + 6) * sizeof(*sc->sample_buffer));
for (y = 0; y < h; y++) {
int16_t *temp = sample[0]; // FIXME: try a normal buffer
@@ -333,29 +333,29 @@ static int decode_slice(AVCodecContext *c, void *arg)
const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift);
const int cx = x >> f->chroma_h_shift;
const int cy = y >> f->chroma_v_shift;
- decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
+ decode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
if (f->chroma_planes) {
- decode_plane(fs, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
- decode_plane(fs, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
+ decode_plane(fs, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
+ decode_plane(fs, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
if (fs->transparency)
- decode_plane(fs, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
+ decode_plane(fs, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
} else if (f->colorspace == 0) {
- decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
- decode_plane(fs, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
+ decode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
+ decode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame32(fs, planes, width, height, p->linesize);
+ decode_rgb_frame32(fs, sc, planes, width, height, p->linesize);
} else {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame(fs, planes, width, height, p->linesize);
+ decode_rgb_frame(fs, sc, planes, width, height, p->linesize);
}
if (fs->ac != AC_GOLOMB_RICE && f->version > 2) {
int v;
@@ -1084,7 +1084,6 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
}
}
av_assert0(!fdst->plane[0].state);
- av_assert0(!fdst->sample_buffer);
av_assert1(fdst->max_slice_count == fsrc->max_slice_count);
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index a90c28cd0e..b9316e04ca 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -127,7 +127,8 @@ static av_always_inline int RENAME(decode_line)(FFV1Context *s, int w,
return 0;
}
-static int RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int h, int stride[4])
+static int RENAME(decode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
+ uint8_t *src[4], int w, int h, int stride[4])
{
int x, y, p;
TYPE *sample[4][2];
@@ -137,13 +138,13 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, uint8_t *src[4], int w, int
int transparency = s->transparency;
for (x = 0; x < 4; x++) {
- sample[x][0] = RENAME(s->sample_buffer) + x * 2 * (w + 6) + 3;
- sample[x][1] = RENAME(s->sample_buffer) + (x * 2 + 1) * (w + 6) + 3;
+ sample[x][0] = RENAME(sc->sample_buffer) + x * 2 * (w + 6) + 3;
+ sample[x][1] = RENAME(sc->sample_buffer) + (x * 2 + 1) * (w + 6) + 3;
}
s->run_index = 0;
- memset(RENAME(s->sample_buffer), 0, 8 * (w + 6) * sizeof(*RENAME(s->sample_buffer)));
+ memset(RENAME(sc->sample_buffer), 0, 8 * (w + 6) * sizeof(*RENAME(sc->sample_buffer)));
for (y = 0; y < h; y++) {
for (p = 0; p < 3 + transparency; p++) {
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index c46df15b0c..f6b1919ee4 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -269,7 +269,8 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state,
#define RENAME(name) name ## 32
#include "ffv1enc_template.c"
-static int encode_plane(FFV1Context *s, const uint8_t *src, int w, int h,
+static int encode_plane(FFV1Context *s, FFV1SliceContext *sc,
+ const uint8_t *src, int w, int h,
int stride, int plane_index, int pixel_stride)
{
int x, y, i, ret;
@@ -277,11 +278,11 @@ static int encode_plane(FFV1Context *s, const uint8_t *src, int w, int h,
int16_t *sample[3];
s->run_index = 0;
- memset(s->sample_buffer, 0, ring_size * (w + 6) * sizeof(*s->sample_buffer));
+ memset(sc->sample_buffer, 0, ring_size * (w + 6) * sizeof(*sc->sample_buffer));
for (y = 0; y < h; y++) {
for (i = 0; i < ring_size; i++)
- sample[i] = s->sample_buffer + (w + 6) * ((h + i - y) % ring_size) + 3;
+ sample[i] = sc->sample_buffer + (w + 6) * ((h + i - y) % ring_size) + 3;
sample[0][-1]= sample[1][0 ];
sample[1][ w]= sample[1][w-1];
@@ -938,7 +939,8 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
}
}
-static void choose_rct_params(FFV1Context *fs, const uint8_t *src[3], const int stride[3], int w, int h)
+static void choose_rct_params(FFV1Context *fs, FFV1SliceContext *sc,
+ const uint8_t *src[3], const int stride[3], int w, int h)
{
#define NB_Y_COEFF 15
static const int rct_y_coeff[15][2] = {
@@ -968,7 +970,7 @@ static void choose_rct_params(FFV1Context *fs, const uint8_t *src[3], const int
for (y = 0; y < h; y++) {
int lastr=0, lastg=0, lastb=0;
for (p = 0; p < 3; p++)
- sample[p] = fs->sample_buffer + p*w;
+ sample[p] = sc->sample_buffer + p*w;
for (x = 0; x < w; x++) {
int b, g, r;
@@ -1041,7 +1043,7 @@ static int encode_slice(AVCodecContext *c, void *arg)
fs->slice_coding_mode = 0;
if (f->version > 3) {
- choose_rct_params(fs, planes, p->linesize, width, height);
+ choose_rct_params(fs, sc, planes, p->linesize, width, height);
} else {
fs->slice_rct_by_coef = 1;
fs->slice_rct_ry_coef = 1;
@@ -1066,21 +1068,21 @@ retry:
const int cx = x >> f->chroma_h_shift;
const int cy = y >> f->chroma_v_shift;
- ret = encode_plane(fs, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
+ ret = encode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
if (f->chroma_planes) {
- ret |= encode_plane(fs, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
- ret |= encode_plane(fs, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
+ ret |= encode_plane(fs, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
+ ret |= encode_plane(fs, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
if (fs->transparency)
- ret |= encode_plane(fs, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
+ ret |= encode_plane(fs, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
} else if (c->pix_fmt == AV_PIX_FMT_YA8) {
- ret = encode_plane(fs, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
- ret |= encode_plane(fs, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
+ ret = encode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
+ ret |= encode_plane(fs, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
- ret = encode_rgb_frame32(fs, planes, width, height, p->linesize);
+ ret = encode_rgb_frame32(fs, sc, planes, width, height, p->linesize);
} else {
- ret = encode_rgb_frame(fs, planes, width, height, p->linesize);
+ ret = encode_rgb_frame(fs, sc, planes, width, height, p->linesize);
}
if (ret < 0) {
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 8953dbe07c..85fbac224b 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -124,7 +124,8 @@ static av_always_inline int RENAME(encode_line)(FFV1Context *s, int w,
return 0;
}
-static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
+static int RENAME(encode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
+ const uint8_t *src[4],
int w, int h, const int stride[4])
{
int x, y, p, i;
@@ -139,13 +140,13 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, const uint8_t *src[4],
s->run_index = 0;
- memset(RENAME(s->sample_buffer), 0, ring_size * MAX_PLANES *
- (w + 6) * sizeof(*RENAME(s->sample_buffer)));
+ memset(RENAME(sc->sample_buffer), 0, ring_size * MAX_PLANES *
+ (w + 6) * sizeof(*RENAME(sc->sample_buffer)));
for (y = 0; y < h; y++) {
for (i = 0; i < ring_size; i++)
for (p = 0; p < MAX_PLANES; p++)
- sample[p][i]= RENAME(s->sample_buffer) + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3;
+ sample[p][i]= RENAME(sc->sample_buffer) + p*ring_size*(w+6) + ((h+i-y)%ring_size)*(w+6) + 3;
for (x = 0; x < w; x++) {
int b, g, r, av_uninit(a);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 09/39] lavc/ffv1: move run_index to the per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (6 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 08/39] lavc/ffv1: move sample_buffer to the " Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-17 22:49 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack Anton Khirnov
` (30 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.h | 3 ++-
libavcodec/ffv1dec.c | 6 +++---
libavcodec/ffv1dec_template.c | 16 ++++++++--------
libavcodec/ffv1enc.c | 6 +++---
libavcodec/ffv1enc_template.c | 16 ++++++++--------
5 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index ccb510a483..68d13a2964 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -77,6 +77,8 @@ typedef struct FFV1SliceContext {
int slice_height;
int slice_x;
int slice_y;
+
+ int run_index;
} FFV1SliceContext;
typedef struct FFV1Context {
@@ -109,7 +111,6 @@ typedef struct FFV1Context {
int context_count[MAX_QUANT_TABLES];
uint8_t state_transition[256];
uint8_t (*initial_states[MAX_QUANT_TABLES])[32];
- int run_index;
int colorspace;
int use32bit;
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index fcf8977a36..a2971d7eea 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -126,7 +126,7 @@ static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
sample[0] = sc->sample_buffer + 3;
sample[1] = sc->sample_buffer + w + 6 + 3;
- s->run_index = 0;
+ sc->run_index = 0;
memset(sc->sample_buffer, 0, 2 * (w + 6) * sizeof(*sc->sample_buffer));
@@ -140,13 +140,13 @@ static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
sample[0][w] = sample[0][w - 1];
if (s->avctx->bits_per_raw_sample <= 8) {
- int ret = decode_line(s, w, sample, plane_index, 8);
+ int ret = decode_line(s, sc, w, sample, plane_index, 8);
if (ret < 0)
return ret;
for (x = 0; x < w; x++)
src[x*pixel_stride + stride * y] = sample[1][x];
} else {
- int ret = decode_line(s, w, sample, plane_index, s->avctx->bits_per_raw_sample);
+ int ret = decode_line(s, sc, w, sample, plane_index, s->avctx->bits_per_raw_sample);
if (ret < 0)
return ret;
if (s->packed_at_lsb) {
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index b9316e04ca..8e2e38c0b9 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -22,16 +22,16 @@
#include "ffv1_template.c"
-static av_always_inline int RENAME(decode_line)(FFV1Context *s, int w,
- TYPE *sample[2],
- int plane_index, int bits)
+static av_always_inline int
+RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, int w,
+ TYPE *sample[2], int plane_index, int bits)
{
PlaneContext *const p = &s->plane[plane_index];
RangeCoder *const c = &s->c;
int x;
int run_count = 0;
int run_mode = 0;
- int run_index = s->run_index;
+ int run_index = sc->run_index;
if (is_input_end(s))
return AVERROR_INVALIDDATA;
@@ -123,7 +123,7 @@ static av_always_inline int RENAME(decode_line)(FFV1Context *s, int w,
sample[1][x] = av_zero_extend(RENAME(predict)(sample[1] + x, sample[0] + x) + (SUINT)diff, bits);
}
- s->run_index = run_index;
+ sc->run_index = run_index;
return 0;
}
@@ -142,7 +142,7 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
sample[x][1] = RENAME(sc->sample_buffer) + (x * 2 + 1) * (w + 6) + 3;
}
- s->run_index = 0;
+ sc->run_index = 0;
memset(RENAME(sc->sample_buffer), 0, 8 * (w + 6) * sizeof(*RENAME(sc->sample_buffer)));
@@ -157,9 +157,9 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
sample[p][1][-1]= sample[p][0][0 ];
sample[p][0][ w]= sample[p][0][w-1];
if (lbd && s->slice_coding_mode == 0)
- ret = RENAME(decode_line)(s, w, sample[p], (p + 1)/2, 9);
+ ret = RENAME(decode_line)(s, sc, w, sample[p], (p + 1)/2, 9);
else
- ret = RENAME(decode_line)(s, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(decode_line)(s, sc, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index f6b1919ee4..8bb9174a1d 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -276,7 +276,7 @@ static int encode_plane(FFV1Context *s, FFV1SliceContext *sc,
int x, y, i, ret;
const int ring_size = s->context_model ? 3 : 2;
int16_t *sample[3];
- s->run_index = 0;
+ sc->run_index = 0;
memset(sc->sample_buffer, 0, ring_size * (w + 6) * sizeof(*sc->sample_buffer));
@@ -289,7 +289,7 @@ static int encode_plane(FFV1Context *s, FFV1SliceContext *sc,
if (s->bits_per_raw_sample <= 8) {
for (x = 0; x < w; x++)
sample[0][x] = src[x * pixel_stride + stride * y];
- if((ret = encode_line(s, w, sample, plane_index, 8)) < 0)
+ if((ret = encode_line(s, sc, w, sample, plane_index, 8)) < 0)
return ret;
} else {
if (s->packed_at_lsb) {
@@ -301,7 +301,7 @@ static int encode_plane(FFV1Context *s, FFV1SliceContext *sc,
sample[0][x] = ((uint16_t*)(src + stride*y))[x] >> (16 - s->bits_per_raw_sample);
}
}
- if((ret = encode_line(s, w, sample, plane_index, s->bits_per_raw_sample)) < 0)
+ if((ret = encode_line(s, sc, w, sample, plane_index, s->bits_per_raw_sample)) < 0)
return ret;
}
}
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 85fbac224b..4dccd531a8 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -22,14 +22,14 @@
#include "ffv1_template.c"
-static av_always_inline int RENAME(encode_line)(FFV1Context *s, int w,
- TYPE *sample[3],
- int plane_index, int bits)
+static av_always_inline int
+RENAME(encode_line)(FFV1Context *s, FFV1SliceContext *sc,
+ int w, TYPE *sample[3], int plane_index, int bits)
{
PlaneContext *const p = &s->plane[plane_index];
RangeCoder *const c = &s->c;
int x;
- int run_index = s->run_index;
+ int run_index = sc->run_index;
int run_count = 0;
int run_mode = 0;
@@ -119,7 +119,7 @@ static av_always_inline int RENAME(encode_line)(FFV1Context *s, int w,
if (run_count)
put_bits(&s->pb, 1, 1);
}
- s->run_index = run_index;
+ sc->run_index = run_index;
return 0;
}
@@ -138,7 +138,7 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
int transparency = s->transparency;
int packed_size = (3 + transparency)*2;
- s->run_index = 0;
+ sc->run_index = 0;
memset(RENAME(sc->sample_buffer), 0, ring_size * MAX_PLANES *
(w + 6) * sizeof(*RENAME(sc->sample_buffer)));
@@ -193,9 +193,9 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
sample[p][0][-1] = sample[p][1][0 ];
sample[p][1][ w] = sample[p][1][w-1];
if (lbd && s->slice_coding_mode == 0)
- ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, 9);
+ ret = RENAME(encode_line)(s, sc, w, sample[p], (p + 1) / 2, 9);
else
- ret = RENAME(encode_line)(s, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(encode_line)(s, sc, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (7 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 09/39] lavc/ffv1: move run_index " Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-17 22:42 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 11/39] lavc/ffv1enc: move bit writer to per-slice context Anton Khirnov
` (29 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
There is no reason to place it in persistent state.
---
libavcodec/ffv1.h | 1 -
libavcodec/ffv1dec.c | 28 +++++++++++++++-------------
libavcodec/ffv1dec_template.c | 23 ++++++++++++-----------
3 files changed, 27 insertions(+), 25 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 68d13a2964..c88aa8c30d 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -85,7 +85,6 @@ typedef struct FFV1Context {
AVClass *class;
AVCodecContext *avctx;
RangeCoder c;
- GetBitContext gb;
PutBitContext pb;
uint64_t rc_stat[256][2];
uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2];
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index a2971d7eea..a1f7206871 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -94,14 +94,14 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state,
return ret;
}
-static int is_input_end(FFV1Context *s)
+static int is_input_end(FFV1Context *s, GetBitContext *gb)
{
if (s->ac != AC_GOLOMB_RICE) {
RangeCoder *const c = &s->c;
if (c->overread > MAX_OVERREAD)
return AVERROR_INVALIDDATA;
} else {
- if (get_bits_left(&s->gb) < 1)
+ if (get_bits_left(gb) < 1)
return AVERROR_INVALIDDATA;
}
return 0;
@@ -118,6 +118,7 @@ static int is_input_end(FFV1Context *s)
#include "ffv1dec_template.c"
static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
+ GetBitContext *gb,
uint8_t *src, int w, int h, int stride, int plane_index,
int pixel_stride)
{
@@ -140,13 +141,13 @@ static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
sample[0][w] = sample[0][w - 1];
if (s->avctx->bits_per_raw_sample <= 8) {
- int ret = decode_line(s, sc, w, sample, plane_index, 8);
+ int ret = decode_line(s, sc, gb, w, sample, plane_index, 8);
if (ret < 0)
return ret;
for (x = 0; x < w; x++)
src[x*pixel_stride + stride * y] = sample[1][x];
} else {
- int ret = decode_line(s, sc, w, sample, plane_index, s->avctx->bits_per_raw_sample);
+ int ret = decode_line(s, sc, gb, w, sample, plane_index, s->avctx->bits_per_raw_sample);
if (ret < 0)
return ret;
if (s->packed_at_lsb) {
@@ -262,6 +263,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
AVFrame * const p = f->picture.f;
const int si = (FFV1Context**)arg - f->slice_context;
FFV1SliceContext *sc = &f->slices[si];
+ GetBitContext gb;
if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
ff_progress_frame_await(&f->last_picture, si);
@@ -322,7 +324,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
if (f->version == 3 && f->micro_version > 1 || f->version > 3)
get_rac(&fs->c, (uint8_t[]) { 129 });
fs->ac_byte_count = f->version > 2 || (!x && !y) ? fs->c.bytestream - fs->c.bytestream_start - 1 : 0;
- init_get_bits(&fs->gb,
+ init_get_bits(&gb,
fs->c.bytestream_start + fs->ac_byte_count,
(fs->c.bytestream_end - fs->c.bytestream_start - fs->ac_byte_count) * 8);
}
@@ -333,29 +335,29 @@ static int decode_slice(AVCodecContext *c, void *arg)
const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift);
const int cx = x >> f->chroma_h_shift;
const int cy = y >> f->chroma_v_shift;
- decode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
+ decode_plane(fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
if (f->chroma_planes) {
- decode_plane(fs, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
- decode_plane(fs, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
+ decode_plane(fs, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
+ decode_plane(fs, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
if (fs->transparency)
- decode_plane(fs, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
+ decode_plane(fs, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
} else if (f->colorspace == 0) {
- decode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
- decode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
+ decode_plane(fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
+ decode_plane(fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame32(fs, sc, planes, width, height, p->linesize);
+ decode_rgb_frame32(fs, sc, &gb, planes, width, height, p->linesize);
} else {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame(fs, sc, planes, width, height, p->linesize);
+ decode_rgb_frame(fs, sc, &gb, planes, width, height, p->linesize);
}
if (fs->ac != AC_GOLOMB_RICE && f->version > 2) {
int v;
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index 8e2e38c0b9..e9d3002be9 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -23,8 +23,8 @@
#include "ffv1_template.c"
static av_always_inline int
-RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, int w,
- TYPE *sample[2], int plane_index, int bits)
+RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, GetBitContext *gb,
+ int w, TYPE *sample[2], int plane_index, int bits)
{
PlaneContext *const p = &s->plane[plane_index];
RangeCoder *const c = &s->c;
@@ -33,7 +33,7 @@ RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, int w,
int run_mode = 0;
int run_index = sc->run_index;
- if (is_input_end(s))
+ if (is_input_end(s, gb))
return AVERROR_INVALIDDATA;
if (s->slice_coding_mode == 1) {
@@ -53,7 +53,7 @@ RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, int w,
int diff, context, sign;
if (!(x & 1023)) {
- if (is_input_end(s))
+ if (is_input_end(s, gb))
return AVERROR_INVALIDDATA;
}
@@ -74,13 +74,13 @@ RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, int w,
if (run_mode) {
if (run_count == 0 && run_mode == 1) {
- if (get_bits1(&s->gb)) {
+ if (get_bits1(gb)) {
run_count = 1 << ff_log2_run[run_index];
if (x + run_count <= w)
run_index++;
} else {
if (ff_log2_run[run_index])
- run_count = get_bits(&s->gb, ff_log2_run[run_index]);
+ run_count = get_bits(gb, ff_log2_run[run_index]);
else
run_count = 0;
if (run_index)
@@ -105,17 +105,17 @@ RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, int w,
if (run_count < 0) {
run_mode = 0;
run_count = 0;
- diff = get_vlc_symbol(&s->gb, &p->vlc_state[context],
+ diff = get_vlc_symbol(gb, &p->vlc_state[context],
bits);
if (diff >= 0)
diff++;
} else
diff = 0;
} else
- diff = get_vlc_symbol(&s->gb, &p->vlc_state[context], bits);
+ diff = get_vlc_symbol(gb, &p->vlc_state[context], bits);
ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
- run_count, run_index, run_mode, x, get_bits_count(&s->gb));
+ run_count, run_index, run_mode, x, get_bits_count(gb));
}
if (sign)
@@ -128,6 +128,7 @@ RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, int w,
}
static int RENAME(decode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
+ GetBitContext *gb,
uint8_t *src[4], int w, int h, int stride[4])
{
int x, y, p;
@@ -157,9 +158,9 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
sample[p][1][-1]= sample[p][0][0 ];
sample[p][0][ w]= sample[p][0][w-1];
if (lbd && s->slice_coding_mode == 0)
- ret = RENAME(decode_line)(s, sc, w, sample[p], (p + 1)/2, 9);
+ ret = RENAME(decode_line)(s, sc, gb, w, sample[p], (p + 1)/2, 9);
else
- ret = RENAME(decode_line)(s, sc, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(decode_line)(s, sc, gb, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 11/39] lavc/ffv1enc: move bit writer to per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (8 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:07 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 12/39] lavc/ffv1: drop redundant FFV1Context.quant_table Anton Khirnov
` (28 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.h | 3 ++-
libavcodec/ffv1enc.c | 7 ++++---
libavcodec/ffv1enc_template.c | 14 +++++++-------
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index c88aa8c30d..dce6e177eb 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -79,13 +79,14 @@ typedef struct FFV1SliceContext {
int slice_y;
int run_index;
+
+ PutBitContext pb;
} FFV1SliceContext;
typedef struct FFV1Context {
AVClass *class;
AVCodecContext *avctx;
RangeCoder c;
- PutBitContext pb;
uint64_t rc_stat[256][2];
uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2];
int version;
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 8bb9174a1d..5692bfa1fc 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1057,7 +1057,7 @@ retry:
}
if (fs->ac == AC_GOLOMB_RICE) {
fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&fs->c, f->version > 2) : 0;
- init_put_bits(&fs->pb,
+ init_put_bits(&sc->pb,
fs->c.bytestream_start + fs->ac_byte_count,
fs->c.bytestream_end - fs->c.bytestream_start - fs->ac_byte_count);
}
@@ -1209,13 +1209,14 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
buf_p = pkt->data;
for (i = 0; i < f->slice_count; i++) {
FFV1Context *fs = f->slice_context[i];
+ FFV1SliceContext *sc = &f->slices[i];
int bytes;
if (fs->ac != AC_GOLOMB_RICE) {
bytes = ff_rac_terminate(&fs->c, 1);
} else {
- flush_put_bits(&fs->pb); // FIXME: nicer padding
- bytes = fs->ac_byte_count + put_bytes_output(&fs->pb);
+ flush_put_bits(&sc->pb); // FIXME: nicer padding
+ bytes = fs->ac_byte_count + put_bytes_output(&sc->pb);
}
if (i > 0 || f->version > 2) {
av_assert0(bytes < pkt->size / f->slice_count);
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 4dccd531a8..8b9e53fa1b 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -39,7 +39,7 @@ RENAME(encode_line)(FFV1Context *s, FFV1SliceContext *sc,
return AVERROR_INVALIDDATA;
}
} else {
- if (put_bytes_left(&s->pb, 0) < w * 4) {
+ if (put_bytes_left(&sc->pb, 0) < w * 4) {
av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return AVERROR_INVALIDDATA;
}
@@ -86,10 +86,10 @@ RENAME(encode_line)(FFV1Context *s, FFV1SliceContext *sc,
while (run_count >= 1 << ff_log2_run[run_index]) {
run_count -= 1 << ff_log2_run[run_index];
run_index++;
- put_bits(&s->pb, 1, 1);
+ put_bits(&sc->pb, 1, 1);
}
- put_bits(&s->pb, 1 + ff_log2_run[run_index], run_count);
+ put_bits(&sc->pb, 1 + ff_log2_run[run_index], run_count);
if (run_index)
run_index--;
run_count = 0;
@@ -103,21 +103,21 @@ RENAME(encode_line)(FFV1Context *s, FFV1SliceContext *sc,
ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
run_count, run_index, run_mode, x,
- (int)put_bits_count(&s->pb));
+ (int)put_bits_count(&sc->pb));
if (run_mode == 0)
- put_vlc_symbol(&s->pb, &p->vlc_state[context], diff, bits);
+ put_vlc_symbol(&sc->pb, &p->vlc_state[context], diff, bits);
}
}
if (run_mode) {
while (run_count >= 1 << ff_log2_run[run_index]) {
run_count -= 1 << ff_log2_run[run_index];
run_index++;
- put_bits(&s->pb, 1, 1);
+ put_bits(&sc->pb, 1, 1);
}
if (run_count)
- put_bits(&s->pb, 1, 1);
+ put_bits(&sc->pb, 1, 1);
}
sc->run_index = run_index;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 12/39] lavc/ffv1: drop redundant FFV1Context.quant_table
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (9 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 11/39] lavc/ffv1enc: move bit writer to per-slice context Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-17 22:37 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table Anton Khirnov
` (27 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
In all cases except decoding version 1 it's either not used, or contains
a copy of a table from quant_tables, which we can just as well use
directly.
When decoding version 1, we can just as well decode into
quant_tables[0], which would otherwise be unused.
---
libavcodec/ffv1.h | 1 -
libavcodec/ffv1dec.c | 10 +++++++---
libavcodec/ffv1enc.c | 6 ++----
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index dce6e177eb..4d57172d5b 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -106,7 +106,6 @@ typedef struct FFV1Context {
int ac; ///< 1=range coder <-> 0=golomb rice
int ac_byte_count; ///< number of bytes used for AC coding
PlaneContext plane[MAX_PLANES];
- int16_t quant_table[MAX_CONTEXT_INPUTS][256];
int16_t quant_tables[MAX_QUANT_TABLES][MAX_CONTEXT_INPUTS][256];
int context_count[MAX_QUANT_TABLES];
uint8_t state_transition[256];
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index a1f7206871..66d9f63c1a 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -764,7 +764,7 @@ static int read_header(FFV1Context *f)
ff_dlog(f->avctx, "%d %d %d\n",
f->chroma_h_shift, f->chroma_v_shift, f->avctx->pix_fmt);
if (f->version < 2) {
- context_count = read_quant_tables(c, f->quant_table);
+ context_count = 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;
@@ -834,7 +834,7 @@ static int read_header(FFV1Context *f)
sizeof(p->quant_table));
context_count = f->context_count[idx];
} else {
- memcpy(p->quant_table, f->quant_table, sizeof(p->quant_table));
+ memcpy(p->quant_table, f->quant_tables[0], sizeof(p->quant_table));
}
if (f->version <= 2) {
@@ -1067,7 +1067,11 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
fdst->use32bit = fsrc->use32bit;
memcpy(fdst->state_transition, fsrc->state_transition,
sizeof(fdst->state_transition));
- memcpy(fdst->quant_table, fsrc->quant_table, sizeof(fsrc->quant_table));
+
+ // in version 1 there is a single per-keyframe quant table, so
+ // we need to propagate it between threads
+ if (fsrc->version < 2)
+ memcpy(fdst->quant_tables[0], fsrc->quant_tables[0], sizeof(fsrc->quant_tables[0]));
for (int i = 0; i < fdst->num_h_slices * fdst->num_v_slices; i++) {
FFV1Context *fssrc = fsrc->slice_context[i];
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 5692bfa1fc..1d00a46cdd 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -367,7 +367,7 @@ static void write_header(FFV1Context *f)
put_symbol(c, state, f->chroma_v_shift, 0);
put_rac(c, state, f->transparency);
- write_quant_tables(c, f->quant_table);
+ write_quant_tables(c, f->quant_tables[f->context_model]);
} else if (f->version < 3) {
put_symbol(c, state, f->slice_count, 0);
for (i = 0; i < f->slice_count; i++) {
@@ -735,15 +735,13 @@ static av_cold int encode_init(AVCodecContext *avctx)
}
s->context_count[0] = (11 * 11 * 11 + 1) / 2;
s->context_count[1] = (11 * 11 * 5 * 5 * 5 + 1) / 2;
- memcpy(s->quant_table, s->quant_tables[s->context_model],
- sizeof(s->quant_table));
for (i = 0; i < s->plane_count; i++) {
PlaneContext *const p = &s->plane[i];
- memcpy(p->quant_table, s->quant_table, sizeof(p->quant_table));
p->quant_table_index = s->context_model;
p->context_count = s->context_count[p->quant_table_index];
+ memcpy(p->quant_table, s->quant_tables[p->quant_table_index], sizeof(p->quant_table));
}
if ((ret = ff_ffv1_allocate_initial_states(s)) < 0)
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (10 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 12/39] lavc/ffv1: drop redundant FFV1Context.quant_table Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-17 22:32 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 14/39] lavc/ffv1: drop write-only PlaneContext.interlace_bit_state Anton Khirnov
` (26 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
It is a copy of FFV1Context.quant_tables[quant_table_index].
---
libavcodec/ffv1.h | 1 -
libavcodec/ffv1_template.c | 22 +++++++++++-----------
libavcodec/ffv1dec.c | 28 ++++++++++++----------------
libavcodec/ffv1dec_template.c | 14 +++++++++-----
libavcodec/ffv1enc.c | 24 ++++++++++++------------
libavcodec/ffv1enc_template.c | 13 ++++++++-----
6 files changed, 52 insertions(+), 50 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 4d57172d5b..a87c2d2a36 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -59,7 +59,6 @@ typedef struct VlcState {
} VlcState;
typedef struct PlaneContext {
- int16_t quant_table[MAX_CONTEXT_INPUTS][256];
int quant_table_index;
int context_count;
uint8_t (*state)[CONTEXT_SIZE];
diff --git a/libavcodec/ffv1_template.c b/libavcodec/ffv1_template.c
index c5f61b0182..d15ad11021 100644
--- a/libavcodec/ffv1_template.c
+++ b/libavcodec/ffv1_template.c
@@ -29,25 +29,25 @@ static inline int RENAME(predict)(TYPE *src, TYPE *last)
return mid_pred(L, L + T - LT, T);
}
-static inline int RENAME(get_context)(PlaneContext *p, TYPE *src,
- TYPE *last, TYPE *last2)
+static inline int RENAME(get_context)(const int16_t quant_table[MAX_CONTEXT_INPUTS][256],
+ TYPE *src, TYPE *last, TYPE *last2)
{
const int LT = last[-1];
const int T = last[0];
const int RT = last[1];
const int L = src[-1];
- if (p->quant_table[3][127] || p->quant_table[4][127]) {
+ if (quant_table[3][127] || quant_table[4][127]) {
const int TT = last2[0];
const int LL = src[-2];
- return p->quant_table[0][(L - LT) & 0xFF] +
- p->quant_table[1][(LT - T) & 0xFF] +
- p->quant_table[2][(T - RT) & 0xFF] +
- p->quant_table[3][(LL - L) & 0xFF] +
- p->quant_table[4][(TT - T) & 0xFF];
+ return quant_table[0][(L - LT) & 0xFF] +
+ quant_table[1][(LT - T) & 0xFF] +
+ quant_table[2][(T - RT) & 0xFF] +
+ quant_table[3][(LL - L) & 0xFF] +
+ quant_table[4][(TT - T) & 0xFF];
} else
- return p->quant_table[0][(L - LT) & 0xFF] +
- p->quant_table[1][(LT - T) & 0xFF] +
- p->quant_table[2][(T - RT) & 0xFF];
+ return quant_table[0][(L - LT) & 0xFF] +
+ quant_table[1][(LT - T) & 0xFF] +
+ quant_table[2][(T - RT) & 0xFF];
}
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 66d9f63c1a..618020d10f 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -117,7 +117,8 @@ static int is_input_end(FFV1Context *s, GetBitContext *gb)
#define RENAME(name) name ## 32
#include "ffv1dec_template.c"
-static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
+static int decode_plane(FFV1Context *f,
+ FFV1Context *s, FFV1SliceContext *sc,
GetBitContext *gb,
uint8_t *src, int w, int h, int stride, int plane_index,
int pixel_stride)
@@ -141,13 +142,13 @@ static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
sample[0][w] = sample[0][w - 1];
if (s->avctx->bits_per_raw_sample <= 8) {
- int ret = decode_line(s, sc, gb, w, sample, plane_index, 8);
+ int ret = decode_line(f, s, sc, gb, w, sample, plane_index, 8);
if (ret < 0)
return ret;
for (x = 0; x < w; x++)
src[x*pixel_stride + stride * y] = sample[1][x];
} else {
- int ret = decode_line(s, sc, gb, w, sample, plane_index, s->avctx->bits_per_raw_sample);
+ int ret = decode_line(f, s, sc, gb, w, sample, plane_index, s->avctx->bits_per_raw_sample);
if (ret < 0)
return ret;
if (s->packed_at_lsb) {
@@ -207,7 +208,6 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
return -1;
}
p->quant_table_index = idx;
- memcpy(p->quant_table, f->quant_tables[idx], sizeof(p->quant_table));
context_count = f->context_count[idx];
if (p->context_count < context_count) {
@@ -335,29 +335,29 @@ static int decode_slice(AVCodecContext *c, void *arg)
const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift);
const int cx = x >> f->chroma_h_shift;
const int cy = y >> f->chroma_v_shift;
- decode_plane(fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
+ decode_plane(f, fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
if (f->chroma_planes) {
- decode_plane(fs, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
- decode_plane(fs, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
+ decode_plane(f, fs, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
+ decode_plane(f, fs, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
if (fs->transparency)
- decode_plane(fs, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
+ decode_plane(f, fs, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
} else if (f->colorspace == 0) {
- decode_plane(fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
- decode_plane(fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
+ decode_plane(f, fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
+ decode_plane(f, fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame32(fs, sc, &gb, planes, width, height, p->linesize);
+ decode_rgb_frame32(f, fs, sc, &gb, planes, width, height, p->linesize);
} else {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame(fs, sc, &gb, planes, width, height, p->linesize);
+ decode_rgb_frame(f, fs, sc, &gb, planes, width, height, p->linesize);
}
if (fs->ac != AC_GOLOMB_RICE && f->version > 2) {
int v;
@@ -830,11 +830,7 @@ static int read_header(FFV1Context *f)
return AVERROR_INVALIDDATA;
}
p->quant_table_index = idx;
- memcpy(p->quant_table, f->quant_tables[idx],
- sizeof(p->quant_table));
context_count = f->context_count[idx];
- } else {
- memcpy(p->quant_table, f->quant_tables[0], sizeof(p->quant_table));
}
if (f->version <= 2) {
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index e9d3002be9..97a28b085a 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -23,7 +23,9 @@
#include "ffv1_template.c"
static av_always_inline int
-RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, GetBitContext *gb,
+RENAME(decode_line)(FFV1Context *f,
+ FFV1Context *s, FFV1SliceContext *sc,
+ GetBitContext *gb,
int w, TYPE *sample[2], int plane_index, int bits)
{
PlaneContext *const p = &s->plane[plane_index];
@@ -57,7 +59,8 @@ RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, GetBitContext *gb,
return AVERROR_INVALIDDATA;
}
- context = RENAME(get_context)(p, sample[1] + x, sample[0] + x, sample[1] + x);
+ context = RENAME(get_context)(f->quant_tables[p->quant_table_index],
+ sample[1] + x, sample[0] + x, sample[1] + x);
if (context < 0) {
context = -context;
sign = 1;
@@ -127,7 +130,8 @@ RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, GetBitContext *gb,
return 0;
}
-static int RENAME(decode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
+static int RENAME(decode_rgb_frame)(FFV1Context *f,
+ FFV1Context *s, FFV1SliceContext *sc,
GetBitContext *gb,
uint8_t *src[4], int w, int h, int stride[4])
{
@@ -158,9 +162,9 @@ static int RENAME(decode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
sample[p][1][-1]= sample[p][0][0 ];
sample[p][0][ w]= sample[p][0][w-1];
if (lbd && s->slice_coding_mode == 0)
- ret = RENAME(decode_line)(s, sc, gb, w, sample[p], (p + 1)/2, 9);
+ ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, 9);
else
- ret = RENAME(decode_line)(s, sc, gb, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 1d00a46cdd..714e007659 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -269,7 +269,8 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state,
#define RENAME(name) name ## 32
#include "ffv1enc_template.c"
-static int encode_plane(FFV1Context *s, FFV1SliceContext *sc,
+static int encode_plane(FFV1Context *f,
+ FFV1Context *s, FFV1SliceContext *sc,
const uint8_t *src, int w, int h,
int stride, int plane_index, int pixel_stride)
{
@@ -289,7 +290,7 @@ static int encode_plane(FFV1Context *s, FFV1SliceContext *sc,
if (s->bits_per_raw_sample <= 8) {
for (x = 0; x < w; x++)
sample[0][x] = src[x * pixel_stride + stride * y];
- if((ret = encode_line(s, sc, w, sample, plane_index, 8)) < 0)
+ if((ret = encode_line(f, s, sc, w, sample, plane_index, 8)) < 0)
return ret;
} else {
if (s->packed_at_lsb) {
@@ -301,7 +302,7 @@ static int encode_plane(FFV1Context *s, FFV1SliceContext *sc,
sample[0][x] = ((uint16_t*)(src + stride*y))[x] >> (16 - s->bits_per_raw_sample);
}
}
- if((ret = encode_line(s, sc, w, sample, plane_index, s->bits_per_raw_sample)) < 0)
+ if((ret = encode_line(f, s, sc, w, sample, plane_index, s->bits_per_raw_sample)) < 0)
return ret;
}
}
@@ -741,7 +742,6 @@ static av_cold int encode_init(AVCodecContext *avctx)
p->quant_table_index = s->context_model;
p->context_count = s->context_count[p->quant_table_index];
- memcpy(p->quant_table, s->quant_tables[p->quant_table_index], sizeof(p->quant_table));
}
if ((ret = ff_ffv1_allocate_initial_states(s)) < 0)
@@ -1066,21 +1066,21 @@ retry:
const int cx = x >> f->chroma_h_shift;
const int cy = y >> f->chroma_v_shift;
- ret = encode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
+ ret = encode_plane(f, fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
if (f->chroma_planes) {
- ret |= encode_plane(fs, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
- ret |= encode_plane(fs, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
+ ret |= encode_plane(f, fs, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
+ ret |= encode_plane(f, fs, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
if (fs->transparency)
- ret |= encode_plane(fs, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
+ ret |= encode_plane(f, fs, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
} else if (c->pix_fmt == AV_PIX_FMT_YA8) {
- ret = encode_plane(fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
- ret |= encode_plane(fs, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
+ ret = encode_plane(f, fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
+ ret |= encode_plane(f, fs, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
- ret = encode_rgb_frame32(fs, sc, planes, width, height, p->linesize);
+ ret = encode_rgb_frame32(f, fs, sc, planes, width, height, p->linesize);
} else {
- ret = encode_rgb_frame(fs, sc, planes, width, height, p->linesize);
+ ret = encode_rgb_frame(f, fs, sc, planes, width, height, p->linesize);
}
if (ret < 0) {
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 8b9e53fa1b..4a5580e1a5 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -23,7 +23,8 @@
#include "ffv1_template.c"
static av_always_inline int
-RENAME(encode_line)(FFV1Context *s, FFV1SliceContext *sc,
+RENAME(encode_line)(FFV1Context *f,
+ FFV1Context *s, FFV1SliceContext *sc,
int w, TYPE *sample[3], int plane_index, int bits)
{
PlaneContext *const p = &s->plane[plane_index];
@@ -60,7 +61,8 @@ RENAME(encode_line)(FFV1Context *s, FFV1SliceContext *sc,
for (x = 0; x < w; x++) {
int diff, context;
- context = RENAME(get_context)(p, sample[0] + x, sample[1] + x, sample[2] + x);
+ context = RENAME(get_context)(f->quant_tables[p->quant_table_index],
+ sample[0] + x, sample[1] + x, sample[2] + x);
diff = sample[0][x] - RENAME(predict)(sample[0] + x, sample[1] + x);
if (context < 0) {
@@ -124,7 +126,8 @@ RENAME(encode_line)(FFV1Context *s, FFV1SliceContext *sc,
return 0;
}
-static int RENAME(encode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
+static int RENAME(encode_rgb_frame)(FFV1Context *f,
+ FFV1Context *s, FFV1SliceContext *sc,
const uint8_t *src[4],
int w, int h, const int stride[4])
{
@@ -193,9 +196,9 @@ static int RENAME(encode_rgb_frame)(FFV1Context *s, FFV1SliceContext *sc,
sample[p][0][-1] = sample[p][1][0 ];
sample[p][1][ w] = sample[p][1][w-1];
if (lbd && s->slice_coding_mode == 0)
- ret = RENAME(encode_line)(s, sc, w, sample[p], (p + 1) / 2, 9);
+ ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, 9);
else
- ret = RENAME(encode_line)(s, sc, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 14/39] lavc/ffv1: drop write-only PlaneContext.interlace_bit_state
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (11 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:12 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 15/39] lavc/ffv1: always use the main context values of plane_count/transparency Anton Khirnov
` (25 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.c | 3 ---
libavcodec/ffv1.h | 1 -
2 files changed, 4 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index a102425596..6a0aca6429 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -169,9 +169,6 @@ void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs)
for (i = 0; i < f->plane_count; i++) {
PlaneContext *p = &fs->plane[i];
- p->interlace_bit_state[0] = 128;
- p->interlace_bit_state[1] = 128;
-
if (fs->ac != AC_GOLOMB_RICE) {
if (f->initial_states[p->quant_table_index]) {
memcpy(p->state, f->initial_states[p->quant_table_index],
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index a87c2d2a36..a3f3b30b49 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -63,7 +63,6 @@ typedef struct PlaneContext {
int context_count;
uint8_t (*state)[CONTEXT_SIZE];
VlcState *vlc_state;
- uint8_t interlace_bit_state[2];
} PlaneContext;
#define MAX_SLICES 1024
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 15/39] lavc/ffv1: always use the main context values of plane_count/transparency
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (12 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 14/39] lavc/ffv1: drop write-only PlaneContext.interlace_bit_state Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:15 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 16/39] lavc/ffv1: move FFV1Context.slice_{coding_mode, rct_.y_coef} to per-slice context Anton Khirnov
` (24 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
They cannot change between slices.
---
libavcodec/ffv1.c | 2 --
libavcodec/ffv1dec.c | 5 ++---
libavcodec/ffv1dec_template.c | 2 +-
libavcodec/ffv1enc.c | 2 +-
libavcodec/ffv1enc_template.c | 2 +-
5 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 6a0aca6429..06a77c3a26 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -56,8 +56,6 @@ av_cold int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs)
{
int j, i;
- fs->plane_count = f->plane_count;
- fs->transparency = f->transparency;
for (j = 0; j < f->plane_count; j++) {
PlaneContext *const p = &fs->plane[j];
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 618020d10f..6d3db25279 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -270,7 +270,6 @@ static int decode_slice(AVCodecContext *c, void *arg)
if(f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY)) {
FFV1Context *fssrc = f->fsrc->slice_context[si];
- av_assert1(fs->plane_count == fssrc->plane_count);
if (!(p->flags & AV_FRAME_FLAG_KEY))
fs->slice_damaged |= fssrc->slice_damaged;
@@ -330,7 +329,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
}
av_assert1(width && height);
- if (f->colorspace == 0 && (f->chroma_planes || !fs->transparency)) {
+ if (f->colorspace == 0 && (f->chroma_planes || !f->transparency)) {
const int chroma_width = AV_CEIL_RSHIFT(width, f->chroma_h_shift);
const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift);
const int cx = x >> f->chroma_h_shift;
@@ -341,7 +340,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
decode_plane(f, fs, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
decode_plane(f, fs, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
- if (fs->transparency)
+ if (f->transparency)
decode_plane(f, fs, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
} else if (f->colorspace == 0) {
decode_plane(f, fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index 97a28b085a..d868617de9 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -140,7 +140,7 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f,
int lbd = s->avctx->bits_per_raw_sample <= 8;
int bits = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
int offset = 1 << bits;
- int transparency = s->transparency;
+ int transparency = f->transparency;
for (x = 0; x < 4; x++) {
sample[x][0] = RENAME(sc->sample_buffer) + x * 2 * (w + 6) + 3;
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 714e007659..d334220e13 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1072,7 +1072,7 @@ retry:
ret |= encode_plane(f, fs, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
ret |= encode_plane(f, fs, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
- if (fs->transparency)
+ if (f->transparency)
ret |= encode_plane(f, fs, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
} else if (c->pix_fmt == AV_PIX_FMT_YA8) {
ret = encode_plane(f, fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 4a5580e1a5..0f47a0b424 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -138,7 +138,7 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f,
int packed = !src[1];
int bits = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8;
int offset = 1 << bits;
- int transparency = s->transparency;
+ int transparency = f->transparency;
int packed_size = (3 + transparency)*2;
sc->run_index = 0;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 16/39] lavc/ffv1: move FFV1Context.slice_{coding_mode, rct_.y_coef} to per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (13 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 15/39] lavc/ffv1: always use the main context values of plane_count/transparency Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:16 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 17/39] lavc/ffv1: always use the main context values of ac Anton Khirnov
` (23 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.h | 6 +++---
libavcodec/ffv1dec.c | 14 +++++++-------
libavcodec/ffv1dec_template.c | 10 +++++-----
libavcodec/ffv1enc.c | 26 +++++++++++++-------------
libavcodec/ffv1enc_template.c | 10 +++++-----
5 files changed, 33 insertions(+), 33 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index a3f3b30b49..e466aedbbe 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -77,6 +77,9 @@ typedef struct FFV1SliceContext {
int slice_y;
int run_index;
+ int slice_coding_mode;
+ int slice_rct_by_coef;
+ int slice_rct_ry_coef;
PutBitContext pb;
} FFV1SliceContext;
@@ -130,9 +133,6 @@ typedef struct FFV1Context {
int num_v_slices;
int num_h_slices;
int slice_reset_contexts;
- int slice_coding_mode;
- int slice_rct_by_coef;
- int slice_rct_ry_coef;
FFV1SliceContext *slices;
} FFV1Context;
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 6d3db25279..8464697fd3 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -240,11 +240,11 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
if (fs->version > 3) {
fs->slice_reset_contexts = get_rac(c, state);
- fs->slice_coding_mode = get_symbol(c, state, 0);
- if (fs->slice_coding_mode != 1) {
- fs->slice_rct_by_coef = get_symbol(c, state, 0);
- fs->slice_rct_ry_coef = get_symbol(c, state, 0);
- if ((uint64_t)fs->slice_rct_by_coef + (uint64_t)fs->slice_rct_ry_coef > 4) {
+ sc->slice_coding_mode = get_symbol(c, state, 0);
+ if (sc->slice_coding_mode != 1) {
+ sc->slice_rct_by_coef = get_symbol(c, state, 0);
+ sc->slice_rct_ry_coef = 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;
}
@@ -294,8 +294,8 @@ static int decode_slice(AVCodecContext *c, void *arg)
}
}
- fs->slice_rct_by_coef = 1;
- fs->slice_rct_ry_coef = 1;
+ sc->slice_rct_by_coef = 1;
+ sc->slice_rct_ry_coef = 1;
if (f->version > 2) {
if (ff_ffv1_init_slice_state(f, fs) < 0)
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index d868617de9..776dc4144f 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -38,7 +38,7 @@ RENAME(decode_line)(FFV1Context *f,
if (is_input_end(s, gb))
return AVERROR_INVALIDDATA;
- if (s->slice_coding_mode == 1) {
+ if (sc->slice_coding_mode == 1) {
int i;
for (x = 0; x < w; x++) {
int v = 0;
@@ -161,10 +161,10 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f,
sample[p][1][-1]= sample[p][0][0 ];
sample[p][0][ w]= sample[p][0][w-1];
- if (lbd && s->slice_coding_mode == 0)
+ if (lbd && sc->slice_coding_mode == 0)
ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, 9);
else
- ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, bits + (sc->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
@@ -174,10 +174,10 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f,
int r = sample[2][1][x];
int a = sample[3][1][x];
- if (s->slice_coding_mode != 1) {
+ if (sc->slice_coding_mode != 1) {
b -= offset;
r -= offset;
- g -= (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2;
+ g -= (b * sc->slice_rct_by_coef + r * sc->slice_rct_ry_coef) >> 2;
b += g;
r += g;
}
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index d334220e13..fb373b598b 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -926,13 +926,13 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
put_symbol(c, state, f->cur_enc_frame->sample_aspect_ratio.num, 0);
put_symbol(c, state, f->cur_enc_frame->sample_aspect_ratio.den, 0);
if (f->version > 3) {
- put_rac(c, state, fs->slice_coding_mode == 1);
- if (fs->slice_coding_mode == 1)
+ put_rac(c, state, sc->slice_coding_mode == 1);
+ if (sc->slice_coding_mode == 1)
ff_ffv1_clear_slice_state(f, fs);
- put_symbol(c, state, fs->slice_coding_mode, 0);
- if (fs->slice_coding_mode != 1) {
- put_symbol(c, state, fs->slice_rct_by_coef, 0);
- put_symbol(c, state, fs->slice_rct_ry_coef, 0);
+ put_symbol(c, state, sc->slice_coding_mode, 0);
+ if (sc->slice_coding_mode != 1) {
+ put_symbol(c, state, sc->slice_rct_by_coef, 0);
+ put_symbol(c, state, sc->slice_rct_ry_coef, 0);
}
}
}
@@ -1016,8 +1016,8 @@ static void choose_rct_params(FFV1Context *fs, FFV1SliceContext *sc,
best = i;
}
- fs->slice_rct_by_coef = rct_y_coeff[best][1];
- fs->slice_rct_ry_coef = rct_y_coeff[best][0];
+ sc->slice_rct_by_coef = rct_y_coeff[best][1];
+ sc->slice_rct_ry_coef = rct_y_coeff[best][0];
}
static int encode_slice(AVCodecContext *c, void *arg)
@@ -1039,12 +1039,12 @@ static int encode_slice(AVCodecContext *c, void *arg)
p->data[2] ? p->data[2] + ps*x + y*p->linesize[2] : NULL,
p->data[3] ? p->data[3] + ps*x + y*p->linesize[3] : NULL};
- fs->slice_coding_mode = 0;
+ sc->slice_coding_mode = 0;
if (f->version > 3) {
choose_rct_params(fs, sc, planes, p->linesize, width, height);
} else {
- fs->slice_rct_by_coef = 1;
- fs->slice_rct_ry_coef = 1;
+ sc->slice_rct_by_coef = 1;
+ sc->slice_rct_ry_coef = 1;
}
retry:
@@ -1084,13 +1084,13 @@ retry:
}
if (ret < 0) {
- av_assert0(fs->slice_coding_mode == 0);
+ av_assert0(sc->slice_coding_mode == 0);
if (fs->version < 4 || !fs->ac) {
av_log(c, AV_LOG_ERROR, "Buffer too small\n");
return ret;
}
av_log(c, AV_LOG_DEBUG, "Coding slice as PCM\n");
- fs->slice_coding_mode = 1;
+ sc->slice_coding_mode = 1;
fs->c = c_bak;
goto retry;
}
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 0f47a0b424..29b50637f4 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -46,7 +46,7 @@ RENAME(encode_line)(FFV1Context *f,
}
}
- if (s->slice_coding_mode == 1) {
+ if (sc->slice_coding_mode == 1) {
for (x = 0; x < w; x++) {
int i;
int v = sample[0][x];
@@ -178,10 +178,10 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f,
r = *((const uint16_t *)(src[2] + x*2 + stride[2]*y));
}
- if (s->slice_coding_mode != 1) {
+ if (sc->slice_coding_mode != 1) {
b -= g;
r -= g;
- g += (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2;
+ g += (b * sc->slice_rct_by_coef + r * sc->slice_rct_ry_coef) >> 2;
b += offset;
r += offset;
}
@@ -195,10 +195,10 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f,
int ret;
sample[p][0][-1] = sample[p][1][0 ];
sample[p][1][ w] = sample[p][1][w-1];
- if (lbd && s->slice_coding_mode == 0)
+ if (lbd && sc->slice_coding_mode == 0)
ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, 9);
else
- ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, bits + (s->slice_coding_mode != 1));
+ ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, bits + (sc->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 17/39] lavc/ffv1: always use the main context values of ac
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (14 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 16/39] lavc/ffv1: move FFV1Context.slice_{coding_mode, rct_.y_coef} to per-slice context Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:23 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 18/39] lavc/ffv1: move FFV1Context.plane to per-slice context Anton Khirnov
` (22 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
It cannot change between slices.
---
libavcodec/ffv1.c | 6 +++---
libavcodec/ffv1dec.c | 14 ++++++--------
libavcodec/ffv1dec_template.c | 6 +++---
libavcodec/ffv1enc.c | 6 +++---
libavcodec/ffv1enc_template.c | 4 ++--
5 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 06a77c3a26..581e775ae2 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -59,7 +59,7 @@ av_cold int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs)
for (j = 0; j < f->plane_count; j++) {
PlaneContext *const p = &fs->plane[j];
- if (fs->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
if (!p->state)
p->state = av_malloc_array(p->context_count, CONTEXT_SIZE *
sizeof(uint8_t));
@@ -78,7 +78,7 @@ av_cold int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs)
}
}
- if (fs->ac == AC_RANGE_CUSTOM_TAB) {
+ if (f->ac == AC_RANGE_CUSTOM_TAB) {
//FIXME only redo if state_transition changed
for (j = 1; j < 256; j++) {
fs->c. one_state[ j] = f->state_transition[j];
@@ -167,7 +167,7 @@ void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs)
for (i = 0; i < f->plane_count; i++) {
PlaneContext *p = &fs->plane[i];
- if (fs->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
if (f->initial_states[p->quant_table_index]) {
memcpy(p->state, f->initial_states[p->quant_table_index],
CONTEXT_SIZE * p->context_count);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 8464697fd3..133baa895a 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -94,10 +94,9 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state,
return ret;
}
-static int is_input_end(FFV1Context *s, GetBitContext *gb)
+static int is_input_end(RangeCoder *c, GetBitContext *gb, int ac)
{
- if (s->ac != AC_GOLOMB_RICE) {
- RangeCoder *const c = &s->c;
+ if (ac != AC_GOLOMB_RICE) {
if (c->overread > MAX_OVERREAD)
return AVERROR_INVALIDDATA;
} else {
@@ -197,7 +196,7 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
av_assert0 ( (unsigned)sc->slice_x + (uint64_t)sc->slice_width <= f->width
&& (unsigned)sc->slice_y + (uint64_t)sc->slice_height <= f->height);
- if (fs->ac == AC_GOLOMB_RICE && sc->slice_width >= (1<<23))
+ if (f->ac == AC_GOLOMB_RICE && sc->slice_width >= (1<<23))
return AVERROR_INVALIDDATA;
for (unsigned i = 0; i < f->plane_count; i++) {
@@ -284,7 +283,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
pdst->state = NULL;
pdst->vlc_state = NULL;
- if (fssrc->ac) {
+ if (f->ac) {
pdst->state = av_malloc_array(CONTEXT_SIZE, psrc->context_count);
memcpy(pdst->state, psrc->state, CONTEXT_SIZE * psrc->context_count);
} else {
@@ -319,7 +318,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
x = sc->slice_x;
y = sc->slice_y;
- if (fs->ac == AC_GOLOMB_RICE) {
+ if (f->ac == AC_GOLOMB_RICE) {
if (f->version == 3 && f->micro_version > 1 || f->version > 3)
get_rac(&fs->c, (uint8_t[]) { 129 });
fs->ac_byte_count = f->version > 2 || (!x && !y) ? fs->c.bytestream - fs->c.bytestream_start - 1 : 0;
@@ -358,7 +357,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
p->data[3] + ps * x + y * p->linesize[3] };
decode_rgb_frame(f, fs, sc, &gb, planes, width, height, p->linesize);
}
- if (fs->ac != AC_GOLOMB_RICE && f->version > 2) {
+ if (f->ac != AC_GOLOMB_RICE && f->version > 2) {
int v;
get_rac(&fs->c, (uint8_t[]) { 129 });
v = fs->c.bytestream_end - fs->c.bytestream - 2 - 5*f->ec;
@@ -791,7 +790,6 @@ static int read_header(FFV1Context *f)
for (int j = 0; j < f->slice_count; j++) {
FFV1Context *fs = f->slice_context[j];
FFV1SliceContext *sc = &f->slices[j];
- fs->ac = f->ac;
fs->packed_at_lsb = f->packed_at_lsb;
fs->slice_damaged = 0;
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index 776dc4144f..30a13e0faf 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -35,7 +35,7 @@ RENAME(decode_line)(FFV1Context *f,
int run_mode = 0;
int run_index = sc->run_index;
- if (is_input_end(s, gb))
+ if (is_input_end(c, gb, f->ac))
return AVERROR_INVALIDDATA;
if (sc->slice_coding_mode == 1) {
@@ -55,7 +55,7 @@ RENAME(decode_line)(FFV1Context *f,
int diff, context, sign;
if (!(x & 1023)) {
- if (is_input_end(s, gb))
+ if (is_input_end(c, gb, f->ac))
return AVERROR_INVALIDDATA;
}
@@ -69,7 +69,7 @@ RENAME(decode_line)(FFV1Context *f,
av_assert2(context < p->context_count);
- if (s->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
diff = get_symbol_inline(c, p->state[context], 1);
} else {
if (context == 0 && run_mode == 0)
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index fb373b598b..7fb5b997cc 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1053,7 +1053,7 @@ retry:
if (f->version > 2) {
encode_slice_header(f, fs, sc);
}
- if (fs->ac == AC_GOLOMB_RICE) {
+ if (f->ac == AC_GOLOMB_RICE) {
fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&fs->c, f->version > 2) : 0;
init_put_bits(&sc->pb,
fs->c.bytestream_start + fs->ac_byte_count,
@@ -1085,7 +1085,7 @@ retry:
if (ret < 0) {
av_assert0(sc->slice_coding_mode == 0);
- if (fs->version < 4 || !fs->ac) {
+ if (fs->version < 4 || !f->ac) {
av_log(c, AV_LOG_ERROR, "Buffer too small\n");
return ret;
}
@@ -1210,7 +1210,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
FFV1SliceContext *sc = &f->slices[i];
int bytes;
- if (fs->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
bytes = ff_rac_terminate(&fs->c, 1);
} else {
flush_put_bits(&sc->pb); // FIXME: nicer padding
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 29b50637f4..970c185e93 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -34,7 +34,7 @@ RENAME(encode_line)(FFV1Context *f,
int run_count = 0;
int run_mode = 0;
- if (s->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
if (c->bytestream_end - c->bytestream < w * 35) {
av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return AVERROR_INVALIDDATA;
@@ -72,7 +72,7 @@ RENAME(encode_line)(FFV1Context *f,
diff = fold(diff, bits);
- if (s->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
if (s->flags & AV_CODEC_FLAG_PASS1) {
put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat,
s->rc_stat2[p->quant_table_index][context]);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 18/39] lavc/ffv1: move FFV1Context.plane to per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (15 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 17/39] lavc/ffv1: always use the main context values of ac Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 19/39] lavc/ffv1: move RangeCoder " Anton Khirnov
` (21 subsequent siblings)
38 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.c | 17 +++++++----------
libavcodec/ffv1.h | 7 ++++---
libavcodec/ffv1dec.c | 16 ++++++++--------
libavcodec/ffv1dec_template.c | 2 +-
libavcodec/ffv1enc.c | 29 ++++++++++++++++-------------
libavcodec/ffv1enc_template.c | 2 +-
6 files changed, 37 insertions(+), 36 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 581e775ae2..7bc4f1b135 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -52,12 +52,13 @@ av_cold int ff_ffv1_common_init(AVCodecContext *avctx)
return 0;
}
-av_cold int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs)
+av_cold int ff_ffv1_init_slice_state(const FFV1Context *f,
+ FFV1Context *fs, FFV1SliceContext *sc)
{
int j, i;
for (j = 0; j < f->plane_count; j++) {
- PlaneContext *const p = &fs->plane[j];
+ PlaneContext *const p = &sc->plane[j];
if (f->ac != AC_GOLOMB_RICE) {
if (!p->state)
@@ -94,7 +95,7 @@ av_cold int ff_ffv1_init_slices_state(FFV1Context *f)
int i, ret;
for (i = 0; i < f->max_slice_count; i++) {
FFV1Context *fs = f->slice_context[i];
- if ((ret = ff_ffv1_init_slice_state(f, fs)) < 0)
+ if ((ret = ff_ffv1_init_slice_state(f, fs, &f->slices[i])) < 0)
return AVERROR(ENOMEM);
}
return 0;
@@ -160,12 +161,12 @@ int ff_ffv1_allocate_initial_states(FFV1Context *f)
return 0;
}
-void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs)
+void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1SliceContext *sc)
{
int i, j;
for (i = 0; i < f->plane_count; i++) {
- PlaneContext *p = &fs->plane[i];
+ PlaneContext *p = &sc->plane[i];
if (f->ac != AC_GOLOMB_RICE) {
if (f->initial_states[p->quant_table_index]) {
@@ -191,17 +192,13 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
int i, j;
for (j = 0; j < s->max_slice_count; j++) {
- FFV1Context *fs = s->slice_context[j];
FFV1SliceContext *sc = &s->slices[j];
av_freep(&sc->sample_buffer);
av_freep(&sc->sample_buffer32);
- if (!fs)
- continue;
-
for (i = 0; i < s->plane_count; i++) {
- PlaneContext *p = &fs->plane[i];
+ PlaneContext *p = &sc->plane[i];
av_freep(&p->state);
av_freep(&p->vlc_state);
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index e466aedbbe..68e59b300b 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -81,6 +81,7 @@ typedef struct FFV1SliceContext {
int slice_rct_by_coef;
int slice_rct_ry_coef;
+ PlaneContext plane[MAX_PLANES];
PutBitContext pb;
} FFV1SliceContext;
@@ -106,7 +107,6 @@ typedef struct FFV1Context {
int plane_count;
int ac; ///< 1=range coder <-> 0=golomb rice
int ac_byte_count; ///< number of bytes used for AC coding
- PlaneContext plane[MAX_PLANES];
int16_t quant_tables[MAX_QUANT_TABLES][MAX_CONTEXT_INPUTS][256];
int context_count[MAX_QUANT_TABLES];
uint8_t state_transition[256];
@@ -138,11 +138,12 @@ typedef struct FFV1Context {
} FFV1Context;
int ff_ffv1_common_init(AVCodecContext *avctx);
-int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs);
+int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs,
+ FFV1SliceContext *sc);
int ff_ffv1_init_slices_state(FFV1Context *f);
int ff_ffv1_init_slice_contexts(FFV1Context *f);
int ff_ffv1_allocate_initial_states(FFV1Context *f);
-void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs);
+void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1SliceContext *sc);
int ff_ffv1_close(AVCodecContext *avctx);
static av_always_inline int fold(int diff, int bits)
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 133baa895a..4d20512643 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -200,7 +200,7 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
return AVERROR_INVALIDDATA;
for (unsigned i = 0; i < f->plane_count; i++) {
- PlaneContext * const p = &fs->plane[i];
+ PlaneContext * const p = &sc->plane[i];
int idx = 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");
@@ -269,13 +269,14 @@ static int decode_slice(AVCodecContext *c, void *arg)
if(f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY)) {
FFV1Context *fssrc = f->fsrc->slice_context[si];
+ const FFV1SliceContext *scsrc = &f->fsrc->slices[si];
if (!(p->flags & AV_FRAME_FLAG_KEY))
fs->slice_damaged |= fssrc->slice_damaged;
for (int i = 0; i < f->plane_count; i++) {
- PlaneContext *psrc = &fssrc->plane[i];
- PlaneContext *pdst = &fs->plane[i];
+ const PlaneContext *psrc = &scsrc->plane[i];
+ PlaneContext *pdst = &sc->plane[i];
av_free(pdst->state);
av_free(pdst->vlc_state);
@@ -297,7 +298,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
sc->slice_rct_ry_coef = 1;
if (f->version > 2) {
- if (ff_ffv1_init_slice_state(f, fs) < 0)
+ if (ff_ffv1_init_slice_state(f, fs, sc) < 0)
return AVERROR(ENOMEM);
if (decode_slice_header(f, fs, sc, p) < 0) {
sc->slice_x = sc->slice_y = sc->slice_height = sc->slice_width = 0;
@@ -305,10 +306,10 @@ static int decode_slice(AVCodecContext *c, void *arg)
return AVERROR_INVALIDDATA;
}
}
- if ((ret = ff_ffv1_init_slice_state(f, fs)) < 0)
+ if ((ret = ff_ffv1_init_slice_state(f, fs, sc)) < 0)
return ret;
if ((p->flags & AV_FRAME_FLAG_KEY) || fs->slice_reset_contexts) {
- ff_ffv1_clear_slice_state(f, fs);
+ ff_ffv1_clear_slice_state(f, sc);
} else if (fs->slice_damaged) {
return AVERROR_INVALIDDATA;
}
@@ -817,7 +818,7 @@ static int read_header(FFV1Context *f)
}
for (int i = 0; i < f->plane_count; i++) {
- PlaneContext *const p = &fs->plane[i];
+ PlaneContext *const p = &sc->plane[i];
if (f->version == 2) {
int idx = get_symbol(c, state, 0);
@@ -1082,7 +1083,6 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
sc->slice_height = sc0->slice_height;
}
}
- av_assert0(!fdst->plane[0].state);
av_assert1(fdst->max_slice_count == fsrc->max_slice_count);
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index 30a13e0faf..42198b5e0b 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -28,7 +28,7 @@ RENAME(decode_line)(FFV1Context *f,
GetBitContext *gb,
int w, TYPE *sample[2], int plane_index, int bits)
{
- PlaneContext *const p = &s->plane[plane_index];
+ PlaneContext *const p = &sc->plane[plane_index];
RangeCoder *const c = &s->c;
int x;
int run_count = 0;
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 7fb5b997cc..1c986927fe 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -384,8 +384,8 @@ static void write_header(FFV1Context *f)
(fs->slice_height + 1) * f->num_v_slices / f->height - 1,
0);
for (j = 0; j < f->plane_count; j++) {
- put_symbol(c, state, f->plane[j].quant_table_index, 0);
- av_assert0(f->plane[j].quant_table_index == f->context_model);
+ put_symbol(c, state, fs->plane[j].quant_table_index, 0);
+ av_assert0(fs->plane[j].quant_table_index == f->context_model);
}
}
}
@@ -737,13 +737,6 @@ static av_cold int encode_init(AVCodecContext *avctx)
s->context_count[0] = (11 * 11 * 11 + 1) / 2;
s->context_count[1] = (11 * 11 * 5 * 5 * 5 + 1) / 2;
- for (i = 0; i < s->plane_count; i++) {
- PlaneContext *const p = &s->plane[i];
-
- p->quant_table_index = s->context_model;
- p->context_count = s->context_count[p->quant_table_index];
- }
-
if ((ret = ff_ffv1_allocate_initial_states(s)) < 0)
return ret;
@@ -881,6 +874,16 @@ slices_ok:
if ((ret = ff_ffv1_init_slice_contexts(s)) < 0)
return ret;
s->slice_count = s->max_slice_count;
+
+ for (int j = 0; j < s->slice_count; j++) {
+ for (int i = 0; i < s->plane_count; i++) {
+ PlaneContext *const p = &s->slices[j].plane[i];
+
+ p->quant_table_index = s->context_model;
+ p->context_count = s->context_count[p->quant_table_index];
+ }
+ }
+
if ((ret = ff_ffv1_init_slices_state(s)) < 0)
return ret;
@@ -916,8 +919,8 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
put_symbol(c, state, (sc->slice_width +1)*f->num_h_slices / f->width -1, 0);
put_symbol(c, state, (sc->slice_height+1)*f->num_v_slices / f->height-1, 0);
for (j=0; j<f->plane_count; j++) {
- put_symbol(c, state, f->plane[j].quant_table_index, 0);
- av_assert0(f->plane[j].quant_table_index == f->context_model);
+ put_symbol(c, state, sc->plane[j].quant_table_index, 0);
+ av_assert0(sc->plane[j].quant_table_index == f->context_model);
}
if (!(f->cur_enc_frame->flags & AV_FRAME_FLAG_INTERLACED))
put_symbol(c, state, 3, 0);
@@ -928,7 +931,7 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
if (f->version > 3) {
put_rac(c, state, sc->slice_coding_mode == 1);
if (sc->slice_coding_mode == 1)
- ff_ffv1_clear_slice_state(f, fs);
+ ff_ffv1_clear_slice_state(f, sc);
put_symbol(c, state, sc->slice_coding_mode, 0);
if (sc->slice_coding_mode != 1) {
put_symbol(c, state, sc->slice_rct_by_coef, 0);
@@ -1049,7 +1052,7 @@ static int encode_slice(AVCodecContext *c, void *arg)
retry:
if (f->key_frame)
- ff_ffv1_clear_slice_state(f, fs);
+ ff_ffv1_clear_slice_state(f, sc);
if (f->version > 2) {
encode_slice_header(f, fs, sc);
}
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 970c185e93..2116c9aee7 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -27,7 +27,7 @@ RENAME(encode_line)(FFV1Context *f,
FFV1Context *s, FFV1SliceContext *sc,
int w, TYPE *sample[3], int plane_index, int bits)
{
- PlaneContext *const p = &s->plane[plane_index];
+ PlaneContext *const p = &sc->plane[plane_index];
RangeCoder *const c = &s->c;
int x;
int run_index = sc->run_index;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 19/39] lavc/ffv1: move RangeCoder to per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (16 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 18/39] lavc/ffv1: move FFV1Context.plane to per-slice context Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:28 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 20/39] lavc/ffv1enc: store per-slice rc_stat(2?) in FFV1SliceContext Anton Khirnov
` (20 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.c | 9 ++--
libavcodec/ffv1.h | 5 +--
libavcodec/ffv1dec.c | 72 ++++++++++++++++----------------
libavcodec/ffv1dec_template.c | 2 +-
libavcodec/ffv1enc.c | 78 ++++++++++++++++++-----------------
libavcodec/ffv1enc_template.c | 2 +-
6 files changed, 85 insertions(+), 83 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 7bc4f1b135..490baac233 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -53,7 +53,7 @@ av_cold int ff_ffv1_common_init(AVCodecContext *avctx)
}
av_cold int ff_ffv1_init_slice_state(const FFV1Context *f,
- FFV1Context *fs, FFV1SliceContext *sc)
+ FFV1SliceContext *sc)
{
int j, i;
@@ -82,8 +82,8 @@ av_cold int ff_ffv1_init_slice_state(const FFV1Context *f,
if (f->ac == AC_RANGE_CUSTOM_TAB) {
//FIXME only redo if state_transition changed
for (j = 1; j < 256; j++) {
- fs->c. one_state[ j] = f->state_transition[j];
- fs->c.zero_state[256 - j] = 256 - fs->c.one_state[j];
+ sc->c. one_state[ j] = f->state_transition[j];
+ sc->c.zero_state[256 - j] = 256 - sc->c.one_state[j];
}
}
@@ -94,8 +94,7 @@ av_cold int ff_ffv1_init_slices_state(FFV1Context *f)
{
int i, ret;
for (i = 0; i < f->max_slice_count; i++) {
- FFV1Context *fs = f->slice_context[i];
- if ((ret = ff_ffv1_init_slice_state(f, fs, &f->slices[i])) < 0)
+ if ((ret = ff_ffv1_init_slice_state(f, &f->slices[i])) < 0)
return AVERROR(ENOMEM);
}
return 0;
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 68e59b300b..01c35dc942 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -83,12 +83,12 @@ typedef struct FFV1SliceContext {
PlaneContext plane[MAX_PLANES];
PutBitContext pb;
+ RangeCoder c;
} FFV1SliceContext;
typedef struct FFV1Context {
AVClass *class;
AVCodecContext *avctx;
- RangeCoder c;
uint64_t rc_stat[256][2];
uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2];
int version;
@@ -138,8 +138,7 @@ typedef struct FFV1Context {
} FFV1Context;
int ff_ffv1_common_init(AVCodecContext *avctx);
-int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs,
- FFV1SliceContext *sc);
+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);
int ff_ffv1_allocate_initial_states(FFV1Context *f);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 4d20512643..e0344c996b 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -167,7 +167,7 @@ static int decode_plane(FFV1Context *f,
static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
FFV1SliceContext *sc, AVFrame *frame)
{
- RangeCoder *c = &fs->c;
+ RangeCoder *c = &sc->c;
uint8_t state[CONTEXT_SIZE];
unsigned ps, context_count;
int sx, sy, sw, sh;
@@ -298,7 +298,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
sc->slice_rct_ry_coef = 1;
if (f->version > 2) {
- if (ff_ffv1_init_slice_state(f, fs, sc) < 0)
+ if (ff_ffv1_init_slice_state(f, sc) < 0)
return AVERROR(ENOMEM);
if (decode_slice_header(f, fs, sc, p) < 0) {
sc->slice_x = sc->slice_y = sc->slice_height = sc->slice_width = 0;
@@ -306,7 +306,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
return AVERROR_INVALIDDATA;
}
}
- if ((ret = ff_ffv1_init_slice_state(f, fs, sc)) < 0)
+ if ((ret = ff_ffv1_init_slice_state(f, sc)) < 0)
return ret;
if ((p->flags & AV_FRAME_FLAG_KEY) || fs->slice_reset_contexts) {
ff_ffv1_clear_slice_state(f, sc);
@@ -321,11 +321,11 @@ static int decode_slice(AVCodecContext *c, void *arg)
if (f->ac == AC_GOLOMB_RICE) {
if (f->version == 3 && f->micro_version > 1 || f->version > 3)
- get_rac(&fs->c, (uint8_t[]) { 129 });
- fs->ac_byte_count = f->version > 2 || (!x && !y) ? fs->c.bytestream - fs->c.bytestream_start - 1 : 0;
+ get_rac(&sc->c, (uint8_t[]) { 129 });
+ fs->ac_byte_count = f->version > 2 || (!x && !y) ? sc->c.bytestream - sc->c.bytestream_start - 1 : 0;
init_get_bits(&gb,
- fs->c.bytestream_start + fs->ac_byte_count,
- (fs->c.bytestream_end - fs->c.bytestream_start - fs->ac_byte_count) * 8);
+ sc->c.bytestream_start + fs->ac_byte_count,
+ (sc->c.bytestream_end - sc->c.bytestream_start - fs->ac_byte_count) * 8);
}
av_assert1(width && height);
@@ -360,8 +360,8 @@ static int decode_slice(AVCodecContext *c, void *arg)
}
if (f->ac != AC_GOLOMB_RICE && f->version > 2) {
int v;
- get_rac(&fs->c, (uint8_t[]) { 129 });
- v = fs->c.bytestream_end - fs->c.bytestream - 2 - 5*f->ec;
+ get_rac(&sc->c, (uint8_t[]) { 129 });
+ v = sc->c.bytestream_end - sc->c.bytestream - 2 - 5*f->ec;
if (v) {
av_log(f->avctx, AV_LOG_ERROR, "bytestream end mismatching by %d\n", v);
fs->slice_damaged = 1;
@@ -420,7 +420,7 @@ static int read_quant_tables(RangeCoder *c,
static int read_extra_header(FFV1Context *f)
{
- RangeCoder *const c = &f->c;
+ RangeCoder c;
uint8_t state[CONTEXT_SIZE];
int ret;
uint8_t state2[32][CONTEXT_SIZE];
@@ -429,10 +429,10 @@ static int read_extra_header(FFV1Context *f)
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);
+ 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);
+ 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;
@@ -443,27 +443,27 @@ static int read_extra_header(FFV1Context *f)
return AVERROR_PATCHWELCOME;
}
if (f->version > 2) {
- c->bytestream_end -= 4;
- f->micro_version = get_symbol(c, state, 0);
+ c.bytestream_end -= 4;
+ f->micro_version = get_symbol(&c, state, 0);
if (f->micro_version < 0)
return AVERROR_INVALIDDATA;
}
- f->ac = get_symbol(c, state, 0);
+ 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->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->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);
+ 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",
@@ -483,7 +483,7 @@ static int read_extra_header(FFV1Context *f)
return AVERROR_PATCHWELCOME;
}
- f->quant_table_count = get_symbol(c, state, 0);
+ 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;
@@ -491,7 +491,7 @@ static int read_extra_header(FFV1Context *f)
}
for (int i = 0; i < f->quant_table_count; i++) {
- f->context_count[i] = read_quant_tables(c, f->quant_tables[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;
@@ -501,19 +501,19 @@ static int read_extra_header(FFV1Context *f)
return ret;
for (int i = 0; i < f->quant_table_count; i++)
- if (get_rac(c, state)) {
+ 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;
+ (pred + get_symbol(&c, state2[k], 1)) & 0xFF;
}
}
if (f->version > 2) {
- f->ec = get_symbol(c, state, 0);
+ f->ec = get_symbol(&c, state, 0);
if (f->micro_version > 2)
- f->intra = get_symbol(c, state, 0);
+ f->intra = get_symbol(&c, state, 0);
}
if (f->version > 2) {
@@ -549,7 +549,7 @@ static int read_header(FFV1Context *f)
{
uint8_t state[CONTEXT_SIZE];
int context_count = -1; //-1 to avoid warning
- RangeCoder *const c = &f->slice_context[0]->c;
+ RangeCoder *const c = &f->slices[0].c;
memset(state, 128, sizeof(state));
@@ -867,7 +867,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
FFV1Context *f = avctx->priv_data;
- RangeCoder *const c = &f->slice_context[0]->c;
+ RangeCoder *const c = &f->slices[0].c;
int ret, key_frame;
uint8_t keystate = 128;
uint8_t *buf_p;
@@ -938,6 +938,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
buf_p = buf + buf_size;
for (int i = f->slice_count - 1; i >= 0; i--) {
FFV1Context *fs = f->slice_context[i];
+ FFV1SliceContext *sc = &f->slices[i];
int trailer = 3 + 5*!!f->ec;
int v;
@@ -972,9 +973,10 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
}
if (i) {
- ff_init_range_decoder(&fs->c, buf_p, v);
+ ff_init_range_decoder(&sc->c, buf_p, v);
+ ff_build_rac_states(&sc->c, 0.05 * (1LL << 32), 256 - 8);
} else
- fs->c.bytestream_end = buf_p + v;
+ sc->c.bytestream_end = buf_p + v;
fs->avctx = avctx;
}
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index 42198b5e0b..4bb15801c1 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -29,7 +29,7 @@ RENAME(decode_line)(FFV1Context *f,
int w, TYPE *sample[2], int plane_index, int bits)
{
PlaneContext *const p = &sc->plane[plane_index];
- RangeCoder *const c = &s->c;
+ RangeCoder *const c = &sc->c;
int x;
int run_count = 0;
int run_mode = 0;
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 1c986927fe..d615d3da87 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -348,7 +348,7 @@ static void write_header(FFV1Context *f)
{
uint8_t state[CONTEXT_SIZE];
int i, j;
- RangeCoder *const c = &f->slice_context[0]->c;
+ RangeCoder *const c = &f->slices[0].c;
memset(state, 128, sizeof(state));
@@ -393,7 +393,7 @@ static void write_header(FFV1Context *f)
static int write_extradata(FFV1Context *f)
{
- RangeCoder *const c = &f->c;
+ RangeCoder c;
uint8_t state[CONTEXT_SIZE];
int i, j, k;
uint8_t state2[32][CONTEXT_SIZE];
@@ -407,56 +407,56 @@ static int write_extradata(FFV1Context *f)
f->avctx->extradata = av_malloc(f->avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
if (!f->avctx->extradata)
return AVERROR(ENOMEM);
- ff_init_range_encoder(c, f->avctx->extradata, f->avctx->extradata_size);
- ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8);
+ ff_init_range_encoder(&c, f->avctx->extradata, f->avctx->extradata_size);
+ ff_build_rac_states(&c, 0.05 * (1LL << 32), 256 - 8);
- put_symbol(c, state, f->version, 0);
+ put_symbol(&c, state, f->version, 0);
if (f->version > 2) {
if (f->version == 3) {
f->micro_version = 4;
} else if (f->version == 4)
f->micro_version = 2;
- put_symbol(c, state, f->micro_version, 0);
+ put_symbol(&c, state, f->micro_version, 0);
}
- put_symbol(c, state, f->ac, 0);
+ put_symbol(&c, state, f->ac, 0);
if (f->ac == AC_RANGE_CUSTOM_TAB)
for (i = 1; i < 256; i++)
- put_symbol(c, state, f->state_transition[i] - c->one_state[i], 1);
+ put_symbol(&c, state, f->state_transition[i] - c.one_state[i], 1);
- put_symbol(c, state, f->colorspace, 0); // YUV cs type
- put_symbol(c, state, f->bits_per_raw_sample, 0);
- put_rac(c, state, f->chroma_planes);
- put_symbol(c, state, f->chroma_h_shift, 0);
- put_symbol(c, state, f->chroma_v_shift, 0);
- put_rac(c, state, f->transparency);
- put_symbol(c, state, f->num_h_slices - 1, 0);
- put_symbol(c, state, f->num_v_slices - 1, 0);
+ put_symbol(&c, state, f->colorspace, 0); // YUV cs type
+ put_symbol(&c, state, f->bits_per_raw_sample, 0);
+ put_rac(&c, state, f->chroma_planes);
+ put_symbol(&c, state, f->chroma_h_shift, 0);
+ put_symbol(&c, state, f->chroma_v_shift, 0);
+ put_rac(&c, state, f->transparency);
+ put_symbol(&c, state, f->num_h_slices - 1, 0);
+ put_symbol(&c, state, f->num_v_slices - 1, 0);
- put_symbol(c, state, f->quant_table_count, 0);
+ put_symbol(&c, state, f->quant_table_count, 0);
for (i = 0; i < f->quant_table_count; i++)
- write_quant_tables(c, f->quant_tables[i]);
+ write_quant_tables(&c, f->quant_tables[i]);
for (i = 0; i < f->quant_table_count; i++) {
if (contains_non_128(f->initial_states[i], f->context_count[i])) {
- put_rac(c, state, 1);
+ put_rac(&c, state, 1);
for (j = 0; j < f->context_count[i]; j++)
for (k = 0; k < CONTEXT_SIZE; k++) {
int pred = j ? f->initial_states[i][j - 1][k] : 128;
- put_symbol(c, state2[k],
+ put_symbol(&c, state2[k],
(int8_t)(f->initial_states[i][j][k] - pred), 1);
}
} else {
- put_rac(c, state, 0);
+ put_rac(&c, state, 0);
}
}
if (f->version > 2) {
- put_symbol(c, state, f->ec, 0);
- put_symbol(c, state, f->intra = (f->avctx->gop_size < 2), 0);
+ put_symbol(&c, state, f->ec, 0);
+ put_symbol(&c, state, f->intra = (f->avctx->gop_size < 2), 0);
}
- f->avctx->extradata_size = ff_rac_terminate(c, 0);
+ f->avctx->extradata_size = ff_rac_terminate(&c, 0);
v = av_crc(av_crc_get_table(AV_CRC_32_IEEE), 0, f->avctx->extradata, f->avctx->extradata_size);
AV_WL32(f->avctx->extradata + f->avctx->extradata_size, v);
f->avctx->extradata_size += 4;
@@ -882,6 +882,8 @@ slices_ok:
p->quant_table_index = s->context_model;
p->context_count = s->context_count[p->quant_table_index];
}
+
+ ff_build_rac_states(&s->slices[j].c, 0.05 * (1LL << 32), 256 - 8);
}
if ((ret = ff_ffv1_init_slices_state(s)) < 0)
@@ -909,7 +911,7 @@ slices_ok:
static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
FFV1SliceContext *sc)
{
- RangeCoder *c = &fs->c;
+ RangeCoder *c = &sc->c;
uint8_t state[CONTEXT_SIZE];
int j;
memset(state, 128, sizeof(state));
@@ -1036,7 +1038,7 @@ static int encode_slice(AVCodecContext *c, void *arg)
const AVFrame *const p = f->cur_enc_frame;
const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step;
int ret;
- RangeCoder c_bak = fs->c;
+ RangeCoder c_bak = sc->c;
const uint8_t *planes[4] = {p->data[0] + ps*x + y*p->linesize[0],
p->data[1] ? p->data[1] + ps*x + y*p->linesize[1] : NULL,
p->data[2] ? p->data[2] + ps*x + y*p->linesize[2] : NULL,
@@ -1057,10 +1059,10 @@ retry:
encode_slice_header(f, fs, sc);
}
if (f->ac == AC_GOLOMB_RICE) {
- fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&fs->c, f->version > 2) : 0;
+ fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&sc->c, f->version > 2) : 0;
init_put_bits(&sc->pb,
- fs->c.bytestream_start + fs->ac_byte_count,
- fs->c.bytestream_end - fs->c.bytestream_start - fs->ac_byte_count);
+ sc->c.bytestream_start + fs->ac_byte_count,
+ sc->c.bytestream_end - sc->c.bytestream_start - fs->ac_byte_count);
}
if (f->colorspace == 0 && c->pix_fmt != AV_PIX_FMT_YA8) {
@@ -1094,7 +1096,7 @@ retry:
}
av_log(c, AV_LOG_DEBUG, "Coding slice as PCM\n");
sc->slice_coding_mode = 1;
- fs->c = c_bak;
+ sc->c = c_bak;
goto retry;
}
@@ -1105,7 +1107,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
const AVFrame *pict, int *got_packet)
{
FFV1Context *f = avctx->priv_data;
- RangeCoder *const c = &f->slice_context[0]->c;
+ RangeCoder *const c = &f->slices[0].c;
uint8_t keystate = 128;
uint8_t *buf_p;
int i, ret;
@@ -1193,15 +1195,15 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
}
for (i = 0; i < f->slice_count; i++) {
- FFV1Context *fs = f->slice_context[i];
+ FFV1SliceContext *sc = &f->slices[i];
uint8_t *start = pkt->data + pkt->size * (int64_t)i / f->slice_count;
int len = pkt->size / f->slice_count;
if (i) {
- ff_init_range_encoder(&fs->c, start, len);
+ ff_init_range_encoder(&sc->c, start, len);
} else {
- av_assert0(fs->c.bytestream_end >= fs->c.bytestream_start + len);
- av_assert0(fs->c.bytestream < fs->c.bytestream_start + len);
- fs->c.bytestream_end = fs->c.bytestream_start + len;
+ av_assert0(sc->c.bytestream_end >= sc->c.bytestream_start + len);
+ av_assert0(sc->c.bytestream < sc->c.bytestream_start + len);
+ sc->c.bytestream_end = sc->c.bytestream_start + len;
}
}
avctx->execute(avctx, encode_slice, &f->slice_context[0], NULL,
@@ -1214,14 +1216,14 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
int bytes;
if (f->ac != AC_GOLOMB_RICE) {
- bytes = ff_rac_terminate(&fs->c, 1);
+ bytes = ff_rac_terminate(&sc->c, 1);
} else {
flush_put_bits(&sc->pb); // FIXME: nicer padding
bytes = fs->ac_byte_count + put_bytes_output(&sc->pb);
}
if (i > 0 || f->version > 2) {
av_assert0(bytes < pkt->size / f->slice_count);
- memmove(buf_p, fs->c.bytestream_start, bytes);
+ memmove(buf_p, sc->c.bytestream_start, bytes);
av_assert0(bytes < (1 << 24));
AV_WB24(buf_p + bytes, bytes);
bytes += 3;
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 2116c9aee7..c27a2e3a39 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -28,7 +28,7 @@ RENAME(encode_line)(FFV1Context *f,
int w, TYPE *sample[3], int plane_index, int bits)
{
PlaneContext *const p = &sc->plane[plane_index];
- RangeCoder *const c = &s->c;
+ RangeCoder *const c = &sc->c;
int x;
int run_index = sc->run_index;
int run_count = 0;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 20/39] lavc/ffv1enc: store per-slice rc_stat(2?) in FFV1SliceContext
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (17 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 19/39] lavc/ffv1: move RangeCoder " Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:30 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 21/39] lavc/ffv1: move ac_byte_count to per-slice context Anton Khirnov
` (19 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Instead of the per-slice FFV1Context, which will be removed in future
commits.
---
libavcodec/ffv1.c | 6 ++----
libavcodec/ffv1.h | 3 +++
libavcodec/ffv1enc.c | 20 ++++++++++----------
libavcodec/ffv1enc_template.c | 4 ++--
4 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 490baac233..4ef04f6b9b 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -127,7 +127,6 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
f->slice_context[i++] = fs;
memcpy(fs, f, sizeof(*fs));
- memset(fs->rc_stat2, 0, sizeof(fs->rc_stat2));
sc->slice_width = sxe - sxs;
sc->slice_height = sye - sys;
@@ -208,9 +207,8 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
for (j = 0; j < s->quant_table_count; j++) {
av_freep(&s->initial_states[j]);
for (i = 0; i < s->max_slice_count; i++) {
- FFV1Context *sf = s->slice_context[i];
- if (sf)
- av_freep(&sf->rc_stat2[j]);
+ FFV1SliceContext *sc = &s->slices[i];
+ av_freep(&sc->rc_stat2[j]);
}
av_freep(&s->rc_stat2[j]);
}
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 01c35dc942..bee7b75614 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -84,6 +84,9 @@ typedef struct FFV1SliceContext {
PlaneContext plane[MAX_PLANES];
PutBitContext pb;
RangeCoder c;
+
+ uint64_t rc_stat[256][2];
+ uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2];
} FFV1SliceContext;
typedef struct FFV1Context {
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index d615d3da87..e3d094141c 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -896,11 +896,11 @@ slices_ok:
return AVERROR(ENOMEM);
for (i = 0; i < s->quant_table_count; i++)
for (j = 0; j < s->max_slice_count; j++) {
- FFV1Context *sf = s->slice_context[j];
- av_assert0(!sf->rc_stat2[i]);
- sf->rc_stat2[i] = av_mallocz(s->context_count[i] *
- sizeof(*sf->rc_stat2[i]));
- if (!sf->rc_stat2[i])
+ FFV1SliceContext *sc = &s->slices[j];
+ av_assert0(!sc->rc_stat2[i]);
+ sc->rc_stat2[i] = av_mallocz(s->context_count[i] *
+ sizeof(*sc->rc_stat2[i]));
+ if (!sc->rc_stat2[i])
return AVERROR(ENOMEM);
}
}
@@ -1126,16 +1126,16 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
av_assert0(f->slice_count == f->max_slice_count);
for (j = 0; j < f->slice_count; j++) {
- FFV1Context *fs = f->slice_context[j];
+ const FFV1SliceContext *sc = &f->slices[j];
for (i = 0; i < 256; i++) {
- f->rc_stat[i][0] += fs->rc_stat[i][0];
- f->rc_stat[i][1] += fs->rc_stat[i][1];
+ f->rc_stat[i][0] += sc->rc_stat[i][0];
+ f->rc_stat[i][1] += sc->rc_stat[i][1];
}
for (i = 0; i < f->quant_table_count; i++) {
for (k = 0; k < f->context_count[i]; k++)
for (m = 0; m < 32; m++) {
- f->rc_stat2[i][k][m][0] += fs->rc_stat2[i][k][m][0];
- f->rc_stat2[i][k][m][1] += fs->rc_stat2[i][k][m][1];
+ f->rc_stat2[i][k][m][0] += sc->rc_stat2[i][k][m][0];
+ f->rc_stat2[i][k][m][1] += sc->rc_stat2[i][k][m][1];
}
}
}
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index c27a2e3a39..c79146d619 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -74,8 +74,8 @@ RENAME(encode_line)(FFV1Context *f,
if (f->ac != AC_GOLOMB_RICE) {
if (s->flags & AV_CODEC_FLAG_PASS1) {
- put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat,
- s->rc_stat2[p->quant_table_index][context]);
+ put_symbol_inline(c, p->state[context], diff, 1, sc->rc_stat,
+ sc->rc_stat2[p->quant_table_index][context]);
} else {
put_symbol_inline(c, p->state[context], diff, 1, NULL, NULL);
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 21/39] lavc/ffv1: move ac_byte_count to per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (18 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 20/39] lavc/ffv1enc: store per-slice rc_stat(2?) in FFV1SliceContext Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:31 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 22/39] lavc/ffv1enc: stop using per-slice FFV1Context Anton Khirnov
` (18 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.h | 2 +-
libavcodec/ffv1dec.c | 6 +++---
libavcodec/ffv1enc.c | 6 +++---
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index bee7b75614..ae81940073 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -85,6 +85,7 @@ typedef struct FFV1SliceContext {
PutBitContext pb;
RangeCoder c;
+ int ac_byte_count; ///< number of bytes used for AC coding
uint64_t rc_stat[256][2];
uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2];
} FFV1SliceContext;
@@ -109,7 +110,6 @@ typedef struct FFV1Context {
const AVFrame *cur_enc_frame;
int plane_count;
int ac; ///< 1=range coder <-> 0=golomb rice
- int ac_byte_count; ///< number of bytes used for AC coding
int16_t quant_tables[MAX_QUANT_TABLES][MAX_CONTEXT_INPUTS][256];
int context_count[MAX_QUANT_TABLES];
uint8_t state_transition[256];
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index e0344c996b..4dc1f4b1cf 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -322,10 +322,10 @@ static int decode_slice(AVCodecContext *c, void *arg)
if (f->ac == AC_GOLOMB_RICE) {
if (f->version == 3 && f->micro_version > 1 || f->version > 3)
get_rac(&sc->c, (uint8_t[]) { 129 });
- fs->ac_byte_count = f->version > 2 || (!x && !y) ? sc->c.bytestream - sc->c.bytestream_start - 1 : 0;
+ sc->ac_byte_count = f->version > 2 || (!x && !y) ? sc->c.bytestream - sc->c.bytestream_start - 1 : 0;
init_get_bits(&gb,
- sc->c.bytestream_start + fs->ac_byte_count,
- (sc->c.bytestream_end - sc->c.bytestream_start - fs->ac_byte_count) * 8);
+ sc->c.bytestream_start + sc->ac_byte_count,
+ (sc->c.bytestream_end - sc->c.bytestream_start - sc->ac_byte_count) * 8);
}
av_assert1(width && height);
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index e3d094141c..3a6a0e6d90 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1059,10 +1059,10 @@ retry:
encode_slice_header(f, fs, sc);
}
if (f->ac == AC_GOLOMB_RICE) {
- fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&sc->c, f->version > 2) : 0;
+ sc->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&sc->c, f->version > 2) : 0;
init_put_bits(&sc->pb,
- sc->c.bytestream_start + fs->ac_byte_count,
- sc->c.bytestream_end - sc->c.bytestream_start - fs->ac_byte_count);
+ sc->c.bytestream_start + sc->ac_byte_count,
+ sc->c.bytestream_end - sc->c.bytestream_start - sc->ac_byte_count);
}
if (f->colorspace == 0 && c->pix_fmt != AV_PIX_FMT_YA8) {
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 22/39] lavc/ffv1enc: stop using per-slice FFV1Context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (19 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 21/39] lavc/ffv1: move ac_byte_count to per-slice context Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:42 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 23/39] lavc/ffv1dec: move slice_reset_contexts to per-slice context Anton Khirnov
` (17 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
All remaining accesses to them are for fields that have the same value
in the main encoder context.
---
libavcodec/ffv1enc.c | 57 ++++++++++++++++-------------------
libavcodec/ffv1enc_template.c | 24 +++++++--------
2 files changed, 37 insertions(+), 44 deletions(-)
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 3a6a0e6d90..ba378a54a4 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -269,13 +269,12 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state,
#define RENAME(name) name ## 32
#include "ffv1enc_template.c"
-static int encode_plane(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+static int encode_plane(FFV1Context *f, FFV1SliceContext *sc,
const uint8_t *src, int w, int h,
int stride, int plane_index, int pixel_stride)
{
int x, y, i, ret;
- const int ring_size = s->context_model ? 3 : 2;
+ const int ring_size = f->context_model ? 3 : 2;
int16_t *sample[3];
sc->run_index = 0;
@@ -287,22 +286,22 @@ static int encode_plane(FFV1Context *f,
sample[0][-1]= sample[1][0 ];
sample[1][ w]= sample[1][w-1];
- if (s->bits_per_raw_sample <= 8) {
+ if (f->bits_per_raw_sample <= 8) {
for (x = 0; x < w; x++)
sample[0][x] = src[x * pixel_stride + stride * y];
- if((ret = encode_line(f, s, sc, w, sample, plane_index, 8)) < 0)
+ if((ret = encode_line(f, sc, w, sample, plane_index, 8)) < 0)
return ret;
} else {
- if (s->packed_at_lsb) {
+ if (f->packed_at_lsb) {
for (x = 0; x < w; x++) {
sample[0][x] = ((uint16_t*)(src + stride*y))[x];
}
} else {
for (x = 0; x < w; x++) {
- sample[0][x] = ((uint16_t*)(src + stride*y))[x] >> (16 - s->bits_per_raw_sample);
+ sample[0][x] = ((uint16_t*)(src + stride*y))[x] >> (16 - f->bits_per_raw_sample);
}
}
- if((ret = encode_line(f, s, sc, w, sample, plane_index, s->bits_per_raw_sample)) < 0)
+ if((ret = encode_line(f, sc, w, sample, plane_index, f->bits_per_raw_sample)) < 0)
return ret;
}
}
@@ -908,8 +907,7 @@ slices_ok:
return 0;
}
-static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
- FFV1SliceContext *sc)
+static void encode_slice_header(FFV1Context *f, FFV1SliceContext *sc)
{
RangeCoder *c = &sc->c;
uint8_t state[CONTEXT_SIZE];
@@ -942,7 +940,7 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
}
}
-static void choose_rct_params(FFV1Context *fs, FFV1SliceContext *sc,
+static void choose_rct_params(const FFV1Context *f, FFV1SliceContext *sc,
const uint8_t *src[3], const int stride[3], int w, int h)
{
#define NB_Y_COEFF 15
@@ -968,7 +966,7 @@ static void choose_rct_params(FFV1Context *fs, FFV1SliceContext *sc,
int stat[NB_Y_COEFF] = {0};
int x, y, i, p, best;
int16_t *sample[3];
- int lbd = fs->bits_per_raw_sample <= 8;
+ int lbd = f->bits_per_raw_sample <= 8;
for (y = 0; y < h; y++) {
int lastr=0, lastg=0, lastb=0;
@@ -1027,10 +1025,8 @@ static void choose_rct_params(FFV1Context *fs, FFV1SliceContext *sc,
static int encode_slice(AVCodecContext *c, void *arg)
{
- FFV1Context *fs = *(void **)arg;
- FFV1Context *f = fs->avctx->priv_data;
- const int si = (FFV1Context**)arg - f->slice_context;
- FFV1SliceContext *sc = &f->slices[si];
+ FFV1SliceContext *sc = arg;
+ FFV1Context *f = c->priv_data;
int width = sc->slice_width;
int height = sc->slice_height;
int x = sc->slice_x;
@@ -1046,7 +1042,7 @@ static int encode_slice(AVCodecContext *c, void *arg)
sc->slice_coding_mode = 0;
if (f->version > 3) {
- choose_rct_params(fs, sc, planes, p->linesize, width, height);
+ choose_rct_params(f, sc, planes, p->linesize, width, height);
} else {
sc->slice_rct_by_coef = 1;
sc->slice_rct_ry_coef = 1;
@@ -1056,7 +1052,7 @@ retry:
if (f->key_frame)
ff_ffv1_clear_slice_state(f, sc);
if (f->version > 2) {
- encode_slice_header(f, fs, sc);
+ encode_slice_header(f, sc);
}
if (f->ac == AC_GOLOMB_RICE) {
sc->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&sc->c, f->version > 2) : 0;
@@ -1071,26 +1067,26 @@ retry:
const int cx = x >> f->chroma_h_shift;
const int cy = y >> f->chroma_v_shift;
- ret = encode_plane(f, fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
+ ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
if (f->chroma_planes) {
- ret |= encode_plane(f, fs, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
- ret |= encode_plane(f, fs, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
+ ret |= encode_plane(f, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
+ ret |= encode_plane(f, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
if (f->transparency)
- ret |= encode_plane(f, fs, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
+ ret |= encode_plane(f, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
} else if (c->pix_fmt == AV_PIX_FMT_YA8) {
- ret = encode_plane(f, fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
- ret |= encode_plane(f, fs, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
+ ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
+ ret |= encode_plane(f, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
- ret = encode_rgb_frame32(f, fs, sc, planes, width, height, p->linesize);
+ ret = encode_rgb_frame32(f, sc, planes, width, height, p->linesize);
} else {
- ret = encode_rgb_frame(f, fs, sc, planes, width, height, p->linesize);
+ ret = encode_rgb_frame(f, sc, planes, width, height, p->linesize);
}
if (ret < 0) {
av_assert0(sc->slice_coding_mode == 0);
- if (fs->version < 4 || !f->ac) {
+ if (f->version < 4 || !f->ac) {
av_log(c, AV_LOG_ERROR, "Buffer too small\n");
return ret;
}
@@ -1206,12 +1202,11 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
sc->c.bytestream_end = sc->c.bytestream_start + len;
}
}
- avctx->execute(avctx, encode_slice, &f->slice_context[0], NULL,
- f->slice_count, sizeof(void *));
+ avctx->execute(avctx, encode_slice, f->slices, NULL,
+ f->slice_count, sizeof(*f->slices));
buf_p = pkt->data;
for (i = 0; i < f->slice_count; i++) {
- FFV1Context *fs = f->slice_context[i];
FFV1SliceContext *sc = &f->slices[i];
int bytes;
@@ -1219,7 +1214,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
bytes = ff_rac_terminate(&sc->c, 1);
} else {
flush_put_bits(&sc->pb); // FIXME: nicer padding
- bytes = fs->ac_byte_count + put_bytes_output(&sc->pb);
+ bytes = sc->ac_byte_count + put_bytes_output(&sc->pb);
}
if (i > 0 || f->version > 2) {
av_assert0(bytes < pkt->size / f->slice_count);
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index c79146d619..0bb0070d37 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -23,8 +23,7 @@
#include "ffv1_template.c"
static av_always_inline int
-RENAME(encode_line)(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+RENAME(encode_line)(FFV1Context *f, FFV1SliceContext *sc,
int w, TYPE *sample[3], int plane_index, int bits)
{
PlaneContext *const p = &sc->plane[plane_index];
@@ -36,12 +35,12 @@ RENAME(encode_line)(FFV1Context *f,
if (f->ac != AC_GOLOMB_RICE) {
if (c->bytestream_end - c->bytestream < w * 35) {
- av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
+ av_log(f->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return AVERROR_INVALIDDATA;
}
} else {
if (put_bytes_left(&sc->pb, 0) < w * 4) {
- av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
+ av_log(f->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return AVERROR_INVALIDDATA;
}
}
@@ -73,7 +72,7 @@ RENAME(encode_line)(FFV1Context *f,
diff = fold(diff, bits);
if (f->ac != AC_GOLOMB_RICE) {
- if (s->flags & AV_CODEC_FLAG_PASS1) {
+ if (f->flags & AV_CODEC_FLAG_PASS1) {
put_symbol_inline(c, p->state[context], diff, 1, sc->rc_stat,
sc->rc_stat2[p->quant_table_index][context]);
} else {
@@ -103,7 +102,7 @@ RENAME(encode_line)(FFV1Context *f,
}
}
- ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
+ ff_dlog(f->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
run_count, run_index, run_mode, x,
(int)put_bits_count(&sc->pb));
@@ -126,17 +125,16 @@ RENAME(encode_line)(FFV1Context *f,
return 0;
}
-static int RENAME(encode_rgb_frame)(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+static int RENAME(encode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc,
const uint8_t *src[4],
int w, int h, const int stride[4])
{
int x, y, p, i;
- const int ring_size = s->context_model ? 3 : 2;
+ const int ring_size = f->context_model ? 3 : 2;
TYPE *sample[4][3];
- int lbd = s->bits_per_raw_sample <= 8;
+ int lbd = f->bits_per_raw_sample <= 8;
int packed = !src[1];
- int bits = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8;
+ int bits = f->bits_per_raw_sample > 0 ? f->bits_per_raw_sample : 8;
int offset = 1 << bits;
int transparency = f->transparency;
int packed_size = (3 + transparency)*2;
@@ -196,9 +194,9 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f,
sample[p][0][-1] = sample[p][1][0 ];
sample[p][1][ w] = sample[p][1][w-1];
if (lbd && sc->slice_coding_mode == 0)
- ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, 9);
+ ret = RENAME(encode_line)(f, sc, w, sample[p], (p + 1) / 2, 9);
else
- ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, bits + (sc->slice_coding_mode != 1));
+ ret = RENAME(encode_line)(f, sc, w, sample[p], (p + 1) / 2, bits + (sc->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 23/39] lavc/ffv1dec: move slice_reset_contexts to per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (20 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 22/39] lavc/ffv1enc: stop using per-slice FFV1Context Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:44 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 24/39] lavc/ffv1dec: move slice_damaged " Anton Khirnov
` (16 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.h | 16 +++++++++++++---
libavcodec/ffv1dec.c | 4 ++--
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index ae81940073..cef61f38ec 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -86,8 +86,19 @@ typedef struct FFV1SliceContext {
RangeCoder c;
int ac_byte_count; ///< number of bytes used for AC coding
- uint64_t rc_stat[256][2];
- uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2];
+
+ union {
+ // decoder-only
+ struct {
+ int slice_reset_contexts;
+ };
+
+ // encoder-only
+ struct {
+ uint64_t rc_stat[256][2];
+ uint64_t (*rc_stat2[MAX_QUANT_TABLES])[32][2];
+ };
+ };
} FFV1SliceContext;
typedef struct FFV1Context {
@@ -135,7 +146,6 @@ typedef struct FFV1Context {
int max_slice_count;
int num_v_slices;
int num_h_slices;
- int slice_reset_contexts;
FFV1SliceContext *slices;
} FFV1Context;
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 4dc1f4b1cf..92e5b2a80b 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -238,7 +238,7 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
}
if (fs->version > 3) {
- fs->slice_reset_contexts = get_rac(c, state);
+ sc->slice_reset_contexts = get_rac(c, state);
sc->slice_coding_mode = get_symbol(c, state, 0);
if (sc->slice_coding_mode != 1) {
sc->slice_rct_by_coef = get_symbol(c, state, 0);
@@ -308,7 +308,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
}
if ((ret = ff_ffv1_init_slice_state(f, sc)) < 0)
return ret;
- if ((p->flags & AV_FRAME_FLAG_KEY) || fs->slice_reset_contexts) {
+ if ((p->flags & AV_FRAME_FLAG_KEY) || sc->slice_reset_contexts) {
ff_ffv1_clear_slice_state(f, sc);
} else if (fs->slice_damaged) {
return AVERROR_INVALIDDATA;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 24/39] lavc/ffv1dec: move slice_damaged to per-slice context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (21 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 23/39] lavc/ffv1dec: move slice_reset_contexts to per-slice context Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:45 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 25/39] lavc/ffv1dec: stop using per-slice FFV1Context Anton Khirnov
` (15 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/ffv1.h | 2 +-
libavcodec/ffv1dec.c | 18 ++++++++----------
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index cef61f38ec..c4803654f2 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -91,6 +91,7 @@ typedef struct FFV1SliceContext {
// decoder-only
struct {
int slice_reset_contexts;
+ int slice_damaged;
};
// encoder-only
@@ -131,7 +132,6 @@ typedef struct FFV1Context {
int ec;
int intra;
- int slice_damaged;
int key_frame_ok;
int context_model;
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 92e5b2a80b..bd46930ec7 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -268,11 +268,10 @@ static int decode_slice(AVCodecContext *c, void *arg)
ff_progress_frame_await(&f->last_picture, si);
if(f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY)) {
- FFV1Context *fssrc = f->fsrc->slice_context[si];
const FFV1SliceContext *scsrc = &f->fsrc->slices[si];
if (!(p->flags & AV_FRAME_FLAG_KEY))
- fs->slice_damaged |= fssrc->slice_damaged;
+ sc->slice_damaged |= scsrc->slice_damaged;
for (int i = 0; i < f->plane_count; i++) {
const PlaneContext *psrc = &scsrc->plane[i];
@@ -302,7 +301,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
return AVERROR(ENOMEM);
if (decode_slice_header(f, fs, sc, p) < 0) {
sc->slice_x = sc->slice_y = sc->slice_height = sc->slice_width = 0;
- fs->slice_damaged = 1;
+ sc->slice_damaged = 1;
return AVERROR_INVALIDDATA;
}
}
@@ -310,7 +309,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
return ret;
if ((p->flags & AV_FRAME_FLAG_KEY) || sc->slice_reset_contexts) {
ff_ffv1_clear_slice_state(f, sc);
- } else if (fs->slice_damaged) {
+ } else if (sc->slice_damaged) {
return AVERROR_INVALIDDATA;
}
@@ -364,7 +363,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
v = sc->c.bytestream_end - sc->c.bytestream - 2 - 5*f->ec;
if (v) {
av_log(f->avctx, AV_LOG_ERROR, "bytestream end mismatching by %d\n", v);
- fs->slice_damaged = 1;
+ sc->slice_damaged = 1;
}
}
@@ -793,7 +792,7 @@ static int read_header(FFV1Context *f)
FFV1SliceContext *sc = &f->slices[j];
fs->packed_at_lsb = f->packed_at_lsb;
- fs->slice_damaged = 0;
+ sc->slice_damaged = 0;
if (f->version == 2) {
int sx = get_symbol(c, state, 0);
@@ -965,7 +964,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
} else {
av_log(f->avctx, AV_LOG_ERROR, "\n");
}
- fs->slice_damaged = 1;
+ sc->slice_damaged = 1;
}
if (avctx->debug & FF_DEBUG_PICT_INFO) {
av_log(avctx, AV_LOG_DEBUG, "slice %d, CRC: 0x%08"PRIX32"\n", i, AV_RB32(buf_p + v - 4));
@@ -989,9 +988,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
sizeof(void*));
for (int i = f->slice_count - 1; i >= 0; i--) {
- FFV1Context *fs = f->slice_context[i];
FFV1SliceContext *sc = &f->slices[i];
- if (fs->slice_damaged && f->last_picture.f) {
+ if (sc->slice_damaged && f->last_picture.f) {
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
const uint8_t *src[4];
uint8_t *dst[4];
@@ -1044,7 +1042,6 @@ static void copy_fields(FFV1Context *fsdst, const FFV1Context *fssrc,
fsdst->ec = fsrc->ec;
fsdst->intra = fsrc->intra;
- fsdst->slice_damaged = fssrc->slice_damaged;
fsdst->key_frame_ok = fsrc->key_frame_ok;
fsdst->packed_at_lsb = fsrc->packed_at_lsb;
@@ -1077,6 +1074,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
const FFV1SliceContext *sc0 = &fsrc->slices[i];
copy_fields(fsdst, fssrc, fsrc);
+ sc->slice_damaged = sc0->slice_damaged;
if (fsrc->version < 3) {
sc->slice_x = sc0->slice_x;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 25/39] lavc/ffv1dec: stop using per-slice FFV1Context
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (22 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 24/39] lavc/ffv1dec: move slice_damaged " Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:48 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 26/39] lavc/ffv1dec: inline copy_fields() into update_thread_context() Anton Khirnov
` (14 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
All remaining accesses to them are for fields that have the same value
in the main encoder context.
Drop now-unused FFV1Context.slice_contexts.
---
libavcodec/ffv1.c | 18 +++---------
libavcodec/ffv1.h | 1 -
libavcodec/ffv1dec.c | 54 ++++++++++++++---------------------
libavcodec/ffv1dec_template.c | 16 +++++------
4 files changed, 33 insertions(+), 56 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 4ef04f6b9b..07cf5564cc 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -102,7 +102,7 @@ av_cold int ff_ffv1_init_slices_state(FFV1Context *f)
av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
{
- int i, max_slice_count = f->num_h_slices * f->num_v_slices;
+ int max_slice_count = f->num_h_slices * f->num_v_slices;
av_assert0(max_slice_count > 0);
@@ -112,7 +112,7 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
f->max_slice_count = max_slice_count;
- for (i = 0; i < max_slice_count;) {
+ for (int i = 0; i < max_slice_count; i++) {
FFV1SliceContext *sc = &f->slices[i];
int sx = i % f->num_h_slices;
int sy = i / f->num_h_slices;
@@ -120,22 +120,15 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
int sxe = f->avctx->width * (sx + 1) / f->num_h_slices;
int sys = f->avctx->height * sy / f->num_v_slices;
int sye = f->avctx->height * (sy + 1) / f->num_v_slices;
- FFV1Context *fs = av_mallocz(sizeof(*fs));
-
- if (!fs)
- return AVERROR(ENOMEM);
-
- f->slice_context[i++] = fs;
- memcpy(fs, f, sizeof(*fs));
sc->slice_width = sxe - sxs;
sc->slice_height = sye - sys;
sc->slice_x = sxs;
sc->slice_y = sys;
- sc->sample_buffer = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
+ sc->sample_buffer = av_malloc_array((f->width + 6), 3 * MAX_PLANES *
sizeof(*sc->sample_buffer));
- sc->sample_buffer32 = av_malloc_array((fs->width + 6), 3 * MAX_PLANES *
+ sc->sample_buffer32 = av_malloc_array((f->width + 6), 3 * MAX_PLANES *
sizeof(*sc->sample_buffer32));
if (!sc->sample_buffer || !sc->sample_buffer32)
return AVERROR(ENOMEM);
@@ -213,9 +206,6 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
av_freep(&s->rc_stat2[j]);
}
- for (i = 0; i < s->max_slice_count; i++)
- av_freep(&s->slice_context[i]);
-
av_freep(&s->slices);
return 0;
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index c4803654f2..9d79219921 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -141,7 +141,6 @@ typedef struct FFV1Context {
int gob_count;
int quant_table_count;
- struct FFV1Context *slice_context[MAX_SLICES];
int slice_count;
int max_slice_count;
int num_v_slices;
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index bd46930ec7..8bb9b83daa 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -116,8 +116,7 @@ static int is_input_end(RangeCoder *c, GetBitContext *gb, int ac)
#define RENAME(name) name ## 32
#include "ffv1dec_template.c"
-static int decode_plane(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+static int decode_plane(FFV1Context *f, FFV1SliceContext *sc,
GetBitContext *gb,
uint8_t *src, int w, int h, int stride, int plane_index,
int pixel_stride)
@@ -140,23 +139,23 @@ static int decode_plane(FFV1Context *f,
sample[1][-1] = sample[0][0];
sample[0][w] = sample[0][w - 1];
- if (s->avctx->bits_per_raw_sample <= 8) {
- int ret = decode_line(f, s, sc, gb, w, sample, plane_index, 8);
+ if (f->avctx->bits_per_raw_sample <= 8) {
+ int ret = decode_line(f, sc, gb, w, sample, plane_index, 8);
if (ret < 0)
return ret;
for (x = 0; x < w; x++)
src[x*pixel_stride + stride * y] = sample[1][x];
} else {
- int ret = decode_line(f, s, sc, gb, w, sample, plane_index, s->avctx->bits_per_raw_sample);
+ int ret = decode_line(f, sc, gb, w, sample, plane_index, f->avctx->bits_per_raw_sample);
if (ret < 0)
return ret;
- if (s->packed_at_lsb) {
+ if (f->packed_at_lsb) {
for (x = 0; x < w; x++) {
((uint16_t*)(src + stride*y))[x*pixel_stride] = sample[1][x];
}
} else {
for (x = 0; x < w; x++) {
- ((uint16_t*)(src + stride*y))[x*pixel_stride] = sample[1][x] << (16 - s->avctx->bits_per_raw_sample) | ((uint16_t **)sample)[1][x] >> (2 * s->avctx->bits_per_raw_sample - 16);
+ ((uint16_t*)(src + stride*y))[x*pixel_stride] = sample[1][x] << (16 - f->avctx->bits_per_raw_sample) | ((uint16_t **)sample)[1][x] >> (2 * f->avctx->bits_per_raw_sample - 16);
}
}
}
@@ -164,7 +163,7 @@ static int decode_plane(FFV1Context *f,
return 0;
}
-static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
+static int decode_slice_header(const FFV1Context *f,
FFV1SliceContext *sc, AVFrame *frame)
{
RangeCoder *c = &sc->c;
@@ -237,7 +236,7 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
frame->sample_aspect_ratio = (AVRational){ 0, 1 };
}
- if (fs->version > 3) {
+ if (f->version > 3) {
sc->slice_reset_contexts = get_rac(c, state);
sc->slice_coding_mode = get_symbol(c, state, 0);
if (sc->slice_coding_mode != 1) {
@@ -255,13 +254,12 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
static int decode_slice(AVCodecContext *c, void *arg)
{
- FFV1Context *fs = *(void **)arg;
- FFV1Context *f = fs->avctx->priv_data;
+ FFV1Context *f = c->priv_data;
+ FFV1SliceContext *sc = arg;
int width, height, x, y, ret;
const int ps = av_pix_fmt_desc_get(c->pix_fmt)->comp[0].step;
AVFrame * const p = f->picture.f;
- const int si = (FFV1Context**)arg - f->slice_context;
- FFV1SliceContext *sc = &f->slices[si];
+ const int si = sc - f->slices;
GetBitContext gb;
if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
@@ -299,7 +297,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
if (f->version > 2) {
if (ff_ffv1_init_slice_state(f, sc) < 0)
return AVERROR(ENOMEM);
- if (decode_slice_header(f, fs, sc, p) < 0) {
+ if (decode_slice_header(f, sc, p) < 0) {
sc->slice_x = sc->slice_y = sc->slice_height = sc->slice_width = 0;
sc->slice_damaged = 1;
return AVERROR_INVALIDDATA;
@@ -333,29 +331,29 @@ static int decode_slice(AVCodecContext *c, void *arg)
const int chroma_height = AV_CEIL_RSHIFT(height, f->chroma_v_shift);
const int cx = x >> f->chroma_h_shift;
const int cy = y >> f->chroma_v_shift;
- decode_plane(f, fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
+ decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
if (f->chroma_planes) {
- decode_plane(f, fs, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
- decode_plane(f, fs, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
+ decode_plane(f, sc, &gb, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
+ decode_plane(f, sc, &gb, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
if (f->transparency)
- decode_plane(f, fs, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
+ decode_plane(f, sc, &gb, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], (f->version >= 4 && !f->chroma_planes) ? 1 : 2, 1);
} else if (f->colorspace == 0) {
- decode_plane(f, fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
- decode_plane(f, fs, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
+ decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] , width, height, p->linesize[0], 0, 2);
+ decode_plane(f, sc, &gb, p->data[0] + ps*x + y*p->linesize[0] + 1, width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame32(f, fs, sc, &gb, planes, width, height, p->linesize);
+ decode_rgb_frame32(f, sc, &gb, planes, width, height, p->linesize);
} else {
uint8_t *planes[4] = { p->data[0] + ps * x + y * p->linesize[0],
p->data[1] + ps * x + y * p->linesize[1],
p->data[2] + ps * x + y * p->linesize[2],
p->data[3] + ps * x + y * p->linesize[3] };
- decode_rgb_frame(f, fs, sc, &gb, planes, width, height, p->linesize);
+ decode_rgb_frame(f, sc, &gb, planes, width, height, p->linesize);
}
if (f->ac != AC_GOLOMB_RICE && f->version > 2) {
int v;
@@ -788,9 +786,7 @@ static int read_header(FFV1Context *f)
}
for (int j = 0; j < f->slice_count; j++) {
- FFV1Context *fs = f->slice_context[j];
FFV1SliceContext *sc = &f->slices[j];
- fs->packed_at_lsb = f->packed_at_lsb;
sc->slice_damaged = 0;
@@ -936,7 +932,6 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
buf_p = buf + buf_size;
for (int i = f->slice_count - 1; i >= 0; i--) {
- FFV1Context *fs = f->slice_context[i];
FFV1SliceContext *sc = &f->slices[i];
int trailer = 3 + 5*!!f->ec;
int v;
@@ -977,15 +972,14 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
} else
sc->c.bytestream_end = buf_p + v;
- fs->avctx = avctx;
}
avctx->execute(avctx,
decode_slice,
- &f->slice_context[0],
+ f->slices,
NULL,
f->slice_count,
- sizeof(void*));
+ sizeof(*f->slices));
for (int i = f->slice_count - 1; i >= 0; i--) {
FFV1SliceContext *sc = &f->slices[i];
@@ -1067,13 +1061,9 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
memcpy(fdst->quant_tables[0], fsrc->quant_tables[0], sizeof(fsrc->quant_tables[0]));
for (int i = 0; i < fdst->num_h_slices * fdst->num_v_slices; i++) {
- FFV1Context *fssrc = fsrc->slice_context[i];
- FFV1Context *fsdst = fdst->slice_context[i];
-
FFV1SliceContext *sc = &fdst->slices[i];
const FFV1SliceContext *sc0 = &fsrc->slices[i];
- copy_fields(fsdst, fssrc, fsrc);
sc->slice_damaged = sc0->slice_damaged;
if (fsrc->version < 3) {
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index 4bb15801c1..64ce74dd03 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -23,8 +23,7 @@
#include "ffv1_template.c"
static av_always_inline int
-RENAME(decode_line)(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+RENAME(decode_line)(FFV1Context *f, FFV1SliceContext *sc,
GetBitContext *gb,
int w, TYPE *sample[2], int plane_index, int bits)
{
@@ -117,7 +116,7 @@ RENAME(decode_line)(FFV1Context *f,
} else
diff = get_vlc_symbol(gb, &p->vlc_state[context], bits);
- ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
+ ff_dlog(f->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
run_count, run_index, run_mode, x, get_bits_count(gb));
}
@@ -130,15 +129,14 @@ RENAME(decode_line)(FFV1Context *f,
return 0;
}
-static int RENAME(decode_rgb_frame)(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+static int RENAME(decode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc,
GetBitContext *gb,
uint8_t *src[4], int w, int h, int stride[4])
{
int x, y, p;
TYPE *sample[4][2];
- int lbd = s->avctx->bits_per_raw_sample <= 8;
- int bits = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
+ int lbd = f->avctx->bits_per_raw_sample <= 8;
+ int bits = f->avctx->bits_per_raw_sample > 0 ? f->avctx->bits_per_raw_sample : 8;
int offset = 1 << bits;
int transparency = f->transparency;
@@ -162,9 +160,9 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f,
sample[p][1][-1]= sample[p][0][0 ];
sample[p][0][ w]= sample[p][0][w-1];
if (lbd && sc->slice_coding_mode == 0)
- ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, 9);
+ ret = RENAME(decode_line)(f, sc, gb, w, sample[p], (p + 1)/2, 9);
else
- ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, bits + (sc->slice_coding_mode != 1));
+ ret = RENAME(decode_line)(f, sc, gb, w, sample[p], (p + 1)/2, bits + (sc->slice_coding_mode != 1));
if (ret < 0)
return ret;
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 26/39] lavc/ffv1dec: inline copy_fields() into update_thread_context()
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (23 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 25/39] lavc/ffv1dec: stop using per-slice FFV1Context Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:48 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 27/39] lavc/ffv1: change FFV1SliceContext.plane into a RefStruct object Anton Khirnov
` (13 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
It is now only called from a single place, so there is no point in it
being a separate function.
---
libavcodec/ffv1dec.c | 38 ++++++++++++++++----------------------
1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 8bb9b83daa..be4a1a2bf3 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -1021,27 +1021,6 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
}
#if HAVE_THREADS
-static void copy_fields(FFV1Context *fsdst, const FFV1Context *fssrc,
- const FFV1Context *fsrc)
-{
- fsdst->version = fsrc->version;
- fsdst->micro_version = fsrc->micro_version;
- fsdst->chroma_planes = fsrc->chroma_planes;
- fsdst->chroma_h_shift = fsrc->chroma_h_shift;
- fsdst->chroma_v_shift = fsrc->chroma_v_shift;
- fsdst->transparency = fsrc->transparency;
- fsdst->plane_count = fsrc->plane_count;
- fsdst->ac = fsrc->ac;
- fsdst->colorspace = fsrc->colorspace;
-
- fsdst->ec = fsrc->ec;
- fsdst->intra = fsrc->intra;
- fsdst->key_frame_ok = fsrc->key_frame_ok;
-
- fsdst->packed_at_lsb = fsrc->packed_at_lsb;
- fsdst->slice_count = fsrc->slice_count;
-}
-
static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
{
FFV1Context *fsrc = src->priv_data;
@@ -1050,7 +1029,22 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
if (dst == src)
return 0;
- copy_fields(fdst, fsrc, fsrc);
+ fdst->version = fsrc->version;
+ fdst->micro_version = fsrc->micro_version;
+ fdst->chroma_planes = fsrc->chroma_planes;
+ fdst->chroma_h_shift = fsrc->chroma_h_shift;
+ fdst->chroma_v_shift = fsrc->chroma_v_shift;
+ fdst->transparency = fsrc->transparency;
+ fdst->plane_count = fsrc->plane_count;
+ fdst->ac = fsrc->ac;
+ fdst->colorspace = fsrc->colorspace;
+
+ fdst->ec = fsrc->ec;
+ fdst->intra = fsrc->intra;
+ fdst->key_frame_ok = fsrc->key_frame_ok;
+
+ fdst->packed_at_lsb = fsrc->packed_at_lsb;
+ fdst->slice_count = fsrc->slice_count;
fdst->use32bit = fsrc->use32bit;
memcpy(fdst->state_transition, fsrc->state_transition,
sizeof(fdst->state_transition));
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 27/39] lavc/ffv1: change FFV1SliceContext.plane into a RefStruct object
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (24 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 26/39] lavc/ffv1dec: inline copy_fields() into update_thread_context() Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 19:53 ` Michael Niedermayer
2024-08-01 8:17 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 28/39] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
` (12 subsequent siblings)
38 siblings, 2 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Frame threading in the FFV1 decoder works in a very unusual way - the
state that needs to be propagated from the previous frame is not decoded
pixels(¹), but each slice's entropy coder state after decoding the slice.
For that purpose, the decoder's update_thread_context() callback stores
a pointer to the previous frame thread's private data. Then, when
decoding each slice, the frame thread uses the standard progress
mechanism to wait for the corresponding slice in the previous frame to
be completed, then copies the entropy coder state from the
previously-stored pointer.
This approach is highly dubious, as update_thread_context() should be
the only point where frame-thread contexts come into direct contact.
There are no guarantees that the stored pointer will be valid at all, or
will contain any particular data after update_thread_context() finishes.
More specifically, this code can break due to the fact that keyframes
reset entropy coder state and thus do not need to wait for the previous
frame. As an example, consider a decoder process with 2 frame threads -
thread 0 with its context 0, and thread 1 with context 1 - decoding a
previous frame P, current frame F, followed by a keyframe K. Then
consider concurrent execution consistent with the following sequence of
events:
* thread 0 starts decoding P
* thread 0 reads P's slice header, then calls
ff_thread_finish_setup() allowing next frame thread to start
* main thread calls update_thread_context() to transfer state from
context 0 to context 1; context 1 stores a pointer to context 0's private
data
* thread 1 starts decoding F
* thread 1 reads F's slice header, then calls
ff_thread_finish_setup() allowing the next frame thread to start
decoding
* thread 0 finishes decoding P
* thread 0 starts decoding K; since K is a keyframe, it does not
wait for F and reallocates the arrays holding entropy coder state
* thread 0 finishes decoding K
* thread 1 reads entropy coder state from its stored pointer to context
0, however it finds state from K rather than from P
This execution is currently prevented by special-casing FFV1 in the
generic frame threading code, however that is supremely ugly. It also
involves unnecessary copies of the state arrays, when in fact they can
only be used by one thread at a time.
This commit addresses these deficiencies by changing the array of
PlaneContext (each of which contains the allocated state arrays)
embedded in FFV1SliceContext into a RefStruct object. This object can
then be propagated across frame threads in standard manner. Since the
code structure guarantees only one thread accesses it at a time, no
copies are necessary. It is also re-created for keyframes, solving the
above issue cleanly.
Special-casing of FFV1 in the generic frame threading code will be
removed in a later commit.
(¹) except in the case of a damaged slice, when previous frame's pixels
are used directly
---
libavcodec/ffv1.c | 30 ++++++++++++++++++++++++------
libavcodec/ffv1.h | 4 +++-
libavcodec/ffv1dec.c | 33 +++++++++------------------------
3 files changed, 36 insertions(+), 31 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 07cf5564cc..9c219b5ddb 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -31,6 +31,7 @@
#include "avcodec.h"
#include "ffv1.h"
+#include "refstruct.h"
av_cold int ff_ffv1_common_init(AVCodecContext *avctx)
{
@@ -52,6 +53,24 @@ av_cold int ff_ffv1_common_init(AVCodecContext *avctx)
return 0;
}
+static void planes_free(FFRefStructOpaque opaque, void *obj)
+{
+ PlaneContext *planes = obj;
+
+ for (int i = 0; i < MAX_PLANES; i++) {
+ PlaneContext *p = &planes[i];
+
+ av_freep(&p->state);
+ av_freep(&p->vlc_state);
+ }
+}
+
+PlaneContext* ff_ffv1_planes_alloc(void)
+{
+ return ff_refstruct_alloc_ext(sizeof(PlaneContext) * MAX_PLANES,
+ 0, NULL, planes_free);
+}
+
av_cold int ff_ffv1_init_slice_state(const FFV1Context *f,
FFV1SliceContext *sc)
{
@@ -132,6 +151,10 @@ av_cold int ff_ffv1_init_slice_contexts(FFV1Context *f)
sizeof(*sc->sample_buffer32));
if (!sc->sample_buffer || !sc->sample_buffer32)
return AVERROR(ENOMEM);
+
+ sc->plane = ff_ffv1_planes_alloc();
+ if (!sc->plane)
+ return AVERROR(ENOMEM);
}
return 0;
@@ -188,12 +211,7 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
av_freep(&sc->sample_buffer);
av_freep(&sc->sample_buffer32);
- for (i = 0; i < s->plane_count; i++) {
- PlaneContext *p = &sc->plane[i];
-
- av_freep(&p->state);
- av_freep(&p->vlc_state);
- }
+ ff_refstruct_unref(&sc->plane);
}
av_freep(&avctx->stats_out);
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 9d79219921..edc3f6aef0 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -81,7 +81,8 @@ typedef struct FFV1SliceContext {
int slice_rct_by_coef;
int slice_rct_ry_coef;
- PlaneContext plane[MAX_PLANES];
+ // RefStruct reference, array of MAX_PLANES elements
+ PlaneContext *plane;
PutBitContext pb;
RangeCoder c;
@@ -153,6 +154,7 @@ int ff_ffv1_common_init(AVCodecContext *avctx);
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);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index be4a1a2bf3..7dc4a537a9 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -38,6 +38,7 @@
#include "mathops.h"
#include "ffv1.h"
#include "progressframe.h"
+#include "refstruct.h"
#include "thread.h"
static inline av_flatten int get_symbol_inline(RangeCoder *c, uint8_t *state,
@@ -265,30 +266,11 @@ static int decode_slice(AVCodecContext *c, void *arg)
if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
ff_progress_frame_await(&f->last_picture, si);
- if(f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY)) {
+ if (f->fsrc) {
const FFV1SliceContext *scsrc = &f->fsrc->slices[si];
if (!(p->flags & AV_FRAME_FLAG_KEY))
sc->slice_damaged |= scsrc->slice_damaged;
-
- for (int i = 0; i < f->plane_count; i++) {
- const PlaneContext *psrc = &scsrc->plane[i];
- PlaneContext *pdst = &sc->plane[i];
-
- av_free(pdst->state);
- av_free(pdst->vlc_state);
- memcpy(pdst, psrc, sizeof(*pdst));
- pdst->state = NULL;
- pdst->vlc_state = NULL;
-
- if (f->ac) {
- pdst->state = av_malloc_array(CONTEXT_SIZE, psrc->context_count);
- memcpy(pdst->state, psrc->state, CONTEXT_SIZE * psrc->context_count);
- } else {
- pdst->vlc_state = av_malloc_array(sizeof(*pdst->vlc_state), psrc->context_count);
- memcpy(pdst->vlc_state, psrc->vlc_state, sizeof(*pdst->vlc_state) * psrc->context_count);
- }
- }
}
sc->slice_rct_by_coef = 1;
@@ -812,6 +794,11 @@ static int read_header(FFV1Context *f)
&& (unsigned)sc->slice_y + (uint64_t)sc->slice_height <= f->height);
}
+ ff_refstruct_unref(&sc->plane);
+ sc->plane = ff_ffv1_planes_alloc();
+ if (!sc->plane)
+ return AVERROR(ENOMEM);
+
for (int i = 0; i < f->plane_count; i++) {
PlaneContext *const p = &sc->plane[i];
@@ -828,10 +815,6 @@ static int read_header(FFV1Context *f)
if (f->version <= 2) {
av_assert0(context_count >= 0);
- if (p->context_count < context_count) {
- av_freep(&p->state);
- av_freep(&p->vlc_state);
- }
p->context_count = context_count;
}
}
@@ -1060,6 +1043,8 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
sc->slice_damaged = sc0->slice_damaged;
+ ff_refstruct_replace(&sc->plane, sc0->plane);
+
if (fsrc->version < 3) {
sc->slice_x = sc0->slice_x;
sc->slice_y = sc0->slice_y;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 28/39] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (25 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 27/39] lavc/ffv1: change FFV1SliceContext.plane into a RefStruct object Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-17 20:51 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 29/39] lavc/thread: move generic-layer API to avcodec_internal.h Anton Khirnov
` (11 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
That variable is shared between frame threads in the same defective way
described in the previous commit. Fix it by adding a RefStruct-managed
arrays of flags that is propagated across frame threads in the standard
manner.
Remove now-unused FFV1Context.fsrc
---
libavcodec/ffv1.c | 2 ++
libavcodec/ffv1.h | 3 ++-
libavcodec/ffv1dec.c | 24 ++++++++++--------------
3 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 9c219b5ddb..333fb3d79b 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -214,6 +214,8 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
ff_refstruct_unref(&sc->plane);
}
+ ff_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]);
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index edc3f6aef0..ae62732650 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -118,7 +118,6 @@ typedef struct FFV1Context {
int64_t picture_number;
int key_frame;
ProgressFrame picture, last_picture;
- struct FFV1Context *fsrc;
const AVFrame *cur_enc_frame;
int plane_count;
@@ -148,6 +147,8 @@ typedef struct FFV1Context {
int num_h_slices;
FFV1SliceContext *slices;
+ // RefStruct object, per-slice damage flags
+ uint8_t *slice_damaged;
} FFV1Context;
int ff_ffv1_common_init(AVCodecContext *avctx);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 7dc4a537a9..c9ac850d98 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -263,16 +263,9 @@ static int decode_slice(AVCodecContext *c, void *arg)
const int si = sc - f->slices;
GetBitContext gb;
- if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
+ if (!(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
ff_progress_frame_await(&f->last_picture, si);
- if (f->fsrc) {
- const FFV1SliceContext *scsrc = &f->fsrc->slices[si];
-
- if (!(p->flags & AV_FRAME_FLAG_KEY))
- sc->slice_damaged |= scsrc->slice_damaged;
- }
-
sc->slice_rct_by_coef = 1;
sc->slice_rct_ry_coef = 1;
@@ -347,6 +340,8 @@ static int decode_slice(AVCodecContext *c, void *arg)
}
}
+ f->slice_damaged[si] = sc->slice_damaged;
+
ff_progress_frame_report(&f->picture, si);
return 0;
@@ -767,11 +762,14 @@ static int read_header(FFV1Context *f)
return AVERROR_INVALIDDATA;
}
+ ff_refstruct_unref(&f->slice_damaged);
+ f->slice_damaged = ff_refstruct_allocz(f->slice_count * sizeof(*f->slice_damaged));
+ if (!f->slice_damaged)
+ return AVERROR(ENOMEM);
+
for (int j = 0; j < f->slice_count; j++) {
FFV1SliceContext *sc = &f->slices[j];
- sc->slice_damaged = 0;
-
if (f->version == 2) {
int sx = get_symbol(c, state, 0);
int sy = get_symbol(c, state, 0);
@@ -1041,8 +1039,6 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
FFV1SliceContext *sc = &fdst->slices[i];
const FFV1SliceContext *sc0 = &fsrc->slices[i];
- sc->slice_damaged = sc0->slice_damaged;
-
ff_refstruct_replace(&sc->plane, sc0->plane);
if (fsrc->version < 3) {
@@ -1053,12 +1049,12 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
}
}
+ ff_refstruct_replace(&fdst->slice_damaged, fsrc->slice_damaged);
+
av_assert1(fdst->max_slice_count == fsrc->max_slice_count);
ff_progress_frame_replace(&fdst->picture, &fsrc->picture);
- fdst->fsrc = fsrc;
-
return 0;
}
#endif
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 29/39] lavc/thread: move generic-layer API to avcodec_internal.h
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (26 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 28/39] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 30/39] lavc/internal: document the precise meaning of AVCodecInternal.draining Anton Khirnov
` (10 subsequent siblings)
38 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
thread.h currently contains both API for decoder use and functions
internal to lavc generic layer. Move the latter to avcodec_internal.h,
which is a more appropriate place for them.
---
libavcodec/avcodec_internal.h | 24 ++++++++++++++++++++++++
libavcodec/pthread.c | 1 +
libavcodec/thread.h | 25 +------------------------
libavcodec/utils.c | 8 --------
4 files changed, 26 insertions(+), 32 deletions(-)
diff --git a/libavcodec/avcodec_internal.h b/libavcodec/avcodec_internal.h
index 0a024378ae..816f39ae76 100644
--- a/libavcodec/avcodec_internal.h
+++ b/libavcodec/avcodec_internal.h
@@ -72,4 +72,28 @@ struct AVCodecInternal *ff_encode_internal_alloc(void);
void ff_codec_close(struct AVCodecContext *avctx);
+int ff_thread_init(struct AVCodecContext *s);
+void ff_thread_free(struct AVCodecContext *s);
+
+/**
+ * Wait for decoding threads to finish and reset internal state.
+ * Called by avcodec_flush_buffers().
+ *
+ * @param avctx The context.
+ */
+void ff_thread_flush(struct AVCodecContext *avctx);
+
+/**
+ * Submit a new frame to a decoding thread.
+ * Returns the next available frame in picture. *got_picture_ptr
+ * will be 0 if none is available.
+ * The return value on success is the size of the consumed packet for
+ * compatibility with FFCodec.decode. This means the decoder
+ * has to consume the full packet.
+ *
+ * Parameters are the same as FFCodec.decode.
+ */
+int ff_thread_decode_frame(struct AVCodecContext *avctx, struct AVFrame *frame,
+ int *got_picture_ptr, struct AVPacket *avpkt);
+
#endif // AVCODEC_AVCODEC_INTERNAL_H
diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c
index ca84b81391..d32e56de0d 100644
--- a/libavcodec/pthread.c
+++ b/libavcodec/pthread.c
@@ -32,6 +32,7 @@
#include "libavutil/thread.h"
#include "avcodec.h"
+#include "avcodec_internal.h"
#include "codec_internal.h"
#include "pthread_internal.h"
#include "thread.h"
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index 5ab12848b4..47c00a0ed2 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -20,7 +20,7 @@
/**
* @file
- * Multithreading support functions
+ * Multithreading API for decoders
* @author Alexander Strange <astrange@ithinksw.com>
*/
@@ -31,27 +31,6 @@
#include "avcodec.h"
-/**
- * Wait for decoding threads to finish and reset internal state.
- * Called by avcodec_flush_buffers().
- *
- * @param avctx The context.
- */
-void ff_thread_flush(AVCodecContext *avctx);
-
-/**
- * Submit a new frame to a decoding thread.
- * Returns the next available frame in picture. *got_picture_ptr
- * will be 0 if none is available.
- * The return value on success is the size of the consumed packet for
- * compatibility with FFCodec.decode. This means the decoder
- * has to consume the full packet.
- *
- * Parameters are the same as FFCodec.decode.
- */
-int ff_thread_decode_frame(AVCodecContext *avctx, AVFrame *picture,
- int *got_picture_ptr, AVPacket *avpkt);
-
int ff_thread_can_start_frame(AVCodecContext *avctx);
/**
@@ -74,11 +53,9 @@ void ff_thread_finish_setup(AVCodecContext *avctx);
*/
int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags);
-int ff_thread_init(AVCodecContext *s);
int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx,
int (*action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr),
int (*main_func)(AVCodecContext *c), void *arg, int *ret, int job_count);
-void ff_thread_free(AVCodecContext *s);
int ff_slice_thread_allocz_entries(AVCodecContext *avctx, int count);
int ff_slice_thread_init_progress(AVCodecContext *avctx);
void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n);
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 337c00e789..b17fc3c7e2 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -806,14 +806,6 @@ int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes)
return FFMAX(0, duration);
}
-#if !HAVE_THREADS
-int ff_thread_init(AVCodecContext *s)
-{
- return -1;
-}
-
-#endif
-
unsigned int av_xiphlacing(unsigned char *s, unsigned int v)
{
unsigned int n = 0;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 30/39] lavc/internal: document the precise meaning of AVCodecInternal.draining
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (27 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 29/39] lavc/thread: move generic-layer API to avcodec_internal.h Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 31/39] lavc/decode: wrap AV_FRAME_FLAG_DISCARD handling in a loop Anton Khirnov
` (9 subsequent siblings)
38 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Also, set draining=1 in case a bitstream filter returns an
internally-triggered EOF. While no bitstream filters currently inserted
by decoders will do that, that may change in the future and it is better
to cover this case.
---
libavcodec/decode.c | 12 +++++-------
libavcodec/internal.h | 6 +++++-
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 791940648d..6ad74bd94b 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -213,8 +213,6 @@ static int decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
int ret;
ret = av_bsf_receive_packet(avci->bsf, pkt);
- if (ret == AVERROR_EOF)
- avci->draining = 1;
if (ret < 0)
return ret;
@@ -247,14 +245,14 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
if (ret == AVERROR(EAGAIN) &&
(!AVPACKET_IS_EMPTY(avci->buffer_pkt) || dc->draining_started)) {
ret = av_bsf_send_packet(avci->bsf, avci->buffer_pkt);
- if (ret < 0) {
- av_packet_unref(avci->buffer_pkt);
- return ret;
- }
+ if (ret >= 0)
+ continue;
- continue;
+ av_packet_unref(avci->buffer_pkt);
}
+ if (ret == AVERROR_EOF)
+ avci->draining = 1;
return ret;
}
}
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index bc20a797ae..d7b0b9f880 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -123,7 +123,11 @@ typedef struct AVCodecInternal {
void *hwaccel_priv_data;
/**
- * checks API usage: after codec draining, flush is required to resume operation
+ * decoding: AVERROR_EOF has been returned from ff_decode_get_packet(); must
+ * not be used by decoders that use the decode() callback, as they
+ * do not call ff_decode_get_packet() directly.
+ *
+ * encoding: a flush frame has been submitted to avcodec_send_frame().
*/
int draining;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 31/39] lavc/decode: wrap AV_FRAME_FLAG_DISCARD handling in a loop
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (28 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 30/39] lavc/internal: document the precise meaning of AVCodecInternal.draining Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-17 21:20 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 32/39] lavc/decode: reindent Anton Khirnov
` (8 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Makes sure discarded frames do not cause EAGAIN to be returned during
flushing, which is forbidden.
---
libavcodec/decode.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 6ad74bd94b..b17cfba26f 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -613,17 +613,22 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
av_assert0(!frame->buf[0]);
if (codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME) {
+ while (1) {
frame->pict_type = dc->initial_pict_type;
frame->flags |= dc->intra_only_flag;
ret = codec->cb.receive_frame(avctx, frame);
emms_c();
if (!ret) {
- if (avctx->codec->type == AVMEDIA_TYPE_VIDEO)
- ret = (frame->flags & AV_FRAME_FLAG_DISCARD) ? AVERROR(EAGAIN) : 0;
- else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
+ if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
int64_t discarded_samples = 0;
ret = discard_samples(avctx, frame, &discarded_samples);
}
+ if (ret == AVERROR(EAGAIN) || (frame->flags & AV_FRAME_FLAG_DISCARD)) {
+ av_frame_unref(frame);
+ continue;
+ }
+ }
+ break;
}
} else
ret = decode_simple_receive_frame(avctx, frame);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 32/39] lavc/decode: reindent
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (29 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 31/39] lavc/decode: wrap AV_FRAME_FLAG_DISCARD handling in a loop Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 33/39] lavc: convert frame threading to the receive_frame() pattern Anton Khirnov
` (7 subsequent siblings)
38 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/decode.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index b17cfba26f..42cee77ec5 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -614,21 +614,21 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
if (codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME) {
while (1) {
- frame->pict_type = dc->initial_pict_type;
- frame->flags |= dc->intra_only_flag;
- ret = codec->cb.receive_frame(avctx, frame);
- emms_c();
- if (!ret) {
- if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
- int64_t discarded_samples = 0;
- ret = discard_samples(avctx, frame, &discarded_samples);
+ frame->pict_type = dc->initial_pict_type;
+ frame->flags |= dc->intra_only_flag;
+ ret = codec->cb.receive_frame(avctx, frame);
+ emms_c();
+ if (!ret) {
+ if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
+ int64_t discarded_samples = 0;
+ ret = discard_samples(avctx, frame, &discarded_samples);
+ }
+ if (ret == AVERROR(EAGAIN) || (frame->flags & AV_FRAME_FLAG_DISCARD)) {
+ av_frame_unref(frame);
+ continue;
+ }
}
- if (ret == AVERROR(EAGAIN) || (frame->flags & AV_FRAME_FLAG_DISCARD)) {
- av_frame_unref(frame);
- continue;
- }
- }
- break;
+ break;
}
} else
ret = decode_simple_receive_frame(avctx, frame);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 33/39] lavc: convert frame threading to the receive_frame() pattern
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (30 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 32/39] lavc/decode: reindent Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 18:44 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 34/39] lavc/decode: reindent after previous commit Anton Khirnov
` (6 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Reorganize the code such that the frame threading code does not call the
decoders directly, but instead calls back into the generic decoding
code. This avoids duplicating the logic that wraps the decoder
invocation and allows receive_frame()-based decoders to use frame
threading.
Further work by Timo Rothenpieler <timo@rothenpieler.org>.
---
libavcodec/avcodec.c | 9 +-
libavcodec/avcodec_internal.h | 25 +--
libavcodec/decode.c | 40 +++--
libavcodec/internal.h | 7 +
libavcodec/pthread_frame.c | 278 +++++++++++++++++++++-------------
5 files changed, 235 insertions(+), 124 deletions(-)
diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
index 214dca4566..6065f1b689 100644
--- a/libavcodec/avcodec.c
+++ b/libavcodec/avcodec.c
@@ -381,10 +381,13 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
avci->draining = 0;
avci->draining_done = 0;
- av_frame_unref(avci->buffer_frame);
- av_packet_unref(avci->buffer_pkt);
+ if (avci->buffer_frame)
+ av_frame_unref(avci->buffer_frame);
+ if (avci->buffer_pkt)
+ av_packet_unref(avci->buffer_pkt);
- if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME)
+ if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME &&
+ !avci->is_frame_mt)
ff_thread_flush(avctx);
else if (ffcodec(avctx->codec)->flush)
ffcodec(avctx->codec)->flush(avctx);
diff --git a/libavcodec/avcodec_internal.h b/libavcodec/avcodec_internal.h
index 816f39ae76..2f0aaab93b 100644
--- a/libavcodec/avcodec_internal.h
+++ b/libavcodec/avcodec_internal.h
@@ -84,16 +84,23 @@ void ff_thread_free(struct AVCodecContext *s);
void ff_thread_flush(struct AVCodecContext *avctx);
/**
- * Submit a new frame to a decoding thread.
- * Returns the next available frame in picture. *got_picture_ptr
- * will be 0 if none is available.
- * The return value on success is the size of the consumed packet for
- * compatibility with FFCodec.decode. This means the decoder
- * has to consume the full packet.
+ * Submit available packets for decoding to worker threads, return a
+ * decoded frame if available. Returns AVERROR(EAGAIN) if none is available.
*
- * Parameters are the same as FFCodec.decode.
+ * Parameters are the same as FFCodec.receive_frame.
*/
-int ff_thread_decode_frame(struct AVCodecContext *avctx, struct AVFrame *frame,
- int *got_picture_ptr, struct AVPacket *avpkt);
+int ff_thread_receive_frame(AVCodecContext *avctx, AVFrame *frame);
+
+/**
+ * Do the actual decoding and obtain a decoded frame from the decoder, if
+ * available. When frame threading is used, this is invoked by the worker
+ * threads, otherwise by the top layer directly.
+ */
+int ff_decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame);
+
+/**
+ * Get a packet for decoding. This gets invoked by the worker threads.
+ */
+int ff_thread_get_packet(AVCodecContext *avctx, AVPacket *pkt);
#endif // AVCODEC_AVCODEC_INTERNAL_H
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 42cee77ec5..dd94280f0b 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -207,6 +207,11 @@ fail:
return ret;
}
+#if !HAVE_THREADS
+#define ff_thread_get_packet(avctx, pkt) (AVERROR_BUG)
+#define ff_thread_receive_frame(avctx, frame) (AVERROR_BUG)
+#endif
+
static int decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
{
AVCodecInternal *avci = avctx->internal;
@@ -240,6 +245,13 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt)
if (avci->draining)
return AVERROR_EOF;
+ /* If we are a worker thread, get the next packet from the threading
+ * context. Otherwise we are the main (user-facing) context, so we get the
+ * next packet from the input filterchain.
+ */
+ if (avctx->internal->is_frame_mt)
+ return ff_thread_get_packet(avctx, pkt);
+
while (1) {
int ret = decode_get_packet(avctx, pkt);
if (ret == AVERROR(EAGAIN) &&
@@ -413,15 +425,11 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame,
return AVERROR_EOF;
if (!pkt->data &&
- !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY ||
- avctx->active_thread_type & FF_THREAD_FRAME))
+ !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
return AVERROR_EOF;
got_frame = 0;
- if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) {
- consumed = ff_thread_decode_frame(avctx, frame, &got_frame, pkt);
- } else {
frame->pict_type = dc->initial_pict_type;
frame->flags |= dc->intra_only_flag;
consumed = codec->cb.decode(avctx, frame, &got_frame, pkt);
@@ -436,7 +444,6 @@ FF_DISABLE_DEPRECATION_WARNINGS
FF_ENABLE_DEPRECATION_WARNINGS
#endif
}
- }
emms_c();
if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) {
@@ -603,12 +610,12 @@ static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame)
return 0;
}
-static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
+int ff_decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
{
AVCodecInternal *avci = avctx->internal;
DecodeContext *dc = decode_ctx(avci);
const FFCodec *const codec = ffcodec(avctx->codec);
- int ret, ok;
+ int ret;
av_assert0(!frame->buf[0]);
@@ -636,6 +643,20 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
if (ret == AVERROR_EOF)
avci->draining_done = 1;
+ return ret;
+}
+
+static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
+{
+ AVCodecInternal *avci = avctx->internal;
+ DecodeContext *dc = decode_ctx(avci);
+ int ret, ok;
+
+ if (avctx->active_thread_type & FF_THREAD_FRAME)
+ ret = ff_thread_receive_frame(avctx, frame);
+ else
+ ret = ff_decode_receive_frame_internal(avctx, frame);
+
/* preserve ret */
ok = detect_colorspace(avctx, frame);
if (ok < 0) {
@@ -2151,7 +2172,8 @@ void ff_decode_flush_buffers(AVCodecContext *avctx)
dc->pts_correction_last_pts =
dc->pts_correction_last_dts = INT64_MIN;
- av_bsf_flush(avci->bsf);
+ if (avci->bsf)
+ av_bsf_flush(avci->bsf);
dc->nb_draining_errors = 0;
dc->draining_started = 0;
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index d7b0b9f880..98ab2797ce 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -53,6 +53,13 @@ typedef struct AVCodecInternal {
*/
int is_copy;
+ /**
+ * This field is set to 1 when frame threading is being used and the parent
+ * AVCodecContext of this AVCodecInternal is a worker-thread context (i.e.
+ * one of those actually doing the decoding), 0 otherwise.
+ */
+ int is_frame_mt;
+
/**
* Audio encoders can set this flag during init to indicate that they
* want the small last frame to be padded to a multiple of pad_samples.
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 85a3dce929..019e33b7b2 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -32,6 +32,7 @@
#include "hwaccel_internal.h"
#include "hwconfig.h"
#include "internal.h"
+#include "packet_internal.h"
#include "pthread_internal.h"
#include "refstruct.h"
#include "thread.h"
@@ -64,6 +65,12 @@ enum {
INITIALIZED, ///< Thread has been properly set up
};
+typedef struct DecodedFrames {
+ AVFrame **f;
+ size_t nb_f;
+ size_t nb_f_allocated;
+} DecodedFrames;
+
typedef struct ThreadFrameProgress {
atomic_int progress[2];
} ThreadFrameProgress;
@@ -88,8 +95,10 @@ typedef struct PerThreadContext {
AVPacket *avpkt; ///< Input packet (for decoding) or output (for encoding).
- AVFrame *frame; ///< Output frame (for decoding) or input (for encoding).
- int got_frame; ///< The output of got_picture_ptr from the last avcodec_decode_video() call.
+ /**
+ * Decoded frames from a single decode iteration.
+ */
+ DecodedFrames df;
int result; ///< The result of the last codec decode/encode() call.
atomic_int state;
@@ -130,14 +139,17 @@ typedef struct FrameThreadContext {
pthread_cond_t async_cond;
int async_lock;
+ DecodedFrames df;
+ int result;
+
+ /**
+ * Packet to be submitted to the next thread for decoding.
+ */
+ AVPacket *next_pkt;
+
int next_decoding; ///< The next context to submit a packet to.
int next_finished; ///< The next context to return output from.
- int delaying; /**<
- * Set for the first N packets, where N is the number of threads.
- * While it is set, ff_thread_en/decode_frame won't return any results.
- */
-
/* hwaccel state for thread-unsafe hwaccels is temporarily stored here in
* order to transfer its ownership to the next decoding thread without the
* need for extra synchronization */
@@ -180,6 +192,52 @@ static void thread_set_name(PerThreadContext *p)
ff_thread_setname(name);
}
+// get a free frame to decode into
+static AVFrame *decoded_frames_get_free(DecodedFrames *df)
+{
+ if (df->nb_f == df->nb_f_allocated) {
+ AVFrame **tmp = av_realloc_array(df->f, df->nb_f + 1,
+ sizeof(*df->f));
+ if (!tmp)
+ return NULL;
+ df->f = tmp;
+
+ df->f[df->nb_f] = av_frame_alloc();
+ if (!df->f[df->nb_f])
+ return NULL;
+
+ df->nb_f_allocated++;
+ }
+
+ av_assert0(!df->f[df->nb_f]->buf[0]);
+
+ return df->f[df->nb_f];
+}
+
+static void decoded_frames_pop(DecodedFrames *df, AVFrame *dst)
+{
+ AVFrame *tmp_frame = df->f[0];
+ av_frame_move_ref(dst, tmp_frame);
+ memmove(df->f, df->f + 1, (df->nb_f - 1) * sizeof(*df->f));
+ df->f[--df->nb_f] = tmp_frame;
+}
+
+static void decoded_frames_flush(DecodedFrames *df)
+{
+ for (size_t i = 0; i < df->nb_f; i++)
+ av_frame_unref(df->f[i]);
+ df->nb_f = 0;
+}
+
+static void decoded_frames_free(DecodedFrames *df)
+{
+ for (size_t i = 0; i < df->nb_f_allocated; i++)
+ av_frame_free(&df->f[i]);
+ av_freep(&df->f);
+ df->nb_f = 0;
+ df->nb_f_allocated = 0;
+}
+
/**
* Codec worker thread.
*
@@ -197,6 +255,8 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
pthread_mutex_lock(&p->mutex);
while (1) {
+ int ret;
+
while (atomic_load(&p->state) == STATE_INPUT_READY && !p->die)
pthread_cond_wait(&p->input_cond, &p->mutex);
@@ -220,18 +280,31 @@ static attribute_align_arg void *frame_worker_thread(void *arg)
p->hwaccel_serializing = 1;
}
- av_frame_unref(p->frame);
- p->got_frame = 0;
- p->frame->pict_type = p->initial_pict_type;
- p->frame->flags |= p->intra_only_flag;
- p->result = codec->cb.decode(avctx, p->frame, &p->got_frame, p->avpkt);
+ ret = 0;
+ while (ret >= 0) {
+ AVFrame *frame;
- if ((p->result < 0 || !p->got_frame) && p->frame->buf[0])
- av_frame_unref(p->frame);
+ /* get the frame which will store the output */
+ frame = decoded_frames_get_free(&p->df);
+ if (!frame) {
+ p->result = AVERROR(ENOMEM);
+ goto alloc_fail;
+ }
+
+ /* do the actual decoding */
+ ret = ff_decode_receive_frame_internal(avctx, frame);
+ if (ret == 0)
+ p->df.nb_f++;
+ else if (ret < 0 && frame->buf[0])
+ av_frame_unref(frame);
+
+ p->result = (ret == AVERROR(EAGAIN)) ? 0 : ret;
+ }
if (atomic_load(&p->state) == STATE_SETTING_UP)
ff_thread_finish_setup(avctx);
+alloc_fail:
if (p->hwaccel_serializing) {
/* wipe hwaccel state for thread-unsafe hwaccels to avoid stale
* pointers lying around;
@@ -426,18 +499,21 @@ static int update_context_from_user(AVCodecContext *dst, const AVCodecContext *s
}
static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
- AVPacket *avpkt)
+ AVPacket *in_pkt)
{
FrameThreadContext *fctx = p->parent;
PerThreadContext *prev_thread = fctx->prev_thread;
const AVCodec *codec = p->avctx->codec;
int ret;
- if (!avpkt->size && !(codec->capabilities & AV_CODEC_CAP_DELAY))
- return 0;
-
pthread_mutex_lock(&p->mutex);
+ av_packet_unref(p->avpkt);
+ av_packet_move_ref(p->avpkt, in_pkt);
+
+ if (AVPACKET_IS_EMPTY(p->avpkt))
+ p->avctx->internal->draining = 1;
+
ret = update_context_from_user(p->avctx, user_avctx);
if (ret) {
pthread_mutex_unlock(&p->mutex);
@@ -448,7 +524,6 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
memory_order_relaxed);
if (prev_thread) {
- int err;
if (atomic_load(&prev_thread->state) == STATE_SETTING_UP) {
pthread_mutex_lock(&prev_thread->progress_mutex);
while (atomic_load(&prev_thread->state) == STATE_SETTING_UP)
@@ -456,10 +531,16 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
pthread_mutex_unlock(&prev_thread->progress_mutex);
}
- err = update_context_from_thread(p->avctx, prev_thread->avctx, 0);
- if (err) {
- pthread_mutex_unlock(&p->mutex);
- return err;
+ /* codecs without delay might not be prepared to be called repeatedly here during
+ * flushing (vp3/theora), and also don't need to be, since from this point on, they
+ * will always return EOF anyway */
+ if (!p->avctx->internal->draining ||
+ (codec->capabilities & AV_CODEC_CAP_DELAY)) {
+ ret = update_context_from_thread(p->avctx, prev_thread->avctx, 0);
+ if (ret) {
+ pthread_mutex_unlock(&p->mutex);
+ return ret;
+ }
}
}
@@ -471,70 +552,47 @@ static int submit_packet(PerThreadContext *p, AVCodecContext *user_avctx,
FFSWAP(void*, p->avctx->internal->hwaccel_priv_data, fctx->stash_hwaccel_priv);
}
- av_packet_unref(p->avpkt);
- ret = av_packet_ref(p->avpkt, avpkt);
- if (ret < 0) {
- pthread_mutex_unlock(&p->mutex);
- av_log(p->avctx, AV_LOG_ERROR, "av_packet_ref() failed in submit_packet()\n");
- return ret;
- }
-
atomic_store(&p->state, STATE_SETTING_UP);
pthread_cond_signal(&p->input_cond);
pthread_mutex_unlock(&p->mutex);
fctx->prev_thread = p;
- fctx->next_decoding++;
+ fctx->next_decoding = (fctx->next_decoding + 1) % p->avctx->thread_count;
return 0;
}
-int ff_thread_decode_frame(AVCodecContext *avctx,
- AVFrame *picture, int *got_picture_ptr,
- AVPacket *avpkt)
+int ff_thread_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{
FrameThreadContext *fctx = avctx->internal->thread_ctx;
- int finished = fctx->next_finished;
- PerThreadContext *p;
- int err;
+ int ret = 0;
/* release the async lock, permitting blocked hwaccel threads to
* go forward while we are in this function */
async_unlock(fctx);
- /*
- * Submit a packet to the next decoding thread.
- */
+ /* submit packets to threads while there are no buffered results to return */
+ while (!fctx->df.nb_f && !fctx->result) {
+ PerThreadContext *p;
- p = &fctx->threads[fctx->next_decoding];
- err = submit_packet(p, avctx, avpkt);
- if (err)
- goto finish;
-
- /*
- * If we're still receiving the initial packets, don't return a frame.
- */
-
- if (fctx->next_decoding > (avctx->thread_count-1-(avctx->codec_id == AV_CODEC_ID_FFV1)))
- fctx->delaying = 0;
-
- if (fctx->delaying) {
- *got_picture_ptr=0;
- if (avpkt->size) {
- err = avpkt->size;
+ /* get a packet to be submitted to the next thread */
+ av_packet_unref(fctx->next_pkt);
+ ret = ff_decode_get_packet(avctx, fctx->next_pkt);
+ if (ret < 0 && ret != AVERROR_EOF)
goto finish;
- }
- }
- /*
- * Return the next available frame from the oldest thread.
- * If we're at the end of the stream, then we have to skip threads that
- * didn't output a frame/error, because we don't want to accidentally signal
- * EOF (avpkt->size == 0 && *got_picture_ptr == 0 && err >= 0).
- */
+ ret = submit_packet(&fctx->threads[fctx->next_decoding], avctx,
+ fctx->next_pkt);
+ if (ret < 0)
+ goto finish;
- do {
- p = &fctx->threads[finished++];
+ /* do not return any frames until all threads have something to do */
+ if (fctx->next_decoding != fctx->next_finished &&
+ !avctx->internal->draining)
+ continue;
+
+ p = &fctx->threads[fctx->next_finished];
+ fctx->next_finished = (fctx->next_finished + 1) % avctx->thread_count;
if (atomic_load(&p->state) != STATE_INPUT_READY) {
pthread_mutex_lock(&p->progress_mutex);
@@ -543,35 +601,26 @@ int ff_thread_decode_frame(AVCodecContext *avctx,
pthread_mutex_unlock(&p->progress_mutex);
}
- av_frame_move_ref(picture, p->frame);
- *got_picture_ptr = p->got_frame;
- picture->pkt_dts = p->avpkt->dts;
- err = p->result;
+ update_context_from_thread(avctx, p->avctx, 1);
+ fctx->result = p->result;
+ p->result = 0;
+ if (p->df.nb_f)
+ FFSWAP(DecodedFrames, fctx->df, p->df);
+ }
- /*
- * A later call with avkpt->size == 0 may loop over all threads,
- * including this one, searching for a frame/error to return before being
- * stopped by the "finished != fctx->next_finished" condition.
- * Make sure we don't mistakenly return the same frame/error again.
- */
- p->got_frame = 0;
- p->result = 0;
+ /* a thread may return multiple frames AND an error
+ * we first return all the frames, then the error */
+ if (fctx->df.nb_f) {
+ decoded_frames_pop(&fctx->df, frame);
+ ret = 0;
+ } else {
+ ret = fctx->result;
+ fctx->result = 0;
+ }
- if (finished >= avctx->thread_count) finished = 0;
- } while (!avpkt->size && !*got_picture_ptr && err >= 0 && finished != fctx->next_finished);
-
- update_context_from_thread(avctx, p->avctx, 1);
-
- if (fctx->next_decoding >= avctx->thread_count) fctx->next_decoding = 0;
-
- fctx->next_finished = finished;
-
- /* return the size of the consumed packet if no error occurred */
- if (err >= 0)
- err = avpkt->size;
finish:
async_lock(fctx);
- return err;
+ return ret;
}
void ff_thread_report_progress(ThreadFrame *f, int n, int field)
@@ -679,7 +728,6 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
pthread_cond_wait(&p->output_cond, &p->progress_mutex);
pthread_mutex_unlock(&p->progress_mutex);
}
- p->got_frame = 0;
}
async_lock(fctx);
@@ -732,6 +780,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
}
ff_refstruct_unref(&ctx->internal->pool);
+ av_packet_free(&ctx->internal->in_pkt);
av_packet_free(&ctx->internal->last_pkt_props);
av_freep(&ctx->internal);
av_buffer_unref(&ctx->hw_frames_ctx);
@@ -739,7 +788,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
&ctx->nb_decoded_side_data);
}
- av_frame_free(&p->frame);
+ decoded_frames_free(&p->df);
ff_pthread_free(p, per_thread_offsets);
av_packet_free(&p->avpkt);
@@ -747,6 +796,9 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
av_freep(&p->avctx);
}
+ decoded_frames_free(&fctx->df);
+ av_packet_free(&fctx->next_pkt);
+
av_freep(&fctx->threads);
ff_pthread_free(fctx, thread_ctx_offsets);
@@ -815,13 +867,17 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
if (err < 0)
return err;
- if (!(p->frame = av_frame_alloc()) ||
- !(p->avpkt = av_packet_alloc()))
+ if (!(p->avpkt = av_packet_alloc()))
return AVERROR(ENOMEM);
+ copy->internal->is_frame_mt = 1;
if (!first)
copy->internal->is_copy = 1;
+ copy->internal->in_pkt = av_packet_alloc();
+ if (!copy->internal->in_pkt)
+ return AVERROR(ENOMEM);
+
copy->internal->last_pkt_props = av_packet_alloc();
if (!copy->internal->last_pkt_props)
return AVERROR(ENOMEM);
@@ -891,8 +947,11 @@ int ff_frame_thread_init(AVCodecContext *avctx)
return err;
}
+ fctx->next_pkt = av_packet_alloc();
+ if (!fctx->next_pkt)
+ return AVERROR(ENOMEM);
+
fctx->async_lock = 1;
- fctx->delaying = 1;
if (codec->p.type == AVMEDIA_TYPE_VIDEO)
avctx->delay = avctx->thread_count - 1;
@@ -933,17 +992,18 @@ void ff_thread_flush(AVCodecContext *avctx)
}
fctx->next_decoding = fctx->next_finished = 0;
- fctx->delaying = 1;
fctx->prev_thread = NULL;
+
+ decoded_frames_flush(&fctx->df);
+ fctx->result = 0;
+
for (i = 0; i < avctx->thread_count; i++) {
PerThreadContext *p = &fctx->threads[i];
- // Make sure decode flush calls with size=0 won't return old frames
- p->got_frame = 0;
- av_frame_unref(p->frame);
+
+ decoded_frames_flush(&p->df);
p->result = 0;
- if (ffcodec(avctx->codec)->flush)
- ffcodec(avctx->codec)->flush(p->avctx);
+ avcodec_flush_buffers(p->avctx);
}
}
@@ -1039,3 +1099,15 @@ enum ThreadingStatus ff_thread_sync_ref(AVCodecContext *avctx, size_t offset)
return FF_THREAD_IS_COPY;
}
+
+int ff_thread_get_packet(AVCodecContext *avctx, AVPacket *pkt)
+{
+ PerThreadContext *p = avctx->internal->thread_ctx;
+
+ if (!AVPACKET_IS_EMPTY(p->avpkt)) {
+ av_packet_move_ref(pkt, p->avpkt);
+ return 0;
+ }
+
+ return avctx->internal->draining ? AVERROR_EOF : AVERROR(EAGAIN);
+}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 34/39] lavc/decode: reindent after previous commit
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (31 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 33/39] lavc: convert frame threading to the receive_frame() pattern Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-08-12 12:49 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 35/39] lavc/hevcdec: switch to receive_frame() Anton Khirnov
` (5 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
---
libavcodec/decode.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index dd94280f0b..deaecf0c01 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -430,20 +430,20 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame,
got_frame = 0;
- frame->pict_type = dc->initial_pict_type;
- frame->flags |= dc->intra_only_flag;
- consumed = codec->cb.decode(avctx, frame, &got_frame, pkt);
+ frame->pict_type = dc->initial_pict_type;
+ frame->flags |= dc->intra_only_flag;
+ consumed = codec->cb.decode(avctx, frame, &got_frame, pkt);
- if (!(codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS))
- frame->pkt_dts = pkt->dts;
- if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) {
+ if (!(codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS))
+ frame->pkt_dts = pkt->dts;
+ if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) {
#if FF_API_FRAME_PKT
FF_DISABLE_DEPRECATION_WARNINGS
- if(!avctx->has_b_frames)
- frame->pkt_pos = pkt->pos;
+ if(!avctx->has_b_frames)
+ frame->pkt_pos = pkt->pos;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
- }
+ }
emms_c();
if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) {
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 35/39] lavc/hevcdec: switch to receive_frame()
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (32 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 34/39] lavc/decode: reindent after previous commit Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 36/39] lavc: add private container FIFO API Anton Khirnov
` (4 subsequent siblings)
38 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Required by following commits, where we will want to output multiple
frames per packet.
---
libavcodec/hevc/hevcdec.c | 29 ++++++++++++++++-------------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 0e4b26dad3..fc87169a1a 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -3401,22 +3401,25 @@ static int hevc_decode_extradata(HEVCContext *s, uint8_t *buf, int length, int f
return 0;
}
-static int hevc_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
- int *got_output, AVPacket *avpkt)
+static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
{
+ HEVCContext *s = avctx->priv_data;
+ AVCodecInternal *avci = avctx->internal;
+ AVPacket *avpkt = avci->in_pkt;
+
int ret;
uint8_t *sd;
size_t sd_size;
- HEVCContext *s = avctx->priv_data;
- if (!avpkt->size) {
- ret = ff_hevc_output_frame(s, rframe, 1);
+ av_packet_unref(avpkt);
+ ret = ff_decode_get_packet(avctx, avpkt);
+ if (ret == AVERROR_EOF) {
+ ret = ff_hevc_output_frame(s, frame, 1);
if (ret < 0)
return ret;
-
- *got_output = ret;
- return 0;
- }
+ return (ret > 0) ? 0 : AVERROR_EOF;
+ } else if (ret < 0)
+ return ret;
sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &sd_size);
if (sd && sd_size > 0) {
@@ -3440,11 +3443,11 @@ static int hevc_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
return ret;
if (s->output_frame->buf[0]) {
- av_frame_move_ref(rframe, s->output_frame);
- *got_output = 1;
+ av_frame_move_ref(frame, s->output_frame);
+ return 0;
}
- return avpkt->size;
+ return AVERROR(EAGAIN);
}
static int hevc_ref_frame(HEVCFrame *dst, const HEVCFrame *src)
@@ -3721,7 +3724,7 @@ const FFCodec ff_hevc_decoder = {
.p.priv_class = &hevc_decoder_class,
.init = hevc_decode_init,
.close = hevc_decode_free,
- FF_CODEC_DECODE_CB(hevc_decode_frame),
+ FF_CODEC_RECEIVE_FRAME_CB(hevc_receive_frame),
.flush = hevc_decode_flush,
UPDATE_THREAD_CONTEXT(hevc_update_thread_context),
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 36/39] lavc: add private container FIFO API
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (33 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 35/39] lavc/hevcdec: switch to receive_frame() Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-08-10 0:09 ` Andreas Rheinhardt
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 37/39] lavc/hevcdec: use a ContainerFifo to hold frames scheduled for output Anton Khirnov
` (3 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
It provides a FIFO for "container" objects like AVFrame/AVPacket and
features an integrated FFRefStructPool-based pool to avoid allocating an
freeing them repeatedly.
---
libavcodec/container_fifo.c | 195 ++++++++++++++++++++++++++++++++++++
libavcodec/container_fifo.h | 87 ++++++++++++++++
2 files changed, 282 insertions(+)
create mode 100644 libavcodec/container_fifo.c
create mode 100644 libavcodec/container_fifo.h
diff --git a/libavcodec/container_fifo.c b/libavcodec/container_fifo.c
new file mode 100644
index 0000000000..86ed15627b
--- /dev/null
+++ b/libavcodec/container_fifo.c
@@ -0,0 +1,195 @@
+/*
+ * 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/error.h"
+#include "libavutil/fifo.h"
+#include "libavutil/frame.h"
+#include "libavutil/mem.h"
+
+#include "container_fifo.h"
+#include "refstruct.h"
+
+struct ContainerFifo {
+ AVFifo *fifo;
+ FFRefStructPool *pool;
+
+ void* (*container_alloc)(void);
+ void (*container_reset)(void *obj);
+ void (*container_free) (void *obj);
+ int (*fifo_write) (void *dst, void *src);
+ int (*fifo_read) (void *dst, void *src);
+
+};
+
+static int container_fifo_init_entry(FFRefStructOpaque opaque, void *obj)
+{
+ ContainerFifo *cf = opaque.nc;
+ void **pobj = obj;
+
+ *pobj = cf->container_alloc();
+ if (!*pobj)
+ return AVERROR(ENOMEM);
+
+ return 0;
+}
+
+static void container_fifo_reset_entry(FFRefStructOpaque opaque, void *obj)
+{
+ ContainerFifo *cf = opaque.nc;
+ cf->container_reset(*(void**)obj);
+}
+
+static void container_fifo_free_entry(FFRefStructOpaque opaque, void *obj)
+{
+ ContainerFifo *cf = opaque.nc;
+ cf->container_free(*(void**)obj);
+}
+
+ContainerFifo*
+ff_container_fifo_alloc(void* (*container_alloc)(void),
+ void (*container_reset)(void *obj),
+ void (*container_free) (void *obj),
+ int (*fifo_write) (void *dst, void *src),
+ int (*fifo_read) (void *dst, void *src))
+{
+ ContainerFifo *cf;
+
+ cf = av_mallocz(sizeof(*cf));
+ if (!cf)
+ return NULL;
+
+ cf->container_alloc = container_alloc;
+ cf->container_reset = container_reset;
+ cf->container_free = container_free;
+ cf->fifo_write = fifo_write;
+ cf->fifo_read = fifo_read;
+
+ cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW);
+ if (!cf->fifo)
+ goto fail;
+
+ cf->pool = ff_refstruct_pool_alloc_ext(sizeof(void*), 0, cf,
+ container_fifo_init_entry,
+ container_fifo_reset_entry,
+ container_fifo_free_entry,
+ NULL);
+ if (!cf->pool)
+ goto fail;
+
+ return cf;
+fail:
+ ff_container_fifo_free(&cf);
+ return NULL;
+}
+
+void ff_container_fifo_free(ContainerFifo **pcf)
+{
+ ContainerFifo *cf;
+
+ if (!*pcf)
+ return;
+
+ cf = *pcf;
+
+ if (cf->fifo) {
+ void *obj;
+ while (av_fifo_read(cf->fifo, &obj, 1) >= 0)
+ ff_refstruct_unref(&obj);
+ av_fifo_freep2(&cf->fifo);
+ }
+
+ ff_refstruct_pool_uninit(&cf->pool);
+
+ av_freep(pcf);
+}
+
+int ff_container_fifo_read(ContainerFifo *cf, void *obj)
+{
+ void **psrc;
+ int ret;
+
+ ret = av_fifo_read(cf->fifo, &psrc, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = cf->fifo_read(obj, *psrc);
+ ff_refstruct_unref(&psrc);
+
+ return ret;
+}
+
+int ff_container_fifo_write(ContainerFifo *cf, void *obj)
+{
+ void **pdst;
+ int ret;
+
+ pdst = ff_refstruct_pool_get(cf->pool);
+ if (!pdst)
+ return AVERROR(ENOMEM);
+
+ ret = cf->fifo_write(*pdst, obj);
+ if (ret < 0)
+ goto fail;
+
+ ret = av_fifo_write(cf->fifo, &pdst, 1);
+ if (ret < 0)
+ goto fail;
+
+ return 0;
+fail:
+ ff_refstruct_unref(&pdst);
+ return ret;
+}
+
+size_t ff_container_fifo_can_read(ContainerFifo *cf)
+{
+ return av_fifo_can_read(cf->fifo);
+}
+
+static void* frame_alloc(void)
+{
+ return av_frame_alloc();
+}
+
+static void frame_reset(void *obj)
+{
+ av_frame_unref(obj);
+}
+
+static void frame_free(void *obj)
+{
+ AVFrame *frame = obj;
+ av_frame_free(&frame);
+}
+
+static int frame_ref(void *dst, void *src)
+{
+ return av_frame_ref(dst, src);
+}
+
+static int frame_move_ref(void *dst, void *src)
+{
+ av_frame_move_ref(dst, src);
+ return 0;
+}
+
+ContainerFifo *ff_container_fifo_alloc_avframe(unsigned flags)
+{
+ return ff_container_fifo_alloc(frame_alloc, frame_reset, frame_free,
+ frame_ref, frame_move_ref);
+}
diff --git a/libavcodec/container_fifo.h b/libavcodec/container_fifo.h
new file mode 100644
index 0000000000..75a8f9e86b
--- /dev/null
+++ b/libavcodec/container_fifo.h
@@ -0,0 +1,87 @@
+/*
+ * 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_CONTAINER_FIFO_H
+#define AVCODEC_CONTAINER_FIFO_H
+
+/**
+ * ContainerFifo is a FIFO for "containers" - dynamically allocated reusable
+ * structs (e.g. AVFrame or AVPacket). ContainerFifo uses an internal pool of
+ * such containers to avoid allocating and freeing them repeatedly.
+ */
+typedef struct ContainerFifo ContainerFifo;
+
+/**
+ * Allocate a new ContainerFifo for the container type defined by provided
+ * callbacks.
+ *
+ * @param container_alloc allocate a new container instance and return a pointer
+ * to it, or NULL on failure
+ * @param container_reset reset the provided container instance to a clean state
+ * @param container_free free the provided container instance
+ * @param fifo_write transfer the contents of src to dst, where src is a
+ * container instance provided to ff_container_fifo_write()
+ * @param fifo_read transfer the contents of src to dst in other cases
+ *
+ * @note fifo_read() and fifo_write() are different parameters in order to allow
+ * fifo_write() implementations that make a new reference in dst, leaving
+ * src untouched (see e.g. ff_container_fifo_alloc_avframe())
+ */
+ContainerFifo*
+ff_container_fifo_alloc(void* (*container_alloc)(void),
+ void (*container_reset)(void *obj),
+ void (*container_free) (void *obj),
+ int (*fifo_write) (void *dst, void *src),
+ int (*fifo_read) (void *dst, void *src));
+
+/**
+ * Allocate a ContainerFifo instance for AVFrames.
+ * Note that ff_container_fifo_write() will call av_frame_ref() on src, making a
+ * new reference in dst and leaving src untouched.
+ *
+ * @param flags unused currently
+ */
+ContainerFifo *ff_container_fifo_alloc_avframe(unsigned flags);
+
+/**
+ * Free a ContainerFifo and everything in it.
+ */
+void ff_container_fifo_free(ContainerFifo **pf);
+
+/**
+ * Write the contents of obj to the FIFO.
+ *
+ * The fifo_write() callback previously provided to ff_container_fifo_alloc()
+ * will be called with obj as src in order to perform the actual transfer.
+ */
+int ff_container_fifo_write(ContainerFifo *pf, void *obj);
+
+/**
+ * Read the next available object from the FIFO into obj.
+ *
+ * The fifo_read() callback previously provided to ff_container_fifo_alloc()
+ * will be called with obj as dst in order to perform the actual transfer.
+ */
+int ff_container_fifo_read(ContainerFifo *pf, void *obj);
+
+/**
+ * @return number of objects available for reading
+ */
+size_t ff_container_fifo_can_read(ContainerFifo *pf);
+
+#endif // AVCODEC_CONTAINER_FIFO_H
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 37/39] lavc/hevcdec: use a ContainerFifo to hold frames scheduled for output
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (34 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 36/39] lavc: add private container FIFO API Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-08-09 23:52 ` Andreas Rheinhardt
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 38/39] lavc/hevcdec: simplify output logic Anton Khirnov
` (2 subsequent siblings)
38 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Instead of a single AVFrame.
Will be useful in future commits, where we will want to produce multiple
output frames for a single coded frame.
---
libavcodec/Makefile | 2 +-
libavcodec/hevc/hevcdec.c | 30 ++++++++++++++++++++----------
libavcodec/hevc/hevcdec.h | 5 +++--
libavcodec/hevc/refs.c | 11 +++--------
4 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 771e2b597e..e67b729bd3 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -431,7 +431,7 @@ OBJS-$(CONFIG_HCA_DECODER) += hcadec.o
OBJS-$(CONFIG_HCOM_DECODER) += hcom.o
OBJS-$(CONFIG_HDR_DECODER) += hdrdec.o
OBJS-$(CONFIG_HDR_ENCODER) += hdrenc.o
-OBJS-$(CONFIG_HEVC_DECODER) += aom_film_grain.o h274.o
+OBJS-$(CONFIG_HEVC_DECODER) += aom_film_grain.o h274.o container_fifo.o
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER) += d3d12va_encode_hevc.o h265_profile_level.o \
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index fc87169a1a..5e28bfe54e 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -3006,6 +3006,10 @@ static int hevc_frame_start(HEVCContext *s)
s->cur_frame->frame_grain->height = s->cur_frame->f->height;
if ((ret = ff_thread_get_buffer(s->avctx, s->cur_frame->frame_grain, 0)) < 0)
goto fail;
+
+ ret = av_frame_copy_props(s->cur_frame->frame_grain, s->cur_frame->f);
+ if (ret < 0)
+ goto fail;
}
s->cur_frame->f->pict_type = 3 - s->sh.slice_type;
@@ -3013,8 +3017,7 @@ static int hevc_frame_start(HEVCContext *s)
if (!IS_IRAP(s))
ff_hevc_bump_frame(s);
- av_frame_unref(s->output_frame);
- ret = ff_hevc_output_frame(s, s->output_frame, 0);
+ ret = ff_hevc_output_frame(s, 0);
if (ret < 0)
goto fail;
@@ -3411,13 +3414,16 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
uint8_t *sd;
size_t sd_size;
+ if (ff_container_fifo_can_read(s->output_fifo))
+ goto do_output;
+
av_packet_unref(avpkt);
ret = ff_decode_get_packet(avctx, avpkt);
if (ret == AVERROR_EOF) {
- ret = ff_hevc_output_frame(s, frame, 1);
+ ret = ff_hevc_output_frame(s, 1);
if (ret < 0)
return ret;
- return (ret > 0) ? 0 : AVERROR_EOF;
+ goto do_output;
} else if (ret < 0)
return ret;
@@ -3442,12 +3448,15 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
if (ret < 0)
return ret;
- if (s->output_frame->buf[0]) {
- av_frame_move_ref(frame, s->output_frame);
+do_output:
+ if (ff_container_fifo_read(s->output_fifo, frame) >= 0) {
+ if (!(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
+ av_frame_remove_side_data(frame, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
+
return 0;
}
- return AVERROR(EAGAIN);
+ return avci->draining ? AVERROR_EOF : AVERROR(EAGAIN);
}
static int hevc_ref_frame(HEVCFrame *dst, const HEVCFrame *src)
@@ -3499,7 +3508,8 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
av_freep(&s->sao_pixel_buffer_h[i]);
av_freep(&s->sao_pixel_buffer_v[i]);
}
- av_frame_free(&s->output_frame);
+
+ ff_container_fifo_free(&s->output_fifo);
for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
ff_hevc_unref_frame(&s->DPB[i], ~0);
@@ -3537,8 +3547,8 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
s->local_ctx[0].logctx = avctx;
s->local_ctx[0].common_cabac_state = &s->cabac;
- s->output_frame = av_frame_alloc();
- if (!s->output_frame)
+ s->output_fifo = ff_container_fifo_alloc_avframe(0);
+ if (!s->output_fifo)
return AVERROR(ENOMEM);
for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index da4d83e661..f2705b8de2 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -31,6 +31,7 @@
#include "libavcodec/avcodec.h"
#include "libavcodec/bswapdsp.h"
#include "libavcodec/cabac.h"
+#include "libavcodec/container_fifo.h"
#include "libavcodec/dovi_rpu.h"
#include "libavcodec/get_bits.h"
#include "libavcodec/h2645_parse.h"
@@ -457,7 +458,7 @@ typedef struct HEVCContext {
/** 1 if the independent slice segment header was successfully parsed */
uint8_t slice_initialized;
- AVFrame *output_frame;
+ ContainerFifo *output_fifo;
uint8_t *sao_pixel_buffer_h[3];
uint8_t *sao_pixel_buffer_v[3];
@@ -636,7 +637,7 @@ static av_always_inline int ff_hevc_nal_is_nonref(enum HEVCNALUnitType type)
* Find next frame in output order and put a reference to it in frame.
* @return 1 if a frame was output, 0 otherwise
*/
-int ff_hevc_output_frame(HEVCContext *s, AVFrame *frame, int flush);
+int ff_hevc_output_frame(HEVCContext *s, int flush);
void ff_hevc_bump_frame(HEVCContext *s);
diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index 48fc4d27da..44ee7c837a 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -171,7 +171,7 @@ static void unref_missing_refs(HEVCContext *s)
}
}
-int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush)
+int ff_hevc_output_frame(HEVCContext *s, int flush)
{
if (IS_IRAP(s) && s->no_rasl_output_flag == 1) {
const static int mask = HEVC_FRAME_FLAG_BUMPING | HEVC_FRAME_FLAG_OUTPUT;
@@ -211,7 +211,8 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush)
if (nb_output) {
HEVCFrame *frame = &s->DPB[min_idx];
- ret = av_frame_ref(out, frame->needs_fg ? frame->frame_grain : frame->f);
+ ret = ff_container_fifo_write(s->output_fifo,
+ frame->needs_fg ? frame->frame_grain : frame->f);
if (frame->flags & HEVC_FRAME_FLAG_BUMPING)
ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_BUMPING);
else
@@ -219,12 +220,6 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush)
if (ret < 0)
return ret;
- if (frame->needs_fg && (ret = av_frame_copy_props(out, frame->f)) < 0)
- return ret;
-
- if (!(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
- av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
-
av_log(s->avctx, AV_LOG_DEBUG,
"Output frame with POC %d.\n", frame->poc);
return 1;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 38/39] lavc/hevcdec: simplify output logic
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (35 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 37/39] lavc/hevcdec: use a ContainerFifo to hold frames scheduled for output Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 39/39] lavc/hevcdec: call ff_thread_finish_setup() even if hwaccel is in use Anton Khirnov
2024-07-24 18:20 ` [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Michael Niedermayer
38 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Current code is written around the "simple" decode API's limitation that
a single input packet (AU/coded frame) triggers the output of at most
one output frame. However the spec contains two cases where a coded
frame may cause multiple frames to be output (cf. C.5.2.2.2):
* start of a new sequence
* overflowing sps_max_dec_pic_buffering
The decoder currently contains rather convoluted logic to handle these
cases:
* decode/output/per-frame sequence counters,
* HEVC_FRAME_FLAG_BUMPING
* ff_hevc_bump_frame()
* special clauses in ff_hevc_output_frame()
However, with the receive_frame() API none of that is necessary, as we
can just output multiple frames at once. Previously added ContainerFifo
allows that to be done in a straightforward and efficient manner.
---
libavcodec/hevc/hevcdec.c | 33 +++++-------
libavcodec/hevc/hevcdec.h | 32 ++++--------
libavcodec/hevc/refs.c | 104 +++++++-------------------------------
3 files changed, 42 insertions(+), 127 deletions(-)
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 5e28bfe54e..28835f48d6 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -2906,6 +2906,7 @@ static int hevc_frame_start(HEVCContext *s)
const HEVCSPS *const sps = pps->sps;
int pic_size_in_ctb = ((sps->width >> sps->log2_min_cb_size) + 1) *
((sps->height >> sps->log2_min_cb_size) + 1);
+ int new_sequence = IS_IDR(s) || IS_BLA(s) || s->last_eos;
int ret;
ff_refstruct_replace(&s->pps, pps);
@@ -2925,7 +2926,7 @@ static int hevc_frame_start(HEVCContext *s)
return pix_fmt;
s->avctx->pix_fmt = pix_fmt;
- s->seq_decode = (s->seq_decode + 1) & HEVC_SEQUENCE_COUNTER_MASK;
+ new_sequence = 1;
}
memset(s->horizontal_bs, 0, s->bs_width * s->bs_height);
@@ -2934,11 +2935,8 @@ static int hevc_frame_start(HEVCContext *s)
memset(s->is_pcm, 0, (sps->min_pu_width + 1) * (sps->min_pu_height + 1));
memset(s->tab_slice_address, -1, pic_size_in_ctb * sizeof(*s->tab_slice_address));
- if ((IS_IDR(s) || IS_BLA(s))) {
- s->seq_decode = (s->seq_decode + 1) & HEVC_SEQUENCE_COUNTER_MASK;
- if (IS_IDR(s))
- ff_hevc_clear_refs(s);
- }
+ if (IS_IDR(s))
+ ff_hevc_clear_refs(s);
s->slice_idx = 0;
s->first_nal_type = s->nal_unit_type;
@@ -2962,6 +2960,12 @@ static int hevc_frame_start(HEVCContext *s)
if (pps->tiles_enabled_flag)
s->local_ctx[0].end_of_tiles_x = pps->column_width[0] << sps->log2_ctb_size;
+ if (new_sequence) {
+ ret = ff_hevc_output_frames(s, 0, 0, s->sh.no_output_of_prior_pics_flag);
+ if (ret < 0)
+ return ret;
+ }
+
ret = export_stream_params_from_sei(s);
if (ret < 0)
return ret;
@@ -3014,10 +3018,8 @@ static int hevc_frame_start(HEVCContext *s)
s->cur_frame->f->pict_type = 3 - s->sh.slice_type;
- if (!IS_IRAP(s))
- ff_hevc_bump_frame(s);
-
- ret = ff_hevc_output_frame(s, 0);
+ ret = ff_hevc_output_frames(s, sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics,
+ sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering, 0);
if (ret < 0)
goto fail;
@@ -3262,8 +3264,6 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal)
break;
case HEVC_NAL_EOS_NUT:
case HEVC_NAL_EOB_NUT:
- s->seq_decode = (s->seq_decode + 1) & HEVC_SEQUENCE_COUNTER_MASK;
- break;
case HEVC_NAL_AUD:
case HEVC_NAL_FD_NUT:
case HEVC_NAL_UNSPEC62:
@@ -3420,7 +3420,7 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
av_packet_unref(avpkt);
ret = ff_decode_get_packet(avctx, avpkt);
if (ret == AVERROR_EOF) {
- ret = ff_hevc_output_frame(s, 1);
+ ret = ff_hevc_output_frames(s, 0, 0, 0);
if (ret < 0)
return ret;
goto do_output;
@@ -3482,7 +3482,6 @@ static int hevc_ref_frame(HEVCFrame *dst, const HEVCFrame *src)
dst->poc = src->poc;
dst->ctb_count = src->ctb_count;
dst->flags = src->flags;
- dst->sequence = src->sequence;
ff_refstruct_replace(&dst->hwaccel_picture_private,
src->hwaccel_picture_private);
@@ -3606,8 +3605,6 @@ static int hevc_update_thread_context(AVCodecContext *dst,
if ((ret = set_sps(s, s0->ps.sps)) < 0)
return ret;
- s->seq_decode = s0->seq_decode;
- s->seq_output = s0->seq_output;
s->poc_tid0 = s0->poc_tid0;
s->eos = s0->eos;
s->no_rasl_output_flag = s0->no_rasl_output_flag;
@@ -3617,10 +3614,6 @@ static int hevc_update_thread_context(AVCodecContext *dst,
s->film_grain_warning_shown = s0->film_grain_warning_shown;
- if (s0->eos) {
- s->seq_decode = (s->seq_decode + 1) & HEVC_SEQUENCE_COUNTER_MASK;
- }
-
ret = ff_h2645_sei_ctx_replace(&s->sei.common, &s0->sei.common);
if (ret < 0)
return ret;
diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
index f2705b8de2..4293f1bd66 100644
--- a/libavcodec/hevc/hevcdec.h
+++ b/libavcodec/hevc/hevcdec.h
@@ -350,10 +350,7 @@ typedef struct DBParams {
#define HEVC_FRAME_FLAG_OUTPUT (1 << 0)
#define HEVC_FRAME_FLAG_SHORT_REF (1 << 1)
#define HEVC_FRAME_FLAG_LONG_REF (1 << 2)
-#define HEVC_FRAME_FLAG_BUMPING (1 << 3)
-
-#define HEVC_SEQUENCE_COUNTER_MASK 0xff
-#define HEVC_SEQUENCE_COUNTER_INVALID (HEVC_SEQUENCE_COUNTER_MASK + 1)
+#define HEVC_FRAME_FLAG_UNAVAILABLE (1 << 3)
typedef struct HEVCFrame {
union {
@@ -375,12 +372,6 @@ typedef struct HEVCFrame {
void *hwaccel_picture_private; ///< RefStruct reference
- /**
- * A sequence counter, so that old frames are output first
- * after a POC reset
- */
- uint16_t sequence;
-
/**
* A combination of HEVC_FRAME_FLAG_*
*/
@@ -519,13 +510,6 @@ typedef struct HEVCContext {
uint8_t *checksum_buf;
int checksum_buf_size;
- /**
- * Sequence counters for decoded and output frames, so that old
- * frames are output first after a POC reset
- */
- uint16_t seq_decode;
- uint16_t seq_output;
-
/** The target for the common_cabac_state of the local contexts. */
HEVCCABACState cabac;
@@ -634,12 +618,16 @@ static av_always_inline int ff_hevc_nal_is_nonref(enum HEVCNALUnitType type)
}
/**
- * Find next frame in output order and put a reference to it in frame.
- * @return 1 if a frame was output, 0 otherwise
+ * Find frames in the DPB that are ready for output and either write them to the
+ * output FIFO or drop their output flag, depending on the value of discard.
+ *
+ * @param max_output maximum number of output-pending frames that can be
+ * present in the DPB before output is triggered
+ * @param max_dpb maximum number of any frames that can be present in the DPB
+ * before output is triggered
*/
-int ff_hevc_output_frame(HEVCContext *s, int flush);
-
-void ff_hevc_bump_frame(HEVCContext *s);
+int ff_hevc_output_frames(HEVCContext *s, unsigned max_output,
+ unsigned max_dpb, int discard);
void ff_hevc_unref_frame(HEVCFrame *frame, int flags);
diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
index 44ee7c837a..50aa06b926 100644
--- a/libavcodec/hevc/refs.c
+++ b/libavcodec/hevc/refs.c
@@ -131,8 +131,7 @@ int ff_hevc_set_new_ref(HEVCContext *s, int poc)
for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
HEVCFrame *frame = &s->DPB[i];
- if (frame->f && frame->sequence == s->seq_decode &&
- frame->poc == poc) {
+ if (frame->f && frame->poc == poc) {
av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence: %d.\n",
poc);
return AVERROR_INVALIDDATA;
@@ -152,7 +151,6 @@ int ff_hevc_set_new_ref(HEVCContext *s, int poc)
ref->flags = HEVC_FRAME_FLAG_SHORT_REF;
ref->poc = poc;
- ref->sequence = s->seq_decode;
ref->f->crop_left = s->ps.sps->output_window.left_offset;
ref->f->crop_right = s->ps.sps->output_window.right_offset;
ref->f->crop_top = s->ps.sps->output_window.top_offset;
@@ -165,112 +163,49 @@ static void unref_missing_refs(HEVCContext *s)
{
for (int i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
HEVCFrame *frame = &s->DPB[i];
- if (frame->sequence == HEVC_SEQUENCE_COUNTER_INVALID) {
+ if (frame->flags & HEVC_FRAME_FLAG_UNAVAILABLE) {
ff_hevc_unref_frame(frame, ~0);
}
}
}
-int ff_hevc_output_frame(HEVCContext *s, int flush)
+int ff_hevc_output_frames(HEVCContext *s, unsigned max_output,
+ unsigned max_dpb, int discard)
{
- if (IS_IRAP(s) && s->no_rasl_output_flag == 1) {
- const static int mask = HEVC_FRAME_FLAG_BUMPING | HEVC_FRAME_FLAG_OUTPUT;
- for (int i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
- HEVCFrame *frame = &s->DPB[i];
- if ((frame->flags & mask) == HEVC_FRAME_FLAG_OUTPUT &&
- frame->sequence != s->seq_decode) {
- if (s->sh.no_output_of_prior_pics_flag == 1)
- ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
- else
- frame->flags |= HEVC_FRAME_FLAG_BUMPING;
- }
- }
- }
- do {
+ while (1) {
+ int nb_dpb = 0;
int nb_output = 0;
int min_poc = INT_MAX;
int i, min_idx, ret;
for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
HEVCFrame *frame = &s->DPB[i];
- if ((frame->flags & HEVC_FRAME_FLAG_OUTPUT) &&
- frame->sequence == s->seq_output) {
+ if (frame->flags & HEVC_FRAME_FLAG_OUTPUT) {
nb_output++;
if (frame->poc < min_poc || nb_output == 1) {
min_poc = frame->poc;
min_idx = i;
}
}
+ nb_dpb += !!frame->flags;
}
- /* wait for more frames before output */
- if (!flush && s->seq_output == s->seq_decode && s->ps.sps &&
- nb_output <= s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].num_reorder_pics)
- return 0;
-
- if (nb_output) {
+ if (nb_output > max_output ||
+ (nb_output && nb_dpb > max_dpb)) {
HEVCFrame *frame = &s->DPB[min_idx];
- ret = ff_container_fifo_write(s->output_fifo,
+ ret = discard ? 0 :
+ ff_container_fifo_write(s->output_fifo,
frame->needs_fg ? frame->frame_grain : frame->f);
- if (frame->flags & HEVC_FRAME_FLAG_BUMPING)
- ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_BUMPING);
- else
- ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
+ ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT);
if (ret < 0)
return ret;
- av_log(s->avctx, AV_LOG_DEBUG,
- "Output frame with POC %d.\n", frame->poc);
- return 1;
+ av_log(s->avctx, AV_LOG_DEBUG, "%s frame with POC %d.\n",
+ discard ? "Discarded" : "Output", frame->poc);
+ continue;
}
-
- if (s->seq_output != s->seq_decode)
- s->seq_output = (s->seq_output + 1) & HEVC_SEQUENCE_COUNTER_MASK;
- else
- break;
- } while (1);
-
- return 0;
-}
-
-void ff_hevc_bump_frame(HEVCContext *s)
-{
- int dpb = 0;
- int min_poc = INT_MAX;
- int i;
-
- for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
- HEVCFrame *frame = &s->DPB[i];
- if ((frame->flags) &&
- frame->sequence == s->seq_output &&
- frame->poc != s->poc) {
- dpb++;
- }
- }
-
- if (s->ps.sps && dpb >= s->ps.sps->temporal_layer[s->ps.sps->max_sub_layers - 1].max_dec_pic_buffering) {
- for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
- HEVCFrame *frame = &s->DPB[i];
- if ((frame->flags) &&
- frame->sequence == s->seq_output &&
- frame->poc != s->poc) {
- if (frame->flags == HEVC_FRAME_FLAG_OUTPUT && frame->poc < min_poc) {
- min_poc = frame->poc;
- }
- }
- }
-
- for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
- HEVCFrame *frame = &s->DPB[i];
- if (frame->flags & HEVC_FRAME_FLAG_OUTPUT &&
- frame->sequence == s->seq_output &&
- frame->poc <= min_poc) {
- frame->flags |= HEVC_FRAME_FLAG_BUMPING;
- }
- }
-
- dpb--;
+ return 0;
}
}
@@ -384,7 +319,7 @@ static HEVCFrame *find_ref_idx(HEVCContext *s, int poc, uint8_t use_msb)
for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
HEVCFrame *ref = &s->DPB[i];
- if (ref->f && ref->sequence == s->seq_decode) {
+ if (ref->f) {
if ((ref->poc & mask) == poc && (use_msb || ref->poc != s->poc))
return ref;
}
@@ -427,8 +362,7 @@ static HEVCFrame *generate_missing_ref(HEVCContext *s, int poc)
}
frame->poc = poc;
- frame->sequence = HEVC_SEQUENCE_COUNTER_INVALID;
- frame->flags = 0;
+ frame->flags = HEVC_FRAME_FLAG_UNAVAILABLE;
if (s->avctx->active_thread_type == FF_THREAD_FRAME)
ff_progress_frame_report(&frame->tf, INT_MAX);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 39/39] lavc/hevcdec: call ff_thread_finish_setup() even if hwaccel is in use
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (36 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 38/39] lavc/hevcdec: simplify output logic Anton Khirnov
@ 2024-07-16 17:11 ` Anton Khirnov
2024-07-24 18:20 ` [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Michael Niedermayer
38 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-16 17:11 UTC (permalink / raw)
To: ffmpeg-devel
Serializing frame threading for non-threadsafe hwaccels is handled at the
generic level, the decoder does not need to care about it.
---
libavcodec/hevc/hevcdec.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
index 28835f48d6..622d9eeb84 100644
--- a/libavcodec/hevc/hevcdec.c
+++ b/libavcodec/hevc/hevcdec.c
@@ -3027,8 +3027,9 @@ static int hevc_frame_start(HEVCContext *s)
ret = FF_HW_CALL(s->avctx, start_frame, NULL, 0);
if (ret < 0)
goto fail;
- } else
- ff_thread_finish_setup(s->avctx);
+ }
+
+ ff_thread_finish_setup(s->avctx);
return 0;
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 28/39] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 28/39] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
@ 2024-07-17 20:51 ` Michael Niedermayer
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 1/3] lavc/ffv1dec: drop code handling AV_PIX_FMT_FLAG_PAL Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-17 20:51 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1082 bytes --]
On Tue, Jul 16, 2024 at 07:11:43PM +0200, Anton Khirnov wrote:
> That variable is shared between frame threads in the same defective way
> described in the previous commit. Fix it by adding a RefStruct-managed
> arrays of flags that is propagated across frame threads in the standard
> manner.
>
> Remove now-unused FFV1Context.fsrc
> ---
> libavcodec/ffv1.c | 2 ++
> libavcodec/ffv1.h | 3 ++-
> libavcodec/ffv1dec.c | 24 ++++++++++--------------
> 3 files changed, 14 insertions(+), 15 deletions(-)
breaks error handling
and introduces a race
try any of the files from:
https://samples.ffmpeg.org/avi/ffv1/
./ffmpeg -i ffv1.3-01ec.avi -f crc -
the results are vissually worse, and differ from run to run
also
./ffmpeg -thread_type slice -i ffv1.3-01ec.avi -f crc -
has issues, its not just the default
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Those who would give up essential Liberty, to purchase a little
temporary Safety, deserve neither Liberty nor Safety -- Benjamin Franklin
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 31/39] lavc/decode: wrap AV_FRAME_FLAG_DISCARD handling in a loop
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 31/39] lavc/decode: wrap AV_FRAME_FLAG_DISCARD handling in a loop Anton Khirnov
@ 2024-07-17 21:20 ` Michael Niedermayer
2024-07-18 8:14 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-17 21:20 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 631 bytes --]
On Tue, Jul 16, 2024 at 07:11:46PM +0200, Anton Khirnov wrote:
> Makes sure discarded frames do not cause EAGAIN to be returned during
> flushing, which is forbidden.
> ---
> libavcodec/decode.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
giving execution back to the user at finer granularity would be better
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
The real ebay dictionary, page 2
"100% positive feedback" - "All either got their money back or didnt complain"
"Best seller ever, very honest" - "Seller refunded buyer after failed scam"
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table Anton Khirnov
@ 2024-07-17 22:32 ` Michael Niedermayer
2024-07-18 8:20 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-17 22:32 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 3640 bytes --]
On Tue, Jul 16, 2024 at 07:11:28PM +0200, Anton Khirnov wrote:
> It is a copy of FFV1Context.quant_tables[quant_table_index].
> ---
> libavcodec/ffv1.h | 1 -
> libavcodec/ffv1_template.c | 22 +++++++++++-----------
> libavcodec/ffv1dec.c | 28 ++++++++++++----------------
> libavcodec/ffv1dec_template.c | 14 +++++++++-----
> libavcodec/ffv1enc.c | 24 ++++++++++++------------
> libavcodec/ffv1enc_template.c | 13 ++++++++-----
> 6 files changed, 52 insertions(+), 50 deletions(-)
>
> diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
> index 4d57172d5b..a87c2d2a36 100644
> --- a/libavcodec/ffv1.h
> +++ b/libavcodec/ffv1.h
> @@ -59,7 +59,6 @@ typedef struct VlcState {
> } VlcState;
>
> typedef struct PlaneContext {
> - int16_t quant_table[MAX_CONTEXT_INPUTS][256];
> int quant_table_index;
> int context_count;
> uint8_t (*state)[CONTEXT_SIZE];
> diff --git a/libavcodec/ffv1_template.c b/libavcodec/ffv1_template.c
> index c5f61b0182..d15ad11021 100644
> --- a/libavcodec/ffv1_template.c
> +++ b/libavcodec/ffv1_template.c
> @@ -29,25 +29,25 @@ static inline int RENAME(predict)(TYPE *src, TYPE *last)
> return mid_pred(L, L + T - LT, T);
> }
>
> -static inline int RENAME(get_context)(PlaneContext *p, TYPE *src,
> - TYPE *last, TYPE *last2)
> +static inline int RENAME(get_context)(const int16_t quant_table[MAX_CONTEXT_INPUTS][256],
> + TYPE *src, TYPE *last, TYPE *last2)
> {
> const int LT = last[-1];
> const int T = last[0];
> const int RT = last[1];
> const int L = src[-1];
>
> - if (p->quant_table[3][127] || p->quant_table[4][127]) {
> + if (quant_table[3][127] || quant_table[4][127]) {
the data for each decoder task should be together and not scattered around
more than needed, reducing cache efficiency
[...]
> diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
> index 66d9f63c1a..618020d10f 100644
> --- a/libavcodec/ffv1dec.c
> +++ b/libavcodec/ffv1dec.c
> @@ -117,7 +117,8 @@ static int is_input_end(FFV1Context *s, GetBitContext *gb)
> #define RENAME(name) name ## 32
> #include "ffv1dec_template.c"
>
> -static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
> +static int decode_plane(FFV1Context *f,
> + FFV1Context *s, FFV1SliceContext *sc,
[...]
> static av_always_inline int
> -RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, GetBitContext *gb,
> +RENAME(decode_line)(FFV1Context *f,
> + FFV1Context *s, FFV1SliceContext *sc,
> + GetBitContext *gb,
> int w, TYPE *sample[2], int plane_index, int bits)
> {
> PlaneContext *const p = &s->plane[plane_index];
> @@ -57,7 +59,8 @@ RENAME(decode_line)(FFV1Context *s, FFV1SliceContext *sc, GetBitContext *gb,
> return AVERROR_INVALIDDATA;
> }
>
> - context = RENAME(get_context)(p, sample[1] + x, sample[0] + x, sample[1] + x);
> + context = RENAME(get_context)(f->quant_tables[p->quant_table_index],
> + sample[1] + x, sample[0] + x, sample[1] + x);
putting all this extra code in the inner per pixel loop is not ok
especially not for the sake of avoiding a memcpy of a few hundread bytes multiple levels of loops outside
[...]
thx
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
In a rich man's house there is no place to spit but his face.
-- Diogenes of Sinope
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 12/39] lavc/ffv1: drop redundant FFV1Context.quant_table
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 12/39] lavc/ffv1: drop redundant FFV1Context.quant_table Anton Khirnov
@ 2024-07-17 22:37 ` Michael Niedermayer
2024-07-17 23:24 ` James Almer
2024-07-18 8:22 ` Anton Khirnov
0 siblings, 2 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-17 22:37 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 765 bytes --]
On Tue, Jul 16, 2024 at 07:11:27PM +0200, Anton Khirnov wrote:
> In all cases except decoding version 1 it's either not used, or contains
> a copy of a table from quant_tables, which we can just as well use
> directly.
>
> When decoding version 1, we can just as well decode into
> quant_tables[0], which would otherwise be unused.
> ---
> libavcodec/ffv1.h | 1 -
> libavcodec/ffv1dec.c | 10 +++++++---
> libavcodec/ffv1enc.c | 6 ++----
> 3 files changed, 9 insertions(+), 8 deletions(-)
the code is 1 line longer and using the first entry as a special
case doesnt seem simpler
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Avoid a single point of failure, be that a person or equipment.
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack Anton Khirnov
@ 2024-07-17 22:42 ` Michael Niedermayer
2024-07-18 9:08 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-17 22:42 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 656 bytes --]
On Tue, Jul 16, 2024 at 07:11:25PM +0200, Anton Khirnov wrote:
> There is no reason to place it in persistent state.
> ---
> libavcodec/ffv1.h | 1 -
> libavcodec/ffv1dec.c | 28 +++++++++++++++-------------
> libavcodec/ffv1dec_template.c | 23 ++++++++++++-----------
> 3 files changed, 27 insertions(+), 25 deletions(-)
more complex code, an additional pointer to pass around
all the stuff should be put together close so its efficiently
using CPU caches
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
What does censorship reveal? It reveals fear. -- Julian Assange
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 09/39] lavc/ffv1: move run_index to the per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 09/39] lavc/ffv1: move run_index " Anton Khirnov
@ 2024-07-17 22:49 ` Michael Niedermayer
2024-07-18 15:36 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-17 22:49 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1644 bytes --]
On Tue, Jul 16, 2024 at 07:11:24PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.h | 3 ++-
> libavcodec/ffv1dec.c | 6 +++---
> libavcodec/ffv1dec_template.c | 16 ++++++++--------
> libavcodec/ffv1enc.c | 6 +++---
> libavcodec/ffv1enc_template.c | 16 ++++++++--------
> 5 files changed, 24 insertions(+), 23 deletions(-)
more complex code
> @@ -140,13 +140,13 @@ static int decode_plane(FFV1Context *s, FFV1SliceContext *sc,
> sample[0][w] = sample[0][w - 1];
>
> if (s->avctx->bits_per_raw_sample <= 8) {
> - int ret = decode_line(s, w, sample, plane_index, 8);
> + int ret = decode_line(s, sc, w, sample, plane_index, 8);
> if (ret < 0)
> return ret;
> for (x = 0; x < w; x++)
> src[x*pixel_stride + stride * y] = sample[1][x];
> } else {
> - int ret = decode_line(s, w, sample, plane_index, s->avctx->bits_per_raw_sample);
> + int ret = decode_line(s, sc, w, sample, plane_index, s->avctx->bits_per_raw_sample);
> if (ret < 0)
> return ret;
> if (s->packed_at_lsb) {
The need for passing an additional pointer around
seems to me a net negative
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
"You are 36 times more likely to die in a bathtub than at the hands of a
terrorist. Also, you are 2.5 times more likely to become a president and
2 times more likely to become an astronaut, than to die in a terrorist
attack." -- Thoughty2
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 12/39] lavc/ffv1: drop redundant FFV1Context.quant_table
2024-07-17 22:37 ` Michael Niedermayer
@ 2024-07-17 23:24 ` James Almer
2024-07-18 8:22 ` Anton Khirnov
1 sibling, 0 replies; 110+ messages in thread
From: James Almer @ 2024-07-17 23:24 UTC (permalink / raw)
To: ffmpeg-devel
On 7/17/2024 7:37 PM, Michael Niedermayer wrote:
> On Tue, Jul 16, 2024 at 07:11:27PM +0200, Anton Khirnov wrote:
>> In all cases except decoding version 1 it's either not used, or contains
>> a copy of a table from quant_tables, which we can just as well use
>> directly.
>>
>> When decoding version 1, we can just as well decode into
>> quant_tables[0], which would otherwise be unused.
>> ---
>> libavcodec/ffv1.h | 1 -
>> libavcodec/ffv1dec.c | 10 +++++++---
>> libavcodec/ffv1enc.c | 6 ++----
>> 3 files changed, 9 insertions(+), 8 deletions(-)
>
> the code is 1 line longer and using the first entry as a special
Two lines are comments...
> case doesnt seem simpler
>
> thx
>
> [...]
>
>
> _______________________________________________
> 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".
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 31/39] lavc/decode: wrap AV_FRAME_FLAG_DISCARD handling in a loop
2024-07-17 21:20 ` Michael Niedermayer
@ 2024-07-18 8:14 ` Anton Khirnov
0 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-18 8:14 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-17 23:20:19)
> On Tue, Jul 16, 2024 at 07:11:46PM +0200, Anton Khirnov wrote:
> > Makes sure discarded frames do not cause EAGAIN to be returned during
> > flushing, which is forbidden.
> > ---
> > libavcodec/decode.c | 11 ++++++++---
> > 1 file changed, 8 insertions(+), 3 deletions(-)
>
> giving execution back to the user at finer granularity would be better
That's not how our API works, unless I misunderstand what you're
suggesting.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-17 22:32 ` Michael Niedermayer
@ 2024-07-18 8:20 ` Anton Khirnov
2024-07-18 14:31 ` Michael Niedermayer
` (2 more replies)
0 siblings, 3 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-18 8:20 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-18 00:32:38)
> the data for each decoder task should be together and not scattered around
> more than needed, reducing cache efficiency
>
> putting all this extra code in the inner per pixel loop is not ok
> especially not for the sake of avoiding a memcpy of a few hundread bytes multiple levels of loops outside
A nice theory, but in practice this patchset makes single-threaded
decoding about 4% faster overall, on a 1920x1080 10bit sample. That's
just the ffv1 parts (up to patch 28), full set also improves frame
threading performance as follows:
threads improvement
---------------------------
2 52% (yes really)
4 16%
8 12%
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 12/39] lavc/ffv1: drop redundant FFV1Context.quant_table
2024-07-17 22:37 ` Michael Niedermayer
2024-07-17 23:24 ` James Almer
@ 2024-07-18 8:22 ` Anton Khirnov
1 sibling, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-18 8:22 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-18 00:37:25)
> On Tue, Jul 16, 2024 at 07:11:27PM +0200, Anton Khirnov wrote:
> > In all cases except decoding version 1 it's either not used, or contains
> > a copy of a table from quant_tables, which we can just as well use
> > directly.
> >
> > When decoding version 1, we can just as well decode into
> > quant_tables[0], which would otherwise be unused.
> > ---
> > libavcodec/ffv1.h | 1 -
> > libavcodec/ffv1dec.c | 10 +++++++---
> > libavcodec/ffv1enc.c | 6 ++----
> > 3 files changed, 9 insertions(+), 8 deletions(-)
>
> the code is 1 line longer and using the first entry as a special
> case doesnt seem simpler
The simplicity is in the fact it's actually not special at all.
quant_tables[quant_table_idx] is always the location of the quant table
for any bitstream version, so the rest of the code does not need to
care.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack
2024-07-17 22:42 ` Michael Niedermayer
@ 2024-07-18 9:08 ` Anton Khirnov
2024-07-18 14:48 ` Michael Niedermayer
0 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-18 9:08 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-18 00:42:05)
> all the stuff should be put together close so its efficiently
> using CPU caches
Which is why it shares its cacheline with PutBitContext, because the
code benefits from having the both in the cache, right? And the 4-byte
hole in PutBitContext is there presumably to aerate the cache for
smoother data streaming.
More seriously, this is not how caches work. Being close together
matters mainly so long as your data fits in a cacheline, beyond that
physical proximity matters little. On stack, the bitreader is likely to
share the cacheline with other data that is currently needed, thus
improving cache utilization.
Another factor that matters in efficient cache use is e.g. not having
multiple copies of the same constant data scattered around, which you're
objecting to in my other patches.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-18 8:20 ` Anton Khirnov
@ 2024-07-18 14:31 ` Michael Niedermayer
2024-07-18 15:14 ` Anton Khirnov
2024-07-18 15:31 ` Paul B Mahol
2024-07-18 17:40 ` Michael Niedermayer
2 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-18 14:31 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 943 bytes --]
On Thu, Jul 18, 2024 at 10:20:09AM +0200, Anton Khirnov wrote:
> Quoting Michael Niedermayer (2024-07-18 00:32:38)
> > the data for each decoder task should be together and not scattered around
> > more than needed, reducing cache efficiency
> >
> > putting all this extra code in the inner per pixel loop is not ok
> > especially not for the sake of avoiding a memcpy of a few hundread bytes multiple levels of loops outside
>
> A nice theory,
that doesnt sound like a friendly description
> but in practice
> this patchset
"this patchset" isnt "this patch", nor does any improvment from "this patchset"
depend on the change of "this patch"
In fact it would probably benefit from droping this patch
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
While the State exists there can be no freedom; when there is freedom there
will be no State. -- Vladimir Lenin
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack
2024-07-18 9:08 ` Anton Khirnov
@ 2024-07-18 14:48 ` Michael Niedermayer
2024-07-18 15:31 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-18 14:48 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2135 bytes --]
On Thu, Jul 18, 2024 at 11:08:59AM +0200, Anton Khirnov wrote:
> Quoting Michael Niedermayer (2024-07-18 00:42:05)
> > all the stuff should be put together close so its efficiently
> > using CPU caches
>
> Which is why it shares its cacheline with PutBitContext, because the
> code benefits from having the both in the cache, right? And the 4-byte
> hole in PutBitContext is there presumably to aerate the cache for
> smoother data streaming.
thanks for spoting these, can you fix these ?
>
> More seriously, this is not how caches work. Being close together
> matters mainly so long as your data fits in a cacheline, beyond that
> physical proximity matters little. On stack, the bitreader is likely to
> share the cacheline with other data that is currently needed, thus
> improving cache utilization.
caches are complex, and being close does matter.
having things in seperate allocations risks hitting aliassing cases
(that is things that cannot be in the cache at the same time)
so when you have the bitstream, the frame buffer, the context already
in 3 independant locations adding a few more increases the risk for hitting
these.
Also sequential memory access is faster than non sequential, it does
make sense to put things together in few places than to scatter them
Its years since ive done hardcore optimization stuff but i dont think
the principles have changed that much that random access is faster than
sequential and that caches work fundamentally differently
>
> Another factor that matters in efficient cache use is e.g. not having
> multiple copies of the same constant data scattered around, which you're
> objecting to in my other patches.
copying the actually used small data together per slice
where its accessed per pixel should improve teh speed per pixel while
making the per slice code a little slower. now we have 4 slices maybe
and millions of pixels. Thats why this can give an overall gain
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
No snowflake in an avalanche ever feels responsible. -- Voltaire
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-18 14:31 ` Michael Niedermayer
@ 2024-07-18 15:14 ` Anton Khirnov
2024-07-18 17:03 ` Michael Niedermayer
0 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-18 15:14 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-18 16:31:51)
> On Thu, Jul 18, 2024 at 10:20:09AM +0200, Anton Khirnov wrote:
> > Quoting Michael Niedermayer (2024-07-18 00:32:38)
> > > the data for each decoder task should be together and not scattered around
> > > more than needed, reducing cache efficiency
> > >
> > > putting all this extra code in the inner per pixel loop is not ok
> > > especially not for the sake of avoiding a memcpy of a few hundread bytes multiple levels of loops outside
> >
>
> > A nice theory,
>
> that doesnt sound like a friendly description
And this does not look like a friendly review. I am getting a very
strong impression that you're looking for reasons to object to the
patches, rather seriously review them.
> > but in practice
>
> > this patchset
>
> "this patchset" isnt "this patch", nor does any improvment from "this patchset"
> depend on the change of "this patch"
> In fact it would probably benefit from droping this patch
Just what would that benefit be?
Storing and copying around multiple copies of the same data is generally
bad for readability, as it requires more cognitive effort to understand
the code - which is why I wrote this patch in the first place. It is
also inefficient in terms of overall memory use and cache utilization,
but I expect the impact of that to be small.
If you're concerned about dereferencing a pointer in an inner loop, I
can add a temporary variable to decode_line() as below, but removing
duplicated data seems like an unambiguous improvement to me.
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index 97a28b085a..d68bbda5be 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -30,6 +30,7 @@ RENAME(decode_line)(FFV1Context *f,
{
PlaneContext *const p = &s->plane[plane_index];
RangeCoder *const c = &s->c;
+ const int16_t (*quant_table)[256] = f->quant_tables[p->quant_table_index];
int x;
int run_count = 0;
int run_mode = 0;
@@ -59,7 +60,7 @@ RENAME(decode_line)(FFV1Context *f,
return AVERROR_INVALIDDATA;
}
- context = RENAME(get_context)(f->quant_tables[p->quant_table_index],
+ context = RENAME(get_context)(quant_table,
sample[1] + x, sample[0] + x, sample[1] + x);
if (context < 0) {
context = -context;
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack
2024-07-18 14:48 ` Michael Niedermayer
@ 2024-07-18 15:31 ` Anton Khirnov
2024-07-18 15:35 ` Paul B Mahol
2024-07-18 18:18 ` Michael Niedermayer
0 siblings, 2 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-18 15:31 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-18 16:48:06)
> On Thu, Jul 18, 2024 at 11:08:59AM +0200, Anton Khirnov wrote:
> > Quoting Michael Niedermayer (2024-07-18 00:42:05)
> > > all the stuff should be put together close so its efficiently
> > > using CPU caches
> >
> > Which is why it shares its cacheline with PutBitContext, because the
> > code benefits from having the both in the cache, right? And the 4-byte
> > hole in PutBitContext is there presumably to aerate the cache for
> > smoother data streaming.
>
> thanks for spoting these, can you fix these ?
I have no interest in optimizing the performance of this code. My
primary goal here is to remove FFV1-specific hacks from the frame
threading code for patch 33/39, which is in turn needed for 38/39.
As a public service, I also spent some effort on making the ffv1 code
easier to understand, but if you insist on keeping the code as it is I
can also just drop its non-compliant frame threading implementation.
> >
> > More seriously, this is not how caches work. Being close together
> > matters mainly so long as your data fits in a cacheline, beyond that
> > physical proximity matters little. On stack, the bitreader is likely to
> > share the cacheline with other data that is currently needed, thus
> > improving cache utilization.
>
> caches are complex, and being close does matter.
> having things in seperate allocations risks hitting aliassing cases
> (that is things that cannot be in the cache at the same time)
> so when you have the bitstream, the frame buffer, the context already
> in 3 independant locations adding a few more increases the risk for hitting
> these.
> Also sequential memory access is faster than non sequential, it does
> make sense to put things together in few places than to scatter them
>
> Its years since ive done hardcore optimization stuff but i dont think
> the principles have changed that much that random access is faster than
> sequential and that caches work fundamentally differently
I don't see how any of these arguments are relevant - I am not moving
the bitreader to a new allocation, but to stack, which is already highly
likely to be in cache.
> >
> > Another factor that matters in efficient cache use is e.g. not having
> > multiple copies of the same constant data scattered around, which you're
> > objecting to in my other patches.
>
> copying the actually used small data together per slice
> where its accessed per pixel should improve teh speed per pixel while
> making the per slice code a little slower. now we have 4 slices maybe
> and millions of pixels. Thats why this can give an overall gain
This all sounds like premature optimization, AKA the root of all evil.
As I said above, I intended to make this code more readable, not faster.
Yet somehow it became faster anyway, which suggests this code is not
very optimized. So then arguing whether this or that specific change
adds or removes a few cycles per frame seems like a waste time to me.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-18 8:20 ` Anton Khirnov
2024-07-18 14:31 ` Michael Niedermayer
@ 2024-07-18 15:31 ` Paul B Mahol
2024-07-18 15:43 ` Anton Khirnov
2024-07-18 17:40 ` Michael Niedermayer
2 siblings, 1 reply; 110+ messages in thread
From: Paul B Mahol @ 2024-07-18 15:31 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Thu, Jul 18, 2024 at 10:20 AM Anton Khirnov <anton@khirnov.net> wrote:
> Quoting Michael Niedermayer (2024-07-18 00:32:38)
> > the data for each decoder task should be together and not scattered
> around
> > more than needed, reducing cache efficiency
> >
> > putting all this extra code in the inner per pixel loop is not ok
> > especially not for the sake of avoiding a memcpy of a few hundread bytes
> multiple levels of loops outside
>
> A nice theory, but in practice this patchset makes single-threaded
> decoding about 4% faster overall, on a 1920x1080 10bit sample. That's
> just the ffv1 parts (up to patch 28), full set also improves frame
> threading performance as follows:
> threads improvement
> ---------------------------
> 2 52% (yes really)
>
What?
Sloppy programming skills....
> 4 16%
> 8 12%
>
> --
> Anton Khirnov
> _______________________________________________
> 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".
>
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack
2024-07-18 15:31 ` Anton Khirnov
@ 2024-07-18 15:35 ` Paul B Mahol
2024-07-18 18:18 ` Michael Niedermayer
1 sibling, 0 replies; 110+ messages in thread
From: Paul B Mahol @ 2024-07-18 15:35 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Thu, Jul 18, 2024 at 5:31 PM Anton Khirnov <anton@khirnov.net> wrote:
> Quoting Michael Niedermayer (2024-07-18 16:48:06)
> > On Thu, Jul 18, 2024 at 11:08:59AM +0200, Anton Khirnov wrote:
> > > Quoting Michael Niedermayer (2024-07-18 00:42:05)
> > > > all the stuff should be put together close so its efficiently
> > > > using CPU caches
> > >
> > > Which is why it shares its cacheline with PutBitContext, because the
> > > code benefits from having the both in the cache, right? And the 4-byte
> > > hole in PutBitContext is there presumably to aerate the cache for
> > > smoother data streaming.
> >
> > thanks for spoting these, can you fix these ?
>
> I have no interest in optimizing the performance of this code. My
> primary goal here is to remove FFV1-specific hacks from the frame
> threading code for patch 33/39, which is in turn needed for 38/39.
>
> As a public service, I also spent some effort on making the ffv1 code
> easier to understand, but if you insist on keeping the code as it is I
> can also just drop its non-compliant frame threading implementation.
>
> > >
> > > More seriously, this is not how caches work. Being close together
> > > matters mainly so long as your data fits in a cacheline, beyond that
> > > physical proximity matters little. On stack, the bitreader is likely to
> > > share the cacheline with other data that is currently needed, thus
> > > improving cache utilization.
> >
> > caches are complex, and being close does matter.
> > having things in seperate allocations risks hitting aliassing cases
> > (that is things that cannot be in the cache at the same time)
> > so when you have the bitstream, the frame buffer, the context already
> > in 3 independant locations adding a few more increases the risk for
> hitting
> > these.
> > Also sequential memory access is faster than non sequential, it does
> > make sense to put things together in few places than to scatter them
> >
> > Its years since ive done hardcore optimization stuff but i dont think
> > the principles have changed that much that random access is faster than
> > sequential and that caches work fundamentally differently
>
> I don't see how any of these arguments are relevant - I am not moving
> the bitreader to a new allocation, but to stack, which is already highly
> likely to be in cache.
>
> > >
> > > Another factor that matters in efficient cache use is e.g. not having
> > > multiple copies of the same constant data scattered around, which
> you're
> > > objecting to in my other patches.
> >
> > copying the actually used small data together per slice
> > where its accessed per pixel should improve teh speed per pixel while
> > making the per slice code a little slower. now we have 4 slices maybe
> > and millions of pixels. Thats why this can give an overall gain
>
> This all sounds like premature optimization, AKA the root of all evil.
> As I said above, I intended to make this code more readable, not faster.
> Yet somehow it became faster anyway, which suggests this code is not
> very optimized. So then arguing whether this or that specific change
> adds or removes a few cycles per frame seems like a waste time to me.
>
Will merge this into Librempeg if it does not get into FFmpeg.
>
> --
> Anton Khirnov
> _______________________________________________
> 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".
>
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 09/39] lavc/ffv1: move run_index to the per-slice context
2024-07-17 22:49 ` Michael Niedermayer
@ 2024-07-18 15:36 ` Anton Khirnov
2024-07-18 17:41 ` Michael Niedermayer
0 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-18 15:36 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-18 00:49:41)
> The need for passing an additional pointer around
>
> seems to me a net negative
It makes it explicitly clear which data is per-slice, and which
per-frame/global, which is much harder to figure out with current code.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-18 15:31 ` Paul B Mahol
@ 2024-07-18 15:43 ` Anton Khirnov
2024-07-18 15:47 ` Paul B Mahol
0 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-18 15:43 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Paul B Mahol (2024-07-18 17:31:50)
> On Thu, Jul 18, 2024 at 10:20 AM Anton Khirnov <anton@khirnov.net> wrote:
>
> > Quoting Michael Niedermayer (2024-07-18 00:32:38)
> > > the data for each decoder task should be together and not scattered
> > around
> > > more than needed, reducing cache efficiency
> > >
> > > putting all this extra code in the inner per pixel loop is not ok
> > > especially not for the sake of avoiding a memcpy of a few hundread bytes
> > multiple levels of loops outside
> >
> > A nice theory, but in practice this patchset makes single-threaded
> > decoding about 4% faster overall, on a 1920x1080 10bit sample. That's
> > just the ffv1 parts (up to patch 28), full set also improves frame
> > threading performance as follows:
> > threads improvement
> > ---------------------------
> > 2 52% (yes really)
> >
>
> What?
Current code is effectively serial with 2 threads.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-18 15:43 ` Anton Khirnov
@ 2024-07-18 15:47 ` Paul B Mahol
0 siblings, 0 replies; 110+ messages in thread
From: Paul B Mahol @ 2024-07-18 15:47 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Thu, Jul 18, 2024 at 5:43 PM Anton Khirnov <anton@khirnov.net> wrote:
> Quoting Paul B Mahol (2024-07-18 17:31:50)
> > On Thu, Jul 18, 2024 at 10:20 AM Anton Khirnov <anton@khirnov.net>
> wrote:
> >
> > > Quoting Michael Niedermayer (2024-07-18 00:32:38)
> > > > the data for each decoder task should be together and not scattered
> > > around
> > > > more than needed, reducing cache efficiency
> > > >
> > > > putting all this extra code in the inner per pixel loop is not ok
> > > > especially not for the sake of avoiding a memcpy of a few hundread
> bytes
> > > multiple levels of loops outside
> > >
> > > A nice theory, but in practice this patchset makes single-threaded
> > > decoding about 4% faster overall, on a 1920x1080 10bit sample. That's
> > > just the ffv1 parts (up to patch 28), full set also improves frame
> > > threading performance as follows:
> > > threads improvement
> > > ---------------------------
> > > 2 52% (yes really)
> > >
> >
> > What?
>
> Current code is effectively serial with 2 threads.
>
Explains why FFv1 implementation is so slow.
>
> --
> Anton Khirnov
> _______________________________________________
> 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".
>
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-18 15:14 ` Anton Khirnov
@ 2024-07-18 17:03 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-18 17:03 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1303 bytes --]
On Thu, Jul 18, 2024 at 05:14:12PM +0200, Anton Khirnov wrote:
[...]
> diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
> index 97a28b085a..d68bbda5be 100644
> --- a/libavcodec/ffv1dec_template.c
> +++ b/libavcodec/ffv1dec_template.c
> @@ -30,6 +30,7 @@ RENAME(decode_line)(FFV1Context *f,
> {
> PlaneContext *const p = &s->plane[plane_index];
> RangeCoder *const c = &s->c;
> + const int16_t (*quant_table)[256] = f->quant_tables[p->quant_table_index];
> int x;
> int run_count = 0;
> int run_mode = 0;
> @@ -59,7 +60,7 @@ RENAME(decode_line)(FFV1Context *f,
> return AVERROR_INVALIDDATA;
> }
>
> - context = RENAME(get_context)(f->quant_tables[p->quant_table_index],
> + context = RENAME(get_context)(quant_table,
> sample[1] + x, sample[0] + x, sample[1] + x);
> if (context < 0) {
> context = -context;
that change is fine.
the removial of the quant_table copy should be benchmarked
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
I have never wished to cater to the crowd; for what I know they do not
approve, and what they approve I do not know. -- Epicurus
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-18 8:20 ` Anton Khirnov
2024-07-18 14:31 ` Michael Niedermayer
2024-07-18 15:31 ` Paul B Mahol
@ 2024-07-18 17:40 ` Michael Niedermayer
2024-07-20 9:22 ` Anton Khirnov
2 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-18 17:40 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2873 bytes --]
On Thu, Jul 18, 2024 at 10:20:09AM +0200, Anton Khirnov wrote:
> Quoting Michael Niedermayer (2024-07-18 00:32:38)
> > the data for each decoder task should be together and not scattered around
> > more than needed, reducing cache efficiency
> >
> > putting all this extra code in the inner per pixel loop is not ok
> > especially not for the sake of avoiding a memcpy of a few hundread bytes multiple levels of loops outside
>
> A nice theory, but in practice this patchset makes single-threaded
> decoding about 4% faster overall, on a 1920x1080 10bit sample. That's
> just the ffv1 parts (up to patch 28), full set also improves frame
> threading performance as follows:
> threads improvement
> ---------------------------
> 2 52% (yes really)
> 4 16%
> 8 12%
I do want the speed improvements, yes.
But
you compare frame threading when slice threading performed
much better than frame threading prior to the patch
also id like to see the individual changes which look like they should
make teh code slower, to be tested individually. If they make the code slower
they should be dropped
Also the code has a bug, benchmarks may theoretically changes once it is fixed
using matrixbench
-i matrixbench_mpeg2.mpg -an -vcodec ffv1 -slices 4 -t 100 -coder 1 -context 1 -bitexact /tCmp/ffv1.2-11.avi
prior patchset:
time ./ffmpeg -thread_type slice -threads 1 -i /tmp/ffv1.2-11.avi -f null -
real 0m31.976s
user 0m32.001s
sys 0m0.080s
time ./ffmpeg -thread_type slice -threads 2 -i /tmp/ffv1.2-11.avi -f null -
real 0m18.086s
user 0m34.199s
sys 0m0.089s
time ./ffmpeg -threads 2 -i /tmp/ffv1.2-11.avi -f null -
real 0m33.578s
user 0m33.611s
sys 0m0.052s
time ./ffmpeg -thread_type slice -threads 4 -i /tmp/ffv1.2-11.avi -f null -
real 0m9.189s
user 0m33.608s
sys 0m0.073s
time ./ffmpeg -threads 4 -i /tmp/ffv1.2-11.avi -f null -
real 0m11.159s
user 0m32.712s
sys 0m0.124s
post patchset:
time ./ffmpeg -thread_type slice -threads 1 -i /tmp/ffv1.2-11.avi -f null -
eal 0m31.755s
user 0m31.758s
sys 0m0.096s
time ./ffmpeg -thread_type slice -threads 2 -i /tmp/ffv1.2-11.avi -f null -
real 0m17.481s
user 0m33.385s
sys 0m0.076s
time ./ffmpeg -threads 2 -i /tmp/ffv1.2-11.avi -f null -
real 0m16.893s
user 0m33.465s
sys 0m0.113s
time ./ffmpeg -thread_type slice -threads 4 -i /tmp/ffv1.2-11.avi -f null -
real 0m9.180s
user 0m33.500s
sys 0m0.088s
time ./ffmpeg -threads 4 -i /tmp/ffv1.2-11.avi -f null -
real 0m8.811s
user 0m33.338s
sys 0m0.061s
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
The bravest are surely those who have the clearest vision
of what is before them, glory and danger alike, and yet
notwithstanding go out to meet it. -- Thucydides
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 09/39] lavc/ffv1: move run_index to the per-slice context
2024-07-18 15:36 ` Anton Khirnov
@ 2024-07-18 17:41 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-18 17:41 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 721 bytes --]
On Thu, Jul 18, 2024 at 05:36:39PM +0200, Anton Khirnov wrote:
> Quoting Michael Niedermayer (2024-07-18 00:49:41)
> > The need for passing an additional pointer around
> >
> > seems to me a net negative
>
> It makes it explicitly clear which data is per-slice, and which
> per-frame/global, which is much harder to figure out with current code.
if its not meassurably slower then its ok
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
When the tyrant has disposed of foreign enemies by conquest or treaty, and
there is nothing more to fear from them, then he is always stirring up
some war or other, in order that the people may require a leader. -- Plato
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack
2024-07-18 15:31 ` Anton Khirnov
2024-07-18 15:35 ` Paul B Mahol
@ 2024-07-18 18:18 ` Michael Niedermayer
2024-07-20 12:15 ` Anton Khirnov
1 sibling, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-18 18:18 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2244 bytes --]
On Thu, Jul 18, 2024 at 05:31:16PM +0200, Anton Khirnov wrote:
> Quoting Michael Niedermayer (2024-07-18 16:48:06)
> > On Thu, Jul 18, 2024 at 11:08:59AM +0200, Anton Khirnov wrote:
> > > Quoting Michael Niedermayer (2024-07-18 00:42:05)
[...]
> > >
> > > Another factor that matters in efficient cache use is e.g. not having
> > > multiple copies of the same constant data scattered around, which you're
> > > objecting to in my other patches.
> >
> > copying the actually used small data together per slice
> > where its accessed per pixel should improve teh speed per pixel while
> > making the per slice code a little slower. now we have 4 slices maybe
> > and millions of pixels. Thats why this can give an overall gain
>
> This all sounds like premature optimization, AKA the root of all evil.
> As I said above, I intended to make this code more readable, not faster.
> Yet somehow it became faster anyway, which suggests this code is not
> very optimized. So then arguing whether this or that specific change
> adds or removes a few cycles per frame seems like a waste time to me.
Making the code faster is welcome
Making the code cleaner is welcome
whats faster is objective (mostly)
whats cleaner is not objective. So we could agree or disagree on that
Things that make the code slower, and dont provide a larger improvment
elsewhere i do object to
About "premature optimization", i have not seen any optimizations being
removed that made the code hard to maintain or work with so this is
not a nice statement.
And iam the first to suport making the code cleaner and easier to maintain
as iam the one maintaining it.
Either way, thanks for your efforts in improving the ffv1 code, they
are appreciated, my objections are not meant to hinder improvments
i just want to make sure it all one by one is an improvment
thx
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Any man who breaks a law that conscience tells him is unjust and willingly
accepts the penalty by staying in jail in order to arouse the conscience of
the community on the injustice of the law is at that moment expressing the
very highest respect for law. - Martin Luther King Jr
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table
2024-07-18 17:40 ` Michael Niedermayer
@ 2024-07-20 9:22 ` Anton Khirnov
0 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-20 9:22 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-18 19:40:04)
> On Thu, Jul 18, 2024 at 10:20:09AM +0200, Anton Khirnov wrote:
> > Quoting Michael Niedermayer (2024-07-18 00:32:38)
> > > the data for each decoder task should be together and not scattered around
> > > more than needed, reducing cache efficiency
> > >
> > > putting all this extra code in the inner per pixel loop is not ok
> > > especially not for the sake of avoiding a memcpy of a few hundread bytes multiple levels of loops outside
> >
> > A nice theory, but in practice this patchset makes single-threaded
> > decoding about 4% faster overall, on a 1920x1080 10bit sample. That's
> > just the ffv1 parts (up to patch 28), full set also improves frame
> > threading performance as follows:
> > threads improvement
> > ---------------------------
> > 2 52% (yes really)
> > 4 16%
> > 8 12%
>
> I do want the speed improvements, yes.
>
> But
> you compare frame threading when slice threading performed
> much better than frame threading prior to the patch
If that were true in general, there'd be no reason for frame threading
support in ffv1, as it has a higher latency and uses more memory; higher
performance is its only advantage.
However you added frame threading in
a0c0900e470fde0d6db360e555620476c2323895 claiming it is faster, which I
can partially confirm even with current master - slice threading
saturates at thread count = slice count, while frame threading scales
beyond it. Frame threading also improves significantly after this set:
threads | slice | frame/before | frame/after
-----------------------------------------------
2 22.6124 43.738 22.0354
4 14.3367 15.115 13.1964
6 14.3850 11.974 10.9745
8 14.3472 9.7229 8.76617
10 14.3579 8.4638 8.6499
12 14.3665 8.4636 8.5735
16 14.2960 7.6926 7.1696
-----------------------------------------------
(values are total decode time in seconds)
Note that after this set frame threading is ALWAYS faster than slice
threading, for any thread count.
> also id like to see the individual changes which look like they should
> make teh code slower, to be tested individually. If they make the code slower
> they should be dropped
I don't think it's meaningful to individually benchmark the patches
moving per-slice data into the new per-slice context. I split them to
simplify testing and review, but it only makes sense to apply all of
them or none, otherwise the code gets more complex.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack
2024-07-18 18:18 ` Michael Niedermayer
@ 2024-07-20 12:15 ` Anton Khirnov
0 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-20 12:15 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-18 20:18:15)
> On Thu, Jul 18, 2024 at 05:31:16PM +0200, Anton Khirnov wrote:
> > Quoting Michael Niedermayer (2024-07-18 16:48:06)
> > > On Thu, Jul 18, 2024 at 11:08:59AM +0200, Anton Khirnov wrote:
> > > > Quoting Michael Niedermayer (2024-07-18 00:42:05)
> [...]
> > > >
> > > > Another factor that matters in efficient cache use is e.g. not having
> > > > multiple copies of the same constant data scattered around, which you're
> > > > objecting to in my other patches.
> > >
> > > copying the actually used small data together per slice
> > > where its accessed per pixel should improve teh speed per pixel while
> > > making the per slice code a little slower. now we have 4 slices maybe
> > > and millions of pixels. Thats why this can give an overall gain
> >
> > This all sounds like premature optimization, AKA the root of all evil.
> > As I said above, I intended to make this code more readable, not faster.
> > Yet somehow it became faster anyway, which suggests this code is not
> > very optimized. So then arguing whether this or that specific change
> > adds or removes a few cycles per frame seems like a waste time to me.
>
> Making the code faster is welcome
> Making the code cleaner is welcome
>
> whats faster is objective (mostly)
> whats cleaner is not objective. So we could agree or disagree on that
>
> Things that make the code slower, and dont provide a larger improvment
> elsewhere i do object to
>
> About "premature optimization", i have not seen any optimizations being
> removed that made the code hard to maintain or work with so this is
> not a nice statement.
> And iam the first to suport making the code cleaner and easier to maintain
> as iam the one maintaining it.
>
> Either way, thanks for your efforts in improving the ffv1 code, they
> are appreciated, my objections are not meant to hinder improvments
> i just want to make sure it all one by one is an improvment
As I said in my other reply, patches 07-25 moving per-slice data to a
new per-slice struct should be considered as one change, as it does not
make sense to apply only some of them and not the others. Some of them,
taken individually, may introduce transient slowdown, because
temporarily there are two per-slice contexts.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 1/3] lavc/ffv1dec: drop code handling AV_PIX_FMT_FLAG_PAL
2024-07-17 20:51 ` Michael Niedermayer
@ 2024-07-22 9:43 ` Anton Khirnov
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice() Anton Khirnov
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 3/3] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
0 siblings, 2 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-22 9:43 UTC (permalink / raw)
To: ffmpeg-devel
No paletted pixel formats are supported by the decoder.
---
libavcodec/ffv1dec.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 7dc4a537a9..aa2c35880e 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -981,10 +981,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
(sc->slice_y >> sv) + ((sc->slice_x >> sh) << pixshift);
}
- if (desc->flags & AV_PIX_FMT_FLAG_PAL) {
- dst[1] = p->data[1];
- src[1] = f->last_picture.f->data[1];
- }
+
av_image_copy(dst, p->linesize, src,
f->last_picture.f->linesize,
avctx->pix_fmt,
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice()
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 1/3] lavc/ffv1dec: drop code handling AV_PIX_FMT_FLAG_PAL Anton Khirnov
@ 2024-07-22 9:43 ` Anton Khirnov
2024-07-22 21:14 ` Michael Niedermayer
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 3/3] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
1 sibling, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-22 9:43 UTC (permalink / raw)
To: ffmpeg-devel
There is no reason to delay it and this is a more natural place for
this code.
---
libavcodec/ffv1dec.c | 53 ++++++++++++++++++++++----------------------
1 file changed, 27 insertions(+), 26 deletions(-)
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index aa2c35880e..5821a4156a 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -290,7 +290,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
if ((p->flags & AV_FRAME_FLAG_KEY) || sc->slice_reset_contexts) {
ff_ffv1_clear_slice_state(f, sc);
} else if (sc->slice_damaged) {
- return AVERROR_INVALIDDATA;
+ goto handle_damage;
}
width = sc->slice_width;
@@ -347,6 +347,32 @@ static int decode_slice(AVCodecContext *c, void *arg)
}
}
+handle_damage:
+ if (sc->slice_damaged && f->last_picture.f) {
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->pix_fmt);
+ const uint8_t *src[4];
+ uint8_t *dst[4];
+
+ ff_progress_frame_await(&f->last_picture, si);
+
+ for (int j = 0; j < desc->nb_components; j++) {
+ int pixshift = desc->comp[j].depth > 8;
+ int sh = (j == 1 || j == 2) ? f->chroma_h_shift : 0;
+ int sv = (j == 1 || j == 2) ? f->chroma_v_shift : 0;
+ dst[j] = p->data[j] + p->linesize[j] *
+ (sc->slice_y >> sv) + ((sc->slice_x >> sh) << pixshift);
+ src[j] = f->last_picture.f->data[j] + f->last_picture.f->linesize[j] *
+ (sc->slice_y >> sv) + ((sc->slice_x >> sh) << pixshift);
+
+ }
+
+ av_image_copy(dst, p->linesize, src,
+ f->last_picture.f->linesize,
+ c->pix_fmt,
+ sc->slice_width,
+ sc->slice_height);
+ }
+
ff_progress_frame_report(&f->picture, si);
return 0;
@@ -964,31 +990,6 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
f->slice_count,
sizeof(*f->slices));
- for (int i = f->slice_count - 1; i >= 0; i--) {
- FFV1SliceContext *sc = &f->slices[i];
- if (sc->slice_damaged && f->last_picture.f) {
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt);
- const uint8_t *src[4];
- uint8_t *dst[4];
- ff_progress_frame_await(&f->last_picture, INT_MAX);
- for (int j = 0; j < desc->nb_components; j++) {
- int pixshift = desc->comp[j].depth > 8;
- int sh = (j == 1 || j == 2) ? f->chroma_h_shift : 0;
- int sv = (j == 1 || j == 2) ? f->chroma_v_shift : 0;
- dst[j] = p->data[j] + p->linesize[j] *
- (sc->slice_y >> sv) + ((sc->slice_x >> sh) << pixshift);
- src[j] = f->last_picture.f->data[j] + f->last_picture.f->linesize[j] *
- (sc->slice_y >> sv) + ((sc->slice_x >> sh) << pixshift);
-
- }
-
- av_image_copy(dst, p->linesize, src,
- f->last_picture.f->linesize,
- avctx->pix_fmt,
- sc->slice_width,
- sc->slice_height);
- }
- }
ff_progress_frame_report(&f->picture, INT_MAX);
ff_progress_frame_unref(&f->last_picture);
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH 3/3] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 1/3] lavc/ffv1dec: drop code handling AV_PIX_FMT_FLAG_PAL Anton Khirnov
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice() Anton Khirnov
@ 2024-07-22 9:43 ` Anton Khirnov
1 sibling, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-22 9:43 UTC (permalink / raw)
To: ffmpeg-devel
That variable is shared between frame threads in the same defective way
described in the previous commit. Fix it by adding a RefStruct-managed
arrays of flags that is propagated across frame threads in the standard
manner.
Remove now-unused FFV1Context.fsrc
---
libavcodec/ffv1.c | 2 ++
libavcodec/ffv1.h | 9 ++++++++-
libavcodec/ffv1dec.c | 26 +++++++++++++-------------
3 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 9c219b5ddb..333fb3d79b 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -214,6 +214,8 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
ff_refstruct_unref(&sc->plane);
}
+ ff_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]);
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index edc3f6aef0..92c629c823 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -118,7 +118,6 @@ typedef struct FFV1Context {
int64_t picture_number;
int key_frame;
ProgressFrame picture, last_picture;
- struct FFV1Context *fsrc;
const AVFrame *cur_enc_frame;
int plane_count;
@@ -148,6 +147,14 @@ typedef struct FFV1Context {
int num_h_slices;
FFV1SliceContext *slices;
+ /* RefStruct object, per-slice damage flags shared between frame threads.
+ *
+ * After a frame thread marks some slice as finished with
+ * ff_progress_frame_report(), the corresponding array element must not be
+ * accessed by this thread anymore, as from then on it is owned by the next
+ * thread.
+ */
+ uint8_t *slice_damaged;
} FFV1Context;
int ff_ffv1_common_init(AVCodecContext *avctx);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 5821a4156a..a69f18e252 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -263,15 +263,10 @@ static int decode_slice(AVCodecContext *c, void *arg)
const int si = sc - f->slices;
GetBitContext gb;
- if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
+ if (!(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
ff_progress_frame_await(&f->last_picture, si);
- if (f->fsrc) {
- const FFV1SliceContext *scsrc = &f->fsrc->slices[si];
-
- if (!(p->flags & AV_FRAME_FLAG_KEY))
- sc->slice_damaged |= scsrc->slice_damaged;
- }
+ sc->slice_damaged |= f->slice_damaged[si];
sc->slice_rct_by_coef = 1;
sc->slice_rct_ry_coef = 1;
@@ -373,6 +368,8 @@ handle_damage:
sc->slice_height);
}
+ f->slice_damaged[si] = sc->slice_damaged;
+
ff_progress_frame_report(&f->picture, si);
return 0;
@@ -793,11 +790,14 @@ static int read_header(FFV1Context *f)
return AVERROR_INVALIDDATA;
}
+ ff_refstruct_unref(&f->slice_damaged);
+ f->slice_damaged = ff_refstruct_allocz(f->slice_count * sizeof(*f->slice_damaged));
+ if (!f->slice_damaged)
+ return AVERROR(ENOMEM);
+
for (int j = 0; j < f->slice_count; j++) {
FFV1SliceContext *sc = &f->slices[j];
- sc->slice_damaged = 0;
-
if (f->version == 2) {
int sx = get_symbol(c, state, 0);
int sy = get_symbol(c, state, 0);
@@ -945,6 +945,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
int trailer = 3 + 5*!!f->ec;
int v;
+ sc->slice_damaged = 0;
+
if (i || f->version > 2) {
if (trailer > buf_p - buf) v = INT_MAX;
else v = AV_RB24(buf_p-trailer) + trailer;
@@ -1039,8 +1041,6 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
FFV1SliceContext *sc = &fdst->slices[i];
const FFV1SliceContext *sc0 = &fsrc->slices[i];
- sc->slice_damaged = sc0->slice_damaged;
-
ff_refstruct_replace(&sc->plane, sc0->plane);
if (fsrc->version < 3) {
@@ -1051,12 +1051,12 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
}
}
+ ff_refstruct_replace(&fdst->slice_damaged, fsrc->slice_damaged);
+
av_assert1(fdst->max_slice_count == fsrc->max_slice_count);
ff_progress_frame_replace(&fdst->picture, &fsrc->picture);
- fdst->fsrc = fsrc;
-
return 0;
}
#endif
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice()
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice() Anton Khirnov
@ 2024-07-22 21:14 ` Michael Niedermayer
2024-07-23 6:52 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-22 21:14 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1057 bytes --]
On Mon, Jul 22, 2024 at 11:43:21AM +0200, Anton Khirnov wrote:
> There is no reason to delay it and this is a more natural place for
> this code.
There is a reason.
By doing it later the surrounding pixels are available and one could
compute motion vectors from these surroundings and use all kinds of stuff
from motion compensation and optical flow and all that.
someone, i dont remember exactly who, (maybe you remember?)
said something about premature optimization is the root of all evil.
Here that actually applies. Moving the code up thwarts write better
error concealment. (and frankly we already have most of that EC code
it would just need a cleanup to free it from the 16x16 limitation)
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
The real ebay dictionary, page 1
"Used only once" - "Some unspecified defect prevented a second use"
"In good condition" - "Can be repaird by experienced expert"
"As is" - "You wouldnt want it even if you were payed for it, if you knew ..."
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice()
2024-07-22 21:14 ` Michael Niedermayer
@ 2024-07-23 6:52 ` Anton Khirnov
2024-07-23 20:14 ` Michael Niedermayer
0 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-23 6:52 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-22 23:14:04)
> On Mon, Jul 22, 2024 at 11:43:21AM +0200, Anton Khirnov wrote:
> > There is no reason to delay it and this is a more natural place for
> > this code.
>
> There is a reason.
> By doing it later the surrounding pixels are available and one could
> compute motion vectors from these surroundings and use all kinds of stuff
> from motion compensation and optical flow and all that.
>
> someone, i dont remember exactly who, (maybe you remember?)
> said something about premature optimization is the root of all evil.
> Here that actually applies. Moving the code up thwarts write better
> error concealment. (and frankly we already have most of that EC code
> it would just need a cleanup to free it from the 16x16 limitation)
This is not an optimization though.
But okay, I am dropping both original patch 28 and these 3 new patches.
Are you ok with the rest of the series?
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice()
2024-07-23 6:52 ` Anton Khirnov
@ 2024-07-23 20:14 ` Michael Niedermayer
2024-07-23 21:02 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-23 20:14 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1446 bytes --]
On Tue, Jul 23, 2024 at 08:52:58AM +0200, Anton Khirnov wrote:
> Quoting Michael Niedermayer (2024-07-22 23:14:04)
> > On Mon, Jul 22, 2024 at 11:43:21AM +0200, Anton Khirnov wrote:
> > > There is no reason to delay it and this is a more natural place for
> > > this code.
> >
> > There is a reason.
> > By doing it later the surrounding pixels are available and one could
> > compute motion vectors from these surroundings and use all kinds of stuff
> > from motion compensation and optical flow and all that.
> >
> > someone, i dont remember exactly who, (maybe you remember?)
> > said something about premature optimization is the root of all evil.
> > Here that actually applies. Moving the code up thwarts write better
> > error concealment. (and frankly we already have most of that EC code
> > it would just need a cleanup to free it from the 16x16 limitation)
>
> This is not an optimization though.
>
> But okay, I am dropping both original patch 28 and these 3 new patches.
> Are you ok with the rest of the series?
The series looked mostly ok, is there somewhere i can take a quick look
at the current set ?
also i definitly want all bugfixes and speedups you did :)
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Does the universe only have a finite lifespan? No, its going to go on
forever, its just that you wont like living in it. -- Hiranya Peiri
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice()
2024-07-23 20:14 ` Michael Niedermayer
@ 2024-07-23 21:02 ` Anton Khirnov
0 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-07-23 21:02 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-23 22:14:19)
> On Tue, Jul 23, 2024 at 08:52:58AM +0200, Anton Khirnov wrote:
> > Quoting Michael Niedermayer (2024-07-22 23:14:04)
> > > On Mon, Jul 22, 2024 at 11:43:21AM +0200, Anton Khirnov wrote:
> > > > There is no reason to delay it and this is a more natural place for
> > > > this code.
> > >
> > > There is a reason.
> > > By doing it later the surrounding pixels are available and one could
> > > compute motion vectors from these surroundings and use all kinds of stuff
> > > from motion compensation and optical flow and all that.
> > >
> > > someone, i dont remember exactly who, (maybe you remember?)
> > > said something about premature optimization is the root of all evil.
> > > Here that actually applies. Moving the code up thwarts write better
> > > error concealment. (and frankly we already have most of that EC code
> > > it would just need a cleanup to free it from the 16x16 limitation)
> >
> > This is not an optimization though.
> >
> > But okay, I am dropping both original patch 28 and these 3 new patches.
> > Are you ok with the rest of the series?
>
> The series looked mostly ok, is there somewhere i can take a quick look
> at the current set ?
I just pushed it to branch 'receive_frame' in my tree.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
` (37 preceding siblings ...)
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 39/39] lavc/hevcdec: call ff_thread_finish_setup() even if hwaccel is in use Anton Khirnov
@ 2024-07-24 18:20 ` Michael Niedermayer
38 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 18:20 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 777 bytes --]
On Tue, Jul 16, 2024 at 07:11:16PM +0200, Anton Khirnov wrote:
> ---
> tests/fate/vcodec.mak | 3 ++-
> tests/ref/vsynth/vsynth1-ffv1-v2 | 4 ++++
> tests/ref/vsynth/vsynth2-ffv1-v2 | 4 ++++
> tests/ref/vsynth/vsynth3-ffv1-v2 | 4 ++++
> tests/ref/vsynth/vsynth_lena-ffv1-v2 | 4 ++++
> 5 files changed, 18 insertions(+), 1 deletion(-)
> create mode 100644 tests/ref/vsynth/vsynth1-ffv1-v2
> create mode 100644 tests/ref/vsynth/vsynth2-ffv1-v2
> create mode 100644 tests/ref/vsynth/vsynth3-ffv1-v2
> create mode 100644 tests/ref/vsynth/vsynth_lena-ffv1-v2
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
He who knows, does not speak. He who speaks, does not know. -- Lao Tsu
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 02/39] lavc/ffv1dec: declare loop variables in the loop where possible
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 02/39] lavc/ffv1dec: declare loop variables in the loop where possible Anton Khirnov
@ 2024-07-24 18:22 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 18:22 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 470 bytes --]
On Tue, Jul 16, 2024 at 07:11:17PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1dec.c | 45 ++++++++++++++++++++++----------------------
> 1 file changed, 22 insertions(+), 23 deletions(-)
LGTM
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Into a blind darkness they enter who follow after the Ignorance,
they as if into a greater darkness enter who devote themselves
to the Knowledge alone. -- Isha Upanishad
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 03/39] lavc/ffv1dec: simplify slice index calculation
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 03/39] lavc/ffv1dec: simplify slice index calculation Anton Khirnov
@ 2024-07-24 18:24 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 18:24 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 404 bytes --]
On Tue, Jul 16, 2024 at 07:11:18PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1dec.c | 5 +----
> 1 file changed, 1 insertion(+), 4 deletions(-)
ok
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Complexity theory is the science of finding the exact solution to an
approximation. Benchmarking OTOH is finding an approximation of the exact
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 04/39] lavc/ffv1dec: drop FFV1Context.cur
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 04/39] lavc/ffv1dec: drop FFV1Context.cur Anton Khirnov
@ 2024-07-24 18:27 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 18:27 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 559 bytes --]
On Tue, Jul 16, 2024 at 07:11:19PM +0200, Anton Khirnov wrote:
> It is merely a pointer to FFV1Context.picture.f, which can just as well
> be used directly.
> ---
> libavcodec/ffv1.h | 1 -
> libavcodec/ffv1dec.c | 33 +++++++++++++++++----------------
> 2 files changed, 17 insertions(+), 17 deletions(-)
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 33/39] lavc: convert frame threading to the receive_frame() pattern
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 33/39] lavc: convert frame threading to the receive_frame() pattern Anton Khirnov
@ 2024-07-24 18:44 ` Michael Niedermayer
2024-07-31 11:26 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 18:44 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1555 bytes --]
On Tue, Jul 16, 2024 at 07:11:48PM +0200, Anton Khirnov wrote:
> Reorganize the code such that the frame threading code does not call the
> decoders directly, but instead calls back into the generic decoding
> code. This avoids duplicating the logic that wraps the decoder
> invocation and allows receive_frame()-based decoders to use frame
> threading.
>
> Further work by Timo Rothenpieler <timo@rothenpieler.org>.
> ---
> libavcodec/avcodec.c | 9 +-
> libavcodec/avcodec_internal.h | 25 +--
> libavcodec/decode.c | 40 +++--
> libavcodec/internal.h | 7 +
> libavcodec/pthread_frame.c | 278 +++++++++++++++++++++-------------
> 5 files changed, 235 insertions(+), 124 deletions(-)
this (frm your recive_frame branch) breaks:
for i in `seq 10` ; do ./ffmpeg -v 0 -i ffv1.3-01ec.avi -t 1 -f crc - ; done
CRC=0xf0227bce
CRC=0xf0227bce
CRC=0xb40076a4
CRC=0xf0227bce
CRC=0xf0227bce
CRC=0xf0227bce
CRC=0xf0227bce
CRC=0xf0227bce
CRC=0xb40076a4
CRC=0x6f1fc654
before:
make -j32 && for i in `seq 10` ; do ./ffmpeg -v 0 -i ffv1.3-01ec.avi -t 1 -f crc - ; done
CRC=0xc2cd3350
CRC=0xc2cd3350
CRC=0xc2cd3350
CRC=0xc2cd3350
CRC=0xc2cd3350
CRC=0xc2cd3350
CRC=0xc2cd3350
CRC=0xc2cd3350
CRC=0xc2cd3350
CRC=0xc2cd3350
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Into a blind darkness they enter who follow after the Ignorance,
they as if into a greater darkness enter who devote themselves
to the Knowledge alone. -- Isha Upanishad
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 05/39] lavc/ffv1dec: drop a pointless variable in decode_slice()
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 05/39] lavc/ffv1dec: drop a pointless variable in decode_slice() Anton Khirnov
@ 2024-07-24 18:58 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 18:58 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 563 bytes --]
On Tue, Jul 16, 2024 at 07:11:20PM +0200, Anton Khirnov wrote:
> fsdst is by construction always equal to fs, there is even an
> av_assert1() checking that. Just use fs directly.
> ---
> libavcodec/ffv1dec.c | 8 +++-----
> 1 file changed, 3 insertions(+), 5 deletions(-)
probably ok
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Into a blind darkness they enter who follow after the Ignorance,
they as if into a greater darkness enter who devote themselves
to the Knowledge alone. -- Isha Upanishad
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 06/39] lavc/ffv1dec: move copy_fields() under HAVE_THREADS
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 06/39] lavc/ffv1dec: move copy_fields() under HAVE_THREADS Anton Khirnov
@ 2024-07-24 18:58 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 18:58 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 515 bytes --]
On Tue, Jul 16, 2024 at 07:11:21PM +0200, Anton Khirnov wrote:
> It is unused otherwise
> ---
> libavcodec/ffv1dec.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
ok
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Frequently ignored answer#1 FFmpeg bugs should be sent to our bugtracker. User
questions about the command line tools should be sent to the ffmpeg-user ML.
And questions about how to use libav* should be sent to the libav-user ML.
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 07/39] lavc/ffv1: add a per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 07/39] lavc/ffv1: add a per-slice context Anton Khirnov
@ 2024-07-24 19:01 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:01 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1031 bytes --]
On Tue, Jul 16, 2024 at 07:11:22PM +0200, Anton Khirnov wrote:
> FFV1 decoder and encoder currently use the same struct - FFV1Context -
> both as codec private data and per-slice context. For this purpose
> FFV1Context contains an array of pointers to per-slice FFV1Context
> instances.
>
> This pattern is highly confusing, as it is not clear which fields are
> per-slice and which per-codec.
>
> Address this by adding a new struct storing only per-slice data. Start
> by moving slice_{x,y,width,height} to it.
> ---
> libavcodec/ffv1.c | 15 ++++++---
> libavcodec/ffv1.h | 13 +++++---
> libavcodec/ffv1dec.c | 76 ++++++++++++++++++++++++--------------------
> libavcodec/ffv1enc.c | 25 ++++++++-------
> 4 files changed, 76 insertions(+), 53 deletions(-)
LGTM
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 08/39] lavc/ffv1: move sample_buffer to the per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 08/39] lavc/ffv1: move sample_buffer to the " Anton Khirnov
@ 2024-07-24 19:04 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:04 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 657 bytes --]
On Tue, Jul 16, 2024 at 07:11:23PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.c | 35 ++++++++++++++++++++---------------
> libavcodec/ffv1.h | 5 +++--
> libavcodec/ffv1dec.c | 27 +++++++++++++--------------
> libavcodec/ffv1dec_template.c | 9 +++++----
> libavcodec/ffv1enc.c | 30 ++++++++++++++++--------------
> libavcodec/ffv1enc_template.c | 9 +++++----
> 6 files changed, 62 insertions(+), 53 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
He who knows, does not speak. He who speaks, does not know. -- Lao Tsu
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 11/39] lavc/ffv1enc: move bit writer to per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 11/39] lavc/ffv1enc: move bit writer to per-slice context Anton Khirnov
@ 2024-07-24 19:07 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:07 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 449 bytes --]
On Tue, Jul 16, 2024 at 07:11:26PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.h | 3 ++-
> libavcodec/ffv1enc.c | 7 ++++---
> libavcodec/ffv1enc_template.c | 14 +++++++-------
> 3 files changed, 13 insertions(+), 11 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Democracy is the form of government in which you can choose your dictator
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 14/39] lavc/ffv1: drop write-only PlaneContext.interlace_bit_state
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 14/39] lavc/ffv1: drop write-only PlaneContext.interlace_bit_state Anton Khirnov
@ 2024-07-24 19:12 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:12 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 454 bytes --]
On Tue, Jul 16, 2024 at 07:11:29PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.c | 3 ---
> libavcodec/ffv1.h | 1 -
> 2 files changed, 4 deletions(-)
ok
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Let us carefully observe those good qualities wherein our enemies excel us
and endeavor to excel them, by avoiding what is faulty, and imitating what
is excellent in them. -- Plutarch
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 15/39] lavc/ffv1: always use the main context values of plane_count/transparency
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 15/39] lavc/ffv1: always use the main context values of plane_count/transparency Anton Khirnov
@ 2024-07-24 19:15 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:15 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 576 bytes --]
On Tue, Jul 16, 2024 at 07:11:30PM +0200, Anton Khirnov wrote:
> They cannot change between slices.
> ---
> libavcodec/ffv1.c | 2 --
> libavcodec/ffv1dec.c | 5 ++---
> libavcodec/ffv1dec_template.c | 2 +-
> libavcodec/ffv1enc.c | 2 +-
> libavcodec/ffv1enc_template.c | 2 +-
> 5 files changed, 5 insertions(+), 8 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
It is a danger to trust the dream we wish for rather than
the science we have, -- Dr. Kenneth Brown
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 16/39] lavc/ffv1: move FFV1Context.slice_{coding_mode, rct_.y_coef} to per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 16/39] lavc/ffv1: move FFV1Context.slice_{coding_mode, rct_.y_coef} to per-slice context Anton Khirnov
@ 2024-07-24 19:16 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:16 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 607 bytes --]
On Tue, Jul 16, 2024 at 07:11:31PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.h | 6 +++---
> libavcodec/ffv1dec.c | 14 +++++++-------
> libavcodec/ffv1dec_template.c | 10 +++++-----
> libavcodec/ffv1enc.c | 26 +++++++++++++-------------
> libavcodec/ffv1enc_template.c | 10 +++++-----
> 5 files changed, 33 insertions(+), 33 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
If you think the mosad wants you dead since a long time then you are either
wrong or dead since a long time.
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 17/39] lavc/ffv1: always use the main context values of ac
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 17/39] lavc/ffv1: always use the main context values of ac Anton Khirnov
@ 2024-07-24 19:23 ` Michael Niedermayer
2024-07-31 8:33 ` [FFmpeg-devel] [PATCH v2 " Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:23 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 533 bytes --]
On Tue, Jul 16, 2024 at 07:11:32PM +0200, Anton Khirnov wrote:
> It cannot change between slices.
that is true currently but considering that its used in some of the inner loops
i dont think carrying an additional pointer around into these loops makes
sense
either leave it or move the ac value to teh stack for these functions
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
It is dangerous to be right in matters on which the established authorities
are wrong. -- Voltaire
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 19/39] lavc/ffv1: move RangeCoder to per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 19/39] lavc/ffv1: move RangeCoder " Anton Khirnov
@ 2024-07-24 19:28 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:28 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 721 bytes --]
On Tue, Jul 16, 2024 at 07:11:34PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.c | 9 ++--
> libavcodec/ffv1.h | 5 +--
> libavcodec/ffv1dec.c | 72 ++++++++++++++++----------------
> libavcodec/ffv1dec_template.c | 2 +-
> libavcodec/ffv1enc.c | 78 ++++++++++++++++++-----------------
> libavcodec/ffv1enc_template.c | 2 +-
> 6 files changed, 85 insertions(+), 83 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Into a blind darkness they enter who follow after the Ignorance,
they as if into a greater darkness enter who devote themselves
to the Knowledge alone. -- Isha Upanishad
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 20/39] lavc/ffv1enc: store per-slice rc_stat(2?) in FFV1SliceContext
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 20/39] lavc/ffv1enc: store per-slice rc_stat(2?) in FFV1SliceContext Anton Khirnov
@ 2024-07-24 19:30 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:30 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 710 bytes --]
On Tue, Jul 16, 2024 at 07:11:35PM +0200, Anton Khirnov wrote:
> Instead of the per-slice FFV1Context, which will be removed in future
> commits.
> ---
> libavcodec/ffv1.c | 6 ++----
> libavcodec/ffv1.h | 3 +++
> libavcodec/ffv1enc.c | 20 ++++++++++----------
> libavcodec/ffv1enc_template.c | 4 ++--
> 4 files changed, 17 insertions(+), 16 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Many that live deserve death. And some that die deserve life. Can you give
it to them? Then do not be too eager to deal out death in judgement. For
even the very wise cannot see all ends. -- Gandalf
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 21/39] lavc/ffv1: move ac_byte_count to per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 21/39] lavc/ffv1: move ac_byte_count to per-slice context Anton Khirnov
@ 2024-07-24 19:31 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:31 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 476 bytes --]
On Tue, Jul 16, 2024 at 07:11:36PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.h | 2 +-
> libavcodec/ffv1dec.c | 6 +++---
> libavcodec/ffv1enc.c | 6 +++---
> 3 files changed, 7 insertions(+), 7 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Dictatorship naturally arises out of democracy, and the most aggravated
form of tyranny and slavery out of the most extreme liberty. -- Plato
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 22/39] lavc/ffv1enc: stop using per-slice FFV1Context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 22/39] lavc/ffv1enc: stop using per-slice FFV1Context Anton Khirnov
@ 2024-07-24 19:42 ` Michael Niedermayer
2024-07-31 8:50 ` [FFmpeg-devel] [PATCH v2 " Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:42 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2435 bytes --]
On Tue, Jul 16, 2024 at 07:11:37PM +0200, Anton Khirnov wrote:
> All remaining accesses to them are for fields that have the same value
> in the main encoder context.
> ---
> libavcodec/ffv1enc.c | 57 ++++++++++++++++-------------------
> libavcodec/ffv1enc_template.c | 24 +++++++--------
> 2 files changed, 37 insertions(+), 44 deletions(-)
[...]
> +RENAME(encode_line)(FFV1Context *f, FFV1SliceContext *sc,
> int w, TYPE *sample[3], int plane_index, int bits)
> {
> PlaneContext *const p = &sc->plane[plane_index];
> @@ -36,12 +35,12 @@ RENAME(encode_line)(FFV1Context *f,
>
> if (f->ac != AC_GOLOMB_RICE) {
> if (c->bytestream_end - c->bytestream < w * 35) {
> - av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
> + av_log(f->avctx, AV_LOG_ERROR, "encoded frame too large\n");
> return AVERROR_INVALIDDATA;
> }
> } else {
> if (put_bytes_left(&sc->pb, 0) < w * 4) {
> - av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
> + av_log(f->avctx, AV_LOG_ERROR, "encoded frame too large\n");
> return AVERROR_INVALIDDATA;
> }
> }
> @@ -73,7 +72,7 @@ RENAME(encode_line)(FFV1Context *f,
> diff = fold(diff, bits);
>
> if (f->ac != AC_GOLOMB_RICE) {
> - if (s->flags & AV_CODEC_FLAG_PASS1) {
> + if (f->flags & AV_CODEC_FLAG_PASS1) {
> put_symbol_inline(c, p->state[context], diff, 1, sc->rc_stat,
> sc->rc_stat2[p->quant_table_index][context]);
> } else {
> @@ -103,7 +102,7 @@ RENAME(encode_line)(FFV1Context *f,
> }
> }
>
> - ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
> + ff_dlog(f->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
> run_count, run_index, run_mode, x,
> (int)put_bits_count(&sc->pb));
>
iam not sure if carrying a 2nd pointer around in the loops in encode_line() for
ac/flags/avctx is worth it. IMHO these could be either on teh stack or in the
slice context
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
It is dangerous to be right in matters on which the established authorities
are wrong. -- Voltaire
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 23/39] lavc/ffv1dec: move slice_reset_contexts to per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 23/39] lavc/ffv1dec: move slice_reset_contexts to per-slice context Anton Khirnov
@ 2024-07-24 19:44 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:44 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 430 bytes --]
On Tue, Jul 16, 2024 at 07:11:38PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.h | 16 +++++++++++++---
> libavcodec/ffv1dec.c | 4 ++--
> 2 files changed, 15 insertions(+), 5 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
I know you won't believe me, but the highest form of Human Excellence is
to question oneself and others. -- Socrates
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 24/39] lavc/ffv1dec: move slice_damaged to per-slice context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 24/39] lavc/ffv1dec: move slice_damaged " Anton Khirnov
@ 2024-07-24 19:45 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:45 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 386 bytes --]
On Tue, Jul 16, 2024 at 07:11:39PM +0200, Anton Khirnov wrote:
> ---
> libavcodec/ffv1.h | 2 +-
> libavcodec/ffv1dec.c | 18 ++++++++----------
> 2 files changed, 9 insertions(+), 11 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Observe your enemies, for they first find out your faults. -- Antisthenes
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 25/39] lavc/ffv1dec: stop using per-slice FFV1Context
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 25/39] lavc/ffv1dec: stop using per-slice FFV1Context Anton Khirnov
@ 2024-07-24 19:48 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:48 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 686 bytes --]
On Tue, Jul 16, 2024 at 07:11:40PM +0200, Anton Khirnov wrote:
> All remaining accesses to them are for fields that have the same value
> in the main encoder context.
>
> Drop now-unused FFV1Context.slice_contexts.
> ---
> libavcodec/ffv1.c | 18 +++---------
> libavcodec/ffv1.h | 1 -
> libavcodec/ffv1dec.c | 54 ++++++++++++++---------------------
> libavcodec/ffv1dec_template.c | 16 +++++------
> 4 files changed, 33 insertions(+), 56 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
No great genius has ever existed without some touch of madness. -- Aristotle
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 26/39] lavc/ffv1dec: inline copy_fields() into update_thread_context()
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 26/39] lavc/ffv1dec: inline copy_fields() into update_thread_context() Anton Khirnov
@ 2024-07-24 19:48 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:48 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 450 bytes --]
On Tue, Jul 16, 2024 at 07:11:41PM +0200, Anton Khirnov wrote:
> It is now only called from a single place, so there is no point in it
> being a separate function.
> ---
> libavcodec/ffv1dec.c | 38 ++++++++++++++++----------------------
> 1 file changed, 16 insertions(+), 22 deletions(-)
ok
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
You can kill me, but you cannot change the truth.
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 27/39] lavc/ffv1: change FFV1SliceContext.plane into a RefStruct object
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 27/39] lavc/ffv1: change FFV1SliceContext.plane into a RefStruct object Anton Khirnov
@ 2024-07-24 19:53 ` Michael Niedermayer
2024-08-01 8:17 ` Anton Khirnov
1 sibling, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-24 19:53 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 3632 bytes --]
On Tue, Jul 16, 2024 at 07:11:42PM +0200, Anton Khirnov wrote:
> Frame threading in the FFV1 decoder works in a very unusual way - the
> state that needs to be propagated from the previous frame is not decoded
> pixels(¹), but each slice's entropy coder state after decoding the slice.
>
> For that purpose, the decoder's update_thread_context() callback stores
> a pointer to the previous frame thread's private data. Then, when
> decoding each slice, the frame thread uses the standard progress
> mechanism to wait for the corresponding slice in the previous frame to
> be completed, then copies the entropy coder state from the
> previously-stored pointer.
>
> This approach is highly dubious, as update_thread_context() should be
> the only point where frame-thread contexts come into direct contact.
> There are no guarantees that the stored pointer will be valid at all, or
> will contain any particular data after update_thread_context() finishes.
>
> More specifically, this code can break due to the fact that keyframes
> reset entropy coder state and thus do not need to wait for the previous
> frame. As an example, consider a decoder process with 2 frame threads -
> thread 0 with its context 0, and thread 1 with context 1 - decoding a
> previous frame P, current frame F, followed by a keyframe K. Then
> consider concurrent execution consistent with the following sequence of
> events:
> * thread 0 starts decoding P
> * thread 0 reads P's slice header, then calls
> ff_thread_finish_setup() allowing next frame thread to start
> * main thread calls update_thread_context() to transfer state from
> context 0 to context 1; context 1 stores a pointer to context 0's private
> data
> * thread 1 starts decoding F
> * thread 1 reads F's slice header, then calls
> ff_thread_finish_setup() allowing the next frame thread to start
> decoding
> * thread 0 finishes decoding P
> * thread 0 starts decoding K; since K is a keyframe, it does not
> wait for F and reallocates the arrays holding entropy coder state
> * thread 0 finishes decoding K
> * thread 1 reads entropy coder state from its stored pointer to context
> 0, however it finds state from K rather than from P
>
> This execution is currently prevented by special-casing FFV1 in the
> generic frame threading code, however that is supremely ugly. It also
> involves unnecessary copies of the state arrays, when in fact they can
> only be used by one thread at a time.
>
> This commit addresses these deficiencies by changing the array of
> PlaneContext (each of which contains the allocated state arrays)
> embedded in FFV1SliceContext into a RefStruct object. This object can
> then be propagated across frame threads in standard manner. Since the
> code structure guarantees only one thread accesses it at a time, no
> copies are necessary. It is also re-created for keyframes, solving the
> above issue cleanly.
>
> Special-casing of FFV1 in the generic frame threading code will be
> removed in a later commit.
>
> (¹) except in the case of a damaged slice, when previous frame's pixels
> are used directly
> ---
> libavcodec/ffv1.c | 30 ++++++++++++++++++++++++------
> libavcodec/ffv1.h | 4 +++-
> libavcodec/ffv1dec.c | 33 +++++++++------------------------
> 3 files changed, 36 insertions(+), 31 deletions(-)
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
If a bugfix only changes things apparently unrelated to the bug with no
further explanation, that is a good sign that the bugfix is wrong.
[-- 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] 110+ messages in thread
* [FFmpeg-devel] [PATCH v2 17/39] lavc/ffv1: always use the main context values of ac
2024-07-24 19:23 ` Michael Niedermayer
@ 2024-07-31 8:33 ` Anton Khirnov
2024-07-31 12:20 ` Michael Niedermayer
0 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-31 8:33 UTC (permalink / raw)
To: ffmpeg-devel
It cannot change between slices.
---
libavcodec/ffv1.c | 6 +++---
libavcodec/ffv1dec.c | 19 +++++++++----------
libavcodec/ffv1dec_template.c | 14 ++++++++------
libavcodec/ffv1enc.c | 11 ++++++-----
libavcodec/ffv1enc_template.c | 12 +++++++-----
5 files changed, 33 insertions(+), 29 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 06a77c3a26..581e775ae2 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -59,7 +59,7 @@ av_cold int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs)
for (j = 0; j < f->plane_count; j++) {
PlaneContext *const p = &fs->plane[j];
- if (fs->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
if (!p->state)
p->state = av_malloc_array(p->context_count, CONTEXT_SIZE *
sizeof(uint8_t));
@@ -78,7 +78,7 @@ av_cold int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs)
}
}
- if (fs->ac == AC_RANGE_CUSTOM_TAB) {
+ if (f->ac == AC_RANGE_CUSTOM_TAB) {
//FIXME only redo if state_transition changed
for (j = 1; j < 256; j++) {
fs->c. one_state[ j] = f->state_transition[j];
@@ -167,7 +167,7 @@ void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs)
for (i = 0; i < f->plane_count; i++) {
PlaneContext *p = &fs->plane[i];
- if (fs->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
if (f->initial_states[p->quant_table_index]) {
memcpy(p->state, f->initial_states[p->quant_table_index],
CONTEXT_SIZE * p->context_count);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 8464697fd3..992b6596ab 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -94,10 +94,9 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState *const state,
return ret;
}
-static int is_input_end(FFV1Context *s, GetBitContext *gb)
+static int is_input_end(RangeCoder *c, GetBitContext *gb, int ac)
{
- if (s->ac != AC_GOLOMB_RICE) {
- RangeCoder *const c = &s->c;
+ if (ac != AC_GOLOMB_RICE) {
if (c->overread > MAX_OVERREAD)
return AVERROR_INVALIDDATA;
} else {
@@ -123,6 +122,7 @@ static int decode_plane(FFV1Context *f,
uint8_t *src, int w, int h, int stride, int plane_index,
int pixel_stride)
{
+ const int ac = f->ac;
int x, y;
int16_t *sample[2];
sample[0] = sc->sample_buffer + 3;
@@ -142,13 +142,13 @@ static int decode_plane(FFV1Context *f,
sample[0][w] = sample[0][w - 1];
if (s->avctx->bits_per_raw_sample <= 8) {
- int ret = decode_line(f, s, sc, gb, w, sample, plane_index, 8);
+ int ret = decode_line(f, s, sc, gb, w, sample, plane_index, 8, ac);
if (ret < 0)
return ret;
for (x = 0; x < w; x++)
src[x*pixel_stride + stride * y] = sample[1][x];
} else {
- int ret = decode_line(f, s, sc, gb, w, sample, plane_index, s->avctx->bits_per_raw_sample);
+ int ret = decode_line(f, s, sc, gb, w, sample, plane_index, s->avctx->bits_per_raw_sample, ac);
if (ret < 0)
return ret;
if (s->packed_at_lsb) {
@@ -197,7 +197,7 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs,
av_assert0 ( (unsigned)sc->slice_x + (uint64_t)sc->slice_width <= f->width
&& (unsigned)sc->slice_y + (uint64_t)sc->slice_height <= f->height);
- if (fs->ac == AC_GOLOMB_RICE && sc->slice_width >= (1<<23))
+ if (f->ac == AC_GOLOMB_RICE && sc->slice_width >= (1<<23))
return AVERROR_INVALIDDATA;
for (unsigned i = 0; i < f->plane_count; i++) {
@@ -284,7 +284,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
pdst->state = NULL;
pdst->vlc_state = NULL;
- if (fssrc->ac) {
+ if (f->ac) {
pdst->state = av_malloc_array(CONTEXT_SIZE, psrc->context_count);
memcpy(pdst->state, psrc->state, CONTEXT_SIZE * psrc->context_count);
} else {
@@ -319,7 +319,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
x = sc->slice_x;
y = sc->slice_y;
- if (fs->ac == AC_GOLOMB_RICE) {
+ if (f->ac == AC_GOLOMB_RICE) {
if (f->version == 3 && f->micro_version > 1 || f->version > 3)
get_rac(&fs->c, (uint8_t[]) { 129 });
fs->ac_byte_count = f->version > 2 || (!x && !y) ? fs->c.bytestream - fs->c.bytestream_start - 1 : 0;
@@ -358,7 +358,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
p->data[3] + ps * x + y * p->linesize[3] };
decode_rgb_frame(f, fs, sc, &gb, planes, width, height, p->linesize);
}
- if (fs->ac != AC_GOLOMB_RICE && f->version > 2) {
+ if (f->ac != AC_GOLOMB_RICE && f->version > 2) {
int v;
get_rac(&fs->c, (uint8_t[]) { 129 });
v = fs->c.bytestream_end - fs->c.bytestream - 2 - 5*f->ec;
@@ -791,7 +791,6 @@ static int read_header(FFV1Context *f)
for (int j = 0; j < f->slice_count; j++) {
FFV1Context *fs = f->slice_context[j];
FFV1SliceContext *sc = &f->slices[j];
- fs->ac = f->ac;
fs->packed_at_lsb = f->packed_at_lsb;
fs->slice_damaged = 0;
diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c
index dbcd4861ac..2e1cad47ac 100644
--- a/libavcodec/ffv1dec_template.c
+++ b/libavcodec/ffv1dec_template.c
@@ -26,7 +26,8 @@ static av_always_inline int
RENAME(decode_line)(FFV1Context *f,
FFV1Context *s, FFV1SliceContext *sc,
GetBitContext *gb,
- int w, TYPE *sample[2], int plane_index, int bits)
+ int w, TYPE *sample[2], int plane_index, int bits,
+ int ac)
{
PlaneContext *const p = &s->plane[plane_index];
RangeCoder *const c = &s->c;
@@ -36,7 +37,7 @@ RENAME(decode_line)(FFV1Context *f,
int run_mode = 0;
int run_index = sc->run_index;
- if (is_input_end(s, gb))
+ if (is_input_end(c, gb, ac))
return AVERROR_INVALIDDATA;
if (sc->slice_coding_mode == 1) {
@@ -56,7 +57,7 @@ RENAME(decode_line)(FFV1Context *f,
int diff, context, sign;
if (!(x & 1023)) {
- if (is_input_end(s, gb))
+ if (is_input_end(c, gb, ac))
return AVERROR_INVALIDDATA;
}
@@ -70,7 +71,7 @@ RENAME(decode_line)(FFV1Context *f,
av_assert2(context < p->context_count);
- if (s->ac != AC_GOLOMB_RICE) {
+ if (ac != AC_GOLOMB_RICE) {
diff = get_symbol_inline(c, p->state[context], 1);
} else {
if (context == 0 && run_mode == 0)
@@ -142,6 +143,7 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f,
int bits = s->avctx->bits_per_raw_sample > 0 ? s->avctx->bits_per_raw_sample : 8;
int offset = 1 << bits;
int transparency = f->transparency;
+ int ac = f->ac;
for (x = 0; x < 4; x++) {
sample[x][0] = RENAME(sc->sample_buffer) + x * 2 * (w + 6) + 3;
@@ -163,9 +165,9 @@ static int RENAME(decode_rgb_frame)(FFV1Context *f,
sample[p][1][-1]= sample[p][0][0 ];
sample[p][0][ w]= sample[p][0][w-1];
if (lbd && sc->slice_coding_mode == 0)
- ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, 9);
+ ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, 9, ac);
else
- ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, bits + (sc->slice_coding_mode != 1));
+ ret = RENAME(decode_line)(f, s, sc, gb, w, sample[p], (p + 1)/2, bits + (sc->slice_coding_mode != 1), ac);
if (ret < 0)
return ret;
}
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index fb373b598b..a6b9ac3d62 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -275,6 +275,7 @@ static int encode_plane(FFV1Context *f,
int stride, int plane_index, int pixel_stride)
{
int x, y, i, ret;
+ const int ac = f->ac;
const int ring_size = s->context_model ? 3 : 2;
int16_t *sample[3];
sc->run_index = 0;
@@ -290,7 +291,7 @@ static int encode_plane(FFV1Context *f,
if (s->bits_per_raw_sample <= 8) {
for (x = 0; x < w; x++)
sample[0][x] = src[x * pixel_stride + stride * y];
- if((ret = encode_line(f, s, sc, w, sample, plane_index, 8)) < 0)
+ if((ret = encode_line(f, s, sc, w, sample, plane_index, 8, ac)) < 0)
return ret;
} else {
if (s->packed_at_lsb) {
@@ -302,7 +303,7 @@ static int encode_plane(FFV1Context *f,
sample[0][x] = ((uint16_t*)(src + stride*y))[x] >> (16 - s->bits_per_raw_sample);
}
}
- if((ret = encode_line(f, s, sc, w, sample, plane_index, s->bits_per_raw_sample)) < 0)
+ if((ret = encode_line(f, s, sc, w, sample, plane_index, s->bits_per_raw_sample, ac)) < 0)
return ret;
}
}
@@ -1053,7 +1054,7 @@ retry:
if (f->version > 2) {
encode_slice_header(f, fs, sc);
}
- if (fs->ac == AC_GOLOMB_RICE) {
+ if (f->ac == AC_GOLOMB_RICE) {
fs->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&fs->c, f->version > 2) : 0;
init_put_bits(&sc->pb,
fs->c.bytestream_start + fs->ac_byte_count,
@@ -1085,7 +1086,7 @@ retry:
if (ret < 0) {
av_assert0(sc->slice_coding_mode == 0);
- if (fs->version < 4 || !fs->ac) {
+ if (fs->version < 4 || !f->ac) {
av_log(c, AV_LOG_ERROR, "Buffer too small\n");
return ret;
}
@@ -1210,7 +1211,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
FFV1SliceContext *sc = &f->slices[i];
int bytes;
- if (fs->ac != AC_GOLOMB_RICE) {
+ if (f->ac != AC_GOLOMB_RICE) {
bytes = ff_rac_terminate(&fs->c, 1);
} else {
flush_put_bits(&sc->pb); // FIXME: nicer padding
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 29b50637f4..9f9d658da1 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -25,7 +25,8 @@
static av_always_inline int
RENAME(encode_line)(FFV1Context *f,
FFV1Context *s, FFV1SliceContext *sc,
- int w, TYPE *sample[3], int plane_index, int bits)
+ int w, TYPE *sample[3], int plane_index, int bits,
+ int ac)
{
PlaneContext *const p = &s->plane[plane_index];
RangeCoder *const c = &s->c;
@@ -34,7 +35,7 @@ RENAME(encode_line)(FFV1Context *f,
int run_count = 0;
int run_mode = 0;
- if (s->ac != AC_GOLOMB_RICE) {
+ if (ac != AC_GOLOMB_RICE) {
if (c->bytestream_end - c->bytestream < w * 35) {
av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
return AVERROR_INVALIDDATA;
@@ -72,7 +73,7 @@ RENAME(encode_line)(FFV1Context *f,
diff = fold(diff, bits);
- if (s->ac != AC_GOLOMB_RICE) {
+ if (ac != AC_GOLOMB_RICE) {
if (s->flags & AV_CODEC_FLAG_PASS1) {
put_symbol_inline(c, p->state[context], diff, 1, s->rc_stat,
s->rc_stat2[p->quant_table_index][context]);
@@ -134,6 +135,7 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f,
int x, y, p, i;
const int ring_size = s->context_model ? 3 : 2;
TYPE *sample[4][3];
+ const int ac = f->ac;
int lbd = s->bits_per_raw_sample <= 8;
int packed = !src[1];
int bits = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8;
@@ -196,9 +198,9 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f,
sample[p][0][-1] = sample[p][1][0 ];
sample[p][1][ w] = sample[p][1][w-1];
if (lbd && sc->slice_coding_mode == 0)
- ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, 9);
+ ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, 9, ac);
else
- ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, bits + (sc->slice_coding_mode != 1));
+ ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, bits + (sc->slice_coding_mode != 1), ac);
if (ret < 0)
return ret;
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH v2 22/39] lavc/ffv1enc: stop using per-slice FFV1Context
2024-07-24 19:42 ` Michael Niedermayer
@ 2024-07-31 8:50 ` Anton Khirnov
2024-07-31 12:32 ` Michael Niedermayer
0 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-31 8:50 UTC (permalink / raw)
To: ffmpeg-devel
All remaining accesses to them are for fields that have the same value
in the main encoder context.
---
libavcodec/ffv1enc.c | 55 +++++++++++++++++------------------
libavcodec/ffv1enc_template.c | 29 +++++++++---------
2 files changed, 41 insertions(+), 43 deletions(-)
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index b861210462..23d757e5c6 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -269,14 +269,14 @@ static inline void put_vlc_symbol(PutBitContext *pb, VlcState *const state,
#define RENAME(name) name ## 32
#include "ffv1enc_template.c"
-static int encode_plane(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+static int encode_plane(FFV1Context *f, FFV1SliceContext *sc,
const uint8_t *src, int w, int h,
int stride, int plane_index, int pixel_stride)
{
int x, y, i, ret;
const int ac = f->ac;
- const int ring_size = s->context_model ? 3 : 2;
+ const int pass1 = !!(f->avctx->flags & AV_CODEC_FLAG_PASS1);
+ const int ring_size = f->context_model ? 3 : 2;
int16_t *sample[3];
sc->run_index = 0;
@@ -288,22 +288,22 @@ static int encode_plane(FFV1Context *f,
sample[0][-1]= sample[1][0 ];
sample[1][ w]= sample[1][w-1];
- if (s->bits_per_raw_sample <= 8) {
+ if (f->bits_per_raw_sample <= 8) {
for (x = 0; x < w; x++)
sample[0][x] = src[x * pixel_stride + stride * y];
- if((ret = encode_line(f, s, sc, w, sample, plane_index, 8, ac)) < 0)
+ if((ret = encode_line(f, sc, f->avctx, w, sample, plane_index, 8, ac, pass1)) < 0)
return ret;
} else {
- if (s->packed_at_lsb) {
+ if (f->packed_at_lsb) {
for (x = 0; x < w; x++) {
sample[0][x] = ((uint16_t*)(src + stride*y))[x];
}
} else {
for (x = 0; x < w; x++) {
- sample[0][x] = ((uint16_t*)(src + stride*y))[x] >> (16 - s->bits_per_raw_sample);
+ sample[0][x] = ((uint16_t*)(src + stride*y))[x] >> (16 - f->bits_per_raw_sample);
}
}
- if((ret = encode_line(f, s, sc, w, sample, plane_index, s->bits_per_raw_sample, ac)) < 0)
+ if((ret = encode_line(f, sc, f->avctx, w, sample, plane_index, f->bits_per_raw_sample, ac, pass1)) < 0)
return ret;
}
}
@@ -909,8 +909,7 @@ slices_ok:
return 0;
}
-static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
- FFV1SliceContext *sc)
+static void encode_slice_header(FFV1Context *f, FFV1SliceContext *sc)
{
RangeCoder *c = &sc->c;
uint8_t state[CONTEXT_SIZE];
@@ -943,7 +942,7 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs,
}
}
-static void choose_rct_params(FFV1Context *fs, FFV1SliceContext *sc,
+static void choose_rct_params(const FFV1Context *f, FFV1SliceContext *sc,
const uint8_t *src[3], const int stride[3], int w, int h)
{
#define NB_Y_COEFF 15
@@ -969,7 +968,7 @@ static void choose_rct_params(FFV1Context *fs, FFV1SliceContext *sc,
int stat[NB_Y_COEFF] = {0};
int x, y, i, p, best;
int16_t *sample[3];
- int lbd = fs->bits_per_raw_sample <= 8;
+ int lbd = f->bits_per_raw_sample <= 8;
for (y = 0; y < h; y++) {
int lastr=0, lastg=0, lastb=0;
@@ -1028,10 +1027,8 @@ static void choose_rct_params(FFV1Context *fs, FFV1SliceContext *sc,
static int encode_slice(AVCodecContext *c, void *arg)
{
- FFV1Context *fs = *(void **)arg;
- FFV1Context *f = fs->avctx->priv_data;
- const int si = (FFV1Context**)arg - f->slice_context;
- FFV1SliceContext *sc = &f->slices[si];
+ FFV1SliceContext *sc = arg;
+ FFV1Context *f = c->priv_data;
int width = sc->slice_width;
int height = sc->slice_height;
int x = sc->slice_x;
@@ -1047,7 +1044,7 @@ static int encode_slice(AVCodecContext *c, void *arg)
sc->slice_coding_mode = 0;
if (f->version > 3) {
- choose_rct_params(fs, sc, planes, p->linesize, width, height);
+ choose_rct_params(f, sc, planes, p->linesize, width, height);
} else {
sc->slice_rct_by_coef = 1;
sc->slice_rct_ry_coef = 1;
@@ -1057,7 +1054,7 @@ retry:
if (f->key_frame)
ff_ffv1_clear_slice_state(f, sc);
if (f->version > 2) {
- encode_slice_header(f, fs, sc);
+ encode_slice_header(f, sc);
}
if (f->ac == AC_GOLOMB_RICE) {
sc->ac_byte_count = f->version > 2 || (!x && !y) ? ff_rac_terminate(&sc->c, f->version > 2) : 0;
@@ -1072,26 +1069,26 @@ retry:
const int cx = x >> f->chroma_h_shift;
const int cy = y >> f->chroma_v_shift;
- ret = encode_plane(f, fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
+ ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 1);
if (f->chroma_planes) {
- ret |= encode_plane(f, fs, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
- ret |= encode_plane(f, fs, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
+ ret |= encode_plane(f, sc, p->data[1] + ps*cx+cy*p->linesize[1], chroma_width, chroma_height, p->linesize[1], 1, 1);
+ ret |= encode_plane(f, sc, p->data[2] + ps*cx+cy*p->linesize[2], chroma_width, chroma_height, p->linesize[2], 1, 1);
}
if (f->transparency)
- ret |= encode_plane(f, fs, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
+ ret |= encode_plane(f, sc, p->data[3] + ps*x + y*p->linesize[3], width, height, p->linesize[3], 2, 1);
} else if (c->pix_fmt == AV_PIX_FMT_YA8) {
- ret = encode_plane(f, fs, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
- ret |= encode_plane(f, fs, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
+ ret = encode_plane(f, sc, p->data[0] + ps*x + y*p->linesize[0], width, height, p->linesize[0], 0, 2);
+ ret |= encode_plane(f, sc, p->data[0] + 1 + ps*x + y*p->linesize[0], width, height, p->linesize[0], 1, 2);
} else if (f->use32bit) {
- ret = encode_rgb_frame32(f, fs, sc, planes, width, height, p->linesize);
+ ret = encode_rgb_frame32(f, sc, planes, width, height, p->linesize);
} else {
- ret = encode_rgb_frame(f, fs, sc, planes, width, height, p->linesize);
+ ret = encode_rgb_frame(f, sc, planes, width, height, p->linesize);
}
if (ret < 0) {
av_assert0(sc->slice_coding_mode == 0);
- if (fs->version < 4 || !f->ac) {
+ if (f->version < 4 || !f->ac) {
av_log(c, AV_LOG_ERROR, "Buffer too small\n");
return ret;
}
@@ -1207,8 +1204,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
sc->c.bytestream_end = sc->c.bytestream_start + len;
}
}
- avctx->execute(avctx, encode_slice, &f->slice_context[0], NULL,
- f->slice_count, sizeof(void *));
+ avctx->execute(avctx, encode_slice, f->slices, NULL,
+ f->slice_count, sizeof(*f->slices));
buf_p = pkt->data;
for (i = 0; i < f->slice_count; i++) {
diff --git a/libavcodec/ffv1enc_template.c b/libavcodec/ffv1enc_template.c
index 24dcf2a68e..bc14926ab9 100644
--- a/libavcodec/ffv1enc_template.c
+++ b/libavcodec/ffv1enc_template.c
@@ -23,10 +23,10 @@
#include "ffv1_template.c"
static av_always_inline int
-RENAME(encode_line)(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+RENAME(encode_line)(FFV1Context *f, FFV1SliceContext *sc,
+ void *logctx,
int w, TYPE *sample[3], int plane_index, int bits,
- int ac)
+ int ac, int pass1)
{
PlaneContext *const p = &sc->plane[plane_index];
RangeCoder *const c = &sc->c;
@@ -37,12 +37,12 @@ RENAME(encode_line)(FFV1Context *f,
if (ac != AC_GOLOMB_RICE) {
if (c->bytestream_end - c->bytestream < w * 35) {
- av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
+ av_log(logctx, AV_LOG_ERROR, "encoded frame too large\n");
return AVERROR_INVALIDDATA;
}
} else {
if (put_bytes_left(&sc->pb, 0) < w * 4) {
- av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n");
+ av_log(logctx, AV_LOG_ERROR, "encoded frame too large\n");
return AVERROR_INVALIDDATA;
}
}
@@ -74,7 +74,7 @@ RENAME(encode_line)(FFV1Context *f,
diff = fold(diff, bits);
if (ac != AC_GOLOMB_RICE) {
- if (s->flags & AV_CODEC_FLAG_PASS1) {
+ if (pass1) {
put_symbol_inline(c, p->state[context], diff, 1, sc->rc_stat,
sc->rc_stat2[p->quant_table_index][context]);
} else {
@@ -104,7 +104,7 @@ RENAME(encode_line)(FFV1Context *f,
}
}
- ff_dlog(s->avctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
+ ff_dlog(logctx, "count:%d index:%d, mode:%d, x:%d pos:%d\n",
run_count, run_index, run_mode, x,
(int)put_bits_count(&sc->pb));
@@ -127,18 +127,18 @@ RENAME(encode_line)(FFV1Context *f,
return 0;
}
-static int RENAME(encode_rgb_frame)(FFV1Context *f,
- FFV1Context *s, FFV1SliceContext *sc,
+static int RENAME(encode_rgb_frame)(FFV1Context *f, FFV1SliceContext *sc,
const uint8_t *src[4],
int w, int h, const int stride[4])
{
int x, y, p, i;
- const int ring_size = s->context_model ? 3 : 2;
+ const int ring_size = f->context_model ? 3 : 2;
TYPE *sample[4][3];
const int ac = f->ac;
- int lbd = s->bits_per_raw_sample <= 8;
+ const int pass1 = !!(f->avctx->flags & AV_CODEC_FLAG_PASS1);
+ int lbd = f->bits_per_raw_sample <= 8;
int packed = !src[1];
- int bits = s->bits_per_raw_sample > 0 ? s->bits_per_raw_sample : 8;
+ int bits = f->bits_per_raw_sample > 0 ? f->bits_per_raw_sample : 8;
int offset = 1 << bits;
int transparency = f->transparency;
int packed_size = (3 + transparency)*2;
@@ -198,9 +198,10 @@ static int RENAME(encode_rgb_frame)(FFV1Context *f,
sample[p][0][-1] = sample[p][1][0 ];
sample[p][1][ w] = sample[p][1][w-1];
if (lbd && sc->slice_coding_mode == 0)
- ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, 9, ac);
+ ret = RENAME(encode_line)(f, sc, f->avctx, w, sample[p], (p + 1) / 2, 9, ac, pass1);
else
- ret = RENAME(encode_line)(f, s, sc, w, sample[p], (p + 1) / 2, bits + (sc->slice_coding_mode != 1), ac);
+ ret = RENAME(encode_line)(f, sc, f->avctx, w, sample[p], (p + 1) / 2,
+ bits + (sc->slice_coding_mode != 1), ac, pass1);
if (ret < 0)
return ret;
}
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 33/39] lavc: convert frame threading to the receive_frame() pattern
2024-07-24 18:44 ` Michael Niedermayer
@ 2024-07-31 11:26 ` Anton Khirnov
2024-07-31 12:59 ` Michael Niedermayer
0 siblings, 1 reply; 110+ messages in thread
From: Anton Khirnov @ 2024-07-31 11:26 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Michael Niedermayer (2024-07-24 20:44:50)
> On Tue, Jul 16, 2024 at 07:11:48PM +0200, Anton Khirnov wrote:
> > Reorganize the code such that the frame threading code does not call the
> > decoders directly, but instead calls back into the generic decoding
> > code. This avoids duplicating the logic that wraps the decoder
> > invocation and allows receive_frame()-based decoders to use frame
> > threading.
> >
> > Further work by Timo Rothenpieler <timo@rothenpieler.org>.
> > ---
> > libavcodec/avcodec.c | 9 +-
> > libavcodec/avcodec_internal.h | 25 +--
> > libavcodec/decode.c | 40 +++--
> > libavcodec/internal.h | 7 +
> > libavcodec/pthread_frame.c | 278 +++++++++++++++++++++-------------
> > 5 files changed, 235 insertions(+), 124 deletions(-)
>
> this (frm your recive_frame branch) breaks:
Then I will need to reintroduce some form of patch 28 - ideally its
second iteration split into 3 patches, as then the ownership semantics
of slice_damaged is much simpler.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 17/39] lavc/ffv1: always use the main context values of ac
2024-07-31 8:33 ` [FFmpeg-devel] [PATCH v2 " Anton Khirnov
@ 2024-07-31 12:20 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-31 12:20 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 680 bytes --]
On Wed, Jul 31, 2024 at 10:33:09AM +0200, Anton Khirnov wrote:
> It cannot change between slices.
> ---
> libavcodec/ffv1.c | 6 +++---
> libavcodec/ffv1dec.c | 19 +++++++++----------
> libavcodec/ffv1dec_template.c | 14 ++++++++------
> libavcodec/ffv1enc.c | 11 ++++++-----
> libavcodec/ffv1enc_template.c | 12 +++++++-----
> 5 files changed, 33 insertions(+), 29 deletions(-)
probably ok assuming benchmarks favor this
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
While the State exists there can be no freedom; when there is freedom there
will be no State. -- Vladimir Lenin
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 22/39] lavc/ffv1enc: stop using per-slice FFV1Context
2024-07-31 8:50 ` [FFmpeg-devel] [PATCH v2 " Anton Khirnov
@ 2024-07-31 12:32 ` Michael Niedermayer
0 siblings, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-31 12:32 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 643 bytes --]
On Wed, Jul 31, 2024 at 10:50:11AM +0200, Anton Khirnov wrote:
> All remaining accesses to them are for fields that have the same value
> in the main encoder context.
> ---
> libavcodec/ffv1enc.c | 55 +++++++++++++++++------------------
> libavcodec/ffv1enc_template.c | 29 +++++++++---------
> 2 files changed, 41 insertions(+), 43 deletions(-)
fine if benchmarks dont disfavour this
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Some people wanted to paint the bikeshed green, some blue and some pink.
People argued and fought, when they finally agreed, only rust was left.
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 33/39] lavc: convert frame threading to the receive_frame() pattern
2024-07-31 11:26 ` Anton Khirnov
@ 2024-07-31 12:59 ` Michael Niedermayer
2024-08-01 14:33 ` [FFmpeg-devel] [PATCH] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Michael Niedermayer @ 2024-07-31 12:59 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2071 bytes --]
On Wed, Jul 31, 2024 at 01:26:23PM +0200, Anton Khirnov wrote:
> Quoting Michael Niedermayer (2024-07-24 20:44:50)
> > On Tue, Jul 16, 2024 at 07:11:48PM +0200, Anton Khirnov wrote:
> > > Reorganize the code such that the frame threading code does not call the
> > > decoders directly, but instead calls back into the generic decoding
> > > code. This avoids duplicating the logic that wraps the decoder
> > > invocation and allows receive_frame()-based decoders to use frame
> > > threading.
> > >
> > > Further work by Timo Rothenpieler <timo@rothenpieler.org>.
> > > ---
> > > libavcodec/avcodec.c | 9 +-
> > > libavcodec/avcodec_internal.h | 25 +--
> > > libavcodec/decode.c | 40 +++--
> > > libavcodec/internal.h | 7 +
> > > libavcodec/pthread_frame.c | 278 +++++++++++++++++++++-------------
> > > 5 files changed, 235 insertions(+), 124 deletions(-)
> >
> > this (frm your recive_frame branch) breaks:
>
> Then I will need to reintroduce some form of patch 28 - ideally its
> second iteration split into 3 patches, as then the ownership semantics
> of slice_damaged is much simpler.
simple is good
race is bad
Some more advanced EC code would be cool, if such a path would stay possible
I mean something that could maybe do a 2nd pass and fill in damaged slices
using both past and future non-damaged slices
(i mean not just for ffv1 but all codecs)
so the codec itself would do simply EC itself not depending on much surrounding
state.
Bit it then could export side data about what areas are damaged and have something
in a 2nd pass go over these areas and fill them in with more advanaced stuff
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Any man who breaks a law that conscience tells him is unjust and willingly
accepts the penalty by staying in jail in order to arouse the conscience of
the community on the injustice of the law is at that moment expressing the
very highest respect for law. - Martin Luther King Jr
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 27/39] lavc/ffv1: change FFV1SliceContext.plane into a RefStruct object
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 27/39] lavc/ffv1: change FFV1SliceContext.plane into a RefStruct object Anton Khirnov
2024-07-24 19:53 ` Michael Niedermayer
@ 2024-08-01 8:17 ` Anton Khirnov
1 sibling, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-08-01 8:17 UTC (permalink / raw)
To: FFmpeg development discussions and patches
pushed all patches up to this one, as they have been approved.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* [FFmpeg-devel] [PATCH] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged
2024-07-31 12:59 ` Michael Niedermayer
@ 2024-08-01 14:33 ` Anton Khirnov
2024-08-06 4:39 ` Anton Khirnov
2024-08-09 21:26 ` Michael Niedermayer
0 siblings, 2 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-08-01 14:33 UTC (permalink / raw)
To: ffmpeg-devel
That variable is shared between frame threads in the same defective way
described in the previous commit. Fix it by adding a RefStruct-managed
arrays of flags that is propagated across frame threads in the standard
manner.
Remove now-unused FFV1Context.fsrc
---
This version keeps the ER code where it is, after all slices are
decoded.
It is a bit more complex though.
libavcodec/ffv1.c | 2 ++
libavcodec/ffv1.h | 14 ++++++++++++-
libavcodec/ffv1dec.c | 47 ++++++++++++++++++++++++++++----------------
3 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c
index 9c219b5ddb..333fb3d79b 100644
--- a/libavcodec/ffv1.c
+++ b/libavcodec/ffv1.c
@@ -214,6 +214,8 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx)
ff_refstruct_unref(&sc->plane);
}
+ ff_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]);
diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index edc3f6aef0..9aa0452922 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -118,7 +118,6 @@ typedef struct FFV1Context {
int64_t picture_number;
int key_frame;
ProgressFrame picture, last_picture;
- struct FFV1Context *fsrc;
const AVFrame *cur_enc_frame;
int plane_count;
@@ -148,6 +147,19 @@ typedef struct FFV1Context {
int num_h_slices;
FFV1SliceContext *slices;
+ /* RefStruct object, per-slice damage flags shared between frame threads.
+ *
+ * After a frame thread marks some slice as finished with
+ * ff_progress_frame_report(), the corresponding array element must not be
+ * accessed by this thread anymore, as from then on it is owned by the next
+ * thread.
+ */
+ uint8_t *slice_damaged;
+ /* Frame damage flag, used to delay announcing progress, since ER is
+ * applied after all the slices are decoded.
+ * NOT shared between frame threads.
+ */
+ uint8_t frame_damaged;
} FFV1Context;
int ff_ffv1_common_init(AVCodecContext *avctx);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 0b0ae956a6..415c66be63 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -254,6 +254,16 @@ static int decode_slice_header(const FFV1Context *f,
return 0;
}
+static void slice_set_damaged(FFV1Context *f, FFV1SliceContext *sc)
+{
+ sc->slice_damaged = 1;
+
+ // only set this for frame threading, as for slice threading its value is
+ // not used and setting it would be a race
+ if (f->avctx->active_thread_type & FF_THREAD_FRAME)
+ f->frame_damaged = 1;
+}
+
static int decode_slice(AVCodecContext *c, void *arg)
{
FFV1Context *f = c->priv_data;
@@ -264,15 +274,11 @@ static int decode_slice(AVCodecContext *c, void *arg)
const int si = sc - f->slices;
GetBitContext gb;
- if (f->fsrc && !(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
+ if (!(p->flags & AV_FRAME_FLAG_KEY) && f->last_picture.f)
ff_progress_frame_await(&f->last_picture, si);
- if (f->fsrc) {
- const FFV1SliceContext *scsrc = &f->fsrc->slices[si];
-
- if (!(p->flags & AV_FRAME_FLAG_KEY))
- sc->slice_damaged |= scsrc->slice_damaged;
- }
+ if (f->slice_damaged[si])
+ slice_set_damaged(f, sc);
sc->slice_rct_by_coef = 1;
sc->slice_rct_ry_coef = 1;
@@ -282,7 +288,7 @@ static int decode_slice(AVCodecContext *c, void *arg)
return AVERROR(ENOMEM);
if (decode_slice_header(f, sc, p) < 0) {
sc->slice_x = sc->slice_y = sc->slice_height = sc->slice_width = 0;
- sc->slice_damaged = 1;
+ slice_set_damaged(f, sc);
return AVERROR_INVALIDDATA;
}
}
@@ -344,11 +350,12 @@ static int decode_slice(AVCodecContext *c, void *arg)
v = sc->c.bytestream_end - sc->c.bytestream - 2 - 5*f->ec;
if (v) {
av_log(f->avctx, AV_LOG_ERROR, "bytestream end mismatching by %d\n", v);
- sc->slice_damaged = 1;
+ slice_set_damaged(f, sc);
}
}
- ff_progress_frame_report(&f->picture, si);
+ if ((c->active_thread_type & FF_THREAD_FRAME) && !f->frame_damaged)
+ ff_progress_frame_report(&f->picture, si);
return 0;
}
@@ -768,11 +775,14 @@ static int read_header(FFV1Context *f)
return AVERROR_INVALIDDATA;
}
+ ff_refstruct_unref(&f->slice_damaged);
+ f->slice_damaged = ff_refstruct_allocz(f->slice_count * sizeof(*f->slice_damaged));
+ if (!f->slice_damaged)
+ return AVERROR(ENOMEM);
+
for (int j = 0; j < f->slice_count; j++) {
FFV1SliceContext *sc = &f->slices[j];
- sc->slice_damaged = 0;
-
if (f->version == 2) {
int sx = get_symbol(c, state, 0);
int sy = get_symbol(c, state, 0);
@@ -857,6 +867,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
f->avctx = avctx;
+ f->frame_damaged = 0;
ff_init_range_decoder(c, buf, buf_size);
ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8);
@@ -920,6 +931,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
int trailer = 3 + 5*!!f->ec;
int v;
+ sc->slice_damaged = 0;
+
if (i || f->version > 2) {
if (trailer > buf_p - buf) v = INT_MAX;
else v = AV_RB24(buf_p-trailer) + trailer;
@@ -943,7 +956,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
} else {
av_log(f->avctx, AV_LOG_ERROR, "\n");
}
- sc->slice_damaged = 1;
+ slice_set_damaged(f, sc);
}
if (avctx->debug & FF_DEBUG_PICT_INFO) {
av_log(avctx, AV_LOG_DEBUG, "slice %d, CRC: 0x%08"PRIX32"\n", i, AV_RB32(buf_p + v - 4));
@@ -988,6 +1001,8 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *rframe,
avctx->pix_fmt,
sc->slice_width,
sc->slice_height);
+
+ f->slice_damaged[i] = 1;
}
}
ff_progress_frame_report(&f->picture, INT_MAX);
@@ -1039,8 +1054,6 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
FFV1SliceContext *sc = &fdst->slices[i];
const FFV1SliceContext *sc0 = &fsrc->slices[i];
- sc->slice_damaged = sc0->slice_damaged;
-
ff_refstruct_replace(&sc->plane, sc0->plane);
if (fsrc->version < 3) {
@@ -1051,12 +1064,12 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
}
}
+ ff_refstruct_replace(&fdst->slice_damaged, fsrc->slice_damaged);
+
av_assert1(fdst->max_slice_count == fsrc->max_slice_count);
ff_progress_frame_replace(&fdst->picture, &fsrc->picture);
- fdst->fsrc = fsrc;
-
return 0;
}
#endif
--
2.43.0
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged
2024-08-01 14:33 ` [FFmpeg-devel] [PATCH] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
@ 2024-08-06 4:39 ` Anton Khirnov
2024-08-09 21:26 ` Michael Niedermayer
1 sibling, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-08-06 4:39 UTC (permalink / raw)
To: FFmpeg development discussions and patches
ping
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged
2024-08-01 14:33 ` [FFmpeg-devel] [PATCH] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
2024-08-06 4:39 ` Anton Khirnov
@ 2024-08-09 21:26 ` Michael Niedermayer
1 sibling, 0 replies; 110+ messages in thread
From: Michael Niedermayer @ 2024-08-09 21:26 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 619 bytes --]
On Thu, Aug 01, 2024 at 04:33:21PM +0200, Anton Khirnov wrote:
> That variable is shared between frame threads in the same defective way
> described in the previous commit. Fix it by adding a RefStruct-managed
> arrays of flags that is propagated across frame threads in the standard
> manner.
>
> Remove now-unused FFV1Context.fsrc
> ---
> This version keeps the ER code where it is, after all slices are
> decoded.
> It is a bit more complex though.
LGTM
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
You can kill me, but you cannot change the truth.
[-- 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 37/39] lavc/hevcdec: use a ContainerFifo to hold frames scheduled for output
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 37/39] lavc/hevcdec: use a ContainerFifo to hold frames scheduled for output Anton Khirnov
@ 2024-08-09 23:52 ` Andreas Rheinhardt
2024-08-12 12:28 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Andreas Rheinhardt @ 2024-08-09 23:52 UTC (permalink / raw)
To: ffmpeg-devel
Anton Khirnov:
> Instead of a single AVFrame.
>
> Will be useful in future commits, where we will want to produce multiple
> output frames for a single coded frame.
> ---
> libavcodec/Makefile | 2 +-
> libavcodec/hevc/hevcdec.c | 30 ++++++++++++++++++++----------
> libavcodec/hevc/hevcdec.h | 5 +++--
> libavcodec/hevc/refs.c | 11 +++--------
> 4 files changed, 27 insertions(+), 21 deletions(-)
>
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 771e2b597e..e67b729bd3 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -431,7 +431,7 @@ OBJS-$(CONFIG_HCA_DECODER) += hcadec.o
> OBJS-$(CONFIG_HCOM_DECODER) += hcom.o
> OBJS-$(CONFIG_HDR_DECODER) += hdrdec.o
> OBJS-$(CONFIG_HDR_ENCODER) += hdrenc.o
> -OBJS-$(CONFIG_HEVC_DECODER) += aom_film_grain.o h274.o
> +OBJS-$(CONFIG_HEVC_DECODER) += aom_film_grain.o h274.o container_fifo.o
> OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
> OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
> OBJS-$(CONFIG_HEVC_D3D12VA_ENCODER) += d3d12va_encode_hevc.o h265_profile_level.o \
> diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
> index fc87169a1a..5e28bfe54e 100644
> --- a/libavcodec/hevc/hevcdec.c
> +++ b/libavcodec/hevc/hevcdec.c
> @@ -3006,6 +3006,10 @@ static int hevc_frame_start(HEVCContext *s)
> s->cur_frame->frame_grain->height = s->cur_frame->f->height;
> if ((ret = ff_thread_get_buffer(s->avctx, s->cur_frame->frame_grain, 0)) < 0)
> goto fail;
> +
> + ret = av_frame_copy_props(s->cur_frame->frame_grain, s->cur_frame->f);
> + if (ret < 0)
> + goto fail;
> }
>
> s->cur_frame->f->pict_type = 3 - s->sh.slice_type;
> @@ -3013,8 +3017,7 @@ static int hevc_frame_start(HEVCContext *s)
> if (!IS_IRAP(s))
> ff_hevc_bump_frame(s);
>
> - av_frame_unref(s->output_frame);
> - ret = ff_hevc_output_frame(s, s->output_frame, 0);
> + ret = ff_hevc_output_frame(s, 0);
> if (ret < 0)
> goto fail;
>
> @@ -3411,13 +3414,16 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
> uint8_t *sd;
> size_t sd_size;
>
> + if (ff_container_fifo_can_read(s->output_fifo))
> + goto do_output;
> +
> av_packet_unref(avpkt);
> ret = ff_decode_get_packet(avctx, avpkt);
> if (ret == AVERROR_EOF) {
> - ret = ff_hevc_output_frame(s, frame, 1);
> + ret = ff_hevc_output_frame(s, 1);
> if (ret < 0)
> return ret;
> - return (ret > 0) ? 0 : AVERROR_EOF;
> + goto do_output;
> } else if (ret < 0)
> return ret;
>
> @@ -3442,12 +3448,15 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
> if (ret < 0)
> return ret;
>
> - if (s->output_frame->buf[0]) {
> - av_frame_move_ref(frame, s->output_frame);
> +do_output:
> + if (ff_container_fifo_read(s->output_fifo, frame) >= 0) {
This looks like it adds a (several) av_frame_move_ref() for the common
case in which we only have one output frame. Can't this be avoided?
> + if (!(avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
> + av_frame_remove_side_data(frame, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
> +
> return 0;
> }
>
> - return AVERROR(EAGAIN);
> + return avci->draining ? AVERROR_EOF : AVERROR(EAGAIN);
> }
>
> static int hevc_ref_frame(HEVCFrame *dst, const HEVCFrame *src)
> @@ -3499,7 +3508,8 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx)
> av_freep(&s->sao_pixel_buffer_h[i]);
> av_freep(&s->sao_pixel_buffer_v[i]);
> }
> - av_frame_free(&s->output_frame);
> +
> + ff_container_fifo_free(&s->output_fifo);
>
> for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
> ff_hevc_unref_frame(&s->DPB[i], ~0);
> @@ -3537,8 +3547,8 @@ static av_cold int hevc_init_context(AVCodecContext *avctx)
> s->local_ctx[0].logctx = avctx;
> s->local_ctx[0].common_cabac_state = &s->cabac;
>
> - s->output_frame = av_frame_alloc();
> - if (!s->output_frame)
> + s->output_fifo = ff_container_fifo_alloc_avframe(0);
> + if (!s->output_fifo)
> return AVERROR(ENOMEM);
>
> for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
> diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
> index da4d83e661..f2705b8de2 100644
> --- a/libavcodec/hevc/hevcdec.h
> +++ b/libavcodec/hevc/hevcdec.h
> @@ -31,6 +31,7 @@
> #include "libavcodec/avcodec.h"
> #include "libavcodec/bswapdsp.h"
> #include "libavcodec/cabac.h"
> +#include "libavcodec/container_fifo.h"
Unnecessary. Just use struct ContainerFifo* below.
> #include "libavcodec/dovi_rpu.h"
> #include "libavcodec/get_bits.h"
> #include "libavcodec/h2645_parse.h"
> @@ -457,7 +458,7 @@ typedef struct HEVCContext {
> /** 1 if the independent slice segment header was successfully parsed */
> uint8_t slice_initialized;
>
> - AVFrame *output_frame;
> + ContainerFifo *output_fifo;
> uint8_t *sao_pixel_buffer_h[3];
> uint8_t *sao_pixel_buffer_v[3];
>
> @@ -636,7 +637,7 @@ static av_always_inline int ff_hevc_nal_is_nonref(enum HEVCNALUnitType type)
> * Find next frame in output order and put a reference to it in frame.
> * @return 1 if a frame was output, 0 otherwise
> */
> -int ff_hevc_output_frame(HEVCContext *s, AVFrame *frame, int flush);
> +int ff_hevc_output_frame(HEVCContext *s, int flush);
>
> void ff_hevc_bump_frame(HEVCContext *s);
>
> diff --git a/libavcodec/hevc/refs.c b/libavcodec/hevc/refs.c
> index 48fc4d27da..44ee7c837a 100644
> --- a/libavcodec/hevc/refs.c
> +++ b/libavcodec/hevc/refs.c
> @@ -171,7 +171,7 @@ static void unref_missing_refs(HEVCContext *s)
> }
> }
>
> -int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush)
> +int ff_hevc_output_frame(HEVCContext *s, int flush)
> {
> if (IS_IRAP(s) && s->no_rasl_output_flag == 1) {
> const static int mask = HEVC_FRAME_FLAG_BUMPING | HEVC_FRAME_FLAG_OUTPUT;
> @@ -211,7 +211,8 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush)
> if (nb_output) {
> HEVCFrame *frame = &s->DPB[min_idx];
>
> - ret = av_frame_ref(out, frame->needs_fg ? frame->frame_grain : frame->f);
> + ret = ff_container_fifo_write(s->output_fifo,
> + frame->needs_fg ? frame->frame_grain : frame->f);
> if (frame->flags & HEVC_FRAME_FLAG_BUMPING)
> ff_hevc_unref_frame(frame, HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_BUMPING);
> else
> @@ -219,12 +220,6 @@ int ff_hevc_output_frame(HEVCContext *s, AVFrame *out, int flush)
> if (ret < 0)
> return ret;
>
> - if (frame->needs_fg && (ret = av_frame_copy_props(out, frame->f)) < 0)
> - return ret;
> -
> - if (!(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN))
> - av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS);
> -
> av_log(s->avctx, AV_LOG_DEBUG,
> "Output frame with POC %d.\n", frame->poc);
> return 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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 36/39] lavc: add private container FIFO API
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 36/39] lavc: add private container FIFO API Anton Khirnov
@ 2024-08-10 0:09 ` Andreas Rheinhardt
2024-08-12 12:14 ` Anton Khirnov
0 siblings, 1 reply; 110+ messages in thread
From: Andreas Rheinhardt @ 2024-08-10 0:09 UTC (permalink / raw)
To: ffmpeg-devel
Anton Khirnov:
> It provides a FIFO for "container" objects like AVFrame/AVPacket and
> features an integrated FFRefStructPool-based pool to avoid allocating an
> freeing them repeatedly.
> ---
> libavcodec/container_fifo.c | 195 ++++++++++++++++++++++++++++++++++++
> libavcodec/container_fifo.h | 87 ++++++++++++++++
> 2 files changed, 282 insertions(+)
> create mode 100644 libavcodec/container_fifo.c
> create mode 100644 libavcodec/container_fifo.h
>
> diff --git a/libavcodec/container_fifo.c b/libavcodec/container_fifo.c
> new file mode 100644
> index 0000000000..86ed15627b
> --- /dev/null
> +++ b/libavcodec/container_fifo.c
> @@ -0,0 +1,195 @@
> +/*
> + * 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/error.h"
> +#include "libavutil/fifo.h"
> +#include "libavutil/frame.h"
> +#include "libavutil/mem.h"
> +
> +#include "container_fifo.h"
> +#include "refstruct.h"
> +
> +struct ContainerFifo {
> + AVFifo *fifo;
> + FFRefStructPool *pool;
> +
> + void* (*container_alloc)(void);
> + void (*container_reset)(void *obj);
> + void (*container_free) (void *obj);
> + int (*fifo_write) (void *dst, void *src);
> + int (*fifo_read) (void *dst, void *src);
> +
> +};
> +
> +static int container_fifo_init_entry(FFRefStructOpaque opaque, void *obj)
> +{
> + ContainerFifo *cf = opaque.nc;
> + void **pobj = obj;
> +
> + *pobj = cf->container_alloc();
> + if (!*pobj)
> + return AVERROR(ENOMEM);
> +
> + return 0;
> +}
> +
> +static void container_fifo_reset_entry(FFRefStructOpaque opaque, void *obj)
> +{
> + ContainerFifo *cf = opaque.nc;
> + cf->container_reset(*(void**)obj);
> +}
> +
> +static void container_fifo_free_entry(FFRefStructOpaque opaque, void *obj)
> +{
> + ContainerFifo *cf = opaque.nc;
> + cf->container_free(*(void**)obj);
> +}
container_fifo_(init|reset|free)_entry seem unnecessary if you simply
expected the user to already provide a RefStruct-compatible callback.
> +
> +ContainerFifo*
> +ff_container_fifo_alloc(void* (*container_alloc)(void),
> + void (*container_reset)(void *obj),
> + void (*container_free) (void *obj),
> + int (*fifo_write) (void *dst, void *src),
> + int (*fifo_read) (void *dst, void *src))
> +{
> + ContainerFifo *cf;
> +
> + cf = av_mallocz(sizeof(*cf));
> + if (!cf)
> + return NULL;
> +
> + cf->container_alloc = container_alloc;
> + cf->container_reset = container_reset;
> + cf->container_free = container_free;
> + cf->fifo_write = fifo_write;
> + cf->fifo_read = fifo_read;
> +
> + cf->fifo = av_fifo_alloc2(1, sizeof(void*), AV_FIFO_FLAG_AUTO_GROW);
> + if (!cf->fifo)
> + goto fail;
> +
> + cf->pool = ff_refstruct_pool_alloc_ext(sizeof(void*), 0, cf,
> + container_fifo_init_entry,
> + container_fifo_reset_entry,
> + container_fifo_free_entry,
> + NULL);
> + if (!cf->pool)
> + goto fail;
> +
> + return cf;
> +fail:
> + ff_container_fifo_free(&cf);
> + return NULL;
> +}
> +
> +void ff_container_fifo_free(ContainerFifo **pcf)
> +{
> + ContainerFifo *cf;
> +
> + if (!*pcf)
> + return;
> +
> + cf = *pcf;
> +
> + if (cf->fifo) {
> + void *obj;
> + while (av_fifo_read(cf->fifo, &obj, 1) >= 0)
> + ff_refstruct_unref(&obj);
> + av_fifo_freep2(&cf->fifo);
> + }
> +
> + ff_refstruct_pool_uninit(&cf->pool);
> +
> + av_freep(pcf);
> +}
> +
> +int ff_container_fifo_read(ContainerFifo *cf, void *obj)
> +{
> + void **psrc;
> + int ret;
> +
> + ret = av_fifo_read(cf->fifo, &psrc, 1);
> + if (ret < 0)
> + return ret;
> +
> + ret = cf->fifo_read(obj, *psrc);
> + ff_refstruct_unref(&psrc);
> +
> + return ret;
> +}
> +
> +int ff_container_fifo_write(ContainerFifo *cf, void *obj)
> +{
> + void **pdst;
> + int ret;
> +
> + pdst = ff_refstruct_pool_get(cf->pool);
> + if (!pdst)
> + return AVERROR(ENOMEM);
> +
> + ret = cf->fifo_write(*pdst, obj);
This API design presumes that one never one to "move" an object into the
fifo. This need not be true at all (indeed, the reference from the
frame_grain frame could be directly moved; it is not used for the
decoding process).
> + if (ret < 0)
> + goto fail;
> +
> + ret = av_fifo_write(cf->fifo, &pdst, 1);
> + if (ret < 0)
> + goto fail;
> +
> + return 0;
> +fail:
> + ff_refstruct_unref(&pdst);
> + return ret;
> +}
> +
> +size_t ff_container_fifo_can_read(ContainerFifo *cf)
> +{
> + return av_fifo_can_read(cf->fifo);
> +}
> +
> +static void* frame_alloc(void)
Inconsistent placement of *
> +{
> + return av_frame_alloc();
> +}
> +
> +static void frame_reset(void *obj)
> +{
> + av_frame_unref(obj);
> +}
> +
> +static void frame_free(void *obj)
> +{
> + AVFrame *frame = obj;
> + av_frame_free(&frame);
> +}
> +
> +static int frame_ref(void *dst, void *src)
> +{
> + return av_frame_ref(dst, src);
> +}
> +
> +static int frame_move_ref(void *dst, void *src)
> +{
> + av_frame_move_ref(dst, src);
> + return 0;
> +}
> +
> +ContainerFifo *ff_container_fifo_alloc_avframe(unsigned flags)
> +{
> + return ff_container_fifo_alloc(frame_alloc, frame_reset, frame_free,
> + frame_ref, frame_move_ref);
> +}
> diff --git a/libavcodec/container_fifo.h b/libavcodec/container_fifo.h
> new file mode 100644
> index 0000000000..75a8f9e86b
> --- /dev/null
> +++ b/libavcodec/container_fifo.h
> @@ -0,0 +1,87 @@
> +/*
> + * 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_CONTAINER_FIFO_H
> +#define AVCODEC_CONTAINER_FIFO_H
> +
> +/**
> + * ContainerFifo is a FIFO for "containers" - dynamically allocated reusable
> + * structs (e.g. AVFrame or AVPacket). ContainerFifo uses an internal pool of
> + * such containers to avoid allocating and freeing them repeatedly.
> + */
> +typedef struct ContainerFifo ContainerFifo;
> +
> +/**
> + * Allocate a new ContainerFifo for the container type defined by provided
> + * callbacks.
> + *
> + * @param container_alloc allocate a new container instance and return a pointer
> + * to it, or NULL on failure
> + * @param container_reset reset the provided container instance to a clean state
> + * @param container_free free the provided container instance
> + * @param fifo_write transfer the contents of src to dst, where src is a
> + * container instance provided to ff_container_fifo_write()
> + * @param fifo_read transfer the contents of src to dst in other cases
> + *
> + * @note fifo_read() and fifo_write() are different parameters in order to allow
> + * fifo_write() implementations that make a new reference in dst, leaving
> + * src untouched (see e.g. ff_container_fifo_alloc_avframe())
> + */
> +ContainerFifo*
> +ff_container_fifo_alloc(void* (*container_alloc)(void),
> + void (*container_reset)(void *obj),
> + void (*container_free) (void *obj),
> + int (*fifo_write) (void *dst, void *src),
> + int (*fifo_read) (void *dst, void *src));
> +
> +/**
> + * Allocate a ContainerFifo instance for AVFrames.
> + * Note that ff_container_fifo_write() will call av_frame_ref() on src, making a
> + * new reference in dst and leaving src untouched.
> + *
> + * @param flags unused currently
> + */
> +ContainerFifo *ff_container_fifo_alloc_avframe(unsigned flags);
> +
> +/**
> + * Free a ContainerFifo and everything in it.
> + */
> +void ff_container_fifo_free(ContainerFifo **pf);
> +
> +/**
> + * Write the contents of obj to the FIFO.
> + *
> + * The fifo_write() callback previously provided to ff_container_fifo_alloc()
> + * will be called with obj as src in order to perform the actual transfer.
> + */
> +int ff_container_fifo_write(ContainerFifo *pf, void *obj);
> +
> +/**
> + * Read the next available object from the FIFO into obj.
> + *
> + * The fifo_read() callback previously provided to ff_container_fifo_alloc()
> + * will be called with obj as dst in order to perform the actual transfer.
> + */
> +int ff_container_fifo_read(ContainerFifo *pf, void *obj);
> +
> +/**
> + * @return number of objects available for reading
> + */
> +size_t ff_container_fifo_can_read(ContainerFifo *pf);
> +
> +#endif // AVCODEC_CONTAINER_FIFO_H
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 36/39] lavc: add private container FIFO API
2024-08-10 0:09 ` Andreas Rheinhardt
@ 2024-08-12 12:14 ` Anton Khirnov
0 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-08-12 12:14 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Andreas Rheinhardt (2024-08-10 02:09:19)
> Anton Khirnov:
> > +static int container_fifo_init_entry(FFRefStructOpaque opaque, void *obj)
> > +{
> > + ContainerFifo *cf = opaque.nc;
> > + void **pobj = obj;
> > +
> > + *pobj = cf->container_alloc();
> > + if (!*pobj)
> > + return AVERROR(ENOMEM);
> > +
> > + return 0;
> > +}
> > +
> > +static void container_fifo_reset_entry(FFRefStructOpaque opaque, void *obj)
> > +{
> > + ContainerFifo *cf = opaque.nc;
> > + cf->container_reset(*(void**)obj);
> > +}
> > +
> > +static void container_fifo_free_entry(FFRefStructOpaque opaque, void *obj)
> > +{
> > + ContainerFifo *cf = opaque.nc;
> > + cf->container_free(*(void**)obj);
> > +}
>
> container_fifo_(init|reset|free)_entry seem unnecessary if you simply
> expected the user to already provide a RefStruct-compatible callback.
I considered that, but decided against it as it would leak
internal implementation details to callers.
> > +int ff_container_fifo_write(ContainerFifo *cf, void *obj)
> > +{
> > + void **pdst;
> > + int ret;
> > +
> > + pdst = ff_refstruct_pool_get(cf->pool);
> > + if (!pdst)
> > + return AVERROR(ENOMEM);
> > +
> > + ret = cf->fifo_write(*pdst, obj);
>
> This API design presumes that one never one to "move" an object into the
> fifo. This need not be true at all (indeed, the reference from the
> frame_grain frame could be directly moved; it is not used for the
> decoding process).
I don't follow, how does the API preclude moving container contents in
the fifo_write() callback? Unless you mean moving the actual container?
> > + if (ret < 0)
> > + goto fail;
> > +
> > + ret = av_fifo_write(cf->fifo, &pdst, 1);
> > + if (ret < 0)
> > + goto fail;
> > +
> > + return 0;
> > +fail:
> > + ff_refstruct_unref(&pdst);
> > + return ret;
> > +}
> > +
> > +size_t ff_container_fifo_can_read(ContainerFifo *cf)
> > +{
> > + return av_fifo_can_read(cf->fifo);
> > +}
> > +
> > +static void* frame_alloc(void)
>
> Inconsistent placement of *
Fixed locally.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 37/39] lavc/hevcdec: use a ContainerFifo to hold frames scheduled for output
2024-08-09 23:52 ` Andreas Rheinhardt
@ 2024-08-12 12:28 ` Anton Khirnov
0 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-08-12 12:28 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Andreas Rheinhardt (2024-08-10 01:52:36)
> Anton Khirnov:
> > @@ -3442,12 +3448,15 @@ static int hevc_receive_frame(AVCodecContext *avctx, AVFrame *frame)
> > if (ret < 0)
> > return ret;
> >
> > - if (s->output_frame->buf[0]) {
> > - av_frame_move_ref(frame, s->output_frame);
> > +do_output:
> > + if (ff_container_fifo_read(s->output_fifo, frame) >= 0) {
>
> This looks like it adds a (several) av_frame_move_ref() for the common
> case in which we only have one output frame. Can't this be avoided?
Does it? Current code has av_frame_ref() into HEVCContext.output_frame,
which is then av_frame_move_ref()'d into the actual output frame.
New code does the same, except with a few more wrappers.
> > diff --git a/libavcodec/hevc/hevcdec.h b/libavcodec/hevc/hevcdec.h
> > index da4d83e661..f2705b8de2 100644
> > --- a/libavcodec/hevc/hevcdec.h
> > +++ b/libavcodec/hevc/hevcdec.h
> > @@ -31,6 +31,7 @@
> > #include "libavcodec/avcodec.h"
> > #include "libavcodec/bswapdsp.h"
> > #include "libavcodec/cabac.h"
> > +#include "libavcodec/container_fifo.h"
>
> Unnecessary. Just use struct ContainerFifo* below.
Sure, changed locally.
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
* Re: [FFmpeg-devel] [PATCH 34/39] lavc/decode: reindent after previous commit
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 34/39] lavc/decode: reindent after previous commit Anton Khirnov
@ 2024-08-12 12:49 ` Anton Khirnov
0 siblings, 0 replies; 110+ messages in thread
From: Anton Khirnov @ 2024-08-12 12:49 UTC (permalink / raw)
To: FFmpeg development discussions and patches
pushed patches up to this one
--
Anton Khirnov
_______________________________________________
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] 110+ messages in thread
end of thread, other threads:[~2024-08-12 12:49 UTC | newest]
Thread overview: 110+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-07-16 17:11 [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 02/39] lavc/ffv1dec: declare loop variables in the loop where possible Anton Khirnov
2024-07-24 18:22 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 03/39] lavc/ffv1dec: simplify slice index calculation Anton Khirnov
2024-07-24 18:24 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 04/39] lavc/ffv1dec: drop FFV1Context.cur Anton Khirnov
2024-07-24 18:27 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 05/39] lavc/ffv1dec: drop a pointless variable in decode_slice() Anton Khirnov
2024-07-24 18:58 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 06/39] lavc/ffv1dec: move copy_fields() under HAVE_THREADS Anton Khirnov
2024-07-24 18:58 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 07/39] lavc/ffv1: add a per-slice context Anton Khirnov
2024-07-24 19:01 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 08/39] lavc/ffv1: move sample_buffer to the " Anton Khirnov
2024-07-24 19:04 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 09/39] lavc/ffv1: move run_index " Anton Khirnov
2024-07-17 22:49 ` Michael Niedermayer
2024-07-18 15:36 ` Anton Khirnov
2024-07-18 17:41 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 10/39] lavc/ffv1dec: move the bitreader to stack Anton Khirnov
2024-07-17 22:42 ` Michael Niedermayer
2024-07-18 9:08 ` Anton Khirnov
2024-07-18 14:48 ` Michael Niedermayer
2024-07-18 15:31 ` Anton Khirnov
2024-07-18 15:35 ` Paul B Mahol
2024-07-18 18:18 ` Michael Niedermayer
2024-07-20 12:15 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 11/39] lavc/ffv1enc: move bit writer to per-slice context Anton Khirnov
2024-07-24 19:07 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 12/39] lavc/ffv1: drop redundant FFV1Context.quant_table Anton Khirnov
2024-07-17 22:37 ` Michael Niedermayer
2024-07-17 23:24 ` James Almer
2024-07-18 8:22 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 13/39] lavc/ffv1: drop redundant PlaneContext.quant_table Anton Khirnov
2024-07-17 22:32 ` Michael Niedermayer
2024-07-18 8:20 ` Anton Khirnov
2024-07-18 14:31 ` Michael Niedermayer
2024-07-18 15:14 ` Anton Khirnov
2024-07-18 17:03 ` Michael Niedermayer
2024-07-18 15:31 ` Paul B Mahol
2024-07-18 15:43 ` Anton Khirnov
2024-07-18 15:47 ` Paul B Mahol
2024-07-18 17:40 ` Michael Niedermayer
2024-07-20 9:22 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 14/39] lavc/ffv1: drop write-only PlaneContext.interlace_bit_state Anton Khirnov
2024-07-24 19:12 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 15/39] lavc/ffv1: always use the main context values of plane_count/transparency Anton Khirnov
2024-07-24 19:15 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 16/39] lavc/ffv1: move FFV1Context.slice_{coding_mode, rct_.y_coef} to per-slice context Anton Khirnov
2024-07-24 19:16 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 17/39] lavc/ffv1: always use the main context values of ac Anton Khirnov
2024-07-24 19:23 ` Michael Niedermayer
2024-07-31 8:33 ` [FFmpeg-devel] [PATCH v2 " Anton Khirnov
2024-07-31 12:20 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 18/39] lavc/ffv1: move FFV1Context.plane to per-slice context Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 19/39] lavc/ffv1: move RangeCoder " Anton Khirnov
2024-07-24 19:28 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 20/39] lavc/ffv1enc: store per-slice rc_stat(2?) in FFV1SliceContext Anton Khirnov
2024-07-24 19:30 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 21/39] lavc/ffv1: move ac_byte_count to per-slice context Anton Khirnov
2024-07-24 19:31 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 22/39] lavc/ffv1enc: stop using per-slice FFV1Context Anton Khirnov
2024-07-24 19:42 ` Michael Niedermayer
2024-07-31 8:50 ` [FFmpeg-devel] [PATCH v2 " Anton Khirnov
2024-07-31 12:32 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 23/39] lavc/ffv1dec: move slice_reset_contexts to per-slice context Anton Khirnov
2024-07-24 19:44 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 24/39] lavc/ffv1dec: move slice_damaged " Anton Khirnov
2024-07-24 19:45 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 25/39] lavc/ffv1dec: stop using per-slice FFV1Context Anton Khirnov
2024-07-24 19:48 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 26/39] lavc/ffv1dec: inline copy_fields() into update_thread_context() Anton Khirnov
2024-07-24 19:48 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 27/39] lavc/ffv1: change FFV1SliceContext.plane into a RefStruct object Anton Khirnov
2024-07-24 19:53 ` Michael Niedermayer
2024-08-01 8:17 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 28/39] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
2024-07-17 20:51 ` Michael Niedermayer
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 1/3] lavc/ffv1dec: drop code handling AV_PIX_FMT_FLAG_PAL Anton Khirnov
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 2/3] lavc/ffv1: move damage handling code to decode_slice() Anton Khirnov
2024-07-22 21:14 ` Michael Niedermayer
2024-07-23 6:52 ` Anton Khirnov
2024-07-23 20:14 ` Michael Niedermayer
2024-07-23 21:02 ` Anton Khirnov
2024-07-22 9:43 ` [FFmpeg-devel] [PATCH 3/3] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 29/39] lavc/thread: move generic-layer API to avcodec_internal.h Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 30/39] lavc/internal: document the precise meaning of AVCodecInternal.draining Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 31/39] lavc/decode: wrap AV_FRAME_FLAG_DISCARD handling in a loop Anton Khirnov
2024-07-17 21:20 ` Michael Niedermayer
2024-07-18 8:14 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 32/39] lavc/decode: reindent Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 33/39] lavc: convert frame threading to the receive_frame() pattern Anton Khirnov
2024-07-24 18:44 ` Michael Niedermayer
2024-07-31 11:26 ` Anton Khirnov
2024-07-31 12:59 ` Michael Niedermayer
2024-08-01 14:33 ` [FFmpeg-devel] [PATCH] lavc/ffv1dec: fix races in accessing FFV1SliceContext.slice_damaged Anton Khirnov
2024-08-06 4:39 ` Anton Khirnov
2024-08-09 21:26 ` Michael Niedermayer
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 34/39] lavc/decode: reindent after previous commit Anton Khirnov
2024-08-12 12:49 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 35/39] lavc/hevcdec: switch to receive_frame() Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 36/39] lavc: add private container FIFO API Anton Khirnov
2024-08-10 0:09 ` Andreas Rheinhardt
2024-08-12 12:14 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 37/39] lavc/hevcdec: use a ContainerFifo to hold frames scheduled for output Anton Khirnov
2024-08-09 23:52 ` Andreas Rheinhardt
2024-08-12 12:28 ` Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 38/39] lavc/hevcdec: simplify output logic Anton Khirnov
2024-07-16 17:11 ` [FFmpeg-devel] [PATCH 39/39] lavc/hevcdec: call ff_thread_finish_setup() even if hwaccel is in use Anton Khirnov
2024-07-24 18:20 ` [FFmpeg-devel] [PATCH 01/39] tests/fate/vcodec: add vsynth tests for FFV1 version 2 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