12a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber/* 22a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * Copyright (C) 2009 The Android Open Source Project 32a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * 42a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 52a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * you may not use this file except in compliance with the License. 62a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * You may obtain a copy of the License at 72a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * 82a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 92a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * 102a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * Unless required by applicable law or agreed to in writing, software 112a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 122a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * See the License for the specific language governing permissions and 142a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber * limitations under the License. 152a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber */ 162a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 173571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber//#define LOG_NDEBUG 0 183571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber#define LOG_TAG "ColorConverter" 193571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber#include <utils/Log.h> 203571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber 21f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/ColorConverter.h> 231472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber#include <media/stagefright/MediaErrors.h> 242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Hubernamespace android { 262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 272a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberColorConverter::ColorConverter( 282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber OMX_COLOR_FORMATTYPE from, OMX_COLOR_FORMATTYPE to) 292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber : mSrcFormat(from), 302a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mDstFormat(to), 312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClip(NULL) { 322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 342a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberColorConverter::~ColorConverter() { 352a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber delete[] mClip; 362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClip = NULL; 372a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberbool ColorConverter::isValid() const { 402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (mDstFormat != OMX_COLOR_Format16bitRGB565) { 412a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return false; 422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 432a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 442a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber switch (mSrcFormat) { 452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_COLOR_FormatYUV420Planar: 462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_COLOR_FormatCbYCrY: 472a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: 481c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber case OMX_COLOR_FormatYUV420SemiPlanar: 49cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: 502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return true; 512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber default: 532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return false; 542a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 57f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas HuberColorConverter::BitmapParams::BitmapParams( 58f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber void *bits, 592a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber size_t width, size_t height, 60f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t cropLeft, size_t cropTop, 61f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t cropRight, size_t cropBottom) 62f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber : mBits(bits), 63f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mWidth(width), 64f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mHeight(height), 65f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCropLeft(cropLeft), 66f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCropTop(cropTop), 67f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCropRight(cropRight), 68f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCropBottom(cropBottom) { 69f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber} 70f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 71f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Hubersize_t ColorConverter::BitmapParams::cropWidth() const { 72f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber return mCropRight - mCropLeft + 1; 73f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber} 74f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 75f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Hubersize_t ColorConverter::BitmapParams::cropHeight() const { 76f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber return mCropBottom - mCropTop + 1; 77f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber} 78f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 791472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convert( 80f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const void *srcBits, 81f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t srcWidth, size_t srcHeight, 82f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t srcCropLeft, size_t srcCropTop, 83f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t srcCropRight, size_t srcCropBottom, 84f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber void *dstBits, 85f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t dstWidth, size_t dstHeight, 86f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t dstCropLeft, size_t dstCropTop, 87f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t dstCropRight, size_t dstCropBottom) { 881472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber if (mDstFormat != OMX_COLOR_Format16bitRGB565) { 891472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return ERROR_UNSUPPORTED; 901472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber } 912a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 92f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber BitmapParams src( 93f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const_cast<void *>(srcBits), 94f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber srcWidth, srcHeight, 95f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber srcCropLeft, srcCropTop, srcCropRight, srcCropBottom); 96f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 97f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber BitmapParams dst( 98f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber dstBits, 99f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber dstWidth, dstHeight, 100f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber dstCropLeft, dstCropTop, dstCropRight, dstCropBottom); 101f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 1021472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber status_t err; 1031472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 1042a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber switch (mSrcFormat) { 1052a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_COLOR_FormatYUV420Planar: 1061472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber err = convertYUV420Planar(src, dst); 1072a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber break; 1082a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1092a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_COLOR_FormatCbYCrY: 1101472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber err = convertCbYCrY(src, dst); 1112a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber break; 1122a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1132a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: 1141472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber err = convertQCOMYUV420SemiPlanar(src, dst); 1152a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber break; 1162a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1171c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber case OMX_COLOR_FormatYUV420SemiPlanar: 1181472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber err = convertYUV420SemiPlanar(src, dst); 1191c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber break; 1201c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 121cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: 122cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan err = convertTIYUV420PackedSemiPlanar(src, dst); 123cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan break; 124cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 1252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber default: 1262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber { 1272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber CHECK(!"Should not be here. Unknown color conversion."); 1282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber break; 1292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 1302a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 1311472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 1321472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return err; 1332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 1342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1351472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convertCbYCrY( 136f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const BitmapParams &src, const BitmapParams &dst) { 137f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber // XXX Untested 1382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint8_t *kAdjustedClip = initClip(); 1402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1411472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber if (!((src.mCropLeft & 1) == 0 1421472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber && src.cropWidth() == dst.cropWidth() 1431472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber && src.cropHeight() == dst.cropHeight())) { 1441472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return ERROR_UNSUPPORTED; 1451472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber } 146f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 1474e260ab948787c2a814543077832847deae890fdJames Dong uint16_t *dst_ptr = (uint16_t *)dst.mBits 1484e260ab948787c2a814543077832847deae890fdJames Dong + dst.mCropTop * dst.mWidth + dst.mCropLeft; 1492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 150f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const uint8_t *src_ptr = (const uint8_t *)src.mBits 151f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber + (src.mCropTop * dst.mWidth + src.mCropLeft) * 2; 1522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 153f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 154f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 155f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber signed y1 = (signed)src_ptr[2 * x + 1] - 16; 156f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber signed y2 = (signed)src_ptr[2 * x + 3] - 16; 157f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber signed u = (signed)src_ptr[2 * x] - 128; 158f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber signed v = (signed)src_ptr[2 * x + 2] - 128; 1592a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_b = u * 517; 1612a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_g = -u * 100; 1622a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_g = -v * 208; 1632a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_r = v * 409; 1642a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1652a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp1 = y1 * 298; 1662a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b1 = (tmp1 + u_b) / 256; 1672a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 1682a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r1 = (tmp1 + v_r) / 256; 1692a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1702a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp2 = y2 * 298; 1712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b2 = (tmp2 + u_b) / 256; 1722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 1732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r2 = (tmp2 + v_r) / 256; 1742a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb1 = 1762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[r1] >> 3) << 11) 1772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 1782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[b1] >> 3); 1792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1802a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb2 = 1812a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[r2] >> 3) << 11) 1822a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 1832a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[b2] >> 3); 1842a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1854e260ab948787c2a814543077832847deae890fdJames Dong if (x + 1 < src.cropWidth()) { 1864e260ab948787c2a814543077832847deae890fdJames Dong *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 1874e260ab948787c2a814543077832847deae890fdJames Dong } else { 1884e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr[x] = rgb1; 1894e260ab948787c2a814543077832847deae890fdJames Dong } 1902a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 1912a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 192f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_ptr += src.mWidth * 2; 1934e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr += dst.mWidth; 1942a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 1951472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 1961472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return OK; 1972a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 1982a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1991472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convertYUV420Planar( 200f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const BitmapParams &src, const BitmapParams &dst) { 201d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber if (!((src.mCropLeft & 1) == 0 2021472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber && src.cropWidth() == dst.cropWidth() 2031472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber && src.cropHeight() == dst.cropHeight())) { 2041472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return ERROR_UNSUPPORTED; 2051472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber } 2062a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2071472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber uint8_t *kAdjustedClip = initClip(); 208f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 209d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber uint16_t *dst_ptr = (uint16_t *)dst.mBits 210d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber + dst.mCropTop * dst.mWidth + dst.mCropLeft; 211f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 212f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const uint8_t *src_y = 213f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; 2142a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2152a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber const uint8_t *src_u = 216f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src_y + src.mWidth * src.mHeight 217f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2; 2182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber const uint8_t *src_v = 220f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_u + (src.mWidth / 2) * (src.mHeight / 2); 2212a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 222f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 223f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 2242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // B = 1.164 * (Y - 16) + 2.018 * (U - 128) 2252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // G = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128) 2262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // R = 1.164 * (Y - 16) + 1.596 * (V - 128) 2272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // B = 298/256 * (Y - 16) + 517/256 * (U - 128) 2292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // G = .................. - 208/256 * (V - 128) - 100/256 * (U - 128) 2302a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // R = .................. + 409/256 * (V - 128) 2312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // min_B = (298 * (- 16) + 517 * (- 128)) / 256 = -277 2332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // min_G = (298 * (- 16) - 208 * (255 - 128) - 100 * (255 - 128)) / 256 = -172 2342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // min_R = (298 * (- 16) + 409 * (- 128)) / 256 = -223 2352a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // max_B = (298 * (255 - 16) + 517 * (255 - 128)) / 256 = 534 2372a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // max_G = (298 * (255 - 16) - 208 * (- 128) - 100 * (- 128)) / 256 = 432 2382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // max_R = (298 * (255 - 16) + 409 * (255 - 128)) / 256 = 481 2392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // clip range -278 .. 535 2412a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed y1 = (signed)src_y[x] - 16; 2432a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 2442a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u = (signed)src_u[x / 2] - 128; 2462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v = (signed)src_v[x / 2] - 128; 2472a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2482a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_b = u * 517; 2492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_g = -u * 100; 2502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_g = -v * 208; 2512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_r = v * 409; 2522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp1 = y1 * 298; 2542a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b1 = (tmp1 + u_b) / 256; 2552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 2562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r1 = (tmp1 + v_r) / 256; 2572a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2582a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp2 = y2 * 298; 2592a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b2 = (tmp2 + u_b) / 256; 2602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 2612a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r2 = (tmp2 + v_r) / 256; 2622a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2632a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb1 = 2642a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[r1] >> 3) << 11) 2652a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 2662a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[b1] >> 3); 2672a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2682a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb2 = 2692a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[r2] >> 3) << 11) 2702a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 2712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[b2] >> 3); 2722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 273d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber if (x + 1 < src.cropWidth()) { 274d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 275d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber } else { 276d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber dst_ptr[x] = rgb1; 277d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber } 2782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 2792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 280f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_y += src.mWidth; 2812a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2822a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (y & 1) { 283f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_u += src.mWidth / 2; 284f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_v += src.mWidth / 2; 2852a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 2862a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 287d7be5c5e812ad79d4838737a5e4dd81a8d776a0dAndreas Huber dst_ptr += dst.mWidth; 2882a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 2891472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 2901472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return OK; 2912a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 2922a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2931472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convertQCOMYUV420SemiPlanar( 294f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const BitmapParams &src, const BitmapParams &dst) { 2952a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint8_t *kAdjustedClip = initClip(); 2962a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2974e260ab948787c2a814543077832847deae890fdJames Dong if (!((src.mCropLeft & 1) == 0 2981472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber && src.cropWidth() == dst.cropWidth() 2991472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber && src.cropHeight() == dst.cropHeight())) { 3001472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return ERROR_UNSUPPORTED; 3011472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber } 302f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 3034e260ab948787c2a814543077832847deae890fdJames Dong uint16_t *dst_ptr = (uint16_t *)dst.mBits 3044e260ab948787c2a814543077832847deae890fdJames Dong + dst.mCropTop * dst.mWidth + dst.mCropLeft; 305f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 306f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const uint8_t *src_y = 307f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; 3082a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 3092a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber const uint8_t *src_u = 310f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src_y + src.mWidth * src.mHeight 311f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber + src.mCropTop * src.mWidth + src.mCropLeft; 3122a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 313f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 314f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 3152a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed y1 = (signed)src_y[x] - 16; 3162a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 3172a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 3182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u = (signed)src_u[x & ~1] - 128; 3192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v = (signed)src_u[(x & ~1) + 1] - 128; 3202a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 3212a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_b = u * 517; 3222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_g = -u * 100; 3232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_g = -v * 208; 3242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_r = v * 409; 3252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 3262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp1 = y1 * 298; 3272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b1 = (tmp1 + u_b) / 256; 3282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 3292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r1 = (tmp1 + v_r) / 256; 3302a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 3312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp2 = y2 * 298; 3322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b2 = (tmp2 + u_b) / 256; 3332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 3341c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed r2 = (tmp2 + v_r) / 256; 3351c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3361c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber uint32_t rgb1 = 3371c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber ((kAdjustedClip[b1] >> 3) << 11) 3381c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 3391c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber | (kAdjustedClip[r1] >> 3); 3401c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3411c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber uint32_t rgb2 = 3421c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber ((kAdjustedClip[b2] >> 3) << 11) 3431c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 3441c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber | (kAdjustedClip[r2] >> 3); 3451c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3464e260ab948787c2a814543077832847deae890fdJames Dong if (x + 1 < src.cropWidth()) { 3474e260ab948787c2a814543077832847deae890fdJames Dong *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 3484e260ab948787c2a814543077832847deae890fdJames Dong } else { 3494e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr[x] = rgb1; 3504e260ab948787c2a814543077832847deae890fdJames Dong } 3511c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber } 3521c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 353f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_y += src.mWidth; 3541c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3551c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber if (y & 1) { 356f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_u += src.mWidth; 3571c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber } 3581c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3594e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr += dst.mWidth; 3601c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber } 3611472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 3621472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return OK; 3631c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber} 3641c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3651472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convertYUV420SemiPlanar( 366f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const BitmapParams &src, const BitmapParams &dst) { 367f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber // XXX Untested 3681c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3691c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber uint8_t *kAdjustedClip = initClip(); 3701c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3714e260ab948787c2a814543077832847deae890fdJames Dong if (!((src.mCropLeft & 1) == 0 3721472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber && src.cropWidth() == dst.cropWidth() 3731472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber && src.cropHeight() == dst.cropHeight())) { 3741472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return ERROR_UNSUPPORTED; 3751472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber } 376f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 3774e260ab948787c2a814543077832847deae890fdJames Dong uint16_t *dst_ptr = (uint16_t *)dst.mBits 3784e260ab948787c2a814543077832847deae890fdJames Dong + dst.mCropTop * dst.mWidth + dst.mCropLeft; 379f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 380f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const uint8_t *src_y = 381f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; 3821c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3831c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber const uint8_t *src_u = 384f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src_y + src.mWidth * src.mHeight 385f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber + src.mCropTop * src.mWidth + src.mCropLeft; 3861c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 387f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 388f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 3891c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed y1 = (signed)src_y[x] - 16; 3901c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 3911c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3921c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed v = (signed)src_u[x & ~1] - 128; 3931c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed u = (signed)src_u[(x & ~1) + 1] - 128; 3941c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 3951c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed u_b = u * 517; 3961c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed u_g = -u * 100; 3971c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed v_g = -v * 208; 3981c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed v_r = v * 409; 3991c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 4001c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed tmp1 = y1 * 298; 4011c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed b1 = (tmp1 + u_b) / 256; 4021c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 4031c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed r1 = (tmp1 + v_r) / 256; 4041c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 4051c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed tmp2 = y2 * 298; 4061c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed b2 = (tmp2 + u_b) / 256; 4071c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 4082a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r2 = (tmp2 + v_r) / 256; 4092a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4102a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb1 = 4112a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[b1] >> 3) << 11) 4122a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 4132a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[r1] >> 3); 4142a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4152a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb2 = 4162a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[b2] >> 3) << 11) 4172a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 4182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[r2] >> 3); 4192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4204e260ab948787c2a814543077832847deae890fdJames Dong if (x + 1 < src.cropWidth()) { 4214e260ab948787c2a814543077832847deae890fdJames Dong *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 4224e260ab948787c2a814543077832847deae890fdJames Dong } else { 4234e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr[x] = rgb1; 4244e260ab948787c2a814543077832847deae890fdJames Dong } 4252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 4262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 427f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_y += src.mWidth; 4282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (y & 1) { 430f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_u += src.mWidth; 4312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 4322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4334e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr += dst.mWidth; 4342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 4351472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 4361472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return OK; 4372a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 4382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 439cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajanstatus_t ColorConverter::convertTIYUV420PackedSemiPlanar( 440cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan const BitmapParams &src, const BitmapParams &dst) { 4413571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber uint8_t *kAdjustedClip = initClip(); 442cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 4434e260ab948787c2a814543077832847deae890fdJames Dong if (!((src.mCropLeft & 1) == 0 4443571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber && src.cropWidth() == dst.cropWidth() 4453571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber && src.cropHeight() == dst.cropHeight())) { 4463571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber return ERROR_UNSUPPORTED; 4473571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber } 448cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 4494e260ab948787c2a814543077832847deae890fdJames Dong uint16_t *dst_ptr = (uint16_t *)dst.mBits 4504e260ab948787c2a814543077832847deae890fdJames Dong + dst.mCropTop * dst.mWidth + dst.mCropLeft; 451cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 452cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan const uint8_t *src_y = (const uint8_t *)src.mBits; 453cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 4543571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber const uint8_t *src_u = 4553571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber (const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2); 456cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 4573571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 4583571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 4593571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber signed y1 = (signed)src_y[x] - 16; 4603571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 461cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 4623571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber signed u = (signed)src_u[x & ~1] - 128; 4633571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber signed v = (signed)src_u[(x & ~1) + 1] - 128; 464cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 465cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed u_b = u * 517; 466cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed u_g = -u * 100; 467cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed v_g = -v * 208; 468cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed v_r = v * 409; 469cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 470cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed tmp1 = y1 * 298; 471cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed b1 = (tmp1 + u_b) / 256; 472cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed g1 = (tmp1 + v_g + u_g) / 256; 473cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed r1 = (tmp1 + v_r) / 256; 474cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 475cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed tmp2 = y2 * 298; 476cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed b2 = (tmp2 + u_b) / 256; 477cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed g2 = (tmp2 + v_g + u_g) / 256; 478cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed r2 = (tmp2 + v_r) / 256; 479cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 480cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan uint32_t rgb1 = 481cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan ((kAdjustedClip[r1] >> 3) << 11) 482cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan | ((kAdjustedClip[g1] >> 2) << 5) 483cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan | (kAdjustedClip[b1] >> 3); 484cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 485cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan uint32_t rgb2 = 486cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan ((kAdjustedClip[r2] >> 3) << 11) 4873571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 4883571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber | (kAdjustedClip[b2] >> 3); 489cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 4904e260ab948787c2a814543077832847deae890fdJames Dong if (x + 1 < src.cropWidth()) { 4914e260ab948787c2a814543077832847deae890fdJames Dong *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 4924e260ab948787c2a814543077832847deae890fdJames Dong } else { 4934e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr[x] = rgb1; 4944e260ab948787c2a814543077832847deae890fdJames Dong } 495cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan } 496cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 4973571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber src_y += src.mWidth; 4983571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber 4993571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber if (y & 1) { 5003571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber src_u += src.mWidth; 501cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan } 502cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 5034e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr += dst.mWidth; 504cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan } 5053571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber 506cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan return OK; 507cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan} 508cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 5092a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberuint8_t *ColorConverter::initClip() { 5102a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber static const signed kClipMin = -278; 5112a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber static const signed kClipMax = 535; 5122a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 5132a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (mClip == NULL) { 5142a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClip = new uint8_t[kClipMax - kClipMin + 1]; 5152a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 5162a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber for (signed i = kClipMin; i <= kClipMax; ++i) { 5172a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i; 5182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 5192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 5202a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 5212a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return &mClip[-kClipMin]; 5222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 5232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 5242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} // namespace android 525