Commit 8eee4caa authored by Andrey Filippov's avatar Andrey Filippov

working on fast write

parent e4468ac7
...@@ -278,7 +278,7 @@ void camogm_init(camogm_state *state, char *pipe_name, uint16_t port_num) ...@@ -278,7 +278,7 @@ void camogm_init(camogm_state *state, char *pipe_name, uint16_t port_num)
state->rawdev.curr_pos_w = state->rawdev.start_pos; state->rawdev.curr_pos_w = state->rawdev.start_pos;
state->rawdev.curr_pos_r = state->rawdev.start_pos; state->rawdev.curr_pos_r = state->rawdev.start_pos;
state->active_chn = ALL_CHN_INACTIVE; state->active_chn = ALL_CHN_INACTIVE;
state->rawdev.mmap_default_size = MMAP_CHUNK_SIZE; state->rawdev.mmap_default_size = MMAP_CHUNK_SIZE; // only used for camogm_read
state->sock_port = port_num; state->sock_port = port_num;
// state->writer_params.data_ready = false; // state->writer_params.data_ready = false;
...@@ -337,6 +337,7 @@ int camogm_start(camogm_state *state) ...@@ -337,6 +337,7 @@ int camogm_start(camogm_state *state)
{ {
int timestamp_start; int timestamp_start;
int rslt; int rslt;
int dummy;
int next_metadata_start, next_jpeg_len, fp; int next_metadata_start, next_jpeg_len, fp;
int port = state->port_num; int port = state->port_num;
...@@ -503,7 +504,7 @@ int camogm_start(camogm_state *state) ...@@ -503,7 +504,7 @@ int camogm_start(camogm_state *state)
} }
// and read it // and read it
lseek(state->fd_head[chn], 0, 0); lseek(state->fd_head[chn], 0, 0);
read(state->fd_head[chn], state->jpegHeader[chn], state->head_size[chn]); dummy=read(state->fd_head[chn], state->jpegHeader[chn], state->head_size[chn]); //?
// Restore read pointer to the original (now there may be no frame ready there yet) // Restore read pointer to the original (now there may be no frame ready there yet)
lseek(state->fd_circ[chn], state->cirbuf_rp[chn], SEEK_SET); lseek(state->fd_circ[chn], state->cirbuf_rp[chn], SEEK_SET);
state->image_size[chn] = 0; state->image_size[chn] = 0;
...@@ -661,31 +662,32 @@ int sendImageFrame(camogm_state *state) ...@@ -661,31 +662,32 @@ int sendImageFrame(camogm_state *state)
// prepare a packet to be sent (a lst of memory chunks) // prepare a packet to be sent (a lst of memory chunks)
state->chunk_index = 0; state->chunk_index = 0;
state->packetchunks[state->chunk_index ].bytes = 1; state->packetchunks[state->chunk_index ].bytes = 1;
state->packetchunks[state->chunk_index++].chunk = &frame_packet_type; state->packetchunks[state->chunk_index++].chunk = &frame_packet_type; // [0]
if (state->exif > 0) { // insert Exif/Tiff if (state->exif > 0) { // insert Exif/Tiff
D4(fprintf(debug_file, "_7_")); D4(fprintf(debug_file, "_7_"));
if (state->this_frame_params[port].color == COLORMODE_RAW) { // Tiff if (state->this_frame_params[port].color == COLORMODE_RAW) { // Tiff
D4(fprintf(debug_file, "_8a_")); D4(fprintf(debug_file, "_8a_"));
state->packetchunks[state->chunk_index ].bytes = state->exifSize[port]; // Tiff Header length state->packetchunks[state->chunk_index ].bytes = state->exifSize[port]; // Tiff Header length [1]
state->packetchunks[state->chunk_index++].chunk = state->ed[port]; // Tiff Header state->packetchunks[state->chunk_index++].chunk = state->ed[port]; // Tiff Header
} else { // JPEG/JP4 } else { // JPEG/JP4
D4(fprintf(debug_file, "_8b_")); D4(fprintf(debug_file, "_8b_"));
state->packetchunks[state->chunk_index ].bytes = 2; state->packetchunks[state->chunk_index ].bytes = 2;
state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port]; state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port]; // [1] jpeg marker
state->packetchunks[state->chunk_index ].bytes = state->exifSize[port]; state->packetchunks[state->chunk_index ].bytes = state->exifSize[port];
state->packetchunks[state->chunk_index++].chunk = state->ed[port]; state->packetchunks[state->chunk_index++].chunk = state->ed[port]; // [2] exif
state->packetchunks[state->chunk_index ].bytes = state->head_size[port] - 2; state->packetchunks[state->chunk_index ].bytes = state->head_size[port] - 2;
state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[port][2]); state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[port][2]); // [3] rest of jpeg header
} }
} else { } else {
D4(fprintf(debug_file, "_8_")); D4(fprintf(debug_file, "_8_"));
state->packetchunks[state->chunk_index ].bytes = state->head_size[port]; state->packetchunks[state->chunk_index ].bytes = state->head_size[port];
state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port]; state->packetchunks[state->chunk_index++].chunk = state->jpegHeader[port]; // [1] all of jpeg marker
} }
D4(fprintf(debug_file, "_9_")); D4(fprintf(debug_file, "_9_"));
/* Jpeg/Tiff image data may be split in two segments (rolled over buffer end) - process both variants */ /* Jpeg/Tiff image data may be split in two segments (rolled over buffer end) - process both variants */
state->chunk_data_index = state->chunk_index; // index of the first data segment
if ((state->cirbuf_rp[port] + state->jpeg_len) > state->circ_buff_size[port]) { // two segments 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 */ /* copy from the beginning of the frame to the end of the buffer */
D4(fprintf(debug_file, "_10_")); D4(fprintf(debug_file, "_10_"));
...@@ -694,14 +696,13 @@ int sendImageFrame(camogm_state *state) ...@@ -694,14 +696,13 @@ int sendImageFrame(camogm_state *state)
/* copy from the beginning of the buffer to the end of the frame */ /* copy from the beginning of the buffer to the end of the frame */
state->packetchunks[state->chunk_index ].bytes = state->jpeg_len - (state->circ_buff_size[port] - state->cirbuf_rp[port]); state->packetchunks[state->chunk_index ].bytes = state->jpeg_len - (state->circ_buff_size[port] - state->cirbuf_rp[port]);
state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[state->port_num][0]; state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[state->port_num][0];
state->writer_params.segments = 2; state->data_segments = 2;
} else { // single segment } else { // single segment
D4(fprintf(debug_file, "_11_")); D4(fprintf(debug_file, "_11_"));
/* copy from the beginning of the frame to the end of the frame (no buffer rollovers) */ /* copy from the beginning of the frame to the end of the frame (no buffer rollovers) */
state->packetchunks[state->chunk_index ].bytes = state->jpeg_len; state->packetchunks[state->chunk_index ].bytes = state->jpeg_len;
state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[state->port_num][state->cirbuf_rp[port] >> 2]; state->packetchunks[state->chunk_index++].chunk = (unsigned char*)&ccam_dma_buf[state->port_num][state->cirbuf_rp[port] >> 2];
state->writer_params.segments = 1; state->data_segments = 1;
} }
D4(fprintf(debug_file, "\tcirbuf_rp[%d] = 0x%x\t", port, state->cirbuf_rp[port])); D4(fprintf(debug_file, "\tcirbuf_rp[%d] = 0x%x\t", port, state->cirbuf_rp[port]));
D5(fprintf(debug_file, "_12_\n")); D5(fprintf(debug_file, "_12_\n"));
...@@ -709,10 +710,8 @@ int sendImageFrame(camogm_state *state) ...@@ -709,10 +710,8 @@ int sendImageFrame(camogm_state *state)
state->packetchunks[state->chunk_index ].bytes = 2; state->packetchunks[state->chunk_index ].bytes = 2;
state->packetchunks[state->chunk_index++].chunk = (unsigned char*)trailer; state->packetchunks[state->chunk_index++].chunk = (unsigned char*)trailer;
} }
dbg_show_packetchunks(state); dbg_show_packetchunks(state);
D6(fprintf(debug_file, "_12.5_ before CAMOGM_FORMAT_XXX @ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0))); D6(fprintf(debug_file, "_12.5_ before CAMOGM_FORMAT_XXX @ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
switch (state->format) { switch (state->format) {
...@@ -768,7 +767,7 @@ static void dbg_show_packetchunks(camogm_state *state) ...@@ -768,7 +767,7 @@ static void dbg_show_packetchunks(camogm_state *state)
{ {
int i; int i;
for (i = 0; i < state->chunk_index; i++) { for (i = 0; i < state->chunk_index; i++) {
D4(fprintf(debug_file, "packetchunk[%d]: ptr = %p, size = %d\n", i, state->packetchunks[i].chunk, state->packetchunks[i].bytes)); D4(fprintf(debug_file, "packetchunk[%d]: ptr = %p, size = %ld\n", i, state->packetchunks[i].chunk, state->packetchunks[i].bytes));
} }
} }
...@@ -1918,7 +1917,7 @@ static int get_sysfs_name(const char *dev_name, char *sys_name, size_t str_sz, i ...@@ -1918,7 +1917,7 @@ static int get_sysfs_name(const char *dev_name, char *sys_name, size_t str_sz, i
*/ */
static int get_disk_range(const char *name, struct range *rng) static int get_disk_range(const char *name, struct range *rng)
{ {
int ret = 0; int ret = 0, dummy;
int fd; int fd;
uint64_t val; uint64_t val;
char data[SMALL_BUFF_LEN] = {0}; char data[SMALL_BUFF_LEN] = {0};
...@@ -1929,7 +1928,7 @@ static int get_disk_range(const char *name, struct range *rng) ...@@ -1929,7 +1928,7 @@ static int get_disk_range(const char *name, struct range *rng)
if (strlen(sysfs_name) > 0) { if (strlen(sysfs_name) > 0) {
fd = open(sysfs_name, O_RDONLY); fd = open(sysfs_name, O_RDONLY);
if (fd >= 0) { if (fd >= 0) {
read(fd, data, SMALL_BUFF_LEN); dummy=read(fd, data, SMALL_BUFF_LEN);
if ((val = strtoull(data, NULL, 10)) != 0) if ((val = strtoull(data, NULL, 10)) != 0)
rng->from = val; rng->from = val;
else else
...@@ -1945,7 +1944,7 @@ static int get_disk_range(const char *name, struct range *rng) ...@@ -1945,7 +1944,7 @@ static int get_disk_range(const char *name, struct range *rng)
if (get_sysfs_name(name, sysfs_name, ELPHEL_PATH_MAX, TYPE_SIZE) > 0) { if (get_sysfs_name(name, sysfs_name, ELPHEL_PATH_MAX, TYPE_SIZE) > 0) {
fd = open(sysfs_name, O_RDONLY); fd = open(sysfs_name, O_RDONLY);
if (fd >= 0) { if (fd >= 0) {
read(fd, data, SMALL_BUFF_LEN); dummy=read(fd, data, SMALL_BUFF_LEN);
if ((val = strtoull(data, NULL, 10)) != 0) if ((val = strtoull(data, NULL, 10)) != 0)
rng->to = rng->from + val; rng->to = rng->from + val;
else else
...@@ -1974,19 +1973,20 @@ static int set_disk_range(const struct range *rng) ...@@ -1974,19 +1973,20 @@ static int set_disk_range(const struct range *rng)
int ret = 0; int ret = 0;
char buff[SMALL_BUFF_LEN] = {0}; char buff[SMALL_BUFF_LEN] = {0};
int len; int len;
int dummy;
fd = open(SYSFS_AHCI_LBA_START, O_WRONLY); fd = open(SYSFS_AHCI_LBA_START, O_WRONLY);
if (fd < 0) if (fd < 0)
return -1; return -1;
len = snprintf(buff, SMALL_BUFF_LEN, "%llu", rng->from); len = snprintf(buff, SMALL_BUFF_LEN, "%llu", rng->from);
write(fd, buff, len + 1); dummy=write(fd, buff, len + 1);
close(fd); close(fd);
fd = open(SYSFS_AHCI_LBA_END, O_WRONLY); fd = open(SYSFS_AHCI_LBA_END, O_WRONLY);
if (fd < 0) if (fd < 0)
return -1; return -1;
len = snprintf(buff, SMALL_BUFF_LEN, "%llu", rng->to); len = snprintf(buff, SMALL_BUFF_LEN, "%llu", rng->to);
write(fd, buff, len + 1); dummy=write(fd, buff, len + 1);
close(fd); close(fd);
return ret; return ret;
...@@ -2019,16 +2019,17 @@ unsigned int select_port(camogm_state *state) ...@@ -2019,16 +2019,17 @@ unsigned int select_port(camogm_state *state)
if (is_chn_active(state, i)) { if (is_chn_active(state, i)) {
file_pos = lseek(state->fd_circ[i], 0, SEEK_CUR); file_pos = lseek(state->fd_circ[i], 0, SEEK_CUR);
if (file_pos != -1) { if (file_pos != -1) {
free_sz = lseek(state->fd_circ[i], LSEEK_CIRC_FREE, SEEK_END); free_sz = lseek(state->fd_circ[i], LSEEK_CIRC_FREE, SEEK_END); // maybe ==-1 if new frame is not yet ready?
lseek(state->fd_circ[i], file_pos, SEEK_SET); lseek(state->fd_circ[i], file_pos, SEEK_SET);
if (state->prog_state == STATE_STARTING || state->prog_state == STATE_RUNNING) if (state->prog_state == STATE_STARTING || state->prog_state == STATE_RUNNING)
D6(fprintf(debug_file, "port %i = %li, ", i, free_sz)); D6(fprintf(debug_file, "port %i = %li, ", i, free_sz));
if ((free_sz < min_sz && free_sz >= 0) || min_sz == -1) {
if (free_sz < CAMOGM_MIN_BUF_FRAMES * state->image_size[i]) { if (free_sz < CAMOGM_MIN_BUF_FRAMES * state->image_size[i]) {
D3(fprintf(debug_file, "port %i has too little free space (<CAMOGM_MIN_BUF_FRAMES * %d), considered BROKEN", i, state->image_size[i])); D3(fprintf(debug_file, "port %i has too little free space (%ld <CAMOGM_MIN_BUF_FRAMES * %d), considered BROKEN, state=%d", \
i, free_sz, state->image_size[i], state->prog_state));
chn = -1; // i; chn = -1; // i;
break; break;
} }
if ((free_sz < min_sz && free_sz >= 0) || min_sz == -1) {
min_sz = free_sz; min_sz = free_sz;
chn = i; chn = i;
} }
...@@ -2049,7 +2050,7 @@ unsigned int select_port(camogm_state *state) ...@@ -2049,7 +2050,7 @@ unsigned int select_port(camogm_state *state)
if ((state->prog_state == STATE_STARTING) || (state->prog_state == STATE_RUNNING)) { if ((state->prog_state == STATE_STARTING) || (state->prog_state == STATE_RUNNING)) {
// if (lseek(state->fd_circ[port], LSEEK_CIRC_READY, SEEK_END) < 0) { // if (lseek(state->fd_circ[port], LSEEK_CIRC_READY, SEEK_END) < 0) {
D3(if ((chn >=0) && (lseek(state->fd_circ[chn], LSEEK_CIRC_READY, SEEK_END) >= 0)) \ D3(if ((chn >=0) && (lseek(state->fd_circ[chn], LSEEK_CIRC_READY, SEEK_END) >= 0)) \
fprintf(debug_file, "selected port: %i, min free size = %d @ %07d\n", chn, min_sz, get_fpga_usec(state->fd_fparmsall[0], 0)); \ fprintf(debug_file, "selected port: %i, min free size = %08ld @ %07d\n", chn, min_sz, get_fpga_usec(state->fd_fparmsall[0], 0)); \
else if (debug_level >= 6) fprintf(debug_file,"no port is ready @ %07d\n", get_fpga_usec(state->fd_fparmsall[0], 0))); else if (debug_level >= 6) fprintf(debug_file,"no port is ready @ %07d\n", get_fpga_usec(state->fd_fparmsall[0], 0)));
} }
...@@ -2139,6 +2140,8 @@ int open_files(camogm_state *state) ...@@ -2139,6 +2140,8 @@ int open_files(camogm_state *state)
clean_up(state); clean_up(state);
return -3; return -3;
} }
syslog (LOG_INFO, "open_files(): ccam_dma_buf[%d] = %p", port, ccam_dma_buf[port]);
// now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state) // now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state)
state->fd_fparmsall[port] = open(ctlFileNames[port], O_RDWR); state->fd_fparmsall[port] = open(ctlFileNames[port], O_RDWR);
...@@ -2340,5 +2343,7 @@ inline void wait_frame_sync(const int fd_fparsall) ...@@ -2340,5 +2343,7 @@ inline void wait_frame_sync(const int fd_fparsall)
lseek(fd_fparsall, LSEEK_FRAME_WAIT_REL + 1, SEEK_END); lseek(fd_fparsall, LSEEK_FRAME_WAIT_REL + 1, SEEK_END);
} }
unsigned long *get_ccam_dma_buf(int port){
return ccam_dma_buf[port];
}
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#ifndef _CAMOGM_H #ifndef _CAMOGM_H
#define _CAMOGM_H #define _CAMOGM_H
#define __USE_GNU // for O_DIRECT
//#define USE_POLL //#define USE_POLL
#include <pthread.h> #include <pthread.h>
#include <stdbool.h> #include <stdbool.h>
...@@ -27,7 +28,9 @@ ...@@ -27,7 +28,9 @@
#include <elphel/c313a.h> #include <elphel/c313a.h>
#include <elphel/x393_devices.h> #include <elphel/x393_devices.h>
#include <syslog.h> #include <syslog.h>
#include <malloc.h> // debugging
//#define NODEBUG
#define CAMOGM_FRAME_NOT_READY 1 ///< frame pointer valid, but not yet acquired #define CAMOGM_FRAME_NOT_READY 1 ///< frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_INVALID 2 ///< invalid frame pointer #define CAMOGM_FRAME_INVALID 2 ///< invalid frame pointer
#define CAMOGM_FRAME_CHANGED 3 ///< frame parameters have changed #define CAMOGM_FRAME_CHANGED 3 ///< frame parameters have changed
...@@ -46,6 +49,18 @@ ...@@ -46,6 +49,18 @@
#define CAMOGM_FORMAT_MOV 3 ///< output as Apple Quicktime #define CAMOGM_FORMAT_MOV 3 ///< output as Apple Quicktime
#define CAMOGM_MIN_BUF_FRAMES 2 ///< buffer should accomodate at list this number of frames #define CAMOGM_MIN_BUF_FRAMES 2 ///< buffer should accomodate at list this number of frames
#ifdef NODEBUG
#define D(x)
#define D0(x)
#define D1(x)
#define D2(x)
#define D3(x)
#define D4(x)
#define D5(x)
#define D6(x)
#define D7(x)
#define DD(x)
#else
#define D(x) { if (debug_file && debug_level) { x; fflush(debug_file); } } #define D(x) { if (debug_file && debug_level) { x; fflush(debug_file); } }
#define D0(x) { if (debug_file) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } } #define D0(x) { if (debug_file) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } }
#define D1(x) { if (debug_file && (debug_level > 0)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } } #define D1(x) { if (debug_file && (debug_level > 0)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } }
...@@ -54,14 +69,15 @@ ...@@ -54,14 +69,15 @@
#define D4(x) { if (debug_file && (debug_level > 3)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } } #define D4(x) { if (debug_file && (debug_level > 3)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } }
#define D5(x) { if (debug_file && (debug_level > 4)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } } #define D5(x) { if (debug_file && (debug_level > 4)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } }
#define D6(x) { if (debug_file && (debug_level > 5)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } } #define D6(x) { if (debug_file && (debug_level > 5)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } }
//#define D7(x) { if (debug_file && (debug_level > 6)) { pthread_mutex_lock(&print_mutex); x; fflush(debug_file); pthread_mutex_unlock(&print_mutex); } }
//#define DD(x) #define D7(x)
#define DD(x) { if (debug_file) { fprintf(debug_file, "%s:%d:", __FILE__, __LINE__); x; fflush(debug_file); } } #define DD(x) { if (debug_file) { fprintf(debug_file, "%s:%d:", __FILE__, __LINE__); x; fflush(debug_file); } }
#endif
/** @brief HEADER_SIZE is defined to be larger than actual header (with EXIF) to use compile-time buffer */ /** @brief HEADER_SIZE is defined to be larger than actual header (with EXIF) to use compile-time buffer */
#define JPEG_HEADER_MAXSIZE 0x300 #define JPEG_HEADER_MAXSIZE 0x300
/** @brief Offset from the beginning of raw device buffer. Must be aligned to physical sector size */ /** @brief Offset from the beginning of raw device buffer. Must be aligned to physical sector size */
#define RAWDEV_START_OFFSET 1024 #define RAWDEV_START_OFFSET 1024 // ????
/** @brief Maximum length of file or raw device path */ /** @brief Maximum length of file or raw device path */
#define ELPHEL_PATH_MAX 300 #define ELPHEL_PATH_MAX 300
#define MMAP_CHUNK_SIZE 10485760 #define MMAP_CHUNK_SIZE 10485760
...@@ -72,6 +88,50 @@ ...@@ -72,6 +88,50 @@
/** @brief Number of chunk pages to overlap preparation with SSD raw write */ /** @brief Number of chunk pages to overlap preparation with SSD raw write */
#define FILE_CHUNKS_PAGES 4 // 2 #define FILE_CHUNKS_PAGES 4 // 2
#define FILE_CHUNKS_TOTAL ((FILE_CHUNKS_NUM) * (FILE_CHUNKS_PAGES)) #define FILE_CHUNKS_TOTAL ((FILE_CHUNKS_NUM) * (FILE_CHUNKS_PAGES))
#define JPEG_MARKER_LEN 2 ///< The size in bytes of JPEG marker
#define JPEG_TRAILER_LEN 2 ///< The size in bytes of JPEG trailer
#define CIRCBUF_ALIGNMENT_SIZE 32 ///< Align of CIRCBUF entries
// Switching CHUNK -> SEGMENT
#define PAGE_PHYS 4096 // 512 // alignment size for O_DIRECT, may be different from LBA block size that is 512
enum segments {
SEGMENT_GLUE, ///< pointer to a page-aligned buffer to accommodate over-page of data, trailer, zeros, header and start of the data
SEGMENT_FIRST, ///< first (or the only) continuous page-aligned data segment that does not need to be copied (may start with ofset to PAGE_PHYS-aligned)
SEGMENT_SECOND, ///< optional second part of the data buffer, end PAGE_PHYS-aligned
SEGMENTS_NUMBER ///< Just to get number of segment types
};
#define SEGMENTS_PAGES 4 // 2
#define SEGMENTS_TOTAL ((SEGMENTS_NUMBER) * (SEGMENTS_PAGES))
/** Glue buffer should be large enough to contain:
* 1: alignment of the circbuf data that does not fit into PAGE_PHYS-aligned area (up to PAGE_PHYS-1)
* 2: optional JPEG trailer (2 bytes)
* 3: JPEG marker
* 4: EXIF/TIFF,
* 5: JPEG HEADER,
* 6: portion of the circbuf data up to PAGE_PHYS alignment (up to PAGE_PHYS-1)
* Trailer alignments (1,2) and header align,ents may share a common page (if they do not overlap)
* Remaining gap should be zero-filled to avoid stray match of the frame start (JPEG or TIFF)
* */
///< Trim address/char pointer to PAGE_PHYS alignment
/// convert to inline functions?
#define PAGE_PHYS_TRIM(x) ((x) & -(PAGE_PHYS))
///< Extend address/char pointer to PAGE_PHYS alignment
#define PAGE_PHYS_CEIL(x) (((x) + (PAGE_PHYS - 1)) & -(PAGE_PHYS))
///< Number of PAGE_PHYS pages to accommodate (x) bytes
#define PAGE_PHYS_NUMBER(x) (((x) + (PAGE_PHYS) - 1) / (PAGE_PHYS))
///< Number of pages needed for the glue segments
/// 512: 12, 4096:4
#define GLUE_SEGMENTS PAGE_PHYS_NUMBER(((PAGE_PHYS)-1) + \
(JPEG_TRAILER_LEN) + \
(JPEG_MARKER_LEN) + \
(MAX_EXIF_SIZE) + \
(JPEG_HEADER_MAXSIZE) +\
(PAGE_PHYS - CIRCBUF_ALIGNMENT_SIZE))
//#define COMMON_BUFF_SZ MAX_EXIF_SIZE + JPEG_HEADER_MAXSIZE + ALIGNMENT_SIZE + 2 * PHY_BLOCK_SIZE
//#define REM_BUFF_SZ 2 * PHY_BLOCK_SIZE
/** /**
* @enum state_flags * @enum state_flags
* @brief Program state flags * @brief Program state flags
...@@ -126,7 +186,7 @@ typedef struct { ...@@ -126,7 +186,7 @@ typedef struct {
uint64_t end_pos; uint64_t end_pos;
volatile uint64_t curr_pos_r; volatile uint64_t curr_pos_r;
uint64_t curr_pos_w; uint64_t curr_pos_w;
uint64_t mmap_default_size; uint64_t mmap_default_size; // only used for camogm_read
uint64_t mmap_current_size; uint64_t mmap_current_size;
uint64_t mmap_offset; uint64_t mmap_offset;
uint64_t file_start; uint64_t file_start;
...@@ -149,27 +209,17 @@ struct writer_params { ...@@ -149,27 +209,17 @@ struct writer_params {
pthread_mutex_t writer_mutex; ///< synchronization mutex for main and writing threads pthread_mutex_t writer_mutex; ///< synchronization mutex for main and writing threads
pthread_cond_t writer_cond; ///< conditional variable indicating that writer thread can proceed with new frame pthread_cond_t writer_cond; ///< conditional variable indicating that writer thread can proceed with new frame
pthread_cond_t main_cond; ///< conditional variable indicating that main thread can update write pointers pthread_cond_t main_cond; ///< conditional variable indicating that main thread can update write pointers
// bool data_ready; ///< flag indicating that new frame is ready for recording, access to this flag
// ///< must be protected with #writer_mutex. Set this flag in main thread and reset in
// ///< disk writing thread.
// ///< For overlapping disk raw writes with chunks preparation (should be atomic - use #writer_mutex)
int chunk_page_prep; ///< page of chunks being prepared. Incremented (mod) after data is prepared for raw write int chunk_page_prep; ///< page of chunks being prepared. Incremented (mod) after data is prepared for raw write
int chunk_page_write; ///< page of chunks to write. Incremented (mod) after recording to disk int chunk_page_write; ///< page of chunks to write. Incremented (mod) after recording to disk
bool writev_run; ///< writev() is active (enable main thread if buffer not full and writew or buf empty) bool writev_run; ///< writev() is active (enable main thread if buffer not full and writew or buf empty)
int last_ret_val; ///< error value return during last frame recording (if any occurred) int last_ret_val; ///< error value return during last frame recording (if any occurred)
bool exit_thread; ///< flag indicating that the writing thread should terminate bool exit_thread; ///< flag indicating that the writing thread should terminate
int state; ///< the state of disk writing thread int state; ///< the state of disk writing thread
int segments; ///< the number of segments in frame struct iovec *data_segments[SEGMENTS_PAGES]; ///< a set of vectors sets pointing to aligned frame data buffers
struct iovec *data_chunks; ///< a set of vectors pointing to aligned frame data buffers
struct iovec was_CHUNK_REM; ///< extracting to a separate entity data_chunks[CHUNK_REM]
// struct iovec *was_CHUNK_COMMON; ///< extracting to a separate entity data_chunks[CHUNK_COMMON]
struct iovec prev_rem_vect; ///< vector pointing to the remainder of the previous frame
unsigned char *rem_buff; ///< buffer containing the unaligned remainder of the current frame
unsigned char *prev_rem_buff; ///< buffer containing the unaligned remainder of the previous frame
// get rid of common_buff
// unsigned char *common_buff; ///< buffer for aligned JPEG header // make multiple?
unsigned char *common_buffs[FILE_CHUNKS_PAGES]; ///< buffer for aligned JPEG header // make multiple? unsigned char *common_buffs[FILE_CHUNKS_PAGES]; ///< buffer for aligned JPEG header // make multiple?
unsigned char *glue_buffs[SEGMENTS_PAGES + 1]; ///< glue buffer (end of previous frame + start of this one
// unsigned char *glue_buffs_carry; ///< extra glue buffer to pass from the previous to the next frame
struct iovec glue_carry_vec; ///< current tail pointer of the carry glue segment
uint64_t lba_start; ///< disk starting LBA uint64_t lba_start; ///< disk starting LBA
uint64_t lba_current; ///< current write position in LBAs uint64_t lba_current; ///< current write position in LBAs
uint64_t lba_end; ///< disk last LBA uint64_t lba_end; ///< disk last LBA
...@@ -241,6 +291,8 @@ typedef struct { ...@@ -241,6 +291,8 @@ typedef struct {
int set_format; ///< output format to set (will be updated after stop) int set_format; ///< output format to set (will be updated after stop)
elph_packet_chunk packetchunks[FILE_CHUNKS_NUM]; elph_packet_chunk packetchunks[FILE_CHUNKS_NUM];
int chunk_index; int chunk_index;
int chunk_data_index; ///< segment index corresponding to first(only) data one
int data_segments; ///< the number of segments in frame
int buf_overruns[SENSOR_PORTS]; int buf_overruns[SENSOR_PORTS];
int buf_min[SENSOR_PORTS]; int buf_min[SENSOR_PORTS];
int set_frames_skip; ///< will be copied to frames_skip if stopped or at start int set_frames_skip; ///< will be copied to frames_skip if stopped or at start
...@@ -287,5 +339,7 @@ int isDaemonEnabled(unsigned int port, int daemonBit); ...@@ -287,5 +339,7 @@ int isDaemonEnabled(unsigned int port, int daemonBit);
int is_fd_valid(int fd); int is_fd_valid(int fd);
int get_fpga_usec(const int fd_fparsall, unsigned int port); int get_fpga_usec(const int fd_fparsall, unsigned int port);
inline void wait_frame_sync(const int fd_fparsall); inline void wait_frame_sync(const int fd_fparsall);
unsigned long *get_ccam_dma_buf(int port);
#endif /* _CAMOGM_H */ #endif /* _CAMOGM_H */
This diff is collapsed.
...@@ -25,37 +25,23 @@ ...@@ -25,37 +25,23 @@
// TODO: Change PHY_BLOCK_SIZE to 4096 as it is 4096 - no, most SSDs are still 512 // TODO: Change PHY_BLOCK_SIZE to 4096 as it is 4096 - no, most SSDs are still 512
#define PHY_BLOCK_SIZE 512 ///< Physical disk block size - still 512 even for the OS with 4096 #define PHY_BLOCK_SIZE 512 ///< Physical disk block size - still 512 even for the OS with 4096
//#define PHY_BLOCK_SIZE 4096 ///< Physical disk block size //#define PHY_BLOCK_SIZE 4096 ///< Physical disk block size
#define JPEG_MARKER_LEN 2 ///< The size in bytes of JPEG marker //#define JPEG_MARKER_LEN 2 ///< The size in bytes of JPEG marker
#define JPEG_SIZE_LEN 2 ///< The size in bytes of JPEG marker length field #define JPEG_SIZE_LEN 2 ///< The size in bytes of JPEG marker length field
#define INCLUDE_REM 1 ///< Include REM buffer to total size calculation #define INCLUDE_REM 1 ///< Include REM buffer to total size calculation
#define EXCLUDE_REM 0 ///< Exclude REM buffer from total size calculation #define EXCLUDE_REM 0 ///< Exclude REM buffer from total size calculation
#if 0
#define MAX_DATA_CHUNKS 9 ///< An array or JPEG frame chunks contains pointers to JPEG leading marker, #define MAX_DATA_CHUNKS 9 ///< An array or JPEG frame chunks contains pointers to JPEG leading marker,
///< JPEG header, Exif data if present, stuffing bytes chunk which aligns ///< JPEG header, Exif data if present, stuffing bytes chunk which aligns
///< the frame size to disk sector boundary, JPEG data which ///< the frame size to disk sector boundary, JPEG data which
///< can be split into two chunks, align buffers, JPEG ///< can be split into two chunks, align buffers, JPEG
///< trailing marker, and pointer to a buffer containing the remainder of a ///< trailing marker, and pointer to a buffer containing the remainder of a
///< frame. Nine chunks of data in total. ///< frame. Nine chunks of data in total.
///
#define ALIGNMENT_SIZE 32 ///< Align buffers length to this amount of bytes #define ALIGNMENT_SIZE 32 ///< Align buffers length to this amount of bytes
/** Common buffer should be large enough to contain JPEG header, Exif, some alignment bytes and remainder from previous frame */ /** Common buffer should be large enough to contain JPEG header, Exif, some alignment bytes and remainder from previous frame */
#define COMMON_BUFF_SZ MAX_EXIF_SIZE + JPEG_HEADER_MAXSIZE + ALIGNMENT_SIZE + 2 * PHY_BLOCK_SIZE #define COMMON_BUFF_SZ MAX_EXIF_SIZE + JPEG_HEADER_MAXSIZE + ALIGNMENT_SIZE + 2 * PHY_BLOCK_SIZE
#define REM_BUFF_SZ 2 * PHY_BLOCK_SIZE #define REM_BUFF_SZ 2 * PHY_BLOCK_SIZE
#endif
///** This structure holds raw device buffer pointers */
//struct drv_pointers {
// uint64_t lba_start; ///< raw buffer starting LBA
// uint64_t lba_end; ///< raw buffer ending LBA
// uint64_t lba_write; ///< current write pointer inside raw buffer
// uint16_t wr_count; ///< the number of LBA to write next time
//};
/** Container structure for frame buffers */
//struct frame_buffers {
// struct fvec exif_buff; ///< Exif buffer
// struct fvec jpheader_buff; ///< JPEG header buffer
// struct fvec trailer_buff; ///< buffer for trailing marker
// struct fvec common_buff; ///< common buffer where other parts are combined
// struct fvec rem_buff; ///< remainder from previous frame
//};
/** Symbolic names for slots in buffer pointers. Buffer alignment function relies on the order of these names, so /** Symbolic names for slots in buffer pointers. Buffer alignment function relies on the order of these names, so
* new names can be added but the overall order should not be changed */ * new names can be added but the overall order should not be changed */
...@@ -71,16 +57,12 @@ enum { ...@@ -71,16 +57,12 @@ enum {
CHUNK_REM ///< pointer to buffer containing the remainder of current frame. It will be recorded during next transaction CHUNK_REM ///< pointer to buffer containing the remainder of current frame. It will be recorded during next transaction
}; };
int init_align_buffers(camogm_state *state); int init_align_buffers(camogm_state *state);
void deinit_align_buffers(camogm_state *state); void deinit_align_buffers(camogm_state *state);
void align_frame(camogm_state *state); void reset_segments(camogm_state *state, int all, int page);
void reset_chunks(camogm_state *state, int all, int page); size_t remap_vectors(camogm_state *state); //, struct iovec *chunks);
//int update_lba(camogm_state *state);
int get_data_buffers(camogm_state *state, struct iovec *mapped, size_t mapped_sz, int page);
int prep_last_block(camogm_state *state, int page);
off64_t lba_to_offset(uint64_t lba); off64_t lba_to_offset(uint64_t lba);
//uint64_t lba_to_offset(uint64_t lba);
#endif /* _CAMOGM_ALIGN_H */ #endif /* _CAMOGM_ALIGN_H */
This diff is collapsed.
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#ifndef _CAMOGM_JPEG_H #ifndef _CAMOGM_JPEG_H
#define _CAMOGM_JPEG_H #define _CAMOGM_JPEG_H
#define __USE_GNU // for O_DIRECT
#include "camogm.h" #include "camogm.h"
...@@ -26,5 +27,7 @@ int camogm_frame_jpeg(camogm_state *state); ...@@ -26,5 +27,7 @@ int camogm_frame_jpeg(camogm_state *state);
int camogm_end_jpeg(camogm_state *state); int camogm_end_jpeg(camogm_state *state);
void camogm_free_jpeg(camogm_state *state); void camogm_free_jpeg(camogm_state *state);
int open_state_file(const rawdev_buffer *rawdev, uint64_t *current_pos); int open_state_file(const rawdev_buffer *rawdev, uint64_t *current_pos);
ssize_t emul_writev (int fd, const struct iovec *iovec, int count);
#endif /* _CAMOGM_JPEG_H */ #endif /* _CAMOGM_JPEG_H */
...@@ -417,7 +417,7 @@ static int read_index(rawdev_buffer *rawdev, struct disk_index **indx) ...@@ -417,7 +417,7 @@ static int read_index(rawdev_buffer *rawdev, struct disk_index **indx)
unsigned char read_buff[TIFF_HDR_OFFSET] = {0}; unsigned char read_buff[TIFF_HDR_OFFSET] = {0};
char str_buff[SMALL_BUFF_LEN] = {0}; char str_buff[SMALL_BUFF_LEN] = {0};
uint64_t save_pos = lseek64(rawdev->rawdev_fd, 0, SEEK_CUR); uint64_t save_pos = lseek64(rawdev->rawdev_fd, 0, SEEK_CUR);
int dummy;
if (indx == NULL) if (indx == NULL)
return -1; return -1;
...@@ -429,16 +429,16 @@ static int read_index(rawdev_buffer *rawdev, struct disk_index **indx) ...@@ -429,16 +429,16 @@ static int read_index(rawdev_buffer *rawdev, struct disk_index **indx)
} }
if (read_buff[2] == 0xff && read_buff[3] == 0xe1) { if (read_buff[2] == 0xff && read_buff[3] == 0xe1) {
// get IFD0 offset from TIFF header // get IFD0 offset from TIFF header
read(rawdev->rawdev_fd, &hdr, sizeof(struct tiff_hdr)); dummy=read(rawdev->rawdev_fd, &hdr, sizeof(struct tiff_hdr));
hdr_byte_order(&hdr); hdr_byte_order(&hdr);
curr_pos = rawdev->file_start + TIFF_HDR_OFFSET + hdr.offset; curr_pos = rawdev->file_start + TIFF_HDR_OFFSET + hdr.offset;
lseek64(rawdev->rawdev_fd, curr_pos, SEEK_SET); lseek64(rawdev->rawdev_fd, curr_pos, SEEK_SET);
// process IFD0 and SubIFD fields // process IFD0 and SubIFD fields
do { do {
read(rawdev->rawdev_fd, &num_entries, sizeof(num_entries)); dummy=read(rawdev->rawdev_fd, &num_entries, sizeof(num_entries));
num_entries = __be16_to_cpu(num_entries); num_entries = __be16_to_cpu(num_entries);
for (int i = 0; i < num_entries; i++) { for (int i = 0; i < num_entries; i++) {
read(rawdev->rawdev_fd, &ifd, sizeof(struct ifd_entry)); dummy=read(rawdev->rawdev_fd, &ifd, sizeof(struct ifd_entry));
ifd_byte_order(&ifd); ifd_byte_order(&ifd);
switch (ifd.tag) { switch (ifd.tag) {
case Exif_Image_PageNumber: case Exif_Image_PageNumber:
...@@ -457,7 +457,7 @@ static int read_index(rawdev_buffer *rawdev, struct disk_index **indx) ...@@ -457,7 +457,7 @@ static int read_index(rawdev_buffer *rawdev, struct disk_index **indx)
} }
// ensure that IFD0 finished correctly (0x00000000 in the end), set file pointer to SubIFD and // ensure that IFD0 finished correctly (0x00000000 in the end), set file pointer to SubIFD and
// process remaining fields // process remaining fields
read(rawdev->rawdev_fd, &data32, sizeof(data32)); dummy=read(rawdev->rawdev_fd, &data32, sizeof(data32));
process -= (subifd_offset == 0 || data32 != 0) ? 2 : 1; process -= (subifd_offset == 0 || data32 != 0) ? 2 : 1;
curr_pos = rawdev->file_start + TIFF_HDR_OFFSET + subifd_offset; curr_pos = rawdev->file_start + TIFF_HDR_OFFSET + subifd_offset;
lseek64(rawdev->rawdev_fd, curr_pos, SEEK_SET); lseek64(rawdev->rawdev_fd, curr_pos, SEEK_SET);
...@@ -815,10 +815,11 @@ static void send_fnum(int sockfd, size_t num) ...@@ -815,10 +815,11 @@ static void send_fnum(int sockfd, size_t num)
{ {
char buff[SMALL_BUFF_LEN] = {0}; char buff[SMALL_BUFF_LEN] = {0};
int len; int len;
int dummy;
len = snprintf(buff, SMALL_BUFF_LEN - 1, "Number of files: %d\n", num); len = snprintf(buff, SMALL_BUFF_LEN - 1, "Number of files: %d\n", num);
buff[len] = '\0'; buff[len] = '\0';
write(sockfd, buff, len); dummy=write(sockfd, buff, len);
} }
/** /**
...@@ -1017,6 +1018,7 @@ void *reader(void *arg) ...@@ -1017,6 +1018,7 @@ void *reader(void *arg)
.sockfd_const = &sockfd, .sockfd_const = &sockfd,
.sockfd_temp = &fd .sockfd_temp = &fd
}; };
int dummy;
memset(&index_dir, 0, sizeof(struct disk_idir)); memset(&index_dir, 0, sizeof(struct disk_idir));
memset(&index_sparse, 0, sizeof(struct disk_idir)); memset(&index_sparse, 0, sizeof(struct disk_idir));
...@@ -1059,7 +1061,7 @@ void *reader(void *arg) ...@@ -1059,7 +1061,7 @@ void *reader(void *arg)
len = snprintf(send_buff, CMD_BUFF_LEN - 1, INDEX_FORMAT_STR, len = snprintf(send_buff, CMD_BUFF_LEN - 1, INDEX_FORMAT_STR,
disk_indx->port, disk_indx->rawtime, disk_indx->usec, disk_indx->f_offset, disk_indx->f_size); disk_indx->port, disk_indx->rawtime, disk_indx->usec, disk_indx->f_offset, disk_indx->f_size);
send_buff[len] = '\0'; send_buff[len] = '\0';
write(fd, send_buff, len); dummy=write(fd, send_buff, len);
disk_indx = disk_indx->next; disk_indx = disk_indx->next;
} }
} else { } else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment