PreviewRenderer.cpp revision 460ba2a3a1fa9318463d3c00595b6732e3d776de
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#define LOG_NDEBUG 1 19#define LOG_TAG "PreviewRenderer" 20#include <utils/Log.h> 21 22#include "PreviewRenderer.h" 23 24#include <binder/MemoryHeapBase.h> 25#include <binder/MemoryHeapPmem.h> 26#include <media/stagefright/MediaDebug.h> 27#include <surfaceflinger/Surface.h> 28 29namespace android { 30 31PreviewRenderer* PreviewRenderer::CreatePreviewRenderer (OMX_COLOR_FORMATTYPE colorFormat, 32 const sp<Surface> &surface, 33 size_t displayWidth, size_t displayHeight, 34 size_t decodedWidth, size_t decodedHeight, 35 int32_t rotationDegrees) { 36 37 PreviewRenderer* returnCtx = 38 new PreviewRenderer(colorFormat, 39 surface, 40 displayWidth, displayHeight, 41 decodedWidth, decodedHeight, 42 rotationDegrees); 43 44 int result = 0; 45 46 int halFormat; 47 switch (returnCtx->mColorFormat) { 48 case OMX_COLOR_FormatYUV420Planar: 49 { 50 halFormat = HAL_PIXEL_FORMAT_YV12; 51 returnCtx->mYUVMode = None; 52 break; 53 } 54 default: 55 halFormat = HAL_PIXEL_FORMAT_RGB_565; 56 57 returnCtx->mConverter = new ColorConverter( 58 returnCtx->mColorFormat, OMX_COLOR_Format16bitRGB565); 59 CHECK(returnCtx->mConverter->isValid()); 60 break; 61 } 62 63 CHECK(returnCtx->mSurface.get() != NULL); 64 CHECK(returnCtx->mDecodedWidth > 0); 65 CHECK(returnCtx->mDecodedHeight > 0); 66 CHECK(returnCtx->mConverter == NULL || returnCtx->mConverter->isValid()); 67 68 result = native_window_set_usage( 69 returnCtx->mSurface.get(), 70 GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN 71 | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); 72 73 if ( result == 0 ) { 74 result = native_window_set_buffer_count(returnCtx->mSurface.get(), 3); 75 if ( result == 0 ) { 76 result = native_window_set_scaling_mode(returnCtx->mSurface.get(), 77 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); 78 if ( result == 0 ) { 79 result = native_window_set_buffers_geometry( 80 returnCtx->mSurface.get(), 81 returnCtx->mDecodedWidth, returnCtx->mDecodedHeight, 82 halFormat); 83 if ( result == 0) { 84 uint32_t transform; 85 switch (rotationDegrees) { 86 case 0: transform = 0; break; 87 case 90: transform = HAL_TRANSFORM_ROT_90; break; 88 case 180: transform = HAL_TRANSFORM_ROT_180; break; 89 case 270: transform = HAL_TRANSFORM_ROT_270; break; 90 default: transform = 0; break; 91 } 92 if (transform) { 93 result = native_window_set_buffers_transform( 94 returnCtx->mSurface.get(), transform); 95 96 } 97 } 98 } 99 } 100 } 101 102 if ( result != 0 ) 103 { 104 /* free the ctx */ 105 returnCtx->~PreviewRenderer(); 106 return NULL; 107 } 108 109 return returnCtx; 110} 111 112PreviewRenderer::PreviewRenderer( 113 OMX_COLOR_FORMATTYPE colorFormat, 114 const sp<Surface> &surface, 115 size_t displayWidth, size_t displayHeight, 116 size_t decodedWidth, size_t decodedHeight, 117 int32_t rotationDegrees) 118 : mColorFormat(colorFormat), 119 mConverter(NULL), 120 mYUVMode(None), 121 mSurface(surface), 122 mDisplayWidth(displayWidth), 123 mDisplayHeight(displayHeight), 124 mDecodedWidth(decodedWidth), 125 mDecodedHeight(decodedHeight) { 126 127 LOGV("input format = %d", mColorFormat); 128 LOGV("display = %d x %d, decoded = %d x %d", 129 mDisplayWidth, mDisplayHeight, mDecodedWidth, mDecodedHeight); 130 131 mDecodedWidth = mDisplayWidth; 132 mDecodedHeight = mDisplayHeight; 133} 134 135PreviewRenderer::~PreviewRenderer() { 136 delete mConverter; 137 mConverter = NULL; 138} 139 140 141// 142// Provides a buffer and associated stride 143// This buffer is allocated by the SurfaceFlinger 144// 145// For optimal display performances, you should : 146// 1) call getBufferYV12() 147// 2) fill the buffer with your data 148// 3) call renderYV12() to take these changes into account 149// 150// For each call to getBufferYV12(), you must also call renderYV12() 151// Expected format in the buffer is YV12 formats (similar to YUV420 planar fromat) 152// for more details on this YV12 cf hardware/libhardware/include/hardware/hardware.h 153// 154void PreviewRenderer::getBufferYV12(uint8_t **data, size_t *stride) { 155 int err = OK; 156 LOGV("getBuffer START"); 157 158 if ((err = mSurface->ANativeWindow::dequeueBuffer(mSurface.get(), &mBuf)) != 0) { 159 LOGW("Surface::dequeueBuffer returned error %d", err); 160 return; 161 } 162 163 CHECK_EQ(0, mSurface->ANativeWindow::lockBuffer(mSurface.get(), mBuf)); 164 165 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 166 167 Rect bounds(mDecodedWidth, mDecodedHeight); 168 169 void *dst; 170 CHECK_EQ(0, mapper.lock( 171 mBuf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst)); 172 LOGV("Buffer locked"); 173 174 *data = (uint8_t*)dst; 175 *stride = mBuf->stride; 176 177 LOGV("getBuffer END %p %d", dst, mBuf->stride); 178} 179 180 181// 182// Display the content of the buffer provided by last call to getBufferYV12() 183// 184// See getBufferYV12() for details. 185// 186void PreviewRenderer::renderYV12() { 187 LOGV("renderYV12() START"); 188 int err = OK; 189 190 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 191 192 if (mBuf!= NULL) { 193 CHECK_EQ(0, mapper.unlock(mBuf->handle)); 194 195 if ((err = mSurface->ANativeWindow::queueBuffer(mSurface.get(), mBuf)) != 0) { 196 LOGW("Surface::queueBuffer returned error %d", err); 197 } 198 } 199 mBuf = NULL; 200 LOGV("renderYV12() END"); 201} 202 203 204 205// 206// Display the given data buffer 207// platformPrivate is not used (kept for backwrad compatibility) 208// Please rather use getbuffer() and the other render()functions (with no params) 209// for optimal display 210// 211void PreviewRenderer::render( 212 const void *data, size_t size, void *platformPrivate) { 213 ANativeWindowBuffer *buf; 214 int err; 215 216 if ((err = mSurface->ANativeWindow::dequeueBuffer(mSurface.get(), &buf)) != 0) { 217 LOGW("Surface::dequeueBuffer returned error %d", err); 218 return; 219 } 220 221 CHECK_EQ(0, mSurface->ANativeWindow::lockBuffer(mSurface.get(), buf)); 222 223 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 224 225 Rect bounds(mDecodedWidth, mDecodedHeight); 226 227 void *dst; 228 CHECK_EQ(0, mapper.lock( 229 buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst)); 230 LOGV("Buffer locked"); 231 232 if (mConverter) { 233 LOGV("Convert to RGB565"); 234 mConverter->convert(data, 235 mDecodedWidth, mDecodedHeight, 236 0,0,mDecodedWidth, mDecodedHeight, 237 dst, mDecodedWidth, mDecodedHeight, 238 0,0,mDecodedWidth, mDecodedHeight); 239 } else if (mYUVMode == None) { 240 // Input and output are both YUV420sp, but the alignment requirements 241 // are different. 242 LOGV("mYUVMode == None %d x %d", mDecodedWidth, mDecodedHeight); 243 size_t srcYStride = mDecodedWidth; 244 const uint8_t *srcY = (const uint8_t *)data; 245 uint8_t *dstY = (uint8_t *)dst; 246 LOGV("srcY = %p dstY = %p", srcY, dstY); 247 LOGV("srcYStride = %d dstYstride = %d", srcYStride, buf->stride); 248 for (size_t i = 0; i < mDecodedHeight; ++i) { 249 memcpy(dstY, srcY, mDecodedWidth); 250 srcY += srcYStride; 251 dstY += buf->stride; 252 } 253 254 size_t srcUVStride = (mDecodedWidth + 1) / 2; 255 size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32); 256 LOGV("srcUVStride = %d dstUVStride = %d", srcUVStride, dstUVStride); 257 258 // Copy V 259 // Source buffer is YUV, skip U 260 const uint8_t *srcV = (const uint8_t *)data 261 + mDecodedHeight * mDecodedWidth + (mDecodedHeight * mDecodedWidth)/4; 262 // Destination buffer is YVU 263 uint8_t *dstUV = (uint8_t *)dst 264 + buf->stride*mDecodedHeight; 265 LOGV("srcV = %p dstUV = %p", srcV, dstUV); 266 for (size_t i = 0; i < (mDecodedHeight+1)/2; ++i) { 267 memcpy(dstUV, srcV, mDecodedWidth/2); 268 srcV += srcUVStride; 269 dstUV += dstUVStride; 270 } 271 272 273 // Copy V 274 // Source buffer is YUV, go back to end of Y 275 const uint8_t *srcU = (const uint8_t *)data 276 + mDecodedHeight * mDecodedWidth ; 277 // Destination buffer is YVU 278 // Keep writing after V buffer has been filled, U follows immediately 279 LOGV("srcU = %p dstUV = %p", srcU, dstUV); 280 for (size_t i = 0; i < (mDecodedHeight+1)/2; ++i) { 281 memcpy(dstUV, srcU, mDecodedWidth/2); 282 srcU += srcUVStride; 283 dstUV += dstUVStride; 284 } 285 } else { 286 memcpy(dst, data, size); 287 } 288 289 CHECK_EQ(0, mapper.unlock(buf->handle)); 290 291 if ((err = mSurface->ANativeWindow::queueBuffer(mSurface.get(), buf)) != 0) { 292 LOGW("Surface::queueBuffer returned error %d", err); 293 } 294 buf = NULL; 295} 296 297} // namespace android 298