From 8922d903503caac014a9e93d119d59379b1bcbee Mon Sep 17 00:00:00 2001
From: Gokul S <g-s@ti.com>
Date: Fri, 25 Apr 2025 18:32:23 +0530
Subject: [PATCH 2/2] working patch for display m2m node in multi_cam app

Signed-off-by: Gokul S <g-s@ti.com>
---
 apps/basic_demos/app_multi_cam/main.c | 109 +++++++++++++++++++++++++-
 1 file changed, 107 insertions(+), 2 deletions(-)

diff --git a/apps/basic_demos/app_multi_cam/main.c b/apps/basic_demos/app_multi_cam/main.c
index 4439f1f..cd8420d 100755
--- a/apps/basic_demos/app_multi_cam/main.c
+++ b/apps/basic_demos/app_multi_cam/main.c
@@ -68,6 +68,8 @@
 #include <VX/vx_khr_pipelining.h>
 #include <TI/video_io_kernels.h>
 
+#include <TI/video_io_display_m2m.h>
+
 #include "app_common.h"
 #include "app_sensor_module.h"
 #include "app_capture_module.h"
@@ -153,6 +155,11 @@ typedef struct {
 
     vx_image gDisplayInImage;
 
+    tivx_display_m2m_params_t display_m2m_params;
+    vx_node displaym2mNode;
+    vx_user_data_object display_m2m_params_obj;
+    vx_object_array display_m2m_output_arr;
+
 } AppObj;
 
 AppObj gAppObj;
@@ -174,6 +181,10 @@ static void set_img_mosaic_params(ImgMosaicObj *imgMosaicObj, vx_uint32 in_width
 #if !(defined(SOC_AM62A) && defined(QNX))
 static void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufInfo, uint32_t update_type);
 #endif
+static vx_status app_init_displayM2M(AppObj *obj, uint32_t num_cameras_enabled);
+static vx_status app_create_graph_displayM2M(AppObj *obj, vx_object_array input_arr, uint32_t num_cameras_enabled);
+static void app_deinit_dispaly_m2m(AppObj *obj);
+static void app_delete_dispaly_m2m(AppObj *obj);
 
 #if defined(SOC_AM62A) && defined(QNX)
 /*AM62A: QNX to use screen package for displaying frames on A53*/
@@ -1056,6 +1067,8 @@ static vx_status app_init(AppObj *obj)
     {
         status = app_init_viss(obj->context, &obj->vissObj, &obj->sensorObj, "viss_obj", obj->objArrSplitObj.output0_num_elements);
         APP_PRINTF("VISS init done!\n");
+        status = app_init_displayM2M(obj, obj->sensorObj.num_cameras_enabled);
+        APP_PRINTF("displaym2m init done!\n");
     }
 
     if((1 == obj->enable_aewb) && (status == VX_SUCCESS))
@@ -1140,6 +1153,8 @@ static void app_deinit(AppObj *obj)
     {
         app_deinit_viss(&obj->vissObj);
         APP_PRINTF("VISS deinit done!\n");
+        app_deinit_dispaly_m2m(obj);
+        APP_PRINTF("display m2m deinit done!\n");
     }
 
     if(1 == obj->enable_aewb)
@@ -1213,6 +1228,8 @@ static void app_delete_graph(AppObj *obj)
 
     app_delete_viss(&obj->vissObj);
     APP_PRINTF("VISS delete done!\n");
+    app_delete_dispaly_m2m(obj);
+    APP_PRINTF("displaym2m delete done!\n");
 
     app_delete_aewb(&obj->aewbObj);
     APP_PRINTF("AEWB delete done!\n");
@@ -1332,6 +1349,11 @@ static vx_status app_create_graph(AppObj *obj)
                 status = app_create_graph_viss(obj->graph, &obj->vissObj, obj->captureObj.raw_image_arr[0], TIVX_TARGET_VPAC_VISS1);
             }
             APP_PRINTF("VISS graph done!\n");
+            if( status == VX_SUCCESS)
+            {
+                status = app_create_graph_displayM2M(obj, obj->vissObj.output_arr, obj->sensorObj.num_cameras_enabled);
+            }
+            APP_PRINTF("displaym2m graph done!\n");
         }
     }
 
@@ -1351,7 +1373,8 @@ static vx_status app_create_graph(AppObj *obj)
         vx_object_array ldc_in_arr;
         if(1 == obj->enable_viss)
         {
-            ldc_in_arr = obj->vissObj.output_arr;
+            // ldc_in_arr = obj->vissObj.output_arr;
+            ldc_in_arr = obj->display_m2m_output_arr;
         }
         else
         {
@@ -1370,7 +1393,8 @@ static vx_status app_create_graph(AppObj *obj)
         vx_object_array mosaic_in_arr;
         if(1 == obj->enable_viss)
         {
-            mosaic_in_arr = obj->vissObj.output_arr;
+            // mosaic_in_arr = obj->vissObj.output_arr;
+            mosaic_in_arr = obj->display_m2m_output_arr;
         }
         else
         {
@@ -1510,6 +1534,10 @@ static vx_status app_create_graph(AppObj *obj)
             {
                 status = tivxSetNodeParameterNumBufByIndex(obj->vissObj.node, 9, APP_BUFFER_Q_DEPTH);
             }
+            if (status == VX_SUCCESS)
+            {
+                status = tivxSetNodeParameterNumBufByIndex(obj->displaym2mNode, 2, APP_BUFFER_Q_DEPTH);
+            }
         }
         if((obj->enable_aewb == 1) && (status == VX_SUCCESS))
         {
@@ -1984,3 +2012,80 @@ static void app_draw_graphics(Draw2D_Handle *handle, Draw2D_BufInfo *draw2dBufIn
   return;
 }
 #endif
+
+static vx_status app_init_displayM2M(AppObj *obj, uint32_t num_cameras_enabled)
+{
+    vx_status status  = VX_SUCCESS;
+    tivx_display_m2m_params_init(&obj->display_m2m_params);
+    obj->display_m2m_params.instId     = 0;
+    obj->display_m2m_params.numPipe    = 1;
+    obj->display_m2m_params.pipeId[0U] = 3;
+    obj->display_m2m_params.overlayId  = 3;
+    obj->display_m2m_params_obj = vxCreateUserDataObject(obj->context, "tivx_display_m2m_params_t", sizeof(tivx_display_m2m_params_t), &obj->display_m2m_params);
+    if (obj->display_m2m_params_obj == NULL)
+    {
+        printf("[ERROR] %s[%d] display_m2m_params_obj create failed\n", __FUNCTION__, __LINE__);
+    }
+
+    vx_image out_image = vxCreateImage(obj->context, obj->sensorObj.sensorParams.sensorInfo.raw_params.width,
+                                                    obj->sensorObj.sensorParams.sensorInfo.raw_params.height,
+                                                    VX_DF_IMAGE_NV12);
+    status = vxGetStatus((vx_reference)out_image);
+
+    if(status == VX_SUCCESS)
+    {
+       obj->display_m2m_output_arr = vxCreateObjectArray(obj->context, (vx_reference)out_image, num_cameras_enabled);
+       vxReleaseImage(&out_image);
+    }
+
+
+    return status;
+}
+
+static vx_status app_create_graph_displayM2M(AppObj *obj, vx_object_array input_arr, uint32_t num_cameras_enabled)
+{
+    vx_status status = VX_SUCCESS;
+    vx_image input, output;
+    vx_bool replicate[] = {vx_false_e, vx_true_e, vx_true_e};
+
+    input = (vx_image)vxGetObjectArrayItem(input_arr, 0);
+
+    output = (vx_image)vxGetObjectArrayItem(obj->display_m2m_output_arr, 0);
+
+    obj->displaym2mNode = tivxDisplayM2MNode(obj->graph, obj->display_m2m_params_obj, input, output);
+    status = vxGetStatus((vx_reference)obj->displaym2mNode);
+
+    if(status == VX_SUCCESS)
+    {
+        vxSetNodeTarget(obj->displaym2mNode, VX_TARGET_STRING, TIVX_TARGET_DISPLAY_M2M1);
+        vxSetReferenceName((vx_reference)obj->displaym2mNode, "DisplayM2MNode");
+
+        vxReplicateNode(obj->graph, obj->displaym2mNode, replicate, 3);
+    }
+    else
+    {
+        printf("Unable to create displaym2m node! \n");
+    }
+
+    vxReleaseImage(&input);
+    vxReleaseImage(&output);
+
+    return status;
+
+}
+
+static void app_deinit_dispaly_m2m(AppObj *obj)
+{
+    vxReleaseUserDataObject(&obj->display_m2m_params_obj);
+
+    vxReleaseObjectArray(&obj->display_m2m_output_arr);
+}
+
+static void app_delete_dispaly_m2m(AppObj *obj)
+{
+    if(obj->displaym2mNode != NULL)
+    {
+        vxReleaseNode(&obj->displaym2mNode);
+    }
+}
+
-- 
2.34.1

