From 6f82497728c49831e230bb631c4c3d6f5deff803 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 22 Jun 2004 21:14:01 +0000 Subject: [PATCH] flush audio encoder buffers at the end fix vorbis in nut again Originally committed as revision 3244 to svn://svn.ffmpeg.org/ffmpeg/trunk --- ffmpeg.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++- libavcodec/avcodec.h | 2 ++ libavcodec/mp3lameaudio.c | 17 +++++++++++---- libavcodec/oggvorbis.c | 38 ++++++++++----------------------- libavcodec/utils.c | 25 +++++++++++----------- libavformat/utils.c | 4 ++++ 6 files changed, 96 insertions(+), 44 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index b313bd5..0ff5ddc 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -582,6 +582,7 @@ static void fill_pad_region(AVPicture* img, int height, int width, } } +static uint8_t *video_buffer= NULL; //FIXME rename, its used for audio too at the end static void do_video_out(AVFormatContext *s, AVOutputStream *ost, @@ -592,7 +593,6 @@ static void do_video_out(AVFormatContext *s, int nb_frames, i, ret; AVFrame *final_picture, *formatted_picture; AVFrame picture_format_temp, picture_crop_temp; - static uint8_t *video_buffer= NULL; uint8_t *buf = NULL, *buf1 = NULL; AVCodecContext *enc, *dec; enum PixelFormat target_pixfmt; @@ -1206,6 +1206,58 @@ static int output_packet(AVInputStream *ist, int ist_index, av_free(buffer_to_free); } discard_packet: + if (pkt == NULL) { + /* EOF handling */ + + for(i=0;isource_index == ist_index) { + AVCodecContext *enc= &ost->st->codec; + os = output_files[ost->file_index]; + + if(ost->st->codec.codec_type == CODEC_TYPE_AUDIO && enc->frame_size <=1) + continue; + if(ost->st->codec.codec_type == CODEC_TYPE_VIDEO && (os->oformat->flags & AVFMT_RAWPICTURE)) + continue; + + if (ost->encoding_needed) { + for(;;) { + AVPacket pkt; + av_init_packet(&pkt); + pkt.stream_index= ost->index; + + switch(ost->st->codec.codec_type) { + case CODEC_TYPE_AUDIO: + ret = avcodec_encode_audio(enc, video_buffer, VIDEO_BUFFER_SIZE, NULL); + audio_size += ret; + pkt.flags |= PKT_FLAG_KEY; + break; + case CODEC_TYPE_VIDEO: + ret = avcodec_encode_video(enc, video_buffer, VIDEO_BUFFER_SIZE, NULL); + video_size += ret; + if(enc->coded_frame && enc->coded_frame->key_frame) + pkt.flags |= PKT_FLAG_KEY; + if (ost->logfile && enc->stats_out) { + fprintf(ost->logfile, "%s", enc->stats_out); + } + break; + default: + ret=-1; + } + + if(ret<=0) + break; + pkt.data= video_buffer; + pkt.size= ret; + if(enc->coded_frame) + pkt.pts= enc->coded_frame->pts; + av_interleaved_write_frame(os, &pkt); + } + } + } + } + } + return 0; fail_decode: return -1; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index c71e4a9..dae92e9 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -294,6 +294,8 @@ extern int motion_estimation_method; #define CODEC_CAP_TRUNCATED 0x0008 /* codec can export data for HW decoding (XvMC) */ #define CODEC_CAP_HWACCEL 0x0010 +/** codec has a non zero delay and needs to be feeded with NULL at the end to get the delayed data */ +#define CODEC_CAP_DELAY 0x0020 //the following defines might change, so dont expect compatibility if u use them #define MB_TYPE_INTRA4x4 0x0001 diff --git a/libavcodec/mp3lameaudio.c b/libavcodec/mp3lameaudio.c index f53aee9..ce02ff0 100644 --- a/libavcodec/mp3lameaudio.c +++ b/libavcodec/mp3lameaudio.c @@ -136,7 +136,9 @@ int MP3lame_encode_frame(AVCodecContext *avctx, int lame_result; /* lame 3.91 dies on '1-channel interleaved' data */ - if (s->stereo) { + + if(data){ + if (s->stereo) { lame_result = lame_encode_buffer_interleaved( s->gfp, data, @@ -144,7 +146,7 @@ int MP3lame_encode_frame(AVCodecContext *avctx, s->buffer + s->buffer_index, BUFFER_SIZE - s->buffer_index ); - } else { + } else { lame_result = lame_encode_buffer( s->gfp, data, @@ -153,6 +155,13 @@ int MP3lame_encode_frame(AVCodecContext *avctx, s->buffer + s->buffer_index, BUFFER_SIZE - s->buffer_index ); + } + }else{ + lame_result= lame_encode_flush( + s->gfp, + s->buffer + s->buffer_index, + BUFFER_SIZE - s->buffer_index + ); } if(lame_result==-1) { @@ -174,7 +183,6 @@ int MP3lame_encode_frame(AVCodecContext *avctx, memmove(s->buffer, s->buffer+len, s->buffer_index); //FIXME fix the audio codec API, so we dont need the memcpy() - //FIXME fix the audio codec API, so we can output multiple packets if we have them /*for(i=0; ivd, samples) ; @@ -125,6 +124,8 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext, vorbis_bitrate_addblock(&context->vb) ; while(vorbis_bitrate_flushpacket(&context->vd, &op)) { + if(op.bytes==1) //id love to say this is a hack, bad sadly its not, appearently the end of stream decission is in libogg + continue; memcpy(context->buffer + context->buffer_index, &op, sizeof(ogg_packet)); context->buffer_index += sizeof(ogg_packet); memcpy(context->buffer + context->buffer_index, op.packet, op.bytes); @@ -138,21 +139,15 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext, ogg_packet *op2= (ogg_packet*)context->buffer; op2->packet = context->buffer + sizeof(ogg_packet); - if(op2->granulepos <= context->fake_pts /*&& (context->fake_pts || context->buffer_index > 4*1024)*/){ - assert(op2->granulepos == context->fake_pts); - l= op2->bytes; + l= op2->bytes; + avccontext->coded_frame->pts= av_rescale(op2->granulepos, AV_TIME_BASE, avccontext->sample_rate); - memcpy(packets, op2->packet, l); - context->buffer_index -= l + sizeof(ogg_packet); - memcpy(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index); - } + memcpy(packets, op2->packet, l); + context->buffer_index -= l + sizeof(ogg_packet); + memcpy(context->buffer, context->buffer + l + sizeof(ogg_packet), context->buffer_index); // av_log(avccontext, AV_LOG_DEBUG, "E%d\n", l); } - if(l || context->fake_pts){ - context->fake_pts += avccontext->frame_size; - } - return l; } @@ -163,19 +158,6 @@ static int oggvorbis_encode_close(AVCodecContext *avccontext) { vorbis_analysis_wrote(&context->vd, 0) ; /* notify vorbisenc this is EOF */ - /* We need to write all the remaining packets into the stream - * on closing */ - - av_log(avccontext, AV_LOG_ERROR, "fixme: not all packets written on oggvorbis_encode_close()\n") ; - -/* - while(vorbis_bitrate_flushpacket(&context->vd, &op)) { - memcpy(packets + l, &op, sizeof(ogg_packet)) ; - memcpy(packets + l + sizeof(ogg_packet), op.packet, op.bytes) ; - l += sizeof(ogg_packet) + op.bytes ; - } -*/ - vorbis_block_clear(&context->vb); vorbis_dsp_clear(&context->vd); vorbis_info_clear(&context->vi); @@ -194,7 +176,8 @@ AVCodec oggvorbis_encoder = { sizeof(OggVorbisContext), oggvorbis_encode_init, oggvorbis_encode_frame, - oggvorbis_encode_close + oggvorbis_encode_close, + .capabilities= CODEC_CAP_DELAY, } ; @@ -313,4 +296,5 @@ AVCodec oggvorbis_decoder = { NULL, oggvorbis_decode_close, oggvorbis_decode_frame, + .capabilities= CODEC_CAP_DELAY, } ; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index a45d57d..4fdd0c2 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -453,24 +453,25 @@ int avcodec_open(AVCodecContext *avctx, AVCodec *codec) int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples) { - int ret; - - ret = avctx->codec->encode(avctx, buf, buf_size, (void *)samples); - avctx->frame_number++; - return ret; + if((avctx->codec->capabilities & CODEC_CAP_DELAY) || samples){ + int ret = avctx->codec->encode(avctx, buf, buf_size, (void *)samples); + avctx->frame_number++; + return ret; + }else + return 0; } int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVFrame *pict) { - int ret; - - ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict); + if((avctx->codec->capabilities & CODEC_CAP_DELAY) || pict){ + int ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict); + avctx->frame_number++; + emms_c(); //needed to avoid a emms_c() call before every return; - emms_c(); //needed to avoid a emms_c() call before every return; - - avctx->frame_number++; - return ret; + return ret; + }else + return 0; } /** diff --git a/libavformat/utils.c b/libavformat/utils.c index 010d8c3..1420f49 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1980,6 +1980,10 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ AVStream *st= s->streams[ pkt->stream_index]; compute_pkt_fields2(st, pkt); + + //FIXME/XXX/HACK drop zero sized packets + if(st->codec.codec_type == CODEC_TYPE_AUDIO && pkt->size==0) + return 0; if(pkt->dts == AV_NOPTS_VALUE) return -1; -- 2.7.4