Loading camogm.c +0 −16 Original line number Diff line number Diff line Loading @@ -490,9 +490,6 @@ int sendImageFrame(camogm_state *state) int * ifp_this = (int*)&(state->this_frame_params[state->port_num]); int fp; int port = state->port_num; unsigned char app15[64] = {0xff, 0xef}; int app15_pos = 0; int stuffing; // This is probably needed only for Quicktime (not to exceed already allocated frame index) if (state->frameno >= (state->max_frames)) { Loading Loading @@ -606,28 +603,15 @@ int sendImageFrame(camogm_state *state) state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port]; state->packetchunks[state->chunk_index ].bytes = state->exifSize[port]; state->packetchunks[state->chunk_index++].chunk = state->ed[port]; app15_pos = state->chunk_index++; state->packetchunks[state->chunk_index ].bytes = state->head_size[port] - 2; state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[port][2]); stuffing = 32 - (2 + state->exifSize[port] + state->head_size[port]) % 32; } else { D3(fprintf(debug_file, "_8_")); app15_pos = state->chunk_index++; state->packetchunks[state->chunk_index ].bytes = state->head_size[port]; state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port]; stuffing = 32 - (state->head_size[port] % 32); } D3(fprintf(debug_file, "_9_")); // align JPEG (+ Exif) header to 32 bytes by adding APP15 marker if (stuffing < 4) { stuffing += 32; } app15[3] = stuffing - 2; state->packetchunks[app15_pos].bytes = stuffing; state->packetchunks[app15_pos].chunk = app15; fprintf(debug_file, "\nadd %d stuffing bytes as APP15\n", stuffing); /* JPEG image data may be split in two segments (rolled over buffer end) - process both variants */ if ((state->cirbuf_rp[port] + state->jpeg_len) > state->circ_buff_size[port]) { // two segments /* copy from the beginning of the frame to the end of the buffer */ Loading camogm.h +1 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,7 @@ typedef struct { pthread_t tid; volatile int thread_state; unsigned char *disk_mmap; int sysfs_fd; } rawdev_buffer; /** Loading camogm_jpeg.c +47 −101 Original line number Diff line number Diff line Loading @@ -31,10 +31,21 @@ #include "camogm_jpeg.h" /** The position of size field in copy buffer */ #define VECTOR_SZ_POS 0 /** The position of vector pointer field in copy buffer */ #define POINTER_POS 1 /* this should be in system includes */ #define DRV_CMD_WRITE (1 << 0) #define DRV_CMD_FINISH (1 << 1) #define DRV_CMD_EXIF (1 << 2) struct frame_data { unsigned int sensor_port; int cirbuf_ptr; int jpeg_len; int meta_index; int cmd; }; const char sysfs_fname[] = "/sys/devices/soc0/amba@0/80000000.elphel-ahci/write"; /* end of system includes */ int camogm_init_jpeg(camogm_state *state) { Loading Loading @@ -84,11 +95,14 @@ int camogm_start_jpeg(camogm_state *state) D3(fprintf(debug_file, "Open raw device %s; start_pos = %llu, end_pos = %llu, curr_pos = %llu\n", state->rawdev.rawdev_path, state->rawdev.start_pos, state->rawdev.end_pos, state->rawdev.curr_pos_w)); lseek64(state->rawdev.rawdev_fd, state->rawdev.curr_pos_w, SEEK_SET); state->rawdev.sysfs_fd = open(sysfs_fname, O_WRONLY); if (state->rawdev.sysfs_fd < 0) { D0(fprintf(debug_file, "Error opening sysfs file: %s\n", sysfs_fname)); return -CAMOGM_FRAME_FILE_ERR; } } } fprintf(debug_file, "Start recording buffer usage statistics\n"); fprintf(debug_file, "\"JPEG write time, us\",\"free buff, %\",\"free buff, %\",\"free buff, %\",\"free buff, %\"\n"); return 0; } Loading @@ -111,8 +125,8 @@ int camogm_frame_jpeg(camogm_state *state) int port = state->port_num; uint32_t start_time, end_time; off_t free_space; struct frame_data fdata = {0}; start_time = lseek(state->fd_circ[0], LSEEK_CIRC_UTIME, SEEK_END); if (!state->rawdev_op) { l = 0; for (i = 0; i < (state->chunk_index) - 1; i++) { Loading @@ -134,104 +148,23 @@ int camogm_frame_jpeg(camogm_state *state) } close(state->ivf); } else { // D3(fprintf(debug_file, "\n%s: current pointers start_pos = %llu, end_pos = %llu, curr_pos = %llu, data in buffer %d\n", __func__, // state->rawdev.start_pos, state->rawdev.end_pos, state->rawdev.curr_pos_w, l)); // split_index = -1; // for (int i = 0, total_len = 0; i < state->chunk_index - 1; i++) { // total_len += state->packetchunks[i + 1].bytes; // if (total_len + state->rawdev.curr_pos_w > state->rawdev.end_pos) { // split_index = i; // chunks_used++; // D3(fprintf(debug_file, "\n>>> raw storage roll over detected\n")); // break; // } // } // k = 0; // l = 0; // for (int i = 0; i < chunks_used; i++) { // ++k; // if (i == split_index) { // // one of the chunks rolls over the end of the raw storage, split it into two segments and // // use additional chunk in chunks_iovec for this additional segment // split_cntr = state->rawdev.end_pos - (l + state->rawdev.curr_pos_w); // split_ptr = state->packetchunks[k].chunk + split_cntr; // // D3(fprintf(debug_file, "Splitting chunk #%d: total chunk size = %ld, start address = 0x%p\n", // i, state->packetchunks[k].bytes, state->packetchunks[k].chunk)); // // // be careful with indexes here // chunks_iovec[i].iov_base = state->packetchunks[k].chunk; // chunks_iovec[i].iov_len = split_cntr; // l += chunks_iovec[i].iov_len; // chunks_iovec[++i].iov_base = split_ptr + 1; // chunks_iovec[i].iov_len = state->packetchunks[k].bytes - split_cntr; // l += chunks_iovec[i].iov_len; // } else { // chunks_iovec[i].iov_base = state->packetchunks[k].chunk; // chunks_iovec[i].iov_len = state->packetchunks[k].bytes; // l += chunks_iovec[i].iov_len; // } // } // // if (split_index < 0) { // iovlen = writev(state->rawdev.rawdev_fd, chunks_iovec, chunks_used); // } else { // iovlen = writev(state->rawdev.rawdev_fd, chunks_iovec, split_index + 1); // fprintf(debug_file, "write first part: split_index = %d, %d bytes written\n", split_index, iovlen); // if (lseek64(state->rawdev.rawdev_fd, state->rawdev.start_pos, SEEK_SET) != state->rawdev.start_pos) { // perror(__func__); // D0(fprintf(debug_file, "error positioning file pointer to the beginning of raw device\n")); // return -CAMOGM_FRAME_FILE_ERR; // } // state->rawdev.overrun++; // iovlen += writev(state->rawdev.rawdev_fd, &chunks_iovec[split_index + 1], chunks_used - split_index); // fprintf(debug_file, "write second part: split_index + 1 = %d, chunks_used - split_index = %d, %d bytes written in total\n", // split_index + 1, chunks_used - split_index, iovlen); // } // if (iovlen < l) { // j = errno; // perror(__func__); // D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l)); // return -CAMOGM_FRAME_FILE_ERR; // } // state->rawdev.curr_pos_w += l; // if (state->rawdev.curr_pos_w > state->rawdev.end_pos) // state->rawdev.curr_pos_w = state->rawdev.curr_pos_w - state->rawdev.end_pos + state->rawdev.start_pos; // D6(fprintf(debug_file, "%d bytes written, curr_pos = %llu\n", l, state->rawdev.curr_pos_w)); uint8_t buff[128] = {0}; uint32_t *buff_p = (uint32_t *)buff; uint8_t *pos; int fd = open("/sys/devices/soc0/amba@0/80000000.elphel-ahci/write", O_WRONLY); if (fd < 0) { perror("ERROR: can not open test_write file\n"); return -CAMOGM_FRAME_FILE_ERR; } buff_p[VECTOR_SZ_POS] = state->chunk_index - 1; fprintf(debug_file, "dump iovect array\n"); for (int i = 0; i < state->chunk_index - 1; i++) { fprintf(debug_file, "ptr: %p, length: %ld\n", state->packetchunks[i + 1].chunk, state->packetchunks[i + 1].bytes); } buff_p[POINTER_POS] = (uint32_t) &state->packetchunks[1]; if (write(fd, buff, 8) < 0) { perror("Can not pass IO vector to driver:"); } close(fd); } end_time = lseek(state->fd_circ[0], LSEEK_CIRC_UTIME, SEEK_END); // fprintf(debug_file, "JPEG write time = %u us\n", end_time - start_time); // fprintf(debug_file, "Free space in buffers: "); // for (int i = 0; i < SENSOR_PORTS; i++) { // int buff_size, jpeg_pos; // jpeg_pos = lseek(state->fd_circ[i], 0 , SEEK_CUR); // free_space = lseek(state->fd_circ[i], LSEEK_CIRC_FREE, SEEK_END); // buff_size = lseek(state->fd_circ[i], 0, SEEK_END); // lseek(state->fd_circ[i], jpeg_pos, SEEK_SET); // fprintf(debug_file, "chn %d = %ld ", // i, // (int)(100 * (float)free_space / (float)buff_size)); // } // fprintf(debug_file, "\b\n"); fdata.sensor_port = port; fdata.cirbuf_ptr = state->cirbuf_rp[port]; fdata.jpeg_len = state->jpeg_len; if (state->exif) { fdata.meta_index = state->this_frame_params[port].meta_index; fdata.cmd |= DRV_CMD_EXIF; } fdata.cmd |= DRV_CMD_WRITE; if (write(state->rawdev.sysfs_fd, &fdata, sizeof(struct frame_data)) < 0) { D0(fprintf(debug_file, "Can not pass IO vector to driver: %s\n", strerror(errno))); return -CAMOGM_FRAME_FILE_ERR; } } return 0; } Loading @@ -246,9 +179,22 @@ int camogm_frame_jpeg(camogm_state *state) int camogm_end_jpeg(camogm_state *state) { int ret = 0; struct frame_data fdata = {0}; if (state->rawdev_op) { ret = close(state->rawdev.rawdev_fd); D0(fprintf(debug_file, "Closing raw device %s\n", state->rawdev.rawdev_path)); ret = close(state->rawdev.rawdev_fd); if (ret == -1) D0(fprintf(debug_file, "Error: %s\n", strerror(errno))); fdata.cmd = DRV_CMD_FINISH; if (write(state->rawdev.sysfs_fd, &fdata, sizeof(struct frame_data)) < 0) { D0(fprintf(debug_file, "Error sending 'finish' command to driver\n")); } D0(fprintf(debug_file, "Closing sysfs file %s\n", sysfs_fname)); ret = close(state->rawdev.sysfs_fd); if (ret == -1) D0(fprintf(debug_file, "Error: %s\n", strerror(errno))); } return ret; } Loading
camogm.c +0 −16 Original line number Diff line number Diff line Loading @@ -490,9 +490,6 @@ int sendImageFrame(camogm_state *state) int * ifp_this = (int*)&(state->this_frame_params[state->port_num]); int fp; int port = state->port_num; unsigned char app15[64] = {0xff, 0xef}; int app15_pos = 0; int stuffing; // This is probably needed only for Quicktime (not to exceed already allocated frame index) if (state->frameno >= (state->max_frames)) { Loading Loading @@ -606,28 +603,15 @@ int sendImageFrame(camogm_state *state) state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port]; state->packetchunks[state->chunk_index ].bytes = state->exifSize[port]; state->packetchunks[state->chunk_index++].chunk = state->ed[port]; app15_pos = state->chunk_index++; state->packetchunks[state->chunk_index ].bytes = state->head_size[port] - 2; state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[port][2]); stuffing = 32 - (2 + state->exifSize[port] + state->head_size[port]) % 32; } else { D3(fprintf(debug_file, "_8_")); app15_pos = state->chunk_index++; state->packetchunks[state->chunk_index ].bytes = state->head_size[port]; state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port]; stuffing = 32 - (state->head_size[port] % 32); } D3(fprintf(debug_file, "_9_")); // align JPEG (+ Exif) header to 32 bytes by adding APP15 marker if (stuffing < 4) { stuffing += 32; } app15[3] = stuffing - 2; state->packetchunks[app15_pos].bytes = stuffing; state->packetchunks[app15_pos].chunk = app15; fprintf(debug_file, "\nadd %d stuffing bytes as APP15\n", stuffing); /* JPEG image data may be split in two segments (rolled over buffer end) - process both variants */ if ((state->cirbuf_rp[port] + state->jpeg_len) > state->circ_buff_size[port]) { // two segments /* copy from the beginning of the frame to the end of the buffer */ Loading
camogm.h +1 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,7 @@ typedef struct { pthread_t tid; volatile int thread_state; unsigned char *disk_mmap; int sysfs_fd; } rawdev_buffer; /** Loading
camogm_jpeg.c +47 −101 Original line number Diff line number Diff line Loading @@ -31,10 +31,21 @@ #include "camogm_jpeg.h" /** The position of size field in copy buffer */ #define VECTOR_SZ_POS 0 /** The position of vector pointer field in copy buffer */ #define POINTER_POS 1 /* this should be in system includes */ #define DRV_CMD_WRITE (1 << 0) #define DRV_CMD_FINISH (1 << 1) #define DRV_CMD_EXIF (1 << 2) struct frame_data { unsigned int sensor_port; int cirbuf_ptr; int jpeg_len; int meta_index; int cmd; }; const char sysfs_fname[] = "/sys/devices/soc0/amba@0/80000000.elphel-ahci/write"; /* end of system includes */ int camogm_init_jpeg(camogm_state *state) { Loading Loading @@ -84,11 +95,14 @@ int camogm_start_jpeg(camogm_state *state) D3(fprintf(debug_file, "Open raw device %s; start_pos = %llu, end_pos = %llu, curr_pos = %llu\n", state->rawdev.rawdev_path, state->rawdev.start_pos, state->rawdev.end_pos, state->rawdev.curr_pos_w)); lseek64(state->rawdev.rawdev_fd, state->rawdev.curr_pos_w, SEEK_SET); state->rawdev.sysfs_fd = open(sysfs_fname, O_WRONLY); if (state->rawdev.sysfs_fd < 0) { D0(fprintf(debug_file, "Error opening sysfs file: %s\n", sysfs_fname)); return -CAMOGM_FRAME_FILE_ERR; } } } fprintf(debug_file, "Start recording buffer usage statistics\n"); fprintf(debug_file, "\"JPEG write time, us\",\"free buff, %\",\"free buff, %\",\"free buff, %\",\"free buff, %\"\n"); return 0; } Loading @@ -111,8 +125,8 @@ int camogm_frame_jpeg(camogm_state *state) int port = state->port_num; uint32_t start_time, end_time; off_t free_space; struct frame_data fdata = {0}; start_time = lseek(state->fd_circ[0], LSEEK_CIRC_UTIME, SEEK_END); if (!state->rawdev_op) { l = 0; for (i = 0; i < (state->chunk_index) - 1; i++) { Loading @@ -134,104 +148,23 @@ int camogm_frame_jpeg(camogm_state *state) } close(state->ivf); } else { // D3(fprintf(debug_file, "\n%s: current pointers start_pos = %llu, end_pos = %llu, curr_pos = %llu, data in buffer %d\n", __func__, // state->rawdev.start_pos, state->rawdev.end_pos, state->rawdev.curr_pos_w, l)); // split_index = -1; // for (int i = 0, total_len = 0; i < state->chunk_index - 1; i++) { // total_len += state->packetchunks[i + 1].bytes; // if (total_len + state->rawdev.curr_pos_w > state->rawdev.end_pos) { // split_index = i; // chunks_used++; // D3(fprintf(debug_file, "\n>>> raw storage roll over detected\n")); // break; // } // } // k = 0; // l = 0; // for (int i = 0; i < chunks_used; i++) { // ++k; // if (i == split_index) { // // one of the chunks rolls over the end of the raw storage, split it into two segments and // // use additional chunk in chunks_iovec for this additional segment // split_cntr = state->rawdev.end_pos - (l + state->rawdev.curr_pos_w); // split_ptr = state->packetchunks[k].chunk + split_cntr; // // D3(fprintf(debug_file, "Splitting chunk #%d: total chunk size = %ld, start address = 0x%p\n", // i, state->packetchunks[k].bytes, state->packetchunks[k].chunk)); // // // be careful with indexes here // chunks_iovec[i].iov_base = state->packetchunks[k].chunk; // chunks_iovec[i].iov_len = split_cntr; // l += chunks_iovec[i].iov_len; // chunks_iovec[++i].iov_base = split_ptr + 1; // chunks_iovec[i].iov_len = state->packetchunks[k].bytes - split_cntr; // l += chunks_iovec[i].iov_len; // } else { // chunks_iovec[i].iov_base = state->packetchunks[k].chunk; // chunks_iovec[i].iov_len = state->packetchunks[k].bytes; // l += chunks_iovec[i].iov_len; // } // } // // if (split_index < 0) { // iovlen = writev(state->rawdev.rawdev_fd, chunks_iovec, chunks_used); // } else { // iovlen = writev(state->rawdev.rawdev_fd, chunks_iovec, split_index + 1); // fprintf(debug_file, "write first part: split_index = %d, %d bytes written\n", split_index, iovlen); // if (lseek64(state->rawdev.rawdev_fd, state->rawdev.start_pos, SEEK_SET) != state->rawdev.start_pos) { // perror(__func__); // D0(fprintf(debug_file, "error positioning file pointer to the beginning of raw device\n")); // return -CAMOGM_FRAME_FILE_ERR; // } // state->rawdev.overrun++; // iovlen += writev(state->rawdev.rawdev_fd, &chunks_iovec[split_index + 1], chunks_used - split_index); // fprintf(debug_file, "write second part: split_index + 1 = %d, chunks_used - split_index = %d, %d bytes written in total\n", // split_index + 1, chunks_used - split_index, iovlen); // } // if (iovlen < l) { // j = errno; // perror(__func__); // D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l)); // return -CAMOGM_FRAME_FILE_ERR; // } // state->rawdev.curr_pos_w += l; // if (state->rawdev.curr_pos_w > state->rawdev.end_pos) // state->rawdev.curr_pos_w = state->rawdev.curr_pos_w - state->rawdev.end_pos + state->rawdev.start_pos; // D6(fprintf(debug_file, "%d bytes written, curr_pos = %llu\n", l, state->rawdev.curr_pos_w)); uint8_t buff[128] = {0}; uint32_t *buff_p = (uint32_t *)buff; uint8_t *pos; int fd = open("/sys/devices/soc0/amba@0/80000000.elphel-ahci/write", O_WRONLY); if (fd < 0) { perror("ERROR: can not open test_write file\n"); return -CAMOGM_FRAME_FILE_ERR; } buff_p[VECTOR_SZ_POS] = state->chunk_index - 1; fprintf(debug_file, "dump iovect array\n"); for (int i = 0; i < state->chunk_index - 1; i++) { fprintf(debug_file, "ptr: %p, length: %ld\n", state->packetchunks[i + 1].chunk, state->packetchunks[i + 1].bytes); } buff_p[POINTER_POS] = (uint32_t) &state->packetchunks[1]; if (write(fd, buff, 8) < 0) { perror("Can not pass IO vector to driver:"); } close(fd); } end_time = lseek(state->fd_circ[0], LSEEK_CIRC_UTIME, SEEK_END); // fprintf(debug_file, "JPEG write time = %u us\n", end_time - start_time); // fprintf(debug_file, "Free space in buffers: "); // for (int i = 0; i < SENSOR_PORTS; i++) { // int buff_size, jpeg_pos; // jpeg_pos = lseek(state->fd_circ[i], 0 , SEEK_CUR); // free_space = lseek(state->fd_circ[i], LSEEK_CIRC_FREE, SEEK_END); // buff_size = lseek(state->fd_circ[i], 0, SEEK_END); // lseek(state->fd_circ[i], jpeg_pos, SEEK_SET); // fprintf(debug_file, "chn %d = %ld ", // i, // (int)(100 * (float)free_space / (float)buff_size)); // } // fprintf(debug_file, "\b\n"); fdata.sensor_port = port; fdata.cirbuf_ptr = state->cirbuf_rp[port]; fdata.jpeg_len = state->jpeg_len; if (state->exif) { fdata.meta_index = state->this_frame_params[port].meta_index; fdata.cmd |= DRV_CMD_EXIF; } fdata.cmd |= DRV_CMD_WRITE; if (write(state->rawdev.sysfs_fd, &fdata, sizeof(struct frame_data)) < 0) { D0(fprintf(debug_file, "Can not pass IO vector to driver: %s\n", strerror(errno))); return -CAMOGM_FRAME_FILE_ERR; } } return 0; } Loading @@ -246,9 +179,22 @@ int camogm_frame_jpeg(camogm_state *state) int camogm_end_jpeg(camogm_state *state) { int ret = 0; struct frame_data fdata = {0}; if (state->rawdev_op) { ret = close(state->rawdev.rawdev_fd); D0(fprintf(debug_file, "Closing raw device %s\n", state->rawdev.rawdev_path)); ret = close(state->rawdev.rawdev_fd); if (ret == -1) D0(fprintf(debug_file, "Error: %s\n", strerror(errno))); fdata.cmd = DRV_CMD_FINISH; if (write(state->rawdev.sysfs_fd, &fdata, sizeof(struct frame_data)) < 0) { D0(fprintf(debug_file, "Error sending 'finish' command to driver\n")); } D0(fprintf(debug_file, "Closing sysfs file %s\n", sysfs_fname)); ret = close(state->rawdev.sysfs_fd); if (ret == -1) D0(fprintf(debug_file, "Error: %s\n", strerror(errno))); } return ret; }