TDA4VM EVM学习笔记(1):屏幕上显示图形文件

本文介绍了基于TDA4VM EVM在屏幕上显示图形文件的实现步骤

1. 按照TI官方要求创建在Linux操作系统下的开发环境。目标可以在Vision_apps使用make生成目标文件。本文的环境是基于SDK8.0.5,Ubuntu 20.04 LTS + Docker

2. 在vision_apps/apps创建文件夹custom_usecase; 在custom_usecase下创建my_disp_img文件夹

3. 在my_disp_img文件夹下创建以下文件

a. concerto.mak

ifeq ($(TARGET_CPU),$(filter $(TARGET_CPU), x86_64 A72))

include $(PRELUDE)

TARGET      := my_disp_img

CSOURCES    := main.c

ifeq ($(TARGET_CPU),A72)
ifeq ($(TARGET_OS),$(filter $(TARGET_OS), LINUX QNX))

TARGETTYPE  := exe

CSOURCES    += main_linux_arm.c

include $(VISION_APPS_PATH)/apps/concerto_a72_inc.mak

endif
endif

ifeq ($(TARGET_OS),SYSBIOS)
ifeq ($(TARGET_CPU),$(filter $(TARGET_CPU), A72))
TARGETTYPE  := library
endif
endif

include $(FINALE)

endif

b. app_common.h

#ifndef _APP_COMMON
#define _APP_COMMON

#include <TI/tivx.h>
#include <TI/tivx_task.h>
#include <tivx_utils_file_rd_wr.h>

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <sys/stat.h>
#include <float.h>
#include <math.h>

//#define APP_DEBUG

#define APP_MAX_FILE_PATH           (256u)
#define APP_ASSERT(x)               assert((x))
#define APP_ASSERT_VALID_REF(ref)   (APP_ASSERT(vxGetStatus((vx_reference)(ref))==VX_SUCCESS));

#define MAX_IMG_WIDTH  (2048)
#define MAX_IMG_HEIGHT (1024)
#define DISPLAY_WIDTH  (1280)
#define DISPLAY_HEIGHT (720)

#ifdef APP_DEBUG
#define APP_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)
#else
#define APP_PRINTF(f_, ...)
#endif

#endif

c. main.c

#include "app_common.h"

typedef struct {
    /* config options */
    char input_file_path[APP_MAX_FILE_PATH];
    char input_file_list[APP_MAX_FILE_PATH];

    /* Input image params */

    tivx_utils_bmp_image_params_t imgParams;
    vx_uint32 img_width;
    vx_uint32 img_height;
    vx_uint32 img_stride;

    /* OpenVX references */
    vx_context context;

    vx_graph   disp_graph;
    vx_node    disp_node;
    vx_image   disp_image;

    vx_user_data_object disp_params_obj;
    tivx_display_params_t disp_params;

    vx_uint32 display_option;
    vx_uint32 delay_in_msecs;

    tivx_task task;
    uint32_t stop_task;
    uint32_t stop_task_done;
} AppObj;

AppObj gAppObj;

static vx_status app_init(AppObj *obj);
static void app_deinit(AppObj *obj);
static vx_status app_create_graph(AppObj *obj);
static vx_status app_verify_graph(AppObj *obj);
static vx_status app_run_graph(AppObj *obj);
static vx_status app_run_graph_interactive(AppObj *obj);
static void app_delete_graph(AppObj *obj);

int app_disp_img_main()
{
    int status = 0;
    AppObj *obj = &gAppObj;
    status = app_init(obj);
    if(status == VX_SUCCESS)
    {
        status = app_create_graph(obj);
    }
    if(status == VX_SUCCESS)
    {
        status = app_verify_graph(obj);
    }
    if(status == VX_SUCCESS)
    {
        status = app_run_graph_interactive(obj);
        
    }
    app_delete_graph(obj);
    app_deinit(obj);
    return status;
}

static int app_init(AppObj *obj)
{
    APP_PRINTF("disp_img: Init ... \n");
    obj->context = vxCreateContext();
    APP_ASSERT_VALID_REF(obj->context);
    obj->disp_image = vxCreateImage(obj->context, DISPLAY_WIDTH, DISPLAY_HEIGHT, VX_DF_IMAGE_RGB);
    APP_ASSERT_VALID_REF(obj->disp_image)
 
    memset(&obj->disp_params, 0, sizeof(tivx_display_params_t));

    obj->disp_params.opMode = TIVX_KERNEL_DISPLAY_BUFFER_COPY_MODE;
    obj->disp_params.pipeId = 0;
    obj->disp_params.outWidth = DISPLAY_WIDTH;
    obj->disp_params.outHeight = DISPLAY_HEIGHT;
    obj->disp_params.posX = (1920-DISPLAY_WIDTH)/2;
    obj->disp_params.posY = (1080-DISPLAY_HEIGHT)/2;

    obj->disp_params_obj = vxCreateUserDataObject(obj->context, "tivx_display_params_t", sizeof(tivx_display_params_t), &obj->disp_params);
    APP_ASSERT_VALID_REF(obj->disp_params_obj)

    obj->delay_in_msecs = 1000; 

    tivxHwaLoadKernels(obj->context);
    snprintf(obj->input_file_path, APP_MAX_FILE_PATH-1, "%s",
        "/opt/vision_apps/test_data/psdkra/app_tidl");

    snprintf(obj->input_file_list, APP_MAX_FILE_PATH-1, "%s",
        "/opt/vision_apps/test_data/psdkra/app_tidl/names.txt");

    APP_PRINTF("disp_img: Init ... Done.\n");

    return 0;
}

static void app_deinit(AppObj *obj)
{
    tivxHwaUnLoadKernels(obj->context);
    vxReleaseContext(&obj->context);
    APP_PRINTF("disp_img: De-init ... Done.\n");
}

static void app_delete_graph(AppObj *obj)
{
    APP_PRINTF("disp_img: Delete ... \n");
    vxReleaseNode(&obj->disp_node);
    vxReleaseGraph(&obj->disp_graph);
    APP_PRINTF("disp_img: Delete ... Done.\n");
}

static vx_status app_create_graph(AppObj *obj)
{
    vx_status status = VX_SUCCESS;
    APP_PRINTF("disp_img: Creating graph ... \n");

    /* Create OpenVx Graph */
    obj->disp_graph = vxCreateGraph(obj->context);
    APP_ASSERT_VALID_REF(obj->disp_graph)
    vxSetReferenceName((vx_reference)obj->disp_graph, "Display");

    obj->disp_node = tivxDisplayNode(obj->disp_graph, obj->disp_params_obj, obj->disp_image);
    APP_ASSERT_VALID_REF(obj->disp_node)

    vxSetNodeTarget(obj->disp_node, VX_TARGET_STRING, TIVX_TARGET_DISPLAY1);

    /* Set names for diferent OpenVX objects */
    vxSetReferenceName((vx_reference)obj->disp_params_obj, "DisplayParams");
    vxSetReferenceName((vx_reference)obj->disp_node, "DisplayNode");

    APP_PRINTF("disp_img: Creating graph ... Done.\n");
    return status;
}

static void app_run_task(void *app_var)
{
    AppObj *obj = (AppObj *)app_var;
    vx_status status = VX_SUCCESS;

    while(!obj->stop_task)
    {
        status = app_run_graph(obj);
        if(status == VX_FAILURE)
        {
            printf("Error processing graph!\n");
            obj->stop_task = 1;
        }
    }
    obj->stop_task_done = 1;
}

static int32_t app_run_task_create(AppObj *obj)
{
    tivx_task_create_params_t params;
    int32_t status;

    tivxTaskSetDefaultCreateParams(&params);
    params.task_main = app_run_task;
    params.app_var = obj;

    obj->stop_task_done = 0;
    obj->stop_task = 0;

    status = tivxTaskCreate(&obj->task, &params);

    return status;
}

static void app_run_task_delete(AppObj *obj)
{
    while(obj->stop_task_done==0)
    {
         tivxTaskWaitMsecs(100);
    }

    tivxTaskDelete(&obj->task);
}

static char menu[] = {
    "\n"
    "\n ================================="
    "\n Display the images from file"
    "\n ================================="
    "\n"
    "\n x: Exit"
    "\n"
    "\n Enter Choice: "
};

static vx_status app_run_graph_interactive(AppObj *obj)
{
    vx_status status = VX_SUCCESS;
    uint32_t done = 0;
    char ch;
    
    status = app_run_task_create(obj);
    if(status != VX_SUCCESS)
    {
        printf("disp_img: ERROR: Unable to create task\n");
    }
    else
    {
        
        while((!done) && (status == VX_SUCCESS))
        {
            printf(menu);
            ch = getchar();
            printf("\n");

            if(ch == 'x')
            {
                obj->stop_task = 1;
                done = 1;
                break;
            }
        }
        app_run_task_delete(obj);
    }
    return status;
}

static vx_status app_verify_graph(AppObj *obj)
{
    vx_status status = VX_SUCCESS;

    APP_PRINTF("disp_img: Verifying graph ... \n");

    /* Verify the TIDL Graph */
    status = vxVerifyGraph(obj->disp_graph);
    if(status != VX_SUCCESS)
    {
        printf("disp_img: ERROR: Verifying display graph ... Failed !!!\n");
        return status;
    }

    APP_PRINTF("disp_img: Verifying display graph ... Done.\n");

    /* wait a while for prints to flush */
    tivxTaskWaitMsecs(100);

    return status;
}

static vx_status app_run_graph_for_one_frame(AppObj *obj, char *curFileName, vx_uint32 counter)
{
    vx_status status = VX_SUCCESS;
    vx_char input_file_name[APP_MAX_FILE_PATH];

    //Clear the full image to black
    void *base_ptr = NULL;
    vx_uint32 plane = 0;
    vx_rectangle_t rect;
    vx_imagepatch_addressing_t addr;
    vx_map_id map_id;
    rect.start_x = rect.start_y = 0;
    rect.end_x = DISPLAY_WIDTH;
    rect.end_y = DISPLAY_HEIGHT;
    status = vxMapImagePatch(obj->disp_image, &rect, plane, &map_id, 
                            &addr, &base_ptr,
                            VX_READ_AND_WRITE, VX_MEMORY_TYPE_HOST, 0);
    if (status == VX_SUCCESS)
    {
        APP_PRINTF("Mapping successful!\n");
        vx_uint32 x,y;
        vx_uint8 pixel = 0;
        /* 2d addressing access */        
        for (y = 0; y < addr.dim_y; y+=addr.step_y) 
        {
            for (x = 0; x < addr.dim_x; x+=addr.step_x) 
            {
                vx_uint8 *ptr2 = vxFormatImagePatchAddress2d(base_ptr,
                    x, y, &addr);
                *ptr2 = pixel; 
                *(ptr2+1) = pixel;
                *(ptr2+2) = pixel;
            }
        } 
        status = vxUnmapImagePatch(obj->disp_image, map_id);
    }
    else
    {
        APP_PRINTF("Mapping failed!\n");
    }
    snprintf(input_file_name, APP_MAX_FILE_PATH-1, "%s/%s",
          obj->input_file_path,
          curFileName
          );
    APP_PRINTF("disp_img: Reading input file %s ... \n", curFileName); 
    /* Read input from file */
    status = tivx_utils_load_vximage_from_bmpfile ( obj->disp_image, input_file_name, (vx_bool)vx_false_e);
    APP_PRINTF("disp_image: Reading input file Done!\n");
    /* Execute the display graph */
    if(status == VX_SUCCESS)
    {
        status = vxProcessGraph(obj->disp_graph);
    }
    APP_PRINTF("disp_img: Running display graph ... Done.\n");
    return status;
}

static vx_status app_run_graph(AppObj *obj)
{
    vx_status status = VX_SUCCESS;
    vx_char curFileName[APP_MAX_FILE_PATH];
    uint64_t cur_time;
    uint64_t max_frames = INT64_MAX;
    vx_uint32 counter = 0;
    FILE* test_case_file;

    test_case_file =  fopen(obj->input_file_list,"r");
    if(test_case_file==NULL)
    {
        printf("Open file Error");
        status = VX_FAILURE;
    }
    if(status == VX_SUCCESS)
    {
        while (fgets(curFileName, sizeof(curFileName), test_case_file) && (counter < max_frames))
        {
            curFileName[strlen(curFileName) - 1] = 0;

            cur_time = tivxPlatformGetTimeInUsecs();

            APP_PRINTF("Input file: %s ...\n", curFileName);
            if(status == VX_SUCCESS)
            {
                status = app_run_graph_for_one_frame(obj, curFileName, counter++);
            }
            APP_PRINTF("Display input file %s ...Done!\n", curFileName);

            cur_time = tivxPlatformGetTimeInUsecs() - cur_time;
            /* convert to msecs */
            cur_time = cur_time/1000;

            if(cur_time < obj->delay_in_msecs)
            {
                tivxTaskWaitMsecs(obj->delay_in_msecs - cur_time);
            }

            /* user asked to stop processing */
            if(obj->stop_task || (status != VX_SUCCESS))
            {
                break;
            }
       }
       fclose(test_case_file);
    }
    return status;
}


备注:记得将图像文件的路径和文件列表替换为自己。本文中使用的test_data集中的文件。

d. main_linux_arm.c

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include <TI/tivx.h>
#include <utils/app_init/include/app_init.h>

int main()
{
    int status = 0;
    
    status = appInit();
    
    if(status==0)
    {
        int app_disp_img_main();
        
        status = app_disp_img_main();
        appDeInit();
    }
    
    return status;
}

4. 在vision_apps下使用make生成可执行文件my_disp_img.out

5. 将文件my_disp_img.out拷贝至开发板/opt/vision_apps下

6. 运行my_disp_img.out将可以看到存储在EVM上的文件可以依次显示在屏幕上,时间间隔为1秒。


【函数说明】

1. tivx_utils_load_vximage_from_bmpfile()

函数定义:

vx_status tivx_utils_load_vximage_from_bmpfile(vx_imageimage,
char * filename,
vx_boolconvert_to_gray_scale 
)

函数功能:

将BMP文件的图像加载到已经创建的vx_image对象中。

参数

image[in] 已经创建的图像对象
filename[in] 扩展名为bmp的图像文件的文件名
convert_to_gray_scale[in] vx_true_e: 将图像文件中RGB转化为8b灰度值
vx_false_e: 保留原始RGB值
备注:目前不能转化

返回值:

VX_SUCCESS:如果BMP文件可以成功加载到image的对象中

【参考信息】

  1. Ti SDK version 8.0.5: Processor SDK Linux Software Developer’s Guide — Processor SDK Linux for J721e Documentation
     
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

耀眼宝玉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值