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 
29 namespace Ti {
30 namespace 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 
41 static const char PARAM_SEP[] = ",";
42 
43 //Camera defaults
44 const char V4LCameraAdapter::DEFAULT_PICTURE_FORMAT[] = "jpeg";
45 const char V4LCameraAdapter::DEFAULT_PICTURE_SIZE[] = "640x480";
46 const char V4LCameraAdapter::DEFAULT_PREVIEW_FORMAT[] = "yuv422i-yuyv";
47 const char V4LCameraAdapter::DEFAULT_PREVIEW_SIZE[] = "640x480";
48 const char V4LCameraAdapter::DEFAULT_NUM_PREV_BUFS[] = "6";
49 const char V4LCameraAdapter::DEFAULT_FRAMERATE[] = "30";
50 const char V4LCameraAdapter::DEFAULT_FOCUS_MODE[] = "infinity";
51 const char * V4LCameraAdapter::DEFAULT_VSTAB = android::CameraParameters::FALSE;
52 const char * V4LCameraAdapter::DEFAULT_VNF = android::CameraParameters::FALSE;
53 
54 
55 const 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 
insertDefaults(CameraProperties::Properties * params,V4L_TI_CAPTYPE & caps)66 status_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 
insertPreviewFormats(CameraProperties::Properties * params,V4L_TI_CAPTYPE & caps)104 status_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 
insertPreviewSizes(CameraProperties::Properties * params,V4L_TI_CAPTYPE & caps)122 status_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 
insertImageSizes(CameraProperties::Properties * params,V4L_TI_CAPTYPE & caps)139 status_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 
insertFrameRates(CameraProperties::Properties * params,V4L_TI_CAPTYPE & caps)154 status_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 
insertCapabilities(CameraProperties::Properties * params,V4L_TI_CAPTYPE & caps)172 status_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 
sortAscend(V4L_TI_CAPTYPE & caps,uint16_t count)208 status_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 
getCaps(const int sensorId,CameraProperties::Properties * params,V4L_HANDLETYPE handle)237 status_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