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