Commit e4468ac7 authored by Andrey Filippov's avatar Andrey Filippov

debugging fast raw recording

parent a54d1b82
......@@ -713,7 +713,7 @@ int sendImageFrame(camogm_state *state)
dbg_show_packetchunks(state);
D6(fprintf(debug_file, "_12.5_ before CAMOGM_FORMAT_XXX @ %06d\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) {
case CAMOGM_FORMAT_NONE: rslt = 0; break;
......@@ -759,7 +759,7 @@ int sendImageFrame(camogm_state *state)
// end_time.tv_sec, end_time.tv_usec,
// state->rawdev.last_jpeg_size));
// D6(fprintf(debug_file, "Write speed: %d MB/s\n", mbps));
D6(fprintf(debug_file, "Exit sendImageFrame() OK @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "Exit sendImageFrame() OK @ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
return 0;
}
......@@ -1405,7 +1405,9 @@ int parse_cmd(camogm_state *state, FILE* npipe)
//skip empty commands
while (((cmd = getLineFromPipe(npipe))) && !cmd[0]) ;
if (!cmd) return 0; // nothing in the pipe
D2(fprintf(debug_file, "Got command (state->port_num=%d): '%s' @ %06d -> ", port, cmd, get_fpga_usec(state->fd_fparmsall[0], 0)));
D2(fprintf(debug_file, "Got command (state->port_num=%d): '%s' @ %07d -> ", port, cmd, get_fpga_usec(state->fd_fparmsall[0], 0)));
D3(syslog (LOG_INFO, "Got command (state->port_num=%d): '%s' @ %07d -> ", port, cmd, get_fpga_usec(state->fd_fparmsall[0], 0)));
if (port >= 0) {
D3(fprintf(debug_file, "Acknowledge received command for port=%d\n", port));
// Acknowledge received command by copying frame number to per-daemon parameter
......@@ -1676,7 +1678,7 @@ int listener_loop(camogm_state *state)
// enter main processing loop
while (process) {
D6(fprintf(debug_file, "--------------- Listener loop @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "--------------- Listener loop @ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
curr_port = select_port(state);
state->port_num = curr_port;
// look at command queue first
......@@ -1690,7 +1692,7 @@ int listener_loop(camogm_state *state)
#endif
cmd = parse_cmd(state, cmd_file);
if (cmd) {
D2(fprintf(debug_file, "DONE command @ %06d\n", get_fpga_usec(state->fd_fparmsall[0], 0)));
D2(fprintf(debug_file, "DONE command @ %07d\n", get_fpga_usec(state->fd_fparmsall[0], 0)));
if (cmd < 0) D0(fprintf(debug_file, "Unrecognized command\n"));
#ifdef USE_POLL
......@@ -1706,7 +1708,7 @@ int listener_loop(camogm_state *state)
} else {
rslt = -sendImageFrame(state);
}
D6(fprintf(debug_file, " ==> %d @ %06d\n",rslt,get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, " ==> %d @ %07d\n",rslt,get_fpga_usec(state->fd_fparmsall[0], 0)));
switch (rslt) {
case 0:
break; // frame sent OK, nothing to do (TODO: check file length/duration)
......@@ -1714,7 +1716,7 @@ int listener_loop(camogm_state *state)
// we'll wait for a frame, not to waste resources. But if the compressor is stopped this program will not respond to any commands
// TODO - add another wait with (short) timeout?
wait_frame_sync(state->fd_fparmsall[curr_port]);
D6(fprintf(debug_file, "No compressed frame ready, waited for the next frame sync for port %d @ %06d\n",curr_port,get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "No compressed frame ready, waited for the next frame sync for port %d @ %07d\n",curr_port,get_fpga_usec(state->fd_fparmsall[0], 0)));
break;
// do not analyze next frame (may be non-existing), will do that next time
/*
......@@ -1728,7 +1730,7 @@ int listener_loop(camogm_state *state)
D0(fprintf(debug_file, "%s:line %d got broken frame (%d) while waiting for ready. Before that fp0=0x%x\n", __FILE__, __LINE__, fp1, fp0));
rslt = CAMOGM_FRAME_BROKEN;
} else {
D6(fprintf(debug_file, "No compressed frame ready, skipped 1 frame sync for port %d @ %06d\n",curr_port,get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "No compressed frame ready, skipped 1 frame sync for port %d @ %07d\n",curr_port,get_fpga_usec(state->fd_fparmsall[0], 0)));
break;
}
}
......@@ -1798,14 +1800,14 @@ int listener_loop(camogm_state *state)
// add port number to error code to facilitate debugging
state->last_error_code = rslt + 100 * state->port_num;
} else if (state->prog_state == STATE_READING) {
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY start for STATE_READING@ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY start for STATE_READING@ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
usleep(COMMAND_LOOP_DELAY);
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY end for STATE_READING@ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY end for STATE_READING@ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
} else { // not running, not starting
state->rawdev.thread_state = STATE_RUNNING;
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY start for STATE_RUNNING@ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY start for STATE_RUNNING@ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
usleep(COMMAND_LOOP_DELAY); // make it longer but interruptible by signals?
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY end for STATE_RUNNING@ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "COMMAND_LOOP_DELAY end for STATE_RUNNING@ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
}
#ifdef USE_POLL
// } // if pfd.revents & POLLIN
......@@ -2011,25 +2013,24 @@ unsigned int select_port(camogm_state *state)
break;
}
}
if (state->prog_state == STATE_STARTING || state->prog_state == STATE_RUNNING)
D3(fprintf(debug_file, "Selecting sensor port, buffer free size: "));
D6(fprintf(debug_file, "Selecting sensor port, buffer free size: "));
for (int i = 0; i < SENSOR_PORTS; i++) {
if (is_chn_active(state, i)) {
file_pos = lseek(state->fd_circ[i], 0, SEEK_CUR);
if (file_pos != -1) {
free_sz = lseek(state->fd_circ[i], LSEEK_CIRC_FREE, SEEK_END);
lseek(state->fd_circ[i], file_pos, SEEK_SET);
if (state->prog_state == STATE_STARTING || state->prog_state == STATE_RUNNING)
D3(fprintf(debug_file, "port %i = %li, ", i, free_sz));
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]));
chn = -1; // i;
break;
}
if ((free_sz < min_sz && free_sz >= 0) || min_sz == -1) {
min_sz = free_sz;
chn = i;
lseek(state->fd_circ[i], file_pos, SEEK_SET);
if (state->prog_state == STATE_STARTING || state->prog_state == STATE_RUNNING)
D6(fprintf(debug_file, "port %i = %li, ", i, free_sz));
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]));
chn = -1; // i;
break;
}
if ((free_sz < min_sz && free_sz >= 0) || min_sz == -1) {
min_sz = free_sz;
chn = i;
}
} else {
if (state->prog_state == STATE_STARTING || state->prog_state == STATE_RUNNING)
......@@ -2042,11 +2043,15 @@ unsigned int select_port(camogm_state *state)
}
} else {
if (state->prog_state == STATE_STARTING || state->prog_state == STATE_RUNNING)
D3(fprintf(debug_file, "port %i is inactive, ", i));
D6(fprintf(debug_file, "port %i is inactive, ", i));
}
}
if (state->prog_state == STATE_STARTING || state->prog_state == STATE_RUNNING)
D3(fprintf(debug_file, "selected port: %i @ %06d\n", chn, get_fpga_usec(state->fd_fparmsall[0], 0)));
if ((state->prog_state == STATE_STARTING) || (state->prog_state == STATE_RUNNING)) {
// 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)) \
fprintf(debug_file, "selected port: %i, min free size = %d @ %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)));
}
return chn;
}
......@@ -2324,7 +2329,7 @@ inline int get_fpga_usec(const int fd_fparsall, unsigned int port)
{
lseek(fd_fparsall, LSEEK_GET_FPGA_TIME, SEEK_END);
// return (int) getGPValue(port, G_MICROSECONDS);
return (int) GLOBALPARS(port, G_MICROSECONDS);
return (int) GLOBALPARS(port, G_MICROSECONDS) + 1000000*(GLOBALPARS(port, G_SECONDS) % 10);
}
/**
......
......@@ -26,6 +26,7 @@
#include <elphel/exifa.h>
#include <elphel/c313a.h>
#include <elphel/x393_devices.h>
#include <syslog.h>
#define CAMOGM_FRAME_NOT_READY 1 ///< frame pointer valid, but not yet acquired
#define CAMOGM_FRAME_INVALID 2 ///< invalid frame pointer
......
......@@ -548,7 +548,7 @@ void align_frame(camogm_state *state)
if (len >= (chunks[paged_CHUNK_DATA_1].iov_len + chunks[paged_CHUNK_TRAILER].iov_len)) {
/* current frame is not split or the second part of JPEG data is too short */
data_len = len - chunks[paged_CHUNK_DATA_1].iov_len - chunks[paged_CHUNK_TRAILER].iov_len;
D6(fprintf(debug_file, "_algn002: data_len=%d, copy %d short JPEG @ %06d\n", data_len, chunks[paged_CHUNK_DATA_1].iov_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_algn002: data_len=%d, copy %d short JPEG @ %07d\n", data_len, chunks[paged_CHUNK_DATA_1].iov_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
src = vectrpos(&chunks[paged_CHUNK_DATA_0], data_len);
vectcpy(chunk_rem, src, data_len);
vectshrink(&chunks[paged_CHUNK_DATA_0], data_len);
......@@ -559,7 +559,7 @@ void align_frame(camogm_state *state)
} else if (len >= chunks[paged_CHUNK_TRAILER].iov_len) {
/* there is enough data in second part to align the frame */
data_len = len - chunks[paged_CHUNK_TRAILER].iov_len;
D6(fprintf(debug_file, "_algn003: data_len=%d, copy %d short JPEG @ %06d\n", data_len, chunks[paged_CHUNK_DATA_1].iov_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_algn003: data_len=%d, copy %d short JPEG @ %07d\n", data_len, chunks[paged_CHUNK_DATA_1].iov_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
src = vectrpos(&chunks[paged_CHUNK_DATA_1], data_len);
vectcpy(chunk_rem, src, data_len);
vectshrink(&chunks[paged_CHUNK_DATA_1], data_len);
......@@ -571,7 +571,7 @@ void align_frame(camogm_state *state)
data_len = PHY_BLOCK_SIZE - (chunks[paged_CHUNK_TRAILER].iov_len - len);
if (data_len >= chunks[paged_CHUNK_DATA_1].iov_len) {
size_t cut_len = data_len - chunks[paged_CHUNK_DATA_1].iov_len;
D6(fprintf(debug_file, "_algn004: cut_len=%d, copy %d short JPEG @ %06d\n", cut_len, chunks[paged_CHUNK_DATA_1].iov_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_algn004: cut_len=%d, copy %d short JPEG @ %07d\n", cut_len, chunks[paged_CHUNK_DATA_1].iov_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
src = vectrpos(&chunks[paged_CHUNK_DATA_0], cut_len);
vectcpy(chunk_rem, src, cut_len);
vectshrink(&chunks[paged_CHUNK_DATA_0], cut_len);
......@@ -580,7 +580,7 @@ void align_frame(camogm_state *state)
vectcpy(chunk_rem, chunks[paged_CHUNK_TRAILER].iov_base, chunks[paged_CHUNK_TRAILER].iov_len);
vectshrink(&chunks[paged_CHUNK_TRAILER], chunks[paged_CHUNK_TRAILER].iov_len);
} else {
D6(fprintf(debug_file, "_algn005: data_len=%d, @ %06d\n", data_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_algn005: data_len=%d, @ %07d\n", data_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
src = vectrpos(&chunks[paged_CHUNK_DATA_1], data_len);
vectcpy(chunk_rem, src, data_len);
vectshrink(&chunks[paged_CHUNK_DATA_1], data_len);
......@@ -594,13 +594,13 @@ void align_frame(camogm_state *state)
chunks[paged_CHUNK_ALIGN].iov_len = 0;
if (chunks[paged_CHUNK_DATA_1].iov_len == 0) {
data_len = chunks[paged_CHUNK_DATA_0].iov_len % ALIGNMENT_SIZE;
D6(fprintf(debug_file, "_algn006: data_len=%d, @ %06d\n", data_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_algn006: data_len=%d, @ %07d\n", data_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
src = vectrpos(&chunks[CHUNK_DATA_0], data_len);
vectcpy(&chunks[paged_CHUNK_ALIGN], src, data_len);
vectshrink(&chunks[paged_CHUNK_DATA_0], data_len);
} else {
data_len = chunks[paged_CHUNK_DATA_1].iov_len % ALIGNMENT_SIZE;
D6(fprintf(debug_file, "_algn007: data_len=%d, @ %06d\n", data_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_algn007: data_len=%d, @ %07d\n", data_len, get_fpga_usec(state->fd_fparmsall[0], 0)));
src = vectrpos(&chunks[paged_CHUNK_DATA_1], data_len);
vectcpy(&chunks[paged_CHUNK_ALIGN], src, data_len);
vectshrink(&chunks[paged_CHUNK_DATA_1], data_len);
......@@ -614,7 +614,7 @@ void align_frame(camogm_state *state)
dev_dbg(NULL, "ERROR: the number of bytes copied to common buffer exceeds its size\n");
}
check_chunks(chunks, page);
D6(fprintf(debug_file, "align_frame() DONE @ %06d\n", get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "align_frame() DONE @ %07d\n", get_fpga_usec(state->fd_fparmsall[0], 0)));
}
......
......@@ -22,9 +22,9 @@
#include <sys/types.h>
#include "camogm.h"
// TODO: Change PHY_BLOCK_SIZE to 4096 as it is 4096!
//#define PHY_BLOCK_SIZE 512 ///< Physical disk block size
#define PHY_BLOCK_SIZE 4096 ///< Physical disk block size
// 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 4096 ///< Physical disk block size
#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 INCLUDE_REM 1 ///< Include REM buffer to total size calculation
......
......@@ -298,71 +298,71 @@ int camogm_frame_jpeg(camogm_state *state)
} else {
sprintf(state->path, "%s%d_%010ld_%06ld.jpeg", state->path_prefix, port, state->this_frame_params[port].timestamp_sec, state->this_frame_params[port].timestamp_usec);
}
if (!state->rawdev_op) {
l = 0;
for (i = 0; i < (state->chunk_index) - 1; i++) {
chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
l += chunks_iovec[i].iov_len;
}
if (((state->ivf = open(state->path, O_RDWR | O_CREAT, 0777))) < 0) {
D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path, state->ivf, errno));
return -CAMOGM_FRAME_FILE_ERR;
}
iovlen = writev(state->ivf, chunks_iovec, (state->chunk_index) - 1);
if (iovlen < l) {
j = errno;
D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
close(state->ivf);
return -CAMOGM_FRAME_FILE_ERR;
}
state->rawdev.last_jpeg_size = l;
close(state->ivf);
} else {
D3(fprintf(debug_file, "_12.7_ camogm_frame_jpeg(): %ld.%06ld:%d @ %06d\n",state->this_frame_params[port].timestamp_sec, state->this_frame_params[port].timestamp_usec, port, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "\ndump iovect array for port %u\n", state->port_num));
for (int i = 0; i < state->chunk_index - 1; i++) {
D6(fprintf(debug_file, "ptr: %p, length: %ld\n", state->packetchunks[i + 1].chunk, state->packetchunks[i + 1].bytes));
}
// next frame is ready for recording, signal this to the writer thread
D6(fprintf(debug_file, "_13__: Yielding thread before getting a lock (%d, %d):%d @ %06d\n", state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, state->writer_params.writev_run, get_fpga_usec(state->fd_fparmsall[0], 0)));
pthread_yield();
pthread_mutex_lock(&state->writer_params.writer_mutex);
D6(fprintf(debug_file, "_13a_: waiting for empty buffer (%d, %d):%d @ %06d\n", state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, state->writer_params.writev_run, get_fpga_usec(state->fd_fparmsall[0], 0)));
// do not run ahead by >= FILE_CHUNKS_PAGES (0 or 1 for just FILE_CHUNKS_PAGES == 2)
// either buffer is completely empty (state->writer_params->chunk_page_prep == state->writer_params->chunk_page_write)
// or it is not full and writev_run is active
while (((state->writer_params.chunk_page_prep - state->writer_params.chunk_page_write + (2 * FILE_CHUNKS_PAGES))
% (2 * FILE_CHUNKS_PAGES) >= FILE_CHUNKS_PAGES) ||
(!state->writer_params.writev_run && (state->writer_params.chunk_page_prep != state->writer_params.chunk_page_write))) {
D6(fprintf(debug_file, "_13b_: waiting for empty buffer (%d, %d):%d @ %06d\n", state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, state->writer_params.writev_run, get_fpga_usec(state->fd_fparmsall[0], 0)));
pthread_cond_wait(&state->writer_params.main_cond, &state->writer_params.writer_mutex);
}
pthread_mutex_unlock(&state->writer_params.writer_mutex);
D6(fprintf(debug_file, "_13c_: got empty buffer (%d, %d):%d @ %06d\n", state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, state->writer_params.writev_run, get_fpga_usec(state->fd_fparmsall[0], 0)));
align_frame(state);
// proceed if last frame was recorded without errors
D6(fprintf(debug_file, "_13d_:frame aligned @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
pthread_mutex_lock(&state->writer_params.writer_mutex);
if (state->writer_params.last_ret_val == 0) {
state->writer_params.chunk_page_prep = (state->writer_params.chunk_page_prep + 1) % (2 * FILE_CHUNKS_PAGES);
// state->writer_params.data_ready = true;
pthread_cond_signal(&state->writer_params.writer_cond);
D6(fprintf(debug_file, "_13e_: chunk_page_prep = %d (%d), signal writer_cond @ %06d\n",state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, get_fpga_usec(state->fd_fparmsall[0], 0)));
}
pthread_mutex_unlock(&state->writer_params.writer_mutex);
if (state->writer_params.last_ret_val != 0) {
return state->writer_params.last_ret_val;
}
// update status file if time has come
curr_time = time(NULL);
if (difftime(curr_time, state->writer_params.stat_update) > STAT_UPDATE_PERIOD) {
save_state_file(state);
D6(fprintf(debug_file, "_13f_: saved state file @ %06d\n", get_fpga_usec(state->fd_fparmsall[0], 0)));
}
}
if (!state->rawdev_op) {
l = 0;
for (i = 0; i < (state->chunk_index) - 1; i++) {
chunks_iovec[i].iov_base = state->packetchunks[i + 1].chunk;
chunks_iovec[i].iov_len = state->packetchunks[i + 1].bytes;
l += chunks_iovec[i].iov_len;
}
if (((state->ivf = open(state->path, O_RDWR | O_CREAT, 0777))) < 0) {
D0(fprintf(debug_file, "Error opening %s for writing, returned %d, errno=%d\n", state->path, state->ivf, errno));
return -CAMOGM_FRAME_FILE_ERR;
}
iovlen = writev(state->ivf, chunks_iovec, (state->chunk_index) - 1);
if (iovlen < l) {
j = errno;
D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
close(state->ivf);
return -CAMOGM_FRAME_FILE_ERR;
}
state->rawdev.last_jpeg_size = l;
close(state->ivf);
} else {
D3(fprintf(debug_file, "_12.7_ camogm_frame_jpeg(): %ld.%06ld:%d @ %07d\n",state->this_frame_params[port].timestamp_sec, state->this_frame_params[port].timestamp_usec, port, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "\ndump iovect array for port %u\n", state->port_num));
for (int i = 0; i < state->chunk_index - 1; i++) {
D6(fprintf(debug_file, "ptr: %p, length: %ld\n", state->packetchunks[i + 1].chunk, state->packetchunks[i + 1].bytes));
}
// next frame is ready for recording, signal this to the writer thread
D6(fprintf(debug_file, "_13__: Yielding thread before getting a lock (%d, %d):%d @ %07d\n", state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, state->writer_params.writev_run, get_fpga_usec(state->fd_fparmsall[0], 0)));
pthread_yield();
pthread_mutex_lock(&state->writer_params.writer_mutex);
D6(fprintf(debug_file, "_13a_: waiting for empty buffer (%d, %d):%d @ %07d\n", state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, state->writer_params.writev_run, get_fpga_usec(state->fd_fparmsall[0], 0)));
// do not run ahead by >= FILE_CHUNKS_PAGES (0 or 1 for just FILE_CHUNKS_PAGES == 2)
// either buffer is completely empty (state->writer_params->chunk_page_prep == state->writer_params->chunk_page_write)
// or it is not full and writev_run is active
while (((state->writer_params.chunk_page_prep - state->writer_params.chunk_page_write + (2 * FILE_CHUNKS_PAGES))
% (2 * FILE_CHUNKS_PAGES) >= FILE_CHUNKS_PAGES) ||
(!state->writer_params.writev_run && (state->writer_params.chunk_page_prep != state->writer_params.chunk_page_write))) {
D6(fprintf(debug_file, "_13b_: waiting for empty buffer (%d, %d):%d @ %07d\n", state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, state->writer_params.writev_run, get_fpga_usec(state->fd_fparmsall[0], 0)));
pthread_cond_wait(&state->writer_params.main_cond, &state->writer_params.writer_mutex);
}
pthread_mutex_unlock(&state->writer_params.writer_mutex);
D6(fprintf(debug_file, "_13c_: got empty buffer (%d, %d):%d @ %07d\n", state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, state->writer_params.writev_run, get_fpga_usec(state->fd_fparmsall[0], 0)));
align_frame(state);
// proceed if last frame was recorded without errors
D6(fprintf(debug_file, "_13d_:frame aligned @ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
pthread_mutex_lock(&state->writer_params.writer_mutex);
if (state->writer_params.last_ret_val == 0) {
state->writer_params.chunk_page_prep = (state->writer_params.chunk_page_prep + 1) % (2 * FILE_CHUNKS_PAGES);
// state->writer_params.data_ready = true;
pthread_cond_signal(&state->writer_params.writer_cond);
D6(fprintf(debug_file, "_13e_: chunk_page_prep = %d (%d), signal writer_cond @ %07d\n",state->writer_params.chunk_page_prep, state->writer_params.chunk_page_write, get_fpga_usec(state->fd_fparmsall[0], 0)));
}
pthread_mutex_unlock(&state->writer_params.writer_mutex);
if (state->writer_params.last_ret_val != 0) {
return state->writer_params.last_ret_val;
}
// update status file if time has come
curr_time = time(NULL);
if (difftime(curr_time, state->writer_params.stat_update) > STAT_UPDATE_PERIOD) {
save_state_file(state);
D6(fprintf(debug_file, "_13f_: saved state file @ %07d\n", get_fpga_usec(state->fd_fparmsall[0], 0)));
}
}
return 0;
return 0;
}
/**
......@@ -382,7 +382,7 @@ int camogm_end_jpeg(camogm_state *state) // TODO: Resolve multippage !
// write any remaining data, do not use writer thread as there can be only one block left CHUNK_REM buffer
pthread_mutex_lock(&state->writer_params.writer_mutex);
// while (state->writer_params.data_ready)
// while (state->writer_params.data_ready)
while (state->writer_params.chunk_page_prep != state->writer_params.chunk_page_write)
// wait for previous frame to be recorded first if it has not be recorded by the moment
pthread_cond_wait(&state->writer_params.main_cond, &state->writer_params.writer_mutex);
......@@ -401,8 +401,8 @@ int camogm_end_jpeg(camogm_state *state) // TODO: Resolve multippage !
state->writer_params.lba_current += 1;
state->rawdev.total_rec_len += bytes;
}
// reset_chunks(state->writer_params.data_chunks, 1);
//*************** See if another buffer(s) must be cleared too? or even use chunk_page_write
// reset_chunks(state->writer_params.data_chunks, 1);
//*************** See if another buffer(s) must be cleared too? or even use chunk_page_write
reset_chunks(state, 1, state->writer_params.chunk_page_prep % FILE_CHUNKS_PAGES);
}
pthread_mutex_unlock(&state->writer_params.writer_mutex);
......@@ -426,6 +426,7 @@ int camogm_end_jpeg(camogm_state *state) // TODO: Resolve multippage !
void *jpeg_writer(void *thread_args)
{
int dbg_us1, dbg_us2, dbg_us; // save usec for difference
long dbg_pos;
int reset_rem;
int chunk_index, i0, i1;
ssize_t iovlen, l, ll, l0, l1, blocks_write, wpage;
......@@ -441,7 +442,7 @@ void *jpeg_writer(void *thread_args)
// lock, will only allow main thread while a) waiting for write buffer, and b) waiting for writev
//// pthread_mutex_lock(&params->writer_mutex);
params->state = STATE_RUNNING;
D6(fprintf(debug_file, "_w000_: Before jpeg_writer loop @ %06d\n", get_fpga_usec(state->fd_fparmsall[0], 0))); // before the debug file is set !
D6(fprintf(debug_file, "_w000_: Before jpeg_writer loop @ %07d\n", get_fpga_usec(state->fd_fparmsall[0], 0))); // before the debug file is set !
while (process) {
/*
while (!params->data_ready && !params->exit_thread) {
......@@ -449,7 +450,7 @@ void *jpeg_writer(void *thread_args)
} // get rid of params->data_ready
*/
pthread_mutex_lock(&params->writer_mutex); // first time before the debug file is set !
D6(fprintf(debug_file, "_w00_: (%d, %d) @ %06d\n", params->chunk_page_prep, params->chunk_page_write, get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_w00_: (%d, %d) @ %07d\n", params->chunk_page_prep, params->chunk_page_write, get_fpga_usec(state->fd_fparmsall[0], 0)));
while ((params->chunk_page_prep == params->chunk_page_write) && !params->exit_thread) {
pthread_cond_wait(&params->writer_cond, &params->writer_mutex);
}
......@@ -459,10 +460,10 @@ void *jpeg_writer(void *thread_args)
}
has_data_to_write = params->chunk_page_prep != params->chunk_page_write;
pthread_mutex_unlock(&params->writer_mutex);
D6(fprintf(debug_file, "_w00.5_: (%d, %d) @ %06d\n", params->chunk_page_prep, params->chunk_page_write,get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_w00.5_: (%d, %d) @ %07d\n", params->chunk_page_prep, params->chunk_page_write,get_fpga_usec(state->fd_fparmsall[0], 0)));
// if (params->data_ready) {
if (has_data_to_write) {
D6(fprintf(debug_file, "_w01_: got write data (%d > %d) @ %06d\n", params->chunk_page_prep, params->chunk_page_write,get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_w01_: got write data (%d > %d) @ %07d\n", params->chunk_page_prep, params->chunk_page_write,get_fpga_usec(state->fd_fparmsall[0], 0)));
/* dummy read cycle from (approximately) the beginning of previous frame;
* this is a debug feature used to find disk errors */
/*//temporary disable for simplicity 05/21/2023
......@@ -493,20 +494,24 @@ void *jpeg_writer(void *thread_args)
l += chunks_iovec[wpage][i].iov_len;
// Moved rollover here
blocks_write = l / PHY_BLOCK_SIZE;
if (state->writer_params.lba_current + blocks_write <= state->writer_params.lba_end) { // almost always - single write
state->writer_params.lba_current += blocks_write;
// D6(fprintf(debug_file, "_w02_: starting writev @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D3(dbg_us1=get_fpga_usec(state->fd_fparmsall[0], 0));
D6(fprintf(debug_file, "_w02_: starting writev @ %06d\n",dbg_us1));
state->writer_params.writev_run = true;
pthread_cond_signal(&params->main_cond);
iovlen = writev(state->writer_params.blockdev_fd, chunks_iovec[wpage], chunk_index);
state->writer_params.writev_run = false;
// D6(fprintf(debug_file, "_w03_: finished writev @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D3(dbg_us=get_fpga_usec(state->fd_fparmsall[0], 0); fprintf(debug_file, "_w03_: finished writev @ %06d (+ %06d, +%06d)\n",dbg_us, (dbg_us-dbg_us1), (dbg_us-dbg_us2)); dbg_us2=dbg_us);
if (iovlen < l) {
D0(fprintf(debug_file, "writev error: %s (returned %i, expected %i)\n", strerror(errno), iovlen, l));
state->writer_params.last_ret_val = -CAMOGM_FRAME_FILE_ERR;
if (state->writer_params.lba_current + blocks_write <= state->writer_params.lba_end) { // almost always - single write
state->writer_params.lba_current += blocks_write;
// D6(fprintf(debug_file, "_w02_: starting writev @ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
// D3(dbg_us1=get_fpga_usec(state->fd_fparmsall[0], 0); dbg_pos = lseek(state->writer_params.blockdev_fd, 0, SEEK_CUR));
D3(dbg_us1=get_fpga_usec(state->fd_fparmsall[0], 0));
D6(dbg_pos = lseek(state->writer_params.blockdev_fd, 0, SEEK_CUR));
D6(fprintf(debug_file, "_w02_: starting writev@ %07d\n", dbg_us1));
state->writer_params.writev_run = true;
pthread_cond_signal(&params->main_cond);
iovlen = writev(state->writer_params.blockdev_fd, chunks_iovec[wpage], chunk_index);
state->writer_params.writev_run = false;
// D6(fprintf(debug_file, "_w03_: finished writev @ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D3(dbg_us=get_fpga_usec(state->fd_fparmsall[0], 0); fprintf(debug_file, "_w03_: finished writev, pos%%block = %ld, pos= %ld @ %07d (+ %07d, +%07d)\n",dbg_pos % PHY_BLOCK_SIZE, dbg_pos,dbg_us, (dbg_us-dbg_us1), (dbg_us-dbg_us2)));
D3(syslog (LOG_INFO, "_w03_: finished writev, pos= %ld @ %07d (+ %07d, +%07d)", dbg_pos, dbg_us, (dbg_us-dbg_us1), (dbg_us-dbg_us2)));
D3(dbg_us2=dbg_us);
if (iovlen < l) {
D0(fprintf(debug_file, "writev error: %s (returned %i, expected %i)\n", strerror(errno), iovlen, l));
state->writer_params.last_ret_val = -CAMOGM_FRAME_FILE_ERR;
reset_rem = 1;
lseek(state->writer_params.blockdev_fd,
(state->writer_params.lba_current - state->writer_params.lba_start) * PHY_BLOCK_SIZE,
......@@ -549,7 +554,7 @@ void *jpeg_writer(void *thread_args)
state->writer_params.last_ret_val = -CAMOGM_FRAME_FILE_ERR;
reset_rem = 1;
} else {
// do not update statistic after the first writed, do it after the second
// do not update statistic after the first writev(), do it after the second
D6(fprintf(debug_file, "(1 of 2) Current position in block device: %lld\n", lseek64(state->writer_params.blockdev_fd, 0, SEEK_CUR)));
// update split chunk to use its second part, shift chunks
if (l1 > 0) { // length to be written after rollover
......@@ -582,7 +587,7 @@ void *jpeg_writer(void *thread_args)
}
}
}
D6(fprintf(debug_file, "_w04: wrote data @ %06d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_w04: wrote data @ %07d\n",get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_w05_: Block device positions: start = %llu, current = %llu, end = %llu\n",
state->writer_params.lba_start, state->writer_params.lba_current, state->writer_params.lba_end));
} else {
......@@ -600,9 +605,9 @@ void *jpeg_writer(void *thread_args)
// params->data_ready = false;
if (params->chunk_page_prep == params->chunk_page_write) {
pthread_cond_signal(&params->main_cond); // ********** Do not signal if can write more !
D6(fprintf(debug_file, "_w06_: wrote data (%d , %d), buffer empty, signal main thread @ %06d\n", params->chunk_page_prep, params->chunk_page_write,get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_w06_: wrote data (%d , %d), buffer empty, signal main thread @ %07d\n", params->chunk_page_prep, params->chunk_page_write,get_fpga_usec(state->fd_fparmsall[0], 0)));
} else {
D6(fprintf(debug_file, "_w06a_: wrote data (%d , %d), has more to write, do not signal! @ %06d\n", params->chunk_page_prep, params->chunk_page_write,get_fpga_usec(state->fd_fparmsall[0], 0)));
D6(fprintf(debug_file, "_w06a_: wrote data (%d , %d), has more to write, do not signal! @ %07d\n", params->chunk_page_prep, params->chunk_page_write,get_fpga_usec(state->fd_fparmsall[0], 0)));
}
pthread_mutex_unlock(&params->writer_mutex); // do not release untill waiting for writev() or waiting for data to write
......
......@@ -68,15 +68,25 @@
*!
*/
define('SSD_ROOT', '/mnt/sda1/');
define('ASSUME_EXT4', 'sda1'); // comment out after testing
define('USE_SYSLOG', 1);
$cmd = $_GET['cmd'];
$debug = $_GET['debug'];
$debuglev = $_GET['debuglev'];
$cmd_pipe = "/var/state/camogm_cmd";
$cmd_state = "/var/state/camogm.state";
$cmd_port = "3456";
$default_state = "/home/root/camogm.disk";
$state_file = "/mnt/sda1/camogm.disk";
//$default_state = "/home/root/camogm.disk";
$default_state = "/etc/elphel393/camogm.disk";
//$state_file = "/mnt/sda1/camogm.disk";
$state_file = "/etc/elphel393/camogm.disk";
$start_str = "camogm -n " . $cmd_pipe . " -p " . $cmd_port;
if (defined('USE_SYSLOG')) {
syslog(LOG_NOTICE, "camogm_interface.php:");
foreach ($_GET as $k => $v){
syslog(LOG_NOTICE, $k ." -> ".$v);
}
}
function check_camogm_running(){
global $start_str;
......@@ -128,7 +138,9 @@ if ($cmd == "run_camogm")
}
// set fast recording mode if there is at least one suitable partition or revert to legacy 'mov' mode
if (defined('USE_SYSLOG')) syslog(LOG_NOTICE, "before get_raw_dev()");
$partitions = get_raw_dev();
if (defined('USE_SYSLOG')) syslog(LOG_NOTICE, "after get_raw_dev()");
if (!empty($partitions)) {
reset($partitions);
$cmd_str = 'format=jpeg;' . 'rawdev_path=' . key($partitions) . ';';
......@@ -193,6 +205,9 @@ else if ($cmd == "run_status")
else if ($cmd=="get_hdd_space"){
if (isset($_GET['mountpoint']))
$mountpoint = $_GET['mountpoint'];
if (!$mountpoint){
$mountpoint = '/mnt/sda1';
}
else
$mountpoint = '/mnt/sda1';
// make sure something is mounted on mountpoint
......@@ -750,7 +765,15 @@ function get_mnt_dev()
foreach ($partitions as $partition => $size) {
$res = array();
$dev = "/dev/" . $partition;
exec("blkid " . $dev, $res);
if (!empty(ASSUME_EXT4)) { // avoiding I/O operations with /dev/sda
if ($partition == ASSUME_EXT4) {
$res = "ext4";
} else {
$res = "";
}
} else {
exec("blkid " . $dev, $res);
}
if (!empty($res)) {
$devices[$i] = preg_replace('/: +.*/', "", $res[0]);
if (preg_match('/(?<=TYPE=")[a-z0-9]+(?=")/', $res[0], $fs) == 1)
......
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