/* * Copyright (c) XMEDIA. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include "xmedia_msensor.h" #include "xmedia_sys.h" #include "xmedia_vi.h" #include "xmedia_venc.h" #include "xmedia_mmz.h" #include "sample_comm.h" #include "sample_comm_sys.h" #include "sample_comm_vi.h" #include "sample_comm_vpss.h" #include "sample_comm_vgs.h" #include "sample_comm_venc.h" #include "sample_comm_isp.h" #include "sample_msensor.h" #define NUMS_IN_BUF 4000 /* max numbers of gyro data or acc data in buffer */ #define GYRO_BUF_SIZE (sizeof(xmedia_msensor_sample_data) * NUMS_IN_BUF) #define ACC_BUF_SIZE (sizeof(xmedia_msensor_sample_data) * NUMS_IN_BUF) #define GYRO_DATA_RECORDER_RANGE 1000 #define GYRO_DATA_DV_RANGE 1000 #define GYRO_DATA_ODR 800 #define ACC_DATA_RANGE 16 #define ACC_DATA_ODR 800 #define INT_MAX 0x7fffffff /* max value for an int */ #define GYRO_BIN_FILE "./gyro_data.bin" #define GYRO_TXT_FILE "./gyro_data.txt" #define GYRO_PARSE_FILE "./gyro_parse_data.txt" typedef struct msensor_get_data_info_ { xmedia_bool thread_start; xmedia_msensor_data_type data_type; xmedia_u32 time_intval; xmedia_s32 msensor_dev; xmedia_s32 venc_chn; } msensor_get_data_info; typedef struct msensor_data_info_ { xmedia_s32 msensor_dev; xmedia_s32 user_id; FILE *gyro_bin_fp; FILE *gyro_txt_fp; } msensor_data_info; static xmedia_bool g_force_exit = XMEDIA_FALSE; xmedia_s32 g_msensor_dev_fd = -1; xmedia_msensor_buf_attr g_msensor_attr[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 }; xmedia_s32 g_gyro_data_range = GYRO_DATA_DV_RANGE; static pthread_t g_msensor_pid[XMEDIA_MSENSOR_MAX_DEV_NUM]; static msensor_get_data_info g_get_data_info[XMEDIA_MSENSOR_MAX_DEV_NUM] = { 0 }; static sample_comm_sensor_type sample_msensor_sensor_type[MAX_SENSOR_NUM] = { SENSOR0_TYPE,SENSOR1_TYPE,SENSOR2_TYPE,SENSOR3_TYPE,SENSOR4_TYPE }; xmedia_void sample_msensor_handle_sig(xmedia_s32 signo) { if (SIGINT == signo || SIGTSTP == signo || SIGTERM == signo) { g_force_exit = XMEDIA_TRUE; } } xmedia_s32 sample_msensor_sys_init(sample_sys_config *sys_config) { xmedia_s32 ret = 0; ret = sample_comm_sys_init(sys_config); if(ret != XMEDIA_SUCCESS) { SAMPLE_PRT("sample_comm_sys_init failed!\n"); return ret; } //in online-online mode,vi and vpss must be reset at the same time ret = sample_comm_vi_init(); if(ret != XMEDIA_SUCCESS) { SAMPLE_PRT("sample_comm_vi_init failed!\n"); return ret; } ret = sample_comm_vpss_init(); if(ret != XMEDIA_SUCCESS) { SAMPLE_PRT("sample_comm_vpss_init failed!\n"); return ret; } ret = sample_comm_venc_init(); if(ret != XMEDIA_SUCCESS) { SAMPLE_PRT("sample_comm_venc_init failed!\n"); return ret; } return XMEDIA_SUCCESS; } xmedia_void sample_msensor_sys_exit(void) { sample_comm_venc_exit(); sample_comm_vpss_exit(); sample_comm_vi_exit(); sample_comm_sys_exit(); } xmedia_void sample_msensor_usage(xmedia_char* args) { printf("Usage1 : %s [index] \n", args); printf("index:\n"); printf("\t 0) h265 + msensor.\n"); printf("\t 1) parse msensor data.\n"); return; } xmedia_u32 h265_encode_sei(xmedia_void *dest_buf, xmedia_void *src_buf, xmedia_u32 in_len_bytes, xmedia_u32 *out_len_bytes) { xmedia_u8 *dest = (xmedia_u8 *)dest_buf; xmedia_u8 *src = (xmedia_u8 *)src_buf; xmedia_s32 tmp_len = 0; xmedia_u32 size; xmedia_u32 tmp_code; xmedia_u32 byte_cnt = 0; xmedia_s32 zero_cnt = 0; xmedia_s32 k; size = in_len_bytes; dest[byte_cnt++] = 0x00; dest[byte_cnt++] = 0x00; dest[byte_cnt++] = 0x00; dest[byte_cnt++] = 0x1; dest[byte_cnt++] = 0x4e; dest[byte_cnt++] = 0x1; dest[byte_cnt++] = 0xF0; while (size >= 255) { size -= 255; dest[byte_cnt++] = 0xFF; } tmp_code = size; dest[byte_cnt++] = tmp_code; tmp_len = byte_cnt; if (size == 0) { zero_cnt = 1; } for (k = 0; k < (xmedia_s32)in_len_bytes; k++) { /* true when 0x000000|0x000001|0x000002|0x000003 */ if ((zero_cnt == 2) && !(src[k] & 0xFC)) { dest[byte_cnt++] = 0x03; zero_cnt = 0; } dest[byte_cnt++] = src[k]; if (src[k] == 0x00) { zero_cnt++; } else { zero_cnt = 0; } } dest[byte_cnt++] = 0x80; *out_len_bytes = byte_cnt; return tmp_len; } xmedia_u32 h264_encode_sei(xmedia_void *dest_buf, xmedia_void *src_buf, xmedia_u32 in_len_bytes, xmedia_u32 *out_len_bytes) { xmedia_u8 *dest = (xmedia_u8 *)dest_buf; xmedia_u8 *src = (xmedia_u8 *)src_buf; xmedia_s32 tmp_len = 0; xmedia_u32 size; xmedia_u32 tmp_code; xmedia_u32 byte_cnt = 0; xmedia_s32 zero_cnt = 0; xmedia_s32 k; size = in_len_bytes; dest[byte_cnt++] = 0x00; dest[byte_cnt++] = 0x00; dest[byte_cnt++] = 0x00; dest[byte_cnt++] = 0x1; dest[byte_cnt++] = 0x6; dest[byte_cnt++] = 0xF0; while (size >= 255) { size -= 255; dest[byte_cnt++] = 0xFF; } tmp_code = size; dest[byte_cnt++] = tmp_code; tmp_len = byte_cnt; if (size == 0) { zero_cnt = 1; } for (k = 0; k < (xmedia_s32)in_len_bytes; k++) { /* true when 0x000000|0x000001|0x000002|0x000003 */ if ((zero_cnt == 2) && !(src[k] & 0xFC)) { dest[byte_cnt++] = 0x03; zero_cnt = 0; } dest[byte_cnt++] = src[k]; if (src[k] == 0x00) { zero_cnt++; } else { zero_cnt = 0; } } dest[byte_cnt++] = 0x80; *out_len_bytes = byte_cnt; return tmp_len; } static void save_gyro_data(xmedia_u8 *data, xmedia_s32 datalen, FILE *pfile) { xmedia_s32 x; xmedia_s32 y; xmedia_s32 z; xmedia_s32 temp; xmedia_u64 pts; xmedia_u8 * temp_ptr = data; xmedia_s32 tmplen = 0; xmedia_char buf[128] = {0}; if (datalen % 24 != 0) { return ; } while (tmplen + 24 <= datalen) { x = *(xmedia_s32 *)temp_ptr; temp_ptr += sizeof(xmedia_s32); y = *(xmedia_s32 *)temp_ptr; temp_ptr += sizeof(xmedia_s32); z = *(xmedia_s32 *)temp_ptr; temp_ptr += sizeof(xmedia_s32); temp = *(xmedia_s32 *)temp_ptr; temp_ptr += sizeof(xmedia_s32); pts = *(xmedia_u64 *)temp_ptr; temp_ptr += sizeof(xmedia_u64); tmplen += 24; sprintf(buf, "%12d,%12d,%12d,%12d,%22llu, \n", x, y, z, temp, pts); fwrite(buf, strlen(buf), 1, pfile); } } // 查找4字节起始码 0x00000001 int find_4byte_start_code(const xmedia_u8* data, int size, int start_pos) { int i; for (i = start_pos; i < size - 4; i++) { if (data[i] == 0x00 && data[i+1] == 0x00 && data[i+2] == 0x00 && data[i+3] == 0x01) { return i; } } return -1; } // 防竞争字节处理 - 移除0x03字节 // 在H.264/H.265中,0x000000, 0x000001, 0x000002, 0x000003前面会插入0x03防止竞争 xmedia_u8* remove_emulation_prevention_bytes(const xmedia_u8* data, int size, int* new_size) { xmedia_u8* output; int output_index = 0; int zero_count = 0; if (size <= 0) { *new_size = 0; return NULL; } // 分配足够大的缓冲区 output = (xmedia_u8*)malloc(size); if (!output) { *new_size = 0; return NULL; } for (int i = 0; i < size; i++) { if (zero_count == 2 && data[i] == 0x03) { // 找到防竞争字节0x03,跳过它 zero_count = 0; continue; } if (data[i] == 0x00) { zero_count++; } else { zero_count = 0; } output[output_index++] = data[i]; } *new_size = output_index; return output; } // 解析H.264 SEI NAL单元(带防竞争处理) int parse_h264_sei_nal(const xmedia_u8* nal_data, int nal_size, FILE *file) { int rbsp_size; xmedia_u8* rbsp_data; int payload_type = 0; xmedia_u8 byte; int pos = 1; // 跳过NAL头(1字节) if (nal_size < 2) { return 0; } // 首先进行防竞争字节处理 rbsp_data = remove_emulation_prevention_bytes(nal_data, nal_size, &rbsp_size); if (!rbsp_data) { return 0; } pos = 1; // 跳过NAL头(1字节) while (pos < rbsp_size) { // 解析payload_type(使用类似UTF-8的变长编码) do { if (pos >= rbsp_size) { break; } byte = rbsp_data[pos++]; payload_type += byte; } while (byte == 0xFF); if (pos >= rbsp_size) { break; } // 解析payload_size(使用类似UTF-8的变长编码) int payload_size = 0; do { if (pos >= rbsp_size) { break; } byte = rbsp_data[pos++]; payload_size += byte; } while (byte == 0xFF); if (pos + payload_size > rbsp_size) { printf("Warning: SEI payload size exceeds RBSP size\n"); break; } save_gyro_data(rbsp_data+pos, payload_size, file); pos += payload_size; // 跳过rbsp_trailing_bits(如果有) if (pos < rbsp_size) { // rbsp_trailing_bits以1开始,后面跟0 if (rbsp_data[pos] == 0x80) { pos++; } } } free(rbsp_data); return 0; } // 解析H.265 SEI NAL单元(带防竞争处理) int parse_h265_sei_nal(const xmedia_u8* nal_data, int nal_size, FILE *file) { int rbsp_size; xmedia_u8* rbsp_data; int payload_type = 0; xmedia_u8 byte; int pos = 2; // 跳过NAL头(1字节) if (nal_size < 3) { return 0; } // 首先进行防竞争字节处理 rbsp_data = remove_emulation_prevention_bytes(nal_data, nal_size, &rbsp_size); if (!rbsp_data) { return 0; } pos = 2; // 跳过NAL头(2字节) while (pos < rbsp_size) { // 解析payload_type(使用类似UTF-8的变长编码) do { if (pos >= rbsp_size) { break; } byte = rbsp_data[pos++]; payload_type += byte; } while (byte == 0xFF); if (pos >= rbsp_size) { break; } // 解析payload_size(使用类似UTF-8的变长编码) int payload_size = 0; do { if (pos >= rbsp_size) { break; } byte = rbsp_data[pos++]; payload_size += byte; } while (byte == 0xFF); if (pos + payload_size > rbsp_size) { printf("Warning: SEI payload size exceeds RBSP size\n"); break; } save_gyro_data(rbsp_data+pos, payload_size, file); pos += payload_size; // 跳过rbsp_trailing_bits(如果有) if (pos < rbsp_size) { // rbsp_trailing_bits以1开始,后面跟0 if (rbsp_data[pos] == 0x80) { pos++; } } } free(rbsp_data); return 0; } // 从码流中解析SEI数据(带防竞争处理) void parse_stream_sei_with_emulation_prevention(const xmedia_u8* stream_data, int stream_size, int is_h265, FILE *file) { int pos = 0; int next_start; int nal_size; xmedia_u8 nal_header; xmedia_u8 nal_unit_type; int is_sei_nal = 0; int start_code_pos; while (pos < stream_size - 4) { // 查找4字节起始码 start_code_pos = find_4byte_start_code(stream_data, stream_size, pos); if (start_code_pos == -1) { break; } pos = start_code_pos + 4; // 移动到起始码后 if (pos >= stream_size) { break; } // 查找下一个起始码以确定NAL单元大小 next_start = find_4byte_start_code(stream_data, stream_size, pos); if (next_start == -1) { nal_size = stream_size - pos; } else { nal_size = next_start - pos; } if (nal_size <= 0) { pos += 1; continue; } // 获取NAL单元类型 nal_header = stream_data[pos]; if (is_h265) { nal_unit_type = (nal_header >> 1) & 0x3F; // H.265: 6位类型 } else { nal_unit_type = nal_header & 0x1F; // H.264: 5位类型 } // 检查是否为SEI NAL单元 if (is_h265) { // H.265: 前缀SEI(39)和后缀SEI(40) is_sei_nal = (nal_unit_type == 39 || nal_unit_type == 40); } else { // H.264: SEI类型为6 is_sei_nal = (nal_unit_type == 6); } //printf(" NAL size: %d bytes, Type: %d\n", nal_size, nal_unit_type); if (is_sei_nal) { if (is_h265) { parse_h265_sei_nal(stream_data + pos, nal_size, file); } else { parse_h264_sei_nal(stream_data + pos, nal_size, file); } } pos += nal_size; } } xmedia_s32 msensor_spi_init(void) { xmedia_s32 fd, ret; xmedia_s32 mode = SPI_MODE_3; /* | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_HIGH */ xmedia_s32 bits = 8; xmedia_u64 speed = 10000000; xmedia_char *dev = "/dev/spidev2.0"; fd = open(dev, O_RDWR); if (fd < 0) { SAMPLE_PRT("open spi def failed\n"); return XMEDIA_FAILURE; } /* set spi mode */ ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); /* SPI_IOC_WR_MODE32 */ if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("can't set spi mode\n"); goto end; } ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); /* SPI_IOC_RD_MODE32 */ if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("can't get spi mode\n"); goto end; } /* * bits per word */ ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("can't set bits per word\n"); goto end; } ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("can't get bits per word\n"); goto end; } /* set spi max speed */ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("can't set bits max speed HZ\n"); goto end; } ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("can't set bits max speed HZ\n"); goto end; } printf("spi mode: 0x%x\n", mode); printf("bits per word: %d\n", bits); printf("max speed: %lld Hz (%lld KHz)\n", speed, speed / 1000); /* speed with precision of 1000 */ end: close(fd); return ret; } xmedia_s32 msensor_init(xmedia_s32 dev) { xmedia_s32 ret; xmedia_u32 buf_size = GYRO_BUF_SIZE + ACC_BUF_SIZE; xmedia_char buf_name[20] = { 0 }; xmedia_msensor_param param; snprintf(buf_name, sizeof(buf_name), "msensor_dev%d", dev); g_msensor_attr[dev].phys_addr = xmedia_mmz_alloc(NULL, buf_name, buf_size); if (g_msensor_attr[dev].phys_addr == 0) { SAMPLE_PRT("alloc mmz for Msensor failed\n"); return XMEDIA_FAILURE; } g_msensor_attr[dev].virt_addr = xmedia_mmz_map(g_msensor_attr[dev].phys_addr, buf_size, XMEDIA_FALSE); if (g_msensor_attr[dev].virt_addr == 0) { SAMPLE_PRT("msensor malloc mmz map failed\n"); xmedia_mmz_free(g_msensor_attr[dev].phys_addr); return XMEDIA_FAILURE; } (xmedia_void) memset(g_msensor_attr[dev].virt_addr, 0, buf_size); g_msensor_attr[dev].buf_len = buf_size; /* set device work mode */ param.attr.device_mask = XMEDIA_MSENSOR_DEVICE_GYRO | XMEDIA_MSENSOR_DEVICE_ACC; param.attr.temperature_mask = XMEDIA_MSENSOR_TEMP_GYRO | XMEDIA_MSENSOR_TEMP_ACC; /* set gyro samplerate and full scale range */ param.config.gyro_config.odr = GYRO_DATA_ODR * XMEDIA_MSENSOR_GRADIENT; param.config.gyro_config.fsr = g_gyro_data_range * XMEDIA_MSENSOR_GRADIENT; /* set accel samplerate and full scale range */ param.config.acc_config.odr = ACC_DATA_ODR * XMEDIA_MSENSOR_GRADIENT; param.config.acc_config.fsr = ACC_DATA_RANGE * XMEDIA_MSENSOR_GRADIENT; (xmedia_void) memcpy(¶m.buf_attr, &g_msensor_attr[dev], sizeof(xmedia_msensor_buf_attr)); ret = xmedia_msensor_create_dev(dev, ¶m); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("msensor_create failed\n"); return XMEDIA_FAILURE; } return ret; } xmedia_void msensor_deinit(xmedia_s32 dev) { xmedia_s32 ret; ret = xmedia_msensor_destroy_dev(dev); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("msensor deinit failed , ret:0x%x !\n", ret); } ret = xmedia_mmz_unmap(g_msensor_attr[dev].virt_addr); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("msensor mmz map failed, ret:0x%x !\n", ret); } ret = xmedia_mmz_free(g_msensor_attr[dev].phys_addr); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("msensor mmz free failed, ret:0x%x !\n", ret); } g_msensor_attr[dev].phys_addr = 0; g_msensor_attr[dev].virt_addr = NULL; return; } xmedia_s32 msensor_start(xmedia_s32 dev) { xmedia_s32 ret; printf("spi init\n"); ret = msensor_spi_init(); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("init spi fail.ret:0x%x !\n", ret); return ret; } printf("spi init ok\n"); ret = msensor_init(dev); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("init gyro fail.ret:0x%x !\n", ret); return ret; } ret = xmedia_msensor_start_dev(dev);; if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("start gyro fail.ret:0x%x !\n", ret); goto msensor_start_fail; } printf("motion sensor start ok\n"); return XMEDIA_SUCCESS; msensor_start_fail: msensor_deinit(dev); return ret; } xmedia_void msensor_stop(xmedia_s32 dev) { xmedia_msensor_stop_dev(dev);; msensor_deinit(dev); return; } xmedia_venc_stream *msensor_mix_gyro_stream(xmedia_payload_type payload_type, FILE* pFd, xmedia_venc_stream* pstStream, xmedia_u32 stream_idex, msensor_data_info *pstdata_info) { xmedia_s32 i; xmedia_msensor_data_info gyro_data; static xmedia_venc_stream *last_stream = XMEDIA_NULL; static xmedia_u32 delta_pts = 0; xmedia_venc_stream *temp_stream; xmedia_s32 addr_offset; xmedia_s32 x; xmedia_s32 y; xmedia_s32 z; xmedia_s32 temp; xmedia_u64 pts; static xmedia_char *gyro_data_buf = XMEDIA_NULL; static xmedia_char *sei_data_buf = XMEDIA_NULL; xmedia_u32 gyro_data_len = 0; xmedia_u32 sei_data_len = 0; xmedia_char * txt_buf; xmedia_char txt_tmp[128] = {0}; xmedia_u32 txt_pos = 0; xmedia_char * temp_ptr; int cyclic; xmedia_s32 ret; xmedia_s32 msensor_dev; xmedia_s32 user_id; if (payload_type != PT_H264 && payload_type != PT_H265) { return pstStream; } if (stream_idex == 0) { last_stream = pstStream; if (gyro_data_buf == XMEDIA_NULL) { gyro_data_buf = malloc(4*1024); } if (sei_data_buf == XMEDIA_NULL) { sei_data_buf = malloc(6*1024); } return XMEDIA_NULL; } if ((gyro_data_buf == XMEDIA_NULL) || (sei_data_buf == XMEDIA_NULL)) { return pstStream; } msensor_dev = pstdata_info->msensor_dev; user_id = pstdata_info->user_id; gyro_data.id = user_id; gyro_data.data_type = XMEDIA_MSENSOR_DATA_TYPE_GYRO; if (stream_idex != 0xFFFFFFFF) { delta_pts = pstStream->pack[0].pts - last_stream->pack[0].pts; gyro_data.begin_pts = last_stream->pack[0].pts; gyro_data.end_pts = pstStream->pack[0].pts; } else { gyro_data.begin_pts = last_stream->pack[0].pts; gyro_data.end_pts = gyro_data.begin_pts + delta_pts; } ret = xmedia_msensor_get_data(msensor_dev, &gyro_data); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("msensor get data failed, pts[%lld]-pts[%lld] ret:0x%x !\n", gyro_data.begin_pts, gyro_data.end_pts, ret); temp_stream = last_stream; last_stream = pstStream; if (stream_idex == 0xFFFFFFFF) { temp_stream = last_stream; last_stream = XMEDIA_NULL; if (gyro_data_buf) { free(gyro_data_buf); gyro_data_buf = XMEDIA_NULL; } if (sei_data_buf) { free(sei_data_buf); sei_data_buf = XMEDIA_NULL; } } return temp_stream; } //SAMPLE_PRT("get gyro data start pts %llu, end pts %llu, diff %llu, num %d %d\n", gyro_data.begin_pts, // gyro_data.end_pts, gyro_data.end_pts - gyro_data.begin_pts, gyro_data.data[0].num, // gyro_data.data[1].num);usleep(100000); gyro_data_len = (gyro_data.data[0].num + gyro_data.data[1].num) * 24; temp_ptr = gyro_data_buf; addr_offset = g_msensor_attr[msensor_dev].phys_addr - (xmedia_u64)(xmedia_uintptr_t)g_msensor_attr[msensor_dev].virt_addr; txt_buf = (xmedia_char *)malloc(1024*1024); txt_pos = 0; memset(txt_tmp, 0, sizeof(txt_tmp)); for (cyclic = 0; cyclic < 2; cyclic++) { for (i = 0; i < gyro_data.data[cyclic].num; i++) { x = *(xmedia_s32 *)(xmedia_uintptr_t)((xmedia_u64)(xmedia_uintptr_t)(gyro_data.data[cyclic].x_phys_addr + i) - addr_offset); y = *(xmedia_s32 *)(xmedia_uintptr_t)((xmedia_u64)(xmedia_uintptr_t)(gyro_data.data[cyclic].y_phys_addr + i) - addr_offset); z = *(xmedia_s32 *)(xmedia_uintptr_t)((xmedia_u64)(xmedia_uintptr_t)(gyro_data.data[cyclic].z_phys_addr + i) - addr_offset); temp = *(xmedia_s32 *)(xmedia_uintptr_t)((xmedia_u64)(xmedia_uintptr_t)(gyro_data.data[cyclic].temperature_phys_addr + i) - addr_offset); pts = *(xmedia_u64 *)(xmedia_uintptr_t)((xmedia_u64)(xmedia_uintptr_t)(gyro_data.data[cyclic].pts_phys_addr + i) - addr_offset); *(xmedia_s32 *)temp_ptr = x; temp_ptr += sizeof(xmedia_s32); *(xmedia_s32 *)temp_ptr = y; temp_ptr += sizeof(xmedia_s32); *(xmedia_s32 *)temp_ptr = z; temp_ptr += sizeof(xmedia_s32); *(xmedia_s32 *)temp_ptr = temp; temp_ptr += sizeof(xmedia_s32); *(xmedia_u64 *)temp_ptr = pts; temp_ptr += sizeof(xmedia_u64); if (txt_buf) { sprintf(txt_tmp, "%12d,%12d,%12d,%12d,%22llu, \n", x, y, z, temp, pts); memcpy(txt_buf+txt_pos, txt_tmp, strlen(txt_tmp)); txt_pos += strlen(txt_tmp); } } } if (txt_buf) { fwrite(txt_buf, txt_pos, 1, pstdata_info->gyro_txt_fp); free(txt_buf); txt_buf = XMEDIA_NULL; } if (payload_type == PT_H264) { h264_encode_sei(sei_data_buf, gyro_data_buf, gyro_data_len, &sei_data_len); fwrite(sei_data_buf, sei_data_len, 1, pFd); if (pstdata_info->gyro_bin_fp) { fwrite(sei_data_buf, sei_data_len, 1, pstdata_info->gyro_bin_fp); } } else if (payload_type == PT_H265) { h265_encode_sei(sei_data_buf, gyro_data_buf, gyro_data_len, &sei_data_len); fwrite(sei_data_buf, sei_data_len, 1, pFd); if (pstdata_info->gyro_bin_fp) { fwrite(sei_data_buf, sei_data_len, 1, pstdata_info->gyro_bin_fp); } } for (i = 0; i < last_stream->pack_count; i++) { fwrite(last_stream->pack[i].vir_addr + last_stream->pack[i].offset, last_stream->pack[i].len - last_stream->pack[i].offset, 1, pFd); } if (stream_idex == 0xFFFFFFFF) { temp_stream = last_stream; last_stream = XMEDIA_NULL; if (gyro_data_buf) { free(gyro_data_buf); gyro_data_buf = XMEDIA_NULL; } if (sei_data_buf) { free(sei_data_buf); sei_data_buf = XMEDIA_NULL; } } else { temp_stream = last_stream; last_stream = pstStream; } return temp_stream; } xmedia_void *msensor_get_data_thread(xmedia_void *args) { xmedia_s32 ret; xmedia_s32 msensor_dev; xmedia_s32 user_id; msensor_data_info msensor_info; msensor_get_data_info *get_data_info = (msensor_get_data_info *)args; FILE *gyro_bin_fp = XMEDIA_NULL; FILE *gyro_txt_fp = XMEDIA_NULL; xmedia_u32 stream_index = 0; //xmedia_u16 temp_pts = 0; xmedia_venc_chn_attr venc_chn_attr; xmedia_payload_type payload_type; xmedia_char file_name[512]; xmedia_char *file_path="./"; FILE *file_ptr; struct timeval time_out; xmedia_venc_stream *venc_stream; xmedia_venc_chn_status stat; xmedia_u32 venc_mask = 0; xmedia_venc_stream *temp_stream; printf("start dump gyro data\n"); gyro_bin_fp = fopen(GYRO_BIN_FILE, "w+"); if (gyro_bin_fp == XMEDIA_NULL) { SAMPLE_PRT("Error: cannot open imu data\n"); return XMEDIA_NULL; } gyro_txt_fp = fopen(GYRO_TXT_FILE, "w+"); if (gyro_txt_fp == XMEDIA_NULL) { fclose(gyro_bin_fp); SAMPLE_PRT("Error: cannot open imu data\n"); return XMEDIA_NULL; } ret = xmedia_venc_get_chn_attr(get_data_info->venc_chn, &venc_chn_attr); if (XMEDIA_SUCCESS != ret) { SAMPLE_PRT("xmedia_venc_get_chn_attr chn[%d] failed with %#x!\n", get_data_info->venc_chn, ret); return XMEDIA_NULL; } payload_type = venc_chn_attr.venc_attr.en_type; if (payload_type != PT_H264 && payload_type != PT_H265) { goto exit; } if (payload_type == PT_H264) { snprintf(file_name, 512, "%s/stream_chn%d%s", file_path, get_data_info->venc_chn, ".h264"); } else { snprintf(file_name, 512, "%s/stream_chn%d%s", file_path, get_data_info->venc_chn, ".h265"); } file_ptr = fopen(file_name, "wb"); if (!file_ptr) { SAMPLE_PRT("open file %s failed!\n", file_name); return XMEDIA_NULL; } chmod(file_name, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); venc_mask |= 1 << get_data_info->venc_chn; msensor_dev = get_data_info->msensor_dev; ret = xmedia_msensor_add_user(msensor_dev, &user_id); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("msensor add user failed, ret:0x%x !\n", ret); goto exit; } msensor_info.msensor_dev = msensor_dev; msensor_info.user_id = user_id; msensor_info.gyro_txt_fp = gyro_txt_fp; msensor_info.gyro_bin_fp = gyro_bin_fp; while (get_data_info->thread_start) { time_out.tv_sec = 2; time_out.tv_usec = 0; ret = xmedia_venc_select(venc_mask, &time_out); if (ret == XMEDIA_ERRCODE_INVALID_PARAM || ret == XMEDIA_FAILURE) { SAMPLE_PRT("select err\n"); break; } else if (ret == XMEDIA_ERRCODE_TIMEOUT) { usleep(100 * 1000); continue; } ret = xmedia_venc_query_status(get_data_info->venc_chn, &stat); if (XMEDIA_SUCCESS != ret) { SAMPLE_PRT("xmedia_venc_query_status chn[%d] failed with %#x!\n", get_data_info->venc_chn, ret); break; } if (0 == stat.cur_packs) { continue; } venc_stream = (xmedia_venc_stream *)malloc(sizeof(xmedia_venc_stream)); if (XMEDIA_NULL == venc_stream) { SAMPLE_PRT("malloc stream pack failed!\n"); break; } memset(venc_stream, 0, sizeof(xmedia_venc_stream)); venc_stream->pack = (xmedia_venc_pack*)malloc(sizeof(xmedia_venc_pack) * stat.cur_packs); if (XMEDIA_NULL == venc_stream->pack) { SAMPLE_PRT("malloc stream pack failed!\n"); free(venc_stream); break; } venc_stream->pack_count = stat.cur_packs; ret = xmedia_venc_get_stream(get_data_info->venc_chn, venc_stream, -1); if (XMEDIA_SUCCESS != ret) { free(venc_stream->pack); venc_stream->pack = XMEDIA_NULL; free(venc_stream); SAMPLE_PRT("xmedia_venc_get_stream failed with %#x!\n", ret); break; } if (PT_JPEG != payload_type) { temp_stream = msensor_mix_gyro_stream(payload_type, file_ptr, venc_stream, stream_index, &msensor_info); stream_index++; if (XMEDIA_NULL != temp_stream) { xmedia_venc_release_stream(get_data_info->venc_chn, temp_stream); free(temp_stream->pack); temp_stream->pack = XMEDIA_NULL; free(temp_stream); } } } temp_stream = msensor_mix_gyro_stream(payload_type, file_ptr, XMEDIA_NULL, 0xFFFFFFFF, &msensor_info); if (XMEDIA_NULL != temp_stream) { xmedia_venc_release_stream(get_data_info->venc_chn, temp_stream); free(temp_stream->pack); temp_stream->pack = XMEDIA_NULL; free(temp_stream); } ret = xmedia_msensor_delete_user(msensor_dev, user_id); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("msensor delete user failed, ret:0x%x !\n", ret); } exit: fclose(gyro_bin_fp); fclose(gyro_txt_fp); return XMEDIA_NULL; } xmedia_s32 sample_msensor_parse_data(xmedia_void) { FILE *file = fopen(GYRO_BIN_FILE, "rb"); FILE *gyro_parse_fp = XMEDIA_NULL; gyro_parse_fp = fopen(GYRO_PARSE_FILE, "w+"); if (gyro_parse_fp == XMEDIA_NULL) { SAMPLE_PRT("Error: cannot open imu data\n"); return XMEDIA_NULL; } if (file == NULL) { fclose(gyro_parse_fp); perror("无法打开文件"); return 1; } // 获取文件大小 fseek(file, 0, SEEK_END); long file_size = ftell(file); fseek(file, 0, SEEK_SET); // 分配内存 unsigned char *buffer = (unsigned char*)malloc(file_size + 1); if (buffer == NULL) { perror("内存分配失败"); fclose(file); return 1; } // 读取整个文件 size_t bytes_read = fread(buffer, 1, file_size, file); buffer[bytes_read] = '\0'; // 添加字符串结束符 fclose(file); parse_stream_sei_with_emulation_prevention(buffer, bytes_read, 1, gyro_parse_fp); fclose(gyro_parse_fp); // 清理 free(buffer); return 0; } xmedia_s32 sample_msensor_start_dump_data(xmedia_s32 dev) { memset(&g_get_data_info[dev], 0, sizeof(msensor_get_data_info)); g_get_data_info[dev].thread_start = XMEDIA_TRUE; g_get_data_info[dev].data_type = XMEDIA_MSENSOR_DATA_TYPE_GYRO; g_get_data_info[dev].time_intval = 4; g_get_data_info[dev].msensor_dev = dev; pthread_create(&g_msensor_pid[dev], 0, msensor_get_data_thread, (xmedia_void *)&g_get_data_info[dev]); return XMEDIA_SUCCESS; } xmedia_s32 sample_msensor_stop_dump_data(xmedia_s32 dev) { if (XMEDIA_TRUE == g_get_data_info[dev].thread_start) { g_get_data_info[dev].thread_start = XMEDIA_FALSE; if (g_msensor_pid[dev] > 0) { pthread_join(g_msensor_pid[dev], 0); } } return XMEDIA_SUCCESS; } xmedia_s32 sample_msensor_init(xmedia_s32 dev_cnt, xmedia_s32 *dev) { xmedia_s32 i; xmedia_s32 ret = XMEDIA_SUCCESS; xmedia_msensor_init(); for (i = 0; i < dev_cnt; i++) { ret = msensor_start(dev[i]); } return ret; } xmedia_void sample_msensor_exit(xmedia_s32 dev_cnt, xmedia_s32 *dev) { xmedia_s32 i; for (i = 0; i < dev_cnt; i++) { msensor_stop(dev[i]); } xmedia_msensor_exit(); } xmedia_s32 sample_venc_h265_msensor(xmedia_bool set_roi) { xmedia_s32 ret = XMEDIA_SUCCESS; xmedia_s32 blk_size = 0; xmedia_video_size pic_size = { 0 }; xmedia_video_size sub_pic_size = { 0 }; sample_comm_video_param video_param = { 0 }; sample_sys_config sys_config = { 0 }; xmedia_s32 msensor_dev = 0; xmedia_s32 vi_dev = 0; xmedia_s32 vi_pipe = 0; xmedia_s32 vi_chn = 0; sample_vi_config vi_config = { 0 }; xmedia_s32 sensor_type = sample_msensor_sensor_type[0]; xmedia_u32 framerate = 0; vi_sensor_info sensor_info = { 0 }; sample_isp_param isp_param = { 0 }; xmedia_isp_config isp_config = { 0 }; xmedia_bool mirror = XMEDIA_FALSE; xmedia_bool flip = XMEDIA_FALSE; xmedia_s32 vpss_chnl = 0; xmedia_s32 vpss_pipe = 0; xmedia_s32 vpss_ichn = 0; xmedia_s32 vpss_ochn[1] = { 0 }; sample_vpss_config vpss_config = { 0 }; xmedia_video_size vpss_ochn_size[VPSS_MAX_OCHN_NUM] = { 0 }; xmedia_s32 venc_chnl = 0; xmedia_s32 venc_chn[1] = { 0 }; xmedia_s32 venc_chn_cnt = 1; sample_venc_config venc_config = { 0 }; xmedia_venc_gop_mode gop_mode; video_param.video_fmt = XMEDIA_VIDEO_FMT_LINEAR; video_param.pixel_fmt = XMEDIA_VIDEO_PIXEL_FMT_YVU_SEMIPLANAR_420; video_param.data_width = XMEDIA_VIDEO_DATA_WIDTH_8; video_param.compress_mode = XMEDIA_VIDEO_COMPRESS_MODE_NONE; sample_comm_vi_get_sensor_info(sensor_type, &sensor_info); sample_comm_vi_get_framerate_by_sensor(sensor_type, &framerate); gop_mode = VENC_GOPMODE_NORMALP; // sys init sys_config.sys_conf.pipe_mode[vi_pipe].vicap_viproc_mode = XMEDIA_WORK_MODE_OFFLINE; sys_config.sys_conf.pipe_mode[vi_pipe].viproc_vpss_mode = XMEDIA_WORK_MODE_OFFLINE; sys_config.sys_conf.pipe_mode[vi_pipe].gdc_vpss_mode = XMEDIA_WORK_MODE_OFFLINE; sys_config.vb_conf.max_pool_cnt = 25; pic_size.width = sensor_info.width; pic_size.height = sensor_info.height; blk_size = sample_comm_sys_get_buffer_size(pic_size, video_param.video_fmt, sensor_info.pixel_format, sensor_info.bit_width, video_param.compress_mode); sys_config.vb_conf.common_pool[0].block_size = blk_size; sys_config.vb_conf.common_pool[0].block_cnt = 2; blk_size = sample_comm_sys_get_buffer_size(pic_size, video_param.video_fmt, video_param.pixel_fmt, video_param.data_width, video_param.compress_mode); sys_config.vb_conf.common_pool[1].block_size = blk_size; sys_config.vb_conf.common_pool[1].block_cnt = 4; sub_pic_size.width = 640; sub_pic_size.height = 480; blk_size = sample_comm_sys_get_buffer_size(sub_pic_size, video_param.video_fmt, video_param.pixel_fmt, video_param.data_width, video_param.compress_mode); sys_config.vb_conf.common_pool[2].block_size = blk_size; sys_config.vb_conf.common_pool[2].block_cnt = 2; sys_config.vb_conf.supplement_config = 1; ret = sample_msensor_sys_init(&sys_config); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("sys init failed !\n"); return ret; } sample_msensor_init(1, &msensor_dev); vi_config.dev_info[vi_dev].dev_en = XMEDIA_TRUE; vi_config.dev_info[vi_dev].dev_no = vi_dev; vi_config.dev_info[vi_dev].sensor_type = sensor_type; vi_config.pipe_info[vi_pipe].pipe_en = XMEDIA_TRUE; vi_config.pipe_info[vi_pipe].pipe_no = vi_pipe; vi_config.pipe_info[vi_pipe].chn_info[vi_chn].chn_en = XMEDIA_TRUE; vi_config.pipe_info[vi_pipe].chn_info[vi_chn].chn_no = vi_chn; vi_config.dev_bind_pipe[vi_dev].pipe[0] = vi_pipe; vi_config.dev_bind_pipe[vi_dev].pipe[1] = -1; isp_config.fps = framerate; isp_config.mode_config.work_mode = XMEDIA_ISP_WORK_MODE_MASTER; isp_config.mode_config.master_mode.blend_stat_enable = XMEDIA_FALSE; isp_config.mode_config.master_mode.slave_num = 0; isp_config.pixel_fmt = sensor_info.pixel_format; isp_config.size.height = sensor_info.height; isp_config.size.width = sensor_info.width; isp_config.wdr_mode = sensor_info.wdr_mode; // isp pipe init isp_param.pipe[vi_pipe] = vi_pipe; isp_param.isp_info[vi_pipe].isp_pipe_en = XMEDIA_TRUE; isp_param.isp_info[vi_pipe].isp_sensor_en = XMEDIA_TRUE; isp_param.isp_info[vi_pipe].sensor_type = sensor_type; isp_param.isp_info[vi_pipe].mirror = mirror; isp_param.isp_info[vi_pipe].flip = flip; memcpy(&(isp_param.isp_info[vi_pipe].isp_config), &isp_config, sizeof(xmedia_isp_config)); // isp init ret = sample_comm_isp_init(&isp_param, &vi_config); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("isp init failed!\n"); goto exit0; } // vi start ret = sample_comm_vi_start(&vi_config, &video_param); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("start vi failed!\n"); goto exit1; } // isp start ret = sample_comm_isp_start(&isp_param); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("start isp failed!\n"); goto exit2; } // vpss config ret = sample_comm_vpss_get_default_pipe_cfg(&vpss_config.pipe_info[vpss_pipe].pipe_config, pic_size, &video_param); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("get default pipe cfg failed !\n"); goto exit2; } vpss_ochn_size[0].width = sensor_info.width; vpss_ochn_size[0].height = sensor_info.height; vpss_config.pipe_info[vpss_pipe].pipe_en = XMEDIA_TRUE; vpss_config.pipe_info[vpss_pipe].pipe_no = vpss_pipe; vpss_chnl = vpss_ochn[0]; vpss_config.pipe_info[vpss_pipe].chn_info[vpss_chnl].chn_en = XMEDIA_TRUE; vpss_config.pipe_info[vpss_pipe].chn_info[vpss_chnl].chn_no = vpss_ochn[0]; ret = sample_comm_vpss_get_default_ochn_cfg(&vpss_config.pipe_info[vpss_pipe].chn_info[vpss_chnl].chn_config, vpss_ochn_size[vpss_chnl], &video_param); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("get default pipe cfg failed !\n"); goto exit2; } vpss_config.pipe_info[vpss_pipe].chn_info[vpss_chnl].chn_config.depth = 0; // vpss start ret = sample_comm_vpss_start(&vpss_config); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("vpss start failed !\n"); goto exit2; } ret = sample_comm_sys_vi_bind_vpss(vi_pipe, vi_chn, vpss_pipe, vpss_ichn); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("vi bind vpss failed !\n"); goto exit3; } venc_chnl = venc_chn[0]; venc_config.chn_info[venc_chnl].venc_en = XMEDIA_TRUE; venc_config.chn_info[venc_chnl].venc_chn = venc_chnl; venc_config.chn_info[venc_chnl].payload_type = PT_H265; venc_config.chn_info[venc_chnl].rc_mode = VENC_RC_MODE_H265CBR; venc_config.chn_info[venc_chnl].venc_gop_attr.gop_mode = gop_mode; sample_comm_venc_get_default_chn_info(vpss_ochn_size[0], framerate, &venc_config.chn_info[venc_chnl]); ret = sample_comm_venc_start(&venc_config); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("venc start failed !\n"); goto exit4; } if (set_roi == XMEDIA_TRUE) { ret = sample_comm_venc_set_roi(venc_chn, venc_chn_cnt); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("venc start get stream failed !\n"); goto exit4; } } ret = sample_comm_sys_vpss_bind_venc(vpss_pipe, vpss_ochn[0], venc_chn[0]); if (ret != XMEDIA_SUCCESS) { SAMPLE_PRT("vpss bind venc failed !\n"); goto exit5; } sample_msensor_start_dump_data(msensor_dev); PAUSE(g_force_exit); sample_msensor_stop_dump_data(msensor_dev); sample_comm_sys_vpss_unbind_venc(vpss_pipe, vpss_ochn[0], venc_chn[0]); exit5: sample_comm_venc_stop(&venc_config); exit4: sample_comm_sys_vi_unbind_vpss(vi_pipe, vi_chn, vpss_pipe, vpss_ichn); exit3: sample_comm_vpss_stop(&vpss_config); exit2: sample_comm_isp_stop(&isp_param); exit1: sample_comm_vi_stop(&vi_config); exit0: sample_comm_isp_exit(&isp_param); sample_msensor_exit(1, &msensor_dev); sample_msensor_sys_exit(); return ret; } int main(int argc,char **argv) { xmedia_s32 ret = XMEDIA_SUCCESS; xmedia_s32 index = 0; xmedia_bool set_roi = XMEDIA_FALSE; signal(SIGINT, sample_msensor_handle_sig); signal(SIGTERM, sample_msensor_handle_sig); if (argc < 2) { sample_msensor_usage(argv[0]); return 0; } index = atoi(argv[1]); if (argc == 2) { switch (index) { case 0: ret = sample_venc_h265_msensor(set_roi); break; case 1: sample_msensor_parse_data(); break; default: sample_msensor_usage(argv[0]); return 0; } } if (XMEDIA_SUCCESS == ret) { SAMPLE_PRT("program exit normally!\n"); } else { SAMPLE_PRT("program exit abnormally!\n"); } return 0; }