Developers making Linux-based products with the Texas Instruments DaVinci DM365 or DM368 will find a plethora of example source code and libraries that allow you to easily build your own applications. However if you want to build a non-Linux product (to use your existing RTOS for example) you will find little guidance on where to start.
Faced with a huge amount of source code and frameworks within the software development kit (DVSDK), it is difficult to figure out where to begin. Having gone through this process recently, I provide below some guidelines on getting up and running with the DM365/DM368 DVSDK and codecs in a non-Linux or RTOS environment.
Is the DVSDK Needed?
If you want to write an application that utilises the JPEG encoder, for example, you will first want to know whether you only need to write a simple application that links to the JPEG encoder library or whether you need to incorporate some auxiliary libraries from the DVSDK. My experience is that some of the DVSDK is indeed very useful and it is not necessary to rewrite portions of it from scratch. You will, however, find that the existing DVSDK code for non-Linux environments needs some modification before it will compile, and suffers from various runtime faults.
Full Codec Engine or Subset
The superset framework is the Codec Engine that provides a common interface across the codecs, but it does appear to be rather Linux-centric and porting the entire framework would be a not insignificant task. If the full Codec Engine is not strictly required by your application, then you may find that you can make better progress by reducing the components to the minimal set required for using the particular codec. I found that there are many parts of the DVSDK which are not required, and only a small subset which are required to let you take full advantage of the codecs.
Building the Relevant DVSDK Components
I started my porting effort by writing a simple JPEG encoder application, and found that there was a JPEG encoder test application that looked like it might prove useful (jpegencTestApp). Messages on the TI forums suggested that it was no longer buildable and not a good starting point and it did look a little Linux-centric (the Makefile defines -DLINUX and there were some mentions of the linuxtools tree). However in the absence of any alternative I persevered with the test application.
It quickly became clear that the test application and the binary JPEG encoder library are not sufficient to create an application – they require some auxiliary libraries from the DVSDK. Most of the components in the DVSDK have prebuilt library binaries available but these are targeted at Linux (for example xdc_target__os_Linux is defined) and they attempt to link to various Linux-specific functions.
The DVSDK does purport to be cross-platform and you can build without defining xdc_target__os_Linux but you will find that there are several bugs that either prevent compilation (which are easy to find) and several other bugs that silently cause failures at runtime (which are much more difficult to spot). If you would like to fix your DVSDK tree to support non-Linux environments then please feel free to contact me and I would be happy to send you a patch.
A few tips that should give you a head-start when porting the DVSDK to a non-Linux environment are:
- Only a subset of the DVSDK is required to build a codec application (e.g. a JPEG encoder). You can simplify the task by building only the libraries that are required for the particular codec application you are building.
- The DVSDK components can generally be compiled with a simple Makefile, allowing you to avoid getting the full TI build scripts working.
- You should compile the DVSDK components without xdc_target__os_Linux defined to take advantage of the places in the DVSDK where TI have already attempted to cater for non-Linux targets. You will generally find that the non-Linux code is buggy, however, without applying fixes (available from me as a patch file).
- The additional GCC flags I use when compiling the DVSDK are as follows (these were the only additional flags required over and above those I normally use to build the rest of my sources):
- ‘-Dxdc_target_types__=”gnu/targets/std.h” -Dxdc_target__os_undefined=1 -DGT_TRACE=0 -DDEBUG=0’
- The codec libraries are delivered in object form and it is not immediately obvious what dependencies are required from the DVSDK. Sometimes the best way to establish the minimal subset of required components for your application is to simply attempt to link to the codec library and resolve the dependencies one by one.
- The obvious components that you need to write porting layers for are the OS abstraction layer (OSAL) components (e.g. to hook into the cache handling of your own RTOS).
- Some of the OS abstraction components only need stubs, such as LockMP which is used for multi-process environments (rather than the typical lightweight threading model used in an RTOS).
- When adding a new component from the DVSDK, you may not need all of the source files from the component’s package folder. If there are multiple files in a framework component (e.g. iresman_edma3Chan.c and iresman_edma3ChanArm.c), check the component’s package.bld file to see which of the source files are required for your architecture.
- You will find that some variables and functions which you need to link are not present in DVSDK components at all. These might be auto-generated by the “XDC” tools. The XDC tools turn TI’s proprietary .cfg files into C files that contain new variables and functions that should be compiled and linked to your project. Contact me for a sample .cfg file suitable for use with the JPEG/MP4 encoder. You use the xs configuro tool to generate the necessary C file. This can be invoked as follows:
- XDCPATH=”<path_to_DVSDK_packages_folders>” <path_to_dvsdk>/xdctools_3_16_03_36/xs xdc.tools.configuro -t gnu.targets.MVArm9 -c /opt/montavista/pro/devkit/arm/v5t_le -p ti.platforms.evmDM365 -o <output_folder> <config_file.cfg>
- If you are using a simple RTOS without full virtual memory/MMU support, you can set the noOS flag to avoid having to provide address-translation functions. This flag can be set to TRUE in your .cfg file for both the ADDRSPACE and MEMUTILS components.
The codecs need to be notified when relevant interrupts have occurred, for example the JPEG and MP4 encoders expect you to provide a VICP_wait() function that they can call to wait for an interrupt to occur. The sample vicp_framework.c in the JPEG encoder test application folder is a good starting point. You will need to provide hooks into your own interrupt dispatcher such that this component’s ISR is called when the relevant interrupts occur. As delivered, the sample code just polls a flag which is set by the ISR – you can improve this by making the ISR post a semaphore or similar, so that the codec library can block on the interrupt occurring rather than poll continuously. The JPEG and MP4 (MJCP) encoders use the ASQINT/SEQINT interrupts (bit 9) so you should attach the vicp_framework.c ISR to that interrupt.
Object Code EABI Issues
One issue that you may face, depending on your build of GCC and your compiler options, is that the codec libraries are built with “-mabi=aapcs-linux“. This specifies EABI with 32 -bit (int) enums, common for Linux ARM builds but not necessarily other RTOS build environments. If your own GCC build makes enums as short as possible rather than forcing them up to 32-bits, then the layout of the structures which the DVSDK passes in and out of the binary codec libraries will not match.
TI do not publish the sources to the codec libraries, and do not provide a version of the codec libraries compiled with short enum support, so you need to modify your own application build to match the codec library (or provide a shim layer). You can do this by building your own application code with “-mabi=aapcs-linux” or “-fno-short-enums“.
Faults in the DVSDK for non-Linux Environments
Although the DVSDK purports to be cross-platform, and does have some conditional compilation to cater for WinCE and non-Linux environments, there are various faults that make it unusable for non-Linux builds without some modification (at least in version 4.02.00.06). Feel free to contact me for a patch, but here are a few examples of issues in this release:
- The heap allocation (ALG_) routines in the JPEG encoder test application seem like a good starting point but are seriously flawed. A simple issue to fix is that the allocations need to be zeroed on allocation (it turns out that the DVSDK components expect these allocations to be zeroed for them). The main issue, however, is that they do not allow memory to be freed; they don’t free up holes in a heap, just drop back to earlier allocation addresses, causing memory stomps all over previous allocations. You are much better off using the allocation routines in fc/utils/api/alg_malloc.c, subject to the following.
- The more sturdy allocator, fc/utils/api/alg_malloc.c, has an implementation for non-Linux (WinCE) environments which is nearly useful. It is a big improvement on the severely broken equivalent in the JPEG encoder test application, but it is itself broken too. The myMemAlign() call has the parameters swapped, suggesting that perhaps this code was in service some time ago but when changes were made for Linux they were not reflected into the non-Linux code. A situation that is repeated in other DVSDK modules.
- Another fault in the same alg_malloc.c module is that it does some realignment on pointers returned by the heap allocator, but does not use the original allocated pointer when the allocation is later freed, causing heap errors.
- There is a memory leak in edma3_configArm.c in non-Linux environments.
- The iresman_vicp2 module has several faults related to freeing of resources when a session is closed, causing various resources to be remain assigned. Many of the faults appear to be related to closing/freeing of resources; presumably the work done on non-Linux environments was for simple session setup without any closing and reopening of other codec sessions.
- Various minor build errors if xdc_target__os_Linux is not defined.
Useful DVSDK Components
You may find that you need a different subset of DVSDK components for your application, but for a simple JPEG and MP4 encoder I made use of the following (note that I used the MJCP MP4 encoder, rather than the HDVICP MP4 encoder):
- RMAN
- OSAL (noOS)
- EDMA3
- VICPSYNC
- IRES: ADDRSPACE, EDMA3CHAN, GROUPUTILS, NULLRESOURCE, VICP(2)
- FC UTILS: GT, ALG_MALLOC, SMGRMP
Alternative Approaches
There are other ways to approach bringing up the codecs in non-Linux environments. One would be to use the standard Linux builds of the DVSDK components and provide abstraction layers for the Linux functions. This would have avoided the build and runtime faults that exist in the DVSDK for non-Linux builds, but at the cost of increasing complexity in terms of the porting layer. You may also prefer to utilise the entire Codec Framework, but I felt that using the absolute minimum required subset of modules reduced the complexity of the entire port.
Please feel free to get in touch if you have any questions or would like to discuss anything further.