This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Codec Engine Debugging in Linux

I have some codec engines that build for various targets. DM6446, DM6467, DM368 (DMVA2).

I have my build environment set up in Eclipse.

How can I create a codec engine server and app that uses the Linux86 library so that I can perform debugging inside Eclipse natively?

I looked at the servers in the codec engine examples directory but they seem geared to servers on TI hardware.

At the root of it I would like to be able to just run ./testapp at the Fedora/Ubuntu terminal and that testapp will start up my VIDANALYTICS codec, do a process call and then delete the codec.

How does a DMA call work on Linux86 through the framework components.  Does it just do a memcpy?

I found this in the codec server guide:

What About Single-Processor Systems?
On systems where there are no "remote" codecs, there is no need to configure a Codec Server.

Does this mean I can just call the codec from an application I write?

  • Matt,

    You can start by building the codec engine examples for Linux86.  In the <codec engine>/examples directory, there is a file called xdcpaths.mak.  (This is described in the build_instructions.html file too).  To build for Linux86, you need to set the following variables in xdcpaths.mak:

        DEVICES := X86

        PROGRAMS := APP_LOCAL

        GPPOS := LINUX_GCC

        CGTOOLS_LINUX86 := _your_Linux86_installation_directory  (for example, I have .../opensource/gcc/4.1.0/Linux/gcc-4.1.0-glibc-2.3.6/i686-unknown-linux-gnu)

    That should be it to get the examples building.  (See the instructions for building in build_instructions.html).

    The ACPY3 and DMAN3 libraries for Linux86 will just use CPU copy for the transfer.

    The 'local' apps (eg, app_local.x86U that should get built when you set the above variables in xdcpaths.mak), are for single processor systems.  If you want to build with debug, add these lines to your .cfg file:

        var ceSettings = xdc.useModule('ti.sdo.ce.global.Settings');
        ceSettings.profile = "debug";

    Then you should be able to step into your codec with gdb.

    Best regards,

        Janet

  • Hi Janet,

    I have written my own application that runs up my codecs in linux and I can step through my codec inside Eclipse.  It's bliss!  We have never set up a easy to use debugging environment before.

    However, I am having trouble with my configuration file.  If you could help me I would be very grateful!

    Currently I have this:

    // Set the OS abstraction layer to Linux
    var osalGlobal = xdc.useModule('ti.sdo.ce.osal.Global');
    osalGlobal.runtimeEnv = osalGlobal.LINUX;

    // Configure VCA core
    var VCA_CORE = xdc.useModule('udpanalytics.vca_core.VCA_CORE');

    // Configure VCA counting line
    var VCA_COUNTING_LINE = xdc.useModule('udpanalytics.vca_counting_line.VCA_COUNTING_LINE');

    // Configure VCA rules
    var VCA_RULES = xdc.useModule('udpanalytics.vca_rules.VCA_RULES');

    // Engine configuration
    var Engine = xdc.useModule('ti.sdo.ce.Engine');
    var myEngine = Engine.create("server", [
    {name: "vca_core", mod: VCA_CORE, local: true, groupId: 0},
    {name: "vca_counting_line", mod: VCA_COUNTING_LINE, local: true, groupId: 0},
    {name: "vca_rules", mod: VCA_RULES, local: true, groupId: 0}
    ]);

    Which got me going an building inside XDC.  Now I need to work out what Modules I need.  I getting segmentation faults in the framework components, which are entirely my fault for doing such a bad job at the .cfg!  I don't really know what all the modules do and what I need :(

    I figured that I needed the resource manger which lead me to include the algorithm module too:

    // Set up the algorithm module
    var ALG = xdc.useModule('ti.sdo.ce.alg.Settings');
    ALG.useHeap = true;
    ALG.useCache = true;

    // Set up the resource manager
    var RMAN = xdc.useModule('ti.sdo.fc.rman.RMAN');
    RMAN.useDSKT2 = false;
    RMAN.tableSize = 10;
    RMAN.persistentAllocFxn = "__ALG_allocMemory";
    RMAN.persistentFreeFxn = "__ALG_freeMemory";
    RMAN.semCreateFxn = "Sem_create";
    RMAN.semDeleteFxn = "Sem_delete";
    RMAN.semPendFxn = "Sem_pend";
    RMAN.semPostFxn = "Sem_post";

    This resulted in an undefined reference to DMAN3 stuff so I added that:

    // Set up the DMA manager
    var DMAN3 = xdc.useModule('ti.sdo.fc.dman3.DMAN3');
    DMAN3.heapInternal = "L1DHEAP";
    DMAN3.heapExternal = "DDRALGHEAP";
    DMAN3.idma3Internal = false;
    DMAN3.maxTCs = 4;
    DMAN3.paRamBaseIndex = 80; // 1st EDMA3 PaRAM set available for DMAN3
    DMAN3.numQdmaChannels = 8; // number of device's QDMA channels to use
    DMAN3.qdmaChannels = [0,1,2,3,4,5,6,7]; // choice of QDMA channels to use
    DMAN3.numPaRamEntries = 48; // number of PaRAM sets exclusively used by DMAN
    DMAN3.numPaRamGroup[0] = 48; // number of PaRAM sets for scratch group 0
    DMAN3.numTccGroup[0] = 32; // number of TCCs assigned to scratch group 0
    DMAN3.tccAllocationMaskL = 0; // bit mask indicating which TCCs 0..31 to use
    DMAN3.tccAllocationMaskH = 0xffffffff; // assign all TCCs 32..63 for DMAN

    I don't really know what all those settings mean at the moment, I just want to get going with out errors.  That compiled but I get segmentation fault:

    @0,258,306us: [+0 T:0xf777a6d0 S:0xff90f3b0] udpanalytics.vca_core.VCA_CORE - VCA_CORE_UDPANALYTICS_free(0x8a404a0, 0x8a40460)
    @0,258,330us: [+0 T:0xf777a6d0 S:0xff90f3c0] OM - Memory_free(0x8a404a0, 0x40)
    @0,258,353us: [+0 T:0xf777a6d0 S:0xff90f390] OM - Memory_segFree(0x0, 0x8a404a0, 0x40)
    @0,258,360us: [+0 T:0xf777a6d0 S:0xff90f3c0] OM - Memory_free(0x40, 0x50c)
    @0,258,366us: [+0 T:0xf777a6d0 S:0xff90f390] OM - Memory_segFree(0x0, 0x40, 0x50c)

    Now I'm thinking that looks like I've written my free function wrong, which is the same issue I was having with the codecs on our Linux MontaVista DMVA2 camera.  I'm really trying to get this PC Linux environment set up so I can debug this kind of stuff before we deploy onto our cameras.  I'm using the 2.25.03.07 framework components you suggested in the other thread I had going with you.

    Our codecs use the ACPY3 IDMA stuff, but I don't really know what to put in my .cfg file.  Could you suggest a .cfg setup that will work on PC Linux that will get my codecs up and running?

    These are all the framework components that are documented:

     

    • IALG - XDAIS Algorithm Interface
    • IDMA3 (C64P)
    • IRES
    • ACPY3 (C64P)
    • DMAN3
    • DSKT2
    • HDINTC
    • HDVICPSYNC
    • Resource manager interface
    • MEMUTILS
    • Resource Manager for IRES-based resources
    • DBC
    • VICPSYNC
    • Generic Trace Support
    • XDAIS Types and Constants
    • Ti_sdo_fc_ires_addrspace_IRESMAN_ADDRSPACE
    • IRES EDMA3 Protocol
    • IRESMAN EDMA3 -
    • IRES HDVICP Protocol
    • IRESMAN PROTOCOL - HDVICP
    • Ti_sdo_fc_ires_memtcm_IRESMAN_MEMTCM
    • IRES SDMA Protocol
    • IRESMAN SDMA -
    • Shared Memory Buffer Protocol
    • IRES VICP Protocol
    • IRES VICP Protocol
    • IRESMAN PROTOCOL - VICP
    • IRESMAN PROTOCOL - VICP
    • SCPY - Functional library for SDMA resources

    I'm not sure what I need to include and configure.

     

  • Hi Matt,

    I was able to build the codec engine example app, video1_copy, for Linux86 and using DMAN3/ACPY3.  I had to modify the package.bld to build for the Linux86 target by adding the 'PC' build to the line below (change marked in red):

            if ((platform.match(/DM6446|DM6467|DM355|DM365|PC/) &&
                    (targ.os == "Linux")) ||
                    targ.suffix.match("64")) {
                print("    app with local DMA-based codecs");
                addExe(targ, platform, "local_dma");
            }

    If you look at the local_dma.cfg file, you will see that there appears to be no DMAN3 configuration.  The relevant lines for Linux are these:

    /* use an osal.  osalGlobal is configured below, based on target. */
    var osalGlobal = xdc.useModule('ti.sdo.ce.osal.Global');

    /* get various codec modules; i.e., implementation of codecs */
    var decoder =    xdc.useModule('ti.sdo.ce.examples.codecs.viddec1_copy.VIDDEC1_COPY');
    var encoder =    xdc.useModule('ti.sdo.ce.examples.codecs.videnc1_copy.VIDENC1_COPY');

    /* Enable VIDENC1_COPY codec's DMA support */
    encoder.alg.useDMA = true;

    osalGlobal.runtimeEnv = osalGlobal.LINUX;

    /*
     *  ======== Engine Configuration ========
     */
    var Engine = xdc.useModule('ti.sdo.ce.Engine');
    var myEngine = Engine.create("video1_copy", [
        {
            name : "viddec1_copy",
            mod  : decoder,
            local: true
        },
        {
            name : "videnc1_copy",
            mod  : encoder,
            local: true
        }
    ]);

    The line "encoder.alg.useDMA = true" causes the ACPY3 module to be pulled in (xdc.useModule('ti.sdo.fc.acpy3.ACPY3'), and the DMA version of the codec library to be used. (We build two versions of the videnc1_copy codec, one with dma and one without).  You can find the videnc1_copy algorithm code in:

        <codec_engine_install_dir>examples/ti/xdais/dm/videnc1_copy/

    Now, if you look in examples/ti/sdo/ce/codecs/videnc1_copy/VIDENC1_COPY.xdc, you see the line:

        override readonly config String idma3Fxns = "VIDENC1COPY_TI_IDMA3";

    When the video1_copy example is built, the configuration process checks for codecs that have non-null idma3Fxns, and if one is found, DMAN3 and ACPY3 will be pulled into the build automatically.  In your case, if your codec is using ACPY3, you just need to have 'xdc.useModule('ti.sdo.fc.acpy3.ACPY3')' in the codec package.xs close() function, and you need to set the idma3Fxns.  I'm sure you are already doing this.

    For RMAN configuration, I think you should be able to get by with just the following configuration:

        /* No DSKT2 on Linux, so need to use the non-default config */
        RMAN.useDSKT2 = false;
        RMAN.persistentAllocFxn = "__ALG_allocMemory";
        RMAN.persistentFreeFxn = "__ALG_freeMemory";

    Can you start with these minimal configurations and see what happens?

    Regards,

        Janet

     

     

  • I do pull the ACPY3 library in, in my package.xs close() method.

    Doesn't look like DMAN3 is pulled in automatically:

    function `Algorithm_init':
    Algorithm_noOS.c:(.text+0x76): undefined reference to `DMAN3_CE_init'
    /home/matt/svn/ipx/ipnc_sdk/IPNC_SDK-OV2715_V2.0/Application/src/dvsdk_2_10_01_18/codec_engine_2_24/packages/ti/sdo/ce/alg/lib/release/Algorithm_noOS.a86U(Algorithm_noOS.o86U): In function `Algorithm_exit':
    Algorithm_noOS.c:(.text+0xd3): undefined reference to `DMAN3_CE_exit'

    So I added:

    var DMAN3 = xdc.useModule('ti.sdo.fc.dman3.DMAN3');

    Do I need to set anything up for that?

    This seems to be working.  However, I know have the segmentation fault that was occuring on my DMVA2 camera.  I thought this was solved with the update to the framework components.  Running it on native linux I can step.

    My IALG free functions looks like this:

    Int VCA_COUNTING_LINE_UDPANALYTICS_free(IALG_Handle handle, IALG_MemRec memTab[])
    {
        VCA_COUNTING_LINE_UDPANALYTICS_Obj *pVcaObj = (VCA_COUNTING_LINE_UDPANALYTICS_Obj*)handle;

        // Function enter tracing statement
        UTILS_trace(pVcaObj->traceHandle, UTILS_TRACE_ENTER, "%s(%08p, %08p)\n", __func__, handle, memTab);

        // Fill the memory table
        return VCA_COUNTING_LINE_UDPANALYTICS_alloc((IALG_Params*)((void*)&(pVcaObj->algParams)), NULL, memTab);
    }

    We store the algorithm parameters that were given at create time, these are used to fill out the memory table exactly as it was filled out in the allocation stage of the algorithm.

    @20,571,061us: [+0 T:0xf7fe36d0 S:0xffffce90] udpanalytics.vca_counting_line.VCA_COUNTING_LINE - VCA_COUNTING_LINE_UDPANALYTICS_free(0x8067480, 0x8067e78)
    @28,611,336us: [+0 T:0xf7fe36d0 S:0xffffceb0] OM - Memory_free(0x8067480, 0x90)
    @28,611,365us: [+0 T:0xf7fe36d0 S:0xffffce80] OM - Memory_segFree(0x0, 0x8067480, 0x90)
    @28,611,376us: [+0 T:0xf7fe36d0 S:0xffffceb0] OM - Memory_free(0x1, 0x50c)
    @28,611,383us: [+0 T:0xf7fe36d0 S:0xffffce80] OM - Memory_segFree(0x0, 0x1, 0x50c)

    I read the documentation for the IALG free function and it says:

    Postcondition:
    memTab[] contains pointers to all of the memory passed to the algorithm via algInit().

    So does this mean that I have to fill out the pointers memTab[].base addresses?  I have stored the memory table in my algorithm context so could just copy the structure back?

    The above code follows the video_copy example (but passing back the algorithm parameters):

    /*
    * ======== VIDDECCOPY_TI_free ========
    */
    Int VIDDECCOPY_TI_free(IALG_Handle handle, IALG_MemRec memTab[])
    {
        GT_2trace(curTrace, GT_ENTER, "VIDDECCOPY_TI_free(0x%lx, 0x%lx)\n",handle, memTab);

        VIDDECCOPY_TI_alloc(NULL, NULL, memTab);
        return (1);
    }

    I don't understand what the framework is trying to free the bogus pointers on Linux?

    Matt

     

  • Matt,

    I'm not sure why you're getting the undefined DMAN3_CE_init() when you don't have the DMAN3 config in your .cfg, but since adding it to the .cfg solves the problem, that seems to be the best solution.

    For your codec's 'free' function, you do need to set the base addresses in the memTab array.  I see that the memTab[0].base is filled in with the object's address by the framework in ALG_delete().  The codec engine examples are so simple that they only have memTab[0] to be freed, so you don't see the general case, unfortunately.

    Here is another example of a 'free' function:

    /*
     *  ======== FIR_TI_free ========
     */
    Int FIR_TI_free(IALG_Handle handle, IALG_MemRec memTab[])
    {
        FIR_TI_Obj *fir = (Void *)handle;

        FIR_TI_alloc(NULL, NULL, memTab);

        memTab[0].base = handle;
       
        memTab[HISTORY].base = fir->history;
        memTab[HISTORY].size = fir->filterLenM1 * sizeof(Int);

        memTab[WORKBUF].size =  (fir->filterLenM1 + fir->frameLen) * sizeof(Int);
        memTab[WORKBUF].base = fir->workBuf;

        return (NUMBUFS);
    }


    The call to FIR_TI_alloc() is filling in memTab[] with memory spaces, sizes, and alignments.  Then the base addresses and sizes are set (not sure why the sizes are being set again).

    Best regards,

        Janet

     

     

  • That fixes the segmentation fault.  We'd implemented the IALG_free() function incorrectly.  I just store the given memory table in IALG_init() and pass it back in IALG_free()

    It's not obvious from the examples that this needs to be done because, as you said, they mostly only use one memory table segment.

    Thanks for the help Janet!

  • Great!  I'm glad to hear you solved that problem.

    Best regards,

        Janet