From 96d8e18a98c59a3131bb3522006525f6a8d24f3f Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Tue, 3 Jan 2012 00:40:08 -0600 Subject: [PATCH 01/46] APIchanges: mention cleaned up header includes Fixes bug 188. Signed-off-by: Jonathan Nieder Signed-off-by: Janne Grunau --- doc/APIchanges | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 951bead713..622e502da6 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -124,8 +124,10 @@ API changes, most recent first: 2011-09-03 - c11fb82 - lavu 51.10.0 Add AV_OPT_SEARCH_FAKE_OBJ flag for av_opt_find() function. -2011-08-26 - f2011ed - lavu 51.9.0 - Add av_fifo_peek2(), deprecate av_fifo_peek(). +2011-08-26 - lavu 51.9.0 + - f2011ed Add av_fifo_peek2(), deprecate av_fifo_peek(). + - add41de..abc78a5 Do not include intfloat_readwrite.h, + mathematics.h, rational.h, pixfmt.h, or log.h from avutil.h. 2011-08-16 - 48f9e45 - lavf 53.4.0 Add avformat_query_codec(). From e3d4f59f9596539c3f454836c9b64e6565484a22 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 09:28:02 -0500 Subject: [PATCH 02/46] adxenc: remove unneeded comments --- libavcodec/adxenc.c | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index ae4b9f7da2..fa97942677 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -33,8 +33,6 @@ * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ */ -/* 18 bytes <-> 32 samples */ - static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav, ADXChannelState *prev) { @@ -60,8 +58,6 @@ static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav, prev->s1 = s1; prev->s2 = s2; - /* -8..+7 */ - if (max==0 && min==0) { memset(adx,0,18); return; @@ -82,35 +78,12 @@ static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav, static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t bufsize) { -#if 0 - struct { - uint32_t offset; /* 0x80000000 + sample start - 4 */ - unsigned char unknown1[3]; /* 03 12 04 */ - unsigned char channel; /* 1 or 2 */ - uint32_t freq; - uint32_t size; - uint32_t unknown2; /* 01 f4 03 00 */ - uint32_t unknown3; /* 00 00 00 00 */ - uint32_t unknown4; /* 00 00 00 00 */ - - /* if loop - unknown3 00 15 00 01 - unknown4 00 00 00 01 - long loop_start_sample; - long loop_start_byte; - long loop_end_sample; - long loop_end_byte; - long - */ - } adxhdr; /* big endian */ - /* offset-6 "(c)CRI" */ -#endif ADXContext *c = avctx->priv_data; AV_WB32(buf+0x00,0x80000000|0x20); AV_WB32(buf+0x04,0x03120400|avctx->channels); AV_WB32(buf+0x08,avctx->sample_rate); - AV_WB32(buf+0x0c,0); /* FIXME: set after */ + AV_WB32(buf+0x0c,0); AV_WB16(buf + 0x10, c->cutoff); AV_WB32(buf + 0x12, 0x03000000); AV_WB32(buf + 0x16, 0x00000000); @@ -124,14 +97,12 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) ADXContext *c = avctx->priv_data; if (avctx->channels > 2) - return -1; /* only stereo or mono =) */ + return -1; avctx->frame_size = 32; avctx->coded_frame= avcodec_alloc_frame(); avctx->coded_frame->key_frame= 1; -// avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32; - /* the cutoff can be adjusted, but this seems to work pretty well */ c->cutoff = 500; ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff); @@ -156,13 +127,6 @@ static int adx_encode_frame(AVCodecContext *avctx, unsigned char *dst = frame; int rest = avctx->frame_size; -/* - input data size = - avconv.c:do_audio_out() - frame_bytes = enc->frame_size * 2 * enc->channels; -*/ - -// printf("sz=%d ",buf_size); fflush(stdout); if (!c->header_parsed) { int hdrsize = adx_encode_header(avctx,dst,buf_size); dst+=hdrsize; From c98c6e18d82a34c7b02d9539d4a79ec3c60fc0b9 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 09:28:15 -0500 Subject: [PATCH 03/46] adxenc: remove unneeded log message --- libavcodec/adxenc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index fa97942677..7c3373ce46 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -107,8 +107,6 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) c->cutoff = 500; ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff); - av_log(avctx, AV_LOG_DEBUG, "adx encode init\n"); - return 0; } From 25edfc88e3d2423cd95509f1270f6229660ee809 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 09:29:11 -0500 Subject: [PATCH 04/46] adxenc: change some data types --- libavcodec/adxenc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index 7c3373ce46..77052544f7 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -33,7 +33,7 @@ * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ */ -static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav, +static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, ADXChannelState *prev) { PutBitContext pb; @@ -76,7 +76,7 @@ static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav, flush_put_bits(&pb); } -static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t bufsize) +static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize) { ADXContext *c = avctx->priv_data; @@ -121,9 +121,9 @@ static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, void *data) { ADXContext *c = avctx->priv_data; - const short *samples = data; - unsigned char *dst = frame; - int rest = avctx->frame_size; + const int16_t *samples = data; + uint8_t *dst = frame; + int rest = avctx->frame_size; if (!c->header_parsed) { int hdrsize = adx_encode_header(avctx,dst,buf_size); @@ -140,7 +140,7 @@ static int adx_encode_frame(AVCodecContext *avctx, } } else { while(rest>=32*2) { - short tmpbuf[32*2]; + int16_t tmpbuf[32*2]; int i; for(i=0;i<32;i++) { From a85ab8ad45bf2dc31c275bd04b2a740631ad6111 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 09:39:05 -0500 Subject: [PATCH 05/46] adxenc: cosmetics: pretty-printing --- libavcodec/adxenc.c | 87 ++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index 77052544f7..cff5bb8dd7 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -39,40 +39,45 @@ static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, PutBitContext pb; int scale; int i; - int s0,s1,s2,d; - int max=0; - int min=0; + int s0, s1, s2, d; + int max = 0; + int min = 0; int data[32]; s1 = prev->s1; s2 = prev->s2; - for(i=0;i<32;i++) { + for (i = 0; i < 32; i++) { s0 = wav[i]; d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS; - data[i]=d; - if (maxd) min=d; + data[i] = d; + if (max < d) + max = d; + if (min > d) + min = d; s2 = s1; s1 = s0; } prev->s1 = s1; prev->s2 = s2; - if (max==0 && min==0) { - memset(adx,0,18); + if (max == 0 && min == 0) { + memset(adx, 0, 18); return; } - if (max/7>-min/8) scale = max/7; - else scale = -min/8; + if (max / 7 > -min / 8) + scale = max / 7; + else + scale = -min / 8; - if (scale==0) scale=1; + if (scale == 0) + scale = 1; AV_WB16(adx, scale); init_put_bits(&pb, adx + 2, 16); for (i = 0; i < 32; i++) - put_sbits(&pb, 4, av_clip(data[i]/scale, -8, 7)); + put_sbits(&pb, 4, av_clip(data[i] / scale, -8, 7)); flush_put_bits(&pb); } @@ -80,16 +85,16 @@ static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize) { ADXContext *c = avctx->priv_data; - AV_WB32(buf+0x00,0x80000000|0x20); - AV_WB32(buf+0x04,0x03120400|avctx->channels); - AV_WB32(buf+0x08,avctx->sample_rate); - AV_WB32(buf+0x0c,0); + AV_WB32(buf + 0x00, 0x80000000 | 0x20); + AV_WB32(buf + 0x04, 0x03120400 | avctx->channels); + AV_WB32(buf + 0x08, avctx->sample_rate); + AV_WB32(buf + 0x0c, 0); AV_WB16(buf + 0x10, c->cutoff); AV_WB32(buf + 0x12, 0x03000000); AV_WB32(buf + 0x16, 0x00000000); AV_WB32(buf + 0x1a, 0x00000000); memcpy (buf + 0x1e, "(c)CRI", 6); - return 0x20+4; + return 0x20 + 4; } static av_cold int adx_encode_init(AVCodecContext *avctx) @@ -100,8 +105,8 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) return -1; avctx->frame_size = 32; - avctx->coded_frame= avcodec_alloc_frame(); - avctx->coded_frame->key_frame= 1; + avctx->coded_frame = avcodec_alloc_frame(); + avctx->coded_frame->key_frame = 1; /* the cutoff can be adjusted, but this seems to work pretty well */ c->cutoff = 500; @@ -113,49 +118,48 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) static av_cold int adx_encode_close(AVCodecContext *avctx) { av_freep(&avctx->coded_frame); - return 0; } -static int adx_encode_frame(AVCodecContext *avctx, - uint8_t *frame, int buf_size, void *data) +static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, + int buf_size, void *data) { - ADXContext *c = avctx->priv_data; + ADXContext *c = avctx->priv_data; const int16_t *samples = data; uint8_t *dst = frame; int rest = avctx->frame_size; if (!c->header_parsed) { - int hdrsize = adx_encode_header(avctx,dst,buf_size); - dst+=hdrsize; + int hdrsize = adx_encode_header(avctx, dst, buf_size); + dst += hdrsize; c->header_parsed = 1; } - if (avctx->channels==1) { - while(rest>=32) { + if (avctx->channels == 1) { + while (rest >= 32) { adx_encode(c, dst, samples, c->prev); - dst+=18; - samples+=32; - rest-=32; + dst += 18; + samples += 32; + rest -= 32; } } else { - while(rest>=32*2) { + while (rest >= 32*2) { int16_t tmpbuf[32*2]; int i; - for(i=0;i<32;i++) { - tmpbuf[i] = samples[i*2]; + for (i = 0; i < 32; i++) { + tmpbuf[i ] = samples[i*2 ]; tmpbuf[i+32] = samples[i*2+1]; } - adx_encode(c, dst, tmpbuf, c->prev); + adx_encode(c, dst, tmpbuf, c->prev ); adx_encode(c, dst + 18, tmpbuf + 32, c->prev + 1); - dst+=18*2; - samples+=32*2; - rest-=32*2; + dst += 18*2; + samples += 32*2; + rest -= 32*2; } } - return dst-frame; + return dst - frame; } AVCodec ff_adpcm_adx_encoder = { @@ -166,6 +170,7 @@ AVCodec ff_adpcm_adx_encoder = { .init = adx_encode_init, .encode = adx_encode_frame, .close = adx_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE}, - .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, + .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), }; From cc40c056d01a95b0a57950d4d8aec9e86060c6b6 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 09:45:17 -0500 Subject: [PATCH 06/46] adxenc: log an error message and return AVERROR(EINVAL) for invalid channels --- libavcodec/adxenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index cff5bb8dd7..a580bb3bc0 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -101,8 +101,10 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) { ADXContext *c = avctx->priv_data; - if (avctx->channels > 2) - return -1; + if (avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR(EINVAL); + } avctx->frame_size = 32; avctx->coded_frame = avcodec_alloc_frame(); From 6b77f07074bfdba7106fdbf20106da7d8522655a Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 09:45:50 -0500 Subject: [PATCH 07/46] adxenc: remove unnecessary setting of coded_frame->key_frame. It is already set by avcodec_alloc_frame(). --- libavcodec/adxenc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index a580bb3bc0..43f7801843 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -108,7 +108,6 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) avctx->frame_size = 32; avctx->coded_frame = avcodec_alloc_frame(); - avctx->coded_frame->key_frame = 1; /* the cutoff can be adjusted, but this seems to work pretty well */ c->cutoff = 500; From 613668210b87e4d7ceabf65c5939f9219570a6f2 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 09:52:32 -0500 Subject: [PATCH 08/46] adxenc: avoid stereo deinterleaving --- libavcodec/adxenc.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index 43f7801843..4f434ba3c4 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -34,11 +34,11 @@ */ static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, - ADXChannelState *prev) + ADXChannelState *prev, int channels) { PutBitContext pb; int scale; - int i; + int i, j; int s0, s1, s2, d; int max = 0; int min = 0; @@ -46,10 +46,10 @@ static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, s1 = prev->s1; s2 = prev->s2; - for (i = 0; i < 32; i++) { + for (i = 0, j = 0; j < 32; i += channels, j++) { s0 = wav[i]; d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS; - data[i] = d; + data[j] = d; if (max < d) max = d; if (min > d) @@ -138,23 +138,15 @@ static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, if (avctx->channels == 1) { while (rest >= 32) { - adx_encode(c, dst, samples, c->prev); + adx_encode(c, dst, samples, c->prev, avctx->channels); dst += 18; samples += 32; rest -= 32; } } else { while (rest >= 32*2) { - int16_t tmpbuf[32*2]; - int i; - - for (i = 0; i < 32; i++) { - tmpbuf[i ] = samples[i*2 ]; - tmpbuf[i+32] = samples[i*2+1]; - } - - adx_encode(c, dst, tmpbuf, c->prev ); - adx_encode(c, dst + 18, tmpbuf + 32, c->prev + 1); + adx_encode(c, dst, samples, c->prev, avctx->channels); + adx_encode(c, dst + 18, samples + 1, c->prev + 1, avctx->channels); dst += 18*2; samples += 32*2; rest -= 32*2; From 99baf2c7d0dfa7d9ced34665ed6f0bf057fc9b30 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 10:12:29 -0500 Subject: [PATCH 09/46] adx: add AVFMT_GENERIC_INDEX to demuxer flags. fixes seeking --- libavformat/adxdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/adxdec.c b/libavformat/adxdec.c index dca9748301..ab11d832d8 100644 --- a/libavformat/adxdec.c +++ b/libavformat/adxdec.c @@ -109,4 +109,5 @@ AVInputFormat ff_adx_demuxer = { .read_packet = adx_read_packet, .extensions = "adx", .value = CODEC_ID_ADPCM_ADX, + .flags = AVFMT_GENERIC_INDEX, }; From 6c117bd8e072319dd0895efd64c4470ad0872213 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 10:14:35 -0500 Subject: [PATCH 10/46] adxenc: remove unneeded loops avctx->frame_size is 32, so that is how many samples we process per call. --- libavcodec/adxenc.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index 4f434ba3c4..12690d2ed0 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -128,7 +128,6 @@ static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, ADXContext *c = avctx->priv_data; const int16_t *samples = data; uint8_t *dst = frame; - int rest = avctx->frame_size; if (!c->header_parsed) { int hdrsize = adx_encode_header(avctx, dst, buf_size); @@ -137,20 +136,12 @@ static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, } if (avctx->channels == 1) { - while (rest >= 32) { adx_encode(c, dst, samples, c->prev, avctx->channels); dst += 18; - samples += 32; - rest -= 32; - } } else { - while (rest >= 32*2) { adx_encode(c, dst, samples, c->prev, avctx->channels); adx_encode(c, dst + 18, samples + 1, c->prev + 1, avctx->channels); dst += 18*2; - samples += 32*2; - rest -= 32*2; - } } return dst - frame; } From f1be41c63d8c2f0d0ecc6cbde4eb50701f809834 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 10:18:09 -0500 Subject: [PATCH 11/46] adxenc: use a loop to encode each channel --- libavcodec/adxenc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index 12690d2ed0..aea479884b 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -128,6 +128,7 @@ static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, ADXContext *c = avctx->priv_data; const int16_t *samples = data; uint8_t *dst = frame; + int ch; if (!c->header_parsed) { int hdrsize = adx_encode_header(avctx, dst, buf_size); @@ -135,13 +136,9 @@ static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, c->header_parsed = 1; } - if (avctx->channels == 1) { - adx_encode(c, dst, samples, c->prev, avctx->channels); - dst += 18; - } else { - adx_encode(c, dst, samples, c->prev, avctx->channels); - adx_encode(c, dst + 18, samples + 1, c->prev + 1, avctx->channels); - dst += 18*2; + for (ch = 0; ch < avctx->channels; ch++) { + adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels); + dst += 18; } return dst - frame; } From 656e606cae8cdb794c4d2640bbb27f96da3cc67e Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 10:23:21 -0500 Subject: [PATCH 12/46] adxenc: use BLOCK_SIZE and BLOCK_SAMPLES macros --- libavcodec/adxenc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index aea479884b..bc6b0f15f0 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -42,7 +42,7 @@ static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, int s0, s1, s2, d; int max = 0; int min = 0; - int data[32]; + int data[BLOCK_SAMPLES]; s1 = prev->s1; s2 = prev->s2; @@ -61,7 +61,7 @@ static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, prev->s2 = s2; if (max == 0 && min == 0) { - memset(adx, 0, 18); + memset(adx, 0, BLOCK_SIZE); return; } @@ -76,7 +76,7 @@ static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, AV_WB16(adx, scale); init_put_bits(&pb, adx + 2, 16); - for (i = 0; i < 32; i++) + for (i = 0; i < BLOCK_SAMPLES; i++) put_sbits(&pb, 4, av_clip(data[i] / scale, -8, 7)); flush_put_bits(&pb); } @@ -105,7 +105,7 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); return AVERROR(EINVAL); } - avctx->frame_size = 32; + avctx->frame_size = BLOCK_SAMPLES; avctx->coded_frame = avcodec_alloc_frame(); @@ -138,7 +138,7 @@ static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, for (ch = 0; ch < avctx->channels; ch++) { adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels); - dst += 18; + dst += BLOCK_SIZE; } return dst - frame; } From 1fb47728cd0a38537c3db8eb23ceea26562e661f Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 10:51:03 -0500 Subject: [PATCH 13/46] adxenc: use bytestream functions for header writing. also add more documentation about the header structure --- libavcodec/adxenc.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index bc6b0f15f0..2664353f9a 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -19,9 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/intreadwrite.h" #include "avcodec.h" #include "adx.h" +#include "bytestream.h" #include "put_bits.h" /** @@ -81,20 +81,29 @@ static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, flush_put_bits(&pb); } +#define HEADER_SIZE 36 + static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize) { ADXContext *c = avctx->priv_data; - AV_WB32(buf + 0x00, 0x80000000 | 0x20); - AV_WB32(buf + 0x04, 0x03120400 | avctx->channels); - AV_WB32(buf + 0x08, avctx->sample_rate); - AV_WB32(buf + 0x0c, 0); - AV_WB16(buf + 0x10, c->cutoff); - AV_WB32(buf + 0x12, 0x03000000); - AV_WB32(buf + 0x16, 0x00000000); - AV_WB32(buf + 0x1a, 0x00000000); - memcpy (buf + 0x1e, "(c)CRI", 6); - return 0x20 + 4; + bytestream_put_be16(&buf, 0x8000); /* header signature */ + bytestream_put_be16(&buf, HEADER_SIZE - 4); /* copyright offset */ + bytestream_put_byte(&buf, 3); /* encoding */ + bytestream_put_byte(&buf, BLOCK_SIZE); /* block size */ + bytestream_put_byte(&buf, 4); /* sample size */ + bytestream_put_byte(&buf, avctx->channels); /* channels */ + bytestream_put_be32(&buf, avctx->sample_rate); /* sample rate */ + bytestream_put_be32(&buf, 0); /* total sample count */ + bytestream_put_be16(&buf, c->cutoff); /* cutoff frequency */ + bytestream_put_byte(&buf, 3); /* version */ + bytestream_put_byte(&buf, 0); /* flags */ + bytestream_put_be32(&buf, 0); /* unknown */ + bytestream_put_be32(&buf, 0); /* loop enabled */ + bytestream_put_be16(&buf, 0); /* padding */ + bytestream_put_buffer(&buf, "(c)CRI", 6); /* copyright signature */ + + return HEADER_SIZE; } static av_cold int adx_encode_init(AVCodecContext *avctx) From 754ebd1a5b68dd63ccceb50a8a852fe8d0c94354 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 10:56:18 -0500 Subject: [PATCH 14/46] adxenc: check output buffer size before writing --- libavcodec/adxenc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index 2664353f9a..20f27981c8 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -87,6 +87,9 @@ static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize) { ADXContext *c = avctx->priv_data; + if (bufsize < HEADER_SIZE) + return AVERROR(EINVAL); + bytestream_put_be16(&buf, 0x8000); /* header signature */ bytestream_put_be16(&buf, HEADER_SIZE - 4); /* copyright offset */ bytestream_put_byte(&buf, 3); /* encoding */ @@ -140,10 +143,19 @@ static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, int ch; if (!c->header_parsed) { - int hdrsize = adx_encode_header(avctx, dst, buf_size); - dst += hdrsize; + int hdrsize; + if ((hdrsize = adx_encode_header(avctx, dst, buf_size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); + return AVERROR(EINVAL); + } + dst += hdrsize; + buf_size -= hdrsize; c->header_parsed = 1; } + if (buf_size < BLOCK_SIZE * avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); + return AVERROR(EINVAL); + } for (ch = 0; ch < avctx->channels; ch++) { adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels); From 779ef255e67162a125841716fd1e81c21feee359 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 11:10:34 -0500 Subject: [PATCH 15/46] adx: add an adx muxer --- Changelog | 2 +- doc/general.texi | 2 +- libavformat/Makefile | 1 + libavformat/allformats.c | 2 +- libavformat/rawenc.c | 12 ++++++++++++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Changelog b/Changelog index 37302082de..b098203fa5 100644 --- a/Changelog +++ b/Changelog @@ -108,7 +108,7 @@ easier to use. The changes are: - Discworld II BMV decoding support - VBLE Decoder - OS X Video Decoder Acceleration (VDA) support -- CRI ADX audio format demuxer +- CRI ADX audio format muxer and demuxer - Playstation Portable PMP format demuxer - PCM format support in OMA demuxer - CLJR encoder diff --git a/doc/general.texi b/doc/general.texi index 8eaa97b17a..65d65bb26b 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -122,7 +122,7 @@ library: @item Brute Force & Ignorance @tab @tab X @tab Used in the game Flash Traffic: City of Angels. @item BWF @tab X @tab X -@item CRI ADX @tab @tab X +@item CRI ADX @tab X @tab X @tab Audio-only format used in console video games. @item Discworld II BMV @tab @tab X @item Interplay C93 @tab @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index de440506ab..8c8a36d206 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -22,6 +22,7 @@ OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o rawdec.o OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_AC3_MUXER) += rawenc.o OBJS-$(CONFIG_ADX_DEMUXER) += adxdec.o +OBJS-$(CONFIG_ADX_MUXER) += rawenc.o OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o riff.o pcm.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 1debddbfc4..523b113205 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -52,7 +52,7 @@ void av_register_all(void) REGISTER_DEMUXER (AAC, aac); REGISTER_MUXDEMUX (AC3, ac3); REGISTER_MUXER (ADTS, adts); - REGISTER_DEMUXER (ADX, adx); + REGISTER_MUXDEMUX (ADX, adx); REGISTER_DEMUXER (AEA, aea); REGISTER_MUXDEMUX (AIFF, aiff); REGISTER_MUXDEMUX (AMR, amr); diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 5f2065e639..6e9f4b78ec 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -45,6 +45,18 @@ AVOutputFormat ff_ac3_muxer = { }; #endif +#if CONFIG_ADX_MUXER +AVOutputFormat ff_adx_muxer = { + .name = "adx", + .long_name = NULL_IF_CONFIG_SMALL("CRI ADX"), + .extensions = "adx", + .audio_codec = CODEC_ID_ADPCM_ADX, + .video_codec = CODEC_ID_NONE, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_DIRAC_MUXER AVOutputFormat ff_dirac_muxer = { .name = "dirac", From 3e57573fce51f219ba37a081baec10f72b45c42e Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 19 Dec 2011 11:31:14 -0500 Subject: [PATCH 16/46] fate: add ADX encoding/decoding test --- tests/codec-regression.sh | 5 +++++ tests/ref/acodec/adpcm_adx | 4 ++++ 2 files changed, 9 insertions(+) create mode 100644 tests/ref/acodec/adpcm_adx diff --git a/tests/codec-regression.sh b/tests/codec-regression.sh index 220593b17f..5fd90f51d5 100755 --- a/tests/codec-regression.sh +++ b/tests/codec-regression.sh @@ -311,6 +311,11 @@ do_audio_encoding g726.wav "-b 32k -ac 1 -ar 8000 -acodec g726" do_audio_decoding fi +if [ -n "$do_adpcm_adx" ] ; then +do_audio_encoding adpcm_adx.adx "-acodec adpcm_adx" +do_audio_decoding +fi + if [ -n "$do_adpcm_ima_wav" ] ; then do_audio_encoding adpcm_ima.wav "-acodec adpcm_ima_wav" do_audio_decoding diff --git a/tests/ref/acodec/adpcm_adx b/tests/ref/acodec/adpcm_adx new file mode 100644 index 0000000000..8d86698101 --- /dev/null +++ b/tests/ref/acodec/adpcm_adx @@ -0,0 +1,4 @@ +0a30509d9296b857e134b762b76dbc31 *./tests/data/acodec/adpcm_adx.adx +297720 ./tests/data/acodec/adpcm_adx.adx +2dbc601ed5259f4d74dc48ccd8da7eaf *./tests/data/adpcm_adx.acodec.out.wav +stddev: 6989.46 PSNR: 19.44 MAXDIFF:65398 bytes: 1058432/ 1058400 From 730280f90d36b5fd5fd400e183dfa4584b34990a Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 3 Jan 2012 17:32:15 -0500 Subject: [PATCH 17/46] adxdec: clear eof flag and channel states when seeking --- libavcodec/adxdec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/adxdec.c b/libavcodec/adxdec.c index 4ccaf2e9f2..3f7f5f4ca1 100644 --- a/libavcodec/adxdec.c +++ b/libavcodec/adxdec.c @@ -165,6 +165,13 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data, return buf - avpkt->data; } +static void adx_decode_flush(AVCodecContext *avctx) +{ + ADXContext *c = avctx->priv_data; + memset(c->prev, 0, sizeof(c->prev)); + c->eof = 0; +} + AVCodec ff_adpcm_adx_decoder = { .name = "adpcm_adx", .type = AVMEDIA_TYPE_AUDIO, @@ -172,6 +179,7 @@ AVCodec ff_adpcm_adx_decoder = { .priv_data_size = sizeof(ADXContext), .init = adx_decode_init, .decode = adx_decode_frame, + .flush = adx_decode_flush, .capabilities = CODEC_CAP_DR1, .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), }; From 9785082c15360303510059a79b61c88c489548c5 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 30 Dec 2011 17:56:04 -0500 Subject: [PATCH 18/46] libspeexenc: fix pts calculations for more than 1 frame per packet --- libavcodec/libspeexenc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c index 18f973f4fd..290718c5f1 100644 --- a/libavcodec/libspeexenc.c +++ b/libavcodec/libspeexenc.c @@ -83,7 +83,8 @@ typedef struct { int abr; ///< flag to enable ABR int pkt_frame_count; ///< frame count for the current packet int lookahead; ///< encoder delay - int sample_count; ///< total sample count (used for pts) + int64_t next_pts; ///< next pts, in sample_rate time base + int pkt_sample_count; ///< sample count in the current packet } LibSpeexEncContext; static av_cold void print_enc_params(AVCodecContext *avctx, @@ -201,7 +202,7 @@ static av_cold int encode_init(AVCodecContext *avctx) /* set encoding delay */ speex_encoder_ctl(s->enc_state, SPEEX_GET_LOOKAHEAD, &s->lookahead); - s->sample_count = -s->lookahead; + s->next_pts = -s->lookahead; /* create header packet bytes from header struct */ /* note: libspeex allocates the memory for header_data, which is freed @@ -235,7 +236,6 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, { LibSpeexEncContext *s = avctx->priv_data; int16_t *samples = data; - int sample_count = s->sample_count; if (data) { /* encode Speex frame */ @@ -243,7 +243,7 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, speex_encode_stereo_int(samples, s->header.frame_size, &s->bits); speex_encode_int(s->enc_state, samples, &s->bits); s->pkt_frame_count++; - s->sample_count += avctx->frame_size; + s->pkt_sample_count += avctx->frame_size; } else { /* handle end-of-stream */ if (!s->pkt_frame_count) @@ -259,8 +259,10 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, if (s->pkt_frame_count == s->frames_per_packet) { s->pkt_frame_count = 0; avctx->coded_frame->pts = - av_rescale_q(sample_count, (AVRational){ 1, avctx->sample_rate }, + av_rescale_q(s->next_pts, (AVRational){ 1, avctx->sample_rate }, avctx->time_base); + s->next_pts += s->pkt_sample_count; + s->pkt_sample_count = 0; if (buf_size > speex_bits_nbytes(&s->bits)) { int ret = speex_bits_write(&s->bits, frame, buf_size); speex_bits_reset(&s->bits); From e451c26c5f0bff9ced74ff6dfa3fce111fed1dbb Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 27 Dec 2011 12:25:18 +0100 Subject: [PATCH 19/46] cabac: drop unused STRICT_LIMITS code branch --- libavcodec/cabac.c | 16 ---------------- libavcodec/cabac.h | 3 --- 2 files changed, 19 deletions(-) diff --git a/libavcodec/cabac.c b/libavcodec/cabac.c index 57ab395ed7..25713ee3ea 100644 --- a/libavcodec/cabac.c +++ b/libavcodec/cabac.c @@ -109,10 +109,6 @@ void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){ c->low= 0; c->range= 0x1FE; c->outstanding_count= 0; -#ifdef STRICT_LIMITS - c->sym_count =0; -#endif - c->pb.bit_left++; //avoids firstBitFlag } @@ -179,10 +175,6 @@ static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ } renorm_cabac_encoder(c); - -#ifdef STRICT_LIMITS - c->symCount++; -#endif } /** @@ -204,10 +196,6 @@ static void put_cabac_bypass(CABACContext *c, int bit){ put_cabac_bit(c, 1); c->low -= 0x400; } - -#ifdef STRICT_LIMITS - c->symCount++; -#endif } /** @@ -232,10 +220,6 @@ static int put_cabac_terminate(CABACContext *c, int bit){ flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong } -#ifdef STRICT_LIMITS - c->symCount++; -#endif - return (put_bits_count(&c->pb)+7)>>3; } diff --git a/libavcodec/cabac.h b/libavcodec/cabac.h index 126064276a..b3f8f55da3 100644 --- a/libavcodec/cabac.h +++ b/libavcodec/cabac.h @@ -41,9 +41,6 @@ typedef struct CABACContext{ int low; int range; int outstanding_count; -#ifdef STRICT_LIMITS - int symCount; -#endif const uint8_t *bytestream_start; const uint8_t *bytestream; const uint8_t *bytestream_end; From 9dec55748cd5cf371d8f3eb35bac073d285f0617 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 27 Dec 2011 11:51:28 +0100 Subject: [PATCH 20/46] cabac: drop unused and disabled get_cabac_u() / get_cabac_ueg() functions --- libavcodec/cabac.c | 15 ------------ libavcodec/cabac.h | 58 ---------------------------------------------- 2 files changed, 73 deletions(-) diff --git a/libavcodec/cabac.c b/libavcodec/cabac.c index 25713ee3ea..bcb242936e 100644 --- a/libavcodec/cabac.c +++ b/libavcodec/cabac.c @@ -343,21 +343,6 @@ START_TIMER av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i); STOP_TIMER("get_cabac") } -#if 0 - for(i=0; i>=1){ - v+= v + get_cabac_bypass(c); - } - i += v; - - if(is_signed && get_cabac_bypass(c)){ - return -i; - }else - return i; -} -#endif /* 0 */ - #endif /* AVCODEC_CABAC_H */ From 54e68fb3b89247084dfaeb3697a18f8ba92c5ea5 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 3 Jan 2012 13:18:49 +0100 Subject: [PATCH 21/46] Merge some declarations and initializations. This fixes compilation failures related to START_TIMER/STOP_TIMER macros and -Werror=declaration-after-statement. START_TIMER declares variables and thus may not be placed after statements outside of a new block. --- libavcodec/dnxhdenc.c | 6 +++--- libavcodec/h264.c | 8 ++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index d1ab597d1d..2b7089b946 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -580,9 +580,9 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, int jobnr, int for (i = 0; i < 8; i++) { DCTELEM *block = ctx->blocks[i]; - int last_index, overflow; - int n = dnxhd_switch_matrix(ctx, i); - last_index = ctx->m.dct_quantize(&ctx->m, block, i, qscale, &overflow); + int overflow, n = dnxhd_switch_matrix(ctx, i); + int last_index = ctx->m.dct_quantize(&ctx->m, block, i, + qscale, &overflow); //START_TIMER; dnxhd_encode_block(ctx, block, last_index, n); //STOP_TIMER("encode_block"); diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 316a57d75e..bb7619dee2 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -4126,9 +4126,7 @@ int main(void){ init_get_bits(&gb, temp, 8*SIZE); for(i=0; i Date: Sat, 31 Dec 2011 09:12:53 -0800 Subject: [PATCH 22/46] h264: return index in buffer on end-of-sequence. Fixes hangs if the last packet contains an end-of-sequence NAL unit, bug 158. --- libavcodec/h264.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index bb7619dee2..9502a7c147 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -4008,7 +4008,7 @@ static int decode_frame(AVCodecContext *avctx, H264Context *h = avctx->priv_data; MpegEncContext *s = &h->s; AVFrame *pict = data; - int buf_index; + int buf_index = 0; s->flags= avctx->flags; s->flags2= avctx->flags2; @@ -4038,7 +4038,7 @@ static int decode_frame(AVCodecContext *avctx, *pict= *(AVFrame*)out; } - return 0; + return buf_index; } buf_index=decode_nal_units(h, buf, buf_size); From f910dbcdb03f84563543e73aa5aab1a83d2c0854 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 3 Jan 2012 13:05:37 -0800 Subject: [PATCH 23/46] swscale: add MMX files to MMX-OBJS instead of OBJS. --- libswscale/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libswscale/Makefile b/libswscale/Makefile index bb9b7d3539..18c82b7ffc 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -17,7 +17,7 @@ OBJS-$(HAVE_MMX) += x86/rgb2rgb.o \ x86/swscale_mmx.o \ x86/yuv2rgb_mmx.o OBJS-$(HAVE_VIS) += sparc/yuv2rgb_vis.o -OBJS-$(HAVE_YASM) += x86/scale.o +MMX-OBJS-$(HAVE_YASM) += x86/scale.o TESTPROGS = colorspace swscale From 9ea3501d8765e4a5c7c1f98d6d841468fe1abba0 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 2 Jan 2012 12:03:02 -0800 Subject: [PATCH 24/46] swscale: don't show full-chroma-int warning for non-RGB output. Non-RGB output always uses full chroma interpolation. --- libswscale/swscale.c | 62 +++++++++++++++++++++++--------------------- libswscale/utils.c | 1 + 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index f24561b8bf..cb5c6e9cd0 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -2223,36 +2223,6 @@ find_c_packed_planar_out_funcs(SwsContext *c, } } else { switch (dstFormat) { - case PIX_FMT_GRAY16BE: - *yuv2packed1 = yuv2gray16BE_1_c; - *yuv2packed2 = yuv2gray16BE_2_c; - *yuv2packedX = yuv2gray16BE_X_c; - break; - case PIX_FMT_GRAY16LE: - *yuv2packed1 = yuv2gray16LE_1_c; - *yuv2packed2 = yuv2gray16LE_2_c; - *yuv2packedX = yuv2gray16LE_X_c; - break; - case PIX_FMT_MONOWHITE: - *yuv2packed1 = yuv2monowhite_1_c; - *yuv2packed2 = yuv2monowhite_2_c; - *yuv2packedX = yuv2monowhite_X_c; - break; - case PIX_FMT_MONOBLACK: - *yuv2packed1 = yuv2monoblack_1_c; - *yuv2packed2 = yuv2monoblack_2_c; - *yuv2packedX = yuv2monoblack_X_c; - break; - case PIX_FMT_YUYV422: - *yuv2packed1 = yuv2yuyv422_1_c; - *yuv2packed2 = yuv2yuyv422_2_c; - *yuv2packedX = yuv2yuyv422_X_c; - break; - case PIX_FMT_UYVY422: - *yuv2packed1 = yuv2uyvy422_1_c; - *yuv2packed2 = yuv2uyvy422_2_c; - *yuv2packedX = yuv2uyvy422_X_c; - break; case PIX_FMT_RGB48LE: *yuv2packed1 = yuv2rgb48le_1_c; *yuv2packed2 = yuv2rgb48le_2_c; @@ -2369,6 +2339,38 @@ find_c_packed_planar_out_funcs(SwsContext *c, break; } } + switch (dstFormat) { + case PIX_FMT_GRAY16BE: + *yuv2packed1 = yuv2gray16BE_1_c; + *yuv2packed2 = yuv2gray16BE_2_c; + *yuv2packedX = yuv2gray16BE_X_c; + break; + case PIX_FMT_GRAY16LE: + *yuv2packed1 = yuv2gray16LE_1_c; + *yuv2packed2 = yuv2gray16LE_2_c; + *yuv2packedX = yuv2gray16LE_X_c; + break; + case PIX_FMT_MONOWHITE: + *yuv2packed1 = yuv2monowhite_1_c; + *yuv2packed2 = yuv2monowhite_2_c; + *yuv2packedX = yuv2monowhite_X_c; + break; + case PIX_FMT_MONOBLACK: + *yuv2packed1 = yuv2monoblack_1_c; + *yuv2packed2 = yuv2monoblack_2_c; + *yuv2packedX = yuv2monoblack_X_c; + break; + case PIX_FMT_YUYV422: + *yuv2packed1 = yuv2yuyv422_1_c; + *yuv2packed2 = yuv2yuyv422_2_c; + *yuv2packedX = yuv2yuyv422_X_c; + break; + case PIX_FMT_UYVY422: + *yuv2packed1 = yuv2uyvy422_1_c; + *yuv2packed2 = yuv2uyvy422_2_c; + *yuv2packedX = yuv2uyvy422_X_c; + break; + } } #define DEBUG_SWSCALE_BUFFERS 0 diff --git a/libswscale/utils.c b/libswscale/utils.c index 12b3202b16..073285b102 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -829,6 +829,7 @@ int sws_init_context(SwsContext *c, SwsFilter *srcFilter, SwsFilter *dstFilter) // reuse chroma for 2 pixels RGB/BGR unless user wants full chroma interpolation if (flags & SWS_FULL_CHR_H_INT && + isAnyRGB(dstFormat) && dstFormat != PIX_FMT_RGBA && dstFormat != PIX_FMT_ARGB && dstFormat != PIX_FMT_BGRA && From 6ea64339c56a3b40621a82d531c04ba968883954 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 2 Jan 2012 12:31:38 -0800 Subject: [PATCH 25/46] swscale: split scale.asm. scale.asm keeps horizontal scaling functions, whereas output.asm gets the vertical scaling/output functions. --- libswscale/Makefile | 3 +- libswscale/x86/output.asm | 409 ++++++++++++++++++++++++++++++++++++++ libswscale/x86/scale.asm | 382 +---------------------------------- 3 files changed, 412 insertions(+), 382 deletions(-) create mode 100644 libswscale/x86/output.asm diff --git a/libswscale/Makefile b/libswscale/Makefile index 18c82b7ffc..89182573f0 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -17,7 +17,8 @@ OBJS-$(HAVE_MMX) += x86/rgb2rgb.o \ x86/swscale_mmx.o \ x86/yuv2rgb_mmx.o OBJS-$(HAVE_VIS) += sparc/yuv2rgb_vis.o -MMX-OBJS-$(HAVE_YASM) += x86/scale.o +MMX-OBJS-$(HAVE_YASM) += x86/output.o \ + x86/scale.o TESTPROGS = colorspace swscale diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm new file mode 100644 index 0000000000..0ec2038d1d --- /dev/null +++ b/libswscale/x86/output.asm @@ -0,0 +1,409 @@ +;****************************************************************************** +;* x86-optimized vertical line scaling functions +;* Copyright (c) 2011 Ronald S. Bultje +;* Kieran Kunhya +;* +;* This file is part of Libav. +;* +;* Libav 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. +;* +;* Libav 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 Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "x86inc.asm" +%include "x86util.asm" + +SECTION_RODATA + +minshort: times 8 dw 0x8000 +yuv2yuvX_16_start: times 4 dd 0x4000 - 0x40000000 +yuv2yuvX_10_start: times 4 dd 0x10000 +yuv2yuvX_9_start: times 4 dd 0x20000 +yuv2yuvX_10_upper: times 8 dw 0x3ff +yuv2yuvX_9_upper: times 8 dw 0x1ff +pd_4: times 4 dd 4 +pd_4min0x40000:times 4 dd 4 - (0x40000) +pw_16: times 8 dw 16 +pw_32: times 8 dw 32 +pw_512: times 8 dw 512 +pw_1024: times 8 dw 1024 + +SECTION .text + +;----------------------------------------------------------------------------- +; vertical line scaling +; +; void yuv2plane1__(const int16_t *src, uint8_t *dst, int dstW, +; const uint8_t *dither, int offset) +; and +; void yuv2planeX__(const int16_t *filter, int filterSize, +; const int16_t **src, uint8_t *dst, int dstW, +; const uint8_t *dither, int offset) +; +; Scale one or $filterSize lines of source data to generate one line of output +; data. The input is 15-bit in int16_t if $output_size is [8,10] and 19-bit in +; int32_t if $output_size is 16. $filter is 12-bits. $filterSize is a multiple +; of 2. $offset is either 0 or 3. $dither holds 8 values. +;----------------------------------------------------------------------------- + +%macro yuv2planeX_fn 4 + +%ifdef ARCH_X86_32 +%define cntr_reg r1 +%define movsx mov +%else +%define cntr_reg r11 +%define movsx movsxd +%endif + +cglobal yuv2planeX_%2_%1, %4, 7, %3 +%if %2 == 8 || %2 == 9 || %2 == 10 + pxor m6, m6 +%endif ; %2 == 8/9/10 + +%if %2 == 8 +%ifdef ARCH_X86_32 +%assign pad 0x2c - (stack_offset & 15) + SUB rsp, pad +%define m_dith m7 +%else ; x86-64 +%define m_dith m9 +%endif ; x86-32 + + ; create registers holding dither + movq m_dith, [r5] ; dither + test r6d, r6d + jz .no_rot +%if mmsize == 16 + punpcklqdq m_dith, m_dith +%endif ; mmsize == 16 + PALIGNR m_dith, m_dith, 3, m0 +.no_rot: +%if mmsize == 16 + punpcklbw m_dith, m6 +%ifdef ARCH_X86_64 + punpcklwd m8, m_dith, m6 + pslld m8, 12 +%else ; x86-32 + punpcklwd m5, m_dith, m6 + pslld m5, 12 +%endif ; x86-32/64 + punpckhwd m_dith, m6 + pslld m_dith, 12 +%ifdef ARCH_X86_32 + mova [rsp+ 0], m5 + mova [rsp+16], m_dith +%endif +%else ; mmsize == 8 + punpcklbw m5, m_dith, m6 + punpckhbw m_dith, m6 + punpcklwd m4, m5, m6 + punpckhwd m5, m6 + punpcklwd m3, m_dith, m6 + punpckhwd m_dith, m6 + pslld m4, 12 + pslld m5, 12 + pslld m3, 12 + pslld m_dith, 12 + mova [rsp+ 0], m4 + mova [rsp+ 8], m5 + mova [rsp+16], m3 + mova [rsp+24], m_dith +%endif ; mmsize == 8/16 +%endif ; %2 == 8 + + xor r5, r5 + +.pixelloop: +%assign %%i 0 + ; the rep here is for the 8bit output mmx case, where dither covers + ; 8 pixels but we can only handle 2 pixels per register, and thus 4 + ; pixels per iteration. In order to not have to keep track of where + ; we are w.r.t. dithering, we unroll the mmx/8bit loop x2. +%if %2 == 8 +%rep 16/mmsize +%endif ; %2 == 8 + +%if %2 == 8 +%ifdef ARCH_X86_32 + mova m2, [rsp+mmsize*(0+%%i)] + mova m1, [rsp+mmsize*(1+%%i)] +%else ; x86-64 + mova m2, m8 + mova m1, m_dith +%endif ; x86-32/64 +%else ; %2 == 9/10/16 + mova m1, [yuv2yuvX_%2_start] + mova m2, m1 +%endif ; %2 == 8/9/10/16 + movsx cntr_reg, r1m +.filterloop_ %+ %%i: + ; input pixels + mov r6, [r2+gprsize*cntr_reg-2*gprsize] +%if %2 == 16 + mova m3, [r6+r5*4] + mova m5, [r6+r5*4+mmsize] +%else ; %2 == 8/9/10 + mova m3, [r6+r5*2] +%endif ; %2 == 8/9/10/16 + mov r6, [r2+gprsize*cntr_reg-gprsize] +%if %2 == 16 + mova m4, [r6+r5*4] + mova m6, [r6+r5*4+mmsize] +%else ; %2 == 8/9/10 + mova m4, [r6+r5*2] +%endif ; %2 == 8/9/10/16 + + ; coefficients + movd m0, [r0+2*cntr_reg-4]; coeff[0], coeff[1] +%if %2 == 16 + pshuflw m7, m0, 0 ; coeff[0] + pshuflw m0, m0, 0x55 ; coeff[1] + pmovsxwd m7, m7 ; word -> dword + pmovsxwd m0, m0 ; word -> dword + + pmulld m3, m7 + pmulld m5, m7 + pmulld m4, m0 + pmulld m6, m0 + + paddd m2, m3 + paddd m1, m5 + paddd m2, m4 + paddd m1, m6 +%else ; %2 == 10/9/8 + punpcklwd m5, m3, m4 + punpckhwd m3, m4 + SPLATD m0, m0 + + pmaddwd m5, m0 + pmaddwd m3, m0 + + paddd m2, m5 + paddd m1, m3 +%endif ; %2 == 8/9/10/16 + + sub cntr_reg, 2 + jg .filterloop_ %+ %%i + +%if %2 == 16 + psrad m2, 31 - %2 + psrad m1, 31 - %2 +%else ; %2 == 10/9/8 + psrad m2, 27 - %2 + psrad m1, 27 - %2 +%endif ; %2 == 8/9/10/16 + +%if %2 == 8 + packssdw m2, m1 + packuswb m2, m2 + movh [r3+r5*1], m2 +%else ; %2 == 9/10/16 +%if %2 == 16 + packssdw m2, m1 + paddw m2, [minshort] +%else ; %2 == 9/10 +%ifidn %1, sse4 + packusdw m2, m1 +%elifidn %1, avx + packusdw m2, m1 +%else ; mmx2/sse2 + packssdw m2, m1 + pmaxsw m2, m6 +%endif ; mmx2/sse2/sse4/avx + pminsw m2, [yuv2yuvX_%2_upper] +%endif ; %2 == 9/10/16 + mova [r3+r5*2], m2 +%endif ; %2 == 8/9/10/16 + + add r5, mmsize/2 + sub r4d, mmsize/2 +%if %2 == 8 +%assign %%i %%i+2 +%endrep +%endif ; %2 == 8 + jg .pixelloop + +%if %2 == 8 +%ifdef ARCH_X86_32 + ADD rsp, pad + RET +%else ; x86-64 + REP_RET +%endif ; x86-32/64 +%else ; %2 == 9/10/16 + REP_RET +%endif ; %2 == 8/9/10/16 +%endmacro + +%define PALIGNR PALIGNR_MMX +%ifdef ARCH_X86_32 +INIT_MMX +yuv2planeX_fn mmx2, 8, 0, 7 +yuv2planeX_fn mmx2, 9, 0, 5 +yuv2planeX_fn mmx2, 10, 0, 5 +%endif + +INIT_XMM +yuv2planeX_fn sse2, 8, 10, 7 +yuv2planeX_fn sse2, 9, 7, 5 +yuv2planeX_fn sse2, 10, 7, 5 + +%define PALIGNR PALIGNR_SSSE3 +yuv2planeX_fn sse4, 8, 10, 7 +yuv2planeX_fn sse4, 9, 7, 5 +yuv2planeX_fn sse4, 10, 7, 5 +yuv2planeX_fn sse4, 16, 8, 5 + +INIT_AVX +yuv2planeX_fn avx, 8, 10, 7 +yuv2planeX_fn avx, 9, 7, 5 +yuv2planeX_fn avx, 10, 7, 5 + +; %1=outout-bpc, %2=alignment (u/a) +%macro yuv2plane1_mainloop 2 +.loop_%2: +%if %1 == 8 + paddsw m0, m2, [r0+r2*2+mmsize*0] + paddsw m1, m3, [r0+r2*2+mmsize*1] + psraw m0, 7 + psraw m1, 7 + packuswb m0, m1 + mov%2 [r1+r2], m0 +%elif %1 == 16 + paddd m0, m4, [r0+r2*4+mmsize*0] + paddd m1, m4, [r0+r2*4+mmsize*1] + paddd m2, m4, [r0+r2*4+mmsize*2] + paddd m3, m4, [r0+r2*4+mmsize*3] + psrad m0, 3 + psrad m1, 3 + psrad m2, 3 + psrad m3, 3 +%if cpuflag(sse4) ; avx/sse4 + packusdw m0, m1 + packusdw m2, m3 +%else ; mmx/sse2 + packssdw m0, m1 + packssdw m2, m3 + paddw m0, m5 + paddw m2, m5 +%endif ; mmx/sse2/sse4/avx + mov%2 [r1+r2*2], m0 + mov%2 [r1+r2*2+mmsize], m2 +%else + paddsw m0, m2, [r0+r2*2+mmsize*0] + paddsw m1, m2, [r0+r2*2+mmsize*1] + psraw m0, 15 - %1 + psraw m1, 15 - %1 + pmaxsw m0, m4 + pmaxsw m1, m4 + pminsw m0, m3 + pminsw m1, m3 + mov%2 [r1+r2*2], m0 + mov%2 [r1+r2*2+mmsize], m1 +%endif + add r2, mmsize + jl .loop_%2 +%endmacro + +%macro yuv2plane1_fn 3 +cglobal yuv2plane1_%1, %3, %3, %2 + add r2, mmsize - 1 + and r2, ~(mmsize - 1) +%if %1 == 8 + add r1, r2 +%else ; %1 != 8 + lea r1, [r1+r2*2] +%endif ; %1 == 8 +%if %1 == 16 + lea r0, [r0+r2*4] +%else ; %1 != 16 + lea r0, [r0+r2*2] +%endif ; %1 == 16 + neg r2 + +%if %1 == 8 + pxor m4, m4 ; zero + + ; create registers holding dither + movq m3, [r3] ; dither + test r4d, r4d + jz .no_rot +%if mmsize == 16 + punpcklqdq m3, m3 +%endif ; mmsize == 16 + PALIGNR_MMX m3, m3, 3, m2 +.no_rot: +%if mmsize == 8 + mova m2, m3 + punpckhbw m3, m4 ; byte->word + punpcklbw m2, m4 ; byte->word +%else + punpcklbw m3, m4 + mova m2, m3 +%endif +%elif %1 == 9 + pxor m4, m4 + mova m3, [pw_512] + mova m2, [pw_32] +%elif %1 == 10 + pxor m4, m4 + mova m3, [pw_1024] + mova m2, [pw_16] +%else ; %1 == 16 +%if cpuflag(sse4) ; sse4/avx + mova m4, [pd_4] +%else ; mmx/sse2 + mova m4, [pd_4min0x40000] + mova m5, [minshort] +%endif ; mmx/sse2/sse4/avx +%endif ; %1 == .. + + ; actual pixel scaling +%if mmsize == 8 + yuv2plane1_mainloop %1, a +%else ; mmsize == 16 + test r1, 15 + jnz .unaligned + yuv2plane1_mainloop %1, a + REP_RET +.unaligned: + yuv2plane1_mainloop %1, u +%endif ; mmsize == 8/16 + REP_RET +%endmacro + +%ifdef ARCH_X86_32 +INIT_MMX mmx +yuv2plane1_fn 8, 0, 5 +yuv2plane1_fn 16, 0, 3 + +INIT_MMX mmx2 +yuv2plane1_fn 9, 0, 3 +yuv2plane1_fn 10, 0, 3 +%endif + +INIT_XMM sse2 +yuv2plane1_fn 8, 5, 5 +yuv2plane1_fn 9, 5, 3 +yuv2plane1_fn 10, 5, 3 +yuv2plane1_fn 16, 6, 3 + +INIT_XMM sse4 +yuv2plane1_fn 16, 5, 3 + +INIT_XMM avx +yuv2plane1_fn 8, 5, 5 +yuv2plane1_fn 9, 5, 3 +yuv2plane1_fn 10, 5, 3 +yuv2plane1_fn 16, 5, 3 diff --git a/libswscale/x86/scale.asm b/libswscale/x86/scale.asm index 1f5e1dbf4c..d35589419c 100644 --- a/libswscale/x86/scale.asm +++ b/libswscale/x86/scale.asm @@ -1,7 +1,6 @@ ;****************************************************************************** -;* x86-optimized horizontal/vertical line scaling functions +;* x86-optimized horizontal line scaling functions ;* Copyright (c) 2011 Ronald S. Bultje -;* Kieran Kunhya ;* ;* This file is part of Libav. ;* @@ -29,17 +28,6 @@ max_19bit_int: times 4 dd 0x7ffff max_19bit_flt: times 4 dd 524287.0 minshort: times 8 dw 0x8000 unicoeff: times 4 dd 0x20000000 -yuv2yuvX_16_start: times 4 dd 0x4000 - 0x40000000 -yuv2yuvX_10_start: times 4 dd 0x10000 -yuv2yuvX_9_start: times 4 dd 0x20000 -yuv2yuvX_10_upper: times 8 dw 0x3ff -yuv2yuvX_9_upper: times 8 dw 0x1ff -pd_4: times 4 dd 4 -pd_4min0x40000:times 4 dd 4 - (0x40000) -pw_16: times 8 dw 16 -pw_32: times 8 dw 32 -pw_512: times 8 dw 512 -pw_1024: times 8 dw 1024 SECTION .text @@ -439,371 +427,3 @@ INIT_XMM SCALE_FUNCS2 sse2, 6, 7, 8 SCALE_FUNCS2 ssse3, 6, 6, 8 SCALE_FUNCS2 sse4, 6, 6, 8 - -;----------------------------------------------------------------------------- -; vertical line scaling -; -; void yuv2plane1__(const int16_t *src, uint8_t *dst, int dstW, -; const uint8_t *dither, int offset) -; and -; void yuv2planeX__(const int16_t *filter, int filterSize, -; const int16_t **src, uint8_t *dst, int dstW, -; const uint8_t *dither, int offset) -; -; Scale one or $filterSize lines of source data to generate one line of output -; data. The input is 15-bit in int16_t if $output_size is [8,10] and 19-bit in -; int32_t if $output_size is 16. $filter is 12-bits. $filterSize is a multiple -; of 2. $offset is either 0 or 3. $dither holds 8 values. -;----------------------------------------------------------------------------- - -%macro yuv2planeX_fn 4 - -%ifdef ARCH_X86_32 -%define cntr_reg r1 -%define movsx mov -%else -%define cntr_reg r11 -%define movsx movsxd -%endif - -cglobal yuv2planeX_%2_%1, %4, 7, %3 -%if %2 == 8 || %2 == 9 || %2 == 10 - pxor m6, m6 -%endif ; %2 == 8/9/10 - -%if %2 == 8 -%ifdef ARCH_X86_32 -%assign pad 0x2c - (stack_offset & 15) - SUB rsp, pad -%define m_dith m7 -%else ; x86-64 -%define m_dith m9 -%endif ; x86-32 - - ; create registers holding dither - movq m_dith, [r5] ; dither - test r6d, r6d - jz .no_rot -%if mmsize == 16 - punpcklqdq m_dith, m_dith -%endif ; mmsize == 16 - PALIGNR m_dith, m_dith, 3, m0 -.no_rot: -%if mmsize == 16 - punpcklbw m_dith, m6 -%ifdef ARCH_X86_64 - punpcklwd m8, m_dith, m6 - pslld m8, 12 -%else ; x86-32 - punpcklwd m5, m_dith, m6 - pslld m5, 12 -%endif ; x86-32/64 - punpckhwd m_dith, m6 - pslld m_dith, 12 -%ifdef ARCH_X86_32 - mova [rsp+ 0], m5 - mova [rsp+16], m_dith -%endif -%else ; mmsize == 8 - punpcklbw m5, m_dith, m6 - punpckhbw m_dith, m6 - punpcklwd m4, m5, m6 - punpckhwd m5, m6 - punpcklwd m3, m_dith, m6 - punpckhwd m_dith, m6 - pslld m4, 12 - pslld m5, 12 - pslld m3, 12 - pslld m_dith, 12 - mova [rsp+ 0], m4 - mova [rsp+ 8], m5 - mova [rsp+16], m3 - mova [rsp+24], m_dith -%endif ; mmsize == 8/16 -%endif ; %2 == 8 - - xor r5, r5 - -.pixelloop: -%assign %%i 0 - ; the rep here is for the 8bit output mmx case, where dither covers - ; 8 pixels but we can only handle 2 pixels per register, and thus 4 - ; pixels per iteration. In order to not have to keep track of where - ; we are w.r.t. dithering, we unroll the mmx/8bit loop x2. -%if %2 == 8 -%rep 16/mmsize -%endif ; %2 == 8 - -%if %2 == 8 -%ifdef ARCH_X86_32 - mova m2, [rsp+mmsize*(0+%%i)] - mova m1, [rsp+mmsize*(1+%%i)] -%else ; x86-64 - mova m2, m8 - mova m1, m_dith -%endif ; x86-32/64 -%else ; %2 == 9/10/16 - mova m1, [yuv2yuvX_%2_start] - mova m2, m1 -%endif ; %2 == 8/9/10/16 - movsx cntr_reg, r1m -.filterloop_ %+ %%i: - ; input pixels - mov r6, [r2+gprsize*cntr_reg-2*gprsize] -%if %2 == 16 - mova m3, [r6+r5*4] - mova m5, [r6+r5*4+mmsize] -%else ; %2 == 8/9/10 - mova m3, [r6+r5*2] -%endif ; %2 == 8/9/10/16 - mov r6, [r2+gprsize*cntr_reg-gprsize] -%if %2 == 16 - mova m4, [r6+r5*4] - mova m6, [r6+r5*4+mmsize] -%else ; %2 == 8/9/10 - mova m4, [r6+r5*2] -%endif ; %2 == 8/9/10/16 - - ; coefficients - movd m0, [r0+2*cntr_reg-4]; coeff[0], coeff[1] -%if %2 == 16 - pshuflw m7, m0, 0 ; coeff[0] - pshuflw m0, m0, 0x55 ; coeff[1] - pmovsxwd m7, m7 ; word -> dword - pmovsxwd m0, m0 ; word -> dword - - pmulld m3, m7 - pmulld m5, m7 - pmulld m4, m0 - pmulld m6, m0 - - paddd m2, m3 - paddd m1, m5 - paddd m2, m4 - paddd m1, m6 -%else ; %2 == 10/9/8 - punpcklwd m5, m3, m4 - punpckhwd m3, m4 - SPLATD m0, m0 - - pmaddwd m5, m0 - pmaddwd m3, m0 - - paddd m2, m5 - paddd m1, m3 -%endif ; %2 == 8/9/10/16 - - sub cntr_reg, 2 - jg .filterloop_ %+ %%i - -%if %2 == 16 - psrad m2, 31 - %2 - psrad m1, 31 - %2 -%else ; %2 == 10/9/8 - psrad m2, 27 - %2 - psrad m1, 27 - %2 -%endif ; %2 == 8/9/10/16 - -%if %2 == 8 - packssdw m2, m1 - packuswb m2, m2 - movh [r3+r5*1], m2 -%else ; %2 == 9/10/16 -%if %2 == 16 - packssdw m2, m1 - paddw m2, [minshort] -%else ; %2 == 9/10 -%ifidn %1, sse4 - packusdw m2, m1 -%elifidn %1, avx - packusdw m2, m1 -%else ; mmx2/sse2 - packssdw m2, m1 - pmaxsw m2, m6 -%endif ; mmx2/sse2/sse4/avx - pminsw m2, [yuv2yuvX_%2_upper] -%endif ; %2 == 9/10/16 - mova [r3+r5*2], m2 -%endif ; %2 == 8/9/10/16 - - add r5, mmsize/2 - sub r4d, mmsize/2 -%if %2 == 8 -%assign %%i %%i+2 -%endrep -%endif ; %2 == 8 - jg .pixelloop - -%if %2 == 8 -%ifdef ARCH_X86_32 - ADD rsp, pad - RET -%else ; x86-64 - REP_RET -%endif ; x86-32/64 -%else ; %2 == 9/10/16 - REP_RET -%endif ; %2 == 8/9/10/16 -%endmacro - -%define PALIGNR PALIGNR_MMX -%ifdef ARCH_X86_32 -INIT_MMX -yuv2planeX_fn mmx2, 8, 0, 7 -yuv2planeX_fn mmx2, 9, 0, 5 -yuv2planeX_fn mmx2, 10, 0, 5 -%endif - -INIT_XMM -yuv2planeX_fn sse2, 8, 10, 7 -yuv2planeX_fn sse2, 9, 7, 5 -yuv2planeX_fn sse2, 10, 7, 5 - -%define PALIGNR PALIGNR_SSSE3 -yuv2planeX_fn sse4, 8, 10, 7 -yuv2planeX_fn sse4, 9, 7, 5 -yuv2planeX_fn sse4, 10, 7, 5 -yuv2planeX_fn sse4, 16, 8, 5 - -INIT_AVX -yuv2planeX_fn avx, 8, 10, 7 -yuv2planeX_fn avx, 9, 7, 5 -yuv2planeX_fn avx, 10, 7, 5 - -; %1=outout-bpc, %2=alignment (u/a) -%macro yuv2plane1_mainloop 2 -.loop_%2: -%if %1 == 8 - paddsw m0, m2, [r0+r2*2+mmsize*0] - paddsw m1, m3, [r0+r2*2+mmsize*1] - psraw m0, 7 - psraw m1, 7 - packuswb m0, m1 - mov%2 [r1+r2], m0 -%elif %1 == 16 - paddd m0, m4, [r0+r2*4+mmsize*0] - paddd m1, m4, [r0+r2*4+mmsize*1] - paddd m2, m4, [r0+r2*4+mmsize*2] - paddd m3, m4, [r0+r2*4+mmsize*3] - psrad m0, 3 - psrad m1, 3 - psrad m2, 3 - psrad m3, 3 -%if cpuflag(sse4) ; avx/sse4 - packusdw m0, m1 - packusdw m2, m3 -%else ; mmx/sse2 - packssdw m0, m1 - packssdw m2, m3 - paddw m0, m5 - paddw m2, m5 -%endif ; mmx/sse2/sse4/avx - mov%2 [r1+r2*2], m0 - mov%2 [r1+r2*2+mmsize], m2 -%else - paddsw m0, m2, [r0+r2*2+mmsize*0] - paddsw m1, m2, [r0+r2*2+mmsize*1] - psraw m0, 15 - %1 - psraw m1, 15 - %1 - pmaxsw m0, m4 - pmaxsw m1, m4 - pminsw m0, m3 - pminsw m1, m3 - mov%2 [r1+r2*2], m0 - mov%2 [r1+r2*2+mmsize], m1 -%endif - add r2, mmsize - jl .loop_%2 -%endmacro - -%macro yuv2plane1_fn 3 -cglobal yuv2plane1_%1, %3, %3, %2 - add r2, mmsize - 1 - and r2, ~(mmsize - 1) -%if %1 == 8 - add r1, r2 -%else ; %1 != 8 - lea r1, [r1+r2*2] -%endif ; %1 == 8 -%if %1 == 16 - lea r0, [r0+r2*4] -%else ; %1 != 16 - lea r0, [r0+r2*2] -%endif ; %1 == 16 - neg r2 - -%if %1 == 8 - pxor m4, m4 ; zero - - ; create registers holding dither - movq m3, [r3] ; dither - test r4d, r4d - jz .no_rot -%if mmsize == 16 - punpcklqdq m3, m3 -%endif ; mmsize == 16 - PALIGNR_MMX m3, m3, 3, m2 -.no_rot: -%if mmsize == 8 - mova m2, m3 - punpckhbw m3, m4 ; byte->word - punpcklbw m2, m4 ; byte->word -%else - punpcklbw m3, m4 - mova m2, m3 -%endif -%elif %1 == 9 - pxor m4, m4 - mova m3, [pw_512] - mova m2, [pw_32] -%elif %1 == 10 - pxor m4, m4 - mova m3, [pw_1024] - mova m2, [pw_16] -%else ; %1 == 16 -%if cpuflag(sse4) ; sse4/avx - mova m4, [pd_4] -%else ; mmx/sse2 - mova m4, [pd_4min0x40000] - mova m5, [minshort] -%endif ; mmx/sse2/sse4/avx -%endif ; %1 == .. - - ; actual pixel scaling -%if mmsize == 8 - yuv2plane1_mainloop %1, a -%else ; mmsize == 16 - test r1, 15 - jnz .unaligned - yuv2plane1_mainloop %1, a - REP_RET -.unaligned: - yuv2plane1_mainloop %1, u -%endif ; mmsize == 8/16 - REP_RET -%endmacro - -%ifdef ARCH_X86_32 -INIT_MMX mmx -yuv2plane1_fn 8, 0, 5 -yuv2plane1_fn 16, 0, 3 - -INIT_MMX mmx2 -yuv2plane1_fn 9, 0, 3 -yuv2plane1_fn 10, 0, 3 -%endif - -INIT_XMM sse2 -yuv2plane1_fn 8, 5, 5 -yuv2plane1_fn 9, 5, 3 -yuv2plane1_fn 10, 5, 3 -yuv2plane1_fn 16, 6, 3 - -INIT_XMM sse4 -yuv2plane1_fn 16, 5, 3 - -INIT_XMM avx -yuv2plane1_fn 8, 5, 5 -yuv2plane1_fn 9, 5, 3 -yuv2plane1_fn 10, 5, 3 -yuv2plane1_fn 16, 5, 3 From 6b3995ccd1c83e8d1d81d84ac78eedc96598c777 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Mon, 2 Jan 2012 12:46:40 -0800 Subject: [PATCH 26/46] swscale: remove obsolete comment. --- libswscale/swscale.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index cb5c6e9cd0..11bb7d6c3f 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -18,39 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* - supported Input formats: YV12, I420/IYUV, YUY2, UYVY, BGR32, BGR32_1, BGR24, BGR16, BGR15, RGB32, RGB32_1, RGB24, Y8/Y800, YVU9/IF09, PAL8 - supported output formats: YV12, I420/IYUV, YUY2, UYVY, {BGR,RGB}{1,4,8,15,16,24,32}, Y8/Y800, YVU9/IF09 - {BGR,RGB}{1,4,8,15,16} support dithering - - unscaled special converters (YV12=I420=IYUV, Y800=Y8) - YV12 -> {BGR,RGB}{1,4,8,12,15,16,24,32} - x -> x - YUV9 -> YV12 - YUV9/YV12 -> Y800 - Y800 -> YUV9/YV12 - BGR24 -> BGR32 & RGB24 -> RGB32 - BGR32 -> BGR24 & RGB32 -> RGB24 - BGR15 -> BGR16 -*/ - -/* -tested special converters (most are tested actually, but I did not write it down ...) - YV12 -> BGR12/BGR16 - YV12 -> YV12 - BGR15 -> BGR16 - BGR16 -> BGR16 - YVU9 -> YV12 - -untested special converters - YV12/I420 -> BGR15/BGR24/BGR32 (it is the yuv2rgb stuff, so it should be OK) - YV12/I420 -> YV12/I420 - YUY2/BGR15/BGR24/BGR32/RGB24/RGB32 -> same format - BGR24 -> BGR32 & RGB24 -> RGB32 - BGR32 -> BGR24 & RGB32 -> RGB24 - BGR24 -> YV12 -*/ - #include #include #include From 0749720b6cdce68e4908dc59f1b4e1399852372b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 30 Dec 2011 12:39:03 +0200 Subject: [PATCH 27/46] avplay: Don't call avio_set_interrupt_cb(NULL) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we don't use avio_set_interrupt_cb for interrupt callbacks, we don't need to call it to reset the interrupt cb either. This avoids a warning about use of deprecated functions. Signed-off-by: Martin Storsjö --- avplay.c | 1 - 1 file changed, 1 deletion(-) diff --git a/avplay.c b/avplay.c index 6dbf140135..3bbb7ef1a2 100644 --- a/avplay.c +++ b/avplay.c @@ -2599,7 +2599,6 @@ static int decode_thread(void *arg) if (is->ic) { avformat_close_input(&is->ic); } - avio_set_interrupt_cb(NULL); if (ret != 0) { SDL_Event event; From 98f24ecd6cfc9c57a555aae6bfcd3d9a4ce9503d Mon Sep 17 00:00:00 2001 From: Christophe GISQUET Date: Sun, 1 Jan 2012 15:28:47 +0100 Subject: [PATCH 28/46] rv34: joint coefficient decoding and dequantization Perform dequantization while decoding coefficients instead of performing it on the entire coefficients buffer. Since quantized coefficients are very sparse, this usually causes a small speedup. Speedup of around 1% on Panda board compared to the removed here neon code. Global speedup is probably around 3%. Signed-off-by: Kostya Shishkov --- libavcodec/arm/rv34dsp_init_neon.c | 3 -- libavcodec/arm/rv34dsp_neon.S | 24 --------- libavcodec/rv34.c | 80 ++++++++++++++++-------------- libavcodec/rv34data.h | 10 ---- libavcodec/rv34dsp.c | 16 ------ libavcodec/rv34dsp.h | 1 - 6 files changed, 44 insertions(+), 90 deletions(-) diff --git a/libavcodec/arm/rv34dsp_init_neon.c b/libavcodec/arm/rv34dsp_init_neon.c index acf2a7dcd3..9a09fde7a9 100644 --- a/libavcodec/arm/rv34dsp_init_neon.c +++ b/libavcodec/arm/rv34dsp_init_neon.c @@ -25,12 +25,9 @@ void ff_rv34_inv_transform_neon(DCTELEM *block); void ff_rv34_inv_transform_noround_neon(DCTELEM *block); -void ff_rv34_dequant4x4_neon(DCTELEM *block, int Qdc, int Q); void ff_rv34dsp_init_neon(RV34DSPContext *c, DSPContext* dsp) { c->rv34_inv_transform_tab[0] = ff_rv34_inv_transform_neon; c->rv34_inv_transform_tab[1] = ff_rv34_inv_transform_noround_neon; - - c->rv34_dequant4x4 = ff_rv34_dequant4x4_neon; } diff --git a/libavcodec/arm/rv34dsp_neon.S b/libavcodec/arm/rv34dsp_neon.S index 423b537fb9..f700f5c321 100644 --- a/libavcodec/arm/rv34dsp_neon.S +++ b/libavcodec/arm/rv34dsp_neon.S @@ -107,27 +107,3 @@ function ff_rv34_inv_transform_noround_neon, export=1 vst4.16 {d0[3], d1[3], d2[3], d3[3]}, [r2,:64], r1 bx lr endfunc - -function ff_rv34_dequant4x4_neon, export=1 - mov r3, r0 - mov r12, #16 - vdup.16 q0, r2 - vmov.16 d0[0], r1 - vld1.16 {d2}, [r0,:64], r12 - vld1.16 {d4}, [r0,:64], r12 - vld1.16 {d6}, [r0,:64], r12 - vld1.16 {d16}, [r0,:64], r12 - vmull.s16 q1, d2, d0 - vmull.s16 q2, d4, d1 - vmull.s16 q3, d6, d1 - vmull.s16 q8, d16, d1 - vqrshrn.s32 d2, q1, #4 - vqrshrn.s32 d4, q2, #4 - vqrshrn.s32 d6, q3, #4 - vqrshrn.s32 d16, q8, #4 - vst1.16 {d2}, [r3,:64], r12 - vst1.16 {d4}, [r3,:64], r12 - vst1.16 {d6}, [r3,:64], r12 - vst1.16 {d16}, [r3,:64], r12 - bx lr -endfunc diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index 1a126be2f9..db2e53aaa5 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -212,7 +212,7 @@ static int rv34_decode_cbp(GetBitContext *gb, RV34VLC *vlc, int table) /** * Get one coefficient value from the bistream and store it. */ -static inline void decode_coeff(DCTELEM *dst, int coef, int esc, GetBitContext *gb, VLC* vlc) +static inline void decode_coeff(DCTELEM *dst, int coef, int esc, GetBitContext *gb, VLC* vlc, int q) { if(coef){ if(coef == esc){ @@ -225,14 +225,14 @@ static inline void decode_coeff(DCTELEM *dst, int coef, int esc, GetBitContext * } if(get_bits1(gb)) coef = -coef; - *dst = coef; + *dst = (coef*q + 8) >> 4; } } /** * Decode 2x2 subblock of coefficients. */ -static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc) +static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc, int q) { int coeffs[4]; @@ -240,15 +240,35 @@ static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, coeffs[1] = modulo_three_table[code][1]; coeffs[2] = modulo_three_table[code][2]; coeffs[3] = modulo_three_table[code][3]; - decode_coeff(dst , coeffs[0], 3, gb, vlc); + decode_coeff(dst , coeffs[0], 3, gb, vlc, q); if(is_block2){ - decode_coeff(dst+8, coeffs[1], 2, gb, vlc); - decode_coeff(dst+1, coeffs[2], 2, gb, vlc); + decode_coeff(dst+8, coeffs[1], 2, gb, vlc, q); + decode_coeff(dst+1, coeffs[2], 2, gb, vlc, q); }else{ - decode_coeff(dst+1, coeffs[1], 2, gb, vlc); - decode_coeff(dst+8, coeffs[2], 2, gb, vlc); + decode_coeff(dst+1, coeffs[1], 2, gb, vlc, q); + decode_coeff(dst+8, coeffs[2], 2, gb, vlc, q); } - decode_coeff(dst+9, coeffs[3], 2, gb, vlc); + decode_coeff(dst+9, coeffs[3], 2, gb, vlc, q); +} + +static inline void decode_subblock3(DCTELEM *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc, + int q_dc, int q_ac1, int q_ac2) +{ + int coeffs[4]; + + coeffs[0] = modulo_three_table[code][0]; + coeffs[1] = modulo_three_table[code][1]; + coeffs[2] = modulo_three_table[code][2]; + coeffs[3] = modulo_three_table[code][3]; + decode_coeff(dst , coeffs[0], 3, gb, vlc, q_dc); + if(is_block2){ + decode_coeff(dst+8, coeffs[1], 2, gb, vlc, q_ac1); + decode_coeff(dst+1, coeffs[2], 2, gb, vlc, q_ac1); + }else{ + decode_coeff(dst+1, coeffs[1], 2, gb, vlc, q_ac1); + decode_coeff(dst+8, coeffs[2], 2, gb, vlc, q_ac1); + } + decode_coeff(dst+9, coeffs[3], 2, gb, vlc, q_ac2); } /** @@ -262,7 +282,7 @@ static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, * o--o */ -static inline void rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc) +static inline void rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc, int q_dc, int q_ac1, int q_ac2) { int code, pattern; @@ -271,39 +291,23 @@ static inline void rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *r pattern = code & 0x7; code >>= 3; - decode_subblock(dst, code, 0, gb, &rvlc->coefficient); + decode_subblock3(dst, code, 0, gb, &rvlc->coefficient, q_dc, q_ac1, q_ac2); if(pattern & 4){ code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); - decode_subblock(dst + 2, code, 0, gb, &rvlc->coefficient); + decode_subblock(dst + 2, code, 0, gb, &rvlc->coefficient, q_ac2); } if(pattern & 2){ // Looks like coefficients 1 and 2 are swapped for this block code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); - decode_subblock(dst + 8*2, code, 1, gb, &rvlc->coefficient); + decode_subblock(dst + 8*2, code, 1, gb, &rvlc->coefficient, q_ac2); } if(pattern & 1){ code = get_vlc2(gb, rvlc->third_pattern[sc].table, 9, 2); - decode_subblock(dst + 8*2+2, code, 0, gb, &rvlc->coefficient); + decode_subblock(dst + 8*2+2, code, 0, gb, &rvlc->coefficient, q_ac2); } } -/** - * Dequantize 4x4 block of DC values for 16x16 macroblock. - * @todo optimize - */ -static inline void rv34_dequant4x4_16x16(DCTELEM *block, int Qdc, int Q) -{ - int i; - - for(i = 0; i < 3; i++) - block[rv34_dezigzag[i]] = (block[rv34_dezigzag[i]] * Qdc + 8) >> 4; - for(; i < 16; i++) - block[rv34_dezigzag[i]] = (block[rv34_dezigzag[i]] * Q + 8) >> 4; -} -/** @} */ //block functions - - /** * @name RV30/40 bitstream parsing * @{ @@ -1097,6 +1101,7 @@ static int rv34_decode_macroblock(RV34DecContext *r, int8_t *intra_types) MpegEncContext *s = &r->s; GetBitContext *gb = &s->gb; int cbp, cbp2; + int q_dc, q_ac; int i, blknum, blkoff; LOCAL_ALIGNED_16(DCTELEM, block16, [64]); int luma_dc_quant; @@ -1133,31 +1138,34 @@ static int rv34_decode_macroblock(RV34DecContext *r, int8_t *intra_types) luma_dc_quant = r->block_type == RV34_MB_P_MIX16x16 ? r->luma_dc_quant_p[s->qscale] : r->luma_dc_quant_i[s->qscale]; if(r->is16){ + q_dc = rv34_qscale_tab[luma_dc_quant]; + q_ac = rv34_qscale_tab[s->qscale]; memset(block16, 0, 64 * sizeof(*block16)); - rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0); - rv34_dequant4x4_16x16(block16, rv34_qscale_tab[luma_dc_quant],rv34_qscale_tab[s->qscale]); + rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac); r->rdsp.rv34_inv_transform_tab[1](block16); } + q_ac = rv34_qscale_tab[s->qscale]; for(i = 0; i < 16; i++, cbp >>= 1){ if(!r->is16 && !(cbp & 1)) continue; blknum = ((i & 2) >> 1) + ((i & 8) >> 2); blkoff = ((i & 1) << 2) + ((i & 4) << 3); if(cbp & 1) - rv34_decode_block(s->block[blknum] + blkoff, gb, r->cur_vlcs, r->luma_vlc, 0); - r->rdsp.rv34_dequant4x4(s->block[blknum] + blkoff, rv34_qscale_tab[s->qscale],rv34_qscale_tab[s->qscale]); + rv34_decode_block(s->block[blknum] + blkoff, gb, + r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac); if(r->is16) //FIXME: optimize s->block[blknum][blkoff] = block16[(i & 3) | ((i & 0xC) << 1)]; r->rdsp.rv34_inv_transform_tab[0](s->block[blknum] + blkoff); } if(r->block_type == RV34_MB_P_MIX16x16) r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1); + q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]]; + q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]; for(; i < 24; i++, cbp >>= 1){ if(!(cbp & 1)) continue; blknum = ((i & 4) >> 2) + 4; blkoff = ((i & 1) << 2) + ((i & 2) << 4); - rv34_decode_block(s->block[blknum] + blkoff, gb, r->cur_vlcs, r->chroma_vlc, 1); - r->rdsp.rv34_dequant4x4(s->block[blknum] + blkoff, rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]],rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]); + rv34_decode_block(s->block[blknum] + blkoff, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac); r->rdsp.rv34_inv_transform_tab[0](s->block[blknum] + blkoff); } if (IS_INTRA(s->current_picture_ptr->f.mb_type[mb_pos])) diff --git a/libavcodec/rv34data.h b/libavcodec/rv34data.h index f8f941d061..fa41a882a6 100644 --- a/libavcodec/rv34data.h +++ b/libavcodec/rv34data.h @@ -100,16 +100,6 @@ static const uint16_t rv34_qscale_tab[32] = { 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211 }; -/** - * 4x4 dezigzag pattern - */ -static const uint8_t rv34_dezigzag[16] = { - 0, 1, 8, 16, - 9, 2, 3, 10, - 17, 24, 25, 18, - 11, 19, 26, 27 -}; - /** * tables used to translate a quantizer value into a VLC set for decoding * The first table is used for intraframes. diff --git a/libavcodec/rv34dsp.c b/libavcodec/rv34dsp.c index 974bf9ec16..1f4cea8544 100644 --- a/libavcodec/rv34dsp.c +++ b/libavcodec/rv34dsp.c @@ -100,26 +100,10 @@ static void rv34_inv_transform_noround_c(DCTELEM *block){ /** @} */ // transform -/** - * Dequantize ordinary 4x4 block. - */ -void ff_rv34_dequant4x4_neon(DCTELEM *block, int Qdc, int Q); -static void rv34_dequant4x4_c(DCTELEM *block, int Qdc, int Q) -{ - int i, j; - - block[0] = (block[0] * Qdc + 8) >> 4; - for (i = 0; i < 4; i++) - for (j = !i; j < 4; j++) - block[j + i*8] = (block[j + i*8] * Q + 8) >> 4; -} - av_cold void ff_rv34dsp_init(RV34DSPContext *c, DSPContext* dsp) { c->rv34_inv_transform_tab[0] = rv34_inv_transform_c; c->rv34_inv_transform_tab[1] = rv34_inv_transform_noround_c; - c->rv34_dequant4x4 = rv34_dequant4x4_c; - if (HAVE_NEON) ff_rv34dsp_init_neon(c, dsp); } diff --git a/libavcodec/rv34dsp.h b/libavcodec/rv34dsp.h index 01352ea793..f2bc20e911 100644 --- a/libavcodec/rv34dsp.h +++ b/libavcodec/rv34dsp.h @@ -56,7 +56,6 @@ typedef struct RV34DSPContext { h264_chroma_mc_func avg_chroma_pixels_tab[3]; rv40_weight_func rv40_weight_pixels_tab[2]; rv34_inv_transform_func rv34_inv_transform_tab[2]; - void (*rv34_dequant4x4)(DCTELEM *block, int Qdc, int Q); rv40_weak_loop_filter_func rv40_weak_loop_filter[2]; rv40_strong_loop_filter_func rv40_strong_loop_filter[2]; rv40_loop_filter_strength_func rv40_loop_filter_strength[2]; From aacf6b3a2fd8bc8603e3deaa6e612ea03cf08707 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Tue, 3 Jan 2012 23:27:35 -0700 Subject: [PATCH 29/46] rv34: fix invalid memory access for small video dimensions For small video dimensions calculations of the upper bound for pixel access may result in negative value. Using an unsigned comparison works only if the greater operand is non-negative. This is fixed by doing edge emulation explicitly for such conditions. Signed-off-by: Kostya Shishkov --- libavcodec/rv34.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index db2e53aaa5..91d678876a 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -680,8 +680,9 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, srcY += src_y * s->linesize + src_x; srcU += uvsrc_y * s->uvlinesize + uvsrc_x; srcV += uvsrc_y * s->uvlinesize + uvsrc_x; - if( (unsigned)(src_x - !!lx*2) > s->h_edge_pos - !!lx*2 - (width <<3) - 4 - || (unsigned)(src_y - !!ly*2) > s->v_edge_pos - !!ly*2 - (height<<3) - 4){ + if(s->h_edge_pos - (width << 3) < 6 || s->v_edge_pos - (height << 3) < 6 || + (unsigned)(src_x - !!lx*2) > s->h_edge_pos - !!lx*2 - (width <<3) - 4 || + (unsigned)(src_y - !!ly*2) > s->v_edge_pos - !!ly*2 - (height<<3) - 4) { uint8_t *uvbuf = s->edge_emu_buffer + 22 * s->linesize; srcY -= 2 + 2*s->linesize; From d209c27b09234cc40bbdbd680aa502b493edf595 Mon Sep 17 00:00:00 2001 From: John Brooks Date: Sun, 11 Dec 2011 02:37:21 -0700 Subject: [PATCH 30/46] vc1dec: fix invalid memory access for small video dimensions For small video dimensions, these calculations of the upper bound for pixel access may have a negative result. Using an unsigned comparison to bound a potentially negative value only works if the greater operand is non-negative. Fixed by doing edge emulation when the upper bound is probably negative, everywhere that this pattern appears. Signed-off-by: Kostya Shishkov --- libavcodec/vc1dec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 3cb7661397..bc8daed7af 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -568,6 +568,7 @@ static void vc1_mc_1mv(VC1Context *v, int dir) } if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + || s->h_edge_pos < 22 || v_edge_pos < 22 || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel * 3 || (unsigned)(src_y - s->mspel) > v_edge_pos - (my&3) - 16 - s->mspel * 3) { uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; @@ -799,6 +800,7 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) if (fieldmv && (src_y & 1) && src_y < 4) src_y--; if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + || s->h_edge_pos < 13 || v_edge_pos < 23 || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 8 - s->mspel * 2 || (unsigned)(src_y - (s->mspel << fieldmv)) > v_edge_pos - (my & 3) - ((8 + s->mspel * 2) << fieldmv)) { srcY -= s->mspel * (1 + (s->linesize << fieldmv)); @@ -998,6 +1000,7 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) } if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) + || s->h_edge_pos < 18 || v_edge_pos < 18 || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9 || (unsigned)uvsrc_y > (v_edge_pos >> 1) - 9) { s->dsp.emulated_edge_mc(s->edge_emu_buffer , srcU, s->uvlinesize, @@ -1102,6 +1105,7 @@ static void vc1_mc_4mv_chroma4(VC1Context *v) if (fieldmv && (uvsrc_y & 1) && uvsrc_y < 2) uvsrc_y--; if ((v->mv_mode == MV_PMODE_INTENSITY_COMP) + || s->h_edge_pos < 10 || v_edge_pos < (5 << fieldmv) || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 5 || (unsigned)uvsrc_y > v_edge_pos - (5 << fieldmv)) { s->dsp.emulated_edge_mc(s->edge_emu_buffer, srcU, s->uvlinesize, @@ -2006,7 +2010,7 @@ static void vc1_interp_mc(VC1Context *v) srcV = s->edge_emu_buffer + 18 * s->linesize; } - if (v->rangeredfrm + if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 16 - s->mspel * 3 || (unsigned)(src_y - s->mspel) > v_edge_pos - (my & 3) - 16 - s->mspel * 3) { uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; From a2d1d216291fd8c1f4a8b3bad4f0b50c084ba96d Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 3 Jan 2012 18:11:36 +0100 Subject: [PATCH 31/46] avio: exit early in fill_buffer without read_packet Fixes an invalid free() with ass in avi. The sample in bug 98 passes parts of AVPacket.data as buffer for the AVIOContext. Since the packet is quite large fill_buffer tries to reallocate the buffer before doing nothing. Fixes bug 98. --- libavformat/aviobuf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 898f35d903..dbbbba5535 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -565,6 +565,10 @@ static void fill_buffer(AVIOContext *s) int len= s->buffer_size - (dst - s->buffer); int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; + /* can't fill the buffer without read_packet, just set EOF if appropiate */ + if (!s->read_packet && s->buf_ptr >= s->buf_end) + s->eof_reached = 1; + /* no need to do anything if EOF already reached */ if (s->eof_reached) return; From af7123b2ad1f5eea8111d0165b64271a9a096265 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 21 Nov 2011 17:03:46 +0100 Subject: [PATCH 32/46] v4l2: do not force interlaced mode Video4linux2 supports both interlaced and non-interlaced mode, do not ask for interlaced if not necessary. --- libavdevice/v4l2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index eb16171c31..a9e32bbfb4 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -64,6 +64,7 @@ struct video_data { enum io_method io_method; int width, height; int frame_size; + int interlaced; int top_field_first; int buffers; @@ -162,7 +163,7 @@ static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t p fmt.fmt.pix.width = *width; fmt.fmt.pix.height = *height; fmt.fmt.pix.pixelformat = pix_fmt; - fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + fmt.fmt.pix.field = V4L2_FIELD_ANY; res = ioctl(fd, VIDIOC_S_FMT, &fmt); if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) { av_log(ctx, AV_LOG_INFO, "The V4L2 driver changed the video from %dx%d to %dx%d\n", *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height); @@ -175,6 +176,11 @@ static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t p res = -1; } + if (fmt.fmt.pix.field == V4L2_FIELD_INTERLACED) { + av_log(ctx, AV_LOG_DEBUG, "The V4L2 driver using the interlaced mode"); + s->interlaced = 1; + } + return res; } @@ -686,7 +692,7 @@ static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) return res; } - if (s1->streams[0]->codec->coded_frame) { + if (s1->streams[0]->codec->coded_frame && s->interlaced) { s1->streams[0]->codec->coded_frame->interlaced_frame = 1; s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first; } From 21aa6ae4fba26597f414bbd28bde129b44f1481d Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 27 Dec 2011 03:38:13 +0100 Subject: [PATCH 33/46] v4l2: uniform and format options --- libavdevice/v4l2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index a9e32bbfb4..b21c180ba2 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -715,11 +715,11 @@ static int v4l2_read_close(AVFormatContext *s1) #define OFFSET(x) offsetof(struct video_data, x) #define DEC AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { - { "standard", "", offsetof(struct video_data, standard), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, - { "channel", "", offsetof(struct video_data, channel), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, - { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, - { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "standard", "TV standard, used only by analog frame grabber", OFFSET(standard), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC }, + { "channel", "TV channel, used only by frame grabber", OFFSET(channel), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC }, + { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { NULL }, }; From a896d7f45acbafd1e7bbc8544c1b74a3c087bdf9 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 27 Dec 2011 05:37:58 +0100 Subject: [PATCH 34/46] v4l2: cosmetics --- libavdevice/v4l2.c | 139 ++++++++++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 45 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index b21c180ba2..3851118bdc 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -117,10 +117,11 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities) if (ctx->flags & AVFMT_FLAG_NONBLOCK) { flags |= O_NONBLOCK; } + fd = open(ctx->filename, flags, 0); if (fd < 0) { av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n", - ctx->filename, strerror(errno)); + ctx->filename, strerror(errno)); return AVERROR(errno); } @@ -128,11 +129,14 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities) res = ioctl(fd, VIDIOC_QUERYCAP, &cap); // ENOIOCTLCMD definition only availble on __KERNEL__ if (res < 0 && ((err = errno) == 515)) { - av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n"); + av_log(ctx, AV_LOG_ERROR, + "QUERYCAP not implemented, probably V4L device but " + "not supporting V4L2\n"); close(fd); return AVERROR(515); } + if (res < 0) { av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", strerror(errno)); @@ -140,39 +144,52 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities) return AVERROR(err); } + if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n"); close(fd); return AVERROR(ENODEV); } + *capabilities = cap.capabilities; return fd; } -static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pix_fmt) +static int device_init(AVFormatContext *ctx, int *width, int *height, + uint32_t pix_fmt) { struct video_data *s = ctx->priv_data; int fd = s->fd; struct v4l2_format fmt; + struct v4l2_pix_format *pix = &fmt.fmt.pix; + int res; memset(&fmt, 0, sizeof(struct v4l2_format)); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.width = *width; - fmt.fmt.pix.height = *height; - fmt.fmt.pix.pixelformat = pix_fmt; - fmt.fmt.pix.field = V4L2_FIELD_ANY; + pix->width = *width; + pix->height = *height; + pix->pixelformat = pix_fmt; + pix->field = V4L2_FIELD_ANY; + res = ioctl(fd, VIDIOC_S_FMT, &fmt); + if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) { - av_log(ctx, AV_LOG_INFO, "The V4L2 driver changed the video from %dx%d to %dx%d\n", *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height); + av_log(ctx, AV_LOG_INFO, + "The V4L2 driver changed the video from %dx%d to %dx%d\n", + *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height); *width = fmt.fmt.pix.width; *height = fmt.fmt.pix.height; } if (pix_fmt != fmt.fmt.pix.pixelformat) { - av_log(ctx, AV_LOG_DEBUG, "The V4L2 driver changed the pixel format from 0x%08X to 0x%08X\n", pix_fmt, fmt.fmt.pix.pixelformat); + av_log(ctx, AV_LOG_DEBUG, + "The V4L2 driver changed the pixel format " + "from 0x%08X to 0x%08X\n", + pix_fmt, fmt.fmt.pix.pixelformat); res = -1; } @@ -300,12 +317,16 @@ static int mmap_init(AVFormatContext *ctx) s->buf_len[i] = buf.length; if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) { - av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size); + av_log(ctx, AV_LOG_ERROR, + "Buffer len [%d] = %d != %d\n", + i, s->buf_len[i], s->frame_size); return -1; } - s->buf_start[i] = mmap (NULL, buf.length, - PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset); + s->buf_start[i] = mmap(NULL, buf.length, + PROT_READ | PROT_WRITE, MAP_SHARED, + s->fd, buf.m.offset); + if (s->buf_start[i] == MAP_FAILED) { av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno)); @@ -327,9 +348,8 @@ static void mmap_release_buffer(AVPacket *pkt) int res, fd; struct buff_data *buf_descriptor = pkt->priv; - if (pkt->data == NULL) { - return; - } + if (pkt->data == NULL) + return; memset(&buf, 0, sizeof(struct v4l2_buffer)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -339,9 +359,10 @@ static void mmap_release_buffer(AVPacket *pkt) av_free(buf_descriptor); res = ioctl(fd, VIDIOC_QBUF, &buf); - if (res < 0) { - av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno)); - } + if (res < 0) + av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", + strerror(errno)); + pkt->data = NULL; pkt->size = 0; } @@ -365,13 +386,16 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) return AVERROR(EAGAIN); } - av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno)); + av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", + strerror(errno)); return AVERROR(errno); } assert (buf.index < s->buffers); if (s->frame_size > 0 && buf.bytesused != s->frame_size) { - av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size); + av_log(ctx, AV_LOG_ERROR, + "The v4l2 frame is %d bytes, but %d bytes are expected\n", + buf.bytesused, s->frame_size); return AVERROR_INVALIDDATA; } @@ -419,7 +443,8 @@ static int mmap_start(AVFormatContext *ctx) res = ioctl(s->fd, VIDIOC_QBUF, &buf); if (res < 0) { - av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno)); + av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", + strerror(errno)); return AVERROR(errno); } @@ -428,7 +453,8 @@ static int mmap_start(AVFormatContext *ctx) type = V4L2_BUF_TYPE_VIDEO_CAPTURE; res = ioctl(s->fd, VIDIOC_STREAMON, &type); if (res < 0) { - av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno)); + av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", + strerror(errno)); return AVERROR(errno); } @@ -465,8 +491,10 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (s->framerate && (ret = av_parse_video_rate(&framerate_q, s->framerate)) < 0) { - av_log(s1, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", s->framerate); + if (s->framerate && + (ret = av_parse_video_rate(&framerate_q, s->framerate)) < 0) { + av_log(s1, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", + s->framerate); return ret; } @@ -481,7 +509,8 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n", s->channel, input.name); if (ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) { - av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n", + av_log(s1, AV_LOG_ERROR, + "The V4L2 driver ioctl set input(%d) failed\n", s->channel); return AVERROR(EIO); } @@ -494,7 +523,8 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) for(i=0;;i++) { standard.index = i; if (ioctl(s->fd, VIDIOC_ENUMSTD, &standard) < 0) { - av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n", + av_log(s1, AV_LOG_ERROR, + "The V4L2 driver ioctl set standard(%s) failed\n", s->standard); return AVERROR(EIO); } @@ -504,10 +534,12 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) } } - av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n", + av_log(s1, AV_LOG_DEBUG, + "The V4L2 driver set standard: %s, id: %"PRIu64"\n", s->standard, (uint64_t)standard.id); if (ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) { - av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n", + av_log(s1, AV_LOG_ERROR, + "The V4L2 driver ioctl set standard(%s) failed\n", s->standard); return AVERROR(EIO); } @@ -518,6 +550,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) framerate_q.den, framerate_q.num); tpf->numerator = framerate_q.den; tpf->denominator = framerate_q.num; + if (ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) { av_log(s1, AV_LOG_ERROR, "ioctl set time per frame(%d/%d) failed\n", @@ -528,14 +561,15 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) if (framerate_q.num != tpf->denominator || framerate_q.den != tpf->numerator) { av_log(s1, AV_LOG_INFO, - "The driver changed the time per frame from %d/%d to %d/%d\n", + "The driver changed the time per frame from " + "%d/%d to %d/%d\n", framerate_q.den, framerate_q.num, tpf->numerator, tpf->denominator); } } else { - /* if timebase value is not set, read the timebase value from the driver */ if (ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) { - av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", strerror(errno)); + av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", + strerror(errno)); return AVERROR(errno); } } @@ -569,6 +603,7 @@ static uint32_t device_try_init(AVFormatContext *s1, } } } + if (desired_format != 0) { *codec_id = fmt_v4l2codec(desired_format); assert(*codec_id != CODEC_ID_NONE); @@ -582,7 +617,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) struct video_data *s = s1->priv_data; AVStream *st; int res = 0; - uint32_t desired_format, capabilities; + uint32_t desired_format, capabilities = 0; enum CodecID codec_id; enum PixelFormat pix_fmt = PIX_FMT_NONE; @@ -591,19 +626,23 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) res = AVERROR(ENOMEM); goto out; } + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ - if (s->video_size && (res = av_parse_video_size(&s->width, &s->height, s->video_size)) < 0) { - av_log(s1, AV_LOG_ERROR, "Could not parse video size '%s'.\n", s->video_size); + if (s->video_size && + (res = av_parse_video_size(&s->width, &s->height, s->video_size)) < 0) { + av_log(s1, AV_LOG_ERROR, "Could not parse video size '%s'.\n", + s->video_size); goto out; } - if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) { - av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format); + if (s->pixel_format && + (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) { + av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", + s->pixel_format); res = AVERROR(EINVAL); goto out; } - capabilities = 0; s->fd = device_open(s1, &capabilities); if (s->fd < 0) { res = AVERROR(EIO); @@ -614,19 +653,24 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) if (!s->width && !s->height) { struct v4l2_format fmt; - av_log(s1, AV_LOG_VERBOSE, "Querying the device for the current frame size\n"); + av_log(s1, AV_LOG_VERBOSE, + "Querying the device for the current frame size\n"); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) { - av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", strerror(errno)); + av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", + strerror(errno)); res = AVERROR(errno); goto out; } + s->width = fmt.fmt.pix.width; s->height = fmt.fmt.pix.height; - av_log(s1, AV_LOG_VERBOSE, "Setting frame size to %dx%d\n", s->width, s->height); + av_log(s1, AV_LOG_VERBOSE, + "Setting frame size to %dx%d\n", s->width, s->height); } - desired_format = device_try_init(s1, pix_fmt, &s->width, &s->height, &codec_id); + desired_format = device_try_init(s1, pix_fmt, &s->width, &s->height, + &codec_id); if (desired_format == 0) { av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for " "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, pix_fmt); @@ -635,15 +679,19 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) res = AVERROR(EIO); goto out; } + if ((res = av_image_check_size(s->width, s->height, 0, s1) < 0)) goto out; + s->frame_format = desired_format; if ((res = v4l2_set_parameters(s1, ap) < 0)) goto out; st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id); - s->frame_size = avpicture_get_size(st->codec->pix_fmt, s->width, s->height); + s->frame_size = + avpicture_get_size(st->codec->pix_fmt, s->width, s->height); + if (capabilities & V4L2_CAP_STREAMING) { s->io_method = io_mmap; res = mmap_init(s1); @@ -675,6 +723,7 @@ out: static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) { struct video_data *s = s1->priv_data; + AVFrame *frame = s1->streams[0]->codec->coded_frame; int res; if (s->io_method == io_mmap) { @@ -692,9 +741,9 @@ static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) return res; } - if (s1->streams[0]->codec->coded_frame && s->interlaced) { - s1->streams[0]->codec->coded_frame->interlaced_frame = 1; - s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first; + if (frame && s->interlaced) { + frame->interlaced_frame = 1; + frame->top_field_first = s->top_field_first; } return pkt->size; From 246007d37096ea096fe1d7961d5542c385911dc2 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 27 Dec 2011 05:52:02 +0100 Subject: [PATCH 35/46] v4l2: simplify away io_method Only mmap is supported. --- libavdevice/v4l2.c | 45 +++++---------------------------------------- 1 file changed, 5 insertions(+), 40 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 3851118bdc..0ed2cecba1 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -51,17 +51,10 @@ static const int desired_video_buffers = 256; -enum io_method { - io_read, - io_mmap, - io_userptr -}; - struct video_data { AVClass *class; int fd; int frame_format; /* V4L2_PIX_FMT_* */ - enum io_method io_method; int width, height; int frame_size; int interlaced; @@ -337,11 +330,6 @@ static int mmap_init(AVFormatContext *ctx) return 0; } -static int read_init(AVFormatContext *ctx) -{ - return -1; -} - static void mmap_release_buffer(AVPacket *pkt) { struct v4l2_buffer buf; @@ -422,11 +410,6 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) return s->buf_len[buf.index]; } -static int read_frame(AVFormatContext *ctx, AVPacket *pkt) -{ - return -1; -} - static int mmap_start(AVFormatContext *ctx) { struct video_data *s = ctx->priv_data; @@ -693,19 +676,13 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) avpicture_get_size(st->codec->pix_fmt, s->width, s->height); if (capabilities & V4L2_CAP_STREAMING) { - s->io_method = io_mmap; - res = mmap_init(s1); - if (res == 0) { + if (!(res = mmap_init(s1))) res = mmap_start(s1); - } } else { - s->io_method = io_read; - res = read_init(s1); + res = AVERROR(ENOSYS); } if (res < 0) { close(s->fd); - - res = AVERROR(EIO); goto out; } s->top_field_first = first_field(s->fd); @@ -726,18 +703,8 @@ static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) AVFrame *frame = s1->streams[0]->codec->coded_frame; int res; - if (s->io_method == io_mmap) { - av_init_packet(pkt); - res = mmap_read_frame(s1, pkt); - } else if (s->io_method == io_read) { - if (av_new_packet(pkt, s->frame_size) < 0) - return AVERROR(EIO); - - res = read_frame(s1, pkt); - } else { - return AVERROR(EIO); - } - if (res < 0) { + av_init_packet(pkt); + if ((res = mmap_read_frame(s1, pkt)) < 0) { return res; } @@ -753,9 +720,7 @@ static int v4l2_read_close(AVFormatContext *s1) { struct video_data *s = s1->priv_data; - if (s->io_method == io_mmap) { - mmap_close(s); - } + mmap_close(s); close(s->fd); return 0; From eb89b4fc0994d682cd3f24b882164439c8c3af28 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 27 Dec 2011 06:27:41 +0100 Subject: [PATCH 36/46] v4l2: refactor device_open Check capabilities directly in the function, further simplify the code. --- libavdevice/v4l2.c | 82 +++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 0ed2cecba1..1e4274c84b 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -100,7 +100,7 @@ static struct fmt_map fmt_conversion_table[] = { { PIX_FMT_NONE, CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG }, }; -static int device_open(AVFormatContext *ctx, uint32_t *capabilities) +static int device_open(AVFormatContext *ctx) { struct v4l2_capability cap; int fd; @@ -113,41 +113,46 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities) fd = open(ctx->filename, flags, 0); if (fd < 0) { + err = errno; + av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n", - ctx->filename, strerror(errno)); - - return AVERROR(errno); - } - - res = ioctl(fd, VIDIOC_QUERYCAP, &cap); - // ENOIOCTLCMD definition only availble on __KERNEL__ - if (res < 0 && ((err = errno) == 515)) { - av_log(ctx, AV_LOG_ERROR, - "QUERYCAP not implemented, probably V4L device but " - "not supporting V4L2\n"); - close(fd); - - return AVERROR(515); - } - - if (res < 0) { - av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", - strerror(errno)); - close(fd); + ctx->filename, strerror(err)); return AVERROR(err); } - if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { - av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n"); - close(fd); + res = ioctl(fd, VIDIOC_QUERYCAP, &cap); + if (res < 0) { + err = errno; + av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", + strerror(err)); - return AVERROR(ENODEV); + goto fail; } - *capabilities = cap.capabilities; + av_log(ctx, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n", + fd, cap.capabilities); + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + av_log(ctx, AV_LOG_ERROR, "Not a video capture device.\n"); + err = ENODEV; + + goto fail; + } + + if (!(cap.capabilities & V4L2_CAP_STREAMING)) { + av_log(ctx, AV_LOG_ERROR, + "The device does not support the streaming I/O method.\n"); + err = ENOSYS; + + goto fail; + } return fd; + +fail: + close(fd); + return AVERROR(err); } static int device_init(AVFormatContext *ctx, int *width, int *height, @@ -600,7 +605,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) struct video_data *s = s1->priv_data; AVStream *st; int res = 0; - uint32_t desired_format, capabilities = 0; + uint32_t desired_format; enum CodecID codec_id; enum PixelFormat pix_fmt = PIX_FMT_NONE; @@ -610,6 +615,12 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) goto out; } + s->fd = device_open(s1); + if (s->fd < 0) { + res = s->fd; + goto out; + } + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ if (s->video_size && @@ -626,13 +637,6 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) goto out; } - s->fd = device_open(s1, &capabilities); - if (s->fd < 0) { - res = AVERROR(EIO); - goto out; - } - av_log(s1, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n", s->fd, capabilities); - if (!s->width && !s->height) { struct v4l2_format fmt; @@ -675,16 +679,12 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) s->frame_size = avpicture_get_size(st->codec->pix_fmt, s->width, s->height); - if (capabilities & V4L2_CAP_STREAMING) { - if (!(res = mmap_init(s1))) - res = mmap_start(s1); - } else { - res = AVERROR(ENOSYS); - } - if (res < 0) { + if ((res = mmap_init(s1)) || + (res = mmap_start(s1)) < 0) { close(s->fd); goto out; } + s->top_field_first = first_field(s->fd); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; From cd2bbad3032780f8d4536aed15b3f5f45b95859c Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 27 Dec 2011 07:41:01 +0100 Subject: [PATCH 37/46] v4l2: set the proper codec_tag Unbreak direct streamcopy. --- libavdevice/v4l2.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 1e4274c84b..cde2f9f317 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -689,6 +689,9 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = codec_id; + if (codec_id == CODEC_ID_RAWVIDEO) + st->codec->codec_tag = + avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt); st->codec->width = s->width; st->codec->height = s->height; st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8; From a6a4793d045cda277f0ec4579d206b36e3cf90b6 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Tue, 27 Dec 2011 06:31:41 +0100 Subject: [PATCH 38/46] v4l2: list available formats Make use of the experimental framesize enumeration ioctl if available. --- configure | 3 ++ doc/indevs.texi | 2 +- libavdevice/v4l2.c | 99 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 96 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 481f0eacaf..9bf65d23cc 100755 --- a/configure +++ b/configure @@ -1135,6 +1135,7 @@ HAVE_LIST=" struct_sockaddr_in6 struct_sockaddr_sa_len struct_sockaddr_storage + struct_v4l2_frmivalenum_discrete symver symver_asm_label symver_gnu_asm @@ -2993,6 +2994,8 @@ texi2html -version > /dev/null 2>&1 && enable texi2html || disable texi2html check_header linux/fb.h check_header linux/videodev.h check_header linux/videodev2.h +check_struct linux/videodev2.h "struct v4l2_frmivalenum" discrete + check_header sys/videoio.h check_func_headers "windows.h vfw.h" capCreateCaptureWindow "$vfwcap_indev_extralibs" diff --git a/doc/indevs.texi b/doc/indevs.texi index 4405a5b0a1..e1b4dddbc5 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -267,7 +267,7 @@ the device. Video4Linux and Video4Linux2 devices only support a limited set of @var{width}x@var{height} sizes and framerates. You can check which are supported for example with the command @file{dov4l} for Video4Linux -devices and the command @file{v4l-info} for Video4Linux2 devices. +devices and using @command{-list_formats all} for Video4Linux2 devices. If the size for the device is set to 0x0, the input device will try to autodetect the size to use. diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index cde2f9f317..2895a01824 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -51,6 +51,10 @@ static const int desired_video_buffers = 256; +#define V4L_ALLFORMATS 3 +#define V4L_RAWFORMATS 1 +#define V4L_COMPFORMATS 2 + struct video_data { AVClass *class; int fd; @@ -65,8 +69,10 @@ struct video_data { unsigned int *buf_len; char *standard; int channel; - char *video_size; /**< String describing video size, set by a private option. */ + char *video_size; /**< String describing video size, + set by a private option. */ char *pixel_format; /**< Set by a private option. */ + int list_format; /**< Set by a private option. */ char *framerate; /**< Set by a private option. */ }; @@ -258,6 +264,69 @@ static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt) return CODEC_ID_NONE; } +#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE +static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat) +{ + struct v4l2_frmsizeenum vfse = { .pixel_format = pixelformat }; + + while(!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) { + switch (vfse.type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + av_log(ctx, AV_LOG_INFO, " %ux%u", + vfse.discrete.width, vfse.discrete.height); + break; + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + case V4L2_FRMSIZE_TYPE_STEPWISE: + av_log(ctx, AV_LOG_INFO, " {%u-%u, %u}x{%u-%u, %u}", + vfse.stepwise.min_width, + vfse.stepwise.max_width, + vfse.stepwise.step_width, + vfse.stepwise.min_height, + vfse.stepwise.max_height, + vfse.stepwise.step_height); + } + vfse.index++; + } +} +#endif + +static void list_formats(AVFormatContext *ctx, int fd, int type) +{ + struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; + + while(!ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) { + enum CodecID codec_id = fmt_v4l2codec(vfd.pixelformat); + enum PixelFormat pix_fmt = fmt_v4l2ff(vfd.pixelformat, codec_id); + + vfd.index++; + + if (!(vfd.flags & V4L2_FMT_FLAG_COMPRESSED) && + type & V4L_RAWFORMATS) { + const char *fmt_name = av_get_pix_fmt_name(pix_fmt); + av_log(ctx, AV_LOG_INFO, "R : %9s : %20s :", + fmt_name ? fmt_name : "Unsupported", + vfd.description); + } else if (vfd.flags & V4L2_FMT_FLAG_COMPRESSED && + type & V4L_COMPFORMATS) { + AVCodec *codec = avcodec_find_encoder(codec_id); + av_log(ctx, AV_LOG_INFO, "C : %9s : %20s :", + codec ? codec->name : "Unsupported", + vfd.description); + } else { + continue; + } + + if (vfd.flags & V4L2_FMT_FLAG_EMULATED) { + av_log(ctx, AV_LOG_WARNING, "%s", "Emulated"); + continue; + } +#if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE + list_framesizes(ctx, fd, vfd.pixelformat); +#endif + av_log(ctx, AV_LOG_INFO, "\n"); + } +} + static int mmap_init(AVFormatContext *ctx) { struct video_data *s = ctx->priv_data; @@ -621,6 +690,12 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) goto out; } + if (s->list_format) { + list_formats(s1, s->fd, s->list_format); + res = AVERROR_EXIT; + goto out; + } + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ if (s->video_size && @@ -629,12 +704,18 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) s->video_size); goto out; } - if (s->pixel_format && - (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) { - av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", - s->pixel_format); - res = AVERROR(EINVAL); - goto out; + + if (s->pixel_format) { + + pix_fmt = av_get_pix_fmt(s->pixel_format); + + if (pix_fmt == PIX_FMT_NONE) { + av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", + s->pixel_format); + + res = AVERROR(EINVAL); + goto out; + } } if (!s->width && !s->height) { @@ -737,6 +818,10 @@ static const AVOption options[] = { { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "list_formats", "List available formats and exit", OFFSET(list_format), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC, "list_formats" }, + { "all", "Show all available formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_ALLFORMATS }, 0, INT_MAX, DEC, "list_formats" }, + { "raw", "Show only non-compressed formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_RAWFORMATS }, 0, INT_MAX, DEC, "list_formats" }, + { "compressed", "Show only compressed formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_COMPFORMATS }, 0, INT_MAX, DEC, "list_formats" }, { NULL }, }; From 00a1cdd2645992c084a6c71746b04babb7cae364 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 3 Jan 2012 13:25:25 +0100 Subject: [PATCH 39/46] Place some START_TIMER invocations in separate blocks. This fixes compilation failures related to START_TIMER/STOP_TIMER macros and -Werror=declaration-after-statement. START_TIMER declares variables and thus may not be placed after statements outside of a new block. --- libavcodec/indeo5.c | 4 ++-- libpostproc/postprocess_template.c | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c index 8b72b1f0c2..019fa2b8da 100644 --- a/libavcodec/indeo5.c +++ b/libavcodec/indeo5.c @@ -757,7 +757,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, switch_buffers(ctx); - //START_TIMER; + //{ START_TIMER; if (ctx->frame_type != FRAMETYPE_NULL) { for (p = 0; p < 3; p++) { @@ -772,7 +772,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, } } - //STOP_TIMER("decode_planes"); + //STOP_TIMER("decode_planes"); } if (ctx->frame.data[0]) avctx->release_buffer(avctx, &ctx->frame); diff --git a/libpostproc/postprocess_template.c b/libpostproc/postprocess_template.c index f1122e5ba0..a609ce8121 100644 --- a/libpostproc/postprocess_template.c +++ b/libpostproc/postprocess_template.c @@ -2472,7 +2472,7 @@ static av_always_inline void RENAME(do_a_deblock)(uint8_t *src, int step, int st int64_t dc_mask, eq_mask, both_masks; int64_t sums[10*8*2]; src+= step*3; // src points to begin of the 8x8 Block -//START_TIMER + //{ START_TIMER __asm__ volatile( "movq %0, %%mm7 \n\t" "movq %1, %%mm6 \n\t" @@ -2998,7 +2998,8 @@ static av_always_inline void RENAME(do_a_deblock)(uint8_t *src, int step, int st STOP_TIMER("step16") }else{ STOP_TIMER("stepX") -}*/ +} + } */ } #endif //HAVE_MMX From 3d72a6f19e656afc52007b8ef9810aedabf41c29 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Tue, 3 Jan 2012 10:29:19 +0100 Subject: [PATCH 40/46] swscale: Use standard multiple inclusion guards in ppc/ header files. --- libswscale/ppc/yuv2rgb_altivec.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libswscale/ppc/yuv2rgb_altivec.h b/libswscale/ppc/yuv2rgb_altivec.h index b809fe13fe..ab5fcde513 100644 --- a/libswscale/ppc/yuv2rgb_altivec.h +++ b/libswscale/ppc/yuv2rgb_altivec.h @@ -21,8 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef PPC_YUV2RGB_ALTIVEC_H -#define PPC_YUV2RGB_ALTIVEC_H 1 +#ifndef SWSCALE_PPC_YUV2RGB_ALTIVEC_H +#define SWSCALE_PPC_YUV2RGB_ALTIVEC_H #define YUV2PACKEDX_HEADER(suffix) \ void ff_yuv2 ## suffix ## _X_altivec(SwsContext *c, const int16_t *lumFilter, \ @@ -39,4 +39,4 @@ YUV2PACKEDX_HEADER(rgba); YUV2PACKEDX_HEADER(rgb24); YUV2PACKEDX_HEADER(bgr24); -#endif /* PPC_YUV2RGB_ALTIVEC_H */ +#endif /* SWSCALE_PPC_YUV2RGB_ALTIVEC_H */ From 89d26797f56ec52dae14f9c47b445c9a39e8ce56 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 3 Jan 2012 20:41:18 -0800 Subject: [PATCH 41/46] ulti: convert to new bytestream API. --- libavcodec/bytestream.h | 6 +++- libavcodec/ulti.c | 72 +++++++++++++++++++---------------------- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/libavcodec/bytestream.h b/libavcodec/bytestream.h index ba3e4e8802..8fbceacc4f 100644 --- a/libavcodec/bytestream.h +++ b/libavcodec/bytestream.h @@ -39,11 +39,15 @@ static av_always_inline void bytestream_put_ ##name(uint8_t **b, const type valu write(*b, value);\ (*b) += bytes;\ }\ +static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g)\ +{\ + return bytestream_get_ ## name(&g->buffer);\ +}\ static av_always_inline type bytestream2_get_ ## name(GetByteContext *g)\ {\ if (g->buffer_end - g->buffer < bytes)\ return 0;\ - return bytestream_get_ ## name(&g->buffer);\ + return bytestream2_get_ ## name ## u(g);\ }\ static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g)\ {\ diff --git a/libavcodec/ulti.c b/libavcodec/ulti.c index 52092b5309..62bab3c38d 100644 --- a/libavcodec/ulti.c +++ b/libavcodec/ulti.c @@ -38,16 +38,9 @@ typedef struct UltimotionDecodeContext { int width, height, blocks; AVFrame frame; const uint8_t *ulti_codebook; + GetByteContext gb; } UltimotionDecodeContext; -#define CHECK_OVERREAD_SIZE(size) \ - do { \ - if (buf_end - buf < (size)) { \ - av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); \ - return AVERROR_INVALIDDATA; \ - } \ - } while(0) - static av_cold int ulti_decode_init(AVCodecContext *avctx) { UltimotionDecodeContext *s = avctx->priv_data; @@ -231,7 +224,6 @@ static int ulti_decode_frame(AVCodecContext *avctx, int i; int skip; int tmp; - const uint8_t *buf_end = buf + buf_size; s->frame.reference = 1; s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; @@ -240,18 +232,20 @@ static int ulti_decode_frame(AVCodecContext *avctx, return -1; } + bytestream2_init(&s->gb, buf, buf_size); + while(!done) { int idx; if(blocks >= s->blocks || y >= s->height) break;//all blocks decoded - CHECK_OVERREAD_SIZE(1); - idx = *buf++; + if (bytestream2_get_bytes_left(&s->gb) < 1) + goto err; + idx = bytestream2_get_byteu(&s->gb); if((idx & 0xF8) == 0x70) { switch(idx) { case 0x70: //change modifier - CHECK_OVERREAD_SIZE(1); - modifier = *buf++; + modifier = bytestream2_get_byte(&s->gb); if(modifier>1) av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier); break; @@ -265,8 +259,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, done = 1; break; case 0x74: //skip some blocks - CHECK_OVERREAD_SIZE(1); - skip = *buf++; + skip = bytestream2_get_byte(&s->gb); if ((blocks + skip) >= s->blocks) break; blocks += skip; @@ -293,8 +286,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, } else { cf = 0; if (idx) { - CHECK_OVERREAD_SIZE(1); - chroma = *buf++; + chroma = bytestream2_get_byte(&s->gb); } } for (i = 0; i < 4; i++) { // for every subblock @@ -302,15 +294,13 @@ static int ulti_decode_frame(AVCodecContext *avctx, if(!code) //skip subblock continue; if(cf) { - CHECK_OVERREAD_SIZE(1); - chroma = *buf++; + chroma = bytestream2_get_byte(&s->gb); } tx = x + block_coords[i * 2]; ty = y + block_coords[(i * 2) + 1]; switch(code) { case 1: - CHECK_OVERREAD_SIZE(1); - tmp = *buf++; + tmp = bytestream2_get_byte(&s->gb); angle = angle_by_index[(tmp >> 6) & 0x3]; @@ -330,8 +320,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, case 2: if (modifier) { // unpack four luma samples - CHECK_OVERREAD_SIZE(3); - tmp = bytestream_get_be24(&buf); + tmp = bytestream2_get_be24(&s->gb); Y[0] = (tmp >> 18) & 0x3F; Y[1] = (tmp >> 12) & 0x3F; @@ -339,8 +328,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, Y[3] = tmp & 0x3F; angle = 16; } else { // retrieve luma samples from codebook - CHECK_OVERREAD_SIZE(2); - tmp = bytestream_get_be16(&buf); + tmp = bytestream2_get_be16(&s->gb); angle = (tmp >> 12) & 0xF; tmp &= 0xFFF; @@ -356,27 +344,27 @@ static int ulti_decode_frame(AVCodecContext *avctx, if (modifier) { // all 16 luma samples uint8_t Luma[16]; - CHECK_OVERREAD_SIZE(12); - - tmp = bytestream_get_be24(&buf); + if (bytestream2_get_bytes_left(&s->gb) < 12) + goto err; + tmp = bytestream2_get_be24u(&s->gb); Luma[0] = (tmp >> 18) & 0x3F; Luma[1] = (tmp >> 12) & 0x3F; Luma[2] = (tmp >> 6) & 0x3F; Luma[3] = tmp & 0x3F; - tmp = bytestream_get_be24(&buf); + tmp = bytestream2_get_be24u(&s->gb); Luma[4] = (tmp >> 18) & 0x3F; Luma[5] = (tmp >> 12) & 0x3F; Luma[6] = (tmp >> 6) & 0x3F; Luma[7] = tmp & 0x3F; - tmp = bytestream_get_be24(&buf); + tmp = bytestream2_get_be24u(&s->gb); Luma[8] = (tmp >> 18) & 0x3F; Luma[9] = (tmp >> 12) & 0x3F; Luma[10] = (tmp >> 6) & 0x3F; Luma[11] = tmp & 0x3F; - tmp = bytestream_get_be24(&buf); + tmp = bytestream2_get_be24u(&s->gb); Luma[12] = (tmp >> 18) & 0x3F; Luma[13] = (tmp >> 12) & 0x3F; Luma[14] = (tmp >> 6) & 0x3F; @@ -384,22 +372,23 @@ static int ulti_decode_frame(AVCodecContext *avctx, ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma); } else { - CHECK_OVERREAD_SIZE(4); - tmp = *buf++; + if (bytestream2_get_bytes_left(&s->gb) < 4) + goto err; + tmp = bytestream2_get_byteu(&s->gb); if(tmp & 0x80) { angle = (tmp >> 4) & 0x7; - tmp = (tmp << 8) + *buf++; + tmp = (tmp << 8) + bytestream2_get_byteu(&s->gb); Y[0] = (tmp >> 6) & 0x3F; Y[1] = tmp & 0x3F; - Y[2] = (*buf++) & 0x3F; - Y[3] = (*buf++) & 0x3F; + Y[2] = bytestream2_get_byteu(&s->gb) & 0x3F; + Y[3] = bytestream2_get_byteu(&s->gb) & 0x3F; ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block } else { // some patterns int f0, f1; - f0 = *buf++; + f0 = bytestream2_get_byteu(&s->gb); f1 = tmp; - Y[0] = (*buf++) & 0x3F; - Y[1] = (*buf++) & 0x3F; + Y[0] = bytestream2_get_byteu(&s->gb) & 0x3F; + Y[1] = bytestream2_get_byteu(&s->gb) & 0x3F; ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma); } } @@ -421,6 +410,11 @@ static int ulti_decode_frame(AVCodecContext *avctx, *(AVFrame*)data= s->frame; return buf_size; + +err: + av_log(avctx, AV_LOG_ERROR, + "Insufficient data\n"); + return AVERROR_INVALIDDATA; } AVCodec ff_ulti_decoder = { From 4be386b318e2c707f3f65df49244768afc47c3d9 Mon Sep 17 00:00:00 2001 From: Jean First Date: Tue, 3 Jan 2012 23:01:28 +0100 Subject: [PATCH 42/46] rtsp: Fix compiler warning for uninitialized variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This one won't ever be used uninitialized in practice, but the compiler doesn't realize it. Signed-off-by: Martin Storsjö --- libavformat/rtsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index fcf168d426..2858a9a806 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1103,7 +1103,7 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, int lower_transport, const char *real_challenge) { RTSPState *rt = s->priv_data; - int rtx, j, i, err, interleave = 0; + int rtx = 0, j, i, err, interleave = 0; RTSPStream *rtsp_st; RTSPMessageHeader reply1, *reply = &reply1; char cmd[2048]; From 2df73eefb4f7c954d2bb80afa823bb7d4f8e5006 Mon Sep 17 00:00:00 2001 From: Jean First Date: Fri, 30 Dec 2011 21:08:02 +0100 Subject: [PATCH 43/46] flvdec: Fix compiler warning for uninitialized variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These can't be used uninitialized in practice, but the compiler doesn't realize it. Signed-off-by: Martin Storsjö --- libavformat/flvdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 4f1c805c81..2f770b30f2 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -441,7 +441,7 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) int ret, i, type, size, flags, is_audio; int64_t next, pos; int64_t dts, pts = AV_NOPTS_VALUE; - int sample_rate, channels; + int sample_rate = 0, channels = 0; AVStream *st = NULL; for(;;avio_skip(s->pb, 4)){ /* pkt size is repeated at end. skip it */ From e8c04f6240b1557aadbab6242912e784656bc24d Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 26 Nov 2011 11:01:33 +0100 Subject: [PATCH 44/46] avconv: add symbolic names for -vsync parameters --- avconv.c | 30 +++++++++++++++++++++++------- doc/avconv.texi | 8 ++++---- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/avconv.c b/avconv.c index 096623e7dc..16f22f4039 100644 --- a/avconv.c +++ b/avconv.c @@ -76,6 +76,11 @@ #include "libavutil/avassert.h" +#define VSYNC_AUTO -1 +#define VSYNC_PASSTHROUGH 0 +#define VSYNC_CFR 1 +#define VSYNC_VFR 2 + const char program_name[] = "avconv"; const int program_birth_year = 2000; @@ -111,7 +116,7 @@ static int do_hex_dump = 0; static int do_pkt_dump = 0; static int do_pass = 0; static char *pass_logfilename_prefix = NULL; -static int video_sync_method = -1; +static int video_sync_method = VSYNC_AUTO; static int audio_sync_method = 0; static float audio_drift_threshold = 0.1; static int copy_ts = 0; @@ -1330,16 +1335,16 @@ static void do_video_out(AVFormatContext *s, *frame_size = 0; format_video_sync = video_sync_method; - if (format_video_sync < 0) - format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? 0 : - (s->oformat->flags & AVFMT_VARIABLE_FPS) ? 2 : 1; + if (format_video_sync == VSYNC_AUTO) + format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : + (s->oformat->flags & AVFMT_VARIABLE_FPS) ? VSYNC_VFR : VSYNC_CFR; - if (format_video_sync) { + if (format_video_sync != VSYNC_PASSTHROUGH) { double vdelta = sync_ipts - ost->sync_opts; // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (vdelta < -1.1) nb_frames = 0; - else if (format_video_sync == 2) { + else if (format_video_sync == VSYNC_VFR) { if (vdelta <= -0.6) { nb_frames = 0; } else if (vdelta > 0.6) @@ -4309,6 +4314,17 @@ static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg return parse_option(o, "filter:v", arg, options); } +static int opt_vsync(const char *opt, const char *arg) +{ + if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR; + else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR; + else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH; + + if (video_sync_method == VSYNC_AUTO) + video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); + return 0; +} + #define OFFSET(x) offsetof(OptionsContext, x) static const OptionDef options[] = { /* main options */ @@ -4339,7 +4355,7 @@ static const OptionDef options[] = { "when dumping packets, also dump the payload" }, { "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" }, { "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, - { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" }, + { "vsync", HAS_ARG | OPT_EXPERT, {(void*)opt_vsync}, "video sync method", "" }, { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" }, diff --git a/doc/avconv.texi b/doc/avconv.texi index 157e233cc6..0a83326379 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -746,15 +746,15 @@ Thread count. Video sync method. @table @option -@item 0 +@item passthrough Each frame is passed with its timestamp from the demuxer to the muxer. -@item 1 +@item cfr Frames will be duplicated and dropped to achieve exactly the requested constant framerate. -@item 2 +@item vfr Frames are passed through with their timestamp or dropped so as to prevent 2 frames from having the same timestamp. -@item -1 +@item auto Chooses between 1 and 2 depending on muxer capabilities. This is the default method. @end table From f13a9ca90602408d96fcbaf249a299ac1243609c Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 4 Jan 2012 20:29:57 +0100 Subject: [PATCH 45/46] v4l2: use V4L2_FMT_FLAG_EMULATED only if it is defined V4L2_FMT_FLAG_EMULATED was added in 2.6.32. --- libavdevice/v4l2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 2895a01824..71e5b1159a 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -316,10 +316,12 @@ static void list_formats(AVFormatContext *ctx, int fd, int type) continue; } +#ifdef V4L2_FMT_FLAG_EMULATED if (vfd.flags & V4L2_FMT_FLAG_EMULATED) { av_log(ctx, AV_LOG_WARNING, "%s", "Emulated"); continue; } +#endif #if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE list_framesizes(ctx, fd, vfd.pixelformat); #endif From feb15cee5e19a1e31d075ec08d598d64c2dc38ef Mon Sep 17 00:00:00 2001 From: Shitiz Garg Date: Fri, 16 Dec 2011 00:36:27 +0530 Subject: [PATCH 46/46] mtv: Make sure audio_subsegments is not 0 audio_subsegments would be 0 and cause floating point exceptions Fixes bugzilla #144 Signed-off-by: Justin Ruggles --- libavformat/mtv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/mtv.c b/libavformat/mtv.c index c3fb15c344..4c3b082881 100644 --- a/libavformat/mtv.c +++ b/libavformat/mtv.c @@ -106,6 +106,12 @@ static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap) avio_skip(pb, 4); audio_subsegments = avio_rl16(pb); + + if (audio_subsegments == 0) { + av_log_ask_for_sample(s, "MTV files without audio are not supported\n"); + return AVERROR_INVALIDDATA; + } + mtv->full_segment_size = audio_subsegments * (MTV_AUDIO_PADDING_SIZE + MTV_ASUBCHUNK_DATA_SIZE) + mtv->img_segment_size;