From b089ca871aaa1b59d43f81bce9d246fadb2e852b Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 13 Apr 2012 11:06:39 -0700 Subject: [PATCH 01/19] dsputil: fix optimized emu_edge function on Win64. Recent register allocation changes (x86inc.asm update) changed the register order and thus opcodes for the inner loops. One of them became >128bytes, which confuses other parts of this function where it jumps to fixed-offset positions to extend the edge by fixed amounts. A simple register change fixes this. --- libavcodec/x86/dsputil_yasm.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/x86/dsputil_yasm.asm b/libavcodec/x86/dsputil_yasm.asm index bec4063260..807c64102b 100644 --- a/libavcodec/x86/dsputil_yasm.asm +++ b/libavcodec/x86/dsputil_yasm.asm @@ -594,7 +594,7 @@ cglobal emu_edge_core, 2, 7, 0 %define valw2 r7w %define valw3 r3w %if WIN64 -%define valw4 r4w +%define valw4 r7w %else ; unix64 %define valw4 r3w %endif From cbf767a87c0e00055d3ebb88053c7cccf814f473 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Thu, 12 Apr 2012 22:00:57 -0700 Subject: [PATCH 02/19] avf: has_duration does not check the global one Some container formats report a global duration, but not a per stream one. --- libavformat/utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/utils.c b/libavformat/utils.c index 6ebfabb721..bcdba8c5df 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1823,6 +1823,8 @@ static int has_duration(AVFormatContext *ic) if (st->duration != AV_NOPTS_VALUE) return 1; } + if (ic->duration) + return 1; return 0; } From f346b6bbebd86525c65bf7f40190d7ba3eb8a90a Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Thu, 12 Apr 2012 18:28:37 -0700 Subject: [PATCH 03/19] tiffdec: K&R cosmetics --- libavcodec/tiff.c | 255 ++++++++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 108 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 26304ca3fe..2a5a302e01 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -53,35 +53,39 @@ typedef struct TiffContext { int strips, rps, sstype; int sot; - const uint8_t* stripdata; - const uint8_t* stripsizes; + const uint8_t *stripdata; + const uint8_t *stripsizes; int stripsize, stripoff; LZWState *lzw; } TiffContext; -static unsigned tget_short(const uint8_t **p, int le) { +static unsigned tget_short(const uint8_t **p, int le) +{ unsigned v = le ? AV_RL16(*p) : AV_RB16(*p); *p += 2; return v; } -static unsigned tget_long(const uint8_t **p, int le) { +static unsigned tget_long(const uint8_t **p, int le) +{ unsigned v = le ? AV_RL32(*p) : AV_RB32(*p); *p += 4; return v; } -static unsigned tget(const uint8_t **p, int type, int le) { - switch(type){ +static unsigned tget(const uint8_t **p, int type, int le) +{ + switch (type) { case TIFF_BYTE : return *(*p)++; case TIFF_SHORT: return tget_short(p, le); - case TIFF_LONG : return tget_long (p, le); + case TIFF_LONG : return tget_long(p, le); default : return UINT_MAX; } } #if CONFIG_ZLIB -static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t *src, int size) +static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t *src, + int size) { z_stream zstream = { 0 }; int zret; @@ -102,7 +106,9 @@ static int tiff_uncompress(uint8_t *dst, unsigned long *len, const uint8_t *src, } #endif -static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uint8_t *src, int size, int lines){ +static int tiff_unpack_strip(TiffContext *s, uint8_t *dst, int stride, + const uint8_t *src, int size, int lines) +{ int c, line, pixels, code; const uint8_t *ssrc = src; int width = ((s->width * s->bpp) + 7) >> 3; @@ -111,21 +117,24 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin return AVERROR_INVALIDDATA; #if CONFIG_ZLIB - if(s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE){ - uint8_t *zbuf; unsigned long outlen; + if (s->compr == TIFF_DEFLATE || s->compr == TIFF_ADOBE_DEFLATE) { + uint8_t *zbuf; + unsigned long outlen; int ret; outlen = width * lines; zbuf = av_malloc(outlen); if (!zbuf) return AVERROR(ENOMEM); ret = tiff_uncompress(zbuf, &outlen, src, size); - if(ret != Z_OK){ - av_log(s->avctx, AV_LOG_ERROR, "Uncompressing failed (%lu of %lu) with error %d\n", outlen, (unsigned long)width * lines, ret); + if (ret != Z_OK) { + av_log(s->avctx, AV_LOG_ERROR, + "Uncompressing failed (%lu of %lu) with error %d\n", outlen, + (unsigned long)width * lines, ret); av_free(zbuf); return -1; } src = zbuf; - for(line = 0; line < lines; line++){ + for (line = 0; line < lines; line++) { memcpy(dst, src, width); dst += stride; src += width; @@ -134,48 +143,53 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin return 0; } #endif - if(s->compr == TIFF_LZW){ - if(ff_lzw_decode_init(s->lzw, 8, src, size, FF_LZW_TIFF) < 0){ + if (s->compr == TIFF_LZW) { + if (ff_lzw_decode_init(s->lzw, 8, src, size, FF_LZW_TIFF) < 0) { av_log(s->avctx, AV_LOG_ERROR, "Error initializing LZW decoder\n"); return -1; } } - if(s->compr == TIFF_CCITT_RLE || s->compr == TIFF_G3 || s->compr == TIFF_G4){ + if (s->compr == TIFF_CCITT_RLE || s->compr == TIFF_G3 + || s->compr == TIFF_G4) { int i, ret = 0; - uint8_t *src2 = av_malloc((unsigned)size + FF_INPUT_BUFFER_PADDING_SIZE); + uint8_t *src2 = av_malloc((unsigned)size + + FF_INPUT_BUFFER_PADDING_SIZE); if (!src2) { - av_log(s->avctx, AV_LOG_ERROR, "Error allocating temporary buffer\n"); + av_log(s->avctx, AV_LOG_ERROR, + "Error allocating temporary buffer\n"); return AVERROR(ENOMEM); } - if(s->fax_opts & 2){ - av_log(s->avctx, AV_LOG_ERROR, "Uncompressed fax mode is not supported (yet)\n"); + if (s->fax_opts & 2) { + av_log(s->avctx, AV_LOG_ERROR, + "Uncompressed fax mode is not supported (yet)\n"); av_free(src2); return -1; } - if(!s->fill_order){ + if (!s->fill_order) { memcpy(src2, src, size); - }else{ - for(i = 0; i < size; i++) + } else { + for (i = 0; i < size; i++) src2[i] = av_reverse[src[i]]; } - memset(src2+size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - switch(s->compr){ + memset(src2 + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + switch (s->compr) { case TIFF_CCITT_RLE: case TIFF_G3: case TIFF_G4: - ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride, s->compr, s->fax_opts); + ret = ff_ccitt_unpack(s->avctx, src2, size, dst, lines, stride, + s->compr, s->fax_opts); break; } av_free(src2); return ret; } - for(line = 0; line < lines; line++){ - if(src - ssrc > size){ + for (line = 0; line < lines; line++) { + if (src - ssrc > size) { av_log(s->avctx, AV_LOG_ERROR, "Source data overread\n"); return -1; } - switch(s->compr){ + switch (s->compr) { case TIFF_RAW: if (ssrc + size - src < width) return AVERROR_INVALIDDATA; @@ -189,21 +203,23 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin src += width; break; case TIFF_PACKBITS: - for(pixels = 0; pixels < width;){ - code = (int8_t)*src++; - if(code >= 0){ + for (pixels = 0; pixels < width;) { + code = (int8_t) * src++; + if (code >= 0) { code++; - if(pixels + code > width){ - av_log(s->avctx, AV_LOG_ERROR, "Copy went out of bounds\n"); + if (pixels + code > width) { + av_log(s->avctx, AV_LOG_ERROR, + "Copy went out of bounds\n"); return -1; } memcpy(dst + pixels, src, code); src += code; pixels += code; - }else if(code != -128){ // -127..-1 + } else if (code != -128) { // -127..-1 code = (-code) + 1; - if(pixels + code > width){ - av_log(s->avctx, AV_LOG_ERROR, "Run went out of bounds\n"); + if (pixels + code > width) { + av_log(s->avctx, AV_LOG_ERROR, + "Run went out of bounds\n"); return -1; } c = *src++; @@ -214,8 +230,9 @@ static int tiff_unpack_strip(TiffContext *s, uint8_t* dst, int stride, const uin break; case TIFF_LZW: pixels = ff_lzw_decode(s->lzw, dst, width); - if(pixels < width){ - av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", pixels, width); + if (pixels < width) { + av_log(s->avctx, AV_LOG_ERROR, "Decoded only %i bytes of %i\n", + pixels, width); return -1; } break; @@ -279,7 +296,8 @@ static int init_image(TiffContext *s) return 0; } -static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *buf, const uint8_t *end_buf) +static int tiff_decode_tag(TiffContext *s, const uint8_t *start, + const uint8_t *buf, const uint8_t *end_buf) { unsigned tag, type, count, off, value = 0; int i, j; @@ -294,12 +312,13 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * off = tget_long(&buf, s->le); if (type == 0 || type >= FF_ARRAY_ELEMS(type_sizes)) { - av_log(s->avctx, AV_LOG_DEBUG, "Unknown tiff type (%u) encountered\n", type); + av_log(s->avctx, AV_LOG_DEBUG, "Unknown tiff type (%u) encountered\n", + type); return 0; } - if(count == 1){ - switch(type){ + if (count == 1) { + switch (type) { case TIFF_BYTE: case TIFF_SHORT: buf -= 4; @@ -311,7 +330,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * buf = NULL; break; case TIFF_STRING: - if(count <= 4){ + if (count <= 4) { buf -= 4; break; } @@ -327,12 +346,13 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * } } - if(buf && (buf < start || buf > end_buf)){ - av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n"); + if (buf && (buf < start || buf > end_buf)) { + av_log(s->avctx, AV_LOG_ERROR, + "Tag referencing position outside the image\n"); return -1; } - switch(tag){ + switch (tag) { case TIFF_WIDTH: s->width = value; break; @@ -341,20 +361,25 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * break; case TIFF_BPP: s->bppcount = count; - if(count > 4){ - av_log(s->avctx, AV_LOG_ERROR, "This format is not supported (bpp=%d, %d components)\n", s->bpp, count); + if (count > 4) { + av_log(s->avctx, AV_LOG_ERROR, + "This format is not supported (bpp=%d, %d components)\n", + s->bpp, count); return -1; } - if(count == 1) s->bpp = value; - else{ - switch(type){ + if (count == 1) + s->bpp = value; + else { + switch (type) { case TIFF_BYTE: - s->bpp = (off & 0xFF) + ((off >> 8) & 0xFF) + ((off >> 16) & 0xFF) + ((off >> 24) & 0xFF); + s->bpp = (off & 0xFF) + ((off >> 8) & 0xFF) + + ((off >> 16) & 0xFF) + ((off >> 24) & 0xFF); break; case TIFF_SHORT: case TIFF_LONG: s->bpp = 0; - for(i = 0; i < count && buf < end_buf; i++) s->bpp += tget(&buf, type, s->le); + for (i = 0; i < count && buf < end_buf; i++) + s->bpp += tget(&buf, type, s->le); break; default: s->bpp = -1; @@ -374,7 +399,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * case TIFF_COMPR: s->compr = value; s->predictor = 0; - switch(s->compr){ + switch (s->compr) { case TIFF_RAW: case TIFF_PACKBITS: case TIFF_LZW: @@ -394,48 +419,54 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * #endif case TIFF_JPEG: case TIFF_NEWJPEG: - av_log(s->avctx, AV_LOG_ERROR, "JPEG compression is not supported\n"); + av_log(s->avctx, AV_LOG_ERROR, + "JPEG compression is not supported\n"); return -1; default: - av_log(s->avctx, AV_LOG_ERROR, "Unknown compression method %i\n", s->compr); + av_log(s->avctx, AV_LOG_ERROR, "Unknown compression method %i\n", + s->compr); return -1; } break; case TIFF_ROWSPERSTRIP: if (type == TIFF_LONG && value == UINT_MAX) value = s->avctx->height; - if(value < 1){ - av_log(s->avctx, AV_LOG_ERROR, "Incorrect value of rows per strip\n"); + if (value < 1) { + av_log(s->avctx, AV_LOG_ERROR, + "Incorrect value of rows per strip\n"); return -1; } s->rps = value; break; case TIFF_STRIP_OFFS: - if(count == 1){ + if (count == 1) { s->stripdata = NULL; s->stripoff = value; - }else + } else s->stripdata = start + off; s->strips = count; - if(s->strips == 1) s->rps = s->height; + if (s->strips == 1) + s->rps = s->height; s->sot = type; - if(s->stripdata > end_buf){ - av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n"); + if (s->stripdata > end_buf) { + av_log(s->avctx, AV_LOG_ERROR, + "Tag referencing position outside the image\n"); return -1; } break; case TIFF_STRIP_SIZE: - if(count == 1){ + if (count == 1) { s->stripsizes = NULL; s->stripsize = value; s->strips = 1; - }else{ + } else { s->stripsizes = start + off; } s->strips = count; s->sstype = type; - if(s->stripsizes > end_buf){ - av_log(s->avctx, AV_LOG_ERROR, "Tag referencing position outside the image\n"); + if (s->stripsizes > end_buf) { + av_log(s->avctx, AV_LOG_ERROR, + "Tag referencing position outside the image\n"); return -1; } break; @@ -443,7 +474,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * s->predictor = value; break; case TIFF_INVERT: - switch(value){ + switch (value) { case 0: s->invert = 1; break; @@ -454,13 +485,15 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * case 3: break; default: - av_log(s->avctx, AV_LOG_ERROR, "Color mode %d is not supported\n", value); + av_log(s->avctx, AV_LOG_ERROR, "Color mode %d is not supported\n", + value); return -1; } break; case TIFF_FILL_ORDER: - if(value < 1 || value > 2){ - av_log(s->avctx, AV_LOG_ERROR, "Unknown FillOrder value %d, trying default one\n", value); + if (value < 1 || value > 2) { + av_log(s->avctx, AV_LOG_ERROR, + "Unknown FillOrder value %d, trying default one\n", value); value = 1; } s->fill_order = value - 1; @@ -474,43 +507,43 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * gp = buf + count / 3 * off; bp = buf + count / 3 * off * 2; off = (type_sizes[type] - 1) << 3; - for(i = 0; i < count / 3; i++){ - j = (tget(&rp, type, s->le) >> off) << 16; + for (i = 0; i < count / 3; i++) { + j = (tget(&rp, type, s->le) >> off) << 16; j |= (tget(&gp, type, s->le) >> off) << 8; - j |= tget(&bp, type, s->le) >> off; + j |= tget(&bp, type, s->le) >> off; pal[i] = j; } s->palette_is_set = 1; break; case TIFF_PLANAR: - if(value == 2){ + if (value == 2) { av_log(s->avctx, AV_LOG_ERROR, "Planar format is not supported\n"); return -1; } break; case TIFF_T4OPTIONS: - if(s->compr == TIFF_G3) + if (s->compr == TIFF_G3) s->fax_opts = value; break; case TIFF_T6OPTIONS: - if(s->compr == TIFF_G4) + if (s->compr == TIFF_G4) s->fax_opts = value; break; default: - av_log(s->avctx, AV_LOG_DEBUG, "Unknown or unsupported tag %d/0X%0X\n", tag, tag); + av_log(s->avctx, AV_LOG_DEBUG, "Unknown or unsupported tag %d/0X%0X\n", + tag, tag); } return 0; } static int decode_frame(AVCodecContext *avctx, - void *data, int *data_size, - AVPacket *avpkt) + void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - TiffContext * const s = avctx->priv_data; + TiffContext *const s = avctx->priv_data; AVFrame *picture = data; - AVFrame * const p = &s->picture; + AVFrame *const p = &s->picture; const uint8_t *orig_buf = buf, *end_buf = buf + buf_size; unsigned off; int id, le, ret; @@ -522,10 +555,13 @@ static int decode_frame(AVCodecContext *avctx, //parse image header if (end_buf - buf < 8) return AVERROR_INVALIDDATA; - id = AV_RL16(buf); buf += 2; - if(id == 0x4949) le = 1; - else if(id == 0x4D4D) le = 0; - else{ + id = AV_RL16(buf); + buf += 2; + if (id == 0x4949) + le = 1; + else if (id == 0x4D4D) + le = 0; + else { av_log(avctx, AV_LOG_ERROR, "TIFF header not found\n"); return -1; } @@ -535,8 +571,9 @@ static int decode_frame(AVCodecContext *avctx, s->fill_order = 0; // As TIFF 6.0 specification puts it "An arbitrary but carefully chosen number // that further identifies the file as a TIFF file" - if(tget_short(&buf, le) != 42){ - av_log(avctx, AV_LOG_ERROR, "The answer to life, universe and everything is not correct!\n"); + if (tget_short(&buf, le) != 42) { + av_log(avctx, AV_LOG_ERROR, + "The answer to life, universe and everything is not correct!\n"); return -1; } // Reset these pointers so we can tell if they were set this frame @@ -549,12 +586,12 @@ static int decode_frame(AVCodecContext *avctx, } buf = orig_buf + off; entries = tget_short(&buf, le); - for(i = 0; i < entries; i++){ - if(tiff_decode_tag(s, orig_buf, buf, end_buf) < 0) + for (i = 0; i < entries; i++) { + if (tiff_decode_tag(s, orig_buf, buf, end_buf) < 0) return -1; buf += 12; } - if(!s->stripdata && !s->stripoff){ + if (!s->stripdata && !s->stripoff) { av_log(avctx, AV_LOG_ERROR, "Image data is missing\n"); return -1; } @@ -562,53 +599,54 @@ static int decode_frame(AVCodecContext *avctx, if ((ret = init_image(s)) < 0) return ret; - if(s->strips == 1 && !s->stripsize){ + if (s->strips == 1 && !s->stripsize) { av_log(avctx, AV_LOG_WARNING, "Image data size missing\n"); s->stripsize = buf_size - s->stripoff; } stride = p->linesize[0]; dst = p->data[0]; - for(i = 0; i < s->height; i += s->rps){ - if(s->stripsizes) { + for (i = 0; i < s->height; i += s->rps) { + if (s->stripsizes) { if (s->stripsizes >= end_buf) return AVERROR_INVALIDDATA; ssize = tget(&s->stripsizes, s->sstype, s->le); } else ssize = s->stripsize; - if(s->stripdata){ + if (s->stripdata) { if (s->stripdata >= end_buf) return AVERROR_INVALIDDATA; soff = tget(&s->stripdata, s->sot, s->le); - }else + } else soff = s->stripoff; if (soff > buf_size || ssize > buf_size - soff) { av_log(avctx, AV_LOG_ERROR, "Invalid strip size/offset\n"); return -1; } - if(tiff_unpack_strip(s, dst, stride, orig_buf + soff, ssize, FFMIN(s->rps, s->height - i)) < 0) + if (tiff_unpack_strip(s, dst, stride, orig_buf + soff, ssize, + FFMIN(s->rps, s->height - i)) < 0) break; dst += s->rps * stride; } - if(s->predictor == 2){ + if (s->predictor == 2) { dst = p->data[0]; soff = s->bpp >> 3; ssize = s->width * soff; - for(i = 0; i < s->height; i++) { - for(j = soff; j < ssize; j++) + for (i = 0; i < s->height; i++) { + for (j = soff; j < ssize; j++) dst[j] += dst[j - soff]; dst += stride; } } - if(s->invert){ + if (s->invert) { uint8_t *src; int j; src = s->picture.data[0]; - for(j = 0; j < s->height; j++){ - for(i = 0; i < s->picture.linesize[0]; i++) + for (j = 0; j < s->height; j++) { + for (i = 0; i < s->picture.linesize[0]; i++) src[i] = 255 - src[i]; src += s->picture.linesize[0]; } @@ -619,7 +657,8 @@ static int decode_frame(AVCodecContext *avctx, return buf_size; } -static av_cold int tiff_init(AVCodecContext *avctx){ +static av_cold int tiff_init(AVCodecContext *avctx) +{ TiffContext *s = avctx->priv_data; s->width = 0; @@ -635,10 +674,10 @@ static av_cold int tiff_init(AVCodecContext *avctx){ static av_cold int tiff_end(AVCodecContext *avctx) { - TiffContext * const s = avctx->priv_data; + TiffContext *const s = avctx->priv_data; ff_lzw_decode_close(&s->lzw); - if(s->picture.data[0]) + if (s->picture.data[0]) avctx->release_buffer(avctx, &s->picture); return 0; } From accea4d9d8ef4a51a02653568118eb2862bf79cc Mon Sep 17 00:00:00 2001 From: Yusuke Nakamura Date: Fri, 13 Apr 2012 18:59:14 +0900 Subject: [PATCH 04/19] mov: Fix detecting there is no sync sample. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stss atom without entries doesn't mean every sample is a sync sample. Signed-off-by: Martin Storsjö --- libavformat/isom.h | 1 + libavformat/mov.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libavformat/isom.h b/libavformat/isom.h index 214af589a5..f716d9323f 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -106,6 +106,7 @@ typedef struct MOVStreamContext { unsigned int sample_size; unsigned int sample_count; int *sample_sizes; + int keyframe_absent; unsigned int keyframe_count; int *keyframes; int time_scale; diff --git a/libavformat/mov.c b/libavformat/mov.c index 1492486dcc..046c030bcf 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1534,7 +1534,10 @@ static int mov_read_stss(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_dlog(c->fc, "keyframe_count = %d\n", entries); if (!entries) + { + sc->keyframe_absent = 1; return 0; + } if (entries >= UINT_MAX / sizeof(int)) return AVERROR_INVALIDDATA; sc->keyframes = av_malloc(entries * sizeof(int)); @@ -1776,7 +1779,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) return; } - if (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index]) { + if (!sc->keyframe_absent && (!sc->keyframe_count || current_sample+key_off == sc->keyframes[stss_index])) { keyframe = 1; if (stss_index + 1 < sc->keyframe_count) stss_index++; From 680097cb6d6b5905fe74c274ee27cb8eebb1513f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 13 Apr 2012 07:40:53 -0700 Subject: [PATCH 05/19] WMAL: Do not try to read rawpcm coefficients if bits is invalid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Storsjö --- libavcodec/wmalosslessdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 4eb9ebecea..feea6efa11 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -936,6 +936,11 @@ static int decode_subframe(WmallDecodeCtx *s) if (rawpcm_tile) { int bits = s->bits_per_sample - padding_zeroes; + if (bits <= 0) { + av_log(s->avctx, AV_LOG_ERROR, + "Invalid number of padding bits in raw PCM tile\n"); + return AVERROR_INVALIDDATA; + } av_dlog(s->avctx, "RAWPCM %d bits per sample. " "total %d bits, remain=%d\n", bits, bits * s->num_channels * subframe_len, get_bits_count(&s->gb)); From f5be7958e313f3f62505ea7f90007800e8e1dcb5 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 13 Apr 2012 17:43:54 +0100 Subject: [PATCH 06/19] qdm2: fix a dubious pointer cast This reworks a loop to get rid of an ugly pointer cast, fixing errors seen with the PathScale ENZO compiler. Signed-off-by: Mans Rullgard --- libavcodec/qdm2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index 8d9d281f5d..54782a24d3 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -140,7 +140,6 @@ typedef struct { /// Parameters built from header parameters, do not change during playback int group_order; ///< order of frame group int fft_order; ///< order of FFT (actually fftorder+1) - int fft_frame_size; ///< size of fft frame, in components (1 comples = re + im) int frame_size; ///< size of data frame int frequency_range; int sub_sampling; ///< subsampling: 0=25%, 1=50%, 2=100% */ @@ -1591,13 +1590,17 @@ static void qdm2_fft_tone_synthesizer (QDM2Context *q, int sub_packet) static void qdm2_calculate_fft (QDM2Context *q, int channel, int sub_packet) { const float gain = (q->channels == 1 && q->nb_channels == 2) ? 0.5f : 1.0f; + float *out = q->output_buffer + channel; int i; q->fft.complex[channel][0].re *= 2.0f; q->fft.complex[channel][0].im = 0.0f; q->rdft_ctx.rdft_calc(&q->rdft_ctx, (FFTSample *)q->fft.complex[channel]); /* add samples to output buffer */ - for (i = 0; i < ((q->fft_frame_size + 15) & ~15); i++) - q->output_buffer[q->channels * i + channel] += ((float *) q->fft.complex[channel])[i] * gain; + for (i = 0; i < FFALIGN(q->fft_size, 8); i++) { + out[0] += q->fft.complex[channel][i].re * gain; + out[q->channels] += q->fft.complex[channel][i].im * gain; + out += 2 * q->channels; + } } @@ -1672,7 +1675,6 @@ static void dump_context(QDM2Context *q) PRINT("checksum_size",q->checksum_size); PRINT("channels",q->channels); PRINT("nb_channels",q->nb_channels); - PRINT("fft_frame_size",q->fft_frame_size); PRINT("fft_size",q->fft_size); PRINT("sub_sampling",q->sub_sampling); PRINT("fft_order",q->fft_order); @@ -1827,7 +1829,6 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) } s->fft_order = av_log2(s->fft_size) + 1; - s->fft_frame_size = 2 * s->fft_size; // complex has two floats // something like max decodable tones s->group_order = av_log2(s->group_size) + 1; From 9206ac80a5c3256738b887cf3cfe39f385ebc672 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Thu, 5 Apr 2012 17:30:19 -0700 Subject: [PATCH 07/19] swscale: handle last pixel if lines have an odd width. Fixes bug 270. --- libswscale/output.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libswscale/output.c b/libswscale/output.c index f1acf9ec92..5bc25fc35a 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -466,7 +466,7 @@ yuv2422_X_c_template(SwsContext *c, const int16_t *lumFilter, { int i; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int j; int Y1 = 1 << 18; int Y2 = 1 << 18; @@ -509,7 +509,7 @@ yuv2422_2_c_template(SwsContext *c, const int16_t *buf[2], int uvalpha1 = 4095 - uvalpha; int i; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 19; int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 19; int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha) >> 19; @@ -534,7 +534,7 @@ yuv2422_1_c_template(SwsContext *c, const int16_t *buf0, int i; if (uvalpha < 2048) { - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = buf0[i * 2] >> 7; int Y2 = buf0[i * 2 + 1] >> 7; int U = ubuf0[i] >> 7; @@ -549,7 +549,7 @@ yuv2422_1_c_template(SwsContext *c, const int16_t *buf0, } } else { const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = buf0[i * 2] >> 7; int Y2 = buf0[i * 2 + 1] >> 7; int U = (ubuf0[i] + ubuf1[i]) >> 8; @@ -589,7 +589,7 @@ yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter, { int i; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int j; int Y1 = -0x40000000; int Y2 = -0x40000000; @@ -652,7 +652,7 @@ yuv2rgb48_2_c_template(SwsContext *c, const int32_t *buf[2], int uvalpha1 = 4095 - uvalpha; int i; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 14; int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 14; int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha + (-128 << 23)) >> 14; @@ -690,7 +690,7 @@ yuv2rgb48_1_c_template(SwsContext *c, const int32_t *buf0, int i; if (uvalpha < 2048) { - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] ) >> 2; int Y2 = (buf0[i * 2 + 1]) >> 2; int U = (ubuf0[i] + (-128 << 11)) >> 2; @@ -718,7 +718,7 @@ yuv2rgb48_1_c_template(SwsContext *c, const int32_t *buf0, } } else { const int32_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] ) >> 2; int Y2 = (buf0[i * 2 + 1]) >> 2; int U = (ubuf0[i] + ubuf1[i] + (-128 << 12)) >> 3; @@ -932,7 +932,7 @@ yuv2rgb_X_c_template(SwsContext *c, const int16_t *lumFilter, { int i; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int j, A1, A2; int Y1 = 1 << 18; int Y2 = 1 << 18; @@ -999,7 +999,7 @@ yuv2rgb_2_c_template(SwsContext *c, const int16_t *buf[2], int uvalpha1 = 4095 - uvalpha; int i; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 19; int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 19; int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha) >> 19; @@ -1037,7 +1037,7 @@ yuv2rgb_1_c_template(SwsContext *c, const int16_t *buf0, int i; if (uvalpha < 2048) { - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = buf0[i * 2] >> 7; int Y2 = buf0[i * 2 + 1] >> 7; int U = ubuf0[i] >> 7; @@ -1064,7 +1064,7 @@ yuv2rgb_1_c_template(SwsContext *c, const int16_t *buf0, } } else { const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1]; - for (i = 0; i < (dstW >> 1); i++) { + for (i = 0; i < ((dstW + 1) >> 1); i++) { int Y1 = buf0[i * 2] >> 7; int Y2 = buf0[i * 2 + 1] >> 7; int U = (ubuf0[i] + ubuf1[i]) >> 8; From 7ae7c41413beb601714a06b4fd18cdb4610b2eda Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 1 Apr 2012 18:53:58 +0200 Subject: [PATCH 08/19] vsrc_buffer: allow using a NULL buffer to signal EOF. --- libavfilter/buffersrc.h | 1 + libavfilter/vsrc_buffer.c | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h index bd82c065e4..918a54faee 100644 --- a/libavfilter/buffersrc.h +++ b/libavfilter/buffersrc.h @@ -32,6 +32,7 @@ * * @param buf buffer containing frame data to be passed down the filtergraph. * This function will take ownership of buf, the user must not free it. + * A NULL buf signals EOF -- i.e. no more frames will be sent to this filter. */ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf); diff --git a/libavfilter/vsrc_buffer.c b/libavfilter/vsrc_buffer.c index dfe5bf5602..46a18df713 100644 --- a/libavfilter/vsrc_buffer.c +++ b/libavfilter/vsrc_buffer.c @@ -35,6 +35,7 @@ typedef struct { enum PixelFormat pix_fmt; AVRational time_base; ///< time_base to set in the output link AVRational pixel_aspect; + int eof; } BufferSourceContext; #define CHECK_PARAM_CHANGE(s, c, width, height, format)\ @@ -50,6 +51,12 @@ int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, AVFilterBufferRef *buf; int ret; + if (!buf) { + c->eof = 1; + return 0; + } else if (c->eof) + return AVERROR(EINVAL); + if (!av_fifo_space(c->fifo) && (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + sizeof(buf))) < 0) @@ -79,6 +86,12 @@ int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf) BufferSourceContext *c = s->priv; int ret; + if (!buf) { + c->eof = 1; + return 0; + } else if (c->eof) + return AVERROR(EINVAL); + if (!av_fifo_space(c->fifo) && (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) + sizeof(buf))) < 0) @@ -160,6 +173,8 @@ static int request_frame(AVFilterLink *link) AVFilterBufferRef *buf; if (!av_fifo_size(c->fifo)) { + if (c->eof) + return AVERROR_EOF; av_log(link->src, AV_LOG_ERROR, "request_frame() called with no available frame!\n"); return AVERROR(EINVAL); @@ -177,7 +192,10 @@ static int request_frame(AVFilterLink *link) static int poll_frame(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; - return !!av_fifo_size(c->fifo); + int size = av_fifo_size(c->fifo); + if (!size && c->eof) + return AVERROR_EOF; + return size/sizeof(AVFilterBufferRef*); } AVFilter avfilter_vsrc_buffer = { From d7bcc71dadea71d86a2b95a4f46aedd392f8b948 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 21 Mar 2012 07:46:56 +0100 Subject: [PATCH 09/19] graphparser: add avfilter_graph_parse2(). Unlike avfilter_graph_parse(), it returns unlinked inputs and outputs to the caller, which allows parsing of graphs where inputs/outputs are not known in advance. --- libavfilter/avfiltergraph.h | 44 ++++++++++-- libavfilter/graphparser.c | 136 +++++++++++++++++++++++++++--------- 2 files changed, 141 insertions(+), 39 deletions(-) diff --git a/libavfilter/avfiltergraph.h b/libavfilter/avfiltergraph.h index 733d1c4a51..0d250df614 100644 --- a/libavfilter/avfiltergraph.h +++ b/libavfilter/avfiltergraph.h @@ -91,11 +91,11 @@ void avfilter_graph_free(AVFilterGraph **graph); /** * A linked-list of the inputs/outputs of the filter chain. * - * This is mainly useful for avfilter_graph_parse(), since this - * function may accept a description of a graph with not connected - * input/output pads. This struct specifies, per each not connected - * pad contained in the graph, the filter context and the pad index - * required for establishing a link. + * This is mainly useful for avfilter_graph_parse() / avfilter_graph_parse2(), + * where it is used to communicate open (unlinked) inputs and outputs from and + * to the caller. + * This struct specifies, per each not connected pad contained in the graph, the + * filter context and the pad index required for establishing a link. */ typedef struct AVFilterInOut { /** unique name for this input/output in the list */ @@ -124,4 +124,38 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, AVFilterInOut *inputs, AVFilterInOut *outputs, void *log_ctx); +/** + * Add a graph described by a string to a graph. + * + * @param[in] graph the filter graph where to link the parsed graph context + * @param[in] filters string to be parsed + * @param[out] inputs a linked list of all free (unlinked) inputs of the + * parsed graph will be returned here. It is to be freed + * by the caller using avfilter_inout_free(). + * @param[out] outputs a linked list of all free (unlinked) outputs of the + * parsed graph will be returned here. It is to be freed by the + * caller using avfilter_inout_free(). + * @return zero on success, a negative AVERROR code on error + * + * @note the difference between avfilter_graph_parse2() and + * avfilter_graph_parse() is that in avfilter_graph_parse(), the caller provides + * the lists of inputs and outputs, which therefore must be known before calling + * the function. On the other hand, avfilter_graph_parse2() \em returns the + * inputs and outputs that are left unlinked after parsing the graph and the + * caller then deals with them. Another difference is that in + * avfilter_graph_parse(), the inputs parameter describes inputs of the + * already existing part of the graph; i.e. from the point of view of + * the newly created part, they are outputs. Similarly the outputs parameter + * describes outputs of the already existing filters, which are provided as + * inputs to the parsed filters. + * avfilter_graph_parse2() takes the opposite approach -- it makes no reference + * whatsoever to already existing parts of the graph and the inputs parameter + * will on return contain inputs of the newly parsed part of the graph. + * Analogously the outputs parameter will contain outputs of the newly created + * filters. + */ +int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, + AVFilterInOut **inputs, + AVFilterInOut **outputs); + #endif /* AVFILTER_AVFILTERGRAPH_H */ diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 90f2936590..7a899a815c 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -184,13 +184,15 @@ static AVFilterInOut *extract_inout(const char *label, AVFilterInOut **links) { AVFilterInOut *ret; - while (*links && strcmp((*links)->name, label)) + while (*links && (!(*links)->name || strcmp((*links)->name, label))) links = &((*links)->next); ret = *links; - if (ret) + if (ret) { *links = ret->next; + ret->next = NULL; + } return ret; } @@ -201,6 +203,18 @@ static void insert_inout(AVFilterInOut **inouts, AVFilterInOut *element) *inouts = element; } +static void append_inout(AVFilterInOut **inouts, AVFilterInOut **element) +{ + while (*inouts && (*inouts)->next) + inouts = &((*inouts)->next); + + if (!*inouts) + *inouts = *element; + else + (*inouts)->next = *element; + *element = NULL; +} + static int link_filter_inouts(AVFilterContext *filt_ctx, AVFilterInOut **curr_inputs, AVFilterInOut **open_inputs, void *log_ctx) @@ -209,14 +223,11 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, while (pad--) { AVFilterInOut *p = *curr_inputs; - if (!p) { - av_log(log_ctx, AV_LOG_ERROR, - "Not enough inputs specified for the \"%s\" filter.\n", - filt_ctx->filter->name); - return AVERROR(EINVAL); - } - *curr_inputs = (*curr_inputs)->next; + if (p) + *curr_inputs = (*curr_inputs)->next; + else if (!(p = av_mallocz(sizeof(*p)))) + return AVERROR(ENOMEM); if (p->filter_ctx) { if ((ret = link_filter(p->filter_ctx, p->pad_idx, filt_ctx, pad, log_ctx)) < 0) @@ -329,18 +340,22 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, return pad; } -int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, - AVFilterInOut *open_inputs, - AVFilterInOut *open_outputs, void *log_ctx) +#if FF_API_GRAPH_AVCLASS +#define log_ctx graph +#else +#define log_ctx NULL +#endif +int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, + AVFilterInOut **inputs, + AVFilterInOut **outputs) { int index = 0, ret; char chr = 0; - AVFilterInOut *curr_inputs = NULL; + AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL; do { AVFilterContext *filter; - const char *filterchain = filters; filters += strspn(filters, WHITESPACES); if ((ret = parse_inputs(&filters, &curr_inputs, &open_outputs, log_ctx)) < 0) @@ -349,12 +364,6 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, if ((ret = parse_filter(&filter, &filters, graph, index, log_ctx)) < 0) goto fail; - if (filter->input_count == 1 && !curr_inputs && !index) { - /* First input can be omitted if it is "[in]" */ - const char *tmp = "[in]"; - if ((ret = parse_inputs(&tmp, &curr_inputs, &open_outputs, log_ctx)) < 0) - goto fail; - } if ((ret = link_filter_inouts(filter, &curr_inputs, &open_inputs, log_ctx)) < 0) goto fail; @@ -366,13 +375,8 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, filters += strspn(filters, WHITESPACES); chr = *filters++; - if (chr == ';' && curr_inputs) { - av_log(log_ctx, AV_LOG_ERROR, - "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", - filterchain); - ret = AVERROR(EINVAL); - goto fail; - } + if (chr == ';' && curr_inputs) + append_inout(&open_outputs, &curr_inputs); index++; } while (chr == ',' || chr == ';'); @@ -384,14 +388,10 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, goto fail; } - if (open_inputs && !strcmp(open_inputs->name, "out") && curr_inputs) { - /* Last output can be omitted if it is "[out]" */ - const char *tmp = "[out]"; - if ((ret = parse_outputs(&tmp, &curr_inputs, &open_inputs, &open_outputs, - log_ctx)) < 0) - goto fail; - } + append_inout(&open_outputs, &curr_inputs); + *inputs = open_inputs; + *outputs = open_outputs; return 0; fail: @@ -401,5 +401,73 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, free_inout(open_inputs); free_inout(open_outputs); free_inout(curr_inputs); + + *inputs = NULL; + *outputs = NULL; + + return ret; +} +#undef log_ctx + +int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, + AVFilterInOut *open_inputs, + AVFilterInOut *open_outputs, void *log_ctx) +{ + int ret; + AVFilterInOut *cur, *match, *inputs = NULL, *outputs = NULL; + + if ((ret = avfilter_graph_parse2(graph, filters, &inputs, &outputs)) < 0) + goto fail; + + /* First input can be omitted if it is "[in]" */ + if (inputs && !inputs->name) + inputs->name = av_strdup("in"); + for (cur = inputs; cur; cur = cur->next) { + if (!cur->name) { + av_log(log_ctx, AV_LOG_ERROR, + "Not enough inputs specified for the \"%s\" filter.\n", + cur->filter_ctx->filter->name); + ret = AVERROR(EINVAL); + goto fail; + } + if (!(match = extract_inout(cur->name, &open_outputs))) + continue; + ret = avfilter_link(match->filter_ctx, match->pad_idx, + cur->filter_ctx, cur->pad_idx); + free_inout(match); + if (ret < 0) + goto fail; + } + + /* Last output can be omitted if it is "[out]" */ + if (outputs && !outputs->name) + outputs->name = av_strdup("out"); + for (cur = outputs; cur; cur = cur->next) { + if (!cur->name) { + av_log(log_ctx, AV_LOG_ERROR, + "Invalid filterchain containing an unlabelled output pad: \"%s\"\n", + filters); + ret = AVERROR(EINVAL); + goto fail; + } + if (!(match = extract_inout(cur->name, &open_inputs))) + continue; + ret = avfilter_link(cur->filter_ctx, cur->pad_idx, + match->filter_ctx, match->pad_idx); + free_inout(match); + if (ret < 0) + goto fail; + } + + fail: + if (ret < 0) { + for (; graph->filter_count > 0; graph->filter_count--) + avfilter_free(graph->filters[graph->filter_count - 1]); + av_freep(&graph->filters); + } + free_inout(inputs); + free_inout(outputs); + free_inout(open_inputs); + free_inout(open_outputs); return ret; } From 4e781c25b7b1955d1a9a0b0771c3ce1acb0957bd Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 9 Apr 2012 05:01:05 +0200 Subject: [PATCH 10/19] graphparser: fix the order of connecting unlabeled links. Right now, e.g. scale,[in]overlay would connect scale to the first overlay input and [in] to the second, which goes against the documentation and is unintuitive. The bug happens because of the ordering mess in curr_inputs variable: 1) the unlabeled links from the previous filter are added to it in correct order 2) input labels are parsed and inserted to the beginning one by one (i.e. in reverse order) 3) curr_inputs is matched against filter inputs in reverse order Fix the problem by always using proper ordering without trying to be clever. --- libavfilter/graphparser.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index 7a899a815c..ebd9cc929c 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -219,9 +219,9 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, AVFilterInOut **curr_inputs, AVFilterInOut **open_inputs, void *log_ctx) { - int pad = filt_ctx->input_count, ret; + int pad, ret; - while (pad--) { + for (pad = 0; pad < filt_ctx->input_count; pad++) { AVFilterInOut *p = *curr_inputs; if (p) @@ -264,6 +264,7 @@ static int link_filter_inouts(AVFilterContext *filt_ctx, static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, AVFilterInOut **open_outputs, void *log_ctx) { + AVFilterInOut *parsed_inputs = NULL; int pad = 0; while (**buf == '[') { @@ -286,12 +287,15 @@ static int parse_inputs(const char **buf, AVFilterInOut **curr_inputs, match->pad_idx = pad; } - insert_inout(curr_inputs, match); + append_inout(&parsed_inputs, &match); *buf += strspn(*buf, WHITESPACES); pad++; } + append_inout(&parsed_inputs, curr_inputs); + *curr_inputs = parsed_inputs; + return pad; } From 12e7e1d03e772b16ae95fa6c79ed870d9335564c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Mon, 9 Apr 2012 06:13:53 +0200 Subject: [PATCH 11/19] graphparser: allow specifying sws flags in the graph description. --- doc/filters.texi | 8 +++++++- libavfilter/graphparser.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index 2a089bef84..446e1243db 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -76,6 +76,12 @@ In a complete filterchain all the unlabelled filter input and output pads must be connected. A filtergraph is considered valid if all the filter input and output pads of all the filterchains are connected. +Libavfilter will automatically insert scale filters where format +conversion is required. It is possible to specify swscale flags +for those automatically inserted scalers by prepending +@code{sws_flags=@var{flags};} +to the filtergraph description. + Follows a BNF description for the filtergraph syntax: @example @var{NAME} ::= sequence of alphanumeric characters and '_' @@ -84,7 +90,7 @@ Follows a BNF description for the filtergraph syntax: @var{FILTER_ARGUMENTS} ::= sequence of chars (eventually quoted) @var{FILTER} ::= [@var{LINKNAMES}] @var{NAME} ["=" @var{ARGUMENTS}] [@var{LINKNAMES}] @var{FILTERCHAIN} ::= @var{FILTER} [,@var{FILTERCHAIN}] -@var{FILTERGRAPH} ::= @var{FILTERCHAIN} [;@var{FILTERGRAPH}] +@var{FILTERGRAPH} ::= [sws_flags=@var{flags};] @var{FILTERCHAIN} [;@var{FILTERGRAPH}] @end example @c man end FILTERGRAPH DESCRIPTION diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index ebd9cc929c..d2d31653a9 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -349,6 +349,30 @@ static int parse_outputs(const char **buf, AVFilterInOut **curr_inputs, #else #define log_ctx NULL #endif + +static int parse_sws_flags(const char **buf, AVFilterGraph *graph) +{ + char *p = strchr(*buf, ';'); + + if (strncmp(*buf, "sws_flags=", 10)) + return 0; + + if (!p) { + av_log(log_ctx, AV_LOG_ERROR, "sws_flags not terminated with ';'.\n"); + return AVERROR(EINVAL); + } + + *buf += 4; // keep the 'flags=' part + + av_freep(&graph->scale_sws_opts); + if (!(graph->scale_sws_opts = av_mallocz(p - *buf + 1))) + return AVERROR(ENOMEM); + av_strlcpy(graph->scale_sws_opts, *buf, p - *buf + 1); + + *buf = p + 1; + return 0; +} + int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs) @@ -358,6 +382,11 @@ int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, AVFilterInOut *curr_inputs = NULL, *open_inputs = NULL, *open_outputs = NULL; + filters += strspn(filters, WHITESPACES); + + if ((ret = parse_sws_flags(&filters, graph)) < 0) + goto fail; + do { AVFilterContext *filter; filters += strspn(filters, WHITESPACES); From 91d3cbe0fde05c45837649c213de879c8d85aa67 Mon Sep 17 00:00:00 2001 From: Stefano Sabatini Date: Sat, 11 Jun 2011 15:30:46 +0200 Subject: [PATCH 12/19] avfiltergraph: make the AVFilterInOut alloc/free API public This is required for letting applications to create and destroy AVFilterInOut structs in a convenient way. Signed-off-by: Anton Khirnov --- avconv.c | 4 ++-- avplay.c | 4 ++-- doc/APIchanges | 4 ++++ libavfilter/avfiltergraph.h | 13 +++++++++++++ libavfilter/graphparser.c | 35 ++++++++++++++++++++--------------- libavfilter/version.h | 2 +- 6 files changed, 42 insertions(+), 20 deletions(-) diff --git a/avconv.c b/avconv.c index 2cefe5d549..719df6ddc4 100644 --- a/avconv.c +++ b/avconv.c @@ -592,8 +592,8 @@ static int configure_video_filters(InputStream *ist, OutputStream *ost) ost->graph->scale_sws_opts = av_strdup(args); if (ost->avfilter) { - AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut)); - AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut)); + AVFilterInOut *outputs = avfilter_inout_alloc(); + AVFilterInOut *inputs = avfilter_inout_alloc(); outputs->name = av_strdup("in"); outputs->filter_ctx = last_filter; diff --git a/avplay.c b/avplay.c index 488d0fcd13..4ebccb2acf 100644 --- a/avplay.c +++ b/avplay.c @@ -1716,8 +1716,8 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c return ret; if (vfilters) { - AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut)); - AVFilterInOut *inputs = av_malloc(sizeof(AVFilterInOut)); + AVFilterInOut *outputs = avfilter_inout_alloc(); + AVFilterInOut *inputs = avfilter_inout_alloc(); outputs->name = av_strdup("in"); outputs->filter_ctx = filt_src; diff --git a/doc/APIchanges b/doc/APIchanges index 889156e0bc..5114e14191 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -12,6 +12,10 @@ libavutil: 2011-04-18 API changes, most recent first: +2012-xx-xx - xxxxxxx - lavfi 2.16.0 - avfiltergraph.h + Add avfilter_graph_parse2(), avfilter_inout_alloc() and + avfilter_inout_free() functions. + 2012-xx-xx - xxxxxxx - lavu 51.27.0 - samplefmt.h Add av_get_packed_sample_fmt() and av_get_planar_sample_fmt() diff --git a/libavfilter/avfiltergraph.h b/libavfilter/avfiltergraph.h index 0d250df614..0d600b91ce 100644 --- a/libavfilter/avfiltergraph.h +++ b/libavfilter/avfiltergraph.h @@ -111,6 +111,19 @@ typedef struct AVFilterInOut { struct AVFilterInOut *next; } AVFilterInOut; +/** + * Allocate a single AVFilterInOut entry. + * Must be freed with avfilter_inout_free(). + * @return allocated AVFilterInOut on success, NULL on failure. + */ +AVFilterInOut *avfilter_inout_alloc(void); + +/** + * Free the supplied list of AVFilterInOut and set *inout to NULL. + * If *inout is NULL, do nothing. + */ +void avfilter_inout_free(AVFilterInOut **inout); + /** * Add a graph described by a string to a graph. * diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index d2d31653a9..454704710b 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -170,13 +170,18 @@ static int parse_filter(AVFilterContext **filt_ctx, const char **buf, AVFilterGr return ret; } -static void free_inout(AVFilterInOut *head) +AVFilterInOut *avfilter_inout_alloc(void) { - while (head) { - AVFilterInOut *next = head->next; - av_free(head->name); - av_free(head); - head = next; + return av_mallocz(sizeof(AVFilterInOut)); +} + +void avfilter_inout_free(AVFilterInOut **inout) +{ + while (*inout) { + AVFilterInOut *next = (*inout)->next; + av_freep(&(*inout)->name); + av_freep(inout); + *inout = next; } } @@ -431,9 +436,9 @@ int avfilter_graph_parse2(AVFilterGraph *graph, const char *filters, for (; graph->filter_count > 0; graph->filter_count--) avfilter_free(graph->filters[graph->filter_count - 1]); av_freep(&graph->filters); - free_inout(open_inputs); - free_inout(open_outputs); - free_inout(curr_inputs); + avfilter_inout_free(&open_inputs); + avfilter_inout_free(&open_outputs); + avfilter_inout_free(&curr_inputs); *inputs = NULL; *outputs = NULL; @@ -467,7 +472,7 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, continue; ret = avfilter_link(match->filter_ctx, match->pad_idx, cur->filter_ctx, cur->pad_idx); - free_inout(match); + avfilter_inout_free(&match); if (ret < 0) goto fail; } @@ -487,7 +492,7 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, continue; ret = avfilter_link(cur->filter_ctx, cur->pad_idx, match->filter_ctx, match->pad_idx); - free_inout(match); + avfilter_inout_free(&match); if (ret < 0) goto fail; } @@ -498,9 +503,9 @@ int avfilter_graph_parse(AVFilterGraph *graph, const char *filters, avfilter_free(graph->filters[graph->filter_count - 1]); av_freep(&graph->filters); } - free_inout(inputs); - free_inout(outputs); - free_inout(open_inputs); - free_inout(open_outputs); + avfilter_inout_free(&inputs); + avfilter_inout_free(&outputs); + avfilter_inout_free(&open_inputs); + avfilter_inout_free(&open_outputs); return ret; } diff --git a/libavfilter/version.h b/libavfilter/version.h index d84b67ff76..5d646e4f86 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBAVFILTER_VERSION_MAJOR 2 -#define LIBAVFILTER_VERSION_MINOR 15 +#define LIBAVFILTER_VERSION_MINOR 16 #define LIBAVFILTER_VERSION_MICRO 0 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ From 07933b44dd72cdc5df34a66991cc0f0386614720 Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Fri, 13 Apr 2012 14:00:19 -0700 Subject: [PATCH 13/19] wmal: Drop unused variable num_possible_block_size. This is probably a leftover from WMA Pro. Signed-off-by: Diego Biurrun --- libavcodec/wmalosslessdec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index feea6efa11..e86cf6004e 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -173,7 +173,7 @@ static av_cold int decode_init(AVCodecContext *avctx) WmallDecodeCtx *s = avctx->priv_data; uint8_t *edata_ptr = avctx->extradata; unsigned int channel_mask; - int i, log2_max_num_subframes, num_possible_block_sizes; + int i, log2_max_num_subframes; s->avctx = avctx; init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE); @@ -225,7 +225,6 @@ static av_cold int decode_init(AVCodecContext *avctx) s->max_subframe_len_bit = 0; s->subframe_len_bits = av_log2(log2_max_num_subframes) + 1; - num_possible_block_sizes = log2_max_num_subframes + 1; s->min_samples_per_subframe = s->samples_per_frame / s->max_num_subframes; s->dynamic_range_compression = s->decode_flags & 0x80; s->bV3RTM = s->decode_flags & 0x100; From 9900dd2d9c9b0612f72279180fcc280ad5564357 Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Fri, 13 Apr 2012 14:00:20 -0700 Subject: [PATCH 14/19] wmal: Skip seekable_frame_in_packet. There is no point in storing the value in a variable, since it is not used anywhere else in the decoder. Signed-off-by: Diego Biurrun --- libavcodec/wmalosslessdec.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index e86cf6004e..46655db7ab 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1164,8 +1164,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, GetBitContext* gb = &s->pgb; const uint8_t* buf = avpkt->data; int buf_size = avpkt->size; - int num_bits_prev_frame, packet_sequence_number, - seekable_frame_in_packet, spliced_packet; + int num_bits_prev_frame, packet_sequence_number, spliced_packet; if (s->packet_done || s->packet_loss) { s->packet_done = 0; @@ -1181,7 +1180,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, /* parse packet header */ init_get_bits(gb, buf, s->buf_bit_size); packet_sequence_number = get_bits(gb, 4); - seekable_frame_in_packet = get_bits1(gb); + skip_bits(gb, 1); // Skip seekable_frame_in_packet, currently ununused spliced_packet = get_bits1(gb); /* get number of bits that need to be added to the previous frame */ From 2e13f579930af93cf3f53a3424a9df009b34c79e Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Fri, 13 Apr 2012 14:00:21 -0700 Subject: [PATCH 15/19] wmal: Warn about missing bitstream splicing feature and ask for sample. Signed-off-by: Diego Biurrun --- libavcodec/wmalosslessdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 46655db7ab..1139392d6d 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1182,6 +1182,8 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, packet_sequence_number = get_bits(gb, 4); skip_bits(gb, 1); // Skip seekable_frame_in_packet, currently ununused spliced_packet = get_bits1(gb); + if (spliced_packet) + av_log_missing_feature(avctx, "Bitstream splicing", 1); /* get number of bits that need to be added to the previous frame */ num_bits_prev_frame = get_bits(gb, s->log2_frame_size); From dac79c273748f430b962ef83e46548a4fc0ce5c9 Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Fri, 13 Apr 2012 14:00:22 -0700 Subject: [PATCH 16/19] wmal: vertical alignment cosmetics Signed-off-by: Diego Biurrun --- libavcodec/wmalosslessdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 1139392d6d..1520a06c45 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1179,9 +1179,9 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, /* parse packet header */ init_get_bits(gb, buf, s->buf_bit_size); - packet_sequence_number = get_bits(gb, 4); + packet_sequence_number = get_bits(gb, 4); skip_bits(gb, 1); // Skip seekable_frame_in_packet, currently ununused - spliced_packet = get_bits1(gb); + spliced_packet = get_bits1(gb); if (spliced_packet) av_log_missing_feature(avctx, "Bitstream splicing", 1); From 7a0cb74fee3235d1cda1d74fdc3850f2ec664b75 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 12 Apr 2012 13:42:09 +0200 Subject: [PATCH 17/19] libxvid: drop some pointless dead code --- libavcodec/libxvid_rc.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libavcodec/libxvid_rc.c b/libavcodec/libxvid_rc.c index 4cb832fb4a..c830767058 100644 --- a/libavcodec/libxvid_rc.c +++ b/libavcodec/libxvid_rc.c @@ -30,16 +30,12 @@ #undef NDEBUG #include -extern unsigned int xvid_debug; - int ff_xvid_rate_control_init(MpegEncContext *s){ char *tmp_name; int fd, i; xvid_plg_create_t xvid_plg_create = { 0 }; xvid_plugin_2pass2_t xvid_2pass2 = { 0 }; -//xvid_debug=-1; - fd=ff_tempfile("xvidrc.", &tmp_name); if (fd == -1) { av_log(NULL, AV_LOG_ERROR, "Can't create temporary pass2 file.\n"); @@ -57,7 +53,6 @@ int ff_xvid_rate_control_init(MpegEncContext *s){ frame_types[rce->pict_type], (int)lrintf(rce->qscale / FF_QP2LAMBDA), rce->i_count, s->mb_num - rce->i_count - rce->skip_count, rce->skip_count, (rce->i_tex_bits + rce->p_tex_bits + rce->misc_bits+7)/8, (rce->header_bits+rce->mv_bits+7)/8); -//av_log(NULL, AV_LOG_ERROR, "%s\n", tmp); write(fd, tmp, strlen(tmp)); } From 219a9ed19ee81d0f351683f21dae6b29a0e65a0c Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Thu, 12 Apr 2012 13:43:09 +0200 Subject: [PATCH 18/19] libxvid: Reorder functions to avoid forward declarations; make functions static. --- libavcodec/libxvidff.c | 541 ++++++++++++++++++++--------------------- 1 file changed, 269 insertions(+), 272 deletions(-) diff --git a/libavcodec/libxvidff.c b/libavcodec/libxvidff.c index 344f6033ff..def80b3fac 100644 --- a/libavcodec/libxvidff.c +++ b/libavcodec/libxvidff.c @@ -73,10 +73,15 @@ struct xvid_ff_pass1 { struct xvid_context *context; /**< Pointer to private context */ }; -/* Prototypes - See function implementation for details */ -int xvid_strip_vol_header(AVCodecContext *avctx, AVPacket *pkt, unsigned int header_len, unsigned int frame_len); -int xvid_ff_2pass(void *ref, int opt, void *p1, void *p2); -void xvid_correct_framerate(AVCodecContext *avctx); +/* + * Xvid 2-Pass Kludge Section + * + * Xvid's default 2-pass doesn't allow us to create data as we need to, so + * this section spends time replacing the first pass plugin so we can write + * statistic information as libavcodec requests in. We have another kludge + * that allows us to pass data to the second pass in Xvid without a custom + * rate-control plugin. + */ /* Wrapper to work around the lack of mkstemp() on mingw. * Also, tries to create file in /tmp first, if possible. @@ -114,6 +119,266 @@ int ff_tempfile(const char *prefix, char **filename) { return fd; /* success */ } +/** + * Initialize the two-pass plugin and context. + * + * @param param Input construction parameter structure + * @param handle Private context handle + * @return Returns XVID_ERR_xxxx on failure, or 0 on success. + */ +static int xvid_ff_2pass_create(xvid_plg_create_t * param, + void ** handle) { + struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param; + char *log = x->context->twopassbuffer; + + /* Do a quick bounds check */ + if( log == NULL ) + return XVID_ERR_FAIL; + + /* We use snprintf() */ + /* This is because we can safely prevent a buffer overflow */ + log[0] = 0; + snprintf(log, BUFFER_REMAINING(log), + "# avconv 2-pass log file, using xvid codec\n"); + snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), + "# Do not modify. libxvidcore version: %d.%d.%d\n\n", + XVID_VERSION_MAJOR(XVID_VERSION), + XVID_VERSION_MINOR(XVID_VERSION), + XVID_VERSION_PATCH(XVID_VERSION)); + + *handle = x->context; + return 0; +} + +/** + * Destroy the two-pass plugin context. + * + * @param ref Context pointer for the plugin + * @param param Destrooy context + * @return Returns 0, success guaranteed + */ +static int xvid_ff_2pass_destroy(struct xvid_context *ref, + xvid_plg_destroy_t *param) { + /* Currently cannot think of anything to do on destruction */ + /* Still, the framework should be here for reference/use */ + if( ref->twopassbuffer != NULL ) + ref->twopassbuffer[0] = 0; + return 0; +} + +/** + * Enable fast encode mode during the first pass. + * + * @param ref Context pointer for the plugin + * @param param Frame data + * @return Returns 0, success guaranteed + */ +static int xvid_ff_2pass_before(struct xvid_context *ref, + xvid_plg_data_t *param) { + int motion_remove; + int motion_replacements; + int vop_remove; + + /* Nothing to do here, result is changed too much */ + if( param->zone && param->zone->mode == XVID_ZONE_QUANT ) + return 0; + + /* We can implement a 'turbo' first pass mode here */ + param->quant = 2; + + /* Init values */ + motion_remove = ~XVID_ME_CHROMA_PVOP & + ~XVID_ME_CHROMA_BVOP & + ~XVID_ME_EXTSEARCH16 & + ~XVID_ME_ADVANCEDDIAMOND16; + motion_replacements = XVID_ME_FAST_MODEINTERPOLATE | + XVID_ME_SKIP_DELTASEARCH | + XVID_ME_FASTREFINE16 | + XVID_ME_BFRAME_EARLYSTOP; + vop_remove = ~XVID_VOP_MODEDECISION_RD & + ~XVID_VOP_FAST_MODEDECISION_RD & + ~XVID_VOP_TRELLISQUANT & + ~XVID_VOP_INTER4V & + ~XVID_VOP_HQACPRED; + + param->vol_flags &= ~XVID_VOL_GMC; + param->vop_flags &= vop_remove; + param->motion_flags &= motion_remove; + param->motion_flags |= motion_replacements; + + return 0; +} + +/** + * Capture statistic data and write it during first pass. + * + * @param ref Context pointer for the plugin + * @param param Statistic data + * @return Returns XVID_ERR_xxxx on failure, or 0 on success + */ +static int xvid_ff_2pass_after(struct xvid_context *ref, + xvid_plg_data_t *param) { + char *log = ref->twopassbuffer; + const char *frame_types = " ipbs"; + char frame_type; + + /* Quick bounds check */ + if( log == NULL ) + return XVID_ERR_FAIL; + + /* Convert the type given to us into a character */ + if( param->type < 5 && param->type > 0 ) { + frame_type = frame_types[param->type]; + } else { + return XVID_ERR_FAIL; + } + + snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), + "%c %d %d %d %d %d %d\n", + frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks, + param->stats.ublks, param->stats.length, param->stats.hlength); + + return 0; +} + +/** + * Dispatch function for our custom plugin. + * This handles the dispatch for the Xvid plugin. It passes data + * on to other functions for actual processing. + * + * @param ref Context pointer for the plugin + * @param cmd The task given for us to complete + * @param p1 First parameter (varies) + * @param p2 Second parameter (varies) + * @return Returns XVID_ERR_xxxx on failure, or 0 on success + */ +static int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) +{ + switch( cmd ) { + case XVID_PLG_INFO: + case XVID_PLG_FRAME: + return 0; + + case XVID_PLG_BEFORE: + return xvid_ff_2pass_before(ref, p1); + + case XVID_PLG_CREATE: + return xvid_ff_2pass_create(p1, p2); + + case XVID_PLG_AFTER: + return xvid_ff_2pass_after(ref, p1); + + case XVID_PLG_DESTROY: + return xvid_ff_2pass_destroy(ref, p1); + + default: + return XVID_ERR_FAIL; + } +} + +/** + * Routine to create a global VO/VOL header for MP4 container. + * What we do here is extract the header from the Xvid bitstream + * as it is encoded. We also strip the repeated headers from the + * bitstream when a global header is requested for MPEG-4 ISO + * compliance. + * + * @param avctx AVCodecContext pointer to context + * @param frame Pointer to encoded frame data + * @param header_len Length of header to search + * @param frame_len Length of encoded frame data + * @return Returns new length of frame data + */ +static int xvid_strip_vol_header(AVCodecContext *avctx, + AVPacket *pkt, + unsigned int header_len, + unsigned int frame_len) { + int vo_len = 0, i; + + for( i = 0; i < header_len - 3; i++ ) { + if( pkt->data[i] == 0x00 && + pkt->data[i+1] == 0x00 && + pkt->data[i+2] == 0x01 && + pkt->data[i+3] == 0xB6 ) { + vo_len = i; + break; + } + } + + if( vo_len > 0 ) { + /* We need to store the header, so extract it */ + if( avctx->extradata == NULL ) { + avctx->extradata = av_malloc(vo_len); + memcpy(avctx->extradata, pkt->data, vo_len); + avctx->extradata_size = vo_len; + } + /* Less dangerous now, memmove properly copies the two + chunks of overlapping data */ + memmove(pkt->data, &pkt->data[vo_len], frame_len - vo_len); + pkt->size = frame_len - vo_len; + } + return 0; +} + +/** + * Routine to correct a possibly erroneous framerate being fed to us. + * Xvid currently chokes on framerates where the ticks per frame is + * extremely large. This function works to correct problems in this area + * by estimating a new framerate and taking the simpler fraction of + * the two presented. + * + * @param avctx Context that contains the framerate to correct. + */ +static void xvid_correct_framerate(AVCodecContext *avctx) +{ + int frate, fbase; + int est_frate, est_fbase; + int gcd; + float est_fps, fps; + + frate = avctx->time_base.den; + fbase = avctx->time_base.num; + + gcd = av_gcd(frate, fbase); + if( gcd > 1 ) { + frate /= gcd; + fbase /= gcd; + } + + if( frate <= 65000 && fbase <= 65000 ) { + avctx->time_base.den = frate; + avctx->time_base.num = fbase; + return; + } + + fps = (float)frate / (float)fbase; + est_fps = roundf(fps * 1000.0) / 1000.0; + + est_frate = (int)est_fps; + if( est_fps > (int)est_fps ) { + est_frate = (est_frate + 1) * 1000; + est_fbase = (int)roundf((float)est_frate / est_fps); + } else + est_fbase = 1; + + gcd = av_gcd(est_frate, est_fbase); + if( gcd > 1 ) { + est_frate /= gcd; + est_fbase /= gcd; + } + + if( fbase > est_fbase ) { + avctx->time_base.den = est_frate; + avctx->time_base.num = est_fbase; + av_log(avctx, AV_LOG_DEBUG, + "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n", + est_fps, (((est_fps - fps)/fps) * 100.0)); + } else { + avctx->time_base.den = frate; + avctx->time_base.num = fbase; + } +} + /** * Create the private context for the encoder. * All buffers are allocated, settings are loaded from the user, @@ -546,274 +811,6 @@ static av_cold int xvid_encode_close(AVCodecContext *avctx) { return 0; } -/** - * Routine to create a global VO/VOL header for MP4 container. - * What we do here is extract the header from the Xvid bitstream - * as it is encoded. We also strip the repeated headers from the - * bitstream when a global header is requested for MPEG-4 ISO - * compliance. - * - * @param avctx AVCodecContext pointer to context - * @param frame Pointer to encoded frame data - * @param header_len Length of header to search - * @param frame_len Length of encoded frame data - * @return Returns new length of frame data - */ -int xvid_strip_vol_header(AVCodecContext *avctx, - AVPacket *pkt, - unsigned int header_len, - unsigned int frame_len) { - int vo_len = 0, i; - - for( i = 0; i < header_len - 3; i++ ) { - if( pkt->data[i] == 0x00 && - pkt->data[i+1] == 0x00 && - pkt->data[i+2] == 0x01 && - pkt->data[i+3] == 0xB6 ) { - vo_len = i; - break; - } - } - - if( vo_len > 0 ) { - /* We need to store the header, so extract it */ - if( avctx->extradata == NULL ) { - avctx->extradata = av_malloc(vo_len); - memcpy(avctx->extradata, pkt->data, vo_len); - avctx->extradata_size = vo_len; - } - /* Less dangerous now, memmove properly copies the two - chunks of overlapping data */ - memmove(pkt->data, &pkt->data[vo_len], frame_len - vo_len); - pkt->size = frame_len - vo_len; - } - return 0; -} - -/** - * Routine to correct a possibly erroneous framerate being fed to us. - * Xvid currently chokes on framerates where the ticks per frame is - * extremely large. This function works to correct problems in this area - * by estimating a new framerate and taking the simpler fraction of - * the two presented. - * - * @param avctx Context that contains the framerate to correct. - */ -void xvid_correct_framerate(AVCodecContext *avctx) { - int frate, fbase; - int est_frate, est_fbase; - int gcd; - float est_fps, fps; - - frate = avctx->time_base.den; - fbase = avctx->time_base.num; - - gcd = av_gcd(frate, fbase); - if( gcd > 1 ) { - frate /= gcd; - fbase /= gcd; - } - - if( frate <= 65000 && fbase <= 65000 ) { - avctx->time_base.den = frate; - avctx->time_base.num = fbase; - return; - } - - fps = (float)frate / (float)fbase; - est_fps = roundf(fps * 1000.0) / 1000.0; - - est_frate = (int)est_fps; - if( est_fps > (int)est_fps ) { - est_frate = (est_frate + 1) * 1000; - est_fbase = (int)roundf((float)est_frate / est_fps); - } else - est_fbase = 1; - - gcd = av_gcd(est_frate, est_fbase); - if( gcd > 1 ) { - est_frate /= gcd; - est_fbase /= gcd; - } - - if( fbase > est_fbase ) { - avctx->time_base.den = est_frate; - avctx->time_base.num = est_fbase; - av_log(avctx, AV_LOG_DEBUG, - "Xvid: framerate re-estimated: %.2f, %.3f%% correction\n", - est_fps, (((est_fps - fps)/fps) * 100.0)); - } else { - avctx->time_base.den = frate; - avctx->time_base.num = fbase; - } -} - -/* - * Xvid 2-Pass Kludge Section - * - * Xvid's default 2-pass doesn't allow us to create data as we need to, so - * this section spends time replacing the first pass plugin so we can write - * statistic information as libavcodec requests in. We have another kludge - * that allows us to pass data to the second pass in Xvid without a custom - * rate-control plugin. - */ - -/** - * Initialize the two-pass plugin and context. - * - * @param param Input construction parameter structure - * @param handle Private context handle - * @return Returns XVID_ERR_xxxx on failure, or 0 on success. - */ -static int xvid_ff_2pass_create(xvid_plg_create_t * param, - void ** handle) { - struct xvid_ff_pass1 *x = (struct xvid_ff_pass1 *)param->param; - char *log = x->context->twopassbuffer; - - /* Do a quick bounds check */ - if( log == NULL ) - return XVID_ERR_FAIL; - - /* We use snprintf() */ - /* This is because we can safely prevent a buffer overflow */ - log[0] = 0; - snprintf(log, BUFFER_REMAINING(log), - "# avconv 2-pass log file, using xvid codec\n"); - snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), - "# Do not modify. libxvidcore version: %d.%d.%d\n\n", - XVID_VERSION_MAJOR(XVID_VERSION), - XVID_VERSION_MINOR(XVID_VERSION), - XVID_VERSION_PATCH(XVID_VERSION)); - - *handle = x->context; - return 0; -} - -/** - * Destroy the two-pass plugin context. - * - * @param ref Context pointer for the plugin - * @param param Destrooy context - * @return Returns 0, success guaranteed - */ -static int xvid_ff_2pass_destroy(struct xvid_context *ref, - xvid_plg_destroy_t *param) { - /* Currently cannot think of anything to do on destruction */ - /* Still, the framework should be here for reference/use */ - if( ref->twopassbuffer != NULL ) - ref->twopassbuffer[0] = 0; - return 0; -} - -/** - * Enable fast encode mode during the first pass. - * - * @param ref Context pointer for the plugin - * @param param Frame data - * @return Returns 0, success guaranteed - */ -static int xvid_ff_2pass_before(struct xvid_context *ref, - xvid_plg_data_t *param) { - int motion_remove; - int motion_replacements; - int vop_remove; - - /* Nothing to do here, result is changed too much */ - if( param->zone && param->zone->mode == XVID_ZONE_QUANT ) - return 0; - - /* We can implement a 'turbo' first pass mode here */ - param->quant = 2; - - /* Init values */ - motion_remove = ~XVID_ME_CHROMA_PVOP & - ~XVID_ME_CHROMA_BVOP & - ~XVID_ME_EXTSEARCH16 & - ~XVID_ME_ADVANCEDDIAMOND16; - motion_replacements = XVID_ME_FAST_MODEINTERPOLATE | - XVID_ME_SKIP_DELTASEARCH | - XVID_ME_FASTREFINE16 | - XVID_ME_BFRAME_EARLYSTOP; - vop_remove = ~XVID_VOP_MODEDECISION_RD & - ~XVID_VOP_FAST_MODEDECISION_RD & - ~XVID_VOP_TRELLISQUANT & - ~XVID_VOP_INTER4V & - ~XVID_VOP_HQACPRED; - - param->vol_flags &= ~XVID_VOL_GMC; - param->vop_flags &= vop_remove; - param->motion_flags &= motion_remove; - param->motion_flags |= motion_replacements; - - return 0; -} - -/** - * Capture statistic data and write it during first pass. - * - * @param ref Context pointer for the plugin - * @param param Statistic data - * @return Returns XVID_ERR_xxxx on failure, or 0 on success - */ -static int xvid_ff_2pass_after(struct xvid_context *ref, - xvid_plg_data_t *param) { - char *log = ref->twopassbuffer; - const char *frame_types = " ipbs"; - char frame_type; - - /* Quick bounds check */ - if( log == NULL ) - return XVID_ERR_FAIL; - - /* Convert the type given to us into a character */ - if( param->type < 5 && param->type > 0 ) { - frame_type = frame_types[param->type]; - } else { - return XVID_ERR_FAIL; - } - - snprintf(BUFFER_CAT(log), BUFFER_REMAINING(log), - "%c %d %d %d %d %d %d\n", - frame_type, param->stats.quant, param->stats.kblks, param->stats.mblks, - param->stats.ublks, param->stats.length, param->stats.hlength); - - return 0; -} - -/** - * Dispatch function for our custom plugin. - * This handles the dispatch for the Xvid plugin. It passes data - * on to other functions for actual processing. - * - * @param ref Context pointer for the plugin - * @param cmd The task given for us to complete - * @param p1 First parameter (varies) - * @param p2 Second parameter (varies) - * @return Returns XVID_ERR_xxxx on failure, or 0 on success - */ -int xvid_ff_2pass(void *ref, int cmd, void *p1, void *p2) { - switch( cmd ) { - case XVID_PLG_INFO: - case XVID_PLG_FRAME: - return 0; - - case XVID_PLG_BEFORE: - return xvid_ff_2pass_before(ref, p1); - - case XVID_PLG_CREATE: - return xvid_ff_2pass_create(p1, p2); - - case XVID_PLG_AFTER: - return xvid_ff_2pass_after(ref, p1); - - case XVID_PLG_DESTROY: - return xvid_ff_2pass_destroy(ref, p1); - - default: - return XVID_ERR_FAIL; - } -} - /** * Xvid codec definition for libavcodec. */ From 7bf9e3391fa21d90ff283fc03a12287fe73db9e8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 14 Apr 2012 12:49:27 +0200 Subject: [PATCH 19/19] vsrc_buffer: fix check from 7ae7c41. The user submitted variable in this function is frame, not buf. --- libavfilter/vsrc_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavfilter/vsrc_buffer.c b/libavfilter/vsrc_buffer.c index 46a18df713..742943aa57 100644 --- a/libavfilter/vsrc_buffer.c +++ b/libavfilter/vsrc_buffer.c @@ -51,7 +51,7 @@ int av_vsrc_buffer_add_frame(AVFilterContext *buffer_filter, AVFrame *frame, AVFilterBufferRef *buf; int ret; - if (!buf) { + if (!frame) { c->eof = 1; return 0; } else if (c->eof)