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