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.

TDA2EVM5777: XDM_INSUFFICIENTDATA at Process() of IVA-HD MPEG4 Encoder

Part Number: TDA2EVM5777


Hi All,
I am working on TDA2x with ARM having Linux Distribution generated from Arago. I have generated a custom firmware for IPU2 core with reference from IPUMM firmware. I am able to load all the binaries of CODEC in firmware generation. Also I am able to create and control the MPEG-4 encoder. As I liked to start humble, all my parameter setting and IO buffers creation and handling are within IPU2 core. My final goal is to use a custom application from ARM to pass on details to IPU2 to launch the IVAHD encoder.

In the process stage, I am facing XDM_INSUFFICIENTDATA error(bit 10 of extended error). I have tried creating IO buffers with malloc, Memory_Alloc and global buffers. But all has the same issue. Kindly help me to solve this error.

Some code snippets are below(I have used omapdrmtest application for encoder as reference):

static void init_common_static_params(encoder *enc)
{
    VIDENC2_Params *params = enc->params;
    params->encodingPreset = XDM_USER_DEFINED; //XDM_USER_DEFINED; //XDM_EncodingPreset
    params->rateControlPreset = IVIDEO_USER_DEFINED;
    params->maxHeight = 480;
    params->maxWidth = 720;
    params->dataEndianness = XDM_BYTE; //XDM_DataFormat
    params->maxBitRate = -1; //IGNORED
    params->minBitRate = 0;
    params->inputChromaFormat = XDM_YUV_420SP; //XDM_ChromaFormat
    params->inputContentType = IVIDEO_PROGRESSIVE; //IVIDEO_ContentType
    params->operatingMode = IVIDEO_ENCODE_ONLY; //IVIDEO_OperatingMode
    params->profile = 3;
    params->level = 6;
    params->inputDataMode = IVIDEO_ENTIREFRAME; //IVIDEO_DataMode
    params->outputDataMode = IVIDEO_ENTIREFRAME; //IVIDEO_DataMode
    params->numInputDataUnits = 1;
    params->numOutputDataUnits = 1;
    params->metadataType[0] = IVIDEO_METADATAPLANE_NONE;
    params->metadataType[1] = IVIDEO_METADATAPLANE_NONE;
    params->metadataType[2] = IVIDEO_METADATAPLANE_NONE;
    return;
}

static int init_mpeg4_static_params(encoder *enc)
{
    IMPEG4ENC_Params *mpeg4enc_params = NULL;
    enc->inArgs = (VIDENC2_InArgs*)malloc(sizeof(IMPEG4ENC_InArgs));
    if (!enc->inArgs) goto bail;
    enc->inArgs->size = sizeof(IMPEG4ENC_InArgs);

    enc->outArgs = (VIDENC2_OutArgs*)malloc(sizeof(IMPEG4ENC_OutArgs));
    if(!enc->outArgs) goto bail;
    enc->outArgs->size = sizeof (IMPEG4ENC_OutArgs);
    enc->mpeg4enc_outArgs = (IMPEG4ENC_OutArgs *) enc->outArgs;

    enc->params = (VIDENC2_Params*)malloc(sizeof(IMPEG4ENC_Params));
    if(!enc->params) goto bail;
    enc->params->size = sizeof(IMPEG4ENC_Params);

    init_common_static_params(enc);

    enc->params->maxInterFrameInterval = 0;
    mpeg4enc_params = enc->mpeg4enc_params = (IMPEG4ENC_Params *) enc->params;

    mpeg4enc_params->useDataPartitioning = 0;
    mpeg4enc_params->useRvlc = 0;
    if (CODEC == H263) {
        mpeg4enc_params->useShortVideoHeader = 1;
    }
    else {
        mpeg4enc_params->useShortVideoHeader = 0;
    }

    mpeg4enc_params->vopTimeIncrementResolution = 30;
    mpeg4enc_params->nonMultiple16RefPadMethod = IMPEG4_PAD_METHOD_MPEG4;
    mpeg4enc_params->pixelRange = IMPEG4ENC_PR_0_255;
    mpeg4enc_params->enableSceneChangeAlgo = IMPEG4ENC_SCDA_DISABLE;
    mpeg4enc_params->useVOS = 0;
    mpeg4enc_params->enableMONA = 0;
    mpeg4enc_params->enableAnalyticinfo = -1;
    mpeg4enc_params->debugTraceLevel = 0;
    mpeg4enc_params->lastNFramesToLog = 0;

        // IMPEG4ENC_RateControlParams
    mpeg4enc_params->rateControlParams.rateControlParamsPreset = IMPEG4_RATECONTROLPARAMS_DEFAULT;
    mpeg4enc_params->rateControlParams.rcAlgo = IMPEG4_RATECONTROLALGO_VBR;
    mpeg4enc_params->rateControlParams.qpI = 5;
    mpeg4enc_params->rateControlParams.qpP = 5;
    mpeg4enc_params->rateControlParams.seIntialQP = 5;
    mpeg4enc_params->rateControlParams.qpMax = 31;
    mpeg4enc_params->rateControlParams.qpMin = 1;
    mpeg4enc_params->rateControlParams.enablePerceptualQuantMode = 0;
    mpeg4enc_params->rateControlParams.allowFrameSkip = 0;
    mpeg4enc_params->rateControlParams.initialBufferLevel = 0;
    mpeg4enc_params->rateControlParams.vbvBufferSize = 0;
    mpeg4enc_params->rateControlParams.qpMinIntra = 0;

    // IMPEG4ENC_InterCodingParams
    mpeg4enc_params->interCodingParams.interCodingPreset = IMPEG4_INTERCODING_DEFAULT;
    mpeg4enc_params->interCodingParams.searchRangeHorP = 144;
    mpeg4enc_params->interCodingParams.searchRangeVerP = 32;
    mpeg4enc_params->interCodingParams.globalOffsetME = 1;
    mpeg4enc_params->interCodingParams.earlySkipThreshold = 200;
    mpeg4enc_params->interCodingParams.enableThresholdingMethod = 1;
    mpeg4enc_params->interCodingParams.minBlockSizeP = IMPEG4_BLOCKSIZE_8x8;
    mpeg4enc_params->interCodingParams.enableRoundingControl = 1;

    // IMPEG4ENC_IntraCodingParams
    mpeg4enc_params->intraCodingParams.intraCodingPreset = IMPEG4_INTRACODING_DEFAULT;
    mpeg4enc_params->intraCodingParams.intraRefreshMethod = 0;
    mpeg4enc_params->intraCodingParams.intraRefreshRate = 0;
    mpeg4enc_params->intraCodingParams.acpredEnable = 1;
    mpeg4enc_params->intraCodingParams.insertGOVHdrBeforeIframe = 0;
    mpeg4enc_params->intraCodingParams.enableDriftControl = 1;

    // IMPEG4ENC_sliceCodingParams
    mpeg4enc_params->sliceCodingParams.sliceCodingPreset = IMPEG4_SLICECODING_DEFAULT;
    mpeg4enc_params->sliceCodingParams.sliceMode = IMPEG4_SLICEMODE_NONE;
    mpeg4enc_params->sliceCodingParams.sliceUnitSize = 0;
    mpeg4enc_params->sliceCodingParams.gobInterval = 0;
    mpeg4enc_params->sliceCodingParams.useHec = 0;

    MSG("alloc VIDENC2_Params successful mpeg4enc_params=%p", mpeg4enc_params);
    enc->codec = VIDENC2_create(enc->engine, (String)"ivahd_mpeg4enc", (VIDENC2_Params *)mpeg4enc_params);
    if(!enc->codec){
        MSG("Codec could not be created %p\n", enc->codec);
        goto bail;
    }
    return 0;
bail:
    encoder_deinit(enc);
    return -1;
}

static void set_common_dyn_params(encoder *enc)
{
    VIDENC2_DynamicParams *dynParams = enc->dynParams;
    dynParams->inputHeight = enc->height;
    dynParams->inputWidth = enc->width;
    dynParams->refFrameRate = enc->fps * 1000; // refFrameRate in fps * 1000
    dynParams->targetFrameRate= enc->fps * 1000; // Target frame rate in fps * 1000
    dynParams->targetBitRate = enc->bps;
    MSG("targetFramerate = %d, targetbitrate = %d\n", dynParams->targetFrameRate, dynParams->targetBitRate);
    dynParams->intraFrameInterval = 30; //Only 1st frame to be intra frame (I-frame)
    dynParams->generateHeader = XDM_ENCODE_AU;
    dynParams->captureWidth = enc->width;
    dynParams->forceFrame = IVIDEO_NA_FRAME;
    dynParams->sampleAspectRatioHeight = 1;
    dynParams->sampleAspectRatioWidth = 1;
    dynParams->ignoreOutbufSizeFlag = XDAS_FALSE; // If this is XDAS_TRUE then getBufferFxn and getBufferHandle needs to be set.
    dynParams->putDataFxn = NULL;
    dynParams->putDataHandle = NULL;
    dynParams->getDataFxn = NULL;
    dynParams->getDataHandle = NULL;
    dynParams->getBufferFxn = NULL;
    dynParams->getBufferHandle = NULL;
    dynParams->lateAcquireArg = -1;
    return;

}

static int init_mpeg4_dyn_params(encoder *enc)
{
    VIDENC2_DynamicParams   *dynParams = NULL;
    XDAS_Int32 err;
    IMPEG4ENC_DynamicParams *mpeg4enc_dynParams;
    dynParams = enc->dynParams = (VIDENC2_DynamicParams*)malloc(sizeof(IMPEG4ENC_DynamicParams));
    if(!enc->dynParams) goto bail;
    enc->dynParams->size = sizeof(IMPEG4ENC_DynamicParams);
    MSG("alloc dynParams successful dynParams=%p size=%d", enc->dynParams, enc->dynParams->size);
    set_common_dyn_params(enc);
    dynParams->interFrameInterval = 0;
    dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_HALFPEL;
    mpeg4enc_dynParams = (IMPEG4ENC_DynamicParams *) dynParams;
    mpeg4enc_dynParams->aspectRatioIdc = IMPEG4ENC_ASPECTRATIO_SQUARE;
     
// IMPEG4ENC_RateControlParams
    memcpy(&mpeg4enc_dynParams->rateControlParams, &(enc->mpeg4enc_params->rateControlParams), sizeof(IMPEG4ENC_RateControlParams));
    // IMPEG4ENC_InterCodingParams
    memcpy(&mpeg4enc_dynParams->interCodingParams, &(enc->mpeg4enc_params->interCodingParams), sizeof(IMPEG4ENC_InterCodingParams));
    // IMPEG4ENC_sliceCodingParams
    memcpy(&mpeg4enc_dynParams->sliceCodingParams, &(enc->mpeg4enc_params->sliceCodingParams), sizeof(IMPEG4ENC_sliceCodingParams));
    enc->mpeg4enc_status = (IMPEG4ENC_Status*)malloc(sizeof(IMPEG4ENC_Status));
    if(!enc->mpeg4enc_status) goto bail;
    ((VIDENC2_Status *)(enc->mpeg4enc_status))->size = sizeof(IMPEG4ENC_Status);
    err = VIDENC2_control(enc->codec, XDM_SETPARAMS, (VIDENC2_DynamicParams *) mpeg4enc_dynParams, (VIDENC2_Status *) (enc->mpeg4enc_status));
    if(err){
        MSG("Codec_control returned err=%d, extendedError=%08x", err, enc->mpeg4enc_status->videnc2Status.extendedError);
        goto bail;
    }
    return 0;
bail:
    encoder_deinit(enc);
    return -1;

}

Output Buffer Creation:
#define GET_PHY_ADDRESS MEMUTILS_getPhysicalAddr


    enc->outBufs->descs[0].memType = XDM_MEMTYPE_RAW;
    enc->outBufs->descs[0].bufSize.bytes = enc->width * enc->height * 2;
#if USE_GLOBAL_MEMORY
    enc->outBufs->descs[0].buf = outBuf;
    enc->outBufs->descs[0].buf = GET_PHY_ADDRESS(outBuf);
#elif USE_MALLOC
    enc->outBufs->descs[0].buf = (XDAS_Int8 *)malloc(enc->width * enc->height * 2);
    enc->outBufs->descs[0].buf = GET_PHY_ADDRESS(enc->outBufs->descs[0].buf);
#else
    Memory_AllocParams alc_params = Memory_DEFAULTPARAMS;
    alc_params.type = ti_sdo_ce_osal_Memory_CONTIGHEAP;
    alc_params.flags = ti_sdo_ce_osal_Memory_CACHED;
    enc->outBufs->descs[0].buf = (XDAS_Int8 *)ti_sdo_ce_osal_Memory_alloc(enc->width * enc->height * 2, &alc_params);
    enc->outBufs->descs[0].buf = GET_PHY_ADDRESS(enc->outBufs->descs[0].buf);
#endif

Input Buffer Creation:
#if USE_GLOBAL_MEMORY
    enc->inBufs->planeDesc[0].buf = yBuf;
    enc->inBufs->planeDesc[1].buf = uvBuf;
    enc->inBufs->planeDesc[0].buf = GET_PHY_ADDRESS(yBuf);
    enc->inBufs->planeDesc[1].buf = GET_PHY_ADDRESS(uvBuf);
#elif USE_MALLOC
    enc->inBufs->planeDesc[0].buf = (XDAS_Int8 *)malloc(enc->width * enc->height);
    enc->inBufs->planeDesc[1].buf = (XDAS_Int8 *)malloc(enc->width * enc->height);
    enc->inBufs->planeDesc[0].buf = GET_PHY_ADDRESS(enc->inBufs->planeDesc[0].buf);
    enc->inBufs->planeDesc[1].buf = GET_PHY_ADDRESS(enc->inBufs->planeDesc[1].buf);
#else
    enc->inBufs->planeDesc[0].buf = (XDAS_Int8 *)ti_sdo_ce_osal_Memory_alloc(enc->width * enc->height, &alc_params);
    enc->inBufs->planeDesc[1].buf = (XDAS_Int8 *)ti_sdo_ce_osal_Memory_alloc(enc->width * enc->height, &alc_params);
    enc->inBufs->planeDesc[0].buf = GET_PHY_ADDRESS(enc->inBufs->planeDesc[0].buf);
    enc->inBufs->planeDesc[1].buf = GET_PHY_ADDRESS(enc->inBufs->planeDesc[1].buf);
#endif

Creation of MPEG4 Encoder (Successful):
    enc->codec = VIDENC2_create(enc->engine, (String)"ivahd_mpeg4enc", (VIDENC2_Params *)mpeg4enc_params);

Control of MPEG4 Encoder (Successful):
    err = VIDENC2_control(enc->codec, XDM_SETPARAMS, (VIDENC2_DynamicParams *) mpeg4enc_dynParams, (VIDENC2_Status *) (enc->mpeg4enc_status));
   
    err = VIDENC2_control(enc->codec, XDM_GETBUFINFO, enc->dynParams, (VIDENC2_Status*) enc->status);

Process of MPEG4 Encoder (Failed):
    err = VIDENC2_process(enc->codec, enc->inBufs, enc->outBufs, (VIDENC2_InArgs *) mpeg4enc_inArgs, (VIDENC2_OutArgs *) mpeg4enc_outArgs);

Any help would be appreciated and thanks in advance.

  • Hi,

    First of all, is it possible to explain why the existing libdce interface and the associated viddec3test or GStreamer applications cannot be used as is?

    What you are attempting to do here is create a custom IPUMM firmware (not the standard TI firmware), change the memory allocations and possibly the interface.

    I will strongly recommend using the existing interface to build your application. 

    It is going to be very difficult to support debug of this issue if you are following a different approach from our standard delivery.

    Regards

    Karthik

  • Hi Karthik,
    Our POC requires the processed image and result data to be sent to another machine via ethernet. As we need to achieve real timeliness, we plan to encode the image (640x480) and transfer via socket. I initially tried with DCE interface, there also I faced similar issue (error at process stage). As I couldn't find proper manual about the DCE library, with my little understanding I found that major part of DCE acts as wrapper to the VIDENC2_*() function calls. So with videnc2test.c as a reference, I wrote some piece of code to directly access VIDENC2_*() calls in IPU2.


    We would like to take ownership of the firmware we use (custom firmware is 95% similar to IPUMM-FW), and to reach real-time performance with reduced resource usage we would like to keep away from GStreamer. As per our code flow, we would have the image accessible in IPU2, so to imitate that I use simple heap allocation calls.

    We thought this is the best approach to reach our goal. Kindly help us with your expertise, whether this is good idea or please suggest us some way/simple "Hello World" demo to achieve invoking IVA-HD encoder with only using IPU2 processor.

    With Regards,

    Subramaniyan

  • Subramaniyan,

    Thanks for the details. 

    If we need to debug this further, my recommendation is to start with videnc2test which is an example application that uses the libdce interface from the A15 side, and provide a reproducible environment. The interface has one to one mapping with the codec capability. Note that this does not use GStreamer.

    You can then translate the progress to your custom firmware once you have a working prototype.

    Can you please share the steps to reproduce the issue so that we can proceed further?

    Regards

    Karthik

  • Dear Karthik,

    By using the videnc2test.c and the ipumm firmware, I am able to do the decoding. While debugging the code I found out that the buffers are passed as File Descriptors to the IVAHD core. These file descriptors are created by the omap_bo_dmabuf() API. Both IO buffers are passed as file descriptors which are created from buffer object of omap_bo_new().

    enc->output_bo = omap_bo_new(enc->dev, output_size, OMAP_BO_WC);

    enc->outBufs->descs[0].buf = (void *)omap_bo_dmabuf(enc->output_bo);

    Kindly let me know are there any other way to pass the pointer addresses directly for the encoder processing at IVA-HD core.

    Thanks and Regards,

    Subramaniyan