![]() |
![]() |
DMAI is a thin utility layer on top of the operating system (Linux, WinCE or DSP/BIOS) and the Codec Engine (CE) to assist in quickly writing portable applications on a Davinci platform. DMAI is used by the DVSDK demos and should make additional demo development quicker than in previous DVSDK releases.
The different DMAI modules communicate using a Buffer abstraction which carries not only the actual data (video, speech, audio etc.) but also meta data describing the Buffer which is used by the Codec Engine and Linux device drivers to perform operations on the data.
DMAI does not wrap the Operating System or CE, but as the below picture shows the application can choose when to use DMAI and when to use the Operating System or Codec Engine directly:
DMAI Block Diagram
I.e. DMAI does not abstract the peripherals themselves, it abstracts the actual operations e.g. frame copying. DMAI then implements a frame copy using the peripherals and resouces at it's disposal on a particular platform (e.g. the Framecopy module is currently implemented using the resizer peripheral on dm6446, but using DMA on dm355).
DMAI is a collection of modules, and the application can pick and choose which modules to use. Since DMAI comes with source code, it can also be used as a reference on how to accomplish certain tasks using e.g. a certain device driver.
If you receive DMAI as part of the DVSDK it will be extracted for you under $(DVSDK_INSTALL_DIR), but if you receive it separate as an update it will be in a tar ball, i.e. dmai_<version>.tar.gz. You extract the archive using tar xzf dmai_<version>.tar.gz.
You can either extract the archive to your $(DVSDK_INSTALL_DIR), since each DMAI release has a unique version number the installations will not conflict. Or you can extract the archive to another directory on your system.
DMAI and all of it's sample applications build using the top level Rules.make file, and depending on which of these two above install options you choose the behavior will be slightly different. This because the top level Rules.make tries to include a Rules.make from one directory above where the DVSDK would keep it's Rules.make if DMAI was delivered as part of a DVSDK, and if found these settings will be used instead of the local DMAI ones. This allows the DVSDK to override how DMAI is built keeping one DVSDK wide Rules.make file, but also allows DMAI to be built standalone without the DVSDK.
After you have extracted the tar ball, the directory structure will look as follows:
dmai_<version> // Rules.make is in this directory |-- docs // Documentation files for DMAI |-- packages // Your XDC path should include this dir | `-- ti | `-- sdo | `-- dmai // DMAI package top level directory | |-- apps // Reference applications | | | | | |-- audio_decode1 // audio decode using IAUDDEC1 | | |-- audio_decode_io // audio decode using IAUDDEC | | |-- audio_decode_io1 // audio decode using IAUDDEC1 | | |-- audio_encode1 // audio encode using IAUDENC1 | | |-- audio_encode_io1 // audio encode using IAUDENC1 | | |-- image_decode_io // image decode using IIMGDEC | | |-- image_decode_io1 // image decode using IIMGDEC1 | | |-- image_encode_io // image encode using IIMGENC | | |-- image_encode_io1 // image encode using IIMGENC1 | | |-- speech_decode1 // speech decode using ISPHDEC1 | | |-- speech_decode_io1 // speech decode using ISPHDEC1 | | |-- speech_encode1 // speech encode using ISPHENC1 | | |-- speech_encode_io1 // speech encode using ISPHENC1 | | |-- video_decode_io // video decode using IVIDDEC | | |-- video_decode_io2 // video decode using IVIDDEC2 | | |-- video_display // video display | | |-- video_encode_io // video encode using IVIDENC | | |-- video_encode_io1 // video encode using IVIDENC1 | | |-- video_encode_io_multich1 // multi channel video encode using IVIDENC1 | | |-- video_loopback // video loopback no copy | | |-- video_loopback_blend // video loopback and blend | | |-- video_loopback_convert // video loopback and color convert | | |-- video_loopback_copy // video loopback copy | | `-- video_loopback_resize // video loopback and resize | | | |-- bios // DSP/BIOS specific source | | | |-- ce // DMAI modules assisting CE usage source | | | |-- lib // Built DMAI libs are put here | | | |-- linux // linux specific source | | |-- dm355 // linux dm355 specific source | | |-- dm365 // linux dm365 specific source | | |-- dm6446 // linux dm6446 / dm357 specific source | | |-- dm6467 // linux dm6467 specific source | | |-- omap3530 // linux omap3530 specific source | | `-- priv // Private header files | | | |-- obj // Compiled object files are put here | |-- priv // Private header files | | | `-- wince // WinCE specific source | `-- wince_pb // WinCE platform builder root directory `-- wince600 // WinCE 6.0 platform builder support
DMAI depends on the Codec Engine OSAL (Operating System Abstraction Layer) . In order to use DMAI an application needs to have the following in it's <application>.cfg XDC configuration file (dm6467 remote linux osal configuration example):
prog.build.platform = "ti.platforms.evmDM6467"; var os = xdc.useModule('ti.sdo.ce.osal.linux.Settings'); osalGlobal.os = os; var ipc = xdc.useModule('ti.sdo.ce.ipc.Settings'); ipc.commType = ipc.COMM_DSPLINK; var DMAI = xdc.loadPackage('ti.sdo.dmai');
See the Codec Engine documentation on how to set up the osal for your platform configuration. The var DMAI assignment at the bottom is always the same, the correct library will be linked in automatically.
Each DMAI module is represented with a header file residing in the top level dmai directory. These module interface header files should be referenced in your app relative to the dmai_<version>/packages directory, e.g. to include the Buffer module you would put the following statement in your application C source file:
#include <ti/sdo/dmai/Buffer.h>
You only need to include the header file of the module you want to use; if a module depends on other DMAI modules or even device drivers or Codec Engine headers, it will include them as appropriate.
You should never reference any header files under any of the priv/ directories, as the headers and their contents are considered internal and may change at any time and your application may break.
All applications using DMAI modules need to call the Dmai_init
function which is defined in the Dmai module before using any other DMAI module API calls.
<module>_create
API call (e.g. Display_create
) to create this instance object. They also all have a <module>_delete
function call to delete any resources allocated by the create call (e.g. Display_delete
). The create call returns a handle with which the instance will be referred to during subsequent module API calls on this instance. No module APIs can of course be called on an instance handle before it is created, and no module API:S can be called on an instance handle after it has been deleted.
All modules with an instance object has an <module>_Attrs
data structure (e.g. Display_Attrs
) which is passed to the <module>_create
call (e.g. Display_create
). This attributes structure contains configuration parameters for the module which it uses to create the instance. All <module>_Attrs
structures have at least one set of defaults (e.g. Display_Attrs_DM6467_VID_DEFAULT
) . Some, like Display_Attrs
, have several sets of defaults to accomodate many typical configurations.
<module>_create
calls, but DMAI still provides defaults you should use.
Display_Handle hDisplay; Display_Attrs dAttrs = Display_Attrs_DM6467_VID_DEFAULT; dAttrs.numBufs = 2; hDisplay = Display_create(NULL, &dAttrs);
The above example will work even if more attributes are added to Display_Attrs
, since all values are assigned defaults before a value (Display_Attrs.numBufs
) is explicitly modified. By keeping the default behavior the same when adding new configuration parameters, upgrade pains can be kept to a minimum as long as this convention is followed.
To further future proof your application you should always use enum values and defines by their name and not their associated number or value. The value may change with new DMAI versions but the name will not (unless mentioned in the Davinci Multimedia Application Interface (DMAI) $versi.
DMAI comes with full source, partly for debugging purposes and as a reference, but also so that the user can recompile it with their own modifications.
There are two ways to build DMAI, either inside or outside the DVSDK for a particular target. Inside means DMAI is extracted inside the DVSDK directory, dvsdk_x_xx_xx_xx
, in which case DMAI will pick up the DVSDK Rules.make file and import the variables set there. For some targets it may be that DMAI needs variables set which are not set in the DVSDK Rules.make in which case they will have to be added. See the Davinci Multimedia Application Interface (DMAI) $versi for details for your particular target.
If the DVSDK already comes with a version of DMAI and you are upgrading, you will need to change the DMAI_INSTALL_DIR
variable in the DVSDK Rules.make file if you want e.g. the DVSDK demos to build using the upgraded DMAI (see Davinci Multimedia Application Interface (DMAI) $versi for compability information for your target).
make to
get a list of available build targets. If you want to compile for e.g. dm6467 ARM Linux, you would execute make dm6467_al
. Building outside the DVSDK allows building for multiple targets with no change to Rules.make.
There are two build configurations available, debug and release. When debug is selected, no compiler optimizations are performed and assertions are enabled. This allows you to catch additional errors while developing your application. For the release configuration assertions are disabled and compiler optimizations are enabled. You can select the build configuration using the BUILD_TYPE
flag (defaults to debug if not set). The same build configurations are available for the apps. E.g. to build dm6446 ARM Linux for release, execute:
make BUILD_TYPE=release dm6446_al
In addition, if you want to see how the build invokes the commands, you can enable verbose printing using the VERBOSE
flag. E.g. for the example above:
make BUILD_TYPE=release VERBOSE=true dm6446_al
There are two methods for building DMAI. Either as a WinCE platform builder subproject or from WinCE platform builder command line.
There are two build configurations available, debug and release. When debug is selected, no compiler optimizations are performed and assertions are enabled. This allows you to catch additional errors while developing your application. For the release configuration assertions are disabled and compiler optimizations are enabled. You can select the build configuration using the BUILD_TYPE
flag (defaults to debug if not set). The same build configurations are available for the apps. E.g. to build omap3530 ARM WinCE for release, execute:
gmake BUILD_TYPE=release o3530_aw
In addition, if you want to see how the build invokes the commands, you can enable verbose printing using the VERBOSE
flag. E.g. for the example above:
gmake BUILD_TYPE=release VERBOSE=true o3530_aw
DMAI consists of several modules which often are independent allowing the user to select where help is needed. E.g. one may want to handle the display device driver oneself but leave color conversion to DMAI, and as long as the Buffer module instances are filled in properly this is possible. Not all modules are supported on all platforms or on all OSes.
There are different types of DMAI modules:
VIDDEC_Handle
) can be obtained from the DMAI class allowing custom codec calls to be made outside the scope of DMAI There are also some miscellaneous support modules such as VideoStd, ColorSpace, Time, Ir, Cpu and the Dmai module itself.
The below diagram shows a source (Loader), CE processing (Vdec) and a sink (Display) module, and how they communicate using a Buffer_Handle:
Video decode
Sound_write
synchronous call is different from the above Display_get
and Display_put
asynchronous model:
Audio decode
Color conversion, Resizing and Video Encode
Buffer_getNumBytesUsed
and process this amount of bytes (as source or destination depending on which Buffer). This may or may not be the same as the size of the Buffer which can be retrieved using Buffer_getSize
.
When a source or processing module fills an output Buffer with data it will set the number of bytes used in the Buffer using Buffer_setNumBytesUsed
to tell the next module (or the application itself) accepting this Buffer how many bytes contain valid data. This of course needs to not excess the actual size of the Buffer which can be retrieved using Buffer_getSize
.
The BufferGfx module is a super class of the Buffer module, i.e. in an object oriented language the BufferGfx module would inherit the Buffer module. This means that each BufferGfx instance has all the properties of a Buffer instance and more; i.e. it has additional graphics properties (such as BufferGfx_Dimensions
and ColorSpace_Type
). This also means that any Buffer API calls can also be made on any BufferGfx module instance, and a BufTab operation also works on each type of Buffer. The base Buffer module instances are typically used for file I/O (using Loader or stdio) or Sound I/O. Note that both a Buffer and BufferGfx instance are referenced using a Buffer_Handle
.
Graphics Buffer dimensions
You can use the BufferGfx_getDimensions call to get the current dimensions and BufferGfx_setDimensions to set new dimensions in case you only want to process part of an image. You normally don't want to change the lineLength parameter.
For example, if you only want to color convert part of an input image you would call BufferGfx_setDimensions on the input buffer before the call to Ccv_execute. Likewise, if your output buffer is larger than the input buffer, you may want to position the result of the operation inside the output buffer by calling BufferGfx_setDimensions on the output buffer before calling Ccv_execute.
All BufferGfx instances get a dimension when they are created, and these original dimensions cannot be changed. Instead, a subwindow is recorded when BufferGfx_setDimensions is called, which will be returned by subsequent BufferGfx_getDimensions calls. If you want to restore the original dimensions you can use the BufferGfx_resetDimensions call.
It's good practice to always set (or reset) the dimensions of a graphics buffer before calling a graphics DMAI module function on a buffer. This way you avoid picking up unwanted dimensions from other processing calls in your application.
Note! Due to the design of XDM not all DMAI modules wrapping Codec Engine VISA modules set the lineLength correctly, since the frame pitch cannot be set on a per buffer basis. This can normally be set in the dynamic parameters of the XDM interface instead, make sure the codec supports this parameter.
A feature added in DMAI 1.16 is support for Buffer References. Before when a Buffer instance was created, it always allocated a buffer in memory for the Buffer instance, but there are cases when this is not desired.
E.g. if a buffer was allocated using a device driver or elsewhere in the system and this buffer is to be used by DMAI, a physical buffer should not be allocated. For this and other use cases, the Buffer Reference concept was introduced.
The Buffer_Attrs.reference flag indicates whether a buffer is a reference or not. If set to TRUE, no memory will be allocated for the Buffer instance. In addition, the API calls Buffer_setUserPtr and Buffer_setSize API calls were added to manipulate a Buffer Reference (note that these API calls do not work on a non-reference Buffer instance). The Buffer_isReference call can be used on a Buffer instance to determine if it's a reference or not.
DMAI Buffer Reference
Here's an example:
Buffer_Handle buffer; Buffer_Handle copyBuffer; Buffer_Attrs attrs; attrs = Buffer_Attrs_DEFAULT; buffer = Buffer_create(1024, &attrs); // creates a buffer object and an underlying data buffer of size 1024 attrs.reference = TRUE; copyBuffer = Buffer_create(Buffer_getSize(buffer), &attrs); // creates a Buffer reference for a memory area of size 1024 Buffer_setUserPtr(copyBuffer, Buffer_getUserPtr(buffer)); // makes this reference point to the existing 1024-byte data buffer //Buffer_setSize(copyBuffer, Buffer_getSize(buffer)); // can change the size to match the existing buffer if necessary Buffer_delete(copyBuffer); // deletes the reference. Will NOT deallocate the data buffer Buffer_delete(buffer); // deletes the original buffer object and deallocate its underlying storage.
This section discusses some ways of obtaining more information from your DMAI based application.
The DMAI modules have trace built in which can be enabled on Linux using the DMAI_DEBUG
environment variable. Setting it to '1' prints errors and warnings, while setting it to '2' prints errors, warnings and debug messages. If you have a target application myapp which uses DMAI you can set this environment variable for just one invocation of the command by executing the following on the target in the bash shell:
> DMAI_DEBUG=2 ./myapp
This will send the DMAI trace output to stdout.
This does not require a recompile of DMAI as trace is always built in.
There are two DMAI API calls added just to print out information about Buffer instances: Buffer_print
is on a per Buffer instance basis and BufTab_print
will print informations for all Buffers in a BufTab.
These functions are quite useful for tracking changes to Buffer state as a Buffer transitions through a system.
The packages/ti/sdo/dmai/apps
directory contains reference applications that use DMAI.
The header of each applications's main.c source file contains a brief description of what the application does.
Each application uses the XDC configuro tool for configuration of the Codec Engine, codecs, and to load support for DMAI. Loading support for DMAI means querying the DMAI XDC package for the appropriate library that should be linked in by the application to provide the DMAI API.
One or more *.cfg
files are present in each application directory to describe the corresponding application's configuration. The application Makefile will look for a [application]_[device].cfg file, and if it exists the application will be built for this device. For example, the Makefile will find
video_display_dm355.cfg
and determine that this application should be built for the dm355 target device.
When a *.cfg
file is not available for a specific device, the application was not validated on that device. In order to run the application on that device, a new *.cfg
should be created by copying and updating the *_[device].cfg
from a different application (for the same device). Make sure that the parameters passed in Engine.createFromServer()
or Engine.create()
are correctly updated.
All applications share the same Makefile in the packages/ti/sdo/dmai/apps/Makefile.app
file, and common configuration is kept in packages/ti/sdo/dmai/apps/app_common.cfg
.
An application will try to access the codecs referenced in the [application]_[device].cfg file along the paths defined by the
XDC_PATH
environment variable. If these codecs are not found a warning will be issued, but the building process will not fail. Most of the applications use codecs which are part of a DVSDK, however some may try to use codecs which are not included in a DVSDK.
Executing make
lists the available build targets.
Then, make [device target]
must be executed to build for a specific target, e.g. make dm6467_al
to build for ARM Linux on the dm6467 device and make dm6446_db
to build for DSP/BIOS on the dm6446 device.
Note! If an application fails to build because the configuration step cannot find the ti.sdo.dmai
package, make sure you have built DMAI itself for the build target.
Before running the application in a Linux environment, the necessary kernel modules must be loaded using the loadmodules.sh
script provided with the DVSDK.
The application executable must be loaded to the target. This can be achieved by manual copy or by executing make install
in the application directory.
If the application is using remote codecs the codec server files (ends with .x64P) must be loaded to the same directory as the application executables.
The usage for each application will be provided by invoking the -h
command-line option. Required parameters must be passed to the application.
Some applications (especially the ones using peripherals) have platform specific constraints. Read [application]/linux/main.c for more information.
DMAI debug trace can be enabled by setting the DMAI_DEBUG environment variable in Linux. Setting it to 1 corresponds to errors and warnings only, 2 corresponds to all trace (see 5.1 Enabling DMAI trace).
In order to run the DSP/BIOS applications, CCS 3.3 and a JTAG emulator are required.
In order to build the application for a specific platform, the [application]/bios directory must include a [application]_[device].cfg and a [application]_[device].tcf. For example, in order to run the audio_decode_io1 DSP/BIOS application on the dm6467 platform, the audio_decode_io1/bios directory must include the files audio_decode_io1_dm6467.cfg and audio_decode_io1_dm6467.tcf. If these files are not included, these files can be created by copying and renaming files existing for a different platform. After re-naming the files, the .tcf file does not require any changes but the .cfg file must be updated to reflect the codec package used. The names used for the engine and the codec must be used as arguments in the args.c file.
When using CCS, each platform requires specific GEL files which set up the memory map. CCS 3.3.81.5 includes the necessary GEL files. If the CCS used does not include the GEL files, download them from Spectrum Digital.
In order to connect the board to CCS an emulator is required. The emulator drivers must be installed before connecting the board to CCS.
Before using CCS, launch CCS Setup and select the Factory Board required by the platform and the emulator used. Right-click on the Processor and select Properties. If the GEL file is not associated with that processor, load the GEL file. After completing the Setup, launch CCS. On heterogenous platforms with ARM and DSP, you need to bring the DSP out of reset before you can connect to it via CCS:
DM6467 EVM
Before powering ON the board set SW3 Boot Mode Configuration switch to the No Boot position: SW3[4:1]=1111.
DM6446 EVM
Before powering ON the board set S3 Configuration switch to 0011111110. The steps for the DM6446 EVM are similar to the steps described above for DM6467 EVM: Connect to ARM, Release the DSP, Connect to DSP.
General
If you are running video applications that do file I/O (ie. all applications with names that end with _io), it is strongly recommended to download and install RTDX 2.10 or above from here.
This enhances CIO by making it up to 60 times faster. After installing it, you should perform the following:
In addition to the DMAI debug trace, it is also possible to enable in CCS the Codec Engine debug trace. See more details here Codec Engine FAQ.
The steps outlined in the WinCE build section will copy all the supported DMAI applications to WinCE release dir. Follow the BSP guidelines for loading the WinCE image to the platform. These sample applications use file-based input and output to perform encode or decode. Issue the desired commands shown below in the target control prompts provided in Visual Studio 2005 Professional Edition (with Windows Embedded CE with Platform Builder support installed). The test commands assume that media files are located in the _FLATRELEASEDIR% directory. In examples given below, this is /Release/data. Similarly output files are expected to be located in the _FLATRELEASEDIR% directory, which may be /Release/results. The output directory is assumed to exist for the output files to be created.
Test commands for DMAI decode applications
These examples are for Omap3530. Each processor type will have its similar executables containing processor name and the procedure to test will be similar. Certain features defined below may not be applicable to other chips. The following should be used as reference only.
To perform an H.264 decode of 50 frames of an H.264 elementary stream into UYVY packed RAW frames:
s video_decode_io2_omap3530 -c h264dec -i /Release/data/davincieffect_ntsc.264 -o /Release/results/davincieffect_ntsc.264.yuv -n 50
To perform an AAC decode of 200 frames of an AAC elementary stream into a PCM audio file:
s audio_decode_io1_omap3530 -c aachedec -i /Release/data/davincieffect.aac -o /Release/results/davincieffect.aac.pcm -n 200
To perform a JPEG decode of a JPEG image into a UYVY Packed RAW frame:
s image_decode_io1_omap3530 -c jpegdec -i /Release/data/fruitbasket_352x288_420p.jpg -o /Release/results/fruitbasket_352x288_420p.uyvy
To perform an MPEG2 decode of 50 frames of an MPEG2 elementary stream into UYVY packed RAW frames:
s video_decode_io2_omap3530 -c mpeg2dec -i /Release/data/davincieffect_cif.m2v -o /Release/results/davincieffect_cif.m2v.yuv -n 50
To perform a speech decode of 1000 speech frames from g.711 alaw format to 16 bit linear PCM format:
s speech_decode_io1_omap3530 -c g711dec -i /Release/data/sounds/davincieffect.g711 -o /Release/results/sounds/davincieffect.pcm --compandinglaw alaw -n 1000
Test commands for DMAI encode applications
To perform a JPEG encode of a UYVY packed RAW frame of resolution 720x480 into a JPEG image:
s image_encode_io1_omap3530 -c jpegenc -i /Release/data/fruitbasket_352x288_420p.uyvy -o /Release/results/fruitbasket_352x288_420p.jpg -r 352x288 --iColorSpace 3
To perform an H.264 encode of 50 UYVY packed RAW frames of resolution 720x480 into an H.264 elementary stream at a bitrate of 1 Mbps:
s video_encode_io1_omap3530 -c h264enc -i /Release/data/davincieffect_ntsc.264.uyvy -o /Release/results/davincieffect_ntsc.264 -r 720x480 -b 1000000 -n 50
To perform a speech encode of 1000 speech frames from 16bit linear PCM format to g.711 alaw format:
s speech_encode_io1_omap3530 -c g711enc -i /Release/data/sounds/davincieffect.pcm -o /Release/results/sounds/davincieffect.alaw --compandinglaw alaw -n 1000
If you want to create your own application using these applications as a reference, and want to put them in your own directory outside the DMAI directory structure, make sure the DMAI_INSTALL_DIR
variable is set correctly at the top of your Makefile. The DMAI application Makefile uses the top level Rules.make
to find the components it needs to build the application, and setting the DMAI_INSTALL_DIR
variable allows the Makefile to find this file.