[FFmpeg-devel] [PATCH] libvorbis encoder: fix non monotone timestamp problem

Nicolas George nicolas.george
Mon Oct 13 19:34:41 CEST 2008


Hi.

Sometimes, the libvorbis encoder dies with a "non monotone timestamps"
problem. For example, with SVN revision 15614 configured with
"--enable-libvorbis --enable-debug", the following command line:

sox -t raw -s2 -c 2 -r 44100 /dev/zero -t wav - trim 0 10 synth 440 |
./ffmpeg_g-orig -f wav -i - -acodec libvorbis -y /tmp/out.ogg

(sox produces a 10-seconds WAV file with a 440 Hz sine)

ffmpeg dies with:

[libvorbis @ 0xdd5d80]error, non monotone timestamps 440960 >= 440960
av_interleaved_write_frame(): Error while opening file

(the rest of the output is just regular stuff, version and streams
identification; I can copy-paste it here, but there is really nothing
useful)

Furthermore, if the output format requires processing at the end, it is not
done; AVI index, for example, is not built.

The problem is that at the end of the stream libavcodec calls
vorbis_analysis_wrote repeatedly with a 0 size. The libvorbisenc
documentation is rather terse about it, but it seems that this should be
done only once: otherwise, this causes libvorbisenc to output the last
packet a second time, with the same granulepos, causing the timestamp
problem.

The fix seems obvious: add a flag to avoid calling vorbis_analysis_wrote
twice with an empty buffer.

The attached patch does that. The second one fixes the indentation. They do
not break the regression tests.

Regards,

-- 
  Nicolas George
-------------- next part --------------
diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c
index ce796a0..6963e70 100644
--- a/libavcodec/libvorbis.c
+++ b/libavcodec/libvorbis.c
@@ -42,6 +42,7 @@ typedef struct OggVorbisContext {
     vorbis_block vb ;
     uint8_t buffer[BUFFER_SIZE];
     int buffer_index;
+    int eof;
 
     /* decoder */
     vorbis_comment vc ;
@@ -136,10 +137,13 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext,
                            int buf_size, void *data)
 {
     OggVorbisContext *context = avccontext->priv_data ;
-    float **buffer ;
     ogg_packet op ;
     signed short *audio = data ;
-    int l, samples = data ? OGGVORBIS_FRAME_SIZE : 0;
+    int l;
+
+    if(data) {
+        int samples = OGGVORBIS_FRAME_SIZE;
+        float **buffer ;
 
     buffer = vorbis_analysis_buffer(&context->vd, samples) ;
 
@@ -154,6 +158,11 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext,
     }
 
     vorbis_analysis_wrote(&context->vd, samples) ;
+    } else {
+        if(!context->eof)
+            vorbis_analysis_wrote(&context->vd, 0) ;
+        context->eof = 1;
+    }
 
     while(vorbis_analysis_blockout(&context->vd, &context->vb) == 1) {
         vorbis_analysis(&context->vb, NULL);
-------------- next part --------------
diff --git a/libavcodec/libvorbis.c b/libavcodec/libvorbis.c
index 6963e70..03c9f88 100644
--- a/libavcodec/libvorbis.c
+++ b/libavcodec/libvorbis.c
@@ -145,19 +145,17 @@ static int oggvorbis_encode_frame(AVCodecContext *avccontext,
         int samples = OGGVORBIS_FRAME_SIZE;
         float **buffer ;
 
-    buffer = vorbis_analysis_buffer(&context->vd, samples) ;
-
-    if(context->vi.channels == 1) {
-        for(l = 0 ; l < samples ; l++)
-            buffer[0][l]=audio[l]/32768.f;
-    } else {
-        for(l = 0 ; l < samples ; l++){
-            buffer[0][l]=audio[l*2]/32768.f;
-            buffer[1][l]=audio[l*2+1]/32768.f;
+        buffer = vorbis_analysis_buffer(&context->vd, samples) ;
+        if(context->vi.channels == 1) {
+            for(l = 0 ; l < samples ; l++)
+                buffer[0][l]=audio[l]/32768.f;
+        } else {
+            for(l = 0 ; l < samples ; l++){
+                buffer[0][l]=audio[l*2]/32768.f;
+                buffer[1][l]=audio[l*2+1]/32768.f;
+            }
         }
-    }
-
-    vorbis_analysis_wrote(&context->vd, samples) ;
+        vorbis_analysis_wrote(&context->vd, samples) ;
     } else {
         if(!context->eof)
             vorbis_analysis_wrote(&context->vd, 0) ;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20081013/142a5922/attachment.pgp>



More information about the ffmpeg-devel mailing list