Extending data structures in XDM

From Texas Instruments Embedded Processors Wiki

Jump to: navigation, search
Translate this page to   

Contents

Overview

In XDM, structures such as codec creation's *_Params, process()'s *_InArgs and *_OutArgs, and control()'s *_DynamicParams and *_Status are all extensible, meaning users can redefine the structure to include additional fields beyond the base ones. To support this extensibility, XDM structures contain size as its first field. This field is used:

The advantage of support for extensions is:

The disadvantages are:

Example

Given a base parameter structure:

typedef struct IVIDDEC_DynamicParams {
    XDAS_Int32 size;            
    XDAS_Int32 decodeHeader;    
    XDAS_Int32 displayWidth;    
    XDAS_Int32 frameSkipMode; 
} IVIDDEC_DynamicParams;

We can extend it with new fields as follows:

typedef struct MYIVIDDEC_DynamicParams {
    IVIDDEC_DynamicParams base;
    XDAS_Int32 newField1;
    XDAS_Int32 newField2;
} MYIVIDDEC_DynamicParams;

When using this new structure, we need to ensure that base.size field is set to the size of the extended structure to ensure correct operation in frameworks (e.g. Codec Engine):

MYIVIDDEC_DynamicParams dParams;
 
    dParams.base.size = sizeof(MYIVIDDEC_DynamicParams);   // Must be set to size of extended structure
    dParams.base.displayWidth = 1024;
    dParams.newField1 = 13;
    ...
 
    /* If using Codec Engine, API call might look like this.  Note the cast */
    VIDDEC_control(handle, id, (VIDDEC_DynamicParams *)&dParams, &status);

Constraints

typedef struct MYIVIDDEC_DynamicParams {
    IVIDDEC_DynamicParams base;
    XDAS_Int32 newField1;
    XDAS_Int16 newField2;
    XDAS_Int16 padding;  // Needed for 32-bit alignment
} MYIVIDDEC_DynamicParams;
/*
 * Increase the size of messages from the default 4kB to 8kB.  To keep the same memory
 * map, we also halve the number of messages from the default 64 to 32.
 */
var osalGlobal = xdc.useModule('ti.sdo.ce.osal.Global');
osalGlobal.armCommMsgSize = 8 * 1024;  // use 8 kB msgs rather than the default 4kB
osalGlobal.armCommNumMsgs = 32;   // create 32 msgs rather than the default 64

Naming Conventions

Because anyone can extend these XDM structs, it's important to attempt to define some conventions on the names of the extended fields. This enables integrators using many different codecs to not have to wonder whether the extended field is .MyField or .myfield or .MYFIELD. This section describes guidelines for naming extended structs.

Naming Conventions
Convention Examples
Field names begin with a lowercase letter. Camel case is used where needed to delimit multiword names. myExtendedField
Fields that indicate boolean flags end with the word "Flag" and are documented to accept XDAS_TRUE or XDAS_FALSE. enableMyFeatureFlag

Distribution

Because these extended structs are codec-specific, they should be provided with the codec, and included in the codec's documentation. Typically, this involves simply adding a header with these definitions in the codec's package.

Notes

The perils of extending inArgs, outArgs

As noted above there are (at least) two ways to extend XDM / VISA interfaces. Extending via dynamic params is fine - for example on DM6467 we do the following: - (code snippet at time of DM6467 Beta)

/* Use extended dynamic parameters to allow tweaking of the QP value */
    IH264VENC_DynamicParams extDynParams = {
        Venc1_DynamicParams_DEFAULT,
        0,    /* ChromaQPOffset */
        18,   /* QPISlice */
        20,   /* QPSlice */
        0,    /* LfDisableIdc */
        0,    /* LFAlphaC0Offset */
        0,    /* LFBetaOffset */
        0,    /* LFParametersFlag */
        51,   /* RateCtrlQpMax */
        0,    /* RateCtrlQpMin */
        0,
    };
 
....
....
 
    extDynParams.videncDynamicParams.size = sizeof(IH264VENC_DynamicParams);
    extDynParams.videncDynamicParams.targetBitRate = params.maxBitRate;
    extDynParams.videncDynamicParams.inputWidth = params.maxWidth;
    extDynParams.videncDynamicParams.inputHeight = params.maxHeight;
 
    /* Create the video encoder */
    hVe1 = Venc1_create(hEngine, "h264enc", &params,
                        (VIDENC1_DynamicParams *) &extDynParams);

Observe that we're calling a generic API, Venc1_create() - there's nothing specific to H264 encode. The only thing we're doing is extending the data fields, in this case mainly to tweak the Quality Parameters (QPISlice, QPSlice). No logic in the code changes.

Now look at what we have to do (again as of DM6467 Beta) for AAC High End Encode.

Int Aac_process(Aenc_Handle hAe, Buffer_Handle hInBuf, Buffer_Handle hOutBuf)
{
    XDAS_Int32              inBufSizeArray[1];
    XDAS_Int32              outBufSizeArray[1];
    XDM_BufDesc             inBufDesc;
    XDM_BufDesc             outBufDesc;
    XDAS_Int32              status;
    IAACENC_InArgs          inArgs;
    IAACENC_OutArgs         outArgs;
    XDAS_Int8              *inPtr;
    XDAS_Int8              *outPtr;
 
    inPtr                   = Buffer_getUserPtr(hInBuf);
    outPtr                  = Buffer_getUserPtr(hOutBuf);
 
    inBufSizeArray[0]       = Buffer_getNumBytesUsed(hInBuf);
    outBufSizeArray[0]      = Buffer_getSize(hOutBuf);
 
    inBufDesc.bufSizes      = inBufSizeArray;
    inBufDesc.bufs          = &inPtr;
    inBufDesc.numBufs       = 1;
 
    outBufDesc.bufSizes     = outBufSizeArray;
    outBufDesc.bufs         = &outPtr;
    outBufDesc.numBufs      = 1;
 
    outArgs.audenc_outArgs.size = sizeof(IAACENC_OutArgs);
 
    /* Special AAC inArgs needed, hence custom Aac_process() required */
    inArgs.audenc_inArgs.size   = sizeof(IAACENC_InArgs);
    inArgs.numAncBytes          = 0;
    inArgs.ancData              = NULL;
 
    /* Stereo 16-bit */
    inArgs.numInSamples         = Buffer_getNumBytesUsed(hInBuf) / 4;
 
    /* Encode the audio buffer */
    status = AUDENC_process(Aenc_getVisaHandle(hAe), &inBufDesc, &outBufDesc,
                            (AUDENC_InArgs *) &inArgs,
                            (AUDENC_OutArgs *) &outArgs);

That's completely different from the extended parameters scenario - we now have Aac_process() instead of just AUDENC_process() (or Aenc_process() to be analogous with naming convention in previous h264 scenario). This is because this particular codec implementation requires inArgs.numInSamples to be buffer size / 4 (the 4 is number of channels * number of bytes per sample). That difference is not comprehended in the AUDENC XDM 0.9 interface.

What would happen if we now added another Audio Encoder that customized inArgs/outArgs? We'd inevitably have to load up the code with ugly #ifdef AACENC #else guards. Worse still there's no plug and play - we couldn't swap out one vendor's AACENC for another since the extensions are, by definition, custom.

All applications (not just the DVSDK demos) suffer - TI's Digital Video Test Bench (DVTB) copies all of the header constants and structures from the AAC Encoder (as of DM6467 Beta) into its application file dvevmStAACEnc.h, in order to 'see' the extensions - this results in increased maintenance.

The good news in the above case is that it may be possible in future to use 'normal VISA' because the number of channels is passed in through AUDENC_DynamicParams.numChannels, and the number of bytes per sample can be derived from AUDENC_DynamicParams.inputBitsPerSample. This is being considered.

However, the custom code logic above clearly shows that inArgs/outArgs extensions equals custom application code which defeats the original intent of the VISA APIs. You simply cannot write generic application code in such cases.

If you believe you need such extensions we strongly encourage you to look at the newer XDM interfaces - perhaps AUDENC1 or VIDDEC2 solves the problem. This XDM FAQ article shows some XDM version details.

If after that, you still believe you need to extend inArgs/outArgs, please make sure you supply test cases that clearly exercise all of the extended modes - this is essential because test suites such as the DVTB will not be able to find problems in this area. Make sure such modes also get tested from an Arm-side application on an SoC platform so that any corner cases with cache-management (see above re address translation etc) are caught.

In summary, extending interfaces via DynamicParams is fine, however doing so via inArgs/outArgs requires custom application logic and is strongly discouraged.

Leave a Comment
Personal tools
Namespaces
Variants
Actions
Navigation
Print/export
Toolbox