Commit d9272e8c authored by Mikhail Karpenko's avatar Mikhail Karpenko

Add new command to set raw device path

parent 8856f31f
...@@ -183,6 +183,11 @@ unsigned long *aglobalPars[SENSOR_PORTS]; /// parameters that are not ...@@ -183,6 +183,11 @@ unsigned long *aglobalPars[SENSOR_PORTS]; /// parameters that are not
camogm_state sstate; camogm_state sstate;
//camogm_state * state; //camogm_state * state;
typedef enum {
RAW_PATH,
FILE_PATH
} path_type;
int debug_level; int debug_level;
FILE* debug_file; FILE* debug_file;
...@@ -198,7 +203,7 @@ void camogm_set_greedy(camogm_state *state, int d); ...@@ -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_ignore_fps(camogm_state *state, int d);
void camogm_set_save_gp(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_exif(camogm_state *state, int d);
void camogm_set_timescale(camogm_state *state, double d); //! set timescale, default=1.0 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 void camogm_set_frames_skip(camogm_state *state, int d); //! set number of frames to skip, if negative - seconds between frames
...@@ -280,52 +285,53 @@ void camogm_init(camogm_state *state, unsigned int port, char *pipe_name) ...@@ -280,52 +285,53 @@ void camogm_init(camogm_state *state, unsigned int port, char *pipe_name)
const char sserial[] = "elp0"; const char sserial[] = "elp0";
int * ipser = (int*)sserial; int * ipser = (int*)sserial;
state->running = 0; // mo memset(state, 0, sizeof(camogm_state));
state->starting = 0; // mo // state->running = 0; // mo
state->vf = NULL; // state->starting = 0; // mo
// state->vf = NULL;
camogm_set_segment_duration(state, DEFAULT_DURATION); camogm_set_segment_duration(state, DEFAULT_DURATION);
camogm_set_segment_length(state, DEFAULT_LENGTH); camogm_set_segment_length(state, DEFAULT_LENGTH);
camogm_set_greedy(state, DEFAULT_GREEDY); camogm_set_greedy(state, DEFAULT_GREEDY);
camogm_set_ignore_fps(state, DEFAULT_IGNORE_FPS); camogm_set_ignore_fps(state, DEFAULT_IGNORE_FPS);
camogm_set_max_frames(state, DEFAULT_FRAMES); camogm_set_max_frames(state, DEFAULT_FRAMES);
camogm_set_frames_per_chunk(state, DEFAULT_FRAMES_PER_CHUNK); camogm_set_frames_per_chunk(state, DEFAULT_FRAMES_PER_CHUNK);
camogm_set_start_after_timestamp(state, 0.0); // start any time // camogm_set_start_after_timestamp(state, 0.0); // start any time
camogm_set_prefix(state, "\0"); // camogm_set_prefix(state, "\0", FILE_PATH);
camogm_set_save_gp(state, 0); // camogm_set_save_gp(state, 0);
camogm_reset(state); // sets state->buf_overruns =- 1 camogm_reset(state); // sets state->buf_overruns =- 1
state->serialno = ipser[0]; state->serialno = ipser[0];
state->last = 0; // state->last = 0;
debug_file = stderr; debug_file = stderr;
camogm_debug_level(DEFAULT_DEBUG_LVL); camogm_debug_level(DEFAULT_DEBUG_LVL);
strcpy(state->debug_name, "stderr"); strcpy(state->debug_name, "stderr");
camogm_set_timescale(state, 1.0); camogm_set_timescale(state, 1.0);
camogm_set_frames_skip(state, 0); // don't skip camogm_set_frames_skip(state, 0); // don't skip
camogm_set_format(state, CAMOGM_FORMAT_MOV); 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->exif = DEFAULT_EXIF;
state->frame_lengths = NULL; state->frame_lengths = NULL;
state->frameno = 0; // state->frameno = 0;
state->formats = 0; // state->formats = 0;
state->last_error_code = 0; // state->last_error_code = 0;
// kml stuff // kml stuff
camogm_kml_set_enable(state, 0); // camogm_kml_set_enable(state, 0);
state->kml_file = NULL; // state->kml_file = NULL;
camogm_kml_set_horHalfFov(state, 20.0); camogm_kml_set_horHalfFov(state, 20.0);
camogm_kml_set_vertHalfFov(state, 15.0); camogm_kml_set_vertHalfFov(state, 15.0);
camogm_kml_set_height_mode(state, 0); camogm_kml_set_height_mode(state, 0);
camogm_kml_set_height(state, 10.0); camogm_kml_set_height(state, 10.0);
camogm_kml_set_period(state, 2); // 2 sec camogm_kml_set_period(state, 2); // 2 sec
camogm_kml_set_near(state, 40.0); // 40 m (distance to PhotoOverlay) 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->port_num = port;
state->pipe_name = pipe_name; state->pipe_name = pipe_name;
state->rawdev.start_pos = RAWDEV_START_OFFSET; state->rawdev.start_pos = RAWDEV_START_OFFSET;
state->rawdev.end_pos = state->rawdev.start_pos; state->rawdev.end_pos = state->rawdev.start_pos;
state->rawdev.curr_pos = state->rawdev.start_pos; state->rawdev.curr_pos = state->rawdev.start_pos;
state->rawdev.overrun = 0; // state->rawdev.overrun = 0;
state->rawdev_op = 0; // state->rawdev_op = 0;
state->active_chn = ALL_CHN_ACTIVE; state->active_chn = ALL_CHN_ACTIVE;
} }
...@@ -366,8 +372,12 @@ int camogm_start(camogm_state *state) ...@@ -366,8 +372,12 @@ int camogm_start(camogm_state *state)
int port = state->port_num; int port = state->port_num;
if (state->active_chn == ALL_CHN_INACTIVE) { if (state->active_chn == ALL_CHN_INACTIVE) {
D1(fprintf(debug_file, "All channels are disabled, will not start\n")); D0(fprintf(debug_file, "All channels are disabled, will not start\n"));
return 0; 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")); D1(fprintf(debug_file, "Starting recording\n"));
...@@ -384,7 +394,7 @@ int camogm_start(camogm_state *state) ...@@ -384,7 +394,7 @@ int camogm_start(camogm_state *state)
switch (state->format) { switch (state->format) {
case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_NONE: rslt = 0; break;
case CAMOGM_FORMAT_OGM: rslt = camogm_init_ogm(); 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; case CAMOGM_FORMAT_MOV: rslt = camogm_init_mov(); break;
} }
state->formats |= 1 << (state->format); state->formats |= 1 << (state->format);
...@@ -841,26 +851,27 @@ void camogm_set_ignore_fps(camogm_state *state, int d) ...@@ -841,26 +851,27 @@ void camogm_set_ignore_fps(camogm_state *state, int d)
state->ignore_fps = d ? 1 : 0; 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)
{ {
strncpy(state->path_prefix, p, sizeof(state->path_prefix) - 1); if (type == FILE_PATH) {
state->path_prefix[sizeof(state->path_prefix) - 1] = '\0'; strncpy(state->path_prefix, p, sizeof(state->path_prefix) - 1);
// check if we are going to write to raw device state->path_prefix[sizeof(state->path_prefix) - 1] = '\0';
if (strncmp("/dev/", state->path_prefix, 5) == 0) { } else if (type == RAW_PATH && (strncmp(p, "/dev/", 5) == 0)) {
state->rawdev.end_pos = get_disk_size(state->path_prefix); 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) { if (state->rawdev.end_pos == 0) {
state->rawdev_op = 0; state->rawdev_op = 0;
state->rawdev.end_pos = state->rawdev.start_pos; state->rawdev.end_pos = state->rawdev.start_pos;
state->path_prefix[0] = '\0'; state->rawdev.rawdev_path[0] = '\0';
printf("ERROR: unable to initiate raw device operation\n"); D0(fprintf(debug_file, "ERROR: unable to initiate raw device operation\n"));
} else { } else {
printf("WARNING: raw device write initiated\n"); D0(fprintf(debug_file, "WARNING: raw device write initiated\n"));
state->rawdev_op = 1; state->rawdev_op = 1;
/* debug code follows */ /* 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;
} }
} }
...@@ -892,7 +903,7 @@ void camogm_set_format(camogm_state *state, int d) ...@@ -892,7 +903,7 @@ void camogm_set_format(camogm_state *state, int d)
switch (state->format) { switch (state->format) {
case CAMOGM_FORMAT_NONE: rslt = 0; break; case CAMOGM_FORMAT_NONE: rslt = 0; break;
case CAMOGM_FORMAT_OGM: rslt = camogm_init_ogm(); 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; case CAMOGM_FORMAT_MOV: rslt = camogm_init_mov(); break;
} }
if (rslt) { if (rslt) {
...@@ -1021,7 +1032,9 @@ void camogm_status(camogm_state *state, char * fn, int xml) ...@@ -1021,7 +1032,9 @@ void camogm_status(camogm_state *state, char * fn, int xml)
" <kml_period>%d</kml_period>\n" \ " <kml_period>%d</kml_period>\n" \
" <kml_last_ts>%d.%06d</kml_last_ts>\n" \ " <kml_last_ts>%d.%06d</kml_last_ts>\n" \
" <greedy>\"%s\"</greedy>\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, \ _state, state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \
_frames_skip, _sec_skip, \ _frames_skip, _sec_skip, \
state->width, state->height, _output_format, _using_exif, \ state->width, state->height, _output_format, _using_exif, \
...@@ -1030,7 +1043,8 @@ void camogm_status(camogm_state *state, char * fn, int xml) ...@@ -1030,7 +1043,8 @@ void camogm_status(camogm_state *state, char * fn, int xml)
state->debug_name, debug_level, _using_global_pointer, \ 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_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, \ _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) { FOR_EACH_PORT(int, chn) {
char *_active = is_chn_active(state, chn) ? "yes" : "no"; char *_active = is_chn_active(state, chn) ? "yes" : "no";
...@@ -1076,9 +1090,11 @@ void camogm_status(camogm_state *state, char * fn, int xml) ...@@ -1076,9 +1090,11 @@ void camogm_status(camogm_state *state, char * fn, int xml)
fprintf(f, "\n"); fprintf(f, "\n");
fprintf(f, "output format \t%s\n", _output_format); fprintf(f, "output format \t%s\n", _output_format);
fprintf(f, "using exif \t%s\n", _using_exif); fprintf(f, "using exif \t%s\n", _using_exif);
fprintf(f, "path prefix: \t%s\n", state->path_prefix); fprintf(f, "path prefix \t%s\n", state->path_prefix);
fprintf(f, "max file duration: \t%d sec\n", state->segment_duration); fprintf(f, "raw device path \t%s\n", state->rawdev.rawdev_path);
fprintf(f, "max file length: \t%d B\n", state->segment_length); 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, "max frames \t%d\n", state->max_frames);
fprintf(f, "timescale \t%f\n", state->timescale); fprintf(f, "timescale \t%f\n", state->timescale);
fprintf(f, "frames per chunk \t%d\n", state->frames_per_chunk); fprintf(f, "frames per chunk \t%d\n", state->frames_per_chunk);
...@@ -1217,7 +1233,7 @@ int parse_cmd(camogm_state *state, FILE* npipe) ...@@ -1217,7 +1233,7 @@ int parse_cmd(camogm_state *state, FILE* npipe)
camogm_set_segment_length(state, d); camogm_set_segment_length(state, d);
return 5; return 5;
} else if (strcmp(cmd, "prefix") == 0) { } else if (strcmp(cmd, "prefix") == 0) {
if (args) camogm_set_prefix(state, args); if (args) camogm_set_prefix(state, args, FILE_PATH);
return 6; return 6;
} else if (strcmp(cmd, "status") == 0) { } else if (strcmp(cmd, "status") == 0) {
camogm_status(state, args, 0); camogm_status(state, args, 0);
...@@ -1319,6 +1335,14 @@ int parse_cmd(camogm_state *state, FILE* npipe) ...@@ -1319,6 +1335,14 @@ int parse_cmd(camogm_state *state, FILE* npipe)
d = strtol(args, NULL, 10); d = strtol(args, NULL, 10);
set_chn_state(state, d, 0); set_chn_state(state, d, 0);
return 27; 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; return -1;
...@@ -1547,11 +1571,12 @@ inline int is_chn_active(camogm_state *s, unsigned int port) ...@@ -1547,11 +1571,12 @@ 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) 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) if (new_state)
s->active_chn |= 1 << port; s->active_chn |= 1 << port;
else else
s->active_chn &= ~(1 << port); s->active_chn &= ~(1 << port);
}
} }
/** /**
......
...@@ -74,10 +74,13 @@ ...@@ -74,10 +74,13 @@
*/ */
/** @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 */
#define ELPHEL_PATH_MAX 300
typedef struct { typedef struct {
int rawdev_fd; int rawdev_fd;
char rawdev_path[ELPHEL_PATH_MAX];
uint32_t overrun; uint32_t overrun;
uint64_t start_pos; uint64_t start_pos;
uint64_t end_pos; uint64_t end_pos;
...@@ -91,7 +94,7 @@ typedef struct { ...@@ -91,7 +94,7 @@ typedef struct {
int ignore_fps; int ignore_fps;
int save_gp; //if non zero, current circbuf pointer will be saved to global pointer, so imgsrv can report /pointers 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_prefix[256];
char path[300]; char path[ELPHEL_PATH_MAX];
int cirbuf_rp[SENSOR_PORTS]; //!-1 - invalid int cirbuf_rp[SENSOR_PORTS]; //!-1 - invalid
int fd_circ[SENSOR_PORTS]; //! file descriptor for circbuf int fd_circ[SENSOR_PORTS]; //! file descriptor for circbuf
int fd_head[SENSOR_PORTS]; //! file descriptor for JPEG header int fd_head[SENSOR_PORTS]; //! file descriptor for JPEG header
......
...@@ -59,41 +59,31 @@ ...@@ -59,41 +59,31 @@
#include <c313a.h> #include <c313a.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <assert.h>
#include <ogg/ogg.h> // has to be before ogmstreams.h #include <ogg/ogg.h> // has to be before ogmstreams.h
#include "ogmstreams.h" // move it to <>? #include "ogmstreams.h" // move it to <>?
#include "camogm_jpeg.h" #include "camogm_jpeg.h"
/** @brief Size of iovec structures holding data to be written */ int camogm_init_jpeg(camogm_state *state)
#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)
{ {
return 0; return 0;
} }
void camogm_free_jpeg(void) 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) int camogm_start_jpeg(camogm_state *state)
{ {
//!TODO: make directory if it does not exist (find the last "/" in the state->path
char * slash; char * slash;
int rslt; int rslt;
...@@ -113,22 +103,32 @@ int camogm_start_jpeg(camogm_state *state) ...@@ -113,22 +103,32 @@ int camogm_start_jpeg(camogm_state *state)
} }
} }
} else { } else {
state->ivf = open(state->path_prefix, O_RDWR); if (state->rawdev_op) {
if (state->ivf < 0) { state->rawdev.rawdev_fd = open(state->rawdev.rawdev_path, O_RDWR);
D0(perror(__func__)); if (state->rawdev.rawdev_fd < 0) {
D0(fprintf(debug_file, "Error opening raw device %s\n", state->path)); D0(perror(__func__));
return -CAMOGM_FRAME_FILE_ERR; D0(fprintf(debug_file, "Error opening raw device %s\n", state->rawdev.rawdev_path));
return -CAMOGM_FRAME_FILE_ERR;
}
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->rawdev.rawdev_fd, state->rawdev.curr_pos, SEEK_SET);
} }
D0(fprintf(debug_file, "Open raw device %s; start_pos = %llu, end_pos = %llu, curr_pos = %llu\n", state->path,
state->rawdev.start_pos, state->rawdev.end_pos, state->rawdev.curr_pos));
lseek64(state->ivf, state->rawdev.curr_pos, SEEK_SET);
} }
return 0; 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 camogm_frame_jpeg(camogm_state *state)
{ {
int i, j, split_index; int i, j, k, split_index;
int chunks_used = state->chunk_index - 1; int chunks_used = state->chunk_index - 1;
ssize_t iovlen, l = 0; ssize_t iovlen, l = 0;
struct iovec chunks_iovec[8]; struct iovec chunks_iovec[8];
...@@ -160,7 +160,6 @@ int camogm_frame_jpeg(camogm_state *state) ...@@ -160,7 +160,6 @@ int camogm_frame_jpeg(camogm_state *state)
} else { } else {
D0(fprintf(debug_file, "\n%s: current pointers start_pos = %llu, end_pos = %llu, curr_pos = %llu, data in buffer %d\n", __func__, 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)); state->rawdev.start_pos, state->rawdev.end_pos, state->rawdev.curr_pos, l));
l = 0;
split_index = -1; split_index = -1;
for (int i = 0, total_len = 0; i < state->chunk_index - 1; i++) { for (int i = 0, total_len = 0; i < state->chunk_index - 1; i++) {
total_len += state->packetchunks[i + 1].bytes; total_len += state->packetchunks[i + 1].bytes;
...@@ -171,34 +170,36 @@ int camogm_frame_jpeg(camogm_state *state) ...@@ -171,34 +170,36 @@ int camogm_frame_jpeg(camogm_state *state)
break; break;
} }
} }
chunks_iovec[0] = start_marker; k = 0;
l += start_marker.iov_len; l = 0;
chunks_used++; for (int i = 0; i < chunks_used; i++) {
for (int i = 1; i < chunks_used; i++) { ++k;
if (i == split_index) { if (i == split_index) {
// one of the chunks rolls over the end of the raw storage, split it into two segments and // 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 // use additional chunk in chunks_iovec for this additional segment
split_cntr = state->rawdev.end_pos - (l + state->rawdev.curr_pos); 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 // 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; chunks_iovec[i].iov_len = split_cntr;
l += chunks_iovec[i].iov_len; l += chunks_iovec[i].iov_len;
chunks_iovec[++i].iov_base = split_ptr + 1; 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; 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 { } else {
chunks_iovec[i].iov_base = state->packetchunks[i].chunk; chunks_iovec[i].iov_base = state->packetchunks[k].chunk;
chunks_iovec[i].iov_len = state->packetchunks[i].bytes; chunks_iovec[i].iov_len = state->packetchunks[k].bytes;
l += chunks_iovec[i].iov_len; 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 */ /* debug code follows */
fprintf(debug_file, "\n=== raw device write, iovec dump ===\n"); fprintf(debug_file, "\n=== raw device write, iovec dump ===\n");
...@@ -209,9 +210,24 @@ int camogm_frame_jpeg(camogm_state *state) ...@@ -209,9 +210,24 @@ int camogm_frame_jpeg(camogm_state *state)
fprintf(debug_file, "total len = %d\n======\n", l); fprintf(debug_file, "total len = %d\n======\n", l);
/* end of debug code */ /* 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) { if (iovlen < l) {
j = errno; j = errno;
perror(__func__);
D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l)); D0(fprintf(debug_file, "writev error %d (returned %d, expected %d)\n", j, iovlen, l));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} }
...@@ -224,9 +240,19 @@ int camogm_frame_jpeg(camogm_state *state) ...@@ -224,9 +240,19 @@ int camogm_frame_jpeg(camogm_state *state)
return 0; 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) int camogm_end_jpeg(camogm_state *state)
{ {
close(state->ivf); int ret = 0;
D0(fprintf(debug_file, "Closing raw device %s\n", state->path_prefix)); if (state->rawdev_op) {
return 0; ret = close(state->rawdev.rawdev_fd);
D0(fprintf(debug_file, "Closing raw device %s\n", state->rawdev.rawdev_path));
}
return ret;
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include "camogm.h" #include "camogm.h"
int camogm_init_jpeg(void); int camogm_init_jpeg(camogm_state *state);
int camogm_start_jpeg(camogm_state *state); int camogm_start_jpeg(camogm_state *state);
int camogm_frame_jpeg(camogm_state *state); int camogm_frame_jpeg(camogm_state *state);
int camogm_end_jpeg(camogm_state *state); int camogm_end_jpeg(camogm_state *state);
......
...@@ -73,7 +73,7 @@ int camogm_start_ogm(camogm_state *state) ...@@ -73,7 +73,7 @@ int camogm_start_ogm(camogm_state *state)
char vendor[] = "ElphelOgm v 0.1"; char vendor[] = "ElphelOgm v 0.1";
int pos; int pos;
stream_header sh; stream_header sh;
unsigned char hdbuf[sizeof(sh) + 1]; char hdbuf[sizeof(sh) + 1];
ogg_packet ogg_header; 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); 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);
...@@ -133,7 +133,7 @@ int camogm_start_ogm(camogm_state *state) ...@@ -133,7 +133,7 @@ int camogm_start_ogm(camogm_state *state)
pos += 4; pos += 4;
hdbuf[pos++] = 1; hdbuf[pos++] = 1;
//! put it into Ogg stream //! put it into Ogg stream
ogg_header.packet = hdbuf; ogg_header.packet = (unsigned char *)hdbuf;
ogg_header.bytes = pos; ogg_header.bytes = pos;
ogg_header.b_o_s = 0; ogg_header.b_o_s = 0;
ogg_header.e_o_s = 0; ogg_header.e_o_s = 0;
......
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