mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-28 14:01:27 +00:00
Merge remote-tracking branch 'qatar/master'
* qatar/master: h264: stricter reference limit enforcement. h264: increase reference poc list from 16 to 32. xa_adpcm: limit filter to prevent xa_adpcm_table[] array bounds overruns. snow: check reference frame indices. snow: reject unsupported chroma shifts. Add ffvhuff encoding and decoding regression test anm: convert to bytestream2 API bytestream: add more unchecked variants for bytestream2 API jvdec: unbreak video decoding jv demux: set video stream duration fate: add pam image regression test Conflicts: libavcodec/adpcm.c libavcodec/anm.c libavcodec/h264.c libavcodec/mpegvideo.h libavcodec/snowdec.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
67235dfa1d
@ -265,8 +265,9 @@ static inline short adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned c
|
||||
return c->predictor;
|
||||
}
|
||||
|
||||
static void xa_decode(short *out, const unsigned char *in,
|
||||
ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc)
|
||||
static int xa_decode(AVCodecContext *avctx,
|
||||
short *out, const unsigned char *in,
|
||||
ADPCMChannelStatus *left, ADPCMChannelStatus *right, int inc)
|
||||
{
|
||||
int i, j;
|
||||
int shift,filter,f0,f1;
|
||||
@ -278,7 +279,7 @@ static void xa_decode(short *out, const unsigned char *in,
|
||||
shift = 12 - (in[4+i*2] & 15);
|
||||
filter = in[4+i*2] >> 4;
|
||||
if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) {
|
||||
av_log_ask_for_sample(NULL, "unknown filter %d\n", filter);
|
||||
av_log_ask_for_sample(avctx, "unknown XA-ADPCM filter %d\n", filter);
|
||||
filter=0;
|
||||
}
|
||||
f0 = xa_adpcm_table[filter][0];
|
||||
@ -309,7 +310,7 @@ static void xa_decode(short *out, const unsigned char *in,
|
||||
shift = 12 - (in[5+i*2] & 15);
|
||||
filter = in[5+i*2] >> 4;
|
||||
if (filter >= FF_ARRAY_ELEMS(xa_adpcm_table)) {
|
||||
av_log_ask_for_sample(NULL, "unknown filter %d\n", filter);
|
||||
av_log_ask_for_sample(avctx, "unknown XA-ADPCM filter %d\n", filter);
|
||||
filter=0;
|
||||
}
|
||||
|
||||
@ -336,6 +337,8 @@ static void xa_decode(short *out, const unsigned char *in,
|
||||
left->sample2 = s_2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -823,8 +826,9 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
break;
|
||||
case CODEC_ID_ADPCM_XA:
|
||||
while (buf_size >= 128) {
|
||||
xa_decode(samples, src, &c->status[0], &c->status[1],
|
||||
avctx->channels);
|
||||
if ((ret = xa_decode(avctx, samples, src, &c->status[0],
|
||||
&c->status[1], avctx->channels)) < 0)
|
||||
return ret;
|
||||
src += 128;
|
||||
samples += 28 * 8;
|
||||
buf_size -= 128;
|
||||
|
@ -30,26 +30,26 @@
|
||||
typedef struct AnmContext {
|
||||
AVFrame frame;
|
||||
int palette[AVPALETTE_COUNT];
|
||||
GetByteContext gb;
|
||||
int x; ///< x coordinate position
|
||||
} AnmContext;
|
||||
|
||||
static av_cold int decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
AnmContext *s = avctx->priv_data;
|
||||
const uint8_t *buf;
|
||||
int i;
|
||||
|
||||
avctx->pix_fmt = PIX_FMT_PAL8;
|
||||
|
||||
if (avctx->extradata_size != 16*8 + 4*256)
|
||||
return -1;
|
||||
|
||||
avcodec_get_frame_defaults(&s->frame);
|
||||
s->frame.reference = 3;
|
||||
bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size);
|
||||
if (bytestream2_get_bytes_left(&s->gb) < 16 * 8 + 4 * 256)
|
||||
return -1;
|
||||
|
||||
buf = avctx->extradata + 16*8;
|
||||
bytestream2_skipu(&s->gb, 16 * 8);
|
||||
for (i = 0; i < 256; i++)
|
||||
s->palette[i] = bytestream_get_le32(&buf);
|
||||
s->palette[i] = bytestream2_get_le32u(&s->gb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -57,7 +57,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
||||
/**
|
||||
* Perform decode operation
|
||||
* @param dst, dst_end Destination image buffer
|
||||
* @param buf, buf_end Source buffer (optional, see below)
|
||||
* @param gb, GetByteContext (optional, see below)
|
||||
* @param pixel Fill color (optional, see below)
|
||||
* @param count Pixel count
|
||||
* @param x Pointer to x-axis counter
|
||||
@ -65,24 +65,22 @@ static av_cold int decode_init(AVCodecContext *avctx)
|
||||
* @param linesize Destination image buffer linesize
|
||||
* @return non-zero if destination buffer is exhausted
|
||||
*
|
||||
* a copy operation is achieved when 'buf' is set
|
||||
* a fill operation is acheived when 'buf' is null and pixel is >= 0
|
||||
* a skip operation is acheived when 'buf' is null and pixel is < 0
|
||||
* a copy operation is achieved when 'gb' is set
|
||||
* a fill operation is acheived when 'gb' is null and pixel is >= 0
|
||||
* a skip operation is acheived when 'gb' is null and pixel is < 0
|
||||
*/
|
||||
static inline int op(uint8_t **dst, const uint8_t *dst_end,
|
||||
const uint8_t **buf, const uint8_t *buf_end,
|
||||
GetByteContext *gb,
|
||||
int pixel, int count,
|
||||
int *x, int width, int linesize)
|
||||
{
|
||||
int remaining = width - *x;
|
||||
while(count > 0) {
|
||||
int striplen = FFMIN(count, remaining);
|
||||
if (buf) {
|
||||
striplen = FFMIN(striplen, buf_end - *buf);
|
||||
if (*buf >= buf_end)
|
||||
if (gb) {
|
||||
if (bytestream2_get_bytes_left(gb) < striplen)
|
||||
goto exhausted;
|
||||
memcpy(*dst, *buf, striplen);
|
||||
*buf += striplen;
|
||||
bytestream2_get_bufferu(gb, *dst, striplen);
|
||||
} else if (pixel >= 0)
|
||||
memset(*dst, pixel, striplen);
|
||||
*dst += striplen;
|
||||
@ -111,9 +109,7 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
AnmContext *s = avctx->priv_data;
|
||||
const uint8_t *buf = avpkt->data;
|
||||
const int buf_size = avpkt->size;
|
||||
const uint8_t *buf_end = buf + buf_size;
|
||||
uint8_t *dst, *dst_end;
|
||||
int count;
|
||||
|
||||
@ -124,35 +120,37 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
dst = s->frame.data[0];
|
||||
dst_end = s->frame.data[0] + s->frame.linesize[0]*avctx->height;
|
||||
|
||||
if (buf[0] != 0x42) {
|
||||
bytestream2_init(&s->gb, avpkt->data, buf_size);
|
||||
|
||||
if (bytestream2_get_byte(&s->gb) != 0x42) {
|
||||
av_log_ask_for_sample(avctx, "unknown record type\n");
|
||||
return buf_size;
|
||||
}
|
||||
if (buf[1]) {
|
||||
if (bytestream2_get_byte(&s->gb)) {
|
||||
av_log_ask_for_sample(avctx, "padding bytes not supported\n");
|
||||
return buf_size;
|
||||
}
|
||||
buf += 4;
|
||||
bytestream2_skip(&s->gb, 2);
|
||||
|
||||
s->x = 0;
|
||||
do {
|
||||
/* if statements are ordered by probability */
|
||||
#define OP(buf, pixel, count) \
|
||||
op(&dst, dst_end, (buf), buf_end, (pixel), (count), &s->x, avctx->width, s->frame.linesize[0])
|
||||
#define OP(gb, pixel, count) \
|
||||
op(&dst, dst_end, (gb), (pixel), (count), &s->x, avctx->width, s->frame.linesize[0])
|
||||
|
||||
int type = bytestream_get_byte(&buf);
|
||||
int type = bytestream2_get_byte(&s->gb);
|
||||
count = type & 0x7F;
|
||||
type >>= 7;
|
||||
if (count) {
|
||||
if (OP(type ? NULL : &buf, -1, count)) break;
|
||||
if (OP(type ? NULL : &s->gb, -1, count)) break;
|
||||
} else if (!type) {
|
||||
int pixel;
|
||||
count = bytestream_get_byte(&buf); /* count==0 gives nop */
|
||||
pixel = bytestream_get_byte(&buf);
|
||||
count = bytestream2_get_byte(&s->gb); /* count==0 gives nop */
|
||||
pixel = bytestream2_get_byte(&s->gb);
|
||||
if (OP(NULL, pixel, count)) break;
|
||||
} else {
|
||||
int pixel;
|
||||
type = bytestream_get_le16(&buf);
|
||||
type = bytestream2_get_le16(&s->gb);
|
||||
count = type & 0x3FFF;
|
||||
type >>= 14;
|
||||
if (!count) {
|
||||
@ -164,11 +162,11 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
pixel = type == 3 ? bytestream_get_byte(&buf) : -1;
|
||||
pixel = type == 3 ? bytestream2_get_byte(&s->gb) : -1;
|
||||
if (type == 1) count += 0x4000;
|
||||
if (OP(type == 2 ? &buf : NULL, pixel, count)) break;
|
||||
if (OP(type == 2 ? &s->gb : NULL, pixel, count)) break;
|
||||
}
|
||||
} while (buf + 1 < buf_end);
|
||||
} while (bytestream2_get_bytes_left(&s->gb) > 0);
|
||||
|
||||
memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);
|
||||
|
||||
|
@ -170,6 +170,12 @@ static av_always_inline void bytestream2_skip(GetByteContext *g,
|
||||
g->buffer += FFMIN(g->buffer_end - g->buffer, size);
|
||||
}
|
||||
|
||||
static av_always_inline void bytestream2_skipu(GetByteContext *g,
|
||||
unsigned int size)
|
||||
{
|
||||
g->buffer += size;
|
||||
}
|
||||
|
||||
static av_always_inline void bytestream2_skip_p(PutByteContext *p,
|
||||
unsigned int size)
|
||||
{
|
||||
@ -257,6 +263,15 @@ static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g,
|
||||
return size2;
|
||||
}
|
||||
|
||||
static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g,
|
||||
uint8_t *dst,
|
||||
unsigned int size)
|
||||
{
|
||||
memcpy(dst, g->buffer, size);
|
||||
g->buffer += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p,
|
||||
const uint8_t *src,
|
||||
unsigned int size)
|
||||
@ -272,6 +287,15 @@ static av_always_inline unsigned int bytestream2_put_buffer(PutByteContext *p,
|
||||
return size2;
|
||||
}
|
||||
|
||||
static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p,
|
||||
const uint8_t *src,
|
||||
unsigned int size)
|
||||
{
|
||||
memcpy(p->buffer, src, size);
|
||||
p->buffer += size;
|
||||
return size;
|
||||
}
|
||||
|
||||
static av_always_inline void bytestream2_set_buffer(PutByteContext *p,
|
||||
const uint8_t c,
|
||||
unsigned int size)
|
||||
@ -286,6 +310,14 @@ static av_always_inline void bytestream2_set_buffer(PutByteContext *p,
|
||||
p->buffer += size2;
|
||||
}
|
||||
|
||||
static av_always_inline void bytestream2_set_bufferu(PutByteContext *p,
|
||||
const uint8_t c,
|
||||
unsigned int size)
|
||||
{
|
||||
memset(p->buffer, c, size);
|
||||
p->buffer += size;
|
||||
}
|
||||
|
||||
static av_always_inline unsigned int bytestream2_get_eof(PutByteContext *p)
|
||||
{
|
||||
return p->eof;
|
||||
|
@ -3034,7 +3034,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
|
||||
h->ref_count[1]= h->pps.ref_count[1];
|
||||
|
||||
if(h->slice_type_nos != AV_PICTURE_TYPE_I){
|
||||
unsigned max= (16<<(s->picture_structure != PICT_FRAME))-1;
|
||||
unsigned max= s->picture_structure == PICT_FRAME ? 15 : 31;
|
||||
|
||||
if(h->slice_type_nos == AV_PICTURE_TYPE_B){
|
||||
h->direct_spatial_mv_pred= get_bits1(&s->gb);
|
||||
}
|
||||
@ -3044,13 +3045,14 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
|
||||
h->ref_count[0]= get_ue_golomb(&s->gb) + 1;
|
||||
if(h->slice_type_nos==AV_PICTURE_TYPE_B)
|
||||
h->ref_count[1]= get_ue_golomb(&s->gb) + 1;
|
||||
}
|
||||
|
||||
}
|
||||
if(h->ref_count[0]-1 > max || h->ref_count[1]-1 > max){
|
||||
if (h->ref_count[0]-1 > max || h->ref_count[1]-1 > max){
|
||||
av_log(h->s.avctx, AV_LOG_ERROR, "reference overflow\n");
|
||||
h->ref_count[0]= h->ref_count[1]= 1;
|
||||
return -1;
|
||||
h->ref_count[0] = h->ref_count[1] = 1;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if(h->slice_type_nos == AV_PICTURE_TYPE_B)
|
||||
h->list_count= 2;
|
||||
else
|
||||
|
@ -150,7 +150,7 @@ static int decode_frame(AVCodecContext *avctx,
|
||||
|
||||
if (video_type == 0 || video_type == 1) {
|
||||
GetBitContext gb;
|
||||
init_get_bits(&gb, buf, FFMIN(video_size, (buf_end - buf) * 8));
|
||||
init_get_bits(&gb, buf, 8 * FFMIN(video_size, buf_end - buf));
|
||||
|
||||
for (j = 0; j < avctx->height; j += 8)
|
||||
for (i = 0; i < avctx->width; i += 8)
|
||||
|
@ -142,6 +142,7 @@ static int decode_q_branch(SnowContext *s, int level, int x, int y){
|
||||
const BlockNode *tl = y && x ? &s->block[index-w-1] : left;
|
||||
const BlockNode *tr = y && trx<w && ((x&1)==0 || level==0) ? &s->block[index-w+(1<<rem_depth)] : tl; //FIXME use lt
|
||||
int s_context= 2*left->level + 2*top->level + tl->level + tr->level;
|
||||
int res;
|
||||
|
||||
if(s->keyframe){
|
||||
set_blocks(s, level, x, y, null_block.color[0], null_block.color[1], null_block.color[2], null_block.mx, null_block.my, null_block.ref, BLOCK_INTRA);
|
||||
@ -170,7 +171,7 @@ static int decode_q_branch(SnowContext *s, int level, int x, int y){
|
||||
ref= get_symbol(&s->c, &s->block_state[128 + 1024 + 32*ref_context], 0);
|
||||
if (ref >= s->ref_frames) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Invalid ref\n");
|
||||
return -1;
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
pred_mv(s, &mx, &my, ref, left, top, tr);
|
||||
mx+= get_symbol(&s->c, &s->block_state[128 + 32*(mx_context + 16*!!ref)], 1);
|
||||
@ -178,14 +179,11 @@ static int decode_q_branch(SnowContext *s, int level, int x, int y){
|
||||
}
|
||||
set_blocks(s, level, x, y, l, cb, cr, mx, my, ref, type);
|
||||
}else{
|
||||
if (decode_q_branch(s, level+1, 2*x+0, 2*y+0)<0)
|
||||
return -1;
|
||||
if (decode_q_branch(s, level+1, 2*x+1, 2*y+0)<0)
|
||||
return -1;
|
||||
if (decode_q_branch(s, level+1, 2*x+0, 2*y+1)<0)
|
||||
return -1;
|
||||
if (decode_q_branch(s, level+1, 2*x+1, 2*y+1)<0)
|
||||
return -1;
|
||||
if ((res = decode_q_branch(s, level+1, 2*x+0, 2*y+0)) < 0 ||
|
||||
(res = decode_q_branch(s, level+1, 2*x+1, 2*y+0)) < 0 ||
|
||||
(res = decode_q_branch(s, level+1, 2*x+0, 2*y+1)) < 0 ||
|
||||
(res = decode_q_branch(s, level+1, 2*x+1, 2*y+1)) < 0)
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -367,11 +365,12 @@ static int decode_blocks(SnowContext *s){
|
||||
int x, y;
|
||||
int w= s->b_width;
|
||||
int h= s->b_height;
|
||||
int res;
|
||||
|
||||
for(y=0; y<h; y++){
|
||||
for(x=0; x<w; x++){
|
||||
if (decode_q_branch(s, 0, x, y) < 0)
|
||||
return -1;
|
||||
if ((res = decode_q_branch(s, 0, x, y)) < 0)
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -385,6 +384,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
|
||||
int bytes_read;
|
||||
AVFrame *picture = data;
|
||||
int level, orientation, plane_index;
|
||||
int res;
|
||||
|
||||
ff_init_range_decoder(c, buf, buf_size);
|
||||
ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
|
||||
@ -413,8 +413,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
|
||||
if(avctx->debug&FF_DEBUG_PICT_INFO)
|
||||
av_log(avctx, AV_LOG_ERROR, "keyframe:%d qlog:%d\n", s->keyframe, s->qlog);
|
||||
|
||||
if (decode_blocks(s) < 0)
|
||||
return -1;
|
||||
if ((res = decode_blocks(s)) < 0)
|
||||
return res;
|
||||
|
||||
for(plane_index=0; plane_index<3; plane_index++){
|
||||
Plane *p= &s->plane[plane_index];
|
||||
|
@ -79,6 +79,7 @@ static int read_header(AVFormatContext *s)
|
||||
vst->codec->codec_tag = 0; /* no fourcc */
|
||||
vst->codec->width = avio_rl16(pb);
|
||||
vst->codec->height = avio_rl16(pb);
|
||||
vst->duration =
|
||||
vst->nb_frames =
|
||||
ast->nb_index_entries = avio_rl16(pb);
|
||||
avpriv_set_pts_info(vst, 64, avio_rl16(pb), 1000);
|
||||
|
@ -227,6 +227,11 @@ do_video_encoding ffv1.avi "-strict -2 -an -vcodec ffv1"
|
||||
do_video_decoding
|
||||
fi
|
||||
|
||||
if [ -n "$do_ffvhuff" ] ; then
|
||||
do_video_encoding ffvhuff.avi "-an -vcodec ffvhuff"
|
||||
do_video_decoding ""
|
||||
fi
|
||||
|
||||
if [ -n "$do_snow" ] ; then
|
||||
do_video_encoding snow.avi "-strict -2 -an -vcodec snow -qscale 2 -flags +qpel -me_method iter -dia_size 2 -cmp 12 -subcmp 12 -s 128x64"
|
||||
do_video_decoding "" "-s 352x288"
|
||||
|
@ -211,6 +211,10 @@ if [ -n "$do_jpg" ] ; then
|
||||
do_image_formats jpg "-pix_fmt yuvj420p" "-f image2"
|
||||
fi
|
||||
|
||||
if [ -n "$do_pam" ] ; then
|
||||
do_image_formats pam
|
||||
fi
|
||||
|
||||
if [ -n "$do_pcx" ] ; then
|
||||
do_image_formats pcx
|
||||
fi
|
||||
|
3
tests/ref/lavf/pam
Normal file
3
tests/ref/lavf/pam
Normal file
@ -0,0 +1,3 @@
|
||||
0dce5565222cf0f8b309467f279aecd2 *./tests/data/images/pam/02.pam
|
||||
./tests/data/images/pam/%02d.pam CRC=0x6da01946
|
||||
304191 ./tests/data/images/pam/02.pam
|
4
tests/ref/vsynth1/ffvhuff
Normal file
4
tests/ref/vsynth1/ffvhuff
Normal file
@ -0,0 +1,4 @@
|
||||
0632ffae6f1e06dd299bf41a845b9099 *./tests/data/vsynth1/ffvhuff.avi
|
||||
5987208 ./tests/data/vsynth1/ffvhuff.avi
|
||||
c5ccac874dbf808e9088bc3107860042 *./tests/data/ffvhuff.vsynth1.out.yuv
|
||||
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200
|
4
tests/ref/vsynth2/ffvhuff
Normal file
4
tests/ref/vsynth2/ffvhuff
Normal file
@ -0,0 +1,4 @@
|
||||
63926d8835dd5779dca0a4bc081ca8ae *./tests/data/vsynth2/ffvhuff.avi
|
||||
4988056 ./tests/data/vsynth2/ffvhuff.avi
|
||||
dde5895817ad9d219f79a52d0bdfb001 *./tests/data/ffvhuff.vsynth2.out.yuv
|
||||
stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200
|
Loading…
Reference in New Issue
Block a user