Hello,
I used to write image processing algorithms using C6Accel on DM8168 but since C6Accel is deprecated, I started to work with Codec Engine (EZSDK 5.04.00.11). I modified image_copy app to make it work with buffersize of 921600 bytes. Here is my new apps/image_copy/app.c file:
/* * Copyright (c) 2012, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /* * ======== app.c ======== */ #include <xdc/std.h> #include <xdc/runtime/Assert.h> #include <xdc/runtime/Diags.h> #include <xdc/runtime/Log.h> #include <ti/sdo/ce/Engine.h> #include <ti/sdo/ce/osal/Memory.h> #include <ti/sdo/ce/image/imgdec.h> #include <ti/sdo/ce/image/imgenc.h> #include <string.h> /* for memset */ #include <stdio.h> #include <stdlib.h> #include <sys/time.h> /* * If an XDAIS algorithm _may_ use DMA, buffers provided to it need to be * aligned on a cache boundary. */ #ifdef CACHE_ENABLED /* * If buffer alignment isn't set on the compiler's command line, set it here * to a default value. */ #ifndef BUFALIGN #define BUFALIGN 128 #endif #else /* Not a cached system, no buffer alignment constraints */ #define BUFALIGN Memory_DEFAULTALIGNMENT #endif #define NSAMPLES 1280*720 /* must be multiple of 128 for cache/DMA reasons */ #define IFRAMESIZE (NSAMPLES * sizeof(Int8)) /* raw frame (input) */ #define EFRAMESIZE (NSAMPLES * sizeof(Int8)) /* encoded frame */ #define OFRAMESIZE (NSAMPLES * sizeof(Int8)) /* decoded frame (output) */ static XDAS_Int8 *inBuf; static XDAS_Int8 *encodedBuf; static XDAS_Int8 *outBuf; static String decoderName = "imgdec_copy"; static String encoderName = "imgenc_copy"; static Void encode_decode(IMGENC_Handle enc, IMGDEC_Handle dec, FILE *in, FILE *out); /* * ======== createInFileIfMissing ======== */ static void createInFileIfMissing(char *inFileName) { int i; FILE *f = fopen(inFileName, "rb"); if (f == NULL) { printf("Input file '%s' not found, generating one.\n", inFileName); f = fopen(inFileName, "wb"); for (i = 0; i < NSAMPLES; i++) { fwrite(&i, sizeof(i), 1, f); } } fclose(f); } /* * ======== smain ======== */ Int smain(String progName, String procId, String engineName, String inFile, String outFile) { Engine_Handle ce = NULL; Engine_Attrs attrs; IMGDEC_Handle dec = NULL; IMGENC_Handle enc = NULL; FILE *in = NULL; FILE *out = NULL; Memory_AllocParams allocParams; createInFileIfMissing(inFile); Log_print4(Diags_USER1, "[+1] App-> Application started, procId %s " "engineName %s input-file %s output-file %s.", (IArg)procId, (IArg)engineName, (IArg)inFile, (IArg)outFile); /* allocate buffers */ allocParams.type = Memory_CONTIGHEAP; allocParams.flags = Memory_NONCACHED; allocParams.align = BUFALIGN; allocParams.seg = 0; inBuf = (XDAS_Int8 *)Memory_alloc(IFRAMESIZE, &allocParams); encodedBuf = (XDAS_Int8 *)Memory_alloc(EFRAMESIZE, &allocParams); outBuf = (XDAS_Int8 *)Memory_alloc(OFRAMESIZE, &allocParams); if ((inBuf == NULL) || (encodedBuf == NULL) || (outBuf == NULL)) { goto end; } /* open file streams for input and output */ if ((in = fopen(inFile, "rb")) == NULL) { printf("App-> ERROR: can't read file %s\n", inFile); goto end; } if ((out = fopen(outFile, "wb")) == NULL) { printf("App-> ERROR: can't write to file %s\n", outFile); goto end; } /* Initialize attrs fields to default values, and set the procId */ Engine_initAttrs(&attrs); attrs.procId = procId; /* reset, load, and start DSP Engine */ if ((ce = Engine_open(engineName, &attrs, NULL)) == NULL) { fprintf(stderr, "%s: error: can't open engine %s\n", progName, engineName); goto end; } /* allocate and initialize video decoder on the engine */ dec = IMGDEC_create(ce, decoderName, NULL); if (dec == NULL) { printf( "App-> ERROR: can't open codec %s\n", decoderName); goto end; } /* allocate and initialize video encoder on the engine */ enc = IMGENC_create(ce, encoderName, NULL); if (enc == NULL) { fprintf(stderr, "%s: error: can't open codec %s\n", progName, encoderName); goto end; } /* use engine to encode, then decode the data */ encode_decode(enc, dec, in, out); end: /* teardown the codecs */ if (enc) { IMGENC_delete(enc); } if (dec) { IMGDEC_delete(dec); } /* close the engine */ if (ce) { Engine_close(ce); } /* close the files */ if (in) { fclose(in); } if (out) { fclose(out); } /* free buffers */ if (inBuf) { Memory_free(inBuf, IFRAMESIZE, &allocParams); } if (encodedBuf) { Memory_free(encodedBuf, EFRAMESIZE, &allocParams); } if (outBuf) { Memory_free(outBuf, OFRAMESIZE, &allocParams); } Log_print0(Diags_USER1, "[+1] app done."); return (0); } double calc_time(struct timeval *before, struct timeval *after) { if (before->tv_usec > after->tv_usec) return (after->tv_usec - before->tv_usec + 1000000) / (double)1000; else return (after->tv_usec - before->tv_usec) / (double)1000; } /* * ======== encode_decode ======== */ static Void encode_decode(IMGENC_Handle enc, IMGDEC_Handle dec, FILE *in, FILE *out) { struct timeval tbegin, tend; Int n; Int32 status; IMGDEC_InArgs decInArgs; IMGDEC_OutArgs decOutArgs; IMGDEC_DynamicParams decDynParams; IMGDEC_Status decStatus; IMGENC_InArgs encInArgs; IMGENC_OutArgs encOutArgs; IMGENC_DynamicParams encDynParams; IMGENC_Status encStatus; XDM_BufDesc inBufDesc; XDAS_Int8 *src[XDM_MAX_IO_BUFFERS]; XDAS_Int32 inBufSizes[XDM_MAX_IO_BUFFERS]; XDM_BufDesc encodedBufDesc; XDAS_Int8 *encoded[XDM_MAX_IO_BUFFERS]; XDAS_Int32 encBufSizes[XDM_MAX_IO_BUFFERS]; XDM_BufDesc outBufDesc; XDAS_Int8 *dst[XDM_MAX_IO_BUFFERS]; XDAS_Int32 outBufSizes[XDM_MAX_IO_BUFFERS]; /* clear and initialize the buffer descriptors */ memset(src, 0, sizeof(src[0]) * XDM_MAX_IO_BUFFERS); memset(encoded, 0, sizeof(encoded[0]) * XDM_MAX_IO_BUFFERS); memset(dst, 0, sizeof(dst[0]) * XDM_MAX_IO_BUFFERS); src[0] = inBuf; encoded[0] = encodedBuf; dst[0] = outBuf; inBufDesc.numBufs = encodedBufDesc.numBufs = outBufDesc.numBufs = 1; inBufDesc.bufSizes = inBufSizes; encodedBufDesc.bufSizes = encBufSizes; outBufDesc.bufSizes = outBufSizes; inBufSizes[0] = encBufSizes[0] = outBufSizes[0] = NSAMPLES; inBufDesc.bufs = src; encodedBufDesc.bufs = encoded; outBufDesc.bufs = dst; /* initialize all "sized" fields */ encInArgs.size = sizeof(encInArgs); decInArgs.size = sizeof(decInArgs); encOutArgs.size = sizeof(encOutArgs); decOutArgs.size = sizeof(decOutArgs); encDynParams.size = sizeof(encDynParams); decDynParams.size = sizeof(decDynParams); encStatus.size = sizeof(encStatus); decStatus.size = sizeof(decStatus); /* * Query the encoder and decoder. * This app expects the encoder to provide 1 buf in and get 1 buf out, * and the buf sizes of the in and out buffer must be able to handle * NSAMPLES bytes of data. */ status = IMGENC_control(enc, XDM_GETSTATUS, &encDynParams, &encStatus); if (status != IMGENC_EOK) { /* failure, report error and exit */ Log_print1(Diags_USER7, "[+7] encode control status = 0x%x", (IArg)status); return; } /* Validate this encoder codec will meet our buffer requirements */ if ((inBufDesc.numBufs < encStatus.bufInfo.minNumInBufs) || (IFRAMESIZE < encStatus.bufInfo.minInBufSize[0]) || (encodedBufDesc.numBufs < encStatus.bufInfo.minNumOutBufs) || (EFRAMESIZE < encStatus.bufInfo.minOutBufSize[0])) { /* failure, report error and exit */ Log_print0(Diags_USER7, "[+7] Error: encoder codec feature conflict"); return; } status = IMGDEC_control(dec, XDM_GETSTATUS, &decDynParams, &decStatus); if (status != IMGDEC_EOK) { /* failure, report error and exit */ Log_print1(Diags_USER7, "[+7] decode control status = 0x%x", (IArg)status); return; } /* Validate this decoder codec will meet our buffer requirements */ if ((encodedBufDesc.numBufs < decStatus.bufInfo.minNumInBufs) || (EFRAMESIZE < decStatus.bufInfo.minInBufSize[0]) || (outBufDesc.numBufs < decStatus.bufInfo.minNumOutBufs) || (OFRAMESIZE < decStatus.bufInfo.minOutBufSize[0])) { /* failure, report error and exit */ Log_print0(Diags_USER7, "[+7] App-> ERROR: decoder does not meet buffer requirements."); return; } /* * Read complete frames from in, encode, decode, and write to out. */ for (n = 0; n < 10; n++) { /* Deal with cache issues, if necessary */ #ifdef CACHE_ENABLED #if defined(xdc_target__isaCompatible_64P) || \ defined(xdc_target__isaCompatible_64T) /* * fread() on this processor is implemented using CCS's stdio, which * is known to write into the cache, not physical memory. To meet * XDAIS DMA Rule 7, we must writeback the cache into physical * memory. Also, per DMA Rule 7, we must invalidate the buffer's * cache before providing it to any xDAIS algorithm. */ Memory_cacheWbInv(inBuf, IFRAMESIZE); #else #error Unvalidated config - add appropriate fread-related cache maintenance #endif /* Per DMA Rule 7, our output buffer cache lines must be cleaned */ Memory_cacheInv(encodedBuf, EFRAMESIZE); #endif Log_print1(Diags_USER1, "[+1] App-> Processing frame %d...", (IArg)n); gettimeofday(&tbegin, NULL); /* encode the frame */ status = IMGENC_process(enc, &inBufDesc, &encodedBufDesc, &encInArgs, &encOutArgs); gettimeofday(&tend, NULL); printf("Processing time: %.3f ms\n", calc_time(&tbegin, &tend)); Log_print2(Diags_USER2, "[+2] App-> Encoder frame %d process returned - 0x%x)", (IArg)n, (IArg)status); #ifdef CACHE_ENABLED /* Writeback this outBuf from the previous call. Also, as encodedBuf * is an inBuf to the next process call, we must invalidate it also, to * clean buffer lines. */ Memory_cacheWbInv(encodedBuf, EFRAMESIZE); /* Per DMA Rule 7, our output buffer cache lines must be cleaned */ Memory_cacheInv(outBuf, OFRAMESIZE); #endif if (status != IMGENC_EOK) { Log_print3(Diags_USER7, "[+7] App-> Encoder frame %d processing FAILED, status = 0x%x, " "extendedError = 0x%x", (IArg)n, (IArg)status, (IArg)(encOutArgs.extendedError)); break; } /* decode the frame */ decInArgs.numBytes = encOutArgs.bytesGenerated; status = IMGDEC_process(dec, &encodedBufDesc, &outBufDesc, &decInArgs, &decOutArgs); Log_print2(Diags_USER2, "[+2] App-> Decoder frame %d process returned - 0x%x)", (IArg)n, (IArg)status); if (status != IMGDEC_EOK) { Log_print3(Diags_USER7, "[+7] App-> Decoder frame %d processing FAILED, status = 0x%x, " "extendedError = 0x%x", (IArg)n, (IArg)status, (IArg)(decOutArgs.extendedError)); break; } #ifdef CACHE_ENABLED /* Writeback the outBuf. */ Memory_cacheWb(outBuf, OFRAMESIZE); #endif /* write to file */ fwrite(dst[0], OFRAMESIZE, 1, out); } Log_print1(Diags_USER1, "[+1] %d frames encoded/decoded", (IArg)n); } /* * @(#) ti.sdo.ce.examples.apps.image_copy; 1, 0, 0,1; 2-24-2012 19:27:54; /db/atree/library/trees/ce/ce-t06/src/ xlibrary */
loamodules.sh:
modprobe cmemk phys_start=0x96C00000 phys_end=0x98000000
modprobe syslink
So the result time of copying from one buffer to another is 28 ms. When I use C6Accel, it takes 7 ms to copy data. Why does Codec Engine processing works several times slower than C6Accel? I tried Codec Engine project the same way on Beagleboard-xM with DVSDK 4.01.00.09, and there were no decrease of perfomance.
Regards,
Sergey