07837afd91bac66bb4100664ee12ac0bd9fe9343
[iec.git] / src / type3_AndroidCloud / anbox-master / android / camera / EmulatedQemuCameraDevice.cpp
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 EmulatedQemuCameraDevice that encapsulates
19  * an emulated camera device connected to the host.
20  */
21
22 #define LOG_NDEBUG 0
23 #define LOG_TAG "EmulatedCamera_QemuDevice"
24 #include <cutils/log.h>
25 #include "EmulatedQemuCamera.h"
26 #include "EmulatedQemuCameraDevice.h"
27
28 namespace android {
29
30 EmulatedQemuCameraDevice::EmulatedQemuCameraDevice(EmulatedQemuCamera* camera_hal)
31     : EmulatedCameraDevice(camera_hal),
32       mQemuClient(),
33       mPreviewFrame(NULL)
34 {
35 }
36
37 EmulatedQemuCameraDevice::~EmulatedQemuCameraDevice()
38 {
39     if (mPreviewFrame != NULL) {
40         delete[] mPreviewFrame;
41     }
42 }
43
44 /****************************************************************************
45  * Public API
46  ***************************************************************************/
47
48 status_t EmulatedQemuCameraDevice::Initialize(const char* device_name)
49 {
50     /* Connect to the service. */
51     char connect_str[256];
52     snprintf(connect_str, sizeof(connect_str), "name=%s", device_name);
53     status_t res = mQemuClient.connectClient(connect_str);
54     if (res != NO_ERROR) {
55         return res;
56     }
57
58     /* Initialize base class. */
59     res = EmulatedCameraDevice::Initialize();
60     if (res == NO_ERROR) {
61         ALOGV("%s: Connected to the emulated camera service '%s'",
62              __FUNCTION__, device_name);
63         mDeviceName = device_name;
64     } else {
65         mQemuClient.queryDisconnect();
66     }
67
68     return res;
69 }
70
71 /****************************************************************************
72  * Emulated camera device abstract interface implementation.
73  ***************************************************************************/
74
75 status_t EmulatedQemuCameraDevice::connectDevice()
76 {
77     ALOGV("%s", __FUNCTION__);
78
79     Mutex::Autolock locker(&mObjectLock);
80     if (!isInitialized()) {
81         ALOGE("%s: Qemu camera device is not initialized.", __FUNCTION__);
82         return EINVAL;
83     }
84     if (isConnected()) {
85         ALOGW("%s: Qemu camera device '%s' is already connected.",
86              __FUNCTION__, (const char*)mDeviceName);
87         return NO_ERROR;
88     }
89
90     /* Connect to the camera device via emulator. */
91     const status_t res = mQemuClient.queryConnect();
92     if (res == NO_ERROR) {
93         ALOGV("%s: Connected to device '%s'",
94              __FUNCTION__, (const char*)mDeviceName);
95         mState = ECDS_CONNECTED;
96     } else {
97         ALOGE("%s: Connection to device '%s' failed",
98              __FUNCTION__, (const char*)mDeviceName);
99     }
100
101     return res;
102 }
103
104 status_t EmulatedQemuCameraDevice::disconnectDevice()
105 {
106     ALOGV("%s", __FUNCTION__);
107
108     Mutex::Autolock locker(&mObjectLock);
109     if (!isConnected()) {
110         ALOGW("%s: Qemu camera device '%s' is already disconnected.",
111              __FUNCTION__, (const char*)mDeviceName);
112         return NO_ERROR;
113     }
114     if (isStarted()) {
115         ALOGE("%s: Cannot disconnect from the started device '%s.",
116              __FUNCTION__, (const char*)mDeviceName);
117         return EINVAL;
118     }
119
120     /* Disconnect from the camera device via emulator. */
121     const status_t res = mQemuClient.queryDisconnect();
122     if (res == NO_ERROR) {
123         ALOGV("%s: Disonnected from device '%s'",
124              __FUNCTION__, (const char*)mDeviceName);
125         mState = ECDS_INITIALIZED;
126     } else {
127         ALOGE("%s: Disconnection from device '%s' failed",
128              __FUNCTION__, (const char*)mDeviceName);
129     }
130
131     return res;
132 }
133
134 status_t EmulatedQemuCameraDevice::startDevice(int width,
135                                                int height,
136                                                uint32_t pix_fmt)
137 {
138     ALOGV("%s", __FUNCTION__);
139
140     Mutex::Autolock locker(&mObjectLock);
141     if (!isConnected()) {
142         ALOGE("%s: Qemu camera device '%s' is not connected.",
143              __FUNCTION__, (const char*)mDeviceName);
144         return EINVAL;
145     }
146     if (isStarted()) {
147         ALOGW("%s: Qemu camera device '%s' is already started.",
148              __FUNCTION__, (const char*)mDeviceName);
149         return NO_ERROR;
150     }
151
152     status_t res = EmulatedCameraDevice::commonStartDevice(width, height, pix_fmt);
153     if (res != NO_ERROR) {
154         ALOGE("%s: commonStartDevice failed", __FUNCTION__);
155         return res;
156     }
157
158     /* Allocate preview frame buffer. */
159     /* TODO: Watch out for preview format changes! At this point we implement
160      * RGB32 only.*/
161     mPreviewFrame = new uint32_t[mTotalPixels];
162     if (mPreviewFrame == NULL) {
163         ALOGE("%s: Unable to allocate %d bytes for preview frame",
164              __FUNCTION__, mTotalPixels);
165         return ENOMEM;
166     }
167
168     /* Start the actual camera device. */
169     res = mQemuClient.queryStart(mPixelFormat, mFrameWidth, mFrameHeight);
170     if (res == NO_ERROR) {
171         ALOGV("%s: Qemu camera device '%s' is started for %.4s[%dx%d] frames",
172              __FUNCTION__, (const char*)mDeviceName,
173              reinterpret_cast<const char*>(&mPixelFormat),
174              mFrameWidth, mFrameHeight);
175         mState = ECDS_STARTED;
176     } else {
177         ALOGE("%s: Unable to start device '%s' for %.4s[%dx%d] frames",
178              __FUNCTION__, (const char*)mDeviceName,
179              reinterpret_cast<const char*>(&pix_fmt), width, height);
180     }
181
182     return res;
183 }
184
185 status_t EmulatedQemuCameraDevice::stopDevice()
186 {
187     ALOGV("%s", __FUNCTION__);
188
189     Mutex::Autolock locker(&mObjectLock);
190     if (!isStarted()) {
191         ALOGW("%s: Qemu camera device '%s' is not started.",
192              __FUNCTION__, (const char*)mDeviceName);
193         return NO_ERROR;
194     }
195
196     /* Stop the actual camera device. */
197     status_t res = mQemuClient.queryStop();
198     if (res == NO_ERROR) {
199         if (mPreviewFrame == NULL) {
200             delete[] mPreviewFrame;
201             mPreviewFrame = NULL;
202         }
203         EmulatedCameraDevice::commonStopDevice();
204         mState = ECDS_CONNECTED;
205         ALOGV("%s: Qemu camera device '%s' is stopped",
206              __FUNCTION__, (const char*)mDeviceName);
207     } else {
208         ALOGE("%s: Unable to stop device '%s'",
209              __FUNCTION__, (const char*)mDeviceName);
210     }
211
212     return res;
213 }
214
215 /****************************************************************************
216  * EmulatedCameraDevice virtual overrides
217  ***************************************************************************/
218
219 status_t EmulatedQemuCameraDevice::getCurrentPreviewFrame(void* buffer)
220 {
221     ALOGW_IF(mPreviewFrame == NULL, "%s: No preview frame", __FUNCTION__);
222     if (mPreviewFrame != NULL) {
223         memcpy(buffer, mPreviewFrame, mTotalPixels * 4);
224         return 0;
225     } else {
226         return EmulatedCameraDevice::getCurrentPreviewFrame(buffer);
227     }
228 }
229
230 /****************************************************************************
231  * Worker thread management overrides.
232  ***************************************************************************/
233
234 bool EmulatedQemuCameraDevice::inWorkerThread()
235 {
236     /* Wait till FPS timeout expires, or thread exit message is received. */
237     WorkerThread::SelectRes res =
238         getWorkerThread()->Select(-1, 1000000 / mEmulatedFPS);
239     if (res == WorkerThread::EXIT_THREAD) {
240         ALOGV("%s: Worker thread has been terminated.", __FUNCTION__);
241         return false;
242     }
243
244     /* Query frames from the service. */
245     status_t query_res = mQemuClient.queryFrame(mCurrentFrame, mPreviewFrame,
246                                                  mFrameBufferSize,
247                                                  mTotalPixels * 4,
248                                                  mWhiteBalanceScale[0],
249                                                  mWhiteBalanceScale[1],
250                                                  mWhiteBalanceScale[2],
251                                                  mExposureCompensation);
252     if (query_res == NO_ERROR) {
253         /* Timestamp the current frame, and notify the camera HAL. */
254         mCurFrameTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
255         mCameraHAL->onNextFrameAvailable(mCurrentFrame, mCurFrameTimestamp, this);
256         return true;
257     } else {
258         ALOGE("%s: Unable to get current video frame: %s",
259              __FUNCTION__, strerror(query_res));
260         mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
261         return false;
262     }
263 }
264
265 }; /* namespace android */