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
00030 #include <unistd.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <signal.h>
00034 #include <fcntl.h>
00035 #include <sys/uio.h>
00036 #include <errno.h>
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 #include <sys/stat.h>
00040
00041
00042 #include <time.h>
00043 #include <string.h>
00044
00045 #include <netinet/in.h>
00046 #include <sys/mman.h>
00047 #include <sys/ioctl.h>
00048
00049 #include <asm/elphel/c313a.h>
00050 #include <asm/elphel/ext353.h>
00051 #include <asm/byteorder.h>
00052
00053
00054 #include <ogg/ogg.h>
00055 #include "ogmstreams.h"
00056
00057 #include "camogm_kml.h"
00058 #include "camogm.h"
00059 const char ExifDirFileName[]="/dev/exif_metadir";
00060
00062 int camogm_init_kml(void) {
00063 return 0;
00064 }
00065 void camogm_free_kml(void) {
00066 }
00067
00068
00069
00071
00073
00074
00075
00076
00077
00080
00081
00082
00083
00084
00085
00086 int camogm_start_kml(void) {
00087
00091 struct exif_dir_table_t dir_table_entry;
00092 int fd_ExifDir;
00093 int indx;
00094 for (indx=0;indx<ExifKmlNumber;indx++) state->kml_exif[indx].ltag=0;
00096 fd_ExifDir=open(ExifDirFileName,O_RDONLY);
00097 if (fd_ExifDir<0) {
00098 D0(fprintf (debug_file,"Error opening %s\n", ExifDirFileName));
00099 return -CAMOGM_FRAME_FILE_ERR;
00100 }
00101 while (read(fd_ExifDir, &dir_table_entry, sizeof(dir_table_entry))>0) {
00102 switch (dir_table_entry.ltag) {
00103 case Exif_Photo_DateTimeOriginal: indx= Exif_Photo_DateTimeOriginal_Index; break;
00104 case Exif_GPSInfo_GPSLatitudeRef: indx= Exif_GPSInfo_GPSLatitudeRef_Index; break;
00105 case Exif_GPSInfo_GPSLatitude: indx= Exif_GPSInfo_GPSLatitude_Index ; break;
00106 case Exif_GPSInfo_GPSLongitudeRef: indx= Exif_GPSInfo_GPSLongitudeRef_Index ; break;
00107 case Exif_GPSInfo_GPSLongitude: indx= Exif_GPSInfo_GPSLongitude_Index; break;
00108 case Exif_GPSInfo_GPSAltitudeRef: indx= Exif_GPSInfo_GPSAltitudeRef_Index; break;
00109 case Exif_GPSInfo_GPSAltitude: indx= Exif_GPSInfo_GPSAltitude_Index; break;
00110 case Exif_GPSInfo_GPSTimeStamp: indx= Exif_GPSInfo_GPSTimeStamp_Index; break;
00111 case Exif_GPSInfo_GPSDateStamp: indx= Exif_GPSInfo_GPSDateStamp_Index; break;
00112 case Exif_GPSInfo_CompassDirectionRef: indx= Exif_GPSInfo_CompassDirectionRef_Index; break;
00113 case Exif_GPSInfo_CompassDirection: indx= Exif_GPSInfo_CompassDirection_Index; break;
00114 case Exif_GPSInfo_CompassPitchRef: indx= Exif_GPSInfo_CompassPitchRef_Index; break;
00115 case Exif_GPSInfo_CompassPitch: indx= Exif_GPSInfo_CompassPitch_Index; break;
00116 case Exif_GPSInfo_CompassRollRef: indx= Exif_GPSInfo_CompassRollRef_Index; break;
00117 case Exif_GPSInfo_CompassRoll: indx= Exif_GPSInfo_CompassRoll_Index; break;
00118 default: indx=-1;
00119 }
00120 if (indx>=0) {
00121 memcpy(&(state->kml_exif[indx]),&dir_table_entry,sizeof(dir_table_entry));
00122 D2(fprintf(debug_file,"indx=%02d, ltag=0x%05x, len=0x%03x, src=0x%03x, dst=0x%03x\n",indx, \
00123 (int) dir_table_entry.ltag, \
00124 (int) dir_table_entry.len, \
00125 (int) dir_table_entry.src, \
00126 (int) dir_table_entry.dst));
00127 }
00128 }
00129 close (fd_ExifDir);
00130 sprintf(state->kml_path,"%s%010ld_%06ld.kml",state->path_prefix,state->this_frame_params.timestamp_sec,state->this_frame_params.timestamp_usec);
00131 if (!((state->kml_file=fopen(state->kml_path,"w+"))) ){
00132 D0(fprintf (debug_file, "Error opening %s for writing\n", state->kml_path));
00133 return -CAMOGM_FRAME_FILE_ERR;
00134 }
00136 fprintf (state->kml_file,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
00137 "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n");
00138 fprintf (state->kml_file,"<Document>\n");
00139 state->kml_used= 1;
00140 return 0;
00141 }
00142
00143 int camogm_frame_kml(void){
00144 char JPEGFileName[300];
00145 char * filename;
00146 int fd_JPEG;
00147 int i,j;
00148 ssize_t iovlen,l;
00149 struct iovec chunks_iovec[7];
00150 char datestr[11];
00151 double longitude=0.0, latitude=0.0, altitude=0.0, heading=0.0, tilt=0.0, roll=0.0, pitch=0.0;
00152 int hours=0, minutes=0;
00153 double seconds=0.0;
00154 int * ip;
00155 if (state->kml_file) {
00156 i=state->this_frame_params.timestamp_sec - (state->kml_last_ts + state->kml_period);
00157 if ((i>1) || ((i==0) && ( state->this_frame_params.timestamp_usec > state->kml_last_uts ))) {
00158
00159 state->kml_last_ts=state->this_frame_params.timestamp_sec;
00160 state->kml_last_uts=state->this_frame_params.timestamp_usec;
00161 if (state->format==CAMOGM_FORMAT_JPEG) {
00162 strcpy (JPEGFileName, state->path);
00163 } else {
00164 sprintf(JPEGFileName,"%s%010ld_%06ld.jpeg",state->path_prefix,state->this_frame_params.timestamp_sec,state->this_frame_params.timestamp_usec);
00165 if (((fd_JPEG=open(JPEGFileName,O_RDWR | O_CREAT, 0777)))>=0){
00166 l=0;
00167 for (i=0; i< (state->chunk_index)-1; i++) {
00168 chunks_iovec[i].iov_base=state->packetchunks[i+1].chunk;
00169 chunks_iovec[i].iov_len= state->packetchunks[i+1].bytes;
00170 l+=chunks_iovec[i].iov_len;
00171 }
00172 iovlen=writev(fd_JPEG,chunks_iovec, (state->chunk_index)-1);
00173 if (iovlen < l) {
00174 j=errno;
00175 D0(fprintf(debug_file,"writev error %d (returned %d, expected %d)\n",j,iovlen,l));
00176 close (fd_JPEG);
00177 return -CAMOGM_FRAME_FILE_ERR;
00178 }
00179 close (fd_JPEG);
00180 } else {
00181 D0(fprintf (debug_file, "Error opening %s for writing, returned %d, errno=%d\n", JPEGFileName,fd_JPEG,errno));
00182 return -CAMOGM_FRAME_FILE_ERR;
00183 }
00184 }
00185
00187 filename=strrchr(JPEGFileName, '/');
00188 filename[0]='\0';
00189 filename++;
00192 if (state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].ltag==Exif_GPSInfo_GPSDateStamp) {
00193 memcpy(datestr, &(state->ed[state->kml_exif[Exif_GPSInfo_GPSDateStamp_Index].dst]) ,10);
00194 datestr[4]='-';datestr[7]='-';datestr[10]='\0';
00195 }
00196 if (state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].ltag==Exif_GPSInfo_GPSTimeStamp) {
00197 ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSTimeStamp_Index].dst]);
00198 hours= __cpu_to_be32( ip[0]);
00199 minutes= __cpu_to_be32( ip[2]);
00200 seconds= (1.0*(__cpu_to_be32( ip[4])+1))/__cpu_to_be32( ip[5]);
00201 D2(fprintf (debug_file,"(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",ip[0],ip[1],ip[2],ip[3],ip[4],ip[5]));
00202 D2(fprintf (debug_file,"(when) 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",__cpu_to_be32(ip[0]), \
00203 __cpu_to_be32(ip[1]), \
00204 __cpu_to_be32(ip[2]), \
00205 __cpu_to_be32(ip[3]), \
00206 __cpu_to_be32(ip[4]), \
00207 __cpu_to_be32(ip[5])));
00208 }
00209 D1(fprintf (debug_file,"when=%sT%02d:%02d:%05.2fZ\n",datestr, hours, minutes, seconds));
00210
00212 if (state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].ltag==Exif_GPSInfo_GPSLongitude) {
00213 ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitude_Index].dst]);
00214 longitude=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3]));
00215 if ((state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].ltag==Exif_GPSInfo_GPSLongitudeRef) &&
00216 (state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst] != 'E')) longitude=-longitude;
00217 D2(fprintf (debug_file,"(longitude) 0x%x 0x%x 0x%x 0x%x '%c'\n",ip[0],ip[1],ip[2],ip[3],state->ed[state->kml_exif[Exif_GPSInfo_GPSLongitudeRef_Index].dst]));
00218 }
00219
00220 if (state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].ltag==Exif_GPSInfo_GPSLatitude) {
00221 ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitude_Index].dst]);
00222 latitude=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3]));
00223 if ((state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].ltag==Exif_GPSInfo_GPSLatitudeRef) &&
00224 (state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst] != 'N')) latitude=-latitude;
00225 D2(fprintf (debug_file,"(latitude) 0x%x 0x%x 0x%x 0x%x '%c'\n",ip[0],ip[1],ip[2],ip[3],state->ed[state->kml_exif[Exif_GPSInfo_GPSLatitudeRef_Index].dst]?'-':'+'));
00226 }
00228 if (state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].ltag==Exif_GPSInfo_GPSAltitude) {
00229 ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitude_Index].dst]);
00230 altitude=(1.0*__cpu_to_be32( ip[0]))/__cpu_to_be32( ip[1]);
00231 if ((state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].ltag==Exif_GPSInfo_GPSAltitudeRef) &&
00232 (state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst] != '\0')) altitude=-altitude;
00233 D2(fprintf (debug_file,"(altitude) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_GPSAltitudeRef_Index].dst]));
00234 }
00235
00236 D1(fprintf (debug_file,"longitude=%f, latitude=%f, altitude=%f\n",longitude, latitude, altitude));
00237
00239 if (state->kml_exif[Exif_GPSInfo_CompassDirection_Index].ltag==Exif_GPSInfo_CompassDirection) {
00240 ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassDirection_Index].dst]);
00241 heading=(1.0*__cpu_to_be32( ip[0]))/__cpu_to_be32( ip[1]);
00242 D2(fprintf (debug_file,"(heading) 0x%x 0x%x\n",ip[0],ip[1]));
00243 }
00245 if (state->kml_exif[Exif_GPSInfo_CompassRoll_Index].ltag==Exif_GPSInfo_CompassRoll) {
00246 ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassRoll_Index].dst]);
00247 roll=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3]));
00248 if ((state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].ltag==Exif_GPSInfo_CompassRollRef) &&
00249 (state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst] != EXIF_COMPASS_ROLL_ASCII[0])) roll=-roll;
00250 D2(fprintf (debug_file,"(roll) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_CompassRollRef_Index].dst]));
00251 }
00252
00253 if (state->kml_exif[Exif_GPSInfo_CompassPitch_Index].ltag==Exif_GPSInfo_CompassPitch) {
00254 ip= (int *) &(state->ed[state->kml_exif[Exif_GPSInfo_CompassPitch_Index].dst]);
00255 pitch=__cpu_to_be32( ip[0])/(1.0*__cpu_to_be32( ip[1])) + __cpu_to_be32( ip[2])/(60.0*__cpu_to_be32( ip[3]));
00256 if ((state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].ltag==Exif_GPSInfo_CompassPitchRef) &&
00257 (state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst] != EXIF_COMPASS_PITCH_ASCII[0])) pitch=-pitch;
00258 D2(fprintf (debug_file,"(pitch) 0x%x 0x%x '%c'\n",ip[0],ip[1],state->ed[state->kml_exif[Exif_GPSInfo_CompassPitchRef_Index].dst]));
00259 }
00261 tilt=roll+90.0;
00262 if (tilt <0.0) tilt=0;
00263 else if (tilt > 180.0) tilt=180.0;
00264 D2(fprintf (debug_file,"heading=%f, roll=%f, pitch=%f, tilt=%f\n",heading, roll, pitch, tilt));
00265
00267 altitude=(state->kml_height_mode?altitude:0.0)+state->kml_height;
00268
00269
00271 fprintf(state->kml_file,"<PhotoOverlay>\n" \
00272 " <shape>rectangle</shape>\n" \
00273 " <TimeStamp>\n" \
00274 " <when>%sT%02d:%02d:%05.2fZ</when>\n" \
00275 " </TimeStamp>\n" \
00276 " <Icon>\n" \
00277 " <href>%s</href>\n" \
00278 " </Icon>\n" \
00279 " <Camera>\n" \
00280 " <longitude>%f</longitude>\n" \
00281 " <latitude>%f</latitude>\n" \
00282 " <altitude>%f</altitude>\n" \
00283 " <heading>%f</heading>\n" \
00284 " <tilt>%f</tilt>\n" \
00285 " <roll>%f</roll>\n" \
00286 " <altitudeMode>%s</altitudeMode>\n" \
00287 " </Camera>\n" \
00288 " <ViewVolume>\n" \
00289 " <leftFov>%f</leftFov>\n" \
00290 " <rightFov>%f</rightFov>\n" \
00291 " <bottomFov>%f</bottomFov>\n" \
00292 " <topFov>%f</topFov>\n" \
00293 " <near>%f</near>\n" \
00294 " </ViewVolume>\n" \
00295 "</PhotoOverlay>\n", \
00296 datestr, hours, minutes, seconds, \
00297 filename, longitude,latitude,altitude,heading,tilt,roll,state->kml_height_mode?"absolute":"relativeToGround", \
00298 -(state->kml_horHalfFov), state->kml_horHalfFov, -(state->kml_vertHalfFov), state->kml_vertHalfFov, state->kml_near);
00299 }
00300 }
00301 return 0;
00302 }
00303
00304
00305 int camogm_end_kml(void){
00306
00307 if (state->kml_file) {
00308 fprintf (state->kml_file,"</Document>\n");
00309 fprintf (state->kml_file,"</kml>\n");
00310 fclose(state->kml_file);
00311 state->kml_file=NULL;
00312 }
00313 return 0;
00314 }
00315