Pete Eberlein <[email protected]> added the comment:

I've been struggling with this problem as well, with a MPEG4-ES stream from a TI
encoder similar to the thread linked above this message.  I can upload the file
if needed.
Here is the output:

$ ffmpeg -f m4v -r 30 -i output.m4v -vcodec copy -y output_mpeg4.avi
FFmpeg version SVN-r19352-4:0.5+svn20090706-2ubuntu2.2, Copyright (c) 2000-2009
Fabrice Bellard, et al.
  configuration: --extra-version=4:0.5+svn20090706-2ubuntu2.2 --prefix=/usr
--enable-avfilter --enable-avfilter-lavf --enable-vdpau --enable-bzlib
--enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora
--enable-libvorbis --enable-pthreads --enable-zlib --disable-stripping
--disable-vhook --enable-gpl --enable-postproc --enable-swscale --enable-x11grab
--enable-libdc1394
--extra-cflags=-I/build/buildd/ffmpeg-0.5+svn20090706/debian/include
--enable-shared --disable-static
  libavutil     49.15. 0 / 49.15. 0
  libavcodec    52.20. 0 / 52.20. 0
  libavformat   52.31. 0 / 52.31. 0
  libavdevice   52. 1. 0 / 52. 1. 0
  libavfilter    0. 4. 0 /  0. 4. 0
  libswscale     0. 7. 1 /  0. 7. 1
  libpostproc   51. 2. 0 / 51. 2. 0
  built on Apr 23 2010 15:38:06, gcc: 4.4.1
Input #0, m4v, from 'output.m4v':
  Duration: N/A, bitrate: N/A
    Stream #0.0: Video: mpeg4, yuv420p, 640x480 [PAR 1:1 DAR 4:3], 30k tbr,
1200k tbn, 30k tbc
Output #0, avi, to 'output_mpeg4.avi':
    Stream #0.0: Video: mpeg4, yuv420p, 640x480 [PAR 1:1 DAR 4:3], q=2-31, 90k
tbn, 30k tbc
Stream mapping:
  Stream #0.0 -> #0.0
Press [q] to stop encoding
[NULL @ 0x19b7130]error, non monotone timestamps 50 >= 50
av_interleaved_write_frame(): Error while opening file

There are a few problems with this:
* The frame rate should not be 30k, it should be 30.
* The stream time_base should not be 1200k, it should be the same as the codec, 
30k.
* The non monotone timestamps error occurs because the stream time_base is 
wrong.

I've created a patch that does several things:
* calculates the ticks_per_frame when parsing the mpeg4 vol header
* reads the bitrate when parsing the mpeg4 vol header
* copies the pts from the current picture to the stream pts
* copies the time_base from the codec to the stream when the ticks_per_frame > 2

The patched output is:

FFmpeg version SVN-r24716, Copyright (c) 2000-2010 the FFmpeg developers
  built on Aug  6 2010 09:54:55 with gcc 4.4.1
  configuration: 
  libavutil     50.23. 0 / 50.23. 0
  libavcore      0. 3. 0 /  0. 3. 0
  libavcodec    52.84. 3 / 52.84. 3
  libavformat   52.78. 0 / 52.78. 0
  libavdevice   52. 2. 1 / 52. 2. 1
  libavfilter    1.27. 1 /  1.27. 1
  libswscale     0.11. 0 /  0.11. 0
[m4v @ 0x24bc470] Estimating duration from bitrate, this may be inaccurate
Input #0, m4v, from 'output.m4v':
  Duration: 00:00:04.78, start: 0.000000, bitrate: 2000 kb/s
    Stream #0.0: Video: mpeg4, yuv420p, 640x480 [PAR 1:1 DAR 4:3], 2000 kb/s, 30
tbr, 30k tbn, 30k tbc
Output #0, avi, to 'output_mpeg4.avi':
  Metadata:
    ISFT            : Lavf52.78.0
    Stream #0.0: Video: mpeg4, yuv420p, 640x480 [PAR 1:1 DAR 4:3], q=2-31, 2000
kb/s, 30 tbn, 30 tbc
Stream mapping:
  Stream #0.0 -> #0.0
Press [q] to stop encoding
frame=  145 fps=  0 q=-1.0 Lsize=    1178kB time=4.83 bitrate=1996.2kbits/s    
video:1169kB audio:0kB global headers:0kB muxing overhead 0.781340%

The resulting file plays back at the correct speed.

I'm not sure if this patch is the best way to solve this problem, but it works
for me.  I'm a little concerned about copying the codec time_base to the stream
time_base based on the ticks_per_frame, and how that might affect other codecs.
 Perhaps the devs can think of a better solution.

----------
nosy: +peberlein2

________________________________________________
FFmpeg issue tracker <[email protected]>
<https://roundup.ffmpeg.org/issue1210>
________________________________________________
Index: libavcodec/mpeg4video_parser.c
===================================================================
--- libavcodec/mpeg4video_parser.c	(revision 24716)
+++ libavcodec/mpeg4video_parser.c	(working copy)
@@ -87,6 +87,7 @@
         avcodec_set_dimensions(avctx, s->width, s->height);
     }
     s1->pict_type= s->pict_type;
+    s1->pts = s->current_picture_ptr->pts;
     pc->first_picture = 0;
     return ret;
 }
Index: libavcodec/mpeg4videodec.c
===================================================================
--- libavcodec/mpeg4videodec.c	(revision 24716)
+++ libavcodec/mpeg4videodec.c	(working copy)
@@ -1519,7 +1519,8 @@
 }
 
 static int decode_vol_header(MpegEncContext *s, GetBitContext *gb){
-    int width, height, vo_ver_id;
+    int width, height, vo_ver_id, bit_rate;
+    AVRational frame_rate;
 
     /* vol header */
     skip_bits(gb, 1); /* random access */
@@ -1545,9 +1546,10 @@
         }
         s->low_delay= get_bits1(gb);
         if(get_bits1(gb)){ /* vbv parameters */
-            get_bits(gb, 15);   /* first_half_bitrate */
+            bit_rate = get_bits(gb, 15) << 15;   /* first_half_bitrate */
             skip_bits1(gb);     /* marker */
-            get_bits(gb, 15);   /* latter_half_bitrate */
+            bit_rate += get_bits(gb, 15);   /* latter_half_bitrate */
+            s->avctx->bit_rate = bit_rate * 400;
             skip_bits1(gb);     /* marker */
             get_bits(gb, 15);   /* first_half_vbv_buffer_size */
             skip_bits1(gb);     /* marker */
@@ -1572,6 +1574,8 @@
 
     check_marker(gb, "before time_increment_resolution");
 
+    frame_rate = s->avctx->time_base; // set previously by raw.c:video_read_header()
+
     s->avctx->time_base.den = get_bits(gb, 16);
     if(!s->avctx->time_base.den){
         av_log(s->avctx, AV_LOG_ERROR, "time_base.den==0\n");
@@ -1588,6 +1592,7 @@
         s->avctx->time_base.num = get_bits(gb, s->time_increment_bits);
     }else
         s->avctx->time_base.num = 1;
+    s->avctx->ticks_per_frame = frame_rate.num * s->avctx->time_base.den / (frame_rate.den * s->avctx->time_base.num);
 
     s->t_frame=0;
 
Index: libavformat/utils.c
===================================================================
--- libavformat/utils.c	(revision 24716)
+++ libavformat/utils.c	(working copy)
@@ -2343,6 +2343,9 @@
         if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
             if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample)
                 st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
+            // some MPEG4 codecs use large ticks per frame so the codec timebase should be used for the stream
+            if (st->codec->ticks_per_frame > 2)
+                st->time_base = st->codec->time_base;
 
             // the check for tb_unreliable() is not completely correct, since this is not about handling
             // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.

Reply via email to