We begin where others give up.

(C) Seewald Solutions, 1180 Wien, Austria. Commercial use prohibited.
![]() |
Projects | Publications | CV | KDD | WEKA | Contact | Business |
I have ported the ISO MPEG4 compliant open-source video codec xvid to Symbian Series 60. I am using the sd2kunix tool chain which allows to compile S60 applications with a unix-like makefile. The code should work with other development kits as well. My intent is not to build (yet another) video player for Symbian, but to encode video on Symbian camera phones in real time and stream it (e.g. via BlueTooth)
Download xvidcore-1.0.3 (or newer version) from xvid.org, or use my local copy.
Apply the S60-EXE patch to the source files. This will give you XVID_CSP_RGB444, which is the bitmap format used by RCameraServ.GetImage() in low quality mode (160x120x12bit). The high quality format is already present (640x480x24bit). Compile for ARM processors with the patched GCC ARM compiler by Symbian. Done.
Disappointingly, RCameraServ.GetImage() seems broken for .EXEs and always gives a KErrCannotConnect (-34) exception, at least on the Nokia 3650.
In any case, to be used in a standard APP, this approach is not sufficient. Contrary to other reports, Symbian OS does allow static non-const global variables in DLLs / APPs, but only under rather severe restrictions - see statichack. An alternative is to replace them by thread-local storage, which is a single pointer for each thread. I have only tested the latter alternative.
To prevent having to do this for every new libxvid release, I have chosen to write a quick-and-dirty perl script which does most of the work. So after applying the S60-EXE patch from above, do...
Apply the EXE-to-CGV patch to the sources. This is very small, it mostly removes some duplicate definitions which would prevent compiling since all header files have to be merged, and declaring a few constant structures const.
Run collectGlobalVars.pl with the source directory and an empty but existing destination directory. Alternatively, you can also directly apply the CGV-to-DLL patch which does the same, but will break sooner. Both will create new source files using thread-local storage, plus the new file global_all_dll.c which you should add to sources.inc
Compile.
Before using any xvid function, you have to call init_thread_local_storage() to initialize the thread-local storage for the current thread. You also need to get a larger heap via User::SwitchHeap(UserHeap::ChunkHeap(...)) and at least 2 MB free memory. TLS is an overhead - encoding takes around 20% longer than in the EXE, but access to RCameraServ.GetImage() finally works.
Quality is very good even in the lowest quality mode. Encoding can be done in realtime for 160x120x12bit frames at around 5-6 FPS at the lowest quality settings (according to xvid_encraw). The encoding time per frame is around 120-200ms, and bandwidth is around 72kBit. Setting the quantizer manually to 16 reduces quality significantly and gives a bandwidth of 36kBit for streaming. I have played with the settings and ultra-low bandwidth settings (by which I mean less than 9.6kBit) are not achievable. I have not checked 640x480x24bit since RCameraServ.GetImage() only returns one image per second.
Check current research on ultra-low bandwidth codes and see whether it would make sense to implement one of them.
Hack the camera hardware interface to see whether 640x480 images can be retrieved faster than 1 FPS.
Comments and suggestions are welcome.