Added graph to FVID2
authorRishabh Garg <rishabh@ti.com>
Tue, 17 Apr 2018 10:41:39 +0000 (16:11 +0530)
committerSivaraj R <sivaraj@ti.com>
Wed, 18 Apr 2018 04:50:18 +0000 (10:20 +0530)
Signed-off-by: Rishabh Garg <rishabh@ti.com>
fvid2.h
fvid2_component.mk [changed mode: 0644->0755]
include/fvid2_graph.h [new file with mode: 0755]
src/fvid2_graph.c [new file with mode: 0755]
src/makefile [changed mode: 0644->0755]

diff --git a/fvid2.h b/fvid2.h
index 2470d591811953d6eb1e391f095899032437910f..011dac8cdc21a6b88a7efbd93ebafc79717c4315 100644 (file)
--- a/fvid2.h
+++ b/fvid2.h
@@ -49,6 +49,7 @@
 #include <ti/drv/fvid2/include/fvid2_utils.h>
 #include <ti/drv/fvid2/include/fvid2_api.h>
 #include <ti/drv/fvid2/include/fvid2_drvMgr.h>
+#include <ti/drv/fvid2/include/fvid2_graph.h>
 
 #ifdef __cplusplus
 extern "C" {
old mode 100644 (file)
new mode 100755 (executable)
index 32c0d49..2184d5f
@@ -34,9 +34,9 @@
 #
 ifeq ($(fvid2_component_make_include), )
 
-fvid2_default_SOCLIST           = j7 am65x
+fvid2_default_SOCLIST           = j7 am65xx
 fvid2_default_j7_CORELIST       = mcu1_0 mcu1_1
-fvid2_default_am65x_CORELIST    = mcu1_0 mcu1_1 mpu1_0
+fvid2_default_am65xx_CORELIST    = mcu1_0 mcu1_1 mpu1_0
 
 ############################
 # fvid2 package
diff --git a/include/fvid2_graph.h b/include/fvid2_graph.h
new file mode 100755 (executable)
index 0000000..deba224
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ *  Copyright (c) Texas Instruments Incorporated 2018
+ *
+ *  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.
+ */
+
+/**
+ *  \file fvid2_graph.h
+ *
+ *  \brief FVID2 Graph interface file.
+ */
+
+#ifndef FVID2_GRAPH_H_
+#define FVID2_GRAPH_H_
+
+/* ========================================================================== */
+/*                             Include Files                                  */
+/* ========================================================================== */
+
+#include <ti/drv/fvid2/fvid2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ========================================================================== */
+/*                           Macros & Typedefs                                */
+/* ========================================================================== */
+
+#define FVID2_GRAPH_DEF_ALIGN        ((uint32_t) 16U)
+#define FVID2_GRAPH_INVALID_NODE_ID  ((uint32_t) 0U)
+#define FVID2_GRAPH_MAX_NODES        ((uint32_t) 80U)
+#define FVID2_GRAPH_MAX_NUM_PATHS    ((uint32_t) 20U)
+
+typedef enum
+{
+    FVID2_GRAPH_NM_DISABLE,
+    FVID2_GRAPH_NM_ENABLE,
+    FVID2_GRAPH_NM_CHECK
+} Fvid2_GraphNodeMode;
+
+typedef enum
+{
+    FVID2_GRAPH_NT_DUMMY,
+    FVID2_GRAPH_NT_DSS,  /* DSS */
+    FVID2_GRAPH_NT_MAX_NODETYPE
+} Fvid2_GraphNodeTypes;
+
+typedef enum
+{
+    FVID2_GRAPH_NT_IN_SINGLE,
+    FVID2_GRAPH_NT_IN_MULTI,
+    FVID2_GRAPH_NT_IN_EMPTY
+} Fvid2_GraphNodeInputType;
+
+typedef enum
+{
+    FVID2_GRAPH_NT_OUT_SINGLE,
+    FVID2_GRAPH_NT_OUT_MULTI,
+    FVID2_GRAPH_NT_OUT_EMPTY
+} Fvid2_GraphNodeOutputType;
+
+/* ========================================================================== */
+/*                         Structure Declarations                             */
+/* ========================================================================== */
+
+typedef struct Fvid2_GraphNodeInfo_t Fvid2_GraphNodeInfo;
+
+typedef struct Fvid2_GraphNodeSet_t
+{
+    uint32_t                numNodes;
+    /**< Number of input/output nodes */
+    Fvid2_GraphNodeInfo    *node[FVID2_GRAPH_MAX_NUM_PATHS];
+    /**< Pointer to the input/output node */
+    uint32_t                isEnabled[FVID2_GRAPH_MAX_NUM_PATHS];
+    /**< Flag to indicate whether input/output is enabled or not. */
+} Fvid2_GraphNodeSet;
+
+struct Fvid2_GraphNodeInfo_t
+{
+    /*Used to select config structure from the CreateParams */
+    uint32_t                    nodeNum;
+
+    /* Tree-connections */
+    Fvid2_GraphNodeInputType    inType;
+    Fvid2_GraphNodeOutputType   outType;
+
+    /* SI/SO/MI/MO */
+    uint32_t                    nodeType;
+    
+    void                       *corePtr;
+    uint32_t                    isDummy;
+    uint32_t                    inUse;
+    Fvid2_GraphNodeSet          input;
+    Fvid2_GraphNodeSet          output;
+};
+
+typedef struct
+{
+    uint32_t                    numNodes;
+    Fvid2_GraphNodeInfo        *list;
+} Fvid2_GraphNodeInfoList;
+
+/**
+ * \brief Structure containing edge information. Edge is a connection
+ *  between two nodes i.e. two modules. Video Hardware can be represented
+ *  by a graph, where each module is node and edge is present between two
+ *  nodes if they are connected.
+ */
+typedef struct
+{
+    uint32_t startNode;
+    /**< Starting node of the edge */
+    uint32_t endNode;
+    /**< End node of the edge */
+} Fvid2_GraphEdgeInfo;
+
+typedef struct
+{
+    uint32_t                numEdges;
+    /**< Number of the edge */
+    Fvid2_GraphEdgeInfo    *list;
+    /**< Edge list */
+} Fvid2_GraphEdgeInfoList;
+
+typedef struct
+{
+    Fvid2_GraphNodeInfoList    *nodeList;
+    Fvid2_GraphEdgeInfoList    *edgeList;
+} Fvid2_GraphInfo;
+
+/* ========================================================================== */
+/*                          Function Declarations                             */
+/* ========================================================================== */
+
+Fvid2_GraphInfo *Fvid2_graphInit(const Fvid2_GraphNodeInfoList *inNodeList,
+                                 const Fvid2_GraphEdgeInfoList *inEdgeList,
+                                 Fvid2_GraphInfo *graphHandle);
+
+int32_t Fvid2_graphDeInit(Fvid2_GraphInfo *graphHandle);
+
+Fvid2_GraphNodeInfo *Fvid2_graphGetNodeInfo(
+                            const Fvid2_GraphNodeInfoList *nodeList,
+                            uint32_t cnt);
+
+int32_t Fvid2_graphAllocNodes(const Fvid2_GraphNodeInfoList *nodeList,
+                              const Fvid2_GraphEdgeInfoList *edgeList,
+                              Fvid2_GraphNodeMode mode);
+
+int32_t Fvid2_graphGetPath(const Fvid2_GraphNodeInfoList *inNodeList,
+                           const Fvid2_GraphEdgeInfoList *inEdgeList,
+                           Fvid2_GraphNodeInfoList *outNodeList,
+                           Fvid2_GraphEdgeInfoList *outEdgeList,
+                           uint32_t maxOutNodeCnt,
+                           uint32_t maxOutEdgeCnt);
+
+int32_t Fvid2_graphFreePath(Fvid2_GraphNodeInfoList *nodeList,
+                      Fvid2_GraphEdgeInfoList *edgeList);
+
+int32_t Fvid2_graphStackIsLastNode(const Fvid2_GraphNodeInfo *currNode,
+                                   uint32_t isForward);
+
+void Fvid2_graphStackInitTraverser(Fvid2_GraphNodeInfo *node);
+
+Fvid2_GraphNodeInfo *Fvid2_graphGetNextNodeToTraverse(uint32_t isForward);
+
+uint32_t Fvid2_graphIsNodeInputAvailable(
+                            const Fvid2_GraphNodeInfoList *nodeList,
+                            uint32_t nodeNum);
+
+uint32_t Fvid2_graphIsNodeOutputAvailable(
+                            const Fvid2_GraphNodeInfoList *nodeList,
+                            uint32_t nodeNum);
+
+void Fvid2_graphInitTraverser(Fvid2_GraphNodeInfo *node);
+
+Fvid2_GraphNodeInfo *Fvid2_graphGetNextChildNode(
+                            const Fvid2_GraphNodeInfo *currNode,
+                            uint32_t isForward);
+
+Fvid2_GraphNodeInfo *Fvid2_graphStackPeak(uint32_t *stNum);
+
+int32_t Fvid2_graphGetEnabledIndex(const uint32_t *array, uint32_t size);
+
+void Fvid2_graphAddEdge(Fvid2_GraphEdgeInfo *edge,
+                        uint32_t startNode,
+                        uint32_t endNode);
+
+#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
+}
+#endif
+
+#endif /* FVID2_GRAPH_H_ */
diff --git a/src/fvid2_graph.c b/src/fvid2_graph.c
new file mode 100755 (executable)
index 0000000..581dc0c
--- /dev/null
@@ -0,0 +1,686 @@
+/*
+ *  Copyright (c) Texas Instruments Incorporated 2018
+ *
+ *  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.
+ */
+
+/**
+ *  \file fvid2_graph.c
+ *
+ *  \brief File containing the graph functions for resource management.
+ *
+ */
+
+/* ========================================================================== */
+/*                             Include Files                                  */
+/* ========================================================================== */
+
+#include <stdint.h>
+#include <ti/drv/fvid2/fvid2.h>
+
+/* ========================================================================== */
+/*                           Macros & Typedefs                                */
+/* ========================================================================== */
+
+/* None */
+
+/* ========================================================================== */
+/*                         Structure Declarations                             */
+/* ========================================================================== */
+
+typedef struct Fvid2_GraphStack_t
+{
+    Fvid2_GraphNodeInfo *node[FVID2_GRAPH_MAX_NODES];
+    /**< Array of node pointers */
+    int32_t stNum[FVID2_GRAPH_MAX_NODES];
+    /**< Keeps track of which child of this node is next to be visited, on
+     *   the stack for a node. */
+    uint8_t isVisited[FVID2_GRAPH_MAX_NODES];
+    /**< Flag keeps track of whether given node is visited or not */
+    int32_t top;
+    /**< Top marker of the stack */
+} Fvid2_GraphStack;
+
+/* ========================================================================== */
+/*                         Internal Function Declarations                     */
+/* ========================================================================== */
+
+static int32_t Fvid2_graphConnect(const Fvid2_GraphNodeInfoList *inNodeList,
+                                  const Fvid2_GraphEdgeInfoList *inEdgeList);
+static void Fvid2_graphStackReset(void);
+static void Fvid2_graphStackPush(Fvid2_GraphNodeInfo *node);
+static void Fvid2_graphStackPop(void);
+static uint32_t Fvid2_graphStackIsVisited(const Fvid2_GraphNodeInfo *node);
+int32_t Fvid2_graphStackIsLastNode(const Fvid2_GraphNodeInfo *currNode,
+                                   uint32_t isForward);
+
+/* ========================================================================== */
+/*                            Global Variables                                */
+/* ========================================================================== */
+
+static Fvid2_GraphStack gFvid2GraphNodeStack;
+
+/* ========================================================================== */
+/*                          Function Definitions                              */
+/* ========================================================================== */
+
+/* Helper function */
+static int32_t Fvid2_graphConnect(const Fvid2_GraphNodeInfoList *inNodeList,
+                                  const Fvid2_GraphEdgeInfoList *inEdgeList)
+{
+    Fvid2_GraphNodeInfo *nodes = inNodeList->list;
+    Fvid2_GraphEdgeInfo *edges = inEdgeList->list;
+    uint32_t cnt, startNode, endNode, index1, index2;
+    for (cnt = 0; cnt < inNodeList->numNodes; cnt++)
+    {
+        Fvid2Utils_memset(&nodes[cnt].input, 0, sizeof (Fvid2_GraphNodeSet));
+        Fvid2Utils_memset(&nodes[cnt].output, 0, sizeof (Fvid2_GraphNodeSet));
+    }
+
+    for (cnt = 0U; cnt < inEdgeList->numEdges; cnt++)
+    {
+        startNode = edges[cnt].startNode;
+        endNode   = edges[cnt].endNode;
+        /* End Node is output node for the start Node so update
+         * information in start node*/
+        index1 = nodes[startNode].output.numNodes;
+        nodes[startNode].output.node[index1] = &nodes[endNode];
+        nodes[startNode].output.numNodes++;
+        GT_assert(Fvid2Trace, (index1 < FVID2_GRAPH_MAX_NUM_PATHS));
+
+        /* Start Node is input node for the end Node so update
+         * information in end node*/
+        index2 = nodes[endNode].input.numNodes;
+        nodes[endNode].input.node[index2] = &nodes[startNode];
+        nodes[endNode].input.numNodes++;
+        GT_assert(Fvid2Trace, (index2 < FVID2_GRAPH_MAX_NUM_PATHS));
+
+        /* Dummy node's input is always enabled */
+        if ((TRUE == nodes[endNode].isDummy) &&
+            (TRUE == nodes[startNode].isDummy))
+        {
+            nodes[startNode].output.isEnabled[index1] = TRUE;
+            nodes[endNode].input.isEnabled[index2]    = TRUE;
+        }
+    }
+
+    return FVID2_SOK;
+}
+
+/** \brief Creates static DSS topology for the fixed edges/nodes. There
+ *  are some dummy nodes in the DSS topology. Input and output of these
+ *  nodes are always enabled and cannot be changed. This function creates
+ *  this static table.
+ *  Called at the init time only
+ */
+Fvid2_GraphInfo *Fvid2_graphInit(const Fvid2_GraphNodeInfoList *inNodeList,
+                                 const Fvid2_GraphEdgeInfoList *inEdgeList,
+                                 Fvid2_GraphInfo *graphHandle)
+{
+    GT_assert(Fvid2Trace, (graphHandle != NULL));
+    GT_assert(Fvid2Trace, (graphHandle->nodeList != NULL));
+    GT_assert(Fvid2Trace, (graphHandle->edgeList != NULL));
+
+    GT_assert(Fvid2Trace, (inNodeList != NULL));
+    GT_assert(Fvid2Trace, (inEdgeList != NULL));
+
+    graphHandle->nodeList->numNodes = inNodeList->numNodes;
+    graphHandle->edgeList->numEdges = inEdgeList->numEdges;
+    graphHandle->nodeList->list     = inNodeList->list;
+    graphHandle->edgeList->list     = inEdgeList->list;
+
+    Fvid2_graphConnect(inNodeList, inEdgeList);
+    return graphHandle;
+}
+
+int32_t Fvid2_graphDeInit(Fvid2_GraphInfo *graphHandle)
+{
+    return FVID2_SOK;
+}
+
+/** \brief Function to get the pointer to node for the given index
+ */
+Fvid2_GraphNodeInfo *Fvid2_graphGetNodeInfo(
+                            const Fvid2_GraphNodeInfoList *nodeList,
+                            uint32_t cnt)
+{
+    Fvid2_GraphNodeInfo *node = NULL;
+    if (cnt < nodeList->numNodes)
+    {
+        node = &nodeList->list[cnt];
+    }
+    return (node);
+}
+
+/** \brief This function allocates nodes within the CORE by enabling
+ *  specified edges.
+ *
+ *  To enable an edge, it enables output of source node and
+ *  enables input of the target node.
+ *
+ *  Returns error if a node is already active.
+ *
+ *  TODO: First edge is assumed as input, Why/How to disable edges?,
+ *  Multiple handle support.
+ *  TODO: If FAIL, run through again and disable if anything was enabled.
+ */
+
+uint32_t Fvid2_graphIsNodeInputAvailable(
+                            const Fvid2_GraphNodeInfoList *nodeList,
+                            uint32_t nodeNum)
+{
+    uint32_t j;
+    uint32_t retVal  = TRUE;
+    Fvid2_GraphNodeInfo *curNode = Fvid2_graphGetNodeInfo(nodeList, nodeNum);
+    if (NULL == curNode)
+    {
+        retVal = FALSE;
+    }
+    else
+    {
+        for (j = 0; j < curNode->input.numNodes; j++)
+        {
+            if (FVID2_GRAPH_NM_ENABLE == curNode->input.isEnabled[j])
+            {
+                retVal = FALSE;
+                break;
+            }
+        }
+    }
+    return retVal;
+}
+
+uint32_t Fvid2_graphIsNodeOutputAvailable(
+                            const Fvid2_GraphNodeInfoList *nodeList,
+                            uint32_t nodeNum)
+{
+    uint32_t j;
+    uint32_t retVal  = TRUE;
+    Fvid2_GraphNodeInfo *curNode = Fvid2_graphGetNodeInfo(nodeList, nodeNum);
+    if (NULL == curNode)
+    {
+        retVal = FALSE;
+    }
+    else
+    {
+        for (j = 0; j < curNode->output.numNodes; j++)
+        {
+            if (FVID2_GRAPH_NM_ENABLE == curNode->output.isEnabled[j])
+            {
+                retVal = FALSE;
+                break;
+            }
+        }
+    }
+    return retVal;
+}
+
+int32_t Fvid2_graphAllocNodes(const Fvid2_GraphNodeInfoList *nodeList,
+                              const Fvid2_GraphEdgeInfoList *edgeList,
+                              Fvid2_GraphNodeMode mode)
+{
+    uint32_t i, j;
+    int32_t retVal = FVID2_SOK;
+    Fvid2_GraphEdgeInfo *inputEdgeList = edgeList->list;
+    for (i = 0; i < edgeList->numEdges; i++)
+    {
+        Fvid2_GraphNodeInfo *startNode = Fvid2_graphGetNodeInfo(
+            nodeList, inputEdgeList[i].startNode);
+        GT_assert(Fvid2Trace, (startNode != NULL));
+        Fvid2_GraphNodeInfo *endNode = Fvid2_graphGetNodeInfo(
+            nodeList, inputEdgeList[i].endNode);
+        GT_assert(Fvid2Trace, (endNode != NULL));
+        if ((startNode->nodeNum == FVID2_GRAPH_INVALID_NODE_ID) &&
+            (endNode->nodeNum == FVID2_GRAPH_INVALID_NODE_ID))
+        {
+            break;
+        }
+
+        /* TODO: Multiple connections from different path probably does not work
+        **/
+        /*      here. Will it be ever required? */
+        /* Example: One handle connects one source for blender, Second handle */
+        /*         connects second source for blender - Is such a case required?
+        **/
+        if (FVID2_GRAPH_NT_OUT_SINGLE == startNode->outType)
+        {
+            uint32_t inUse = FALSE;
+            for (j = 0; j < startNode->output.numNodes; j++)
+            {
+                if (FVID2_GRAPH_NM_ENABLE == startNode->output.isEnabled[j])
+                {
+                    inUse = TRUE;
+                    break;
+                }
+            }
+            if ((FALSE == inUse) || (FVID2_GRAPH_NM_DISABLE == mode))
+            {
+                for (j = 0; j < startNode->output.numNodes; j++)
+                {
+                    if (startNode->output.node[j] == endNode)
+                    {
+                        startNode->output.isEnabled[j] = mode;
+                        break;
+                    }
+                }
+                if (j == startNode->output.numNodes)
+                {
+                    retVal = FVID2_EFAIL;
+                }
+            }
+        }
+        else if (FVID2_GRAPH_NT_OUT_MULTI == startNode->outType)
+        {
+            for (j = 0; j < startNode->output.numNodes; j++)
+            {
+                if (startNode->output.node[j] == endNode)
+                {
+                    startNode->output.isEnabled[j] = mode;
+                    break;
+                }
+            }
+            if (j == startNode->output.numNodes)
+            {
+                retVal = FVID2_EFAIL;
+            }
+        }
+        else
+        {
+            /*Do nothing */
+        }
+
+        if (FVID2_GRAPH_NT_IN_SINGLE == endNode->inType)
+        {
+            uint32_t inUse = FALSE;
+            for (j = 0; j < endNode->input.numNodes; j++)
+            {
+                if (FVID2_GRAPH_NM_ENABLE == endNode->input.isEnabled[j])
+                {
+                    inUse = TRUE;
+                    break;
+                }
+            }
+            if ((FALSE == inUse) || (FVID2_GRAPH_NM_DISABLE == mode))
+            {
+                for (j = 0; j < endNode->input.numNodes; j++)
+                {
+                    if (endNode->input.node[j] == startNode)
+                    {
+                        endNode->input.isEnabled[j] = mode;
+                        break;
+                    }
+                }
+                if (j == endNode->input.numNodes)
+                {
+                    retVal = FVID2_EFAIL;
+                }
+            }
+        }
+        else if (FVID2_GRAPH_NT_IN_MULTI == endNode->inType)
+        {
+            for (j = 0; j < endNode->input.numNodes; j++)
+            {
+                if (endNode->input.node[j] == startNode)
+                {
+                    endNode->input.isEnabled[j] = mode;
+                    break;
+                }
+            }
+            if (j == endNode->input.numNodes)
+            {
+                retVal = FVID2_EFAIL;
+            }
+        }
+        else
+        {
+            /*Do nothing */
+        }
+    }
+
+    return retVal;
+}
+
+/**
+ * findPath()
+ */
+/**
+ * Inputs
+ * PORTA/B_08/16/24
+ * isCSCEnabled
+ * isSCEnabled
+ */
+/**
+ * Algo:
+ * Decide FirstNode
+ * Decide LastNodes
+ * curNode = FirstNode
+ * if(isCSCEnabled) {join curNode to CSC; curNode = CSC}
+ * if(isSCEnabled)  {join curNode to SC; curNode = SC}
+ * foreach(LastNode_option1, LastNode_option2)
+ * {
+ * join curNode to LastNode
+ * if (successful) break
+ * else next
+ * }
+ */
+
+/** \brief This function gets a list of valid nodes in an edge list and
+ *  also enable the input in each entry. Fill in VpsCore_VipPathObj
+ *
+ *  Should be called only after Fvid2_graphAllocNodes() is successful
+ *
+ *  TODO: Connections should be made in this function and not copied from
+ *  main graph (as is done currently) since this will fail for multiple handle
+ *  scenarios.
+ */
+int32_t Fvid2_graphGetPath(const Fvid2_GraphNodeInfoList *inNodeList,
+                           const Fvid2_GraphEdgeInfoList *inEdgeList,
+                           Fvid2_GraphNodeInfoList *outNodeList,
+                           Fvid2_GraphEdgeInfoList *outEdgeList,
+                           uint32_t maxOutNodeCnt,
+                           uint32_t maxOutEdgeCnt)
+{
+    uint32_t i, j;
+    uint32_t pathEdgeCount = inEdgeList->numEdges;
+    uint32_t pathNodeCount = 0;
+    uint32_t numInNodes = inNodeList->numNodes;
+    uint32_t nodes[FVID2_GRAPH_MAX_NODES] = {0};
+
+    for (i = 0; i < inEdgeList->numEdges; i++)
+    {
+        j = inEdgeList->list[i].startNode;
+        nodes[j] = 1U;
+        j = inEdgeList->list[i].endNode;
+        nodes[j] = 1U;
+    }
+
+    for (i = 0; i < numInNodes; i++)
+    {
+        if (nodes[i] == 1U)
+        {
+            pathNodeCount++;
+        }
+    }
+
+    GT_assert(Fvid2Trace, (pathNodeCount < maxOutNodeCnt));
+    outNodeList->numNodes = pathNodeCount;
+
+    GT_assert(Fvid2Trace, (outNodeList->list != NULL));
+
+    GT_assert(Fvid2Trace, (pathEdgeCount < maxOutEdgeCnt));
+    outEdgeList->numEdges = pathEdgeCount;
+    GT_assert(Fvid2Trace, (outEdgeList->list != NULL));
+
+    for (i = 0; i < pathEdgeCount; i++)
+    {
+        outEdgeList->list[i].startNode =
+            inEdgeList->list[i].startNode;
+        outEdgeList->list[i].endNode =
+            inEdgeList->list[i].endNode;
+    }
+
+    j = 0;
+    for (i = 0; i < numInNodes; i++)
+    {
+        if (nodes[i] == 1U)
+        {
+            Fvid2Utils_memcpy((void *) &outNodeList->list[j],
+                            (void *) &inNodeList->list[i],
+                            sizeof (Fvid2_GraphNodeInfo));
+
+            /* Reset connection info from the original graph */
+            Fvid2Utils_memset((void *) (outNodeList->list[j].input.node), 0,
+                              sizeof (Fvid2_GraphNodeInfo *) * FVID2_GRAPH_MAX_NUM_PATHS);
+            Fvid2Utils_memset((void *) (outNodeList->list[j].output.node), 0,
+                              sizeof (Fvid2_GraphNodeInfo *) * FVID2_GRAPH_MAX_NUM_PATHS);
+            j++;
+        }
+    }
+
+    return FVID2_SOK;
+}
+
+int32_t Fvid2_graphFreePath(Fvid2_GraphNodeInfoList *nodeList,
+                      Fvid2_GraphEdgeInfoList *edgeList)
+{
+    if (NULL != nodeList->list)
+    {
+        nodeList->numNodes = 0;
+        nodeList->list     = NULL;
+    }
+    if (NULL != edgeList->list)
+    {
+        edgeList->numEdges = 0;
+        edgeList->list     = NULL;
+    }
+    return FVID2_SOK;
+}
+
+void Fvid2_graphInitTraverser(Fvid2_GraphNodeInfo *node)
+{
+    /* Initialize Stack */
+    Fvid2_graphStackReset();
+
+    /* Push root node onto stack */
+    Fvid2_graphStackPush(node);
+}
+
+static void Fvid2_graphStackReset(void)
+{
+    Fvid2Utils_memset(&gFvid2GraphNodeStack, 0, sizeof (gFvid2GraphNodeStack));
+    gFvid2GraphNodeStack.top = (-(int32_t)1);
+
+    /* Initialize All stack numbers with -1 */
+    Fvid2Utils_memset(gFvid2GraphNodeStack.stNum, 0, sizeof (uint32_t) * FVID2_GRAPH_MAX_NODES);
+    Fvid2Utils_memset(gFvid2GraphNodeStack.isVisited, 0, sizeof (FVID2_GRAPH_MAX_NODES));
+}
+
+/* Push a node on the stack */
+static void Fvid2_graphStackPush(Fvid2_GraphNodeInfo *node)
+{
+    gFvid2GraphNodeStack.top++;
+    gFvid2GraphNodeStack.node[gFvid2GraphNodeStack.top] = node;
+}
+
+/* Remove top node from the stack */
+static void Fvid2_graphStackPop(void)
+{
+    /* Remove the node from the stack */
+    gFvid2GraphNodeStack.stNum[gFvid2GraphNodeStack.top] = 0;
+    gFvid2GraphNodeStack.node[gFvid2GraphNodeStack.top]  = NULL;
+    gFvid2GraphNodeStack.top--;
+}
+
+static uint32_t Fvid2_graphStackIsVisited(const Fvid2_GraphNodeInfo *node)
+{
+    uint32_t visited = TRUE;
+
+    if (0 == gFvid2GraphNodeStack.isVisited[node->nodeNum])
+    {
+        visited = FALSE;
+    }
+
+    return (visited);
+}
+
+int32_t Fvid2_graphStackIsLastNode(const Fvid2_GraphNodeInfo *currNode,
+                                   uint32_t isForward)
+{
+    int32_t ret = (int32_t) TRUE;
+
+    if (((TRUE == isForward) && (0 != currNode->output.numNodes)) ||
+        ((FALSE == isForward) && (0 != currNode->input.numNodes)))
+    {
+        ret = (int32_t) FALSE;
+    }
+
+    return (ret);
+}
+
+/* Function to get the next enabled node for the currNode */
+Fvid2_GraphNodeInfo *Fvid2_graphGetNextChildNode(
+                            const Fvid2_GraphNodeInfo *currNode,
+                            uint32_t isForward)
+{
+    Fvid2_GraphNodeInfo *node = NULL;
+    uint32_t isEnabled = TRUE;
+    uint32_t nodeNum, nextNodeNum;
+    uint32_t loopEnd = 1U;
+
+    nodeNum = gFvid2GraphNodeStack.top;
+    nextNodeNum = (uint32_t) gFvid2GraphNodeStack.stNum[nodeNum];
+    do
+    {
+        /* Traversing from input Node to Venc Nodes */
+        if (TRUE == isForward)
+        {
+            /* Get the next node from the output nodes */
+            if (nextNodeNum < currNode->output.numNodes)
+            {
+                node = currNode->output.node[nextNodeNum];
+                isEnabled = currNode->output.isEnabled[nextNodeNum];
+            }
+            else
+            {
+                loopEnd = 0;
+            }
+        }
+        else  /* Traversing from Venc Nodes to input node */
+        {
+            /* Get the next node from the input nodes */
+            if (nextNodeNum < currNode->input.numNodes)
+            {
+                node = currNode->input.node[(nextNodeNum)];
+                isEnabled = currNode->input.isEnabled[nextNodeNum];
+            }
+            else
+            {
+                loopEnd = 0;
+            }
+        }
+        if (0U == loopEnd)
+        {
+            break;
+        }
+        nextNodeNum += 1U;
+    } while (FALSE == isEnabled);
+
+    if (FALSE == isEnabled)
+    {
+        node = NULL;
+    }
+    else
+    {
+        gFvid2GraphNodeStack.stNum[nodeNum] = (int32_t) nextNodeNum;
+    }
+    return (node);
+}
+
+/* Get the top node on the stack */
+Fvid2_GraphNodeInfo *Fvid2_graphStackPeak(uint32_t *stNum)
+{
+    *stNum = (uint32_t) gFvid2GraphNodeStack.stNum[gFvid2GraphNodeStack.top];
+    return (gFvid2GraphNodeStack.node[gFvid2GraphNodeStack.top]);
+}
+
+Fvid2_GraphNodeInfo *Fvid2_graphGetNextNodeToTraverse(uint32_t isForward)
+{
+    uint32_t nodeNum;
+    Fvid2_GraphNodeInfo *currNode = NULL, *nextNode = NULL;
+
+    while (gFvid2GraphNodeStack.top > (-(int32_t)1))
+    {
+        /* Get the stack top node */
+        currNode = Fvid2_graphStackPeak(&nodeNum);
+
+        if (FALSE == Fvid2_graphStackIsVisited(currNode))
+        {
+            /* If current node is ot visited, return it to the caller. */
+            break;
+        }
+        else
+        {
+            /* Get the Next Node */
+            nextNode = Fvid2_graphGetNextChildNode(currNode, isForward);
+
+            /* If next node is not null, push it onto stack so that it can
+             * be traversed */
+            if (NULL != nextNode)
+            {
+                /* Push the start node onto stack */
+                Fvid2_graphStackPush(nextNode);
+            }
+            else
+            {
+                /* Remove the node from the stack */
+                Fvid2_graphStackPop();
+            }
+        }
+    }
+    if ((-(int32_t)1) == gFvid2GraphNodeStack.top)
+    {
+        currNode = NULL;
+    }
+
+    if (NULL != currNode)
+    {
+        nodeNum = currNode->nodeNum;
+        gFvid2GraphNodeStack.isVisited[nodeNum] = (uint8_t) 1;
+    }
+
+    return (currNode);
+}
+
+int32_t Fvid2_graphGetEnabledIndex(const uint32_t *array, uint32_t size)
+{
+    uint32_t i;
+    int32_t  retVal = FVID2_EFAIL;
+
+    for (i = 0; i < size; i++)
+    {
+        if ((uint32_t) 0 != array[i])
+        {
+            retVal = (int32_t) i;
+            break;
+        }
+    }
+    return retVal;
+}
+
+void Fvid2_graphAddEdge(Fvid2_GraphEdgeInfo *edge,
+                        uint32_t startNode,
+                        uint32_t endNode)
+{
+    if (startNode != endNode)
+    {
+        edge->startNode = startNode;
+        edge->endNode = endNode;
+    }
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index 3d0e8f8..f35b2d0
@@ -15,7 +15,7 @@ INCLUDE_EXTERNAL_INTERFACES = pdk
 # Common source files and CFLAGS across all platforms and cores
 PACKAGE_SRCS_COMMON = .
 
-SRCS_COMMON += fvid2_drvMgr.c fvid2_utils.c
+SRCS_COMMON += fvid2_drvMgr.c fvid2_utils.c fvid2_graph.c
 
 CFLAGS_LOCAL_COMMON = $(PDK_CFLAGS)
 PACKAGE_SRCS_COMMON = fvid2.h fvid2_component.mk include src