Commit 6190b834 authored by Andrey Filippov's avatar Andrey Filippov

implemented ssd raw data sending

parent 7b0fd0dd
......@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _LARGEFILE64_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -23,6 +23,7 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
......@@ -66,6 +67,23 @@
#define GLOBALPARS_SNGL(x) (globalPars[(x)-FRAMEPAR_GLOBALS]) ///< should work in drivers and applications, First 32 parameter values are not erased with initGlobalPars
#endif
int cumulHistImage ( // returns number of pixels
uint16_t * src,
int * offs,
int len,
int width,
int height,
int telem,
int bin_shift,
int hist_size,
int hist_min,
int * hist16, // if null, will only calculate *sum_val, *mn and *mx
long long* sum_val,
int * mn,
int * mx
);
/**
* @struct file_set
* This structure holds a set of file names and file descriptors corresponding to
......@@ -110,6 +128,8 @@ struct file_set {
int sensor_port;
int timestamp_name;
int base_chn;
char *ssd_name;
int ssd_fd; // SSD raw disk file descriptor
// data to convert TIFF to 8-bit uncompressed bmp for quick preview
// int tiff_mn;
// int tiff_mx;
......@@ -120,7 +140,7 @@ struct file_set {
};
static struct file_set files[SENSOR_PORTS];
static char ssd_name[256];
unsigned long * ccam_dma_buf;
char trailer[TRAILER_SIZE] = { 0xff, 0xd9 };
const char *circbuf_fnames[] = {
......@@ -217,7 +237,9 @@ const char url_args[] = "This server supports sequence of commands entered in th
"tiff_auto=[value] may preceed tiff_convert and calculate and set min/max for conversion using tiff_stat internally.\n"
" Value is a 2-digit decimal, low digit applies to cut from the lower (cold) values, high digit - to cut from the high (hot) ones:\n"
" Value 0 - use asolute min/max values, 1 - 0.1%% to 100.0%%, 10 - 0%% to 99.9%%, 22 - from 0.5%% to 99.5%%, 03 - from 1%% to 100%%,\n"
" Value 24 - from 5%% to 99.5%%, 55 - 10%% to 90%%.\n";
" Value 24 - from 5%% to 99.5%%, 55 - 10%% to 90%%.\n"
"read raw SSD data (device provided in command line, such as 'imgsrv -p 2323 -s /dev/sda2')"
"ssdO...O:C...C - send raw SSD data at byte offset O...O, count C...C bytes";
// path to file containing serial number
static const char path_to_serial[] = "/sys/devices/soc0/elphel393-init/serial";
......@@ -249,11 +271,11 @@ unsigned long getCurrentFrameNumberCompressor( struct file_set *fset);
* @param[in] serial pointer to buffer
* @return 0 if data was extracted successfully and negative error code otherwise
*/
int readCameraSerialNumberFromSysFS(char *path,char *serial){
int readCameraSerialNumberFromSysFS(const char *path, const char *serial){
int fd;
fd = open(path,O_RDONLY);
if (fd<0) return -1;
read(fd,serial,strlen(serial));
read(fd,(char *) serial,strlen(serial));
close(fd);
return 0;
}
......@@ -336,7 +358,7 @@ int printExifXML(int exif_page, struct file_set *fset)
// fset->exif_dev_fd = fd_exif;
exif_page_start = lseek(fset->exif_dev_fd, exif_page, SEEK_END); // select specified Exif page
printf("<debugExifPage>\"%d (0x%x)\"</debugExifPage>\n", exif_page,exif_page);
printf("<debugExifPageStart>\"0x%08x\"</debugExifPageStart>\n", exif_page_start);
printf("<debugExifPageStart>\"0x%08lx\"</debugExifPageStart>\n", exif_page_start);
if (exif_page_start < 0) {
printf("<error>\"Exif page (%d) is out of range\"</error>\n", exif_page);
fprintf(stderr, "%s:%d:%s: Exif page (%d) is out of range\n", __FILE__, __LINE__, __FUNCTION__, exif_page);
......@@ -345,7 +367,7 @@ int printExifXML(int exif_page, struct file_set *fset)
return -1; // Error opening Exif
}
// Camera Serial Number
readCameraSerialNumberFromSysFS(&path_to_serial,CameraSerialNumber);
readCameraSerialNumberFromSysFS((const char *) (&path_to_serial),CameraSerialNumber);
printf("<CameraSerialNumber>\"%.2s:%.2s:%.2s:%.2s:%.2s:%.2s\"</CameraSerialNumber>\n",
&CameraSerialNumber[0],
&CameraSerialNumber[2],
......@@ -681,7 +703,7 @@ int metaXML(struct file_set *fset, int mode)
"<signffff> 0x%x </signffff>\n" \
"<currentSensorFrame>%d</currentSensorFrame>\n" \
"<latestCompressedFrame>%d</latestCompressedFrame>\n"\
"<timestampHex> %08x %08x</timestampHex>\n" \
"<timestampHex> %08lx %08lx</timestampHex>\n" \
"<currentSensorFrameHex>0x%08x</currentSensorFrameHex>\n" \
"<latestCompressedFrameHex>0x%08x</latestCompressedFrameHex>\n"
......@@ -740,7 +762,7 @@ unsigned long getCurrentFrameNumberSensor(struct file_set *fset)
return 0;
}
frame_number = lseek(fset->framepars_dev_fd, 0, SEEK_CUR );
fprintf(stderr, "%s:%d:%s: frame_number= %d\n", __FILE__, __LINE__, __FUNCTION__, frame_number);
fprintf(stderr, "%s:%d:%s: frame_number= %ld\n", __FILE__, __LINE__, __FUNCTION__, frame_number);
return frame_number;
}
......@@ -756,7 +778,7 @@ unsigned long getCurrentFrameNumberCompressor(struct file_set *fset)
return 0;
}
frame_number = lseek(fset->circbuf_fd, LSEEK_CIRC_GETFRAME, SEEK_END );
fprintf(stderr, "%s:%d:%s: frame_number= %d\n", __FILE__, __LINE__, __FUNCTION__, frame_number);
fprintf(stderr, "%s:%d:%s: frame_number= %ld\n", __FILE__, __LINE__, __FUNCTION__, frame_number);
return frame_number;
}
......@@ -816,8 +838,9 @@ int framePointersXML(struct file_set *fset)
#endif
// int fd_circ = fset->circbuf_fd;
// fprintf(stderr, "%s:%d:%s: Starting\n", __FILE__, __LINE__, __FUNCTION__);
if (fset->framepars_dev_fd <0)
if (fset->framepars_dev_fd <0) {
fset->framepars_dev_fd = open(fset->framepars_dev_name, O_RDWR);
}
if (fset->framepars_dev_fd < 0) { // check control OK
printf("Error opening %s\n", fset->framepars_dev_name);
fprintf(stderr, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, fset->framepars_dev_name);
......@@ -948,7 +971,7 @@ int TiffStats(struct file_set * fset,
int buff_size;
int jpeg_len; // bytes
int jpeg_start; // bytes
int l, i, j;
int l, i; // , j;
int color_mode;
int timestamp_start;
int width;
......@@ -962,7 +985,7 @@ int TiffStats(struct file_set * fset,
char *out_str; // 1024
char *out_strp;
char perc_name[64];
// char perc_name[64];
int out_size = 4096; // 15 percentiles - 827, should be sufficient to fit XML
// const float percentiles[] = {0.1,1.0,10,50.0,90.0,99.0,99.9};
......@@ -1233,9 +1256,9 @@ int frameNumbersXML(struct file_set *fset)
{
// very rarely exceeds 512
char s[528]; // 512 // 341;// VERIFY size!)
int p; //, wp, rp;
int nf = 0;
int nfl = 0;
// int p; //, wp, rp;
// int nf = 0;
// int nfl = 0;
int frame_number, compressed_frame_number;
int frame16, sensor_state, compressor_state;
char *cp_sensor_state, *cp_compressor_state;
......@@ -1246,8 +1269,9 @@ int frameNumbersXML(struct file_set *fset)
// int fd_circ = fset->circbuf_fd;
// fprintf(stderr, "%s:%d:%s: Starting\n", __FILE__, __LINE__, __FUNCTION__);
if (fset->framepars_dev_fd <0)
if (fset->framepars_dev_fd <0) {
fset->framepars_dev_fd = open(fset->framepars_dev_name, O_RDWR);
}
if (fset->framepars_dev_fd < 0) { // check control OK
printf("Error opening %s\n", fset->framepars_dev_name);
fprintf(stderr, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, fset->framepars_dev_name);
......@@ -1585,9 +1609,10 @@ uint8_t * convertImage (
int width,
int height,
int telem){
uint16_t pix16;
/// uint16_t pix16;
int ipix;
uint8_t * pix8;
/// uint8_t * pix8;
uint8_t pix8;
int iscale;
int start_pix = 0; // index in src to start copying
int end_pix = len; // index in src to end copying
......@@ -1971,10 +1996,10 @@ int sendImage(struct file_set *fset,
D(fprintf(stderr, "MIME = '%s', extension = '%s',bufferImageData=%df\n",mime_type, extension,bufferImageData));
printf("Content-Type: image/%s\r\n", mime_type);
if (saveImage) {
printf("Content-Disposition: attachment; filename=\"%s%ld_%06d_%d.%s\"\r\n", // does not open, asks for filename to save
printf("Content-Disposition: attachment; filename=\"%s%ld_%06ld_%d.%s\"\r\n", // does not open, asks for filename to save
fset->timestamp_name?"":"elphelimg_", frame_params.timestamp_sec, frame_params.timestamp_usec, fset->sensor_port + fset->base_chn, extension);
} else {
printf("Content-Disposition: inline; filename=\"%s%ld_%06d_%d.%s\"\r\n", // opens in browser, asks to save on right-click
printf("Content-Disposition: inline; filename=\"%s%ld_%06ld_%d.%s\"\r\n", // opens in browser, asks to save on right-click
fset->timestamp_name?"":"elphelimg_", frame_params.timestamp_sec, frame_params.timestamp_usec, fset->sensor_port + fset->base_chn, extension);
}
// bufferImageData - always with tiff_convert
......@@ -2127,13 +2152,13 @@ void listener_loop(struct file_set *fset)
int tiff_bin_shift = 3; // histogram bin size is 1<<3 == 8
int tiff_bin = 1;
int tiff_auto = -1;
long long ssd_offs_byte, ssd_count_bytes, ssd_sent_bytes; //, ssd_set_byte;
// imgsrv -p 2323 -s /dev/sda2
// int bin_shift, // binsize = 1 << bin_shift
int tiff_hist_size; // size of the histogram = ( 1 << size_shift)
int tiff_hist_min; // subtract from value before binning
memset((char*)&sock, 0, sizeof(sock));
sock.sin_port = htons(fset->port_num);
sock.sin_family = AF_INET;
......@@ -2180,6 +2205,81 @@ void listener_loop(struct file_set *fset)
fflush(stdout);
_exit(0);
}
// Send SSD raw data
if (strncmp(cp, "ssd", 3) == 0) {
cp+=3;
// long long ssd_start_byte, ssd_len_bytes;
// long long strtoll(const char *nptr, char **endptr, int base);
ssd_offs_byte = strtoll(cp, &cp1, 10);
if (strncmp(cp1, ":", 1)){
fprintf(stderr, "Separator ':' expected between start byte and length, got %s (%s)\n", cp1, cp);
out1x1gif();
}
cp1++;
ssd_count_bytes = strtoll(cp1, &cp2, 10);
if ((ssd_offs_byte < 0) || (ssd_count_bytes <= 0)){
fprintf(stderr, "Non-negative start (byte) and positive length (bytes) are expected, got %lld, %lld (%s)\n", \
ssd_offs_byte, ssd_count_bytes, cp);
out1x1gif();
fflush(stdout);
_exit(0);
}
fprintf(stderr, "SSD name='%s'\n", fset->ssd_name);
fset->ssd_fd = open64(fset->ssd_name, O_RDONLY);
if (fset->ssd_fd < 0) { // check control OK
fprintf(stderr, "Error opening %s\n", fset->ssd_name);
out1x1gif();
fflush(stdout);
_exit(0);
}
printf("HTTP/1.0 200 OK\r\n");
printf("Server: Elphel Imgsrv\r\n");
printf("Access-Control-Allow-Origin: *\r\n");
printf("Access-Control-Expose-Headers: Content-Disposition\r\n");
printf("Content-Length: %lld\r\n",ssd_count_bytes);
printf("Content-Type: text/plain\r\n");
printf("\r\n");
// ssd_sent_bytes
// out1x1gif();
//STDOUT_FILENO
//ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
fprintf(stderr, "Sending %lld bytes, offs=%lld\n", ssd_count_bytes, ssd_offs_byte);
#if 0
ssd_offs_byte=lseek64(fset->ssd_fd, ssd_offs_byte, SEEK_SET);
fprintf(stderr, "lseek64()-> %lld, STDOUT_FILENO=%d, errno=%d\n", ssd_offs_byte, STDOUT_FILENO, errno);
while (ssd_count_bytes > 0) {
ssd_sent_bytes = sendfile64(STDOUT_FILENO, fset->ssd_fd, NULL, ssd_count_bytes);
if (ssd_sent_bytes <= 0){
fprintf(stderr, "sendfile64() failed: sent %lld bytes (wanted %lld), offs=%lld, errno=%d\n", \
ssd_sent_bytes, ssd_count_bytes, ssd_offs_byte, errno);
break;
}
if (ssd_sent_bytes < ssd_count_bytes) {
fprintf(stderr, "sendfile64() did not send all: sent %lld bytes (wanted %lld), offs=%lld\n", ssd_sent_bytes, ssd_count_bytes, ssd_offs_byte);
}
ssd_count_bytes -= ssd_sent_bytes;
}
#else
while (ssd_count_bytes > 0) {
ssd_sent_bytes = sendfile64(STDOUT_FILENO, fset->ssd_fd, &ssd_offs_byte, ssd_count_bytes);
if (ssd_sent_bytes <= 0){
fprintf(stderr, "sendfile64() failed: sent %lld bytes (wanted %lld), offs=%lld, errno=%d\n", \
ssd_sent_bytes, ssd_count_bytes, ssd_offs_byte, errno);
break;
}
if (ssd_sent_bytes < ssd_count_bytes) {
fprintf(stderr, "sendfile64() did not send all: sent %lld bytes (wanted %lld), offs=%lld\n", ssd_sent_bytes, ssd_count_bytes, ssd_offs_byte);
}
ssd_count_bytes -= ssd_sent_bytes;
}
#endif
fprintf(stderr, "Sent %lld bytes (wanted %lld), offs=%lld\n", ssd_sent_bytes, ssd_count_bytes, ssd_offs_byte);
close (fset->ssd_fd);
fset->ssd_fd = -1;
fflush(stdout);
_exit(0);
}
// Process 'frame' and 'wframe' commands - they do not need circbuf (now they do!)
if ((strncmp(cp, "frame", 5) == 0) || (strncmp(cp, "wframe", 6) == 0) || (strncmp(cp, "sframe", 6) == 0) ) {
if (strncmp(cp, "wframe", 6) == 0) waitFrameSync(fset);
......@@ -2465,12 +2565,15 @@ void listener_loop(struct file_set *fset)
/**
* @brief Parse command line options
* imgsrv -p 2323
* imgsrv -p 2323 -s /dev/sda2
* @param[in] argc the number of command line arguments; passed from main()
* @param[in] argv array of pointers to command line arguments; passed from main()
* @param[in,out] fset array of #file_set structures; this function will set port
* numbers in the structures
* @param[in] fset_sz the number of elements in @e fset
* @return 0 if command line options were successfully processed and
* Add -s /dev/sda for the ssd partition to open
* -1 in case of an error
*/
int parse_cmd_line(int argc, const char *argv[], struct file_set *fset, int fset_sz)
......@@ -2482,7 +2585,8 @@ int parse_cmd_line(int argc, const char *argv[], struct file_set *fset, int fset
printf(app_args, argv[0]);
printf(url_args);
return -1;
} else if (argc == 3) {
// } else if (argc == 3) { // Old version pre 2023-08-01
} else if (argc >= 3) {
port = strtol(argv[2], NULL, 10);
if (!port) {
printf("Invalid port number %d\n", port);
......@@ -2490,8 +2594,12 @@ int parse_cmd_line(int argc, const char *argv[], struct file_set *fset, int fset
}
for (int i = 0; i < fset_sz; i++) {
fset[i].port_num = port + i;
fset[i].ssd_name = NULL;
fset[i].ssd_fd = -1;
}
} else if (argc > 3) {
// } else if (argc > 3) {
if (argc > 3) {
/* Old version pre 2023-08-01
i = 0;
// start parsing from first port number which is second positional parameter in cmd line
while ((i < fset_sz) && (i + 2 < argc)) {
......@@ -2506,6 +2614,23 @@ int parse_cmd_line(int argc, const char *argv[], struct file_set *fset, int fset
if (i < fset_sz - 1) {
printf("Wrong ports quantity\n");
return -1;
}
*/
if (argc != 5) {
printf("Wrong number of arguments: %d\n", argc);
return -1;
}
if (strcasecmp(argv[3], "-s")){ // ssd partition - whole disk?
printf("Expecting '-s' for argv[3], got '%s'\n", argv[3]);
return -1;
}
strcpy(ssd_name, argv[4]);
// printf("Got ssd name= '%s'\n", argv[4]);
// printf("Got ssd name= '%s'\n", ssd_name);
//ssd_name
for (int i = 0; i < fset_sz; i++) {
fset[i].ssd_name = ssd_name;
}
}
}
......
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