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 an abstract class EmulatedCameraDevice that defines
19 * functionality expected from an emulated physical camera device:
20 * - Obtaining and setting camera parameters
21 * - Capturing frames
22 * - Streaming video
23 * - etc.
24 */
25
26 #define LOG_NDEBUG 0
27 #define LOG_TAG "EmulatedCamera_Device"
28 #include <cutils/log.h>
29 #include <sys/select.h>
30 #include <cmath>
31 #include "Alignment.h"
32 #include "EmulatedCamera.h"
33 #include "EmulatedCameraDevice.h"
34
35 #undef min
36 #undef max
37 #include <algorithm>
38
39 namespace android {
40
41 const float GAMMA_CORRECTION = 2.2f;
EmulatedCameraDevice(EmulatedCamera * camera_hal)42 EmulatedCameraDevice::EmulatedCameraDevice(EmulatedCamera* camera_hal)
43 : mObjectLock(),
44 mCameraHAL(camera_hal),
45 mExposureCompensation(1.0f),
46 mWhiteBalanceScale(NULL),
47 mSupportedWhiteBalanceScale(),
48 mState(ECDS_CONSTRUCTED),
49 mTriggerAutoFocus(false)
50 {
51 }
52
~EmulatedCameraDevice()53 EmulatedCameraDevice::~EmulatedCameraDevice()
54 {
55 ALOGV("EmulatedCameraDevice destructor");
56 for (size_t i = 0; i < mSupportedWhiteBalanceScale.size(); ++i) {
57 if (mSupportedWhiteBalanceScale.valueAt(i) != NULL) {
58 delete[] mSupportedWhiteBalanceScale.valueAt(i);
59 }
60 }
61 }
62
63 /****************************************************************************
64 * Emulated camera device public API
65 ***************************************************************************/
66
Initialize()67 status_t EmulatedCameraDevice::Initialize()
68 {
69 if (isInitialized()) {
70 ALOGW("%s: Emulated camera device is already initialized: mState = %d",
71 __FUNCTION__, mState);
72 return NO_ERROR;
73 }
74
75 mState = ECDS_INITIALIZED;
76
77 return NO_ERROR;
78 }
79
startDeliveringFrames(bool one_burst)80 status_t EmulatedCameraDevice::startDeliveringFrames(bool one_burst)
81 {
82 ALOGV("%s", __FUNCTION__);
83
84 if (!isStarted()) {
85 ALOGE("%s: Device is not started", __FUNCTION__);
86 return EINVAL;
87 }
88
89 /* Frames will be delivered from the thread routine. */
90 const status_t res = startWorkerThread(one_burst);
91 ALOGE_IF(res != NO_ERROR, "%s: startWorkerThread failed", __FUNCTION__);
92 return res;
93 }
94
stopDeliveringFrames()95 status_t EmulatedCameraDevice::stopDeliveringFrames()
96 {
97 ALOGV("%s", __FUNCTION__);
98
99 if (!isStarted()) {
100 ALOGW("%s: Device is not started", __FUNCTION__);
101 return NO_ERROR;
102 }
103
104 const status_t res = stopWorkerThread();
105 ALOGE_IF(res != NO_ERROR, "%s: stopWorkerThread failed", __FUNCTION__);
106 return res;
107 }
108
setPreviewFrameRate(int framesPerSecond)109 status_t EmulatedCameraDevice::setPreviewFrameRate(int framesPerSecond) {
110 if (framesPerSecond <= 0) {
111 return EINVAL;
112 }
113 mFramesPerSecond = framesPerSecond;
114 return NO_ERROR;
115 }
116
setExposureCompensation(const float ev)117 void EmulatedCameraDevice::setExposureCompensation(const float ev) {
118 ALOGV("%s", __FUNCTION__);
119
120 if (!isStarted()) {
121 ALOGW("%s: Fake camera device is not started.", __FUNCTION__);
122 }
123
124 mExposureCompensation = std::pow(2.0f, ev / GAMMA_CORRECTION);
125 ALOGV("New exposure compensation is %f", mExposureCompensation);
126 }
127
initializeWhiteBalanceModes(const char * mode,const float r_scale,const float b_scale)128 void EmulatedCameraDevice::initializeWhiteBalanceModes(const char* mode,
129 const float r_scale,
130 const float b_scale) {
131 ALOGV("%s with %s, %f, %f", __FUNCTION__, mode, r_scale, b_scale);
132 float* value = new float[3];
133 value[0] = r_scale; value[1] = 1.0f; value[2] = b_scale;
134 mSupportedWhiteBalanceScale.add(String8(mode), value);
135 }
136
setWhiteBalanceMode(const char * mode)137 void EmulatedCameraDevice::setWhiteBalanceMode(const char* mode) {
138 ALOGV("%s with white balance %s", __FUNCTION__, mode);
139 mWhiteBalanceScale =
140 mSupportedWhiteBalanceScale.valueFor(String8(mode));
141 }
142
143 /* Computes the pixel value after adjusting the white balance to the current
144 * one. The input the y, u, v channel of the pixel and the adjusted value will
145 * be stored in place. The adjustment is done in RGB space.
146 */
changeWhiteBalance(uint8_t & y,uint8_t & u,uint8_t & v) const147 void EmulatedCameraDevice::changeWhiteBalance(uint8_t& y,
148 uint8_t& u,
149 uint8_t& v) const {
150 float r_scale = mWhiteBalanceScale[0];
151 float b_scale = mWhiteBalanceScale[2];
152 int r = static_cast<float>(YUV2R(y, u, v)) / r_scale;
153 int g = YUV2G(y, u, v);
154 int b = static_cast<float>(YUV2B(y, u, v)) / b_scale;
155
156 y = RGB2Y(r, g, b);
157 u = RGB2U(r, g, b);
158 v = RGB2V(r, g, b);
159 }
160
checkAutoFocusTrigger()161 void EmulatedCameraDevice::checkAutoFocusTrigger() {
162 // The expected value is a reference so we need it to be a variable
163 bool expectedTrigger = true;
164 if (mTriggerAutoFocus.compare_exchange_strong(expectedTrigger, false)) {
165 // If the compare exchange returns true then the value was the expected
166 // 'true' and was successfully set to 'false'. So that means it's time
167 // to trigger an auto-focus event and that we have disabled that trigger
168 // so it won't happen until another request is received.
169 mCameraHAL->autoFocusComplete();
170 }
171 }
172
getCurrentFrameImpl(const uint8_t * source,uint8_t * dest,uint32_t pixelFormat) const173 status_t EmulatedCameraDevice::getCurrentFrameImpl(const uint8_t* source,
174 uint8_t* dest,
175 uint32_t pixelFormat) const {
176 if (pixelFormat == mPixelFormat) {
177 memcpy(dest, source, mFrameBufferSize);
178 return NO_ERROR;
179 } else if (pixelFormat == V4L2_PIX_FMT_YUV420 &&
180 mPixelFormat == V4L2_PIX_FMT_YVU420) {
181 // Convert from YV12 to YUV420 without alignment
182 const int ySize = mYStride * mFrameHeight;
183 const int uvSize = mUVStride * (mFrameHeight / 2);
184 if (mYStride == mFrameWidth) {
185 // Copy Y straight up
186 memcpy(dest, source, ySize);
187 } else {
188 // Strip alignment
189 for (int y = 0; y < mFrameHeight; ++y) {
190 memcpy(dest + y * mFrameWidth,
191 source + y * mYStride,
192 mFrameWidth);
193 }
194 }
195
196 if (mUVStride == mFrameWidth / 2) {
197 // Swap U and V
198 memcpy(dest + ySize, source + ySize + uvSize, uvSize);
199 memcpy(dest + ySize + uvSize, source + ySize, uvSize);
200 } else {
201 // Strip alignment
202 uint8_t* uvDest = dest + mFrameWidth * mFrameHeight;
203 const uint8_t* uvSource = source + ySize + uvSize;
204
205 for (int i = 0; i < 2; ++i) {
206 for (int y = 0; y < mFrameHeight / 2; ++y) {
207 memcpy(uvDest + y * (mFrameWidth / 2),
208 uvSource + y * mUVStride,
209 mFrameWidth / 2);
210 }
211 uvDest += (mFrameHeight / 2) * (mFrameWidth / 2);
212 uvSource -= uvSize;
213 }
214 }
215 return NO_ERROR;
216 }
217 ALOGE("%s: Invalid pixel format conversion [%.4s to %.4s] requested",
218 __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat),
219 reinterpret_cast<const char*>(&pixelFormat));
220 return EINVAL;
221 }
222
getCurrentFrame(void * buffer,uint32_t pixelFormat)223 status_t EmulatedCameraDevice::getCurrentFrame(void* buffer,
224 uint32_t pixelFormat)
225 {
226 if (!isStarted()) {
227 ALOGE("%s: Device is not started", __FUNCTION__);
228 return EINVAL;
229 }
230 if (buffer == nullptr) {
231 ALOGE("%s: Invalid buffer provided", __FUNCTION__);
232 return EINVAL;
233 }
234
235 FrameLock lock(*this);
236 const void* source = mCameraThread->getPrimaryBuffer();
237 if (source == nullptr) {
238 ALOGE("%s: No framebuffer", __FUNCTION__);
239 return EINVAL;
240 }
241 return getCurrentFrameImpl(reinterpret_cast<const uint8_t*>(source),
242 reinterpret_cast<uint8_t*>(buffer),
243 pixelFormat);
244 }
245
getCurrentPreviewFrame(void * buffer)246 status_t EmulatedCameraDevice::getCurrentPreviewFrame(void* buffer)
247 {
248 if (!isStarted()) {
249 ALOGE("%s: Device is not started", __FUNCTION__);
250 return EINVAL;
251 }
252 if (buffer == nullptr) {
253 ALOGE("%s: Invalid buffer provided", __FUNCTION__);
254 return EINVAL;
255 }
256
257 FrameLock lock(*this);
258 const void* currentFrame = mCameraThread->getPrimaryBuffer();
259 if (currentFrame == nullptr) {
260 ALOGE("%s: No framebuffer", __FUNCTION__);
261 return EINVAL;
262 }
263
264 /* In emulation the framebuffer is never RGB. */
265 switch (mPixelFormat) {
266 case V4L2_PIX_FMT_YVU420:
267 YV12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
268 return NO_ERROR;
269 case V4L2_PIX_FMT_YUV420:
270 YU12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
271 return NO_ERROR;
272 case V4L2_PIX_FMT_NV21:
273 NV21ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
274 return NO_ERROR;
275 case V4L2_PIX_FMT_NV12:
276 NV12ToRGB32(currentFrame, buffer, mFrameWidth, mFrameHeight);
277 return NO_ERROR;
278
279 default:
280 ALOGE("%s: Unknown pixel format %.4s",
281 __FUNCTION__, reinterpret_cast<const char*>(&mPixelFormat));
282 return EINVAL;
283 }
284 }
285
getCurrentFrame()286 const void* EmulatedCameraDevice::getCurrentFrame() {
287 if (mCameraThread.get()) {
288 return mCameraThread->getPrimaryBuffer();
289 }
290 return nullptr;
291 }
292
FrameLock(EmulatedCameraDevice & cameraDevice)293 EmulatedCameraDevice::FrameLock::FrameLock(EmulatedCameraDevice& cameraDevice)
294 : mCameraDevice(cameraDevice) {
295 mCameraDevice.lockCurrentFrame();
296 }
297
~FrameLock()298 EmulatedCameraDevice::FrameLock::~FrameLock() {
299 mCameraDevice.unlockCurrentFrame();
300 }
301
setAutoFocus()302 status_t EmulatedCameraDevice::setAutoFocus() {
303 mTriggerAutoFocus = true;
304 return NO_ERROR;
305 }
306
cancelAutoFocus()307 status_t EmulatedCameraDevice::cancelAutoFocus() {
308 mTriggerAutoFocus = false;
309 return NO_ERROR;
310 }
311
requestRestart(int width,int height,uint32_t pixelFormat,bool takingPicture,bool oneBurst)312 bool EmulatedCameraDevice::requestRestart(int width, int height,
313 uint32_t pixelFormat,
314 bool takingPicture, bool oneBurst) {
315 if (mCameraThread.get() == nullptr) {
316 ALOGE("%s: No thread alive to perform the restart, is preview on?",
317 __FUNCTION__);
318 return false;
319 }
320 mCameraThread->requestRestart(width, height, pixelFormat,
321 takingPicture, oneBurst);
322 return true;
323 }
324
325 /****************************************************************************
326 * Emulated camera device private API
327 ***************************************************************************/
328
commonStartDevice(int width,int height,uint32_t pix_fmt)329 status_t EmulatedCameraDevice::commonStartDevice(int width,
330 int height,
331 uint32_t pix_fmt)
332 {
333 /* Validate pixel format, and calculate framebuffer size at the same time. */
334 switch (pix_fmt) {
335 case V4L2_PIX_FMT_YVU420:
336 case V4L2_PIX_FMT_YUV420:
337 // For these pixel formats the strides have to be aligned to 16 byte
338 // boundaries as per the format specification
339 // https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12
340 mYStride = align(width, 16);
341 mUVStride = align(mYStride / 2, 16);
342 // The second term should use half the height but since there are
343 // two planes the multiplication with two cancels that out
344 mFrameBufferSize = mYStride * height + mUVStride * height;
345 break;
346 case V4L2_PIX_FMT_NV21:
347 case V4L2_PIX_FMT_NV12:
348 mYStride = width;
349 // Because of interleaving the UV stride is the same as the Y stride
350 // since it covers two pixels, one U and one V.
351 mUVStride = mYStride;
352 // Since the U/V stride covers both U and V we don't multiply by two
353 mFrameBufferSize = mYStride * height + mUVStride * (height / 2);
354 break;
355 default:
356 ALOGE("%s: Unknown pixel format %.4s",
357 __FUNCTION__, reinterpret_cast<const char*>(&pix_fmt));
358 return EINVAL;
359 }
360
361 /* Cache framebuffer info. */
362 mFrameWidth = width;
363 mFrameHeight = height;
364 mPixelFormat = pix_fmt;
365 mTotalPixels = width * height;
366
367 /* Allocate framebuffer. */
368 mFrameBuffers[0].resize(mFrameBufferSize);
369 mFrameBuffers[1].resize(mFrameBufferSize);
370 ALOGV("%s: Allocated %zu bytes for %d pixels in %.4s[%dx%d] frame",
371 __FUNCTION__, mFrameBufferSize, mTotalPixels,
372 reinterpret_cast<const char*>(&mPixelFormat), mFrameWidth, mFrameHeight);
373 return NO_ERROR;
374 }
375
commonStopDevice()376 void EmulatedCameraDevice::commonStopDevice()
377 {
378 mFrameWidth = mFrameHeight = mTotalPixels = 0;
379 mPixelFormat = 0;
380
381 mFrameBuffers[0].clear();
382 mFrameBuffers[1].clear();
383 // No need to keep all that memory allocated if the camera isn't running
384 mFrameBuffers[0].shrink_to_fit();
385 mFrameBuffers[1].shrink_to_fit();
386 }
387
388 /****************************************************************************
389 * Worker thread management.
390 ***************************************************************************/
391
startWorkerThread(bool one_burst)392 status_t EmulatedCameraDevice::startWorkerThread(bool one_burst)
393 {
394 ALOGV("%s", __FUNCTION__);
395
396 if (!isInitialized()) {
397 ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
398 return EINVAL;
399 }
400
401 mCameraThread = new CameraThread(this, staticProduceFrame, this);
402 if (mCameraThread == NULL) {
403 ALOGE("%s: Unable to instantiate CameraThread object", __FUNCTION__);
404 return ENOMEM;
405 }
406 status_t res = mCameraThread->startThread(one_burst);
407 if (res != NO_ERROR) {
408 ALOGE("%s: Unable to start CameraThread: %s",
409 __FUNCTION__, strerror(res));
410 return res;
411 }
412
413 return res;
414 }
415
stopWorkerThread()416 status_t EmulatedCameraDevice::stopWorkerThread()
417 {
418 ALOGV("%s", __FUNCTION__);
419
420 if (!isInitialized()) {
421 ALOGE("%s: Emulated camera device is not initialized", __FUNCTION__);
422 return EINVAL;
423 }
424
425 status_t res = mCameraThread->stopThread();
426 if (res != NO_ERROR) {
427 ALOGE("%s: Unable to stop CameraThread", __FUNCTION__);
428 return res;
429 }
430 res = mCameraThread->joinThread();
431 if (res != NO_ERROR) {
432 ALOGE("%s: Unable to join CameraThread", __FUNCTION__);
433 return res;
434 }
435
436 // Destroy the thread as well
437 mCameraThread.clear();
438 return res;
439 }
440
CameraThread(EmulatedCameraDevice * dev,ProduceFrameFunc producer,void * producerOpaque)441 EmulatedCameraDevice::CameraThread::CameraThread(EmulatedCameraDevice* dev,
442 ProduceFrameFunc producer,
443 void* producerOpaque)
444 : WorkerThread("Camera_CameraThread", dev, dev->mCameraHAL),
445 mCurFrameTimestamp(0),
446 mProducerFunc(producer),
447 mProducerOpaque(producerOpaque),
448 mRestartWidth(0),
449 mRestartHeight(0),
450 mRestartPixelFormat(0),
451 mRestartOneBurst(false),
452 mRestartTakingPicture(false),
453 mRestartRequested(false) {
454
455 }
456
getPrimaryBuffer() const457 const void* EmulatedCameraDevice::CameraThread::getPrimaryBuffer() const {
458 if (mFrameProducer.get()) {
459 return mFrameProducer->getPrimaryBuffer();
460 }
461 return nullptr;
462 }
463
lockPrimaryBuffer()464 void EmulatedCameraDevice::CameraThread::lockPrimaryBuffer() {
465 mFrameProducer->lockPrimaryBuffer();
466 }
467
unlockPrimaryBuffer()468 void EmulatedCameraDevice::CameraThread::unlockPrimaryBuffer() {
469 mFrameProducer->unlockPrimaryBuffer();
470 }
471
472 bool
waitForFrameOrTimeout(nsecs_t timeout)473 EmulatedCameraDevice::CameraThread::waitForFrameOrTimeout(nsecs_t timeout) {
474 // Keep waiting until the frame producer indicates that a frame is available
475 // This does introduce some unnecessary latency to the first frame delivery
476 // but avoids a lot of thread synchronization.
477 do {
478 // We don't have any specific fd we want to select so we pass in -1
479 // timeout is in nanoseconds but Select expects microseconds
480 Mutex::Autolock lock(mRunningMutex);
481 mRunningCondition.waitRelative(mRunningMutex, timeout);
482 if (!mRunning) {
483 ALOGV("%s: CameraThread has been terminated.", __FUNCTION__);
484 return false;
485 }
486 // Set a short timeout in case there is no frame available and we are
487 // going to loop. This way we ensure a sleep but keep a decent latency
488 timeout = milliseconds(5);
489 } while (!mFrameProducer->hasFrame());
490
491 return true;
492 }
493
inWorkerThread()494 bool EmulatedCameraDevice::CameraThread::inWorkerThread() {
495 /* Wait till FPS timeout expires, or thread exit message is received. */
496 nsecs_t wakeAt =
497 mCurFrameTimestamp + 1000000000.0 / mCameraDevice->mFramesPerSecond;
498 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
499 nsecs_t timeout = std::max<nsecs_t>(0, wakeAt - now);
500
501 if (!waitForFrameOrTimeout(timeout)) {
502 return false;
503 }
504
505 /* Check if a restart and potentially apply the requested changes */
506 if (!checkRestartRequest()) {
507 return false;
508 }
509
510 /* Check if an auto-focus event needs to be triggered */
511 mCameraDevice->checkAutoFocusTrigger();
512
513 mCurFrameTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
514 mCameraHAL->onNextFrameAvailable(mCurFrameTimestamp, mCameraDevice);
515
516 return true;
517 }
518
onThreadStart()519 status_t EmulatedCameraDevice::CameraThread::onThreadStart() {
520 void* primaryBuffer = mCameraDevice->getPrimaryBuffer();
521 void* secondaryBuffer = mCameraDevice->getSecondaryBuffer();
522 mFrameProducer = new FrameProducer(mCameraDevice,
523 mProducerFunc, mProducerOpaque,
524 primaryBuffer, secondaryBuffer);
525 if (mFrameProducer.get() == nullptr) {
526 ALOGE("%s: Could not instantiate FrameProducer object", __FUNCTION__);
527 return ENOMEM;
528 }
529 return mFrameProducer->startThread(mOneBurst);
530 }
531
onThreadExit()532 void EmulatedCameraDevice::CameraThread::onThreadExit() {
533 if (mFrameProducer.get()) {
534 if (mFrameProducer->stopThread() == NO_ERROR) {
535 mFrameProducer->joinThread();
536 mFrameProducer.clear();
537 }
538 }
539 }
540
FrameProducer(EmulatedCameraDevice * dev,ProduceFrameFunc producer,void * opaque,void * primaryBuffer,void * secondaryBuffer)541 EmulatedCameraDevice::CameraThread::FrameProducer::FrameProducer(
542 EmulatedCameraDevice* dev,
543 ProduceFrameFunc producer,
544 void* opaque,
545 void* primaryBuffer,
546 void* secondaryBuffer)
547 : WorkerThread("Camera_FrameProducer", dev, dev->mCameraHAL),
548 mProducer(producer),
549 mOpaque(opaque),
550 mPrimaryBuffer(primaryBuffer),
551 mSecondaryBuffer(secondaryBuffer),
552 mLastFrame(0),
553 mHasFrame(false) {
554
555 }
556
557 const void*
getPrimaryBuffer() const558 EmulatedCameraDevice::CameraThread::FrameProducer::getPrimaryBuffer() const {
559 return mPrimaryBuffer;
560 }
561
lockPrimaryBuffer()562 void EmulatedCameraDevice::CameraThread::FrameProducer::lockPrimaryBuffer() {
563 mBufferMutex.lock();
564 }
unlockPrimaryBuffer()565 void EmulatedCameraDevice::CameraThread::FrameProducer::unlockPrimaryBuffer() {
566 mBufferMutex.unlock();
567 }
568
requestRestart(int width,int height,uint32_t pixelFormat,bool takingPicture,bool oneBurst)569 void EmulatedCameraDevice::CameraThread::requestRestart(int width,
570 int height,
571 uint32_t pixelFormat,
572 bool takingPicture,
573 bool oneBurst) {
574 Mutex::Autolock lock(mRequestMutex);
575 mRestartWidth = width;
576 mRestartHeight = height;
577 mRestartPixelFormat = pixelFormat;
578 mRestartTakingPicture = takingPicture;
579 mRestartOneBurst = oneBurst;
580 mRestartRequested = true;
581 }
582
hasFrame() const583 bool EmulatedCameraDevice::CameraThread::FrameProducer::hasFrame() const {
584 return mHasFrame;
585 }
586
checkRestartRequest()587 bool EmulatedCameraDevice::CameraThread::checkRestartRequest() {
588 Mutex::Autolock lock(mRequestMutex);
589 if (mRestartRequested) {
590 mRestartRequested = false;
591 status_t res = mFrameProducer->stopThread();
592 if (res != NO_ERROR) {
593 ALOGE("%s: Could not stop frame producer thread", __FUNCTION__);
594 mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
595 return false;
596 }
597 res = mFrameProducer->joinThread();
598 if (res != NO_ERROR) {
599 ALOGE("%s: Could not join frame producer thread", __FUNCTION__);
600 mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
601 return false;
602 }
603 mFrameProducer.clear();
604 res = mCameraDevice->stopDevice();
605 if (res != NO_ERROR) {
606 ALOGE("%s: Could not stop device", __FUNCTION__);
607 mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
608 return false;
609 }
610 res = mCameraDevice->startDevice(mRestartWidth,
611 mRestartHeight,
612 mRestartPixelFormat);
613 if (res != NO_ERROR) {
614 ALOGE("%s: Could not start device", __FUNCTION__);
615 mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
616 return false;
617 }
618 if (mRestartTakingPicture) {
619 mCameraHAL->setTakingPicture(true);
620 }
621 mOneBurst = mRestartOneBurst;
622
623 // Pretend like this a thread start, performs the remaining setup
624 if (onThreadStart() != NO_ERROR) {
625 mCameraDevice->stopDevice();
626 mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
627 return false;
628 }
629
630 // Now wait for the frame producer to start producing before we proceed
631 return waitForFrameOrTimeout(0);
632 }
633 return true;
634 }
635
inWorkerThread()636 bool EmulatedCameraDevice::CameraThread::FrameProducer::inWorkerThread() {
637 nsecs_t nextFrame =
638 mLastFrame + 1000000000 / mCameraDevice->mFramesPerSecond;
639 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
640 nsecs_t timeout = std::max<nsecs_t>(0, nextFrame - now);
641
642 {
643 Mutex::Autolock lock(mRunningMutex);
644 mRunningCondition.waitRelative(mRunningMutex, timeout);
645 if (!mRunning) {
646 ALOGV("%s: FrameProducer has been terminated.", __FUNCTION__);
647 return false;
648 }
649 }
650
651 // Produce one frame and place it in the secondary buffer
652 mLastFrame = systemTime(SYSTEM_TIME_MONOTONIC);
653 if (!mProducer(mOpaque, mSecondaryBuffer)) {
654 ALOGE("FrameProducer could not produce frame, exiting thread");
655 mCameraHAL->onCameraDeviceError(CAMERA_ERROR_SERVER_DIED);
656 return false;
657 }
658
659 {
660 // Switch buffers now that the secondary buffer is ready
661 Mutex::Autolock lock(mBufferMutex);
662 std::swap(mPrimaryBuffer, mSecondaryBuffer);
663 }
664 mHasFrame = true;
665 return true;
666 }
667
lockCurrentFrame()668 void EmulatedCameraDevice::lockCurrentFrame() {
669 mCameraThread->lockPrimaryBuffer();
670 }
671
unlockCurrentFrame()672 void EmulatedCameraDevice::unlockCurrentFrame() {
673 mCameraThread->unlockPrimaryBuffer();
674 }
675
676 }; /* namespace android */
677