00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #include <unistd.h>
00071 #include <stdio.h>
00072 #include <stdlib.h>
00073 #include <signal.h>
00074 #include <fcntl.h>
00075 #include <sys/uio.h>
00076 #include <errno.h>
00077 #include <sys/types.h>
00078 #include <sys/socket.h>
00079 #include <sys/stat.h>
00080
00081
00082 #include <time.h>
00083 #include <string.h>
00084
00085 #include <netinet/in.h>
00086 #include <sys/mman.h>
00087 #include <sys/ioctl.h>
00088
00089 #include <asm/elphel/c313a.h>
00090
00091 #include <asm/elphel/ext353.h>
00092 #include <asm/byteorder.h>
00093
00094
00095 #include <ogg/ogg.h>
00096 #include "ogmstreams.h"
00097
00098
00099 #include "camogm_ogm.h"
00100 #include "camogm_jpeg.h"
00101 #include "camogm_mov.h"
00102 #include "camogm_kml.h"
00103 #include "camogm.h"
00104 #include "camogm_wav.h"
00105
00106 #include <alsa/asoundlib.h>
00107
00108 #define TRAILER_SIZE 0x02
00109 #define MAP_OPTIONS MAP_FILE|MAP_PRIVATE
00110
00111 char trailer[TRAILER_SIZE] = {0xff,0xd9};
00112
00113 const char ExifFileName[]="/dev/exif_exif";
00114
00115 const char HeadFileName[]="/dev/jpeghead";
00116 const char SensParsFileName[]="/dev/sensorpars";
00117 unsigned long * ccam_dma_buf;
00118 unsigned long * imageParamsR;
00119 int buff_size;
00120
00121 #define DEFAULT_DURATION 60
00122 #define DEFAULT_LENGTH 100000000
00123
00124 #define DEFAULT_FRAMES 16384
00125 #define DEFAULT_FRAMES_PER_CHUNK 10
00126
00127 #define DEFAULT_LENGTH 100000000
00128 #define DEFAULT_EXIF 1
00129
00130 #define DEFAULT_AUDIO_RATE 44100
00131 #define DEFAULT_AUDIO_CHANNELS 2
00132
00133 #define AUDIO_RATE_MAX 44100
00134 #define AUDIO_RATE_MIN 11025
00135 #define AUDIO_CHANNELS_MAX 2
00136 #define AUDIO_CHANNELS_MIN 1
00137
00138 static char cmdbuf[1024];
00139 static int cmdbufp=0;
00140 static int cmdstrt=0;
00141
00142 camogm_state sstate;
00143 camogm_state * state;
00144
00145 int debug_level;
00146 FILE* debug_file;
00147
00148
00149 int camogm_init(void);
00150
00151 int camogm_start(int by_command);
00152 int camogm_stop(int by_command);
00153
00154 int camogm_reset(void);
00155 int camogm_debug(const char * fname);
00156 int camogm_debug_level(int d);
00157 void camogm_set_segment_duration(int sd);
00158 void camogm_set_segment_length(int sl);
00159 void camogm_set_save_gp(int d);
00160 void camogm_set_prefix (const char * p);
00161 void camogm_set_exif(int d);
00162 void camogm_set_timescale(double d);
00163 void camogm_set_frames_skip(int d);
00164 void camogm_set_format(int d);
00165
00166 void camogm_kml_set_enable(int d);
00167 void camogm_kml_set_horHalfFov (double dd);
00168 void camogm_kml_set_vertHalfFov(double dd);
00169 void camogm_kml_set_height_mode(int d);
00170 void camogm_kml_set_height(double dd);
00171 void camogm_kml_set_period(int d);
00172 void camogm_kml_set_near(double dd);
00173
00174
00175 int parse_cmd(FILE* npipe);
00176 char * getLineFromPipe(FILE* npipe);
00177
00178 int sendImageFrame (void);
00179
00180 void camogm_set_max_frames(int d);
00181 void camogm_set_frames_per_chunk(int d);
00182
00183
00184 void camogm_set_audio_state(char *args);
00185 void camogm_set_audio_format(char *args);
00186 void camogm_set_sync_state(char *args);
00187 void audio_process(void);
00188 void audio_init(int by_command);
00189 void audio_start(int by_command);
00190 void audio_end(int by_command);
00191 void audio_free(void);
00193 void put_uint16(void *buf, u_int16_t val)
00194 {
00195 unsigned char *tmp;
00196
00197 tmp = (unsigned char *) buf;
00198
00199 tmp[0] = val & 0xff;
00200 tmp[1] = (val >>= 8) & 0xff;
00201 }
00202
00203 void put_uint32(void *buf, u_int32_t val)
00204 {
00205 unsigned char *tmp;
00206
00207 tmp = (unsigned char *) buf;
00208
00209 tmp[0] = val & 0xff;
00210 tmp[1] = (val >>= 8) & 0xff;
00211 tmp[2] = (val >>= 8) & 0xff;
00212 tmp[3] = (val >>= 8) & 0xff;
00213 }
00214
00215 void put_uint64(void *buf, u_int64_t val)
00216 {
00217 unsigned char *tmp;
00218
00219 tmp = (unsigned char *) buf;
00220
00221 tmp[0] = val & 0xff;
00222 tmp[1] = (val >>= 8) & 0xff;
00223 tmp[2] = (val >>= 8) & 0xff;
00224 tmp[3] = (val >>= 8) & 0xff;
00225 tmp[4] = (val >>= 8) & 0xff;
00226 tmp[5] = (val >>= 8) & 0xff;
00227 tmp[6] = (val >>= 8) & 0xff;
00228 tmp[7] = (val >>= 8) & 0xff;
00229 }
00230
00231 int camogm_init(void) {
00232 const char sserial[]="elp0";
00233 int * ipser= (int*) sserial;
00234 state->running=0;
00235 state->starting=0;
00236 state->vf=NULL;
00237 camogm_set_segment_duration(DEFAULT_DURATION);
00238 camogm_set_segment_length(DEFAULT_LENGTH);
00239 camogm_set_max_frames(DEFAULT_FRAMES);
00240 camogm_set_frames_per_chunk(DEFAULT_FRAMES_PER_CHUNK);
00241 camogm_set_prefix ("\0");
00242 camogm_set_save_gp(0);
00243 camogm_reset();
00244 state->serialno= ipser[0];
00245 state->last= 0;
00246 debug_file= stderr;
00247 camogm_debug_level(1);
00248 strcpy(state->debug_name,"stderr");
00249 camogm_set_timescale(1.0);
00250 camogm_set_frames_skip(0);
00251 camogm_set_format(CAMOGM_FORMAT_OGM);
00252 camogm_set_audio_state("off");
00253 camogm_set_audio_format("44100/1");
00254 camogm_set_sync_state("off");
00255 state->exifSize=0;
00256 state->exif= DEFAULT_EXIF;
00257 state->frame_lengths=NULL;
00258 state->frameno=0;
00259 state->formats=0;
00260
00262 camogm_kml_set_enable(0);
00263 state->kml_file=NULL;
00264 camogm_kml_set_horHalfFov (20.0);
00265 camogm_kml_set_vertHalfFov(15.0);
00266 camogm_kml_set_height_mode(0);
00267 camogm_kml_set_height(10.0);
00268 camogm_kml_set_period(2);
00269 camogm_kml_set_near(40.0);
00270 state->kml_path[0]='\0';
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 return 0;
00296 }
00297
00298
00299 int camogm_debug(const char * fname) {
00300 int none=1;
00301 if (fname && strlen(fname) && strcmp(fname, "none") && strcmp(fname, "null") && strcmp(fname, "/dev/null")) none=0;
00302 if (debug_file){
00303 if (strcmp(state->debug_name, "stdout") && strcmp(state->debug_name, "stderr")) fclose (debug_file);
00304 debug_file=NULL;
00305 state->debug_name[0]='\0';
00306 }
00307 if (!none) {
00308 if (strcmp(fname, "stdout") ==0) debug_file=stdout;
00309 else if (strcmp(fname, "stderr") ==0) debug_file=stderr;
00310 else debug_file=fopen(fname,"w+");
00311 }
00312 if (debug_file) {
00313 strncpy(state->debug_name,fname,sizeof(state->debug_name)-1);
00314 state->debug_name[sizeof(state->debug_name)-1]='\0';
00315 }
00316 return 0;
00317 }
00318
00319 int camogm_debug_level(int d) {
00320 debug_level=d;
00321 return 0;
00322 }
00323
00324
00325
00326
00327 int camogm_start(int by_command) {
00328 int timestamp_start;
00329 int rslt;
00330 int next_metadata_start, next_jpeg_len, fp;
00331 D1(fprintf (debug_file,"Starting recording\n"));
00332 state->frameno=0;
00333 state->timescale= state->set_timescale;
00334
00335 int * ifp = (int *) &(state->frame_params) ;
00336 int * ifp_this = (int *) &(state->this_frame_params) ;
00337 if (state->kml_enable) camogm_init_kml() ;
00338
00339 audio_init(by_command);
00340 if (state->format != state->set_format) {
00341 state->format= state->set_format;
00342 switch (state->format) {
00343 case CAMOGM_FORMAT_NONE: rslt= 0; break;
00344 case CAMOGM_FORMAT_OGM: rslt= camogm_init_ogm(); break;
00345 case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break;
00346 case CAMOGM_FORMAT_MOV: rslt= camogm_init_mov(); break;
00347 }
00348 state->formats |= 1 << (state->format);
00350 }
00351 state->max_frames= state->set_max_frames;
00352 state->frames_per_chunk= state->frames_per_chunk;
00353 state->starting=1;
00354
00355 D3(fprintf (debug_file,"1: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00356 if ((state->cirbuf_rp <0) || (lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET) < 0) || (lseek(state->fd_circ,LSEEK_CIRC_VALID,SEEK_END) < 0 )) {
00357 D3(fprintf (debug_file,"2: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00358 state->cirbuf_rp=lseek(state->fd_circ,LSEEK_CIRC_LAST,SEEK_END);
00359 if (((fp=lseek(state->fd_circ,LSEEK_CIRC_PREV,SEEK_END)))>=0) state->cirbuf_rp=fp;
00360 state->buf_overruns++;
00362
00363
00364 state->buf_min=imageParamsR[G_FREECIRCBUF];
00365
00366 } else {
00367
00368
00369
00370 if (state->buf_min > imageParamsR[G_FREECIRCBUF]) state->buf_min=imageParamsR[G_FREECIRCBUF];
00371
00372 }
00373 D3(fprintf (debug_file,"3: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00374 D3(fprintf (debug_file,"4:lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END)=%d\n",(int) lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END)));
00375
00377 if (lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END) <0) return -CAMOGM_FRAME_NOT_READY;
00378 D3(fprintf (debug_file,"5: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00379 state->metadata_start=(state->cirbuf_rp)-32;
00380 if (state->metadata_start<0) state->metadata_start+=state->circ_buff_size;
00381
00383
00384 memcpy (&(state->frame_params), (unsigned long * ) &ccam_dma_buf[state->metadata_start>>2],32);
00385 state->jpeg_len=state->frame_params.frame_length;
00386
00387
00388 if (state->frame_params.signffff !=0xffff) {
00389 D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->frame_params.signffff));
00390 state->cirbuf_rp=-1;
00391 D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp));
00392 D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n",ifp[0],ifp[1],ifp[2],ifp[3],ifp[4],ifp[5],ifp[6],ifp[7]));
00393 return -CAMOGM_FRAME_BROKEN;
00394 }
00397 timestamp_start=(state->cirbuf_rp)+((state->jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC;
00398 if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00399 memcpy (&(state->frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00400
00402 if ((lseek(state->fd_circ,LSEEK_CIRC_NEXT,SEEK_END) < 0 ) ||
00404 (((fp=lseek(state->fd_circ,LSEEK_CIRC_READY,SEEK_END))) < 0)) {
00405 lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET);
00406 return -CAMOGM_FRAME_NOT_READY;
00407 }
00408 next_metadata_start=fp-32;
00409 if (next_metadata_start<0) next_metadata_start+= state->circ_buff_size;
00410 memcpy (&(state->this_frame_params), (unsigned long * ) &ccam_dma_buf[next_metadata_start>>2],32);
00411 next_jpeg_len=state->this_frame_params.frame_length;
00412 if (state->this_frame_params.signffff !=0xffff) {
00413 D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->this_frame_params.signffff));
00414 D1(fprintf(debug_file, "fp=0x%x\r\n",(int) fp));
00415 D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n",ifp_this[0],ifp_this[1],ifp_this[2],ifp_this[3],ifp_this[4],ifp_this[5],ifp_this[6],ifp_this[7]));
00416
00417
00418
00419 state->cirbuf_rp=-1;
00420 return -CAMOGM_FRAME_BROKEN;
00421 }
00423 timestamp_start=fp+((next_jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC;
00424 if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00425 memcpy (&(state->this_frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00427 if ((state->frame_params.width != state->this_frame_params.width) ||
00428 (state->frame_params.height != state->this_frame_params.height)) {
00430 state->cirbuf_rp=fp;
00431 return -CAMOGM_FRAME_CHANGED;
00432 }
00434 state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+
00435 1000000*(state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec);
00436
00438 state->frames_skip= state->set_frames_skip;
00439 if (state->frames_skip > 0) {
00440 state->frames_skip_left=0;
00441 state->frame_period *= (state->frames_skip+1);
00442
00443 } else if (state->frames_skip < 0) {
00444 state->frame_period=-(state->frames_skip) ;
00445 state->frames_skip_left=state->frame_params.timestamp_sec;
00446 }
00447 state->time_unit= (ogg_int64_t) (((double) state-> frame_period) * ((double) 10) / ((double) state-> timescale));
00448 state->width=state->frame_params.width;
00449 state->height=state->frame_params.height;
00450
00453 lseek(state->fd_head,state->cirbuf_rp+1,SEEK_END);
00454
00455 lseek(state->fd_head,0,0);
00456 read (state->fd_head,state->jpegHeader,state->head_size);
00458 lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET);
00460 audio_start(by_command);
00461 switch (state->format) {
00462 case CAMOGM_FORMAT_NONE: rslt= 0; break;
00463 case CAMOGM_FORMAT_OGM: rslt= camogm_start_ogm(); break;
00464 case CAMOGM_FORMAT_JPEG: rslt= camogm_start_jpeg(); break;
00465 case CAMOGM_FORMAT_MOV: rslt= camogm_start_mov(); break;
00466 default: rslt=0;
00467 }
00468 if (rslt) return rslt;
00469 if (state->kml_enable) rslt=camogm_start_kml() ;
00470 if (rslt) return rslt;
00471 state->running=1;
00472 state->starting=0;
00473 D1(fprintf (debug_file,"Started OK\n"));
00474 return 0;
00475 }
00476
00477
00478 int sendImageFrame(void) {
00479 int rslt;
00480
00481
00482 unsigned char frame_packet_type = PACKET_IS_SYNCPOINT;
00483
00484
00485
00486 int timestamp_start;
00487
00488
00489 int * ifp_this = (int *) &(state->this_frame_params) ;
00490
00492 if(state->frameno >= (state->max_frames))
00493 return -CAMOGM_FRAME_CHANGED;
00495
00496
00497 if(state->format != state->set_format)
00498 return -CAMOGM_FRAME_CHANGED;
00500 if((state->vf) && (state->segment_length >=0) && (ftell(state->vf) > state->segment_length))
00501 return -CAMOGM_FRAME_CHANGED;
00503 if(((state->ivf) >= 0) && (state->segment_length >= 0) && (lseek(state->ivf, 0, SEEK_CUR) > state->segment_length))
00504 return -CAMOGM_FRAME_CHANGED;
00506 if(lseek(state->fd_circ, state->cirbuf_rp, SEEK_SET) < 0)
00507 return -CAMOGM_FRAME_INVALID;
00508
00509 if(lseek(state->fd_circ, LSEEK_CIRC_READY, SEEK_END) < 0)
00510 return -CAMOGM_FRAME_NOT_READY;
00511
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00525 if((state->frames_skip > 0) && (state->frames_skip_left > 0 )) {
00526 state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
00528 if(state->save_gp)
00529 lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
00530 state->frames_skip_left--;
00531 return -CAMOGM_FRAME_NOT_READY;
00532 }
00533
00535
00536 state->metadata_start = state->cirbuf_rp - 32;
00537 if(state->metadata_start < 0)
00538 state->metadata_start += state->circ_buff_size;
00539 memcpy(&(state->this_frame_params), (unsigned long * ) &ccam_dma_buf[state->metadata_start>>2],32);
00540 state->jpeg_len = state->this_frame_params.frame_length;
00541 if(state->this_frame_params.signffff != 0xffff) {
00542 D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->this_frame_params.signffff));
00543 D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp));
00544 D1(fprintf(debug_file, "%08x %08x %08x %08x %08x %08x %08x %08x\r\n",ifp_this[0],ifp_this[1],ifp_this[2],ifp_this[3],ifp_this[4],ifp_this[5],ifp_this[6],ifp_this[7]));
00545 return -CAMOGM_FRAME_BROKEN;
00546 }
00547
00549 timestamp_start = state->cirbuf_rp + ((state->jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC;
00550 if(timestamp_start >= state->circ_buff_size)
00551 timestamp_start -= state->circ_buff_size;
00552
00553 memcpy(&(state->this_frame_params.timestamp_sec), (unsigned long *)&ccam_dma_buf[timestamp_start >> 2], 8);
00555 if((state->frame_params.width != state->this_frame_params.width) || (state->frame_params.height != state->this_frame_params.height))
00556 return -CAMOGM_FRAME_CHANGED;
00557
00558 if((state->segment_duration > 0) && ((state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec) > state->segment_duration))
00559 return -CAMOGM_FRAME_CHANGED;
00561 if((state->frames_skip < 0) && (state->frames_skip_left > state->this_frame_params.timestamp_sec)) {
00562 state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
00564 if(state->save_gp)
00565 lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
00566 return -CAMOGM_FRAME_NOT_READY;
00567 }
00568
00569
00570
00571 if(state->exif) {
00572 D3(fprintf(debug_file,"_5_"));
00574
00575 state->exifSize = lseek(state->fd_exif, 1, SEEK_END);
00576
00577 if(state->exifSize > 0) {
00578
00579 lseek(state->fd_exif, state->this_frame_params.meta_index, SEEK_END);
00580 rslt = read(state->fd_exif, state->ed, state->exifSize);
00581 if(rslt < 0)
00582 rslt = 0;
00583 state->exifSize = rslt;
00584 } else state->exifSize = 0;
00585 } else state->exifSize=0;
00586
00587
00588
00590 state->chunk_index=0;
00591 state->packetchunks[state->chunk_index ].bytes=1;
00592 state->packetchunks[state->chunk_index++].chunk=&frame_packet_type;
00593 if(state->exif > 0) {
00594
00595 state->packetchunks[state->chunk_index ].bytes = 2;
00596 state->packetchunks[state->chunk_index++].chunk = state->jpegHeader;
00597 state->packetchunks[state->chunk_index ].bytes = state->exifSize;
00598 state->packetchunks[state->chunk_index++].chunk = state->ed;
00599 state->packetchunks[state->chunk_index ].bytes = state->head_size - 2;
00600 state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[2]);
00601 } else {
00602
00603 state->packetchunks[state->chunk_index ].bytes = state->head_size;
00604 state->packetchunks[state->chunk_index++].chunk = state->jpegHeader;
00605 }
00606
00607
00609
00610 if((state->cirbuf_rp + state->jpeg_len) > state->circ_buff_size) {
00611
00612
00613
00614
00615 state->packetchunks[state->chunk_index ].bytes = state->circ_buff_size-state->cirbuf_rp;
00616 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) &ccam_dma_buf[state->cirbuf_rp >> 2];
00618
00619 state->packetchunks[state->chunk_index ].bytes = state->jpeg_len - (state->circ_buff_size - state->cirbuf_rp);
00620 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) &ccam_dma_buf[0];
00621 } else {
00622
00623
00625
00626 state->packetchunks[state->chunk_index ].bytes = state->jpeg_len;
00627 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) &ccam_dma_buf[state->cirbuf_rp >> 2];
00628 }
00629
00630 state->packetchunks[state->chunk_index ].bytes = 2;
00631 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) trailer;
00632
00633 switch (state->format) {
00634 case CAMOGM_FORMAT_NONE: rslt=0; break;
00635 case CAMOGM_FORMAT_OGM: rslt = camogm_frame_ogm(); break;
00636 case CAMOGM_FORMAT_JPEG: rslt = camogm_frame_jpeg(); break;
00637 case CAMOGM_FORMAT_MOV: rslt = camogm_frame_mov(); break;
00638 default: rslt = 0;
00639 }
00640 if(rslt)
00641 return rslt;
00642 if(state->kml_used)
00643 rslt = camogm_frame_kml() ;
00644 if(rslt)
00645 return rslt;
00646
00647
00649 state->frameno++;
00650 state->cirbuf_rp = lseek(state->fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
00652 if(state->save_gp)
00653 lseek(state->fd_circ, LSEEK_CIRC_SETP, SEEK_END);
00654
00655
00656
00657 if(state->frames_skip > 0) {
00658 state->frames_skip_left = state->frames_skip;
00659 } else {
00660 if(state->frames_skip < 0) {
00661 state->frames_skip_left += -(state->frames_skip);
00662 }
00663 }
00664 return 0;
00665 }
00666
00667 int camogm_stop(int by_command) {
00668 int rslt=0;
00669 if (!state->running) {
00670 if (!state->starting) {
00671 D2(fprintf (debug_file,"Recording was not running, nothing to stop\n"));
00672 } else {
00673 state->starting=0;
00674 D1(fprintf (debug_file,"Dropping attempt to start\n"));
00675 }
00676 return 0;
00677 }
00678 D1(fprintf (debug_file,"Ending recording\n"));
00679 if (state->kml_used) camogm_end_kml() ;
00680 audio_end(by_command);
00681 switch (state->format) {
00682 case CAMOGM_FORMAT_NONE: rslt= 0; break;
00683 case CAMOGM_FORMAT_OGM: rslt= camogm_end_ogm(); break;
00684 case CAMOGM_FORMAT_JPEG: rslt= camogm_end_jpeg();break;
00685 case CAMOGM_FORMAT_MOV: rslt= camogm_end_mov(); break;
00687 }
00689 if (state->vf) fclose (state->vf);
00690 state->vf=NULL;
00691 if (rslt) return rslt;
00692 state->last=1;
00694 state->running=0;
00695 state->starting=0;
00696 return 0;
00697 }
00698
00699 void camogm_free() {
00700 int f;
00702
00703 for (f=0;f<31;f++) {
00704 if (state->formats & ( 1 << (state->format))) {
00705 switch (f) {
00706 case CAMOGM_FORMAT_NONE: break;
00707 case CAMOGM_FORMAT_OGM: camogm_free_ogm(); break;
00708 case CAMOGM_FORMAT_JPEG: camogm_free_jpeg();break;
00709 case CAMOGM_FORMAT_MOV: camogm_free_mov(); break;
00710 }
00711 }
00712 }
00713 state->formats=0;
00714 }
00715
00716 int camogm_reset(void) {
00717 state->cirbuf_rp=-1;
00718 state->buf_overruns=-1;
00719 return 0;
00720 }
00721
00723 void camogm_kml_set_enable(int d) {
00724 state->kml_enable=d;
00725 }
00726 void camogm_kml_set_horHalfFov (double dd) {
00727 state->kml_horHalfFov=dd;
00728 }
00729 void camogm_kml_set_vertHalfFov(double dd) {
00730 state->kml_vertHalfFov=dd;
00731 }
00732 void camogm_kml_set_height_mode(int d) {
00733 state->kml_height_mode=d;
00734 }
00735 void camogm_kml_set_height(double dd) {
00736 state->kml_height=dd;
00737 }
00738 void camogm_kml_set_period(int d) {
00739 state->kml_period=d;
00740 state->kml_last_ts=0;
00741 state->kml_last_uts=0;
00742 }
00743 void camogm_kml_set_near(double dd) {
00744 state->kml_near=dd;
00745 }
00746
00747
00748 void camogm_set_segment_duration(int sd) {
00749 state->segment_duration=sd;
00750 }
00751 void camogm_set_segment_length(int sl) {
00752 state->segment_length= sl;
00753 }
00754 void camogm_set_save_gp(int d) {
00755 state->save_gp= d;
00756 }
00757 void camogm_set_exif(int d) {
00758 state->exif= d;
00759 }
00760
00761 void camogm_set_prefix (const char * p) {
00762 strncpy(state->path_prefix, p, sizeof(state->path_prefix)-1);
00763 state->path_prefix[sizeof(state->path_prefix)-1]='\0';
00764 }
00765
00766 void camogm_set_timescale(double d) {
00767 state->set_timescale= d;
00768 if ((state->running==0) && (state->starting==0)) {
00769 state->timescale=state->set_timescale;
00770 }
00771 }
00772
00773 void camogm_set_frames_skip(int d) {
00774 state->set_frames_skip= d;
00775 if ((state->running==0) && (state->starting==0)) {
00776 state->frames_skip= state->set_frames_skip;
00777
00778 state->frames_skip_left= 0;
00779 }
00780 }
00781
00782 void camogm_set_format(int d) {
00783 int rslt=0;
00784 state->set_format= d;
00785 if ((state->running==0) && (state->starting==0)) {
00786 state->format= state->set_format;
00787 switch (state->format) {
00788 case CAMOGM_FORMAT_NONE: rslt= 0; break;
00789 case CAMOGM_FORMAT_OGM: rslt= camogm_init_ogm(); break;
00790 case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break;
00791 case CAMOGM_FORMAT_MOV: rslt= camogm_init_mov(); break;
00792 }
00793 if (rslt) {
00794 D0(fprintf (debug_file,"%s:%d: Error setting format to=%d\n",__FILE__,__LINE__, state->format));
00795 }
00796 state->formats |= 1 << (state->format);
00797 }
00798 }
00799
00801 void camogm_set_max_frames(int d) {
00802 state->set_max_frames= d;
00803 if ((state->running==0) && (state->starting==0)) state->max_frames= d;
00804 }
00805
00806 void camogm_set_frames_per_chunk(int d) {
00807 state->set_frames_per_chunk= d;
00808 if ((state->running==0) && (state->starting==0)) state->frames_per_chunk= d;
00809 }
00810
00811 void camogm_status(char * fn, int xml) {
00812 int _len=0;
00813 int _dur,_udur;
00814
00815 FILE* f;
00816 char *_state, *_output_format, *_using_exif, *_using_global_pointer, *_compressor_state;
00817 int _b_free, _b_used;
00818 int _frames_remain=0;
00819 int _sec_remain=0;
00820 int _frames_skip=0;
00821 int _sec_skip=0;
00822 char *_kml_enable, *_kml_used, *_kml_height_mode;
00823
00824 _kml_enable= state->kml_enable?"yes":"no";
00825 _kml_used= state->kml_used?"yes":"no";
00826 _kml_height_mode= state->kml_height_mode?"GPS altitude":"map ground level";
00827
00828
00829 _b_free=imageParamsR[G_FREECIRCBUF];
00830 _b_used=imageParamsR[G_CIRCBUFSIZE]-imageParamsR[G_FREECIRCBUF];
00831
00832 if (!fn) f=stdout;
00833 else if (strcmp(fn, "stdout")==0) f=stdout;
00834 else if (strcmp(fn, "stderr")==0) f=stderr;
00835 else {
00836 if (!((f=fopen (fn,"w")))) {
00837 D0(fprintf (debug_file,"Error opening %s\n", fn));
00838 return;
00839 }
00840 }
00841 if (state->vf) _len=ftell(state->vf);
00842 else if ((state->ivf)>=0) _len=lseek(state->ivf, 0, SEEK_CUR);
00843 _dur= state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec;
00844 _udur=state->this_frame_params.timestamp_usec-state->frame_params.timestamp_usec;
00845 if (_udur<0) {
00846 _dur-=1;
00847 _udur+=1000000;
00848 } else if (_udur>=1000000) {
00849 _dur+=1;
00850 _udur-=1000000;
00851 }
00852 _state= state->running? "running":(state->starting?"starting":"stopped");
00853 _output_format= state->format?((state->format==CAMOGM_FORMAT_OGM)?"ogm":
00854 ((state->format==CAMOGM_FORMAT_JPEG)?"jpeg":
00855 ((state->format==CAMOGM_FORMAT_MOV)?"mov":
00856 "other"))):"none";
00857 _using_exif= state->exif?"yes":"no";
00858 _using_global_pointer=state->save_gp?"yes":"no";
00860 #if 0
00861 _compressor_state=(imageParamsR[P_CAMSEQSTATE]==CAMSEQ_RUN)?"running":
00862 ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_SINGLE)?"acquiring":
00863 ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_STOP)?"stoppping":
00864 ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_JPEG)?"stopped":
00865 ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_OFF)?"reset":"other"))));
00866 #endif
00867 if ( state->frames_skip >0 ) {
00868 _frames_remain= state->frames_skip_left;
00869 _frames_skip=state->frames_skip;
00870 } else if ( state->frames_skip <0 ) {
00871 _sec_remain= (state->frames_skip_left - state->this_frame_params.timestamp_sec);
00872 _sec_skip=-(state->frames_skip);
00873 }
00874
00875
00876 if (xml) {
00877 fprintf (f,"<?xml version=\"1.0\"?>\n" \
00878 "<camogm_state>\n" \
00879 " <state>\"%s\"</state>\n" \
00880 " <compressor_state>\"%s\"</compressor_state>\n" \
00881 " <file_name>\"%s\"</file_name>\n" \
00882 " <frame_number>%d</frame_number>\n" \
00883 " <file_duration>%d.%06d</file_duration>\n" \
00884 " <file_length>%d</file_length>\n" \
00885 " <frame_period>%d</frame_period>\n" \
00886 " <frames_skip>%d</frames_skip>\n" \
00887 " <seconds_skip>%d</seconds_skip>\n" \
00888 " <frames_skip_left>%d</frames_skip_left>\n" \
00889 " <seconds_skip_left>%d</seconds_skip_left>\n" \
00890 " <frame_width>%d</frame_width>\n" \
00891 " <frame_height>%d</frame_height>\n" \
00892 " <format>\"%s\"</format>\n" \
00893 " <exif>\"%s\"</exif>\n" \
00894 " <prefix>\"%s\"</prefix>\n" \
00895 " <max_duration>%d</max_duration>\n" \
00896 " <max_length>%d</max_length>\n" \
00897 " <max_frames>%d</max_frames>\n" \
00898 " <timescale>%f</timescale>\n" \
00899 " <frames_per_chunk>%d</frames_per_chunk>\n" \
00900 " <buffer_overruns>%d</buffer_overruns>\n" \
00901 " <buffer_minimal>%d</buffer_minimal>\n" \
00902 " <buffer_free>%d</buffer_free>\n" \
00903 " <buffer_used>%d</buffer_used>\n" \
00904 " <circbuf_rp>%d</circbuf_rp>\n" \
00905 " <debug_output>\"%s\"</debug_output>\n" \
00906 " <debug_level>%d</debug_level>\n" \
00907 " <use_global_rp>\"%s\"</use_global_rp>\n" \
00908 " <kml_enable>\"%s\"</kml_enable>\n" \
00909 " <kml_used>\"%s\"</kml_used>\n" \
00910 " <kml_path>\"%s\"</kml_path>\n" \
00911 " <kml_horHalfFov>\"%f\"</kml_horHalfFov>\n" \
00912 " <kml_vertHalfFov>\"%f\"</kml_vertHalfFov>\n" \
00913 " <kml_near>\"%f\"</kml_near>\n" \
00914 " <kml_height_mode>\"%s\"</kml_height_mode>\n" \
00915 " <kml_height>\"%f\"</kml_height>\n" \
00916 " <kml_period>%d</kml_period>\n" \
00917 " <kml_last_ts>%d.%06d</kml_last_ts>\n" \
00918 "</camogm_state>\n",
00919 _state,_compressor_state,state->path,state->frameno,_dur,_udur,_len,state->frame_period, \
00920 _frames_skip,_sec_skip,_frames_remain, _sec_remain, \
00921 state->width,state->height,_output_format,_using_exif, \
00922 state->path_prefix, state->segment_duration, state->segment_length, state->max_frames, state->timescale, \
00923 state->frames_per_chunk, state->buf_overruns, state->buf_min, _b_free, _b_used, state->cirbuf_rp, \
00924 state->debug_name, debug_level, _using_global_pointer, \
00925 _kml_enable,_kml_used,state->kml_path,state->kml_horHalfFov,state->kml_vertHalfFov,state->kml_near,\
00926 _kml_height_mode,state->kml_height,state->kml_period,state->kml_last_ts,state->kml_last_uts);
00927 } else {
00928 fprintf (f,"state %s\n", _state);
00929 fprintf (f,"compressor state %s\n", _compressor_state);
00930 fprintf (f,"file %s\n", state->path);
00931 fprintf (f,"frame %d\n", state->frameno);
00932 fprintf (f,"file duration %d.%06d sec\n",_dur,_udur);
00933 fprintf (f,"file length %d B\n", _len);
00934 fprintf (f,"frame period %d (0x%x)\n", state->frame_period,state->frame_period);
00935 if ( _frames_skip >0 ) fprintf (f,"frames to skip %d (left %d)\n",_frames_skip, _frames_remain);
00936 if ( _sec_skip <0 ) fprintf (f,"timelapse period %d sec (remaining %d sec)\n", _sec_skip, _sec_remain);
00937 fprintf (f,"width %d (0x%x)\n", state->width,state->width);
00938 fprintf (f,"height %d (0x%x)\n", state->height,state->height);
00939 fprintf (f,"\n");
00940 fprintf (f,"output format %s\n", _output_format);
00941 fprintf (f,"using exif %s\n", _using_exif);
00942 fprintf (f,"path prefix: %s\n", state->path_prefix);
00943 fprintf (f,"max file duration: %d sec\n", state->segment_duration);
00944 fprintf (f,"max file length: %d B\n", state->segment_length);
00945 fprintf (f,"max frames %d\n", state->max_frames);
00946 fprintf (f,"timescale %f\n", state->timescale);
00947 fprintf (f,"frames per chunk %d\n", state->frames_per_chunk);
00948 fprintf (f,"\n");
00949 fprintf (f,"buffer overruns %d\n", state->buf_overruns);
00950 fprintf (f,"buffer minimal %d\n", state->buf_min);
00951 fprintf (f,"buffer free %d\n", _b_free);
00952 fprintf (f,"buffer used %d\n", _b_used);
00953 fprintf (f,"circbuf_rp %d (0x%x)\n", state->cirbuf_rp,state->cirbuf_rp);
00954 fprintf (f,"\n");
00955 fprintf (f,"debug output to %s\n", state->debug_name);
00956 fprintf (f,"debug level %d\n", debug_level);
00957 fprintf (f,"use global pointer %s\n", _using_global_pointer);
00958 fprintf (f,"\n\n");
00959 fprintf (f,"kml_enable %s\n", _kml_enable);
00960 fprintf (f,"kml_used %s\n", _kml_used);
00961 fprintf (f,"kml_path %s\n", state->kml_path);
00962 fprintf (f,"kml_horHalfFov %f degrees\n",state->kml_horHalfFov);
00963 fprintf (f,"kml_vertHalfFov %f degrees\n",state->kml_vertHalfFov);
00964 fprintf (f,"kml_near %f m\n", state->kml_near);
00965 fprintf (f,"kml height mode %s\n", _kml_height_mode);
00966 fprintf (f,"kml_height (extra) %f m\n", state->kml_height);
00967 fprintf (f,"kml_period %d\n", state->kml_period);
00968 fprintf (f,"kml_last_ts %d.%06d\n", state->kml_last_ts,state->kml_last_uts);
00969 fprintf (f,"\n\n");
00970
00971 }
00972 if ((f!=stdout) && (f!=stderr)) fclose (f);
00973 if (state->buf_overruns>=0) state->buf_overruns=0;
00974 state->buf_min=_b_free;
00975 }
00976
00978 char * getLineFromPipe(FILE* npipe) {
00979 int fl;
00980 char * nlp;
00982 if (cmdstrt > 0) {
00984 memmove(cmdbuf, &cmdbuf[cmdstrt], sizeof(cmdbuf)- cmdstrt);
00985 cmdbufp-=cmdstrt;
00986 cmdstrt=0;
00987 }
00989 if (!cmdbufp) cmdbuf[cmdbufp]=0;
00990
00991 nlp= strpbrk(cmdbuf,";\n");
00992 if (!nlp) {
00993 fl=fread(&cmdbuf[cmdbufp], 1,sizeof(cmdbuf)-cmdbufp-1,npipe);
00994 cmdbuf[cmdbufp+fl]=0;
00996
00997 nlp= strpbrk(&cmdbuf[cmdbufp],";\n");
00998 cmdbufp+=fl;
00999 }
01000 if (nlp) {
01001
01002 nlp[0]=0;
01003 cmdstrt=nlp-cmdbuf+1;
01004
01005
01006 for (fl=0; cmdbuf[fl] && strchr(" \t",cmdbuf[fl]); fl++);
01007
01008 return &cmdbuf[fl];
01009 } else {
01010
01011 return NULL;
01012 }
01013 }
01014
01015 int parse_cmd(FILE* npipe) {
01016 char * cmd;
01017 char * args;
01018 char * argse;
01019 int d;
01020 double dd;
01021
01023 while(((cmd=getLineFromPipe(npipe))) && !cmd[0]) ;
01024 if (!cmd) return 0;
01025
01026 args=strpbrk(cmd,"= \t");
01028 if (args) {
01029 args[0]=0;
01030 args++;
01031 while (strchr("= \t",args[0])) args++;
01032 if (args[0]) {
01034 for (argse=strchr(args,'\0')-1; strchr("= \t",argse[0]);argse--) argse[0]='\0';
01035 }
01036 if (!args[0]) args=NULL;
01037 }
01039 if (strcmp(cmd, "start")==0) {
01040 camogm_start(1);
01041 return 1;
01042 } else if (strcmp(cmd, "reset")==0) {
01043 camogm_reset();
01044 return 2;
01045 } else if (strcmp(cmd, "stop")==0) {
01046 camogm_stop(1);
01047 return 3;
01048 } else if (strcmp(cmd, "exit")==0) {
01049 camogm_stop(1);
01050 camogm_free();
01051 exit (0);
01052 } else if (strcmp(cmd, "duration")==0) {
01053 if (!(args) || (((d= strtol(args, NULL, 10)))<=0)) d=DEFAULT_DURATION;
01054 camogm_set_segment_duration(d);
01055 return 4;
01056 } else if (strcmp(cmd, "length")==0) {
01057 if (!(args) || (((d= strtol(args, NULL, 10)))<=0)) d=DEFAULT_LENGTH;
01058 camogm_set_segment_length(d);
01059 return 5;
01060 } else if (strcmp(cmd, "prefix")==0) {
01061 if (args) camogm_set_prefix (args);
01062 return 6;
01063 } else if (strcmp(cmd, "status")==0) {
01064 camogm_status(args, 0);
01065 return 7;
01066 } else if (strcmp(cmd, "xstatus")==0) {
01067 camogm_status(args, 1);
01068 return 7;
01069 } else if (strcmp(cmd, "save_gp")==0) {
01070 if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_set_save_gp(d);
01071 return 8;
01072 } else if (strcmp(cmd, "exif")==0) {
01073 if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_set_exif(d);
01074 return 8;
01075 } else if (strcmp(cmd, "debug")==0) {
01076 camogm_debug(args);
01077 return 9;
01078 } else if (strcmp(cmd, "timescale")==0) {
01079 dd= strtod(args,NULL);
01080 camogm_set_timescale(dd?dd:1.0);
01081 return 10;
01084
01085
01086 } else if (strcmp(cmd, "frameskip")==0) {
01087 d= strtol(args, NULL, 10);
01088 camogm_set_frames_skip(d);
01089 return 11;
01090 } else if (strcmp(cmd, "timelapse")==0) {
01091 d= strtol(args, NULL, 10);
01092 camogm_set_frames_skip(-d);
01093 return 11;
01094 } else if (strcmp(cmd, "format")==0) {
01095 if (args) {
01096 if (strcmp(args, "none")==0) camogm_set_format(0);
01097 else if ((strcmp(args, "ogm" )==0) || (strcmp(args, "ogg")==0)) camogm_set_format(CAMOGM_FORMAT_OGM);
01098 else if ((strcmp(args, "jpeg")==0) || (strcmp(args, "jpg")==0)) camogm_set_format(CAMOGM_FORMAT_JPEG);
01099 else if (strcmp(args, "mov" )==0) camogm_set_format(CAMOGM_FORMAT_MOV);
01100 }
01101 return 12;
01102 } else if (strcmp(cmd, "debuglev")==0) {
01103 d= strtol(args, NULL, 10);
01104 camogm_debug_level(d?d:0);
01105 return 13;
01106 } else if (strcmp(cmd, "kml")==0) {
01107 if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_kml_set_enable(d);
01108 return 14;
01109 } else if (strcmp(cmd, "kml_hhf")==0) {
01110 dd= strtod(args,NULL);
01111 camogm_kml_set_horHalfFov(dd);
01112 return 15;
01113 } else if (strcmp(cmd, "kml_vhf")==0) {
01114 dd= strtod(args,NULL);
01115 camogm_kml_set_vertHalfFov(dd);
01116 return 16;
01117 } else if (strcmp(cmd, "kml_near")==0) {
01118 dd= strtod(args,NULL);
01119 camogm_kml_set_near(dd);
01120 return 17;
01121 } else if (strcmp(cmd, "kml_alt")==0) {
01122 if (args) {
01123 if (strcmp(args, "gps" )==0) camogm_kml_set_height_mode(1);
01124 else if (strcmp(args, "ground")==0) camogm_kml_set_height_mode(0);
01125 }
01126 return 18;
01127 } else if (strcmp(cmd, "kml_height")==0) {
01128 dd= strtod(args,NULL);
01129 camogm_kml_set_height(dd);
01130 return 19;
01131 } else if (strcmp(cmd, "kml_period")==0) {
01132 d= strtol(args, NULL, 10);
01133 camogm_kml_set_period(d?d:1);
01134 return 20;
01135 } else if (strcmp(cmd, "audio")==0) {
01136 if (args) {
01137 camogm_set_audio_state(args);
01138 }
01139 return 21;
01140 } else if (strcmp(cmd, "audio_format")==0) {
01141 if (args) {
01142 camogm_set_audio_format(args);
01143 }
01144 return 22;
01145 } else if (strcmp(cmd, "allow_sync")==0) {
01146 if (args) {
01147 camogm_set_sync_state(args);
01148 }
01149 return 23;
01150 }
01151
01152 return -1;
01153 }
01154
01155 int main(int argc, char *argv[])
01156 {
01157 const char circbufFileName[]="/dev/circbuf";
01158
01159 FILE * cmd_file;
01160 const char usage[]= "This program allows recording of the video/images acquired by Elphel camera to the storage media.\n" \
01161 "It is designed to run in the background and accept commands through a named pipe.\n\n" \
01162 "Usage:\n\n" \
01163 "%s <named_pipe_name>\n\n" \
01164 "i.e.:\n\n" \
01165 "%s /var/state/camogm_cmd\n\n" \
01166 "When the program is runninig you may send commands by writing strings to the command file\n" \
01167 "(/var/state/camogm_cmd in the example above). The complete list of available commands is available\n" \
01168 "on Elphel Wiki (http://wiki.elphel.com/index.php?title=Camogm), here is the example of usage\n" \
01169 "from the shell prompt in the camera:\n\n" \
01170 "echo \"status; exif=1; format=jpeg;status=/var/tmp/camogm.status\" > /var/state/camogm_cmd\n\n" \
01171 "That will print status information on the standard output (may not be visible if the program was not\n" \
01172 "started from the same session), set exif mode on (each frame will have the full Exif header including\n" \
01173 "a precise time stamp), set output format to a series of individual JPEG files, and then send status\n" \
01174 "information to a file /var/tmp/camogm.status in the camera file system.\n\n" \
01175 "This program does not control the process of acquisition of the video/images to the camera internal\n" \
01176 "buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected\n" \
01177 "format and stores the result files.\n\n";
01178 int go=1;
01179 int cmd;
01180 int i,rslt;
01181 state= &sstate;
01183 if ((argc < 2) || (argv[1][1]=='-')) {
01184 printf (usage,argv[0],argv[0]);
01185 return 0;
01186 }
01187 camogm_init();
01188
01190 state->fd_exif = open(ExifFileName, O_RDONLY);
01191 if (state->fd_exif<0) {
01192 D0(fprintf (debug_file,"Error opening %s\n", ExifFileName));
01193 return -1;
01194 }
01195
01197 state->fd_head = open(HeadFileName, O_RDWR);
01198 if (state->fd_head<0) {
01199 D0(fprintf (debug_file,"Error opening %s\n", HeadFileName));
01200 return -1;
01201 }
01202 state->head_size=lseek(state->fd_head,0,SEEK_END);
01203 if (state->head_size>JPEG_HEADER_SIZE) {
01204 D0(fprintf (debug_file,"%s:%d: Too big JPEG header (%d > %d)",__FILE__,__LINE__,state->head_size, JPEG_HEADER_SIZE ));
01205 return -2;
01206 }
01207
01209 state->fd_circ = open(circbufFileName, O_RDWR);
01210 if (state->fd_circ<0) {
01211 D0(fprintf (debug_file,"Error opening %s\n", circbufFileName));
01212 return -2;
01213 }
01215 state->circ_buff_size=lseek(state->fd_circ,0,SEEK_END);
01216 ccam_dma_buf = (unsigned long *) mmap(0, state->circ_buff_size, PROT_READ, MAP_SHARED, state->fd_circ, 0);
01217 if((int)ccam_dma_buf == -1) {
01218 D0(fprintf (debug_file,"Error in mmap of %s\n",circbufFileName));
01219
01220 close(state->fd_circ);
01221 return -3;
01222 }
01223
01225
01227 state->fd_sens = open(SensParsFileName, O_RDWR);
01228 if (state->fd_sens<0) {
01229 D0(fprintf (debug_file,"Error opening %s\n", SensParsFileName));
01230 return -2;
01231 }
01233 state->senspars_size=lseek(state->fd_sens,0,SEEK_END);
01234 imageParamsR = (unsigned long *) mmap(0, state->senspars_size, PROT_READ, MAP_SHARED, state->fd_sens, 0);
01235 if((int)imageParamsR == -1) {
01236 D0(fprintf (debug_file,"Error in mmap of %s\n",SensParsFileName));
01237 close(state->fd_sens);
01238 close(state->fd_circ);
01239 return -3;
01240 }
01241
01242
01243
01246 i=unlink (argv[1]);
01247 if (i) {
01248 D1(fprintf (debug_file,"Unlink %s returned %d, errno=%d \n", argv[1], i, errno));
01249 }
01250 i=mkfifo(argv[1], 0777);
01252 if (i) {
01253 if (errno==EEXIST) {
01254 D1(fprintf (debug_file,"Named pipe %s already exists, will use it.\n", argv[1]));
01255 } else {
01256 D0(fprintf (debug_file,"Can not create a named pipe %s, errno=%d \n", argv[1], errno));
01257 return -4;
01258 }
01259 }
01260
01263 if (!((cmd_file=fopen(argv[1],"r")))) {
01264 D0(fprintf (debug_file,"Can not open command file %s\n",argv[1]));
01265 return -5;
01266 }
01267 D1(fprintf (debug_file,"Pipe %s open for reading\n",argv[1]));
01268
01270 #define COMMAND_LOOP_DELAY 500000 //0.5sec
01271
01272 while(go) {
01273
01275 cmd = parse_cmd(cmd_file);
01276 if(cmd) {
01277 if(cmd < 0)
01278 D0(fprintf(debug_file,"Unrecognized command\n"));
01279 } else {
01280 if(state->running) {
01281
01282 audio_process();
01283
01284
01285
01286 switch((rslt = -sendImageFrame())) {
01287 case 0:
01288
01289
01290
01291
01292 break;
01293 case CAMOGM_FRAME_NOT_READY:
01294
01295
01296
01297
01298
01299
01300
01301 lseek(state->fd_circ,LSEEK_CIRC_WAIT,SEEK_END);
01302 break;
01303 case CAMOGM_FRAME_CHANGED:
01304 case CAMOGM_FRAME_NEXTFILE:
01305 case CAMOGM_FRAME_INVALID:
01306 case CAMOGM_FRAME_BROKEN:
01307
01308
01309 camogm_stop(0);
01310 camogm_start(0);
01311 break;
01312 case CAMOGM_FRAME_FILE_ERR:
01313 case CAMOGM_FRAME_OTHER:
01314 D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt));
01315 break;
01316 default:
01317 D0(fprintf (debug_file,"%s:line %d - should not get here (rslt=%d)\n",__FILE__,__LINE__,rslt));
01318 exit (-1);
01319 }
01320 } else {
01321 if(state->starting) {
01322
01323
01325 switch ((rslt = -camogm_start(1))) {
01326 case 0:
01327 break;
01328 case CAMOGM_FRAME_NOT_READY:
01329
01330
01331
01332 case CAMOGM_FRAME_CHANGED:
01333 case CAMOGM_FRAME_NEXTFILE:
01334 case CAMOGM_FRAME_INVALID:
01335 case CAMOGM_FRAME_BROKEN:
01336
01337 usleep( COMMAND_LOOP_DELAY) ;
01338 break;
01339 case CAMOGM_FRAME_FILE_ERR:
01340 case CAMOGM_FRAME_OTHER:
01341 D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt));
01342 break;
01343 default:
01344 D0(fprintf (debug_file,"%s:line %d - should not get here (rslt=%d)\n",__FILE__,__LINE__,rslt));
01345 exit (-1);
01346 }
01347 } else {
01348 usleep( COMMAND_LOOP_DELAY) ;
01349 }
01350 }
01351 }
01352 }
01353 return 0;
01354 }
01355
01356
01357
01358
01359
01360
01361
01362 void camogm_set_audio_state(char *args) {
01363 if(strcmp(args, "on") == 0 || strcmp(args, "enable") == 0) {
01364 state->audio_enable = 1;
01365 }
01366 if(strcmp(args, "off") == 0 || strcmp(args, "disable") == 0) {
01367 state->audio_enable = 0;
01368 }
01369 fprintf(stderr, "request for audio state: %s\n", args);
01370 }
01371
01372 void camogm_set_sync_state(char *args) {
01373 if(strcmp(args, "on") == 0 || strcmp(args, "enable") == 0) {
01374 state->allow_sync = 1;
01375 }
01376 if(strcmp(args, "off") == 0 || strcmp(args, "disable") == 0) {
01377 state->allow_sync = 0;
01378 }
01379 }
01380
01381 void camogm_set_audio_format(char *args) {
01382 char buf[8];
01383 int i;
01384 int channels = -1;
01385 int rate = -1;
01386 char *right = strstr(args, "/");
01387 if(right != NULL) {
01388 channels = atol(&right[1]);
01389 if(channels < AUDIO_CHANNELS_MIN)
01390 channels = AUDIO_CHANNELS_MIN;
01391 if(channels > AUDIO_CHANNELS_MAX)
01392 channels = AUDIO_CHANNELS_MAX;
01393 state->audio_channels = channels;
01394 }
01395 for(i = 0; i < 7; i++) {
01396 if(args[i] != '\0' && args[i] != '/')
01397 buf[i] = args[i];
01398 else
01399 break;
01400 }
01401 buf[i] = '\0';
01402 if(buf[0] != '\0') {
01403 rate = atol(buf);
01404 if(rate < AUDIO_RATE_MIN)
01405 rate = AUDIO_RATE_MIN;
01406 if(rate > AUDIO_RATE_MAX)
01407 rate = AUDIO_RATE_MAX;
01408 state->audio_rate = rate;
01409 }
01410
01411 fprintf(stderr, "request for audio format: %s; after apply: rate == %d; channels == %d\n", args, state->audio_rate, state->audio_channels);
01412 }
01413
01414 #define SBUFFER_PREFIX 16
01415 int audio_set = 0;
01416 int audio_present = 0;
01417 snd_pcm_t *capture_handle = NULL;
01418 char *sbuffer = NULL;
01419 long sbuffer_len = 0;
01420 long sample_time = 100;
01421
01422
01423 void audio_process(void) {
01424 if(audio_present == 0)
01425 return;
01426 if(state->format != CAMOGM_FORMAT_OGM) {
01427 int slen;
01428 int _len = 0;
01429 while((slen = snd_pcm_readi(capture_handle, sbuffer, sbuffer_len)) > 0) {
01430 wave_push((void *)sbuffer, slen * 2 * state->audio_channels);
01431 _len += slen;
01432 }
01433 fprintf(stderr, "process == %d bytes, request == %d bytes\n", _len, sbuffer_len);
01434 }
01435 if(state->format == CAMOGM_FORMAT_OGM) {
01436 int slen;
01437 int _len = 0;
01438 snd_pcm_status_t *status;
01439 snd_pcm_status_alloca(&status);
01440 snd_timestamp_t ts;
01441 for(;;) {
01442 long avail = 0;
01443 avail = snd_pcm_avail_update(capture_handle);
01444 snd_pcm_status(capture_handle, status);
01445 snd_pcm_status_get_tstamp(status, &ts);
01446
01447
01448 if(avail >= sbuffer_len) {
01449 slen = snd_pcm_mmap_readi(capture_handle, (void *)(sbuffer + SBUFFER_PREFIX), sbuffer_len);
01450
01451 if(slen > 0)
01452 camogm_audio_ogm_push((void *)(sbuffer + SBUFFER_PREFIX), slen * 2 * state->audio_channels, slen, SBUFFER_PREFIX);
01453 } else {
01454
01455 break;
01456 }
01457 }
01458 }
01459 }
01460
01461 void audio_init(by_command) {
01462 int slen;
01463 if(state->audio_enable == 0) {
01464 return;
01465 }
01466
01467 if(by_command && !audio_set) {
01468 snd_pcm_hw_params_t *hw_params;
01469 audio_set = 1;
01470
01471 sbuffer_len = state->audio_rate * state->audio_channels * sample_time;
01472 sbuffer_len /= 1000;
01473 sbuffer_len -= sbuffer_len % 2;
01474
01475 state->audio_format = SND_PCM_FORMAT_S16_LE;
01476
01477 int err;
01478 sbuffer = (void *)malloc(sbuffer_len * 8 + SBUFFER_PREFIX);
01479 if((err = snd_pcm_open(&capture_handle, "default", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
01480 return;
01481 if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
01482 return;
01483 if((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0)
01484 return;
01485 snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
01486 snd_pcm_access_mask_none(mask);
01487 snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
01488 if((err = snd_pcm_hw_params_set_access_mask(capture_handle, hw_params, mask)) < 0)
01489 return;
01490 if((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, state->audio_format)) < 0)
01491 return;
01492 unsigned int t = state->audio_rate;
01493 if((err = snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &t, 0)) < 0)
01494 return;
01495 state->audio_rate = t;
01496 if((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params, state->audio_channels)) < 0)
01497 return;
01498 if((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0)
01499 return;
01500 snd_pcm_uframes_t buffer_time = 2000000;
01501 if((err = snd_pcm_hw_params_set_buffer_time_near(capture_handle, hw_params, &buffer_time, 0)) < 0)
01502 return;
01503 fprintf(stderr, "buffer_time is == %d\n", buffer_time);
01504
01505 snd_pcm_sw_params_t *sw_params;
01506 snd_pcm_sw_params_malloc(&sw_params);
01507 err = snd_pcm_sw_params_current(capture_handle, sw_params);
01508 if(err < 0) return;
01509 err = snd_pcm_sw_params_set_tstamp_mode(capture_handle, sw_params, SND_PCM_TSTAMP_MMAP);
01510 if(err < 0) return;
01511 err = snd_pcm_sw_params(capture_handle, sw_params);
01512 if(err < 0) return;
01513
01514 snd_pcm_sw_params_free(sw_params);
01515
01516
01517
01518 snd_pcm_access_mask_free(mask);
01519 snd_pcm_hw_params_free(hw_params);
01520 if((err = snd_pcm_prepare(capture_handle)) < 0)
01521 return;
01522
01523
01524
01525 audio_present = 1;
01526 fprintf(stderr, "audio_init(%d)... OK\n", by_command);
01527
01528 while((slen = snd_pcm_mmap_readi(capture_handle, (void *)(sbuffer), 2)) < 0)
01529 snd_pcm_prepare(capture_handle);
01530 fprintf(stderr, "audio: device is open... !!!!!!!!!!!!!!!!!!!; slen == %d\n", slen);
01531 }
01532 struct timeval tv;
01533 gettimeofday(&tv, NULL);
01534 fprintf(stderr, "audio_init(%d) - at %d:%06d\n", by_command, tv.tv_sec, (unsigned)tv.tv_usec);
01535
01536 }
01537
01538 void audio_start(int by_command) {
01539 if(state->format != CAMOGM_FORMAT_OGM) {
01540 if(audio_present) {
01541 char fname[256];
01542 sprintf(fname, "%s_01.wav", state->path_prefix);
01543
01544 fprintf(stderr, "open WAV file, name == \"%s\"\n", fname);
01545 wave_begin(fname);
01546
01547 }
01548 }
01549 struct timeval tv;
01550 gettimeofday(&tv, NULL);
01551 fprintf(stderr, "audio_start(%d) - at %d:%06d\n", by_command, tv.tv_sec, (unsigned)tv.tv_usec);
01552 }
01553
01554 void audio_end(int by_command) {
01555 if(audio_present) {
01556 if(state->format != CAMOGM_FORMAT_OGM) {
01557
01558 fprintf(stderr, "close WAV file\n");
01559 wave_end();
01560 }
01561 }
01562
01563 if(by_command && audio_set) {
01564 audio_present = 0;
01565 audio_set = 0;
01566 snd_pcm_close(capture_handle);
01567 fprintf(stderr, "audio: device is closed... !!!!!!!!!!!!!!!!!!!\n");
01568 free((void *)sbuffer);
01569 sbuffer = NULL;
01570 }
01571
01572 struct timeval tv;
01573 gettimeofday(&tv, NULL);
01574 fprintf(stderr, "audio_end(%d) - at %d:%06d\n", by_command, tv.tv_sec, (unsigned)tv.tv_usec);
01575 }
01576
01577 void audio_free(void) {
01578 fprintf(stderr, "audio_free()\n");
01579 }