• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     /* Gets current framebuffer, converted into preview frame format.
147      * This method must be called on a connected instance of this class with a
148      * started camera device. If it is called on a disconnected instance, or
149      * camera device has not been started, this method must return a failure.
150      * Note that this method should be called only after at least one frame has
151      * been captured and delivered. Otherwise it will return garbage in the
152      * preview frame buffer. Typically, this method shuld be called from
153      * onNextFrameAvailable callback.
154      * Param:
155      *  buffer - Buffer, large enough to contain the entire preview frame.
156      * Return:
157      *  NO_ERROR on success, or an appropriate error status.
158      */
159     virtual status_t getCurrentPreviewFrame(void* buffer);
160 
161     /* Gets width of the frame obtained from the physical device.
162      * Return:
163      *  Width of the frame obtained from the physical device. Note that value
164      *  returned from this method is valid only in case if camera device has been
165      *  started.
166      */
getFrameWidth()167     inline int getFrameWidth() const
168     {
169         LOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
170         return mFrameWidth;
171     }
172 
173     /* Gets height of the frame obtained from the physical device.
174      * Return:
175      *  Height of the frame obtained from the physical device. Note that value
176      *  returned from this method is valid only in case if camera device has been
177      *  started.
178      */
getFrameHeight()179     inline int getFrameHeight() const
180     {
181         LOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
182         return mFrameHeight;
183     }
184 
185     /* Gets byte size of the current frame buffer.
186      * Return:
187      *  Byte size of the frame buffer. Note that value returned from this method
188      *  is valid only in case if camera device has been started.
189      */
getFrameBufferSize()190     inline size_t getFrameBufferSize() const
191     {
192         LOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
193         return mFrameBufferSize;
194     }
195 
196     /* Gets number of pixels in the current frame buffer.
197      * Return:
198      *  Number of pixels in the frame buffer. Note that value returned from this
199      *  method is valid only in case if camera device has been started.
200      */
getPixelNum()201     inline int getPixelNum() const
202     {
203         LOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
204         return mTotalPixels;
205     }
206 
207     /* Gets pixel format of the frame that camera device streams to this class.
208      * Throughout camera framework, there are three different forms of pixel
209      * format representation:
210      *  - Original format, as reported by the actual camera device. Values for
211      *    this format are declared in bionic/libc/kernel/common/linux/videodev2.h
212      *  - String representation as defined in CameraParameters::PIXEL_FORMAT_XXX
213      *    strings in frameworks/base/include/camera/CameraParameters.h
214      *  - HAL_PIXEL_FORMAT_XXX format, as defined in system/core/include/system/graphics.h
215      * Since emulated camera device gets its data from the actual device, it gets
216      * pixel format in the original form. And that's the pixel format
217      * representation that will be returned from this method. HAL components will
218      * need to translate value returned from this method to the appropriate form.
219      * This method must be called only on started instance of this class, since
220      * it's applicable only when camera device is ready to stream frames.
221      * Param:
222      *  pix_fmt - Upon success contains the original pixel format.
223      * Return:
224      *  Current framebuffer's pixel format. Note that value returned from this
225      *  method is valid only in case if camera device has been started.
226      */
getOriginalPixelFormat()227     inline uint32_t getOriginalPixelFormat() const
228     {
229         LOGE_IF(!isStarted(), "%s: Device is not started", __FUNCTION__);
230         return mPixelFormat;
231     }
232 
233     /*
234      * State checkers.
235      */
236 
isInitialized()237     inline bool isInitialized() const {
238         /* Instance is initialized when the worker thread has been successfuly
239          * created (but not necessarily started). */
240         return mWorkerThread.get() != NULL && mState != ECDS_CONSTRUCTED;
241     }
isConnected()242     inline bool isConnected() const {
243         /* Instance is connected when its status is either"connected", or
244          * "started". */
245         return mState == ECDS_CONNECTED || mState == ECDS_STARTED;
246     }
isStarted()247     inline bool isStarted() const {
248         return mState == ECDS_STARTED;
249     }
250 
251     /****************************************************************************
252      * Emulated camera device private API
253      ***************************************************************************/
254 protected:
255     /* Performs common validation and calculation of startDevice parameters.
256      * Param:
257      *  width, height, pix_fmt - Parameters passed to the startDevice method.
258      * Return:
259      *  NO_ERROR on success, or an appropriate error status.
260      */
261     virtual status_t commonStartDevice(int width, int height, uint32_t pix_fmt);
262 
263     /* Performs common cleanup on stopDevice.
264      * This method will undo what commonStartDevice had done.
265      */
266     virtual void commonStopDevice();
267 
268     /****************************************************************************
269      * Worker thread management.
270      * Typicaly when emulated camera device starts capturing frames from the
271      * actual device, it does that in a worker thread created in StartCapturing,
272      * and terminated in StopCapturing. Since this is such a typical scenario,
273      * it makes sence to encapsulate worker thread management in the base class
274      * for all emulated camera devices.
275      ***************************************************************************/
276 
277 protected:
278     /* Starts the worker thread.
279      * Typically, worker thread is started from startDeliveringFrames method of
280      * this class.
281      * Param:
282      *  one_burst - Controls how many times thread loop should run. If this
283      *      parameter is 'true', thread routine will run only once If this
284      *      parameter is 'false', thread routine will run until stopWorkerThread
285      *      method is called. See startDeliveringFrames for more info.
286      * Return:
287      *  NO_ERROR on success, or an appropriate error status.
288      */
289     virtual status_t startWorkerThread(bool one_burst);
290 
291     /* Stops the worker thread.
292      * Note that this method will always wait for the worker thread to terminate.
293      * Typically, worker thread is started from stopDeliveringFrames method of
294      * this class.
295      * Return:
296      *  NO_ERROR on success, or an appropriate error status.
297      */
298     virtual status_t stopWorkerThread();
299 
300     /* Implementation of the worker thread routine.
301      * In the default implementation of the worker thread routine we simply
302      * return 'false' forcing the thread loop to exit, and the thread to
303      * terminate. Derived class should override that method to provide there the
304      * actual frame delivery.
305      * Return:
306      *  true To continue thread loop (this method will be called again), or false
307      *  to exit the thread loop and to terminate the thread.
308      */
309     virtual bool inWorkerThread();
310 
311     /* Encapsulates a worker thread used by the emulated camera device.
312      */
313     friend class WorkerThread;
314     class WorkerThread : public Thread {
315 
316         /****************************************************************************
317          * Public API
318          ***************************************************************************/
319 
320         public:
WorkerThread(EmulatedCameraDevice * camera_dev)321             inline explicit WorkerThread(EmulatedCameraDevice* camera_dev)
322                 : Thread(true),   // Callbacks may involve Java calls.
323                   mCameraDevice(camera_dev),
324                   mThreadControl(-1),
325                   mControlFD(-1)
326             {
327             }
328 
~WorkerThread()329             inline ~WorkerThread()
330             {
331                 LOGW_IF(mThreadControl >= 0 || mControlFD >= 0,
332                         "%s: Control FDs are opened in the destructor",
333                         __FUNCTION__);
334                 if (mThreadControl >= 0) {
335                     close(mThreadControl);
336                 }
337                 if (mControlFD >= 0) {
338                     close(mControlFD);
339                 }
340             }
341 
342             /* Starts the thread
343              * Param:
344              *  one_burst - Controls how many times thread loop should run. If
345              *      this parameter is 'true', thread routine will run only once
346              *      If this parameter is 'false', thread routine will run until
347              *      stopThread method is called. See startWorkerThread for more
348              *      info.
349              * Return:
350              *  NO_ERROR on success, or an appropriate error status.
351              */
startThread(bool one_burst)352             inline status_t startThread(bool one_burst)
353             {
354                 mOneBurst = one_burst;
355                 return run(NULL, ANDROID_PRIORITY_URGENT_DISPLAY, 0);
356             }
357 
358             /* Overriden base class method.
359              * It is overriden in order to provide one-time initialization just
360              * prior to starting the thread routine.
361              */
362             status_t readyToRun();
363 
364             /* Stops the thread. */
365             status_t stopThread();
366 
367             /* Values returned from the Select method of this class. */
368             enum SelectRes {
369                 /* A timeout has occurred. */
370                 TIMEOUT,
371                 /* Data are available for read on the provided FD. */
372                 READY,
373                 /* Thread exit request has been received. */
374                 EXIT_THREAD,
375                 /* An error has occurred. */
376                 ERROR
377             };
378 
379             /* Select on an FD event, keeping in mind thread exit message.
380              * Param:
381              *  fd - File descriptor on which to wait for an event. This
382              *      parameter may be negative. If it is negative this method will
383              *      only wait on a control message to the thread.
384              *  timeout - Timeout in microseconds. 0 indicates no timeout (wait
385              *      forever).
386              * Return:
387              *  See SelectRes enum comments.
388              */
389             SelectRes Select(int fd, int timeout);
390 
391         /****************************************************************************
392          * Private API
393          ***************************************************************************/
394 
395         private:
396             /* Implements abstract method of the base Thread class. */
threadLoop()397             bool threadLoop()
398             {
399                 /* Simply dispatch the call to the containing camera device. */
400                 if (mCameraDevice->inWorkerThread()) {
401                     /* Respect "one burst" parameter (see startThread). */
402                     return !mOneBurst;
403                 } else {
404                     return false;
405                 }
406             }
407 
408             /* Containing camera device object. */
409             EmulatedCameraDevice*   mCameraDevice;
410 
411             /* FD that is used to send control messages into the thread. */
412             int                     mThreadControl;
413 
414             /* FD that thread uses to receive control messages. */
415             int                     mControlFD;
416 
417             /* Controls number of times the thread loop runs.
418              * See startThread for more information. */
419             bool                    mOneBurst;
420 
421             /* Enumerates control messages that can be sent into the thread. */
422             enum ControlMessage {
423                 /* Stop the thread. */
424                 THREAD_STOP
425             };
426     };
427 
428     /* Worker thread accessor. */
getWorkerThread()429     inline WorkerThread* getWorkerThread() const
430     {
431         return mWorkerThread.get();
432     }
433 
434     /****************************************************************************
435      * Data members
436      ***************************************************************************/
437 
438 protected:
439     /* Locks this instance for parameters, state, etc. change. */
440     Mutex                       mObjectLock;
441 
442     /* Worker thread that is used in frame capturing. */
443     sp<WorkerThread>            mWorkerThread;
444 
445     /* Timestamp of the current frame. */
446     nsecs_t                     mCurFrameTimestamp;
447 
448     /* Emulated camera object containing this instance. */
449     EmulatedCamera*             mCameraHAL;
450 
451     /* Framebuffer containing the current frame. */
452     uint8_t*                    mCurrentFrame;
453 
454     /*
455      * Framebuffer properties.
456      */
457 
458     /* Byte size of the framebuffer. */
459     size_t                      mFrameBufferSize;
460 
461     /* Original pixel format (one of the V4L2_PIX_FMT_XXX values, as defined in
462      * bionic/libc/kernel/common/linux/videodev2.h */
463     uint32_t                    mPixelFormat;
464 
465     /* Frame width */
466     int                         mFrameWidth;
467 
468     /* Frame height */
469     int                         mFrameHeight;
470 
471     /* Total number of pixels */
472     int                         mTotalPixels;
473 
474     /* Defines possible states of the emulated camera device object.
475      */
476     enum EmulatedCameraDeviceState {
477         /* Object has been constructed. */
478         ECDS_CONSTRUCTED,
479         /* Object has been initialized. */
480         ECDS_INITIALIZED,
481         /* Object has been connected to the physical device. */
482         ECDS_CONNECTED,
483         /* Camera device has been started. */
484         ECDS_STARTED,
485     };
486 
487     /* Object state. */
488     EmulatedCameraDeviceState   mState;
489 };
490 
491 }; /* namespace android */
492 
493 #endif  /* HW_EMULATOR_CAMERA_EMULATED_CAMERA_DEVICE_H */
494