Tuesday, April 16, 2013

Building omxplayer on a Raspberry Pi

The past couple days, I set aside my PIC work and concentrated on setting up a Raspberry Pi ("RPi"). I've got a couple of these, and will use them as video streamers for televisions in my house.

There is quite a bit of documentation for getting an RPi set up, so I won't repeat that here. My current focus is on getting video streaming working. An obvious candidate is RaspBMC, but I was looking for something very bare-bones to simply put a video onto the HDMI output. I ran across PyPlex which seemed right up my alley: Python and effectively an interface-less control of the video.

Yah. Well. Then I look at the setup/build requirements. twisted-web? pexpect? Seriously? Somebody has made this much more complicated than it should be. Whatever happened to just using BaseHTTPServer and the subprocess module?

Digging in, I find it is using omxplayer underneath. No wonder they're using pexpect -- there is a tty/keyboard interface to omxplayer. (of course, pty might be simpler than pexpect, but whatever) So this PyPlex thing starts up a web service and then controls omxplayer via a tty connection. I'm not seeing reliability and responsiveness here. And a lot of code, to boot.

Tearing off another layer of the onion, I start looking at omxplayer. Sigh. Requirements hell yet again. GCC 4.7. Boost. ffmpeg. Oh, and it is generally set up for cross-compilation rather than building on the RPi. This isn't a bad concept in general, as the RPi is no speed demon. But the build only takes a long time because they chose ffmpeg, whereas the Raspbian distribution uses libav. (these two libraries are reasonably similar, as libav forked from ffmpeg rather nastily a couple years ago)

So I'm looking at this giant pile of C++ code with a bunch of crazy requirements, which would take hours to build on my RPi. This is the wonderful state of video on the RPi. Sigh.

Well... I found a post by Keith Wright where he talks about building (a tweaked fork) of omxplayer on Raspbian. Much better, but the instructions still have crazy oddities about reconfiguring RAM, sudo to build in strange filesystem locations, and hey! fun! building ffmpeg from scratch again. Sigh. A guy just can't get any love around here.

Being the good geek that I am... this just wasn't something that I want to put up with. I want to build this sucker on my RPi, using standard tooling and libraries that come on Raspbian.

First up, I started from huceke/omxplayer rather than Keith's because it is much newer. But I did grab the Makefile.include from Keith, as it was sane for building on the RPi. Adjusted some of the paths to point to the installed items. Then, I had to install the following packages on the RPi: libpcre3-dev, libavcodec-dev, libavdevice-dev, libavfilter-dev, libavformat-dev, libboost-dev. As I started working through getting omxplayer built, I ran into a bug in a system header.

In /opt/vc/include/interface/vmcs_host/vcgencmd.h, line 33 needs to be changed to:
#include "interface/vmcs_host/linux/vchost_config.h"
I've filed a pull request to github:raspberrypi/firmware to fix this. Not sure if that is the Right place (that code may come from upstream?), but hopefully somebody will see it.

Next up, I had to hack away, tweak, and otherwise put a bit of pain on the omxplayer sources. Some hacks were easy, but others likely broke stuff (I'm not sure if subtitles work any more). Hard to tell. A/V code is not easy, and not something that I'm familiar with.

You can find all of my changes in my omxplayer fork. Clone that to your RPi, install the necessary packages, and hit "make". No system reconfiguration. No sudo. No hours of ffmpeg building. No GCC 4.7 requirement.

Clone. Make.

Go have fun, and watch some movies!

(my next step is to tear off the user interface bits, and shift to a simpler, pure-C library which I can wrap/control from Python)


Greg Stein said...

Oh: also had to install libpcre3-dev

lvariu said...

Hi Greg,

Very nice post, especially not needing to compile the whole of ffmpeg. I do however get in trouble while compiling BitstreamConverter.cpp:

apparently I am missing libswresample/swresample.h . Did a quick search on google, however nothing turns up the information I need for Raspberry. I'm running the latest Raspbian image from February 2013. Any thoughts ?

Thanks !

Greg Stein said...

@lvariu: I need to set up my board again, and will look into this. I suspect: just comment out the #include. (I may have forgot to merge/commit a change)

I also got a comment back on my "fix" for vcgencmd.h: the correct fix is a Makefile change, adding -I/opt/vc/include/interface/vmcs_host/linux/. I'll get that merged in, too.

lvariu said...

Thanks for the reply !

Yeah, I've figured out that the linker option must be added into the makefile. I was initially trying to compile the huceke version, including the ffmpeg.

I was trying to strip down omxplayer to the bare minimum for video playback and use this as a base to play multiple files in preset zones on the screen.

Greg Stein said...

I've just committed/pushed fixes for both issues: the Makefile.include change, and the resample change.

I've verified that it builds cleanly on a new Raspbian image, given the extra -dev package installs mentioned in the post.

N1VG said...

Thanks so much for posting this! I'm customizing omxplayer for an art project and I needed it to change the source region on the fly. Looks like it's going to work. Would have taken me a lot longer to get here without your code to start from.

Cyrus said...

OMXSubtitleTagSami.cpp:28:38: fatal error: boost/algorithm/string.hpp: No such file or directory
compilation terminated.
make: *** [OMXSubtitleTagSami.o] Error 1

The above is the error I get when typing the make command.

Greg Stein said...

@Cyrus: did you install libboost-dev ?

DOB said...

Nice! Easy to build and works best of the 3 forks I tried (other two were the default raspbian package, and the popcornmix fork that I struggled to build and ends up having audio sync issues)

jtheath said...

Hi Greg,

Thank you for posting this - very helpful! First compile resulted in a build error, SubtitleRenderer.h (included by OMXPlayerSubtitles.cpp) includes ft2build.h which wasn't present so needed to install libfreetype6-dev to resolve the reference.

Other than that, sweet ride.

Planning to put a socket front-end on this.

Best, Joe

jtheath said...

Needed to install libfreetype6-dev to resolve ft2buiild.h dependency (in SubtitleRenderer.h itself #included by OMXPlayerSubtitles.cpp).

Other than than, sweet ride.

Much appreciated! Joe

ncvp said...

Thanks for the fork. Like everyone else, I found it just worked.

I'm working on remote control of OMXPlayer, and having trouble with seek consistency. See http://ncvp.co.uk/pivpr/

Any suggestions?

- Nick

Brad Goodman said...

Thanks for the help! Seems like I'm trying to do the same thing as you - create a "control path" for omxplayer where I can have better external control of it - like even being able to specify/switch/*fade* videos while in-play. To make matters a (whole lot) worse - I'm trying to cross compile omxplayer. :-O

Possumkeys said...

I keep getting errors with DllAvUtil.h, such as ::av_get_channel_layout has not been declared, in DllAvFormat.h, ::url_feof has not been declared and so on. ALl this is during inclusion in BitstreamConverter.h

Possumkeys said...

I keep getting errors with DllAvUtil.h, such as ::av_get_channel_layout has not been declared, in DllAvFormat.h, ::url_feof has not been declared and so on. ALl this is during inclusion in BitstreamConverter.h

Greg Stein said...

Hey @Possumkeys ... I suspect bitrot. I'm betting the dependencies have updated in the past two years since I worked on this. I'll be getting back to it, soon, and will merge/fix.

I welcome any pull requests to fix this issues.