• 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 /*
18  * Contains implementation of a class PreviewWindow that encapsulates
19  * functionality of a preview window set via set_preview_window camera HAL API.
20  */
21 
22 #define LOG_NDEBUG 0
23 #define LOG_TAG "EmulatedCamera_Preview"
24 #include <cutils/log.h>
25 #include "EmulatedCameraDevice.h"
26 #include "PreviewWindow.h"
27 #include "GrallocModule.h"
28 
29 namespace android {
30 
PreviewWindow()31 PreviewWindow::PreviewWindow()
32     : mPreviewWindow(NULL),
33       mPreviewFrameWidth(0),
34       mPreviewFrameHeight(0),
35       mPreviewEnabled(false)
36 {
37 }
38 
~PreviewWindow()39 PreviewWindow::~PreviewWindow()
40 {
41 }
42 
43 /****************************************************************************
44  * Camera API
45  ***************************************************************************/
46 
setPreviewWindow(struct preview_stream_ops * window,int preview_fps)47 status_t PreviewWindow::setPreviewWindow(struct preview_stream_ops* window,
48                                          int preview_fps)
49 {
50     ALOGV("%s: current: %p -> new: %p", __FUNCTION__, mPreviewWindow, window);
51 
52     status_t res = NO_ERROR;
53     Mutex::Autolock locker(&mObjectLock);
54 
55     /* Reset preview info. */
56     mPreviewFrameWidth = mPreviewFrameHeight = 0;
57 
58     if (window != NULL) {
59         /* The CPU will write each frame to the preview window buffer.
60          * Note that we delay setting preview window buffer geometry until
61          * frames start to come in. */
62         res = window->set_usage(window, GRALLOC_USAGE_SW_WRITE_OFTEN);
63         if (res != NO_ERROR) {
64             window = NULL;
65             res = -res; // set_usage returns a negative errno.
66             ALOGE("%s: Error setting preview window usage %d -> %s",
67                  __FUNCTION__, res, strerror(res));
68         }
69     }
70     mPreviewWindow = window;
71 
72     return res;
73 }
74 
startPreview()75 status_t PreviewWindow::startPreview()
76 {
77     ALOGV("%s", __FUNCTION__);
78 
79     Mutex::Autolock locker(&mObjectLock);
80     mPreviewEnabled = true;
81 
82     return NO_ERROR;
83 }
84 
stopPreview()85 void PreviewWindow::stopPreview()
86 {
87     ALOGV("%s", __FUNCTION__);
88 
89     Mutex::Autolock locker(&mObjectLock);
90     mPreviewEnabled = false;
91 }
92 
93 /****************************************************************************
94  * Public API
95  ***************************************************************************/
96 
onNextFrameAvailable(nsecs_t timestamp,EmulatedCameraDevice * camera_dev)97 void PreviewWindow::onNextFrameAvailable(nsecs_t timestamp,
98                                          EmulatedCameraDevice* camera_dev)
99 {
100     int res;
101     Mutex::Autolock locker(&mObjectLock);
102 
103     if (!isPreviewEnabled() || mPreviewWindow == NULL) {
104         return;
105     }
106 
107     /* Make sure that preview window dimensions are OK with the camera device */
108     if (adjustPreviewDimensions(camera_dev)) {
109         /* Need to set / adjust buffer geometry for the preview window.
110          * Note that in the emulator preview window uses only RGB for pixel
111          * formats. */
112         ALOGV("%s: Adjusting preview windows %p geometry to %dx%d",
113              __FUNCTION__, mPreviewWindow, mPreviewFrameWidth,
114              mPreviewFrameHeight);
115         res = mPreviewWindow->set_buffers_geometry(mPreviewWindow,
116                                                    mPreviewFrameWidth,
117                                                    mPreviewFrameHeight,
118                                                    HAL_PIXEL_FORMAT_RGBA_8888);
119         if (res != NO_ERROR) {
120             ALOGE("%s: Error in set_buffers_geometry %d -> %s",
121                  __FUNCTION__, -res, strerror(-res));
122             return;
123         }
124     }
125 
126     /*
127      * Push new frame to the preview window.
128      */
129 
130     /* Dequeue preview window buffer for the frame. */
131     buffer_handle_t* buffer = NULL;
132     int stride = 0;
133     res = mPreviewWindow->dequeue_buffer(mPreviewWindow, &buffer, &stride);
134     if (res != NO_ERROR || buffer == NULL) {
135         ALOGE("%s: Unable to dequeue preview window buffer: %d -> %s",
136             __FUNCTION__, -res, strerror(-res));
137         return;
138     }
139 
140     /* Let the preview window to lock the buffer. */
141     res = mPreviewWindow->lock_buffer(mPreviewWindow, buffer);
142     if (res != NO_ERROR) {
143         ALOGE("%s: Unable to lock preview window buffer: %d -> %s",
144              __FUNCTION__, -res, strerror(-res));
145         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
146         return;
147     }
148 
149     /* Now let the graphics framework to lock the buffer, and provide
150      * us with the framebuffer data address. */
151     void* img = NULL;
152     res = GrallocModule::getInstance().lock(
153         *buffer, GRALLOC_USAGE_SW_WRITE_OFTEN,
154         0, 0, mPreviewFrameWidth, mPreviewFrameHeight, &img);
155     if (res != NO_ERROR) {
156         ALOGE("%s: gralloc.lock failure: %d -> %s",
157              __FUNCTION__, res, strerror(res));
158         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
159         return;
160     }
161 
162     int64_t frame_timestamp = 0L;
163     /* Frames come in in YV12/NV12/NV21 format. Since preview window doesn't
164      * supports those formats, we need to obtain the frame in RGB565. */
165     res = camera_dev->getCurrentPreviewFrame(img, &frame_timestamp);
166     if (res == NO_ERROR) {
167         /* Show it. */
168         mPreviewWindow->set_timestamp(mPreviewWindow,
169                                       frame_timestamp != 0L ? frame_timestamp : timestamp);
170         mPreviewWindow->enqueue_buffer(mPreviewWindow, buffer);
171     } else {
172         ALOGE("%s: Unable to obtain preview frame: %d", __FUNCTION__, res);
173         mPreviewWindow->cancel_buffer(mPreviewWindow, buffer);
174     }
175     GrallocModule::getInstance().unlock(*buffer);
176 }
177 
178 /***************************************************************************
179  * Private API
180  **************************************************************************/
181 
adjustPreviewDimensions(EmulatedCameraDevice * camera_dev)182 bool PreviewWindow::adjustPreviewDimensions(EmulatedCameraDevice* camera_dev)
183 {
184     /* Match the cached frame dimensions against the actual ones. */
185     if (mPreviewFrameWidth == camera_dev->getFrameWidth() &&
186         mPreviewFrameHeight == camera_dev->getFrameHeight()) {
187         /* They match. */
188         return false;
189     }
190 
191     /* They don't match: adjust the cache. */
192     mPreviewFrameWidth = camera_dev->getFrameWidth();
193     mPreviewFrameHeight = camera_dev->getFrameHeight();
194 
195     return true;
196 }
197 
198 }; /* namespace android */
199