commit 3429174f7f82d4ab17bb892c8d553929f833c3e7
Author: Nikhil Dasan <a0496626@ti.com>
Date:   Tue Sep 3 15:58:57 2024 +0530

    decode display
    
    Signed-off-by: Nikhil Dasan <a0496626@ti.com>

diff --git a/apps/basic_demos/app_decode_display/concerto.mak b/apps/basic_demos/app_decode_display/concerto.mak
new file mode 100644
index 0000000..0c62cae
--- /dev/null
+++ b/apps/basic_demos/app_decode_display/concerto.mak
@@ -0,0 +1,19 @@
+ifeq ($(TARGET_CPU), $(filter $(TARGET_CPU), A72))
+
+include $(PRELUDE)
+
+TARGET      := vx_app_decode_display
+TARGETTYPE  := exe
+
+CSOURCES    = main.c
+
+IDIRS       += $(TIOVX_PATH)/utils/include
+
+include $(VISION_APPS_PATH)/apps/concerto_mpu_inc.mak
+
+IDIRS += $(VISION_APPS_KERNELS_IDIRS)
+IDIRS += $(VISION_APPS_MODULES_IDIRS)
+
+include $(FINALE)
+
+endif
diff --git a/apps/basic_demos/app_decode_display/main.c b/apps/basic_demos/app_decode_display/main.c
new file mode 100644
index 0000000..bccef7f
--- /dev/null
+++ b/apps/basic_demos/app_decode_display/main.c
@@ -0,0 +1,192 @@
+
+///
+/// @copyright Copyright (c) 2023 Ford Motor Company
+///
+/// CONFIDENTIAL - FORD MOTOR COMPANY
+///
+/// This is an unpublished work, which is a trade secret, created in 2023. Ford Motor Company owns all rights to this
+/// work and intends to maintain it in confidence to preserve its trade secret status. Ford Motor Company reserves the
+/// right to protect this work as an unpublished copyrighted work in the event of an inadvertent or deliberate
+/// unauthorized publication. Ford Motor Company also reserves its rights under the copyright laws to protect this work
+/// as a published work. Those having access to this work may not copy it, use it, or disclose the information contained
+/// in it without the written authorization of Ford Motor Company.
+///
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <utils/app_init/include/app_init.h>
+#include <TI/tivx.h>
+#include <TI/video_io_kernels.h>
+#include <TI/video_io_display.h>
+#include "v4l2_decode_module.h"
+
+#define EDGEAI_DATA_PATH    "/opt/vision_apps/test_data"
+#define APP_BUFQ_DEPTH      (6)
+#define DISPLAY_PIPE_UP     (2)
+#define APP_NUM_ITERATIONS  (10000)
+
+/*
+ * Utility API used to add a graph parameter from a node, node parameter index
+ */
+static void add_graph_parameter_by_node_index(vx_graph graph, vx_node node, vx_uint32 node_parameter_index)
+{
+    vx_parameter parameter = vxGetParameterByIndex(node, node_parameter_index);
+
+    vxAddParameterToGraph(graph, parameter);
+    vxReleaseParameter(&parameter);
+}
+
+int main()
+{
+    vx_image image_nv12[APP_BUFQ_DEPTH];
+    vx_graph graph = NULL;
+    vx_status status = VX_SUCCESS;
+    vx_graph_parameter_queue_params_t graph_parameters_queue_params_list[1];
+    vx_uint32 buf_id = 0;
+    vx_image test_image;
+    uint32_t num_refs_capture;
+
+    v4l2DecodeCfg v4l2_decode_cfg;
+    v4l2DecodeHandle *v4l2_decode_handle;
+    v4l2DecodeOutFmt v4l2_decode_fmt;
+    Buf *dqbuf = NULL;
+    Buf enqbuf = {0};
+    uint32_t curr_id = 0xFF, prev_id = 0xFF;
+
+
+    tivx_display_params_t display_params;
+    vx_user_data_object display_param_obj;
+    vx_node displayNode;
+
+    status = appInit();
+
+    vx_context context;
+    context = vxCreateContext();
+    status = vxGetStatus((vx_reference) context);
+
+    tivxVideoIOLoadKernels(context);
+
+    v4l2_decode_init_cfg(&v4l2_decode_cfg);
+    v4l2_decode_cfg.bufq_depth = APP_BUFQ_DEPTH;
+    sprintf(v4l2_decode_cfg.file, "%s/videos/video0_1280_768.h265", EDGEAI_DATA_PATH);
+    v4l2_decode_handle = v4l2_decode_create_handle(&v4l2_decode_cfg, &v4l2_decode_fmt);
+
+    // build the graph
+    if(status == VX_SUCCESS)
+    {
+        graph = vxCreateGraph(context);
+        status = vxGetStatus((vx_reference)graph);
+        if(status == VX_SUCCESS)
+        {
+            VX_PRINT(VX_ZONE_INFO,"Successfully created graph. Status: %d.\n", status);
+            for (buf_id=0; buf_id< APP_BUFQ_DEPTH; buf_id++)
+            {
+                image_nv12[buf_id] = vxCreateImage(context,v4l2_decode_fmt.width, v4l2_decode_fmt.height, VX_DF_IMAGE_NV12);
+                status |= vxGetStatus((vx_reference)image_nv12[buf_id]);
+            }
+            memset(&display_params, 0, sizeof(tivx_display_params_t));
+            display_params.opMode = TIVX_KERNEL_DISPLAY_ZERO_BUFFER_COPY_MODE;
+            display_params.pipeId = 0; // TODO: Need to clean this up ultimately when merging back to mainline
+            display_params.outHeight = v4l2_decode_fmt.height;
+            display_params.outWidth = v4l2_decode_fmt.width;
+            display_params.posX = 0;
+            display_params.posY = 0;
+            display_param_obj = vxCreateUserDataObject(context, "tivx_display_params_t", sizeof(tivx_display_params_t), &display_params);
+            displayNode = tivxDisplayNode(graph, display_param_obj, image_nv12[0]);
+            status = vxSetNodeTarget(displayNode, VX_TARGET_STRING, TIVX_TARGET_DISPLAY1);
+        }        
+    }
+
+    if(status == VX_SUCCESS)
+    {
+        uint32_t graph_parameter_num = 0;
+        add_graph_parameter_by_node_index(graph, displayNode, 1);
+        /* set graph schedule config such that graph parameter @ index 0 is enqueuable */
+        graph_parameters_queue_params_list[graph_parameter_num].graph_parameter_index = graph_parameter_num;
+        graph_parameters_queue_params_list[graph_parameter_num].refs_list_size = APP_BUFQ_DEPTH;
+        graph_parameters_queue_params_list[graph_parameter_num].refs_list = (vx_reference*)&(image_nv12[0]);
+        graph_parameter_num++;
+
+        status = vxSetGraphScheduleConfig(graph,
+                        VX_GRAPH_SCHEDULE_MODE_QUEUE_AUTO,
+                        graph_parameter_num,
+                        graph_parameters_queue_params_list
+                        );
+    }
+
+    // Verify the graph
+    if(status == VX_SUCCESS)
+    {
+        status = vxVerifyGraph(graph);
+        if (status == VX_SUCCESS)
+        {
+            VX_PRINT(VX_ZONE_INFO,"Graph verification successful.\n");
+        }
+        else
+        {
+            VX_PRINT(VX_ZONE_ERROR, "Graph verification failed. Status : %d\n", status);
+        }
+    }
+
+    for (int i = 0; i < APP_BUFQ_DEPTH; i++) {
+        enqbuf.buf_index = i;
+        enqbuf.handle = (vx_reference)image_nv12[i];
+        v4l2_decode_enqueue_buf(v4l2_decode_handle, &enqbuf);
+    }
+    v4l2_decode_start(v4l2_decode_handle);
+
+    if(status == VX_SUCCESS)
+    {
+        for(buf_id = 0; buf_id < DISPLAY_PIPE_UP; buf_id++)
+        {
+            prev_id = curr_id;
+            dqbuf = v4l2_decode_dqueue_buf(v4l2_decode_handle);
+            curr_id = dqbuf->buf_index;
+            status = vxGraphParameterEnqueueReadyRef(graph, 0, (vx_reference*)&(image_nv12[curr_id]), 1);
+        }
+
+        for (int i = 0; i < APP_NUM_ITERATIONS; i++)
+        {
+            if(status == VX_SUCCESS)
+            {
+                status = vxGraphParameterDequeueDoneRef(graph, 0, (vx_reference*)&test_image, 1, &num_refs_capture);
+                enqbuf.buf_index = prev_id;
+                enqbuf.handle = (vx_reference)test_image;
+                v4l2_decode_enqueue_buf(v4l2_decode_handle, &enqbuf);
+            }
+            if(status == VX_SUCCESS)
+            {
+                prev_id = curr_id;
+                dqbuf = v4l2_decode_dqueue_buf(v4l2_decode_handle);
+                curr_id = dqbuf->buf_index;
+                status = vxGraphParameterEnqueueReadyRef(graph, 0, (vx_reference*)&image_nv12[curr_id], 1);
+            }
+        }
+
+        v4l2_decode_stop(v4l2_decode_handle);
+
+        for(buf_id = 0; buf_id < DISPLAY_PIPE_UP-1; buf_id++)
+        {
+            status = vxGraphParameterDequeueDoneRef(graph, 0, (vx_reference*)&test_image, 1, &num_refs_capture);
+        }
+    }
+
+    printf("Completed...... Status : %d\n", status);
+
+    v4l2_decode_delete_handle(v4l2_decode_handle);
+
+    for(buf_id=0; buf_id<APP_BUFQ_DEPTH; buf_id++)
+    {
+        vxReleaseImage(&image_nv12[buf_id]);
+    }
+    vxReleaseUserDataObject(&display_param_obj);
+    vxReleaseNode(&displayNode);
+    vxReleaseGraph(&graph);
+    tivxVideoIOUnLoadKernels(context);
+    vxReleaseContext(&context);
+
+    appDeInit();
+
+    return 0;
+}
diff --git a/modules/concerto.mak b/modules/concerto.mak
index 46bbd34..841c70d 100644
--- a/modules/concerto.mak
+++ b/modules/concerto.mak
@@ -20,6 +20,7 @@ STATIC_LIBS     += $(VISION_APPS_STEREO_LIBS)
 STATIC_LIBS     += $(VISION_APPS_SRV_LIBS)
 
 SHARED_LIBS += GLESv2 EGL
+SHARED_LIBS += avformat avutil avcodec
 
 ifeq ($(TARGET_OS),LINUX)
 SHARED_LIBS += rt gbm
diff --git a/modules/include/codec_input_demuxer.h b/modules/include/codec_input_demuxer.h
new file mode 100644
index 0000000..8e2b3e4
--- /dev/null
+++ b/modules/include/codec_input_demuxer.h
@@ -0,0 +1,103 @@
+/*
+ *
+ * Copyright (c) 2024 Texas Instruments Incorporated
+ *
+ * All rights reserved not granted herein.
+ *
+ * Limited License.
+ *
+ * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
+ * license under copyrights and patents it now or hereafter owns or controls to make,
+ * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
+ * terms herein.  With respect to the foregoing patent license, such license is granted
+ * solely to the extent that any such patent is necessary to Utilize the software alone.
+ * The patent license shall not apply to any combinations which include this software,
+ * other than combinations with devices manufactured by or for TI ("TI Devices").
+ * No hardware patent is licensed hereunder.
+ *
+ * Redistributions must preserve existing copyright notices and reproduce this license
+ * (including the above copyright notice and the disclaimer and (if applicable) source
+ * code license limitations below) in the documentation and/or other materials provided
+ * with the distribution
+ *
+ * Redistribution and use in binary form, without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *       No reverse engineering, decompilation, or disassembly of this software is
+ * permitted with respect to any software provided in binary form.
+ *
+ * *       any redistribution and use are licensed by TI for use only with TI Devices.
+ *
+ * *       Nothing shall obligate TI to provide you with source code for the software
+ * licensed and provided to you in object code.
+ *
+ * If software source code is provided to you, modification and redistribution of the
+ * source code are permitted provided that the following conditions are met:
+ *
+ * *       any redistribution and use of the source code, including any resulting derivative
+ * works, are licensed by TI for use only with TI Devices.
+ *
+ * *       any redistribution and use of any object code compiled from the source code
+ * and any resulting derivative works, are licensed by TI for use only with TI Devices.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
+ *
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * DISCLAIMER.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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 _CODEC_INPUT_DEMUXER
+#define _CODEC_INPUT_DEMUXER
+
+#include <libavformat/avformat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_FRAMES 1000
+
+#ifdef TIOVX_MODULE_DEBUG
+#define TIOVX_MODULE_PRINTF(f_, ...) printf("[TIOVX_MODULES][DEBUG] %d: %s: "f_, __LINE__, __func__, ##__VA_ARGS__)
+#else
+#define TIOVX_MODULE_PRINTF(f_, ...)
+#endif
+
+#define TIOVX_MODULE_ERROR(f_, ...) printf("[TIOVX_MODULES][ERROR] %d: %s: "f_, __LINE__, __func__, ##__VA_ARGS__)
+
+typedef struct
+{
+    size_t frame_sizes[MAX_FRAMES];
+    int width;
+    int height;
+    int bitdepth;
+    int num_bytes_per_pix;
+    enum AVPixelFormat pix_fmt;
+    enum AVCodecID codec;
+    int profile;
+    int level;
+    int num_frames;
+} streamContext;
+
+int stream_framelevel_parsing(streamContext *str, char *input_file,
+        int max_frames);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_CODEC_INPUT_DEMUXER
diff --git a/modules/include/v4l2_decode_module.h b/modules/include/v4l2_decode_module.h
new file mode 100644
index 0000000..55083f1
--- /dev/null
+++ b/modules/include/v4l2_decode_module.h
@@ -0,0 +1,171 @@
+/*
+ *
+ * Copyright (c) 2024 Texas Instruments Incorporated
+ *
+ * All rights reserved not granted herein.
+ *
+ * Limited License.
+ *
+ * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
+ * license under copyrights and patents it now or hereafter owns or controls to make,
+ * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
+ * terms herein.  With respect to the foregoing patent license, such license is granted
+ * solely to the extent that any such patent is necessary to Utilize the software alone.
+ * The patent license shall not apply to any combinations which include this software,
+ * other than combinations with devices manufactured by or for TI ("TI Devices").
+ * No hardware patent is licensed hereunder.
+ *
+ * Redistributions must preserve existing copyright notices and reproduce this license
+ * (including the above copyright notice and the disclaimer and (if applicable) source
+ * code license limitations below) in the documentation and/or other materials provided
+ * with the distribution
+ *
+ * Redistribution and use in binary form, without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *       No reverse engineering, decompilation, or disassembly of this software is
+ * permitted with respect to any software provided in binary form.
+ *
+ * *       any redistribution and use are licensed by TI for use only with TI Devices.
+ *
+ * *       Nothing shall obligate TI to provide you with source code for the software
+ * licensed and provided to you in object code.
+ *
+ * If software source code is provided to you, modification and redistribution of the
+ * source code are permitted provided that the following conditions are met:
+ *
+ * *       any redistribution and use of the source code, including any resulting derivative
+ * works, are licensed by TI for use only with TI Devices.
+ *
+ * *       any redistribution and use of any object code compiled from the source code
+ * and any resulting derivative works, are licensed by TI for use only with TI Devices.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
+ *
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * DISCLAIMER.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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 _V4L2_DECODE_MODULE
+#define _V4L2_DECODE_MODULE
+
+#include <linux/videodev2.h>
+#include "app_modules.h"
+#include <semaphore.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef TIOVX_MODULE_DEBUG
+#define TIOVX_MODULE_PRINTF(f_, ...) printf("[TIOVX_MODULES][DEBUG] %d: %s: "f_, __LINE__, __func__, ##__VA_ARGS__)
+#else
+#define TIOVX_MODULE_PRINTF(f_, ...)
+#endif
+
+#define TIOVX_MODULE_ERROR(f_, ...) printf("[TIOVX_MODULES][ERROR] %d: %s: "f_, __LINE__, __func__, ##__VA_ARGS__)
+
+#define CLR(o) memset(o, 0, sizeof(*o))
+
+#define TIOVX_MODULES_MAX_BUFQ_DEPTH (16u)
+
+typedef struct {
+    char        device[TIVX_TARGET_MAX_NAME];
+    char        file[TIVX_TARGET_MAX_NAME];
+    uint32_t    bufq_depth;
+} v4l2DecodeCfg;
+
+typedef struct {
+    uint32_t    width;
+    uint32_t    height;
+    uint32_t    color_format;
+} v4l2DecodeOutFmt;
+
+typedef struct _Buf     Buf;
+typedef struct _BufPool BufPool;
+
+/*!
+ * \brief Structure describing a Buffer object.
+ */
+struct _Buf {
+   /*! \brief Bufferpool to which the buffer belongs to \ref _BufPool */
+   BufPool            *pool;
+
+/*! \brief Index of the buffer with respect to all the buffers in the pool */
+   vx_int32           buf_index;
+
+/*! \brief Object array for the buffer */
+   vx_object_array    arr;
+
+/*! \brief 0th handle of the object array */
+   vx_reference       handle;
+
+/*! \brief Number of channels */
+   vx_int32           num_channels;
+};
+
+/*!
+ * \brief Structure describing a Buffer pool.
+ */
+struct _BufPool {
+/*! \brief List of buffers in the pool \ref _Buf */
+   Buf                bufs[TIOVX_MODULES_MAX_BUFQ_DEPTH];
+
+/*! \brief Number of buffers in the pool */
+   vx_int32           bufq_depth;
+
+/*! \brief Array that contains all free buffers \ref _Buf */
+   Buf                *freeQ[TIOVX_MODULES_MAX_BUFQ_DEPTH];
+
+/*! \brief Number of buffers that are free */
+   vx_int32           free_count;
+
+/*! \brief List of buffers that are enqueued \ref _Buf */
+   Buf                *enqueuedQ[TIOVX_MODULES_MAX_BUFQ_DEPTH];
+
+/*! \brief Head pointer for queue management */
+   vx_int32           enqueue_head;
+
+/*! \brief Tail pointer for queue management */
+   vx_int32           enqueue_tail;
+
+/*! \brief Ref list for graph param */
+   vx_reference       ref_list[TIOVX_MODULES_MAX_BUFQ_DEPTH];
+
+/*! \brief Mutex for queue management */
+   pthread_mutex_t    lock;
+
+/*! \brief Semaphore for acquire and release */
+   sem_t              sem;
+};
+
+typedef struct _v4l2DecodeHandle v4l2DecodeHandle;
+
+void v4l2_decode_init_cfg(v4l2DecodeCfg *cfg);
+v4l2DecodeHandle *v4l2_decode_create_handle(v4l2DecodeCfg *cfg,
+                                            v4l2DecodeOutFmt *out_fmt);
+int v4l2_decode_start(v4l2DecodeHandle *handle);
+int v4l2_decode_enqueue_buf(v4l2DecodeHandle *handle, Buf *tiovx_buffer);
+Buf *v4l2_decode_dqueue_buf(v4l2DecodeHandle *handle);
+int v4l2_decode_stop(v4l2DecodeHandle *handle);
+int v4l2_decode_delete_handle(v4l2DecodeHandle *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/modules/src/codec_input_demuxer.c b/modules/src/codec_input_demuxer.c
new file mode 100644
index 0000000..1aadf16
--- /dev/null
+++ b/modules/src/codec_input_demuxer.c
@@ -0,0 +1,304 @@
+/*
+ *
+ * Copyright (c) 2024 Texas Instruments Incorporated
+ *
+ * All rights reserved not granted herein.
+ *
+ * Limited License.
+ *
+ * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
+ * license under copyrights and patents it now or hereafter owns or controls to make,
+ * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
+ * terms herein.  With respect to the foregoing patent license, such license is granted
+ * solely to the extent that any such patent is necessary to Utilize the software alone.
+ * The patent license shall not apply to any combinations which include this software,
+ * other than combinations with devices manufactured by or for TI ("TI Devices").
+ * No hardware patent is licensed hereunder.
+ *
+ * Redistributions must preserve existing copyright notices and reproduce this license
+ * (including the above copyright notice and the disclaimer and (if applicable) source
+ * code license limitations below) in the documentation and/or other materials provided
+ * with the distribution
+ *
+ * Redistribution and use in binary form, without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *       No reverse engineering, decompilation, or disassembly of this software is
+ * permitted with respect to any software provided in binary form.
+ *
+ * *       any redistribution and use are licensed by TI for use only with TI Devices.
+ *
+ * *       Nothing shall obligate TI to provide you with source code for the software
+ * licensed and provided to you in object code.
+ *
+ * If software source code is provided to you, modification and redistribution of the
+ * source code are permitted provided that the following conditions are met:
+ *
+ * *       any redistribution and use of the source code, including any resulting derivative
+ * works, are licensed by TI for use only with TI Devices.
+ *
+ * *       any redistribution and use of any object code compiled from the source code
+ * and any resulting derivative works, are licensed by TI for use only with TI Devices.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
+ *
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * DISCLAIMER.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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 "codec_input_demuxer.h"
+
+#include <libavcodec/avcodec.h>
+#include <libavcodec/bsf.h>
+#include <libavutil/pixdesc.h>
+
+struct ESdescriptor {
+    int length;
+    unsigned char *data;
+};
+
+struct demux {
+    AVFormatContext *afc;
+    AVStream *st;
+    AVCodecParameters *cc;
+    AVBSFContext *bsfcontext;
+    struct ESdescriptor esds;
+    /* Used for mpeg4 esds data copy */
+    int first_in_buff;
+};
+
+static AVFormatContext *open_stream_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) {
+        TIOVX_MODULE_ERROR("[CODEC_DEMUX] %s: lavf error %d\n", 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]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !st)
+            st = afc->streams[i];
+        else
+            afc->streams[i]->discard = AVDISCARD_ALL;
+    }
+
+    return st;
+}
+
+struct demux *demux_init(const char * filename, int *width, int *height,
+        int *bitdepth, enum AVPixelFormat *pix_fmt, enum AVCodecID *codec)
+{
+    struct demux *demux = NULL;
+    AVFormatContext *afc = open_stream_file(filename);
+    AVStream *st = find_stream(afc);
+    AVCodecParameters *cc = st->codecpar;
+    const AVBitStreamFilter *bsf = NULL;
+    AVBSFContext *bsfcontext = NULL;
+
+    if ((cc->codec_id != AV_CODEC_ID_H264) &&
+        (cc->codec_id != AV_CODEC_ID_HEVC)) {
+        TIOVX_MODULE_ERROR("[CODEC_DEMUX] could not open '%s': "
+                "unsupported codec %d", filename, cc->codec_id);
+        return NULL;
+    }
+
+    if (cc->extradata && cc->extradata_size > 0 && cc->extradata[0] == 1) {
+        TIOVX_MODULE_ERROR("[CODEC_DEMUX] initializing bitstream filter");
+        if(cc->codec_id == AV_CODEC_ID_H264) {
+            bsf = av_bsf_get_by_name("h264_mp4toannexb");
+            av_bsf_alloc(bsf,&bsfcontext);
+            av_bsf_init(bsfcontext);
+        } else {
+            bsf = av_bsf_get_by_name("hevc_mp4toannexb");
+            av_bsf_alloc(bsf,&bsfcontext);
+            av_bsf_init(bsfcontext);
+        }
+        if (!bsf) {
+            TIOVX_MODULE_ERROR("[CODEC_DEMUX] 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->format;
+    *codec = cc->codec_id;
+
+    demux = calloc(1, sizeof(*demux));
+
+    demux->afc = afc;
+    demux->cc = cc;
+    demux->st = st;
+    demux->bsfcontext = bsfcontext;
+    demux->first_in_buff = 0;
+
+    return demux;
+}
+
+int demux_read(struct demux *demux, unsigned char *input, int size)
+{
+    AVPacket pk = { };
+    int count=-1;
+    while (!av_read_frame(demux->afc, &pk)) {
+        if (pk.stream_index == demux->st->index) {
+            count++;
+            uint8_t *buf = NULL;
+            int bufsize = 0;
+
+            if (demux->bsfcontext) {
+                int ret;
+                ret = av_bsf_send_packet(demux->bsfcontext,&pk);
+                if (ret < 0) {
+                    TIOVX_MODULE_ERROR("[CODEC_DEMUX] bsf_send_packet error: %d",
+                            ret);
+                    return 0;
+                }
+                while(av_bsf_receive_packet(demux->bsfcontext,&pk) == 0) {
+                    bufsize+=pk.size;
+                }
+            } 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->bsfcontext)
+                av_free(buf);
+
+            av_packet_unref(&pk);
+
+            return bufsize;
+        }
+        av_packet_unref(&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->bsfcontext)
+         av_bsf_free(&demux->bsfcontext);
+    free(demux->esds.data);
+    free(demux);
+}
+
+int stream_framelevel_parsing(streamContext *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;
+    unsigned char *inp_buf;
+
+    demux = demux_init(input_file, &inp_width, &inp_height, &bitdepth, &pix_fmt,
+                       &codec);
+    if (!demux)
+    {
+        TIOVX_MODULE_ERROR("[CODEC_DEMUX] could not open demuxer\n");
+        return -1;
+    }
+
+    inp_buf_len = (inp_width * inp_height);
+
+    inp_buf = malloc(inp_buf_len);
+    if(inp_buf == NULL)
+    {
+        TIOVX_MODULE_ERROR("[CODEC_DEMUX] Memory allocation failed "
+                "for inp_buf\n");
+        return -1;
+    }
+
+    TIOVX_MODULE_PRINTF("[CODEC_DEMUX] demuxer is initialized, "
+                                "width=%d, height=%d\n", inp_width, inp_height);
+    str->width = inp_width;
+    str->height = inp_height;
+    str->bitdepth = bitdepth;
+    str->pix_fmt = pix_fmt;
+    str->codec = codec;
+    str->profile = demux->cc->profile;
+    str->level = demux->cc->level;
+
+
+    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;
+
+    while(1)
+    {
+        frame_size = demux_read(demux, inp_buf, inp_buf_len);
+        if (frame_size)
+        {
+            str->frame_sizes[frame_num] = frame_size;
+            frame_num++;
+        } else {
+            break;
+        }
+        if (max_frames > 0 && frame_num >= max_frames)
+            break;
+    }
+
+    demux_deinit(demux);
+    free(inp_buf);
+
+    str->num_frames = frame_num;
+
+    return frame_num;
+}
diff --git a/modules/src/concerto.mak b/modules/src/concerto.mak
index ae3ba90..fc8b554 100755
--- a/modules/src/concerto.mak
+++ b/modules/src/concerto.mak
@@ -18,12 +18,15 @@ CSOURCES    += app_scaler_module.c
 CSOURCES    += app_tidl_module.c
 CSOURCES    += app_img_mosaic_module.c
 CSOURCES    += app_obj_arr_split_module.c
+CSOURCES    += v4l2_decode_module.c
+CSOURCES    += codec_input_demuxer.c
 
 IDIRS       += $(IMAGING_IDIRS)
 IDIRS       += $(VISION_APPS_PATH)/kernels/img_proc/include
 IDIRS       += $(VISION_APPS_PATH)/kernels/fileio/include
 IDIRS       += $(TIDL_PATH)/ti_dl/inc
 IDIRS       += $(VISION_APPS_PATH)/modules/include
+IDIRS       += $(APP_UTILS_PATH)
 
 include $(FINALE)
 
diff --git a/modules/src/v4l2_decode_module.c b/modules/src/v4l2_decode_module.c
new file mode 100644
index 0000000..8455193
--- /dev/null
+++ b/modules/src/v4l2_decode_module.c
@@ -0,0 +1,671 @@
+/*
+ *
+ * Copyright (c) 2024 Texas Instruments Incorporated
+ *
+ * All rights reserved not granted herein.
+ *
+ * Limited License.
+ *
+ * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
+ * license under copyrights and patents it now or hereafter owns or controls to make,
+ * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
+ * terms herein.  With respect to the foregoing patent license, such license is granted
+ * solely to the extent that any such patent is necessary to Utilize the software alone.
+ * The patent license shall not apply to any combinations which include this software,
+ * other than combinations with devices manufactured by or for TI ("TI Devices").
+ * No hardware patent is licensed hereunder.
+ *
+ * Redistributions must preserve existing copyright notices and reproduce this license
+ * (including the above copyright notice and the disclaimer and (if applicable) source
+ * code license limitations below) in the documentation and/or other materials provided
+ * with the distribution
+ *
+ * Redistribution and use in binary form, without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *       No reverse engineering, decompilation, or disassembly of this software is
+ * permitted with respect to any software provided in binary form.
+ *
+ * *       any redistribution and use are licensed by TI for use only with TI Devices.
+ *
+ * *       Nothing shall obligate TI to provide you with source code for the software
+ * licensed and provided to you in object code.
+ *
+ * If software source code is provided to you, modification and redistribution of the
+ * source code are permitted provided that the following conditions are met:
+ *
+ * *       any redistribution and use of the source code, including any resulting derivative
+ * works, are licensed by TI for use only with TI Devices.
+ *
+ * *       any redistribution and use of any object code compiled from the source code
+ * and any resulting derivative works, are licensed by TI for use only with TI Devices.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
+ *
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * DISCLAIMER.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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 "v4l2_decode_module.h"
+#include "codec_input_demuxer.h"
+#include <utils/mem/include/app_mem.h>
+
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <poll.h>
+
+#define TIOVX_MODULES_DATA_PATH "/opt/vision_apps/test_data"
+#define V4L2_DECODE_DEFAULT_DEVICE "/dev/video0"
+#define V4L2_DECODE_DEFAULT_INPUT_FILE TIOVX_MODULES_DATA_PATH"/videos/video0_1280_768.h264"
+#define V4L2_DECODE_DEFAULT_BUFQ_DEPTH 4
+#define V4L2_DECODE_MAX_BUFQ_DEPTH 10
+#define V4L2_DECODE_MAX_BUFQ_DEPTH_OFFSET 3 //This is set in wave5 driver
+
+#define MAX_OUTBUFS 4
+#define ALIGN(x,a) (((x) + (a) - 1L) & ~((a) - 1L))
+#define HW_ALIGN 64
+
+void v4l2_decode_init_cfg(v4l2DecodeCfg *cfg)
+{
+    cfg->bufq_depth = V4L2_DECODE_DEFAULT_BUFQ_DEPTH;
+    sprintf(cfg->device, V4L2_DECODE_DEFAULT_DEVICE);
+    sprintf(cfg->file, V4L2_DECODE_DEFAULT_INPUT_FILE);
+}
+
+typedef struct {
+    void *mapped;
+    int offset;
+    int length;
+} outBuf;
+
+struct _v4l2DecodeHandle {
+    v4l2DecodeCfg cfg;
+    int fd;
+    Buf *bufq[V4L2_DECODE_MAX_BUFQ_DEPTH];
+    bool queued[V4L2_DECODE_MAX_BUFQ_DEPTH];
+    streamContext str;
+    uint32_t num_outbufs;
+    outBuf outbufs[MAX_OUTBUFS];
+    FILE *rdfd;
+    int current_frame;
+    uint8_t outbuf_head;
+    uint8_t outbuf_tail;
+};
+
+static int getImageDmaFd(vx_reference ref, vx_int32 *fd, vx_uint32 *pitch, vx_uint64 *size, vx_uint32 *offset, vx_uint32 count)
+{
+   vx_image img = (vx_image)ref;
+   vx_rectangle_t rect;
+   vx_imagepatch_addressing_t image_addr;
+   vx_map_id map_id;
+   void * data_ptr;
+   vx_uint32 img_width;
+   vx_uint32 img_height;
+   vx_size   num_planes;
+   vx_df_image img_format;
+   vx_status status;
+
+   vxQueryImage(img, VX_IMAGE_WIDTH, &img_width, sizeof(vx_uint32));
+   vxQueryImage(img, VX_IMAGE_HEIGHT, &img_height, sizeof(vx_uint32));
+   vxQueryImage(img, VX_IMAGE_PLANES, &num_planes, sizeof(vx_size));
+   vxQueryImage(img, VX_IMAGE_FORMAT, &img_format, sizeof(vx_df_image));
+
+   if (num_planes > count) {
+       TIOVX_MODULE_ERROR("Count < number of planes\n");
+       return -1;
+   }
+
+   for (vx_uint32 plane = 0; plane < num_planes; plane++)
+   {
+       rect.start_x = 0;
+       rect.start_y = 0;
+       rect.end_x = img_width;
+       rect.end_y = img_height;
+       status = vxMapImagePatch(img,
+                               &rect,
+                               plane,
+                               &map_id,
+                               &image_addr,
+                               &data_ptr,
+                               VX_WRITE_ONLY,
+                               VX_MEMORY_TYPE_HOST,
+                               VX_NOGAP_X);
+       if(VX_SUCCESS != status) {
+           TIOVX_MODULE_ERROR("Map Image failed\n");
+           return -1;
+       }
+       pitch[plane] = image_addr.stride_y;
+       size[plane] = (image_addr.dim_y/image_addr.step_y) * ((image_addr.dim_x * image_addr.stride_x)/image_addr.step_x);
+       fd[plane] = appMemGetDmaBufFd(data_ptr, &offset[plane]);
+       vxUnmapImagePatch(img, map_id);
+   }
+
+   return num_planes;
+}
+
+static int xioctl(int fh, int request, void *arg)
+{
+    int r;
+
+    do {
+        r = ioctl(fh, request, arg);
+    } while (-1 == r && EINTR == errno);
+
+    return r;
+}
+
+int v4l2_decode_check_caps(v4l2DecodeHandle *handle)
+{
+    struct v4l2_capability cap;
+    int status = 0;
+
+    if (-1 == xioctl(handle->fd, VIDIOC_QUERYCAP, &cap)) {
+        if (EINVAL == errno) {
+            TIOVX_MODULE_ERROR("[V4L2_DECODE] %s is no V4L2 device\n",
+                    handle->cfg.device);
+        } else {
+            TIOVX_MODULE_ERROR("[V4L2_DECODE] VIDIOC_QUERYCAP Failed\n");
+        }
+
+        status = -1;
+    }
+
+    if (!(cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] %s is not a M2M device\n",
+                    handle->cfg.device);
+        status = -1;
+    }
+
+    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] %s does not support streaming i/o\n",
+                    handle->cfg.device);
+        status = -1;
+    }
+
+    return status;
+}
+
+int v4l2_decode_set_fmt(v4l2DecodeHandle *handle)
+{
+    struct v4l2_format fmt;
+    int status = 0;
+
+    CLR(&fmt);
+    fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    fmt.fmt.pix_mp.width = handle->str.width;
+    fmt.fmt.pix_mp.height = handle->str.height;
+    fmt.fmt.pix_mp.plane_fmt[0].sizeimage = (handle->str.width * handle->str.height);
+    fmt.fmt.pix_mp.num_planes = 1;
+
+    if(handle->str.codec == AV_CODEC_ID_H264) {
+        fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+    } else if(handle->str.codec == AV_CODEC_ID_HEVC) {
+        fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_HEVC;
+    }
+
+    if (0 > xioctl(handle->fd, VIDIOC_S_FMT, &fmt)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Output Set format failed\n");
+        status = -1;
+        goto ret;
+    }
+
+    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
+    fmt.fmt.pix_mp.plane_fmt[0].sizeimage =
+                                fmt.fmt.pix_mp.width * fmt.fmt.pix_mp.height *
+                                handle->str.num_bytes_per_pix * 3 /2;
+    fmt.fmt.pix_mp.width = ALIGN(handle->str.width, HW_ALIGN);
+    fmt.fmt.pix_mp.height = ALIGN(handle->str.height, HW_ALIGN);
+    fmt.fmt.pix_mp.num_planes = 1;
+    fmt.fmt.pix_mp.plane_fmt[0].bytesperline =
+                                            ALIGN(handle->str.width, HW_ALIGN) *
+                                            handle->str.num_bytes_per_pix;
+
+    if (0 > xioctl(handle->fd, VIDIOC_S_FMT, &fmt)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Capture Set format failed\n");
+        status = -1;
+        goto ret;
+    }
+
+ret:
+    return status;
+}
+
+int v4l2_decode_request_capture_buffers(v4l2DecodeHandle *handle)
+{
+    struct v4l2_requestbuffers req;
+    int status = 0;
+
+    CLR(&req);
+    req.count = handle->cfg.bufq_depth + V4L2_DECODE_MAX_BUFQ_DEPTH_OFFSET;
+    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    req.memory = V4L2_MEMORY_DMABUF;
+
+    if (0 > xioctl(handle->fd, VIDIOC_REQBUFS, &req)) {
+        if (EINVAL == errno) {
+            TIOVX_MODULE_ERROR("[V4L2_DECODE] %s does not support DMABUF\n",
+                    handle->cfg.device);
+        } else {
+            TIOVX_MODULE_ERROR("[V4L2_DECODE] VIDIOC_REQBUFS failed\n");
+        }
+        status = -1;
+
+        return status;
+    }
+
+    if (req.count < handle->cfg.bufq_depth) {
+        TIOVX_MODULE_ERROR("Failed to allocate requested buffers,"
+                           " requested %d, allocted %d\n",
+                           handle->cfg.bufq_depth, req.count);
+        status = -1;
+    }
+
+    return status;
+}
+
+int v4l2_decode_request_output_buffers(v4l2DecodeHandle *handle)
+{
+    struct v4l2_requestbuffers req;
+    int status = 0;
+
+    CLR(&req);
+    req.count = MAX_OUTBUFS;
+    req.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    req.memory = V4L2_MEMORY_MMAP;
+
+    if (0 > xioctl(handle->fd, VIDIOC_REQBUFS, &req)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] VIDIOC_REQBUFS failed\n");
+        status = -1;
+        return status;
+    }
+
+    handle->num_outbufs = req.count;
+
+    return status;
+}
+
+int v4l2_decode_map_output_buffers(v4l2DecodeHandle *handle)
+{
+    struct v4l2_buffer buffer;
+    struct v4l2_plane buf_planes[1];
+    int status = 0;
+
+    for (int i = 0; i < handle->num_outbufs; i++) {
+        CLR(&buffer);
+        buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+        buffer.index = i;
+        buffer.m.planes = buf_planes;
+        buffer.length = 1;
+
+        if (0 > xioctl(handle->fd, VIDIOC_QUERYBUF, &buffer)) {
+            TIOVX_MODULE_ERROR("[V4L2_DECODE] VIDIOC_QUERYBUF failed "
+                               ": buf index = %d\n", i);
+            status = -1;
+            return status;
+        }
+
+        handle->outbufs[i].mapped = mmap(NULL, buffer.m.planes[0].length,
+                                PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd,
+                                buffer.m.planes[0].m.mem_offset);
+        handle->outbufs[i].offset = buffer.m.planes[0].m.mem_offset;
+        handle->outbufs[i].length = buffer.m.planes[0].length;
+
+        if (MAP_FAILED == handle->outbufs[i].mapped) {
+            TIOVX_MODULE_ERROR("[V4L2_DECODE] mmap buffer failed "
+                               ": buf index = %d\n", i);
+            status = -1;
+            return status;
+        }
+    }
+    return status;
+}
+
+int v4l2_decode_enqueue_outbuf(v4l2DecodeHandle *handle)
+{
+    struct v4l2_buffer buf;
+    struct v4l2_plane buf_planes[1];
+    int status = 0;
+    outBuf *outbuf;
+
+    if (handle->current_frame >= handle->str.num_frames) {
+        rewind(handle->rdfd);
+        handle->current_frame = 0;
+    }
+
+    if (handle->outbuf_head == handle->outbuf_tail) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Queue Full\n");
+        status = -1;
+        goto ret;
+    }
+
+    CLR(&buf);
+
+    outbuf = &handle->outbufs[handle->outbuf_head];
+    memset(outbuf->mapped, 0, outbuf->length);
+    fread(outbuf->mapped, handle->str.frame_sizes[handle->current_frame],
+            1, handle->rdfd);
+
+    buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    buf.memory = V4L2_MEMORY_MMAP;
+    buf.m.planes = buf_planes;
+    buf.length = 1;
+    buf.index = handle->outbuf_head;
+
+    CLR(&buf_planes[0]);
+    buf_planes[0].bytesused = handle->str.frame_sizes[handle->current_frame];
+    buf_planes[0].m.mem_offset = outbuf->offset;
+    buf_planes[0].data_offset = 0;
+
+    if (-1 == xioctl(handle->fd, VIDIOC_QBUF, &buf)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] VIDIOC_QBUF failed\n");
+        status = -1;
+    } else {
+        handle->outbuf_head = (handle->outbuf_head + 1) % handle->num_outbufs;
+    }
+
+    handle->current_frame += 1;
+
+ret:
+    return status;
+
+}
+
+int v4l2_decode_dqueue_outbuf(v4l2DecodeHandle *handle)
+{
+    struct v4l2_buffer buf;
+    struct v4l2_plane buf_planes[3];
+    int status = 0;
+
+    if ((handle->outbuf_tail + 1) % handle->num_outbufs == handle->outbuf_head) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Queue Empty\n");
+        status = -1;
+        return status;
+    } else {
+        handle->outbuf_tail = (handle->outbuf_tail + 1) %
+                                                handle->num_outbufs;
+    }
+
+    CLR(&buf);
+    buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    buf.memory = V4L2_MEMORY_MMAP;
+    buf.m.planes = buf_planes;
+    buf.length = 1;
+
+    while (1) {
+        if (-1 == xioctl(handle->fd, VIDIOC_DQBUF, &buf)) {
+            if (errno == EAGAIN) {
+                continue;
+            } else {
+                TIOVX_MODULE_ERROR("[V4L2_DECODE] VIDIOC_DQBUF failed\n");
+                status = -1;
+                break;
+            }
+        } else {
+            break;
+        }
+    }
+
+    return status;
+}
+
+int v4l2_decode_start_output(v4l2DecodeHandle *handle)
+{
+    int status = 0;
+    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+    if (-1 == xioctl(handle->fd, VIDIOC_STREAMON, &type)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] output VIDIOC_STREAMON failed\n");
+        status = -1;
+    }
+
+    return status;
+}
+
+v4l2DecodeHandle *v4l2_decode_create_handle(v4l2DecodeCfg *cfg,
+                                            v4l2DecodeOutFmt *out_fmt)
+{
+    v4l2DecodeHandle *handle = NULL;
+
+    handle = malloc(sizeof(v4l2DecodeHandle));
+    handle->fd = -1;
+    handle->current_frame = 0;
+    memcpy(&handle->cfg, cfg, sizeof(v4l2DecodeCfg));
+
+    if (stream_framelevel_parsing(&handle->str, cfg->file, MAX_FRAMES) < 0) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Stream parsing failed\n");
+        goto free_handle;
+    }
+
+    handle->rdfd = fopen(cfg->file, "r");
+    if (handle->rdfd  == NULL) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Failed to open input file %s\n",
+                            cfg->file);
+        goto free_handle;
+    }
+
+    handle->fd = open(cfg->device, O_RDWR | O_NONBLOCK, 0);
+    if (-1 == handle->fd) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Cannot open '%s': %d, %s\n",
+                            cfg->device, errno, strerror(errno));
+        goto free_handle;
+    }
+
+    if (0 != v4l2_decode_check_caps(handle)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Check caps failed\n");
+        goto free_fd;
+    }
+
+    if (0 != v4l2_decode_set_fmt(handle)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Set format failed\n");
+        goto free_fd;
+    }
+
+    if (0 != v4l2_decode_request_output_buffers(handle)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] request output buffers failed\n");
+        goto free_fd;
+    }
+
+    if (0 != v4l2_decode_map_output_buffers(handle)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] mapping output buffers failed\n");
+        goto free_fd;
+    }
+
+    handle->outbuf_head = 0;
+    handle->outbuf_tail = handle->num_outbufs - 1;
+
+    for (int i=0; i < handle->num_outbufs - 1; i++) {
+        v4l2_decode_enqueue_outbuf(handle);
+    }
+
+    if (0 != v4l2_decode_start_output(handle)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] starting output failed\n");
+        goto free_fd;
+    }
+
+    if (0 != v4l2_decode_request_capture_buffers(handle)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] request capture buffers failed\n");
+        goto free_fd;
+    }
+
+    for (int i=0; i < handle->cfg.bufq_depth; i++) {
+        handle->queued[i] = false;
+    }
+
+    out_fmt->width = ALIGN(handle->str.width, HW_ALIGN);
+    out_fmt->height = ALIGN(handle->str.height, HW_ALIGN);
+
+    return handle;
+
+free_fd:
+    close(handle->fd);
+free_handle:
+    free(handle);
+    return NULL;
+}
+
+int v4l2_decode_start(v4l2DecodeHandle *handle)
+{
+    int status = 0;
+    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+    if (-1 == xioctl(handle->fd, VIDIOC_STREAMON, &type)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] capture VIDIOC_STREAMON failed\n");
+        status = -1;
+    }
+
+    return status;
+}
+
+int v4l2_decode_enqueue_buf(v4l2DecodeHandle *handle, Buf *tiovx_buffer)
+{
+    struct v4l2_buffer buf;
+    struct v4l2_plane buf_planes[3];
+    int status = 0;
+    uint32_t pitch[4];
+    int fd[4];
+    long unsigned int size[4];
+    unsigned int offset[4];
+
+
+    if (handle->queued[tiovx_buffer->buf_index] == true) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Buffer alread enqueued\n");
+        status = -1;
+        goto ret;
+    }
+
+    getImageDmaFd(tiovx_buffer->handle, fd, pitch, size, offset, 2);
+
+    CLR(&buf);
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    buf.memory = V4L2_MEMORY_DMABUF;
+    buf.index = tiovx_buffer->buf_index;
+    buf.m.planes = buf_planes;
+    buf.length = 1;
+
+    CLR(buf_planes);
+    buf_planes[0].m.fd = fd[0];
+    buf_planes[0].length = size[0] + size[1];
+
+    if (-1 == xioctl(handle->fd, VIDIOC_QBUF, &buf)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] VIDIOC_QBUF failed\n");
+        status = -1;
+    } else {
+        handle->queued[tiovx_buffer->buf_index] = true;
+        handle->bufq[tiovx_buffer->buf_index] = tiovx_buffer;
+    }
+
+ret:
+    return status;
+}
+
+Buf *v4l2_decode_dqueue_buf(v4l2DecodeHandle *handle)
+{
+    Buf *tiovx_buffer = NULL;
+    struct v4l2_buffer buf;
+    struct v4l2_plane buf_planes[3];
+    struct pollfd pfd;
+    int ret = 0;
+
+poll:
+    CLR(&pfd);
+    pfd.fd = handle->fd;
+    pfd.events = POLLIN | POLLOUT | POLLPRI;
+    pfd.revents = 0;
+
+    ret = poll(&pfd, 1, 100);
+    if (ret < 0) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] POLL failed\n");
+        goto ret;
+    }
+
+    if (pfd.revents & POLLPRI) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] Decoding finished\n");
+        goto ret;
+    }
+
+    if (pfd.revents & POLLOUT) {
+        v4l2_decode_dqueue_outbuf(handle);
+        v4l2_decode_enqueue_outbuf(handle);
+    }
+
+    if ((pfd.revents & POLLIN) == 0) {
+        goto poll;
+    }
+
+    CLR(&buf);
+    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+    buf.memory = V4L2_MEMORY_DMABUF;
+    buf.m.planes = buf_planes;
+    buf.length = 1;
+
+    while (1) {
+        if (-1 == xioctl(handle->fd, VIDIOC_DQBUF, &buf)) {
+            if (errno == EAGAIN) {
+                continue;
+            } else {
+                TIOVX_MODULE_ERROR("[V4L2_DECODE] VIDIOC_DQBUF failed\n");
+                break;
+            }
+        } else {
+            break;
+        }
+    }
+
+    handle->queued[buf.index] = false;
+    tiovx_buffer = handle->bufq[buf.index];
+    tiovx_buffer->buf_index = buf.index;
+
+ret:
+    return tiovx_buffer;
+}
+
+int v4l2_decode_stop(v4l2DecodeHandle *handle)
+{
+    int status = 0;
+    enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+    if (-1 == xioctl(handle->fd, VIDIOC_STREAMOFF, &type)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] capture VIDIOC_STREAMOFF failed\n");
+        status = -1;
+    }
+
+    type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+    if (-1 == xioctl(handle->fd, VIDIOC_STREAMOFF, &type)) {
+        TIOVX_MODULE_ERROR("[V4L2_DECODE] output VIDIOC_STREAMOFF failed\n");
+        status = -1;
+    }
+
+    return status;
+}
+
+int v4l2_decode_delete_handle(v4l2DecodeHandle *handle)
+{
+    int status = 0;
+
+    fclose(handle->rdfd);
+    close(handle->fd);
+    free(handle);
+
+    return status;
+}
