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