]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/omapdrmtest.git/blobdiff - viddec3test.c
Add more checks to detect certain process call errors and exit
[glsdk/omapdrmtest.git] / viddec3test.c
index 1679981d018aa077554c2782c273dbd4b494e8da..984334a771d201e9f53a61140a1563eaac8eebfb 100644 (file)
  * You should have received a copy of the GNU General Public License along with
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <libdce.h>
+#include <xf86drm.h>
+#include <omap_drm.h>
+#include <omap_drmif.h>
 
-#include <dce.h>
-#include <xdc/std.h>
-#include <ti/xdais/xdas.h>
-#include <ti/sdo/ce/Engine.h>
-#include <ti/sdo/ce/video3/viddec3.h>
+#include <pthread.h>
 
 #include "util.h"
 #include "demux.h"
 #define PADX  32
 /* Padding for height as per Codec requirement (for h264)*/
 #define PADY  24
+/* omap drm device handle */
+struct omap_device *dev = NULL;
 
 struct decoder {
        struct display *disp;
        struct demux *demux;
        struct buffer *framebuf;
-
        Engine_Handle engine;
        VIDDEC3_Handle codec;
        VIDDEC3_Params *params;
@@ -47,17 +47,19 @@ struct decoder {
        XDM2_BufDesc *outBufs;
        VIDDEC3_InArgs *inArgs;
        VIDDEC3_OutArgs *outArgs;
-
        char *input;
        struct omap_bo *input_bo;
        int input_sz, uv_offset;
-
+       int padded_width;
+       int padded_height;
+       int num_outBuf;
+       size_t *outBuf_fd;
        suseconds_t tdisp;
-
 };
 
 /* When true, do not actually call VIDDEC3_process. For benchmarking. */
 static int no_process = 0;
+static int inloop = 0;
 
 /* When true, loop at end of playback. */
 static int loop = 0;
@@ -71,6 +73,7 @@ usage(char *name)
        MSG("viddec3test options:");
        MSG("\t-h, --help: Print this help and exit.");
        MSG("\t--loop\tRestart playback at end of stream.");
+       MSG("\t--inloop\tRestart playback at end of stream along with decoder reinitialization.");
        MSG("\t--no-process\tDo not actually call VIDDEC3_process method. For benchmarking.");
        MSG("");
        disp_usage();
@@ -79,99 +82,126 @@ usage(char *name)
 static void
 decoder_close(struct decoder *decoder)
 {
-       if (decoder->codec)          VIDDEC3_delete(decoder->codec);
-       if (decoder->engine)         Engine_close(decoder->engine);
+       if(!decoder) return;
+       /* free output buffers allocated by display */
+       if(inloop < 2 && decoder->disp) disp_free_buffers(decoder->disp,decoder->num_outBuf);
+
+       if (decoder->status)         dce_free(decoder->status);
        if (decoder->params)         dce_free(decoder->params);
        if (decoder->dynParams)      dce_free(decoder->dynParams);
-       if (decoder->status)         dce_free(decoder->status);
-       if (decoder->inBufs)         free(decoder->inBufs);
-       if (decoder->outBufs)        free(decoder->outBufs);
+       if (decoder->inBufs) {
+               dce_buf_unlock(1, &(decoder->inBufs->descs[0].buf));
+               close(decoder->inBufs->descs[0].buf);
+               dce_free(decoder->inBufs);
+       }
+       if (decoder->outBufs)        dce_free(decoder->outBufs);
        if (decoder->inArgs)         dce_free(decoder->inArgs);
        if (decoder->outArgs)        dce_free(decoder->outArgs);
-       if (decoder->input_bo)       omap_bo_del(decoder->input_bo);
-       if (decoder->demux)          demux_deinit(decoder->demux);
-       if (decoder->disp)           disp_close(decoder->disp);
-
-       free(decoder);
+       if (decoder->codec)          VIDDEC3_delete(decoder->codec);
+       if (decoder->engine)         Engine_close(decoder->engine);
+    if (decoder->input_bo)       omap_bo_del(decoder->input_bo);
+       if (decoder->outBuf_fd)      free(decoder->outBuf_fd);
+       if(inloop < 2) {
+               if (dev)                             dce_deinit(dev);
+               if (decoder->demux)          demux_deinit(decoder->demux);
+               if (decoder->disp)           disp_close(decoder->disp);
+               if(decoder) free(decoder);
+       }
 }
 
 static struct decoder *
 decoder_open(int argc, char **argv)
 {
-       struct decoder *decoder;
+       static struct decoder *decoder = NULL;
        char *infile = NULL;
-       int i, num_buffers;
-       int width, height, padded_width, padded_height;
+       int i;
+       static int width, height, padded_width, padded_height;
        Engine_Error ec;
        XDAS_Int32 err;
 
-       decoder = calloc(1, sizeof(*decoder));
-       if (!decoder)
-               return NULL;
-
-       MSG("%p: Opening Display..", decoder);
-       decoder->disp = disp_open(argc, argv);
-       if (!decoder->disp)
-               goto usage;
-
-       /* loop thru args, find input file.. */
-       for (i = 1; i < argc; i++) {
-               int fd;
-               if (!argv[i]) {
-                       continue;
-               }
-               fd = open(argv[i], 0);
-               if (fd > 0) {
-                       infile = argv[i];
-                       argv[i] = NULL;
-                       close(fd);
+    if(inloop < 2) {
+               decoder = calloc(1, sizeof(*decoder));
+               if (!decoder)
+                       return NULL;
+
+               MSG("%p: Opening Display..", decoder);
+               decoder->disp = disp_open(argc, argv);
+               if (!decoder->disp)
+                       goto usage;
+
+           /* loop thru args, find input file.. */
+               for (i = 1; i < argc; i++) {
+                       int fd;
+                           if (!argv[i]) {
+                                   continue;
+                       }
+                       fd = open(argv[i], 0);
+                       if (fd > 0) {
+                               infile = argv[i];
+                               argv[i] = NULL;
+                               close(fd);
+                               break;
+                       }
                        break;
                }
-               break;
-       }
-
-       if (check_args(argc, argv) || !infile)
-               goto usage;
-
-       MSG("%p: Opening Demuxer..", decoder);
-       decoder->demux = demux_init(infile, &width, &height);
-       if (!decoder->demux) {
-               ERROR("%p: could not open demuxer", decoder);
-               goto fail;
-       }
-
-       MSG("%p: infile=%s, width=%d, height=%d", decoder, infile, width, height);
-
-       /* calculate output buffer parameters: */
-       width  = ALIGN2 (width, 4);        /* round up to macroblocks */
-       height = ALIGN2 (height, 4);       /* round up to macroblocks */
-       padded_width  = ALIGN2 (width + (2*PADX), 7);
-       padded_height = height + 4*PADY;
-       num_buffers   = MIN(16, 32768 / ((width/16) * (height/16))) + 3;
-
-       MSG("%p: padded_width=%d, padded_height=%d, num_buffers=%d",
-                       decoder, padded_width, padded_height, num_buffers);
+               if (check_args(argc, argv) || !infile)
+                       goto usage;
+               MSG("%p: Opening Demuxer..", decoder);
+               decoder->demux = demux_init(infile, &width, &height);
+               if (!decoder->demux) {
+                       ERROR("%p: could not open demuxer", decoder);
+                       goto fail;
+               }
+               MSG("%p: infile=%s, width=%d, height=%d", decoder, infile, width, height);
+
+               /* calculate output buffer parameters: */
+               width  = ALIGN2 (width, 4);        /* round up to macroblocks */
+               height = ALIGN2 (height, 4);       /* round up to macroblocks */
+               if (decoder->demux->cc->codec_id == CODEC_ID_MPEG2VIDEO) {
+                       padded_width = width;
+                       padded_height= height;
+               }
+               else {
+                       padded_width  = ALIGN2 (width + (2*PADX), 7);
+                       padded_height = height + 4*PADY;
+               }
+               decoder->num_outBuf   = MIN(16, 32768 / ((width/16) * (height/16))) + 3;
+               decoder->padded_width = padded_width;
+               decoder->padded_height = padded_height;
+               MSG("%p: padded_width=%d, padded_height=%d, num_buffers=%d",
+                       decoder, padded_width, padded_height, decoder->num_outBuf);
+               dce_set_fd(decoder->disp->fd);
+               dev = dce_init();
+               if(dev == NULL) {
+                       ERROR("%p: dce init failed", dev);
+                       goto fail;
+               }
+               decoder->framebuf = disp_get_fb(decoder->disp);
+               if (! disp_get_vid_buffers(decoder->disp, decoder->num_outBuf,
+                               FOURCC_STR("NV12"), decoder->padded_width, decoder->padded_height)) {
+                       ERROR("%p: could not allocate buffers", decoder);
+                       goto fail;
+               }
+               if(inloop) inloop = 2; /*Don't bother about looping if not asked to*/
+    }
 
        if (!decoder->disp->multiplanar) {
                decoder->uv_offset = padded_width * padded_height;
+               decoder->outBuf_fd = malloc(sizeof(int)*decoder->num_outBuf);
                MSG("%p: uv_offset=%d", decoder, decoder->uv_offset);
        }
+       else{
+               decoder->outBuf_fd = malloc(sizeof(int)*(decoder->num_outBuf*2));
+       }
 
        decoder->input_sz = width * height;
        decoder->input_bo = omap_bo_new(decoder->disp->dev,
                        decoder->input_sz, OMAP_BO_WC);
        decoder->input = omap_bo_map(decoder->input_bo);
 
-       decoder->framebuf = disp_get_fb(decoder->disp);
 
-       if (! disp_get_vid_buffers(decoder->disp, num_buffers,
-                       FOURCC_STR("NV12"), padded_width, padded_height)) {
-               ERROR("%p: could not allocate buffers", decoder);
-               goto fail;
-       }
 
        MSG("%p: Opening Engine..", decoder);
-       dce_set_fd(decoder->disp->fd);
        decoder->engine = Engine_open("ivahd_vidsvr", NULL, &ec);
        if (!decoder->engine) {
                ERROR("%p: could not open engine", decoder);
@@ -190,7 +220,7 @@ decoder_open(int argc, char **argv)
        decoder->params->operatingMode    = IVIDEO_DECODE_ONLY;
        decoder->params->displayDelay     = IVIDDEC3_DISPLAY_DELAY_AUTO;
        decoder->params->displayBufsMode  = IVIDDEC3_DISPLAYBUFS_EMBEDDED;
-MSG("displayBufsMode: %d", decoder->params->displayBufsMode);
+       MSG("displayBufsMode: %d", decoder->params->displayBufsMode);
        decoder->params->inputDataMode    = IVIDEO_ENTIREFRAME;
        decoder->params->metadataType[0]  = IVIDEO_METADATAPLANE_NONE;
        decoder->params->metadataType[1]  = IVIDEO_METADATAPLANE_NONE;
@@ -200,8 +230,20 @@ MSG("displayBufsMode: %d", decoder->params->displayBufsMode);
        decoder->params->numOutputDataUnits = 0;
        decoder->params->errorInfoMode    = IVIDEO_ERRORINFO_OFF;
 
-       decoder->codec = VIDDEC3_create(decoder->engine,
-                       "ivahd_h264dec", decoder->params);
+       if (decoder->demux->cc->codec_id == CODEC_ID_MPEG2VIDEO) {
+            decoder->codec = VIDDEC3_create(decoder->engine,
+                                        "ivahd_mpeg2vdec", decoder->params);
+        }
+        else if (decoder->demux->cc->codec_id == CODEC_ID_H264) {
+            decoder->codec = VIDDEC3_create(decoder->engine,
+                                        "ivahd_h264dec", decoder->params);
+        }
+       else if (decoder->demux->cc->codec_id == CODEC_ID_MPEG4) {
+               decoder->demux->first_in_buff = 1;
+               decoder->codec = VIDDEC3_create(decoder->engine,
+                                        "ivahd_mpeg4dec", decoder->params);
+       }
+
        if (!decoder->codec) {
                ERROR("%p: could not create codec", decoder);
                goto fail;
@@ -235,22 +277,18 @@ MSG("displayBufsMode: %d", decoder->params->displayBufsMode);
                goto fail;
        }
 
-       decoder->inBufs = calloc(1, sizeof(XDM2_BufDesc));
+       decoder->inBufs = dce_alloc(sizeof(XDM2_BufDesc));
        decoder->inBufs->numBufs = 1;
-       decoder->inBufs->descs[0].buf =
-                       (XDAS_Int8 *)omap_bo_handle(decoder->input_bo);
+       decoder->inBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_dmabuf(decoder->input_bo);
+       dce_buf_lock(1, &(decoder->inBufs->descs[0].buf));
        decoder->inBufs->descs[0].bufSize.bytes = omap_bo_size(decoder->input_bo);
-       decoder->inBufs->descs[0].memType = XDM_MEMTYPE_BO;
+       decoder->inBufs->descs[0].memType = XDM_MEMTYPE_RAW;
 
-       decoder->outBufs = calloc(1, sizeof(XDM2_BufDesc));
-       decoder->outBufs->numBufs = 2;
-       decoder->outBufs->descs[0].memType = XDM_MEMTYPE_BO;
 
-       if (decoder->disp->multiplanar) {
-               decoder->outBufs->descs[1].memType = XDM_MEMTYPE_BO;
-       } else {
-               decoder->outBufs->descs[1].memType = XDM_MEMTYPE_BO_OFFSET;
-       }
+       decoder->outBufs = dce_alloc(sizeof(XDM2_BufDesc));
+       decoder->outBufs->numBufs = 2;
+       decoder->outBufs->descs[0].memType = XDM_MEMTYPE_RAW;
+       decoder->outBufs->descs[1].memType = XDM_MEMTYPE_RAW;
 
        decoder->inArgs = dce_alloc(sizeof(IVIDDEC3_InArgs));
        decoder->inArgs->size = sizeof(IVIDDEC3_InArgs);
@@ -265,6 +303,7 @@ MSG("displayBufsMode: %d", decoder->params->displayBufsMode);
 usage:
        usage(argv[0]);
 fail:
+       if(inloop) inloop = 1; /*Error case: delete everything*/
        if (decoder)
                decoder_close(decoder);
        return NULL;
@@ -278,18 +317,20 @@ decoder_process(struct decoder *decoder)
        VIDDEC3_InArgs *inArgs = decoder->inArgs;
        VIDDEC3_OutArgs *outArgs = decoder->outArgs;
        struct buffer *buf;
+       int freeBufCount =0;
        int i, n;
-
-       buf = disp_get_vid_buffer(decoder->disp);
-       if (!buf) {
-               ERROR("%p: fail: out of buffers", decoder);
-               return -1;
-       }
+       XDAS_Int32 err;
+       int eof = 0; /* end of file flag */
 
        /* demux; in loop mode, we can do two tries at the end of the stream. */
        for (i = 0; i < 2; i++) {
                n = demux_read(decoder->demux, decoder->input, decoder->input_sz);
                if (n) {
+                       buf = disp_get_vid_buffer(decoder->disp);
+                       if (!buf) {
+                               ERROR("%p: fail: out of buffers", decoder);
+                               return -1;
+                       }
                        inBufs->descs[0].bufSize.bytes = n;
                        inArgs->numBytes = n;
                        DBG("%p: push: %d bytes (%p)", decoder, n, buf);
@@ -305,85 +346,124 @@ decoder_process(struct decoder *decoder)
                                        return -1;
                                }
                                MSG("%p: rewound.", decoder);
-                               continue;
+                               if(!inloop) continue;
                        }
-
-                       /* Not in loop or second try: end. */
+                       eof = 1; /* set the flag for end of file to 1 */
+                       /* Control call call with XDM_FLUSH command */
+                       err = VIDDEC3_control(decoder->codec, XDM_FLUSH,
+                                       decoder->dynParams, decoder->status);
                        inBufs->numBufs = 0;
+                       outBufs->numBufs = 0;
                        inArgs->inputID = 0;
                }
                break;
        }
 
-       inArgs->inputID = (XDAS_Int32)buf;
-       outBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_handle(buf->bo[0]);
-
-       if (buf->multiplanar) {
-               outBufs->descs[0].bufSize.bytes = omap_bo_size(buf->bo[0]);
-               outBufs->descs[1].buf = (XDAS_Int8 *)omap_bo_handle(buf->bo[1]);
-               outBufs->descs[1].bufSize.bytes = omap_bo_size(buf->bo[1]);
-       } else {
-               outBufs->descs[0].bufSize.bytes = decoder->uv_offset;
-               outBufs->descs[1].buf = (XDAS_Int8 *)decoder->uv_offset;
-               outBufs->descs[1].bufSize.bytes = omap_bo_size(buf->bo[0]) - decoder->uv_offset;
-       }
+        /*set the parameters if it is not the end of file */
+       if (!eof) {
+               inArgs->inputID = (XDAS_Int32)buf;
+               outBufs->descs[0].buf = buf->fd[0];
+               outBufs->descs[1].buf = (buf->multiplanar) ?buf->fd[1]:(XDAS_Int8 *)((outBufs->descs[0].buf));
 
-       if (no_process) {
-               /* Do not process. This is for benchmarking. We need to "fake"
-                * the outArgs. */
-               outArgs->outputID[0] = buf;
-               outArgs->outputID[1] = NULL;
-               outArgs->freeBufID[0] = buf;
-               outArgs->freeBufID[1] = NULL;
-               outArgs->outBufsInUseFlag = 0;
-
-       } else {
-               XDAS_Int32 err;
-               suseconds_t tproc;
-               tproc = mark(NULL);
-               err = VIDDEC3_process(decoder->codec, inBufs, outBufs, inArgs, outArgs);
-               DBG("%p: processed returned in: %ldus", decoder, (long int)mark(&tproc));
-               if (err) {
-                       ERROR("%p: process returned error: %d", decoder, err);
-                       ERROR("%p: extendedError: %08x", decoder, outArgs->extendedError);
-                       if (XDM_ISFATALERROR(outArgs->extendedError))
-                               return -1;
+
+               if(buf->multiplanar){
+                       decoder->outBuf_fd[0] = buf->fd[0];
+                       decoder->outBuf_fd[1] = buf->fd[1];
+            dce_buf_lock(2,decoder->outBuf_fd);
+               }
+               else{
+                       decoder->outBuf_fd[0] = buf->fd[0];
+                       dce_buf_lock(1,decoder->outBuf_fd);
                }
+               decoder->outBufs->descs[0].bufSize.bytes =decoder->padded_width*decoder->padded_height;
+               decoder->outBufs->descs[1].bufSize.bytes = decoder->padded_width* (decoder->padded_height/2);
        }
 
-       for (i = 0; outArgs->outputID[i]; i++) {
-               /* calculate offset to region of interest */
-               XDM_Rect *r = &(outArgs->displayBufs.bufDesc[0].activeFrameRegion);
-
-               /* get the output buffer and write it to file */
-               buf = (struct buffer *)outArgs->outputID[i];
-               DBG("%p: post buffer: %p %d,%d %d,%d", decoder, buf,
-                               r->topLeft.x, r->topLeft.y,
-                               r->bottomRight.x, r->bottomRight.y);
-               disp_post_vid_buffer(decoder->disp, buf,
-                               r->topLeft.x, r->topLeft.y,
-                               r->bottomRight.x - r->topLeft.x,
-                               r->bottomRight.y - r->topLeft.y);
-               DBG("%p: display in: %ldus", decoder, (long int)mark(&decoder->tdisp));
-       }
+       do {
+               if (no_process) {
+                       /* Do not process. This is for benchmarking. We need to "fake"
+                        * the outArgs. */
+                       outArgs->outputID[0] = 0;
+                       outArgs->freeBufID[0] = 0;
+                       if(!eof) {
+                               outArgs->outputID[0] = buf;
+                               outArgs->freeBufID[0] = buf;
+                       }
+                       outArgs->outputID[1] = NULL;
+                       outArgs->freeBufID[1] = NULL;
+                       outArgs->outBufsInUseFlag = 0;
 
-       for (i = 0; outArgs->freeBufID[i]; i++) {
-               buf = (struct buffer *)outArgs->freeBufID[i];
-               disp_put_vid_buffer(decoder->disp, buf);
-       }
+               } else {
+                       suseconds_t tproc;
+                       tproc = mark(NULL);
+                       err = VIDDEC3_process(decoder->codec, inBufs, outBufs, inArgs, outArgs);
+                       DBG("%p: processed returned in: %ldus", decoder, (long int)mark(&tproc));
+                       if (err) {
+                               ERROR("%p: process returned error: %d", decoder, err);
+                               ERROR("%p: extendedError: %08x", decoder, outArgs->extendedError);
+                               if (XDM_ISFATALERROR(outArgs->extendedError) || ( err == DCE_EXDM_UNSUPPORTED ) || ( err == DCE_EIPC_CALL_FAIL ) || ( err == DCE_EINVALID_INPUT ))
+                                       return -1;
+                       }
+               }
 
-       if (outArgs->outBufsInUseFlag) {
-               MSG("%p: TODO... outBufsInUseFlag", decoder); // XXX
-       }
+               for (i = 0; outArgs->outputID[i]; i++) {
+                       /* calculate offset to region of interest */
+                       XDM_Rect *r = &(outArgs->displayBufs.bufDesc[0].activeFrameRegion);
+
+                       /* get the output buffer and write it to file */
+                       buf = (struct buffer *)outArgs->outputID[i];
+                       if(!no_process)
+                               disp_post_vid_buffer(decoder->disp, buf,
+                                       r->topLeft.x, r->topLeft.y,
+                                       r->bottomRight.x - r->topLeft.x,
+                                       r->bottomRight.y - r->topLeft.y);
+               }
+
+               for (i = 0; outArgs->freeBufID[i]; i++) {
+                       buf = (struct buffer *)outArgs->freeBufID[i];
+                       disp_put_vid_buffer(decoder->disp, buf);
+
+                       if(buf->multiplanar){
+                               decoder->outBuf_fd[freeBufCount++] = buf->fd[0];
+                               decoder->outBuf_fd[freeBufCount++] = buf->fd[1];
+                       }
+                       else{
+                               decoder->outBuf_fd[freeBufCount++] = buf->fd[0];
+                               DBG("FreeBufID: %p fd:%d\n", outArgs->freeBufID[i], buf->fd[0]);
+                       }
+               }
+
+               if(freeBufCount){
+            if(!eof)dce_buf_unlock(freeBufCount,decoder->outBuf_fd);
+                       freeBufCount =0;
+               }
+               if (outArgs->outBufsInUseFlag) {
+                       MSG("%p: TODO... outBufsInUseFlag", decoder); // XXX
+               }
+       } while ((err == 0) && eof && !no_process);
 
        return (inBufs->numBufs > 0) ? 0 : -1;
 }
 
+void *decode_stream(void *decoderHandle)
+{
+       int ret = 0;
+       struct decoder *decoder = (struct decoder*)decoderHandle;
+    int n = 0;
+    if(!decoder) goto exit;
+
+    while((ret = decoder_process(decoder)) == 0);
+    if((ret != -1 && ret != 0) && inloop) inloop = 1; /*Assuming Good case. Otherwise logic gets messy*/
+    decoder_close(decoder);
+exit:
+       return NULL;
+}
+
 int
 main(int argc, char **argv)
 {
        struct decoder *decoders[8] = {};
-       int i, n, first = 0, ndecoders = 0;
+       int i, first = 0, ndecoders = 0;
 
        for (i = 1; i < argc; i++) {
                if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
@@ -398,6 +478,11 @@ main(int argc, char **argv)
                        no_process = 1;
                        argv[i] = NULL;
 
+               } else if (!strcmp(argv[i], "--inloop")) {
+                       inloop = 1; // this means inloop is detected
+                       DBG("detected inloop = %d\n", inloop);
+                       loop = 1; //we want rewind as well
+                       argv[i] = NULL;
                } else if (!strcmp(argv[i], "--")) {
                        argv[first] = argv[0];
                        decoders[ndecoders++] = decoder_open(i - first, &argv[first]);
@@ -406,21 +491,37 @@ main(int argc, char **argv)
        }
 
        argv[first] = argv[0];
-       decoders[ndecoders++] = decoder_open(i - first, &argv[first]);
+       argc = i - first;
 
-       do {
-               for (i = 0, n = 0; i < ndecoders; i++) {
+       if(ndecoders) decoders[ndecoders++] = decoder_open(argc ,&argv[first]);
+
+       if (ndecoders > 1) {
+               pthread_t threadIds[8];
+
+               for (i = 0; i < ndecoders; i++) {
                        if (decoders[i]) {
-                               int ret = decoder_process(decoders[i]);
-                               if (ret) {
-                                       decoder_close(decoders[i]);
-                                       decoders[i] = NULL;
-                                       continue;
-                               }
-                               n++;
+                               int ret = pthread_create(&threadIds[i], NULL,
+                                               &decode_stream, decoders[i]);
+                               if (ret != 0)
+                                       ERROR("%p: creation of pthread, error: %d",
+                                                       decoders[i], ret);
                        }
                }
-       } while(n > 0);
+
+               for (i = 0; i < ndecoders; i++) {
+                       pthread_join(threadIds[i], NULL);
+               }
+       }
+       else {
+               int itr = 0;
+               do {
+                       decoders[0] = decoder_open(argc, &argv[first]);
+                       decode_stream(decoders[0]);
+                       if (inloop) {
+                               MSG("=================Iteration %d complete =============== %d\n", ++itr);
+                       }
+               }while(inloop);
+       }
 
        return 0;
 }