Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

Overriding stubs and skeletons

From Texas Instruments Wiki
Jump to: navigation, search

This page is about overriding Codec Engine stubs and skeletons of an XDM algorithm.

Introduction

This topic deals with overriding stubs and skeletons used by a specific codec without modifying the functional definition of the XDM API. For more details about stubs and skeletons, including details about defining your own 'class' of algorithms that exposes a custom set of non-XDM APIs, refer to the CE Algorithm Producers Guide.

Overriding the stubs and skeleton used by a particular XDM codec is an advanced technique that a codec producer or an integrator could use for various purposes, such as:

  • To customize address translation and cache management for a specific codec. For example, if you extend the dynamic parameters of the control() function or the inArgs/outArgs structures of the process function with a pointer to a buffer, you can write your own address translation and cache management code for this buffer in customized stubs and skeleton.
  • To facilitate debugging. One can add code in stubs and skeletons to trap error conditions.
  • To add your own time benchmark functions (e.g. gettimeofday(), CLK_gethtime(), etc.) to benchmark the various parts of a given process()/control() call.

Keep in mind that in XDM, only the process() and control() functions go through the stubs and skeletons at run time. create() and delete() bypass them hence this technique does not apply to them.

One other reminder is that any code you put into stubs and skeletons is only run in situations where a codec is run remotely to the application (i.e. on a different CPU from the one where the application is run). So any pre-processing and post-processing apart from address translation and cache management is typically better handled in an adapter layer (see adapter app note), so that there is no dependency on whether a codec is run locally or remotely.

Procedure

It is suggested you start with the existing stubs and/or skeleton of the class of algorithm your codec belongs to from the <ce install directory>\packages\ti\sdo\ce\<class> directory:

  • audio encoder: use audenc_stubs.c and audenc_skel.c
  • audio decoder: use auddec_stubs.c and auddec_skel.c
  • video encoder: use videnc_stubs.c and viddec_skel.c
  • video1 encoder (XDM 1.0): use videnc1_stubs.c and videnc1_skel.c
  • video2 decoder (XDM 1.0): use viddec2_stubs.c and viddec2_skel.c

... etc.

The stubs and skeletons for all VISA classes are provided in CE 1.20 and above. If you are using older versions it is suggested that you upgrade to the latest version so that you obtain the bug fixes.

Copy the desired files and their associated header files (e.g. auddec.h and _auddec.h for audio decode) from the Codec Engine installation (under <codec_engine_install_dir>/packages/ti/sdo/ce/<class>/ directory) to your codec package directory (ideally under a ce/ directory if it exists). Modify the code to do what you want. If you want to print something to the CE trace, take a look at the Printing in stubs and skeletons topic.

NOTE - Of course, you need to be sure you're picking up the right stubs and skeletons! i.e. you need to know whether your codec is implementing IVIDDEC or IVIDDEC2. This wiki article shows you how to determine this.

Ensure you rename the stubs and skeleton function tables (e.g. AUDDEC_SKEL and AUDDEC_STUBS) to a new, unique name. The recommended format is <MODULE_NAME>_<VENDOR_NAME>_SKELFXNS and <MODULE_NAME>_<VENDOR_NAME>_STUBSFXNS. This is important as you don't want to replace the stubs and skeletons for other codecs in the system.

Example - mycodec/ce/auddec_stubs.c

// Stub function table
IAUDDEC_Fxns MYCODEC_MYCOMPANY_STUBSFXNS = {
    {&MYCODEC_MYCOMPANY_STUBSFXNS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
    process, control,
};

Example - mycodec/ce/auddec_skel.c

// Skeleton function table
SKEL_Fxns MYCODEC_MYCOMPANY_SKELFXNS = {
    call,
    (SKEL_CREATEFXN)&AUDDEC_create,
    (SKEL_DESTROYFXN)&AUDDEC_delete,
};

In ce/package.bld (or use the one in the base codec directory, if there is no 'ce' directory in the codec package) of the codec package, add the file(s) to create a library as follows:

var SRCS = ["auddec_skel.c", "auddec_stubs.c", ];  // Add your source files here
 
for (var i = 0; i < Build.targets.length; i++) {
    var targ = Build.targets[i];
 
    Pkg.addLibrary("lib/auddecskelstubs", targ, {  // Create a library with name auddecskelstubs.a<target>
        }).addObjects(SRCS);
}

If, for example, you are only interested in overriding the skeleton your package.bld should probably look something like this (example given for viddec2) :-

/*
 *  ======== package.bld ========
 */
 
Pkg.attrs.exportAll = true;
 
var SRCS = ["viddec2_skel.c", "viddec2.c" ];  // Add your source files here
 
for (var i = 0; i < Build.targets.length; i++) {
    var targ = Build.targets[i];
 
    if (targ.name == "C64P") {
        Pkg.addLibrary("lib/viddec2skelstubs", targ, {  // Create a library with name viddec2skelstubs.a<target>
           }).addObjects(SRCS);
    }
}

If a file named ce/package.xs already exists in the ce directory and has defined the libraries it returns using a getLibs() function (or in the case where there is no 'ce' directory in the codec package, if the package.xs file in the base codec directory has defined the libraries it returns), then you need to modify it to return the new library as well.

Example:

function getLibs(prog)
{
    /* name of stubs and skeleton library */
    var name = "lib/auddecskelstubs";
 
    /* setting up 'lib' to return libraries for this package */
    var lib;
    /* ... */
 
    /* append the library containing the stubs and skeleton to the list of libraries to be returned */
    lib = lib + ";" + name + ".a" + prog.build.target.suffix;
 
    print("    will link with: " + lib);
 
    return (lib);
}

If, for example, you are only interested in overriding the skeleton your package.xs should probably look something like this (example given for viddec2) :-

function getLibs(prog)
{
    /* name of stubs and skeleton library */
    var name = "lib/viddec2skelstubs";
 
    /* setting up 'lib' to return libraries for this package */
    var lib;
    /* ... */
 
    if (prog.build.target.isa == "64P") {
 
       /* append the library containing the stubs and skeleton to the list of libraries to be returned */
       lib = name + ".a" + prog.build.target.suffix;
 
       print("    will link with: " + lib);
    }
 
    return (lib);
}

In the ce\<module>.xdc file where you define the ialgFxns symbol, add the lines to bind the new stubs and/or skeleton function table symbols.

Example:

override readonly config String stubFxns = "MYCODEC_MYCOMPANY_STUBSFXNS";   //new stubs
override readonly config String serverFxns = "MYCODEC_MYCOMPANY_SKELFXNS"; //new skeleton

Rebuild the codec package. Now it is using the customized stubs and/or skeleton.

If you are only interested in overriding the stubs but not the skeletons (or vice-versa), simply leave out the line that overrides it, and omit the source file from the list of SRCS in the file ce/package.bld.

You can confirm that it worked by looking at the build log - you should see e.g. (example given for viddec2) :-

    will link with: lib/viddec2skelstubs.a64P

Pros and Cons

Pros and Cons of this technique when compared to writing a full extension package

Pros:

  • Can keep the same API as defined in XDM, with the exception of some parameter/argument structures that could potentially be extended
  • Restricted to be used by a particular codec package, hence no need to support it as a new 'class' of algorithms going forward

Cons:

  • Not as easily reusable by other codecs whereas an interface defined in an extension package can be easily 'inherited' by any codec.
  • Less flexible as it does not change the API.