[GUIDE] H.264 Streams for Ubuntu with OpenCV
Hi! I had a lot of difficulty managing to get OpenCV to work nicely with H.264 streams on Ubuntu, particularly with my ELP camera with on-board H.264 encoding. I am writing up everything that I found out in the hopes that it'll help someone else out, the advice should be portable to other Linux distros with little extra effort.
First thing is please read the whole post here before following any links to other guides that I reference as I may provide an alteration to what is there. Let me know if anything is unclear and I'll edit accordingly.
So, OpenCV can't use the H.264 codecs used by ffmpeg, namely libx264, unless it's all compiled using shared libraries. I found doing this a lot more difficult than I felt that it needed to be mainly because I couldn't find any solid documentation around.
So the first solution is the easiest, and that's to use gstreamer. When you compile OpenCV with cmake, use -DWITH_FFMPEG=OFF and -DWITH_GSTREAMER=ON. I haven't done much testing but this should sort you out. I also wasn't able to encode for some reason, only decode. I was still determined to get it working with ffmpeg however!!
DO NOT FOLLOW EXACTLY but here is the ffmpeg compilation guide where we'll be starting from:
https://trac.ffmpeg.org/wiki/Compilat...
Follow as normal until you reach the libx264 section, here we will doing the manual compilation option but adding the flag --enable-shared to the call to configure. The modified command looks similar to this:
cd ~/ffmpeg_sources && \ git -C x264 pull 2> /dev/null || git clone --depth 1 https://git.videolan.org/git/x264 && \ cd x264 && \ PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --enable-static --enable-shared --enable-pic && \ PATH="$HOME/bin:$PATH" make && \ make install
This is actually sufficient for the purposes here, but if you want the other libraries then it's the same deal, the essential flags are --enable-shared and --enable-pic. This will force the compilation of shared libraries and also position independent code (pic). I ended up also removing the --enable-static flags for safety but I am unsure if it's required.
Now onto the actual ffmpeg compilation. We are again adding --enable-shared and --enable-pic but also --cc="gcc -m64 -fPIC".
This last one tells ffmpeg to use the flags -m64 and -fPIC in calls to gcc. -m64 ensuring 64-bit environment and -fPIC will force position independent code. Perhaps sometimes --enable-pic is sufficient but it wasn't for me.
I also removed --pkg-config-flags="--static" and added --disable-static though I can't guarantee that these are essential but they appeared necessary in my case. The command that I used is so (note no libx265, add --enable-libx265 if you need):
cd ~/ffmpeg_sources && \ wget -O ffmpeg-snapshot.tar.bz2 https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2 && \ tar xjvf ffmpeg-snapshot.tar.bz2 && \ cd ffmpeg ...
If you want to preserve information like this, it would be nice if you could create an extra tutorial and contribute it through a pull request. Here it will silently disappear, never to be looked at again ...
Good idea! I will get on that shortly.
Hi, thank you for the guide! Really useful! I'm getting this problem, do you have any clue on how to solve it?
/usr/bin/ld: /home/nicola/ffmpeg_build/lib/libfdk-aac.a(genericStds.o): relocation R_X86_64_PC32 against symbol `stdout@@GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Bad value collect2: error: ld returned 1 exit status ffbuild/library.mak:102: recipe for target 'libavcodec/libavcodec.so.58' failed make: * [libavcodec/libavcodec.so.58] Error 1