diff options
Diffstat (limited to 'camera/V4LCameraAdapter/V4LCapabilities.cpp')
-rw-r--r-- | camera/V4LCameraAdapter/V4LCapabilities.cpp | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/camera/V4LCameraAdapter/V4LCapabilities.cpp b/camera/V4LCameraAdapter/V4LCapabilities.cpp new file mode 100644 index 0000000..f03ba9b --- /dev/null +++ b/camera/V4LCameraAdapter/V4LCapabilities.cpp @@ -0,0 +1,365 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * 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. + */ + +/** +* @file V4LCapabilities.cpp +* +* This file implements the V4L Capabilities feature. +* +*/ + +#include "CameraHal.h" +#include "V4LCameraAdapter.h" +#include "ErrorUtils.h" +#include "TICameraParameters.h" + +namespace Ti { +namespace Camera { + +/************************************ + * global constants and variables + *************************************/ + +#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0])) +#define MAX_RES_STRING_LENGTH 10 +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 + +static const char PARAM_SEP[] = ","; + +//Camera defaults +const char V4LCameraAdapter::DEFAULT_PICTURE_FORMAT[] = "jpeg"; +const char V4LCameraAdapter::DEFAULT_PICTURE_SIZE[] = "640x480"; +const char V4LCameraAdapter::DEFAULT_PREVIEW_FORMAT[] = "yuv420sp"; +const char V4LCameraAdapter::DEFAULT_PREVIEW_SIZE[] = "640x480"; +const char V4LCameraAdapter::DEFAULT_NUM_PREV_BUFS[] = "6"; +const char V4LCameraAdapter::DEFAULT_FRAMERATE[] = "30"; +const char V4LCameraAdapter::DEFAULT_FOCUS_MODE[] = "infinity"; +const char V4LCameraAdapter::DEFAULT_FRAMERATE_RANGE[] = "30000,30000"; +const char * V4LCameraAdapter::DEFAULT_VSTAB = android::CameraParameters::FALSE; +const char * V4LCameraAdapter::DEFAULT_VNF = android::CameraParameters::FALSE; + + +const CapPixelformat V4LCameraAdapter::mPixelformats [] = { + { V4L2_PIX_FMT_YUYV, android::CameraParameters::PIXEL_FORMAT_YUV422I }, + { V4L2_PIX_FMT_JPEG, android::CameraParameters::PIXEL_FORMAT_JPEG }, +}; + +/***************************************** + * internal static function declarations + *****************************************/ + +/**** Utility functions to help translate V4L Caps to Parameter ****/ + +status_t V4LCameraAdapter::insertDefaults(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) +{ + status_t ret = NO_ERROR; + LOG_FUNCTION_NAME; + + params->set(CameraProperties::PREVIEW_FORMAT, DEFAULT_PREVIEW_FORMAT); + + params->set(CameraProperties::PICTURE_FORMAT, DEFAULT_PICTURE_FORMAT); + params->set(CameraProperties::PICTURE_SIZE, DEFAULT_PICTURE_SIZE); + params->set(CameraProperties::PREVIEW_SIZE, DEFAULT_PREVIEW_SIZE); + params->set(CameraProperties::PREVIEW_FRAME_RATE, DEFAULT_FRAMERATE); + params->set(CameraProperties::REQUIRED_PREVIEW_BUFS, DEFAULT_NUM_PREV_BUFS); + params->set(CameraProperties::FOCUS_MODE, DEFAULT_FOCUS_MODE); + + params->set(CameraProperties::CAMERA_NAME, "USBCAMERA"); + params->set(CameraProperties::JPEG_THUMBNAIL_SIZE, "320x240"); + params->set(CameraProperties::JPEG_QUALITY, "90"); + params->set(CameraProperties::JPEG_THUMBNAIL_QUALITY, "50"); + params->set(CameraProperties::FRAMERATE_RANGE, DEFAULT_FRAMERATE_RANGE); + params->set(CameraProperties::S3D_PRV_FRAME_LAYOUT, "none"); + params->set(CameraProperties::SUPPORTED_EXPOSURE_MODES, "auto"); + params->set(CameraProperties::SUPPORTED_ISO_VALUES, "auto"); + params->set(CameraProperties::SUPPORTED_ANTIBANDING, "auto"); + params->set(CameraProperties::SUPPORTED_EFFECTS, "none"); + params->set(CameraProperties::SUPPORTED_IPP_MODES, "ldc-nsf"); + params->set(CameraProperties::FACING_INDEX, TICameraParameters::FACING_FRONT); + params->set(CameraProperties::ORIENTATION_INDEX, 0); + params->set(CameraProperties::SENSOR_ORIENTATION, "0"); + params->set(CameraProperties::VSTAB, DEFAULT_VSTAB); + params->set(CameraProperties::VNF, DEFAULT_VNF); + + //For compatibility + params->set(CameraProperties::SUPPORTED_ZOOM_RATIOS,"0"); + params->set(CameraProperties::SUPPORTED_ZOOM_STAGES, "0"); + params->set(CameraProperties::ZOOM, "0"); + params->set(CameraProperties::ZOOM_SUPPORTED, "true"); + + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t V4LCameraAdapter::insertPreviewFormats(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) { + + char supported[MAX_PROP_VALUE_LENGTH]; + + memset(supported, '\0', MAX_PROP_VALUE_LENGTH); + for (int i = 0; i < caps.ulPreviewFormatCount; i++) { + for (unsigned int j = 0; j < ARRAY_SIZE(mPixelformats); j++) { + if(caps.ePreviewFormats[i] == mPixelformats[j].pixelformat ) { + strncat (supported, mPixelformats[j].param, MAX_PROP_VALUE_LENGTH-1 ); + strncat (supported, PARAM_SEP, 1 ); + } + } + } + strncat(supported, android::CameraParameters::PIXEL_FORMAT_YUV420P, MAX_PROP_VALUE_LENGTH - 1); + strncat (supported, PARAM_SEP, 1 ); + strncat(supported, android::CameraParameters::PIXEL_FORMAT_YUV420SP, MAX_PROP_VALUE_LENGTH - 1); + params->set(CameraProperties::SUPPORTED_PREVIEW_FORMATS, supported); + return NO_ERROR; +} + +status_t V4LCameraAdapter::insertPreviewSizes(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) { + + char supported[MAX_PROP_VALUE_LENGTH]; + + memset(supported, '\0', MAX_PROP_VALUE_LENGTH); + for (int i = 0; i < caps.ulPreviewResCount; i++) { + if (supported[0] != '\0') { + strncat(supported, PARAM_SEP, 1); + } + strncat (supported, caps.tPreviewRes[i].param, MAX_PROP_VALUE_LENGTH-1 ); + } + + params->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, supported); + params->set(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES, supported); + return NO_ERROR; +} + +status_t V4LCameraAdapter::insertImageSizes(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) { + + char supported[MAX_PROP_VALUE_LENGTH]; + + memset(supported, '\0', MAX_PROP_VALUE_LENGTH); + for (int i = 0; i < caps.ulCaptureResCount; i++) { + if (supported[0] != '\0') { + strncat(supported, PARAM_SEP, 1); + } + strncat (supported, caps.tCaptureRes[i].param, MAX_PROP_VALUE_LENGTH-1 ); + } + params->set(CameraProperties::SUPPORTED_PICTURE_SIZES, supported); + return NO_ERROR; +} + +status_t V4LCameraAdapter::insertFrameRates(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) { + + char supported[MAX_PROP_VALUE_LENGTH]; + char temp[MAX_PROP_VALUE_LENGTH]; + + memset(supported, '\0', MAX_PROP_VALUE_LENGTH); + for (int i = 0; i < caps.ulFrameRateCount; i++) { + snprintf (temp, sizeof(temp) - 1, "%d", caps.ulFrameRates[i] ); + if (supported[0] != '\0') { + strncat(supported, PARAM_SEP, 1); + } + strncat (supported, temp, MAX_PROP_VALUE_LENGTH-1 ); + } + + params->set(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES, supported); + + memset(supported, 0, sizeof(supported)); + + for (int i = caps.ulFrameRateCount - 1; i >= 0 ; i--) { + if ( supported[0] ) strncat(supported, PARAM_SEP, 1); + snprintf(temp, sizeof(temp) - 1, "(%d,%d)", caps.ulFrameRates[i] * CameraHal::VFR_SCALE, caps.ulFrameRates[i] * CameraHal::VFR_SCALE); + strcat(supported, temp); + } + + params->set(CameraProperties::FRAMERATE_RANGE_SUPPORTED, supported); + + return NO_ERROR; +} + +status_t V4LCameraAdapter::insertCapabilities(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + if ( NO_ERROR == ret ) { + ret = insertPreviewFormats(params, caps); + } + + if ( NO_ERROR == ret ) { + ret = insertImageSizes(params, caps); + } + + if ( NO_ERROR == ret ) { + ret = insertPreviewSizes(params, caps); + } + + if ( NO_ERROR == ret ) { + ret = insertFrameRates(params, caps); + } + + //Insert Supported Focus modes. + params->set(CameraProperties::SUPPORTED_FOCUS_MODES, "infinity"); + + params->set(CameraProperties::SUPPORTED_PICTURE_FORMATS, "jpeg"); + + if ( NO_ERROR == ret ) { + ret = insertDefaults(params, caps); + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t V4LCameraAdapter::sortAscend(V4L_TI_CAPTYPE &caps, uint16_t count) { + size_t tempRes; + size_t w, h, tmpW,tmpH; + for (int i=0; i<count; i++) { + w = caps.tPreviewRes[i].width; + h = caps.tPreviewRes[i].height; + tempRes = w*h; + for (int j=i+1; j<count; j++) { + tmpW = caps.tPreviewRes[j].width; + tmpH = caps.tPreviewRes[j].height; + + if (tempRes > (tmpW * tmpH) ) { + caps.tPreviewRes[j].width = w; + caps.tPreviewRes[j].height = h; + w = tmpW; + h = tmpH; + } + } + caps.tPreviewRes[i].width = w; + caps.tPreviewRes[i].height = h; + + } + return NO_ERROR; +} + +/***************************************** + * public exposed function declarations + *****************************************/ + +status_t V4LCameraAdapter::getCaps(const int sensorId, CameraProperties::Properties* params, + V4L_HANDLETYPE handle) { + status_t status = NO_ERROR; + V4L_TI_CAPTYPE caps; + int i = 0; + int j = 0; + struct v4l2_fmtdesc fmtDesc; + struct v4l2_frmsizeenum frmSizeEnum; + struct v4l2_frmivalenum frmIvalEnum; + + //get supported pixel formats + for ( i = 0; status == NO_ERROR; i++) { + fmtDesc.index = i; + fmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + status = ioctl (handle, VIDIOC_ENUM_FMT, &fmtDesc); + if (status == NO_ERROR) { + CAMHAL_LOGDB("fmtDesc[%d].description::pixelformat::flags== (%s::%d::%d)",i, fmtDesc.description,fmtDesc.pixelformat,fmtDesc.flags); + caps.ePreviewFormats[i] = fmtDesc.pixelformat; + } + } + caps.ulPreviewFormatCount = i; + + //get preview sizes & capture image sizes + status = NO_ERROR; + for ( i = 0; status == NO_ERROR; i++) { + frmSizeEnum.index = i; + //Check for frame sizes for default pixel format + //TODO: Check for frame sizes for all supported pixel formats + frmSizeEnum.pixel_format = DEFAULT_PIXEL_FORMAT; + status = ioctl (handle, VIDIOC_ENUM_FRAMESIZES, &frmSizeEnum); + if(frmSizeEnum.type != V4L2_FRMSIZE_TYPE_DISCRETE) { + break; + } + if (status == NO_ERROR) { + CAMHAL_LOGDB("frmSizeEnum.index[%d].width x height == (%d x %d)", i, frmSizeEnum.discrete.width, frmSizeEnum.discrete.height); + caps.tPreviewRes[i].width = frmSizeEnum.discrete.width; + caps.tPreviewRes[i].height = frmSizeEnum.discrete.height; + snprintf(caps.tPreviewRes[i].param, MAX_RES_STRING_LENGTH,"%dx%d",frmSizeEnum.discrete.width,frmSizeEnum.discrete.height); + + caps.tCaptureRes[i].width = frmSizeEnum.discrete.width; + caps.tCaptureRes[i].height = frmSizeEnum.discrete.height; + snprintf(caps.tCaptureRes[i].param, MAX_RES_STRING_LENGTH,"%dx%d",frmSizeEnum.discrete.width,frmSizeEnum.discrete.height); + } + else { + caps.ulCaptureResCount = i; + caps.ulPreviewResCount = i; + } + } + if(frmSizeEnum.type != V4L2_FRMSIZE_TYPE_DISCRETE) { + CAMHAL_LOGDB("\nmin_width x height = %d x %d ",frmSizeEnum.stepwise.min_width, frmSizeEnum.stepwise.min_height); + CAMHAL_LOGDB("\nmax_width x height = %d x %d ",frmSizeEnum.stepwise.max_width, frmSizeEnum.stepwise.max_height); + CAMHAL_LOGDB("\nstep width x height = %d x %d ",frmSizeEnum.stepwise.step_width,frmSizeEnum.stepwise.step_height); + //TODO: populate the sizes when type = V4L2_FRMSIZE_TYPE_STEPWISE + } + + //sort the preview sizes in ascending order + sortAscend(caps, caps.ulPreviewResCount); + + //get supported frame rates + bool fps30 = false; + for ( j=caps.ulPreviewResCount-1; j >= 0; j--) { + CAMHAL_LOGDB(" W x H = %d x %d", caps.tPreviewRes[j].width, caps.tPreviewRes[j].height); + status = NO_ERROR; + for ( i = 0; status == NO_ERROR; i++) { + frmIvalEnum.index = i; + //Check for supported frame rates for the default pixel format. + frmIvalEnum.pixel_format = DEFAULT_PIXEL_FORMAT; + frmIvalEnum.width = caps.tPreviewRes[j].width; + frmIvalEnum.height = caps.tPreviewRes[j].height; + + status = ioctl (handle, VIDIOC_ENUM_FRAMEINTERVALS, &frmIvalEnum); + if(frmIvalEnum.type != V4L2_FRMIVAL_TYPE_DISCRETE) { + break; + } + if (status == NO_ERROR) { + CAMHAL_LOGDB("frmIvalEnum[%d].frame rate= %d)",i, (frmIvalEnum.discrete.denominator/frmIvalEnum.discrete.numerator)); + caps.ulFrameRates[i] = (frmIvalEnum.discrete.denominator/frmIvalEnum.discrete.numerator); + if (caps.ulFrameRates[i] == 30) { + fps30 = true; + } + } + else { + caps.ulFrameRateCount = i; + } + } + if(fps30) { + break; + } + } + + if(frmIvalEnum.type != V4L2_FRMIVAL_TYPE_DISCRETE) { + //TODO: populate the frame rates when type = V4L2_FRMIVAL_TYPE_STEPWISE; + } + + //update the preview resolution with the highest resolution which supports 30fps. +/* // for video preview the application choose the resolution from the mediaprofiles.xml. + // so populating all supported preview resolution is required for video mode. + caps.tPreviewRes[0].width = caps.tPreviewRes[j].width; + caps.tPreviewRes[0].height = caps.tPreviewRes[j].height; + snprintf(caps.tPreviewRes[0].param, MAX_RES_STRING_LENGTH,"%dx%d",caps.tPreviewRes[j].width,caps.tPreviewRes[j].height); + caps.ulPreviewResCount = 1; +*/ + insertCapabilities (params, caps); + return NO_ERROR; +} + + + +} // namespace Camera +} // namespace Ti |