Commit 697be65d authored by Mikhail Karpenko's avatar Mikhail Karpenko

Load appropriate QuickTime template

This commit also fixes a bug with 'exit' command processing
parent df1c1959
...@@ -63,10 +63,6 @@ ...@@ -63,10 +63,6 @@
#define ALL_CHN_INACTIVE 0x00 #define ALL_CHN_INACTIVE 0x00
/** @brief This is a basic helper macro for processing all sensor ports at a time */ /** @brief This is a basic helper macro for processing all sensor ports at a time */
#define FOR_EACH_PORT(indtype, indvar) for (indtype indvar = 0; indvar < SENSOR_PORTS; indvar++) #define FOR_EACH_PORT(indtype, indvar) for (indtype indvar = 0; indvar < SENSOR_PORTS; indvar++)
/** @brief container_of macro as in the kernel */
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
char trailer[TRAILER_SIZE] = { 0xff, 0xd9 }; char trailer[TRAILER_SIZE] = { 0xff, 0xd9 };
...@@ -1000,7 +996,7 @@ void camogm_set_format(camogm_state *state, int d) ...@@ -1000,7 +996,7 @@ void camogm_set_format(camogm_state *state, int d)
state->set_format = d; state->set_format = d;
if (state->prog_state == STATE_STOPPED) { if (state->prog_state == STATE_STOPPED) {
state->format = state->set_format; state->format = state->set_format;
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;
...@@ -1551,7 +1547,7 @@ int parse_cmd(camogm_state *state, FILE* npipe) ...@@ -1551,7 +1547,7 @@ int parse_cmd(camogm_state *state, FILE* npipe)
return 11; return 11;
} else if (strcmp(cmd, "format") == 0) { } else if (strcmp(cmd, "format") == 0) {
if (args) { if (args) {
if (strcmp(args, "none") == 0) camogm_set_format(state, 0); if (strcmp(args, "none") == 0) camogm_set_format(state, CAMOGM_FORMAT_NONE);
else if ((strcmp(args, "ogm" ) == 0) || (strcmp(args, "ogg") == 0)) camogm_set_format(state, CAMOGM_FORMAT_OGM); else if ((strcmp(args, "ogm" ) == 0) || (strcmp(args, "ogg") == 0)) camogm_set_format(state, CAMOGM_FORMAT_OGM);
else if ((strcmp(args, "jpeg") == 0) || (strcmp(args, "jpg") == 0)) camogm_set_format(state, CAMOGM_FORMAT_JPEG); else if ((strcmp(args, "jpeg") == 0) || (strcmp(args, "jpg") == 0)) camogm_set_format(state, CAMOGM_FORMAT_JPEG);
else if (strcmp(args, "mov" ) == 0) camogm_set_format(state, CAMOGM_FORMAT_MOV); else if (strcmp(args, "mov" ) == 0) camogm_set_format(state, CAMOGM_FORMAT_MOV);
...@@ -1641,8 +1637,19 @@ int parse_cmd(camogm_state *state, FILE* npipe) ...@@ -1641,8 +1637,19 @@ int parse_cmd(camogm_state *state, FILE* npipe)
if ((args) && ((d = strtol(args, NULL, 10)) > 0)) camogm_set_dummy_read(state, d); if ((args) && ((d = strtol(args, NULL, 10)) > 0)) camogm_set_dummy_read(state, d);
return 30; return 30;
} else if (strcmp(cmd, "audio") == 0) { } else if (strcmp(cmd, "audio") == 0) {
if (args) if (args) {
camogm_set_audio_state(state, args); camogm_set_audio_state(state, args);
if (state->format != CAMOGM_FORMAT_NONE) {
/* Some file format initialization functions may depend on the state of audio recording, i.e.
* MOV will load different header template when audio is enabled; thus we need to trigger
* format selector in case the state of audio processing has changed. Here, format is reset
* regardless of its previous state which will trigger format selector when file recording
* starts.
*/
camogm_free(state);
state->format = CAMOGM_FORMAT_NONE;
}
}
return 31; return 31;
} else if (strcmp(cmd, "audio_volume") == 0) { } else if (strcmp(cmd, "audio_volume") == 0) {
if (args) if (args)
......
...@@ -70,6 +70,10 @@ ...@@ -70,6 +70,10 @@
#define COMMAND_LOOP_DELAY 500000 #define COMMAND_LOOP_DELAY 500000
/** @brief File can be split up to this number of chunks */ /** @brief File can be split up to this number of chunks */
#define FILE_CHUNKS_NUM 8 #define FILE_CHUNKS_NUM 8
/** @brief container_of macro as in the kernel */
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
/** /**
* @enum state_flags * @enum state_flags
......
...@@ -78,7 +78,7 @@ struct audio { ...@@ -78,7 +78,7 @@ struct audio {
int frame_period; ///< video frame period, used to calculate time stamps for audio samples int frame_period; ///< video frame period, used to calculate time stamps for audio samples
void (*get_fpga_time)(const struct audio *audio, struct timeval *tv);//< callback function which can get FPGA time void (*get_fpga_time)(const struct audio *audio, struct timeval *tv);//< callback function which can get FPGA time
int (*write_samples)(void *buff, int len, int slen); ///< callback function which actually write data to file, this must set int (*write_samples)(void *buff, int len, int slen); ///< callback function which actually write data to file, this must be set
///< in the camogm_init_* function when appropriate format is selected ///< in the camogm_init_* function when appropriate format is selected
}; };
......
...@@ -153,7 +153,7 @@ static int save_state_file(const camogm_state *state) ...@@ -153,7 +153,7 @@ static int save_state_file(const camogm_state *state)
/** /**
* @brief Initialize synchronization resources for disk writing thread and then start this thread. This function * @brief Initialize synchronization resources for disk writing thread and then start this thread. This function
* is call each time JPEG format is set or changed, thus we need to check the state of writing thread before * is called each time JPEG format is set or changed, thus we need to check the state of writing thread before
* initialization to prevent spawning multiple threads. * initialization to prevent spawning multiple threads.
* @param[in] state a pointer to a structure containing current state * @param[in] state a pointer to a structure containing current state
* @return 0 if initialization was successful and negative value otherwise * @return 0 if initialization was successful and negative value otherwise
...@@ -202,19 +202,21 @@ int camogm_init_jpeg(camogm_state *state) ...@@ -202,19 +202,21 @@ int camogm_init_jpeg(camogm_state *state)
*/ */
void camogm_free_jpeg(camogm_state *state) void camogm_free_jpeg(camogm_state *state)
{ {
pthread_cond_destroy(&state->writer_params.main_cond); if (state->writer_params.state == STATE_RUNNING) {
pthread_cond_destroy(&state->writer_params.writer_cond); pthread_cond_destroy(&state->writer_params.main_cond);
pthread_mutex_destroy(&state->writer_params.writer_mutex); pthread_cond_destroy(&state->writer_params.writer_cond);
pthread_mutex_destroy(&state->writer_params.writer_mutex);
// terminate writing thread
pthread_mutex_lock(&state->writer_params.writer_mutex);
state->writer_params.exit_thread = true;
pthread_cond_signal(&state->writer_params.writer_cond);
pthread_mutex_unlock(&state->writer_params.writer_mutex);
pthread_join(state->writer_params.writer_thread, NULL);
state->writer_params.exit_thread = false;
deinit_align_buffers(state); // terminate writing thread
pthread_mutex_lock(&state->writer_params.writer_mutex);
state->writer_params.exit_thread = true;
pthread_cond_signal(&state->writer_params.writer_cond);
pthread_mutex_unlock(&state->writer_params.writer_mutex);
pthread_join(state->writer_params.writer_thread, NULL);
state->writer_params.exit_thread = false;
deinit_align_buffers(state);
}
} }
/** Calculate the total length of current frame */ /** Calculate the total length of current frame */
......
...@@ -27,12 +27,13 @@ ...@@ -27,12 +27,13 @@
#include "camogm_mov.h" #include "camogm_mov.h"
/** @brief Quicktime header length (w/o index tables) enough to accommodate static data */ /** @brief QuickTime header length (w/o index tables) enough to accommodate static data */
#define QUICKTIME_MIN_HEADER 0x300 #define QUICKTIME_MIN_HEADER 0x300
// for the parser // for the parser
const char hexStr[] = "0123456789abcdef"; const char hexStr[] = "0123456789abcdef";
const char qtSourceFileName[] = "/etc/qt_source"; const char qt_template_v[] = "/etc/qt_source"; // QuickTime template for video files
const char qt_template_av[] = "/etc/qt_audio"; // QuickTime template for video + audio files
char comStr[1024]; char comStr[1024];
int width = 1280; int width = 1280;
int height = 1024; int height = 1024;
...@@ -41,9 +42,9 @@ int sample_dur = 80; ...@@ -41,9 +42,9 @@ int sample_dur = 80;
int samplesPerChunk = 10; int samplesPerChunk = 10;
int framesize = 80000; int framesize = 80000;
int timescale = 600; int timescale = 600;
int * sizes; // array of frame sizes int * sizes; // array of frame sizes
int iPos; // position in the string "iFile" int iPos; // position in the string "iFile"
int ofd; // output file descriptor (file opened by the caller) int ofd; // output file descriptor (file opened by the caller)
int iFileLen; int iFileLen;
char * q_template = NULL; char * q_template = NULL;
long headerSize = 0; long headerSize = 0;
...@@ -51,9 +52,9 @@ const char *iFile = NULL; ...@@ -51,9 +52,9 @@ const char *iFile = NULL;
int quicktime_template_parser(camogm_state *state, int quicktime_template_parser(camogm_state *state,
const char * i_iFile, // now - string containing header template const char * i_iFile, // now - string containing header template
int i_ofd, // output file descriptor (opened) int i_ofd, // output file descriptor (opened)
int i_width, // width in pixels int i_width, // width in pixels
int i_height, int i_height,
int i_nframes, int i_nframes,
int i_sample_dur, int i_sample_dur,
...@@ -61,7 +62,7 @@ int quicktime_template_parser(camogm_state *state, ...@@ -61,7 +62,7 @@ int quicktime_template_parser(camogm_state *state,
int i_framesize, int i_framesize,
int i_timescale, int i_timescale,
int * i_sizes, int * i_sizes,
int data_start // put zero if the header is written before data (no gap) int data_start // put zero if the header is written before data (no gap)
); );
void putBigEndian(unsigned long d, int l); void putBigEndian(unsigned long d, int l);
int parse_special(void); int parse_special(void);
...@@ -78,21 +79,26 @@ int camogm_init_mov(camogm_state *state) ...@@ -78,21 +79,26 @@ int camogm_init_mov(camogm_state *state)
{ {
FILE* qt_header; FILE* qt_header;
int size; int size;
char *qt_template = qt_template_v;
if ((qt_header = fopen(qtSourceFileName, "r")) == NULL) { if (state->audio.audio_enable)
D0(fprintf(debug_file, "Error opening Quicktime header template %s for reading\n", qtSourceFileName)); qt_template = qt_template_av;
if ((qt_header = fopen(qt_template, "r")) == NULL) {
D0(fprintf(debug_file, "Error opening QuickTime header template %s for reading\n", qt_template));
return -CAMOGM_FRAME_FILE_ERR; return -CAMOGM_FRAME_FILE_ERR;
} else {
D5(fprintf(debug_file, "Template file: %s\n", qt_template));
} }
fseek(qt_header, 0, SEEK_END); fseek(qt_header, 0, SEEK_END);
size = ftell(qt_header); size = ftell(qt_header);
if (!((q_template = malloc(size + 1)))) { if (!((q_template = malloc(size + 1)))) {
D0(fprintf(debug_file, "Could not allocate %d bytes of memory for Quicktime header template\n", (size + 1))); D0(fprintf(debug_file, "Could not allocate %d bytes of memory for QuickTime header template\n", (size + 1)));
fclose(qt_header); fclose(qt_header);
return -CAMOGM_FRAME_MALLOC; return -CAMOGM_FRAME_MALLOC;
} }
fseek(qt_header, 0, SEEK_SET); //rewind fseek(qt_header, 0, SEEK_SET); //rewind
if (fread(q_template, size, 1, qt_header) < 1) { if (fread(q_template, size, 1, qt_header) < 1) {
D0(fprintf(debug_file, "Could not read %d bytes of Quicktime header template from %s\n", (size + 1), qtSourceFileName)); D0(fprintf(debug_file, "Could not read %d bytes of QuickTime header template from %s\n", (size + 1), qt_template));
free(q_template); free(q_template);
q_template = NULL; q_template = NULL;
fclose(qt_header); fclose(qt_header);
......
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