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 #ifndef HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H 18 #define HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H 19 20 /* 21 * Contains declaration of an abstract class EmulatedCameraDevice that defines 22 * functionality expected from an emulated physical camera device: 23 * - Obtaining and setting camera device parameters 24 * - Capturing frames 25 * - Streaming video 26 * - etc. 27 */ 28 29 #include <utils/KeyedVector.h> 30 #include <utils/String8.h> 31 #include <utils/threads.h> 32 #include "Converters.h" 33 #include "EmulatedCameraCommon.h" 34 35 #include "guest/libs/platform_support/api_level_fixes.h" 36 #if VSOC_PLATFORM_SDK_BEFORE(O_MR1) 37 #include <camera/CameraParameters.h> 38 #else 39 #include <CameraParameters.h> 40 41 using ::android::hardware::camera::common::V1_0::helper::CameraParameters; 42 #endif 43 44 namespace android { 45 46 class EmulatedCamera; 47 48 /* Encapsulates an abstract class EmulatedCameraDevice that defines 49 * functionality expected from an emulated physical camera device: 50 * - Obtaining and setting camera device parameters 51 * - Capturing frames 52 * - Streaming video 53 * - etc. 54 */ 55 class EmulatedCameraDevice { 56 public: 57 /* Constructs EmulatedCameraDevice instance. 58 * Param: 59 * camera_hal - Emulated camera that implements the camera HAL API, and 60 * manages (contains) this object. 61 */ 62 explicit EmulatedCameraDevice(EmulatedCamera* camera_hal); 63 64 /* Destructs EmulatedCameraDevice instance. */ 65 virtual ~EmulatedCameraDevice(); 66 67 /*************************************************************************** 68 * Emulated camera device abstract interface 69 **************************************************************************/ 70 71 public: 72 /* Connects to the camera device. 73 * This method must be called on an initialized instance of this class. 74 * Return: 75 * NO_ERROR on success, or an appropriate error status. 76 */ 77 virtual status_t connectDevice() = 0; 78 79 /* Disconnects from the camera device. 80 * Return: 81 * NO_ERROR on success, or an appropriate error status. If this method is 82 * called for already disconnected, or uninitialized instance of this class, 83 * a successful status must be returned from this method. If this method is 84 * called for an instance that is in the "started" state, this method must 85 * return a failure. 86 */ 87 virtual status_t disconnectDevice() = 0; 88 89 /* Starts the camera device. 90 * This method tells the camera device to start capturing frames of the given 91 * dimensions for the given pixel format. Note that this method doesn't start 92 * the delivery of the captured frames to the emulated camera. Call 93 * startDeliveringFrames method to start delivering frames. This method must 94 * be called on a connected instance of this class. If it is called on a 95 * disconnected instance, this method must return a failure. 96 * Param: 97 * width, height - Frame dimensions to use when capturing video frames. 98 * pix_fmt - Pixel format to use when capturing video frames. 99 * fps - Target rate of frames per second. 100 * Return: 101 * NO_ERROR on success, or an appropriate error status. 102 */ 103 virtual status_t startDevice(int width, int height, uint32_t pix_fmt, 104 int fps) = 0; 105 106 /* Stops the camera device. 107 * This method tells the camera device to stop capturing frames. Note that 108 * this method doesn't stop delivering frames to the emulated camera. Always 109 * call stopDeliveringFrames prior to calling this method. 110 * Return: 111 * NO_ERROR on success, or an appropriate error status. If this method is 112 * called for an object that is not capturing frames, or is disconnected, 113 * or is uninitialized, a successful status must be returned from this 114 * method. 115 */ 116 virtual status_t stopDevice() = 0; 117 118 /*************************************************************************** 119 * Emulated camera device public API 120 **************************************************************************/ 121 122 public: 123 /* Initializes EmulatedCameraDevice instance. 124 * Derived classes should override this method in order to cache static 125 * properties of the physical device (list of supported pixel formats, frame 126 * sizes, etc.) If this method is called on an already initialized instance, 127 * it must return a successful status. 128 * Return: 129 * NO_ERROR on success, or an appropriate error status. 130 */ 131 virtual status_t Initialize(); 132 133 /* Initializes the white balance modes parameters. 134 * The parameters are passed by each individual derived camera API to 135 * represent that different camera manufacturers may have different 136 * preferences on the white balance parameters. Green channel in the RGB 137 * color space is fixed to keep the luminance to be reasonably constant. 138 * 139 * Param: 140 * mode the text describing the current white balance mode 141 * r_scale the scale factor for the R channel in RGB space 142 * b_scale the scale factor for the B channel in RGB space. 143 */ 144 void initializeWhiteBalanceModes(const char* mode, const float r_scale, 145 const float b_scale); 146 147 /* Starts delivering frames captured from the camera device. 148 * This method will start the worker thread that would be pulling frames from 149 * the camera device, and will deliver the pulled frames back to the emulated 150 * camera via onNextFrameAvailable callback. This method must be called on a 151 * connected instance of this class with a started camera device. If it is 152 * called on a disconnected instance, or camera device has not been started, 153 * this method must return a failure. 154 * Param: 155 * one_burst - Controls how many frames should be delivered. If this 156 * parameter is 'true', only one captured frame will be delivered to the 157 * emulated camera. If this parameter is 'false', frames will keep 158 * coming until stopDeliveringFrames method is called. Typically, this 159 * parameter is set to 'true' only in order to obtain a single frame 160 * that will be used as a "picture" in takePicture method of the 161 * emulated camera. 162 * Return: 163 * NO_ERROR on success, or an appropriate error status. 164 */ 165 virtual status_t startDeliveringFrames(bool one_burst); 166 167 /* Stops delivering frames captured from the camera device. 168 * This method will stop the worker thread started by startDeliveringFrames. 169 * Return: 170 * NO_ERROR on success, or an appropriate error status. 171 */ 172 virtual status_t stopDeliveringFrames(); 173 174 /* Sets the exposure compensation for the camera device. 175 */ 176 void setExposureCompensation(const float ev); 177 178 /* Sets the white balance mode for the device. 179 */ 180 void setWhiteBalanceMode(const char* mode); 181 182 /* Initiates focus operation. 183 */ 184 virtual void startAutoFocus(); 185 186 /* Gets current framebuffer, converted into preview frame format. 187 * This method must be called on a connected instance of this class with a 188 * started camera device. If it is called on a disconnected instance, or 189 * camera device has not been started, this method must return a failure. 190 * Note that this method should be called only after at least one frame has 191 * been captured and delivered. Otherwise it will return garbage in the 192 * preview frame buffer. Typically, this method shuld be called from 193 * onNextFrameAvailable callback. 194 * Param: 195 * buffer - Buffer, large enough to contain the entire preview frame. 196 * Return: 197 * NO_ERROR on success, or an appropriate error status. 198 */ 199 virtual status_t getCurrentPreviewFrame(void* buffer); 200 201 /* Gets width of the frame obtained from the physical device. 202 * Return: 203 * Width of the frame obtained from the physical device. Note that value 204 * returned from this method is valid only in case if camera device has been 205 * started. 206 */ getFrameWidth()207 inline int getFrameWidth() const { 208 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); 209 return mFrameWidth; 210 } 211 212 /* Gets height of the frame obtained from the physical device. 213 * Return: 214 * Height of the frame obtained from the physical device. Note that value 215 * returned from this method is valid only in case if camera device has been 216 * started. 217 */ getFrameHeight()218 inline int getFrameHeight() const { 219 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); 220 return mFrameHeight; 221 } 222 223 /* Gets byte size of the current frame buffer. 224 * Return: 225 * Byte size of the frame buffer. Note that value returned from this method 226 * is valid only in case if camera device has been started. 227 */ getFrameBufferSize()228 inline size_t getFrameBufferSize() const { 229 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); 230 return mFrameBufferSize; 231 } 232 233 /* Gets number of pixels in the current frame buffer. 234 * Return: 235 * Number of pixels in the frame buffer. Note that value returned from this 236 * method is valid only in case if camera device has been started. 237 */ getPixelNum()238 inline int getPixelNum() const { 239 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); 240 return mTotalPixels; 241 } 242 243 /* Gets pixel format of the frame that camera device streams to this class. 244 * Throughout camera framework, there are three different forms of pixel 245 * format representation: 246 * - Original format, as reported by the actual camera device. Values for 247 * this format are declared in bionic/libc/kernel/common/linux/videodev2.h 248 * - String representation as defined in CameraParameters::PIXEL_FORMAT_XXX 249 * strings in frameworks/base/include/camera/CameraParameters.h 250 * - HAL_PIXEL_FORMAT_XXX format, as defined in 251 * system/core/include/system/graphics.h Since emulated camera device gets its 252 * data from the actual device, it gets pixel format in the original form. And 253 * that's the pixel format representation that will be returned from this 254 * method. HAL components will need to translate value returned from this 255 * method to the appropriate form. This method must be called only on started 256 * instance of this class, since it's applicable only when camera device is 257 * ready to stream frames. Param: pix_fmt - Upon success contains the original 258 * pixel format. Return: Current framebuffer's pixel format. Note that value 259 * returned from this method is valid only in case if camera device has been 260 * started. 261 */ getOriginalPixelFormat()262 inline uint32_t getOriginalPixelFormat() const { 263 ALOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__); 264 return mPixelFormat; 265 } 266 267 /* Gets image metadata (from HAL). 268 * Return: 269 * Filled in ImageMetadata structure (in/out parameter). 270 */ 271 const CameraParameters* getCameraParameters(); 272 273 /* 274 * State checkers. 275 */ 276 isInitialized()277 inline bool isInitialized() const { 278 /* Instance is initialized when the worker thread has been successfuly 279 * created (but not necessarily started). */ 280 return mWorkerThread.get() != NULL && mState != ECDS_CONSTRUCTED; 281 } isConnected()282 inline bool isConnected() const { 283 /* Instance is connected when its status is either"connected", or 284 * "started". */ 285 return mState == ECDS_CONNECTED || mState == ECDS_STARTED; 286 } isStarted()287 inline bool isStarted() const { return mState == ECDS_STARTED; } 288 289 /**************************************************************************** 290 * Emulated camera device private API 291 ***************************************************************************/ 292 protected: 293 /* Performs common validation and calculation of startDevice parameters. 294 * Param: 295 * width, height, pix_fmt, fps - Parameters passed to startDevice method. 296 * Return: 297 * NO_ERROR on success, or an appropriate error status. 298 */ 299 virtual status_t commonStartDevice(int width, int height, uint32_t pix_fmt, 300 int fps); 301 302 /* Performs common cleanup on stopDevice. 303 * This method will undo what commonStartDevice had done. 304 */ 305 virtual void commonStopDevice(); 306 307 /** Computes a luminance value after taking the exposure compensation. 308 * value into account. 309 * 310 * Param: 311 * inputY - The input luminance value. 312 * Return: 313 * The luminance value after adjusting the exposure compensation. 314 */ changeExposure(const uint8_t & inputY)315 inline uint8_t changeExposure(const uint8_t& inputY) const { 316 return static_cast<uint8_t>( 317 clamp(static_cast<float>(inputY) * mExposureCompensation)); 318 } 319 320 /** Simulates focusing and reports completion to the client. 321 */ 322 void simulateAutoFocus(); 323 324 /** Computes the pixel value in YUV space after adjusting to the current 325 * white balance mode. 326 */ 327 void changeWhiteBalance(uint8_t& y, uint8_t& u, uint8_t& v) const; 328 329 /**************************************************************************** 330 * Worker thread management. 331 * Typicaly when emulated camera device starts capturing frames from the 332 * actual device, it does that in a worker thread created in StartCapturing, 333 * and terminated in StopCapturing. Since this is such a typical scenario, 334 * it makes sence to encapsulate worker thread management in the base class 335 * for all emulated camera devices. 336 ***************************************************************************/ 337 338 protected: 339 /* Starts the worker thread. 340 * Typically, worker thread is started from startDeliveringFrames method of 341 * this class. 342 * Param: 343 * one_burst - Controls how many times thread loop should run. If this 344 * parameter is 'true', thread routine will run only once If this 345 * parameter is 'false', thread routine will run until stopWorkerThread 346 * method is called. See startDeliveringFrames for more info. 347 * Return: 348 * NO_ERROR on success, or an appropriate error status. 349 */ 350 virtual status_t startWorkerThread(bool one_burst); 351 352 /* Stops the worker thread. 353 * Note that this method will always wait for the worker thread to terminate. 354 * Typically, worker thread is started from stopDeliveringFrames method of 355 * this class. 356 * Return: 357 * NO_ERROR on success, or an appropriate error status. 358 */ 359 virtual status_t stopWorkerThread(); 360 361 /* Implementation of the worker thread routine. 362 * In the default implementation of the worker thread routine we simply 363 * return 'false' forcing the thread loop to exit, and the thread to 364 * terminate. Derived class should override that method to provide there the 365 * actual frame delivery. 366 * Return: 367 * true To continue thread loop (this method will be called again), or false 368 * to exit the thread loop and to terminate the thread. 369 */ 370 virtual bool inWorkerThread(); 371 372 /* Encapsulates a worker thread used by the emulated camera device. 373 */ 374 friend class WorkerThread; 375 class WorkerThread : public Thread { 376 /**************************************************************************** 377 * Public API 378 ***************************************************************************/ 379 380 public: WorkerThread(EmulatedCameraDevice * camera_dev)381 inline explicit WorkerThread(EmulatedCameraDevice* camera_dev) 382 : Thread(true), // Callbacks may involve Java calls. 383 mCameraDevice(camera_dev), 384 mThreadControl(-1), 385 mControlFD(-1) {} 386 ~WorkerThread()387 inline ~WorkerThread() { 388 ALOGW_IF(mThreadControl >= 0 || mControlFD >= 0, 389 "%s: Control FDs are opened in the destructor", __FUNCTION__); 390 if (mThreadControl >= 0) { 391 close(mThreadControl); 392 } 393 if (mControlFD >= 0) { 394 close(mControlFD); 395 } 396 } 397 398 /* Starts the thread 399 * Param: 400 * one_burst - Controls how many times thread loop should run. If 401 * this parameter is 'true', thread routine will run only once 402 * If this parameter is 'false', thread routine will run until 403 * stopThread method is called. See startWorkerThread for more 404 * info. 405 * Return: 406 * NO_ERROR on success, or an appropriate error status. 407 */ startThread(bool one_burst)408 inline status_t startThread(bool one_burst) { 409 mOneBurst = one_burst; 410 return run("Camera_startThread", ANDROID_PRIORITY_URGENT_DISPLAY, 0); 411 } 412 413 /* Overriden base class method. 414 * It is overriden in order to provide one-time initialization just 415 * prior to starting the thread routine. 416 */ 417 status_t readyToRun(); 418 419 /* Stops the thread. */ 420 status_t stopThread(); 421 422 /* Values returned from the Select method of this class. */ 423 enum SelectRes { 424 /* A timeout has occurred. */ 425 TIMEOUT, 426 /* Data are available for read on the provided FD. */ 427 READY, 428 /* Thread exit request has been received. */ 429 EXIT_THREAD, 430 /* An error has occurred. */ 431 ERROR 432 }; 433 434 /* Select on an FD event, keeping in mind thread exit message. 435 * Param: 436 * fd - File descriptor on which to wait for an event. This 437 * parameter may be negative. If it is negative this method will 438 * only wait on a control message to the thread. 439 * timeout - Timeout in microseconds. 0 indicates no timeout (wait 440 * forever). 441 * Return: 442 * See SelectRes enum comments. 443 */ 444 SelectRes Select(int fd, int timeout); 445 446 /**************************************************************************** 447 * Private API 448 ***************************************************************************/ 449 450 private: 451 /* Implements abstract method of the base Thread class. */ threadLoop()452 bool threadLoop() { 453 /* Simply dispatch the call to the containing camera device. */ 454 if (mCameraDevice->inWorkerThread()) { 455 /* Respect "one burst" parameter (see startThread). */ 456 return !mOneBurst; 457 } else { 458 return false; 459 } 460 } 461 462 /* Containing camera device object. */ 463 EmulatedCameraDevice* mCameraDevice; 464 465 /* FD that is used to send control messages into the thread. */ 466 int mThreadControl; 467 468 /* FD that thread uses to receive control messages. */ 469 int mControlFD; 470 471 /* Controls number of times the thread loop runs. 472 * See startThread for more information. */ 473 bool mOneBurst; 474 475 /* Enumerates control messages that can be sent into the thread. */ 476 enum ControlMessage { 477 /* Stop the thread. */ 478 THREAD_STOP 479 }; 480 481 Condition mSetup; 482 }; 483 484 /* Worker thread accessor. */ getWorkerThread()485 inline WorkerThread* getWorkerThread() const { return mWorkerThread.get(); } 486 487 /**************************************************************************** 488 * Data members 489 ***************************************************************************/ 490 491 protected: 492 /* Locks this instance for parameters, state, etc. change. */ 493 Mutex mObjectLock; 494 495 /* Worker thread that is used in frame capturing. */ 496 sp<WorkerThread> mWorkerThread; 497 498 /* Timestamp of the current frame. */ 499 nsecs_t mCurFrameTimestamp; 500 501 /* Emulated camera object containing this instance. */ 502 EmulatedCamera* mCameraHAL; 503 504 /* Framebuffer containing the current frame. */ 505 uint8_t* mCurrentFrame; 506 507 /* 508 * Framebuffer properties. 509 */ 510 511 /* Byte size of the framebuffer. */ 512 size_t mFrameBufferSize; 513 514 /* Original pixel format (one of the V4L2_PIX_FMT_XXX values, as defined in 515 * bionic/libc/kernel/common/linux/videodev2.h */ 516 uint32_t mPixelFormat; 517 518 /* Frame width */ 519 int mFrameWidth; 520 521 /* Frame height */ 522 int mFrameHeight; 523 524 /* Total number of pixels */ 525 int mTotalPixels; 526 527 /* Requested FPS rate */ 528 int mTargetFps; 529 530 /* Exposure compensation value */ 531 float mExposureCompensation; 532 533 float* mWhiteBalanceScale; 534 535 bool mIsFocusing; 536 537 DefaultKeyedVector<String8, float*> mSupportedWhiteBalanceScale; 538 539 /* Defines possible states of the emulated camera device object. 540 */ 541 enum EmulatedCameraDeviceState { 542 /* Object has been constructed. */ 543 ECDS_CONSTRUCTED, 544 /* Object has been initialized. */ 545 ECDS_INITIALIZED, 546 /* Object has been connected to the physical device. */ 547 ECDS_CONNECTED, 548 /* Camera device has been started. */ 549 ECDS_STARTED, 550 }; 551 552 /* Object state. */ 553 EmulatedCameraDeviceState mState; 554 }; 555 556 }; /* namespace android */ 557 558 #endif /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H */ 559