parent
3171c860a5
commit
5682fcd9b8
@ -0,0 +1,64 @@
|
||||
# .SILENT:
|
||||
|
||||
DEPENDFILE=.depend
|
||||
VERSION=0.1
|
||||
|
||||
PREFIX=/usr/local
|
||||
DATAPREFIX=/var/lib
|
||||
RUNPID=/var/run/miniwebcam.pid
|
||||
ETCPREFIX=/etc
|
||||
DEFAULT_SERVERPORT=20010
|
||||
|
||||
CXX=g++
|
||||
CXXFLAGS= -ggdb -fPIC -Wall -std=c++11 -I/usr/local/include
|
||||
LDFLAGS= -lUDPTCPNetwork -L/usr/local/lib -ljpeg
|
||||
OBJFILES= webserver.o configuration.o main.o video.o convert.o debayer.o
|
||||
|
||||
all: dep miniwebcam
|
||||
|
||||
miniwebcam: dep $(OBJFILES)
|
||||
$(CXX) $(OBJFILES) -o $@ -L./ -I./ $(LDFLAGS)
|
||||
|
||||
install: miniwebcam
|
||||
cp -rf miniwebcam $(PREFIX)/bin
|
||||
|
||||
uninstall:
|
||||
rm -rf $(PREFIX)/bin/miniwebcam
|
||||
|
||||
config:
|
||||
echo "#ifndef _CONFIG_H_" > config.h
|
||||
echo "#define _CONFIG_H_" >> config.h
|
||||
echo "" >> config.h
|
||||
echo "#define VERSION \"$(VERSION)\"" >> config.h
|
||||
echo "" >> config.h
|
||||
echo "#define PREFIX \"$(PREFIX)\"" >> config.h
|
||||
echo "#define RUNPID \"$(RUNPID)\"" >> config.h
|
||||
echo "#define ETCPREFIX \"$(ETCPREFIX)\"" >> config.h
|
||||
echo "" >> config.h
|
||||
echo "#define DEFAULT_SERVERPORT \""$(DEFUALT_SERVERPORT)"\"" >> config.h
|
||||
echo "" >> config.h
|
||||
echo "#endif" >> config.h
|
||||
echo "" >> config.h
|
||||
|
||||
rebuild: clean all
|
||||
|
||||
dep:
|
||||
$(CXX) -MM `ls *.cc` $(CXXFLAGS) > $(DEPENDFILE)
|
||||
|
||||
clean:
|
||||
rm *.s -rf
|
||||
rm *.o -rf
|
||||
rm *.oo -rf
|
||||
rm *~ -rf
|
||||
rm -rf .depend
|
||||
rm -rf *.so
|
||||
rm -rf *.so.*
|
||||
rm -rf miniwebcam
|
||||
rm -rf config.h
|
||||
rm -rf Makefile.rules
|
||||
|
||||
cleanall: clean
|
||||
|
||||
source: cleanall
|
||||
|
||||
-include $(DEPENDFILE)
|
||||
@ -0,0 +1,423 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef BUILD_WINDOWS
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include "convert.h"
|
||||
#include "video.h"
|
||||
#include "configuration.h"
|
||||
#include "debayer.h"
|
||||
|
||||
int debayer_mode = 0; // testing 0 or 1
|
||||
|
||||
uint32_t convert_pixelformats [] = {
|
||||
V4L2_PIX_FMT_MJPEG,
|
||||
V4L2_PIX_FMT_YUYV,
|
||||
V4L2_PIX_FMT_RGB32,
|
||||
V4L2_PIX_FMT_BGR32,
|
||||
V4L2_PIX_FMT_RGB24,
|
||||
V4L2_PIX_FMT_BGR24,
|
||||
V4L2_PIX_FMT_UYVY,
|
||||
V4L2_PIX_FMT_SGRBG16,
|
||||
V4L2_PIX_FMT_SGRBG8,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* helper part for converting different video types
|
||||
*/
|
||||
|
||||
//
|
||||
// jpeg: replacement for error_exit
|
||||
//
|
||||
METHODDEF(void) jpg_error_exit (j_common_ptr cinfo) {
|
||||
jpg_error_ptr myerr = (jpg_error_ptr) cinfo->err;
|
||||
(*cinfo->err->output_message) (cinfo);
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// clamp and convert2rgb is build on the sample of the v4l2 api documentation
|
||||
//
|
||||
inline unsigned char clamp (double x) {
|
||||
int r = (int)x;
|
||||
|
||||
if (r < 0) return 0;
|
||||
else if (r > 255) return 255;
|
||||
else return r;
|
||||
};
|
||||
|
||||
|
||||
inline void convert2rgb (unsigned char Y1, unsigned char Cb, unsigned char Cr,
|
||||
unsigned char *ER, unsigned char *EB, unsigned char *EG) {
|
||||
int y1, pb, pr;
|
||||
|
||||
y1 = Y1 - 16;
|
||||
pb = Cb - 128;
|
||||
pr = Cr - 128;
|
||||
|
||||
*ER = clamp (y1 + 1.402 * pr);
|
||||
*EB = clamp (y1 - 0.344 * pb - 0.714 * pr);
|
||||
*EG = clamp (y1 + 1.772 * pb);
|
||||
};
|
||||
|
||||
|
||||
int ConvertStart(ConvertData *cdata, uint32_t pixelformat) {
|
||||
if (cdata == NULL) return 0;
|
||||
|
||||
if (pixelformat == V4L2_PIX_FMT_MJPEG) {
|
||||
jpeg_create_decompress(&cdata->cinfo);
|
||||
}
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
int ConvertStop(ConvertData *cdata, uint32_t pixelformat) {
|
||||
if (cdata == NULL) return 0;
|
||||
if (pixelformat == V4L2_PIX_FMT_MJPEG) jpeg_destroy_decompress(&cdata->cinfo);
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* converts the video from input type to RGB24 type - 24Bit
|
||||
*/
|
||||
int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch) {
|
||||
int xs, ys;
|
||||
int xd, yd;
|
||||
unsigned char r,g,b;
|
||||
unsigned char cb, cr, y1;
|
||||
unsigned char *ptrdst = NULL;
|
||||
|
||||
struct jpg_error_mgr jerr;
|
||||
if (cdata == NULL) return 0;
|
||||
|
||||
// check if there is a destination and that the destination is large to keep
|
||||
// the full image
|
||||
if (dest == NULL || ptrsrc == NULL)
|
||||
return 0;
|
||||
|
||||
dest->SetSize(srcw, srch);
|
||||
ptrdst = dest->GetPixBuf();
|
||||
|
||||
switch (pixelformat) {
|
||||
case (V4L2_PIX_FMT_RGB32):
|
||||
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
|
||||
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
|
||||
/* read the pixel */
|
||||
|
||||
r = *(ptrsrc++);
|
||||
g = *(ptrsrc++);
|
||||
b = *(ptrsrc++);
|
||||
ptrsrc++;
|
||||
|
||||
/* only paint the image if the source is within the destination */
|
||||
if (xd < srcw) {
|
||||
/* set the pixel */
|
||||
*(ptrdst++) = r;
|
||||
*(ptrdst++) = g;
|
||||
*(ptrdst++) = b;
|
||||
xd++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the source image is too small ignore the other places.. */
|
||||
if (xd < srcw)
|
||||
ptrdst += 3 * (srcw - xd);
|
||||
yd++;
|
||||
}
|
||||
break;
|
||||
|
||||
case (V4L2_PIX_FMT_BGR32):
|
||||
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
|
||||
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
|
||||
/* read the pixel */
|
||||
|
||||
ptrsrc++;
|
||||
b = *(ptrsrc++);
|
||||
g = *(ptrsrc++);
|
||||
r = *(ptrsrc++);
|
||||
|
||||
/* only paint the image if the source is within the destination */
|
||||
if (xd < srcw) {
|
||||
/* set the pixel */
|
||||
*(ptrdst++) = r;
|
||||
*(ptrdst++) = g;
|
||||
*(ptrdst++) = b;
|
||||
xd++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the source image is too small ignore the other places.. */
|
||||
if (xd < srcw)
|
||||
ptrdst += 3 * (srcw - xd);
|
||||
yd++;
|
||||
}
|
||||
break;
|
||||
case (V4L2_PIX_FMT_RGB24):
|
||||
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
|
||||
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
|
||||
/* read the pixel */
|
||||
|
||||
r = *(ptrsrc++);
|
||||
g = *(ptrsrc++);
|
||||
b = *(ptrsrc++);
|
||||
|
||||
/* only paint the image if the source is within the destination */
|
||||
if (xd < srcw) {
|
||||
/* set the pixel */
|
||||
*(ptrdst++) = r;
|
||||
*(ptrdst++) = g;
|
||||
*(ptrdst++) = b;
|
||||
xd++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the source image is too small ignore the other places.. */
|
||||
if (xd < srcw)
|
||||
ptrdst += 3 * (srcw - xd);
|
||||
yd++;
|
||||
}
|
||||
break;
|
||||
|
||||
case (V4L2_PIX_FMT_BGR24):
|
||||
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
|
||||
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
|
||||
/* read the pixel */
|
||||
|
||||
b = *(ptrsrc++);
|
||||
g = *(ptrsrc++);
|
||||
r = *(ptrsrc++);
|
||||
|
||||
/* only paint the image if the source is within the destination */
|
||||
if (xd < srcw) {
|
||||
/* set the pixel */
|
||||
*(ptrdst++) = r;
|
||||
*(ptrdst++) = g;
|
||||
*(ptrdst++) = b;
|
||||
xd++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the source image is too small ignore the other places.. */
|
||||
if (xd < srcw)
|
||||
ptrdst += 3 * (srcw - xd);
|
||||
yd++;
|
||||
}
|
||||
break;
|
||||
|
||||
case (V4L2_PIX_FMT_SGRBG16):
|
||||
if (debayer_mode == 0)
|
||||
debayer_grbg16_simple ((uint16_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch);
|
||||
else
|
||||
debayer_grbg16_bilinear ((uint16_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch);
|
||||
break;
|
||||
|
||||
case (V4L2_PIX_FMT_SGRBG8):
|
||||
if (debayer_mode == 0)
|
||||
debayer_grbg8_simple ((uint8_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch);
|
||||
else
|
||||
debayer_grbg8_bilinear ((uint8_t *)ptrsrc, srcw, srch, ptrdst, srcw, srch);
|
||||
break;
|
||||
|
||||
case (V4L2_PIX_FMT_UYVY):
|
||||
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
|
||||
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
|
||||
/* read the pixel */
|
||||
if (xs & 1) {
|
||||
y1 = (unsigned char)*(ptrsrc + 1);
|
||||
cr = (unsigned char)*(ptrsrc);
|
||||
cb = (unsigned char)*(ptrsrc - 2);
|
||||
}
|
||||
else {
|
||||
y1 = (unsigned char)*(ptrsrc + 1);
|
||||
cr = (unsigned char)*(ptrsrc + 2);
|
||||
cb = (unsigned char)*(ptrsrc);
|
||||
}
|
||||
|
||||
convert2rgb (y1, cr, cb, &r, &g, &b);
|
||||
ptrsrc += 2;
|
||||
|
||||
/* only paint the image if the source is within the destination */
|
||||
if (xd < srcw) {
|
||||
/* set the pixel */
|
||||
*(ptrdst++) = r;
|
||||
*(ptrdst++) = g;
|
||||
*(ptrdst++) = b;
|
||||
xd++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the source image is too small ignore the other places.. */
|
||||
if (xd < srcw)
|
||||
ptrdst += 3 * (srcw - xd);
|
||||
yd++;
|
||||
}
|
||||
break;
|
||||
|
||||
case (V4L2_PIX_FMT_YUYV):
|
||||
for (ys = 0, yd = 0; ys < (signed int)srch; ys++) {
|
||||
if (yd < srch) {
|
||||
for (xs = 0, xd = 0; xs < (signed int)srcw; xs++) {
|
||||
/* read the pixel */
|
||||
if (xs & 1) {
|
||||
y1 = *(ptrsrc);
|
||||
cb = *(ptrsrc + 1);
|
||||
cr = *(ptrsrc - 1);
|
||||
}
|
||||
else {
|
||||
y1 = *(ptrsrc);
|
||||
cb = *(ptrsrc + 3);
|
||||
cr = *(ptrsrc + 1);
|
||||
}
|
||||
convert2rgb (y1, cr, cb, &r, &g, &b);
|
||||
ptrsrc += 2;
|
||||
|
||||
/* only paint the image if the source is within the destination */
|
||||
if (xd < srcw) {
|
||||
/* set the pixel */
|
||||
*(ptrdst++) = r;
|
||||
*(ptrdst++) = g;
|
||||
*(ptrdst++) = b;
|
||||
xd++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the source image is too small ignore the other places.. */
|
||||
if (xd < srcw)
|
||||
ptrdst += 3 * (srcw - xd);
|
||||
yd++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case (V4L2_PIX_FMT_MJPEG):
|
||||
cdata->cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = jpg_error_exit;
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
// jpeg data and allocations will be destroyed via StopCapture.
|
||||
printf ("%s:%d %s JPEG Error\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
jpeg_mem_src(&cdata->cinfo, ptrsrc, srcsize);
|
||||
jpeg_read_header(&cdata->cinfo, TRUE);
|
||||
jpeg_start_decompress(&cdata->cinfo);
|
||||
|
||||
while (cdata->cinfo.output_scanline < cdata->cinfo.output_height) {
|
||||
unsigned char *temp_array[] = {ptrdst + (cdata->cinfo.output_scanline) * srcw * 3};
|
||||
jpeg_read_scanlines(&cdata->cinfo, temp_array, 1);
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cdata->cinfo);
|
||||
|
||||
break;
|
||||
default:
|
||||
printf ("%s:%d Error no default possible, need to finish\n", __FILE__, __LINE__);
|
||||
exit (-1);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
std::string convert_from_pixelformat (uint32_t fmt) {
|
||||
char txt[5];
|
||||
|
||||
snprintf (txt, 5, "%c%c%c%c", ((char*)&fmt)[0], ((char*)&fmt)[1], ((char*)&fmt)[2], ((char*)&fmt)[3]);
|
||||
return txt;
|
||||
};
|
||||
|
||||
|
||||
uint32_t convert_to_pixelformat(std::string s) {
|
||||
uint32_t u = 0;
|
||||
|
||||
u = ((unsigned char) s[0]) + ((unsigned char) s[1] << 8) +
|
||||
((unsigned char) s[2] << 16) + ((unsigned char) s[3] << 24);
|
||||
|
||||
return u;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* copy part of an raw image
|
||||
* destination must be pointer in case we need to align the size of the destination image.
|
||||
* this function will also realloc needed memory if needed. (only if: givin size < needed size)
|
||||
*
|
||||
* crop image to event set of dimensions
|
||||
*/
|
||||
int PixCopy(unsigned char *srcdata, uint32_t srcpixfmt, int srcw, int srch,
|
||||
unsigned char **dstdataptr, int *dstsize, int *dstw, int *dsth,
|
||||
int regionx, int regiony, int regionw, int regionh) {
|
||||
|
||||
if (srcpixfmt == 0 || srcpixfmt == V4L2_PIX_FMT_MJPEG) return 0;
|
||||
if (srcdata == NULL || dstdataptr == NULL) return 0;
|
||||
|
||||
// crop size to an even number
|
||||
(*dsth) = regionw & ~1;
|
||||
(*dstw) = regionh & ~1;
|
||||
|
||||
int bytesperpixel = 3;
|
||||
int dsize = 0;
|
||||
|
||||
switch (srcpixfmt) {
|
||||
case (V4L2_PIX_FMT_SGRBG8):
|
||||
bytesperpixel = 1;
|
||||
break;
|
||||
case (V4L2_PIX_FMT_SGRBG16):
|
||||
bytesperpixel = 2;
|
||||
break;
|
||||
case (V4L2_PIX_FMT_BGR32):
|
||||
case (V4L2_PIX_FMT_RGB32):
|
||||
bytesperpixel = 4;
|
||||
break;
|
||||
case (V4L2_PIX_FMT_BGR24):
|
||||
case (V4L2_PIX_FMT_RGB24):
|
||||
bytesperpixel = 3;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// calculate image size and allocate memory if needed
|
||||
dsize = (*dsth) * (*dstw) * bytesperpixel;
|
||||
if ((*dstsize) < dsize || (*dstdataptr) == NULL) {
|
||||
*dstdataptr = (unsigned char*) realloc (*dstdataptr, dsize);
|
||||
if (*dstdataptr == NULL) {
|
||||
errorexit((char*)"%s:%d could not realloc memory. dsize:%d error:%s\n", __FILE__, __LINE__, dsize, strerror(errno));
|
||||
}
|
||||
*dstsize = dsize;
|
||||
printf ("%s:%d reallocate memory for destination raw image\n", __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
unsigned char *dptr, *sptr;
|
||||
int y, dy, x;
|
||||
|
||||
// debug_drawraw(srcdata, srcpixfmt, srcw, srch);
|
||||
for (y = regiony & (~1), dy = 0; dy < *dsth && y < srch; y++, dy++) {
|
||||
x = regionx & (~1);
|
||||
dptr = (*dstdataptr) + bytesperpixel * (dy * *dstw);
|
||||
sptr = (srcdata) + bytesperpixel * ( y * srcw + x);
|
||||
memcpy (dptr, sptr, *dstw * bytesperpixel);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
|
||||
#ifndef _CONVERT_H_
|
||||
#define _CONVERT_H_
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <jpeglib.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "video.h"
|
||||
|
||||
#ifndef CLEAR
|
||||
#define CLEAR(x) memset (&(x), 0, sizeof (x))
|
||||
#endif
|
||||
|
||||
struct {
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
} typedef ConvertData;
|
||||
|
||||
int Convert (ConvertData *cdata, VideoFrame *dest, unsigned char *ptrsrc, int srcsize, uint32_t pixelformat, int srcw, int srch);
|
||||
int ConvertStart(ConvertData *cdata, uint32_t pixelformat);
|
||||
int ConvertStop(ConvertData *cdata, uint32_t pixelformat);
|
||||
|
||||
int PixCopy(unsigned char *srcdata, uint32_t srcpixfmt, int srcw, int srch,
|
||||
unsigned char **dstdataptr, int *dstsize, int *dstw, int *dsth,
|
||||
int regionx, int regiony, int regionw, int regionh);
|
||||
|
||||
extern uint32_t convert_pixelformats[];
|
||||
std::string convert_from_pixelformat (uint32_t fmt);
|
||||
uint32_t convert_to_pixelformat(std::string s);
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,366 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
The function converts a 16bit GRBG 2x2 CFA coded image into an 8bit
|
||||
RGB image by setting the missing RGB values to zero.
|
||||
*/
|
||||
void debayer_grbg16_simple (uint16_t * src, int src_w, int src_h,
|
||||
uint8_t * dst, int dst_w, int dst_h) {
|
||||
|
||||
// GG RR
|
||||
// BB GG
|
||||
uint16_t t;
|
||||
uint8_t r, g, b;
|
||||
int ys, yd, xs, xd;
|
||||
|
||||
for (ys = 0, yd = 0; ys < src_h && yd < dst_h; ys++, yd++) {
|
||||
for (xs = 0, xd = 0; xs < src_w; xs++) {
|
||||
|
||||
/* read the pixel but only the higher 8bit, assuming data is little endian */
|
||||
t = (*(src++) >> 8) & 0xff;
|
||||
|
||||
if (xs & 1) {
|
||||
if (ys & 1) {
|
||||
// lower right green pixel
|
||||
b = 0; g = t; r = 0;
|
||||
} else {
|
||||
// upper right red pixel
|
||||
b = 0; g = 0; r = t;
|
||||
}
|
||||
} else {
|
||||
if (ys & 1) {
|
||||
// lower left blue pixel
|
||||
b = t; g = 0; r = 0;
|
||||
} else {
|
||||
// upper left green pixel
|
||||
b = 0; g = t; r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* only paint the image if the source is within the destination */
|
||||
if (xd < dst_w) {
|
||||
/* set the pixel */
|
||||
*(dst++) = r;
|
||||
*(dst++) = g;
|
||||
*(dst++) = b;
|
||||
xd++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the source image is too small ignore the other places */
|
||||
if (xd < dst_w)
|
||||
dst += 3 * (dst_w - xd);
|
||||
}
|
||||
}
|
||||
|
||||
// macros to make code better readable
|
||||
#define CE (*(src))
|
||||
#define UP (*(src-src_w))
|
||||
#define DN (*(src+src_w))
|
||||
#define LE (*(src-1))
|
||||
#define RI (*(src+1))
|
||||
#define UPLE (*(src-src_w-1))
|
||||
#define UPRI (*(src-src_w+1))
|
||||
#define DNLE (*(src+src_w-1))
|
||||
#define DNRI (*(src+src_w+1))
|
||||
|
||||
#define BITCONV(d) ((d>>8) & 0xff)
|
||||
#define STORE *(dst++) = BITCONV(r); *(dst++) = BITCONV(g); *(dst++) = BITCONV(b); src++;
|
||||
#define STORE8 *(dst++) = (r & 0xff); *(dst++) = (g & 0xff); *(dst++) = (b & 0xff); src++;
|
||||
|
||||
|
||||
/*
|
||||
The function converts a 16bit GRBG 2x2 CFA coded image into an 8bit
|
||||
RGB image by bilinear interpolation.
|
||||
*/
|
||||
void debayer_grbg16_bilinear (uint16_t * src, int src_w, int src_h,
|
||||
uint8_t * dst, int dst_w, int dst_h) {
|
||||
|
||||
// GG RR GG RR
|
||||
// BB GG BB GG
|
||||
// GG RR GG RR
|
||||
// BB GG BB GG
|
||||
uint32_t r, g, b;
|
||||
int xs, ys;
|
||||
|
||||
// start with upper left pixel (green)
|
||||
r = RI;
|
||||
g = CE;
|
||||
b = DN;
|
||||
STORE;
|
||||
|
||||
// upper first line, starts with RR GG RR ...
|
||||
for (xs = 1; xs < src_w - 1; xs+=2) {
|
||||
// red pixel
|
||||
r = CE;
|
||||
g = (LE + RI + DN) / 3;
|
||||
b = (DNLE + DNRI) / 2;
|
||||
STORE;
|
||||
// green pixel
|
||||
r = (LE + RI) / 2;
|
||||
g = CE;
|
||||
b = DN;
|
||||
STORE;
|
||||
}
|
||||
|
||||
// upper right pixel (red)
|
||||
r = CE;
|
||||
g = (DN + LE) / 2;
|
||||
b = DNLE;
|
||||
STORE;
|
||||
|
||||
// go through the "body" of the image
|
||||
for (ys = 1; ys < src_h - 1; ys+=2) {
|
||||
|
||||
// every second line with BB GG BB GG (start at 2nd line)
|
||||
|
||||
// left hand pixel (blue)
|
||||
r = (UPRI + DNRI) / 2;
|
||||
g = (UP + DN + RI) / 3;
|
||||
b = CE;
|
||||
STORE;
|
||||
for (xs = 1; xs < src_w - 1; xs+=2) {
|
||||
// green pixel
|
||||
r = (UP + DN) / 2;
|
||||
g = CE;
|
||||
b = (LE + RI) / 2;
|
||||
STORE;
|
||||
// blue pixel
|
||||
r = (UPLE + UPRI + DNLE + DNRI) / 4;
|
||||
g = (LE + RI + UP + DN) / 4;
|
||||
b = CE;
|
||||
STORE;
|
||||
}
|
||||
// last pixel in line (green)
|
||||
r = (UP + DN) / 2;
|
||||
g = CE;
|
||||
b = LE;
|
||||
STORE;
|
||||
|
||||
// every second line with GG RR GG RR ... (start at 3rd line)
|
||||
|
||||
// left hand pixel (green)
|
||||
r = RI;
|
||||
g = CE;
|
||||
b = (UP + DN) / 2;
|
||||
STORE;
|
||||
for (xs = 1; xs < src_w - 1; xs+=2) {
|
||||
// red pixel
|
||||
r = CE;
|
||||
g = (LE + RI + UP + DN) / 4;
|
||||
b = (UPLE + UPRI + DNLE + DNRI) / 4;
|
||||
STORE;
|
||||
// green pixel
|
||||
r = (LE + RI) / 2;
|
||||
g = CE;
|
||||
b = (UP + DN) / 2;
|
||||
STORE;
|
||||
}
|
||||
// last pixel in line (red)
|
||||
r = CE;
|
||||
g = (UP + DN + LE) / 3;
|
||||
b = (UPLE + DNLE) / 2;
|
||||
STORE;
|
||||
}
|
||||
|
||||
// bottom left pixel
|
||||
r = UPRI;
|
||||
g = (UP + RI) / 2;
|
||||
b = CE;
|
||||
STORE;
|
||||
|
||||
// last line starting with GG BB GG ...
|
||||
for (xs = 1; xs < src_w - 1; xs+=2) {
|
||||
// green pixel
|
||||
r = UP;
|
||||
g = CE;
|
||||
b = (LE + RI) / 2;
|
||||
STORE;
|
||||
// blue pixel
|
||||
r = (UPLE + UPRI) / 2;
|
||||
g = (LE + UP + RI) / 2;
|
||||
b = CE;
|
||||
STORE;
|
||||
}
|
||||
|
||||
// bottom right pixel (green)
|
||||
r = UP;
|
||||
g = CE;
|
||||
b = LE;
|
||||
STORE;
|
||||
}
|
||||
|
||||
/*
|
||||
The function converts a 8bit GRBG 2x2 CFA coded image into an 8bit
|
||||
RGB image by setting the missing RGB values to zero.
|
||||
*/
|
||||
void debayer_grbg8_simple (uint8_t * src, int src_w, int src_h,
|
||||
uint8_t * dst, int dst_w, int dst_h) {
|
||||
|
||||
// GG RR
|
||||
// BB GG
|
||||
uint8_t t;
|
||||
uint8_t r, g, b;
|
||||
int ys, yd, xs, xd;
|
||||
|
||||
for (ys = 0, yd = 0; ys < src_h && yd < dst_h; ys++, yd++) {
|
||||
for (xs = 0, xd = 0; xs < src_w; xs++) {
|
||||
|
||||
/* read the pixel but only the higher 8bit, assuming data is little endian */
|
||||
t = *(src++);
|
||||
|
||||
if (xs & 1) {
|
||||
if (ys & 1) {
|
||||
// lower right green pixel
|
||||
b = 0; g = t; r = 0;
|
||||
} else {
|
||||
// upper right red pixel
|
||||
b = 0; g = 0; r = t;
|
||||
}
|
||||
} else {
|
||||
if (ys & 1) {
|
||||
// lower left blue pixel
|
||||
b = t; g = 0; r = 0;
|
||||
} else {
|
||||
// upper left green pixel
|
||||
b = 0; g = t; r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* only paint the image if the source is within the destination */
|
||||
if (xd < dst_w) {
|
||||
/* set the pixel */
|
||||
*(dst++) = r;
|
||||
*(dst++) = g;
|
||||
*(dst++) = b;
|
||||
xd++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if the source image is too small ignore the other places */
|
||||
if (xd < dst_w)
|
||||
dst += 3 * (dst_w - xd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The function converts a 8bit GRBG 2x2 CFA coded image into an 8bit
|
||||
RGB image by bilinear interpolation.
|
||||
*/
|
||||
void debayer_grbg8_bilinear (uint8_t * src, int src_w, int src_h,
|
||||
uint8_t * dst, int dst_w, int dst_h) {
|
||||
|
||||
// GG RR GG RR
|
||||
// BB GG BB GG
|
||||
// GG RR GG RR
|
||||
// BB GG BB GG
|
||||
uint16_t r, g, b;
|
||||
int xs, ys;
|
||||
|
||||
// start with upper left pixel (green)
|
||||
r = RI;
|
||||
g = CE;
|
||||
b = DN;
|
||||
STORE8;
|
||||
|
||||
// upper first line, starts with RR GG RR ...
|
||||
for (xs = 1; xs < src_w - 1; xs+=2) {
|
||||
// red pixel
|
||||
r = CE;
|
||||
g = (LE + RI + DN) / 3;
|
||||
b = (DNLE + DNRI) / 2;
|
||||
STORE8;
|
||||
// green pixel
|
||||
r = (LE + RI) / 2;
|
||||
g = CE;
|
||||
b = DN;
|
||||
STORE8;
|
||||
}
|
||||
|
||||
// upper right pixel (red)
|
||||
r = CE;
|
||||
g = (DN + LE) / 2;
|
||||
b = DNLE;
|
||||
STORE8;
|
||||
|
||||
// go through the "body" of the image
|
||||
for (ys = 1; ys < src_h - 1; ys+=2) {
|
||||
|
||||
// every second line with BB GG BB GG (start at 2nd line)
|
||||
|
||||
// left hand pixel (blue)
|
||||
r = (UPRI + DNRI) / 2;
|
||||
g = (UP + DN + RI) / 3;
|
||||
b = CE;
|
||||
STORE8;
|
||||
for (xs = 1; xs < src_w - 1; xs+=2) {
|
||||
// green pixel
|
||||
r = (UP + DN) / 2;
|
||||
g = CE;
|
||||
b = (LE + RI) / 2;
|
||||
STORE8;
|
||||
// blue pixel
|
||||
r = (UPLE + UPRI + DNLE + DNRI) / 4;
|
||||
g = (LE + RI + UP + DN) / 4;
|
||||
b = CE;
|
||||
STORE8;
|
||||
}
|
||||
// last pixel in line (green)
|
||||
r = (UP + DN) / 2;
|
||||
g = CE;
|
||||
b = LE;
|
||||
STORE8;
|
||||
|
||||
// every second line with GG RR GG RR ... (start at 3rd line)
|
||||
|
||||
// left hand pixel (green)
|
||||
r = RI;
|
||||
g = CE;
|
||||
b = (UP + DN) / 2;
|
||||
STORE8;
|
||||
for (xs = 1; xs < src_w - 1; xs+=2) {
|
||||
// red pixel
|
||||
r = CE;
|
||||
g = (LE + RI + UP + DN) / 4;
|
||||
b = (UPLE + UPRI + DNLE + DNRI) / 4;
|
||||
STORE8;
|
||||
// green pixel
|
||||
r = (LE + RI) / 2;
|
||||
g = CE;
|
||||
b = (UP + DN) / 2;
|
||||
STORE8;
|
||||
}
|
||||
// last pixel in line (red)
|
||||
r = CE;
|
||||
g = (UP + DN + LE) / 3;
|
||||
b = (UPLE + DNLE) / 2;
|
||||
STORE8;
|
||||
}
|
||||
|
||||
// bottom left pixel
|
||||
r = UPRI;
|
||||
g = (UP + RI) / 2;
|
||||
b = CE;
|
||||
STORE8;
|
||||
|
||||
// last line starting with GG BB GG ...
|
||||
for (xs = 1; xs < src_w - 1; xs+=2) {
|
||||
// green pixel
|
||||
r = UP;
|
||||
g = CE;
|
||||
b = (LE + RI) / 2;
|
||||
STORE8;
|
||||
// blue pixel
|
||||
r = (UPLE + UPRI) / 2;
|
||||
g = (LE + UP + RI) / 2;
|
||||
b = CE;
|
||||
STORE8;
|
||||
}
|
||||
|
||||
// bottom right pixel (green)
|
||||
r = UP;
|
||||
g = CE;
|
||||
b = LE;
|
||||
STORE8;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
#ifndef _DEBAYER_H_
|
||||
#define _DEBAYER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void debayer_grbg16_simple (uint16_t * src, int src_w, int src_h,
|
||||
uint8_t * dst, int dst_w, int dst_h);
|
||||
void debayer_grbg8_simple (uint8_t * src, int src_w, int src_h,
|
||||
uint8_t * dst, int dst_w, int dst_h);
|
||||
|
||||
void debayer_grbg16_bilinear (uint16_t * src, int src_w, int src_h,
|
||||
uint8_t * dst, int dst_w, int dst_h);
|
||||
void debayer_grbg8_bilinear (uint8_t * src, int src_w, int src_h,
|
||||
uint8_t * dst, int dst_w, int dst_h);
|
||||
|
||||
#endif
|
||||
@ -1,534 +0,0 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "json.h"
|
||||
|
||||
/***********************************************************************
|
||||
***********************************************************************
|
||||
*
|
||||
* JSONParse
|
||||
*
|
||||
***********************************************************************
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
enum {
|
||||
STEP_NONE = 0,
|
||||
STEP_STARTNAME,
|
||||
STEP_NAME,
|
||||
STEP_STARTVALUE,
|
||||
STEP_VALUE,
|
||||
STEP_END
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* clear out all data
|
||||
*/
|
||||
void JSONParse::Clear() {
|
||||
jsondata = "";
|
||||
names.clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* read every element and keep only this in memory.
|
||||
*/
|
||||
int JSONParse::Set(string json) {
|
||||
int i;
|
||||
int step;
|
||||
int level;
|
||||
bool ignorenext;
|
||||
|
||||
JSONElement jelement;
|
||||
|
||||
Clear();
|
||||
|
||||
// find start and read until end
|
||||
for (step = STEP_NONE, i = 0, ignorenext = false; (unsigned int)i < json.length(); i++) {
|
||||
// need to copy next character
|
||||
if (ignorenext) {
|
||||
ignorenext = false;
|
||||
if (step == STEP_NAME) jelement.name += json[i];
|
||||
if (step == STEP_VALUE) jelement.value += json[i];
|
||||
}
|
||||
|
||||
// searching for startname
|
||||
else if (step == STEP_NONE) {
|
||||
if (json[i] == '{') {
|
||||
step = STEP_STARTNAME;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// searching for startname
|
||||
else if (step == STEP_STARTNAME) {
|
||||
if (json[i] == '"') {
|
||||
step = STEP_NAME;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// copy name
|
||||
else if (step == STEP_NAME) {
|
||||
if (json[i] == '"') {
|
||||
step = STEP_STARTVALUE;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
jelement.name += json[i];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// searching for startvalue
|
||||
else if (step == STEP_STARTVALUE) {
|
||||
if (json[i] == '"') {
|
||||
step = STEP_VALUE;
|
||||
jelement.type = JSON_T_STRING;
|
||||
continue;
|
||||
}
|
||||
if (json[i] == '{') {
|
||||
step = STEP_VALUE;
|
||||
level = 0;
|
||||
jelement.type = JSON_T_OBJECT;
|
||||
jelement.value = "{";
|
||||
continue;
|
||||
}
|
||||
if (json[i] == '[') {
|
||||
step = STEP_VALUE;
|
||||
level = 0;
|
||||
jelement.type = JSON_T_ARRAY;
|
||||
jelement.value = "[";
|
||||
continue;
|
||||
}
|
||||
if ((json[i] >= '0' && json[i] <= '9') ||
|
||||
(json[i] == '+' || json[i] == '-')) {
|
||||
step = STEP_VALUE;
|
||||
level = 0;
|
||||
jelement.type = JSON_T_NUMBER;
|
||||
jelement.value = json[i];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// copy value
|
||||
else if (step == STEP_VALUE) {
|
||||
if (jelement.type == JSON_T_STRING) {
|
||||
if (json[i] == '"') step = STEP_END;
|
||||
else jelement.value += json[i];
|
||||
continue;
|
||||
}
|
||||
else if (jelement.type == JSON_T_OBJECT) {
|
||||
if (json[i] == '}' && level == 0) {
|
||||
jelement.value += json[i];
|
||||
step = STEP_END;
|
||||
}
|
||||
else {
|
||||
if (json[i] == '{') level++; // increase level
|
||||
if (json[i] == '}') level--; // decrease level
|
||||
jelement.value += json[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (jelement.type == JSON_T_ARRAY) {
|
||||
if (json[i] == ']' && level == 0) {
|
||||
jelement.value += json[i];
|
||||
step = STEP_END;
|
||||
}
|
||||
else {
|
||||
if (json[i] == '[') level++; // increase level
|
||||
if (json[i] == ']') level--; // decrease level
|
||||
jelement.value += json[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (jelement.type == JSON_T_NUMBER) {
|
||||
if ((json[i] < '0' || json[i] > '9') && json[i] != '.' &&
|
||||
json[i] != '+' && json[i] != 'e' && json[i] != 'E') step = STEP_END;
|
||||
else {
|
||||
jelement.value += json[i];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// another element?
|
||||
if (step == STEP_END) {
|
||||
if (json[i] == ',') {
|
||||
if (jelement.type != JSON_T_NONE) {
|
||||
names.push_back (jelement);
|
||||
}
|
||||
jelement.Clear();
|
||||
step = STEP_STARTNAME;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (jelement.type != JSON_T_NONE) {
|
||||
names.push_back (jelement);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int JSONParse::GetValue(string varname, string *dest) {
|
||||
list<JSONElement>::iterator iter;
|
||||
|
||||
if (dest == NULL) return 0;
|
||||
*dest = "";
|
||||
|
||||
for (iter = names.begin(); iter != names.end(); iter++) {
|
||||
if (varname.compare(iter->name) == 0) {
|
||||
*dest = iter->value;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int JSONParse::GetValueInt(string varname, int *dest) {
|
||||
string s;
|
||||
int res = GetValue(varname, &s);
|
||||
if (res) {
|
||||
*dest = atoi (s.c_str());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int JSONParse::GetValueDouble(string varname, double *dest) {
|
||||
string s;
|
||||
int res = GetValue(varname, &s);
|
||||
if (res) {
|
||||
*dest = atof (s.c_str());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int JSONParse::GetValueInt64(string varname, int64_t *dest) {
|
||||
string s;
|
||||
int res = GetValue(varname, &s);
|
||||
if (res) {
|
||||
*dest = atol (s.c_str());
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int JSONParse::GetObjectJson(string varname, JSONParse *dest) {
|
||||
list<JSONElement>::iterator iter;
|
||||
|
||||
if (dest == NULL) return 0;
|
||||
|
||||
for (iter = names.begin(); iter != names.end(); iter++) {
|
||||
if (varname.compare(iter->name) == 0) {
|
||||
dest->Set(iter->value);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
#define MAXRECURSIVE 255
|
||||
int JSONParse::GetIdx(string src, int idx, string *dest) {
|
||||
char recursive[MAXRECURSIVE];
|
||||
int i = 0, rcnt = 0, cnt = 0;
|
||||
|
||||
(*dest) = "";
|
||||
|
||||
for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0;
|
||||
for (i = 0; (unsigned int) i < src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
|
||||
if (src[i] == '[') {
|
||||
recursive[rcnt++] = src[i];
|
||||
continue;
|
||||
}
|
||||
else if (src[i] == '{' && recursive[rcnt] != '"') recursive[++rcnt] = src[i];
|
||||
else if (src[i] == '}' && recursive[rcnt] == '{') rcnt--;
|
||||
else if (src[i] == '"' && recursive[rcnt] == '"') rcnt--;
|
||||
else if (src[i] == '"') recursive[++rcnt] = src[i];
|
||||
else if (src[i] == ',' && rcnt == 1) {
|
||||
cnt++;
|
||||
continue;
|
||||
}
|
||||
else if (src[i] == ']' && rcnt == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rcnt > 0 && cnt == idx) {
|
||||
(*dest) += src[i];
|
||||
if (src[i] == '\\') (*dest) += src[i];
|
||||
}
|
||||
else {
|
||||
if (src[i] == '\\')i++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// final checks
|
||||
if (cnt == 0 && idx == 0 && // empty source/array?
|
||||
dest->size() == 0) return 0; //
|
||||
if (cnt >= idx) return 1; // found the right element
|
||||
return 0; // element not found
|
||||
}
|
||||
#undef MAXRECURSIVE
|
||||
|
||||
int JSONParse::GetValueIdx(string varname, int idx, string *dest) {
|
||||
list<JSONElement>::iterator iter;
|
||||
|
||||
if (dest == NULL) return 0;
|
||||
|
||||
for (iter = names.begin(); iter != names.end(); iter++) {
|
||||
if (varname.compare(iter->name) == 0) {
|
||||
return GetIdx(iter->value, idx, dest);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
int JSONParse::GetObjectIdx(string varname, int idx, JSONParse *dest) {
|
||||
list<JSONElement>::iterator iter;
|
||||
string deststr;
|
||||
int ret = 0;
|
||||
|
||||
if (dest == NULL) return 0;
|
||||
|
||||
for (iter = names.begin(); iter != names.end(); iter++) {
|
||||
if (varname.compare(iter->name) == 0) {
|
||||
ret = GetIdx(iter->value, idx, &deststr);
|
||||
if (ret == 1) dest->Set(deststr);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
list<JSONElement> JSONParse::GetElements() {
|
||||
list<JSONElement> l;
|
||||
list<JSONElement>::iterator iter;
|
||||
|
||||
l.clear();
|
||||
for (iter = names.begin(); iter != names.end(); iter++) {
|
||||
l.push_back(*iter);
|
||||
}
|
||||
|
||||
return l;
|
||||
};
|
||||
|
||||
|
||||
void JSONParse::AddObject (JSONElement element) {
|
||||
names.push_back (element);
|
||||
};
|
||||
|
||||
|
||||
void JSONParse::AddObject (string name, JSONParse jp) {
|
||||
JSONElement je;
|
||||
je.SetObject(name, jp.ToString());
|
||||
names.push_back(je);
|
||||
};
|
||||
|
||||
|
||||
void JSONParse::AddObject (string name, int val) {
|
||||
JSONElement je;
|
||||
je.Set(name, val);
|
||||
names.push_back(je);
|
||||
};
|
||||
|
||||
|
||||
void JSONParse::AddObject (string name, int64_t val) {
|
||||
JSONElement je;
|
||||
je.Set(name, val);
|
||||
names.push_back(je);
|
||||
};
|
||||
|
||||
|
||||
void JSONParse::AddObject (string name, string val) {
|
||||
JSONElement je;
|
||||
je.Set(name, val);
|
||||
names.push_back(je);
|
||||
};
|
||||
|
||||
|
||||
void JSONParse::AddObject (string name, double val) {
|
||||
JSONElement je;
|
||||
je.Set(name, val);
|
||||
names.push_back(je);
|
||||
};
|
||||
|
||||
|
||||
string JSONParse::ToString() {
|
||||
list<JSONElement>::iterator iter;
|
||||
string output;
|
||||
int level, i;
|
||||
|
||||
output = "{";
|
||||
|
||||
for (level = 1, iter = names.begin(); iter != names.end(); iter++) {
|
||||
if (iter != names.begin()) output += ",";
|
||||
output += "\n";
|
||||
for (i = 0; i < 4*level; i++) output += " ";
|
||||
output += iter->GetString();
|
||||
}
|
||||
|
||||
output += "\n}\n";
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Load/Save elements to a file.
|
||||
* Return Value: -1 .. on Error, errno will be set
|
||||
* 0 .. on Success
|
||||
*/
|
||||
int JSONParse::LoadFromFile(string filename) {
|
||||
int fd;
|
||||
struct stat fs;
|
||||
char *buffer;
|
||||
|
||||
if (stat(filename.c_str(), &fs) != 0) return -1;
|
||||
buffer = (char *) malloc (fs.st_size+1);
|
||||
memset (buffer, 0x0, fs.st_size+1);
|
||||
|
||||
fd = open(filename.c_str(), O_RDONLY);
|
||||
if (fd < 0) return -1;
|
||||
read (fd, buffer, fs.st_size);
|
||||
close (fd);
|
||||
|
||||
Set(buffer);
|
||||
free (buffer);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
int JSONParse::SaveToFile(string filename) {
|
||||
ofstream out(filename);
|
||||
|
||||
if (!out) return -1;
|
||||
|
||||
out << ToString();
|
||||
out.close();
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
***********************************************************************
|
||||
*
|
||||
* JSONElement
|
||||
*
|
||||
***********************************************************************
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
|
||||
void JSONElement::Set (string n, double v) {
|
||||
name = n;
|
||||
value = to_string(v);
|
||||
type = JSON_T_NUMBER;
|
||||
};
|
||||
|
||||
|
||||
void JSONElement::Set (string n, int v) {
|
||||
name = n;
|
||||
value = to_string(v);
|
||||
type = JSON_T_NUMBER;
|
||||
};
|
||||
|
||||
|
||||
void JSONElement::Set (string n, int64_t v) {
|
||||
name = n;
|
||||
value = to_string(v);
|
||||
type = JSON_T_NUMBER;
|
||||
};
|
||||
|
||||
|
||||
void JSONElement::Set (string n, string v) {
|
||||
name = n;
|
||||
value = v;
|
||||
type = JSON_T_STRING;
|
||||
};
|
||||
|
||||
|
||||
void JSONElement::SetArray (string n, list<JSONElement> *l) {
|
||||
list<JSONElement>::iterator iter;
|
||||
|
||||
name = n;
|
||||
value = "[";
|
||||
type = JSON_T_STRING;
|
||||
|
||||
for (iter = l->begin(); iter != l->end(); iter++) {
|
||||
if (iter != l->begin()) value += ",";
|
||||
value += iter->GetString();
|
||||
}
|
||||
value += "]";
|
||||
};
|
||||
|
||||
|
||||
void JSONElement::SetObject (string n, string s) {
|
||||
name = n;
|
||||
value = s;
|
||||
type = JSON_T_OBJECT;
|
||||
};
|
||||
|
||||
|
||||
string JSONElement::GetString () {
|
||||
string output = "";
|
||||
string filename = __FILE__;
|
||||
|
||||
switch (type) {
|
||||
case(JSON_T_NUMBER):
|
||||
output += "\"" + name + "\" : " + value;
|
||||
break;
|
||||
case(JSON_T_STRING):
|
||||
if (value.length()==0) {
|
||||
output += "\"" + name + "\" : \"\"";
|
||||
}
|
||||
else if (value[0] != '"') {
|
||||
output += "\"" + name + "\" : \"" + value + "\"";
|
||||
}
|
||||
else output += "\"" + name + "\" : " + value;
|
||||
break;
|
||||
case(JSON_T_OBJECT):
|
||||
output += "\"" + name + "\" : " + value;
|
||||
break;
|
||||
case(JSON_T_ARRAY):
|
||||
if (value.length()==0) {
|
||||
output += "\"" + name + "\" : []";
|
||||
}
|
||||
else if (value[0] != '[') {
|
||||
output += "\"" + name + "\" : [" + value + "]";
|
||||
}
|
||||
else output += "\"" + name + "\" : " + value;
|
||||
break;
|
||||
default:
|
||||
output += "\"error\" : \""+ filename + ":" + to_string(__LINE__) + " JSONElement unknown type error\"("+to_string(type)+")";
|
||||
break;
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
@ -1,80 +0,0 @@
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef _JSON_H_
|
||||
#define _JSON_H_
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
enum {
|
||||
JSON_T_NONE,
|
||||
JSON_T_STRING,
|
||||
JSON_T_NUMBER,
|
||||
JSON_T_OBJECT,
|
||||
JSON_T_ARRAY
|
||||
};
|
||||
|
||||
class JSONElement {
|
||||
public:
|
||||
int type;
|
||||
string name;
|
||||
string value;
|
||||
|
||||
JSONElement() { Clear(); };
|
||||
~JSONElement() {};
|
||||
|
||||
void Clear() { type = JSON_T_NONE; name = ""; value = ""; };
|
||||
void Set (string n, double v);
|
||||
void Set (string n, int v);
|
||||
void Set (string n, int64_t v);
|
||||
void Set (string n, string v);
|
||||
void SetArray (string n, list<JSONElement> *l);
|
||||
void SetObject (string n, string s);
|
||||
string GetString();
|
||||
};
|
||||
|
||||
class JSONParse {
|
||||
private:
|
||||
string jsondata;
|
||||
list<JSONElement> names;
|
||||
|
||||
public:
|
||||
JSONParse() { Set("{}"); };
|
||||
JSONParse(string json) { Set(json); };
|
||||
~JSONParse() {};
|
||||
|
||||
void Clear();
|
||||
int Set(string json);
|
||||
|
||||
int GetValue(string varname, string *dest);
|
||||
int GetValueInt(string varname, int *dest);
|
||||
int GetValueDouble(string varname, double *dest);
|
||||
int GetValueInt64(string varname, int64_t *dest);
|
||||
int GetObjectJson(string varname, JSONParse *dest);
|
||||
|
||||
int GetIdx(string src, int idx, string *dest);
|
||||
int GetValueIdx(string varname, int idx, string *dest);
|
||||
int GetObjectIdx(string varname, int idx, JSONParse *dest);
|
||||
|
||||
list<JSONElement> GetElements();
|
||||
|
||||
void AddObject (JSONElement element);
|
||||
void AddObject (string name, int val);
|
||||
void AddObject (string name, int64_t val);
|
||||
void AddObject (string name, string val);
|
||||
void AddObject (string name, double val);
|
||||
void AddObject (string name, JSONParse jp);
|
||||
|
||||
int LoadFromFile(string filename);
|
||||
int SaveToFile(string filename);
|
||||
|
||||
string ToString();
|
||||
};
|
||||
|
||||
#endif // _JSON_H_
|
||||
@ -1,25 +0,0 @@
|
||||
|
||||
project('miniwebcam', 'cpp', default_options: [
|
||||
'cpp_std=gnu++14'
|
||||
])
|
||||
|
||||
miniwebcam_src = [
|
||||
'main.cc',
|
||||
'configuration.cc',
|
||||
'webserver.cc',
|
||||
'json.cc'
|
||||
]
|
||||
|
||||
miniwebcam_headers = [
|
||||
'configuration.h',
|
||||
'miniwebcam.h',
|
||||
'json.h'
|
||||
]
|
||||
|
||||
|
||||
executable('miniwebcam',
|
||||
install : true,
|
||||
sources: miniwebcam_src,
|
||||
extra_files: miniwebcam_headers
|
||||
)
|
||||
|
||||
@ -0,0 +1,108 @@
|
||||
|
||||
#include "miniwebcam.h"
|
||||
#include "video.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
VideoFrame::VideoFrame() {
|
||||
mem = NULL;
|
||||
width = 0;
|
||||
height = 0;
|
||||
mem_allocated = 0;
|
||||
};
|
||||
|
||||
VideoFrame::~VideoFrame() {
|
||||
FreeFrame();
|
||||
};
|
||||
|
||||
|
||||
void VideoFrame::FreeFrame() {
|
||||
if (mem != NULL) {
|
||||
free (mem);
|
||||
mem = NULL;
|
||||
width = 0;
|
||||
height = 0;
|
||||
mem_allocated = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void VideoFrame::AllocateFrame() {
|
||||
printf ("VideoFrame::AllocateFrame()\n");
|
||||
int memnewsize = width * height * 3;
|
||||
if (memnewsize >= mem_allocated) return;
|
||||
else if (memnewsize == 0) FreeFrame();
|
||||
|
||||
mem = (unsigned char *) realloc (mem, memnewsize);
|
||||
mem_allocated = memnewsize;
|
||||
|
||||
if (mem == NULL) {
|
||||
debug ("Error on allocation new frame\n");
|
||||
exit (1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int VideoFrame::SetSize(int w, int h) {
|
||||
if (w < 0 && h < 0) return 0;
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
AllocateFrame();
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
|
||||
|
||||
void VideoFrameFloat::AllocateFrame() {
|
||||
printf ("VideoFrameFloat::AllocateFrame()\n");
|
||||
int memnewsize = width * height * 3 * sizeof(float);
|
||||
if (memnewsize >= mem_allocated) return;
|
||||
else if (memnewsize == 0) FreeFrame();
|
||||
|
||||
mem = (unsigned char *) realloc (mem, memnewsize);
|
||||
mem_allocated = memnewsize;
|
||||
|
||||
if (mem == NULL) {
|
||||
debug ("Error on allocation new frame\n");
|
||||
exit (1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
|
||||
VideoDevice::VideoDevice() {
|
||||
videofd = 0;
|
||||
};
|
||||
|
||||
|
||||
VideoDevice::~VideoDevice() {
|
||||
|
||||
};
|
||||
|
||||
|
||||
int VideoDevice::SetDevice() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int VideoDevice::Start(int w, int h) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int VideoDevice::Stop() {
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
int VideoDevice::GetFrame(VideoFrame *destframe) {
|
||||
return 0;
|
||||
};
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
|
||||
#ifndef _VIDEO_H_
|
||||
#define _VIDEO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/mman.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include <jpeglib.h>
|
||||
|
||||
enum {
|
||||
IOMODE_READ,
|
||||
IOMODE_MMAP
|
||||
};
|
||||
|
||||
//
|
||||
// jpeg error handling
|
||||
//
|
||||
struct jpg_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
typedef struct jpg_error_mgr *jpg_error_ptr;
|
||||
|
||||
|
||||
//
|
||||
// only contain 24bit each color 8Bit
|
||||
class VideoFrame {
|
||||
private:
|
||||
virtual void AllocateFrame();
|
||||
protected:
|
||||
void FreeFrame();
|
||||
int mem_allocated;
|
||||
unsigned char *mem;
|
||||
int height;
|
||||
int width;
|
||||
public:
|
||||
VideoFrame();
|
||||
~VideoFrame();
|
||||
|
||||
int GetHeight() { return height; };
|
||||
int GetWidth() { return width; };
|
||||
unsigned char *GetPixBuf() { return mem; };
|
||||
|
||||
int SetSize(int w, int h);
|
||||
};
|
||||
|
||||
|
||||
class VideoFrameFloat : public VideoFrame {
|
||||
private:
|
||||
void AllocateFrame();
|
||||
protected:
|
||||
public:
|
||||
};
|
||||
|
||||
|
||||
class VideoDevice {
|
||||
private:
|
||||
int videofd;
|
||||
protected:
|
||||
public:
|
||||
VideoDevice();
|
||||
~VideoDevice();
|
||||
|
||||
int SetDevice();
|
||||
int Start(int w, int h);
|
||||
int Stop();
|
||||
int GetFrame(VideoFrame *destframe);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,2 @@
|
||||
|
||||
#include "webserver.h"
|
||||
@ -0,0 +1,6 @@
|
||||
#ifndef _WEBSERVER_H_
|
||||
#define _WEBSERVER_H_
|
||||
|
||||
#include "miniwebcam.h"
|
||||
|
||||
#endif
|
||||
Loading…
Reference in new issue