Green & purple vertical lines after mencoder processing?
Question
Hi,
I am still working on a movie file with all of a day's motion in it, and am currently trying the approach of processing all the .jpg files with an external encoder, ie. mencoder (part of the mplayer suite). This would involve no patches to Motion, if it works.
I'm now using the Motion daily snapshot of 30-11-2006 and the ffmpeg library snapshot also of 30-11-2006 (SVN-r7186). Mencoder version is the current version on their website, 1.0rc1-3.3.5.
The issue is, I encode with mencoder (command line included below) and when playing back the Avi file on my PC (windows 2000) with Media Player Classic, vertical fine lines in green are seen. In
VirtualDub, vertical purple lines are seen. (I realise these are windows programs unfortunately but my linux box is headless).
I'm hosting the files at my website:
84.51.146.238/output-msmpeg4v2.avi (1.6Mb)
84.51.146.238/media_p_classic.jpg (180kb)
84.51.146.238/virtualdub.jpg (200kb)
I also met this problem with previous versions of motion (3.2.6) and ffmpeg (2006-03-06 snapshot) but I upgraded to the latest versions to eliminate them - unfortunately I haven't managed to eliminate them....
I suspect a colourspace issue but know no more than that really. I have tried other movie file formats (mpeg-1, huffyuv etc) with the same results.
My mencoder command line is:
mencoder mf://20061201-07*cam2.jpg -mf w=640:h=480:fps=25:type=jpg -ovc lavc -lavcopts vcodec=msmpeg4v2 -nosound -o output-msmpeg4v2.avi
The output from mencoder is:
MEncoder 1.0rc1-3.3.5 (C) 2000-2006 MPlayer Team
CPU: ARM
success: format: 16 data: 0x0 - 0x0
MF file format detected.
[mf] search expr: 20061201-07*cam2.jpg
[mf] number of files: 15 (60)
VIDEO: [IJPG] 640x480 24bpp 25.000 fps 0.0 kbps ( 0.0 kbyte/s)
[V] filefmt:16 fourcc:0x47504A49 size:640x480 fps:25.00 ftime:=0.0400
Opening video filter: [expand osd=1]
Expand: -1 x -1, -1 ; -1, osd: 1, aspect: 0.000000, round: 1
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
Selected video codec: [ffmjpeg] vfm: ffmpeg (FFmpeg MJPEG decoder)
==========================================================================
VDec: vo config request - 640 x 480 (preferred colorspace: Planar YV12)
VDec: using Planar YV12 as output csp (no 3)
Movie-Aspect is undefined - no prescaling applied.
videocodec: libavcodec (640x480 fourcc=3234504d [24PM])
Writing header...
ODML: Aspect information not (yet?) available or unspecified, not writing vprp header.
Writing header...
ODML: Aspect information not (yet?) available or unspecified, not writing vprp header.
[msmpeg4v2 @ 0x513940]warning, clipping 1 dct coefficients to -127..127
[msmpeg4v2 @ 0x513940]warning, clipping 1 dct coefficients to -127..127
[msmpeg4v2 @ 0x513940]warning, clipping 1 dct coefficients to -127..127
[msmpeg4v2 @ 0x513940]warning, clipping 1 dct coefficients to -127..127
[msmpeg4v2 @ 0x513940]warning, clipping 1 dct coefficients to -127..127
Pos: 0.6s 15f (100%) 1.35fps Trem: 0min 1mb A-V:0.000 [0:0]
Flushing video frames
Writing index...
Writing header...
ODML: Aspect information not (yet?) available or unspecified, not writing vprp header.
Video stream: 22834.547 kbit/s (2854318 B/s) size: 1712591 bytes 0.600 secs 15 frames
#
Update
I have just tested using motion's ppm output file format, then converted to jpeg using 'convert' ; these jpeg files were clear (ok), then used mencoder to encode the resulting jpg files. The encoded video contained the purple lines again - this surely says that mencoder is at fault.
I tried using command-line ffmpeg, which I initially refused to do, because it cannot use my file naming convention - input files must be trivially named like image0001.jpg etc. I renamed 5 files and gave it a try.
# ffmpeg -i frame%02d.jpg out.mpg
FFmpeg version SVN-r7186, Copyright (c) 2000-2006 Fabrice Bellard, et al.
configuration: --prefix=/opt --enable-static --enable-shared
libavutil version: 49.1.0
libavcodec version: 51.25.0
libavformat version: 51.6.0
built on Nov 30 2006 17:56:47, gcc: 3.3.5
Input #0, image2, from 'frame%02d.jpg':
Duration: 00:00:00.2, start: 0.000000, bitrate: N/A
Stream #0.0: Video: mjpeg, yuvj420p, 640x480, 25.00 fps(r)
File 'out.mpg' already exists. Overwrite ? [y/N] y
Output #0, mpeg, to 'out.mpg':
Stream #0.0: Video: mpeg1video, yuv420p, 640x480, q=2-31, 200 kb/s, 25.00 fps(c)
Stream mapping:
Stream #0.0 -> #0.0
Press [q] to stop encoding
frame= 5 q=4.6 Lsize= 170kB time=0.2 bitrate=8704.0kbits/s
video:169kB audio:0kB global headers:0kB muxing overhead 0.708104%
#
Copy to Windows and... success! A five-frame movie encoded with no green/purple artifacts. But, it's a long way to where I want to go.... selecting the files of one camera only (ie. I need to use wildcards) and not forcing me to rename my files as 0001 0002 etc.
# cat 20061201-*cam2.jpg | ffmpeg -f mjpeg -s 640x480 -i - -r 25 -aspect 4:3 out3.mpg
FFmpeg version SVN-r7186, Copyright (c) 2000-2006 Fabrice Bellard, et al.
configuration: --prefix=/opt --enable-static --enable-shared
libavutil version: 49.1.0
libavcodec version: 51.25.0
libavformat version: 51.6.0
built on Nov 30 2006 17:56:47, gcc: 3.3.5
Input #0, mjpeg, from 'pipe:':
Duration: N/A, bitrate: N/A
Stream #0.0: Video: mjpeg, yuvj420p, 640x480, 25.00 fps(r)
Output #0, mpeg, to 'out3.mpg':
Stream #0.0: Video: mpeg1video, yuv420p, 640x480, q=2-31, 200 kb/s, 25.00 fps(c)
Stream mapping:
Stream #0.0 -> #0.0
[mpeg1video @ 0x4038757c]get_buffer() failed (stride changed)ts/s
Segmentation fault
# ls -l out3.mpg
-rw------- 1 root root 739328 Dec 1 14:40 out3.mpg
Closer.
I've been running the encode step repeatedly, and notice something. As the frame count goes up, the q= number goes down (2 = best quality, 31=worst).
Frame 6 q=6.8, Frame 12 q=24.2, soon afterwards it reaches q=31 and stays there until segfault occurs.
The same effect occurs when I add '-vcodec msmpeg4v2' to use mpeg-4.
I guess this is a Support question :- Perhaps this is why I see the similar effect in a Motion-generated timelapse ffmpeg film?
# cat 20061201-*cam2.jpg | ffmpeg -f mjpeg -s 640x480 -i - -y -r 25 -aspect 4:3 -s 640x480 -b 1000000 -vcodec mjpeg out4.avi
FFmpeg version SVN-r7186, Copyright (c) 2000-2006 Fabrice Bellard, et al.
configuration: --prefix=/opt --enable-static --enable-shared
libavutil version: 49.1.0
libavcodec version: 51.25.0
libavformat version: 51.6.0
built on Nov 30 2006 17:56:47, gcc: 3.3.5
Input #0, mjpeg, from 'pipe:':
Duration: N/A, bitrate: N/A
Stream #0.0: Video: mjpeg, yuvj420p, 640x480, 25.00 fps(r)
Output #0, avi, to 'out4.avi':
Stream #0.0: Video: mjpeg, yuvj420p, 640x480, q=2-31, 1000 kb/s, 25.00 fps(c)
Stream mapping:
Stream #0.0 -> #0.0
[mjpeg @ 0x4038757c]get_buffer() failed (stride changed)3.4kbits/s
[mjpeg @ 0x4038757c]get_buffer() failed (stride changed)
frame= 45 q=24.8 Lsize= 3495kB time=1.8 bitrate=15908.3kbits/s
video:3489kB audio:0kB global headers:0kB muxing overhead 0.189806%
Segmentation fault
It looks like it is not the stride change which directly causes the segfault, as they can occur more than once. The resulting mjpeg avi is playable and does not show a quality decrease towards the end (after all, it is all I-frames).
I try again using different input files and constraining the quality (-qmax 4):
# cat 20061124-*cam2.jpg | ffmpeg -f mjpeg -s 640x480 -i - -y -r 25 -aspect 4:3 -s 640x480 -b 1000000 -vcodec mjpeg -qmax 4 out4b.avi
FFmpeg version SVN-r7186, Copyright (c) 2000-2006 Fabrice Bellard, et al.
configuration: --prefix=/opt --enable-static --enable-shared
libavutil version: 49.1.0
libavcodec version: 51.25.0
libavformat version: 51.6.0
built on Nov 30 2006 17:56:47, gcc: 3.3.5
Input #0, mjpeg, from 'pipe:':
Duration: N/A, bitrate: N/A
Stream #0.0: Video: mjpeg, yuvj420p, 640x480, 25.00 fps(r)
Output #0, avi, to 'out4b.avi':
Stream #0.0: Video: mjpeg, yuvj420p, 640x480, q=2-4, 1000 kb/s, 25.00 fps(c)
Stream mapping:
Stream #0.0 -> #0.0
frame= 196 q=24.8 Lsize= 12818kB time=7.8 bitrate=13393.2kbits/s
video:12807kB audio:0kB global headers:0kB muxing overhead 0.079963%
Who knows why, but it worked. I note that it over-rode my bitrate argument.
Update, 4th December.
I have achieved an mpeg-1 file which plays under Windows (Media Player Classic, and
VirtualDub are my test softwares on Windows 2000). I suspect one possible problem was that a mpeg-1 video stream can be found stand-alone, in an Elementary Stream (ES) file, or muxed in a Program Stream (PS) file. Some playing software will not play the ES files, but does not state this explicitly.
I am using ffmpeg itself for the conversion. This is advantageous in that it is likely, but not always, to be found on a system running Motion.
FFMPEG Version: snapshot 2006-11-30 and Motion version: snapshot 2006-11-30
Also I have a solution to the problem that ffmpeg required trivial filenames like 0001 0002 etc. Ffmpeg will accept standard input with the '-i -' option.
But, if you use a simple '*.jpg' file specification (and this is true for any program) with a large number of matching files in the directory, it sometimes will not work. This is because the Linux command line length limit is exceeded when filename globbing is done (ie. expansion of the wildcard * ). The solution below uses 'find' which can handle any number of files and pipes into ffmpeg. My test directory has 14,000 files in it.
This is the way to process
any number of jpeg files into an mpeg-1 at 25fps (My source jpegs are 1fps and it looks like a fast-running film):
find . -name '20061201*cam2.jpg' -exec cat '{}' ';' | ffmpeg -f mjpeg -s 640x480 -i - -y -r 25 \
-aspect 4:3 -s 640x480 -b 1000000 -vcodec mpeg1video -me zero -sameq $OUTPUTFILE
Ffmpeg outut (snipped headers):
.....
frame=14762 q=1.0 Lsize= 763686kB time=590.4 bitrate=10595.7kbits/s
video:760772kB audio:0kB global headers:0kB muxing overhead 0.382980%
Issues noticed:
Time to encode was over 11 hours on my lightweight server, with nice -n 2 , while running Motion with 2 netcams.
Still the bitrate specification is not observed to the rate supplied. Perhaps the -sameq option is over-riding it (it means to use the same output quality as found on the input -- and I use 95% quality jpegs). The -me zero option is an attempt to increase speed (and can be omitted).
This is good news, as the ffmpeg package is already installed on my system for use by Motion. The
large MPlayer package can be removed, along with all the others I tried.
'Motion' gets a mention on the Transcode Wiki, here:
http://www.transcoding.org/cgi-bin/transcode?Making_Animations
(although I could not compile Transcode)
Conclusion
This is a means to get one file containing motion-only video, by encoding
all the jpeg images output by Motion. It was necessary to find a workaround because I noticed artifacts in the Motion Mpeg-1 output in timelapse mode, and also in a patch I added to output motion frames in the same way as timelapse ones. (Note: This was with an older ffmpeg snapshot and motion-3.2.6 and I should find out if it's still the case).
There are quite high disk space & time penalties to off-line encoding such as this, when large amounts of motion are involved. The disk space of course can be reclaimed by deleting the Jpegs after a successful encode, but the time cannot.
The ideal solution is to have Motion output an Mpeg-1 file without artifacts - perhaps now a set of working ffmpeg command line parameters are known, these can be used inside Motion itself. I will look at this as a way forward.
@Kenneth: Perhaps now this could/should be moved to a Wiki page called "Post-processing Jpeg files into a film, with mencoder and ffmpeg" ?
I am happy to 'tune' it after the move has occurred, so it makes more sense.
Simon.
Environment
Motion version: |
snap 2006-11-30 |
ffmpeg version: |
snap 2006-11-30 |
Libraries: |
ffmpeg |
Server OS: |
NSLU2 Linux Unslung 6.8 |
--
SimonW - 01 Dec 2006
Answer