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