diff --git a/viddec3test.c b/viddec3test.c
index 9e0fa0476e9368195039df81d0b58f1cb6f17098..c7f3626a6bc3efa3440179844fc53ee0eb81305c 100644 (file)
--- a/viddec3test.c
+++ b/viddec3test.c
* 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"
+/* Used for mpeg4 esds data copy */
+int first_in_buff = 0;
+
/* Padding for width as per Codec Requirement (for h264) */
#define PADX 32
/* Padding for height as per Codec requirement (for h264)*/
#define PADY 24
+/* omap drm device handle */
+struct omap_device *dev = NULL;
-static void
-usage(char *name)
-{
- MSG("Usage: %s [OPTIONS] INFILE", name);
- MSG("Test of viddec3 decoder.");
- MSG("");
- disp_usage();
-}
-
-int
-main(int argc, char **argv)
-{
+struct decoder {
struct display *disp;
struct demux *demux;
struct buffer *framebuf;
- char *infile = NULL;
- char *input = NULL;
- struct omap_bo *input_bo = NULL;
- int ret = 1, i, input_sz, num_buffers;
- int width, height, padded_width, padded_height;
- Engine_Error ec;
- XDAS_Int32 err;
Engine_Handle engine;
VIDDEC3_Handle codec;
VIDDEC3_Params *params;
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;
+
+/* When true, loop at end of playback. */
+static int loop = 0;
+
+static void
+usage(char *name)
+{
+ MSG("Usage: %s [OPTIONS] INFILE", name);
+ MSG("Test of viddec3 decoder.");
+ MSG("");
+ MSG("viddec3test options:");
+ MSG("\t-h, --help: Print this help and exit.");
+ MSG("\t--loop\tRestart playback at end of stream.");
+ MSG("\t--no-process\tDo not actually call VIDDEC3_process method. For benchmarking.");
+ MSG("");
+ disp_usage();
+}
- MSG("Opening Display..");
- disp = disp_open(argc, argv);
- if (!disp) {
- usage(argv[0]);
- return 1;
+static void
+decoder_close(struct decoder *decoder)
+{
+ /* free output buffers allocated by display */
+ 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->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->codec) VIDDEC3_delete(decoder->codec);
+ if (decoder->engine) Engine_close(decoder->engine);
+ if (dev) dce_deinit(dev);
+ if (decoder->input_bo) omap_bo_del(decoder->input_bo);
+ if (decoder->demux) demux_deinit(decoder->demux);
+ if (decoder->disp) disp_close(decoder->disp);
+ if (decoder->outBuf_fd) free(decoder->outBuf_fd);
+ free(decoder);
+}
+
+static struct decoder *
+decoder_open(int argc, char **argv)
+{
+ struct decoder *decoder;
+ char *infile = NULL;
+ int i;
+ 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++) {
break;
}
- if (check_args(argc, argv) || !infile) {
- ERROR("invalid args");
+ if (check_args(argc, argv) || !infile)
goto usage;
- }
- MSG("Opening Demuxer..");
- demux = demux_init(infile, &width, &height);
- if (!demux) {
- 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("infile=%s, width=%d, height=%d", infile, width, height);
+ 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("padded_width=%d, padded_height=%d, num_buffers=%d",
- padded_width, padded_height, num_buffers);
+ 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);
+
+ 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));
+ }
- input_sz = width * height;
- input_bo = omap_bo_new(disp->dev, input_sz, OMAP_BO_WC);
- input = omap_bo_map(input_bo);
+ 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);
- framebuf = disp_get_fb(disp);
+ if (! disp_get_vid_buffers(decoder->disp, decoder->num_outBuf,
+ FOURCC_STR("NV12"), padded_width, padded_height)) {
+ ERROR("%p: could not allocate buffers", decoder);
+ goto fail;
+ }
- if (! disp_get_vid_buffers(disp, num_buffers, FOURCC_STR("NV12"),
- padded_width, padded_height)) {
- goto out;
+ MSG("%p: Opening Engine..", decoder);
+ dce_set_fd(decoder->disp->fd);
+ dev = dce_init();
+ if(dev == NULL) {
+ ERROR("%p: dce init failed", dev);
+ goto fail;
+ }
+ decoder->engine = Engine_open("ivahd_vidsvr", NULL, &ec);
+ if (!decoder->engine) {
+ ERROR("%p: could not open engine", decoder);
+ goto fail;
}
- MSG("Opening Engine..");
- dce_set_fd(disp->fd);
- engine = Engine_open("ivahd_vidsvr", NULL, &ec);
- if (!engine) {
- ERROR("fail");
- goto out;
+ decoder->params = dce_alloc(sizeof(IVIDDEC3_Params));
+ decoder->params->size = sizeof(IVIDDEC3_Params);
+
+ decoder->params->maxWidth = width;
+ decoder->params->maxHeight = height;
+ decoder->params->maxFrameRate = 30000;
+ decoder->params->maxBitRate = 10000000;
+ decoder->params->dataEndianness = XDM_BYTE;
+ decoder->params->forceChromaFormat= XDM_YUV_420SP;
+ 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);
+ decoder->params->inputDataMode = IVIDEO_ENTIREFRAME;
+ decoder->params->metadataType[0] = IVIDEO_METADATAPLANE_NONE;
+ decoder->params->metadataType[1] = IVIDEO_METADATAPLANE_NONE;
+ decoder->params->metadataType[2] = IVIDEO_METADATAPLANE_NONE;
+ decoder->params->numInputDataUnits= 0;
+ decoder->params->outputDataMode = IVIDEO_ENTIREFRAME;
+ decoder->params->numOutputDataUnits = 0;
+ decoder->params->errorInfoMode = IVIDEO_ERRORINFO_OFF;
+
+ 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) {
+ first_in_buff = 1;
+ decoder->codec = VIDDEC3_create(decoder->engine,
+ "ivahd_mpeg4dec", decoder->params);
}
- params = dce_alloc(sizeof(IVIDDEC3_Params));
- params->size = sizeof(IVIDDEC3_Params);
-
- params->maxWidth = width;
- params->maxHeight = height;
- params->maxFrameRate = 30000;
- params->maxBitRate = 10000000;
- params->dataEndianness = XDM_BYTE;
- params->forceChromaFormat= XDM_YUV_420SP;
- params->operatingMode = IVIDEO_DECODE_ONLY;
- params->displayDelay = IVIDDEC3_DISPLAY_DELAY_AUTO;
- params->displayBufsMode = IVIDDEC3_DISPLAYBUFS_EMBEDDED;
- params->inputDataMode = IVIDEO_ENTIREFRAME;
- params->metadataType[0] = IVIDEO_METADATAPLANE_NONE;
- params->metadataType[1] = IVIDEO_METADATAPLANE_NONE;
- params->metadataType[2] = IVIDEO_METADATAPLANE_NONE;
- params->numInputDataUnits= 0;
- params->outputDataMode = IVIDEO_ENTIREFRAME;
- params->numOutputDataUnits = 0;
- params->errorInfoMode = IVIDEO_ERRORINFO_OFF;
-
- codec = VIDDEC3_create(engine, "ivahd_h264dec", params);
- if (!codec) {
- ERROR("fail");
- goto out;
+ if (!decoder->codec) {
+ ERROR("%p: could not create codec", decoder);
+ goto fail;
}
- dynParams = dce_alloc(sizeof(IVIDDEC3_DynamicParams));
- dynParams->size = sizeof(IVIDDEC3_DynamicParams);
+ decoder->dynParams = dce_alloc(sizeof(IVIDDEC3_DynamicParams));
+ decoder->dynParams->size = sizeof(IVIDDEC3_DynamicParams);
- dynParams->decodeHeader = XDM_DECODE_AU;
+ decoder->dynParams->decodeHeader = XDM_DECODE_AU;
/*Not Supported: Set default*/
- dynParams->displayWidth = 0;
- dynParams->frameSkipMode = IVIDEO_NO_SKIP;
- dynParams->newFrameFlag = XDAS_TRUE;
+ decoder->dynParams->displayWidth = 0;
+ decoder->dynParams->frameSkipMode = IVIDEO_NO_SKIP;
+ decoder->dynParams->newFrameFlag = XDAS_TRUE;
- status = dce_alloc(sizeof(IVIDDEC3_Status));
- status->size = sizeof(IVIDDEC3_Status);
+ decoder->status = dce_alloc(sizeof(IVIDDEC3_Status));
+ decoder->status->size = sizeof(IVIDDEC3_Status);
- err = VIDDEC3_control(codec, XDM_SETPARAMS, dynParams, status);
+ err = VIDDEC3_control(decoder->codec, XDM_SETPARAMS,
+ decoder->dynParams, decoder->status);
if (err) {
- ERROR("fail: %d", err);
- goto out;
+ ERROR("%p: fail: %d", decoder, err);
+ goto fail;
}
/* not entirely sure why we need to call this here.. just copying omx.. */
- err = VIDDEC3_control(codec, XDM_GETBUFINFO, dynParams, status);
+ err = VIDDEC3_control(decoder->codec, XDM_GETBUFINFO,
+ decoder->dynParams, decoder->status);
if (err) {
- ERROR("fail: %d", err);
- goto out;
+ ERROR("%p: fail: %d", decoder, err);
+ goto fail;
}
- inBufs = malloc(sizeof(XDM2_BufDesc));
- inBufs->numBufs = 1;
- inBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_handle(input_bo);
- inBufs->descs[0].memType = XDM_MEMTYPE_BO;
+ decoder->inBufs = dce_alloc(sizeof(XDM2_BufDesc));
+ decoder->inBufs->numBufs = 1;
+ 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_RAW;
- outBufs = malloc(sizeof(XDM2_BufDesc));
- outBufs->numBufs = 2;
- outBufs->descs[0].memType = XDM_MEMTYPE_BO;
- outBufs->descs[1].memType = XDM_MEMTYPE_BO;
- inArgs = dce_alloc(sizeof(IVIDDEC3_InArgs));
- inArgs->size = sizeof(IVIDDEC3_InArgs);
+ 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;
- outArgs = dce_alloc(sizeof(IVIDDEC3_OutArgs));
- outArgs->size = sizeof(IVIDDEC3_OutArgs);
+ decoder->inArgs = dce_alloc(sizeof(IVIDDEC3_InArgs));
+ decoder->inArgs->size = sizeof(IVIDDEC3_InArgs);
- tdisp = mark(NULL);
+ decoder->outArgs = dce_alloc(sizeof(IVIDDEC3_OutArgs));
+ decoder->outArgs->size = sizeof(IVIDDEC3_OutArgs);
- while (inBufs->numBufs && outBufs->numBufs) {
- struct buffer *buf;
- int n;
- suseconds_t tproc;
+ decoder->tdisp = mark(NULL);
- buf = disp_get_vid_buffer(disp);
- if (!buf) {
- ERROR("fail: out of buffers");
- goto shutdown;
- }
+ return decoder;
+
+usage:
+ usage(argv[0]);
+fail:
+ if (decoder)
+ decoder_close(decoder);
+ return NULL;
+}
+
+static int
+decoder_process(struct decoder *decoder)
+{
+ XDM2_BufDesc *inBufs = decoder->inBufs;
+ XDM2_BufDesc *outBufs = decoder->outBufs;
+ VIDDEC3_InArgs *inArgs = decoder->inArgs;
+ VIDDEC3_OutArgs *outArgs = decoder->outArgs;
+ struct buffer *buf;
+ int freeBufCount =0;
+ int i, n;
+ XDAS_Int32 err;
+ int eof = 0; /* end of file flag */
+
+ buf = disp_get_vid_buffer(decoder->disp);
+ if (!buf) {
+ ERROR("%p: fail: out of buffers", decoder);
+ return -1;
+ }
- n = demux_read(demux, input, input_sz);
+ /* 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) {
+
inBufs->descs[0].bufSize.bytes = n;
inArgs->numBytes = n;
- MSG("push: %d bytes (%p)", n, buf);
+ DBG("%p: push: %d bytes (%p)", decoder, n, buf);
} else {
/* end of input.. do we need to flush? */
- MSG("end of input");
+ MSG("%p: end of input", decoder);
+
+ /* In loop mode: rewind and retry once. */
+ if (loop && i == 0) {
+ int err = demux_rewind(decoder->demux);
+ if (err < 0) {
+ ERROR("%p: demux_rewind returned error: %d", decoder, err);
+ return -1;
+ }
+ MSG("%p: rewound.", decoder);
+ continue;
+ }
+ 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;
+ }
+ /*set the parameters if it is not the end of file */
+ if (!eof) {
inArgs->inputID = (XDAS_Int32)buf;
- outBufs->descs[0].buf = (XDAS_Int8 *)omap_bo_handle(buf->bo[0]);
- outBufs->descs[1].buf = (XDAS_Int8 *)omap_bo_handle(buf->bo[1]);
-
- tproc = mark(NULL);
- err = VIDDEC3_process(codec, inBufs, outBufs, inArgs, outArgs);
- MSG("processed returned in: %ldus", (long int)mark(&tproc));
- if (err) {
- ERROR("process returned error: %d", err);
- ERROR("extendedError: %08x", outArgs->extendedError);
- if (XDM_ISFATALERROR(outArgs->extendedError))
- goto shutdown;
+ outBufs->descs[0].buf = buf->fd[0];
+ outBufs->descs[1].buf = (buf->multiplanar) ?buf->fd[1]:(XDAS_Int8 *)((outBufs->descs[0].buf));
+
+
+ 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);
+ }
+
+ do {
+ 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 {
+ 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;
+ }
}
for (i = 0; outArgs->outputID[i]; i++) {
/* get the output buffer and write it to file */
buf = (struct buffer *)outArgs->outputID[i];
- MSG("post buffer: %p %d,%d %d,%d", buf,
+ disp_post_vid_buffer(decoder->disp, buf,
r->topLeft.x, r->topLeft.y,
- r->bottomRight.x, r->bottomRight.y);
- disp_post_vid_buffer(disp, buf, r->topLeft.x, r->topLeft.y,
r->bottomRight.x - r->topLeft.x,
r->bottomRight.y - r->topLeft.y);
- MSG("display in: %ldus", (long int)mark(&tdisp));
}
for (i = 0; outArgs->freeBufID[i]; i++) {
buf = (struct buffer *)outArgs->freeBufID[i];
- disp_put_vid_buffer(disp, buf);
+ 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){
+ dce_buf_unlock(freeBufCount,decoder->outBuf_fd);
+ freeBufCount =0;
+ }
if (outArgs->outBufsInUseFlag) {
- MSG("TODO... outBufsInUseFlag"); // XXX
+ MSG("%p: TODO... outBufsInUseFlag", decoder); // XXX
+ }
+ } while ((err == 0) && eof);
+
+ return (inBufs->numBufs > 0) ? 0 : -1;
+}
+
+void *decode_stream(void *decoderHandle)
+{
+ int n = 0;
+ struct decoder *decoders = (struct decoder*)decoderHandle;
+
+ do {
+ if (decoders) {
+ int ret = decoder_process(decoders);
+ if (ret) {
+ decoder_close(decoders);
+ decoders = NULL;
+ n = 0;
+ continue;
+ }
+ n++;
+ }
+ } while(n > 0);
+
+ return NULL;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct decoder *decoders[8] = {};
+ int i, first = 0, ndecoders = 0;
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
+ usage(argv[0]);
+ exit(0);
+
+ } else if (!strcmp(argv[i], "--loop")) {
+ loop = 1;
+ argv[i] = NULL;
+
+ } else if (!strcmp(argv[i], "--no-process")) {
+ no_process = 1;
+ argv[i] = NULL;
+
+ } else if (!strcmp(argv[i], "--")) {
+ argv[first] = argv[0];
+ decoders[ndecoders++] = decoder_open(i - first, &argv[first]);
+ first = i;
}
}
- MSG("Ok!");
- ret = 0;
+ argv[first] = argv[0];
+
+ decoders[ndecoders++] = decoder_open(i - first, &argv[first]);
-shutdown:
- VIDDEC3_delete(codec);
+ if (ndecoders > 1) {
+ pthread_t threadIds[8];
-out:
- if (engine) Engine_close(engine);
- if (params) dce_free(params);
- if (dynParams) dce_free(dynParams);
- if (status) dce_free(status);
- if (inBufs) free(inBufs);
- if (outBufs) free(outBufs);
- if (inArgs) dce_free(inArgs);
- if (outArgs) dce_free(outArgs);
- if (input_bo) omap_bo_del(input_bo);
- if (demux) demux_deinit(demux);
+ for (i = 0; i < ndecoders; i++) {
+ if (decoders[i]) {
+ int ret = pthread_create(&threadIds[i], NULL,
+ &decode_stream, decoders[i]);
+ if (ret != 0)
+ ERROR("%p: creation of pthread, error: %d",
+ decoders[i], ret);
+ }
+ }
- return ret;
+ for (i = 0; i < ndecoders; i++) {
+ pthread_join(threadIds[i], NULL);
+ }
+ }
+ else {
+ decode_stream(decoders[0]);
+ }
-usage:
- usage(argv[0]);
- return ret;
+ return 0;
}