From 2b3d041cdc88fe556e61f70130a3a7eb024e0958 Mon Sep 17 00:00:00 2001 From: "Panagiotis H.M. Issaris" Date: Tue, 10 Jan 2012 14:48:57 +0100 Subject: [PATCH 01/36] applehttp: Do seeking within segments, too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhance seeking by demuxing until the requested timestamp is reached within the segment selected by the seek code using the playlist info. Some mpegts streams don't have dts set for all packets though, this seeking method doesn't work well for that case. Signed-off-by: Martin Storsjö --- libavformat/hls.c | 55 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/libavformat/hls.c b/libavformat/hls.c index 82aa7647ae..c4046f29c6 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -100,6 +100,8 @@ typedef struct HLSContext { int end_of_segment; int first_packet; int64_t first_timestamp; + int64_t seek_timestamp; + int seek_flags; AVIOInterruptCB *interrupt_callback; } HLSContext; @@ -545,6 +547,7 @@ static int hls_read_header(AVFormatContext *s) c->first_packet = 1; c->first_timestamp = AV_NOPTS_VALUE; + c->seek_timestamp = AV_NOPTS_VALUE; return 0; fail: @@ -604,14 +607,37 @@ start: /* Make sure we've got one buffered packet from each open variant * stream */ if (var->needed && !var->pkt.data) { - ret = av_read_frame(var->ctx, &var->pkt); - if (ret < 0) { - if (!var->pb.eof_reached) - return ret; - reset_packet(&var->pkt); - } else { - if (c->first_timestamp == AV_NOPTS_VALUE) - c->first_timestamp = var->pkt.dts; + while (1) { + int64_t ts_diff; + AVStream *st; + ret = av_read_frame(var->ctx, &var->pkt); + if (ret < 0) { + if (!var->pb.eof_reached) + return ret; + reset_packet(&var->pkt); + break; + } else { + if (c->first_timestamp == AV_NOPTS_VALUE) + c->first_timestamp = var->pkt.dts; + } + + if (c->seek_timestamp == AV_NOPTS_VALUE) + break; + + if (var->pkt.dts == AV_NOPTS_VALUE) { + c->seek_timestamp = AV_NOPTS_VALUE; + break; + } + + st = var->ctx->streams[var->pkt.stream_index]; + ts_diff = av_rescale_rnd(var->pkt.dts, AV_TIME_BASE, + st->time_base.den, AV_ROUND_DOWN) - + c->seek_timestamp; + if (ts_diff >= 0 && (c->seek_flags & AVSEEK_FLAG_ANY || + var->pkt.flags & AV_PKT_FLAG_KEY)) { + c->seek_timestamp = AV_NOPTS_VALUE; + break; + } } } /* Check if this stream has the packet with the lowest dts */ @@ -652,10 +678,21 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, if ((flags & AVSEEK_FLAG_BYTE) || !c->variants[0]->finished) return AVERROR(ENOSYS); + c->seek_flags = flags; + c->seek_timestamp = stream_index < 0 ? timestamp : + av_rescale_rnd(timestamp, AV_TIME_BASE, + s->streams[stream_index]->time_base.den, + flags & AVSEEK_FLAG_BACKWARD ? + AV_ROUND_DOWN : AV_ROUND_UP); timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); + if (s->duration < c->seek_timestamp) { + c->seek_timestamp = AV_NOPTS_VALUE; + return AVERROR(EIO); + } + ret = AVERROR(EIO); for (i = 0; i < c->n_variants; i++) { /* Reset reading */ @@ -682,6 +719,8 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, } pos += var->segments[j]->duration; } + if (ret) + c->seek_timestamp = AV_NOPTS_VALUE; } return ret; } From b18f8cbf3dd27ba881770ef588fcb4d1de4a41f5 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Sun, 19 Feb 2012 06:38:49 -0800 Subject: [PATCH 02/36] Revert two swscale commits. Revert "swscale: update context offsets after removal of AlpMmxFilter." (commit a95e3fa90b4190381b65d180eec5a4027075e2da) and Revert "swscale: Remove some write-only variables related to alpha handling." (commit 9d03cb9fc5ddf914920ab0dbe13f19a34c754966). They broke alpha handling - it's the evil inline asm that still uses that variable, so it's not truely write-only. --- libswscale/swscale_internal.h | 10 ++++++---- libswscale/x86/swscale_mmx.c | 14 ++++++++++++++ libswscale/x86/swscale_template.c | 4 ++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 8da1201cbc..bc36826ea2 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -352,10 +352,11 @@ typedef struct SwsContext { #define U_TEMP "11*8+4*4*256*2+24" #define V_TEMP "11*8+4*4*256*2+32" #define Y_TEMP "11*8+4*4*256*2+40" -#define UV_OFF_PX "11*8+4*4*256*2+48" -#define UV_OFF_BYTE "11*8+4*4*256*2+56" -#define DITHER16 "11*8+4*4*256*2+64" -#define DITHER32 "11*8+4*4*256*2+80" +#define ALP_MMX_FILTER_OFFSET "11*8+4*4*256*2+48" +#define UV_OFF_PX "11*8+4*4*256*3+48" +#define UV_OFF_BYTE "11*8+4*4*256*3+56" +#define DITHER16 "11*8+4*4*256*3+64" +#define DITHER32 "11*8+4*4*256*3+80" DECLARE_ALIGNED(8, uint64_t, redDither); DECLARE_ALIGNED(8, uint64_t, greenDither); @@ -377,6 +378,7 @@ typedef struct SwsContext { DECLARE_ALIGNED(8, uint64_t, u_temp); DECLARE_ALIGNED(8, uint64_t, v_temp); DECLARE_ALIGNED(8, uint64_t, y_temp); + int32_t alpMmxFilter[4 * MAX_FILTER_SIZE]; // alignment of these values is not necessary, but merely here // to maintain the same offset across x8632 and x86-64. Once we // use proper offset macros in the asm, they can be removed. diff --git a/libswscale/x86/swscale_mmx.c b/libswscale/x86/swscale_mmx.c index c112cb8a6d..764472e95e 100644 --- a/libswscale/x86/swscale_mmx.c +++ b/libswscale/x86/swscale_mmx.c @@ -90,6 +90,7 @@ void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufI const int flags= c->flags; int16_t **lumPixBuf= c->lumPixBuf; int16_t **chrUPixBuf= c->chrUPixBuf; + int16_t **alpPixBuf= c->alpPixBuf; const int vLumBufSize= c->vLumBufSize; const int vChrBufSize= c->vChrBufSize; int16_t *vLumFilterPos= c->vLumFilterPos; @@ -98,6 +99,7 @@ void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufI int16_t *vChrFilter= c->vChrFilter; int32_t *lumMmxFilter= c->lumMmxFilter; int32_t *chrMmxFilter= c->chrMmxFilter; + int32_t av_unused *alpMmxFilter= c->alpMmxFilter; const int vLumFilterSize= c->vLumFilterSize; const int vChrFilterSize= c->vChrFilterSize; const int chrDstY= dstY>>c->chrDstVSubSample; @@ -113,6 +115,7 @@ void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufI if (dstY < dstH - 2) { const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize; const int16_t **chrUSrcPtr= (const int16_t **) chrUPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize; + const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL; int i; if (flags & SWS_ACCURATE_RND) { int s= APCK_SIZE / 8; @@ -122,6 +125,12 @@ void updateMMXDitherTables(SwsContext *c, int dstY, int lumBufIndex, int chrBufI lumMmxFilter[s*i+APCK_COEF/4 ]= lumMmxFilter[s*i+APCK_COEF/4+1]= vLumFilter[dstY*vLumFilterSize + i ] + (vLumFilterSize>1 ? vLumFilter[dstY*vLumFilterSize + i + 1]<<16 : 0); + if (CONFIG_SWSCALE_ALPHA && alpPixBuf) { + *(const void**)&alpMmxFilter[s*i ]= alpSrcPtr[i ]; + *(const void**)&alpMmxFilter[s*i+APCK_PTR2/4 ]= alpSrcPtr[i+(vLumFilterSize>1)]; + alpMmxFilter[s*i+APCK_COEF/4 ]= + alpMmxFilter[s*i+APCK_COEF/4+1]= lumMmxFilter[s*i+APCK_COEF/4 ]; + } } for (i=0; ialpPixBuf) { YSCALEYUV2PACKEDX YSCALEYUV2RGBX - YSCALEYUV2PACKEDX_YA(LUM_MMX_FILTER_OFFSET, %%mm0, %%mm3, %%mm6, %%mm1, %%mm7) + YSCALEYUV2PACKEDX_YA(ALP_MMX_FILTER_OFFSET, %%mm0, %%mm3, %%mm6, %%mm1, %%mm7) "psraw $3, %%mm1 \n\t" "psraw $3, %%mm7 \n\t" "packuswb %%mm7, %%mm1 \n\t" From 8fb26950ed3c4cd1e175c4439726884926cba022 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Sat, 18 Feb 2012 18:57:22 -0800 Subject: [PATCH 03/36] h264: don't use redzone in loopfilter on win64. Red zone usage is not allowed in the Win64 ABI. --- libavcodec/x86/h264_deblock.asm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libavcodec/x86/h264_deblock.asm b/libavcodec/x86/h264_deblock.asm index f264edb65f..0f61922276 100644 --- a/libavcodec/x86/h264_deblock.asm +++ b/libavcodec/x86/h264_deblock.asm @@ -824,9 +824,13 @@ cglobal deblock_v_chroma_8_mmxext, 5,6 ; void ff_deblock_h_chroma( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 ) ;----------------------------------------------------------------------------- cglobal deblock_h_chroma_8_mmxext, 5,7 -%if ARCH_X86_64 +%if UNIX64 %define buf0 [rsp-24] %define buf1 [rsp-16] +%elif WIN64 + sub rsp, 16 + %define buf0 [rsp] + %define buf1 [rsp+8] %else %define buf0 r0m %define buf1 r2m @@ -839,6 +843,9 @@ cglobal deblock_h_chroma_8_mmxext, 5,7 movq m0, buf0 movq m3, buf1 TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) +%if WIN64 + add rsp, 16 +%endif RET ALIGN 16 From 8c8c7b5e37a64df105100ef3d0e6722c991faa9b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 19 Feb 2012 11:16:16 +0100 Subject: [PATCH 04/36] zmbvenc: move header writing to the end of encode_frame(). This makes switching to encode2() simpler, because it allows us to know exactly how large should the output buffer be before we start writing into it. --- libavcodec/zmbvenc.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/libavcodec/zmbvenc.c b/libavcodec/zmbvenc.c index ebb6624cb8..6425353ff1 100644 --- a/libavcodec/zmbvenc.c +++ b/libavcodec/zmbvenc.c @@ -138,17 +138,6 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void p->key_frame= keyframe; chpal = !keyframe && memcmp(p->data[1], c->pal2, 1024); - fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0); - *buf++ = fl; len++; - if(keyframe){ - deflateReset(&c->zstream); - *buf++ = 0; len++; // hi ver - *buf++ = 1; len++; // lo ver - *buf++ = 1; len++; // comp - *buf++ = 4; len++; // format - 8bpp - *buf++ = ZMBV_BLOCK; len++; // block width - *buf++ = ZMBV_BLOCK; len++; // block height - } palptr = (uint32_t*)p->data[1]; src = p->data[0]; prev = c->prev; @@ -223,6 +212,9 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void src += p->linesize[0]; } + if (keyframe) + deflateReset(&c->zstream); + c->zstream.next_in = c->work_buf; c->zstream.avail_in = work_size; c->zstream.total_in = 0; @@ -235,6 +227,16 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void return -1; } + fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0); + *buf++ = fl; len++; + if (keyframe) { + *buf++ = 0; len++; // hi ver + *buf++ = 1; len++; // lo ver + *buf++ = 1; len++; // comp + *buf++ = 4; len++; // format - 8bpp + *buf++ = ZMBV_BLOCK; len++; // block width + *buf++ = ZMBV_BLOCK; len++; // block height + } memcpy(buf, c->comp_buf, c->zstream.total_out); return len + c->zstream.total_out; } From 11505f39e128e4b9a79aa1998bf3c56f45c5bb14 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 10 Feb 2012 10:30:05 +0100 Subject: [PATCH 05/36] zmbvenc: switch to encode2(). --- libavcodec/zmbvenc.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/libavcodec/zmbvenc.c b/libavcodec/zmbvenc.c index 6425353ff1..1c1e78d912 100644 --- a/libavcodec/zmbvenc.c +++ b/libavcodec/zmbvenc.c @@ -29,6 +29,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "internal.h" #include @@ -115,19 +116,18 @@ static int zmbv_me(ZmbvEncContext *c, uint8_t *src, int sstride, uint8_t *prev, return bv; } -static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void *data) +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) { ZmbvEncContext * const c = avctx->priv_data; - AVFrame *pict = data; AVFrame * const p = &c->pic; - uint8_t *src, *prev; + uint8_t *src, *prev, *buf; uint32_t *palptr; - int len = 0; int keyframe, chpal; int fl; - int work_size = 0; + int work_size = 0, pkt_size; int bw, bh; - int i, j; + int i, j, ret; keyframe = !c->curfrm; c->curfrm++; @@ -227,18 +227,29 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size, void return -1; } + pkt_size = c->zstream.total_out + 1 + 6*keyframe; + if ((ret = ff_alloc_packet(pkt, pkt_size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting packet of size %d.\n", pkt_size); + return ret; + } + buf = pkt->data; + fl = (keyframe ? ZMBV_KEYFRAME : 0) | (chpal ? ZMBV_DELTAPAL : 0); - *buf++ = fl; len++; + *buf++ = fl; if (keyframe) { - *buf++ = 0; len++; // hi ver - *buf++ = 1; len++; // lo ver - *buf++ = 1; len++; // comp - *buf++ = 4; len++; // format - 8bpp - *buf++ = ZMBV_BLOCK; len++; // block width - *buf++ = ZMBV_BLOCK; len++; // block height + *buf++ = 0; // hi ver + *buf++ = 1; // lo ver + *buf++ = 1; // comp + *buf++ = 4; // format - 8bpp + *buf++ = ZMBV_BLOCK; // block width + *buf++ = ZMBV_BLOCK; // block height } memcpy(buf, c->comp_buf, c->zstream.total_out); - return len + c->zstream.total_out; + + pkt->flags |= AV_PKT_FLAG_KEY*keyframe; + *got_packet = 1; + + return 0; } @@ -331,7 +342,7 @@ AVCodec ff_zmbv_encoder = { .id = CODEC_ID_ZMBV, .priv_data_size = sizeof(ZmbvEncContext), .init = encode_init, - .encode = encode_frame, + .encode2 = encode_frame, .close = encode_end, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_PAL8, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), From 2abee9be826144be2e20c329f0c93e393735f26f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 06/36] v410enc: switch to encode2(). --- libavcodec/v410enc.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/libavcodec/v410enc.c b/libavcodec/v410enc.c index a6b3ddbf30..b90771f754 100644 --- a/libavcodec/v410enc.c +++ b/libavcodec/v410enc.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "internal.h" static av_cold int v410_encode_init(AVCodecContext *avctx) { @@ -40,20 +41,19 @@ static av_cold int v410_encode_init(AVCodecContext *avctx) return 0; } -static int v410_encode_frame(AVCodecContext *avctx, uint8_t *buf, - int buf_size, void *data) +static int v410_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pic, int *got_packet) { - AVFrame *pic = data; - uint8_t *dst = buf; + uint8_t *dst; uint16_t *y, *u, *v; uint32_t val; - int i, j; - int output_size = 0; + int i, j, ret; - if (buf_size < avctx->width * avctx->height * 4) { - av_log(avctx, AV_LOG_ERROR, "Out buffer is too small.\n"); - return AVERROR(ENOMEM); + if ((ret = ff_alloc_packet(pkt, avctx->width * avctx->height * 4)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); + return ret; } + dst = pkt->data; avctx->coded_frame->reference = 0; avctx->coded_frame->key_frame = 1; @@ -70,14 +70,15 @@ static int v410_encode_frame(AVCodecContext *avctx, uint8_t *buf, val |= (uint32_t) v[j] << 22; AV_WL32(dst, val); dst += 4; - output_size += 4; } y += pic->linesize[0] >> 1; u += pic->linesize[1] >> 1; v += pic->linesize[2] >> 1; } - return output_size; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + return 0; } static av_cold int v410_encode_close(AVCodecContext *avctx) @@ -92,7 +93,7 @@ AVCodec ff_v410_encoder = { .type = AVMEDIA_TYPE_VIDEO, .id = CODEC_ID_V410, .init = v410_encode_init, - .encode = v410_encode_frame, + .encode2 = v410_encode_frame, .close = v410_encode_close, .pix_fmts = (const enum PixelFormat[]){ PIX_FMT_YUV444P10, PIX_FMT_NONE }, .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), From bc9c70e5a33b988a2cb2e42777dc976dafd6e849 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 07/36] huffyuv: switch to encode2(). --- libavcodec/huffyuv.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index 0c5f6be3b3..4f07808805 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -1226,9 +1226,10 @@ static av_cold int decode_end(AVCodecContext *avctx) #endif /* CONFIG_HUFFYUV_DECODER || CONFIG_FFVHUFF_DECODER */ #if CONFIG_HUFFYUV_ENCODER || CONFIG_FFVHUFF_ENCODER -static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ HYuvContext *s = avctx->priv_data; - AVFrame *pict = data; const int width= s->width; const int width2= s->width>>1; const int height= s->height; @@ -1236,7 +1237,13 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, const int fake_ustride= s->interlaced ? pict->linesize[1]*2 : pict->linesize[1]; const int fake_vstride= s->interlaced ? pict->linesize[2]*2 : pict->linesize[2]; AVFrame * const p= &s->picture; - int i, j, size=0; + int i, j, size = 0, ret; + + if (!pkt->data && + (ret = av_new_packet(pkt, width * height * 3 * 4 + FF_MIN_BUFFER_SIZE)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error allocating output packet.\n"); + return ret; + } *p = *pict; p->pict_type= AV_PICTURE_TYPE_I; @@ -1247,7 +1254,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, generate_len_table(s->len[i], s->stats[i]); if(generate_bits_table(s->bits[i], s->len[i])<0) return -1; - size+= store_table(s, s->len[i], &buf[size]); + size += store_table(s, s->len[i], &pkt->data[size]); } for(i=0; i<3; i++) @@ -1255,7 +1262,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, s->stats[i][j] >>= 1; } - init_put_bits(&s->pb, buf+size, buf_size-size); + init_put_bits(&s->pb, pkt->data + size, pkt->size - size); if(avctx->pix_fmt == PIX_FMT_YUV422P || avctx->pix_fmt == PIX_FMT_YUV420P){ int lefty, leftu, leftv, y, cy; @@ -1413,12 +1420,16 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, avctx->stats_out[0] = '\0'; if(!(s->avctx->flags2 & CODEC_FLAG2_NO_OUTPUT)){ flush_put_bits(&s->pb); - s->dsp.bswap_buf((uint32_t*)buf, (uint32_t*)buf, size); + s->dsp.bswap_buf((uint32_t*)pkt->data, (uint32_t*)pkt->data, size); } s->picture_number++; - return size*4; + pkt->size = size*4; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } static av_cold int encode_end(AVCodecContext *avctx) @@ -1471,7 +1482,7 @@ AVCodec ff_huffyuv_encoder = { .id = CODEC_ID_HUFFYUV, .priv_data_size = sizeof(HYuvContext), .init = encode_init, - .encode = encode_frame, + .encode2 = encode_frame, .close = encode_end, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV422P, PIX_FMT_RGB32, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), @@ -1485,7 +1496,7 @@ AVCodec ff_ffvhuff_encoder = { .id = CODEC_ID_FFVHUFF, .priv_data_size = sizeof(HYuvContext), .init = encode_init, - .encode = encode_frame, + .encode2 = encode_frame, .close = encode_end, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_RGB32, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), From 1ea575504654331aae7d6d87edfcf4caa98822d6 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 08/36] pnmenc: switch to encode2(). --- libavcodec/pnmenc.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/libavcodec/pnmenc.c b/libavcodec/pnmenc.c index a27a278d47..40621c852e 100644 --- a/libavcodec/pnmenc.c +++ b/libavcodec/pnmenc.c @@ -21,21 +21,23 @@ #include "avcodec.h" #include "bytestream.h" +#include "internal.h" #include "pnm.h" -static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, - int buf_size, void *data) +static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) { PNMContext *s = avctx->priv_data; - AVFrame *pict = data; AVFrame * const p = (AVFrame*)&s->picture; - int i, h, h1, c, n, linesize; + int i, h, h1, c, n, linesize, ret; uint8_t *ptr, *ptr1, *ptr2; - if (buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200) { + if ((ret = ff_alloc_packet(pkt, avpicture_get_size(avctx->pix_fmt, + avctx->width, + avctx->height) + 200)) < 0) { av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); - return -1; + return ret; } *p = *pict; @@ -43,8 +45,8 @@ static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, p->key_frame = 1; s->bytestream_start = - s->bytestream = outbuf; - s->bytestream_end = outbuf + buf_size; + s->bytestream = pkt->data; + s->bytestream_end = pkt->data + pkt->size; h = avctx->height; h1 = h; @@ -108,7 +110,11 @@ static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, ptr2 += p->linesize[2]; } } - return s->bytestream - s->bytestream_start; + pkt->size = s->bytestream - s->bytestream_start; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } @@ -119,7 +125,7 @@ AVCodec ff_pgm_encoder = { .id = CODEC_ID_PGM, .priv_data_size = sizeof(PNMContext), .init = ff_pnm_init, - .encode = pnm_encode_frame, + .encode2 = pnm_encode_frame, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), }; @@ -132,7 +138,7 @@ AVCodec ff_pgmyuv_encoder = { .id = CODEC_ID_PGMYUV, .priv_data_size = sizeof(PNMContext), .init = ff_pnm_init, - .encode = pnm_encode_frame, + .encode2 = pnm_encode_frame, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), }; @@ -145,7 +151,7 @@ AVCodec ff_ppm_encoder = { .id = CODEC_ID_PPM, .priv_data_size = sizeof(PNMContext), .init = ff_pnm_init, - .encode = pnm_encode_frame, + .encode2 = pnm_encode_frame, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB48BE, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), }; @@ -158,7 +164,7 @@ AVCodec ff_pbm_encoder = { .id = CODEC_ID_PBM, .priv_data_size = sizeof(PNMContext), .init = ff_pnm_init, - .encode = pnm_encode_frame, + .encode2 = pnm_encode_frame, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), }; From 4fd7cfef0ba1185d4df9e152724eb0ddee623378 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 19 Feb 2012 10:01:01 +0100 Subject: [PATCH 09/36] roqvideoenc: add const qualifier to the input frame. --- libavcodec/roqvideo.h | 2 +- libavcodec/roqvideoenc.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libavcodec/roqvideo.h b/libavcodec/roqvideo.h index a1ff10af7d..e2dc272c04 100644 --- a/libavcodec/roqvideo.h +++ b/libavcodec/roqvideo.h @@ -69,7 +69,7 @@ typedef struct RoqContext { unsigned int framesSinceKeyframe; - AVFrame *frame_to_enc; + const AVFrame *frame_to_enc; uint8_t *out_buf; struct RoqTempData *tmpData; } RoqContext; diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c index 2a62d5509d..01267b3717 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -112,7 +112,7 @@ static inline int square(int x) return x*x; } -static inline int eval_sse(uint8_t *a, uint8_t *b, int count) +static inline int eval_sse(const uint8_t *a, const uint8_t *b, int count) { int diff=0; @@ -124,8 +124,8 @@ static inline int eval_sse(uint8_t *a, uint8_t *b, int count) // FIXME Could use DSPContext.sse, but it is not so speed critical (used // just for motion estimation). -static int block_sse(uint8_t **buf1, uint8_t **buf2, int x1, int y1, int x2, - int y2, int *stride1, int *stride2, int size) +static int block_sse(uint8_t * const *buf1, uint8_t * const *buf2, int x1, int y1, + int x2, int y2, const int *stride1, const int *stride2, int size) { int i, k; int sse=0; @@ -260,7 +260,7 @@ static void create_cel_evals(RoqContext *enc, RoqTempdata *tempData) /** * Get macroblocks from parts of the image */ -static void get_frame_mb(AVFrame *frame, int x, int y, uint8_t mb[], int dim) +static void get_frame_mb(const AVFrame *frame, int x, int y, uint8_t mb[], int dim) { int i, j, cp; @@ -754,8 +754,8 @@ static void reconstruct_and_encode_image(RoqContext *enc, RoqTempdata *tempData, /** * Create a single YUV cell from a 2x2 section of the image */ -static inline void frame_block_to_cell(uint8_t *block, uint8_t **data, - int top, int left, int *stride) +static inline void frame_block_to_cell(uint8_t *block, uint8_t * const *data, + int top, int left, const int *stride) { int i, j, u=0, v=0; @@ -775,7 +775,7 @@ static inline void frame_block_to_cell(uint8_t *block, uint8_t **data, /** * Create YUV clusters for the entire image */ -static void create_clusters(AVFrame *frame, int w, int h, uint8_t *yuvClusters) +static void create_clusters(const AVFrame *frame, int w, int h, uint8_t *yuvClusters) { int i, j, k, l; @@ -1004,7 +1004,7 @@ static void roq_write_video_info_chunk(RoqContext *enc) static int roq_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data) { RoqContext *enc = avctx->priv_data; - AVFrame *frame= data; + const AVFrame *frame= data; uint8_t *buf_start = buf; enc->out_buf = buf; From 3227770092c8beb73582d2df08c3e32055b283d5 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 10/36] roqvideoenc: switch to encode2(). --- libavcodec/roqvideoenc.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c index 01267b3717..0ae6190bb8 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -59,6 +59,7 @@ #include "roqvideo.h" #include "bytestream.h" #include "elbg.h" +#include "internal.h" #include "mathops.h" #define CHROMA_BIAS 1 @@ -1001,13 +1002,12 @@ static void roq_write_video_info_chunk(RoqContext *enc) bytestream_put_byte(&enc->out_buf, 0x00); } -static int roq_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data) +static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) { RoqContext *enc = avctx->priv_data; - const AVFrame *frame= data; - uint8_t *buf_start = buf; + int size, ret; - enc->out_buf = buf; enc->avctx = avctx; enc->frame_to_enc = frame; @@ -1019,10 +1019,12 @@ static int roq_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_s /* 138 bits max per 8x8 block + * 256 codebooks*(6 bytes 2x2 + 4 bytes 4x4) + 8 bytes frame header */ - if (((enc->width*enc->height/64)*138+7)/8 + 256*(6+4) + 8 > buf_size) { - av_log(avctx, AV_LOG_ERROR, " RoQ: Output buffer too small!\n"); - return -1; + size = ((enc->width * enc->height / 64) * 138 + 7) / 8 + 256 * (6 + 4) + 8; + if ((ret = ff_alloc_packet(pkt, size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet with size %d.\n", size); + return ret; } + enc->out_buf = pkt->data; /* Check for I frame */ if (enc->framesSinceKeyframe == avctx->gop_size) @@ -1046,7 +1048,12 @@ static int roq_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_s /* Encode the actual frame */ roq_encode_video(enc); - return enc->out_buf - buf_start; + pkt->size = enc->out_buf - pkt->data; + if (enc->framesSinceKeyframe == 1) + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } static int roq_encode_end(AVCodecContext *avctx) @@ -1071,7 +1078,7 @@ AVCodec ff_roq_encoder = { .id = CODEC_ID_ROQ, .priv_data_size = sizeof(RoqContext), .init = roq_encode_init, - .encode = roq_encode_frame, + .encode2 = roq_encode_frame, .close = roq_encode_end, .supported_framerates = (const AVRational[]){{30,1}, {0,0}}, .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV444P, PIX_FMT_NONE}, From 1e742ea3c8c284cedad7171cafdc9a9c8f3108d7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 19 Feb 2012 10:44:52 +0100 Subject: [PATCH 11/36] targaenc: don't modify input frame. Set the pict_type/key_frame properties on the coded picture. --- libavcodec/targaenc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavcodec/targaenc.c b/libavcodec/targaenc.c index 276bcc83eb..1d857e53e0 100644 --- a/libavcodec/targaenc.c +++ b/libavcodec/targaenc.c @@ -91,9 +91,6 @@ static int targa_encode_frame(AVCodecContext *avctx, return AVERROR(EINVAL); } - p->pict_type= AV_PICTURE_TYPE_I; - p->key_frame= 1; - /* zero out the header and only set applicable fields */ memset(outbuf, 0, 12); AV_WL16(outbuf+12, avctx->width); @@ -154,6 +151,7 @@ static av_cold int targa_encode_init(AVCodecContext *avctx) avcodec_get_frame_defaults(&s->picture); s->picture.key_frame= 1; + s->picture.pict_type = AV_PICTURE_TYPE_I; avctx->coded_frame= &s->picture; return 0; From 61eaf45c99fd4f6545401e6ef50e7a1916000c59 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 12/36] targaenc: switch to encode2(). --- libavcodec/targaenc.c | 56 +++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/libavcodec/targaenc.c b/libavcodec/targaenc.c index 1d857e53e0..6ac219ee30 100644 --- a/libavcodec/targaenc.c +++ b/libavcodec/targaenc.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "internal.h" #include "rle.h" #include "targa.h" @@ -39,7 +40,7 @@ typedef struct TargaContext { * @param h Image height * @return Size of output in bytes, or -1 if larger than out_size */ -static int targa_encode_rle(uint8_t *outbuf, int out_size, AVFrame *pic, +static int targa_encode_rle(uint8_t *outbuf, int out_size, const AVFrame *pic, int bpp, int w, int h) { int y,ret; @@ -59,7 +60,7 @@ static int targa_encode_rle(uint8_t *outbuf, int out_size, AVFrame *pic, return out - outbuf; } -static int targa_encode_normal(uint8_t *outbuf, AVFrame *pic, int bpp, int w, int h) +static int targa_encode_normal(uint8_t *outbuf, const AVFrame *pic, int bpp, int w, int h) { int i, n = bpp * w; uint8_t *out = outbuf; @@ -74,11 +75,10 @@ static int targa_encode_normal(uint8_t *outbuf, AVFrame *pic, int bpp, int w, in return out - outbuf; } -static int targa_encode_frame(AVCodecContext *avctx, - unsigned char *outbuf, - int buf_size, void *data){ - AVFrame *p = data; - int bpp, picsize, datasize = -1; +static int targa_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *p, int *got_packet) +{ + int bpp, picsize, datasize = -1, ret; uint8_t *out; if(avctx->width > 0xffff || avctx->height > 0xffff) { @@ -86,43 +86,43 @@ static int targa_encode_frame(AVCodecContext *avctx, return AVERROR(EINVAL); } picsize = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); - if(buf_size < picsize + 45) { + if ((ret = ff_alloc_packet(pkt, picsize + 45)) < 0) { av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); - return AVERROR(EINVAL); + return ret; } /* zero out the header and only set applicable fields */ - memset(outbuf, 0, 12); - AV_WL16(outbuf+12, avctx->width); - AV_WL16(outbuf+14, avctx->height); + memset(pkt->data, 0, 12); + AV_WL16(pkt->data+12, avctx->width); + AV_WL16(pkt->data+14, avctx->height); /* image descriptor byte: origin is always top-left, bits 0-3 specify alpha */ - outbuf[17] = 0x20 | (avctx->pix_fmt == PIX_FMT_BGRA ? 8 : 0); + pkt->data[17] = 0x20 | (avctx->pix_fmt == PIX_FMT_BGRA ? 8 : 0); switch(avctx->pix_fmt) { case PIX_FMT_GRAY8: - outbuf[2] = TGA_BW; /* uncompressed grayscale image */ - outbuf[16] = 8; /* bpp */ + pkt->data[2] = TGA_BW; /* uncompressed grayscale image */ + pkt->data[16] = 8; /* bpp */ break; case PIX_FMT_RGB555LE: - outbuf[2] = TGA_RGB; /* uncompresses true-color image */ - outbuf[16] = 16; /* bpp */ + pkt->data[2] = TGA_RGB; /* uncompresses true-color image */ + pkt->data[16] = 16; /* bpp */ break; case PIX_FMT_BGR24: - outbuf[2] = TGA_RGB; /* uncompressed true-color image */ - outbuf[16] = 24; /* bpp */ + pkt->data[2] = TGA_RGB; /* uncompressed true-color image */ + pkt->data[16] = 24; /* bpp */ break; case PIX_FMT_BGRA: - outbuf[2] = TGA_RGB; /* uncompressed true-color image */ - outbuf[16] = 32; /* bpp */ + pkt->data[2] = TGA_RGB; /* uncompressed true-color image */ + pkt->data[16] = 32; /* bpp */ break; default: av_log(avctx, AV_LOG_ERROR, "Pixel format '%s' not supported.\n", av_get_pix_fmt_name(avctx->pix_fmt)); return AVERROR(EINVAL); } - bpp = outbuf[16] >> 3; + bpp = pkt->data[16] >> 3; - out = outbuf + 18; /* skip past the header we just output */ + out = pkt->data + 18; /* skip past the header we just output */ /* try RLE compression */ if (avctx->coder_type != FF_CODER_TYPE_RAW) @@ -130,7 +130,7 @@ static int targa_encode_frame(AVCodecContext *avctx, /* if that worked well, mark the picture as RLE compressed */ if(datasize >= 0) - outbuf[2] |= 8; + pkt->data[2] |= 8; /* if RLE didn't make it smaller, go back to no compression */ else datasize = targa_encode_normal(out, p, bpp, avctx->width, avctx->height); @@ -142,7 +142,11 @@ static int targa_encode_frame(AVCodecContext *avctx, * aspect ratio and encoder ID fields available? */ memcpy(out, "\0\0\0\0\0\0\0\0TRUEVISION-XFILE.", 26); - return out + 26 - outbuf; + pkt->size = out + 26 - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } static av_cold int targa_encode_init(AVCodecContext *avctx) @@ -163,7 +167,7 @@ AVCodec ff_targa_encoder = { .id = CODEC_ID_TARGA, .priv_data_size = sizeof(TargaContext), .init = targa_encode_init, - .encode = targa_encode_frame, + .encode2 = targa_encode_frame, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_BGR24, PIX_FMT_BGRA, PIX_FMT_RGB555LE, PIX_FMT_GRAY8, PIX_FMT_NONE}, .long_name= NULL_IF_CONFIG_SMALL("Truevision Targa image"), }; From fb11e22fda5a2e5e2601a6f2f82b2bf50bb0bc5a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 13/36] sgienc: switch to encode2(). --- libavcodec/sgienc.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c index 9d02eea136..fac7facd0c 100644 --- a/libavcodec/sgienc.c +++ b/libavcodec/sgienc.c @@ -21,6 +21,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "internal.h" #include "sgi.h" #include "rle.h" @@ -41,17 +42,17 @@ static av_cold int encode_init(AVCodecContext *avctx) return 0; } -static int encode_frame(AVCodecContext *avctx, unsigned char *buf, - int buf_size, void *data) +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) { SgiContext *s = avctx->priv_data; AVFrame * const p = &s->picture; - uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf; - int x, y, z, length, tablesize; + uint8_t *offsettab, *lengthtab, *in_buf, *encode_buf, *buf; + int x, y, z, length, tablesize, ret; unsigned int width, height, depth, dimension; - unsigned char *orig_buf = buf, *end_buf = buf + buf_size; + unsigned char *end_buf; - *p = *(AVFrame*)data; + *p = *frame; p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; @@ -76,12 +77,18 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, } tablesize = depth * height * 4; - length = tablesize * 2 + SGI_HEADER_SIZE; + length = SGI_HEADER_SIZE; + if (avctx->coder_type == FF_CODER_TYPE_RAW) + length += depth * height * width; + else // assume ff_rl_encode() produces at most 2x size of input + length += tablesize * 2 + depth * height * (2 * width + 1); - if (buf_size < length) { - av_log(avctx, AV_LOG_ERROR, "buf_size too small(need %d, got %d)\n", length, buf_size); - return -1; + if ((ret = ff_alloc_packet(pkt, length)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", length); + return ret; } + buf = pkt->data; + end_buf = pkt->data + pkt->size; /* Encode header. */ bytestream_put_be16(&buf, SGI_MAGIC); @@ -124,7 +131,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, in_buf = p->data[0] + p->linesize[0] * (height - 1) + z; for (y = 0; y < height; y++) { - bytestream_put_be32(&offsettab, buf - orig_buf); + bytestream_put_be32(&offsettab, buf - pkt->data); for (x = 0; x < width; x++) encode_buf[x] = in_buf[depth * x]; @@ -156,7 +163,11 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, } /* total length */ - return buf - orig_buf; + pkt->size = buf - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } AVCodec ff_sgi_encoder = { @@ -165,7 +176,7 @@ AVCodec ff_sgi_encoder = { .id = CODEC_ID_SGI, .priv_data_size = sizeof(SgiContext), .init = encode_init, - .encode = encode_frame, + .encode2 = encode_frame, .pix_fmts= (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGBA, PIX_FMT_GRAY8, PIX_FMT_NONE}, .long_name= NULL_IF_CONFIG_SMALL("SGI image"), }; From 55fd7da10739bb0072664e5083d33f4778fd5413 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 12 Feb 2012 09:32:40 +0100 Subject: [PATCH 14/36] pcxenc: switch to encode2(). --- libavcodec/pcxenc.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/libavcodec/pcxenc.c b/libavcodec/pcxenc.c index 308456808a..c8259cd8b2 100644 --- a/libavcodec/pcxenc.c +++ b/libavcodec/pcxenc.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "internal.h" typedef struct PCXContext { AVFrame picture; @@ -95,19 +96,19 @@ static int pcx_rle_encode( uint8_t *dst, int dst_size, return dst - dst_start; } -static int pcx_encode_frame(AVCodecContext *avctx, - unsigned char *buf, int buf_size, void *data) +static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) { PCXContext *s = avctx->priv_data; AVFrame *const pict = &s->picture; - const uint8_t *buf_start = buf; - const uint8_t *buf_end = buf + buf_size; + const uint8_t *buf_end; + uint8_t *buf; - int bpp, nplanes, i, y, line_bytes, written; + int bpp, nplanes, i, y, line_bytes, written, ret, max_pkt_size; const uint32_t *pal = NULL; const uint8_t *src; - *pict = *(AVFrame *)data; + *pict = *frame; pict->pict_type = AV_PICTURE_TYPE_I; pict->key_frame = 1; @@ -144,6 +145,14 @@ static int pcx_encode_frame(AVCodecContext *avctx, line_bytes = (avctx->width * bpp + 7) >> 3; line_bytes = (line_bytes + 1) & ~1; + max_pkt_size = 128 + avctx->height * 2 * line_bytes * nplanes + (pal ? 256*3 + 1 : 0); + if ((ret = ff_alloc_packet(pkt, max_pkt_size)) < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet of size %d.\n", max_pkt_size); + return ret; + } + buf = pkt->data; + buf_end = pkt->data + pkt->size; + bytestream_put_byte(&buf, 10); // manufacturer bytestream_put_byte(&buf, 5); // version bytestream_put_byte(&buf, 1); // encoding @@ -160,7 +169,7 @@ static int pcx_encode_frame(AVCodecContext *avctx, bytestream_put_byte(&buf, nplanes); // number of planes bytestream_put_le16(&buf, line_bytes); // scanline plane size in bytes - while (buf - buf_start < 128) + while (buf - pkt->data < 128) *buf++= 0; src = pict->data[0]; @@ -186,7 +195,11 @@ static int pcx_encode_frame(AVCodecContext *avctx, } } - return buf - buf_start; + pkt->size = buf - pkt->data; + pkt->flags |= AV_PKT_FLAG_KEY; + *got_packet = 1; + + return 0; } AVCodec ff_pcx_encoder = { @@ -195,7 +208,7 @@ AVCodec ff_pcx_encoder = { .id = CODEC_ID_PCX, .priv_data_size = sizeof(PCXContext), .init = pcx_encode_init, - .encode = pcx_encode_frame, + .encode2 = pcx_encode_frame, .pix_fmts = (const enum PixelFormat[]){ PIX_FMT_RGB24, PIX_FMT_RGB8, PIX_FMT_BGR8, PIX_FMT_RGB4_BYTE, PIX_FMT_BGR4_BYTE, PIX_FMT_GRAY8, PIX_FMT_PAL8, From a4f97be1a9ed80f47ca93ebfc5faaaba658250c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 20 Jan 2012 16:29:09 +0200 Subject: [PATCH 15/36] hls: Reset the AVIOContext when seeking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids reading any old data in the AVIOContext buffer after the seek, and indicates to the mpegts demuxer that we've seeked, avoiding continuity check errors. Signed-off-by: Martin Storsjö --- libavformat/hls.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/hls.c b/libavformat/hls.c index c4046f29c6..e876735468 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -708,6 +708,10 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, av_free_packet(&var->pkt); reset_packet(&var->pkt); var->pb.eof_reached = 0; + /* Clear any buffered data */ + var->pb.buf_end = var->pb.buf_ptr = var->pb.buffer; + /* Reset the pos, to let the mpegts demuxer know we've seeked. */ + var->pb.pos = 0; /* Locate the segment that contains the target timestamp */ for (j = 0; j < var->n_segments; j++) { From 310c372e12f26df2dbed29a57cdeee13522c8d47 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 16 Feb 2012 22:04:08 -0500 Subject: [PATCH 16/36] libmp3lame: remove unneeded 'stereo' field from Mp3AudioContext --- libavcodec/libmp3lame.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 3ac033f758..b8ccb26115 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -35,7 +35,6 @@ typedef struct Mp3AudioContext { AVClass *class; lame_global_flags *gfp; - int stereo; uint8_t buffer[BUFFER_SIZE]; int buffer_index; int reservoir; @@ -48,8 +47,6 @@ static av_cold int MP3lame_encode_init(AVCodecContext *avctx) if (avctx->channels > 2) return -1; - s->stereo = avctx->channels > 1 ? 1 : 0; - if ((s->gfp = lame_init()) == NULL) goto err; lame_set_in_samplerate(s->gfp, avctx->sample_rate); @@ -60,7 +57,7 @@ static av_cold int MP3lame_encode_init(AVCodecContext *avctx) } else { lame_set_quality(s->gfp, avctx->compression_level); } - lame_set_mode(s->gfp, s->stereo ? JOINT_STEREO : MONO); + lame_set_mode(s->gfp, avctx->channels > 1 ? JOINT_STEREO : MONO); lame_set_brate(s->gfp, avctx->bit_rate / 1000); if (avctx->flags & CODEC_FLAG_QSCALE) { lame_set_brate(s->gfp, 0); @@ -153,7 +150,7 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, /* lame 3.91 dies on '1-channel interleaved' data */ if (data) { - if (s->stereo) { + if (avctx->channels > 1) { lame_result = lame_encode_buffer_interleaved(s->gfp, data, avctx->frame_size, s->buffer + s->buffer_index, From 8dad25ebf7384d824d2a0980ed74c77a32174cc3 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 16 Feb 2012 22:12:03 -0500 Subject: [PATCH 17/36] libmp3lame: improve error handling in MP3lame_encode_init() --- libavcodec/libmp3lame.c | 46 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index b8ccb26115..1241cdc754 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -40,15 +40,27 @@ typedef struct Mp3AudioContext { int reservoir; } Mp3AudioContext; -static av_cold int MP3lame_encode_init(AVCodecContext *avctx) + +static av_cold int MP3lame_encode_close(AVCodecContext *avctx) { Mp3AudioContext *s = avctx->priv_data; + av_freep(&avctx->coded_frame); + + lame_close(s->gfp); + return 0; +} + +static av_cold int MP3lame_encode_init(AVCodecContext *avctx) +{ + Mp3AudioContext *s = avctx->priv_data; + int ret; + if (avctx->channels > 2) - return -1; + return AVERROR(EINVAL); if ((s->gfp = lame_init()) == NULL) - goto err; + return AVERROR(ENOMEM); lame_set_in_samplerate(s->gfp, avctx->sample_rate); lame_set_out_samplerate(s->gfp, avctx->sample_rate); lame_set_num_channels(s->gfp, avctx->channels); @@ -66,19 +78,23 @@ static av_cold int MP3lame_encode_init(AVCodecContext *avctx) } lame_set_bWriteVbrTag(s->gfp,0); lame_set_disable_reservoir(s->gfp, !s->reservoir); - if (lame_init_params(s->gfp) < 0) - goto err_close; + if (lame_init_params(s->gfp) < 0) { + ret = -1; + goto error; + } avctx->frame_size = lame_get_framesize(s->gfp); avctx->coded_frame = avcodec_alloc_frame(); + if (!avctx->coded_frame) { + ret = AVERROR(ENOMEM); + goto error; + } avctx->coded_frame->key_frame = 1; return 0; - -err_close: - lame_close(s->gfp); -err: - return -1; +error: + MP3lame_encode_close(avctx); + return ret; } static const int sSampleRates[] = { @@ -198,16 +214,6 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, return 0; } -static av_cold int MP3lame_encode_close(AVCodecContext *avctx) -{ - Mp3AudioContext *s = avctx->priv_data; - - av_freep(&avctx->coded_frame); - - lame_close(s->gfp); - return 0; -} - #define OFFSET(x) offsetof(Mp3AudioContext, x) #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { From 35cfd7d09c6ac363863255b622e7a03b2415e573 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 16 Feb 2012 22:12:21 -0500 Subject: [PATCH 18/36] libmp3lame: do not set coded_frame->key_frame. it is already set in avcodec_alloc_frame() --- libavcodec/libmp3lame.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 1241cdc754..040965579d 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -89,7 +89,6 @@ static av_cold int MP3lame_encode_init(AVCodecContext *avctx) ret = AVERROR(ENOMEM); goto error; } - avctx->coded_frame->key_frame = 1; return 0; error: From 469d2a8e8e07a080cfadb6368de86043b43e20d2 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 16 Feb 2012 22:18:31 -0500 Subject: [PATCH 19/36] libmp3lame: remove outdated comment. We now require at least libmp3lame 3.98.3. lame_encode_buffer_interleaved() still doesn't work for mono, but it does not "die"; it just expects a stereo interleaved buffer. --- libavcodec/libmp3lame.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 040965579d..6ce4f648a6 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -162,8 +162,6 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, int len; int lame_result; - /* lame 3.91 dies on '1-channel interleaved' data */ - if (data) { if (avctx->channels > 1) { lame_result = lame_encode_buffer_interleaved(s->gfp, data, From bf909fc456156d66f522930b636fa0226ddcae7b Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 16 Feb 2012 22:25:51 -0500 Subject: [PATCH 20/36] libmp3lame: convert some debugging code to av_dlog() also remove unneeded commented-out full frame data debugging --- libavcodec/libmp3lame.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 6ce4f648a6..2b8c1456b9 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -195,17 +195,14 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, return 0; len = mp3len(s->buffer, NULL, NULL); - //av_log(avctx, AV_LOG_DEBUG, "in:%d packet-len:%d index:%d\n", - // avctx->frame_size, len, s->buffer_index); + av_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len, + s->buffer_index); if (len <= s->buffer_index) { memcpy(frame, s->buffer, len); s->buffer_index -= len; memmove(s->buffer, s->buffer + len, s->buffer_index); // FIXME fix the audio codec API, so we do not need the memcpy() - /*for(i=0; i Date: Thu, 16 Feb 2012 22:27:46 -0500 Subject: [PATCH 21/36] libmp3lame: cosmetics: remove some pointless comments --- libavcodec/libmp3lame.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 2b8c1456b9..1e0beb58eb 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -181,7 +181,6 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, if (lame_result < 0) { if (lame_result == -1) { - /* output buffer too small */ av_log(avctx, AV_LOG_ERROR, "lame: output buffer too small (buffer index: %d, free bytes: %d)\n", s->buffer_index, BUFFER_SIZE - s->buffer_index); @@ -202,7 +201,6 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, s->buffer_index -= len; memmove(s->buffer, s->buffer + len, s->buffer_index); - // FIXME fix the audio codec API, so we do not need the memcpy() return len; } else return 0; From 1f516c045152e428b64e1c69105b447a6c484355 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 16 Feb 2012 23:06:54 -0500 Subject: [PATCH 22/36] libmp3lame: use avpriv_mpegaudio_decode_header() for output frame parsing --- libavcodec/Makefile | 2 +- libavcodec/libmp3lame.c | 63 +++++------------------------------------ 2 files changed, 8 insertions(+), 57 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 92a5c13b76..93ff7d4a67 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -579,7 +579,7 @@ OBJS-$(CONFIG_LIBGSM_DECODER) += libgsm.o OBJS-$(CONFIG_LIBGSM_ENCODER) += libgsm.o OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsm.o OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsm.o -OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o +OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 1e0beb58eb..a15aed3d16 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -29,6 +29,7 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "mpegaudio.h" +#include "mpegaudiodecheader.h" #include #define BUFFER_SIZE (7200 + 2 * MPA_FRAME_SIZE + MPA_FRAME_SIZE / 4) @@ -100,65 +101,11 @@ static const int sSampleRates[] = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000, 0 }; -static const int sBitRates[2][3][15] = { - { - { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, - { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, - { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } - }, - { - { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }, - { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }, - { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } - }, -}; - -static const int sSamplesPerFrame[2][3] = { - { 384, 1152, 1152 }, - { 384, 1152, 576 } -}; - -static const int sBitsPerSlot[3] = { 32, 8, 8 }; - -static int mp3len(void *data, int *samplesPerFrame, int *sampleRate) -{ - uint32_t header = AV_RB32(data); - int layerID = 3 - ((header >> 17) & 0x03); - int bitRateID = ((header >> 12) & 0x0f); - int sampleRateID = ((header >> 10) & 0x03); - int bitsPerSlot = sBitsPerSlot[layerID]; - int isPadded = ((header >> 9) & 0x01); - static int const mode_tab[4] = { 2, 3, 1, 0 }; - int mode = mode_tab[(header >> 19) & 0x03]; - int mpeg_id = mode > 0; - int temp0, temp1, bitRate; - - if (((header >> 21) & 0x7ff) != 0x7ff || mode == 3 || layerID == 3 || - sampleRateID == 3) { - return -1; - } - - if (!samplesPerFrame) - samplesPerFrame = &temp0; - if (!sampleRate) - sampleRate = &temp1; - - //*isMono = ((header >> 6) & 0x03) == 0x03; - - *sampleRate = sSampleRates[sampleRateID] >> mode; - bitRate = sBitRates[mpeg_id][layerID][bitRateID] * 1000; - *samplesPerFrame = sSamplesPerFrame[mpeg_id][layerID]; - //av_log(NULL, AV_LOG_DEBUG, - // "sr:%d br:%d spf:%d l:%d m:%d\n", - // *sampleRate, bitRate, *samplesPerFrame, layerID, mode); - - return *samplesPerFrame * bitRate / (bitsPerSlot * *sampleRate) + isPadded; -} - static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, int buf_size, void *data) { Mp3AudioContext *s = avctx->priv_data; + MPADecodeHeader hdr; int len; int lame_result; @@ -193,7 +140,11 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, if (s->buffer_index < 4) return 0; - len = mp3len(s->buffer, NULL, NULL); + if (avpriv_mpegaudio_decode_header(&hdr, AV_RB32(s->buffer))) { + av_log(avctx, AV_LOG_ERROR, "free format output not supported\n"); + return -1; + } + len = hdr.frame_size; av_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len, s->buffer_index); if (len <= s->buffer_index) { From 232e16dd02ff93e2d25e3d30d01961f98ee08c75 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 16 Feb 2012 23:28:38 -0500 Subject: [PATCH 23/36] libmp3lame: use the LAME default bit rate Also, only set bit rate for CBR. --- libavcodec/libmp3lame.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index a15aed3d16..79384b84db 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -28,6 +28,7 @@ #include "libavutil/log.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "internal.h" #include "mpegaudio.h" #include "mpegaudiodecheader.h" #include @@ -71,11 +72,12 @@ static av_cold int MP3lame_encode_init(AVCodecContext *avctx) lame_set_quality(s->gfp, avctx->compression_level); } lame_set_mode(s->gfp, avctx->channels > 1 ? JOINT_STEREO : MONO); - lame_set_brate(s->gfp, avctx->bit_rate / 1000); if (avctx->flags & CODEC_FLAG_QSCALE) { - lame_set_brate(s->gfp, 0); lame_set_VBR(s->gfp, vbr_default); lame_set_VBR_quality(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA); + } else { + if (avctx->bit_rate) + lame_set_brate(s->gfp, avctx->bit_rate / 1000); } lame_set_bWriteVbrTag(s->gfp,0); lame_set_disable_reservoir(s->gfp, !s->reservoir); @@ -171,6 +173,11 @@ static const AVClass libmp3lame_class = { .version = LIBAVUTIL_VERSION_INT, }; +static const AVCodecDefault libmp3lame_defaults[] = { + { "b", "0" }, + { NULL }, +}; + AVCodec ff_libmp3lame_encoder = { .name = "libmp3lame", .type = AVMEDIA_TYPE_AUDIO, @@ -185,4 +192,5 @@ AVCodec ff_libmp3lame_encoder = { .supported_samplerates = sSampleRates, .long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"), .priv_class = &libmp3lame_class, + .defaults = libmp3lame_defaults, }; From e2322252764daad55dfe977dc3dba3e4e5ab67e1 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 17 Feb 2012 00:04:54 -0500 Subject: [PATCH 24/36] libmp3lame: renaming, rearrangement, alignment, and comments --- libavcodec/libmp3lame.c | 88 ++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 79384b84db..365b6395f8 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -24,6 +24,8 @@ * Interface to libmp3lame for mp3 encoding. */ +#include + #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -31,21 +33,21 @@ #include "internal.h" #include "mpegaudio.h" #include "mpegaudiodecheader.h" -#include #define BUFFER_SIZE (7200 + 2 * MPA_FRAME_SIZE + MPA_FRAME_SIZE / 4) -typedef struct Mp3AudioContext { + +typedef struct LAMEContext { AVClass *class; lame_global_flags *gfp; uint8_t buffer[BUFFER_SIZE]; int buffer_index; int reservoir; -} Mp3AudioContext; +} LAMEContext; -static av_cold int MP3lame_encode_close(AVCodecContext *avctx) +static av_cold int mp3lame_encode_close(AVCodecContext *avctx) { - Mp3AudioContext *s = avctx->priv_data; + LAMEContext *s = avctx->priv_data; av_freep(&avctx->coded_frame); @@ -53,25 +55,34 @@ static av_cold int MP3lame_encode_close(AVCodecContext *avctx) return 0; } -static av_cold int MP3lame_encode_init(AVCodecContext *avctx) +static av_cold int mp3lame_encode_init(AVCodecContext *avctx) { - Mp3AudioContext *s = avctx->priv_data; + LAMEContext *s = avctx->priv_data; int ret; - if (avctx->channels > 2) - return AVERROR(EINVAL); - + /* initialize LAME and get defaults */ if ((s->gfp = lame_init()) == NULL) return AVERROR(ENOMEM); - lame_set_in_samplerate(s->gfp, avctx->sample_rate); - lame_set_out_samplerate(s->gfp, avctx->sample_rate); - lame_set_num_channels(s->gfp, avctx->channels); - if (avctx->compression_level == FF_COMPRESSION_DEFAULT) { - lame_set_quality(s->gfp, 5); - } else { - lame_set_quality(s->gfp, avctx->compression_level); + + /* channels */ + if (avctx->channels > 2) { + ret = AVERROR(EINVAL); + goto error; } + lame_set_num_channels(s->gfp, avctx->channels); lame_set_mode(s->gfp, avctx->channels > 1 ? JOINT_STEREO : MONO); + + /* sample rate */ + lame_set_in_samplerate (s->gfp, avctx->sample_rate); + lame_set_out_samplerate(s->gfp, avctx->sample_rate); + + /* algorithmic quality */ + if (avctx->compression_level == FF_COMPRESSION_DEFAULT) + lame_set_quality(s->gfp, 5); + else + lame_set_quality(s->gfp, avctx->compression_level); + + /* rate control */ if (avctx->flags & CODEC_FLAG_QSCALE) { lame_set_VBR(s->gfp, vbr_default); lame_set_VBR_quality(s->gfp, avctx->global_quality / (float)FF_QP2LAMBDA); @@ -79,15 +90,21 @@ static av_cold int MP3lame_encode_init(AVCodecContext *avctx) if (avctx->bit_rate) lame_set_brate(s->gfp, avctx->bit_rate / 1000); } + + /* do not get a Xing VBR header frame from LAME */ lame_set_bWriteVbrTag(s->gfp,0); + + /* bit reservoir usage */ lame_set_disable_reservoir(s->gfp, !s->reservoir); + + /* set specified parameters */ if (lame_init_params(s->gfp) < 0) { ret = -1; goto error; } - avctx->frame_size = lame_get_framesize(s->gfp); - avctx->coded_frame = avcodec_alloc_frame(); + avctx->frame_size = lame_get_framesize(s->gfp); + avctx->coded_frame = avcodec_alloc_frame(); if (!avctx->coded_frame) { ret = AVERROR(ENOMEM); goto error; @@ -95,18 +112,14 @@ static av_cold int MP3lame_encode_init(AVCodecContext *avctx) return 0; error: - MP3lame_encode_close(avctx); + mp3lame_encode_close(avctx); return ret; } -static const int sSampleRates[] = { - 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000, 0 -}; - -static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, +static int mp3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, int buf_size, void *data) { - Mp3AudioContext *s = avctx->priv_data; + LAMEContext *s = avctx->priv_data; MPADecodeHeader hdr; int len; int lame_result; @@ -127,7 +140,6 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, lame_result = lame_encode_flush(s->gfp, s->buffer + s->buffer_index, BUFFER_SIZE - s->buffer_index); } - if (lame_result < 0) { if (lame_result == -1) { av_log(avctx, AV_LOG_ERROR, @@ -136,12 +148,13 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, } return -1; } - s->buffer_index += lame_result; + /* Move 1 frame from the LAME buffer to the output packet, if available. + We have to parse the first frame header in the output buffer to + determine the frame size. */ if (s->buffer_index < 4) return 0; - if (avpriv_mpegaudio_decode_header(&hdr, AV_RB32(s->buffer))) { av_log(avctx, AV_LOG_ERROR, "free format output not supported\n"); return -1; @@ -152,14 +165,13 @@ static int MP3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, if (len <= s->buffer_index) { memcpy(frame, s->buffer, len); s->buffer_index -= len; - memmove(s->buffer, s->buffer + len, s->buffer_index); return len; } else return 0; } -#define OFFSET(x) offsetof(Mp3AudioContext, x) +#define OFFSET(x) offsetof(LAMEContext, x) #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "reservoir", "Use bit reservoir.", OFFSET(reservoir), AV_OPT_TYPE_INT, { 1 }, 0, 1, AE }, @@ -178,18 +190,22 @@ static const AVCodecDefault libmp3lame_defaults[] = { { NULL }, }; +static const int libmp3lame_sample_rates[] = { + 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000, 0 +}; + AVCodec ff_libmp3lame_encoder = { .name = "libmp3lame", .type = AVMEDIA_TYPE_AUDIO, .id = CODEC_ID_MP3, - .priv_data_size = sizeof(Mp3AudioContext), - .init = MP3lame_encode_init, - .encode = MP3lame_encode_frame, - .close = MP3lame_encode_close, + .priv_data_size = sizeof(LAMEContext), + .init = mp3lame_encode_init, + .encode = mp3lame_encode_frame, + .close = mp3lame_encode_close, .capabilities = CODEC_CAP_DELAY, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = sSampleRates, + .supported_samplerates = libmp3lame_sample_rates, .long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"), .priv_class = &libmp3lame_class, .defaults = libmp3lame_defaults, From e00959a9b176f6ad19853b75796dbc12ea264a78 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 17 Feb 2012 01:50:57 -0500 Subject: [PATCH 25/36] libmp3lame: support float and s32 sample formats --- libavcodec/libmp3lame.c | 95 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 365b6395f8..d9f8120411 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -38,10 +38,12 @@ typedef struct LAMEContext { AVClass *class; + AVCodecContext *avctx; lame_global_flags *gfp; uint8_t buffer[BUFFER_SIZE]; int buffer_index; int reservoir; + void *planar_samples[2]; } LAMEContext; @@ -50,6 +52,8 @@ static av_cold int mp3lame_encode_close(AVCodecContext *avctx) LAMEContext *s = avctx->priv_data; av_freep(&avctx->coded_frame); + av_freep(&s->planar_samples[0]); + av_freep(&s->planar_samples[1]); lame_close(s->gfp); return 0; @@ -60,6 +64,8 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) LAMEContext *s = avctx->priv_data; int ret; + s->avctx = avctx; + /* initialize LAME and get defaults */ if ((s->gfp = lame_init()) == NULL) return AVERROR(ENOMEM); @@ -110,12 +116,75 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) goto error; } + /* sample format */ + if (avctx->sample_fmt == AV_SAMPLE_FMT_S32 || + avctx->sample_fmt == AV_SAMPLE_FMT_FLT) { + int ch; + for (ch = 0; ch < avctx->channels; ch++) { + s->planar_samples[ch] = av_malloc(avctx->frame_size * + av_get_bytes_per_sample(avctx->sample_fmt)); + if (!s->planar_samples[ch]) { + ret = AVERROR(ENOMEM); + goto error; + } + } + } + return 0; error: mp3lame_encode_close(avctx); return ret; } +#define DEINTERLEAVE(type, scale) do { \ + int ch, i; \ + for (ch = 0; ch < s->avctx->channels; ch++) { \ + const type *input = samples; \ + type *output = s->planar_samples[ch]; \ + input += ch; \ + for (i = 0; i < s->avctx->frame_size; i++) { \ + output[i] = *input * scale; \ + input += s->avctx->channels; \ + } \ + } \ +} while (0) + +static int encode_frame_int16(LAMEContext *s, void *samples) +{ + if (s->avctx->channels > 1) { + return lame_encode_buffer_interleaved(s->gfp, samples, + s->avctx->frame_size, + s->buffer + s->buffer_index, + BUFFER_SIZE - s->buffer_index); + } else { + return lame_encode_buffer(s->gfp, samples, NULL, s->avctx->frame_size, + s->buffer + s->buffer_index, + BUFFER_SIZE - s->buffer_index); + } +} + +static int encode_frame_int32(LAMEContext *s, void *samples) +{ + DEINTERLEAVE(int32_t, 1); + + return lame_encode_buffer_int(s->gfp, + s->planar_samples[0], s->planar_samples[1], + s->avctx->frame_size, + s->buffer + s->buffer_index, + BUFFER_SIZE - s->buffer_index); +} + +static int encode_frame_float(LAMEContext *s, void *samples) +{ + DEINTERLEAVE(float, 32768.0f); + + return lame_encode_buffer_float(s->gfp, + s->planar_samples[0], s->planar_samples[1], + s->avctx->frame_size, + s->buffer + s->buffer_index, + BUFFER_SIZE - s->buffer_index); +} + static int mp3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, int buf_size, void *data) { @@ -125,16 +194,18 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, unsigned char *frame, int lame_result; if (data) { - if (avctx->channels > 1) { - lame_result = lame_encode_buffer_interleaved(s->gfp, data, - avctx->frame_size, - s->buffer + s->buffer_index, - BUFFER_SIZE - s->buffer_index); - } else { - lame_result = lame_encode_buffer(s->gfp, data, data, - avctx->frame_size, s->buffer + - s->buffer_index, BUFFER_SIZE - - s->buffer_index); + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16: + lame_result = encode_frame_int16(s, data); + break; + case AV_SAMPLE_FMT_S32: + lame_result = encode_frame_int32(s, data); + break; + case AV_SAMPLE_FMT_FLT: + lame_result = encode_frame_float(s, data); + break; + default: + return AVERROR_BUG; } } else { lame_result = lame_encode_flush(s->gfp, s->buffer + s->buffer_index, @@ -203,7 +274,9 @@ AVCodec ff_libmp3lame_encoder = { .encode = mp3lame_encode_frame, .close = mp3lame_encode_close, .capabilities = CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .supported_samplerates = libmp3lame_sample_rates, .long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"), From 0996f406c4d32858e00637206fff7c435b51488c Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sun, 19 Feb 2012 05:20:01 +0000 Subject: [PATCH 26/36] pnmdec: remove useless .pix_fmts Signed-off-by: Paul B Mahol Signed-off-by: Justin Ruggles --- libavcodec/pnmdec.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c index e0e9f66551..c5d236f971 100644 --- a/libavcodec/pnmdec.c +++ b/libavcodec/pnmdec.c @@ -197,7 +197,6 @@ AVCodec ff_pgm_decoder = { .close = ff_pnm_end, .decode = pnm_decode_frame, .capabilities = CODEC_CAP_DR1, - .pix_fmts = (const enum PixelFormat[]){PIX_FMT_GRAY8, PIX_FMT_GRAY16BE, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), }; #endif @@ -212,7 +211,6 @@ AVCodec ff_pgmyuv_decoder = { .close = ff_pnm_end, .decode = pnm_decode_frame, .capabilities = CODEC_CAP_DR1, - .pix_fmts = (const enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), }; #endif @@ -227,7 +225,6 @@ AVCodec ff_ppm_decoder = { .close = ff_pnm_end, .decode = pnm_decode_frame, .capabilities = CODEC_CAP_DR1, - .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB48BE, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), }; #endif @@ -242,7 +239,6 @@ AVCodec ff_pbm_decoder = { .close = ff_pnm_end, .decode = pnm_decode_frame, .capabilities = CODEC_CAP_DR1, - .pix_fmts = (const enum PixelFormat[]){PIX_FMT_MONOWHITE, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), }; #endif @@ -257,7 +253,6 @@ AVCodec ff_pam_decoder = { .close = ff_pnm_end, .decode = pnm_decode_frame, .capabilities = CODEC_CAP_DR1, - .pix_fmts = (const enum PixelFormat[]){PIX_FMT_RGB24, PIX_FMT_RGB32, PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), }; #endif From 0b42a9388c98c8669811d4e7e5da7240e6707a41 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 13 Feb 2012 15:35:00 -0500 Subject: [PATCH 27/36] avutil: add av_rescale_q_rnd() to allow different rounding --- doc/APIchanges | 3 +++ libavutil/avutil.h | 2 +- libavutil/mathematics.c | 11 +++++++++-- libavutil/mathematics.h | 6 ++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index f962432651..ca521d41a5 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2011-04-18 API changes, most recent first: +2012-02-xx - xxxxxxx - lavu 51.23.1 - mathematics.h + Add av_rescale_q_rnd() + 2012-02-xx - xxxxxxx - lavu 51.22.1 - pixdesc.h Add PIX_FMT_PSEUDOPAL flag. diff --git a/libavutil/avutil.h b/libavutil/avutil.h index 05e9248375..b5f9a24f14 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -154,7 +154,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 51 -#define LIBAVUTIL_VERSION_MINOR 22 +#define LIBAVUTIL_VERSION_MINOR 23 #define LIBAVUTIL_VERSION_MICRO 1 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libavutil/mathematics.c b/libavutil/mathematics.c index e6ce2f98ad..e2f06eda29 100644 --- a/libavutil/mathematics.c +++ b/libavutil/mathematics.c @@ -130,10 +130,17 @@ int64_t av_rescale(int64_t a, int64_t b, int64_t c){ return av_rescale_rnd(a, b, c, AV_ROUND_NEAR_INF); } -int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq){ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding rnd) +{ int64_t b= bq.num * (int64_t)cq.den; int64_t c= cq.num * (int64_t)bq.den; - return av_rescale_rnd(a, b, c, AV_ROUND_NEAR_INF); + return av_rescale_rnd(a, b, c, rnd); +} + +int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) +{ + return av_rescale_q_rnd(a, bq, cq, AV_ROUND_NEAR_INF); } int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b){ diff --git a/libavutil/mathematics.h b/libavutil/mathematics.h index 0b072ebe63..ec27979bc9 100644 --- a/libavutil/mathematics.h +++ b/libavutil/mathematics.h @@ -95,6 +95,12 @@ int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_cons */ int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const; +/** + * Rescale a 64-bit integer by 2 rational numbers with specified rounding. + */ +int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, + enum AVRounding) av_const; + /** * Compare 2 timestamps each in its own timebases. * The result of the function is undefined if one of the timestamps From e9cda853511d7c5a8fa16da4f99cf8ead86bf658 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 12 Jan 2012 20:03:17 -0500 Subject: [PATCH 28/36] avcodec: add duration field to AVCodecParserContext This will allow parsers to export the duration of the current frame being output, if known, instead of using AVCodecContext.frame_size. --- doc/APIchanges | 3 +++ libavcodec/avcodec.h | 7 +++++++ libavformat/utils.c | 14 ++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/doc/APIchanges b/doc/APIchanges index ca521d41a5..12fa80396a 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2011-04-18 API changes, most recent first: +2012-xx-xx - xxxxxxx - lavc 54.x.x + Add duration field to AVCodecParserContext + 2012-02-xx - xxxxxxx - lavu 51.23.1 - mathematics.h Add av_rescale_q_rnd() diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 51b956ba81..7128a83148 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -3994,6 +3994,13 @@ typedef struct AVCodecParserContext { * Previous frame byte position. */ int64_t last_pos; + + /** + * Duration of the current frame. + * For audio, this is in units of 1 / AVCodecContext.sample_rate. + * For all other types, this is in units of AVCodecContext.time_base. + */ + int duration; } AVCodecParserContext; typedef struct AVCodecParser { diff --git a/libavformat/utils.c b/libavformat/utils.c index 33775b9a2b..24175228ab 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1039,6 +1039,20 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (pkt->size) { got_packet: pkt->duration = 0; + if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codec->sample_rate > 0) { + pkt->duration = av_rescale_q_rnd(st->parser->duration, + (AVRational){ 1, st->codec->sample_rate }, + st->time_base, + AV_ROUND_DOWN); + } + } else if (st->codec->time_base.num != 0 && + st->codec->time_base.den != 0) { + pkt->duration = av_rescale_q_rnd(st->parser->duration, + st->codec->time_base, + st->time_base, + AV_ROUND_DOWN); + } pkt->stream_index = st->index; pkt->pts = st->parser->pts; pkt->dts = st->parser->dts; From c7f3f1c91eae60dfb3e789ce4a366b2e82ef0970 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 12 Jan 2012 20:53:09 -0500 Subject: [PATCH 29/36] flac parser: set duration instead of frame_size --- libavcodec/flac_parser.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index 87f3f95042..6a4032ded6 100644 --- a/libavcodec/flac_parser.c +++ b/libavcodec/flac_parser.c @@ -71,6 +71,7 @@ typedef struct FLACHeaderMarker { } FLACHeaderMarker; typedef struct FLACParseContext { + AVCodecParserContext *pc; /**< parent context */ AVCodecContext *avctx; /**< codec context pointer for logging */ FLACHeaderMarker *headers; /**< linked-list that starts at the first CRC-8 verified header within buffer */ @@ -458,7 +459,7 @@ static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf, fpc->avctx->sample_rate = header->fi.samplerate; fpc->avctx->channels = header->fi.channels; - fpc->avctx->frame_size = header->fi.blocksize; + fpc->pc->duration = header->fi.blocksize; *poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); @@ -484,7 +485,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { FLACFrameInfo fi; if (frame_header_is_valid(avctx, buf, &fi)) - avctx->frame_size = fi.blocksize; + s->duration = fi.blocksize; *poutbuf = buf; *poutbuf_size = buf_size; return buf_size; @@ -630,8 +631,8 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "Junk frame till offset %i\n", fpc->best_header->offset); - /* Set frame_size to 0. It is unknown or invalid in a junk frame. */ - avctx->frame_size = 0; + /* Set duration to 0. It is unknown or invalid in a junk frame. */ + s->duration = 0; *poutbuf_size = fpc->best_header->offset; *poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size, &fpc->wrap_buf, @@ -652,6 +653,7 @@ handle_error: static int flac_parse_init(AVCodecParserContext *c) { FLACParseContext *fpc = c->priv_data; + fpc->pc = c; /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before it drains. This is allocated early to avoid slow reallocation. */ fpc->fifo_buf = av_fifo_alloc(FLAC_AVG_FRAME_SIZE * (FLAC_MIN_HEADERS + 3)); From 16e54ac7255d47e70ba9ba60d5ce5d0a0e44b223 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 12 Jan 2012 20:59:43 -0500 Subject: [PATCH 30/36] (e)ac3 parser: set duration instead of frame_size --- libavcodec/aac_ac3_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c index 58f30a4180..8132ce899a 100644 --- a/libavcodec/aac_ac3_parser.c +++ b/libavcodec/aac_ac3_parser.c @@ -93,7 +93,7 @@ get_next: avctx->channels = s->channels; avctx->channel_layout = s->channel_layout; } - avctx->frame_size = s->samples; + s1->duration = s->samples; avctx->audio_service_type = s->service_type; } From 7575ffac8a2da4c03a606f6a94286979d953dde5 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 12 Jan 2012 21:05:08 -0500 Subject: [PATCH 31/36] mpegaudio parser: set duration instead of frame_size --- libavcodec/mpegaudio_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegaudio_parser.c b/libavcodec/mpegaudio_parser.c index c6d670de2a..5fd9037b53 100644 --- a/libavcodec/mpegaudio_parser.c +++ b/libavcodec/mpegaudio_parser.c @@ -77,7 +77,7 @@ static int mpegaudio_parse(AVCodecParserContext *s1, if(s->header_count > 1){ avctx->sample_rate= sr; avctx->channels = channels; - avctx->frame_size = frame_size; + s1->duration = frame_size; avctx->bit_rate = bit_rate; } break; From 2460b168b4ca308504ee9f7966e3e4cfb3fc90e6 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 13 Jan 2012 00:40:10 -0500 Subject: [PATCH 32/36] gsm parser: set duration --- libavcodec/gsm_parser.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libavcodec/gsm_parser.c b/libavcodec/gsm_parser.c index a2965d3fb5..89afe80ef0 100644 --- a/libavcodec/gsm_parser.c +++ b/libavcodec/gsm_parser.c @@ -31,6 +31,7 @@ typedef struct GSMParseContext { ParseContext pc; int block_size; + int duration; int remaining; } GSMParseContext; @@ -44,8 +45,14 @@ static int gsm_parse(AVCodecParserContext *s1, AVCodecContext *avctx, if (!s->block_size) { switch (avctx->codec_id) { - case CODEC_ID_GSM: s->block_size = GSM_BLOCK_SIZE; break; - case CODEC_ID_GSM_MS: s->block_size = GSM_MS_BLOCK_SIZE; break; + case CODEC_ID_GSM: + s->block_size = GSM_BLOCK_SIZE; + s->duration = GSM_FRAME_SIZE; + break; + case CODEC_ID_GSM_MS: + s->block_size = GSM_MS_BLOCK_SIZE; + s->duration = GSM_FRAME_SIZE * 2; + break; default: return AVERROR(EINVAL); } @@ -66,6 +73,9 @@ static int gsm_parse(AVCodecParserContext *s1, AVCodecContext *avctx, *poutbuf_size = 0; return buf_size; } + + s1->duration = s->duration; + *poutbuf = buf; *poutbuf_size = buf_size; return next; From b3a4c7e0f1faa327a52b10840eed14e116587894 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 12 Jan 2012 23:43:30 -0500 Subject: [PATCH 33/36] mlp parser: set duration instead of frame_size --- libavcodec/mlp_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index e0fedeb7e9..be71867c2d 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -311,7 +311,7 @@ static int mlp_parse(AVCodecParserContext *s, else avctx->sample_fmt = AV_SAMPLE_FMT_S16; avctx->sample_rate = mh.group1_samplerate; - avctx->frame_size = mh.access_unit_size; + s->duration = mh.access_unit_size; if (mh.stream_type == 0xbb) { /* MLP stream */ From 41ac9bb253c371e95abc854786334c857bbe4065 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 12 Jan 2012 23:43:31 -0500 Subject: [PATCH 34/36] adx parser: set duration --- libavcodec/adx_parser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/adx_parser.c b/libavcodec/adx_parser.c index de3b1b073f..8dc87fcc58 100644 --- a/libavcodec/adx_parser.c +++ b/libavcodec/adx_parser.c @@ -80,6 +80,9 @@ static int adx_parse(AVCodecParserContext *s1, *poutbuf_size = 0; return buf_size; } + + s1->duration = BLOCK_SAMPLES; + *poutbuf = buf; *poutbuf_size = buf_size; return next; From 91a28b0e8e4f09a8256727e8a514bf98da81e186 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 7 Feb 2012 15:37:45 -0500 Subject: [PATCH 35/36] avcodec: add ff_samples_to_time_base() convenience function to internal.h --- libavcodec/internal.h | 11 +++++++++++ libavcodec/libspeexenc.c | 5 +---- libavcodec/libvorbis.c | 5 +++-- libavcodec/utils.c | 15 ++++++--------- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/libavcodec/internal.h b/libavcodec/internal.h index b435a359fb..bedb2ed85d 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -26,6 +26,7 @@ #include +#include "libavutil/mathematics.h" #include "libavutil/pixfmt.h" #include "avcodec.h" @@ -127,4 +128,14 @@ int avpriv_unlock_avformat(void); */ int ff_alloc_packet(AVPacket *avpkt, int size); +/** + * Rescale from sample rate to AVCodecContext.time_base. + */ +static av_always_inline int64_t ff_samples_to_time_base(AVCodecContext *avctx, + int64_t samples) +{ + return av_rescale_q(samples, (AVRational){ 1, avctx->sample_rate }, + avctx->time_base); +} + #endif /* AVCODEC_INTERNAL_H */ diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c index bccf9c810d..73a1d4e8c2 100644 --- a/libavcodec/libspeexenc.c +++ b/libavcodec/libspeexenc.c @@ -67,7 +67,6 @@ #include #include #include -#include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "avcodec.h" #include "internal.h" @@ -258,9 +257,7 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, /* write output if all frames for the packet have been encoded */ if (s->pkt_frame_count == s->frames_per_packet) { s->pkt_frame_count = 0; - avctx->coded_frame->pts = - av_rescale_q(s->next_pts, (AVRational){ 1, avctx->sample_rate }, - avctx->time_base); + avctx->coded_frame->pts = ff_samples_to_time_base(avctx, s->next_pts); s->next_pts += s->pkt_sample_count; s->pkt_sample_count = 0; if (buf_size > speex_bits_nbytes(&s->bits)) { diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c index 25e600671f..4d58fdc34e 100644 --- a/libavcodec/libvorbis.c +++ b/libavcodec/libvorbis.c @@ -29,8 +29,8 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "bytestream.h" +#include "internal.h" #include "vorbis.h" -#include "libavutil/mathematics.h" #undef NDEBUG #include @@ -216,7 +216,8 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext, op2->packet = context->buffer + sizeof(ogg_packet); l = op2->bytes; - avccontext->coded_frame->pts = av_rescale_q(op2->granulepos, (AVRational) { 1, avccontext->sample_rate }, avccontext->time_base); + avccontext->coded_frame->pts = ff_samples_to_time_base(avccontext, + op2->granulepos); //FIXME we should reorder the user supplied pts and not assume that they are spaced by 1/sample_rate if (l > buf_size) { diff --git a/libavcodec/utils.c b/libavcodec/utils.c index 255406ffdd..2ab3b8e560 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -886,9 +886,8 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, if (!ret && *got_packet_ptr) { if (!(avctx->codec->capabilities & CODEC_CAP_DELAY)) { avpkt->pts = frame->pts; - avpkt->duration = av_rescale_q(frame->nb_samples, - (AVRational){ 1, avctx->sample_rate }, - avctx->time_base); + avpkt->duration = ff_samples_to_time_base(avctx, + frame->nb_samples); } avpkt->dts = avpkt->pts; } else { @@ -944,9 +943,8 @@ int attribute_align_arg avcodec_encode_audio2(AVCodecContext *avctx, once all encoders supporting CODEC_CAP_SMALL_LAST_FRAME use encode2() */ if (fs_tmp) { - avpkt->duration = av_rescale_q(avctx->frame_size, - (AVRational){ 1, avctx->sample_rate }, - avctx->time_base); + avpkt->duration = ff_samples_to_time_base(avctx, + avctx->frame_size); } } avpkt->size = ret; @@ -1018,9 +1016,8 @@ int attribute_align_arg avcodec_encode_audio(AVCodecContext *avctx, /* fabricate frame pts from sample count. this is needed because the avcodec_encode_audio() API does not have a way for the user to provide pts */ - frame->pts = av_rescale_q(avctx->internal->sample_count, - (AVRational){ 1, avctx->sample_rate }, - avctx->time_base); + frame->pts = ff_samples_to_time_base(avctx, + avctx->internal->sample_count); avctx->internal->sample_count += frame->nb_samples; } else { frame = NULL; From 770a5c6d025e9c8eb3f5aba9cf1d7d7938fb918a Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 31 Jan 2012 15:57:53 -0500 Subject: [PATCH 36/36] adpcmenc: Use correct frame_size for Yamaha ADPCM. Output packet size should match avctx->block_align. The target output packet size is 1024 bytes. Before: mono - 1024 samples -> 512 bytes stereo - 2048 samples -> 2048 bytes After: mono - 2048 samples -> 1024 bytes stereo - 1024 samples -> 1024 bytes --- libavcodec/adpcmenc.c | 2 +- tests/ref/acodec/adpcm_yam | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c index a24238ccb8..25a07c4464 100644 --- a/libavcodec/adpcmenc.c +++ b/libavcodec/adpcmenc.c @@ -122,7 +122,7 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) } break; case CODEC_ID_ADPCM_YAMAHA: - avctx->frame_size = BLKSIZE * avctx->channels; + avctx->frame_size = BLKSIZE * 2 / avctx->channels; avctx->block_align = BLKSIZE; break; case CODEC_ID_ADPCM_SWF: diff --git a/tests/ref/acodec/adpcm_yam b/tests/ref/acodec/adpcm_yam index 0fd702954e..f7c9f757a6 100644 --- a/tests/ref/acodec/adpcm_yam +++ b/tests/ref/acodec/adpcm_yam @@ -1,4 +1,4 @@ -006f8dc92eb4f7bab82eded314ca1124 *./tests/data/acodec/adpcm_yam.wav -266298 ./tests/data/acodec/adpcm_yam.wav -c36a9d5a1e0ad57fbe9665a31373b7c1 *./tests/data/adpcm_yam.acodec.out.wav -stddev: 1247.60 PSNR: 34.41 MAXDIFF:39895 bytes: 1064960/ 1058400 +e9c14f701d25947317db9367b9dc772d *./tests/data/acodec/adpcm_yam.wav +265274 ./tests/data/acodec/adpcm_yam.wav +1488b5974fa040a65f0d407fc0224c6a *./tests/data/adpcm_yam.acodec.out.wav +stddev: 1247.60 PSNR: 34.41 MAXDIFF:39895 bytes: 1060864/ 1058400