Loading camogm.c +65 −40 Original line number Diff line number Diff line Loading @@ -183,6 +183,11 @@ unsigned long *aglobalPars[SENSOR_PORTS]; /// parameters that are not camogm_state sstate; //camogm_state * state; typedef enum { RAW_PATH, FILE_PATH } path_type; int debug_level; FILE* debug_file; Loading @@ -198,7 +203,7 @@ void camogm_set_greedy(camogm_state *state, int d); void camogm_set_ignore_fps(camogm_state *state, int d); void camogm_set_save_gp(camogm_state *state, int d); void camogm_set_prefix(camogm_state *state, const char * p); void camogm_set_prefix(camogm_state *state, const char * p, path_type type); void camogm_set_exif(camogm_state *state, int d); void camogm_set_timescale(camogm_state *state, double d); //! set timescale, default=1.0 void camogm_set_frames_skip(camogm_state *state, int d); //! set number of frames to skip, if negative - seconds between frames Loading Loading @@ -280,52 +285,53 @@ void camogm_init(camogm_state *state, unsigned int port, char *pipe_name) const char sserial[] = "elp0"; int * ipser = (int*)sserial; state->running = 0; // mo state->starting = 0; // mo state->vf = NULL; memset(state, 0, sizeof(camogm_state)); // state->running = 0; // mo // state->starting = 0; // mo // state->vf = NULL; camogm_set_segment_duration(state, DEFAULT_DURATION); camogm_set_segment_length(state, DEFAULT_LENGTH); camogm_set_greedy(state, DEFAULT_GREEDY); camogm_set_ignore_fps(state, DEFAULT_IGNORE_FPS); camogm_set_max_frames(state, DEFAULT_FRAMES); camogm_set_frames_per_chunk(state, DEFAULT_FRAMES_PER_CHUNK); camogm_set_start_after_timestamp(state, 0.0); // start any time camogm_set_prefix(state, "\0"); camogm_set_save_gp(state, 0); // camogm_set_start_after_timestamp(state, 0.0); // start any time // camogm_set_prefix(state, "\0", FILE_PATH); // camogm_set_save_gp(state, 0); camogm_reset(state); // sets state->buf_overruns =- 1 state->serialno = ipser[0]; state->last = 0; // state->last = 0; debug_file = stderr; camogm_debug_level(DEFAULT_DEBUG_LVL); strcpy(state->debug_name, "stderr"); camogm_set_timescale(state, 1.0); camogm_set_frames_skip(state, 0); // don't skip camogm_set_format(state, CAMOGM_FORMAT_MOV); FOR_EACH_PORT(int, chn) {state->exifSize[chn] = 0;} // FOR_EACH_PORT(int, chn) {state->exifSize[chn] = 0;} state->exif = DEFAULT_EXIF; state->frame_lengths = NULL; state->frameno = 0; state->formats = 0; state->last_error_code = 0; // state->frameno = 0; // state->formats = 0; // state->last_error_code = 0; // kml stuff camogm_kml_set_enable(state, 0); state->kml_file = NULL; // camogm_kml_set_enable(state, 0); // state->kml_file = NULL; camogm_kml_set_horHalfFov(state, 20.0); camogm_kml_set_vertHalfFov(state, 15.0); camogm_kml_set_height_mode(state, 0); camogm_kml_set_height(state, 10.0); camogm_kml_set_period(state, 2); // 2 sec camogm_kml_set_near(state, 40.0); // 40 m (distance to PhotoOverlay) state->kml_path[0] = '\0'; // state->kml_path[0] = '\0'; state->port_num = port; state->pipe_name = pipe_name; state->rawdev.start_pos = RAWDEV_START_OFFSET; state->rawdev.end_pos = state->rawdev.start_pos; state->rawdev.curr_pos = state->rawdev.start_pos; state->rawdev.overrun = 0; state->rawdev_op = 0; // state->rawdev.overrun = 0; // state->rawdev_op = 0; state->active_chn = ALL_CHN_ACTIVE; } Loading Loading @@ -366,8 +372,12 @@ int camogm_start(camogm_state *state) int port = state->port_num; if (state->active_chn == ALL_CHN_INACTIVE) { D1(fprintf(debug_file, "All channels are disabled, will not start\n")); return 0; D0(fprintf(debug_file, "All channels are disabled, will not start\n")); return CAMOGM_FRAME_OTHER; } if (state->rawdev_op && state->format != CAMOGM_FORMAT_JPEG) { D0(fprintf(debug_file, "Raw device write initiated, but file format is not JPEG. Will not start\n")); return CAMOGM_FRAME_OTHER; } D1(fprintf(debug_file, "Starting recording\n")); Loading @@ -384,7 +394,7 @@ int camogm_start(camogm_state *state) switch (state->format) { case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_OGM: rslt = camogm_init_ogm(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(state); break; case CAMOGM_FORMAT_MOV: rslt = camogm_init_mov(); break; } state->formats |= 1 << (state->format); Loading Loading @@ -841,26 +851,27 @@ void camogm_set_ignore_fps(camogm_state *state, int d) state->ignore_fps = d ? 1 : 0; } void camogm_set_prefix(camogm_state *state, const char * p) void camogm_set_prefix(camogm_state *state, const char * p, path_type type) { if (type == FILE_PATH) { strncpy(state->path_prefix, p, sizeof(state->path_prefix) - 1); state->path_prefix[sizeof(state->path_prefix) - 1] = '\0'; // check if we are going to write to raw device if (strncmp("/dev/", state->path_prefix, 5) == 0) { state->rawdev.end_pos = get_disk_size(state->path_prefix); } else if (type == RAW_PATH && (strncmp(p, "/dev/", 5) == 0)) { strncpy(state->rawdev.rawdev_path, p, sizeof(state->rawdev.rawdev_path) - 1); state->rawdev.rawdev_path[sizeof(state->rawdev.rawdev_path) - 1] = '\0'; state->rawdev.end_pos = get_disk_size(state->rawdev.rawdev_path); if (state->rawdev.end_pos == 0) { state->rawdev_op = 0; state->rawdev.end_pos = state->rawdev.start_pos; state->path_prefix[0] = '\0'; printf("ERROR: unable to initiate raw device operation\n"); state->rawdev.rawdev_path[0] = '\0'; D0(fprintf(debug_file, "ERROR: unable to initiate raw device operation\n")); } else { printf("WARNING: raw device write initiated\n"); D0(fprintf(debug_file, "WARNING: raw device write initiated\n")); state->rawdev_op = 1; /* debug code follows */ state->rawdev.end_pos = state->rawdev.start_pos + 10485760; // 10Mib size state->rawdev.end_pos = 20971520; // 20Mib size /* end of debug code */ } } else { state->rawdev_op = 0; } } Loading Loading @@ -892,7 +903,7 @@ void camogm_set_format(camogm_state *state, int d) switch (state->format) { case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_OGM: rslt = camogm_init_ogm(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(state); break; case CAMOGM_FORMAT_MOV: rslt = camogm_init_mov(); break; } if (rslt) { Loading Loading @@ -1021,7 +1032,9 @@ void camogm_status(camogm_state *state, char * fn, int xml) " <kml_period>%d</kml_period>\n" \ " <kml_last_ts>%d.%06d</kml_last_ts>\n" \ " <greedy>\"%s\"</greedy>\n" \ " <ignore_fps>\"%s\"</ignore_fps>\n", " <ignore_fps>\"%s\"</ignore_fps>\n" \ " <raw_device_path>\"%s\"</raw_device_path>\n" \ " <raw_device_overruns>%d</raw_device_overruns>\n", _state, state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \ _frames_skip, _sec_skip, \ state->width, state->height, _output_format, _using_exif, \ Loading @@ -1030,7 +1043,8 @@ void camogm_status(camogm_state *state, char * fn, int xml) state->debug_name, debug_level, _using_global_pointer, \ _kml_enable, _kml_used, state->kml_path, state->kml_horHalfFov, state->kml_vertHalfFov, state->kml_near, \ _kml_height_mode, state->kml_height, state->kml_period, state->kml_last_ts, state->kml_last_uts, \ state->greedy ? "yes" : "no", state->ignore_fps ? "yes" : "no"); state->greedy ? "yes" : "no", state->ignore_fps ? "yes" : "no", state->rawdev.rawdev_path, state->rawdev.overrun); FOR_EACH_PORT(int, chn) { char *_active = is_chn_active(state, chn) ? "yes" : "no"; Loading Loading @@ -1076,9 +1090,11 @@ void camogm_status(camogm_state *state, char * fn, int xml) fprintf(f, "\n"); fprintf(f, "output format \t%s\n", _output_format); fprintf(f, "using exif \t%s\n", _using_exif); fprintf(f, "path prefix: \t%s\n", state->path_prefix); fprintf(f, "max file duration: \t%d sec\n", state->segment_duration); fprintf(f, "max file length: \t%d B\n", state->segment_length); fprintf(f, "path prefix \t%s\n", state->path_prefix); fprintf(f, "raw device path \t%s\n", state->rawdev.rawdev_path); fprintf(f, "raw device overruns\t%d\n", state->rawdev.overrun); fprintf(f, "max file duration \t%d sec\n", state->segment_duration); fprintf(f, "max file length \t%d B\n", state->segment_length); fprintf(f, "max frames \t%d\n", state->max_frames); fprintf(f, "timescale \t%f\n", state->timescale); fprintf(f, "frames per chunk \t%d\n", state->frames_per_chunk); Loading Loading @@ -1217,7 +1233,7 @@ int parse_cmd(camogm_state *state, FILE* npipe) camogm_set_segment_length(state, d); return 5; } else if (strcmp(cmd, "prefix") == 0) { if (args) camogm_set_prefix(state, args); if (args) camogm_set_prefix(state, args, FILE_PATH); return 6; } else if (strcmp(cmd, "status") == 0) { camogm_status(state, args, 0); Loading Loading @@ -1319,6 +1335,14 @@ int parse_cmd(camogm_state *state, FILE* npipe) d = strtol(args, NULL, 10); set_chn_state(state, d, 0); return 27; } else if (strcmp(cmd, "rawdev_path") == 0) { if (args) { camogm_set_prefix(state, args, RAW_PATH); } else { state->rawdev_op = 0; state->rawdev.rawdev_path[0] = '\0'; } return 28; } return -1; Loading Loading @@ -1547,12 +1571,13 @@ inline int is_chn_active(camogm_state *s, unsigned int port) */ inline void set_chn_state(camogm_state *s, unsigned int port, unsigned int new_state) { if (port >= 0 && port < SENSOR_PORTS) if (port >= 0 && port < SENSOR_PORTS) { if (new_state) s->active_chn |= 1 << port; else s->active_chn &= ~(1 << port); } } /** * @brief Open files provided by circbuf driver. Loading camogm.h +5 −2 Original line number Diff line number Diff line Loading @@ -75,9 +75,12 @@ /** @brief Offset from the beginning of raw device buffer. Must be aligned to physical sector size */ #define RAWDEV_START_OFFSET 1024 /** @brief Maximum length of file or raw device path */ #define ELPHEL_PATH_MAX 300 typedef struct { int rawdev_fd; char rawdev_path[ELPHEL_PATH_MAX]; uint32_t overrun; uint64_t start_pos; uint64_t end_pos; Loading @@ -91,7 +94,7 @@ typedef struct { int ignore_fps; int save_gp; //if non zero, current circbuf pointer will be saved to global pointer, so imgsrv can report /pointers char path_prefix[256]; char path[300]; char path[ELPHEL_PATH_MAX]; int cirbuf_rp[SENSOR_PORTS]; //!-1 - invalid int fd_circ[SENSOR_PORTS]; //! file descriptor for circbuf int fd_head[SENSOR_PORTS]; //! file descriptor for JPEG header Loading camogm_jpeg.c +74 −48 Original line number Diff line number Diff line Loading @@ -59,41 +59,31 @@ #include <c313a.h> #include <asm/byteorder.h> #include <assert.h> #include <ogg/ogg.h> // has to be before ogmstreams.h #include "ogmstreams.h" // move it to <>? #include "camogm_jpeg.h" /** @brief Size of iovec structures holding data to be written */ #define IOVEC_SIZE 10 /** @brief File starting marker, contains "stelphel" string in ASCII symbols */ unsigned char elphelst[] = {0x73, 0x74, 0x65, 0x6c, 0x70, 0x68, 0x65, 0x6c}; /** @brief File ending marker, contains "enelphel" string in ASCII symbols */ unsigned char elphelen[] = {0x65, 0x6e, 0x65, 0x6c, 0x70, 0x68, 0x65, 0x6c}; static struct iovec start_marker = { .iov_base = elphelst, .iov_len = sizeof(elphelst) }; static struct iovec end_marker = { .iov_base = elphelen, .iov_len = sizeof(elphelen) }; //! may add something - called first time format is changed to this one (only once) recording is stopped int camogm_init_jpeg(void) int camogm_init_jpeg(camogm_state *state) { return 0; } void camogm_free_jpeg(void) { } /** * @brief Called every time the JPEG files recording is started. * * This function checks if the raw device write is initiated and tries to open the device specified. The device * will be closed in #camogm_end_jpeg function. * @param[in] state a pointer to a structure containing current state * @return 0 if the device was opened successfully and negative error code otherwise */ int camogm_start_jpeg(camogm_state *state) { //!TODO: make directory if it does not exist (find the last "/" in the state->path char * slash; int rslt; Loading @@ -113,22 +103,32 @@ int camogm_start_jpeg(camogm_state *state) } } } else { state->ivf = open(state->path_prefix, O_RDWR); if (state->ivf < 0) { if (state->rawdev_op) { state->rawdev.rawdev_fd = open(state->rawdev.rawdev_path, O_RDWR); if (state->rawdev.rawdev_fd < 0) { D0(perror(__func__)); D0(fprintf(debug_file, "Error opening raw device %s\n", state->path)); D0(fprintf(debug_file, "Error opening raw device %s\n", state->rawdev.rawdev_path)); return -CAMOGM_FRAME_FILE_ERR; } D0(fprintf(debug_file, "Open raw device %s; start_pos = %llu, end_pos = %llu, curr_pos = %llu\n", state->path, 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)); lseek64(state->ivf, state->rawdev.curr_pos, SEEK_SET); lseek64(state->rawdev.rawdev_fd, state->rawdev.curr_pos, SEEK_SET); } } return 0; } /** * @brief Write single JPEG frame * * This function will write single JPEG file * @param state a pointer to a structure containing current state * @return */ int camogm_frame_jpeg(camogm_state *state) { int i, j, split_index; int i, j, k, split_index; int chunks_used = state->chunk_index - 1; ssize_t iovlen, l = 0; struct iovec chunks_iovec[8]; Loading Loading @@ -160,7 +160,6 @@ int camogm_frame_jpeg(camogm_state *state) } else { D0(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, l)); l = 0; split_index = -1; for (int i = 0, total_len = 0; i < state->chunk_index - 1; i++) { total_len += state->packetchunks[i + 1].bytes; Loading @@ -171,34 +170,36 @@ int camogm_frame_jpeg(camogm_state *state) break; } } chunks_iovec[0] = start_marker; l += start_marker.iov_len; chunks_used++; for (int i = 1; i < chunks_used; i++) { 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); split_ptr = state->packetchunks[i].chunk + split_cntr; split_ptr = state->packetchunks[k].chunk + split_cntr; 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[i].chunk; 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[i].bytes - split_cntr; chunks_iovec[i].iov_len = state->packetchunks[k].bytes - split_cntr; l += chunks_iovec[i].iov_len; fprintf(debug_file, "Lump 1: size = %ld, start address = 0x%p\n", chunks_iovec[i - 1].iov_len, chunks_iovec[i - 1].iov_base); fprintf(debug_file, "Lump 2: size = %ld, start address = 0x%p\n\n", chunks_iovec[i].iov_len, chunks_iovec[i].iov_base); } else { chunks_iovec[i].iov_base = state->packetchunks[i].chunk; chunks_iovec[i].iov_len = state->packetchunks[i].bytes; chunks_iovec[i].iov_base = state->packetchunks[k].chunk; chunks_iovec[i].iov_len = state->packetchunks[k].bytes; l += chunks_iovec[i].iov_len; } } // consider start_marker here and increment chunks_used assert(chunks_used < IOVEC_SIZE); chunks_iovec[chunks_used] = end_marker; l += end_marker.iov_len; chunks_used++; /* debug code follows */ fprintf(debug_file, "\n=== raw device write, iovec dump ===\n"); Loading @@ -209,9 +210,24 @@ int camogm_frame_jpeg(camogm_state *state) fprintf(debug_file, "total len = %d\n======\n", l); /* end of debug code */ iovlen = writev(state->ivf, chunks_iovec, chunks_used); 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; } Loading @@ -224,9 +240,19 @@ int camogm_frame_jpeg(camogm_state *state) return 0; } /** * @brief Finish JPEG file write operation * * This function checks whether raw device write was on and closes raw device file. * @param state a pointer to a structure containing current state * @return 0 if the device was closed successfully and -1 otherwise */ int camogm_end_jpeg(camogm_state *state) { close(state->ivf); D0(fprintf(debug_file, "Closing raw device %s\n", state->path_prefix)); return 0; int ret = 0; if (state->rawdev_op) { ret = close(state->rawdev.rawdev_fd); D0(fprintf(debug_file, "Closing raw device %s\n", state->rawdev.rawdev_path)); } return ret; } camogm_jpeg.h +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ #include "camogm.h" int camogm_init_jpeg(void); int camogm_init_jpeg(camogm_state *state); int camogm_start_jpeg(camogm_state *state); int camogm_frame_jpeg(camogm_state *state); int camogm_end_jpeg(camogm_state *state); Loading camogm_ogm.c +2 −2 Original line number Diff line number Diff line Loading @@ -73,7 +73,7 @@ int camogm_start_ogm(camogm_state *state) char vendor[] = "ElphelOgm v 0.1"; int pos; stream_header sh; unsigned char hdbuf[sizeof(sh) + 1]; char hdbuf[sizeof(sh) + 1]; ogg_packet ogg_header; sprintf(state->path, "%s%010ld_%06ld.ogm", state->path_prefix, state->frame_params[state->port_num].timestamp_sec, state->frame_params[state->port_num].timestamp_usec); Loading Loading @@ -133,7 +133,7 @@ int camogm_start_ogm(camogm_state *state) pos += 4; hdbuf[pos++] = 1; //! put it into Ogg stream ogg_header.packet = hdbuf; ogg_header.packet = (unsigned char *)hdbuf; ogg_header.bytes = pos; ogg_header.b_o_s = 0; ogg_header.e_o_s = 0; Loading Loading
camogm.c +65 −40 Original line number Diff line number Diff line Loading @@ -183,6 +183,11 @@ unsigned long *aglobalPars[SENSOR_PORTS]; /// parameters that are not camogm_state sstate; //camogm_state * state; typedef enum { RAW_PATH, FILE_PATH } path_type; int debug_level; FILE* debug_file; Loading @@ -198,7 +203,7 @@ void camogm_set_greedy(camogm_state *state, int d); void camogm_set_ignore_fps(camogm_state *state, int d); void camogm_set_save_gp(camogm_state *state, int d); void camogm_set_prefix(camogm_state *state, const char * p); void camogm_set_prefix(camogm_state *state, const char * p, path_type type); void camogm_set_exif(camogm_state *state, int d); void camogm_set_timescale(camogm_state *state, double d); //! set timescale, default=1.0 void camogm_set_frames_skip(camogm_state *state, int d); //! set number of frames to skip, if negative - seconds between frames Loading Loading @@ -280,52 +285,53 @@ void camogm_init(camogm_state *state, unsigned int port, char *pipe_name) const char sserial[] = "elp0"; int * ipser = (int*)sserial; state->running = 0; // mo state->starting = 0; // mo state->vf = NULL; memset(state, 0, sizeof(camogm_state)); // state->running = 0; // mo // state->starting = 0; // mo // state->vf = NULL; camogm_set_segment_duration(state, DEFAULT_DURATION); camogm_set_segment_length(state, DEFAULT_LENGTH); camogm_set_greedy(state, DEFAULT_GREEDY); camogm_set_ignore_fps(state, DEFAULT_IGNORE_FPS); camogm_set_max_frames(state, DEFAULT_FRAMES); camogm_set_frames_per_chunk(state, DEFAULT_FRAMES_PER_CHUNK); camogm_set_start_after_timestamp(state, 0.0); // start any time camogm_set_prefix(state, "\0"); camogm_set_save_gp(state, 0); // camogm_set_start_after_timestamp(state, 0.0); // start any time // camogm_set_prefix(state, "\0", FILE_PATH); // camogm_set_save_gp(state, 0); camogm_reset(state); // sets state->buf_overruns =- 1 state->serialno = ipser[0]; state->last = 0; // state->last = 0; debug_file = stderr; camogm_debug_level(DEFAULT_DEBUG_LVL); strcpy(state->debug_name, "stderr"); camogm_set_timescale(state, 1.0); camogm_set_frames_skip(state, 0); // don't skip camogm_set_format(state, CAMOGM_FORMAT_MOV); FOR_EACH_PORT(int, chn) {state->exifSize[chn] = 0;} // FOR_EACH_PORT(int, chn) {state->exifSize[chn] = 0;} state->exif = DEFAULT_EXIF; state->frame_lengths = NULL; state->frameno = 0; state->formats = 0; state->last_error_code = 0; // state->frameno = 0; // state->formats = 0; // state->last_error_code = 0; // kml stuff camogm_kml_set_enable(state, 0); state->kml_file = NULL; // camogm_kml_set_enable(state, 0); // state->kml_file = NULL; camogm_kml_set_horHalfFov(state, 20.0); camogm_kml_set_vertHalfFov(state, 15.0); camogm_kml_set_height_mode(state, 0); camogm_kml_set_height(state, 10.0); camogm_kml_set_period(state, 2); // 2 sec camogm_kml_set_near(state, 40.0); // 40 m (distance to PhotoOverlay) state->kml_path[0] = '\0'; // state->kml_path[0] = '\0'; state->port_num = port; state->pipe_name = pipe_name; state->rawdev.start_pos = RAWDEV_START_OFFSET; state->rawdev.end_pos = state->rawdev.start_pos; state->rawdev.curr_pos = state->rawdev.start_pos; state->rawdev.overrun = 0; state->rawdev_op = 0; // state->rawdev.overrun = 0; // state->rawdev_op = 0; state->active_chn = ALL_CHN_ACTIVE; } Loading Loading @@ -366,8 +372,12 @@ int camogm_start(camogm_state *state) int port = state->port_num; if (state->active_chn == ALL_CHN_INACTIVE) { D1(fprintf(debug_file, "All channels are disabled, will not start\n")); return 0; D0(fprintf(debug_file, "All channels are disabled, will not start\n")); return CAMOGM_FRAME_OTHER; } if (state->rawdev_op && state->format != CAMOGM_FORMAT_JPEG) { D0(fprintf(debug_file, "Raw device write initiated, but file format is not JPEG. Will not start\n")); return CAMOGM_FRAME_OTHER; } D1(fprintf(debug_file, "Starting recording\n")); Loading @@ -384,7 +394,7 @@ int camogm_start(camogm_state *state) switch (state->format) { case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_OGM: rslt = camogm_init_ogm(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(state); break; case CAMOGM_FORMAT_MOV: rslt = camogm_init_mov(); break; } state->formats |= 1 << (state->format); Loading Loading @@ -841,26 +851,27 @@ void camogm_set_ignore_fps(camogm_state *state, int d) state->ignore_fps = d ? 1 : 0; } void camogm_set_prefix(camogm_state *state, const char * p) void camogm_set_prefix(camogm_state *state, const char * p, path_type type) { if (type == FILE_PATH) { strncpy(state->path_prefix, p, sizeof(state->path_prefix) - 1); state->path_prefix[sizeof(state->path_prefix) - 1] = '\0'; // check if we are going to write to raw device if (strncmp("/dev/", state->path_prefix, 5) == 0) { state->rawdev.end_pos = get_disk_size(state->path_prefix); } else if (type == RAW_PATH && (strncmp(p, "/dev/", 5) == 0)) { strncpy(state->rawdev.rawdev_path, p, sizeof(state->rawdev.rawdev_path) - 1); state->rawdev.rawdev_path[sizeof(state->rawdev.rawdev_path) - 1] = '\0'; state->rawdev.end_pos = get_disk_size(state->rawdev.rawdev_path); if (state->rawdev.end_pos == 0) { state->rawdev_op = 0; state->rawdev.end_pos = state->rawdev.start_pos; state->path_prefix[0] = '\0'; printf("ERROR: unable to initiate raw device operation\n"); state->rawdev.rawdev_path[0] = '\0'; D0(fprintf(debug_file, "ERROR: unable to initiate raw device operation\n")); } else { printf("WARNING: raw device write initiated\n"); D0(fprintf(debug_file, "WARNING: raw device write initiated\n")); state->rawdev_op = 1; /* debug code follows */ state->rawdev.end_pos = state->rawdev.start_pos + 10485760; // 10Mib size state->rawdev.end_pos = 20971520; // 20Mib size /* end of debug code */ } } else { state->rawdev_op = 0; } } Loading Loading @@ -892,7 +903,7 @@ void camogm_set_format(camogm_state *state, int d) switch (state->format) { case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_OGM: rslt = camogm_init_ogm(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(); break; case CAMOGM_FORMAT_JPEG: rslt = camogm_init_jpeg(state); break; case CAMOGM_FORMAT_MOV: rslt = camogm_init_mov(); break; } if (rslt) { Loading Loading @@ -1021,7 +1032,9 @@ void camogm_status(camogm_state *state, char * fn, int xml) " <kml_period>%d</kml_period>\n" \ " <kml_last_ts>%d.%06d</kml_last_ts>\n" \ " <greedy>\"%s\"</greedy>\n" \ " <ignore_fps>\"%s\"</ignore_fps>\n", " <ignore_fps>\"%s\"</ignore_fps>\n" \ " <raw_device_path>\"%s\"</raw_device_path>\n" \ " <raw_device_overruns>%d</raw_device_overruns>\n", _state, state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \ _frames_skip, _sec_skip, \ state->width, state->height, _output_format, _using_exif, \ Loading @@ -1030,7 +1043,8 @@ void camogm_status(camogm_state *state, char * fn, int xml) state->debug_name, debug_level, _using_global_pointer, \ _kml_enable, _kml_used, state->kml_path, state->kml_horHalfFov, state->kml_vertHalfFov, state->kml_near, \ _kml_height_mode, state->kml_height, state->kml_period, state->kml_last_ts, state->kml_last_uts, \ state->greedy ? "yes" : "no", state->ignore_fps ? "yes" : "no"); state->greedy ? "yes" : "no", state->ignore_fps ? "yes" : "no", state->rawdev.rawdev_path, state->rawdev.overrun); FOR_EACH_PORT(int, chn) { char *_active = is_chn_active(state, chn) ? "yes" : "no"; Loading Loading @@ -1076,9 +1090,11 @@ void camogm_status(camogm_state *state, char * fn, int xml) fprintf(f, "\n"); fprintf(f, "output format \t%s\n", _output_format); fprintf(f, "using exif \t%s\n", _using_exif); fprintf(f, "path prefix: \t%s\n", state->path_prefix); fprintf(f, "max file duration: \t%d sec\n", state->segment_duration); fprintf(f, "max file length: \t%d B\n", state->segment_length); fprintf(f, "path prefix \t%s\n", state->path_prefix); fprintf(f, "raw device path \t%s\n", state->rawdev.rawdev_path); fprintf(f, "raw device overruns\t%d\n", state->rawdev.overrun); fprintf(f, "max file duration \t%d sec\n", state->segment_duration); fprintf(f, "max file length \t%d B\n", state->segment_length); fprintf(f, "max frames \t%d\n", state->max_frames); fprintf(f, "timescale \t%f\n", state->timescale); fprintf(f, "frames per chunk \t%d\n", state->frames_per_chunk); Loading Loading @@ -1217,7 +1233,7 @@ int parse_cmd(camogm_state *state, FILE* npipe) camogm_set_segment_length(state, d); return 5; } else if (strcmp(cmd, "prefix") == 0) { if (args) camogm_set_prefix(state, args); if (args) camogm_set_prefix(state, args, FILE_PATH); return 6; } else if (strcmp(cmd, "status") == 0) { camogm_status(state, args, 0); Loading Loading @@ -1319,6 +1335,14 @@ int parse_cmd(camogm_state *state, FILE* npipe) d = strtol(args, NULL, 10); set_chn_state(state, d, 0); return 27; } else if (strcmp(cmd, "rawdev_path") == 0) { if (args) { camogm_set_prefix(state, args, RAW_PATH); } else { state->rawdev_op = 0; state->rawdev.rawdev_path[0] = '\0'; } return 28; } return -1; Loading Loading @@ -1547,12 +1571,13 @@ inline int is_chn_active(camogm_state *s, unsigned int port) */ inline void set_chn_state(camogm_state *s, unsigned int port, unsigned int new_state) { if (port >= 0 && port < SENSOR_PORTS) if (port >= 0 && port < SENSOR_PORTS) { if (new_state) s->active_chn |= 1 << port; else s->active_chn &= ~(1 << port); } } /** * @brief Open files provided by circbuf driver. Loading
camogm.h +5 −2 Original line number Diff line number Diff line Loading @@ -75,9 +75,12 @@ /** @brief Offset from the beginning of raw device buffer. Must be aligned to physical sector size */ #define RAWDEV_START_OFFSET 1024 /** @brief Maximum length of file or raw device path */ #define ELPHEL_PATH_MAX 300 typedef struct { int rawdev_fd; char rawdev_path[ELPHEL_PATH_MAX]; uint32_t overrun; uint64_t start_pos; uint64_t end_pos; Loading @@ -91,7 +94,7 @@ typedef struct { int ignore_fps; int save_gp; //if non zero, current circbuf pointer will be saved to global pointer, so imgsrv can report /pointers char path_prefix[256]; char path[300]; char path[ELPHEL_PATH_MAX]; int cirbuf_rp[SENSOR_PORTS]; //!-1 - invalid int fd_circ[SENSOR_PORTS]; //! file descriptor for circbuf int fd_head[SENSOR_PORTS]; //! file descriptor for JPEG header Loading
camogm_jpeg.c +74 −48 Original line number Diff line number Diff line Loading @@ -59,41 +59,31 @@ #include <c313a.h> #include <asm/byteorder.h> #include <assert.h> #include <ogg/ogg.h> // has to be before ogmstreams.h #include "ogmstreams.h" // move it to <>? #include "camogm_jpeg.h" /** @brief Size of iovec structures holding data to be written */ #define IOVEC_SIZE 10 /** @brief File starting marker, contains "stelphel" string in ASCII symbols */ unsigned char elphelst[] = {0x73, 0x74, 0x65, 0x6c, 0x70, 0x68, 0x65, 0x6c}; /** @brief File ending marker, contains "enelphel" string in ASCII symbols */ unsigned char elphelen[] = {0x65, 0x6e, 0x65, 0x6c, 0x70, 0x68, 0x65, 0x6c}; static struct iovec start_marker = { .iov_base = elphelst, .iov_len = sizeof(elphelst) }; static struct iovec end_marker = { .iov_base = elphelen, .iov_len = sizeof(elphelen) }; //! may add something - called first time format is changed to this one (only once) recording is stopped int camogm_init_jpeg(void) int camogm_init_jpeg(camogm_state *state) { return 0; } void camogm_free_jpeg(void) { } /** * @brief Called every time the JPEG files recording is started. * * This function checks if the raw device write is initiated and tries to open the device specified. The device * will be closed in #camogm_end_jpeg function. * @param[in] state a pointer to a structure containing current state * @return 0 if the device was opened successfully and negative error code otherwise */ int camogm_start_jpeg(camogm_state *state) { //!TODO: make directory if it does not exist (find the last "/" in the state->path char * slash; int rslt; Loading @@ -113,22 +103,32 @@ int camogm_start_jpeg(camogm_state *state) } } } else { state->ivf = open(state->path_prefix, O_RDWR); if (state->ivf < 0) { if (state->rawdev_op) { state->rawdev.rawdev_fd = open(state->rawdev.rawdev_path, O_RDWR); if (state->rawdev.rawdev_fd < 0) { D0(perror(__func__)); D0(fprintf(debug_file, "Error opening raw device %s\n", state->path)); D0(fprintf(debug_file, "Error opening raw device %s\n", state->rawdev.rawdev_path)); return -CAMOGM_FRAME_FILE_ERR; } D0(fprintf(debug_file, "Open raw device %s; start_pos = %llu, end_pos = %llu, curr_pos = %llu\n", state->path, 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)); lseek64(state->ivf, state->rawdev.curr_pos, SEEK_SET); lseek64(state->rawdev.rawdev_fd, state->rawdev.curr_pos, SEEK_SET); } } return 0; } /** * @brief Write single JPEG frame * * This function will write single JPEG file * @param state a pointer to a structure containing current state * @return */ int camogm_frame_jpeg(camogm_state *state) { int i, j, split_index; int i, j, k, split_index; int chunks_used = state->chunk_index - 1; ssize_t iovlen, l = 0; struct iovec chunks_iovec[8]; Loading Loading @@ -160,7 +160,6 @@ int camogm_frame_jpeg(camogm_state *state) } else { D0(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, l)); l = 0; split_index = -1; for (int i = 0, total_len = 0; i < state->chunk_index - 1; i++) { total_len += state->packetchunks[i + 1].bytes; Loading @@ -171,34 +170,36 @@ int camogm_frame_jpeg(camogm_state *state) break; } } chunks_iovec[0] = start_marker; l += start_marker.iov_len; chunks_used++; for (int i = 1; i < chunks_used; i++) { 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); split_ptr = state->packetchunks[i].chunk + split_cntr; split_ptr = state->packetchunks[k].chunk + split_cntr; 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[i].chunk; 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[i].bytes - split_cntr; chunks_iovec[i].iov_len = state->packetchunks[k].bytes - split_cntr; l += chunks_iovec[i].iov_len; fprintf(debug_file, "Lump 1: size = %ld, start address = 0x%p\n", chunks_iovec[i - 1].iov_len, chunks_iovec[i - 1].iov_base); fprintf(debug_file, "Lump 2: size = %ld, start address = 0x%p\n\n", chunks_iovec[i].iov_len, chunks_iovec[i].iov_base); } else { chunks_iovec[i].iov_base = state->packetchunks[i].chunk; chunks_iovec[i].iov_len = state->packetchunks[i].bytes; chunks_iovec[i].iov_base = state->packetchunks[k].chunk; chunks_iovec[i].iov_len = state->packetchunks[k].bytes; l += chunks_iovec[i].iov_len; } } // consider start_marker here and increment chunks_used assert(chunks_used < IOVEC_SIZE); chunks_iovec[chunks_used] = end_marker; l += end_marker.iov_len; chunks_used++; /* debug code follows */ fprintf(debug_file, "\n=== raw device write, iovec dump ===\n"); Loading @@ -209,9 +210,24 @@ int camogm_frame_jpeg(camogm_state *state) fprintf(debug_file, "total len = %d\n======\n", l); /* end of debug code */ iovlen = writev(state->ivf, chunks_iovec, chunks_used); 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; } Loading @@ -224,9 +240,19 @@ int camogm_frame_jpeg(camogm_state *state) return 0; } /** * @brief Finish JPEG file write operation * * This function checks whether raw device write was on and closes raw device file. * @param state a pointer to a structure containing current state * @return 0 if the device was closed successfully and -1 otherwise */ int camogm_end_jpeg(camogm_state *state) { close(state->ivf); D0(fprintf(debug_file, "Closing raw device %s\n", state->path_prefix)); return 0; int ret = 0; if (state->rawdev_op) { ret = close(state->rawdev.rawdev_fd); D0(fprintf(debug_file, "Closing raw device %s\n", state->rawdev.rawdev_path)); } return ret; }
camogm_jpeg.h +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ #include "camogm.h" int camogm_init_jpeg(void); int camogm_init_jpeg(camogm_state *state); int camogm_start_jpeg(camogm_state *state); int camogm_frame_jpeg(camogm_state *state); int camogm_end_jpeg(camogm_state *state); Loading
camogm_ogm.c +2 −2 Original line number Diff line number Diff line Loading @@ -73,7 +73,7 @@ int camogm_start_ogm(camogm_state *state) char vendor[] = "ElphelOgm v 0.1"; int pos; stream_header sh; unsigned char hdbuf[sizeof(sh) + 1]; char hdbuf[sizeof(sh) + 1]; ogg_packet ogg_header; sprintf(state->path, "%s%010ld_%06ld.ogm", state->path_prefix, state->frame_params[state->port_num].timestamp_sec, state->frame_params[state->port_num].timestamp_usec); Loading Loading @@ -133,7 +133,7 @@ int camogm_start_ogm(camogm_state *state) pos += 4; hdbuf[pos++] = 1; //! put it into Ogg stream ogg_header.packet = hdbuf; ogg_header.packet = (unsigned char *)hdbuf; ogg_header.bytes = pos; ogg_header.b_o_s = 0; ogg_header.e_o_s = 0; Loading