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 #include <sched.h>
00085
00086 #include <netinet/in.h>
00087 #include <sys/mman.h>
00088 #include <sys/ioctl.h>
00089
00090 #include <asm/elphel/c313a.h>
00091
00092 #include <asm/elphel/ext353.h>
00093 #include <asm/byteorder.h>
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
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 600
00122 //#define DEFAULT_DURATION 60
00123 //#define DEFAULT_DURATION 10
00124 //#define DEFAULT_LENGTH 100000000
00125 #define DEFAULT_LENGTH (700 * 1024 * 1024)
00126
00127 #define DEFAULT_FRAMES 16384
00128
00129 #define DEFAULT_FRAMES_PER_CHUNK 1
00130
00131
00132 #define DEFAULT_EXIF 1
00133
00134 #define DEFAULT_AUDIO_RATE 44100
00135 #define DEFAULT_AUDIO_CHANNELS 2
00136
00137 #define AUDIO_RATE_MAX 44100
00138 #define AUDIO_RATE_MIN 11025
00139 #define AUDIO_CHANNELS_MAX 2
00140 #define AUDIO_CHANNELS_MIN 1
00141
00142 static char cmdbuf[1024];
00143 static int cmdbufp=0;
00144 static int cmdstrt=0;
00145
00146 camogm_state sstate;
00147 camogm_state * state;
00148
00149 int debug_level;
00150 FILE* debug_file;
00151
00152
00153 int camogm_init(void);
00154
00155 int camogm_start(int by_command);
00156 int camogm_stop(int by_command);
00157
00158 int camogm_reset(void);
00159 int camogm_debug(const char * fname);
00160 int camogm_debug_level(int d);
00161 void camogm_set_segment_duration(int sd);
00162 void camogm_set_segment_length(int sl);
00163 void camogm_set_save_gp(int d);
00164 void camogm_set_prefix (const char * p);
00165 void camogm_set_exif(int d);
00166 void camogm_set_timescale(double d);
00167 void camogm_set_frames_skip(int d);
00168 void camogm_set_format(int d);
00169
00170 void camogm_kml_set_enable(int d);
00171 void camogm_kml_set_horHalfFov (double dd);
00172 void camogm_kml_set_vertHalfFov(double dd);
00173 void camogm_kml_set_height_mode(int d);
00174 void camogm_kml_set_height(double dd);
00175 void camogm_kml_set_period(int d);
00176 void camogm_kml_set_near(double dd);
00177
00178
00179 int parse_cmd(FILE* npipe);
00180 char * getLineFromPipe(FILE* npipe);
00181
00182 int sendImageFrame (void);
00183
00184 void camogm_set_max_frames(int d);
00185 void camogm_set_frames_per_chunk(int d);
00186
00187
00188 void camogm_set_audio_state(char *args);
00189 void camogm_set_audio_format(char *args);
00190 void camogm_set_sync_state(char *args);
00191 void audio_process(void);
00192 void audio_init(int by_command);
00193 void audio_start(int by_command);
00194 void audio_end(int by_command);
00195 void audio_free(void);
00196 void camogm_audio_initialize(void);
00198
00199 int time_comp(struct timeval *t1, struct timeval *t2) {
00200 if(t1->tv_sec > t2->tv_sec)
00201 return 1;
00202 if(t1->tv_sec == t2->tv_sec) {
00203 if(t1->tv_usec > t2->tv_usec)
00204 return 1;
00205 if(t1->tv_usec == t2->tv_usec)
00206 return 0;
00207 }
00208 return -1;
00209 }
00210
00211 void time_normalize(struct timeval *tv) {
00212 while(tv->tv_usec >= 1000000) {
00213 tv->tv_usec -= 1000000;
00214 tv->tv_sec += 1;
00215 }
00216 }
00217
00218 struct timeval time_delta(struct timeval *t1, struct timeval *t2) {
00219 struct timeval tv;
00220 tv.tv_sec = t1->tv_sec - t2->tv_sec;
00221 if(t1->tv_usec >= t2->tv_usec) {
00222 tv.tv_usec = t1->tv_usec - t2->tv_usec;
00223 } else {
00224 tv.tv_usec = 1000000 + t1->tv_usec - t2->tv_usec;
00225 tv.tv_sec -= 1;
00226 }
00227 return tv;
00228 }
00229
00230 void put_uint16(void *buf, u_int16_t val)
00231 {
00232 unsigned char *tmp;
00233
00234 tmp = (unsigned char *) buf;
00235
00236 tmp[0] = val & 0xff;
00237 tmp[1] = (val >>= 8) & 0xff;
00238 }
00239
00240 void put_uint32(void *buf, u_int32_t val)
00241 {
00242 unsigned char *tmp;
00243
00244 tmp = (unsigned char *) buf;
00245
00246 tmp[0] = val & 0xff;
00247 tmp[1] = (val >>= 8) & 0xff;
00248 tmp[2] = (val >>= 8) & 0xff;
00249 tmp[3] = (val >>= 8) & 0xff;
00250 }
00251
00252 void put_uint64(void *buf, u_int64_t val)
00253 {
00254 unsigned char *tmp;
00255
00256 tmp = (unsigned char *) buf;
00257
00258 tmp[0] = val & 0xff;
00259 tmp[1] = (val >>= 8) & 0xff;
00260 tmp[2] = (val >>= 8) & 0xff;
00261 tmp[3] = (val >>= 8) & 0xff;
00262 tmp[4] = (val >>= 8) & 0xff;
00263 tmp[5] = (val >>= 8) & 0xff;
00264 tmp[6] = (val >>= 8) & 0xff;
00265 tmp[7] = (val >>= 8) & 0xff;
00266 }
00267
00268 int camogm_init(void) {
00269 const char sserial[]="elp0";
00270 int * ipser= (int*) sserial;
00271 state->running=0;
00272 state->starting=0;
00273
00274 state->vf = 0;
00275 camogm_set_segment_duration(DEFAULT_DURATION);
00276 camogm_set_segment_length(DEFAULT_LENGTH);
00277 camogm_set_max_frames(DEFAULT_FRAMES);
00278 camogm_set_frames_per_chunk(DEFAULT_FRAMES_PER_CHUNK);
00279 camogm_set_prefix ("\0");
00280
00281 camogm_set_save_gp(0);
00282 camogm_reset();
00283 state->serialno= ipser[0];
00284 state->last= 0;
00285 debug_file= stderr;
00286 camogm_debug_level(1);
00287 strcpy(state->debug_name,"stderr");
00288 camogm_set_timescale(1.0);
00289 camogm_set_frames_skip(0);
00290 camogm_set_format(CAMOGM_FORMAT_OGM);
00291
00292 camogm_set_audio_state("on");
00293 camogm_set_audio_format("44100/2");
00294 camogm_set_audio_state("off");
00295
00296 camogm_set_sync_state("off");
00297 state->exifSize=0;
00298 state->exif= DEFAULT_EXIF;
00299
00300 state->frameno=0;
00301 state->formats=0;
00302
00303 camogm_audio_initialize();
00304
00306 camogm_kml_set_enable(0);
00307 state->kml_file=NULL;
00308 camogm_kml_set_horHalfFov (20.0);
00309 camogm_kml_set_vertHalfFov(15.0);
00310 camogm_kml_set_height_mode(0);
00311 camogm_kml_set_height(10.0);
00312 camogm_kml_set_period(2);
00313 camogm_kml_set_near(40.0);
00314 state->kml_path[0]='\0';
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 return 0;
00340 }
00341
00342
00343 int camogm_debug(const char * fname) {
00344 int none=1;
00345 if (fname && strlen(fname) && strcmp(fname, "none") && strcmp(fname, "null") && strcmp(fname, "/dev/null")) none=0;
00346 if (debug_file){
00347 if (strcmp(state->debug_name, "stdout") && strcmp(state->debug_name, "stderr")) fclose (debug_file);
00348 debug_file=NULL;
00349 state->debug_name[0]='\0';
00350 }
00351 if (!none) {
00352 if (strcmp(fname, "stdout") ==0) debug_file=stdout;
00353 else if (strcmp(fname, "stderr") ==0) debug_file=stderr;
00354 else debug_file=fopen(fname,"w+");
00355 }
00356 if (debug_file) {
00357 strncpy(state->debug_name,fname,sizeof(state->debug_name)-1);
00358 state->debug_name[sizeof(state->debug_name)-1]='\0';
00359 }
00360 return 0;
00361 }
00362
00363 int camogm_debug_level(int d) {
00364 debug_level=d;
00365 return 0;
00366 }
00367
00368
00369
00370
00371 int camogm_start(int by_command) {
00372 int timestamp_start;
00373 int rslt;
00374 int next_metadata_start, next_jpeg_len, fp;
00375 D1(fprintf (debug_file,"Starting recording\n"));
00376 state->frameno=0;
00377 state->timescale= state->set_timescale;
00378
00379 int * ifp = (int *) &(state->frame_params) ;
00380 int * ifp_this = (int *) &(state->this_frame_params) ;
00381 if (state->kml_enable) camogm_init_kml() ;
00382
00383 audio_init(by_command);
00384 if (state->format != state->set_format) {
00385 state->format= state->set_format;
00386 switch (state->format) {
00387 case CAMOGM_FORMAT_NONE: rslt= 0; break;
00388 case CAMOGM_FORMAT_OGM: rslt= camogm_init_ogm(); break;
00389 case CAMOGM_FORMAT_JPEG: rslt= camogm_init_jpeg();break;
00390 case CAMOGM_FORMAT_MOV: rslt= camogm_init_mov(); break;
00391 }
00392 state->formats |= 1 << (state->format);
00394 }
00395 state->max_frames= state->set_max_frames;
00396 state->frames_per_chunk= state->frames_per_chunk;
00397 state->starting=1;
00398
00399 D3(fprintf (debug_file,"1: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00400 if ((state->cirbuf_rp <0) || (lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET) < 0) || (lseek(state->fd_circ,CIRCLSEEK_VALID,SEEK_END) < 0 )) {
00401 D3(fprintf (debug_file,"2: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00402 state->cirbuf_rp=lseek(state->fd_circ,CIRCLSEEK_LAST,SEEK_END);
00403 if (((fp=lseek(state->fd_circ,CIRCLSEEK_PREV,SEEK_END)))>=0) state->cirbuf_rp=fp;
00404 state->buf_overruns++;
00406
00407
00408 state->buf_min=imageParamsR[P_FREECIRCBUF];
00409
00410 } else {
00411
00412
00413
00414 if (state->buf_min > imageParamsR[P_FREECIRCBUF]) state->buf_min=imageParamsR[P_FREECIRCBUF];
00415
00416 }
00417 D3(fprintf (debug_file,"3: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00418 D3(fprintf (debug_file,"4:lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END)=%d\n",(int) lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END)));
00419
00421 if (lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END) <0) return -CAMOGM_FRAME_NOT_READY;
00422 D3(fprintf (debug_file,"5: state->cirbuf_rp=0x%x\n",state->cirbuf_rp));
00423 state->metadata_start=(state->cirbuf_rp)-32;
00424 if (state->metadata_start<0) state->metadata_start+=state->circ_buff_size;
00425
00427
00428 memcpy (&(state->frame_params), (unsigned long * ) &ccam_dma_buf[state->metadata_start>>2],32);
00429 state->jpeg_len=state->frame_params.frame_length;
00430
00431
00432 if (state->frame_params.signffff !=0xffff) {
00433 D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->frame_params.signffff));
00434 state->cirbuf_rp=-1;
00435 D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp));
00436 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]));
00437 return -CAMOGM_FRAME_BROKEN;
00438 }
00441 timestamp_start=(state->cirbuf_rp)+((state->jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC;
00442 if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00443 memcpy (&(state->frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00444
00446 if ((lseek(state->fd_circ,CIRCLSEEK_NEXT,SEEK_END) < 0 ) ||
00448 (((fp=lseek(state->fd_circ,CIRCLSEEK_READY,SEEK_END))) < 0)) {
00449 lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET);
00450 return -CAMOGM_FRAME_NOT_READY;
00451 }
00452 next_metadata_start=fp-32;
00453 if (next_metadata_start<0) next_metadata_start+= state->circ_buff_size;
00454 memcpy (&(state->this_frame_params), (unsigned long * ) &ccam_dma_buf[next_metadata_start>>2],32);
00455 next_jpeg_len=state->this_frame_params.frame_length;
00456 if (state->this_frame_params.signffff !=0xffff) {
00457 D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->this_frame_params.signffff));
00458 D1(fprintf(debug_file, "fp=0x%x\r\n",(int) fp));
00459 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]));
00460
00461
00462
00463 state->cirbuf_rp=-1;
00464 return -CAMOGM_FRAME_BROKEN;
00465 }
00467 timestamp_start=fp+((next_jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC;
00468 if (timestamp_start >= state->circ_buff_size) timestamp_start-=state->circ_buff_size;
00469 memcpy (&(state->this_frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
00471 if ((state->frame_params.width != state->this_frame_params.width) ||
00472 (state->frame_params.height != state->this_frame_params.height)) {
00474 state->cirbuf_rp=fp;
00475 return -CAMOGM_FRAME_CHANGED;
00476 }
00478 state->frame_period=(state->this_frame_params.timestamp_usec - state->frame_params.timestamp_usec)+
00479 1000000*(state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec);
00480
00482 state->frames_skip= state->set_frames_skip;
00483 if (state->frames_skip > 0) {
00484 state->frames_skip_left=0;
00485 state->frame_period *= (state->frames_skip+1);
00486
00487 } else if (state->frames_skip < 0) {
00488 state->frame_period=-(state->frames_skip) ;
00489 state->frames_skip_left=state->frame_params.timestamp_sec;
00490 }
00491 state->time_unit= (ogg_int64_t) (((double) state-> frame_period) * ((double) 10) / ((double) state-> timescale));
00492 state->width=state->frame_params.width;
00493 state->height=state->frame_params.height;
00494
00497 lseek(state->fd_head,state->cirbuf_rp+1,SEEK_END);
00498
00499 lseek(state->fd_head,0,0);
00500 read (state->fd_head,state->jpegHeader,state->head_size);
00502 lseek(state->fd_circ,state->cirbuf_rp,SEEK_SET);
00504 audio_start(by_command);
00505 switch (state->format) {
00506 case CAMOGM_FORMAT_NONE: rslt= 0; break;
00507 case CAMOGM_FORMAT_OGM: rslt= camogm_start_ogm(); break;
00508 case CAMOGM_FORMAT_JPEG: rslt= camogm_start_jpeg(); break;
00509 case CAMOGM_FORMAT_MOV: rslt= camogm_start_mov(); break;
00510 default: rslt=0;
00511 }
00512 if (rslt) return rslt;
00513 if (state->kml_enable) rslt=camogm_start_kml() ;
00514 if (rslt) return rslt;
00515 state->running=1;
00516 state->starting=0;
00517 D1(fprintf (debug_file,"Started OK\n"));
00518 return 0;
00519 }
00520
00521 struct timeval v_ts;
00522
00523 int sendImageFrame(void) {
00524 int rslt;
00525
00526
00527 unsigned char frame_packet_type = PACKET_IS_SYNCPOINT;
00528
00529
00530
00531 int timestamp_start;
00532
00533
00534 int * ifp_this = (int *) &(state->this_frame_params) ;
00535
00536 struct timeval ts;
00537
00538
00539 if(state->frameno >= (state->max_frames)) {
00540 fprintf(stderr, "--------------------> there is not enough frames...");
00541 return -CAMOGM_FRAME_CHANGED;
00542 }
00543
00544
00545
00546 if(state->format != state->set_format)
00547 return -CAMOGM_FRAME_CHANGED;
00548
00549
00550 if((state->vf) && (state->segment_length >= 0) && (lseek(state->vf, 0, SEEK_CUR) > state->segment_length))
00551 return -CAMOGM_FRAME_CHANGED;
00552
00553 if(((state->ivf) >= 0) && (state->segment_length >= 0) && (lseek(state->ivf, 0, SEEK_CUR) > state->segment_length))
00554 return -CAMOGM_FRAME_CHANGED;
00555
00556 if(lseek(state->fd_circ, state->cirbuf_rp, SEEK_SET) < 0)
00557 return -CAMOGM_FRAME_INVALID;
00558
00559 if(lseek(state->fd_circ, CIRCLSEEK_READY, SEEK_END) < 0)
00560 return -CAMOGM_FRAME_NOT_READY;
00561
00562
00563 if((state->frames_skip > 0) && (state->frames_skip_left > 0)) {
00564 state->cirbuf_rp = lseek(state->fd_circ, CIRCLSEEK_NEXT, SEEK_END);
00565
00566 if(state->save_gp)
00567 lseek(state->fd_circ, CIRCLSEEK_SETP, SEEK_END);
00568 state->frames_skip_left--;
00569 return -CAMOGM_FRAME_NOT_READY;
00570 }
00571
00572
00573
00574 state->metadata_start = state->cirbuf_rp - 32;
00575 if(state->metadata_start < 0)
00576 state->metadata_start += state->circ_buff_size;
00577 memcpy(&(state->this_frame_params), (unsigned long *)&ccam_dma_buf[state->metadata_start >> 2], 32);
00578 state->jpeg_len = state->this_frame_params.frame_length;
00579 if(state->this_frame_params.signffff != 0xffff) {
00580 D0(fprintf(debug_file, "%s:%d: wrong signature - %d\r\n",__FILE__,__LINE__,(int) state->this_frame_params.signffff));
00581 D1(fprintf(debug_file, "state->cirbuf_rp=0x%x\r\n",(int) state->cirbuf_rp));
00582 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]));
00583 return -CAMOGM_FRAME_BROKEN;
00584 }
00585
00586
00587 timestamp_start = state->cirbuf_rp + ((state->jpeg_len + CCAM_MMAP_META + 3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC;
00588 if(timestamp_start >= state->circ_buff_size)
00589 timestamp_start -= state->circ_buff_size;
00590
00591 memcpy(&(state->this_frame_params.timestamp_sec), (unsigned long *)&ccam_dma_buf[timestamp_start >> 2], 8);
00592
00593 ts.tv_sec = state->this_frame_params.timestamp_sec;
00594 ts.tv_usec = state->this_frame_params.timestamp_usec;
00595
00596
00597 if((state->frame_params.width != state->this_frame_params.width) || (state->frame_params.height != state->this_frame_params.height))
00598 return -CAMOGM_FRAME_CHANGED;
00599
00600 if((state->segment_duration > 0) && ((state->this_frame_params.timestamp_sec - state->frame_params.timestamp_sec) > state->segment_duration)) {
00601 fprintf(stderr, "!!! close file !!! \n");
00602 return -CAMOGM_FRAME_CHANGED;
00603 }
00604
00605 if((state->frames_skip < 0) && (state->frames_skip_left > state->this_frame_params.timestamp_sec)) {
00606 state->cirbuf_rp = lseek(state->fd_circ, CIRCLSEEK_NEXT, SEEK_END);
00607
00608 if(state->save_gp)
00609 lseek(state->fd_circ, CIRCLSEEK_SETP, SEEK_END);
00610 return -CAMOGM_FRAME_NOT_READY;
00611 }
00612
00613
00614
00615 if(state->exif) {
00616 D3(fprintf(debug_file,"_5_"));
00617
00618
00619 state->exifSize = lseek(state->fd_exif, 1, SEEK_END);
00620
00621 if(state->exifSize > 0) {
00622
00623 lseek(state->fd_exif, state->this_frame_params.meta_index, SEEK_END);
00624 rslt = read(state->fd_exif, state->ed, state->exifSize);
00625 if(rslt < 0)
00626 rslt = 0;
00627 state->exifSize = rslt;
00628 } else {
00629 state->exifSize = 0;
00630 }
00631 } else {
00632 state->exifSize = 0;
00633 }
00634
00635
00636
00637
00638 state->chunk_index=0;
00639 state->packetchunks[state->chunk_index ].bytes=1;
00640 state->packetchunks[state->chunk_index++].chunk=&frame_packet_type;
00641 if(state->exif > 0) {
00642
00643 state->packetchunks[state->chunk_index ].bytes = 2;
00644 state->packetchunks[state->chunk_index++].chunk = state->jpegHeader;
00645 state->packetchunks[state->chunk_index ].bytes = state->exifSize;
00646 state->packetchunks[state->chunk_index++].chunk = state->ed;
00647 state->packetchunks[state->chunk_index ].bytes = state->head_size - 2;
00648 state->packetchunks[state->chunk_index++].chunk = &(state->jpegHeader[2]);
00649 } else {
00650
00651 state->packetchunks[state->chunk_index ].bytes = state->head_size;
00652 state->packetchunks[state->chunk_index++].chunk = state->jpegHeader;
00653 }
00654
00655
00656
00657
00658 if((state->cirbuf_rp + state->jpeg_len) > state->circ_buff_size) {
00659
00660
00661
00662 state->packetchunks[state->chunk_index ].bytes = state->circ_buff_size-state->cirbuf_rp;
00663 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) &ccam_dma_buf[state->cirbuf_rp >> 2];
00664
00665
00666 state->packetchunks[state->chunk_index ].bytes = state->jpeg_len - (state->circ_buff_size - state->cirbuf_rp);
00667 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) &ccam_dma_buf[0];
00668 } else {
00669
00670
00671
00672 state->packetchunks[state->chunk_index ].bytes = state->jpeg_len;
00673 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) &ccam_dma_buf[state->cirbuf_rp >> 2];
00674 }
00675
00676 state->packetchunks[state->chunk_index ].bytes = 2;
00677 state->packetchunks[state->chunk_index++].chunk = (unsigned char*) trailer;
00678
00679
00680
00681 long delta = ts.tv_sec - v_ts.tv_sec;
00682 delta *= 1000000;
00683 delta += ts.tv_usec;
00684 delta -= v_ts.tv_usec;
00685
00686 v_ts = ts;
00687 state->ts_video = ts;
00688
00689 int flag = 1;
00690 if(ctx_a.begin_of_stream_with_audio) {
00691 if(ctx_a.begin_of_stream_with_audio_trigger) {
00692 state->ts_video_start = state->ts_audio;
00693 state->ts_video_start.tv_usec += state->frame_period / 2;
00694 time_normalize(&state->ts_video_start);
00695 ctx_a.begin_of_stream_with_audio_trigger = 0;
00696
00697 long audio_to_skip = 0;
00698 struct timeval tv = state->ts_video;
00699 while(time_comp(&tv, &state->ts_video_start) < 0) {
00700 tv.tv_usec += state->frame_period;
00701 time_normalize(&tv);
00702 }
00703 tv.tv_sec -= 1;
00704 tv.tv_usec += 1000000;
00705 tv.tv_usec -= state->frame_period / 2;
00706 time_normalize(&tv);
00707 if(tv.tv_sec != state->ts_audio.tv_sec) {
00708 audio_to_skip = tv.tv_sec - state->ts_audio.tv_sec;
00709 audio_to_skip *= 1000000;
00710 }
00711 audio_to_skip += tv.tv_usec;
00712 audio_to_skip -= state->ts_audio.tv_usec;
00713 double s = state->audio_rate;
00714 s /= 1000.0;
00715 s *= audio_to_skip;
00716 s /= 1000.0;
00717 ctx_a.audio_skip_samples = (long)s;
00718 ctx_a.movie_start = tv;
00719 DA( fprintf(stderr, "____ AUDIO started from: %d:%06d; we need to record it from: %d:%06d; audio_to_skip_us == %d; audio samples to skip == %d\n", state->ts_audio.tv_sec, state->ts_audio.tv_usec, tv.tv_sec, tv.tv_usec, audio_to_skip, ctx_a.audio_skip_samples););
00720 }
00721 DA( fprintf(stderr, "AUDIO (start): %d:%06d; VIDEO (current): %d:%06d; frame period is: %d\n", state->ts_audio.tv_sec, state->ts_audio.tv_usec, state->ts_video.tv_sec, state->ts_video.tv_usec, state->frame_period););
00722 if(time_comp(&state->ts_video_start, &state->ts_video) > 0) {
00723 DA( fprintf(stderr, "skip the video frame\n"););
00724 flag = 0;
00725 } else {
00726 DA( fprintf(stderr, "save the VIDEO frame with time: %d:%06d\n", state->ts_video.tv_sec, state->ts_video.tv_usec););
00727 ctx_a.begin_of_stream_with_audio = 0;
00728 }
00729 }
00730 if(flag) {
00731 switch (state->format) {
00732 case CAMOGM_FORMAT_NONE: rslt=0; break;
00733 case CAMOGM_FORMAT_OGM: rslt = camogm_frame_ogm(); break;
00734 case CAMOGM_FORMAT_JPEG: rslt = camogm_frame_jpeg(); break;
00735 case CAMOGM_FORMAT_MOV: rslt = camogm_frame_mov(); break;
00736 default: rslt = 0;
00737 }
00738 } else {
00739 rslt = 0;
00740 }
00741
00742 if(rslt)
00743 return rslt;
00744 if(state->kml_used)
00745 rslt = camogm_frame_kml() ;
00746 if(rslt)
00747 return rslt;
00748
00749
00750
00751 if(flag)
00752 state->frameno++;
00753 state->cirbuf_rp = lseek(state->fd_circ, CIRCLSEEK_NEXT, SEEK_END);
00754
00755 if(state->save_gp)
00756 lseek(state->fd_circ, CIRCLSEEK_SETP, SEEK_END);
00757
00758
00759
00760 if(state->frames_skip > 0) {
00761 state->frames_skip_left = state->frames_skip;
00762 } else {
00763 if(state->frames_skip < 0) {
00764 state->frames_skip_left += -(state->frames_skip);
00765 }
00766 }
00767 return 0;
00768 }
00769
00770 void audio_finish(int by_command) {
00771
00772
00773 DA( fprintf(stderr, "here must be last push of the audio to the file\n"););
00774 struct timeval m_end;
00775 DA( fprintf(stderr, " movie start at: %d:%06d\n", ctx_a.movie_start.tv_sec, ctx_a.movie_start.tv_usec););
00776 m_end = state->ts_video;
00777 m_end.tv_usec += state->frame_period / 2;
00778 time_normalize(&m_end);
00779 DA( fprintf(stderr, " movie end at: %d:%06d\n", m_end.tv_sec, m_end.tv_usec););
00780
00781 struct timeval m_len;
00782 if(m_len.tv_sec != ctx_a.movie_start.tv_sec) {
00783 m_len.tv_sec = m_end.tv_sec - 1;
00784 m_len.tv_usec = m_end.tv_usec + 1000000;
00785 }
00786 m_len.tv_sec -= ctx_a.movie_start.tv_sec;
00787 m_len.tv_usec -= ctx_a.movie_start.tv_usec;
00788 time_normalize(&m_len);
00789 DA( fprintf(stderr, " movie length: %d:%06d\n", m_len.tv_sec, m_len.tv_usec););
00790 ctx_a.movie_start = m_end;
00791
00792 int fd_stream = open("/dev/ext353", O_RDWR);
00793 unsigned long rtc[4];
00794 ioctl(fd_stream, EXT_GET_TIME_SYNC, (void *)&rtc[0]);
00795 close(fd_stream);
00796 DA( fprintf(stderr, "_________________ END ____________________\n"););
00797 DA( fprintf(stderr, " sys time == %d:%06d\n", rtc[0], rtc[1]););
00798 DA( fprintf(stderr, " FPGA time == %d:%06d\n", rtc[2], rtc[3]););
00799 DA( fprintf(stderr, "AUDIO sys time == %d:%06d\n", ctx_a.time_last.tv_sec, ctx_a.time_last.tv_usec););
00800 int flag = 0;
00801 struct timeval audio_last;
00802 audio_last = ctx_a.time_last;
00803 if(m_len.tv_sec > audio_last.tv_sec) {
00804 m_len.tv_sec--;
00805 m_len.tv_usec += 1000000;
00806 }
00807 m_len.tv_sec -= audio_last.tv_sec;
00808 m_len.tv_usec -= audio_last.tv_usec;
00809 time_normalize(&m_len);
00810 long to_finish_us = m_len.tv_usec + 1000000 * m_len.tv_sec;
00811 DA( fprintf(stderr, "... and now we need to save audio for this time: %d:%06d - i.e. %06d usecs\n", m_len.tv_sec, m_len.tv_usec, to_finish_us););
00812 double s = state->audio_rate;
00813 s /= 1000.0;
00814 s *= to_finish_us;
00815 s /= 1000.0;
00816 ctx_a.to_finish_samples = (long)s;
00817
00818 do {
00819 audio_process();
00820 if(ctx_a.to_finish_samples > 0)
00821 sched_yield();
00822 } while(ctx_a.to_finish_samples > 0);
00823 audio_end(by_command);
00824 }
00825
00826 int camogm_stop(int by_command) {
00827 int rslt = 0;
00828 if(!state->running) {
00829 if(!state->starting) {
00830 D2(fprintf (debug_file,"Recording was not running, nothing to stop\n"));
00831 } else {
00832 state->starting = 0;
00833 D1(fprintf (debug_file,"Dropping attempt to start\n"));
00834 }
00835 return 0;
00836 }
00837 D1(fprintf (debug_file,"Ending recording\n"));
00838 if(state->kml_used)
00839 camogm_end_kml() ;
00840
00841 if(ctx_a.audio_present)
00842 audio_finish(by_command);
00843
00844 switch(state->format) {
00845 case CAMOGM_FORMAT_NONE: rslt = 0; break;
00846 case CAMOGM_FORMAT_OGM: rslt = camogm_end_ogm(); break;
00847 case CAMOGM_FORMAT_JPEG: rslt = camogm_end_jpeg();break;
00848 case CAMOGM_FORMAT_MOV: rslt = camogm_end_mov(); break;
00849
00850 }
00851
00852 if(state->vf)
00853 close(state->vf);
00854 state->vf = 0;
00855 if(rslt)
00856 return rslt;
00857 state->last = 1;
00858
00859 state->running = 0;
00860 state->starting = 0;
00861 return 0;
00862 }
00863
00864 void camogm_free() {
00865 int f;
00866
00867
00868 for(f = 0; f < 31; f++) {
00869 if(state->formats & ( 1 << (state->format))) {
00870 switch(f) {
00871 case CAMOGM_FORMAT_NONE: break;
00872 case CAMOGM_FORMAT_OGM: camogm_free_ogm(); break;
00873 case CAMOGM_FORMAT_JPEG: camogm_free_jpeg();break;
00874 case CAMOGM_FORMAT_MOV: camogm_free_mov(); break;
00875 }
00876 }
00877 }
00878 state->formats = 0;
00879 }
00880
00881 int camogm_reset(void) {
00882 state->cirbuf_rp=-1;
00883 state->buf_overruns=-1;
00884 return 0;
00885 }
00886
00888 void camogm_kml_set_enable(int d) {
00889 state->kml_enable=d;
00890 }
00891 void camogm_kml_set_horHalfFov (double dd) {
00892 state->kml_horHalfFov=dd;
00893 }
00894 void camogm_kml_set_vertHalfFov(double dd) {
00895 state->kml_vertHalfFov=dd;
00896 }
00897 void camogm_kml_set_height_mode(int d) {
00898 state->kml_height_mode=d;
00899 }
00900 void camogm_kml_set_height(double dd) {
00901 state->kml_height=dd;
00902 }
00903 void camogm_kml_set_period(int d) {
00904 state->kml_period=d;
00905 state->kml_last_ts=0;
00906 state->kml_last_uts=0;
00907 }
00908 void camogm_kml_set_near(double dd) {
00909 state->kml_near=dd;
00910 }
00911
00912
00913 void camogm_set_segment_duration(int sd) {
00914 state->segment_duration=sd;
00915 }
00916 void camogm_set_segment_length(int sl) {
00917 state->segment_length= sl;
00918 }
00919 void camogm_set_save_gp(int d) {
00920 state->save_gp= d;
00921 }
00922 void camogm_set_exif(int d) {
00923 state->exif= d;
00924 }
00925
00926 void camogm_set_prefix (const char * p) {
00927 strncpy(state->path_prefix, p, sizeof(state->path_prefix)-1);
00928 state->path_prefix[sizeof(state->path_prefix)-1]='\0';
00929 }
00930
00931 void camogm_set_timescale(double d) {
00932 state->set_timescale= d;
00933 if ((state->running==0) && (state->starting==0)) {
00934 state->timescale=state->set_timescale;
00935 }
00936 }
00937
00938 void camogm_set_frames_skip(int d) {
00939 state->set_frames_skip= d;
00940 if ((state->running==0) && (state->starting==0)) {
00941 state->frames_skip= state->set_frames_skip;
00942
00943 state->frames_skip_left= 0;
00944 }
00945 }
00946
00947 void camogm_set_format(int d) {
00948 int rslt=0;
00949 state->set_format = d;
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 }
00966
00968 void camogm_set_max_frames(int d) {
00969 state->set_max_frames= d;
00970 if ((state->running==0) && (state->starting==0)) state->max_frames= d;
00971 }
00972
00973 void camogm_set_frames_per_chunk(int d) {
00974 state->set_frames_per_chunk= d;
00975 if ((state->running==0) && (state->starting==0)) state->frames_per_chunk= d;
00976 }
00977
00978 void camogm_status(char * fn, int xml) {
00979 int _len=0;
00980 int _dur,_udur;
00981
00982 FILE* f;
00983 char *_state, *_output_format, *_using_exif, *_using_global_pointer, *_compressor_state;
00984 int _b_free, _b_used;
00985 int _frames_remain=0;
00986 int _sec_remain=0;
00987 int _frames_skip=0;
00988 int _sec_skip=0;
00989 char *_kml_enable, *_kml_used, *_kml_height_mode;
00990
00991 _kml_enable= state->kml_enable?"yes":"no";
00992 _kml_used= state->kml_used?"yes":"no";
00993 _kml_height_mode= state->kml_height_mode?"GPS altitude":"map ground level";
00994 char *_audio_enable, *_allow_sync;
00995 _audio_enable= state->set_audio_enable?"yes":"no";
00996 _allow_sync= state->set_allow_sync?"yes":"no";
00997
00998
00999 _b_free=imageParamsR[P_FREECIRCBUF];
01000 _b_used=imageParamsR[P_CIRCBUFSIZE]-imageParamsR[P_FREECIRCBUF];
01001
01002 if (!fn) f=stdout;
01003 else if (strcmp(fn, "stdout")==0) f=stdout;
01004 else if (strcmp(fn, "stderr")==0) f=stderr;
01005 else {
01006 if (!((f=fopen (fn,"w")))) {
01007 D0(fprintf (debug_file,"Error opening %s\n", fn));
01008 return;
01009 }
01010 }
01011
01012 if (state->vf) _len=lseek(state->vf, 0, SEEK_CUR);
01013 else if ((state->ivf)>=0) _len=lseek(state->ivf, 0, SEEK_CUR);
01014 _dur= state->this_frame_params.timestamp_sec-state->frame_params.timestamp_sec;
01015 _udur=state->this_frame_params.timestamp_usec-state->frame_params.timestamp_usec;
01016 if (_udur<0) {
01017 _dur-=1;
01018 _udur+=1000000;
01019 } else if (_udur>=1000000) {
01020 _dur+=1;
01021 _udur-=1000000;
01022 }
01023 _state= state->running? "running":(state->starting?"starting":"stopped");
01024 _output_format= state->format?((state->format==CAMOGM_FORMAT_OGM)?"ogm":
01025 ((state->format==CAMOGM_FORMAT_JPEG)?"jpeg":
01026 ((state->format==CAMOGM_FORMAT_MOV)?"mov":
01027 "other"))):"none";
01028 _using_exif= state->exif?"yes":"no";
01029 _using_global_pointer=state->save_gp?"yes":"no";
01030 _compressor_state=(imageParamsR[P_CAMSEQSTATE]==CAMSEQ_RUN)?"running":
01031 ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_SINGLE)?"acquiring":
01032 ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_STOP)?"stoppping":
01033 ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_JPEG)?"stopped":
01034 ((imageParamsR[P_CAMSEQSTATE]==CAMSEQ_OFF)?"reset":"other"))));
01035 if ( state->frames_skip >0 ) {
01036 _frames_remain= state->frames_skip_left;
01037 _frames_skip=state->frames_skip;
01038 } else if ( state->frames_skip <0 ) {
01039 _sec_remain= (state->frames_skip_left - state->this_frame_params.timestamp_sec);
01040 _sec_skip=-(state->frames_skip);
01041 }
01042
01043
01044 if (xml) {
01045 fprintf (f,"<?xml version=\"1.0\"?>\n" \
01046 "<camogm_state>\n" \
01047 " <state>\"%s\"</state>\n" \
01048 " <compressor_state>\"%s\"</compressor_state>\n" \
01049 " <file_name>\"%s\"</file_name>\n" \
01050 " <frame_number>%d</frame_number>\n" \
01051 " <file_duration>%d.%06d</file_duration>\n" \
01052 " <file_length>%d</file_length>\n" \
01053 " <frame_period>%d</frame_period>\n" \
01054 " <frames_skip>%d</frames_skip>\n" \
01055 " <seconds_skip>%d</seconds_skip>\n" \
01056 " <frames_skip_left>%d</frames_skip_left>\n" \
01057 " <seconds_skip_left>%d</seconds_skip_left>\n" \
01058 " <frame_width>%d</frame_width>\n" \
01059 " <frame_height>%d</frame_height>\n" \
01060 " <format>\"%s\"</format>\n" \
01061 " <exif>\"%s\"</exif>\n" \
01062 " <prefix>\"%s\"</prefix>\n" \
01063 " <max_duration>%d</max_duration>\n" \
01064 " <max_length>%d</max_length>\n" \
01065 " <max_frames>%d</max_frames>\n" \
01066 " <timescale>%f</timescale>\n" \
01067 " <frames_per_chunk>%d</frames_per_chunk>\n" \
01068 " <buffer_overruns>%d</buffer_overruns>\n" \
01069 " <buffer_minimal>%d</buffer_minimal>\n" \
01070 " <buffer_free>%d</buffer_free>\n" \
01071 " <buffer_used>%d</buffer_used>\n" \
01072 " <circbuf_rp>%d</circbuf_rp>\n" \
01073 " <debug_output>\"%s\"</debug_output>\n" \
01074 " <debug_level>%d</debug_level>\n" \
01075 " <use_global_rp>\"%s\"</use_global_rp>\n" \
01076 " <kml_enable>\"%s\"</kml_enable>\n" \
01077 " <kml_used>\"%s\"</kml_used>\n" \
01078 " <kml_path>\"%s\"</kml_path>\n" \
01079 " <kml_horHalfFov>\"%f\"</kml_horHalfFov>\n" \
01080 " <kml_vertHalfFov>\"%f\"</kml_vertHalfFov>\n" \
01081 " <kml_near>\"%f\"</kml_near>\n" \
01082 " <kml_height_mode>\"%s\"</kml_height_mode>\n" \
01083 " <kml_height>\"%f\"</kml_height>\n" \
01084 " <kml_period>%d</kml_period>\n" \
01085 " <kml_last_ts>%d.%06d</kml_last_ts>\n" \
01086 " <audio_enable>\"%s\"</audio_enable>\n" \
01087 " <audio_channels>\"%d\"</audio_channels>\n" \
01088 " <audio_rate>\"%d\"</audio_rate>\n" \
01089 " <allow_sync>\"%s\"</allow_sync>\n" \
01090 "</camogm_state>\n",
01091 _state,_compressor_state,state->path,state->frameno,_dur,_udur,_len,state->frame_period, \
01092 _frames_skip,_sec_skip,_frames_remain, _sec_remain, \
01093 state->width,state->height,_output_format,_using_exif, \
01094 state->path_prefix, state->segment_duration, state->segment_length, state->max_frames, state->timescale, \
01095 state->frames_per_chunk, state->buf_overruns, state->buf_min, _b_free, _b_used, state->cirbuf_rp, \
01096 state->debug_name, debug_level, _using_global_pointer, \
01097 _kml_enable,_kml_used,state->kml_path,state->kml_horHalfFov,state->kml_vertHalfFov,state->kml_near,\
01098 _kml_height_mode,state->kml_height,state->kml_period,state->kml_last_ts,state->kml_last_uts,\
01099 _audio_enable,state->set_audio_channels,state->set_audio_rate,_allow_sync);
01100 } else {
01101 fprintf (f,"state %s\n", _state);
01102 fprintf (f,"compressor state %s\n", _compressor_state);
01103 fprintf (f,"file %s\n", state->path);
01104 fprintf (f,"frame %d\n", state->frameno);
01105 fprintf (f,"file duration %d.%06d sec\n",_dur,_udur);
01106 fprintf (f,"file length %d B\n", _len);
01107 fprintf (f,"frame period %d (0x%x)\n", state->frame_period,state->frame_period);
01108 if ( _frames_skip >0 ) fprintf (f,"frames to skip %d (left %d)\n",_frames_skip, _frames_remain);
01109 if ( _sec_skip <0 ) fprintf (f,"timelapse period %d sec (remaining %d sec)\n", _sec_skip, _sec_remain);
01110 fprintf (f,"width %d (0x%x)\n", state->width,state->width);
01111 fprintf (f,"height %d (0x%x)\n", state->height,state->height);
01112 fprintf (f,"\n");
01113 fprintf (f,"output format %s\n", _output_format);
01114 fprintf (f,"using exif %s\n", _using_exif);
01115 fprintf (f,"path prefix: %s\n", state->path_prefix);
01116 fprintf (f,"max file duration: %d sec\n", state->segment_duration);
01117 fprintf (f,"max file length: %d B\n", state->segment_length);
01118 fprintf (f,"max frames %d\n", state->max_frames);
01119 fprintf (f,"timescale %f\n", state->timescale);
01120 fprintf (f,"frames per chunk %d\n", state->frames_per_chunk);
01121 fprintf (f,"\n");
01122 fprintf (f,"buffer overruns %d\n", state->buf_overruns);
01123 fprintf (f,"buffer minimal %d\n", state->buf_min);
01124 fprintf (f,"buffer free %d\n", _b_free);
01125 fprintf (f,"buffer used %d\n", _b_used);
01126 fprintf (f,"circbuf_rp %d (0x%x)\n", state->cirbuf_rp,state->cirbuf_rp);
01127 fprintf (f,"\n");
01128 fprintf (f,"debug output to %s\n", state->debug_name);
01129 fprintf (f,"debug level %d\n", debug_level);
01130 fprintf (f,"use global pointer %s\n", _using_global_pointer);
01131 fprintf (f,"\n\n");
01132 fprintf (f,"kml_enable %s\n", _kml_enable);
01133 fprintf (f,"kml_used %s\n", _kml_used);
01134 fprintf (f,"kml_path %s\n", state->kml_path);
01135 fprintf (f,"kml_horHalfFov %f degrees\n",state->kml_horHalfFov);
01136 fprintf (f,"kml_vertHalfFov %f degrees\n",state->kml_vertHalfFov);
01137 fprintf (f,"kml_near %f m\n", state->kml_near);
01138 fprintf (f,"kml height mode %s\n", _kml_height_mode);
01139 fprintf (f,"kml_height (extra) %f m\n", state->kml_height);
01140 fprintf (f,"kml_period %d\n", state->kml_period);
01141 fprintf (f,"kml_last_ts %d.%06d\n", state->kml_last_ts,state->kml_last_uts);
01142 fprintf (f,"audio_enable %s\n", _audio_enable);
01143 fprintf (f,"audio_channels %d\n", state->set_audio_channels);
01144 fprintf (f,"audio_rate %d\n", state->set_audio_rate);
01145 fprintf (f,"allow_sync %s\n", _allow_sync);
01146 fprintf (f,"\n\n");
01147
01148 }
01149 if ((f!=stdout) && (f!=stderr)) fclose (f);
01150 if (state->buf_overruns>=0) state->buf_overruns=0;
01151 state->buf_min=_b_free;
01152 }
01153
01155 char * getLineFromPipe(FILE* npipe) {
01156 int fl;
01157 char * nlp;
01159 if (cmdstrt > 0) {
01161 memmove(cmdbuf, &cmdbuf[cmdstrt], sizeof(cmdbuf)- cmdstrt);
01162 cmdbufp-=cmdstrt;
01163 cmdstrt=0;
01164 }
01166 if (!cmdbufp) cmdbuf[cmdbufp]=0;
01167
01168 nlp= strpbrk(cmdbuf,";\n");
01169 if (!nlp) {
01170 fl=fread(&cmdbuf[cmdbufp], 1,sizeof(cmdbuf)-cmdbufp-1,npipe);
01171 cmdbuf[cmdbufp+fl]=0;
01173
01174 nlp= strpbrk(&cmdbuf[cmdbufp],";\n");
01175 cmdbufp+=fl;
01176 }
01177 if (nlp) {
01178
01179 nlp[0]=0;
01180 cmdstrt=nlp-cmdbuf+1;
01181
01182
01183 for (fl=0; cmdbuf[fl] && strchr(" \t",cmdbuf[fl]); fl++);
01184
01185 return &cmdbuf[fl];
01186 } else {
01187
01188 return NULL;
01189 }
01190 }
01191
01192 int parse_cmd(FILE* npipe) {
01193 char * cmd;
01194 char * args;
01195 char * argse;
01196 int d;
01197 double dd;
01198
01200 while(((cmd=getLineFromPipe(npipe))) && !cmd[0]) ;
01201 if (!cmd) return 0;
01202
01203 args=strpbrk(cmd,"= \t");
01205 if (args) {
01206 args[0]=0;
01207 args++;
01208 while (strchr("= \t",args[0])) args++;
01209 if (args[0]) {
01211 for (argse=strchr(args,'\0')-1; strchr("= \t",argse[0]);argse--) argse[0]='\0';
01212 }
01213 if (!args[0]) args=NULL;
01214 }
01216 if (strcmp(cmd, "start")==0) {
01217 camogm_start(1);
01218 return 1;
01219 } else if (strcmp(cmd, "reset")==0) {
01220 camogm_reset();
01221 return 2;
01222 } else if (strcmp(cmd, "stop")==0) {
01223 camogm_stop(1);
01224 return 3;
01225 } else if (strcmp(cmd, "exit")==0) {
01226 camogm_stop(1);
01227 camogm_free();
01228 exit (0);
01229 } else if (strcmp(cmd, "duration")==0) {
01230 if (!(args) || (((d= strtol(args, NULL, 10)))<=0)) d=DEFAULT_DURATION;
01231 camogm_set_segment_duration(d);
01232 return 4;
01233 } else if (strcmp(cmd, "length")==0) {
01234 if (!(args) || (((d= strtol(args, NULL, 10)))<=0)) d=DEFAULT_LENGTH;
01235 camogm_set_segment_length(d);
01236 return 5;
01237 } else if (strcmp(cmd, "prefix")==0) {
01238 if (args) camogm_set_prefix (args);
01239 return 6;
01240 } else if (strcmp(cmd, "status")==0) {
01241 camogm_status(args, 0);
01242 return 7;
01243 } else if (strcmp(cmd, "xstatus")==0) {
01244 camogm_status(args, 1);
01245 return 7;
01246 } else if (strcmp(cmd, "save_gp")==0) {
01247 if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_set_save_gp(d);
01248 return 8;
01249 } else if (strcmp(cmd, "exif")==0) {
01250 if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_set_exif(d);
01251 return 8;
01252 } else if (strcmp(cmd, "debug")==0) {
01253 camogm_debug(args);
01254 return 9;
01255 } else if (strcmp(cmd, "timescale")==0) {
01256 dd= strtod(args,NULL);
01257 camogm_set_timescale(dd?dd:1.0);
01258 return 10;
01261
01262
01263 } else if (strcmp(cmd, "frameskip")==0) {
01264 d= strtol(args, NULL, 10);
01265 camogm_set_frames_skip(d);
01266 return 11;
01267 } else if (strcmp(cmd, "timelapse")==0) {
01268 d= strtol(args, NULL, 10);
01269 camogm_set_frames_skip(-d);
01270 return 11;
01271 } else if (strcmp(cmd, "format")==0) {
01272 if (args) {
01273 if (strcmp(args, "none")==0) camogm_set_format(0);
01274 else if ((strcmp(args, "ogm" )==0) || (strcmp(args, "ogg")==0)) camogm_set_format(CAMOGM_FORMAT_OGM);
01275 else if ((strcmp(args, "jpeg")==0) || (strcmp(args, "jpg")==0)) camogm_set_format(CAMOGM_FORMAT_JPEG);
01276 else if (strcmp(args, "mov" )==0) camogm_set_format(CAMOGM_FORMAT_MOV);
01277 }
01278 return 12;
01279 } else if (strcmp(cmd, "debuglev")==0) {
01280 d= strtol(args, NULL, 10);
01281 camogm_debug_level(d?d:0);
01282 return 13;
01283 } else if (strcmp(cmd, "kml")==0) {
01284 if ((args) && (((d= strtol(args, NULL, 10)))>=0)) camogm_kml_set_enable(d);
01285 return 14;
01286 } else if (strcmp(cmd, "kml_hhf")==0) {
01287 dd= strtod(args,NULL);
01288 camogm_kml_set_horHalfFov(dd);
01289 return 15;
01290 } else if (strcmp(cmd, "kml_vhf")==0) {
01291 dd= strtod(args,NULL);
01292 camogm_kml_set_vertHalfFov(dd);
01293 return 16;
01294 } else if (strcmp(cmd, "kml_near")==0) {
01295 dd= strtod(args,NULL);
01296 camogm_kml_set_near(dd);
01297 return 17;
01298 } else if (strcmp(cmd, "kml_alt")==0) {
01299 if (args) {
01300 if (strcmp(args, "gps" )==0) camogm_kml_set_height_mode(1);
01301 else if (strcmp(args, "ground")==0) camogm_kml_set_height_mode(0);
01302 }
01303 return 18;
01304 } else if (strcmp(cmd, "kml_height")==0) {
01305 dd= strtod(args,NULL);
01306 camogm_kml_set_height(dd);
01307 return 19;
01308 } else if (strcmp(cmd, "kml_period")==0) {
01309 d= strtol(args, NULL, 10);
01310 camogm_kml_set_period(d?d:1);
01311 return 20;
01312 } else if (strcmp(cmd, "audio")==0) {
01313 if (args) {
01314 camogm_set_audio_state(args);
01315 }
01316 return 21;
01317 } else if (strcmp(cmd, "audio_format")==0) {
01318 if (args) {
01319 camogm_set_audio_format(args);
01320 }
01321 return 22;
01322 } else if (strcmp(cmd, "allow_sync")==0) {
01323 if (args) {
01324 camogm_set_sync_state(args);
01325 }
01326 return 23;
01327 }
01328
01329 return -1;
01330 }
01331
01332 int main(int argc, char *argv[])
01333 {
01334 const char circbufFileName[]="/dev/circbuf";
01335
01336 FILE * cmd_file;
01337 debug_file = stderr;
01338 const char usage[]= "This program allows recording of the video/images acquired by Elphel camera to the storage media.\n" \
01339 "It is designed to run in the background and accept commands through a named pipe.\n\n" \
01340 "Usage:\n\n" \
01341 "%s <named_pipe_name>\n\n" \
01342 "i.e.:\n\n" \
01343 "%s /var/state/camogm_cmd\n\n" \
01344 "When the program is runninig you may send commands by writing strings to the command file\n" \
01345 "(/var/state/camogm_cmd in the example above). The complete list of available commands is available\n" \
01346 "on Elphel Wiki (http://wiki.elphel.com/index.php?title=Camogm), here is the example of usage\n" \
01347 "from the shell prompt in the camera:\n\n" \
01348 "echo \"status; exif=1; format=jpeg;status=/var/tmp/camogm.status\" > /var/state/camogm_cmd\n\n" \
01349 "That will print status information on the standard output (may not be visible if the program was not\n" \
01350 "started from the same session), set exif mode on (each frame will have the full Exif header including\n" \
01351 "a precise time stamp), set output format to a series of individual JPEG files, and then send status\n" \
01352 "information to a file /var/tmp/camogm.status in the camera file system.\n\n" \
01353 "This program does not control the process of acquisition of the video/images to the camera internal\n" \
01354 "buffer, it only retrieves that data from the buffer (waiting when needed), packages it to selected\n" \
01355 "format and stores the result files.\n\n";
01356 int go=1;
01357 int cmd;
01358 int i,rslt;
01359 state= &sstate;
01361 if ((argc < 2) || (argv[1][1]=='-')) {
01362 printf (usage,argv[0],argv[0]);
01363 return 0;
01364 }
01365 camogm_init();
01366
01368 state->fd_exif = open(ExifFileName, O_RDONLY);
01369 if (state->fd_exif<0) {
01370 D0(fprintf (debug_file,"Error opening %s\n", ExifFileName));
01371 return -1;
01372 }
01373
01375 state->fd_head = open(HeadFileName, O_RDWR);
01376 if (state->fd_head<0) {
01377 D0(fprintf (debug_file,"Error opening %s\n", HeadFileName));
01378 return -1;
01379 }
01380 state->head_size=lseek(state->fd_head,0,SEEK_END);
01381 if (state->head_size>JPEG_HEADER_SIZE) {
01382 D0(fprintf (debug_file,"%s:%d: Too big JPEG header (%d > %d)",__FILE__,__LINE__,state->head_size, JPEG_HEADER_SIZE ));
01383 return -2;
01384 }
01385
01387 state->fd_circ = open(circbufFileName, O_RDWR);
01388 if (state->fd_circ<0) {
01389 D0(fprintf (debug_file,"Error opening %s\n", circbufFileName));
01390 return -2;
01391 }
01393 state->circ_buff_size=lseek(state->fd_circ,0,SEEK_END);
01394 ccam_dma_buf = (unsigned long *) mmap(0, state->circ_buff_size, PROT_READ, MAP_SHARED, state->fd_circ, 0);
01395 if((int)ccam_dma_buf == -1) {
01396 D0(fprintf (debug_file,"Error in mmap of %s\n",circbufFileName));
01397
01398 close(state->fd_circ);
01399 return -3;
01400 }
01401
01403
01405 state->fd_sens = open(SensParsFileName, O_RDWR);
01406 if (state->fd_sens<0) {
01407 D0(fprintf (debug_file,"Error opening %s\n", SensParsFileName));
01408 return -2;
01409 }
01411 state->senspars_size=lseek(state->fd_sens,0,SEEK_END);
01412 imageParamsR = (unsigned long *) mmap(0, state->senspars_size, PROT_READ, MAP_SHARED, state->fd_sens, 0);
01413 if((int)imageParamsR == -1) {
01414 D0(fprintf (debug_file,"Error in mmap of %s\n",SensParsFileName));
01415 close(state->fd_sens);
01416 close(state->fd_circ);
01417 return -3;
01418 }
01419
01420
01421
01424 i=unlink (argv[1]);
01425 if (i) {
01426 D1(fprintf (debug_file,"Unlink %s returned %d, errno=%d \n", argv[1], i, errno));
01427 }
01428 i=mkfifo(argv[1], 0777);
01430 if (i) {
01431 if (errno==EEXIST) {
01432 D1(fprintf (debug_file,"Named pipe %s already exists, will use it.\n", argv[1]));
01433 } else {
01434 D0(fprintf (debug_file,"Can not create a named pipe %s, errno=%d \n", argv[1], errno));
01435 return -4;
01436 }
01437 }
01438
01441 if (!((cmd_file=fopen(argv[1],"r")))) {
01442 D0(fprintf (debug_file,"Can not open command file %s\n",argv[1]));
01443 return -5;
01444 }
01445 D1(fprintf (debug_file,"Pipe %s open for reading\n",argv[1]));
01446
01448 #define COMMAND_LOOP_DELAY 500000 //0.5sec
01449
01450 while(go) {
01451
01453 cmd = parse_cmd(cmd_file);
01454 if(cmd) {
01455 if(cmd < 0)
01456 D0(fprintf(debug_file,"Unrecognized command\n"));
01457 } else {
01458 if(state->running) {
01459
01460
01461
01462
01463
01464 switch((rslt = -sendImageFrame())) {
01465 case 0:
01466 audio_process();
01467
01468
01469
01470
01471 break;
01472 case CAMOGM_FRAME_NOT_READY:
01473
01476
01477
01478
01479
01480
01481 lseek(state->fd_circ,CIRCLSEEK_WAIT,SEEK_END);
01482 break;
01483 case CAMOGM_FRAME_CHANGED:
01484 case CAMOGM_FRAME_NEXTFILE:
01485 case CAMOGM_FRAME_INVALID:
01486 case CAMOGM_FRAME_BROKEN:
01487
01488
01489 fprintf(stderr, "broken frame - restart of sequence...\n");
01490 camogm_stop(0);
01491 camogm_start(0);
01492 break;
01493 case CAMOGM_FRAME_FILE_ERR:
01494 case CAMOGM_FRAME_OTHER:
01495 D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt));
01496 break;
01497 default:
01498 D0(fprintf (debug_file,"%s:line %d - should not get here (rslt=%d)\n",__FILE__,__LINE__,rslt));
01499 exit (-1);
01500 }
01501 if(rslt != 0 && rslt != CAMOGM_FRAME_NOT_READY) {
01502 fprintf(stderr, "loosed frame...\n");
01503 }
01504 } else {
01505 if(state->starting) {
01506
01507
01509 switch ((rslt = -camogm_start(1))) {
01510 case 0:
01511 break;
01512 case CAMOGM_FRAME_NOT_READY:
01513
01514
01515
01516 case CAMOGM_FRAME_CHANGED:
01517 case CAMOGM_FRAME_NEXTFILE:
01518 case CAMOGM_FRAME_INVALID:
01519 case CAMOGM_FRAME_BROKEN:
01520
01521 usleep( COMMAND_LOOP_DELAY) ;
01522 break;
01523 case CAMOGM_FRAME_FILE_ERR:
01524 case CAMOGM_FRAME_OTHER:
01525 D0(fprintf (debug_file,"%s:line %d - error=%d\n",__FILE__,__LINE__,rslt));
01526 break;
01527 default:
01528 D0(fprintf (debug_file,"%s:line %d - should not get here (rslt=%d)\n",__FILE__,__LINE__,rslt));
01529 exit (-1);
01530 }
01531 } else {
01532 usleep( COMMAND_LOOP_DELAY) ;
01533 }
01534 }
01535 }
01536 }
01537 return 0;
01538 }
01539
01540
01541
01542
01543
01544
01545
01546 void camogm_set_audio_state(char *args) {
01547 if(strcmp(args, "on") == 0 || strcmp(args, "enable") == 0) {
01548 state->set_audio_enable = 1;
01549 }
01550 if(strcmp(args, "off") == 0 || strcmp(args, "disable") == 0) {
01551 state->set_audio_enable = 0;
01552 }
01553 DA( fprintf(stderr, "request for audio state: %s\n", args););
01554 }
01555
01556 void camogm_set_sync_state(char *args) {
01557 if(strcmp(args, "on") == 0 || strcmp(args, "enable") == 0) {
01558 state->set_allow_sync = 1;
01559 }
01560 if(strcmp(args, "off") == 0 || strcmp(args, "disable") == 0) {
01561 state->set_allow_sync = 0;
01562 }
01563 }
01564
01565 void camogm_set_audio_format(char *args) {
01566 char buf[8];
01567 int i;
01568 int channels = -1;
01569 int rate = -1;
01570 char *right = strstr(args, "/");
01571 if(right != NULL) {
01572 channels = atol(&right[1]);
01573 if(channels < AUDIO_CHANNELS_MIN)
01574 channels = AUDIO_CHANNELS_MIN;
01575 if(channels > AUDIO_CHANNELS_MAX)
01576 channels = AUDIO_CHANNELS_MAX;
01577 state->set_audio_channels = channels;
01578 }
01579 for(i = 0; i < 7; i++) {
01580 if(args[i] != '\0' && args[i] != '/')
01581 buf[i] = args[i];
01582 else
01583 break;
01584 }
01585 buf[i] = '\0';
01586 if(buf[0] != '\0') {
01587 rate = atol(buf);
01588 if(rate < AUDIO_RATE_MIN)
01589 rate = AUDIO_RATE_MIN;
01590 if(rate > AUDIO_RATE_MAX)
01591 rate = AUDIO_RATE_MAX;
01592 state->set_audio_rate = rate;
01593 }
01594
01595 DA( fprintf(stderr, "request for audio format: %s; after apply: rate == %d; channels == %d\n", args, state->set_audio_rate, state->set_audio_channels););
01596 }
01597
01598 void camogm_audio_initialize(void) {
01599 ctx_a.audio_present = 0;
01600 ctx_a.audio_set = 0;
01601 ctx_a.capture_handle = NULL;
01602 ctx_a.sbuffer = NULL;
01603 ctx_a.sample_time = 200;
01604 }
01605
01606 void audio_process(void) {
01607 if(ctx_a.audio_present == 0)
01608 return;
01609 if(state->format == CAMOGM_FORMAT_JPEG)
01610 return;
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625 int counter = 0;
01626 void *_buf;
01627 int _buf_len;
01628 struct timeval tv_sys;
01629 if(state->format == CAMOGM_FORMAT_OGM || state->format == CAMOGM_FORMAT_MOV) {
01630 int slen;
01631 int _len = 0;
01632 snd_pcm_status_t *status;
01633 snd_pcm_status_alloca(&status);
01634 snd_timestamp_t ts;
01635 for(;;) {
01636 counter++;
01637 long avail = 0;
01638 avail = snd_pcm_avail_update(ctx_a.capture_handle);
01639 gettimeofday(&tv_sys);
01640 tv_sys.tv_usec += ctx_a.sample_time;
01641 time_normalize(&tv_sys);
01642 snd_pcm_status(ctx_a.capture_handle, status);
01643 snd_pcm_status_get_tstamp(status, &ts);
01644
01645
01646 int to_push_flag = 0;
01647 int to_read = ctx_a.sbuffer_len;
01648 if(ctx_a.to_finish_samples < 0)
01649 ctx_a.to_finish_samples = 0;
01650 if(avail >= ctx_a.sbuffer_len && ctx_a.to_finish_samples == 0)
01651 to_push_flag = 1;
01652 if(ctx_a.to_finish_samples > 0) {
01653 if(ctx_a.to_finish_samples > ctx_a.sbuffer_len) {
01654 if(avail >= ctx_a.sbuffer_len) {
01655 to_read = ctx_a.sbuffer_len;
01656 ctx_a.to_finish_samples -= ctx_a.sbuffer_len;
01657 to_push_flag = 2;
01658 }
01659 } else {
01660 if(avail >= ctx_a.to_finish_samples) {
01661 to_read = ctx_a.to_finish_samples;
01662 ctx_a.to_finish_samples = 0;
01663 to_push_flag = 2;
01664 }
01665 }
01666 }
01667 if(to_push_flag) {
01668 slen = snd_pcm_mmap_readi(ctx_a.capture_handle, (void *)(ctx_a.sbuffer + AUDIO_SBUFFER_PREFIX), to_read);
01669
01670
01671 if(slen > 0) {
01672 int flag = 1;
01673 long offset = 0;
01674
01675 if(to_push_flag == 1) {
01676 struct timeval sl = ctx_a.time_last;
01677 sl.tv_usec += ctx_a.sample_time;
01678 time_normalize(&sl);
01679 struct timeval m_end;
01680 m_end = state->ts_video;
01681 m_end.tv_usec += state->frame_period / 2;
01682 time_normalize(&m_end);
01683 struct timeval m_len;
01684 if(m_len.tv_sec != ctx_a.movie_start.tv_sec) {
01685 m_len.tv_sec = m_end.tv_sec - 1;
01686 m_len.tv_usec = m_end.tv_usec + 1000000;
01687 }
01688 m_len.tv_sec -= ctx_a.movie_start.tv_sec;
01689 m_len.tv_usec -= ctx_a.movie_start.tv_usec;
01690 time_normalize(&m_len);
01691 if(time_comp(&sl, &m_len) > 0) {
01692
01693 break;
01694 }
01695 }
01696
01697
01698
01699
01700 if(ctx_a.audio_skip_samples != 0) {
01701 DA(fprintf(stderr, "skip_samples == %d\n", ctx_a.audio_skip_samples, slen););
01702 if(ctx_a.audio_skip_samples >= slen) {
01703 ctx_a.audio_skip_samples -= slen;
01704 flag = 0;
01705 } else {
01706 offset = ctx_a.audio_skip_samples;
01707 ctx_a.audio_skip_samples = 0;
01708 }
01709 }
01710 if(flag) {
01711 long samples = slen - offset;
01712 ctx_a.audio_count += samples;
01713 _buf = (void *)(ctx_a.sbuffer + AUDIO_SBUFFER_PREFIX);
01714 _buf = (void *)((char *)_buf + offset * 2 * state->audio_channels);
01715 _buf_len = samples * 2 * state->audio_channels;
01716 if(state->format == CAMOGM_FORMAT_OGM)
01717 camogm_audio_ogm_push(_buf, _buf_len, samples, AUDIO_SBUFFER_PREFIX);
01718 if(state->format == CAMOGM_FORMAT_MOV)
01719 camogm_audio_mov(_buf, _buf_len, samples);
01720 float tr = 1.0 / state->audio_rate;
01721 float l = tr * ctx_a.audio_count;
01722 unsigned long s = (unsigned long)l;
01723 l -= s;
01724 l *= 1000000;
01725 unsigned long us = (unsigned long)l;
01726 ctx_a.time_last.tv_sec = s;
01727 ctx_a.time_last.tv_usec = us;
01728 DA( fprintf(stderr, "%d: sound time %d:%06d, at %d:%06d; and the sound time is: %d:%06d, samples: %d\n", counter, s, us, tv_sys.tv_sec, tv_sys.tv_usec, ctx_a.time_last.tv_sec, ctx_a.time_last.tv_usec, samples););
01729 }
01730 }
01731 } else {
01732 break;
01733 }
01734 }
01735 }
01736 }
01737
01738 void audio_init(by_command) {
01739
01740 state->audio_enable = state->set_audio_enable;
01741 state->audio_rate = state->set_audio_rate;
01742 state->audio_channels = state->set_audio_channels;
01743 state->allow_sync = state->set_allow_sync;
01744
01745
01746
01747
01748 int slen;
01749 snd_timestamp_t audio_ts;
01750 if(state->audio_enable == 0) {
01751 return;
01752 }
01753 if(state->format == CAMOGM_FORMAT_JPEG)
01754 return;
01755
01756 if(by_command && !ctx_a.audio_set) {
01757 snd_pcm_hw_params_t *hw_params;
01758 ctx_a.audio_set = 1;
01759
01760
01761 ctx_a.sbuffer_len = state->audio_rate * ctx_a.sample_time;
01762 ctx_a.sbuffer_len /= 1000;
01763 ctx_a.sbuffer_len -= ctx_a.sbuffer_len % 2;
01764
01765 DA( fprintf(stderr, "sbuffer_len == %d\n", ctx_a.sbuffer_len););
01766
01767
01768 int audio_format = SND_PCM_FORMAT_S16_LE;
01769
01770 int err;
01771 ctx_a.sbuffer = (void *)malloc(ctx_a.sbuffer_len * 8 + AUDIO_SBUFFER_PREFIX);
01772 if((err = snd_pcm_open(&ctx_a.capture_handle, "default", SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
01773 return;
01774 if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
01775 return;
01776 if((err = snd_pcm_hw_params_any(ctx_a.capture_handle, hw_params)) < 0)
01777 return;
01778 snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
01779 snd_pcm_access_mask_none(mask);
01780 snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
01781 if((err = snd_pcm_hw_params_set_access_mask(ctx_a.capture_handle, hw_params, mask)) < 0)
01782 return;
01783
01784 if((err = snd_pcm_hw_params_set_format(ctx_a.capture_handle, hw_params, audio_format)) < 0)
01785 return;
01786 unsigned int t = state->audio_rate;
01787 if((err = snd_pcm_hw_params_set_rate_near(ctx_a.capture_handle, hw_params, &t, 0)) < 0)
01788 return;
01789 state->audio_rate = t;
01790 if((err = snd_pcm_hw_params_set_channels(ctx_a.capture_handle, hw_params, state->audio_channels)) < 0)
01791 return;
01792 if((err = snd_pcm_hw_params(ctx_a.capture_handle, hw_params)) < 0)
01793 return;
01794 snd_pcm_uframes_t buffer_time = 2000000;
01795 if((err = snd_pcm_hw_params_set_buffer_time_near(ctx_a.capture_handle, hw_params, &buffer_time, 0)) < 0)
01796 return;
01797
01798
01799 snd_pcm_sw_params_t *sw_params;
01800 snd_pcm_sw_params_malloc(&sw_params);
01801 err = snd_pcm_sw_params_current(ctx_a.capture_handle, sw_params);
01802 if(err < 0) return;
01803 err = snd_pcm_sw_params_set_tstamp_mode(ctx_a.capture_handle, sw_params, SND_PCM_TSTAMP_MMAP);
01804 if(err < 0) return;
01805 err = snd_pcm_sw_params(ctx_a.capture_handle, sw_params);
01806 if(err < 0) return;
01807 snd_pcm_sw_params_free(sw_params);
01808
01809 snd_pcm_hw_params_free(hw_params);
01810 if((err = snd_pcm_prepare(ctx_a.capture_handle)) < 0)
01811 return;
01812
01813 ctx_a.audio_present = 1;
01814 ctx_a.begin_of_stream_with_audio = 1;
01815 ctx_a.begin_of_stream_with_audio_trigger = 1;
01816
01817 ctx_a.audio_count = 0;
01818 ctx_a.audio_skip_samples = 0;
01819
01820 int fd_stream = open("/dev/ext353", O_RDWR);
01821 unsigned long rtc[4];
01822 ioctl(fd_stream, EXT_GET_TIME_SYNC, (void *)&rtc[0]);
01823 close(fd_stream);
01824 DA( fprintf(stderr, "SYNC; sys time == %d:%06d; ", rtc[0], rtc[1]););
01825 DA( fprintf(stderr, "FPGA time == %d:%06d\n", rtc[2], rtc[3]););
01826
01827 fprintf(stderr, "audio_init(%d)... OK\n", by_command);
01828 snd_pcm_status_t *status;
01829 snd_pcm_status_alloca(&status);
01830 while((slen = snd_pcm_mmap_readi(ctx_a.capture_handle, (void *)(ctx_a.sbuffer), 2)) < 0)
01831 snd_pcm_prepare(ctx_a.capture_handle);
01832 snd_pcm_status(ctx_a.capture_handle, status);
01833 snd_pcm_status_get_tstamp(status, &audio_ts);
01834 DA( fprintf(stderr, "audio: device is open... !!!!!!!!!!!!!!!!!!!; slen == %d\n", slen););
01835
01836 struct timeval d;
01837 d.tv_sec = rtc[0] - 1;
01838 d.tv_usec = rtc[1] + 1000000;
01839 d.tv_sec -= rtc[2];
01840 d.tv_usec -= rtc[3];
01841 time_normalize(&d);
01842 struct timeval tv;
01843 tv = audio_ts;
01844 tv.tv_sec -= 1;
01845 tv.tv_usec += 1000000;
01846 tv.tv_sec -= d.tv_sec;
01847 tv.tv_usec -= d.tv_usec;
01848 time_normalize(&tv);
01849 state->ts_audio = tv;
01850
01851 gettimeofday(&tv, NULL);
01852 DA( fprintf(stderr, "audio_init(%d) - at %d:%06d", by_command, tv.tv_sec, (unsigned)tv.tv_usec););
01853 DA( fprintf(stderr, "status at %d:%06d\n", audio_ts.tv_sec, audio_ts.tv_usec););
01854 }
01855 }
01856
01857 void audio_start(int by_command) {
01858 state->audio_frameno = 0;
01859 state->audio_samples = 0;
01860 ctx_a.to_finish_samples = 0;
01861 ctx_a.time_last.tv_sec = 0;
01862 ctx_a.time_last.tv_usec = 0;
01863 ctx_a.audio_count = 0;
01864 if(state->format == CAMOGM_FORMAT_JPEG)
01865 return;
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877 struct timeval tv;
01878 gettimeofday(&tv, NULL);
01879 DA( fprintf(stderr, "audio_start(%d) - at %d:%06d\n", by_command, tv.tv_sec, (unsigned)tv.tv_usec););
01880 }
01881
01882 void audio_end(int by_command) {
01883 if(ctx_a.audio_present) {
01884 if(state->format == CAMOGM_FORMAT_JPEG)
01885 return;
01886
01887
01888
01889
01890
01891
01892
01893 }
01894
01895 if(by_command && ctx_a.audio_set) {
01896 ctx_a.audio_present = 0;
01897 ctx_a.audio_set = 0;
01898 snd_pcm_close(ctx_a.capture_handle);
01899 DA( fprintf(stderr, "audio: device is closed... !!!!!!!!!!!!!!!!!!!\n"););
01900 free((void *)ctx_a.sbuffer);
01901 ctx_a.sbuffer = NULL;
01902 }
01903
01904 struct timeval tv;
01905 gettimeofday(&tv, NULL);
01906 DA( fprintf(stderr, "audio_end(%d) - at %d:%06d\n", by_command, tv.tv_sec, (unsigned)tv.tv_usec););
01907 }
01908
01909 void audio_free(void) {
01910
01911 }