@@ -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);
@@ -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);
@@ -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;