Some time ago, I went to a conference and was keen enough to setup a webcam to take a picture every couple of seconds. I then had 27,000 JPEG images, which I wanted to turn into a simple MPEG movie. This document details the process I went through to make this happen.
The version of this howto which you are currently reading is an update of the original version. I updated the document about a year after initially going through the process. This version reflects a few small changes in the open source projects which I used to perform the conversion, and some error corrections from the original version of this document.
Since the original version of this article, I have updated my machine from a pretty vanilla Redhat 7.1 box to a Debian unstable machine, for those who care about such things. Where things have changed from my experience about a year ago, I'll let you know.
I'm also a little surprised about the amount of email I have received about the original version of this document — obviously lots of people are trying to solve this kind of problem. I also get a lot of email from people using Microsoft Windows™ and wanting to perform a similar conversion. Unfortunately, as someone who doesn't use Windows very much, I cannot recommend a way of doing this sort of processing on that platform, although it is possible that MJPEG tools could be compiled for Windows™ — I just haven't tried. I would recommend Google as a way of finding something to help you out.
Michael has been working in the image processing field for several years, including a couple of years managing and developing large image databases for an Australian government department. He currently works for TOWER Software, who manufacture a world leading EDMS and Records Management package named TRIM. Michael is also the developer of Panda, an open source PDF generation API, as well as a bunch of other Open Source code.
Michael has a website at http://www.stillhq.com, and may be emailed at mikal@stillhq.com
When I went searching for something to convert my many JPEG files to a MPEG moving, I quickly came across the MJPEG tools project. The URL for this project is http://mjpeg.sourceforge.net. MJPEG tools is very powerful, but there are lots of dependencies, which we should talk about first. There are also a few build and install problems with some of these dependencies which need to be resolved along the way, which I have also documented here. The updated version of this article was written with version 1.6.1 beta.
Let's work through the various MJPEG tools dependencies one by one, and discuss what needs to be done to get them installed on your machine.
This library can be found at http://avifile.sourceforge.net. It is needed by MJPEG tools to be able to handle AVI files. The version I used was 0.7.37. It follows the standard autotools install process:
./configure make make install
For Debian, just use apt-get install libavifile0.7-dev.
"Simple DirectMedia Layer is a cross-platform multimedia library designed to provide fast access to the graphics framebuffer and audio device. It is used by MPEG playback software, emulators, and many popular games, including the award winning Linux port of "Civilization: Call To Power." Simple DirectMedia Layer supports Linux, Win32, BeOS, MacOS, Solaris, IRIX, and FreeBSD." -- http://www.libsdl.org/index.php
libsdl can be found at http://www.libsdl.org, and is needed for some of the MJPEG playback routines. I used version 1.2.5. Again, installing is done by simply:
./configure make make install
For Debian, just do a apt-get install libsdl-dev.
The NASM web page can be found at http://nasm.sourceforge.net/. An explanation of where NASM came from can be found in the documentation:
The Netwide Assembler grew out of an idea on comp.lang.asm.x86 (or possibly alt.lang.asm - I forget which), which was essentially that there didn't seem to be a good free x86-series assembler around, and that maybe someone ought to write one.
So here, for your coding pleasure, is NASM. At present it's still in prototype stage - we don't promise that it can outperform any of these assemblers. But please, please send us bug reports, fixes, helpful information, and anything else you can get your hands on (and thanks to the many people who've done this already! You all know who you are), and we'll improve it out of all recognition. Again. | ||
| --http://home.attbi.com/~fbkotler/nasmdoc1.html#section-1.1 | ||
I downloaded 0.98.36 when I wrote the updated version of this article.
Install it by doing the autotools thing once more. Note that the make install step is still broken (it didn't work for the first version of the article a year ago either), and that I had to do this to get it to install:
mkdir bin mkdir man mkdir man/man1 make install cp bin/nasm /usr/local/bin/ cp man/man1/n* /usr/local/man/man1/
This seems to be because it is trying to install everything in the the current working directory, instead of the system wide install location. You should also note that apt-get install nasm on a Debian machine does exactly what is expected of it, and packages exactly the version which was available from the NASM website.
We'll also need the MJPEG people's MMX JPEG library, which was at version 0.1.4 at the time of writing this article. I believe the difference between the standard JPEG library and the MMX JPEG library is that the MMX version is optimized for MMX processors, and wont run on processors without MMX. The standard libjpeg also seems to be an option here, although my machine have MMX, so I didn't try it. I downloaded version 0.1.4, and did the autotools thing.
For some reason they have disabled the install make target, possibly because they're worried about clobbering the standard libjpeg install. This reason doesn't really work though, as the library files have different names from those used in libjpeg. I did:
[root@localhost jpeg-mmx-0.1.4]# make install Make install has been disabled If you really want to install libjpeg-mmx, please use make install_real [root@localhost jpeg-mmx-0.1.4]# make install_real /usr/bin/install -c -m 644 jconfig.h /usr/local/include/jconfig.h /usr/bin/install -c -m 644 ./jpeglib.h /usr/local/include/jpeglib.h /usr/bin/install -c -m 644 ./jmorecfg.h /usr/local/include/jmorecfg.h /usr/bin/install -c -m 644 ./jerror.h /usr/local/include/jerror.h /usr/bin/install -c -m 644 ./jinclude.h /usr/local/include/jinclude.h /usr/bin/install -c -m 644 libjpeg-mmx.a /usr/local/lib/libjpeg-mmx.a [root@localhost jpeg-mmx-0.1.4]#
And annoyingly, I also had to manually copy a file:
cp jpegint.h /usr/local/include/
TODO: Debian package?
movtar is actually written by the MJPEG people. You can download it from http://download.sourceforge.net/mjpeg/. I used the 1.3.0 release, which hasn't changed since I wrote this article a year ago. The install was autotooled once more. I am sure by now I don't have to explain how to do that...
TODO: Debian package
Since I first wrote this article, MJPEG tools appears to have added a dependency on the fontconfig library from www.fontconfig.org. I installed version 2.2.1. Annoyingly, the autotools configuration for MJPEG tools didn't detect that fontconfig was missing, it just failed to compile.
TODO: Debian package
I downloaded version 1.6.1 from the SourceForge website. Yet again, the install process was based off the autotools.
Then we can go ahead and make the project:
./configure make make install
For those who are interested, my build configuration at the end of the configure script looked like:
MJPEG tools 1.6.1 build configuration :
- X86 Optimizations:
- MMX/3DNow!/SSE enabled : true
- cmov support enabled : true
****************************************************************************
* NOTE: *
* The resultant binaries will ***NOT*** run on a K6 or Pentium CPU *
****************************************************************************
- video4linux recording/playback: true
- software MJPEG playback : true
- movtar playback/recording : true
- Quicktime playback/recording : false
- AVI MJPEG playback/recording : true (always)
- libDV (digital video) support : false
- AVIFILE divx encoding support : true
- Gtk+ support for glav : true
- glibc support for >2GB files : trueThis time around, because I am using a newer version of GCC, I had to apply the following patch:
diff -urN mjpegtools-1.6.1/mplex/multplex.cc mjpegtools-1.6.1-hacked2/mplex/multplex.cc --- mjpegtools-1.6.1/mplex/multplex.cc 2002-04-30 00:36:00.000000000 +1000 +++ mjpegtools-1.6.1-hacked2/mplex/multplex.cc 2003-07-25 09:05:40.000000000 +1000 @@ -3,6 +3,7 @@ #include <math.h> #include <stdlib.h> #include <unistd.h> +#include <assert.h> #include <mjpeg_types.h> #include <mjpeg_logging.h> diff -urN mjpegtools-1.6.1/mplex/stillsstream.cc mjpegtools-1.6.1-hacked2/mplex/stillsstream.cc --- mjpegtools-1.6.1/mplex/stillsstream.cc 2002-04-18 14:32:02.000000000 +1000 +++ mjpegtools-1.6.1-hacked2/mplex/stillsstream.cc 2003-07-25 09:07:55.000000000 +1000 @@ -22,6 +22,7 @@ #include <format_codes.h> +#include <assert.h> #include "stillsstream.hh" #include "interact.hh" diff -urN mjpegtools-1.6.1/mplex/systems.cc mjpegtools-1.6.1-hacked2/mplex/systems.cc --- mjpegtools-1.6.1/mplex/systems.cc 2002-04-30 00:36:01.000000000 +1000 +++ mjpegtools-1.6.1-hacked2/mplex/systems.cc 2003-07-25 09:07:19.000000000 +1000 @@ -4,6 +4,7 @@ #include <string.h> #include <sys/param.h> #include <sys/stat.h> +#include <assert.h> #include "systems.hh" #include "mplexconsts.hh" diff -urN mjpegtools-1.6.1/yuvdenoise/Makefile.am mjpegtools-1.6.1-hacked2/yuvdenoise/Makefile.am --- mjpegtools-1.6.1/yuvdenoise/Makefile.am 2002-03-25 07:52:57.000000000 +1100 +++ mjpegtools-1.6.1-hacked2/yuvdenoise/Makefile.am 2003-07-25 09:20:06.000000000 +1000 @@ -3,7 +3,9 @@ EXTRA_DIST = .cvsignore MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I $(top_srcdir)/utils -I $(top_srcdir) -AM_CFLAGS = -funroll-all-loops -finline-functions -ffast-math -frerun-cse-after-loop -frerun-loop-opt -fexpensive-optimizations -fmove-all-movables -Werror + +# Mikal: Turned off -Werror because of ASM changes in GCC +AM_CFLAGS = -funroll-all-loops -finline-functions -ffast-math -frerun-cse-after-loop -frerun-loop-opt -fexpensive-optimizations -fmove-all-movables bin_PROGRAMS = yuvdenoise yuvdenoise_SOURCES = main.c deinterlace.c deinterlace.h denoise.c denoise.h motion.c motion.h global.h diff -urN mjpegtools-1.6.1/yuvdenoise/Makefile.in mjpegtools-1.6.1-hacked2/yuvdenoise/Makefile.in --- mjpegtools-1.6.1/yuvdenoise/Makefile.in 2002-12-09 23:58:03.000000000 +1100 +++ mjpegtools-1.6.1-hacked2/yuvdenoise/Makefile.in 2003-07-25 09:21:36.000000000 +1000 @@ -134,7 +134,9 @@ EXTRA_DIST = .cvsignore MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I $(top_srcdir)/utils -I $(top_srcdir) -AM_CFLAGS = -funroll-all-loops -finline-functions -ffast-math -frerun-cse-after-loop -frerun-loop-opt -fexpensive-optimizations -fmove-all-movables -Werror + +# Mikal: Removed -Werror because of GCC asm changes +AM_CFLAGS = -funroll-all-loops -finline-functions -ffast-math -frerun-cse-after-loop -frerun-loop-opt -fexpensive-optimizations -fmove-all-movables bin_PROGRAMS = yuvdenoise yuvdenoise_SOURCES = main.c deinterlace.c deinterlace.h denoise.c denoise.h motion.c motion.h global.h
Code: mjpegtools.patch
TODO: Debian package
Finally, we can use MJPEG tools to convert the JPEGs into a MPEG stream.
When I originally wrote this article, I recommended that people use the following command line, which is what I had found recommended on the web, and what worked for me:
jpeg2yuv -f 25 -j frame-%05d.jpg -I p | mpeg2enc -o mpegfile.m1v
It turns out that the recommended command line is much more like:
ls *.ppm | xargs -n1 cat | ppmtoy4m | mpeg2enc -o mpegfile.m1v
It should be noted that this command line requires that the input images be PPM files instead of JPEG files however. We can get around this by using convert to change the format of the images:
for item in `ls *.jpg` do convert $item $item.ppm done
Note that the conversion is also quite slow, I walked away and came back later.
In this document I have discussed how to install MJPEG tools and it's dependancies, and then discussed how to convert a bunch of JPEGs to PPM files, and then a single MPEG movie. I hope you have found this document of some use. Feel free to send me email if you have more questions, although I don't gaurantee to personally answer then many hundreds of emails I receive each day.