/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* auto generate by HHB_VERSION "1.13.x" */ #include #include #include #include #include #include #include #include #include #include #include "io.h" #include "shl_ref.h" #include "process_linker_types.h" #include "process_linker.h" #include "process.h" #include "video_mem.h" #define MODULE_NAME "dw_test" #define _DMABUF_FD_SRC_ #define FILE_LENGTH 1028 #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define IMG_WIDTH 300 #define IMG_HEIGHT 300 #define STRIDE_WIDTH 304 #define STRIDE_HEIGHT 304 #define RESIZE_WIDTH 304 #define RESIZE_HEIGHT 304 #define CROP_WIDTH 304 #define CROP_HEGHT 304 #define R_MEAN 127.5 #define G_MEAN 127.5 #define B_MEAN 127.5 #define SCALE (1.0/127.5) int input_size[] = {1 * 3 * STRIDE_HEIGHT * STRIDE_WIDTH, }; #define BASE_MEMORY 0xD0000000 //#define BASE_MEMORY 0xc0c00000 #ifndef NULL #define NULL ((void *)0) #endif #define NUM_OF_BUFFERS 5 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) typedef struct _ServerParams { char *plinkname; char *inputfile; PlinkColorFormat format; int width; int height; int stride; int frames; } ServerParams; typedef struct _PlinkChannel { PlinkChannelID id; PlinkHandle plink; PlinkPacket pkt; int sendid; int backid; int exit; int available_bufs; } PlinkChannel; typedef struct _PictureBuffer { unsigned int bus_address; void *virtual_address; unsigned int size; int fd; } PictureBuffer; void printUsage(char *name) { printf("usage: %s [options]\n" "\n" " Available options:\n" " -l plink file name (default: /tmp/plink.test)\n" " -i input YUV file name (mandatory)\n" " -f input color format (default: 2)\n" " 2 - I420\n" " 3 - NV12\n" " -w video width (mandatory)\n" " -h video height (mandatory)\n" " -s video buffer stride (default: video width)\n" " -n number of frames to send (default: 10)\n" "\n", name); } /* * Preprocess function */ void preprocess(struct image_data *img, int is_rgb, int to_bgr) { uint32_t new_height, new_width; uint32_t min_side; if (is_rgb) { im2rgb(img); } if (RESIZE_WIDTH == 0) { min_side = MIN(img->shape[0], img->shape[1]); new_height = (uint32_t) (img->shape[0] * (((float)RESIZE_HEIGHT) / (float)min_side)); new_width = (uint32_t) (img->shape[1] * (((float)RESIZE_HEIGHT) / (float)min_side)); imresize(img, new_height, new_width); } else { imresize(img, RESIZE_HEIGHT, RESIZE_WIDTH); } data_crop(img, CROP_HEGHT, CROP_WIDTH); sub_mean(img, R_MEAN, G_MEAN, B_MEAN); data_scale(img, SCALE); if(to_bgr) { imrgb2bgr(img); } imhwc2chw(img); } void parseParams(int argc, char **argv, ServerParams *params) { int i = 1; memset(params, 0, sizeof(*params)); params->plinkname = "/tmp/plink_npu_rgb.test"; params->width = IMG_WIDTH; params->height = IMG_HEIGHT; params->stride = STRIDE_WIDTH; params->frames = 3; params->format = PLINK_COLOR_Format24BitBGR888Planar; while (i < argc) { if (argv[i][0] != '-' || strlen(argv[i]) < 2) { i++; continue; } if (argv[i][1] == 'l') { if (++i < argc) { params->plinkname = argv[i++]; } } else if (argv[i][1] == 'i') { if (++i < argc) { params->inputfile = argv[i++]; } } else if (argv[i][1] == 'f') { if (++i < argc) { params->format = atoi(argv[i++]); } } else if (argv[i][1] == 'w') { if (++i < argc) { params->width = atoi(argv[i++]); if (params->stride == 0) params->stride = params->width; } } else if (argv[i][1] == 'h') { if (++i < argc) { params->height = atoi(argv[i++]); } } else if (argv[i][1] == 's') { if (++i < argc) { params->stride = atoi(argv[i++]); } } else if (argv[i][1] == 'n') { if (++i < argc) { params->frames = atoi(argv[i++]); } } }; } int checkParams(ServerParams *params) { if (params->plinkname == NULL || params->inputfile == NULL || params->format == PLINK_COLOR_FormatUnused || params->width == 0 || params->height == 0 || params->stride == 0) return -1; return 0; } int getBufferSize(ServerParams *params) { int size = 0; switch (params->format) { case PLINK_COLOR_FormatYUV420Planar: case PLINK_COLOR_FormatYUV420SemiPlanar: size = params->stride * params->height * 3 / 2; break; case PLINK_COLOR_Format24BitRGB888Planar: case PLINK_COLOR_Format24BitBGR888Planar: size = params->stride * params->height * 3; break; default: size = 0; } return size; } void constructRGBInfo(PlinkRGBInfo *info, ServerParams *params, unsigned int bus_address, int id) { //int size = params->width * params->stride; int size_r = params->stride * params->stride; info->header.type = PLINK_TYPE_2D_RGB; info->header.size = DATA_SIZE(*info); info->header.id = id + 1; info->format = params->format; info->bus_address_b = bus_address; info->bus_address_g = info->bus_address_b + size_r; info->bus_address_r = info->bus_address_g + size_r; info->img_width = params->width; info->img_height = params->height; info->stride_r = params->stride; info->stride_g = params->stride; info->stride_b = params->stride; info->offset_r = 0; info->offset_g = 0; info->offset_b = 0; } int getBufferCount(PlinkPacket *pkt) { int ret = 0; for (int i = 0; i < pkt->num; i++) { PlinkDescHdr *hdr = (PlinkDescHdr *)(pkt->list[i]); if (hdr->type == PLINK_TYPE_MESSAGE) { int *data = (int *)(pkt->list[i] + DATA_HEADER_SIZE); if (*data == PLINK_EXIT_CODE) { ret |= 0x80000000; // set bit 31 to 1 to indicate 'exit' } else if (*data >= 0) ret++; } } return ret; } void retreiveSentBuffers(PlinkHandle plink, PlinkChannel *channel) { PlinkStatus sts = PLINK_STATUS_OK; while (channel->available_bufs < NUM_OF_BUFFERS) { do { sts = PLINK_recv(plink, channel->id, &channel->pkt); int count = getBufferCount(&channel->pkt); if (count > 0) { channel->available_bufs += count; } } while (sts == PLINK_STATUS_MORE_DATA); } } #ifdef _DMABUF_FD_SRC_ void AllocateBuffers(PictureBuffer picbuffers[NUM_OF_BUFFERS], unsigned int size, void *vmem) { unsigned int buffer_size = (size + 0xFFF) & ~0xFFF; VmemParams params; params.size = buffer_size; params.flags = VMEM_FLAG_CONTIGUOUS | VMEM_FLAG_4GB_ADDR; for (int i = 0; i < NUM_OF_BUFFERS; i++) { VMEM_allocate(vmem, ¶ms); VMEM_mmap(vmem, ¶ms); VMEM_export(vmem, ¶ms); printf("[SERVER] mmap %p from %x with size %d, dma-buf fd %d\n", params.vir_address, params.phy_address, params.size, params.fd); picbuffers[i].virtual_address = params.vir_address; picbuffers[i].bus_address = params.phy_address; picbuffers[i].size = buffer_size; picbuffers[i].fd = params.fd; } } void FreeBuffers(PictureBuffer picbuffers[NUM_OF_BUFFERS], void *vmem) { VmemParams params; memset(¶ms, 0, sizeof(params)); for (int i = 0; i < NUM_OF_BUFFERS; i++) { close(picbuffers[i].fd); params.size = picbuffers[i].size; params.vir_address = picbuffers[i].virtual_address; params.phy_address = picbuffers[i].bus_address; VMEM_free(vmem, ¶ms); } } #else void AllocateBuffers(PictureBuffer picbuffers[NUM_OF_BUFFERS], unsigned int size, int fd_mem) { unsigned int bus_address = BASE_MEMORY; unsigned int buffer_size = (size + 0xFFF) & ~0xFFF; for (int i = 0; i < NUM_OF_BUFFERS; i++) { picbuffers[i].virtual_address = mmap(0, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_mem, bus_address); printf("mmap %p from %x with size %d\n", picbuffers[i].virtual_address, bus_address, size); picbuffers[i].bus_address = bus_address; picbuffers[i].size = buffer_size; bus_address += buffer_size; } } void FreeBuffers(PictureBuffer picbuffers[NUM_OF_BUFFERS], unsigned int size, int fd_mem) { for (int i = 0; i < NUM_OF_BUFFERS; i++) { munmap(picbuffers[i].virtual_address, picbuffers[i].size); } } #endif int main(int argc, char **argv) { char **data_path = NULL; PlinkStatus sts = PLINK_STATUS_OK; ServerParams params; PlinkChannel channel[2]; PlinkHandle plink = NULL; PlinkRGBInfo pic; PlinkMsg msg; int input_num = 1; int output_num = 1; int i; int index = 0; if (argc < (1 + input_num)) { printf("Please set valide args: ./dw_src_test image.rgb\n"); return -1; } else { data_path = argv + 1; } parseParams(argc, argv, ¶ms); if (checkParams(¶ms) != 0) { printUsage(argv[0]); //return 0; } FILE *fp; #if 0 fp = fopen(params.inputfile, "rb"); if (fp == NULL) { printf("failed to open %s\n", params.inputfile); errExit("fopen"); } #endif #ifdef _DMABUF_FD_SRC_ void *vmem = NULL; if (VMEM_create(&vmem) != VMEM_STATUS_OK) errExit("Failed to create VMEM."); #else int fd_mem = open("/dev/mem", O_RDWR | O_SYNC); if (fd_mem < 0) { printf("%s: failed to open /dev/mem", MODULE_NAME); return -1; } #endif int in_size = input_size[0]; char filename[FILE_LENGTH] = {0}; char filename_prefix[FILE_LENGTH] = {0}; uint64_t start_time, end_time; int frames = params.frames; PictureBuffer picbuffers[NUM_OF_BUFFERS]; #ifdef _DMABUF_FD_SRC_ AllocateBuffers(picbuffers, in_size, vmem); #else AllocateBuffers(picbuffers, in_size, fd_mem); #endif sts = PLINK_create(&plink, params.plinkname, PLINK_MODE_SERVER); memset(&channel[0], 0, sizeof(channel[0])); channel[0].available_bufs = NUM_OF_BUFFERS; sts = PLINK_connect(plink, &channel[0].id); int frmcnt = 0; do { int sendid = channel[0].sendid; fill_buffer_from_file(data_path[0], picbuffers[sendid].virtual_address); //snprintf(filename, FILE_LENGTH, "%s_src_data%u.txt", filename_prefix, i); //save_uint8_to_file(filename, (uint8_t*)picbuffers[index].virtual_address, in_size); constructRGBInfo(&pic, ¶ms, picbuffers[sendid].bus_address, sendid); printf("[SERVER] Processed frame %d 0x%010llx: %dx%d, stride = %d\n", sendid, pic.bus_address_b, pic.img_width, pic.img_height, pic.stride_b); channel[0].pkt.list[0] = &pic; channel[0].pkt.num = 1; #ifdef _DMABUF_FD_SRC_ channel[0].pkt.fd = picbuffers[sendid].fd; #else channel[0].pkt.fd = PLINK_INVALID_FD; // physical address #endif sts = PLINK_send(plink, channel[0].id, &channel[0].pkt); channel[0].sendid = (channel[0].sendid + 1) % NUM_OF_BUFFERS; channel[0].available_bufs -= 1; // Notify npu one picture is ready for inference int timeout = 0; if (channel[0].available_bufs == 0) timeout = 60000; // wait up to 60 seconds if buffers are used up if (PLINK_wait(plink, channel[0].id, timeout) == PLINK_STATUS_OK) { do { sts = PLINK_recv(plink, channel[0].id, &channel[0].pkt); int count = getBufferCount(&channel[0].pkt); if (count < 0) channel[0].exit = 1; channel[0].available_bufs += count; } while (sts == PLINK_STATUS_MORE_DATA); } index = (index + 1) % NUM_OF_BUFFERS; } while (channel[0].exit == 0 && frmcnt < frames); retreiveSentBuffers(plink, &channel[0]); cleanup: msg.header.type = PLINK_TYPE_MESSAGE; msg.header.size = DATA_SIZE(PlinkMsg); msg.msg = PLINK_EXIT_CODE; channel[0].pkt.list[0] = &msg; channel[0].pkt.num = 1; channel[0].pkt.fd = PLINK_INVALID_FD; sts = PLINK_send(plink, channel[0].id, &channel[0].pkt); sleep(1); // Sleep one second to make sure client is ready for exit PLINK_close(plink, PLINK_CLOSE_ALL); #ifdef _DMABUF_FD_SRC_ FreeBuffers(picbuffers, vmem); #else FreeBuffers(picbuffers, in_size, fd_mem); #endif if (fp != NULL) fclose(fp); return 0; }