Commit fba25f17 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Fix formatting

Fix source code formatting with 'uncrustify' command-line utility
parent 3f787424
/*!*************************************************************************** /*!***************************************************************************
*! FILE NAME : imgsrv.c *! FILE NAME : imgsrv.c
*! DESCRIPTION: Simple and fast HTTP server to send camera still images *! DESCRIPTION: Simple and fast HTTP server to send camera still images
*! Copyright (C) 2007-2008 Elphel, Inc. *! Copyright (C) 2007-2008 Elphel, Inc.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! This program is free software: you can redistribute it and/or modify *! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by *! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or *! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version. *! (at your option) any later version.
*! *!
*! This program is distributed in the hope that it will be useful, *! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of *! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details. *! GNU General Public License for more details.
*! *!
*! You should have received a copy of the GNU General Public License *! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>. *! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------** *! -----------------------------------------------------------------------------**
*! *!
*! $Log: imgsrv.c,v $ *! $Log: imgsrv.c,v $
*! Revision 1.15 2014/06/25 23:32:26 dzhimiev *! Revision 1.15 2014/06/25 23:32:26 dzhimiev
*! 1. fixed imgsrv /n -> /r/n *! 1. fixed imgsrv /n -> /r/n
*! 2. updated revision number *! 2. updated revision number
*! *!
*! Revision 1.14 2012/04/08 04:11:28 elphel *! Revision 1.14 2012/04/08 04:11:28 elphel
*! 8.2.2 changes related to temperatures measurement and embedding in the Exif MakerNote *! 8.2.2 changes related to temperatures measurement and embedding in the Exif MakerNote
*! *!
*! Revision 1.13 2011/12/22 05:33:06 elphel *! Revision 1.13 2011/12/22 05:33:06 elphel
*! Added trigger command *! Added trigger command
*! *!
*! Revision 1.12 2010/08/16 17:10:24 elphel *! Revision 1.12 2010/08/16 17:10:24 elphel
*! added reporting frame number (for inter-camera synchronization) *! added reporting frame number (for inter-camera synchronization)
*! *!
*! Revision 1.11 2010/08/10 21:14:31 elphel *! Revision 1.11 2010/08/10 21:14:31 elphel
*! 8.0.8.39 - added EEPROM support for multiplexor and sensor boards, so autocampars.php uses application-specific defaults. Exif Orientation tag support, camera Model reflects application and optional mode (i.e. camera number in Eyesis) *! 8.0.8.39 - added EEPROM support for multiplexor and sensor boards, so autocampars.php uses application-specific defaults. Exif Orientation tag support, camera Model reflects application and optional mode (i.e. camera number in Eyesis)
*! *!
*! Revision 1.10 2010/08/03 06:13:51 elphel *! Revision 1.10 2010/08/03 06:13:51 elphel
*! bugfix - was not copying last 8 bytes of MakerNote *! bugfix - was not copying last 8 bytes of MakerNote
*! *!
*! Revision 1.9 2010/08/01 19:30:24 elphel *! Revision 1.9 2010/08/01 19:30:24 elphel
*! new readonly parameter FRAME_SIZE and it support in the applications *! new readonly parameter FRAME_SIZE and it support in the applications
*! *!
*! Revision 1.8 2010/07/20 20:13:34 elphel *! Revision 1.8 2010/07/20 20:13:34 elphel
*! 8.0.8.33 - added MakerNote info for composite images made with multisensor cameras (with 10359 board) *! 8.0.8.33 - added MakerNote info for composite images made with multisensor cameras (with 10359 board)
*! *!
*! Revision 1.7 2010/03/04 06:41:40 elphel *! Revision 1.7 2010/03/04 06:41:40 elphel
*! 8.0.7.3 - more data to makerNote *! 8.0.7.3 - more data to makerNote
*! *!
*! Revision 1.6 2010/02/18 22:59:26 elphel *! Revision 1.6 2010/02/18 22:59:26 elphel
*! 8.0.7.1 - file extension/mime type depends on color mode now (*.jpeg, *.jp4, *.jp46) *! 8.0.7.1 - file extension/mime type depends on color mode now (*.jpeg, *.jp4, *.jp46)
*! *!
*! Revision 1.5 2009/12/28 06:24:17 elphel *! Revision 1.5 2009/12/28 06:24:17 elphel
*! 8.0.6.6 - added MakerNote to Exif, it icludes channels gains and gammas/black levels *! 8.0.6.6 - added MakerNote to Exif, it icludes channels gains and gammas/black levels
*! *!
*! Revision 1.4 2009/10/12 19:20:23 elphel *! Revision 1.4 2009/10/12 19:20:23 elphel
*! Added "Content-Disposition" support to suggest filenames to save images *! Added "Content-Disposition" support to suggest filenames to save images
*! *!
*! Revision 1.3 2009/02/25 17:47:51 spectr_rain *! Revision 1.3 2009/02/25 17:47:51 spectr_rain
*! removed deprecated dependency *! removed deprecated dependency
*! *!
*! Revision 1.2 2009/02/18 06:25:41 elphel *! Revision 1.2 2009/02/18 06:25:41 elphel
*! fixed unterminated string of 1 character (GPS mode - 2/3) *! fixed unterminated string of 1 character (GPS mode - 2/3)
*! *!
*! Revision 1.1.1.1 2008/11/27 20:04:01 elphel *! Revision 1.1.1.1 2008/11/27 20:04:01 elphel
*! *!
*! *!
*! Revision 1.11 2008/11/03 18:42:21 elphel *! Revision 1.11 2008/11/03 18:42:21 elphel
*! comment typo *! comment typo
*! *!
*! Revision 1.10 2008/10/29 04:18:28 elphel *! Revision 1.10 2008/10/29 04:18:28 elphel
*! v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue) *! v.8.0.alpha10 made a separate structure for global parameters (not related to particular frames in a frame queue)
*! *!
*! Revision 1.9 2008/10/25 19:51:40 elphel *! Revision 1.9 2008/10/25 19:51:40 elphel
*! updated copyright year *! updated copyright year
*! *!
*! Revision 1.8 2008/10/21 21:28:52 elphel *! Revision 1.8 2008/10/21 21:28:52 elphel
*! support for xml meta output *! support for xml meta output
*! *!
*! Revision 1.7 2008/10/13 16:55:53 elphel *! Revision 1.7 2008/10/13 16:55:53 elphel
*! removed (some) obsolete P_* parameters, renamed CIRCLSEEK to LSEEK_CIRC constants (same as other similar) *! removed (some) obsolete P_* parameters, renamed CIRCLSEEK to LSEEK_CIRC constants (same as other similar)
*! *!
*! Revision 1.6 2008/10/11 18:46:07 elphel *! Revision 1.6 2008/10/11 18:46:07 elphel
*! snapshot *! snapshot
*! *!
*! Revision 1.5 2008/10/06 08:31:08 elphel *! Revision 1.5 2008/10/06 08:31:08 elphel
*! snapshot, first images *! snapshot, first images
*! *!
*! Revision 1.4 2008/09/07 19:48:08 elphel *! Revision 1.4 2008/09/07 19:48:08 elphel
*! snapshot *! snapshot
*! *!
*! Revision 1.3 2008/08/11 19:10:45 elphel *! Revision 1.3 2008/08/11 19:10:45 elphel
*! reduced syntax "complaints" from KDevelop *! reduced syntax "complaints" from KDevelop
*! *!
*! Revision 1.2 2008/05/16 06:06:54 elphel *! Revision 1.2 2008/05/16 06:06:54 elphel
*! supporting variable JPEG header length *! supporting variable JPEG header length
*! *!
*! Revision 1.14 2008/04/22 22:14:56 elphel *! Revision 1.14 2008/04/22 22:14:56 elphel
*! Added malloc failures handling, syslog logging of such events *! Added malloc failures handling, syslog logging of such events
*! *!
*! Revision 1.13 2008/04/16 20:30:33 elphel *! Revision 1.13 2008/04/16 20:30:33 elphel
*! added optional fps reduction to multipart JPEGs *! added optional fps reduction to multipart JPEGs
*! *!
*! Revision 1.11 2008/04/07 09:13:35 elphel *! Revision 1.11 2008/04/07 09:13:35 elphel
*! Changes related to new Exif generation/processing *! Changes related to new Exif generation/processing
*! *!
*! Revision 1.10 2008/03/22 04:39:53 elphel *! Revision 1.10 2008/03/22 04:39:53 elphel
*! remove complaints about "&_time=..." *! remove complaints about "&_time=..."
*! *!
*! Revision 1.9 2007/12/03 08:28:45 elphel *! Revision 1.9 2007/12/03 08:28:45 elphel
*! Multiple changes, mostly cleanup *! Multiple changes, mostly cleanup
*! *!
*! Revision 1.8 2007/11/16 08:56:19 elphel *! Revision 1.8 2007/11/16 08:56:19 elphel
*! Added support for 2 additional commands to check circbuf usage *! Added support for 2 additional commands to check circbuf usage
*! *!
*! Revision 1.7 2007/11/04 23:25:16 elphel *! Revision 1.7 2007/11/04 23:25:16 elphel
*! removed extra (used during debug) munmap that caused segfault after sending "img" (so no /nxt/save) *! removed extra (used during debug) munmap that caused segfault after sending "img" (so no /nxt/save)
*! *!
*! Revision 1.6 2007/11/04 05:47:40 elphel *! Revision 1.6 2007/11/04 05:47:40 elphel
*! Cleaned up from debug code inserted to fight mmap/caching bug (fixed by now) *! Cleaned up from debug code inserted to fight mmap/caching bug (fixed by now)
*! *!
*! Revision 1.5 2007/11/01 18:59:37 elphel *! Revision 1.5 2007/11/01 18:59:37 elphel
*! debugging mmap/caching problems *! debugging mmap/caching problems
*! *!
*! Revision 1.4 2007/10/30 16:56:06 elphel *! Revision 1.4 2007/10/30 16:56:06 elphel
*! release 7.1.4.5 - working on "can not find 0xffff in frame parameters" bug. Temporary fix *! release 7.1.4.5 - working on "can not find 0xffff in frame parameters" bug. Temporary fix
*! *!
*! Revision 1.3 2007/10/27 00:55:32 elphel *! Revision 1.3 2007/10/27 00:55:32 elphel
*! untested revision - need to go *! untested revision - need to go
*! *!
*! Revision 1.2 2007/10/11 06:42:28 elphel *! Revision 1.2 2007/10/11 06:42:28 elphel
*! Fixed bug - /meta command should return trivial xml file, not 1x1 pixel gif *! Fixed bug - /meta command should return trivial xml file, not 1x1 pixel gif
*! *!
*! Revision 1.1.1.1 2007/10/02 19:44:54 elphel *! Revision 1.1.1.1 2007/10/02 19:44:54 elphel
*! This is a fresh tree based on elphel353-2.10 *! This is a fresh tree based on elphel353-2.10
*! *!
*! Revision 1.4 2007/10/02 19:44:54 elphel *! Revision 1.4 2007/10/02 19:44:54 elphel
*! More functionality (buffer manipulation commands, clean interface, xml responces) *! More functionality (buffer manipulation commands, clean interface, xml responces)
*! *!
*! Revision 1.3 2007/09/29 16:21:25 elphel *! Revision 1.3 2007/09/29 16:21:25 elphel
*! removed IOCTL usage from /dev/circbuf, improved comments, other minor changes *! removed IOCTL usage from /dev/circbuf, improved comments, other minor changes
*! *!
*! Revision 1.2 2007/09/25 23:35:16 elphel *! Revision 1.2 2007/09/25 23:35:16 elphel
*! added Exif initialization, made it to work in background mode *! added Exif initialization, made it to work in background mode
*! *!
*! Revision 1.1 2007/09/23 06:49:10 elphel *! Revision 1.1 2007/09/23 06:49:10 elphel
*! Simple web server designed for particular task - serving camera JPEG images. It is faster, than through any of the web servers tested. Only some of the functionality is implemented (no Exif yet, no synchronization with the camera) *! Simple web server designed for particular task - serving camera JPEG images. It is faster, than through any of the web servers tested. Only some of the functionality is implemented (no Exif yet, no synchronization with the camera)
*! *!
*! *!
*/ */
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -180,7 +180,7 @@ ...@@ -180,7 +180,7 @@
#if ELPHEL_DEBUG_THIS #if ELPHEL_DEBUG_THIS
#define D(x) fprintf(stderr,"%s:%d:%s: ",__FILE__,__LINE__,__FUNCTION__);x #define D(x) fprintf(stderr, "%s:%d:%s: ", __FILE__, __LINE__, __FUNCTION__); x
#else #else
#define D(x) #define D(x)
#endif #endif
...@@ -193,14 +193,14 @@ ...@@ -193,14 +193,14 @@
#define JPEG_HEADER_MAXSIZE 0x300 // will not change #define JPEG_HEADER_MAXSIZE 0x300 // will not change
#define TRAILER_SIZE 0x02 #define TRAILER_SIZE 0x02
#define MAP_OPTIONS MAP_FILE|MAP_PRIVATE #define MAP_OPTIONS MAP_FILE | MAP_PRIVATE
//#define GLOBALPARS(x) globalPars[(x)-FRAMEPAR_GLOBALS] // should work in drivers and application //#define GLOBALPARS(x) globalPars[(x)-FRAMEPAR_GLOBALS] // should work in drivers and application
unsigned long * ccam_dma_buf; /* mmapped array */ unsigned long * ccam_dma_buf; /* mmapped array */
char trailer[TRAILER_SIZE] = {0xff,0xd9}; char trailer[TRAILER_SIZE] = { 0xff, 0xd9 };
const char url_args[]="This server supports sequence of commands entered in the URL (separated by \"/\", case sensitive )\n" const char url_args[] = "This server supports sequence of commands entered in the URL (separated by \"/\", case sensitive )\n"
"executing them from left to right as they appear in the URL\n" "executing them from left to right as they appear in the URL\n"
"img - send image at the current pointer (if it is first command - use last acquired image, if none availabe - send 1x1 gif)\n" "img - send image at the current pointer (if it is first command - use last acquired image, if none availabe - send 1x1 gif)\n"
"bimg - same as above, but save the whole image in the memory before sending - useful to avoid overruns with slow connection \n" "bimg - same as above, but save the whole image in the memory before sending - useful to avoid overruns with slow connection \n"
...@@ -245,325 +245,329 @@ void waitFrameSync(); ...@@ -245,325 +245,329 @@ void waitFrameSync();
unsigned long getCurrentFrameNumber(); unsigned long getCurrentFrameNumber();
#define saferead255(f,d,l) read(f,d,((l)<256)?(l):255) #define saferead255(f, d, l) read(f, d, ((l) < 256) ? (l) : 255)
int printExifXML(int exif_page) { int printExifXML(int exif_page)
{
int indx; int indx;
long numfields=0; long numfields = 0;
struct exif_dir_table_t dir_table_entry; struct exif_dir_table_t dir_table_entry;
int fd_exifdir; int fd_exifdir;
struct exif_dir_table_t exif_dir[ExifKmlNumber] ; /// store locations of the fields needed for KML generations in the Exif block struct exif_dir_table_t exif_dir[ExifKmlNumber]; /// store locations of the fields needed for KML generations in the Exif block
/// Create Exif directory /// Create Exif directory
/// Read the size of the Exif data /// Read the size of the Exif data
fd_exifdir = open(EXIFDIR_DEV_NAME, O_RDONLY); fd_exifdir = open(EXIFDIR_DEV_NAME, O_RDONLY);
if (fd_exifdir <0) { if (fd_exifdir < 0) {
printf ("<error>\"Opening %s\"</error>\n",EXIFDIR_DEV_NAME); printf("<error>\"Opening %s\"</error>\n", EXIFDIR_DEV_NAME);
return -2 ; /// Error opening Exif directory return -2; /// Error opening Exif directory
} }
for (indx=0; indx<ExifKmlNumber; indx++) exif_dir[indx].ltag=0; for (indx = 0; indx < ExifKmlNumber; indx++) exif_dir[indx].ltag = 0;
while (read(fd_exifdir, &dir_table_entry, sizeof(dir_table_entry))>0) { while (read(fd_exifdir, &dir_table_entry, sizeof(dir_table_entry)) > 0) {
switch (dir_table_entry.ltag) { switch (dir_table_entry.ltag) {
case Exif_Image_ImageDescription: indx= Exif_Image_ImageDescription_Index; break; case Exif_Image_ImageDescription: indx = Exif_Image_ImageDescription_Index; break;
case Exif_Image_FrameNumber: indx= Exif_Image_FrameNumber_Index; break; case Exif_Image_FrameNumber: indx = Exif_Image_FrameNumber_Index; break;
case Exif_Photo_DateTimeOriginal: indx= Exif_Photo_DateTimeOriginal_Index; break; case Exif_Photo_DateTimeOriginal: indx = Exif_Photo_DateTimeOriginal_Index; break;
case Exif_Photo_SubSecTimeOriginal: indx= Exif_Photo_SubSecTimeOriginal_Index; break; case Exif_Photo_SubSecTimeOriginal: indx = Exif_Photo_SubSecTimeOriginal_Index; break;
case Exif_Photo_ExposureTime: indx= Exif_Photo_ExposureTime_Index; break; case Exif_Photo_ExposureTime: indx = Exif_Photo_ExposureTime_Index; break;
case Exif_Photo_MakerNote: indx= Exif_Photo_MakerNote_Index; break; case Exif_Photo_MakerNote: indx = Exif_Photo_MakerNote_Index; break;
case Exif_Image_Orientation: indx= Exif_Image_Orientation_Index; break; case Exif_Image_Orientation: indx = Exif_Image_Orientation_Index; break;
case Exif_GPSInfo_GPSLatitudeRef: indx= Exif_GPSInfo_GPSLatitudeRef_Index; break; case Exif_GPSInfo_GPSLatitudeRef: indx = Exif_GPSInfo_GPSLatitudeRef_Index; break;
case Exif_GPSInfo_GPSLatitude: indx= Exif_GPSInfo_GPSLatitude_Index ; break; case Exif_GPSInfo_GPSLatitude: indx = Exif_GPSInfo_GPSLatitude_Index; break;
case Exif_GPSInfo_GPSLongitudeRef: indx= Exif_GPSInfo_GPSLongitudeRef_Index ; break; case Exif_GPSInfo_GPSLongitudeRef: indx = Exif_GPSInfo_GPSLongitudeRef_Index; break;
case Exif_GPSInfo_GPSLongitude: indx= Exif_GPSInfo_GPSLongitude_Index; break; case Exif_GPSInfo_GPSLongitude: indx = Exif_GPSInfo_GPSLongitude_Index; break;
case Exif_GPSInfo_GPSAltitudeRef: indx= Exif_GPSInfo_GPSAltitudeRef_Index; break; case Exif_GPSInfo_GPSAltitudeRef: indx = Exif_GPSInfo_GPSAltitudeRef_Index; break;
case Exif_GPSInfo_GPSAltitude: indx= Exif_GPSInfo_GPSAltitude_Index; break; case Exif_GPSInfo_GPSAltitude: indx = Exif_GPSInfo_GPSAltitude_Index; break;
case Exif_GPSInfo_GPSTimeStamp: indx= Exif_GPSInfo_GPSTimeStamp_Index; break; case Exif_GPSInfo_GPSTimeStamp: indx = Exif_GPSInfo_GPSTimeStamp_Index; break;
case Exif_GPSInfo_GPSDateStamp: indx= Exif_GPSInfo_GPSDateStamp_Index; break; case Exif_GPSInfo_GPSDateStamp: indx = Exif_GPSInfo_GPSDateStamp_Index; break;
case Exif_GPSInfo_GPSMeasureMode: indx= Exif_GPSInfo_GPSMeasureMode_Index; break; case Exif_GPSInfo_GPSMeasureMode: indx = Exif_GPSInfo_GPSMeasureMode_Index; break;
case Exif_GPSInfo_CompassDirectionRef: indx= Exif_GPSInfo_CompassDirectionRef_Index; break; case Exif_GPSInfo_CompassDirectionRef: indx = Exif_GPSInfo_CompassDirectionRef_Index; break;
case Exif_GPSInfo_CompassDirection: indx= Exif_GPSInfo_CompassDirection_Index; break; case Exif_GPSInfo_CompassDirection: indx = Exif_GPSInfo_CompassDirection_Index; break;
case Exif_GPSInfo_CompassPitchRef: indx= Exif_GPSInfo_CompassPitchRef_Index; break; case Exif_GPSInfo_CompassPitchRef: indx = Exif_GPSInfo_CompassPitchRef_Index; break;
case Exif_GPSInfo_CompassPitch: indx= Exif_GPSInfo_CompassPitch_Index; break; case Exif_GPSInfo_CompassPitch: indx = Exif_GPSInfo_CompassPitch_Index; break;
case Exif_GPSInfo_CompassRollRef: indx= Exif_GPSInfo_CompassRollRef_Index; break; case Exif_GPSInfo_CompassRollRef: indx = Exif_GPSInfo_CompassRollRef_Index; break;
case Exif_GPSInfo_CompassRoll: indx= Exif_GPSInfo_CompassRoll_Index; break; case Exif_GPSInfo_CompassRoll: indx = Exif_GPSInfo_CompassRoll_Index; break;
default: indx=-1; default: indx = -1;
} }
if (indx>=0) { if (indx >= 0) {
memcpy(&(exif_dir[indx]),&dir_table_entry,sizeof(dir_table_entry)); memcpy(&(exif_dir[indx]), &dir_table_entry, sizeof(dir_table_entry));
numfields++; numfields++;
} }
} }
close (fd_exifdir); close(fd_exifdir);
/// Create XML files iteslf /// Create XML files iteslf
long rational3[6]; long rational3[6];
long makerNote[14]; long makerNote[14];
long exif_page_start; long exif_page_start;
char val[256]; char val[256];
int hours=0, minutes=0; int hours = 0, minutes = 0;
double seconds=0.0; double seconds = 0.0;
double longitude=0.0, latitude=0.0, altitude=0.0, heading=0.0, roll=0.0, pitch=0.0, exposure=0.0; double longitude = 0.0, latitude = 0.0, altitude = 0.0, heading = 0.0, roll = 0.0, pitch = 0.0, exposure = 0.0;
val[255]='\0'; val[255] = '\0';
int fd_exif= open(EXIF_DEV_NAME, O_RDONLY); int fd_exif = open(EXIF_DEV_NAME, O_RDONLY);
if (fd_exif <0) { if (fd_exif < 0) {
printf ("<error>\"Opening %s\"</error>\n",EXIF_DEV_NAME); printf("<error>\"Opening %s\"</error>\n", EXIF_DEV_NAME);
return -3 ; return -3;
} }
exif_page_start= lseek (fd_exif, exif_page, SEEK_END); /// select specified Exif page exif_page_start = lseek(fd_exif, exif_page, SEEK_END); /// select specified Exif page
if (exif_page_start<0) { if (exif_page_start < 0) {
printf ("<error>\"Exif page (%d) is out of range\"</error>\n",exif_page); printf("<error>\"Exif page (%d) is out of range\"</error>\n", exif_page);
close (fd_exif); close(fd_exif);
return -1 ; /// Error opening Exif return -1; /// Error opening Exif
} }
///Image Description ///Image Description
if (exif_dir[Exif_Image_ImageDescription_Index].ltag==Exif_Image_ImageDescription) { // Exif_Image_ImageDescription is present in template if (exif_dir[Exif_Image_ImageDescription_Index].ltag == Exif_Image_ImageDescription) { // Exif_Image_ImageDescription is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_Image_ImageDescription_Index].dst, exif_page_start + exif_dir[Exif_Image_ImageDescription_Index].dst,
SEEK_SET); SEEK_SET);
saferead255(fd_exif, val, exif_dir[Exif_Image_ImageDescription_Index].len); saferead255(fd_exif, val, exif_dir[Exif_Image_ImageDescription_Index].len);
printf("<ImageDescription>\"%s\"</ImageDescription>\n",val); printf("<ImageDescription>\"%s\"</ImageDescription>\n", val);
} }
///Exif_Image_FrameNumber_Index 0x13 ///Exif_Image_FrameNumber_Index 0x13
if (exif_dir[Exif_Image_FrameNumber_Index].ltag==Exif_Image_FrameNumber) { // Exif_Image_FrameNumber_Index is present in template if (exif_dir[Exif_Image_FrameNumber_Index].ltag == Exif_Image_FrameNumber) { // Exif_Image_FrameNumber_Index is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_Image_FrameNumber_Index].dst, exif_page_start + exif_dir[Exif_Image_FrameNumber_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 4); read(fd_exif, rational3, 4);
sprintf (val,"%ld", (long) __cpu_to_be32( rational3[0])); sprintf(val, "%ld", (long)__cpu_to_be32( rational3[0]));
printf("<FrameNumber>\"%s\"</FrameNumber>\n",val); printf("<FrameNumber>\"%s\"</FrameNumber>\n", val);
} }
///Exif_Image_Orientation_Index 0x15 ///Exif_Image_Orientation_Index 0x15
if (exif_dir[Exif_Image_Orientation_Index].ltag==Exif_Image_Orientation) { // Exif_Image_Orientation_Index is present in template if (exif_dir[Exif_Image_Orientation_Index].ltag == Exif_Image_Orientation) { // Exif_Image_Orientation_Index is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_Image_Orientation_Index].dst, exif_page_start + exif_dir[Exif_Image_Orientation_Index].dst,
SEEK_SET); SEEK_SET);
rational3[0]=0; rational3[0] = 0;
read(fd_exif, rational3, 2); read(fd_exif, rational3, 2);
sprintf (val,"%ld", (long) ( rational3[0]>>8)); sprintf(val, "%ld", (long)( rational3[0] >> 8));
printf("<Orientation>\"%s\"</Orientation>\n",val); printf("<Orientation>\"%s\"</Orientation>\n", val);
} }
///DateTimeOriginal (with subseconds) ///DateTimeOriginal (with subseconds)
if (exif_dir[Exif_Photo_DateTimeOriginal_Index].ltag==Exif_Photo_DateTimeOriginal) { if (exif_dir[Exif_Photo_DateTimeOriginal_Index].ltag == Exif_Photo_DateTimeOriginal) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_Photo_DateTimeOriginal_Index].dst, exif_page_start + exif_dir[Exif_Photo_DateTimeOriginal_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, val, 19); read(fd_exif, val, 19);
val[19]='\0'; val[19] = '\0';
if (exif_dir[Exif_Photo_SubSecTimeOriginal_Index].ltag==Exif_Photo_SubSecTimeOriginal) { if (exif_dir[Exif_Photo_SubSecTimeOriginal_Index].ltag == Exif_Photo_SubSecTimeOriginal) {
val[19]='.'; val[19] = '.';
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_Photo_SubSecTimeOriginal_Index].dst, exif_page_start + exif_dir[Exif_Photo_SubSecTimeOriginal_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, &val[20], 7); read(fd_exif, &val[20], 7);
val[27]='\0'; val[27] = '\0';
} }
printf("<DateTimeOriginal>\"%s\"</DateTimeOriginal>\n",val); printf("<DateTimeOriginal>\"%s\"</DateTimeOriginal>\n", val);
} }
///Exif_Photo_ExposureTime ///Exif_Photo_ExposureTime
if (exif_dir[Exif_Photo_ExposureTime_Index].ltag==Exif_Photo_ExposureTime) { // Exif_Photo_ExposureTime is present in template if (exif_dir[Exif_Photo_ExposureTime_Index].ltag == Exif_Photo_ExposureTime) { // Exif_Photo_ExposureTime is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_Photo_ExposureTime_Index].dst, exif_page_start + exif_dir[Exif_Photo_ExposureTime_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 8); read(fd_exif, rational3, 8);
exposure=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]); exposure = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
sprintf (val,"%f",exposure); sprintf(val, "%f", exposure);
printf("<ExposureTime>\"%s\"</ExposureTime>\n",val); printf("<ExposureTime>\"%s\"</ExposureTime>\n", val);
} }
///Exif_Photo_MakerNote ///Exif_Photo_MakerNote
if (exif_dir[Exif_Photo_MakerNote_Index].ltag==Exif_Photo_MakerNote) { // Exif_Photo_MakerNote is present in template if (exif_dir[Exif_Photo_MakerNote_Index].ltag == Exif_Photo_MakerNote) { // Exif_Photo_MakerNote is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_Photo_MakerNote_Index].dst, exif_page_start + exif_dir[Exif_Photo_MakerNote_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, makerNote, 64); read(fd_exif, makerNote, 64);
sprintf (val, sprintf(val,
"0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx", "0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx",
(long) __cpu_to_be32(makerNote[0]), (long)__cpu_to_be32(makerNote[0]),
(long) __cpu_to_be32(makerNote[1]), (long)__cpu_to_be32(makerNote[1]),
(long) __cpu_to_be32(makerNote[2]), (long)__cpu_to_be32(makerNote[2]),
(long) __cpu_to_be32(makerNote[3]), (long)__cpu_to_be32(makerNote[3]),
(long) __cpu_to_be32(makerNote[4]), (long)__cpu_to_be32(makerNote[4]),
(long) __cpu_to_be32(makerNote[5]), (long)__cpu_to_be32(makerNote[5]),
(long) __cpu_to_be32(makerNote[6]), (long)__cpu_to_be32(makerNote[6]),
(long) __cpu_to_be32(makerNote[7]), (long)__cpu_to_be32(makerNote[7]),
(long) __cpu_to_be32(makerNote[8]), (long)__cpu_to_be32(makerNote[8]),
(long) __cpu_to_be32(makerNote[9]), (long)__cpu_to_be32(makerNote[9]),
(long) __cpu_to_be32(makerNote[10]), (long)__cpu_to_be32(makerNote[10]),
(long) __cpu_to_be32(makerNote[11]), (long)__cpu_to_be32(makerNote[11]),
(long) __cpu_to_be32(makerNote[12]), (long)__cpu_to_be32(makerNote[12]),
(long) __cpu_to_be32(makerNote[13]), (long)__cpu_to_be32(makerNote[13]),
(long) __cpu_to_be32(makerNote[14]), (long)__cpu_to_be32(makerNote[14]),
(long) __cpu_to_be32(makerNote[15])); (long)__cpu_to_be32(makerNote[15]));
printf("<MakerNote>\"%s\"</MakerNote>\n",val); printf("<MakerNote>\"%s\"</MakerNote>\n", val);
} }
/// GPS measure mode /// GPS measure mode
if (exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].ltag==Exif_GPSInfo_GPSMeasureMode) { if (exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].ltag == Exif_GPSInfo_GPSMeasureMode) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSMeasureMode_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, val, 1); read(fd_exif, val, 1);
val[1]='\0'; val[1] = '\0';
printf("<GPSMeasureMode>\"%s\"</GPSMeasureMode>\n",val); printf("<GPSMeasureMode>\"%s\"</GPSMeasureMode>\n", val);
} }
///GPS date/time ///GPS date/time
if (exif_dir[Exif_GPSInfo_GPSDateStamp_Index].ltag==Exif_GPSInfo_GPSDateStamp) { if (exif_dir[Exif_GPSInfo_GPSDateStamp_Index].ltag == Exif_GPSInfo_GPSDateStamp) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSDateStamp_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSDateStamp_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, val, 10); read(fd_exif, val, 10);
val[10]='\0'; val[10] = '\0';
if (exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].ltag==Exif_GPSInfo_GPSTimeStamp) { if (exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].ltag == Exif_GPSInfo_GPSTimeStamp) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSTimeStamp_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 24); read(fd_exif, rational3, 24);
hours= __cpu_to_be32( rational3[0]); hours = __cpu_to_be32( rational3[0]);
minutes= __cpu_to_be32( rational3[2]); minutes = __cpu_to_be32( rational3[2]);
seconds= (1.0*(__cpu_to_be32( rational3[4])+1))/__cpu_to_be32( rational3[5]); /// GPS likes ".999", let's inc by one - anyway will round that out seconds = (1.0 * (__cpu_to_be32( rational3[4]) + 1)) / __cpu_to_be32( rational3[5]); /// GPS likes ".999", let's inc by one - anyway will round that out
sprintf (&val[10]," %02d:%02d:%05.2f",hours,minutes,seconds); sprintf(&val[10], " %02d:%02d:%05.2f", hours, minutes, seconds);
} }
printf("<GPSDateTime>\"%s\"</GPSDateTime>\n",val); printf("<GPSDateTime>\"%s\"</GPSDateTime>\n", val);
} }
/// knowing format provided from GPS - degrees and minutes only, no seconds: /// knowing format provided from GPS - degrees and minutes only, no seconds:
///GPS Longitude ///GPS Longitude
if (exif_dir[Exif_GPSInfo_GPSLongitude_Index].ltag==Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template if (exif_dir[Exif_GPSInfo_GPSLongitude_Index].ltag == Exif_GPSInfo_GPSLongitude) { // Exif_GPSInfo_GPSLongitude is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSLongitude_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSLongitude_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 24); read(fd_exif, rational3, 24);
longitude=__cpu_to_be32( rational3[0])/(1.0*__cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2])/(60.0*__cpu_to_be32( rational3[3])); longitude = __cpu_to_be32( rational3[0]) / (1.0 * __cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2]) / (60.0 * __cpu_to_be32( rational3[3]));
if (exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].ltag==Exif_GPSInfo_GPSLongitudeRef) { if (exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].ltag == Exif_GPSInfo_GPSLongitudeRef) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSLongitudeRef_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, val, 1); read(fd_exif, val, 1);
if (val[0]!= 'E') longitude=-longitude; if (val[0] != 'E') longitude = -longitude;
} }
sprintf (val,"%f",longitude); sprintf(val, "%f", longitude);
printf("<GPSLongitude>\"%s\"</GPSLongitude>\n",val); printf("<GPSLongitude>\"%s\"</GPSLongitude>\n", val);
} }
///GPS Latitude ///GPS Latitude
if (exif_dir[Exif_GPSInfo_GPSLatitude_Index].ltag==Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template if (exif_dir[Exif_GPSInfo_GPSLatitude_Index].ltag == Exif_GPSInfo_GPSLatitude) { // Exif_GPSInfo_GPSLatitude is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSLatitude_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSLatitude_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 24); read(fd_exif, rational3, 24);
latitude=__cpu_to_be32( rational3[0])/(1.0*__cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2])/(60.0*__cpu_to_be32( rational3[3])); latitude = __cpu_to_be32( rational3[0]) / (1.0 * __cpu_to_be32( rational3[1])) + __cpu_to_be32( rational3[2]) / (60.0 * __cpu_to_be32( rational3[3]));
if (exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].ltag==Exif_GPSInfo_GPSLatitudeRef) { if (exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].ltag == Exif_GPSInfo_GPSLatitudeRef) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSLatitudeRef_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, val, 1); read(fd_exif, val, 1);
if (val[0] != 'N') latitude=-latitude; if (val[0] != 'N') latitude = -latitude;
} }
sprintf (val,"%f",latitude); sprintf(val, "%f", latitude);
printf("<GPSLatitude>\"%s\"</GPSLatitude>\n",val); printf("<GPSLatitude>\"%s\"</GPSLatitude>\n", val);
} }
///GPS Altitude ///GPS Altitude
if (exif_dir[Exif_GPSInfo_GPSAltitude_Index].ltag==Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template if (exif_dir[Exif_GPSInfo_GPSAltitude_Index].ltag == Exif_GPSInfo_GPSAltitude) { // Exif_GPSInfo_GPSAltitude is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSAltitude_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSAltitude_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 8); read(fd_exif, rational3, 8);
altitude=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]); altitude = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].ltag==Exif_GPSInfo_GPSAltitudeRef) { if (exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].ltag == Exif_GPSInfo_GPSAltitudeRef) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_GPSAltitudeRef_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, val, 1); read(fd_exif, val, 1);
if (val[0] != '\0') altitude=-altitude; if (val[0] != '\0') altitude = -altitude;
} }
sprintf (val,"%f",altitude); sprintf(val, "%f", altitude);
printf("<GPSAltitude>\"%s\"</GPSAltitude>\n",val); printf("<GPSAltitude>\"%s\"</GPSAltitude>\n", val);
} }
///Compass Direction (magnetic) ///Compass Direction (magnetic)
if (exif_dir[Exif_GPSInfo_CompassDirection_Index].ltag==Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template if (exif_dir[Exif_GPSInfo_CompassDirection_Index].ltag == Exif_GPSInfo_CompassDirection) { // Exif_GPSInfo_CompassDirection is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_CompassDirection_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassDirection_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 8); read(fd_exif, rational3, 8);
heading=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]); heading = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
sprintf (val,"%f",heading); sprintf(val, "%f", heading);
printf("<CompassDirection>\"%s\"</CompassDirection>\n",val); printf("<CompassDirection>\"%s\"</CompassDirection>\n", val);
} }
///Processing 'hacked' pitch and roll (made of Exif destination latitude/longitude) ///Processing 'hacked' pitch and roll (made of Exif destination latitude/longitude)
///Compass Roll ///Compass Roll
if (exif_dir[Exif_GPSInfo_CompassRoll_Index].ltag==Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template if (exif_dir[Exif_GPSInfo_CompassRoll_Index].ltag == Exif_GPSInfo_CompassRoll) { // Exif_GPSInfo_CompassRoll is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_CompassRoll_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassRoll_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 8); read(fd_exif, rational3, 8);
roll=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]); roll = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_CompassRollRef_Index].ltag==Exif_GPSInfo_CompassRollRef) { if (exif_dir[Exif_GPSInfo_CompassRollRef_Index].ltag == Exif_GPSInfo_CompassRollRef) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_CompassRollRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassRollRef_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, val, 1); read(fd_exif, val, 1);
if (val[0] != EXIF_COMPASS_ROLL_ASCII[0]) roll=-roll; if (val[0] != EXIF_COMPASS_ROLL_ASCII[0]) roll = -roll;
} }
sprintf (val,"%f",roll); sprintf(val, "%f", roll);
printf("<CompassRoll>\"%s\"</CompassRoll>\n",val); printf("<CompassRoll>\"%s\"</CompassRoll>\n", val);
} }
///Compass Pitch ///Compass Pitch
if (exif_dir[Exif_GPSInfo_CompassPitch_Index].ltag==Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template if (exif_dir[Exif_GPSInfo_CompassPitch_Index].ltag == Exif_GPSInfo_CompassPitch) { // Exif_GPSInfo_CompassPitch is present in template
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_CompassPitch_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassPitch_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, rational3, 8); read(fd_exif, rational3, 8);
pitch=(1.0*__cpu_to_be32( rational3[0]))/__cpu_to_be32( rational3[1]); pitch = (1.0 * __cpu_to_be32( rational3[0])) / __cpu_to_be32( rational3[1]);
if (exif_dir[Exif_GPSInfo_CompassPitchRef_Index].ltag==Exif_GPSInfo_CompassPitchRef) { if (exif_dir[Exif_GPSInfo_CompassPitchRef_Index].ltag == Exif_GPSInfo_CompassPitchRef) {
lseek (fd_exif, lseek(fd_exif,
exif_page_start+exif_dir[Exif_GPSInfo_CompassPitchRef_Index].dst, exif_page_start + exif_dir[Exif_GPSInfo_CompassPitchRef_Index].dst,
SEEK_SET); SEEK_SET);
read(fd_exif, val, 1); read(fd_exif, val, 1);
if (val[0] != EXIF_COMPASS_PITCH_ASCII[0]) pitch=-pitch; if (val[0] != EXIF_COMPASS_PITCH_ASCII[0]) pitch = -pitch;
} }
sprintf (val,"%f",pitch); sprintf(val, "%f", pitch);
printf("<CompassPitch>\"%s\"</CompassPitch>\n",val); printf("<CompassPitch>\"%s\"</CompassPitch>\n", val);
} }
close (fd_exif); close(fd_exif);
return 0; return 0;
} }
int metaXML(int fd_circ, int mode) { /// mode: 0 - new (send headers), 1 - continue, 2 - finish int metaXML(int fd_circ, int mode) /// mode: 0 - new (send headers), 1 - continue, 2 - finish
int frameParamPointer=0; {
int frameParamPointer = 0;
struct interframe_params_t frame_params; struct interframe_params_t frame_params;
int jpeg_len,jpeg_start,buff_size,timestamp_start; int jpeg_len, jpeg_start, buff_size, timestamp_start;
if (mode==2) {/// just close the xml file
printf ("</meta>\n"); if (mode == 2) { /// just close the xml file
printf("</meta>\n");
return 0; return 0;
} else if (mode==0) { /// open the XML output (length is undefined - multiple frames meta data might be output) } else if (mode == 0) { /// open the XML output (length is undefined - multiple frames meta data might be output)
printf("HTTP/1.0 200 OK\r\n"); printf("HTTP/1.0 200 OK\r\n");
printf("Server: Elphel Imgsrv\r\n"); printf("Server: Elphel Imgsrv\r\n");
printf("Content-Type: text/xml\r\n"); printf("Content-Type: text/xml\r\n");
printf("Pragma: no-cache\r\n"); printf("Pragma: no-cache\r\n");
printf("\r\n"); printf("\r\n");
printf ("<?xml version=\"1.0\"?>\n" \ printf("<?xml version=\"1.0\"?>\n" \
"<meta>\n"); "<meta>\n");
} }
jpeg_start=lseek(fd_circ,0,SEEK_CUR); //get the current read pointer jpeg_start = lseek(fd_circ, 0, SEEK_CUR); //get the current read pointer
D(fprintf(stderr,"jpeg_start= (long)=0x%x\n",jpeg_start>>2)); D(fprintf(stderr, "jpeg_start= (long)=0x%x\n", jpeg_start >> 2));
if (jpeg_start <0 ) { if (jpeg_start < 0 ) {
printf("<error>\"No frame at the current pointer\"</error>\n"); printf("<error>\"No frame at the current pointer\"</error>\n");
return -1; return -1;
} }
buff_size=lseek(fd_circ,0,SEEK_END); buff_size = lseek(fd_circ, 0, SEEK_END);
/// restore file poinetr after lseek-ing the end /// restore file poinetr after lseek-ing the end
lseek(fd_circ, jpeg_start, SEEK_SET); lseek(fd_circ, jpeg_start, SEEK_SET);
frameParamPointer=jpeg_start-32; frameParamPointer = jpeg_start - 32;
if (frameParamPointer<0) frameParamPointer+=buff_size; if (frameParamPointer < 0) frameParamPointer += buff_size;
memcpy (&frame_params, (unsigned long * ) &ccam_dma_buf[frameParamPointer>>2],32); /// ccam_dma_buf - global memcpy(&frame_params, (unsigned long* )&ccam_dma_buf[frameParamPointer >> 2], 32); /// ccam_dma_buf - global
// jpeg_len=frame_params.frame_length; // jpeg_len=frame_params.frame_length;
///// Copy timestamp (goes after the image data) ///// Copy timestamp (goes after the image data)
// timestamp_start=jpeg_start+((jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; //! magic shift - should index first byte of the time stamp // timestamp_start=jpeg_start+((jpeg_len+CCAM_MMAP_META+3) & (~0x1f)) + 32 - CCAM_MMAP_META_SEC; //! magic shift - should index first byte of the time stamp
...@@ -616,28 +620,33 @@ int metaXML(int fd_circ, int mode) { /// mode: 0 - new (send headers), 1 - con ...@@ -616,28 +620,33 @@ int metaXML(int fd_circ, int mode) { /// mode: 0 - new (send headers), 1 - con
return 0; return 0;
} }
unsigned long getCurrentFrameNumber() { unsigned long getCurrentFrameNumber()
const char ctlFileName[]="/dev/frameparsall"; {
const char ctlFileName[] = "/dev/frameparsall";
int fd_fparmsall = open(ctlFileName, O_RDWR); int fd_fparmsall = open(ctlFileName, O_RDWR);
unsigned long frame_number=lseek(fd_fparmsall, 0, SEEK_CUR ); unsigned long frame_number = lseek(fd_fparmsall, 0, SEEK_CUR );
close(fd_fparmsall); close(fd_fparmsall);
return frame_number; return frame_number;
} }
void waitFrameSync() { void waitFrameSync()
const char ctlFileName[]="/dev/frameparsall"; {
const char ctlFileName[] = "/dev/frameparsall";
int fd_fparmsall = open(ctlFileName, O_RDWR); int fd_fparmsall = open(ctlFileName, O_RDWR);
lseek(fd_fparmsall, LSEEK_FRAME_WAIT_REL+1, SEEK_END); /// skip 1 frame before returning
lseek(fd_fparmsall, LSEEK_FRAME_WAIT_REL + 1, SEEK_END); /// skip 1 frame before returning
close(fd_fparmsall); close(fd_fparmsall);
} }
int framePointersXML(int fd_circ) { int framePointersXML(int fd_circ)
const char ctlFileName[]="/dev/frameparsall"; {
const char ctlFileName[] = "/dev/frameparsall";
int fd_fparmsall; int fd_fparmsall;
char s[512]; // 341; char s[512]; // 341;
int p, wp, rp; int p, wp, rp;
int nf=0; int nf = 0;
int nfl=0; int nfl = 0;
int buf_free, buf_used, frame_size; int buf_free, buf_used, frame_size;
int save_p; //! save current file pointer, then restore it before return int save_p; //! save current file pointer, then restore it before return
int frame8, frame_number, sensor_state, compressor_state; int frame8, frame_number, sensor_state, compressor_state;
...@@ -649,61 +658,61 @@ int framePointersXML(int fd_circ) { ...@@ -649,61 +658,61 @@ int framePointersXML(int fd_circ) {
fd_fparmsall = open(ctlFileName, O_RDWR); fd_fparmsall = open(ctlFileName, O_RDWR);
if (fd_fparmsall<0) { // check control OK if (fd_fparmsall < 0) { // check control OK
printf ("Error opening %s\n", ctlFileName); printf("Error opening %s\n", ctlFileName);
fprintf(stderr,"%s:%d:%s: Error opening %s\n",__FILE__,__LINE__,__FUNCTION__, ctlFileName); fprintf(stderr, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileName);
return -1; return -1;
} }
//! now try to mmap //! now try to mmap
frameParsAll = (struct framepars_all_t *) mmap(0, sizeof (struct framepars_all_t) , PROT_READ, MAP_SHARED, fd_fparmsall, 0); frameParsAll = (struct framepars_all_t*)mmap(0, sizeof(struct framepars_all_t), PROT_READ, MAP_SHARED, fd_fparmsall, 0);
if((int)frameParsAll == -1) { if ((int)frameParsAll == -1) {
frameParsAll=NULL; frameParsAll = NULL;
printf("Error in mmap /dev/frameparsall"); printf("Error in mmap /dev/frameparsall");
fprintf(stderr,"%s:%d:%s: Error in mmap in %s\n",__FILE__,__LINE__,__FUNCTION__,ctlFileName); fprintf(stderr, "%s:%d:%s: Error in mmap in %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileName);
close (fd_fparmsall); close(fd_fparmsall);
fd_fparmsall = -1; fd_fparmsall = -1;
return -1; return -1;
} }
framePars=frameParsAll->framePars; framePars = frameParsAll->framePars;
globalPars=frameParsAll->globalPars; globalPars = frameParsAll->globalPars;
// Read current sensor state - defined in c313a.h // Read current sensor state - defined in c313a.h
frame_number=lseek(fd_fparmsall, 0, SEEK_CUR ); frame_number = lseek(fd_fparmsall, 0, SEEK_CUR );
frame8= frame_number & PARS_FRAMES_MASK; frame8 = frame_number & PARS_FRAMES_MASK;
// printf ("Current frame number is %d\n",frame_number); // printf ("Current frame number is %d\n",frame_number);
sensor_state=framePars[frame8].pars[P_SENSOR_RUN]; sensor_state = framePars[frame8].pars[P_SENSOR_RUN];
compressor_state=framePars[frame8].pars[P_COMPRESSOR_RUN]; compressor_state = framePars[frame8].pars[P_COMPRESSOR_RUN];
cp_sensor_state= (sensor_state==0)? cp_sensor_state = (sensor_state == 0) ?
"SENSOR_RUN_STOP": "SENSOR_RUN_STOP" :
((sensor_state==1)? ((sensor_state == 1) ?
"SENSOR_RUN_SINGLE": "SENSOR_RUN_SINGLE" :
((sensor_state==2)?"SENSOR_RUN_CONT":"UNKNOWN")); ((sensor_state == 2) ? "SENSOR_RUN_CONT" : "UNKNOWN"));
cp_compressor_state= (compressor_state==0)? cp_compressor_state = (compressor_state == 0) ?
"COMPRESSOR_RUN_STOP": "COMPRESSOR_RUN_STOP" :
((compressor_state==1)? ((compressor_state == 1) ?
"COMPRESSOR_RUN_SINGLE": "COMPRESSOR_RUN_SINGLE" :
((compressor_state==2)?"COMPRESSOR_RUN_CONT":"UNKNOWN")); ((compressor_state == 2) ? "COMPRESSOR_RUN_CONT" : "UNKNOWN"));
save_p=lseek(fd_circ,0,SEEK_CUR); //!save current file pointer before temporarily moving it save_p = lseek(fd_circ, 0, SEEK_CUR); //!save current file pointer before temporarily moving it
rp=lseek(fd_circ,LSEEK_CIRC_TORP,SEEK_END); //! set current rp global rp (may be invalid <0) rp = lseek(fd_circ, LSEEK_CIRC_TORP, SEEK_END); //! set current rp global rp (may be invalid <0)
wp=lseek(fd_circ,LSEEK_CIRC_TOWP,SEEK_END); //! set current rp pointer to FPGA write pointer wp = lseek(fd_circ, LSEEK_CIRC_TOWP, SEEK_END); //! set current rp pointer to FPGA write pointer
p=wp; p = wp;
while ((p>=0) & (nf<500)) { while ((p >= 0) & (nf < 500)) {
if (p==rp) nfl=nf; if (p == rp) nfl = nf;
p=lseek(fd_circ,LSEEK_CIRC_PREV,SEEK_END); p = lseek(fd_circ, LSEEK_CIRC_PREV, SEEK_END);
nf++; nf++;
} }
buf_free=GLOBALPARS(G_FREECIRCBUF); buf_free = GLOBALPARS(G_FREECIRCBUF);
frame_size=GLOBALPARS(G_FRAME_SIZE); frame_size = GLOBALPARS(G_FRAME_SIZE);
lseek(fd_circ,save_p,SEEK_SET); //! restore file pointer after temporarily moving it lseek(fd_circ, save_p, SEEK_SET); //! restore file pointer after temporarily moving it
buf_free=lseek(fd_circ,LSEEK_CIRC_FREE,SEEK_END); //! will change file pointer buf_free = lseek(fd_circ, LSEEK_CIRC_FREE, SEEK_END); //! will change file pointer
lseek(fd_circ,save_p,SEEK_SET); //! restore file pointer after temporarily moving it lseek(fd_circ, save_p, SEEK_SET); //! restore file pointer after temporarily moving it
buf_used=lseek(fd_circ,LSEEK_CIRC_USED,SEEK_END); //! will change file pointer buf_used = lseek(fd_circ, LSEEK_CIRC_USED, SEEK_END); //! will change file pointer
lseek(fd_circ,save_p,SEEK_SET); //! restore file pointer after temporarily moving it lseek(fd_circ, save_p, SEEK_SET); //! restore file pointer after temporarily moving it
sprintf (s,"<?xml version=\"1.0\"?>\n" \ sprintf(s, "<?xml version=\"1.0\"?>\n" \
"<frame_pointers>\n" \ "<frame_pointers>\n" \
" <this>%d</this>\n" \ " <this>%d</this>\n" \
" <write>%d</write>\n" \ " <write>%d</write>\n" \
...@@ -720,7 +729,7 @@ int framePointersXML(int fd_circ) { ...@@ -720,7 +729,7 @@ int framePointersXML(int fd_circ) {
save_p, save_p,
wp, wp,
rp, rp,
nf-1, nf - 1,
nfl, nfl,
buf_free, buf_free,
buf_used, buf_used,
...@@ -730,19 +739,20 @@ int framePointersXML(int fd_circ) { ...@@ -730,19 +739,20 @@ int framePointersXML(int fd_circ) {
cp_compressor_state); cp_compressor_state);
printf("HTTP/1.0 200 OK\r\n"); printf("HTTP/1.0 200 OK\r\n");
printf("Server: Elphel Imgsrv\r\n"); printf("Server: Elphel Imgsrv\r\n");
printf("Content-Length: %d\r\n",strlen(s)); printf("Content-Length: %d\r\n", strlen(s));
printf("Content-Type: text/xml\r\n"); printf("Content-Type: text/xml\r\n");
printf("Pragma: no-cache\r\n"); printf("Pragma: no-cache\r\n");
printf("\r\n"); printf("\r\n");
printf(s); printf(s);
//! No need to unmap? //! No need to unmap?
close(fd_fparmsall); close(fd_fparmsall);
D(fprintf (stderr,">%s< [%d bytes]\n",s,strlen(s))); D(fprintf(stderr, ">%s< [%d bytes]\n", s, strlen(s)));
return 0; return 0;
} }
//fwrite (&cbuffer[offset],1,bytesLeft,stdout); //fwrite (&cbuffer[offset],1,bytesLeft,stdout);
int out1x1gif(void) { int out1x1gif(void)
char s[]="HTTP/1.0 200 OK\r\n" \ {
char s[] = "HTTP/1.0 200 OK\r\n" \
"Server: Elphel Imgsrv\r\n" \ "Server: Elphel Imgsrv\r\n" \
"Content-Length: 35\r\n" \ "Content-Length: 35\r\n" \
"Content-Type: image/gif\r\n" \ "Content-Type: image/gif\r\n" \
...@@ -750,20 +760,23 @@ int out1x1gif(void) { ...@@ -750,20 +760,23 @@ int out1x1gif(void) {
"GIF87a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00" \ "GIF87a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00" \
"\xff\xff\xff\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x4c" \ "\xff\xff\xff\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x4c" \
"\x01\x00\x3b"; "\x01\x00\x3b";
fwrite (s,1,sizeof(s),stdout); //! we have zeros in the string
fwrite(s, 1, sizeof(s), stdout); //! we have zeros in the string
return 0; //! always good return 0; //! always good
} }
void errorMsgXML(char * msg) { void errorMsgXML(char * msg)
{
char s[1024]; // was 701 acrtually char s[1024]; // was 701 acrtually
sprintf (s,"<?xml version=\"1.0\"?>\n" \
sprintf(s, "<?xml version=\"1.0\"?>\n" \
"<frame_params>\n" \ "<frame_params>\n" \
"<error>%s</error>\n" \ "<error>%s</error>\n" \
"</frame_params>\n",msg); "</frame_params>\n", msg);
D(fprintf (stderr,">%s< [%d bytes]",s,strlen(s))); D(fprintf(stderr, ">%s< [%d bytes]", s, strlen(s)));
printf("HTTP/1.0 200 OK\r\n"); printf("HTTP/1.0 200 OK\r\n");
printf("Server: Elphel Imgsrv\r\n"); printf("Server: Elphel Imgsrv\r\n");
printf("Content-Length: %d\r\n",strlen(s)); printf("Content-Length: %d\r\n", strlen(s));
printf("Content-Type: text/xml\r\n"); printf("Content-Type: text/xml\r\n");
printf("Pragma: no-cache\r\n"); printf("Pragma: no-cache\r\n");
printf("\r\n"); printf("\r\n");
...@@ -775,12 +788,13 @@ void errorMsgXML(char * msg) { ...@@ -775,12 +788,13 @@ void errorMsgXML(char * msg) {
//! read pointer in fd_circ should be at the start of the frame to be sent //! read pointer in fd_circ should be at the start of the frame to be sent
//! mmap will be opened in this function //! mmap will be opened in this function
int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) { int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage)
const char HeadFileName[]="/dev/jpeghead0"; {
const char ExifFileName[]="/dev/exif_exif"; const char HeadFileName[] = "/dev/jpeghead0";
int exifDataSize=0; const char ExifFileName[] = "/dev/exif_exif";
int exifDataSize = 0;
/// int exifIndexPointer=0; /// int exifIndexPointer=0;
int frameParamPointer=0; int frameParamPointer = 0;
struct interframe_params_t frame_params; struct interframe_params_t frame_params;
/// struct frame_exif_t frame_exif; //just 8 bytes /// struct frame_exif_t frame_exif; //just 8 bytes
int buff_size; int buff_size;
...@@ -791,30 +805,31 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) { ...@@ -791,30 +805,31 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) {
int head_size; int head_size;
int jpeg_full_size, jpeg_this_size; int jpeg_full_size, jpeg_this_size;
char * jpeg_copy; char * jpeg_copy;
int l,i; int l, i;
int color_mode; int color_mode;
char * mime_type; char * mime_type;
char * extension; char * extension;
/// int metadata_start; //metadata pointer (in bytes, from the start of the ccam_dma_buf) /// int metadata_start; //metadata pointer (in bytes, from the start of the ccam_dma_buf)
jpeg_start=lseek(fd_circ,0,SEEK_CUR); //get the current read pointer jpeg_start = lseek(fd_circ, 0, SEEK_CUR); //get the current read pointer
D(fprintf(stderr,"jpeg_start (long) = 0x%x\n",jpeg_start)); D(fprintf(stderr, "jpeg_start (long) = 0x%x\n", jpeg_start));
fd_head = open(HeadFileName, O_RDWR); fd_head = open(HeadFileName, O_RDWR);
if (fd_head<0) { // check control OK if (fd_head < 0) { // check control OK
fprintf (stderr,"Error opening %s\n", HeadFileName); fprintf(stderr, "Error opening %s\n", HeadFileName);
return -1; return -1;
} }
lseek(fd_head,jpeg_start+1,SEEK_END); /// create JPEG header, find out it's size TODO: lseek(fd_head, jpeg_start + 1, SEEK_END); /// create JPEG header, find out it's size TODO:
head_size=lseek(fd_head,0,SEEK_END); head_size = lseek(fd_head, 0, SEEK_END);
if (head_size>JPEG_HEADER_MAXSIZE) { if (head_size > JPEG_HEADER_MAXSIZE) {
fprintf(stderr,"%s:%d: Too big JPEG header (%d > %d)",__FILE__,__LINE__,head_size, JPEG_HEADER_MAXSIZE ); fprintf(stderr, "%s:%d: Too big JPEG header (%d > %d)", __FILE__, __LINE__, head_size, JPEG_HEADER_MAXSIZE );
close (fd_head); close(fd_head);
return -2; return -2;
} }
/*! find total buffer length (it is in defines, actually in c313a.h */ /*! find total buffer length (it is in defines, actually in c313a.h */
buff_size=lseek(fd_circ,0,SEEK_END); buff_size = lseek(fd_circ, 0, SEEK_END);
/*! restore file poinetr after lseek-ing the end */ /*! restore file poinetr after lseek-ing the end */
lseek(fd_circ, jpeg_start, SEEK_SET); lseek(fd_circ, jpeg_start, SEEK_SET);
D(fprintf(stderr,"position (longs) = 0x%x\n", (int) lseek(fd_circ,0,SEEK_CUR))); D(fprintf(stderr, "position (longs) = 0x%x\n", (int)lseek(fd_circ, 0, SEEK_CUR)));
/*! now let's try mmap itself */ /*! now let's try mmap itself */
/// exifIndexPointer=jpeg_start-8; /// exifIndexPointer=jpeg_start-8;
...@@ -823,12 +838,12 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) { ...@@ -823,12 +838,12 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) {
frameParamPointer += buff_size; frameParamPointer += buff_size;
fprintf(stderr, "frameParamPointer = 0x%x, jpeg_start = 0x%x, buff_size = 0x%x\n", fprintf(stderr, "frameParamPointer = 0x%x, jpeg_start = 0x%x, buff_size = 0x%x\n",
frameParamPointer, jpeg_start, buff_size); frameParamPointer, jpeg_start, buff_size);
memcpy(&frame_params, (unsigned long *) &ccam_dma_buf[frameParamPointer >> 2], sizeof(struct interframe_params_t)); memcpy(&frame_params, (unsigned long*)&ccam_dma_buf[frameParamPointer >> 2], sizeof(struct interframe_params_t));
jpeg_len=frame_params.frame_length; jpeg_len = frame_params.frame_length;
//color_mode=frame_params.color; //color_mode=frame_params.color;
if (frame_params.signffff != 0xffff) { if (frame_params.signffff != 0xffff) {
fprintf(stderr, "wrong signature signff = 0x%x \n", (int)frame_params.signffff); fprintf(stderr, "wrong signature signff = 0x%x \n", (int)frame_params.signffff);
close (fd_head); close(fd_head);
return -4; return -4;
} }
...@@ -836,52 +851,52 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) { ...@@ -836,52 +851,52 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) {
//D(fprintf(stderr,"frame_params.meta_index=0x%x\n",(int) frame_params.meta_index)); //D(fprintf(stderr,"frame_params.meta_index=0x%x\n",(int) frame_params.meta_index));
/// read Exif to buffer: /// read Exif to buffer:
fd_exif = open(ExifFileName, O_RDONLY); fd_exif = open(ExifFileName, O_RDONLY);
if (fd_exif<0) { // check control OK if (fd_exif < 0) { // check control OK
fprintf (stderr,"Error opening %s\n", ExifFileName); fprintf(stderr, "Error opening %s\n", ExifFileName);
close (fd_head); close(fd_head);
return -5; return -5;
} }
exifDataSize=lseek(fd_exif,1,SEEK_END); // at the beginning of page 1 - position == page length exifDataSize = lseek(fd_exif, 1, SEEK_END); // at the beginning of page 1 - position == page length
if (exifDataSize < 0) exifDataSize=0; // error from lseek; if (exifDataSize < 0) exifDataSize = 0; // error from lseek;
if (!exifDataSize) close(fd_exif); if (!exifDataSize) close(fd_exif);
} else { } else {
//frame_params.meta_index=0; //frame_params.meta_index=0;
fd_exif=-1; fd_exif = -1;
} }
///Maybe make buffer that will fit both Exif and JPEG? ///Maybe make buffer that will fit both Exif and JPEG?
//!Get metadata, update Exif and JFIF headers if ep and ed poinetrs are non-zero (NULL will generate files with JFIF-only headers) //!Get metadata, update Exif and JFIF headers if ep and ed poinetrs are non-zero (NULL will generate files with JFIF-only headers)
/// Now we always malloc buffer, before - only for bimg, using fixed-size header buffer - was it faster? /// Now we always malloc buffer, before - only for bimg, using fixed-size header buffer - was it faster?
jpeg_full_size=jpeg_len+head_size+2+exifDataSize; jpeg_full_size = jpeg_len + head_size + 2 + exifDataSize;
fprintf(stderr, "jpeg_len = 0x%x, head_size = 0x%x, exifDataSize = 0x%x, jpeg_full_size = 0z%x\n", fprintf(stderr, "jpeg_len = 0x%x, head_size = 0x%x, exifDataSize = 0x%x, jpeg_full_size = 0z%x\n",
jpeg_len, head_size, exifDataSize, jpeg_full_size); jpeg_len, head_size, exifDataSize, jpeg_full_size);
if (bufferImageData) jpeg_this_size=jpeg_full_size; /// header+frame if (bufferImageData) jpeg_this_size = jpeg_full_size; /// header+frame
else jpeg_this_size=head_size+exifDataSize; /// only header else jpeg_this_size = head_size + exifDataSize; /// only header
jpeg_copy=malloc(jpeg_this_size); jpeg_copy = malloc(jpeg_this_size);
if (!jpeg_copy) { if (!jpeg_copy) {
syslog(LOG_ERR, "%s:%d malloc (%d) failed", __FILE__,__LINE__,jpeg_this_size); syslog(LOG_ERR, "%s:%d malloc (%d) failed", __FILE__, __LINE__, jpeg_this_size);
/// If we really want it, but don't get it - let's try more /// If we really want it, but don't get it - let's try more
for (i=0;i<10;i++) { for (i = 0; i < 10; i++) {
usleep(((jpeg_this_size & 0x3ff) + 5) * 100); // up to 0.1 sec usleep(((jpeg_this_size & 0x3ff) + 5) * 100); // up to 0.1 sec
jpeg_copy=malloc(jpeg_this_size); jpeg_copy = malloc(jpeg_this_size);
if (jpeg_copy) break; if (jpeg_copy) break;
syslog(LOG_ERR, "%s:%d malloc (%d) failed", __FILE__,__LINE__,jpeg_this_size); syslog(LOG_ERR, "%s:%d malloc (%d) failed", __FILE__, __LINE__, jpeg_this_size);
} }
if (!jpeg_copy) { if (!jpeg_copy) {
syslog(LOG_ERR, "%s:%d malloc (%d) failed 10 times - giving up", __FILE__,__LINE__,jpeg_this_size); syslog(LOG_ERR, "%s:%d malloc (%d) failed 10 times - giving up", __FILE__, __LINE__, jpeg_this_size);
exit (1); exit(1);
} }
} }
lseek(fd_head,0,0); lseek(fd_head, 0, 0);
read (fd_head,&jpeg_copy[exifDataSize],head_size); read(fd_head, &jpeg_copy[exifDataSize], head_size);
close (fd_head); close(fd_head);
if (exifDataSize>0) {//! insert Exif if (exifDataSize > 0) { //! insert Exif
memcpy (jpeg_copy,&jpeg_copy[exifDataSize],2); //! copy first 2 bytes of the JFIF header before Exif memcpy(jpeg_copy, &jpeg_copy[exifDataSize], 2); //! copy first 2 bytes of the JFIF header before Exif
//lseek(fd_exif,frame_params.meta_index,SEEK_END); //! select meta page to use (matching frame) //lseek(fd_exif,frame_params.meta_index,SEEK_END); //! select meta page to use (matching frame)
read (fd_exif,&jpeg_copy[2],exifDataSize); //! Insert Exif itself read(fd_exif, &jpeg_copy[2], exifDataSize); //! Insert Exif itself
close(fd_exif); close(fd_exif);
} }
switch (color_mode) { switch (color_mode) {
...@@ -889,8 +904,8 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) { ...@@ -889,8 +904,8 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) {
// case COLORMODE_COLOR: //! color, 4:2:0, 18x18(old) // case COLORMODE_COLOR: //! color, 4:2:0, 18x18(old)
case COLORMODE_JP46: //! jp4, original (4:2:0) case COLORMODE_JP46: //! jp4, original (4:2:0)
case COLORMODE_JP46DC: //! jp4, dc -improved (4:2:0) case COLORMODE_JP46DC: //! jp4, dc -improved (4:2:0)
mime_type="jp46"; mime_type = "jp46";
extension="jp46"; extension = "jp46";
break; break;
// case COLORMODE_COLOR20: //! color, 4:2:0, 20x20, middle of the tile (not yet implemented) // case COLORMODE_COLOR20: //! color, 4:2:0, 20x20, middle of the tile (not yet implemented)
case COLORMODE_JP4: //! jp4, 4 blocks, (legacy) case COLORMODE_JP4: //! jp4, 4 blocks, (legacy)
...@@ -899,13 +914,13 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) { ...@@ -899,13 +914,13 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) {
case COLORMODE_JP4HDR: //! jp4, 4 blocks, differential HDR: red := (R-G1), blue:=(B-G1), green=G1, green2 (high gain)=G2) (G1 and G2 - diagonally opposite) case COLORMODE_JP4HDR: //! jp4, 4 blocks, differential HDR: red := (R-G1), blue:=(B-G1), green=G1, green2 (high gain)=G2) (G1 and G2 - diagonally opposite)
case COLORMODE_JP4DIFF2: //! jp4, 4 blocks, differential, divide differences by 2: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (G2-G1)/2 case COLORMODE_JP4DIFF2: //! jp4, 4 blocks, differential, divide differences by 2: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (G2-G1)/2
case COLORMODE_JP4HDR2: //! jp4, 4 blocks, differential HDR: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (high gain)=G2), case COLORMODE_JP4HDR2: //! jp4, 4 blocks, differential HDR: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (high gain)=G2),
mime_type="jp4"; mime_type = "jp4";
extension="jp4"; extension = "jp4";
break; break;
// case COLORMODE_MONO4: //! monochrome, 4 blocks (but still with 2x2 macroblocks) // case COLORMODE_MONO4: //! monochrome, 4 blocks (but still with 2x2 macroblocks)
default: default:
mime_type="jpeg"; mime_type = "jpeg";
extension="jpeg"; extension = "jpeg";
} }
// char * mime_type; // char * mime_type;
...@@ -924,40 +939,40 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) { ...@@ -924,40 +939,40 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) {
#define COLORMODE_JP4HDR2 10 // jp4, 4 blocks, differential HDR: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (high gain)=G2), #define COLORMODE_JP4HDR2 10 // jp4, 4 blocks, differential HDR: red := (R-G1)/2, blue:=(B-G1)/2, green=G1, green2 (high gain)=G2),
#define COLORMODE_MONO4 14 // monochrome, 4 blocks (but still with 2x2 macroblocks) #define COLORMODE_MONO4 14 // monochrome, 4 blocks (but still with 2x2 macroblocks)
*/ */
printf("Content-Type: image/%s\r\n",mime_type); printf("Content-Type: image/%s\r\n", mime_type);
if (saveImage) printf("Content-Disposition: attachment; filename=\"elphelimg_%ld.%s\"\r\n",frame_params.timestamp_sec,extension); /// does not open, asks for filename to save if (saveImage) printf("Content-Disposition: attachment; filename=\"elphelimg_%ld.%s\"\r\n", frame_params.timestamp_sec, extension); /// does not open, asks for filename to save
else printf("Content-Disposition: inline; filename=\"elphelimg_%ld.%s\"\r\n",frame_params.timestamp_sec,extension); /// opens in browser, asks to save on right-click else printf("Content-Disposition: inline; filename=\"elphelimg_%ld.%s\"\r\n", frame_params.timestamp_sec, extension); /// opens in browser, asks to save on right-click
if (bufferImageData) { /*! Buffer the whole file before sending over the network to make sure it will not be corrupted if the circular buffer will be overrun) */ if (bufferImageData) { /*! Buffer the whole file before sending over the network to make sure it will not be corrupted if the circular buffer will be overrun) */
l=head_size+exifDataSize; l = head_size + exifDataSize;
/*! JPEG image data may be split in two segments (rolled over buffer end) - process both variants */ /*! JPEG image data may be split in two segments (rolled over buffer end) - process both variants */
if ((jpeg_start+jpeg_len) > buff_size) { // two segments if ((jpeg_start + jpeg_len) > buff_size) { // two segments
memcpy (&jpeg_copy[l], (unsigned long * ) &ccam_dma_buf[jpeg_start>>2],buff_size-jpeg_start); memcpy(&jpeg_copy[l], (unsigned long* )&ccam_dma_buf[jpeg_start >> 2], buff_size - jpeg_start);
l+=buff_size-jpeg_start; l += buff_size - jpeg_start;
memcpy (&jpeg_copy[l],(unsigned long * ) &ccam_dma_buf[0],jpeg_len-(buff_size-jpeg_start)); memcpy(&jpeg_copy[l], (unsigned long* )&ccam_dma_buf[0], jpeg_len - (buff_size - jpeg_start));
} else { /*! single segment */ } else { /*! single segment */
memcpy (&jpeg_copy[l],(unsigned long * ) &ccam_dma_buf[jpeg_start>>2],jpeg_len); memcpy(&jpeg_copy[l], (unsigned long* )&ccam_dma_buf[jpeg_start >> 2], jpeg_len);
} }
memcpy (&jpeg_copy[jpeg_len+head_size+exifDataSize],trailer,2); memcpy(&jpeg_copy[jpeg_len + head_size + exifDataSize], trailer, 2);
printf("Content-Length: %d\r\n",jpeg_full_size); printf("Content-Length: %d\r\n", jpeg_full_size);
printf("\r\n"); printf("\r\n");
sendBuffer(jpeg_copy, jpeg_full_size); sendBuffer(jpeg_copy, jpeg_full_size);
} else { /*! fast connection, no need to buffer image, so we'll try to run it faster */ } else { /*! fast connection, no need to buffer image, so we'll try to run it faster */
printf("Content-Length: %d\r\n",jpeg_full_size); printf("Content-Length: %d\r\n", jpeg_full_size);
printf("\r\n"); printf("\r\n");
sendBuffer(jpeg_copy, head_size+exifDataSize); //JPEG+Exif sendBuffer(jpeg_copy, head_size + exifDataSize); //JPEG+Exif
/*! JPEG image data may be split in two segments (rolled over buffer end) - process both variants */ /*! JPEG image data may be split in two segments (rolled over buffer end) - process both variants */
if ((jpeg_start+jpeg_len) > buff_size) { // two segments if ((jpeg_start + jpeg_len) > buff_size) { // two segments
/*! copy from the beginning of the frame to the end of the buffer */ /*! copy from the beginning of the frame to the end of the buffer */
sendBuffer((void *) &ccam_dma_buf[jpeg_start>>2], buff_size-jpeg_start); sendBuffer((void*)&ccam_dma_buf[jpeg_start >> 2], buff_size - jpeg_start);
/*! copy from the beginning of the buffer to the end of the frame */ /*! copy from the beginning of the buffer to the end of the frame */
sendBuffer((void *) &ccam_dma_buf[0], jpeg_len-(buff_size-jpeg_start)); sendBuffer((void*)&ccam_dma_buf[0], jpeg_len - (buff_size - jpeg_start));
} else { // single segment } else { // single segment
/*! copy from the beginning of the frame to the end of the frame (no buffer rollovers) */ /*! copy from the beginning of the frame to the end of the frame (no buffer rollovers) */
sendBuffer((void *) &ccam_dma_buf[jpeg_start>>2], jpeg_len); sendBuffer((void*)&ccam_dma_buf[jpeg_start >> 2], jpeg_len);
} }
sendBuffer(trailer,2); sendBuffer(trailer, 2);
} }
free(jpeg_copy); free(jpeg_copy);
return 0; return 0;
...@@ -966,18 +981,20 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) { ...@@ -966,18 +981,20 @@ int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage) {
/*! repeat writes to stdout until all data is sent */ /*! repeat writes to stdout until all data is sent */
void sendBuffer(void * buffer, int len) { void sendBuffer(void * buffer, int len)
int bytesLeft=len; {
int offset=0; int bytesLeft = len;
int offset = 0;
int bytesWritten; int bytesWritten;
char * cbuffer= (char *) buffer; char * cbuffer = (char*)buffer;
D(fprintf (stderr,"buffer=%p, len=%d\n",buffer, len));
while (bytesLeft>0) { D(fprintf(stderr, "buffer=%p, len=%d\n", buffer, len));
D(fprintf (stderr," --bytesLeft=%d\n",bytesLeft)); while (bytesLeft > 0) {
D(fprintf(stderr, " --bytesLeft=%d\n", bytesLeft));
bytesWritten= fwrite (&cbuffer[offset],1,bytesLeft,stdout);
bytesLeft-= bytesWritten; bytesWritten = fwrite(&cbuffer[offset], 1, bytesLeft, stdout);
offset+= bytesWritten; bytesLeft -= bytesWritten;
offset += bytesWritten;
} }
} }
...@@ -987,33 +1004,34 @@ D(fprintf (stderr," --bytesLeft=%d\n",bytesLeft)); ...@@ -987,33 +1004,34 @@ D(fprintf (stderr," --bytesLeft=%d\n",bytesLeft));
void listener_loop(int port) void listener_loop(int port)
{ {
char errormsg[1024]; char errormsg[1024];
const char circbufFileName[]="/dev/circbuf0"; const char circbufFileName[] = "/dev/circbuf0";
int fd_circ; int fd_circ;
int this_p; //! current frame pointer (bytes) int this_p; //! current frame pointer (bytes)
int rslt; int rslt;
int buf_images=0; int buf_images = 0;
int suggest_save_images=0; int suggest_save_images = 0;
char buf [1024]; char buf [1024];
int len=0; int len = 0;
int current_len; int current_len;
char * cp, *cp1, *cp2; char * cp, *cp1, *cp2;
int slow,skip; // reduce frame rate by slow int slow, skip; // reduce frame rate by slow
int sent2socket=-1; // 1 - img, 2 - meta, 3 - pointers int sent2socket = -1; // 1 - img, 2 - meta, 3 - pointers
struct sockaddr_in sock; struct sockaddr_in sock;
int res; int res;
int one=1; int one = 1;
int buff_size; int buff_size;
memset((char *)&sock, 0, sizeof(sock));
memset((char*)&sock, 0, sizeof(sock));
sock.sin_port = htons(port); sock.sin_port = htons(port);
sock.sin_family = AF_INET; sock.sin_family = AF_INET;
res = socket(AF_INET, SOCK_STREAM, 0); res = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); setsockopt(res, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one));
bind(res, (struct sockaddr * ) &sock,sizeof(sock)); bind(res, (struct sockaddr* )&sock, sizeof(sock));
listen(res, 10); listen(res, 10);
int exif_enable=1; int exif_enable = 1;
while (1) { while (1) {
int fd; int fd;
fd = accept(res,NULL,0); fd = accept(res, NULL, 0);
if (fd == -1) continue; if (fd == -1) continue;
signal(SIGCHLD, SIG_IGN); // no zombies, please! signal(SIGCHLD, SIG_IGN); // no zombies, please!
...@@ -1027,19 +1045,19 @@ void listener_loop(int port) ...@@ -1027,19 +1045,19 @@ void listener_loop(int port)
dup2(fd, 1); dup2(fd, 1);
close(fd); close(fd);
/*! We need just the first line of the GET to read parameters */ /*! We need just the first line of the GET to read parameters */
if (fgets(buf, sizeof(buf)-1, stdin)) len=strlen(buf); if (fgets(buf, sizeof(buf) - 1, stdin)) len = strlen(buf);
cp=buf; cp = buf;
strsep(&cp, "/?"); // ignore everything before first "/" or "?" strsep(&cp, "/?"); // ignore everything before first "/" or "?"
if (cp) { if (cp) {
//! Now cp points to the first character after the first "/" or "?" in the url //! Now cp points to the first character after the first "/" or "?" in the url
//! we need to remove everything after (and including) the first space //! we need to remove everything after (and including) the first space
cp1=strchr(cp,' '); cp1 = strchr(cp, ' ');
if (cp1) cp1[0]='\0'; if (cp1) cp1[0] = '\0';
} }
if (!cp || (strlen(cp)==0)) { //!no url commands - probably the server url was manually entered if (!cp || (strlen(cp) == 0)) { //!no url commands - probably the server url was manually entered
printf("HTTP/1.0 200 OK\r\n"); printf("HTTP/1.0 200 OK\r\n");
printf("Server: Elphel Imgsrv\r\n"); printf("Server: Elphel Imgsrv\r\n");
printf("Content-Length: %d\r\n",strlen(url_args)); printf("Content-Length: %d\r\n", strlen(url_args));
printf("Content-Type: text/plain\r\n"); printf("Content-Type: text/plain\r\n");
printf("\r\n"); printf("\r\n");
printf(url_args); printf(url_args);
...@@ -1047,166 +1065,166 @@ void listener_loop(int port) ...@@ -1047,166 +1065,166 @@ void listener_loop(int port)
_exit(0); _exit(0);
} }
/// Process 'frame' and 'wframe' commands - theys do not need circbuf /// Process 'frame' and 'wframe' commands - theys do not need circbuf
if ((strncmp(cp, "frame",5)==0) || (strncmp(cp, "wframe",6)==0)){ if ((strncmp(cp, "frame", 5) == 0) || (strncmp(cp, "wframe", 6) == 0)) {
if (strncmp(cp, "wframe",6)==0) waitFrameSync(); if (strncmp(cp, "wframe", 6) == 0) waitFrameSync();
printf("HTTP/1.0 200 OK\r\n"); printf("HTTP/1.0 200 OK\r\n");
printf("Server: Elphel Imgsrv\r\n"); printf("Server: Elphel Imgsrv\r\n");
printf("Content-Length: 11\r\n"); printf("Content-Length: 11\r\n");
printf("Content-Type: text/plain\r\n"); printf("Content-Type: text/plain\r\n");
printf("\r\n"); printf("\r\n");
printf("%010ld\r\n",getCurrentFrameNumber()); printf("%010ld\r\n", getCurrentFrameNumber());
fflush(stdout); fflush(stdout);
_exit(0); _exit(0);
} }
//!now process the commands one at a time, but first - open the circbuf file and setup the pointer //!now process the commands one at a time, but first - open the circbuf file and setup the pointer
fd_circ = open(circbufFileName, O_RDWR); fd_circ = open(circbufFileName, O_RDWR);
if (fd_circ<0) { // check control OK if (fd_circ < 0) { // check control OK
fprintf (stderr,"Error opening %s\n", circbufFileName); fprintf(stderr, "Error opening %s\n", circbufFileName);
out1x1gif(); out1x1gif();
fflush(stdout); fflush(stdout);
_exit(0); _exit(0);
} }
/*! find total buffer length (it is in defines, actually in c313a.h */ /*! find total buffer length (it is in defines, actually in c313a.h */
buff_size=lseek(fd_circ,0,SEEK_END); buff_size = lseek(fd_circ, 0, SEEK_END);
fprintf(stderr, "%s: read circbuf size: %d\n", __func__, buff_size); fprintf(stderr, "%s: read circbuf size: %d\n", __func__, buff_size);
/*! now let's try mmap itself */ /*! now let's try mmap itself */
ccam_dma_buf = (unsigned long *) mmap(0, buff_size, PROT_READ, MAP_SHARED, fd_circ, 0); ccam_dma_buf = (unsigned long*)mmap(0, buff_size, PROT_READ, MAP_SHARED, fd_circ, 0);
if((int)ccam_dma_buf == -1) { if ((int)ccam_dma_buf == -1) {
fprintf(stderr, "Error in mmap\n"); fprintf(stderr, "Error in mmap\n");
close(fd_circ); // - caller opened, caller - to close close(fd_circ); // - caller opened, caller - to close
out1x1gif(); out1x1gif();
fflush(stdout); fflush(stdout);
_exit(0); _exit(0);
} }
this_p=lseek(fd_circ,LSEEK_CIRC_LAST,SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_LAST, SEEK_END);
D(fprintf(stderr, "%s: current frame pointer this_p (in bytes): 0x%x\n", __func__, this_p)); D(fprintf(stderr, "%s: current frame pointer this_p (in bytes): 0x%x\n", __func__, this_p));
//!continue with iterating through the commands //!continue with iterating through the commands
while ((cp1=strsep(&cp, "/?&"))) { while ((cp1 = strsep(&cp, "/?&"))) {
// printf ("1->%s", cp1); // printf ("1->%s", cp1);
// fprintf (stderr, "1->%s",cp1); // fprintf (stderr, "1->%s",cp1);
//!if the first caracter is digit,it is a file pointer //!if the first caracter is digit,it is a file pointer
if (strchr("0123456789",cp1[0])) { if (strchr("0123456789", cp1[0])) {
this_p= lseek(fd_circ,strtol(cp1, NULL, 10),SEEK_SET); this_p = lseek(fd_circ, strtol(cp1, NULL, 10), SEEK_SET);
} else if ((strcmp(cp1, "img")==0) || (strcmp(cp1, "bimg")==0) || (strcmp(cp1, "simg")==0) || (strcmp(cp1, "sbimg")==0)) { } else if ((strcmp(cp1, "img") == 0) || (strcmp(cp1, "bimg") == 0) || (strcmp(cp1, "simg") == 0) || (strcmp(cp1, "sbimg") == 0)) {
fprintf(stderr, "%s: processing img command\n", __func__); fprintf(stderr, "%s: processing img command\n", __func__);
if (sent2socket>0) break; //! image/xmldata was already sent to socket, ignore if (sent2socket > 0) break; //! image/xmldata was already sent to socket, ignore
if (lseek(fd_circ,LSEEK_CIRC_READY,SEEK_END)<0) { //! here passes OK, some not ready error is later, in sendimage (make it return different numbers) if (lseek(fd_circ, LSEEK_CIRC_READY, SEEK_END) < 0) { //! here passes OK, some not ready error is later, in sendimage (make it return different numbers)
rslt=out1x1gif(); rslt = out1x1gif();
fprintf(stderr, "%s: no frame is available\n", __func__); fprintf(stderr, "%s: no frame is available\n", __func__);
} else { } else {
printf("HTTP/1.0 200 OK\r\n"); printf("HTTP/1.0 200 OK\r\n");
printf("Server: Elphel Imgsrv\r\n"); printf("Server: Elphel Imgsrv\r\n");
printf("Expires: 0\r\n"); printf("Expires: 0\r\n");
printf("Pragma: no-cache\r\n"); printf("Pragma: no-cache\r\n");
buf_images= ((strcmp(cp1, "img")==0) || (strcmp(cp1, "simg")==0))?0:1; buf_images = ((strcmp(cp1, "img") == 0) || (strcmp(cp1, "simg") == 0)) ? 0 : 1;
suggest_save_images=((strcmp(cp1, "simg")==0) || (strcmp(cp1, "sbimg")==0))?1:0; suggest_save_images = ((strcmp(cp1, "simg") == 0) || (strcmp(cp1, "sbimg") == 0)) ? 1 : 0;
fprintf(stderr, "%s: sending image\n", __func__); fprintf(stderr, "%s: sending image\n", __func__);
rslt=sendImage(buf_images, fd_circ, exif_enable, suggest_save_images); //! verify driver that file pointer did not move rslt = sendImage(buf_images, fd_circ, exif_enable, suggest_save_images); //! verify driver that file pointer did not move
} }
sent2socket=1; sent2socket = 1;
if (rslt<0) { if (rslt < 0) {
if (sent2socket==1) out1x1gif(); if (sent2socket == 1) out1x1gif();
else { else {
sprintf(errormsg,"sendImage error = %d (%s:line %d)",rslt,__FILE__,__LINE__); sprintf(errormsg, "sendImage error = %d (%s:line %d)", rslt, __FILE__, __LINE__);
errorMsgXML(errormsg); errorMsgXML(errormsg);
} }
} }
fflush(stdout); //! let's not keep client waiting - anyway we've sent it all even when more commands maybe left fflush(stdout); //! let's not keep client waiting - anyway we've sent it all even when more commands maybe left
///multipart - always last ///multipart - always last
} else if ((strncmp(cp1, "mimg",4)==0) || (strncmp(cp1, "bmimg",5)==0) || (strncmp(cp1, "mbimg",5)==0)) { } else if ((strncmp(cp1, "mimg", 4) == 0) || (strncmp(cp1, "bmimg", 5) == 0) || (strncmp(cp1, "mbimg", 5) == 0)) {
if (sent2socket>0) break; //! image/xmldata was already sent to socket, ignore if (sent2socket > 0) break; //! image/xmldata was already sent to socket, ignore
if (lseek(fd_circ,LSEEK_CIRC_READY,SEEK_END)<0) //! here passes OK, some not ready error is later, in sendimage (make it return different numbers) if (lseek(fd_circ, LSEEK_CIRC_READY, SEEK_END) < 0) //! here passes OK, some not ready error is later, in sendimage (make it return different numbers)
rslt=out1x1gif(); rslt = out1x1gif();
else { else {
//TODO: //TODO:
buf_images= (strncmp(cp1, "mimg",4)==0)?0:1; buf_images = (strncmp(cp1, "mimg", 4) == 0) ? 0 : 1;
cp2=cp1+(buf_images?5:4); cp2 = cp1 + (buf_images ? 5 : 4);
slow=strtol(cp2, NULL, 10); slow = strtol(cp2, NULL, 10);
if (slow < 1) slow =1; if (slow < 1) slow = 1;
printf("HTTP/1.0 200 OK\r\n"); printf("HTTP/1.0 200 OK\r\n");
printf("Server: Elphel Imgsrv\r\n"); printf("Server: Elphel Imgsrv\r\n");
printf("Expires: 0\r\n"); printf("Expires: 0\r\n");
printf("Pragma: no-cache\r\n"); printf("Pragma: no-cache\r\n");
printf("Content-Type: multipart/x-mixed-replace;boundary=ElphelMultipartJPEGBoundary\r\n"); printf("Content-Type: multipart/x-mixed-replace;boundary=ElphelMultipartJPEGBoundary\r\n");
rslt=0; rslt = 0;
while (rslt>=0) { while (rslt >= 0) {
printf("\r\n--ElphelMultipartJPEGBoundary\r\n"); printf("\r\n--ElphelMultipartJPEGBoundary\r\n");
rslt=sendImage(buf_images, fd_circ, exif_enable, 0); //! verify driver that file pointer did not move rslt = sendImage(buf_images, fd_circ, exif_enable, 0); //! verify driver that file pointer did not move
fflush(stdout); fflush(stdout);
if (rslt>=0) for (skip=0;skip<slow;skip++) { if (rslt >= 0) for (skip = 0; skip < slow; skip++) {
this_p=lseek(fd_circ,LSEEK_CIRC_NEXT, SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
/// If these "next" is not ready yet - wait, else - use latest image /// If these "next" is not ready yet - wait, else - use latest image
if ((lseek(fd_circ,LSEEK_CIRC_VALID,SEEK_END) >= 0) && //! no sense to wait if the pointer is invalid if ((lseek(fd_circ, LSEEK_CIRC_VALID, SEEK_END) >= 0) && //! no sense to wait if the pointer is invalid
(lseek(fd_circ,LSEEK_CIRC_READY,SEEK_END) < 0) && //! or the frame is already ready (lseek(fd_circ, LSEEK_CIRC_READY, SEEK_END) < 0) && //! or the frame is already ready
(lseek(fd_circ,LSEEK_CIRC_VALID,SEEK_END) >= 0)) //! test valid once again, after not ready - it might change (lseek(fd_circ, LSEEK_CIRC_VALID, SEEK_END) >= 0)) //! test valid once again, after not ready - it might change
this_p=lseek(fd_circ,LSEEK_CIRC_WAIT,SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_WAIT, SEEK_END);
else this_p=lseek(fd_circ,LSEEK_CIRC_LAST, SEEK_END); else this_p = lseek(fd_circ, LSEEK_CIRC_LAST, SEEK_END);
} }
} }
_exit(0); _exit(0);
} }
} else if (strcmp(cp1, "pointers")==0) { } else if (strcmp(cp1, "pointers") == 0) {
if (sent2socket>0) break; //! image/xmldata was already sent to socket, ignore if (sent2socket > 0) break; //! image/xmldata was already sent to socket, ignore
framePointersXML(fd_circ); //! will restore file pointer after itself framePointersXML(fd_circ); //! will restore file pointer after itself
sent2socket=3; sent2socket = 3;
fflush(stdout); //! let's not keep client waiting - anyway we've sent it all even when more commands maybe left fflush(stdout); //! let's not keep client waiting - anyway we've sent it all even when more commands maybe left
} else if (strcmp(cp1, "meta")==0) { } else if (strcmp(cp1, "meta") == 0) {
if ((sent2socket>0) && (sent2socket!=2)) break; //! image/xmldata was already sent to socket, ignore if ((sent2socket > 0) && (sent2socket != 2)) break; //! image/xmldata was already sent to socket, ignore
metaXML(fd_circ,(sent2socket>0)?1:0); /// 0 - new (send headers), 1 - continue, 2 - finish metaXML(fd_circ, (sent2socket > 0) ? 1 : 0); /// 0 - new (send headers), 1 - continue, 2 - finish
sent2socket=2; sent2socket = 2;
fflush(stdout); //! let's not keep client waiting - anyway we've sent it all even when more commands maybe left fflush(stdout); //! let's not keep client waiting - anyway we've sent it all even when more commands maybe left
} else if (strcmp(cp1, "noexif")==0) { } else if (strcmp(cp1, "noexif") == 0) {
exif_enable=0; exif_enable = 0;
} else if (strcmp(cp1, "exif")==0) { } else if (strcmp(cp1, "exif") == 0) {
exif_enable=1; exif_enable = 1;
} else if (strcmp(cp1, "torp")==0) { } else if (strcmp(cp1, "torp") == 0) {
this_p=lseek(fd_circ,LSEEK_CIRC_TORP, SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_TORP, SEEK_END);
} else if (strcmp(cp1, "towp")==0) { } else if (strcmp(cp1, "towp") == 0) {
this_p=lseek(fd_circ,LSEEK_CIRC_TOWP, SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_TOWP, SEEK_END);
} else if (strcmp(cp1, "prev")==0) { } else if (strcmp(cp1, "prev") == 0) {
this_p=lseek(fd_circ,LSEEK_CIRC_PREV, SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_PREV, SEEK_END);
} else if (strcmp(cp1, "next")==0) { } else if (strcmp(cp1, "next") == 0) {
this_p=lseek(fd_circ,LSEEK_CIRC_NEXT, SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_NEXT, SEEK_END);
} else if (strcmp(cp1, "last")==0) { } else if (strcmp(cp1, "last") == 0) {
this_p=lseek(fd_circ,LSEEK_CIRC_LAST, SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_LAST, SEEK_END);
} else if (strcmp(cp1, "first")==0) { } else if (strcmp(cp1, "first") == 0) {
this_p=lseek(fd_circ,LSEEK_CIRC_FIRST,SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_FIRST, SEEK_END);
} else if (strcmp(cp1, "second")==0) { } else if (strcmp(cp1, "second") == 0) {
this_p=lseek(fd_circ,LSEEK_CIRC_SCND, SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_SCND, SEEK_END);
} else if (strcmp(cp1, "save")==0) { } else if (strcmp(cp1, "save") == 0) {
this_p=lseek(fd_circ,LSEEK_CIRC_SETP,SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_SETP, SEEK_END);
} else if (strcmp(cp1, "wait")==0) { } else if (strcmp(cp1, "wait") == 0) {
if ((lseek(fd_circ,LSEEK_CIRC_VALID,SEEK_END) >= 0) && //! no sense to wait if the pointer is invalid if ((lseek(fd_circ, LSEEK_CIRC_VALID, SEEK_END) >= 0) && //! no sense to wait if the pointer is invalid
(lseek(fd_circ,LSEEK_CIRC_READY,SEEK_END) < 0) && //! or the frame is already ready (lseek(fd_circ, LSEEK_CIRC_READY, SEEK_END) < 0) && //! or the frame is already ready
(lseek(fd_circ,LSEEK_CIRC_VALID,SEEK_END) >= 0)) //! test valid once again, after not ready - it might change (lseek(fd_circ, LSEEK_CIRC_VALID, SEEK_END) >= 0)) //! test valid once again, after not ready - it might change
this_p=lseek(fd_circ,LSEEK_CIRC_WAIT,SEEK_END); this_p = lseek(fd_circ, LSEEK_CIRC_WAIT, SEEK_END);
} else if (strcmp(cp1, "trig")==0) { } else if (strcmp(cp1, "trig") == 0) {
// printf ("trig argument\n"); // printf ("trig argument\n");
int fd_fpga=open("/dev/fpgaio", O_RDWR); int fd_fpga = open("/dev/fpgaio", O_RDWR);
// printf ("fd_fpga = 0x%x\n",fd_fpga); // printf ("fd_fpga = 0x%x\n",fd_fpga);
if (fd_fpga>=0){ if (fd_fpga >= 0) {
//int aaa; //int aaa;
lseek (fd_fpga, 0x7b,SEEK_SET) ; //!TODO: remove absolute register address from user application! 32-bit registers, not bytes lseek(fd_fpga, 0x7b, SEEK_SET); //!TODO: remove absolute register address from user application! 32-bit registers, not bytes
//printf ("lseek()-> 0x%x\n",aaa); //printf ("lseek()-> 0x%x\n",aaa);
long data=1; long data = 1;
write(fd_fpga,&data,4); // actually send the trigger pulse (will leave camera in single-shot mode) write(fd_fpga, &data, 4); // actually send the trigger pulse (will leave camera in single-shot mode)
//printf ("write()-> 0x%x\n",aaa); //printf ("write()-> 0x%x\n",aaa);
close (fd_fpga); close(fd_fpga);
} }
} else if (strcmp(cp1, "favicon.ico")==0) { } else if (strcmp(cp1, "favicon.ico") == 0) {
///ignore silently - for now, later make an icon? ///ignore silently - for now, later make an icon?
} else { } else {
if (cp1[0]!='_') fprintf(stderr,"Unrecognized URL command: \"%s\" - ignoring\n",cp1); //!allow "&_time=..." be silently ignored - needed for javascript image reload if (cp1[0] != '_') fprintf(stderr, "Unrecognized URL command: \"%s\" - ignoring\n", cp1); //!allow "&_time=..." be silently ignored - needed for javascript image reload
} }
} //!while ((cp1=strsep(&cp, "/?&"))) } //!while ((cp1=strsep(&cp, "/?&")))
if (sent2socket<=0) { //! Nothing was sent to the client so far and the command line is over. Let's return 1x1 pixel gif if (sent2socket <= 0) { //! Nothing was sent to the client so far and the command line is over. Let's return 1x1 pixel gif
out1x1gif(); out1x1gif();
} else if (sent2socket==2) { } else if (sent2socket == 2) {
metaXML(fd_circ,2); /// 0 - new (send headers), 1 - continue, 2 - finish metaXML(fd_circ, 2); /// 0 - new (send headers), 1 - continue, 2 - finish
} }
fflush(stdout); // probably it is not needed anymore, just in case fflush(stdout); // probably it is not needed anymore, just in case
...@@ -1219,17 +1237,20 @@ void listener_loop(int port) ...@@ -1219,17 +1237,20 @@ void listener_loop(int port)
/*! set port, start listening/answering HTTP requests */ /*! set port, start listening/answering HTTP requests */
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
const char usage[]= "Usage:\n%s -p <port_number>\n" \ const char usage[] = "Usage:\n%s -p <port_number>\n" \
"Start image server, bind it to port <port_number>\n"; "Start image server, bind it to port <port_number>\n";
int port; int port;
if ((argc < 3) || (strcasecmp(argv[1], "-p"))) { if ((argc < 3) || (strcasecmp(argv[1], "-p"))) {
printf (usage,argv[0]); printf(usage, argv[0]);
printf (url_args); printf(url_args);
return 0; return 0;
} }
port=strtol(argv[2], NULL, 10); port = strtol(argv[2], NULL, 10);
if (!port) {printf ("Invalid port number %d\n", port); return -1;} if (!port) {
printf("Invalid port number %d\n", port); return -1;
}
signal(SIGCHLD, SIG_IGN); // no zombies, please! signal(SIGCHLD, SIG_IGN); // no zombies, please!
if (fork() == 0) { // child if (fork() == 0) { // child
listener_loop(port); listener_loop(port);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment