This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: TIOVX应用中需要多个颜色空间变换的Node,如何设计

Part Number: TDA4VM

SOC: TDA4VM

Linux SDK: ti-processor-sdk-linux-j7-evm-08_05_00_08

RTOS SDK: ti-processor-sdk-rtos-j721e-evm-08_05_00_11

Graph:

我的疑问:

node_1 和 node_3都用于颜色格式变换,那创建DSS M2M node的时候如何设置下面的参数已区别这两个node?

typedef struct {
    /*! Write-back pipeline to use. IDs=> 0: Write-back pipe-line1 */
    uint32_t instId;
    /*! Number of pipe-lines to be used,
        should be set to '1' as blending is not supported currently */
    uint32_t numPipe;
    /*! IDs of pipe-lines to be used,
        IDs=> 0:VID1, 1:VIDL1, 2:VID2 */
    uint32_t pipeId[TIVX_DISPLAY_M2M_MAX_PIPE];
    /*! Overlay to be used. IDs=> 0:Overlay1 1:Overlay2 2:Overlay3 3:Overlay4 */
    uint32_t overlayId;
} tivx_display_m2m_params_t;

  • test_display_m2m.c例程中 上面结构体内参数在4个线程中是一样的,不同是线程处理函数内 vxSetNodeTarget(m2m_node, VX_TARGET_STRING, &testParams->nodeName[0U]),每个testParams->nodeName 是不同的。

    那么是否我也可以做类似的处理,两个node 只是vxSetNodeTarget 指定不同的 nodeName 即可。

    for (taskIdx = 0U ; taskIdx < DSS_M2M_NUM_CH ; taskIdx++)
            {
                createTask         = 0U;
                testParams         = &gTestParams[taskIdx];
                testParams->taskId = taskIdx;
                ASSERT_EQ_VX_STATUS(VX_SUCCESS, tivxEventCreate(&testParams->eventHandle_TaskFinished));
                testParams->instId     = DSS_M2M_WB_PIPE_INST_ID;
                testParams->numPipe    = DSS_M2M_PIPE_NUM;
                /* Note: Directly assigning as only one pipe is supported currently */
                testParams->pipeId[0U] = DSS_M2M_PIPE_INST_ID;
                testParams->overlayId  = DSS_M2M_OVERLAY_ID;
                testParams->inFmt      = DSS_M2M_CH0_IN_FRAME_FORMAT;
                testParams->iterationCnt = (gLoop_cnt / (taskIdx + 1U));
                switch (taskIdx)
                {
                    case 0U:
                        /* Initialize test parameters for task 0 */
                        createTask               = 1U;
                        testParams->inWidth      = DSS_M2M_CH0_IN_FRAME_WIDTH;
                        testParams->inHeight     = DSS_M2M_CH0_IN_FRAME_HEIGHT;
                        testParams->inBpp        = DSS_M2M_CH0_IN_FRAME_BPP;
                        testParams->inPitch      = DSS_M2M_CH0_IN_FRAME_PITCH;
                        testParams->outFmt       = DSS_M2M_CH0_OUT_FRAME_FORMAT;
                        testParams->outWidth     = DSS_M2M_CH0_OUT_FRAME_WIDTH;
                        testParams->outHeight    = DSS_M2M_CH0_OUT_FRAME_HEIGHT;
                        strcpy(&testParams->nodeName[0U], TIVX_TARGET_DISPLAY_M2M1);
                    break;
                    case 1U:
                        createTask               = 1U;
                        /* Initialize test parameters for task 1 */
                        testParams->inFmt        = DSS_M2M_CH1_IN_FRAME_FORMAT;
                        testParams->inWidth      = DSS_M2M_CH1_IN_FRAME_WIDTH;
                        testParams->inHeight     = DSS_M2M_CH1_IN_FRAME_HEIGHT;
                        testParams->inBpp        = DSS_M2M_CH1_IN_FRAME_BPP;
                        testParams->inPitch      = DSS_M2M_CH1_IN_FRAME_PITCH;
                        testParams->outFmt       = DSS_M2M_CH1_OUT_FRAME_FORMAT;
                        testParams->outWidth     = DSS_M2M_CH1_OUT_FRAME_WIDTH;
                        testParams->outHeight    = DSS_M2M_CH1_OUT_FRAME_HEIGHT;
                        strcpy(&testParams->nodeName[0U], TIVX_TARGET_DISPLAY_M2M2);
                    break;
                    case 2U:
                        createTask               = 1U;
                        /* Initialize test parameters for task 1 */
                        testParams->inFmt        = DSS_M2M_CH2_IN_FRAME_FORMAT;
                        testParams->inWidth      = DSS_M2M_CH2_IN_FRAME_WIDTH;
                        testParams->inHeight     = DSS_M2M_CH2_IN_FRAME_HEIGHT;
                        testParams->inBpp        = DSS_M2M_CH2_IN_FRAME_BPP;
                        testParams->inPitch      = DSS_M2M_CH2_IN_FRAME_PITCH;
                        testParams->outFmt       = DSS_M2M_CH2_OUT_FRAME_FORMAT;
                        testParams->outWidth     = DSS_M2M_CH2_OUT_FRAME_WIDTH;
                        testParams->outHeight    = DSS_M2M_CH2_OUT_FRAME_HEIGHT;
                        strcpy(&testParams->nodeName[0U], TIVX_TARGET_DISPLAY_M2M3);
                    break;
                    case 3U:
                        createTask               = 1U;
                        /* Initialize test parameters for task 1 */
                        testParams->inFmt        = DSS_M2M_CH3_IN_FRAME_FORMAT;
                        testParams->inWidth      = DSS_M2M_CH3_IN_FRAME_WIDTH;
                        testParams->inHeight     = DSS_M2M_CH3_IN_FRAME_HEIGHT;
                        testParams->inBpp        = DSS_M2M_CH3_IN_FRAME_BPP;
                        testParams->inPitch      = DSS_M2M_CH3_IN_FRAME_PITCH;
                        testParams->outFmt       = DSS_M2M_CH3_OUT_FRAME_FORMAT;
                        testParams->outWidth     = DSS_M2M_CH3_OUT_FRAME_WIDTH;
                        testParams->outHeight    = DSS_M2M_CH3_OUT_FRAME_HEIGHT;
                        strcpy(&testParams->nodeName[0U], TIVX_TARGET_DISPLAY_M2M4);
                    break;
                    default:
                    break;
                }
                if (createTask == 1U)
                {
                    /* Setting up task params for m2m_task */
                    tivxTaskSetDefaultCreateParams(&testParams->taskParams_m2m);
                    testParams->taskParams_m2m.task_main     = &tivxTask_m2m;
                    testParams->taskParams_m2m.app_var       = testParams;
                    testParams->taskParams_m2m.stack_ptr     = NULL;
                    testParams->taskParams_m2m.stack_size    = TIVX_TARGET_DEFAULT_STACK_SIZE;
                    testParams->taskParams_m2m.core_affinity = TIVX_TASK_AFFINITY_ANY;
                    testParams->taskParams_m2m.priority      = TIVX_TARGET_DEFAULT_TASK_PRIORITY1;
    
                    printf("Creating Task %d...\n", testParams->taskId);
                    /* Create Tasks */
                    ASSERT_EQ_VX_STATUS(VX_SUCCESS,
                                        tivxTaskCreate(&testParams->taskHandle_m2m,
                                        &testParams->taskParams_m2m));
                }
            }

  • 您好,

    对于创建DSS M2M node时区分node_1和node_3的颜色格式变换,需要设置tivx_display_m2m_params_t结构体中的参数。具体来说:

    1. 对于node_1,可以设置以下参数:
    - instId:设置为相应的写回流水线ID,例如0代表写回流水线1
    - numPipe:设置为1,因为当前不支持混合(blending)
    - pipeId:设置用于颜色格式变换的管道ID,例如0代表VID1管道
    - overlayId:设置用于显示的叠加层ID,例如0代表Overlay1

    2. 对于node_3,可以设置以下参数
    - instId:同样设置为相应的写回流水线ID,例如0代表写回流水线1。
    - numPipe:设置为1。
    - pipeId:设置用于颜色格式变换的管道ID,例如2代表VID2管道。
    - overlayId:设置用于显示的叠加层ID,例如0代表Overlay1。

  • 您好,

    那么是否我也可以做类似的处理

    是的,您可以使用类似的方法来处理两个节点。

    对于每个节点,您可以在结构体中设置不同的nodeName,然后在线程处理函数中使用不同的nodeName来设置节点的目标。

    在您的代码中,对于每个任务,您可以根据taskIdx设置不同的nodeName。例如,对于taskIdx为0的任务,您可以使用以下代码设置nodeName:

    strcpy(&testParams->nodeName[0U], TIVX_TARGET_DISPLAY_M2M1);

    对于taskIdx为1的任务,您可以使用以下代码设置不同的nodeName:

    strcpy(&testParams->nodeName[0U], TIVX_TARGET_DISPLAY_M2M2);

    通过这种方式,您可以为每个节点设置不同的目标,并在处理函数内部使用不同的nodeName。这将使每个节点在执行时使用不同的目标,并具有不同的行为。

  • 您好!

    在 ti-processor-sdk-rtos-j721e-evm-08_05_00_11\vision_apps\platform\j721e\rtos\common\app_init.c 中我注意到

    static void appRegisterOpenVXTargetKernels()
    {       ......
            #if defined(ENABLE_DSS_SINGLE) || defined(ENABLE_DSS_DUAL)
            tivxRegisterHwaTargetDisplayKernels();
            tivxRegisterHwaTargetDisplayM2MKernels();
            #endif
            ......
    }

    因为我们这边需要 A72 core 在 Linux 下运行 Weston,所以我把 DSS module的控制权转移到了 A72 core那边。此时 ENABLE_DSS_SINGLE 和 ENABLE_DSS_DUAL 都是 undef的,这样看来 DisplayM2MKernels 没有注册,相应的颜色变换肯定是不能工作的。

    我们原本设计是想 node_2 在 A72 core上用openGL 做处理,因为openGL 处理的图像输入输出都是 RGB,而Capture node 输出和 CSI_TX node输入都是 UYVY,所以加入了node_1和node_3的颜色格式变换,想着能用硬件来做颜色变换能提高效率,现在看来我们这个设计有问题,干脆把颜色变换也放到A72 core上用openGL处理算了,这样可以吧?就是担心效率会降低

  • 您好,

    是的,您可以将颜色变换任务放到A72核心上使用OpenGL进行处理。这样做的好处是,您可以使用OpenGL的硬件加速功能来提高颜色变换的效率。虽然在DSS模块上使用硬件加速的颜色变换可能会更高效,但如果DSS模块的控制权已经转移到A72核心上,并且您无法在A72核心上注册DSS模块的DisplayM2MKernels,那么将颜色变换任务放到A72核心上使用OpenGL处理是一个可行的解决方案。

    但是请注意,由于OpenGL处理的图像输入和输出都是RGB格式,而Capture节点输出和CSI_TX节点输入是UYVY格式,因此您需要在A72核心上使用OpenGL进行颜色格式转换。确保在进行颜色转换时选择适当的OpenGL着色器或转换算法,以确保正确的颜色转换。

    然而虽然这种方法可能会导致一些性能损失,但如果您无法在A72核心上使用硬件加速的颜色变换,这是一个可行的替代方案。

  • 您好!

    感谢您的回复,我先尝试在A72核心上注册DSS模块的DisplayM2MKernels 看看

  • 好的,有问题随时交流,谢谢!