Opened 4 years ago

Last modified 3 years ago

#730 open defect

Encoded video plays too fast for network input

Reported by: hackeron Owned by:
Priority: normal Component: undetermined
Version: git-master Keywords:
Cc: Blocked By:
Blocking: Reproduced by developer: yes
Analyzed by developer: no

Description

Many IP cameras have MJPEG streams that vary in framerate depending network conditions, ambient light, just plain slow processors on the camera itself, etc. This can be anything from 8fps to 30fps - even if the camera is set to a fixed framerate.

Right now, if you set a framerate in ffmpeg, the duration ffmpeg thinks the movie is does not match reality, sometimes by a factor of more than 3x. While ffmpeg supports variable framerate it requires timestamps which in this case do not exist.

Gstreamer has an option called do-timestamp=true that would be very useful in ffmpeg. From their website: "Timestamps are set on the buffers as they arrive from the camera. These are used by the mime/multipart demultiplexer to emit timestamps on the JPEG-encoded video frame buffers. This allows the multiplexer to timestamp the frames in the resulting file."

This would allow ffmpeg to set the timestamp of "now" on every single frame as it comes in and know the correct duration of the recording. This means correct duration, a/v sync and just being able to seek to specific parts of the recording.

Change History (9)

comment:1 Changed 4 years ago by cehoyos

  • Component changed from FFmpeg to undetermined

Please add a failing command line (as simple as possible, without using external libraries) and complete, uncut console output.

comment:2 Changed 4 years ago by hackeron

ffmpeg -f mjpeg -i http://admin:@82.13.197.168:82/video.cgi -vcodec copy out.avi

You will notice that the duration ffmpeg thinks the video is does not match reality. It tried with -timestamp now, -vsync 1, -re, and various combinations - but ffmpeg just counts the number of frames it expects, not the number of frames that it gets.

comment:3 Changed 4 years ago by cehoyos

Please add complete, uncut console output (and I suspect if you add time in front of your command line, the problem is easier to understand).

comment:4 Changed 4 years ago by hackeron

OK

$ URL="http://admin:@192.168.0.108/"; time ffmpeg -t 30 -f mjpeg -i ${URL}mjpeg.cgi -vcodec copy output.avi
ffmpeg version 0.8.6, Copyright (c) 2000-2011 the FFmpeg developers

built on Nov 17 2011 00:53:28 with gcc 4.2.1 (Apple Inc. build 5666) (dot 3)
configuration: --prefix=/usr/local/Cellar/ffmpeg/0.8.6 --enable-shared --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --cc=/usr/bin/gcc-4.2 --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libxvid --disable-ffplay
libavutil 51. 9. 1 / 51. 9. 1
libavcodec 53. 7. 0 / 53. 7. 0
libavformat 53. 4. 0 / 53. 4. 0
libavdevice 53. 1. 1 / 53. 1. 1
libavfilter 2. 23. 0 / 2. 23. 0
libswscale 2. 0. 0 / 2. 0. 0
libpostproc 51. 2. 0 / 51. 2. 0

[mjpeg @ 0x7ff204007c00] max_analyze_duration 5000000 reached at 5000000
[mjpeg @ 0x7ff204007c00] Estimating duration from bitrate, this may be inaccurate
Input #0, mjpeg, from 'http://admin:@192.168.0.108/mjpeg.cgi':

Duration: N/A, bitrate: N/A

Stream #0.0: Video: mjpeg, yuvj422p, 640x480, 25 fps, 25 tbr, 1200k tbn, 25 tbc

Output #0, avi, to 'output.avi':

Metadata:

ISFT : Lavf53.4.0
Stream #0.0: Video: mjpeg, yuvj422p, 640x480, q=2-31, 25 tbn, 25 tbc

Stream mapping:

Stream #0.0 -> #0.0

Press [q] to stop, ? for help
frame= 750 fps= 24 q=-1.0 Lsize= 25547kB time=00:00:30.00 bitrate=6976.1kbits/s
video:25524kB audio:0kB global headers:0kB muxing overhead 0.092094%

real 0m48.163s
user 0m0.213s
sys 0m0.620s

Notice ffmpeg thinks it has 30 seconds of video - but in reality the video is 48 seconds in length.

Version 0, edited 4 years ago by hackeron (next)

comment:5 Changed 4 years ago by cehoyos

  • Reproduced by developer set
  • Status changed from new to open
  • Summary changed from Generate timestamps for source (like do-timestamp=true in gstreamer) to Encoded video plays too fast for network input
  • Type changed from enhancement to defect
  • Version changed from unspecified to git-master

Received input is recorded as 25fps, but is actually a magnitude "slower".
ffmpeg -analyzeduration 1 -f mjpeg -r 3.5 -i http://admin:@82.13.197.168:82/video.cgi works better from here, but assuming the stream is VFR, it cannot work.

$ time ./ffmpeg -f mjpeg -i http://admin:@82.13.197.168:82/video.cgi out.avi
ffmpeg version N-35633-g5207f95, Copyright (c) 2000-2011 the FFmpeg developers
  built on Dec 10 2011 16:57:53 with gcc 4.5.3
  configuration: --cc='/usr/local/gcc-4.5.3/bin/gcc -m32'
  libavutil    51. 32. 0 / 51. 32. 0
  libavcodec   53. 42. 0 / 53. 42. 0
  libavformat  53. 24. 0 / 53. 24. 0
  libavdevice  53.  4. 0 / 53.  4. 0
  libavfilter   2. 52. 0 /  2. 52. 0
  libswscale    2.  1. 0 /  2.  1. 0
[mjpeg @ 0x8da4ae0] Estimating duration from bitrate, this may be inaccurate
Input #0, mjpeg, from 'http://admin:@82.13.197.168:82/video.cgi':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: mjpeg, yuvj422p, 640x480, 25 fps, 25 tbr, 1200k tbn, 25 tbc
Incompatible pixel format 'yuvj422p' for codec 'mpeg4', auto-selecting format 'yuv420p'
[buffer @ 0x8dbaea0] w:640 h:480 pixfmt:yuvj422p tb:1/1000000 sar:0/1 sws_param:
[buffersink @ 0x8db7ae0] auto-inserting filter 'auto-inserted scale 0' between the filter 'src' and the filter 'out'
[scale @ 0x914c2e0] w:640 h:480 fmt:yuvj422p -> w:640 h:480 fmt:yuv420p flags:0x4
Output #0, avi, to 'out.avi':
  Metadata:
    ISFT            : Lavf53.24.0
    Stream #0:0: Video: mpeg4 (FMP4 / 0x34504D46), yuv420p, 640x480, q=2-31, 200 kb/s, 25 tbn, 25 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (mjpeg -> mpeg4)
Press [q] to stop, [?] for help
frame=  747 fps=  4 q=31.0 Lsize=    1153kB time=00:00:29.88 bitrate= 316.1kbits/s
video:1130kB audio:0kB global headers:0kB muxing overhead 2.073742%

real    3m29.035s
user    0m5.007s
sys     0m0.136s

comment:6 Changed 4 years ago by hackeron

Same thing with an mpeg-es stream from another IP camera:

$ time ffmpeg -re -y -t 10 -i http://admin:@192.168.0.126/test.cmp -acodec copy -vcodec libx264 -crf 25 -preset ultrafast ffmpeg.ts
ffmpeg version git-2011-12-10-78fde93, Copyright (c) 2000-2011 the FFmpeg developers
  built on Dec 10 2011 19:56:39 with gcc 4.2.1 (Apple Inc. build 5666) (dot 3)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/HEAD --enable-shared --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --cc=/usr/bin/gcc-4.2 --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libxvid --disable-ffplay
  libavutil    51. 32. 0 / 51. 32. 0
  libavcodec   53. 42. 0 / 53. 42. 0
  libavformat  53. 24. 0 / 53. 24. 0
  libavdevice  53.  4. 0 / 53.  4. 0
  libavfilter   2. 52. 0 /  2. 52. 0
  libswscale    2.  1. 0 /  2.  1. 0
  libpostproc  51.  2. 0 / 51.  2. 0
[nc @ 0x7f983081ae00] Estimating duration from bitrate, this may be inaccurate
Input #0, nc, from 'http://admin:@192.168.0.126/test.cmp':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: mpeg4, yuv420p, 720x576 [SAR 1:1 DAR 5:4], 100 fps, 100 tbr, 100 tbn, 100 tbc
[buffer @ 0x7f983041e3c0] w:720 h:576 pixfmt:yuv420p tb:1/1000000 sar:1/1 sws_param:
[libx264 @ 0x7f983081d800] using SAR=1/1
[libx264 @ 0x7f983081d800] using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE4.2
[libx264 @ 0x7f983081d800] profile Constrained Baseline, level 3.2
[mpegts @ 0x7f983081d200] muxrate VBR, pcr every 10 pkts, sdt every 200, pat/pmt every 40 pkts
Output #0, mpegts, to 'ffmpeg.ts':
  Metadata:
    encoder         : Lavf53.24.0
    Stream #0:0: Video: h264, yuv420p, 720x576 [SAR 1:1 DAR 5:4], q=-1--1, 90k tbn, 100 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg4 -> libx264)
Press [q] to stop, [?] for help
frame=  999 fps= 15 q=-1.0 Lsize=   10687kB time=00:00:09.98 bitrate=8772.5kbits/s    
video:9800kB audio:0kB global headers:0kB muxing overhead 9.051934%
[libx264 @ 0x7f983081d800] frame I:4     Avg QP:28.75  size: 31858
[libx264 @ 0x7f983081d800] frame P:995   Avg QP:34.00  size:  9958
[libx264 @ 0x7f983081d800] mb I  I16..4: 100.0%  0.0%  0.0%
[libx264 @ 0x7f983081d800] mb P  I16..4: 65.4%  0.0%  0.0%  P16..4: 32.1%  0.0%  0.0%  0.0%  0.0%    skip: 2.5%
[libx264 @ 0x7f983081d800] coded y,uvDC,uvAC intra: 50.2% 70.0% 6.9% inter: 28.3% 64.0% 0.1%
[libx264 @ 0x7f983081d800] i16 v,h,dc,p: 19% 14% 58% 10%
[libx264 @ 0x7f983081d800] i8c dc,h,v,p: 51% 21% 23%  5%
[libx264 @ 0x7f983081d800] kb/s:8036.26

real	1m33.620s
user	0m10.997s
sys	0m0.535s

FFMPEG seems to think the input is 100fps when in reality it's something around 20-30fps VFR and records a 10 second video that in reality is a minute and a half :/

Looks like FFMPEG cannot record any live source from http correctly :(

comment:7 Changed 4 years ago by cehoyos

Is this also reproducible with -vcodec mpeg4 instead of libx264?

comment:8 Changed 4 years ago by hackeron

No, no difference using mpeg4

$ time ffmpeg -re -y -t 10 -i http://admin:@192.168.0.126/test.cmp -acodec copy -vcodec libx264 -crf 25 -preset ultrafast ffmpeg.ts
-bash: $: command not found
Roman-Gaufmans-MacBook-Pro:~ hackeron$ time ffmpeg -re -y -t 10 -i http://admin:@192.168.0.126/test.cmp -acodec copy -vcodec mpeg4 ffmpeg.ts
ffmpeg version git-2011-12-10-78fde93, Copyright (c) 2000-2011 the FFmpeg developers
  built on Dec 10 2011 19:56:39 with gcc 4.2.1 (Apple Inc. build 5666) (dot 3)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/HEAD --enable-shared --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --cc=/usr/bin/gcc-4.2 --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libxvid --disable-ffplay
  libavutil    51. 32. 0 / 51. 32. 0
  libavcodec   53. 42. 0 / 53. 42. 0
  libavformat  53. 24. 0 / 53. 24. 0
  libavdevice  53.  4. 0 / 53.  4. 0
  libavfilter   2. 52. 0 /  2. 52. 0
  libswscale    2.  1. 0 /  2.  1. 0
  libpostproc  51.  2. 0 / 51.  2. 0
[nc @ 0x7f8b7881ae00] Estimating duration from bitrate, this may be inaccurate
Input #0, nc, from 'http://admin:@192.168.0.126/test.cmp':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: mpeg4, yuv420p, 720x576 [SAR 1:1 DAR 5:4], 100 fps, 100 tbr, 100 tbn, 100 tbc
[buffer @ 0x7f8b7841e060] w:720 h:576 pixfmt:yuv420p tb:1/1000000 sar:1/1 sws_param:
[mpegts @ 0x7f8b7881dc00] muxrate VBR, pcr every 10 pkts, sdt every 200, pat/pmt every 40 pkts
Output #0, mpegts, to 'ffmpeg.ts':
  Metadata:
    encoder         : Lavf53.24.0
    Stream #0:0: Video: mpeg4, yuv420p, 720x576 [SAR 1:1 DAR 5:4], q=2-31, 200 kb/s, 90k tbn, 100 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (mpeg4 -> mpeg4)
Press [q] to stop, [?] for help
frame=  999 fps= 32 q=31.0 Lsize=    1388kB time=00:00:09.99 bitrate=1138.0kbits/s    
video:1161kB audio:0kB global headers:0kB muxing overhead 19.558646%

real	0m44.579s
user	0m5.549s
sys	0m0.363s

ffmpeg thinks it's recording 10 seconds, in reality the video is 44 seconds.

comment:9 Changed 3 years ago by michael

try -use_wallclock_as_timestamps 1

Note: See TracTickets for help on using tickets.