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.

Getting crazy with jpeg encoder ...

Other Parts Discussed in Thread: DM3730

Hello everybody

Since a few Days i am trying to implement the jpeg encoder into the encode/decode demo...

at first i hope this is possible but i couldn't imagine why it shouldn't be possible....

the first step i made was to add the jpeg encoder engine to the encodedecode.cfg

/* ============================================================================

* Copyright (c) Texas Instruments Incorporated 2007

* Use of this software is controlled by the terms and conditions found in the

* license agreement under which this software has been supplied or provided.

* ============================================================================*/

var osalGlobal = xdc.useModule( 'ti.sdo.ce.osal.Global' );

osalGlobal.runtimeEnv = osalGlobal.LINUX;

var MPEG4ENC = xdc.useModule('ti.sdo.codecs.mpeg4enc.dm355.ce.MPEG4ENC');

var MPEG4DEC = xdc.useModule('ti.sdo.codecs.mpeg4dec.dm355.ce.MPEG4DEC');

var JPEGENC = xdc.useModule('ti.sdo.codecs.jpegenc.dm355.ce.JPEGENC');

/*======== Engine Configuration ========*/

var Engine = xdc.useModule('ti.sdo.ce.Engine');

var demoEngine = Engine.create("encodedecode", [

{name: "mpeg4enc", mod: MPEG4ENC, local: true, groupId: 1},

{name: "mpeg4dec", mod: MPEG4DEC, local: true, groupId: 1},

{name: "jpegenc", mod: JPEGENC, local: true, groupId: 1},

]);

Next step i made was to start the engine inside the video1.c, this was already there, only thing i made was to took it out of the if clause to start it also if passthrough is active.

After this i allocated and initialized the jpeg encoder (mpeg4 encoder/decoder stays off, cause of passthrough)

Therefor i used a copy of the funktion to start the mpeg4 encoder (videoEncodeAlgCreate) and renamed the copy into "jpgEncodeAlgCreate"

/******************************************************************************

* jpgEncodeAlgCreate

******************************************************************************/

static int jpgEncodeAlgCreate(Engine_Handle hEngine, IMGENC1_Handle *hImgencPtr, int width, int height)

{

IMGENC1_DynamicParams dynParams;

IMGENC1_Status encStatus;

IMGENC1_Params encParams;

IMGENC1_Handle hImgenc;

XDAS_Int32 status;

/* allocate and initialize image encoder on the engine */

encParams.size = sizeof(IMGENC1_Params);

encParams.maxWidth = width;

encParams.maxHeight = height;

encParams.maxScans = 4;

encParams.dataEndianness = XDM_DEFAULT;

encParams.forceChromaFormat = XDM_YUV_422ILE;

/* Create JPEG encoder instance */

hImgenc = IMGENC1_create(hEngine, "jpegenc", &encParams);

if (hImgenc == NULL) {

printf("Failed to open jpg encode algorithm: %s (0x%x)\n", "jpegenc", Engine_getLastError(hEngine));

return FAILURE;

}

/* set the parameters for encoding */

dynParams.size = sizeof(IMGENC1_DynamicParams);

dynParams.numAU = XDM_DEFAULT;

dynParams.inputChromaFormat = XDM_YUV_422ILE;

dynParams.inputHeight = height;

dynParams.inputWidth = width;

dynParams.captureWidth = 0;

dynParams.generateHeader = XDM_ENCODE_AU;

dynParams.qValue = 73;

/* Set video encoder dynamic parameters */

encStatus.size = sizeof(IMGENC1_Status);

encStatus.data.buf = NULL;

status = IMGENC1_control(hImgenc, XDM_SETPARAMS, &dynParams, &encStatus);

if (status != VIDENC1_EOK) {

printf("XDM_SETPARAMS failed, status=%ld\n", status);

return FAILURE;

}

*hImgencPtr = hImgenc;

return SUCCESS;

}

This function stops executing the programm with these errors.

starting the programm with ./encodedecode  -r 720x576 -x -p

Encodedecode Demo started.

Codec Engines opend in video thread (<-- this is a line in the videoThrFxn after starting the Engine, after this my jpgencodeAlgCreate is called)

CMEMK Error: GETPHYS: Failed to convert virtual 0x4001dac0 to physical.

CMEM Error: getPhys: Failed to get physical address of 0x4001dac0

Failed to open jpg encode algorithm: jpegenc (0x0)

Capturing 720x576 video (cropped to 720x576)

Encodedecode Error: Failed FBIO_WAITFORVSYNC (Connection timed out)

 

I also added imgenc1.h gt.h and stdlib.h cause they were included in the jpgenc example...

I commented the video Main Loop out, cause i want only one frame as picture. I tested these befor and i saw only one picture on the tv after that.

So now i have no idea why it wont start the jpeg encoder ... i hope you can help me... i simply want to build some jpegs out of the video stream befor encoding to mpeg4.

p.s. the jpegenc example is no futher help, i looked at it already... or do you have some more guides about that?

p.p.s here is also the jpeg encode function but the programm quits befor its execution and the other function calls

jpegEncodeAlgCreate call

/* Reset, load, and start DSP Engine */

hEngine = Engine_open(ENGINE_NAME, NULL, NULL);

if (hEngine == NULL) {

printf("Failed to open codec engine %s\n", ENGINE_NAME);

cleanup(THREAD_FAILURE);

} else {

printf("Codec Engines opened in video thread\n");

}

/* Allocate and initialize jpeg encoder on the engine */

if (jpgEncodeAlgCreate(hEngine, &hImgenc, envp->imageWidth, envp->imageHeight) == FAILURE) {

cleanup(THREAD_FAILURE);

}

encodejpg call

if (encodeJpeg(hImgenc, ce.virtBuf, ce.bufSize, encBuf, encBufSize, &frameSize) == FAILURE) {

breakLoop(THREAD_FAILURE);

}

/******************************************************************************

* encodeJpeg

******************************************************************************/

static int encodeJpeg(IMGENC1_Handle hImgenc, char *inBuf, int inBufSize,

char *outBuf, int outBufMaxSize, int *outBufSize)

{

IVIDEO1_BufDescIn inBufDesc;

XDM_BufDesc outBufDesc;

XDAS_Int32 outBufSizeArray[1];

XDAS_Int32 status;

VIDENC1_InArgs inArgs;

VIDENC1_OutArgs outArgs;

outBufSizeArray[0] = outBufMaxSize;

inBufDesc.numBufs = 1;

inBufDesc.frameWidth = 720;

inBufDesc.frameHeight = 576;

inBufDesc.bufDesc[0].bufSize = inBufSize;

inBufDesc.bufDesc[0].buf = inBuf;

outBufDesc.numBufs = 1;

outBufDesc.bufSizes = outBufSizeArray;

outBufDesc.bufs = (XDAS_Int8 **) &outBuf;

inArgs.size = sizeof(VIDENC1_InArgs);

outArgs.size = sizeof(VIDENC1_OutArgs);

/* Encode Jpeg/video buffer */

status = IMGENC1_process(hImgenc, &inBufDesc, &outBufDesc, &inArgs, &outArgs);

if (status != IMGENC1_EOK) {

printf("VIDENC1_process() failed with a fatal error (%ld ext: %#lx\n",

status, outArgs.extendedError);

return FAILURE;

}

*outBufSize = outArgs.bytesGenerated;

return SUCCESS;

}

  • Are the messages below coming from your Linux user application (I would guess yes)

    CMEMK Error: GETPHYS: Failed to convert virtual 0x4001dac0 to physical.

    CMEM Error: getPhys: Failed to get physical address of 0x4001dac0

    Failed to open jpg encode algorithm: jpegenc (0x0)

    I did not see them in the code segments you included in your post.  At fist glance, it appears there is an issue with cmemk.ko; it is either incompatible with the rest of the DVSDK software you are using or it simply is not configured to handle the buffer sizes the user application is requesting from it (Have you changed buffer sizes?).  However, I wonder if failure to open jpg encode algorithm is a result of this or a separate issue (I believe you do not pass it CMEM buffers until the process stage, hence it should not be ailing to open).

     

     

  • Hi

    The First 2 statements must be auto generated, the last one is in the code (2nd quote block, above the first "return FAILURE")

    Changed Buffersize? No i dont know how to do this, should i do this?

    and forgive me, but i dont understand this sentence "(I believe you do not pass it CMEM buffers until the process stage, hence it should not be ailing to open)."

    Alex

  • The life of a codec (e.g. JPEG) instance consists of the following phases (there are codec engine APIs for each)

    Open (usually done during init phase)

    Control (used to configure, usually during init phase)

    Process (called often during main processing loop to actually do encoding or decoding)

    Close (called as program cleans up and exits)

    My previous sentence "(I believe you do not pass it CMEM buffers until the process stage, hence it should not be ailing to open).", referred to this process phase. 

    FYI, CMEM (Contiguous Memory allocator) allocates buffers that can be accessed by both ARM and DSP; it is used to pass data between ARM user application and DSP algorithm (e.g. JPEG encode).  By using CMEM, we only need to pass buffer pointer as opposed to entire buffer (time consuming).  CMEM buffer are normally passed during "Process" stage.

    FYI, all this is explained in the codec engine documentation (see codec_engine_X_XX/docs folder under DVSDK installation).

    [Edit] In summary, it appears we may be looking at two issues, 

    1) Why would opening instance of JPEG encode fail?

    2) Why is CMEM reporting errors; if it was working before and none of the parameters into cmem function calls have changed, then this should not be happening.  Therefore, something else must have changed.

     

  • Hi

    I think i have encountered the problem.

    I i delete the line "IMGENC1_process(hImgenc, &inBufDesc, &outBufDesc, &inArgs, &outArgs)" i can run the programm without memory issues.

    So i tried inside my "encodeJpeg" function (where i deleted this line) to route the inputbuffer for jpeg encoding into a file.

    It was a very nice to see no error, so i thought i had raw image data into a file.

    I tried to convert them with the jpegenc example into a jpeg and this was also fine.

    I got a jpeg of that picture i shot some minutes ago.

    So i think i have some problems with the pointers of the buffers cause the error message also was somthing like: "cant convert from virtual to physical"

    so the first of your 2 mentioned issues solved i with deleting the mpeg4 encoder and decoder out of the encodedecode demo, maybe their was also some bad links in the memory mappings.

    2nd issue i think is what i hav written above, i mixed up the different pointers and buffers.

    so now its time to go home, tomorrow is also another day :)

    alex

  • Alex,

    I am glad you made some progress. If I understood correctly, you are still having memory pointer issues, correct? 

    If so, I imagine there are still pieces of the original source code trying to execute MPEG4-related activities; when you resume work on this, let us know if there is anything we can assist you with. 

  • Hi

    I've found the wrong pointer causing my memory problems, no everything runs fine... almost...

    the call for "IMGENC1_process(IMGENC1_Handle, &inBufDesc, &outBufDesc, &encInArgs, &encOutArgs)" didnt change the OutputBuffer. Its the same befor and after the call for the encoding engine.

    I verified that with two outputfiles and compared them. The InputBuffer inside the InputBuffer Descripter is filled up with raw picture data. Like yesterday i am able to encode such a file manually to a Jpeg.

    But in the Outputbuffer inside the Outputbuffer Descripter, there is only "Bit Waste". I get a Jpeg with a lot of funny colors. It has the full filesize of a 720*576*24/8 picture --> 1,6MByte

    Sometime i get a picture, where i can identify the object i have shot. But there are also funny colors, its like being on drugs ;)

    Do you have heard of this already?

  • It seems so, that i am encoding the wrong buffer, but why??

    If i restart the programm again without rebooting the board, i get a wrong color picture of that object i have shot in the further programm run.

    Edit:

    Ah i know where the old picture comes from...

    1.) Reboot the Board

    2.) encoded a raw picture with jpegenc from examples (raw picture is one i have shot befor reboot)

    3.)started my program to shot pictures and encode them befor saving @nfs

    --> so i got always the same wrong colored picture as jpeg. if i took another raw picture with example jpegencoder i will get this picture...

    so why the hell he wouldnt take the new input at the inputbuffer? Its there! if i save the inputbuffer as raw pic i always get the actually picture...

     

    edit2:

    i must correct myself, it must be the outputbuffer, cause the encoder wont refresh the outputbuffer i took. Cause in the inputbuffer is the right raw data.

    So something during encoding goes wrong i think. and if i reboot the board and use directly my programm, i got a grey picture with some artefacts in the uper left corner

  • Alex,

    One thing that comes to mind with regards to buffer pointers is that the original demo source code uses multiple video buffers (common in video application) to avoid tearing effects in video (e.g. display one buffer, while working on a different buffer).  For a JPEG application, this may not be needed.  Have you tried taking multiple pictures back to back to see if this is an ping-pong buffer issue?

  • Juan Gonzales said:

    Have you tried taking multiple pictures back to back to see if this is an ping-pong buffer issue?

    i wrote an application that shots every second (every 25th frame) a picture, it was allways the same picture.

    I'll try now to reduce the buffers to a minimum in the hole application.

     

  • Ok i found the issue why my encoded jpeg's always have a filesize of 1,6mb.

    i did fwrite(encodedBuf, 1, encodedBufSize, file) <-- the buffer for 720x576x24/8 is round about 1,6Mbyte. And with this instruction i wrote the hole buffer to a file.

    I changed it to fwrite(encodedBuf, 1, encOutArgs.bytesGenerated, file) <-- now my jpeg file is 607 Bytes large. But its only Black!

  • Hello, i solved the problem i think but there is a new one^^

    I setted up the dynamic encoding parameters, but i forgot to send them to the engine (shame on me) :)

    IMGENC1_control(hImgenc, XDM_SETPARAMS, &dynParams, &imgStatus) was missing after setting up the dynParams.* ...

    Now i got pictures, buit some of the are grey and only in the first few lines are some wrong or random colors.

    Could this be a reason of "multithreading" and that i have only one buffer for capturing and displaying left? So a new buffer is captured while the old one is still being encoded?

    I will try now to get back to more Buffers. Maybe you have another reason for this?

     

    edit: Ok Singlebuffering is not the reason for grey/corrupt images

    edit2: Ok i think i have found the reason for grey/corrupt images:

    encParam.maxScans is default at 4, i took it to one an almost every picture was corrupt, so i took it to 10 and the corrupt pictures didnt show again.

    So what does this value do?

    edit3: ok i was wrong... i still get corrupt images

  • Alex,

    I did not believe the number of buffers was the problem; I bleieve the maxScans parameter is described in the JPEG encoder user's guide; it is supposed to describe the parameters needed by JPEG encoder.  I do not know this off the top of my head and I am in training most of the day today, but wanted to point you in the right direction.

  • Hi again!

    Now i think i solved it... finally!

    I think the problem was the jpeg encoder.

    I initializied it first whil programm startup. After that i only encoded pictures. At the end of the programm i stopped  the encoder.

    So i got randomly corrupt pictures.

     

    I tried to start the encoder befor creating a jpeg and stop it directly after one shot. And start it again befor taking the next picture and stop em again.

    So every picture which is generated is a valid jpeg without display errors!

    :)

  • Alex,

    If I understood correctly, this sounds like a bug in JPEG encoder.  Can you please confirm my understanding to see if I need to report this?

    You need to "start, encode jpeg image, stop" for each jpeg image you want to encode; otherwise, you see corruption.  Is this correct?  If so, would you mind providing the APIs you are using for "start, encode jpeg image, stop" sequence.

    Thank you in advance for your help with this.

  • Hi, i hope im helping your understanding if i paste my sourcecode of the "image shot" part.

    First the short Version:

    if i dont use at the end of EncodeJpeg function thos two commands Memory_contigFree(encodedBuf, encodedBufSize) and IMGENC1_delete(hImgenc) and if i dont call the jpgEncodeAlgCreate Function befor calling IMGENC1_process() i get sometimes corrupt images.

    The Enginbe itself is only started at the beginning of the programm and is quittted while exiting the programm. But have a closer look at the sourcecode i think it should display the problem better than my english :)

    The Encoder Create Code

     

    /******************************************************************************

    * jpgEncodeAlgCreate

    ******************************************************************************/

    static int jpgEncodeAlgCreate(Engine_Handle hEngine, IMGENC1_Handle *hImgencPtr, int width, int height)

    {

    IMGENC1_Params encParams;

    IMGENC1_Handle hImgenc;

    IMGENC1_DynamicParams dynParams;

    IMGENC1_Status imgStatus;

    XDAS_Int32 status;

    /* allocate and initialize image encoder on the engine */

    encParams.size = sizeof(IMGENC1_Params);

    encParams.maxWidth = width;

    encParams.maxHeight = height;

    encParams.maxScans = 200;

    encParams.dataEndianness = XDM_DEFAULT;

    encParams.forceChromaFormat = XDM_CHROMAFORMAT_DEFAULT;

     

    /* Create JPEG encoder instance */

    if ((hImgenc = IMGENC1_create(hEngine, "jpegenc", &encParams)) == NULL) {

    printf("Failed to open jpg encode algorithm: %s (0x%x)\n", "jpegenc", Engine_getLastError(hEngine));

    return FAILURE;

    }

    /* set the parameters for encoding */

    dynParams.size = sizeof(IMGENC1_DynamicParams);

    dynParams.numAU = XDM_DEFAULT;

    dynParams.inputChromaFormat = XDM_CHROMAFORMAT_DEFAULT;

    dynParams.inputHeight = height;

    dynParams.inputWidth = width;

    dynParams.captureWidth = 0;

    dynParams.generateHeader = XDM_ENCODE_AU;

    dynParams.qValue = 100;

    imgStatus.size = sizeof(imgStatus);

    if (IMGENC1_control(hImgenc, XDM_SETPARAMS, &dynParams, &imgStatus) == XDM_EFAIL) {

    printf("could not set PARAMS");

    return FAILURE;

    }

    status = IMGENC1_control(hImgenc, XDM_GETBUFINFO, &dynParams, &imgStatus);

    if (status != IMGENC1_EOK) {

    printf("XDM_GETBUFINFO failed, status=%ld\n", status);

    return FAILURE;

    }

     

    // Allocate intermediate buffer (for encoded data)

    encodedBufSize = imgStatus.bufInfo.minOutBufSize[0];

    encodedBuf = (XDAS_Int8 *)Memory_contigAlloc(encodedBufSize, Memory_DEFAULTALIGNMENT);

    printf("Contiguous buffer allocated at physical address %#lx\n", Memory_getPhysicalAddress(encodedBuf));

    *hImgencPtr = hImgenc;

    return SUCCESS;

    }

     

    The Encode and Save Funktion

     

    /******************************************************************************

    * encodeJpeg

    ******************************************************************************/

    static int encodeJpeg(Engine_Handle hEngine, IMGENC1_Handle hImgenc, XDAS_Int8 *inBuf)

    {

    XDAS_Int32 status;

    IMGENC1_InArgs encInArgs;

    IMGENC1_OutArgs encOutArgs;

    IMGENC1_DynamicParams encDynParams;

    XDM1_BufDesc inBufDesc;

    XDM1_BufDesc encodedBufDesc;

    time_t zeit;

    char strzeit[256];

    struct tm *zeitinfo;

    setlocale(LC_ALL, "");

    time(&zeit);

    zeitinfo = localtime(&zeit);

    strftime(strzeit, 255, "%Y.%m.%d_%R:%S", zeitinfo);

     

    inBufDesc.numBufs = 1;

    inBufDesc.descs[0].bufSize = inBufSize;

    inBufDesc.descs[0].buf = inBuf;

    encodedBufDesc.numBufs = 1;

    encodedBufDesc.descs[0].bufSize = encodedBufSize;

    encodedBufDesc.descs[0].buf = encodedBuf;

    encInArgs.size = sizeof(encInArgs);

    encOutArgs.size = sizeof(encOutArgs);

    encDynParams.size = sizeof(encDynParams);

    /* Encode Jpeg/video buffer */

    status = IMGENC1_process(hImgenc, &inBufDesc, &encodedBufDesc, &encInArgs, &encOutArgs);

    if (status == IMGENC1_EOK) {

    printf("Encoder process returned - %d bytes)\n", encOutArgs.bytesGenerated);

    char dateiname[40];

    strcpy(dateiname,"usb/");

    strcat(dateiname,strzeit);

    strcat(dateiname,".jpg");

    FILE *filestream = NULL;

    filestream = fopen(dateiname, "w");

    fwrite(encodedBuf, 1, encOutArgs.bytesGenerated, filestream);

    fclose(filestream);

     

    printf("Schreibe Datei: %s\n", dateiname);

    }

    else {

    printf("Encoder frame processing FAILED extendedError = 0x%x\n", encOutArgs.extendedError);

    }

    if (encodedBuf) {

    Memory_contigFree(encodedBuf, encodedBufSize);

     

     

    printf("Speicher freigegeben\n");

    }

    if (hImgenc) {

    IMGENC1_delete(hImgenc);

    printf("Encoder freigegeben\n");

    }

    return SUCCESS;

    }

     

    The Loop and Call of this two functions

     

    printf("Entering video main loop.\n");

    while (!gblGetQuit()) {

    /* Receive a buffer with a displayed frame from the display thread */

    if (FifoUtil_get(envp->hDisplayOutFifo, &de) == FIFOUTIL_FAILURE) {

    printf("Failed to get buffer from input fifo\n");

    }

    /* Is the display thread flushing the pipe? */

    if (de.id == DISPLAY_FLUSH) {

    breakLoop(THREAD_SUCCESS);

    }

    /* Get a buffer from the capture thread */

    if (FifoUtil_get(envp->hCaptureOutFifo, &ce) == FIFOUTIL_FAILURE) {

    printf("Failed to put buffer in output fifo\n");

    }

    /* Is the capture thread flushing the pipe? */

    if (ce.id == CAPTURE_FLUSH) {

    breakLoop(THREAD_SUCCESS);

    }

    if (gbl_shot == 0/*envp->passThrough*/) {

    /* Copy the buffer without processing */

    memcpy(de.virtBuf, ce.virtBuf, ce.bufSize);

    /* Send frame buffer to capture thread */

    if (FifoUtil_put(envp->hCaptureInFifo, &ce) == FIFOUTIL_FAILURE) {

    ERR("Failed to put buffer in output fifo\n");

    breakLoop(THREAD_FAILURE);

    }

    }

    i++;

    if (i == 75/*gbl_shot == 1*/) {

    // Allocate and initialize jpeg encoder on the engine

    if (jpgEncodeAlgCreate(hEngine, &hImgenc, envp->imageWidth, envp->imageHeight) == FAILURE) {

    cleanup(THREAD_FAILURE);

    }

    printf("jpg encoder created\n");

    gbl_shot = 0;

    /* Create Jpeg */

    if (encodeJpeg(hEngine, hImgenc, ce.virtBuf) == FAILURE) {

    breakLoop(THREAD_FAILURE);

    }

    /* Send frame buffer to capture thread */

    if (FifoUtil_put(envp->hCaptureInFifo, &ce) == FIFOUTIL_FAILURE) {

    printf("Failed to put buffer in output fifo\n");

    }

    i = 0;

    }

    /* Send frame buffer to display thread */

    if (FifoUtil_put(envp->hDisplayInFifo, &de) == FIFOUTIL_FAILURE) {

    printf("Failed to put buffer in output fifo\n");

    }

    }

  • Hi Alex,

    Thank you for the response; I have been doing some investigating and it appears you need to call on IMGDEC_Control(hdec, XDM_RESET,...) after each process call (no need to delete and create codec instance again).  I got the following code segment from a colleague of mines

    status = IMGDEC_control( hDec, XDM_SETPARAMS, &idecDynParams, &idecStatus );

    if( status != IMGDEC_EOK ){
          printf( "IMGDEC_control(XDM_SETPARAMS): error1\n" );
          break;
    }

    /* JPEG  decode */
    status = IMGDEC_process( hDec, &encodedBufDesc, &outBufDesc,&decInArgs, &decOutArgs);

    if (status != IMGDEC_EOK) {
          printf("JPEG Decoder frame %d processing FAILED1, status = 0x%x, "
                    "extendedError = 0x%x\n", n, status, decOutArgs.extendedError);
          break;
    }
    else {
           Memory_cacheWbInv( dst, FRAMESIZE );
    }

    status = IMGDEC_control( hDec, XDM_RESET, &idecDynParams, &idecStatus );

    f( status != IMGDEC_EOK ){
         printf( "IMGDEC_control(XDM_RESET): error1\n" );
         break;
    }

     

     

  • Hi Juan

    I tried using the XDM_RESET, but i get corrupt pictures again if i dont create and delete codec instance for every picture. I changed the example you wrote from IMGDEC to IMGENC1 and called the IMGENC1_control after encoding a picture. But there are the same corrupt pictures like without using the XDM_RESET.

    Alex

  • Alex,

    Let me do some more digging around. At the moment, I would stick with creating and deleting the codec instance.

  • I also have a problem with the JPEG encoder that is very similar.

    I have a 5mpix CMOS sensor that I use to take snapshots, convert to YUV, JPEG encode them and save to disk. I used the encode demo as the basis for the code, so the capture thread gets the CMOS data & converts to YUV, the video thread encodes the frame and the writer  thread saves the pictures to disk.

    What I've found is that when the CCDC input is running - AT ALL - then there is a high probability that the JPEG encoder will produce a corrupted output. The corruption that I see is a section of the frame will be torn and shifted.

    To prove that it is in the enocoder-CCDC combination  I captured 3 frames, turned off the video capture and JPEG encoded the 3 static frames. This produced no issues with the encoder.

    However, when I turn the input back on again - some number of frames get corrupted pretty quickly.

    My immediate solution was to make sure that when I am running the encoder that the CCDC input is not transfering any data (a few sleep statements here and there) but it doesn't always work.

     

  • Steve,

    Apologies for the delay, I just got back from vacation and answering forum posts. 

    From your description above, I am wondering if you are using double (or tripple buffering).  Ideally, the application should use one buffer to capture CCD data, a second buffer to encode (and possibly display), and optionally a third for display.  This would avoid the need for adding sleep commands.  By default, the encode demo uses tripple buffering (if I recall correctly); therefore if you maintained the tripple buffering nature, I would add print statements to see how these buffers are being used (e.g. capture, encode, display).

  • Alex,

    It appears this is a known issue (XDM_RESET not working properly); I will need to push this internally towards a resolution in a future software release.

  • I elimanated the input to the jpeg encoder as the problem by saving the YUV file before each encoding. In every case the input to the encoder was perfect.

    But to answer your question, the code started out with the same buffering as the demo code - which was three input buffers, three video buffers, three write buffers. Thats when I saw the problem first.

    This really is a case of JUST HAVING THE CCDC running causes JPEG corruption. You don't even have to use the input (feed the encoder a static good picture) and the encoder corrupts the picture.

  • that sounds like the same issue i had. try to stop the encode instance after every encoded picture, and (re)start it befor encoding. I think this will work, until TI has fixed the encoder reset issue.

    I also thought it was in relation to the tripple buffering of video encode demo, so i reduced it to only one buffer for capture, encode and write. But there were also the same corrupt pictures. So i would say its not caused through multi buffering.

    @Juan:
    Thanx for your help so far.

  • I took this one step further - I compiled the 'jpegenc' program that was supplied in the SDK and called that from my program. Essentially after I created the YUV file I saved it to /tmp, then I called jpegenc using the system() function call.

    This still resulted in corrupt pictures. And the input frame was always fine.

    I believe that there is some kind of DMA problem with the CCDC and the codec...

  • I am not that familiar with the MJCP, since it is really only used through the codecs so I am not sure if this is the case (we may have to get further comment on this), but based on the symptoms it sounds like there may be some real time deadlines that must be met within the MJCP for the JPEG encoding process to complete properly, as the major change resulting from having the CCDC active while the MJCP is processing is that the MJCP could suffer delays in access to DDR bandwidth.

    Based on this my first thought on trying to resolve the issue would be to increase the priority of the MJCP, though it seems that its bus priority is fixed at a low level (5) so you would have to adjust the priority of the VPSS and perhaps other accessors to be lower (>5). The priority system is discussed in section 9.9 of SPRUFB3, in the case of the VPSS you would need to adjust the value in the VPSS PCR register (lowest three bits called CPRIORITY). Note that this could have unintended consequences though, lowering the VPSS priority could cause seperate real time deadline problems and may lead to capture or display anomalies particularly if the DDR bandwidth is already being saturated, so this is not a true guaranteed solution but may be worth a shot.

  • Bernie has a good point.  In both of your cases, a delay (via sleep or deleting/creating new codec instance) appears to alleviate the sympton; it is conceivable that this is due to DDR2 bandwidth contention that gets alleviated by a delay.  Another way to test would be to reduce the size of the image being captured and encoded.

  • This is good info... what doc gives the detail on the VPSS PCR register? Can't seem to find it with the ones that I have.

  • There is the Video Processing Front End (VPFE) and the Video Processing Back End (VPBE) User Guides.  They both have separate PCR registers.

    http://focus.ti.com/lit/ug/spruf72c/spruf72c.pdf

    http://focus.ti.com/lit/ug/spruf71a/spruf71a.pdf

  • Both the guides define a PCR register, and in fact there are PCR registers for many peripherals, but in this case I believe you want the VPSS Buffer Logic PCR register for which there is only one (you control both VPBE and VPFE priority with one register, both documents are defining the same register), I am not sure where the 2784h offset comes from in the VPBE guide, but the 0x01C70804 address used in the VPFE document makes more sense as it aligns with the datasheet addressing scheme. Essentially you want to make the lower three bits of 0x01C70804 a value larger than 5.

  • It is possible to add the mpg codec to the encoder demo?If so,could somebody explain how to do it?Thanks

  • By MPG, do you mean MPEG4?   If so, DM355 has support for MPEG4 and JPEG and I believe the encode demo supports MPEG4 already (separate demo is available for JPEG).

    If you mean something other than MPEG4, I am afraid it may not be possible.  Some of our other DaVinci processors do have a flexible DSP which can be used to support other MPEG formats, but DM355 is lower cost and video compression support is limited to MPEG4 in hardware.

  • Did you find a resolution to this issue? I think we are seeing the same thing when doing 5MP images.

  • I am capturing 5MP images @ 4hz, coverting them in two passes via the IPIPE and then JPEG encoding. What I see is about every 3rd frame or so has as artifact like below. As I increase load on the system, say capturing audio at the same time I see worse artifacts and they will also start to appear on the other side.

     

  • Are you referring to the top right corner?  If it happens every third frame all the time, this may be a buffer misaligment issue. 

    Also, what do you mean by worse artifacts when you put more  load on the system?   does it happen more frequently, or in more places...  . 

  • That is what I saw as well. My theory is that there is an interaction with the CCDC and the JPEG encoder - it was only when I made sure that the CCDC was not capturing frames into memory was I able to get reasonable pictures *most* of the time. At one point someone suggested that modifying DMA priority might fix it, but when ever I tried that my camera just hung.
  • Yes I am referring to the top right corner. Artifacts similar to those appears more frequently (ie. more that every 3rd frame) and in more places of the image. I am aligning to a 32 byte boundary when doing the split processing or is there some other alignment you are talking about?

  • The other strange thing to note is the blocks that get spliced it look to be from a different frame. It almost seems like the CCDC still tries filling a buffer even though I have it dequeued.

  • That doesn't explain the image shift since if it was operating correctly it would put the next frames data in the same spot. I had that problem before and you really only notice it when you have movement in the image.

  • Yes that is very true. We didn't notice it for quite a while when testing against a static scene but with movement you can see the issue.

  • Any more ideas on this?

    I double checked buffers and alignments those seem to be fine. I have found that changing the IPIPE to use the SDRAM clock and the DIVIDE_EIGHT clock divisor eliminates the artifacts. This is not a good solution for me though as I need to capture 5MP @ 4hz and the change causing IPIPE processing to be > 500ms per image. It seems as I noted in an earlier post the the severity (frequency) of artifacts in the images increases with system load on the ARM core.

    I have seen some other posts with people that are having DDR bandwidth issues but they seem to be using the VPBE and outputting analog video. I am just doing a CMOS capture via CCDC, IPIPE and the JPEG encoding. Any info or tuning tips will be appreciated.

  • Hi,

    Similar kind of issue, we have observed with IPIPE module of DM355 as posted on davinci open source.
            http://n2.nabble.com/Re-DM355-IPIPE-Image-corruption-in-resizing-td2238244.html

    Someone suggested me the below solution:

        > Image corruption behavior is not at all certain. This corruption occurs while processing n number of images in loop. I was encounted same problem in CCD Bayer to RGB conversion. This situation was fixed VPSSCLK divide by 5 or more.

    But that didn't work for me, other solution worked for me, and that was to disable interrupts before IPIPE_START. No corruption in image was observed, if we disable interrupts before IPIPE_START and re-enable them after IPIPE_START. To disable interrupts we wrote 0xF0220 to 0x1c48018 register, and 0x238B to 0x1c4801C register. Values were restored to original after IPIPE_START. We haven't disabled all interrupts of the system. Here we have disabled VPFE capture interrupts, as for me corruption was while resizing using IPIPE module.
    In your case corruption is while RGB to YUV conversion, so disbaling VPFE interrupts will not be possible for you.

    Hope this information helps you somewhat.

  •  

    have you worked out solution for multiply jpeg encodings without deleting and creating codec? i use latest dvsdk on dm3730, and this problem still exists, when i execute below code, only first jpeg is ok, other are corrupted - no 2 bytes in header, when i repair header all jpegs are the same ;/

    /* Wait to wake up */
        /*************************************************************************************/
        mutex.lock();
        state = false;
        waitCondition.wait(&mutex);
        state = true;
        /*************************************************************************************/

        /* Process encoding and restart codec */
        /*************************************************************************************/
    //    Memory_cacheWbInv(Buffer_getUserPtr(*buf), Buffer_getSize(*buf));
    //    Memory_cacheInv(Buffer_getUserPtr(BufTab_getBuf(encoderBufTab, (counter % Settings::IMAGE_NUM))), Buffer_getSize(BufTab_getBuf(encoderBufTab, (counter % Settings::IMAGE_NUM))));
        Ienc1_process(encHandle, *buf, BufTab_getBuf(encoderBufTab, (counter % Settings::IMAGE_NUM)));
    //    Memory_cacheWb(Buffer_getUserPtr(BufTab_getBuf(encoderBufTab, (counter % Settings::IMAGE_NUM))), Buffer_getSize(BufTab_getBuf(encoderBufTab, (counter % Settings::IMAGE_NUM))));
        //    Ienc1_delete(encHandle);
        //    encHandle = Ienc1_create(engineHandle, codecName, &encoderParams, &encoderDynamicParams);
    //    IMGENC1_control(Ienc1_getVisaHandle(encHandle), XDM_RESET, &encoderDynamicParams, &imgStatus);
    //    IMGENC1_control(Ienc1_getVisaHandle(encHandle), XDM_FLUSH, &encoderDynamicParams, &imgStatus);
        msleep(40);
        counter++;
        /*************************************************************************************/

        /* Unlock mutex */
        /*************************************************************************************/
        mutex.unlock();
        /****