1/*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18* @file V4LCapabilities.cpp
19*
20* This file implements the V4L Capabilities feature.
21*
22*/
23
24#include "CameraHal.h"
25#include "V4LCameraAdapter.h"
26#include "ErrorUtils.h"
27#include "TICameraParameters.h"
28
29namespace Ti {
30namespace Camera {
31
32/************************************
33 * global constants and variables
34 *************************************/
35
36#define ARRAY_SIZE(array) (sizeof((array)) / sizeof((array)[0]))
37#define MAX_RES_STRING_LENGTH 10
38#define DEFAULT_WIDTH 640
39#define DEFAULT_HEIGHT 480
40
41static const char PARAM_SEP[] = ",";
42
43//Camera defaults
44const char V4LCameraAdapter::DEFAULT_PICTURE_FORMAT[] = "jpeg";
45const char V4LCameraAdapter::DEFAULT_PICTURE_SIZE[] = "640x480";
46const char V4LCameraAdapter::DEFAULT_PREVIEW_FORMAT[] = "yuv422i-yuyv";
47const char V4LCameraAdapter::DEFAULT_PREVIEW_SIZE[] = "640x480";
48const char V4LCameraAdapter::DEFAULT_NUM_PREV_BUFS[] = "6";
49const char V4LCameraAdapter::DEFAULT_FRAMERATE[] = "30";
50const char V4LCameraAdapter::DEFAULT_FOCUS_MODE[] = "infinity";
51const char * V4LCameraAdapter::DEFAULT_VSTAB = android::CameraParameters::FALSE;
52const char * V4LCameraAdapter::DEFAULT_VNF = android::CameraParameters::FALSE;
53
54
55const CapPixelformat V4LCameraAdapter::mPixelformats [] = {
56    { V4L2_PIX_FMT_YUYV, android::CameraParameters::PIXEL_FORMAT_YUV422I },
57    { V4L2_PIX_FMT_JPEG, android::CameraParameters::PIXEL_FORMAT_JPEG },
58};
59
60/*****************************************
61 * internal static function declarations
62 *****************************************/
63
64/**** Utility functions to help translate V4L Caps to Parameter ****/
65
66status_t V4LCameraAdapter::insertDefaults(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps)
67{
68    status_t ret = NO_ERROR;
69    LOG_FUNCTION_NAME;
70
71    params->set(CameraProperties::PREVIEW_FORMAT, DEFAULT_PREVIEW_FORMAT);
72
73    params->set(CameraProperties::PICTURE_FORMAT, DEFAULT_PICTURE_FORMAT);
74    params->set(CameraProperties::PICTURE_SIZE, DEFAULT_PICTURE_SIZE);
75    params->set(CameraProperties::PREVIEW_SIZE, DEFAULT_PREVIEW_SIZE);
76    params->set(CameraProperties::PREVIEW_FRAME_RATE, DEFAULT_FRAMERATE);
77    params->set(CameraProperties::REQUIRED_PREVIEW_BUFS, DEFAULT_NUM_PREV_BUFS);
78    params->set(CameraProperties::FOCUS_MODE, DEFAULT_FOCUS_MODE);
79
80    params->set(CameraProperties::CAMERA_NAME, "USBCAMERA");
81    params->set(CameraProperties::JPEG_THUMBNAIL_SIZE, "320x240");
82    params->set(CameraProperties::JPEG_QUALITY, "90");
83    params->set(CameraProperties::JPEG_THUMBNAIL_QUALITY, "50");
84    params->set(CameraProperties::FRAMERATE_RANGE_SUPPORTED, "(30000,30000)");
85    params->set(CameraProperties::FRAMERATE_RANGE, "30000,30000");
86    params->set(CameraProperties::S3D_PRV_FRAME_LAYOUT, "none");
87    params->set(CameraProperties::SUPPORTED_EXPOSURE_MODES, "auto");
88    params->set(CameraProperties::SUPPORTED_ISO_VALUES, "auto");
89    params->set(CameraProperties::SUPPORTED_ANTIBANDING, "auto");
90    params->set(CameraProperties::SUPPORTED_EFFECTS, "none");
91    params->set(CameraProperties::SUPPORTED_IPP_MODES, "ldc-nsf");
92    params->set(CameraProperties::FACING_INDEX, TICameraParameters::FACING_FRONT);
93    params->set(CameraProperties::ORIENTATION_INDEX, 0);
94    params->set(CameraProperties::SENSOR_ORIENTATION, "0");
95    params->set(CameraProperties::VSTAB, DEFAULT_VSTAB);
96    params->set(CameraProperties::VNF, DEFAULT_VNF);
97
98
99    LOG_FUNCTION_NAME_EXIT;
100
101    return ret;
102}
103
104status_t V4LCameraAdapter::insertPreviewFormats(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) {
105
106    char supported[MAX_PROP_VALUE_LENGTH];
107
108    memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
109    for (int i = 0; i < caps.ulPreviewFormatCount; i++) {
110        for (unsigned int j = 0; j < ARRAY_SIZE(mPixelformats); j++) {
111            if(caps.ePreviewFormats[i] == mPixelformats[j].pixelformat ) {
112                strncat (supported, mPixelformats[j].param, MAX_PROP_VALUE_LENGTH-1 );
113                strncat (supported, PARAM_SEP, 1 );
114            }
115        }
116    }
117    strncat(supported, android::CameraParameters::PIXEL_FORMAT_YUV420P, MAX_PROP_VALUE_LENGTH - 1);
118    params->set(CameraProperties::SUPPORTED_PREVIEW_FORMATS, supported);
119    return NO_ERROR;
120}
121
122status_t V4LCameraAdapter::insertPreviewSizes(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) {
123
124    char supported[MAX_PROP_VALUE_LENGTH];
125
126    memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
127    for (int i = 0; i < caps.ulPreviewResCount; i++) {
128        if (supported[0] != '\0') {
129            strncat(supported, PARAM_SEP, 1);
130        }
131        strncat (supported, caps.tPreviewRes[i].param, MAX_PROP_VALUE_LENGTH-1 );
132    }
133
134    params->set(CameraProperties::SUPPORTED_PREVIEW_SIZES, supported);
135    params->set(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES, supported);
136    return NO_ERROR;
137}
138
139status_t V4LCameraAdapter::insertImageSizes(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) {
140
141    char supported[MAX_PROP_VALUE_LENGTH];
142
143    memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
144    for (int i = 0; i < caps.ulCaptureResCount; i++) {
145        if (supported[0] != '\0') {
146            strncat(supported, PARAM_SEP, 1);
147        }
148        strncat (supported, caps.tCaptureRes[i].param, MAX_PROP_VALUE_LENGTH-1 );
149    }
150    params->set(CameraProperties::SUPPORTED_PICTURE_SIZES, supported);
151    return NO_ERROR;
152}
153
154status_t V4LCameraAdapter::insertFrameRates(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps) {
155
156    char supported[MAX_PROP_VALUE_LENGTH];
157    char temp[10];
158
159    memset(supported, '\0', MAX_PROP_VALUE_LENGTH);
160    for (int i = 0; i < caps.ulFrameRateCount; i++) {
161        snprintf (temp, 10, "%d", caps.ulFrameRates[i] );
162        if (supported[0] != '\0') {
163            strncat(supported, PARAM_SEP, 1);
164        }
165        strncat (supported, temp, MAX_PROP_VALUE_LENGTH-1 );
166    }
167
168    params->set(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES, supported);
169    return NO_ERROR;
170}
171
172status_t V4LCameraAdapter::insertCapabilities(CameraProperties::Properties* params, V4L_TI_CAPTYPE &caps)
173{
174    status_t ret = NO_ERROR;
175
176    LOG_FUNCTION_NAME;
177
178    if ( NO_ERROR == ret ) {
179        ret = insertPreviewFormats(params, caps);
180    }
181
182    if ( NO_ERROR == ret ) {
183        ret = insertImageSizes(params, caps);
184    }
185
186    if ( NO_ERROR == ret ) {
187        ret = insertPreviewSizes(params, caps);
188    }
189
190    if ( NO_ERROR == ret ) {
191        ret = insertFrameRates(params, caps);
192    }
193
194    //Insert Supported Focus modes.
195    params->set(CameraProperties::SUPPORTED_FOCUS_MODES, "infinity");
196
197    params->set(CameraProperties::SUPPORTED_PICTURE_FORMATS, "jpeg");
198
199    if ( NO_ERROR == ret ) {
200        ret = insertDefaults(params, caps);
201    }
202
203    LOG_FUNCTION_NAME_EXIT;
204
205    return ret;
206}
207
208status_t V4LCameraAdapter::sortAscend(V4L_TI_CAPTYPE &caps, uint16_t count) {
209    size_t tempRes;
210    size_t w, h, tmpW,tmpH;
211    for (int i=0; i<count; i++) {
212        w = caps.tPreviewRes[i].width;
213        h = caps.tPreviewRes[i].height;
214        tempRes = w*h;
215        for (int j=i+1; j<count; j++) {
216            tmpW = caps.tPreviewRes[j].width;
217            tmpH = caps.tPreviewRes[j].height;
218
219            if (tempRes > (tmpW * tmpH) ) {
220                caps.tPreviewRes[j].width = w;
221                caps.tPreviewRes[j].height = h;
222                w = tmpW;
223                h = tmpH;
224                }
225            }
226        caps.tPreviewRes[i].width = w;
227        caps.tPreviewRes[i].height = h;
228
229        }
230    return NO_ERROR;
231}
232
233/*****************************************
234 * public exposed function declarations
235 *****************************************/
236
237status_t V4LCameraAdapter::getCaps(const int sensorId, CameraProperties::Properties* params,
238                                   V4L_HANDLETYPE handle) {
239     status_t status = NO_ERROR;
240     V4L_TI_CAPTYPE caps;
241     int i = 0;
242     int j = 0;
243     struct v4l2_fmtdesc fmtDesc;
244     struct v4l2_frmsizeenum frmSizeEnum;
245     struct v4l2_frmivalenum frmIvalEnum;
246
247    //get supported pixel formats
248    for ( i = 0; status == NO_ERROR; i++) {
249        fmtDesc.index = i;
250        fmtDesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
251        status = ioctl (handle, VIDIOC_ENUM_FMT, &fmtDesc);
252        if (status == NO_ERROR) {
253            CAMHAL_LOGDB("fmtDesc[%d].description::pixelformat::flags== (%s::%d::%d)",i, fmtDesc.description,fmtDesc.pixelformat,fmtDesc.flags);
254            caps.ePreviewFormats[i] = fmtDesc.pixelformat;
255        }
256    }
257    caps.ulPreviewFormatCount = i;
258
259    //get preview sizes & capture image sizes
260    status = NO_ERROR;
261    for ( i = 0; status == NO_ERROR; i++) {
262        frmSizeEnum.index = i;
263        //Check for frame sizes for default pixel format
264        //TODO: Check for frame sizes for all supported pixel formats
265        frmSizeEnum.pixel_format = V4L2_PIX_FMT_YUYV;
266        status = ioctl (handle, VIDIOC_ENUM_FRAMESIZES, &frmSizeEnum);
267        if (status == NO_ERROR) {
268            int width;
269            int height;
270
271            if(frmSizeEnum.type != V4L2_FRMSIZE_TYPE_DISCRETE) {
272                CAMHAL_LOGDB("\nfrmSizeEnum.type = %d", frmSizeEnum.type);
273                CAMHAL_LOGDB("\nmin_width x height = %d x %d ",frmSizeEnum.stepwise.min_width, frmSizeEnum.stepwise.min_height);
274                CAMHAL_LOGDB("\nmax_width x height = %d x %d ",frmSizeEnum.stepwise.max_width, frmSizeEnum.stepwise.max_height);
275                CAMHAL_LOGDB("\nstep width x height = %d x %d ",frmSizeEnum.stepwise.step_width,frmSizeEnum.stepwise.step_height);
276                //TODO: validate populating the sizes when type = V4L2_FRMSIZE_TYPE_STEPWISE
277                width = frmSizeEnum.stepwise.max_width;
278                height = frmSizeEnum.stepwise.max_height;
279            }
280            else {
281                CAMHAL_LOGDB("frmSizeEnum.index[%d].width x height == (%d x %d)", i, frmSizeEnum.discrete.width, frmSizeEnum.discrete.height);
282                width = frmSizeEnum.discrete.width;
283                height = frmSizeEnum.discrete.height;
284            }
285
286            caps.tCaptureRes[i].width = width;
287            caps.tCaptureRes[i].height = height;
288            caps.tPreviewRes[i].width =  width;
289            caps.tPreviewRes[i].height = height;
290
291            snprintf(caps.tPreviewRes[i].param, MAX_RES_STRING_LENGTH,"%dx%d",caps.tPreviewRes[i].width,caps.tPreviewRes[i].height);
292            snprintf(caps.tCaptureRes[i].param, MAX_RES_STRING_LENGTH,"%dx%d",caps.tCaptureRes[i].width,caps.tCaptureRes[i].height);
293        }
294        else {
295            caps.ulCaptureResCount = i;
296            caps.ulPreviewResCount = i;
297        }
298    }
299
300    //sort the preview sizes in ascending order
301    sortAscend(caps, caps.ulPreviewResCount);
302
303    //get supported frame rates
304    bool fps30 = false;
305    for ( j=caps.ulPreviewResCount-1; j >= 0; j--) {
306        CAMHAL_LOGDB(" W x H = %d x %d", caps.tPreviewRes[j].width, caps.tPreviewRes[j].height);
307        status = NO_ERROR;
308        for ( i = 0; status == NO_ERROR; i++) {
309            frmIvalEnum.index = i;
310            //Check for supported frame rates for the default pixel format.
311            frmIvalEnum.pixel_format = V4L2_PIX_FMT_YUYV;
312            frmIvalEnum.width = caps.tPreviewRes[j].width;
313            frmIvalEnum.height = caps.tPreviewRes[j].height;
314
315            status = ioctl (handle, VIDIOC_ENUM_FRAMEINTERVALS, &frmIvalEnum);
316            if (status == NO_ERROR) {
317                if(frmIvalEnum.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
318                    CAMHAL_LOGDB("frmIvalEnum[%d].type = %d)", i, frmIvalEnum.type);
319                    CAMHAL_LOGDB("frmIvalEnum[%d].stepwise.min = %d/%d)", i, frmIvalEnum.stepwise.min.denominator, frmIvalEnum.stepwise.min.numerator);
320                    CAMHAL_LOGDB("frmIvalEnum[%d].stepwise.max = %d/%d)", i, frmIvalEnum.stepwise.max.denominator, frmIvalEnum.stepwise.max.numerator);
321                    CAMHAL_LOGDB("frmIvalEnum[%d].stepwise.step = %d/%d)", i, frmIvalEnum.stepwise.step.denominator, frmIvalEnum.stepwise.step.numerator);
322                    caps.ulFrameRates[i] = (frmIvalEnum.stepwise.max.denominator/frmIvalEnum.stepwise.max.numerator);
323                }
324                else {
325                    CAMHAL_LOGDB("frmIvalEnum[%d].frame rate= %d)",i, (frmIvalEnum.discrete.denominator/frmIvalEnum.discrete.numerator));
326                    caps.ulFrameRates[i] = (frmIvalEnum.discrete.denominator/frmIvalEnum.discrete.numerator);
327                }
328
329                if (caps.ulFrameRates[i] == 30) {
330                    fps30 = true;
331                }
332            }
333            else if (i == 0) {
334                // Framerate reporting is not guaranteed in V4L2 implementation.
335                caps.ulFrameRates[i] = 30;
336                fps30 = true;
337                caps.ulFrameRateCount = 1;
338            } else {
339                CAMHAL_LOGE("caps.ulFrameRateCount = %d",i);
340                caps.ulFrameRateCount = i;
341            }
342        }
343        if(fps30) {
344            break;
345        }
346    }
347
348    if(frmIvalEnum.type != V4L2_FRMIVAL_TYPE_DISCRETE) {
349        //TODO: populate the frame rates when type = V4L2_FRMIVAL_TYPE_STEPWISE;
350    }
351
352    //update the preview resolution with the highest resolution which supports 30fps.
353/*  // for video preview the application choose the resolution from the mediaprofiles.xml.
354    // so populating all supported preview resolution is required for video mode.
355    caps.tPreviewRes[0].width = caps.tPreviewRes[j].width;
356    caps.tPreviewRes[0].height = caps.tPreviewRes[j].height;
357    snprintf(caps.tPreviewRes[0].param, MAX_RES_STRING_LENGTH,"%dx%d",caps.tPreviewRes[j].width,caps.tPreviewRes[j].height);
358    caps.ulPreviewResCount = 1;
359*/
360    insertCapabilities (params, caps);
361    return NO_ERROR;
362}
363
364
365
366} // namespace Camera
367} // namespace Ti
368