diff options
-rw-r--r-- | camera/Android.mk | 3 | ||||
-rw-r--r-- | camera/V4LCameraAdapter/V4LCameraAdapter.cpp | 110 | ||||
-rw-r--r-- | camera/V4LCameraAdapter/V4LCapabilities.cpp | 261 | ||||
-rw-r--r-- | camera/inc/V4LCameraAdapter/V4LCameraAdapter.h | 65 |
4 files changed, 395 insertions, 44 deletions
diff --git a/camera/Android.mk b/camera/Android.mk index f97b2a9..ea9e2ec 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -65,7 +65,8 @@ OMAP4_CAMERA_OMX_SRC:= \ OMXCameraAdapter/OMXDccDataSave.cpp \ OMAP4_CAMERA_USB_SRC:= \ - V4LCameraAdapter/V4LCameraAdapter.cpp + V4LCameraAdapter/V4LCameraAdapter.cpp \ + V4LCameraAdapter/V4LCapabilities.cpp \ # # OMX Camera HAL diff --git a/camera/V4LCameraAdapter/V4LCameraAdapter.cpp b/camera/V4LCameraAdapter/V4LCameraAdapter.cpp index 18ccf21..af92405 100644 --- a/camera/V4LCameraAdapter/V4LCameraAdapter.cpp +++ b/camera/V4LCameraAdapter/V4LCameraAdapter.cpp @@ -58,7 +58,7 @@ namespace android { //#define SAVE_RAW_FRAMES 1 Mutex gV4LAdapterLock; -const char *device = DEVICE; +char device[15]; /*--------------------Camera Adapter Class STARTS here-----------------------------*/ @@ -636,6 +636,36 @@ int V4LCameraAdapter::previewThread() return ret; } +//scan for video devices +void detectVideoDevice(char** video_device_list, int& num_device) { + char dir_path[20]; + char* filename; + char** dev_list = video_device_list; + DIR *d; + struct dirent *dir; + int index = 0; + + strcpy(dir_path, DEVICE_PATH); + d = opendir(dir_path); + if(d) { + //read each entry in the /dev/ and find if there is videox entry. + while ((dir = readdir(d)) != NULL) { + filename = dir->d_name; + if (strncmp(filename, DEVICE_NAME, 5) == 0) { + strcpy(dev_list[index],DEVICE_PATH); + strncat(dev_list[index],filename,sizeof(DEVICE_NAME)); + index++; + } + } //end of while() + closedir(d); + num_device = index; + + for(int i=0; i<index; i++){ + CAMHAL_LOGDB("Video device list::dev_list[%d]= %s",i,dev_list[i]); + } + } +} + extern "C" CameraAdapter* V4LCameraAdapter_Factory(size_t sensor_index) { CameraAdapter *adapter = NULL; @@ -663,6 +693,10 @@ extern "C" status_t V4LCameraAdapter_Capabilities( struct v4l2_capability cap; int tempHandle = NULL; int num_cameras_supported = 0; + char device_list[5][15]; + char* video_device_list[5]; + int num_v4l_devices = 0; + int sensorId = 0; CameraProperties::Properties* properties = NULL; LOG_FUNCTION_NAME; @@ -676,50 +710,52 @@ extern "C" status_t V4LCameraAdapter_Capabilities( return BAD_VALUE; } + for (int i = 0; i < 5; i++) { + video_device_list[i] = device_list[i]; + } //look for the connected video devices - if (ret == NO_ERROR && (starting_camera + num_cameras_supported) < max_camera) { + detectVideoDevice(video_device_list, num_v4l_devices); - if ((tempHandle = open(device, O_RDWR)) == -1) { - CAMHAL_LOGEB("Error while opening handle to V4L2 Camera: %s", strerror(errno)); - return NO_ERROR; - } + for (int i = 0; i < num_v4l_devices; i++) { + if ( (starting_camera + num_cameras_supported) < max_camera) { + sensorId = starting_camera + num_cameras_supported; - ret = ioctl (tempHandle, VIDIOC_QUERYCAP, &cap); - if (ret < 0) - { - CAMHAL_LOGEA("Error when querying the capabilities of the V4L Camera"); - goto EXIT; - } + CAMHAL_LOGDB("Opening device[%d] = %s..",i, video_device_list[i]); + if ((tempHandle = open(video_device_list[i], O_RDWR)) == -1) { + CAMHAL_LOGEB("Error while opening handle to V4L2 Camera(%s): %s",video_device_list[i], strerror(errno)); + continue; + } - //check for video capture devices - if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) - { - CAMHAL_LOGEA("Error while adapter initialization: video capture not supported."); - goto EXIT; - } + ret = ioctl (tempHandle, VIDIOC_QUERYCAP, &cap); + if (ret < 0) { + CAMHAL_LOGEA("Error when querying the capabilities of the V4L Camera"); + close(tempHandle); + continue; + } + + //check for video capture devices + if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { + CAMHAL_LOGEA("Error while adapter initialization: video capture not supported."); + close(tempHandle); + continue; + } - num_cameras_supported++; - properties = properties_array + starting_camera; - - // TODO: Need to tell camera properties what other cameras we can support - properties->set(CameraProperties::CAMERA_NAME, "USBCAMERA"); - properties->set(CameraProperties::PREVIEW_SIZE, "640x480"); - properties->set(CameraProperties::PREVIEW_FORMAT, "yuv420sp"); - properties->set(CameraProperties::SUPPORTED_PREVIEW_FORMATS, "yuv420sp"); - properties->set(CameraProperties::PICTURE_SIZE, "640x480"); - properties->set(CameraProperties::JPEG_THUMBNAIL_SIZE, "320x240"); - properties->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, "640x480"); - properties->set(CameraProperties::SUPPORTED_PICTURE_SIZES, "640x480"); - properties->set(CameraProperties::REQUIRED_PREVIEW_BUFS, "6"); - properties->set(CameraProperties::FRAMERATE_RANGE_SUPPORTED, "30000,30000"); - properties->set(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES, "30000,30000"); - properties->set(CameraProperties::FRAMERATE_RANGE, "30000,30000"); - properties->set(CameraProperties::PREVIEW_FRAME_RATE, "30000"); + strcpy(device, video_device_list[i]); + properties = properties_array + starting_camera + num_cameras_supported; - } + //fetch capabilities for this camera + V4LCameraAdapter::getCaps( sensorId, properties, tempHandle ); + + num_cameras_supported++; + + } + //For now exit this loop once a valid video capture device is found. + //TODO: find all V4L capture devices and it capabilities + break; + }//end of for() loop supportedCameras = num_cameras_supported; - CAMHAL_LOGDB("V4L cameras detected =%d", num_cameras_supported); + CAMHAL_LOGDB("Number of V4L cameras detected =%d", num_cameras_supported); EXIT: LOG_FUNCTION_NAME_EXIT; diff --git a/camera/V4LCameraAdapter/V4LCapabilities.cpp b/camera/V4LCameraAdapter/V4LCapabilities.cpp new file mode 100644 index 0000000..fdc16d6 --- /dev/null +++ b/camera/V4LCameraAdapter/V4LCapabilities.cpp @@ -0,0 +1,261 @@ +/* + * 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 android { + +/************************************ + * 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[] = "yuv422i"; +const char V4LCameraAdapter::DEFAULT_PREVIEW_SIZE[] = "640x480"; +const char V4LCameraAdapter::DEFAULT_NUM_PREV_BUFS[] = "6"; +const char V4LCameraAdapter::DEFAULT_FRAMERATE[] = "30"; + + +const CapPixelformat V4LCameraAdapter::mPixelformats [] = { + { V4L2_PIX_FMT_YUYV, CameraParameters::PIXEL_FORMAT_YUV422I }, + { V4L2_PIX_FMT_JPEG, 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::CAMERA_NAME, "USBCAMERA"); + params->set(CameraProperties::JPEG_THUMBNAIL_SIZE, "320x240"); + params->set(CameraProperties::FRAMERATE_RANGE_SUPPORTED, "30000,30000"); + params->set(CameraProperties::FRAMERATE_RANGE, "30000,30000"); + 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, CameraParameters::PIXEL_FORMAT_YUV420P, 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++) { + strncat (supported, caps.tPreviewRes[i].param, MAX_PROP_VALUE_LENGTH-1 ); + strncat (supported, PARAM_SEP, 1 ); + } + params->set(CameraProperties::SUPPORTED_PREVIEW_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++) { + strncat (supported, caps.tCaptureRes[i].param, MAX_PROP_VALUE_LENGTH-1 ); + strncat (supported, PARAM_SEP, 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]; + + memset(supported, '\0', MAX_PROP_VALUE_LENGTH); + for (int i = 0; i < caps.ulFrameRateCount; i++) { + snprintf (supported, 10, "%d", caps.ulFrameRates[i]*1000 ); + strncat (supported, PARAM_SEP, 1 ); + } + params->set(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES, 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); + } + + if ( NO_ERROR == ret ) { + ret = insertDefaults(params, caps); + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/***************************************** + * 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; + 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 = V4L2_PIX_FMT_YUYV; + 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 + } + + //get supported frame rates + status = NO_ERROR; + for ( i = 0; status == NO_ERROR; i++) { + frmIvalEnum.index = i; + //Check for supported frame rates for the default pixel format and default image frame size. + //TODO: Check supported frame rates for all supported pixel format + resolution + frmIvalEnum.pixel_format = V4L2_PIX_FMT_YUYV; + frmIvalEnum.width = DEFAULT_WIDTH; + frmIvalEnum.height = DEFAULT_HEIGHT; + status = ioctl (handle, VIDIOC_ENUM_FRAMEINTERVALS, &frmIvalEnum); + if(frmIvalEnum.type != V4L2_FRMIVAL_TYPE_DISCRETE) { + break; + } + if (status == NO_ERROR) { + LOGD("frmIvalEnum[%d].frame rate= %d)",i, (frmIvalEnum.discrete.denominator/frmIvalEnum.discrete.numerator)); + caps.ulFrameRates[i] = (frmIvalEnum.discrete.denominator/frmIvalEnum.discrete.numerator); + } + else { + caps.ulFrameRateCount = i; + } + } + if(frmIvalEnum.type != V4L2_FRMIVAL_TYPE_DISCRETE) { + //TODO: populate the frame rates when type = V4L2_FRMIVAL_TYPE_STEPWISE; + } + + insertCapabilities (params, caps); + return NO_ERROR; +} + + + +}; diff --git a/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h b/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h index 1279bd0..9a16275 100644 --- a/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h +++ b/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h @@ -28,8 +28,28 @@ namespace android { #define DEFAULT_PIXEL_FORMAT V4L2_PIX_FMT_YUYV #define NB_BUFFER 10 -#define DEVICE "/dev/video0" +#define DEVICE "/dev/videoxx" +#define DEVICE_PATH "/dev/" +#define DEVICE_NAME "videoxx" +typedef int V4L_HANDLETYPE; + +struct CapPixelformat { + uint32_t pixelformat; + const char *param; +}; + +struct CapResolution { + size_t width, height; + char param[10]; +}; + +struct CapU32 { + uint32_t num; + const char *param; +}; + +typedef CapU32 CapFramerate; struct VideoInfo { struct v4l2_capability cap; @@ -44,6 +64,16 @@ struct VideoInfo { int framesizeIn; }; +typedef struct V4L_TI_CAPTYPE { + uint16_t ulPreviewFormatCount; // supported preview pixelformat count + uint32_t ePreviewFormats[32]; + uint16_t ulPreviewResCount; // supported preview resolution sizes + CapResolution tPreviewRes[32]; + uint16_t ulCaptureResCount; // supported capture resolution sizes + CapResolution tCaptureRes[32]; + uint16_t ulFrameRateCount; // supported frame rate + uint16_t ulFrameRates[32]; +}V4L_TI_CAPTYPE; /** * Class which completely abstracts the camera hardware interaction from camera hal @@ -79,6 +109,8 @@ public: // API virtual status_t UseBuffersPreview(void* bufArr, int num); + static status_t getCaps(const int sensorId, CameraProperties::Properties* params, V4L_HANDLETYPE handle); + protected: //----------Parent class method implementation------------------------------------ @@ -120,6 +152,28 @@ private: public: private: + //capabilities data + static const CapPixelformat mPixelformats []; + static const CapResolution mPreviewRes []; + static const CapFramerate mFramerates []; + static const CapResolution mImageCapRes []; + + //camera defaults + static const char DEFAULT_PREVIEW_FORMAT[]; + static const char DEFAULT_PREVIEW_SIZE[]; + static const char DEFAULT_FRAMERATE[]; + static const char DEFAULT_NUM_PREV_BUFS[]; + + static const char DEFAULT_PICTURE_FORMAT[]; + static const char DEFAULT_PICTURE_SIZE[]; + + static status_t insertDefaults(CameraProperties::Properties*, V4L_TI_CAPTYPE&); + static status_t insertCapabilities(CameraProperties::Properties*, V4L_TI_CAPTYPE&); + static status_t insertPreviewFormats(CameraProperties::Properties* , V4L_TI_CAPTYPE&); + static status_t insertPreviewSizes(CameraProperties::Properties* , V4L_TI_CAPTYPE&); + static status_t insertImageSizes(CameraProperties::Properties* , V4L_TI_CAPTYPE&); + static status_t insertFrameRates(CameraProperties::Properties* , V4L_TI_CAPTYPE&); + int mPreviewBufferCount; KeyedVector<int, int> mPreviewBufs; mutable Mutex mPreviewBufsLock; @@ -140,12 +194,11 @@ private: int mSensorIndex; - // protected by mLock - sp<PreviewThread> mPreviewThread; - - struct VideoInfo *mVideoInfo; - int mCameraHandle; + // protected by mLock + sp<PreviewThread> mPreviewThread; + struct VideoInfo *mVideoInfo; + int mCameraHandle; int nQueued; int nDequeued; |