• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
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  * Contains implementation of a class EmulatedQemuCamera that encapsulates
19  * functionality of an emulated camera connected to the host.
20  */
21 
22 #define LOG_NDEBUG 0
23 #define LOG_TAG "EmulatedCamera_QemuCamera"
24 #include <cutils/log.h>
25 #include "EmulatedQemuCamera.h"
26 #include "EmulatedCameraFactory.h"
27 
28 #undef min
29 #undef max
30 #include <sstream>
31 #include <string>
32 #include <vector>
33 
34 namespace android {
35 
EmulatedQemuCamera(int cameraId,struct hw_module_t * module)36 EmulatedQemuCamera::EmulatedQemuCamera(int cameraId, struct hw_module_t* module)
37         : EmulatedCamera(cameraId, module),
38           mQemuCameraDevice(this)
39 {
40 }
41 
~EmulatedQemuCamera()42 EmulatedQemuCamera::~EmulatedQemuCamera()
43 {
44 }
45 
46 /****************************************************************************
47  * EmulatedCamera virtual overrides.
48  ***************************************************************************/
49 
Initialize(const char * device_name,const char * frame_dims,const char * facing_dir)50 status_t EmulatedQemuCamera::Initialize(const char* device_name,
51                                         const char* frame_dims,
52                                         const char* facing_dir)
53 {
54     ALOGV("%s:\n   Name=%s\n   Facing '%s'\n   Dimensions=%s",
55          __FUNCTION__, device_name, facing_dir, frame_dims);
56     /* Save dimensions. */
57     mFrameDims = frame_dims;
58 
59     /* Initialize camera device. */
60     status_t res = mQemuCameraDevice.Initialize(device_name);
61     if (res != NO_ERROR) {
62         return res;
63     }
64 
65     /* Initialize base class. */
66     res = EmulatedCamera::Initialize();
67     if (res != NO_ERROR) {
68         return res;
69     }
70 
71     /*
72      * Set customizable parameters.
73      */
74     using Size = std::pair<int, int>;
75     std::vector<Size> resolutions;
76     std::stringstream ss(frame_dims);
77     std::string input;
78     while (std::getline(ss, input, ',')) {
79         int width = 0;
80         int height = 0;
81         char none = 0;
82         /* Expect only two results because that means there was nothing after
83          * the height, we don't want any trailing characters. Otherwise we just
84          * ignore this entry. */
85         if (sscanf(input.c_str(), "%dx%d%c", &width, &height, &none) == 2) {
86             resolutions.push_back(Size(width, height));
87             ALOGI("%s: %dx%d", __FUNCTION__, width, height);
88         }
89     }
90 
91     /* The Android framework contains a wrapper around the v1 Camera API so that
92      * it can be used with API v2. This wrapper attempts to figure out the
93      * sensor resolution of the camera by looking at the resolution with the
94      * largest area and infer that the dimensions of that resolution must also
95      * be the size of the camera sensor. Any resolution with a dimension that
96      * exceeds the sensor size will be rejected so Camera API calls will start
97      * failing. To work around this we remove any resolutions with at least one
98      * dimension exceeding that of the max area resolution. */
99 
100     /* First find the resolution with the maximum area, the "sensor size" */
101     int maxArea = 0;
102     int maxAreaWidth = 0;
103     int maxAreaHeight = 0;
104     for (const auto& res : resolutions) {
105         int area = res.first * res.second;
106         if (area > maxArea) {
107             maxArea = area;
108             maxAreaWidth = res.first;
109             maxAreaHeight = res.second;
110         }
111     }
112 
113     /* Next remove any resolution with a dimension exceeding the sensor size. */
114     for (auto res = resolutions.begin(); res != resolutions.end(); ) {
115         if (res->first > maxAreaWidth || res->second > maxAreaHeight) {
116             /* Width and/or height larger than sensor, remove it */
117             res = resolutions.erase(res);
118         } else {
119             ++res;
120         }
121     }
122 
123     if (resolutions.empty()) {
124         ALOGE("%s: Qemu camera has no valid resolutions", __FUNCTION__);
125         return EINVAL;
126     }
127 
128     /* Next rebuild the frame size string for the camera parameters */
129     std::stringstream sizesStream;
130     for (size_t i = 0; i < resolutions.size(); ++i) {
131         if (i != 0) {
132             sizesStream << ',';
133         }
134         sizesStream << resolutions[i].first << 'x' << resolutions[i].second;
135     }
136     std::string sizes = sizesStream.str();
137 
138     mParameters.set(EmulatedCamera::FACING_KEY, facing_dir);
139     mParameters.set(EmulatedCamera::ORIENTATION_KEY,
140                     gEmulatedCameraFactory.getQemuCameraOrientation());
141     mParameters.set(CameraParameters::KEY_ROTATION,
142                     gEmulatedCameraFactory.getQemuCameraOrientation());
143     mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
144                     sizes.c_str());
145     mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
146                     sizes.c_str());
147     mParameters.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
148                     sizes.c_str());
149 
150     std::string preferred_size = std::to_string(resolutions[0].first)
151         + "x" + std::to_string(resolutions[0].second);
152     mParameters.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO,
153                     preferred_size.c_str());
154 
155     /*
156      * Use first dimension reported by the device to set current preview and
157      * picture sizes.
158      */
159     int x = resolutions[0].first;
160     int y = resolutions[0].second;
161     mParameters.setPreviewSize(x, y);
162     mParameters.setPictureSize(x, y);
163 
164     ALOGV("%s: Qemu camera %s is initialized. Current frame is %dx%d",
165          __FUNCTION__, device_name, x, y);
166 
167     return NO_ERROR;
168 }
169 
getCameraDevice()170 EmulatedCameraDevice* EmulatedQemuCamera::getCameraDevice()
171 {
172     return &mQemuCameraDevice;
173 }
174 
175 };  /* namespace android */
176