Initial commit
authorAngela Stegmaier <angelabaker@ti.com>
Wed, 19 Jun 2019 15:14:57 +0000 (10:14 -0500)
committerAngela Stegmaier <angelabaker@ti.com>
Wed, 19 Jun 2019 15:42:38 +0000 (10:42 -0500)
Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
Signed-off-by: David Huang <d-huang@ti.com>
.gitignore [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
README.txt [new file with mode: 0644]
autogen.sh [new file with mode: 0644]
configure.ac [new file with mode: 0644]
demux.c [new file with mode: 0644]
demux.h [new file with mode: 0644]
main.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..76cd141
--- /dev/null
@@ -0,0 +1,2 @@
+main.o
+tidec_decode
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..3c91449
--- /dev/null
@@ -0,0 +1,24 @@
+#
+#  Copyright (C) 2018 Texas Instruments
+#
+#  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/>.
+#
+
+bin_PROGRAMS = tidec_decode
+
+LDADD_COMMON = @DRM_LIBS@
+AM_CFLAGS = @DRM_CFLAGS@ @WARN_CFLAGS@ -I$(top_srcdir)/util
+LDFLAGS = -lm -lavcodec -lavutil -lavformat -lswresample -lbz2 -lz -llzma -ltheoraenc -ltheoradec -logg
+
+tidec_decode_SOURCES = main.c demux.c
+tidec_decode_LDADD = $(LDADD_COMMON)
diff --git a/README.txt b/README.txt
new file mode 100644 (file)
index 0000000..0c50665
--- /dev/null
@@ -0,0 +1,57 @@
+=======
+PREREQ:
+=======
+* cross compiler is in PATH, eg:
+       export PATH=$PATH:/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin
+* Modify the Makefile on to point to the proper directory on your machine or pass from command line:
+       DRMHEADERS --> should point to location of the DRM headers, eg:
+               DRMHEADERS = $HOME/buildroot/output/host/usr/aarch64-buildroot-linux-gnu/sysroot/usr
+* Modify the Makefile on to point to location of the Kernel headers (linux source code path), eg:
+        KERNELHEADERS = $HOME/ti-linux-kernel
+======
+BUILD:
+======
+make
+
+=======
+OUTPUT:
+=======
+tidec_decode binary
+
+=============
+SETUP TARGET:
+=============
+* Copy the output binary to the target rootfs
+* The following modules must also be present on the target:
+       - videobuf2-common.ko
+       - videobuf2-memops.ko
+       - videobuf2-v4l2.ko
+       - videobuf2-dma-sg.ko
+       - videobuf2-dma-contig.ko
+       - v4l2-mem2mem.ko
+       - vxd-dec.ko
+
+========
+EXECUTE:
+========
+* On the target:
+       # insmod videobuf2-common.ko
+       # insmod videobuf2-memops.ko
+       # insmod videobuf2-v4l2.ko
+       # insmod videobuf2-dma-sg.ko
+       # insmod videobuf2-dma-contig.ko
+       # insmod v4l2-mem2mem.ko
+       # insmod vxd-dec.ko
+       # ./tidec_decode
+* On successful completion, you will see this trace:
+       "test app completed successfully"
+
+==============
+RETURN VALUES:
+==============
+- 0: test app completed successfully
+- EXIT_FAILURE: test app failed to complete successfully
+
+
+* Reference: credentiality2.blogspot.com/2010/04/v4l2-example.html
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100644 (file)
index 0000000..1ecf200
--- /dev/null
@@ -0,0 +1,18 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+test -n "$NOCONFIGURE" && {
+  echo "skipping configure stage as requested."
+  echo "autogen.sh done."
+  exit 0
+}
+
+$srcdir/configure --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..968abe0
--- /dev/null
@@ -0,0 +1,98 @@
+#  
+#  Copyright (C) 2018 Texas Instruments
+#  
+#  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/>.
+#  
+
+# Initialize Autoconf
+AC_PREREQ([2.60])
+AC_INIT([tidec_decode], [1.0.0], [https://www.ti.com], [tidec_decode])
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_HEADERS([config.h])
+
+# Initialize Automake
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+AM_MAINTAINER_MODE
+
+# Enable quiet compiles on automake 1.11.
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+# Initialize libtool
+AC_PROG_LIBTOOL
+AC_PROG_CXX
+
+# Obtain compiler/linker options for depedencies
+PKG_CHECK_MODULES(DRM, libdrm libavformat libavcodec)
+
+dnl ===========================================================================
+dnl check compiler flags
+AC_DEFUN([LIBDRM_CC_TRY_FLAG], [
+  AC_MSG_CHECKING([whether $CC supports $1])
+
+  libdrm_save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $1"
+
+  AC_COMPILE_IFELSE([ ], [libdrm_cc_flag=yes], [libdrm_cc_flag=no])
+  CFLAGS="$libdrm_save_CFLAGS"
+
+  if test "x$libdrm_cc_flag" = "xyes"; then
+    ifelse([$2], , :, [$2])
+  else
+    ifelse([$3], , :, [$3])
+  fi
+  AC_MSG_RESULT([$libdrm_cc_flag])
+])
+
+MAYBE_WARN="-Wall -Wextra \
+-Wsign-compare -Werror-implicit-function-declaration \
+-Wpointer-arith -Wwrite-strings -Wstrict-prototypes \
+-Wnested-externs \
+-Wpacked -Wswitch-enum -Wmissing-format-attribute \
+-Wstrict-aliasing=2 -Winit-self -Wunsafe-loop-optimizations \
+-Wdeclaration-after-statement -Wold-style-definition \
+-Wno-missing-field-initializers -Wno-unused-parameter \
+-Wno-attributes -Wno-long-long -Winline"
+
+# invalidate cached value if MAYBE_WARN has changed
+if test "x$libdrm_cv_warn_maybe" != "x$MAYBE_WARN"; then
+        unset libdrm_cv_warn_cflags
+fi
+AC_CACHE_CHECK([for supported warning flags], libdrm_cv_warn_cflags, [
+        echo
+        WARN_CFLAGS=""
+
+        # Some warning options are not supported by all versions of
+        # gcc, so test all desired options against the current
+        # compiler.
+        #
+        # Note that there are some order dependencies
+        # here. Specifically, an option that disables a warning will
+        # have no net effect if a later option then enables that
+        # warnings, (perhaps implicitly). So we put some grouped
+        # options (-Wall and -Wextra) up front and the -Wno options
+        # last.
+
+        for W in $MAYBE_WARN; do
+                LIBDRM_CC_TRY_FLAG([$W], [WARN_CFLAGS="$WARN_CFLAGS $W"])
+        done
+
+        libdrm_cv_warn_cflags=$WARN_CFLAGS
+        libdrm_cv_warn_maybe=$MAYBE_WARN
+
+        AC_MSG_CHECKING([which warning flags were supported])])
+WARN_CFLAGS="$libdrm_cv_warn_cflags"
+AC_SUBST(WARN_CFLAGS)
+
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
diff --git a/demux.c b/demux.c
new file mode 100644 (file)
index 0000000..c457fc6
--- /dev/null
+++ b/demux.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2018 Texas Instruments, Inc.
+ * 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 "demux.h"
+
+char mpeg4head[45] = { 0, 0, 0, 0 };
+int get_esds_offset(const char *filename, struct demux *demux);
+
+static AVFormatContext *
+open_file(const char *filename)
+{
+       AVFormatContext *afc = NULL;
+       int err = avformat_open_input(&afc, filename, NULL, NULL);
+
+       if (!err)
+               err = avformat_find_stream_info(afc, NULL);
+
+       if (err < 0) {
+               printf("%s: lavf error %d", filename, err);
+               exit(1);
+       }
+
+       av_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, int *bitdepth, enum AVPixelFormat *pix_fmt, enum AVCodecID *codec)
+{
+       AVFormatContext *afc = open_file(filename);
+       AVStream *st = find_stream(afc);
+       AVCodecContext *cc = st->codec;
+       AVBitStreamFilterContext *bsf = NULL;
+       struct demux *demux;
+
+       if ((cc->codec_id != AV_CODEC_ID_H264) &&
+           (cc->codec_id != AV_CODEC_ID_MPEG2VIDEO) &&
+           (cc->codec_id != AV_CODEC_ID_MPEG4) &&
+           (cc->codec_id != AV_CODEC_ID_HEVC)) {
+               printf("could not open '%s': unsupported codec %d", filename,
+                       cc->codec_id);
+               return NULL;
+       }
+
+       if (cc->extradata && cc->extradata_size > 0 && cc->extradata[0] == 1) {
+               printf("initializing bitstream filter");
+               bsf = av_bitstream_filter_init("h264_mp4toannexb");
+               if (!bsf) {
+                       printf("could not open '%s': failed to initialize bitstream filter",
+                               filename);
+                       return NULL;
+               }
+       }
+
+       *width = cc->width;
+       *height = cc->height;
+       *bitdepth = cc->bits_per_raw_sample;
+       *pix_fmt = cc->pix_fmt;
+       *codec = cc->codec_id;
+
+       demux = calloc(1, sizeof(*demux));
+
+       demux->afc = afc;
+       demux->cc = cc;
+       demux->st = st;
+       demux->bsf = bsf;
+       demux->first_in_buff = 0;
+
+       return demux;
+}
+
+struct demux * demux_init(const char * filename, int *width, int *height,
+                       int *bitdepth, enum AVPixelFormat *pix_fmt, enum AVCodecID *codec)
+{
+       struct demux *demux;
+
+       av_register_all();
+       avcodec_register_all();
+       demux = open_stream(filename, width, height, bitdepth, pix_fmt, codec);
+       if ((demux != NULL) && (demux->cc->codec_id == AV_CODEC_ID_MPEG4)) {
+               if (get_esds_offset(filename, demux))
+                       return NULL;
+       }
+
+       return demux;
+}
+
+int get_esds_offset(const char *filename, struct demux *demux)
+{
+       FILE *inputStream;
+       int i = 0;
+       unsigned char *buffer = NULL;
+       unsigned long fileLen;
+       int esds_index = 0;
+       inputStream = fopen(filename, "rb");
+       if (!inputStream) {
+               printf("Unable to open %s\n", filename);
+               return -1;
+       }
+
+       // Get the length
+       fseek(inputStream, 0, SEEK_END);
+       fileLen = ftell(inputStream);
+       fseek(inputStream, 0, SEEK_SET);
+       buffer = malloc(fileLen);
+       if (!buffer) {
+               printf("Memory error!\n");
+               fclose(inputStream);
+               return -1;
+       }
+
+       // File to buffer
+       fread(buffer, fileLen, 1, inputStream);
+       fclose(inputStream);
+       printf("Buffer starts: %p\n", &buffer[0]);
+       printf("Buffer ends: %p\n", &buffer[fileLen]);
+
+       //Determines offset of known_string
+       for (i = 0; i < fileLen; i++) {
+               if ((buffer[i] == 0x65) && (buffer[++i] == 0x73))
+                       if ((buffer[++i] == 0x64) && (buffer[i + 1] == 0x73)) {
+                               printf("data in buffer = %x  %x  %x %d \n",
+                                      buffer[i],
+                                      buffer[i + 1],
+                                      buffer[i + 2],
+                                      buffer[i + 27]);
+                               esds_index = i + 27;
+                               break;
+                       }
+       }
+
+       demux->esds.length = buffer[esds_index];
+       demux->esds.data = malloc(demux->esds.length);
+       for (i = 1; i <= demux->esds.length; i++) {
+               demux->esds.data[i - 1] = buffer[esds_index + i];
+               printf(" index= %x \n", demux->esds.data[i - 1]);
+       }
+
+       free(buffer);
+
+       return 0;
+}
+
+int demux_read(struct demux *demux, unsigned 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;
+                               ret = av_bitstream_filter_filter(demux->bsf,
+                                                                demux->cc,
+                                                                NULL,
+                                                                &buf,
+                                                                &bufsize,
+                                                                pk.data,
+                                                                pk.size,
+                                                                0);
+                               if (ret < 0) {
+                                       printf("bsf error: %d", ret);
+                                       return 0;
+                               }
+                       } else {
+                               buf = pk.data;
+                               bufsize = pk.size;
+                       }
+
+                       if (bufsize > size)
+                               bufsize = size;
+
+                       if (demux->first_in_buff == 1) {
+                               memcpy(input, demux->esds.data, demux->esds.length);
+                               memcpy(input + demux->esds.length, buf, bufsize);
+                               demux->first_in_buff = 0;
+                               bufsize = bufsize + demux->esds.length;
+                       }
+                       else {
+                               memcpy(input, buf, bufsize);
+                       }
+
+                       if (demux->bsf)
+                               av_free(buf);
+
+                       av_free_packet(&pk);
+
+                       return bufsize;
+               }
+               av_free_packet(&pk);
+       }
+
+       return 0;
+}
+
+int demux_rewind(struct demux *demux)
+{
+       return av_seek_frame(demux->afc, demux->st->index, 0, AVSEEK_FLAG_FRAME);
+}
+
+void demux_deinit(struct demux *demux)
+{
+       avformat_close_input(&demux->afc);
+       if (demux->bsf)
+               av_bitstream_filter_close(demux->bsf);
+       free(demux->esds.data);
+       free(demux);
+}
diff --git a/demux.h b/demux.h
new file mode 100644 (file)
index 0000000..4793e7e
--- /dev/null
+++ b/demux.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018 Texas Instruments, Inc.
+ * 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__
+
+#include <libavformat/avformat.h>
+#include <libavcodec/avcodec.h>
+#include <libavutil/pixdesc.h>
+
+struct ESdescriptor {
+       int length;
+       unsigned char *data;
+};
+
+struct demux {
+       AVFormatContext *afc;
+       AVStream *st;
+       AVCodecContext *cc;
+       AVBitStreamFilterContext *bsf;
+       struct ESdescriptor esds;
+       /* Used for mpeg4 esds data copy */
+       int first_in_buff;
+};
+struct demux *demux_init(const char * filename, int *width, int *height,
+               int *bitdepth, enum AVPixelFormat *pix_fmt, enum AVCodecID *codec);
+int demux_read(struct demux *demux, unsigned char *input, int size);
+int demux_rewind(struct demux *demux);
+void demux_deinit(struct demux *demux);
+
+#endif /* __DEMUX_H__ */
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..95a1c12
--- /dev/null
+++ b/main.c
@@ -0,0 +1,1493 @@
+/*
+ * Texas Instruments IMG video driver test application.
+ *
+ * Copyright (c) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <malloc.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <poll.h>
+#include <dirent.h>
+
+#include <asm/types.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-controls.h>
+
+#include <drm.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <drm_fourcc.h>
+
+#include "demux.h"
+
+/* HEVC aka H.265 */
+#define V4L2_PIX_FMT_HEVC     v4l2_fourcc('H', 'E', 'V', 'C')
+/* TI NV12 10-bit, two bytes per channel */
+#define V4L2_PIX_FMT_TI1210   v4l2_fourcc('T', 'I', '1', '2')
+/* TI YUV422 10-bit, two bytes per channel */
+#define V4L2_PIX_FMT_TI1610   v4l2_fourcc('T', 'I', '1', '6')
+
+static const struct AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
+               [AV_PIX_FMT_YUV420P] = {
+                               .name = "yuv420p",
+               },
+               [AV_PIX_FMT_YUYV422] = {
+                               .name = "yuyv422",
+               },
+               [AV_PIX_FMT_YVYU422] = {
+                               .name = "yvyu422",
+               },
+               [AV_PIX_FMT_YUV422P] = {
+                               .name = "yuv422p",
+               },
+               [AV_PIX_FMT_YUV444P] = {
+                               .name = "yuv444p",
+               },
+               [AV_PIX_FMT_YUV410P] = {
+                               .name = "yuv410p",
+               },
+               [AV_PIX_FMT_YUV411P] = {
+                               .name = "yuv411p",
+               },
+               [AV_PIX_FMT_YUVJ411P] = {
+                               .name = "yuvj411p",
+               },
+               [AV_PIX_FMT_YUVJ420P] = {
+                               .name = "yuvj420p",
+               },
+               [AV_PIX_FMT_YUVJ422P] = {
+                               .name = "yuvj422p",
+               },
+               [AV_PIX_FMT_YUVJ444P] = {
+                               .name = "yuvj444p",
+               },
+               [AV_PIX_FMT_XVMC] = {
+                               .name = "xvmc",
+                               .flags = AV_PIX_FMT_FLAG_HWACCEL,
+               },
+               [AV_PIX_FMT_UYVY422] = {
+                               .name = "uyvy422",
+               },
+               [AV_PIX_FMT_UYYVYY411] = {
+                               .name = "uyyvyy411",
+               },
+               [AV_PIX_FMT_NV12] = {
+                               .name = "nv12",
+               },
+               [AV_PIX_FMT_NV21] = {
+                               .name = "nv21",
+               },
+               [AV_PIX_FMT_YUV440P] = {
+                               .name = "yuv440p",
+               },
+               [AV_PIX_FMT_YUVJ440P] = {
+                               .name = "yuvj440p",
+               },
+               [AV_PIX_FMT_YUV440P10LE] = {
+                               .name = "yuv440p10le",
+               },
+               [AV_PIX_FMT_YUV440P10BE] = {
+                               .name = "yuv440p10be",
+               },
+               [AV_PIX_FMT_YUV440P12LE] = {
+                               .name = "yuv440p12le",
+               },
+               [AV_PIX_FMT_YUV440P12BE] = {
+                               .name = "yuv440p12be",
+               },
+               [AV_PIX_FMT_YUVA420P] = {
+                               .name = "yuva420p",
+               },
+               [AV_PIX_FMT_YUVA422P] = {
+                               .name = "yuva422p",
+               },
+               [AV_PIX_FMT_YUVA444P] = {
+                               .name = "yuva444p",
+               },
+               [AV_PIX_FMT_YUVA420P9BE] = {
+                               .name = "yuva420p9be",
+               },
+               [AV_PIX_FMT_YUVA420P9LE] = {
+                               .name = "yuva420p9le",
+               },
+               [AV_PIX_FMT_YUVA422P9BE] = {
+                               .name = "yuva422p9be",
+               },
+               [AV_PIX_FMT_YUVA422P9LE] = {
+                               .name = "yuva422p9le",
+               },
+               [AV_PIX_FMT_YUVA444P9BE] = {
+                               .name = "yuva444p9be",
+               },
+               [AV_PIX_FMT_YUVA444P9LE] = {
+                               .name = "yuva444p9le",
+               },
+               [AV_PIX_FMT_YUVA420P10BE] = {
+                               .name = "yuva420p10be",
+               },
+               [AV_PIX_FMT_YUVA420P10LE] = {
+                               .name = "yuva420p10le",
+               },
+               [AV_PIX_FMT_YUVA422P10BE] = {
+                               .name = "yuva422p10be",
+               },
+               [AV_PIX_FMT_YUVA422P10LE] = {
+                               .name = "yuva422p10le",
+               },
+               [AV_PIX_FMT_YUVA444P10BE] = {
+                               .name = "yuva444p10be",
+               },
+               [AV_PIX_FMT_YUVA444P10LE] = {
+                               .name = "yuva444p10le",
+               },
+               [AV_PIX_FMT_YUVA420P16BE] = {
+                               .name = "yuva420p16be",
+               },
+               [AV_PIX_FMT_YUVA420P16LE] = {
+                               .name = "yuva420p16le",
+               },
+               [AV_PIX_FMT_YUVA422P16BE] = {
+                               .name = "yuva422p16be",
+               },
+               [AV_PIX_FMT_YUVA422P16LE] = {
+                               .name = "yuva422p16le",
+               },
+               [AV_PIX_FMT_YUVA444P16BE] = {
+                               .name = "yuva444p16be",
+               },
+               [AV_PIX_FMT_YUVA444P16LE] = {
+                               .name = "yuva444p16le",
+               },
+               [AV_PIX_FMT_YUV420P9LE] = {
+                               .name = "yuv420p9le",
+               },
+               [AV_PIX_FMT_YUV420P9BE] = {
+                               .name = "yuv420p9be",
+               },
+               [AV_PIX_FMT_YUV420P10LE] = {
+                               .name = "yuv420p10le",
+               },
+               [AV_PIX_FMT_YUV420P10BE] = {
+                               .name = "yuv420p10be",
+               },
+               [AV_PIX_FMT_YUV420P12LE] = {
+                               .name = "yuv420p12le",
+               },
+               [AV_PIX_FMT_YUV420P12BE] = {
+                               .name = "yuv420p12be",
+               },
+               [AV_PIX_FMT_YUV420P14LE] = {
+                               .name = "yuv420p14le",
+               },
+               [AV_PIX_FMT_YUV420P14BE] = {
+                               .name = "yuv420p14be",
+               },
+               [AV_PIX_FMT_YUV420P16LE] = {
+                               .name = "yuv420p16le",
+               },
+               [AV_PIX_FMT_YUV420P16BE] = {
+                               .name = "yuv420p16be",
+               },
+               [AV_PIX_FMT_YUV422P9LE] = {
+                               .name = "yuv422p9le",
+               },
+               [AV_PIX_FMT_YUV422P9BE] = {
+                               .name = "yuv422p9be",
+               },
+               [AV_PIX_FMT_YUV422P10LE] = {
+                               .name = "yuv422p10le",
+               },
+               [AV_PIX_FMT_YUV422P10BE] = {
+                               .name = "yuv422p10be",
+               },
+               [AV_PIX_FMT_YUV422P12LE] = {
+                               .name = "yuv422p12le",
+               },
+               [AV_PIX_FMT_YUV422P12BE] = {
+                               .name = "yuv422p12be",
+               },
+               [AV_PIX_FMT_YUV422P14LE] = {
+                               .name = "yuv422p14le",
+               },
+               [AV_PIX_FMT_YUV422P14BE] = {
+                               .name = "yuv422p14be",
+               },
+               [AV_PIX_FMT_YUV422P16LE] = {
+                               .name = "yuv422p16le",
+               },
+               [AV_PIX_FMT_YUV422P16BE] = {
+                               .name = "yuv422p16be",
+               },
+               [AV_PIX_FMT_YUV444P16LE] = {
+                               .name = "yuv444p16le",
+               },
+               [AV_PIX_FMT_YUV444P16BE] = {
+                               .name = "yuv444p16be",
+               },
+               [AV_PIX_FMT_YUV444P10LE] = {
+                               .name = "yuv444p10le",
+               },
+               [AV_PIX_FMT_YUV444P10BE] = {
+                               .name = "yuv444p10be",
+               },
+               [AV_PIX_FMT_YUV444P9LE] = {
+                               .name = "yuv444p9le",
+               },
+               [AV_PIX_FMT_YUV444P9BE] = {
+                               .name = "yuv444p9be",
+               },
+               [AV_PIX_FMT_YUV444P12LE] = {
+                               .name = "yuv444p12le",
+               },
+               [AV_PIX_FMT_YUV444P12BE] = {
+                               .name = "yuv444p12be",
+               },
+               [AV_PIX_FMT_YUV444P14LE] = {
+                               .name = "yuv444p14le",
+               },
+               [AV_PIX_FMT_YUV444P14BE] = {
+                               .name = "yuv444p14be",
+               },
+               [AV_PIX_FMT_P010LE] = {
+                               .name = "p010le",
+               },
+               [AV_PIX_FMT_P010BE] = {
+                               .name = "p010be",
+               },
+               [AV_PIX_FMT_P016LE] = {
+                               .name = "p016le",
+               },
+               [AV_PIX_FMT_P016BE] = {
+                               .name = "p016be",
+               }
+};
+
+#define memzero(x)     memset(&(x), 0, sizeof (x))
+#define MAX_TEST_FDS   10
+#define MAX_FRAMES     1000
+#define ALIGN(x,a)     (((x) + (a) - 1L) & ~((a) - 1L))
+#define HW_ALIGN       64
+
+#define MAX_OUTBUFS 2
+
+#define DISPLAY_LAG 3
+
+#define MAX_CAPBUFS_H264 16
+#define MAX_CAPBUFS (MAX_CAPBUFS_H264 + DISPLAY_LAG)
+
+#define MIN(a, b) ((a < b) ? a : b)
+
+#define DEVICE_NAME "cardx"
+
+//#define DEBUG
+#ifdef DEBUG
+#define debug_printf(fmt, arg...) printf(fmt, ##arg);
+#else
+#define debug_printf(fmt, arg...)
+#endif
+
+/* Enable the below option for converting YUV422 decoded output to NV12 format*/
+#define CC_YUV422PLANAR_TO_NV12
+
+#define PROFILE
+#ifdef PROFILE
+#define perf_printf(fmt, arg...) printf(fmt, ##arg);
+#else
+       perf_printf(fmt, arg...)
+#endif
+
+static int drmfd1 = -1;
+#define FMT_NUM_PLANES 1 /* Used when creating V4l2 buffers for capture buffers */
+
+/*
+ * @bo_handle: drm buffer handle
+ * @dbuf_fd: dma buffer handle
+ * @mapped: Pointer to mmap'ed buffer memory
+ * @offset: offset of buffer
+ * @length: Buffer length for munmap
+ */
+struct buffer {
+       unsigned int bo_handle;
+       int dbuf_fd;
+       void *mapped;
+       int offset;
+       int length;
+};
+
+struct stream_context
+{
+       size_t frame_sizes[MAX_FRAMES];
+       int width;
+       int height;
+       int bitdepth;
+       int num_bytes_per_pix;
+       enum AVPixelFormat pix_fmt;
+       enum AVCodecID codec;
+};
+
+/*
+ *
+ * @fourcc: The V4L2 fourcc value
+ * @size_num: The numerator to multiply image size by
+ * @size_den: The denominator to divide image size by
+ */
+struct output_format
+{
+       uint32_t fourcc;
+       int size_num;
+       int size_den;
+};
+
+static void errno_exit(const char *s)
+{
+       printf("%s error %d, %s\n", s, errno, strerror(errno));
+       exit(EXIT_FAILURE);
+}
+
+static int handle_outbuf(int fd, int index, int rdfd, struct buffer buff,
+       struct stream_context *str, int nframes, int sleep_time)
+{
+       struct v4l2_buffer buf;
+       struct v4l2_plane buf_planes[1];
+       struct v4l2_decoder_cmd cmd = {};
+       int ret = 0;
+       int send_cmd = 0;
+       static int fs_ind = 0;
+
+       memset(buff.mapped, 0, (str->width * str->height));
+       read(rdfd, buff.mapped, str->frame_sizes[fs_ind]);
+
+       memzero(buf);
+       memzero(buf_planes[0]);
+
+       buf_planes[0].bytesused = str->frame_sizes[fs_ind];
+       buf_planes[0].m.mem_offset = buff.offset;
+       buf_planes[0].data_offset = 0;
+
+       fs_ind++;
+
+       /* Stop queueing OUTPUT buffers if no more content */
+       if (fs_ind > nframes)
+               return ret;
+
+       if (fs_ind == nframes) {
+               debug_printf("[fd%d] handle_outbuf sending DEC_CMD_STOP\n", fd);
+               cmd.cmd = V4L2_DEC_CMD_STOP;
+               ret = ioctl(fd, VIDIOC_TRY_DECODER_CMD, &cmd);
+               if (ret < 0) {
+                       printf("[fd%d] handle_outbuf TRY_DECODER_CMD failed trying FLAG_LAST ret=%d err=%s\n",
+                                       fd, ret, strerror(errno));
+                       buf.flags |= V4L2_BUF_FLAG_LAST;
+               } else {
+                       send_cmd = 1;
+               }
+       }
+
+       buf.index = index;
+       buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       buf.memory = V4L2_MEMORY_MMAP;
+       buf.m.planes = buf_planes;
+       buf.length = 1;
+
+       ret = ioctl(fd, VIDIOC_QBUF, &buf);
+       if (ret < 0)
+               printf("[fd%d] handle_outbuf QBUF failed ret=%d err=%s\n",
+                               fd, ret, strerror(errno));
+       else
+               debug_printf("[fd%d] handle_outbuf QBUF success\n", fd);
+
+       if (send_cmd) {
+               debug_printf("[fd%d] handle_outbuf sending DEC_CMD_STOP after %d ms delay\n", fd, sleep_time / 1000);
+               usleep(sleep_time);
+               cmd.cmd = V4L2_DEC_CMD_STOP;
+               ret = ioctl(fd, VIDIOC_DECODER_CMD, &cmd);
+               if (ret < 0)
+                       printf("[fd%d] handle_outbuf DECODER_CMD failed ret=%d err=%s\n",
+                                       fd, ret, strerror(errno));
+       }
+
+       return ret;
+}
+
+static int handle_capbuf(int fd, int wrfd, int index, struct buffer buff,
+               int save, struct stream_context *str, struct output_format fmt, int usedrmbuff)
+{
+       struct v4l2_buffer buf;
+       struct v4l2_plane buf_planes[1];
+       int ret = 0;
+       int i;
+       int h = ALIGN(str->height, HW_ALIGN);
+       int s = ALIGN(str->width, HW_ALIGN) * str->num_bytes_per_pix;
+
+       if(save && (wrfd >= 0))
+       {
+               switch (fmt.fourcc) {
+                       case (V4L2_PIX_FMT_NV12):
+                       case (V4L2_PIX_FMT_TI1210):
+                               /*
+                               for(i=0; i<str->height; i++)
+                                       write(wrfd, buff.mapped + (i * s),
+                                                       str->width);
+
+                               for(i=0; i<(str->height/2); i++)
+                                       write(wrfd, buff.mapped + (h * s) +
+                                                       (i * s), str->width);
+                               */
+                               for(i=0; i<str->height; i++)
+                                       write(wrfd, buff.mapped + (i * s),
+                                                       (str->width *
+                                                        str->num_bytes_per_pix));
+
+                               for(i=0; i<(str->height/2); i++)
+                                       write(wrfd, buff.mapped + (h * s) +
+                                                       (i * s),
+                                                       (str->width *
+                                                        str->num_bytes_per_pix));
+                               break;
+                       case (V4L2_PIX_FMT_NV16):
+                       case (V4L2_PIX_FMT_TI1610):
+#ifdef CC_YUV422PLANAR_TO_NV12
+                               for (i = 0; i < str->height; i++)
+                                       write(wrfd, buff.mapped + (i * s),
+                                               str->width * str->num_bytes_per_pix);
+                               for (i = 0; i < str->height; i+=2)
+                                       write(wrfd, buff.mapped + (h * s) + (i * s), str->width * str->num_bytes_per_pix);
+
+#else
+                               for (i = 0; i < str->height; i++)
+                                       write(wrfd, buff.mapped + (i * s),
+                                                       2* str->width * str->num_bytes_per_pix);
+#endif
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       memzero(buf);
+       memzero(buf_planes[0]);
+
+       buf_planes[0].m.fd = buff.dbuf_fd;
+       buf_planes[0].length = buff.length;
+
+       buf.index = index;
+       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       if (usedrmbuff == 0) {
+               /* Using v4l2 buffers for capture */
+               buf.memory = V4L2_MEMORY_MMAP;
+       } else {
+               /* Using drm buffers for capture */
+               buf.memory = V4L2_MEMORY_DMABUF;
+       }
+       buf.m.planes = buf_planes;
+       buf.length = 1;
+
+       ret = ioctl(fd, VIDIOC_QBUF, &buf);
+       if (ret < 0)
+               printf("[fd%d] handle_capbuf QBUF failed ret=%d err=%s\n",
+                               fd, ret, strerror(errno));
+       else
+               debug_printf("[fd%d] handle_capbuf QBUF success\n", fd);
+
+       return ret;
+}
+
+static int mainloop(int fd, int rdfd, int wrfd,
+               struct stream_context *str, struct buffer outbufs[],
+               struct buffer capbufs[], int n_outbufs,
+               int n_capbufs, int nframes, int enable_prof,
+               struct output_format fmt, int sleep_time, int usedrmbuff)
+{
+       int type, i, ret = 0;
+       uint32_t flags = 0;
+       struct v4l2_buffer buf;
+       struct v4l2_plane buf_planes[2];
+       struct pollfd pfd;
+       struct timeval times;
+       long curr_time = 0;
+       static long prev_time = 0;
+       struct v4l2_event event;
+
+       debug_printf("[fd%d] MAINLOOP\n", fd);
+
+       pfd.fd = fd;
+       pfd.events = POLLIN | POLLOUT | POLLPRI;
+       pfd.revents = 0;
+
+       for (i = 0; i < n_outbufs; i++)
+               handle_outbuf(fd, i, rdfd, outbufs[i], str, nframes, 0);
+
+       for (i = 0; i < n_capbufs; i++)
+               handle_capbuf(fd, wrfd, i, capbufs[i], 0, str, fmt, usedrmbuff);
+
+       type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       ret = ioctl(fd, VIDIOC_STREAMON, &type);
+       if (ret) {
+               printf("[fd%d] OUTPUT VIDIOC_STREAMON failed with ret %d\n",
+                       fd, ret);
+               return ret;
+       }
+
+       type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       ret = ioctl(fd, VIDIOC_STREAMON, &type);
+       if (ret)
+               printf("[fd%d] CAPTURE VIDIOC_STREAMON failed with ret %d\n",
+                       fd, ret);
+
+       i = 0;
+       while (!(flags & V4L2_BUF_FLAG_LAST)) {
+               pfd.revents = 0;
+
+               /* Poll for any event for 100ms */
+               ret = poll(&pfd, 1, 100);
+               if (ret < 0) {
+                       printf("poll had an error %d: %s\n",
+                               errno, strerror(errno));
+               } else if (ret > 0) {
+                       if (pfd.revents & POLLOUT) {
+                               while (1) {
+                                       /* Check for OUTPUT buffer */
+                                       memzero(buf);
+                                       buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+                                       buf.memory = V4L2_MEMORY_MMAP;
+                                       buf.m.planes = buf_planes;
+                                       buf.length = 1;
+                                       ret = ioctl(fd, VIDIOC_DQBUF, &buf);
+                                       if (ret < 0) {
+                                               if (errno != EAGAIN) {
+                                                       printf("[fd%d] OUTPUT VIDIOC_DQBUF failed: ret=%d errno=%d: %s\n",
+                                                               fd, ret, errno,
+                                                               strerror(errno));
+                                               } else {
+                                                       debug_printf("[fd%d] OUTPUT EAGAIN\n", fd);
+                                                       break;
+                                               }
+                                       } else {
+                                               handle_outbuf(fd, buf.index, rdfd,
+                                                               outbufs[buf.index],
+                                                               str, nframes,
+                                                               sleep_time);
+                                       }
+                               }
+                       }
+                       if (pfd.revents & POLLIN) {
+                               while (1) {
+                                       /* Check for CAPTURE buffer */
+                                       memzero(buf);
+                                       buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+                                       if (usedrmbuff == 0) {
+                                               /* Using v4l2 bufffers for capture */
+                                               buf.memory = V4L2_MEMORY_MMAP;
+                                       } else {
+                                               /* Using drm buffers for capture */
+                                               buf.memory = V4L2_MEMORY_DMABUF;
+                                       }
+                                       buf.m.planes = buf_planes;
+                                       buf.length = 2;
+                                       ret = ioctl(fd, VIDIOC_DQBUF, &buf);
+                                       if (ret < 0) {
+                                               if (errno != EAGAIN) {
+                                                       printf("[fd%d] CAPTURE VIDIOC_DQBUF failed: ret=%d errno=%d: %s\n",
+                                                               fd, ret, errno,
+                                                               strerror(errno));
+                                               } else {
+                                                       debug_printf("[fd%d] CAPTURE EAGAIN\n", fd);
+                                                       break;
+                                               }
+                                       } else {
+                                               if (enable_prof) {
+                                                       gettimeofday(&times, NULL);
+                                                       curr_time =
+                                                       (times.tv_sec * 1000000 + times.tv_usec);
+
+                                                       perf_printf("Picture buffer dequeue time is %ld us\n",
+                                                                       (curr_time - prev_time));
+
+                                                       prev_time = curr_time;
+                                               }
+                                               debug_printf("[fd%d] CAPTURE VIDIOC_DQBUF bytesused=%d\n",
+                                                               fd, buf.m.planes[0].bytesused);
+                                               if (buf.m.planes[0].bytesused)
+                                                       handle_capbuf(fd, wrfd,
+                                                                     buf.index,
+                                                                     capbufs[buf.index],
+                                                                     1, str,
+                                                                     fmt, usedrmbuff);
+                                               flags = buf.flags;
+                                               debug_printf("[fd%d] CAPTURE VIDIOC_DQBUF buffer %d flags=%08x FLAG_LAST=%08x\n",
+                                                               fd, buf.index,
+                                                               flags,
+                                                               V4L2_BUF_FLAG_LAST);
+                                               if (buf.flags & V4L2_BUF_FLAG_LAST)
+                                                       break;
+                                       }
+                               }
+                       }
+                       if (pfd.revents & POLLPRI) {
+                               /* Check for events */
+                               memzero(event);
+                               ret = ioctl(fd, VIDIOC_DQEVENT, &event);
+                               if (ret < 0) {
+                                       printf("[fd%d] VIDIOC_DQEVENT failed:: ret=%d errno=%d: %s\n",
+                                                       fd, ret, errno,
+                                                       strerror(errno));
+                               } else if (event.type == V4L2_EVENT_EOS) {
+                                       debug_printf("[fd%d] GOT EVENT\n", fd);
+                               } else {
+                                       printf("[fd%d] VIDIOC_DQEVENT got unexpected event %d\n",
+                                                       fd, event.type);
+                               }
+                       }
+               }
+       }
+
+       debug_printf("Stream ended, calling STREAMOFF\n");
+       type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
+       if (ret) {
+               printf("[fd%d] VIDIOC_STREAMOFF on OUTPUT failed with ret %d\n",
+                               fd, ret);
+               return ret;
+       }
+
+       type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
+       if (ret)
+               printf("[fd%d] VIDIOC_STREAMOFF on CAPTURE failed with ret %d\n",
+                               fd, ret);
+
+       return ret;
+}
+
+static void uninit_device(int fd, struct buffer outbufs[],
+               struct buffer capbufs[], int *n_outbufs, int *n_capbufs, int usedrmbuff)
+{
+       struct drm_mode_destroy_dumb gem_destroy;
+       int i, ret = 0;
+       struct v4l2_event_subscription sub;
+
+       debug_printf("[fd%d] uninit_device\n", fd);
+
+       for (i = 0; i < *n_outbufs; i++) {
+               debug_printf("[fd%d] munmap outbuf %d mapped=0x%p length=%d\n",
+                               fd, i, outbufs[i].mapped, outbufs[i].length);
+               ret = munmap(outbufs[i].mapped, outbufs[i].length);
+               if (ret) {
+                       printf("[fd%d] munmap failed for outbuf %d: %d %s\n",
+                                       fd, i, errno, strerror(errno));
+               }
+       }
+
+/* For unint capbufs, check which was used, drm or v4l2*/
+       if (usedrmbuff == 0) {
+               /* Using v4l2 bufffers for capture */
+               for (i = 0; i < *n_capbufs; i++) {
+                       debug_printf("[fd%d] munmap capbuf %d mapped=0x%p length=%d\n", fd, i, capbufs[i].mapped, capbufs[i].length);
+                       ret = munmap(capbufs[i].mapped, capbufs[i].length);
+                       if (ret) {
+                               printf("[fd%d] munmap failed for capbuf %d: %d %s\n", fd, i, errno, strerror(errno));
+                       }
+               }
+       } else {
+               /* Using drm bufffers for capture */
+               for (i = 0; i < *n_capbufs; i++) {
+                       debug_printf("[fd%d] munmap capbuf %d mapped=0x%p length=%d\n", fd, i, capbufs[i].mapped, capbufs[i].length);
+                       ret = munmap(capbufs[i].mapped, capbufs[i].length);
+                       if (ret) {
+                               printf("[fd%d] munmap failed for  %d: %d %s\n", fd, i, errno, strerror(errno));
+                       }
+                       debug_printf("[fd%d] destroy gem capbuf %d handle=%d\n",
+                                       fd, i, capbufs[i].bo_handle);
+                       memset(&gem_destroy, 0, sizeof(gem_destroy));
+                       gem_destroy.handle = capbufs[i].bo_handle;
+                       ret = ioctl(drmfd1, DRM_IOCTL_MODE_DESTROY_DUMB, &gem_destroy);
+                       if (ret)
+                               printf("    DRM_IOCTL_MODE_DESTROY_DUMB failed\n");
+               }
+       }
+
+       memset(&sub, 0, sizeof(sub));
+       sub.type = V4L2_EVENT_ALL;
+
+       debug_printf("[fd%d] Calling V4L2 IOCTL VIDIOC_SUBSCRIBE_EVENT\n", fd);
+       ret = ioctl(fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
+       if (ret != 0) {
+               printf("[fd%d] Failed to unsubscribe to events: err: %d %s\n",
+                               fd, errno, strerror(errno));
+       }
+}
+
+static int create_drm_buffer(struct buffer *b,
+       unsigned int width, unsigned int height)
+{
+       struct drm_mode_create_dumb gem;
+       struct drm_mode_map_dumb gem_map;
+       struct drm_mode_destroy_dumb gem_destroy;
+       int ret;
+
+       memset(&gem, 0, sizeof gem);
+       gem.width = width;
+       gem.height = height;
+       gem.bpp = 8;
+
+       ret = ioctl(drmfd1, DRM_IOCTL_MODE_CREATE_DUMB, &gem);
+       if (ret) {
+               printf("    DRM_IOCTL_MODE_CREATE_DUMB failed\n");
+               return ret;
+       }
+
+       b->bo_handle = gem.handle;
+
+       struct drm_prime_handle prime;
+       memset(&prime, 0, sizeof prime);
+       prime.handle = b->bo_handle;
+
+       ret = ioctl(drmfd1, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime);
+       if (ret) {
+               printf("    DRM_IOCTL_PRIME_HANDLE_TO_FD failed\n");
+               goto fail_gem;
+       }
+       b->dbuf_fd = prime.fd;
+
+       memset(&gem_map, 0, sizeof(gem_map));
+       gem_map.handle = gem.handle;
+
+       ret = ioctl(drmfd1, DRM_IOCTL_MODE_MAP_DUMB, &gem_map);
+       if (ret) {
+               printf("    DRM_IOCTL_MODE_MAP_DUMB failed\n");
+               goto fail_gem;
+       }
+
+       b->mapped = mmap(NULL, (size_t)gem.size, PROT_READ,
+                       MAP_SHARED, drmfd1, gem_map.offset);
+       if (MAP_FAILED == b->mapped) {
+               printf("    mmap failed %d: %s\n", errno, strerror(errno));
+               goto fail_gem;
+       }
+       b->offset = gem_map.offset;
+       b->length = gem.size;
+
+       return 0;
+fail_gem:
+       memset(&gem_destroy, 0, sizeof gem_destroy);
+       gem_destroy.handle = b->bo_handle;
+       ret = ioctl(drmfd1, DRM_IOCTL_MODE_DESTROY_DUMB, &gem_destroy);
+
+       return ret;
+}
+
+int stream_framelevel_parsing(struct stream_context *str, char *input_file, int max_frames)
+{
+       struct demux *demux;
+       int inp_buf_len = 0;
+       int inp_width, inp_height;
+       int frame_num = 0;
+       int frame_size = 0;
+       int bitdepth = 0;
+       enum AVPixelFormat pix_fmt;
+       enum AVCodecID codec;
+
+       /* Demux initialization */
+       demux = demux_init(input_file, &inp_width, &inp_height, &bitdepth, &pix_fmt, &codec);
+       if (!demux)
+       {
+               printf("%s: could not open demuxer\n", __FUNCTION__);
+               return -1;
+       }
+
+       debug_printf("\n%s: bitdepth: %d\n",__FUNCTION__, bitdepth);
+       debug_printf("%s: pix_fmt: %d\n",__FUNCTION__, pix_fmt);
+       debug_printf("%s: pix_fmt_string: %s\n",__FUNCTION__, pix_fmt != AV_PIX_FMT_NONE ?
+                       av_pix_fmt_descriptors[pix_fmt].name : "unknown");
+       debug_printf("\n%s: codec: %d\n",__FUNCTION__, codec);
+       if(codec == AV_CODEC_ID_H264)
+               debug_printf("\n%s: codec: H264",__FUNCTION__);
+       if(codec == AV_CODEC_ID_HEVC)
+               debug_printf("\n%s: codec format: HEVC\n",__FUNCTION__);
+
+       inp_buf_len = (inp_width * inp_height);
+
+       unsigned char *inp_buf = malloc(inp_buf_len);
+       if(inp_buf == NULL)
+       {
+               printf("%s: Memory allocation failed for inp_buf\n",
+                               __FUNCTION__);
+               return -1;
+       }
+
+       debug_printf("%s: demuxer is initialized, width=%d, height=%d\n",
+               __FUNCTION__, inp_width, inp_height);
+       str->width = inp_width;
+       str->height = inp_height;
+       str->bitdepth = bitdepth;
+       str->pix_fmt = pix_fmt;
+       str->codec = codec;
+
+       if(bitdepth == 8 || pix_fmt == AV_PIX_FMT_YUV420P ||
+                       pix_fmt == AV_PIX_FMT_YUV422P)
+               str->num_bytes_per_pix = 1;
+       if(bitdepth == 10 || pix_fmt == AV_PIX_FMT_YUV420P10LE ||
+                       pix_fmt == AV_PIX_FMT_YUV422P10LE)
+               str->num_bytes_per_pix = 2;
+
+       /*read the frame size and store into array*/
+       while(1)
+       {
+               frame_size = demux_read(demux, inp_buf, inp_buf_len);
+               if (frame_size)
+               {
+                       debug_printf("frame %d frame size in demux %d\n",
+                               frame_num, frame_size);
+                       str->frame_sizes[frame_num] = frame_size;
+                       frame_num++;
+               }
+               else
+               {
+                       /*if the input file contains less number frames*/
+                       break;
+               }
+               if (max_frames > 0 && frame_num >= max_frames)
+                       break;
+       }
+
+       /* Demux de-initialization */
+       demux_deinit(demux);
+       free(inp_buf);
+
+       debug_printf("H264 frame sizes update is done\n");
+       return frame_num;
+}
+
+static int init_device(int fd, int rdfd,
+               struct stream_context *str, struct buffer outbufs[],
+               struct buffer capbufs[], int *n_outbufs, int *n_capbufs,
+               struct output_format format, int usedrmbuff)
+{
+       struct v4l2_format fmt;
+       struct v4l2_requestbuffers reqbuf;
+       struct v4l2_buffer buffer;
+       struct v4l2_plane buf_planes[1];
+       int ret = 0;
+       int i, j;
+       /*for v4l2 based capture buffers*/
+       struct v4l2_buffer buffer_cap;
+       struct v4l2_plane buf_planes_cap[FMT_NUM_PLANES];
+
+       debug_printf("[fd%d] init_device\n", fd);
+
+       memzero(fmt);
+       fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       fmt.fmt.pix_mp.width = str->width;
+       fmt.fmt.pix_mp.height = str->height;
+       fmt.fmt.pix_mp.plane_fmt[0].sizeimage = (str->width * str->height);
+       fmt.fmt.pix_mp.num_planes = 1;
+
+       if(str->codec == AV_CODEC_ID_H264)
+               fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+       if(str->codec == AV_CODEC_ID_HEVC)
+               fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_HEVC;
+
+       ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
+       if (ret != 0) {
+               printf("[fd%d] VIDIOC_S_FMT errorno %d, %s\n",
+                       fd, errno, strerror(errno));
+               return ret;
+       }
+
+       debug_printf("[fd%d] After S_FMT on OUTPUT\n", fd);
+
+       fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       fmt.fmt.pix_mp.pixelformat = format.fourcc;
+       fmt.fmt.pix_mp.plane_fmt[0].sizeimage =
+               ((fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height) *
+                format.size_num) * (str->num_bytes_per_pix) / format.size_den;
+       fmt.fmt.pix_mp.width = ALIGN(str->width, HW_ALIGN);
+       fmt.fmt.pix_mp.height = ALIGN(str->height, HW_ALIGN);
+       fmt.fmt.pix_mp.num_planes = 1;
+       fmt.fmt.pix_mp.plane_fmt[0].bytesperline = ALIGN(str->width, HW_ALIGN) * str->num_bytes_per_pix;
+
+       ret = ioctl(fd, VIDIOC_S_FMT, &fmt);
+       if (ret) {
+               printf("[fd%d] VIDIOC_S_FMT errorno %d, %s\n",
+                       fd, errno, strerror(errno));
+               return ret;
+       }
+
+       debug_printf("[fd%d] After S_FMT on CAPTURE\n", fd);
+
+       fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+       ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
+       if (ret) {
+               printf("[fd%d] VIDIOC_G_FMT errorno %d, %s\n",
+                       fd, errno, strerror(errno));
+               return ret;
+       }
+
+       debug_printf("[fd%d] After G_FMT on OUTPUT\n", fd);
+       debug_printf("[fd%d] After G_FMT fmt.fmt.pix_mp.pixelformat = %c%c%c%c numplanes %d\n",
+                       fd, fmt.fmt.pix_mp.pixelformat & 0xff,
+                       (fmt.fmt.pix_mp.pixelformat >> 8) & 0xff,
+                       (fmt.fmt.pix_mp.pixelformat >>16) & 0xff,
+                       (fmt.fmt.pix_mp.pixelformat >> 24) & 0xff,
+                       fmt.fmt.pix_mp.num_planes);
+
+       debug_printf("[fd%d] fmt.fmt.pix_mp.width %d fmt.fmt.pix_mp.height %d"
+                       " sizeimage %d bytesperline %d\n",
+                       fd, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
+                       fmt.fmt.pix_mp.plane_fmt[0].sizeimage,
+                       fmt.fmt.pix_mp.plane_fmt[0].bytesperline);
+
+       fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+       ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
+       if (ret) {
+               printf("[fd%d] VIDIOC_G_FMT errorno %d, %s\n",
+                       fd, errno, strerror(errno));
+               return ret;
+       }
+
+       debug_printf("[fd%d] After G_FMT on CAPTURE\n", fd);
+       debug_printf("[fd%d] After G_FMT fmt.fmt.pix_mp.pixelformat = %c%c%c%c numplanes %d\n",
+                       fd, fmt.fmt.pix_mp.pixelformat & 0xff,
+                       (fmt.fmt.pix_mp.pixelformat >> 8) & 0xff,
+                       (fmt.fmt.pix_mp.pixelformat >>16) & 0xff,
+                       (fmt.fmt.pix_mp.pixelformat >> 24) & 0xff,
+                       fmt.fmt.pix_mp.num_planes);
+
+       debug_printf("[fd%d] fmt.fmt.pix_mp.width %d fmt.fmt.pix_mp.height %d"
+                       " sizeimage %d bytesperline %d\n",
+                       fd, fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
+                       fmt.fmt.pix_mp.plane_fmt[1].sizeimage,
+                       fmt.fmt.pix_mp.plane_fmt[1].bytesperline);
+
+       /* Setup Decoder OUTPUT (SRC buffer) through VIDIOC_REQBUFS */
+       debug_printf("[fd%d] Setup decoding OUTPUT with VIDIOC_REQBUFS buffer size %u\n",
+               fd, fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
+
+       memzero(reqbuf);
+       reqbuf.count = *n_outbufs;
+       reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       reqbuf.memory = V4L2_MEMORY_MMAP;
+
+       ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
+       if (ret) {
+               printf("[fd%d] Err REQBUFS failed on OUTPUT queue ret %d errno %d\n",
+                       fd, ret, errno);
+               return ret;
+       }
+       debug_printf("[fd%d] After VIDIOC_REQBUFS getting buf_cnt %d\n",
+               fd, reqbuf.count);
+       *n_outbufs = reqbuf.count;
+
+       /* QUERYBUF on OUTPUT - memory of V4L2_MEMORY_MMAP */
+       for (i = 0; i < *n_outbufs; i++) {
+               memset(&buffer, 0, sizeof(buffer));
+               buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+               buffer.index = i;
+               buffer.m.planes = buf_planes;
+               buffer.length = 1;
+
+               ret = ioctl(fd, VIDIOC_QUERYBUF, &buffer);
+               if (ret < 0) {
+                       printf("[fd%d] CANNOT QUERY BUFFERS ret = %d\n",
+                               fd, ret);
+                       return -1;
+               }
+
+               debug_printf("[fd%d] query buf, buffer %p plane 0 = %d buffer.length %d buffer.data_offset %d buffer.mem_offset %d\n",
+                               fd, &buffer, buffer.m.planes[0].length,
+                               buffer.length, buffer.m.planes[0].data_offset,
+                               buffer.m.planes[0].m.mem_offset);
+
+               outbufs[i].mapped = mmap(NULL, buffer.m.planes[0].length,
+                               PROT_READ | PROT_WRITE, MAP_SHARED,
+                               fd, buffer.m.planes[0].m.mem_offset);
+               outbufs[i].offset = buffer.m.planes[0].m.mem_offset;
+               outbufs[i].length = buffer.m.planes[0].length;
+
+               debug_printf("[fd%d] After mmap -> outbufs[%d].mapped = 0x%p\n",
+                       fd, i, outbufs[i].mapped);
+
+               if (MAP_FAILED == outbufs[i].mapped) {
+                       while (i >= 0) {
+                               /* Unmap all previous buffers */
+                               i--;
+                               munmap(outbufs[i].mapped,
+                                       fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
+                               outbufs[i].mapped = NULL;
+                       }
+                       printf("[fd%d] Cant mmap buffers Y", fd);
+                       return -1;
+               }
+       }
+
+       /* Setup Decoder CAPTURE (DST buffer) through VIDIOC_REQBUFS */
+
+       if (usedrmbuff == 0) {
+               /* Setup Decoder CAPTURE (DST buffer) through VIDIOC_REQBUFS */
+               debug_printf("[fd%d] Setup decoding CAPTURE with VIDIOC_REQBUFS\n", fd);
+               debug_printf("[fd%d] buffer(y) size %u buffer(uv) size %u\n",
+                                       fd, fmt.fmt.pix_mp.plane_fmt[0].sizeimage,
+                                       fmt.fmt.pix_mp.plane_fmt[1].sizeimage);
+
+               memzero(reqbuf);
+               reqbuf.count = *n_capbufs;
+               reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+               reqbuf.memory = V4L2_MEMORY_MMAP;
+
+               ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
+               if (ret) {
+                       printf("[fd%d] Err REQBUFS failed on CAPTURE queue ret %d errno %d\n",
+                               fd, ret, errno);
+                       return ret;
+               }
+               debug_printf("[fd%d] After VIDIOC_REQBUFS getting buf_cnt %d\n",
+                       fd, reqbuf.count);
+               *n_capbufs = reqbuf.count;
+               /*Creating Capbuffers with v4l2 BUFFERS*/
+               /* QUERYBUF on Capture - memory of V4L2_MEMORY_MMAP */
+               for (j = 0; j < *n_capbufs; j++) {
+                       memset(&buffer_cap, 0, sizeof(buffer_cap));
+                       buffer_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+                       buffer_cap.index = j;
+                       buffer_cap.m.planes = buf_planes_cap;
+                       buffer_cap.length = FMT_NUM_PLANES;
+                       buffer_cap.memory = V4L2_MEMORY_MMAP;
+
+                       ret = ioctl(fd, VIDIOC_QUERYBUF, &buffer_cap);
+                       if (ret < 0) {
+                               printf("[fd%d] CANNOT QUERY BUFFERS for Capture ret = %d\n",
+                                               fd, ret);
+                               return -1;
+                       }
+                       debug_printf("[fd%d] query buf, buffer %p plane 0 = %d buffer_cap.length %d buffer_cap.data_offset %d buffer_cap.mem_offset %d\n",
+                                       fd, &buffer_cap,
+                                       buffer_cap.m.planes[0].length,
+                                       buffer_cap.length,
+                                       buffer_cap.m.planes[0].data_offset,
+                                       buffer_cap.m.planes[0].m.mem_offset);
+
+                       capbufs[j].mapped = mmap(NULL, buffer_cap.m.planes[0].length,
+                                       PROT_READ, MAP_SHARED,
+                                       fd, buffer_cap.m.planes[0].m.mem_offset);
+                       capbufs[j].offset = buffer_cap.m.planes[0].m.mem_offset;
+                       capbufs[j].length = buffer_cap.m.planes[0].length;
+
+                       debug_printf("[fd%d] After mmap -> capbufs[%d].mapped = 0x%p\n",
+                                       fd, j, capbufs[j].mapped);
+
+                       if (MAP_FAILED == capbufs[j].mapped) {
+                               while (j >= 0) {
+                                       /* Unmap all previous buffers */
+                                       j--;
+                                       munmap(capbufs[j].mapped,
+                                                fmt.fmt.pix_mp.plane_fmt[0].sizeimage);
+                                                capbufs[j].mapped = NULL;
+                               }
+                               printf("[fd%d] Cant mmap capture buffers Y\n", fd);
+                               return -1;
+                       }
+               }
+       } else {
+               debug_printf("[fd%d] Setup decoding CAPTURE with VIDIOC_REQBUFS\n", fd);
+               debug_printf("[fd%d] buffer(y) size %u buffer(uv) size %u\n",
+                               fd, fmt.fmt.pix_mp.plane_fmt[0].sizeimage,
+                               fmt.fmt.pix_mp.plane_fmt[1].sizeimage);
+
+               memzero(reqbuf);
+               reqbuf.count = *n_capbufs;
+               reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+               reqbuf.memory = V4L2_MEMORY_DMABUF;
+
+               ret = ioctl(fd, VIDIOC_REQBUFS, &reqbuf);
+               if (ret) {
+                       printf("[fd%d] Err REQBUFS failed on CAPTURE queue ret %d errno %d\n",
+                                       fd, ret, errno);
+                       return ret;
+               }
+               debug_printf("[fd%d] After VIDIOC_REQBUFS getting buf_cnt %d\n",
+                               fd, reqbuf.count);
+               *n_capbufs = reqbuf.count;
+
+               /* Create DRM buffers */
+               for (i = 0; i < *n_capbufs; i++) {
+                       ret = create_drm_buffer(&capbufs[i],
+                                       ALIGN(fmt.fmt.pix_mp.width, HW_ALIGN),
+                                       ((str->num_bytes_per_pix *
+                                               fmt.fmt.pix_mp.height * format.size_num) /
+                                        format.size_den));
+                       if (ret) {
+                               printf("[fd%d] failed to create drm buffers\n", fd);
+                               return -1;
+                       }
+                       debug_printf("[fd%d] Create_DRM_BUFFERS drm_y_buffer[%d].dbuf_fd 0x%x\n",
+                                       fd, i, capbufs[i].dbuf_fd);
+               }
+       }
+       return ret;
+}
+
+static void close_device(int fd)
+{
+       debug_printf("[fd%d] close_device\n", fd);
+       if (-1 == close(fd))
+               errno_exit ("close");
+       fd = -1;
+}
+
+static int open_device(char *dev_name)
+{
+       struct v4l2_capability cap;
+       struct v4l2_fmtdesc argp;
+       int ret = 0;
+       int fd = -1;
+       struct v4l2_event_subscription sub;
+
+       fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);
+       if (-1 == fd) {
+               printf("Cannot open '%s': %d, %s\n",
+                               dev_name, errno, strerror(errno));
+               return -1;
+       }
+
+       ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
+       if (ret != 0) {
+               printf("Failed to verify capabilities\n");
+               return -1;
+       }
+
+       debug_printf("[fd%d] Info (%s): driver\"%s\" bus_info=\"%s\" card=\"%s\" fd=0x%x\n",
+                       fd, dev_name, cap.driver, cap.bus_info, cap.card, fd);
+
+       debug_printf("[fd%d] Info (%s): capabilities\"0x%x\" device_caps=\"0x%x\" \n",
+                       fd, dev_name, cap.capabilities, cap.device_caps);
+
+       memset(&argp, 0, sizeof(argp));
+       argp.index = 0;
+       argp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+       debug_printf("[fd%d] Calling V4L2 IOCTL VIDIOC_ENUM_FMT on CAPTURE\n",
+                       fd);
+       while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &argp)) == 0) {
+               debug_printf("[fd%d] argp.index = %d, {pixelformat = %c%c%c%c}, description = '%s'\n",
+                               fd, argp.index, argp.pixelformat & 0xff,
+                               (argp.pixelformat >> 8) & 0xff,
+                               (argp.pixelformat >>16) & 0xff,
+                               (argp.pixelformat >> 24) & 0xff,
+                               argp.description);
+               argp.index ++;
+       }
+
+       argp.index = 0;
+       argp.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+       debug_printf("[fd%d] Calling V4L2 IOCTL VIDIOC_ENUM_FMT on OUTPUT\n",
+                       fd);
+       while ((ret = ioctl(fd, VIDIOC_ENUM_FMT, &argp)) == 0) {
+               debug_printf("[fd%d] argp.index = %d, {pixelformat = %c%c%c%c}, description = '%s'\n",
+                               fd, argp.index, argp.pixelformat & 0xff,
+                               (argp.pixelformat >> 8) & 0xff,
+                               (argp.pixelformat >>16) & 0xff,
+                               (argp.pixelformat >> 24) & 0xff,
+                               argp.description);
+               argp.index ++;
+       }
+
+       memset(&sub, 0, sizeof(sub));
+       sub.type = V4L2_EVENT_EOS;
+
+       debug_printf("[fd%d] Calling V4L2 IOCTL VIDIOC_SUBSCRIBE_EVENT\n", fd);
+       ret = ioctl(fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
+       if (ret != 0) {
+               printf("[fd%d] Failed to subscribe to events: err: %d %s\n",
+                               fd, errno, strerror(errno));
+       }
+
+       return fd;
+}
+
+int main(int argc, char **argv)
+{
+       char *dev_name = "/dev/video0";
+       int i = 0;
+       int ret = 0;
+       unsigned int num_devs = 1;
+       int fds[MAX_TEST_FDS];
+       int rdfd = -1;
+       int wrfd = -1;
+       int c;
+       int n_outbufs, n_capbufs, n_frames;
+       struct buffer outbufs[MAX_OUTBUFS];
+       struct buffer capbufs[MAX_CAPBUFS];
+       struct stream_context str_context;
+       char input_file[256];
+       char output_file_base[120];
+       char output_file[128];
+       const char *dir_path = "/dev/dri/";
+       char drm_file_name[20];
+       DIR *d;
+       struct dirent *dir;
+       drmModeResPtr res;
+       int max_frames = -1;
+       int enable_prof = 0;
+       int sleep_time = 0;
+       struct output_format fmt;
+       int use_drm_capbuff = 1; /* Defaulting to use drm dss Capture Buffers */
+
+       printf("TI DEC V4L2 Codec decoding example application\n");
+       printf("Copyright (c) 2018 Texas Instruments, Inc.\n");
+
+       /* Parse the input args */
+       while (1)
+       {
+               c = getopt (argc, argv, "nf:hbi:o:d:te:");
+               if (c == -1)
+                       break;
+
+               switch (c) {
+                       case 'n':
+                               num_devs = atoi(optarg);
+                               break;
+                       case 'h':
+                               printf("Use:\n");
+                               printf("\t./tidec_decode -i <input_file> [OPTIONS]\n");
+                               printf("\tThe final output file/s will be '<output_file_base>_xx.out'\n");
+                               printf("\twhere xx ranges from 00, 01, 02, ...\n");
+                               printf("\tdepending on how many fds are specified to -n\n");
+                               printf("\tOPTIONS:\n");
+                               printf("\t\t-h help\n");
+                               printf("\t\t-b DO NOT use drm dss device capture buffer (instead, use v4l2)\n");
+                               printf("\t\t-n <number> number of fds to open\n");
+                               printf("\t\t-o <output_file_base> Dump output stream to file\n");
+                               printf("\t\t\tThe final output file/s will be '<output_file_base>_xx.out'\n");
+                               printf("\t\t\twhere xx ranges from 00, 01, 02, ...\n");
+                               printf("\t\t\tdepending on how many fds are specified to -n\n");
+                               printf("\t\t-f <number of frames to decode> Maximum number of frames to decode\n");
+                               printf("\t\t-d <path> Path to which drm device to use for buffer allocation\n");
+                               printf("\t\t-t for enable time profiling\n");
+                               printf("\t\t-e <number of ms> Number of milliseconds to sleep between\n");
+                               printf("\t\t\tqueueing the last bitstream buffer and sending CMD_STOP\n");
+                               printf("\t\t\tUsed to test various timing scenarios for EOS\n");
+                               break;
+                       case 'b':
+                               use_drm_capbuff = 0; /* DO NOT use drm dss device*/
+                               break;
+                       case 'i':
+                               snprintf(input_file, sizeof(input_file),
+                                               "%s", optarg);
+                               break;
+                       case 'o':
+                               snprintf(output_file_base,
+                                               sizeof(output_file_base),
+                                               "%s", optarg);
+                               break;
+                       case 'f':
+                               max_frames = atoi(optarg);
+                               break;
+                       case 'd':
+                               snprintf(drm_file_name, sizeof(drm_file_name),
+                                               "%s", optarg);
+                               break;
+                       case 't':
+                               enable_prof = 1;
+                               break;
+                       case 'e':
+                               sleep_time = 1000 * atoi(optarg);
+                               break;
+                       default:
+                               printf("Unrecognized argument %c\n", c);
+               }
+       }
+
+       if (0 == strlen(input_file)) {
+               printf("Requires an input value\n");
+               printf("\t./tidec_decode -i <input_file> [OPTIONS]\n");
+               return EXIT_FAILURE;
+       }
+
+       /* validate input args */
+       if (num_devs > MAX_TEST_FDS) {
+               printf("Invalid value passed for number of devices %d\n",
+                               num_devs);
+               return EXIT_FAILURE;
+       }
+
+       for (i = 0; i < num_devs; i++) {
+               debug_printf("*** Calling open_device for device %d \n", i);
+               fds[i] = open_device(dev_name);
+               if (fds[i] < 0)
+                       return EXIT_FAILURE;
+               debug_printf("*** device %d is fd %d", i, fds[i]);
+       }
+
+       if (use_drm_capbuff == 0) {
+               printf("\nUsing v4l2 for capture buffers\n");
+       } else {
+               if (strlen(drm_file_name) > 0) {
+                       drmfd1 = open(drm_file_name, O_CLOEXEC);
+                       if (drmfd1 < 0) {
+                               printf("Failed to open drm device\n");
+                               return EXIT_FAILURE;
+                       }
+               } else {
+                       d = opendir(dir_path);
+                       if (!d) {
+                               printf("Failed to open drm device directory\n");
+                               return EXIT_FAILURE;
+                       }
+                       while ((dir = readdir(d)) != NULL) {
+                               if(strncmp(dir->d_name, DEVICE_NAME, 4) == 0) {
+                                       strcpy(drm_file_name, dir_path);
+                                       strncat(drm_file_name, dir->d_name,
+                                               sizeof(DEVICE_NAME));
+                                       drmfd1 = open(drm_file_name, O_CLOEXEC);
+                                       if (drmfd1 < 0) {
+                                               printf("Failed to open drm device %s\n",
+                                                               drm_file_name);
+                                       }
+                                       printf("No drm device specified, testing %s\n",
+                                                       drm_file_name);
+                                       res = drmModeGetResources(drmfd1);
+                                       if (res && res->count_crtcs > 0 &&
+                                                       res->count_connectors > 0 &&
+                                                       res->count_encoders > 0) {
+                                               printf("No drm device specified, using %s\n",
+                                                               drm_file_name);
+                                               break;
+                                       }
+                                       close(drmfd1);
+                                       drmfd1 = -1;
+                               }
+                       }
+               }
+               if (drmfd1 < 0) {
+                       printf("Failed to open drm device\n");
+                       return EXIT_FAILURE;
+               }
+       }
+
+       /* Get the stream width, height and framesizes of H264 stream */
+       n_frames = stream_framelevel_parsing(&str_context, input_file, max_frames);
+       if (n_frames < 0) {
+               printf("Failed to init frame sizes\n");
+               return EXIT_FAILURE;
+       }
+
+       switch (str_context.pix_fmt) {
+               case AV_PIX_FMT_YUV420P:
+                       fmt.fourcc = V4L2_PIX_FMT_NV12;
+                       fmt.size_num = 3;
+                       fmt.size_den = 2;
+                       break;
+               case AV_PIX_FMT_YUV422P:
+                       fmt.fourcc = V4L2_PIX_FMT_NV16;
+                       fmt.size_num = 2;
+                       fmt.size_den = 1;
+                       break;
+               case AV_PIX_FMT_YUV420P10LE:
+                       fmt.fourcc = V4L2_PIX_FMT_TI1210;
+                       fmt.size_num = 3;
+                       fmt.size_den = 2;
+                       break;
+               case AV_PIX_FMT_YUV422P10LE:
+                       fmt.fourcc = V4L2_PIX_FMT_TI1610;
+                       fmt.size_num = 2;
+                       fmt.size_den = 1;
+                       break;
+               default:
+                       printf("Invalid pixel format detected\n");
+                       return -1;
+       }
+
+       for (i = 0; i < num_devs; i++) {
+               n_outbufs = MAX_OUTBUFS;
+               /* Request number of output buffers based on h264 spec
+                * + display delay */
+               n_capbufs = MIN(MAX_CAPBUFS_H264, (32768 /
+                                       ((str_context.width / 16) *
+                                       (str_context.height / 16)))) +
+                                       DISPLAY_LAG;
+
+               debug_printf("Opening input file\n");
+               rdfd = open(input_file, O_RDONLY);
+               if (rdfd < 0) {
+                       printf("Failed to open input file %s", input_file);
+               }
+
+               if (strcmp(output_file_base, "")) {
+                       snprintf(output_file, sizeof(output_file),
+                                       "%s_%02d.raw", output_file_base, i);
+                       wrfd = open(output_file,
+                                       O_CREAT | O_WRONLY | O_SYNC | O_TRUNC,
+                                       0777);
+               }
+
+               if (wrfd < 0) {
+                       if (strcmp(output_file_base, "")) {
+                               printf("Failed to open output file %s\n",
+                                               output_file);
+                               return EXIT_FAILURE;
+                       } else {
+                               printf("No output file specified\n");
+                       }
+               } else {
+                       debug_printf("Opened output file %s\n", output_file);
+               }
+
+               ret = init_device(fds[i], rdfd, &str_context, outbufs,
+                               capbufs, &n_outbufs, &n_capbufs, fmt, use_drm_capbuff);
+               if (ret) {
+                       printf("init_device failed with ret %d for device %d [fd%d]\n",
+                                       ret, i, fds[i]);
+                       return EXIT_FAILURE;
+               }
+
+               if (mainloop(fds[i], rdfd, wrfd, &str_context, outbufs,
+                                       capbufs, n_outbufs,
+                                       n_capbufs, n_frames,
+                                       enable_prof, fmt,
+                                       sleep_time, use_drm_capbuff)) {
+                       return EXIT_FAILURE;
+               }
+
+               close(rdfd);
+               if (!(wrfd < 0))
+                       close(wrfd);
+               rdfd = -1;
+               wrfd = -1;
+
+               uninit_device(fds[i], outbufs, capbufs, &n_outbufs, &n_capbufs, use_drm_capbuff);
+
+               debug_printf("*** Calling close_device for device %d [fd%d]\n",
+                               i, fds[i]);
+               close_device(fds[i]);
+       }
+
+       if (use_drm_capbuff && drmfd1)
+               close(drmfd1);
+
+       printf("test app completed successfully\n");
+       return 0;
+}