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