Commit 6393936e authored by Mikhail Karpenko's avatar Mikhail Karpenko

Add PageNumber field to Exif and process it

This field corresponds to sensor port number
parent 11711b85
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
</tool> </tool>
<tool id="org.eclipse.cdt.build.core.settings.holder.176385540" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder"> <tool id="org.eclipse.cdt.build.core.settings.holder.176385540" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1931881995" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath"> <option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1931881995" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/linux-elphel/sysroots/elphel393/usr/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/linux-elphel/linux/source/include/elphel}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/linux-elphel/linux/source/include/elphel}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/linux-elphel/sysroots/elphel393/usr/include}&quot;"/>
</option> </option>
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1408747788" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/> <inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1408747788" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
</tool> </tool>
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
<HostComputer tag="0x013c" format="ASCII" function="SERIAL"/> <HostComputer tag="0x013c" format="ASCII" function="SERIAL"/>
<FrameNumber tag="0x83bb" format="LONG" count="1" seq="25" dlen="4"/> <FrameNumber tag="0x83bb" format="LONG" count="1" seq="25" dlen="4"/>
<Orientation tag="0x112" format="SHORT" count="1" seq="27" dlen="2"/> <Orientation tag="0x112" format="SHORT" count="1" seq="27" dlen="2"/>
<PageNumber tag="0x129" format="SHORT" count="1" seq="28" dlen="2"/>
<ExifTag tag="0x8769" format="LONG" function="EXIFTAG"/> <ExifTag tag="0x8769" format="LONG" function="EXIFTAG"/>
<GPSTag tag="0x08825" format="LONG" function="GPSTAG"/> <GPSTag tag="0x08825" format="LONG" function="GPSTAG"/>
</Image> </Image>
......
...@@ -173,58 +173,53 @@ ...@@ -173,58 +173,53 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#if ELPHEL_DEBUG #if ELPHEL_DEBUG
#define ELPHEL_DEBUG_THIS 1 #define ELPHEL_DEBUG_THIS 1
#else #else
#define ELPHEL_DEBUG_THIS 0 #define ELPHEL_DEBUG_THIS 0
#endif #endif
#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
//#define USEHTTP10(x)
#define USEHTTP10(x) x
// HEADER_SIZE is defined to be larger than actual header (later - with EXIF) to use compile-time buffer // HEADER_SIZE is defined to be larger than actual header (later - with EXIF) to use compile-time buffer
//#define JPEG_HEADER_SIZE 0x26f // will not change
#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 /** @brief the length of MakerNote buffer in @e long */
//#define GLOBALPARS(x) globalPars[(x)-FRAMEPAR_GLOBALS] // should work in drivers and application #define MAKERNOTE_LEN 16
#define IMAGE_CHN_NUM 4
struct file_set { struct file_set {
unsigned short port_num; unsigned short port_num;
unsigned char sensor_num;
const char *cirbuf_fn; const char *cirbuf_fn;
int circbuf_fd; int circbuf_fd;
const char *jphead_fn; const char *jphead_fn;
int jphead_fd; int jphead_fd;
const char *exif_dev_name;
int exif_dev_fd;
const char *exifmeta_dev_name;
int exifmeta_dev_fd;
}; };
static struct file_set files[IMAGE_CHN_NUM]; static struct file_set files[SENSOR_PORTS];
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 *circbuf_fnames[] = { const char *circbuf_fnames[] = {
"/dev/circbuf0", "/dev/circbuf0",
"/dev/circbuf1", "/dev/circbuf1",
"/dev/circbuf2", "/dev/circbuf2",
"/dev/circbuf3" "/dev/circbuf3"
}; };
const char *jhead_fnames[] = { const char *jhead_fnames[] = {
"/dev/jpeghead0", "/dev/jpeghead0",
"/dev/jpeghead1", "/dev/jpeghead1",
"/dev/jpeghead2", "/dev/jpeghead2",
"/dev/jpeghead3", "/dev/jpeghead3",
}; };
static const char *exif_dev_names[SENSOR_PORTS] = { EXIF_DEV_NAMES };
static const char *exifmeta_dev_names[SENSOR_PORTS] = { EXIFMETA_DEV_NAMES };
const char app_args[] = "Usage:\n%s -p <port_number_1> [<port_number_2> <port_number_3> <port_number_4>]\n" \ const char app_args[] = "Usage:\n%s -p <port_number_1> [<port_number_2> <port_number_3> <port_number_4>]\n" \
"Start image server, bind it to ports <port_number_1> <port_number_2> <port_number_3> <port_number_4>\n" \ "Start image server, bind it to ports <port_number_1> <port_number_2> <port_number_3> <port_number_4>\n" \
...@@ -262,22 +257,20 @@ const char url_args[] = "This server supports sequence of commands entered in th ...@@ -262,22 +257,20 @@ const char url_args[] = "This server supports sequence of commands entered in th
" In this special mode autoexposure/white balance will not work in most cases,\n" " In this special mode autoexposure/white balance will not work in most cases,\n"
" camera should be set in triggered mode (TRIG=4), internal (TRIG_CONDITION=0).\n" " camera should be set in triggered mode (TRIG=4), internal (TRIG_CONDITION=0).\n"
" No effect on free-running or \"slave\" cameras, so it is OK to send it to all."; " No effect on free-running or \"slave\" cameras, so it is OK to send it to all.";
//int sendImage(int bufferImageData, int fd_circ, int use_Exif);
//int sendImage(int bufferImageData, int fd_circ, int use_Exif, int saveImage); int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int saveImage);
void sendBuffer(void * buffer, int len); void sendBuffer(void * buffer, int len);
//void listener_loop(int port, const char *circbuf_fname); void listener_loop(struct file_set *fset);
void errorMsgXML(char * msg); void errorMsgXML(char * msg);
int framePointersXML(int fd_circ); int framePointersXML(struct file_set *fset);
int metaXML(int fd_circ, int mode); /// mode: 0 - new (send headers), 1 - continue, 2 - finish int metaXML(struct file_set *fset, int mode); /// mode: 0 - new (send headers), 1 - continue, 2 - finish
int printExifXML(int exif_page); int printExifXML(int exif_page, struct file_set *fset);
int out1x1gif(void); int out1x1gif(void);
void waitFrameSync(); 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, struct file_set *fset)
{ {
int indx; int indx;
long numfields = 0; long numfields = 0;
...@@ -285,8 +278,8 @@ int printExifXML(int exif_page) ...@@ -285,8 +278,8 @@ int printExifXML(int exif_page)
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);
...@@ -317,6 +310,7 @@ int printExifXML(int exif_page) ...@@ -317,6 +310,7 @@ int printExifXML(int exif_page)
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;
case Exif_Image_PageNumber: indx = Exif_Image_PageNumber_Index; break;
default: indx = -1; default: indx = -1;
} }
if (indx >= 0) { if (indx >= 0) {
...@@ -325,28 +319,29 @@ int printExifXML(int exif_page) ...@@ -325,28 +319,29 @@ int printExifXML(int exif_page)
} }
} }
close(fd_exifdir); close(fd_exifdir);
/// Create XML files iteslf
/// Create XML files itself
long rational3[6]; long rational3[6];
long makerNote[14]; long makerNote[MAKERNOTE_LEN];
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(fset->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", fset->exif_dev_name);
return -3; return -3;
} }
fset->exif_dev_fd = fd_exif;
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,
...@@ -354,7 +349,7 @@ int printExifXML(int exif_page) ...@@ -354,7 +349,7 @@ int printExifXML(int exif_page)
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,
...@@ -364,7 +359,7 @@ int printExifXML(int exif_page) ...@@ -364,7 +359,7 @@ int printExifXML(int exif_page)
printf("<FrameNumber>\"%s\"</FrameNumber>\n", val); printf("<FrameNumber>\"%s\"</FrameNumber>\n", val);
} }
///Exif_Image_Orientation_Index 0x15 ///Exif_Image_Orientation_Index 0x14
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,
...@@ -375,7 +370,18 @@ int printExifXML(int exif_page) ...@@ -375,7 +370,18 @@ int printExifXML(int exif_page)
printf("<Orientation>\"%s\"</Orientation>\n", val); printf("<Orientation>\"%s\"</Orientation>\n", val);
} }
///DateTimeOriginal (with subseconds) // Exif_Image_PageNumber
if (exif_dir[Exif_Image_PageNumber_Index].ltag == Exif_Image_PageNumber) { // Exif_Image_Orientation_Index is present in template
lseek(fd_exif,
exif_page_start + exif_dir[Exif_Image_PageNumber_Index].dst,
SEEK_SET);
rational3[0] = 0;
read(fd_exif, rational3, 2);
sprintf(val, "%u", __cpu_to_be16(rational3[0]));
printf("<SensorNumber>\"%s\"</SensorNumber>\n", val);
}
///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,
...@@ -392,7 +398,7 @@ int printExifXML(int exif_page) ...@@ -392,7 +398,7 @@ int printExifXML(int exif_page)
} }
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,
...@@ -403,7 +409,7 @@ int printExifXML(int exif_page) ...@@ -403,7 +409,7 @@ int printExifXML(int exif_page)
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,
...@@ -430,8 +436,7 @@ int printExifXML(int exif_page) ...@@ -430,8 +436,7 @@ int printExifXML(int exif_page)
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,
...@@ -440,7 +445,8 @@ int printExifXML(int exif_page) ...@@ -440,7 +445,8 @@ int printExifXML(int exif_page)
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,
...@@ -460,8 +466,8 @@ int printExifXML(int exif_page) ...@@ -460,8 +466,8 @@ int printExifXML(int exif_page)
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,
...@@ -478,7 +484,7 @@ int printExifXML(int exif_page) ...@@ -478,7 +484,7 @@ int printExifXML(int exif_page)
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,
...@@ -495,7 +501,7 @@ int printExifXML(int exif_page) ...@@ -495,7 +501,7 @@ int printExifXML(int exif_page)
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,
...@@ -513,7 +519,7 @@ int printExifXML(int exif_page) ...@@ -513,7 +519,7 @@ int printExifXML(int exif_page)
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,
...@@ -523,8 +529,8 @@ int printExifXML(int exif_page) ...@@ -523,8 +529,8 @@ int printExifXML(int exif_page)
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,
...@@ -543,7 +549,7 @@ int printExifXML(int exif_page) ...@@ -543,7 +549,7 @@ int printExifXML(int exif_page)
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,
...@@ -565,13 +571,12 @@ int printExifXML(int exif_page) ...@@ -565,13 +571,12 @@ int printExifXML(int exif_page)
return 0; return 0;
} }
int metaXML(struct file_set *fset, 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;
int fd_circ = fset->circbuf_fd;
if (mode == 2) { /// just close the xml file if (mode == 2) { /// just close the xml file
printf("</meta>\n"); printf("</meta>\n");
...@@ -593,18 +598,18 @@ int metaXML(int fd_circ, int mode) /// mode: 0 - new (send headers), 1 - con ...@@ -593,18 +598,18 @@ int metaXML(int fd_circ, int mode) /// mode: 0 - new (send headers), 1 - con
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
if (timestamp_start >= buff_size) timestamp_start-=buff_size; if (timestamp_start >= buff_size) timestamp_start-=buff_size;
memcpy (&(frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8); memcpy (&(frame_params.timestamp_sec), (unsigned long * ) &ccam_dma_buf[timestamp_start>>2],8);
///TODO: Parse Exif data if available and add here ///TODO: Parse Exif data if available and add here
printf ("<frame>\n" \ printf ("<frame>\n" \
"<start> 0x%x </start>\n" \ "<start> 0x%x </start>\n" \
"<hash32_r> 0x%x </hash32_r>\n" \ "<hash32_r> 0x%x </hash32_r>\n" \
...@@ -634,17 +639,17 @@ int metaXML(int fd_circ, int mode) /// mode: 0 - new (send headers), 1 - con ...@@ -634,17 +639,17 @@ int metaXML(int fd_circ, int mode) /// mode: 0 - new (send headers), 1 - con
, frame_params.timestamp_usec , frame_params.timestamp_usec
, (int) frame_params.signffff , (int) frame_params.signffff
); );
///28-31 unsigned long timestamp_sec ; //! number of seconds since 1970 till the start of the frame exposure ///28-31 unsigned long timestamp_sec ; //! number of seconds since 1970 till the start of the frame exposure
///28-31 unsigned long frame_length ; //! JPEG frame length in circular buffer, bytes ///28-31 unsigned long frame_length ; //! JPEG frame length in circular buffer, bytes
/// }; /// };
///32-35 unsigned long timestamp_usec; //! number of microseconds to add ///32-35 unsigned long timestamp_usec; //! number of microseconds to add
if (frame_params.signffff !=0xffff) { if (frame_params.signffff !=0xffff) {
printf("<error>\"wrong signature (should be 0xffff)\"</error>\n"); printf("<error>\"wrong signature (should be 0xffff)\"</error>\n");
} else { } else {
///Put Exif data here ///Put Exif data here
printf ("<Exif>\n"); printf ("<Exif>\n");
printExifXML(frame_params.meta_index); printExifXML(frame_params.meta_index, fset);
printf ("</Exif>\n"); printf ("</Exif>\n");
} }
printf ("</frame>\n"); printf ("</frame>\n");
...@@ -670,7 +675,7 @@ void waitFrameSync() ...@@ -670,7 +675,7 @@ void waitFrameSync()
close(fd_fparmsall); close(fd_fparmsall);
} }
int framePointersXML(int fd_circ) int framePointersXML(struct file_set *fset)
{ {
const char ctlFileName[] = "/dev/frameparsall"; const char ctlFileName[] = "/dev/frameparsall";
int fd_fparmsall; int fd_fparmsall;
...@@ -683,10 +688,10 @@ int framePointersXML(int fd_circ) ...@@ -683,10 +688,10 @@ int framePointersXML(int fd_circ)
int frame8, frame_number, sensor_state, compressor_state; int frame8, frame_number, sensor_state, compressor_state;
char *cp_sensor_state, *cp_compressor_state; char *cp_sensor_state, *cp_compressor_state;
struct framepars_all_t *frameParsAll; struct framepars_all_t **frameParsAll;
struct framepars_t *framePars; struct framepars_t *aframePars[SENSOR_PORTS];
unsigned long *globalPars; unsigned long *aglobalPars[SENSOR_PORTS];
int fd_circ = fset->circbuf_fd;
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
...@@ -695,8 +700,8 @@ int framePointersXML(int fd_circ) ...@@ -695,8 +700,8 @@ int framePointersXML(int fd_circ)
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");
...@@ -705,15 +710,16 @@ int framePointersXML(int fd_circ) ...@@ -705,15 +710,16 @@ int framePointersXML(int fd_circ)
fd_fparmsall = -1; fd_fparmsall = -1;
return -1; return -1;
} }
framePars = frameParsAll->framePars; for (int j = 0; j < SENSOR_PORTS; j++) {
globalPars = frameParsAll->globalPars; aframePars[j] = frameParsAll[j]->framePars;
aglobalPars[j] = frameParsAll[j]->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); sensor_state = aframePars[fset->port_num][frame8].pars[P_SENSOR_RUN];
sensor_state = framePars[frame8].pars[P_SENSOR_RUN]; compressor_state = aframePars[fset->port_num][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) ?
...@@ -734,8 +740,8 @@ int framePointersXML(int fd_circ) ...@@ -734,8 +740,8 @@ int framePointersXML(int fd_circ)
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(fset->port_num, G_FREECIRCBUF);
frame_size = GLOBALPARS(G_FRAME_SIZE); frame_size = GLOBALPARS(fset->port_num, 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
...@@ -775,12 +781,13 @@ int framePointersXML(int fd_circ) ...@@ -775,12 +781,13 @@ int framePointersXML(int fd_circ)
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?
munmap(frameParsAll, sizeof(struct framepars_all_t));
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);
int out1x1gif(void) int out1x1gif(void)
{ {
char s[] = "HTTP/1.0 200 OK\r\n" \ char s[] = "HTTP/1.0 200 OK\r\n" \
...@@ -798,7 +805,7 @@ int out1x1gif(void) ...@@ -798,7 +805,7 @@ int out1x1gif(void)
void errorMsgXML(char * msg) void errorMsgXML(char * msg)
{ {
char s[1024]; // was 701 acrtually char s[1024];
sprintf(s, "<?xml version=\"1.0\"?>\n" \ sprintf(s, "<?xml version=\"1.0\"?>\n" \
"<frame_params>\n" \ "<frame_params>\n" \
...@@ -821,15 +828,11 @@ void errorMsgXML(char * msg) ...@@ -821,15 +828,11 @@ void errorMsgXML(char * msg)
int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int saveImage) int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int saveImage)
{ {
//const char HeadFileName[] = "/dev/jpeghead0";
const char ExifFileName[] = "/dev/exif_exif";
int exifDataSize = 0; int exifDataSize = 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
int buff_size; int buff_size;
int jpeg_len; //bytes int jpeg_len; // bytes
int jpeg_start; // bytes int jpeg_start; // bytes
int fd_head; int fd_head;
int fd_exif; int fd_exif;
...@@ -841,7 +844,6 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -841,7 +844,6 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
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)
jpeg_start = lseek(fset->circbuf_fd, 0, SEEK_CUR); //get the current read pointer jpeg_start = lseek(fset->circbuf_fd, 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(fset->jphead_fn, O_RDWR); fd_head = open(fset->jphead_fn, O_RDWR);
...@@ -850,21 +852,20 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -850,21 +852,20 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
return -1; return -1;
} }
fset->jphead_fd = fd_head; fset->jphead_fd = fd_head;
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
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(fset->circbuf_fd, 0, SEEK_END); buff_size = lseek(fset->circbuf_fd, 0, SEEK_END);
/*! restore file poinetr after lseek-ing the end */ /*! restore file poinetr after lseek-ing the end */
lseek(fset->circbuf_fd, jpeg_start, SEEK_SET); lseek(fset->circbuf_fd, jpeg_start, SEEK_SET);
D(fprintf(stderr, "position (longs) = 0x%x\n", (int)lseek(fset->circbuf_fd, 0, SEEK_CUR))); D(fprintf(stderr, "position (longs) = 0x%x\n", (int)lseek(fset->circbuf_fd, 0, SEEK_CUR)));
/*! now let's try mmap itself */ /*! now let's try mmap itself */
/// exifIndexPointer=jpeg_start-8;
frameParamPointer = jpeg_start - sizeof(struct interframe_params_t) + 4; frameParamPointer = jpeg_start - sizeof(struct interframe_params_t) + 4;
if (frameParamPointer < 0) if (frameParamPointer < 0)
frameParamPointer += buff_size; frameParamPointer += buff_size;
...@@ -875,17 +876,19 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -875,17 +876,19 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
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);
#ifdef ELPHEL_DEBUG_THIS
lseek(fset->circbuf_fd, LSEEK_CIRC_STOP_COMPRESSOR, SEEK_END); lseek(fset->circbuf_fd, LSEEK_CIRC_STOP_COMPRESSOR, SEEK_END);
#endif
close(fd_head); close(fd_head);
return -4; return -4;
} }
if (use_Exif) { if (use_Exif) {
//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(fset->exif_dev_name, 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", fset->exif_dev_name);
close(fd_head); close(fd_head);
return -5; return -5;
} }
...@@ -893,24 +896,24 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -893,24 +896,24 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
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 = 0x%x\n", fprintf(stderr, "jpeg_len = 0x%x, head_size = 0x%x, exifDataSize = 0x%x, jpeg_full_size = 0x%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);
...@@ -926,21 +929,21 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -926,21 +929,21 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
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) {
// case COLORMODE_MONO6: //! monochrome, (4:2:0), // case COLORMODE_MONO6: //! monochrome, (4:2:0),
// 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)
case COLORMODE_JP4DC: //! jp4, 4 blocks, dc -improved case COLORMODE_JP4DC: //! jp4, 4 blocks, dc -improved
case COLORMODE_JP4DIFF: //! jp4, 4 blocks, differential red := (R-G1), blue:=(B-G1), green=G1, green2 (G2-G1). G1 is defined by Bayer shift, any pixel can be used case COLORMODE_JP4DIFF: //! jp4, 4 blocks, differential red := (R-G1), blue:=(B-G1), green=G1, green2 (G2-G1). G1 is defined by Bayer shift, any pixel can be used
...@@ -950,15 +953,15 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -950,15 +953,15 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
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;
// char * extension; // char * extension;
/* /*
#define COLORMODE_MONO6 0 // monochrome, (4:2:0), #define COLORMODE_MONO6 0 // monochrome, (4:2:0),
#define COLORMODE_COLOR 1 // color, 4:2:0, 18x18(old) #define COLORMODE_COLOR 1 // color, 4:2:0, 18x18(old)
#define COLORMODE_JP46 2 // jp4, original (4:2:0) #define COLORMODE_JP46 2 // jp4, original (4:2:0)
...@@ -978,30 +981,12 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -978,30 +981,12 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
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) */
// tell driver to flush CPU caches #ifdef ELPHEL_DEBUG_THIS
const char *fname = "/sys/devices/soc0/elphel393-mem@0/flush_cpu_cache";
char cmd[128] = {0};
int jpeg_end;
int cmd_len;
// int fd_sys = open(fname, O_RDWR);
unsigned long start_time, end_time; unsigned long start_time, end_time;
// if (fd_sys < 0) {
// fprintf(stderr, "unable to open sysfs entry: %s\n", fname);
// } else {
//// jpeg_end = jpeg_start + jpeg_len;
// jpeg_end = jpeg_start + (sizeof(struct interframe_params_t) - 4) * 512;
// if (jpeg_end > buff_size)
// jpeg_end -= buff_size;
// cmd_len = snprintf(cmd, 127, "%u:%d:%d", fset->sensor_num, jpeg_start, jpeg_end);
// if (write(fd_sys, cmd, cmd_len) == -1)
// fprintf(stderr, "failed to write to sysfs\n");
// close(fd_sys);
// }
start_time = lseek(fset->circbuf_fd, LSEEK_CIRC_UTIME, SEEK_END); start_time = lseek(fset->circbuf_fd, LSEEK_CIRC_UTIME, SEEK_END);
#endif
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;
...@@ -1009,9 +994,10 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -1009,9 +994,10 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
} 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);
} }
#ifdef ELPHEL_DEBUG_THIS
end_time = lseek(fset->circbuf_fd, LSEEK_CIRC_UTIME, SEEK_END); end_time = lseek(fset->circbuf_fd, LSEEK_CIRC_UTIME, SEEK_END);
fprintf(stderr, "memcpy time = %lu\n", end_time - start_time); D(fprintf(stderr, "memcpy time = %lu\n", end_time - start_time));
#endif
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");
...@@ -1020,24 +1006,22 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav ...@@ -1020,24 +1006,22 @@ int sendImage(struct file_set *fset, int bufferImageData, int use_Exif, int sav
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;
} }
/*! 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)
{ {
...@@ -1056,13 +1040,9 @@ void sendBuffer(void * buffer, int len) ...@@ -1056,13 +1040,9 @@ void sendBuffer(void * buffer, int len)
} }
} }
void listener_loop(struct file_set *fset) void listener_loop(struct file_set *fset)
{ {
char errormsg[1024]; char errormsg[1024];
//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;
...@@ -1092,22 +1072,22 @@ void listener_loop(struct file_set *fset) ...@@ -1092,22 +1072,22 @@ void listener_loop(struct file_set *fset)
if (fd == -1) continue; if (fd == -1) continue;
signal(SIGCHLD, SIG_IGN); // no zombies, please! signal(SIGCHLD, SIG_IGN); // no zombies, please!
/*! do we need any fork at all if we now serve images to one client at a time? */ /*! do we need any fork at all if we now serve images to one client at a time? */
if (fork() == 0) { if (fork() == 0) {
close(res); close(res);
/*! setup stdin and stdout */ /*! setup stdin and stdout */
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
dup2(fd, 0); dup2(fd, 0);
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';
} }
...@@ -1121,7 +1101,7 @@ void listener_loop(struct file_set *fset) ...@@ -1121,7 +1101,7 @@ void listener_loop(struct file_set *fset)
fflush(stdout); fflush(stdout);
_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");
...@@ -1133,7 +1113,7 @@ void listener_loop(struct file_set *fset) ...@@ -1133,7 +1113,7 @@ void listener_loop(struct file_set *fset)
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(fset->cirbuf_fn, O_RDWR); fd_circ = open(fset->cirbuf_fn, O_RDWR);
if (fd_circ < 0) { // check control OK if (fd_circ < 0) { // check control OK
fprintf(stderr, "Error opening %s\n", fset->cirbuf_fn); fprintf(stderr, "Error opening %s\n", fset->cirbuf_fn);
...@@ -1142,10 +1122,10 @@ void listener_loop(struct file_set *fset) ...@@ -1142,10 +1122,10 @@ void listener_loop(struct file_set *fset)
_exit(0); _exit(0);
} }
fset->circbuf_fd = fd_circ; fset->circbuf_fd = fd_circ;
/*! 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");
...@@ -1156,11 +1136,9 @@ void listener_loop(struct file_set *fset) ...@@ -1156,11 +1136,9 @@ void listener_loop(struct file_set *fset)
} }
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); // if the first character is a digit, it is a file pointer
// fprintf (stderr, "1->%s",cp1);
//!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)) {
...@@ -1189,13 +1167,13 @@ void listener_loop(struct file_set *fset) ...@@ -1189,13 +1167,13 @@ void listener_loop(struct file_set *fset)
} }
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);
...@@ -1213,7 +1191,7 @@ void listener_loop(struct file_set *fset) ...@@ -1213,7 +1191,7 @@ void listener_loop(struct file_set *fset)
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
...@@ -1225,12 +1203,12 @@ void listener_loop(struct file_set *fset) ...@@ -1225,12 +1203,12 @@ void listener_loop(struct file_set *fset)
} }
} 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(fset); //! 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(fset, (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) {
...@@ -1259,18 +1237,18 @@ void listener_loop(struct file_set *fset) ...@@ -1259,18 +1237,18 @@ void listener_loop(struct file_set *fset)
(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) {
...@@ -1282,7 +1260,7 @@ void listener_loop(struct file_set *fset) ...@@ -1282,7 +1260,7 @@ void listener_loop(struct file_set *fset)
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(fset, 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
...@@ -1341,8 +1319,11 @@ void init_file_set(struct file_set *fset, int fset_sz) ...@@ -1341,8 +1319,11 @@ void init_file_set(struct file_set *fset, int fset_sz)
fset[i].circbuf_fd = -1; fset[i].circbuf_fd = -1;
fset[i].jphead_fn = jhead_fnames[i]; fset[i].jphead_fn = jhead_fnames[i];
fset[i].jphead_fd = -1; fset[i].jphead_fd = -1;
fset[i].exif_dev_name = exif_dev_names[i];
fset[i].exif_dev_fd = -1;
fset[i].exifmeta_dev_name = exifmeta_dev_names[i];
fset[i].exifmeta_dev_fd = -1;
fset[i].port_num = 0; fset[i].port_num = 0;
fset[i].sensor_num = i;
} }
} }
...@@ -1351,8 +1332,8 @@ int main(int argc, char *argv[]) ...@@ -1351,8 +1332,8 @@ int main(int argc, char *argv[])
{ {
int res = 0; int res = 0;
init_file_set(files, IMAGE_CHN_NUM); init_file_set(files, SENSOR_PORTS);
res = parse_cmd_line(argc, (const char **)argv, files, IMAGE_CHN_NUM); res = parse_cmd_line(argc, (const char **)argv, files, SENSOR_PORTS);
if (res < 0) if (res < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
...@@ -1363,7 +1344,7 @@ int main(int argc, char *argv[]) ...@@ -1363,7 +1344,7 @@ int main(int argc, char *argv[])
} }
// spawn a process for each port // spawn a process for each port
for (int i = 0; i < IMAGE_CHN_NUM; i++) { for (int i = 0; i < SENSOR_PORTS; i++) {
if (fork() == 0) { if (fork() == 0) {
listener_loop(&files[i]); listener_loop(&files[i]);
_exit(0); // should not get here? _exit(0); // should not get here?
......
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