]> git.sesse.net Git - ffmpeg/commitdiff
flush audio encoder buffers at the end
authorMichael Niedermayer <michaelni@gmx.at>
Tue, 22 Jun 2004 21:14:01 +0000 (21:14 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Tue, 22 Jun 2004 21:14:01 +0000 (21:14 +0000)
fix vorbis in nut again

Originally committed as revision 3244 to svn://svn.ffmpeg.org/ffmpeg/trunk

ffmpeg.c
libavcodec/avcodec.h
libavcodec/mp3lameaudio.c
libavcodec/oggvorbis.c
libavcodec/utils.c
libavformat/utils.c

index b313bd59f8e067883afc9bfc8ae54729e0cbc93e..0ff5ddc9e409ac22f6121702cc9114d8316ac1cc 100644 (file)
--- 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;i<nb_ostreams;i++) {
+            ost = ost_table[i];
+            if (ost->source_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;
index c71e4a946e2ffb3dad5b2713fab888e84e7a9c67..dae92e903d4d8efda5000f7c9ece4a0a2c846ec0 100644 (file)
@@ -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
index f53aee9272a5ee07492e28c9f05e27328d1f1159..ce02ff0c106084fdb1766cf671921f86f98f1f55 100644 (file)
@@ -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; i<len; i++){
     av_log(avctx, AV_LOG_DEBUG, "%2X ", frame[i]);
 }*/
@@ -201,5 +209,6 @@ AVCodec mp3lame_encoder = {
     sizeof(Mp3AudioContext),
     MP3lame_encode_init,
     MP3lame_encode_frame,
-    MP3lame_encode_close
+    MP3lame_encode_close,
+    .capabilities= CODEC_CAP_DELAY,
 };
index f24f4fae72268c90d8aece1bca98bfb580094945..803de206323bd051c0577e2d4d359c86313fc8ae 100644 (file)
@@ -21,7 +21,6 @@ typedef struct OggVorbisContext {
     vorbis_block vb ;
     uint8_t buffer[BUFFER_SIZE];
     int buffer_index;
-    int64_t fake_pts; //pts which libavformat will guess, HACK FIXME
 
     /* decoder */
     vorbis_comment vc ;
@@ -104,7 +103,7 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext,
     float **buffer ;
     ogg_packet op ;
     signed char *audio = data ;
-    int l, samples = OGGVORBIS_FRAME_SIZE ;
+    int l, samples = data ? OGGVORBIS_FRAME_SIZE : 0;
 
     buffer = vorbis_analysis_buffer(&context->vd, 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,
 } ;
index a45d57de00056e56ec977fede9886fc849b097b5..4fdd0c2aba15627769cd4e465c90b13c7eaf3445 100644 (file)
@@ -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;
 }
 
 /** 
index 010d8c3100c2304532095ec34017e461f24bb049..1420f496fcd757b3ae034577fbea934b5cb911d2 100644 (file)
@@ -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;