SoftwareRenderer.cpp revision 20111aa043c5f404472bc63b90bc5aad906b1101
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "SoftwareRenderer" 1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h> 1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#undef NDEBUG 2120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <assert.h> 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <binder/MemoryHeapBase.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/SoftwareRenderer.h> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ui/ISurface.h> 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define QCOM_YUV 0 3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberSoftwareRenderer::SoftwareRenderer( 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<ISurface> &surface, 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t displayWidth, size_t displayHeight, 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t decodedWidth, size_t decodedHeight) 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mISurface(surface), 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDisplayWidth(displayWidth), 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDisplayHeight(displayHeight), 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDecodedWidth(decodedWidth), 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDecodedHeight(decodedHeight), 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFrameSize(mDecodedWidth * mDecodedHeight * 2), // RGB565 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mMemoryHeap(new MemoryHeapBase(2 * mFrameSize)), 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mIndex(0) { 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(mISurface.get() != NULL); 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(mDecodedWidth > 0); 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(mDecodedHeight > 0); 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(mMemoryHeap->heapID() >= 0); 4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ISurface::BufferHeap bufferHeap( 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDisplayWidth, mDisplayHeight, 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDecodedWidth, mDecodedHeight, 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber PIXEL_FORMAT_RGB_565, 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mMemoryHeap); 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = mISurface->registerBuffers(bufferHeap); 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(err == OK); 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberSoftwareRenderer::~SoftwareRenderer() { 5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mISurface->unregisterBuffers(); 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid SoftwareRenderer::render( 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const void *data, size_t size, void *platformPrivate) { 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber assert(size >= (mDecodedWidth * mDecodedHeight * 3) / 2); 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const signed kClipMin = -278; 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const signed kClipMax = 535; 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static uint8_t kClip[kClipMax - kClipMin + 1]; 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static uint8_t *kAdjustedClip = &kClip[-kClipMin]; 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static bool clipInitialized = false; 7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!clipInitialized) { 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (signed i = kClipMin; i <= kClipMax; ++i) { 7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber kClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i; 7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber clipInitialized = true; 7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = mIndex * mFrameSize; 8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber void *dst = (uint8_t *)mMemoryHeap->getBase() + offset; 8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t *dst_ptr = (uint32_t *)dst; 8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *src_y = (const uint8_t *)data; 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *src_u = 8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)src_y + mDecodedWidth * mDecodedHeight; 9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if !QCOM_YUV 9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *src_v = 9320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber (const uint8_t *)src_u + (mDecodedWidth / 2) * (mDecodedHeight / 2); 9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t y = 0; y < mDecodedHeight; ++y) { 9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t x = 0; x < mDecodedWidth; x += 2) { 9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // B = 1.164 * (Y - 16) + 2.018 * (U - 128) 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // G = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128) 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // R = 1.164 * (Y - 16) + 1.596 * (V - 128) 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // B = 298/256 * (Y - 16) + 517/256 * (U - 128) 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // G = .................. - 208/256 * (V - 128) - 100/256 * (U - 128) 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // R = .................. + 409/256 * (V - 128) 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // min_B = (298 * (- 16) + 517 * (- 128)) / 256 = -277 10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // min_G = (298 * (- 16) - 208 * (255 - 128) - 100 * (255 - 128)) / 256 = -172 10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // min_R = (298 * (- 16) + 409 * (- 128)) / 256 = -223 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // max_B = (298 * (255 - 16) + 517 * (255 - 128)) / 256 = 534 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // max_G = (298 * (255 - 16) - 208 * (- 128) - 100 * (- 128)) / 256 = 432 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // max_R = (298 * (255 - 16) + 409 * (255 - 128)) / 256 = 481 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // clip range -278 .. 535 11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed y1 = (signed)src_y[x] - 16; 11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if QCOM_YUV 12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed u = (signed)src_u[x & ~1] - 128; 12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed v = (signed)src_u[(x & ~1) + 1] - 128; 12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#else 12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed u = (signed)src_u[x / 2] - 128; 12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed v = (signed)src_v[x / 2] - 128; 12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed u_b = u * 517; 12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed u_g = -u * 100; 12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed v_g = -v * 208; 13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed v_r = v * 409; 13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed tmp1 = y1 * 298; 13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed b1 = (tmp1 + u_b) / 256; 13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed r1 = (tmp1 + v_r) / 256; 13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed tmp2 = y2 * 298; 13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed b2 = (tmp2 + u_b) / 256; 13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber signed r2 = (tmp2 + v_r) / 256; 14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t rgb1 = 14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ((kAdjustedClip[r1] >> 3) << 11) 14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber | (kAdjustedClip[b1] >> 3); 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t rgb2 = 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ((kAdjustedClip[r2] >> 3) << 11) 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber | (kAdjustedClip[b2] >> 3); 15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber dst_ptr[x / 2] = (rgb2 << 16) | rgb1; 15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber src_y += mDecodedWidth; 15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (y & 1) { 15820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if QCOM_YUV 15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber src_u += mDecodedWidth; 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#else 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber src_u += mDecodedWidth / 2; 16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber src_v += mDecodedWidth / 2; 16320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 16420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 16520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber dst_ptr += mDecodedWidth / 2; 16720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 16820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mISurface->postBuffer(offset); 17020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mIndex = 1 - mIndex; 17120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 17220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 17320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 174