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