MYNT-EYE-S-SDK/src/mynteye/uvc/macosx/CameraEngine.cpp
2018-12-11 17:08:31 +08:00

698 lines
20 KiB
C++

// Copyright 2018 Slightech Co., Ltd. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <vector>
#include "CameraEngine.h"
const char* dstr[] = { "default","dc1394","ps3eye","raspi","uvccam","","","","","","file","folder"};
const char* fstr[] = { "unknown", "mono8", "mono16", "rgb8", "rgb16", "mono16s", "rgb16s", "raw8", "raw16", "rgba", "yuyv", "uyvy", "yuv411", "yuv444", "yuv420p", "yuv410p", "yvyu", "yuv211", "", "", "jpeg", "mjpeg", "mpeg", "mpeg2", "mpeg4", "h263", "h264", "", "", "", "dvpal", "dvntsc" };
void CameraEngine::printInfo() {
printf("camera: %s\n",cfg->name);
printf("driver: %s\n",dstr[cfg->driver]);
printf("codec: %s\n",fstr[cfg->cam_format]);
if (cfg->frame_mode<0) {
if (cfg->cam_fps==(int)cfg->cam_fps) printf("format: %dx%d, %dfps\n",cfg->frame_width,cfg->frame_height,(int)cfg->cam_fps);
else printf("format: %dx%d, %.1ffps\n",cfg->frame_width,cfg->frame_height,cfg->cam_fps);
}
else printf("format7_%d: %dx%d\n",cfg->frame_mode,cfg->frame_width,cfg->frame_height);
}
void CameraEngine::setMinMaxConfig(CameraConfig *cam_cfg, std::vector<CameraConfig> cfg_list) {
if ((cam_cfg->cam_width>0) && (cam_cfg->cam_height>0) && (cam_cfg->cam_fps>0)) return;
int max_width = 0;
int max_height = 0;
int min_width = INT_MAX;
int min_height = INT_MAX;
float max_fps = 0;
float min_fps = INT_MAX;
for (unsigned int i=0;i<cfg_list.size();i++) {
if (cfg_list[i].cam_format!=cam_cfg->cam_format) continue; // wrong format
if (cfg_list[i].frame_mode!=cam_cfg->frame_mode) continue; // wrong format7
if (cfg_list[i].cam_width>max_width) max_width = cfg_list[i].cam_width;
if (cfg_list[i].cam_width<min_width) min_width = cfg_list[i].cam_width;
if (cfg_list[i].cam_height>max_height) max_height = cfg_list[i].cam_height;
if (cfg_list[i].cam_width<min_height) min_height = cfg_list[i].cam_height;
}
if ((cam_cfg->cam_width==SETTING_MAX) || (cam_cfg->cam_width>max_width)) cam_cfg->cam_width = max_width;
else if ((cam_cfg->cam_width==SETTING_MIN) || (cam_cfg->cam_width<min_width)) cam_cfg->cam_width = min_width;
if ((cam_cfg->cam_height==SETTING_MAX) || (cam_cfg->cam_height>max_height)) cam_cfg->cam_height = max_height;
else if ((cam_cfg->cam_height==SETTING_MIN) || (cam_cfg->cam_height<min_height)) cam_cfg->cam_height = min_height;
if (cam_cfg->cam_fps>0) return;
for (unsigned int i=0;i<cfg_list.size();i++) {
if (cfg_list[i].cam_format!=cam_cfg->cam_format) continue; // wrong format
if (cfg_list[i].frame_mode!=cam_cfg->frame_mode) continue; // wrong format7
if ((cfg_list[i].cam_width!=cam_cfg->cam_width) || (cfg_list[i].cam_height!=cam_cfg->cam_height)) continue; // wrong size
if (cfg_list[i].cam_fps>max_fps) max_fps = cfg_list[i].cam_fps;
if (cfg_list[i].cam_fps<min_fps) min_fps = cfg_list[i].cam_fps;
}
if ((cam_cfg->cam_fps==SETTING_MAX) || (cam_cfg->cam_fps>max_fps)) cam_cfg->cam_fps = max_fps;
if ((cam_cfg->cam_fps==SETTING_MIN) || (cam_cfg->cam_fps<min_fps)) cam_cfg->cam_fps = min_fps;
}
bool CameraEngine::showSettingsDialog(bool lock) {
return true;
}
void CameraEngine::control(unsigned char key) {
if(!settingsDialog) return;
int step = 0;
switch(key) {
case VALUE_DECREASE:
step = getCameraSettingStep(currentCameraSetting);
if (step==1) step = (int)((float)ctrl_max/256.0f);
if (step<1) step=1;
ctrl_val -= step;
if (ctrl_val<ctrl_min) ctrl_val=ctrl_min;
setCameraSetting(currentCameraSetting,ctrl_val);
break;
case VALUE_INCREASE:
step = getCameraSettingStep(currentCameraSetting);
if (step==1) step = (int)((float)ctrl_max/256.0f);
if (step<1) step=1;
ctrl_val += step;
if (ctrl_val>ctrl_max) ctrl_val=ctrl_max;
setCameraSetting(currentCameraSetting,ctrl_val);
break;
case SETTING_PREVIOUS:
currentCameraSetting--;
if(currentCameraSetting<0) {
if (cfg->color) currentCameraSetting=COLOR_BLUE;
else currentCameraSetting=BACKLIGHT;
}
if ((!hasCameraSetting(currentCameraSetting)) || (getCameraSettingAuto(currentCameraSetting)))
control(SETTING_PREVIOUS);
break;
case SETTING_NEXT:
currentCameraSetting++;
if ((cfg->color) && (currentCameraSetting>COLOR_BLUE)) currentCameraSetting=0;
else if ((!cfg->color) && (currentCameraSetting>BACKLIGHT)) currentCameraSetting=0;
if ((!hasCameraSetting(currentCameraSetting)) || (getCameraSettingAuto(currentCameraSetting)))
control(SETTING_NEXT);
break;
case KEY_D:
resetCameraSettings();
break;
}
ctrl_val = getCameraSetting(currentCameraSetting);
ctrl_max = getMaxCameraSetting(currentCameraSetting);
ctrl_min = getMinCameraSetting(currentCameraSetting);
}
void CameraEngine::uyvy2gray(int width, int height, unsigned char *src, unsigned char *dest) {
for (int i=height*width/2;i>0;i--) {
src++;
*dest++ = *src++;
src++;
*dest++ = *src++;
}
}
void CameraEngine::crop_uyvy2gray(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
cam_buf += 2*y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
for (int i=frm_h;i>0;i--) {
cam_buf += 2*x_off;
for (int j=frm_w/2;j>0;j--) {
cam_buf++;
*frm_buf++ = *cam_buf++;
cam_buf++;
*frm_buf++ = *cam_buf++;
}
cam_buf += 2*x_end;
}
}
void CameraEngine::yuyv2gray(int width, int height, unsigned char *src, unsigned char *dest) {
for (int i=height*width/2;i>0;i--) {
*dest++ = *src++;
src++;
*dest++ = *src++;
src++;
}
}
void CameraEngine::crop_yuyv2gray(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
cam_buf += 2*y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
for (int i=frm_h;i>0;i--) {
cam_buf += 2*x_off;
for (int j=frm_w/2;j>0;j--) {
*frm_buf++ = *cam_buf++;
cam_buf++;
*frm_buf++ = *cam_buf++;
cam_buf++;
}
cam_buf += 2*x_end;
}
}
//void yuv2rgb_conv(int Y1, int Y2, int U, int V, unsigned char *dest) {
void yuv2rgb_conv(int Y, int U, int V, unsigned char *dest) {
/*int R = (int)(Y + 1.370705f * V);
int G = (int)(Y - 0.698001f * V - 0.337633f * U);
int B = (int)(Y + 1.732446f * U);*/
// integer method is twice as fast
int C = 298*(Y - 16);
int R = (C + 409*V + 128) >> 8;
int G = (C - 100*U - 208*V + 128) >> 8;
int B = (C + 516*U + 128) >> 8;
SAT(R);
SAT(G);
SAT(B);
*dest++ = R;
*dest++ = G;
*dest++ = B;
}
void CameraEngine::uyvy2rgb(int width, int height, unsigned char *src, unsigned char *dest) {
int Y1,Y2,U,V;
for(int i=width*height/2;i>0;i--) {
// U and V are +-0.5
U = *src++ - 128;
Y1 = *src++;
V = *src++ - 128;
Y2 = *src++;
yuv2rgb_conv(Y1,U,V,dest);
yuv2rgb_conv(Y2,U,V,dest+=3);
dest+=3;
}
}
void CameraEngine::crop_uyvy2rgb(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
int Y1,Y2,U,V;
cam_buf += 2*y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
for (int i=frm_h;i>0;i--) {
cam_buf += 2*x_off;
for (int j=frm_w/2;j>0;j--) {
// U and V are +-0.5
U = *cam_buf++ - 128;
Y1 = *cam_buf++;
V = *cam_buf++ - 128;
Y2 = *cam_buf++;
yuv2rgb_conv(Y1,U,V,frm_buf);
yuv2rgb_conv(Y2,U,V,frm_buf+=3);
frm_buf+=3;
}
cam_buf += 2*x_end;
}
}
void CameraEngine::yuyv2rgb(int width, int height, unsigned char *src, unsigned char *dest) {
int Y1,Y2,U,V;
for(int i=width*height/2;i>0;i--) {
Y1 = *src++;
U = *src++ - 128;
Y2 = *src++;
V = *src++ - 128;
yuv2rgb_conv(Y1,U,V,dest);
yuv2rgb_conv(Y2,U,V,dest+=3);
dest+=3;
}
}
void CameraEngine::crop_yuyv2rgb(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
int Y1,Y2,U,V;
cam_buf += 2*y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
for (int i=frm_h;i>0;i--) {
cam_buf += 2*x_off;
for (int j=frm_w/2;j>0;j--) {
// U and V are +-0.5
Y1 = *cam_buf++;
U = *cam_buf++ - 128;
Y2 = *cam_buf++;
V = *cam_buf++ - 128;
yuv2rgb_conv(Y1,U,V,frm_buf);
yuv2rgb_conv(Y2,U,V,frm_buf+=3);
frm_buf+=3;
}
cam_buf += 2*x_end;
}
}
void CameraEngine::gray2rgb(int width, int height, unsigned char *src, unsigned char *dest) {
int size = width*height;
for (int i=size;i>0;i--) {
unsigned char pixel = *src++;
*dest++ = pixel;
*dest++ = pixel;
*dest++ = pixel;
}
}
void CameraEngine::crop_gray2rgb(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
cam_buf += y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
for (int i=frm_h;i>0;i--) {
cam_buf += x_off;
for (int j=frm_w;j>0;j--) {
unsigned char pixel = *cam_buf++;
*frm_buf++ = pixel;
*frm_buf++ = pixel;
*frm_buf++ = pixel;
}
cam_buf += x_end;
}
}
void CameraEngine::grayw2rgb(int width, int height, unsigned char *src, unsigned char *dest) {
unsigned short src_pixel;
unsigned char dest_pixel;
unsigned char pixel;
for(int i=width*height;i>0;i--) {
pixel = *src++ ;
src_pixel = pixel | (*src++ << 8);
dest_pixel = (unsigned char)(src_pixel/4);
*dest++ = dest_pixel;
*dest++ = dest_pixel;
*dest++ = dest_pixel;
}
}
void CameraEngine::crop_grayw2rgb(int cam_w, unsigned char *src, unsigned char *dest) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
unsigned short src_pixel;
unsigned char dest_pixel;
unsigned char pixel;
src += 2*y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
for (int i=frm_h;i>0;i--) {
src += 2*x_off;
for (int j=frm_w;j>0;j--) {
pixel = *src++;
src_pixel = pixel | (*src++ << 8);
dest_pixel = (unsigned char)(src_pixel/4);
*dest++ = dest_pixel;
*dest++ = dest_pixel;
*dest++ = dest_pixel;
}
src += 2*x_end;
}
}
void CameraEngine::grayw2gray(int width, int height, unsigned char *src, unsigned char *dest) {
unsigned short value;
unsigned char pixel;
for(int i=width*height;i>0;i--) {
pixel = *src++;
value = pixel | (*src++ << 8);
*dest++ = (unsigned char)(value/4);
}
}
void CameraEngine::crop_grayw2gray(int cam_w, unsigned char *src, unsigned char *dest) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
unsigned short src_pixel;
unsigned char pixel;
src += 2*y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
for (int i=frm_h;i>0;i--) {
src += 2*x_off;
for (int j=frm_w;j>0;j--) {
pixel = *src++;
src_pixel = pixel | (*src++ << 8);
*dest++ = (unsigned char)(src_pixel/4);
}
src += 2*x_end;
}
}
void CameraEngine::crop(int cam_w, int cam_h, unsigned char *cam_buf, unsigned char *frm_buf, int b) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
cam_buf += b*(y_off*cam_w + x_off);
for (int i=frm_h;i>0;i--) {
memcpy(frm_buf, cam_buf, b*cam_w);
cam_buf += b*cam_w;
frm_buf += b*frm_w;
}
}
void CameraEngine::flip(int width, int height, unsigned char *src, unsigned char *dest, int b) {
int size = b*width*height;
dest += size-1;
for(int i=size;i>0;i--) {
*dest-- = *src++;
}
}
void CameraEngine::flip_crop(int cam_w, int cam_h, unsigned char *cam_buf, unsigned char *frm_buf, int b) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
cam_buf += b*y_off*cam_w;
frm_buf += b*frm_w*frm_h-1;
int xend = (cam_w-(frm_w+x_off));
for (int i=frm_h;i>0;i--) {
cam_buf += b*x_off;
for (int j=b*frm_w;j>0;j--) {
*frm_buf-- = *cam_buf++;
}
cam_buf += b*xend;
}
}
void CameraEngine::rgb2gray(int width, int height, unsigned char *src, unsigned char *dest) {
int R,G,B;
for (int i=width*height;i>0;i--) {
R = *src++;
G = *src++;
B = *src++;
*dest++ = HBT(R*77 + G*151 + B*28);
}
}
void CameraEngine::flip_rgb2gray(int width, int height, unsigned char *src, unsigned char *dest) {
int size = width*height;
dest += size-1;
int R,G,B;
for (int i=size;i>0;i--) {
R = *src++;
G = *src++;
B = *src++;
*dest-- = HBT(R*77 + G*151 + B*28);
}
}
void CameraEngine::crop_rgb2gray(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
cam_buf += 3*y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
int R,G,B;
for (int i=frm_h;i>0;i--) {
cam_buf += 3*x_off;
for (int j=frm_w;j>0;j--) {
R = *cam_buf++;
G = *cam_buf++;
B = *cam_buf++;
*frm_buf++ = HBT(R*77 + G*151 + B*28);
}
cam_buf += 3*x_end;
}
}
void CameraEngine::flip_crop_rgb2gray(int cam_w, unsigned char *cam_buf, unsigned char *frm_buf) {
if(!cfg->frame) return;
int x_off = cfg->frame_xoff;
int y_off = cfg->frame_yoff;
int frm_w = cfg->frame_width;
int frm_h = cfg->frame_height;
cam_buf += 3*y_off*cam_w;
int x_end = cam_w-(frm_w+x_off);
frm_buf += frm_w*frm_h-1;
int R,G,B;
for (int i=frm_h;i>0;i--) {
cam_buf += 3*x_off;
for (int j=frm_w;j>0;j--) {
R = *cam_buf++;
G = *cam_buf++;
B = *cam_buf++;
*frm_buf-- = HBT(R*77 + G*151 + B*28);
}
cam_buf += 3*x_end;
}
}
void CameraEngine::setupFrame() {
if(!cfg->frame) {
cfg->frame_width = cfg->cam_width;
cfg->frame_height = cfg->cam_height;
return;
}
// size sanity check
if (cfg->frame_width%2!=0) cfg->frame_width--;
if (cfg->frame_height%2!=0) cfg->frame_height--;
if (cfg->frame_width<=0) cfg->frame_width = cfg->cam_width;
if (cfg->frame_height<=0) cfg->frame_height = cfg->cam_height;
if (cfg->frame_width > cfg->cam_width) cfg->frame_width = cfg->cam_width;
if (cfg->frame_height > cfg->cam_height) cfg->frame_height = cfg->cam_height;
// no cropping if same size
if ((cfg->frame_width==cfg->cam_width) && (cfg->frame_height==cfg->cam_height)) {
cfg->frame_width = cfg->cam_width;
cfg->frame_height = cfg->cam_height;
cfg->frame = false;
return;
}
// offset sanity check
int xdiff = cfg->cam_width-cfg->frame_width;
if (xdiff<0) cfg->frame_xoff = 0;
else if (cfg->frame_xoff > xdiff) cfg->frame_xoff = xdiff;
int ydiff = cfg->cam_height-cfg->frame_height;
if (ydiff<0) cfg->frame_yoff = 0;
else if (cfg->frame_yoff > ydiff) cfg->frame_yoff = ydiff;
}
void CameraEngine::applyCameraSetting(int mode, int value) {
if (!hasCameraSetting(mode)) return;
switch (value) {
case SETTING_AUTO:
if (hasCameraSettingAuto(mode)) {
setCameraSettingAuto(mode,true);
return;
}
case SETTING_OFF:
case SETTING_DEFAULT:
setDefaultCameraSetting(mode);
return;
case SETTING_MIN:
setCameraSettingAuto(mode,false);
setCameraSetting(mode,getMinCameraSetting(mode)); return;
case SETTING_MAX:
setCameraSettingAuto(mode,false);
setCameraSetting(mode,getMaxCameraSetting(mode)); return;
default: {
int max = getMaxCameraSetting(mode);
int min = getMinCameraSetting(mode);
if (value<min) value = min;
else if (value>max) value = max;
setCameraSettingAuto(mode,false);
setCameraSetting(mode,value);
}
}
}
void CameraEngine::resetCameraSettings() {
for (int mode=MODE_MIN;mode<=MODE_MAX;mode++)
setDefaultCameraSetting(mode);
}
void CameraEngine::applyCameraSettings() {
resetCameraSettings();
applyCameraSetting(BRIGHTNESS,cfg->brightness);
applyCameraSetting(CONTRAST,cfg->contrast);
applyCameraSetting(SHARPNESS,cfg->sharpness);
applyCameraSetting(GAIN,cfg->gain);
applyCameraSetting(EXPOSURE,cfg->exposure);
applyCameraSetting(SHUTTER,cfg->shutter);
applyCameraSetting(FOCUS,cfg->focus);
applyCameraSetting(WHITE,cfg->white);
applyCameraSetting(POWERLINE,cfg->powerline);
applyCameraSetting(BACKLIGHT,cfg->backlight);
applyCameraSetting(GAMMA,cfg->gamma);
applyCameraSetting(SATURATION,cfg->saturation);
applyCameraSetting(COLOR_HUE,cfg->hue);
applyCameraSetting(COLOR_RED,cfg->red);
applyCameraSetting(COLOR_GREEN,cfg->green);
applyCameraSetting(COLOR_BLUE,cfg->blue);
}
int CameraEngine::updateSetting(int mode) {
if (!hasCameraSetting(mode)) return SETTING_OFF;
if (getCameraSettingAuto(mode)) return SETTING_AUTO;
int value = getCameraSetting(mode);
if (value==getDefaultCameraSetting(mode)) value = SETTING_DEFAULT;
else if (value==getMinCameraSetting(mode)) value = SETTING_MIN;
else if (value==getMaxCameraSetting(mode)) value = SETTING_MAX;
return value;
}
void CameraEngine::updateSettings() {
cfg->brightness = updateSetting(BRIGHTNESS);
cfg->contrast = updateSetting(CONTRAST);
cfg->sharpness = updateSetting(SHARPNESS);
cfg->gain = updateSetting(GAIN);
cfg->exposure = updateSetting(EXPOSURE);
cfg->shutter = updateSetting(SHUTTER);
cfg->focus = updateSetting(FOCUS);
cfg->white = updateSetting(WHITE);
cfg->backlight = updateSetting(BACKLIGHT);
cfg->powerline = updateSetting(POWERLINE);
cfg->gamma = updateSetting(GAMMA);
if (cfg->color) {
cfg->saturation = updateSetting(SATURATION);
cfg->hue = updateSetting(COLOR_HUE);
cfg->red = updateSetting(COLOR_RED);
cfg->green = updateSetting(COLOR_GREEN);
cfg->blue = updateSetting(COLOR_BLUE);
} else {
cfg->saturation = SETTING_OFF;
cfg->hue = SETTING_OFF;
cfg->red = SETTING_OFF;
cfg->green = SETTING_OFF;
cfg->blue = SETTING_OFF;
}
}