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