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 31 PreviewWindow::PreviewWindow() 32 : mPreviewWindow(NULL), 33 mPreviewFrameWidth(0), 34 mPreviewFrameHeight(0), 35 mPreviewEnabled(false) 36 { 37 } 38 39 PreviewWindow::~PreviewWindow() 40 { 41 } 42 43 /**************************************************************************** 44 * Camera API 45 ***************************************************************************/ 46 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 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 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 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 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