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