SoftwareRenderer.cpp revision 5a52a060fcbe4804bcf4f61b8a457fe0e18a9014
1/* 2 * Copyright (C) 2009 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#define LOG_TAG "SoftwareRenderer" 18#include <utils/Log.h> 19 20#include "../include/SoftwareRenderer.h" 21 22#include <cutils/properties.h> // for property_get 23#include <media/stagefright/foundation/ADebug.h> 24#include <media/stagefright/foundation/AMessage.h> 25#include <system/window.h> 26#include <ui/GraphicBufferMapper.h> 27#include <gui/IGraphicBufferProducer.h> 28 29namespace android { 30 31static bool runningInEmulator() { 32 char prop[PROPERTY_VALUE_MAX]; 33 return (property_get("ro.kernel.qemu", prop, NULL) > 0); 34} 35 36static int ALIGN(int x, int y) { 37 // y must be a power of 2. 38 return (x + y - 1) & ~(y - 1); 39} 40 41SoftwareRenderer::SoftwareRenderer(const sp<ANativeWindow> &nativeWindow) 42 : mColorFormat(OMX_COLOR_FormatUnused), 43 mConverter(NULL), 44 mYUVMode(None), 45 mNativeWindow(nativeWindow), 46 mWidth(0), 47 mHeight(0), 48 mCropLeft(0), 49 mCropTop(0), 50 mCropRight(0), 51 mCropBottom(0), 52 mCropWidth(0), 53 mCropHeight(0) { 54} 55 56SoftwareRenderer::~SoftwareRenderer() { 57 delete mConverter; 58 mConverter = NULL; 59} 60 61void SoftwareRenderer::resetFormatIfChanged(const sp<AMessage> &format) { 62 CHECK(format != NULL); 63 64 int32_t colorFormatNew; 65 CHECK(format->findInt32("color-format", &colorFormatNew)); 66 67 int32_t widthNew, heightNew; 68 CHECK(format->findInt32("stride", &widthNew)); 69 CHECK(format->findInt32("slice-height", &heightNew)); 70 71 int32_t cropLeftNew, cropTopNew, cropRightNew, cropBottomNew; 72 if (!format->findRect( 73 "crop", &cropLeftNew, &cropTopNew, &cropRightNew, &cropBottomNew)) { 74 cropLeftNew = cropTopNew = 0; 75 cropRightNew = widthNew - 1; 76 cropBottomNew = heightNew - 1; 77 } 78 79 if (static_cast<int32_t>(mColorFormat) == colorFormatNew && 80 mWidth == widthNew && 81 mHeight == heightNew && 82 mCropLeft == cropLeftNew && 83 mCropTop == cropTopNew && 84 mCropRight == cropRightNew && 85 mCropBottom == cropBottomNew) { 86 // Nothing changed, no need to reset renderer. 87 return; 88 } 89 90 mColorFormat = static_cast<OMX_COLOR_FORMATTYPE>(colorFormatNew); 91 mWidth = widthNew; 92 mHeight = heightNew; 93 mCropLeft = cropLeftNew; 94 mCropTop = cropTopNew; 95 mCropRight = cropRightNew; 96 mCropBottom = cropBottomNew; 97 98 mCropWidth = mCropRight - mCropLeft + 1; 99 mCropHeight = mCropBottom - mCropTop + 1; 100 101 int halFormat; 102 size_t bufWidth, bufHeight; 103 104 switch (mColorFormat) { 105 case OMX_COLOR_FormatYUV420Planar: 106 case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: 107 { 108 if (!runningInEmulator()) { 109 halFormat = HAL_PIXEL_FORMAT_YV12; 110 bufWidth = (mCropWidth + 1) & ~1; 111 bufHeight = (mCropHeight + 1) & ~1; 112 break; 113 } 114 115 // fall through. 116 } 117 118 default: 119 halFormat = HAL_PIXEL_FORMAT_RGB_565; 120 bufWidth = mCropWidth; 121 bufHeight = mCropHeight; 122 123 mConverter = new ColorConverter( 124 mColorFormat, OMX_COLOR_Format16bitRGB565); 125 CHECK(mConverter->isValid()); 126 break; 127 } 128 129 CHECK(mNativeWindow != NULL); 130 CHECK(mCropWidth > 0); 131 CHECK(mCropHeight > 0); 132 CHECK(mConverter == NULL || mConverter->isValid()); 133 134 CHECK_EQ(0, 135 native_window_set_usage( 136 mNativeWindow.get(), 137 GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN 138 | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP)); 139 140 CHECK_EQ(0, 141 native_window_set_scaling_mode( 142 mNativeWindow.get(), 143 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)); 144 145 // Width must be multiple of 32??? 146 CHECK_EQ(0, native_window_set_buffers_dimensions( 147 mNativeWindow.get(), 148 bufWidth, 149 bufHeight)); 150 CHECK_EQ(0, native_window_set_buffers_format( 151 mNativeWindow.get(), 152 halFormat)); 153 154 // NOTE: native window uses extended right-bottom coordinate 155 android_native_rect_t crop; 156 crop.left = mCropLeft; 157 crop.top = mCropTop; 158 crop.right = mCropRight + 1; 159 crop.bottom = mCropBottom + 1; 160 ALOGV("setting crop: [%d, %d, %d, %d] for size [%zu, %zu]", 161 crop.left, crop.top, crop.right, crop.bottom, bufWidth, bufHeight); 162 163 CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop)); 164 165 int32_t rotationDegrees; 166 if (!format->findInt32("rotation-degrees", &rotationDegrees)) { 167 rotationDegrees = 0; 168 } 169 uint32_t transform; 170 switch (rotationDegrees) { 171 case 0: transform = 0; break; 172 case 90: transform = HAL_TRANSFORM_ROT_90; break; 173 case 180: transform = HAL_TRANSFORM_ROT_180; break; 174 case 270: transform = HAL_TRANSFORM_ROT_270; break; 175 default: transform = 0; break; 176 } 177 178 CHECK_EQ(0, native_window_set_buffers_transform( 179 mNativeWindow.get(), transform)); 180} 181 182void SoftwareRenderer::render( 183 const void *data, size_t /*size*/, int64_t timestampNs, 184 void* /*platformPrivate*/, const sp<AMessage>& format) { 185 resetFormatIfChanged(format); 186 187 ANativeWindowBuffer *buf; 188 int err; 189 if ((err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), 190 &buf)) != 0) { 191 ALOGW("Surface::dequeueBuffer returned error %d", err); 192 return; 193 } 194 195 GraphicBufferMapper &mapper = GraphicBufferMapper::get(); 196 197 Rect bounds(mCropWidth, mCropHeight); 198 199 void *dst; 200 CHECK_EQ(0, mapper.lock( 201 buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst)); 202 203 if (mConverter) { 204 mConverter->convert( 205 data, 206 mWidth, mHeight, 207 mCropLeft, mCropTop, mCropRight, mCropBottom, 208 dst, 209 buf->stride, buf->height, 210 0, 0, mCropWidth - 1, mCropHeight - 1); 211 } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) { 212 // YV12 really 213 const uint8_t *src_y = (const uint8_t *)data; 214 const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight; 215 const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2); 216 217 uint8_t *dst_y = (uint8_t *)dst; 218 size_t dst_y_size = buf->stride * buf->height; 219 size_t dst_c_stride = ALIGN(buf->stride / 2, 16); 220 size_t dst_c_size = dst_c_stride * buf->height / 2; 221 uint8_t *dst_v = dst_y + dst_y_size; 222 uint8_t *dst_u = dst_v + dst_c_size; 223 224 for (int y = 0; y < mCropHeight; ++y) { 225 memcpy(dst_y, src_y, mCropWidth); 226 227 src_y += mWidth; 228 dst_y += buf->stride; 229 } 230 231 for (int y = 0; y < (mCropHeight + 1) / 2; ++y) { 232 memcpy(dst_u, src_u, (mCropWidth + 1) / 2); 233 memcpy(dst_v, src_v, (mCropWidth + 1) / 2); 234 235 src_u += mWidth / 2; 236 src_v += mWidth / 2; 237 dst_u += dst_c_stride; 238 dst_v += dst_c_stride; 239 } 240 } else { 241 CHECK_EQ(mColorFormat, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar); 242 243 const uint8_t *src_y = 244 (const uint8_t *)data; 245 246 const uint8_t *src_uv = 247 (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2); 248 249 uint8_t *dst_y = (uint8_t *)dst; 250 251 size_t dst_y_size = buf->stride * buf->height; 252 size_t dst_c_stride = ALIGN(buf->stride / 2, 16); 253 size_t dst_c_size = dst_c_stride * buf->height / 2; 254 uint8_t *dst_v = dst_y + dst_y_size; 255 uint8_t *dst_u = dst_v + dst_c_size; 256 257 for (int y = 0; y < mCropHeight; ++y) { 258 memcpy(dst_y, src_y, mCropWidth); 259 260 src_y += mWidth; 261 dst_y += buf->stride; 262 } 263 264 for (int y = 0; y < (mCropHeight + 1) / 2; ++y) { 265 size_t tmp = (mCropWidth + 1) / 2; 266 for (size_t x = 0; x < tmp; ++x) { 267 dst_u[x] = src_uv[2 * x]; 268 dst_v[x] = src_uv[2 * x + 1]; 269 } 270 271 src_uv += mWidth; 272 dst_u += dst_c_stride; 273 dst_v += dst_c_stride; 274 } 275 } 276 277 CHECK_EQ(0, mapper.unlock(buf->handle)); 278 279 if ((err = native_window_set_buffers_timestamp(mNativeWindow.get(), 280 timestampNs)) != 0) { 281 ALOGW("Surface::set_buffers_timestamp returned error %d", err); 282 } 283 284 if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf, 285 -1)) != 0) { 286 ALOGW("Surface::queueBuffer returned error %d", err); 287 } 288 buf = NULL; 289} 290 291} // namespace android 292