#include "libavutil/crc.h"
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
+#include "libavutil/timer.h"
#include "avcodec.h"
+#include "internal.h"
#include "get_bits.h"
#include "put_bits.h"
-#include "dsputil.h"
#include "rangecoder.h"
#include "golomb.h"
#include "mathops.h"
unsigned ps, i, context_count;
memset(state, 128, sizeof(state));
- av_assert0(f->version > 2);
+ if (fs->ac > 1) {
+ for (i = 1; i < 256; i++) {
+ fs->c.one_state[i] = f->state_transition[i];
+ fs->c.zero_state[256 - i] = 256 - fs->c.one_state[i];
+ }
+ }
fs->slice_x = get_symbol(c, state, 0) * f->width;
fs->slice_y = get_symbol(c, state, 0) * f->height;
ps = get_symbol(c, state, 0);
if (ps == 1) {
- f->picture.interlaced_frame = 1;
- f->picture.top_field_first = 1;
+ f->cur->interlaced_frame = 1;
+ f->cur->top_field_first = 1;
} else if (ps == 2) {
- f->picture.interlaced_frame = 1;
- f->picture.top_field_first = 0;
+ f->cur->interlaced_frame = 1;
+ f->cur->top_field_first = 0;
} else if (ps == 3) {
- f->picture.interlaced_frame = 0;
+ f->cur->interlaced_frame = 0;
+ }
+ f->cur->sample_aspect_ratio.num = get_symbol(c, state, 0);
+ f->cur->sample_aspect_ratio.den = get_symbol(c, state, 0);
+
+ if (av_image_check_sar(f->width, f->height,
+ f->cur->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 };
}
- f->picture.sample_aspect_ratio.num = get_symbol(c, state, 0);
- f->picture.sample_aspect_ratio.den = get_symbol(c, state, 0);
return 0;
}
FFV1Context *fs = *(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)->flags & PIX_FMT_PLANAR)
+ const int ps = (av_pix_fmt_desc_get(c->pix_fmt)->flags & AV_PIX_FMT_FLAG_PLANAR)
? (c->bits_per_raw_sample > 8) + 1
: 4;
- AVFrame *const p = &f->picture;
+ AVFrame *const p = f->cur;
if (f->version > 2) {
if (decode_slice_header(f, fs) < 0) {
}
if ((ret = ffv1_init_slice_state(f, fs)) < 0)
return ret;
- if (f->picture.key_frame)
+ if (f->cur->key_frame)
ffv1_clear_slice_state(f, fs);
width = fs->slice_width;
height = fs->slice_height;
memset(state, 128, sizeof(state));
if (f->version < 2) {
+ int chroma_planes, chroma_h_shift, chroma_v_shift, transparency, colorspace, bits_per_raw_sample;
unsigned v = get_symbol(c, state, 0);
if (v > 1) {
av_log(f->avctx, AV_LOG_ERROR,
get_symbol(c, state, 1) + c->one_state[i];
}
- f->colorspace = get_symbol(c, state, 0); //YUV cs type
+ colorspace = get_symbol(c, state, 0); //YUV cs type
+ bits_per_raw_sample = f->version > 0 ? get_symbol(c, state, 0) : f->avctx->bits_per_raw_sample;
+ chroma_planes = get_rac(c, state);
+ chroma_h_shift = get_symbol(c, state, 0);
+ chroma_v_shift = get_symbol(c, state, 0);
+ transparency = get_rac(c, state);
+
+ if (f->plane_count) {
+ if (colorspace != f->colorspace ||
+ bits_per_raw_sample != f->avctx->bits_per_raw_sample ||
+ chroma_planes != f->chroma_planes ||
+ chroma_h_shift != f->chroma_h_shift ||
+ chroma_v_shift != f->chroma_v_shift ||
+ transparency != f->transparency) {
+ av_log(f->avctx, AV_LOG_ERROR, "Invalid change of global parameters\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
- if (f->version > 0)
- f->avctx->bits_per_raw_sample = get_symbol(c, state, 0);
+ f->colorspace = colorspace;
+ f->avctx->bits_per_raw_sample = bits_per_raw_sample;
+ f->chroma_planes = chroma_planes;
+ f->chroma_h_shift = chroma_h_shift;
+ f->chroma_v_shift = chroma_v_shift;
+ f->transparency = transparency;
- f->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 = 2 + f->transparency;
}
return AVERROR(ENOSYS);
}
switch (f->avctx->bits_per_raw_sample) {
+ case 0:
case 8:
f->avctx->pix_fmt = AV_PIX_FMT_RGB32;
break;
fs->slice_x /= f->num_h_slices;
fs->slice_y /= f->num_v_slices;
- fs->slice_width /= f->num_h_slices - fs->slice_x;
- fs->slice_height /= f->num_v_slices - fs->slice_y;
+ fs->slice_width = fs->slice_width / f->num_h_slices - fs->slice_x;
+ fs->slice_height = fs->slice_height / f->num_v_slices - fs->slice_y;
if ((unsigned)fs->slice_width > f->width ||
(unsigned)fs->slice_height > f->height)
return AVERROR_INVALIDDATA;
ffv1_common_init(avctx);
+ f->last_picture = av_frame_alloc();
+ if (!f->last_picture)
+ return AVERROR(ENOMEM);
+
if (avctx->extradata && (ret = read_extra_header(f)) < 0)
return ret;
}
static int ffv1_decode_frame(AVCodecContext *avctx, void *data,
- int *data_size, AVPacket *avpkt)
+ int *got_frame, AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size;
FFV1Context *f = avctx->priv_data;
RangeCoder *const c = &f->slice_context[0]->c;
- AVFrame *const p = &f->picture;
int i, ret;
uint8_t keystate = 128;
const uint8_t *buf_p;
+ AVFrame *const p = data;
- AVFrame *picture = data;
-
- /* release previously stored data */
- if (p->data[0])
- avctx->release_buffer(avctx, p);
+ f->cur = p;
ff_init_range_decoder(c, buf, buf_size);
ff_build_rac_states(c, 0.05 * (1LL << 32), 256 - 8);
} else {
if (!f->key_frame_ok) {
av_log(avctx, AV_LOG_ERROR,
- "Cant decode non keyframe without valid keyframe\n");
+ "Cannot decode non-keyframe without valid keyframe\n");
return AVERROR_INVALIDDATA;
}
p->key_frame = 0;
}
- p->reference = 3; //for error concealment
- if ((ret = avctx->get_buffer(avctx, p)) < 0) {
+ if ((ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
ff_init_range_decoder(&fs->c, buf_p, v);
} else
fs->c.bytestream_end = (uint8_t *)(buf_p + v);
+
+ fs->cur = p;
}
avctx->execute(avctx, decode_slice, &f->slice_context[0], NULL,
for (i = f->slice_count - 1; i >= 0; i--) {
FFV1Context *fs = f->slice_context[i];
int j;
- if (fs->slice_damaged && f->last_picture.data[0]) {
+ if (fs->slice_damaged && f->last_picture->data[0]) {
const uint8_t *src[4];
uint8_t *dst[4];
for (j = 0; j < 4; j++) {
int sh = (j == 1 || j == 2) ? f->chroma_h_shift : 0;
int sv = (j == 1 || j == 2) ? f->chroma_v_shift : 0;
- dst[j] = f->picture.data[j] + f->picture.linesize[j] *
+ dst[j] = p->data[j] + p->linesize[j] *
(fs->slice_y >> sv) + (fs->slice_x >> sh);
- src[j] = f->last_picture.data[j] +
- f->last_picture.linesize[j] *
+ src[j] = f->last_picture->data[j] +
+ f->last_picture->linesize[j] *
(fs->slice_y >> sv) + (fs->slice_x >> sh);
}
- av_image_copy(dst, f->picture.linesize, (const uint8_t **)src,
- f->last_picture.linesize,
+ av_image_copy(dst, p->linesize, (const uint8_t **)src,
+ f->last_picture->linesize,
avctx->pix_fmt, fs->slice_width,
fs->slice_height);
}
f->picture_number++;
- *picture = *p;
- *data_size = sizeof(AVFrame);
+ av_frame_unref(f->last_picture);
+ if ((ret = av_frame_ref(f->last_picture, p)) < 0)
+ return ret;
+ f->cur = NULL;
- FFSWAP(AVFrame, f->picture, f->last_picture);
+ *got_frame = 1;
return buf_size;
}
+static av_cold int ffv1_decode_close(AVCodecContext *avctx)
+{
+ FFV1Context *s = avctx->priv_data;;
+
+ av_frame_free(&s->last_picture);
+
+ ffv1_close(avctx);
+
+ return 0;
+}
+
AVCodec ff_ffv1_decoder = {
.name = "ffv1",
+ .long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"),
.type = AVMEDIA_TYPE_VIDEO,
.id = AV_CODEC_ID_FFV1,
.priv_data_size = sizeof(FFV1Context),
.init = ffv1_decode_init,
- .close = ffv1_close,
+ .close = ffv1_decode_close,
.decode = ffv1_decode_frame,
.capabilities = CODEC_CAP_DR1 /*| CODEC_CAP_DRAW_HORIZ_BAND*/ |
CODEC_CAP_SLICE_THREADS,
- .long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"),
};