add viddec3 decoder test
authorRob Clark <rob@ti.com>
Thu, 26 Jan 2012 20:24:26 +0000 (14:24 -0600)
committerRob Clark <rob@ti.com>
Thu, 26 Jan 2012 20:24:30 +0000 (14:24 -0600)
.gitignore
Makefile.am
README
configure.ac
util/Makefile.am
util/demux.c [new file with mode: 0644]
util/demux.h [new file with mode: 0644]
util/util.h
viddec3test.c [new file with mode: 0644]

index b4f9d7d137afb979c2086b8eb95d0718b339ddf6..ef0bd422a83a3bc29b63d83d88713ee4bd55d64c 100644 (file)
@@ -29,3 +29,4 @@ depcomp
 # test executables:
 dmabuftest
 fliptest
+viddec3test
index 95e8e22f4142bd444edb9e8b733261a557ae152c..e176126d2afd42cb21e3d349702713544308ab72 100644 (file)
 SUBDIRS = util
 bin_PROGRAMS = fliptest dmabuftest
 
-LDADD_COMMON = @DRM_LIBS@ @X11_LIBS@ util/libutil.la
-CFLAGS = @DRM_CFLAGS@ @X11_CFLAGS@ @WARN_CFLAGS@ -I$(top_srcdir)/util
+if ENABLE_DCE
+bin_PROGRAMS += viddec3test
+endif
+
+LDADD_COMMON = util/libutil.la @DRM_LIBS@ @X11_LIBS@ @DCE_LIBS@
+CFLAGS = @DRM_CFLAGS@ @X11_CFLAGS@ @DCE_CFLAGS@ @WARN_CFLAGS@ -I$(top_srcdir)/util
 
 fliptest_SOURCES = fliptest.c
-fliptest_LDADD = $(LDADD_COMMON) util/libutil.la
+fliptest_LDADD = $(LDADD_COMMON)
 
 dmabuftest_SOURCES = dmabuftest.c
-dmabuftest_LDADD = $(LDADD_COMMON) util/libutil.la
+dmabuftest_LDADD = $(LDADD_COMMON)
+
+if ENABLE_DCE
+viddec3test_SOURCES = viddec3test.c
+viddec3test_LDADD = $(LDADD_COMMON)
+endif
diff --git a/README b/README
index 7c80a3d8ad244615d658a61bd0ee208464b66c7d..e0668abb26566208b8577596a46fc52e198b2d9a 100644 (file)
--- a/README
+++ b/README
@@ -1 +1,8 @@
 A home for omapdrm tests.
+
+Example to run w/ KMS for full-screen overlay display:
+sudo ./viddec3test -s 7:1920x1080 ~/Videos/h264/quantum_of_solace-tlr1_h1080p.mov
+
+Example to run with x11/dri2video for windowed display:
+export DISPLAY=:0.0
+./viddec3test ~/Videos/h264/quantum_of_solace-tlr1_h1080p.mov
index 47a356510d494d8034660f3d3a93d922e60d2832..06a930f36f04f5620e03a2e8e94ee38b68f9bf2b 100644 (file)
@@ -36,7 +36,6 @@ PKG_CHECK_MODULES(DRM, libdrm libdrm_omap)
 
 # Check optional X11:
 PKG_CHECK_MODULES(X11, x11 libdri2, [HAVE_X11=yes], [HAVE_X11=no])
-
 if test "x$HAVE_X11" = "xyes"; then
        AC_DEFINE(HAVE_X11, 1, [Have X11 support])
 else
@@ -44,6 +43,15 @@ else
 fi
 AM_CONDITIONAL(ENABLE_X11, [test "x$HAVE_X11" = xyes])
 
+# Check for libdce and libav..
+PKG_CHECK_MODULES(DCE, libdce libavformat libavutil, [HAVE_DCE=yes], [HAVE_DCE=no])
+if test "x$HAVE_DCE" = "xyes"; then
+       AC_DEFINE(HAVE_DCE, 1, [Have DCE support])
+       AC_MSG_NOTICE([Detected libdce and libavformat, building video codec tests])
+else
+       AC_MSG_WARN([No libdce and/or libavformat support detected, disabling video codec tests])
+fi
+AM_CONDITIONAL(ENABLE_DCE, [test "x$HAVE_DCE" = xyes])
 
 dnl ===========================================================================
 dnl check compiler flags
index 5c063dc58f152819f49d2ed8b47c393424dfcc0e..9d3ddd2fa24b1530d7707866e0f9b1e8c5ba9777 100644 (file)
@@ -26,5 +26,9 @@ if ENABLE_X11
 libutil_la_SOURCES += display-x11.c
 endif
 
-libutil_la_LIBADD = @DRM_LIBS@ @X11_LIBS@
-libutil_la_CFLAGS = @DRM_CFLAGS@ @X11_CFLAGS@ @WARN_CFLAGS@
+if ENABLE_DCE
+libutil_la_SOURCES += demux.c
+endif
+
+libutil_la_LIBADD = @DRM_LIBS@ @X11_LIBS@ @DCE_LIBS@
+libutil_la_CFLAGS = @DRM_CFLAGS@ @X11_CFLAGS@ @DCE_CFLAGS@ @WARN_CFLAGS@
diff --git a/util/demux.c b/util/demux.c
new file mode 100644 (file)
index 0000000..3aee5f3
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+#include <libavformat/avformat.h>
+#include <libavcodec/avcodec.h>
+
+#include "util.h"
+
+struct demux {
+       AVFormatContext *afc;
+       AVStream *st;
+       AVCodecContext *cc;
+       AVBitStreamFilterContext *bsf;
+};
+
+static AVFormatContext *
+open_file(const char *filename)
+{
+       AVFormatContext *afc;
+       int err = av_open_input_file(&afc, filename, NULL, 0, NULL);
+
+       if (!err)
+               err = av_find_stream_info(afc);
+
+       if (err < 0) {
+               ERROR("%s: lavf error %d", filename, err);
+               exit(1);
+       }
+
+       dump_format(afc, 0, filename, 0);
+
+       return afc;
+}
+
+static AVStream *
+find_stream(AVFormatContext *afc)
+{
+       AVStream *st = NULL;
+       unsigned int i;
+
+       for (i = 0; i < afc->nb_streams; i++) {
+               if (afc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st)
+                       st = afc->streams[i];
+               else
+                       afc->streams[i]->discard = AVDISCARD_ALL;
+       }
+
+       return st;
+}
+
+static struct demux * open_stream(const char * filename, int *width, int *height)
+{
+       AVFormatContext *afc = open_file(filename);
+       AVStream *st = find_stream(afc);
+       AVCodecContext *cc = st->codec;
+       AVBitStreamFilterContext *bsf = NULL;
+       struct demux *demux;
+
+       if (cc->codec_id != CODEC_ID_H264) {
+               ERROR("could not open '%s': unsupported codec %d", filename, cc->codec_id);
+               return NULL;
+       }
+
+       if (cc->extradata && cc->extradata_size > 0 && cc->extradata[0] == 1) {
+               MSG("initializing bitstream filter");
+               bsf = av_bitstream_filter_init("h264_mp4toannexb");
+               if (!bsf) {
+                       ERROR("could not open '%s': failed to initialize bitstream filter", filename);
+                       return NULL;
+               }
+       }
+
+       *width = cc->width;
+       *height = cc->height;
+
+       demux = calloc(1, sizeof(*demux));
+
+       demux->afc = afc;
+       demux->cc  = cc;
+       demux->st  = st;
+       demux->bsf = bsf;
+
+       return demux;
+}
+
+struct demux * demux_init(const char * filename, int *width, int *height)
+{
+       av_register_all();
+       avcodec_register_all();
+       return open_stream(filename, width, height);
+}
+
+int demux_read(struct demux *demux, char *input, int size)
+{
+       AVPacket pk = {};
+
+       while (!av_read_frame(demux->afc, &pk)) {
+               if (pk.stream_index == demux->st->index) {
+                       uint8_t *buf;
+                       int bufsize;
+
+                       if (demux->bsf) {
+                               int ret;
+                               MSG("%p %d bytes", pk.data, pk.size);
+                               ret = av_bitstream_filter_filter(demux->bsf, demux->cc,
+                                               NULL, &buf, &bufsize, pk.data, pk.size, 0);
+                               if (ret < 0) {
+                                       ERROR("bsf error: %d", ret);
+                                       return 0;
+                               }
+                       } else {
+                               buf     = pk.data;
+                               bufsize = pk.size;
+                       }
+
+                       if (bufsize > size)
+                               bufsize = size;
+
+                       memcpy(input, buf, bufsize);
+
+                       if (demux->bsf)
+                               av_free(buf);
+
+                       av_free_packet(&pk);
+
+                       return bufsize;
+               }
+               av_free_packet(&pk);
+       }
+
+       return 0;
+}
+
+void demux_deinit(struct demux *demux)
+{
+       av_close_input_file(demux->afc);
+       if (demux->bsf)
+               av_bitstream_filter_close(demux->bsf);
+       free(demux);
+}
diff --git a/util/demux.h b/util/demux.h
new file mode 100644 (file)
index 0000000..058997d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011, 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.
+ */
+
+#ifndef __DEMUX_H__
+#define __DEMUX_H__
+
+struct demux;
+
+struct demux * demux_init(const char * filename, int *width, int *height);
+int demux_read(struct demux *demux, char *input, int size);
+void demux_deinit(struct demux *demux);
+
+#endif /* __DEMUX_H__ */
index 720c11b802cb77f5dddf2a36d00e8095ec62d6eb..cba6234b73dd131228a2444e96bea0966bbfb08a 100644 (file)
@@ -29,6 +29,9 @@
 #include <omap_drm.h>
 #include <omap_drmif.h>
 
+/* align x to next highest multiple of 2^n */
+#define ALIGN2(x,n)   (((x) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1))
+
 typedef enum {
        false = 0,
        true = 1
diff --git a/viddec3test.c b/viddec3test.c
new file mode 100644 (file)
index 0000000..6ee59fd
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * 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 <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 "util.h"
+#include "demux.h"
+
+/* Padding for width as per Codec Requirement (for h264) */
+#define PADX  32
+/* Padding for height as per Codec requirement (for h264)*/
+#define PADY  24
+
+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 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;
+       VIDDEC3_DynamicParams *dynParams;
+       VIDDEC3_Status *status;
+       XDM2_BufDesc *inBufs;
+       XDM2_BufDesc *outBufs;
+       VIDDEC3_InArgs *inArgs;
+       VIDDEC3_OutArgs *outArgs;
+
+       MSG("Opening Display..");
+       disp = disp_open(argc, argv);
+       if (!disp) {
+               usage(argv[0]);
+               return 1;
+       }
+
+       /* 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;
+       }
+
+       if (check_args(argc, argv) || !infile) {
+               ERROR("invalid args");
+               goto usage;
+       }
+
+       MSG("Opening Demuxer..");
+       demux = demux_init(infile, &width, &height);
+       if (!demux) {
+               goto usage;
+       }
+
+       MSG("infile=%s, width=%d, height=%d", 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);
+
+       input_sz = width * height;
+       input_bo = omap_bo_new(disp->dev, input_sz, OMAP_BO_WC);
+       input = omap_bo_map(input_bo);
+
+       framebuf = disp_get_fb(disp);
+
+       if (! disp_get_vid_buffers(disp, num_buffers, FOURCC_STR("NV12"),
+                       padded_width, padded_height)) {
+               goto out;
+       }
+
+       MSG("Opening Engine..");
+       dce_set_fd(disp->fd);
+       engine = Engine_open("ivahd_vidsvr", NULL, &ec);
+       if (!engine) {
+               ERROR("fail");
+               goto out;
+       }
+
+       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;
+       }
+
+       dynParams = dce_alloc(sizeof(IVIDDEC3_DynamicParams));
+       dynParams->size = sizeof(IVIDDEC3_DynamicParams);
+
+       dynParams->decodeHeader  = XDM_DECODE_AU;
+
+       /*Not Supported: Set default*/
+       dynParams->displayWidth  = 0;
+       dynParams->frameSkipMode = IVIDEO_NO_SKIP;
+       dynParams->newFrameFlag  = XDAS_TRUE;
+
+       status = dce_alloc(sizeof(IVIDDEC3_Status));
+       status->size = sizeof(IVIDDEC3_Status);
+
+       err = VIDDEC3_control(codec, XDM_SETPARAMS, dynParams, status);
+       if (err) {
+               ERROR("fail: %d", err);
+               goto out;
+       }
+
+       /* not entirely sure why we need to call this here.. just copying omx.. */
+       err = VIDDEC3_control(codec, XDM_GETBUFINFO, dynParams, status);
+       if (err) {
+               ERROR("fail: %d", err);
+               goto out;
+       }
+
+       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;
+
+       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);
+
+       outArgs = dce_alloc(sizeof(IVIDDEC3_OutArgs));
+       outArgs->size = sizeof(IVIDDEC3_OutArgs);
+
+       while (inBufs->numBufs && outBufs->numBufs) {
+               struct buffer *buf;
+               int n;
+               suseconds_t t;
+
+               buf = disp_get_vid_buffer(disp);
+               if (!buf) {
+                       ERROR("fail: out of buffers");
+                       goto shutdown;
+               }
+
+               n = demux_read(demux, input, input_sz);
+               if (n) {
+                       inBufs->descs[0].bufSize.bytes = n;
+                       inArgs->numBytes = n;
+                       MSG("push: %d bytes (%p)", n, buf);
+               } else {
+                       /* end of input.. do we need to flush? */
+                       MSG("end of input");
+                       inBufs->numBufs = 0;
+                       inArgs->inputID = 0;
+               }
+
+               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]);
+
+               t = mark(NULL);
+               err = VIDDEC3_process(codec, inBufs, outBufs, inArgs, outArgs);
+               MSG("processed returned in: %ldus", (long int)mark(&t));
+               if (err) {
+                       ERROR("process returned error: %d", err);
+                       ERROR("extendedError: %08x", outArgs->extendedError);
+                       if (XDM_ISFATALERROR(outArgs->extendedError))
+                               goto shutdown;
+               }
+
+               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];
+                       MSG("post buffer: %p %d,%d %d,%d", 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);
+               }
+
+               for (i = 0; outArgs->freeBufID[i]; i++) {
+                       buf = (struct buffer *)outArgs->freeBufID[i];
+                       disp_put_vid_buffer(disp, buf);
+               }
+
+               if (outArgs->outBufsInUseFlag) {
+                       MSG("TODO... outBufsInUseFlag"); // XXX
+               }
+       }
+
+       MSG("Ok!");
+       ret = 0;
+
+shutdown:
+       VIDDEC3_delete(codec);
+
+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);
+
+       return ret;
+
+usage:
+       usage(argv[0]);
+       return ret;
+}