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> 222d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#include <media/stagefright/foundation/ALooper.h> 232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/ColorConverter.h> 241472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber#include <media/stagefright/MediaErrors.h> 252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 26d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang#include "libyuv/convert_from.h" 27026d520295b52d136a6962a05882a696fe620725Chong Zhang#include "libyuv/video_common.h" 284fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang#include <functional> 292d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#include <sys/time.h> 302d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 31d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang#define USE_LIBYUV 322d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#define PERF_PROFILING 0 332d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 342d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 352d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#if defined(__aarch64__) || defined(__ARM_NEON__) 362d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#define USE_NEON_Y410 1 372d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#else 382d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#define USE_NEON_Y410 0 392d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#endif 402d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 412d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#if USE_NEON_Y410 422d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#include <arm_neon.h> 432d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#endif 44d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang 452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Hubernamespace android { 462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 472a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberColorConverter::ColorConverter( 482a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber OMX_COLOR_FORMATTYPE from, OMX_COLOR_FORMATTYPE to) 492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber : mSrcFormat(from), 502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mDstFormat(to), 512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClip(NULL) { 522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 542a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberColorConverter::~ColorConverter() { 552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber delete[] mClip; 562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClip = NULL; 572a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 582a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 592a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberbool ColorConverter::isValid() const { 602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber switch (mSrcFormat) { 614fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang case OMX_COLOR_FormatYUV420Planar16: 624fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang if (mDstFormat == OMX_COLOR_FormatYUV444Y410) { 634fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return true; 644fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang } 654fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang // fall-thru 662a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_COLOR_FormatYUV420Planar: 67026d520295b52d136a6962a05882a696fe620725Chong Zhang return mDstFormat == OMX_COLOR_Format16bitRGB565 68026d520295b52d136a6962a05882a696fe620725Chong Zhang || mDstFormat == OMX_COLOR_Format32BitRGBA8888 69026d520295b52d136a6962a05882a696fe620725Chong Zhang || mDstFormat == OMX_COLOR_Format32bitBGRA8888; 70026d520295b52d136a6962a05882a696fe620725Chong Zhang 712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_COLOR_FormatCbYCrY: 722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: 731c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber case OMX_COLOR_FormatYUV420SemiPlanar: 74cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: 75026d520295b52d136a6962a05882a696fe620725Chong Zhang return mDstFormat == OMX_COLOR_Format16bitRGB565; 762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber default: 782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return false; 792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 802a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 812a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 825343bc86119430e55fe43e132242291a74164f27Chong Zhangbool ColorConverter::isDstRGB() const { 835343bc86119430e55fe43e132242291a74164f27Chong Zhang return mDstFormat == OMX_COLOR_Format16bitRGB565 845343bc86119430e55fe43e132242291a74164f27Chong Zhang || mDstFormat == OMX_COLOR_Format32BitRGBA8888 855343bc86119430e55fe43e132242291a74164f27Chong Zhang || mDstFormat == OMX_COLOR_Format32bitBGRA8888; 865343bc86119430e55fe43e132242291a74164f27Chong Zhang} 875343bc86119430e55fe43e132242291a74164f27Chong Zhang 88f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas HuberColorConverter::BitmapParams::BitmapParams( 89f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber void *bits, 902a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber size_t width, size_t height, 91f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t cropLeft, size_t cropTop, 92026d520295b52d136a6962a05882a696fe620725Chong Zhang size_t cropRight, size_t cropBottom, 93026d520295b52d136a6962a05882a696fe620725Chong Zhang OMX_COLOR_FORMATTYPE colorFromat) 94f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber : mBits(bits), 95026d520295b52d136a6962a05882a696fe620725Chong Zhang mColorFormat(colorFromat), 96f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mWidth(width), 97f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mHeight(height), 98f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCropLeft(cropLeft), 99f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCropTop(cropTop), 100f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCropRight(cropRight), 101f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber mCropBottom(cropBottom) { 102026d520295b52d136a6962a05882a696fe620725Chong Zhang switch(mColorFormat) { 103026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format16bitRGB565: 104026d520295b52d136a6962a05882a696fe620725Chong Zhang mBpp = 2; 105026d520295b52d136a6962a05882a696fe620725Chong Zhang mStride = 2 * mWidth; 106026d520295b52d136a6962a05882a696fe620725Chong Zhang break; 107026d520295b52d136a6962a05882a696fe620725Chong Zhang 108026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format32bitBGRA8888: 109026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format32BitRGBA8888: 1105343bc86119430e55fe43e132242291a74164f27Chong Zhang case OMX_COLOR_FormatYUV444Y410: 111026d520295b52d136a6962a05882a696fe620725Chong Zhang mBpp = 4; 112026d520295b52d136a6962a05882a696fe620725Chong Zhang mStride = 4 * mWidth; 113026d520295b52d136a6962a05882a696fe620725Chong Zhang break; 114026d520295b52d136a6962a05882a696fe620725Chong Zhang 1152d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang case OMX_COLOR_FormatYUV420Planar16: 1162d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang mBpp = 2; 1172d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang mStride = 2 * mWidth; 1182d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang break; 1192d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 120026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_FormatYUV420Planar: 121026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_FormatCbYCrY: 122026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: 123026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_FormatYUV420SemiPlanar: 124026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: 125026d520295b52d136a6962a05882a696fe620725Chong Zhang mBpp = 1; 126026d520295b52d136a6962a05882a696fe620725Chong Zhang mStride = mWidth; 127026d520295b52d136a6962a05882a696fe620725Chong Zhang break; 128026d520295b52d136a6962a05882a696fe620725Chong Zhang 129026d520295b52d136a6962a05882a696fe620725Chong Zhang default: 130026d520295b52d136a6962a05882a696fe620725Chong Zhang ALOGE("Unsupported color format %d", mColorFormat); 131026d520295b52d136a6962a05882a696fe620725Chong Zhang mBpp = 1; 132026d520295b52d136a6962a05882a696fe620725Chong Zhang mStride = mWidth; 133026d520295b52d136a6962a05882a696fe620725Chong Zhang break; 134026d520295b52d136a6962a05882a696fe620725Chong Zhang } 135f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber} 136f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 137f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Hubersize_t ColorConverter::BitmapParams::cropWidth() const { 138f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber return mCropRight - mCropLeft + 1; 139f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber} 140f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 141f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Hubersize_t ColorConverter::BitmapParams::cropHeight() const { 142f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber return mCropBottom - mCropTop + 1; 143f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber} 144f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 1451472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convert( 146f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const void *srcBits, 147f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t srcWidth, size_t srcHeight, 148f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t srcCropLeft, size_t srcCropTop, 149f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t srcCropRight, size_t srcCropBottom, 150f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber void *dstBits, 151f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t dstWidth, size_t dstHeight, 152f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t dstCropLeft, size_t dstCropTop, 153f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber size_t dstCropRight, size_t dstCropBottom) { 154f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber BitmapParams src( 155f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const_cast<void *>(srcBits), 156f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber srcWidth, srcHeight, 157026d520295b52d136a6962a05882a696fe620725Chong Zhang srcCropLeft, srcCropTop, srcCropRight, srcCropBottom, mSrcFormat); 158f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 159f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber BitmapParams dst( 160f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber dstBits, 161f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber dstWidth, dstHeight, 162026d520295b52d136a6962a05882a696fe620725Chong Zhang dstCropLeft, dstCropTop, dstCropRight, dstCropBottom, mDstFormat); 163f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 164d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang if (!((src.mCropLeft & 1) == 0 165d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang && src.cropWidth() == dst.cropWidth() 166d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang && src.cropHeight() == dst.cropHeight())) { 167d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang return ERROR_UNSUPPORTED; 168d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang } 169d3e0d861aa68a7ef129fe228595bff734448ebc8Chong Zhang 1701472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber status_t err; 1711472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 1722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber switch (mSrcFormat) { 1732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_COLOR_FormatYUV420Planar: 174d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang#ifdef USE_LIBYUV 175d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang err = convertYUV420PlanarUseLibYUV(src, dst); 176d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang#else 1771472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber err = convertYUV420Planar(src, dst); 178d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang#endif 1792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber break; 1802a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1812d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang case OMX_COLOR_FormatYUV420Planar16: 1822d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang { 1832d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#if PERF_PROFILING 1842d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang int64_t startTimeUs = ALooper::GetNowUs(); 1852d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#endif 1862d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang err = convertYUV420Planar16(src, dst); 1872d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#if PERF_PROFILING 1882d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang int64_t endTimeUs = ALooper::GetNowUs(); 1892d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang ALOGD("convertYUV420Planar16 took %lld us", (long long) (endTimeUs - startTimeUs)); 1902d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#endif 1912d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang break; 1922d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 1932d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 1942a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_COLOR_FormatCbYCrY: 1951472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber err = convertCbYCrY(src, dst); 1962a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber break; 1972a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1982a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: 1991472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber err = convertQCOMYUV420SemiPlanar(src, dst); 2002a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber break; 2012a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2021c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber case OMX_COLOR_FormatYUV420SemiPlanar: 2031472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber err = convertYUV420SemiPlanar(src, dst); 2041c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber break; 2051c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 206cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: 207cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan err = convertTIYUV420PackedSemiPlanar(src, dst); 208cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan break; 209cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 2102a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber default: 2112a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber { 2122a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber CHECK(!"Should not be here. Unknown color conversion."); 2132a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber break; 2142a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 2152a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 2161472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 2171472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return err; 2182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 2192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2201472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convertCbYCrY( 221f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const BitmapParams &src, const BitmapParams &dst) { 222f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber // XXX Untested 2232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint8_t *kAdjustedClip = initClip(); 2252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2264e260ab948787c2a814543077832847deae890fdJames Dong uint16_t *dst_ptr = (uint16_t *)dst.mBits 2274e260ab948787c2a814543077832847deae890fdJames Dong + dst.mCropTop * dst.mWidth + dst.mCropLeft; 2282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 229f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const uint8_t *src_ptr = (const uint8_t *)src.mBits 230f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber + (src.mCropTop * dst.mWidth + src.mCropLeft) * 2; 2312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 232f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 233f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 234f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber signed y1 = (signed)src_ptr[2 * x + 1] - 16; 235f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber signed y2 = (signed)src_ptr[2 * x + 3] - 16; 236f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber signed u = (signed)src_ptr[2 * x] - 128; 237f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber signed v = (signed)src_ptr[2 * x + 2] - 128; 2382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_b = u * 517; 2402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_g = -u * 100; 2412a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_g = -v * 208; 2422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_r = v * 409; 2432a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2442a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp1 = y1 * 298; 2452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b1 = (tmp1 + u_b) / 256; 2462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 2472a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r1 = (tmp1 + v_r) / 256; 2482a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp2 = y2 * 298; 2502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b2 = (tmp2 + u_b) / 256; 2512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 2522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r2 = (tmp2 + v_r) / 256; 2532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2542a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb1 = 2552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[r1] >> 3) << 11) 2562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 2572a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[b1] >> 3); 2582a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2592a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb2 = 2602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[r2] >> 3) << 11) 2612a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 2622a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[b2] >> 3); 2632a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2644e260ab948787c2a814543077832847deae890fdJames Dong if (x + 1 < src.cropWidth()) { 2654e260ab948787c2a814543077832847deae890fdJames Dong *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 2664e260ab948787c2a814543077832847deae890fdJames Dong } else { 2674e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr[x] = rgb1; 2684e260ab948787c2a814543077832847deae890fdJames Dong } 2692a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 2702a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 271f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_ptr += src.mWidth * 2; 2724e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr += dst.mWidth; 2732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 2741472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 2751472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return OK; 2762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 2772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 278d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuangstatus_t ColorConverter::convertYUV420PlanarUseLibYUV( 279d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang const BitmapParams &src, const BitmapParams &dst) { 280026d520295b52d136a6962a05882a696fe620725Chong Zhang uint8_t *dst_ptr = (uint8_t *)dst.mBits 281026d520295b52d136a6962a05882a696fe620725Chong Zhang + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp; 282d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang 283d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang const uint8_t *src_y = 284026d520295b52d136a6962a05882a696fe620725Chong Zhang (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft; 285d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang 286d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang const uint8_t *src_u = 287026d520295b52d136a6962a05882a696fe620725Chong Zhang (const uint8_t *)src.mBits + src.mStride * src.mHeight 288026d520295b52d136a6962a05882a696fe620725Chong Zhang + (src.mCropTop / 2) * (src.mStride / 2) + (src.mCropLeft / 2); 289d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang 290d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang const uint8_t *src_v = 291026d520295b52d136a6962a05882a696fe620725Chong Zhang src_u + (src.mStride / 2) * (src.mHeight / 2); 292026d520295b52d136a6962a05882a696fe620725Chong Zhang 293026d520295b52d136a6962a05882a696fe620725Chong Zhang switch (mDstFormat) { 294026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format16bitRGB565: 295026d520295b52d136a6962a05882a696fe620725Chong Zhang libyuv::I420ToRGB565(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2, 296026d520295b52d136a6962a05882a696fe620725Chong Zhang (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight()); 297026d520295b52d136a6962a05882a696fe620725Chong Zhang break; 298d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang 299026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format32BitRGBA8888: 300026d520295b52d136a6962a05882a696fe620725Chong Zhang libyuv::ConvertFromI420(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2, 301026d520295b52d136a6962a05882a696fe620725Chong Zhang (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight(), libyuv::FOURCC_ABGR); 302026d520295b52d136a6962a05882a696fe620725Chong Zhang break; 303d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang 304026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format32bitBGRA8888: 305026d520295b52d136a6962a05882a696fe620725Chong Zhang libyuv::ConvertFromI420(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2, 306026d520295b52d136a6962a05882a696fe620725Chong Zhang (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight(), libyuv::FOURCC_ARGB); 307026d520295b52d136a6962a05882a696fe620725Chong Zhang break; 308026d520295b52d136a6962a05882a696fe620725Chong Zhang 309026d520295b52d136a6962a05882a696fe620725Chong Zhang default: 310026d520295b52d136a6962a05882a696fe620725Chong Zhang return ERROR_UNSUPPORTED; 311026d520295b52d136a6962a05882a696fe620725Chong Zhang } 312d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang 313d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang return OK; 314d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang} 315d36af484a8dd3bbaf7ed7de31852c9f802243392Hangyu Kuang 3164fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhangstd::function<void (void *, void *, void *, size_t, 3174fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed *, signed *, signed *, signed *)> 3184fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong ZhanggetReadFromSrc(OMX_COLOR_FORMATTYPE srcFormat) { 3194fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang switch(srcFormat) { 3204fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang case OMX_COLOR_FormatYUV420Planar: 3214fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return [](void *src_y, void *src_u, void *src_v, size_t x, 3224fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed *y1, signed *y2, signed *u, signed *v) { 3234fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *y1 = ((uint8_t*)src_y)[x] - 16; 3244fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *y2 = ((uint8_t*)src_y)[x + 1] - 16; 3254fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *u = ((uint8_t*)src_u)[x / 2] - 128; 3264fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *v = ((uint8_t*)src_v)[x / 2] - 128; 3274fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang }; 3284fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang case OMX_COLOR_FormatYUV420Planar16: 3294fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return [](void *src_y, void *src_u, void *src_v, size_t x, 3304fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed *y1, signed *y2, signed *u, signed *v) { 3314fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *y1 = (signed)(((uint16_t*)src_y)[x] >> 2) - 16; 3324fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *y2 = (signed)(((uint16_t*)src_y)[x + 1] >> 2) - 16; 3334fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *u = (signed)(((uint16_t*)src_u)[x / 2] >> 2) - 128; 3344fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *v = (signed)(((uint16_t*)src_v)[x / 2] >> 2) - 128; 3354fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang }; 3364fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang default: 3374fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang TRESPASS(); 3384fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang } 3394fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return nullptr; 3404fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang} 3414fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang 3424fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhangstd::function<void (void *, bool, signed, signed, signed, signed, signed, signed)> 3434fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong ZhanggetWriteToDst(OMX_COLOR_FORMATTYPE dstFormat, uint8_t *kAdjustedClip) { 3444fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang switch (dstFormat) { 345026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format16bitRGB565: 346026d520295b52d136a6962a05882a696fe620725Chong Zhang { 3474fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return [kAdjustedClip](void *dst_ptr, bool uncropped, 3484fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed r1, signed g1, signed b1, 3494fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed r2, signed g2, signed b2) { 3504fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang uint32_t rgb1 = 3514fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang ((kAdjustedClip[r1] >> 3) << 11) 3524fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | ((kAdjustedClip[g1] >> 2) << 5) 3534fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[b1] >> 3); 354026d520295b52d136a6962a05882a696fe620725Chong Zhang 3554fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang if (uncropped) { 3564fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang uint32_t rgb2 = 3574fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang ((kAdjustedClip[r2] >> 3) << 11) 3584fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | ((kAdjustedClip[g2] >> 2) << 5) 3594fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[b2] >> 3); 360026d520295b52d136a6962a05882a696fe620725Chong Zhang 3614fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *(uint32_t *)dst_ptr = (rgb2 << 16) | rgb1; 3624fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang } else { 3634fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang *(uint16_t *)dst_ptr = rgb1; 3644fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang } 3654fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang }; 366026d520295b52d136a6962a05882a696fe620725Chong Zhang } 367026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format32BitRGBA8888: 368026d520295b52d136a6962a05882a696fe620725Chong Zhang { 3694fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return [kAdjustedClip](void *dst_ptr, bool uncropped, 3704fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed r1, signed g1, signed b1, 3714fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed r2, signed g2, signed b2) { 3724fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang ((uint32_t *)dst_ptr)[0] = 3734fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang (kAdjustedClip[r1]) 3744fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[g1] << 8) 3754fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[b1] << 16) 376026d520295b52d136a6962a05882a696fe620725Chong Zhang | (0xFF << 24); 3774fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang 3784fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang if (uncropped) { 3794fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang ((uint32_t *)dst_ptr)[1] = 3804fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang (kAdjustedClip[r2]) 3814fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[g2] << 8) 3824fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[b2] << 16) 3834fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (0xFF << 24); 3844fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang } 3854fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang }; 386026d520295b52d136a6962a05882a696fe620725Chong Zhang } 387026d520295b52d136a6962a05882a696fe620725Chong Zhang case OMX_COLOR_Format32bitBGRA8888: 388026d520295b52d136a6962a05882a696fe620725Chong Zhang { 3894fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return [kAdjustedClip](void *dst_ptr, bool uncropped, 3904fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed r1, signed g1, signed b1, 3914fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed r2, signed g2, signed b2) { 3924fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang ((uint32_t *)dst_ptr)[0] = 3934fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang (kAdjustedClip[b1]) 3944fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[g1] << 8) 3954fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[r1] << 16) 396026d520295b52d136a6962a05882a696fe620725Chong Zhang | (0xFF << 24); 3974fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang 3984fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang if (uncropped) { 3994fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang ((uint32_t *)dst_ptr)[1] = 4004fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang (kAdjustedClip[b2]) 4014fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[g2] << 8) 4024fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (kAdjustedClip[r2] << 16) 4034fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang | (0xFF << 24); 4044fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang } 4054fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang }; 406026d520295b52d136a6962a05882a696fe620725Chong Zhang } 407026d520295b52d136a6962a05882a696fe620725Chong Zhang default: 4084fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang TRESPASS(); 409026d520295b52d136a6962a05882a696fe620725Chong Zhang } 4104fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return nullptr; 411026d520295b52d136a6962a05882a696fe620725Chong Zhang} 4124fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang 4131472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convertYUV420Planar( 414f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const BitmapParams &src, const BitmapParams &dst) { 4151472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber uint8_t *kAdjustedClip = initClip(); 416f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 4174fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang auto readFromSrc = getReadFromSrc(mSrcFormat); 4184fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang auto writeToDst = getWriteToDst(mDstFormat, kAdjustedClip); 4194fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang 420026d520295b52d136a6962a05882a696fe620725Chong Zhang uint8_t *dst_ptr = (uint8_t *)dst.mBits 4214fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp; 422f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 4234fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang uint8_t *src_y = (uint8_t *)src.mBits 4244fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang + src.mCropTop * src.mStride + src.mCropLeft * src.mBpp; 4252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4264fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang uint8_t *src_u = (uint8_t *)src.mBits + src.mStride * src.mHeight 4274fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2 * src.mBpp; 4282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4294fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang uint8_t *src_v = src_u + (src.mStride / 2) * (src.mHeight / 2); 4302a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 431f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 432f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 4332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // B = 1.164 * (Y - 16) + 2.018 * (U - 128) 4342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // G = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128) 4352a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // R = 1.164 * (Y - 16) + 1.596 * (V - 128) 4362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4372a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // B = 298/256 * (Y - 16) + 517/256 * (U - 128) 4382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // G = .................. - 208/256 * (V - 128) - 100/256 * (U - 128) 4392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // R = .................. + 409/256 * (V - 128) 4402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4412a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // min_B = (298 * (- 16) + 517 * (- 128)) / 256 = -277 4422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // min_G = (298 * (- 16) - 208 * (255 - 128) - 100 * (255 - 128)) / 256 = -172 4432a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // min_R = (298 * (- 16) + 409 * (- 128)) / 256 = -223 4442a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // max_B = (298 * (255 - 16) + 517 * (255 - 128)) / 256 = 534 4462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // max_G = (298 * (255 - 16) - 208 * (- 128) - 100 * (- 128)) / 256 = 432 4472a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // max_R = (298 * (255 - 16) + 409 * (255 - 128)) / 256 = 481 4482a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber // clip range -278 .. 535 4502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4514fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang signed y1, y2, u, v; 4524fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang readFromSrc(src_y, src_u, src_v, x, &y1, &y2, &u, &v); 4532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4542a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_b = u * 517; 4552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_g = -u * 100; 4562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_g = -v * 208; 4572a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_r = v * 409; 4582a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4592a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp1 = y1 * 298; 4602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b1 = (tmp1 + u_b) / 256; 4612a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 4622a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r1 = (tmp1 + v_r) / 256; 4632a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4642a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp2 = y2 * 298; 4652a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b2 = (tmp2 + u_b) / 256; 4662a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 4672a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r2 = (tmp2 + v_r) / 256; 4682a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 469026d520295b52d136a6962a05882a696fe620725Chong Zhang bool uncropped = x + 1 < src.cropWidth(); 4704fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang writeToDst(dst_ptr + x * dst.mBpp, uncropped, r1, g1, b1, r2, g2, b2); 4712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 4722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 473026d520295b52d136a6962a05882a696fe620725Chong Zhang src_y += src.mStride; 4742a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (y & 1) { 476026d520295b52d136a6962a05882a696fe620725Chong Zhang src_u += src.mStride / 2; 477026d520295b52d136a6962a05882a696fe620725Chong Zhang src_v += src.mStride / 2; 4782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 4792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 480026d520295b52d136a6962a05882a696fe620725Chong Zhang dst_ptr += dst.mStride; 4812a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 4821472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 4831472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return OK; 4842a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 4852a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 4864fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhangstatus_t ColorConverter::convertYUV420Planar16( 4874fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang const BitmapParams &src, const BitmapParams &dst) { 4884fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang if (mDstFormat == OMX_COLOR_FormatYUV444Y410) { 4894fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return convertYUV420Planar16ToY410(src, dst); 4904fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang } 4914fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang 4924fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang return convertYUV420Planar(src, dst); 4934fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang} 4944fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhang 4952d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang/* 4962d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * Pack 10-bit YUV into RGBA_1010102. 4972d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * 4982d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * Media sends 10-bit YUV in a RGBA_1010102 format buffer. SF will handle 4992d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * the conversion to RGB using RenderEngine fallback. 5002d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * 5012d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * We do not perform a YUV->RGB conversion here, however the conversion with 5022d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * BT2020 to Full range is below for reference: 5032d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * 5042d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * B = 1.168 *(Y - 64) + 2.148 *(U - 512) 5052d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * G = 1.168 *(Y - 64) - 0.652 *(V - 512) - 0.188 *(U - 512) 5062d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * R = 1.168 *(Y - 64) + 1.683 *(V - 512) 5072d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * 5082d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * B = 1196/1024 *(Y - 64) + 2200/1024 *(U - 512) 5092d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * G = .................... - 668/1024 *(V - 512) - 192/1024 *(U - 512) 5102d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * R = .................... + 1723/1024 *(V - 512) 5112d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * 5122d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * min_B = (1196 *(- 64) + 2200 *(- 512)) / 1024 = -1175 5132d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * min_G = (1196 *(- 64) - 668 *(1023 - 512) - 192 *(1023 - 512)) / 1024 = -504 5142d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * min_R = (1196 *(- 64) + 1723 *(- 512)) / 1024 = -937 5152d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * 5162d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * max_B = (1196 *(1023 - 64) + 2200 *(1023 - 512)) / 1024 = 2218 5172d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * max_G = (1196 *(1023 - 64) - 668 *(- 512) - 192 *(- 512)) / 1024 = 1551 5182d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * max_R = (1196 *(1023 - 64) + 1723 *(1023 - 512)) / 1024 = 1980 5192d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * 5202d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * clip range -1175 .. 2218 5212d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang * 5222d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang */ 5232d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5242d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#if !USE_NEON_Y410 5252d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5264fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhangstatus_t ColorConverter::convertYUV420Planar16ToY410( 5272d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const BitmapParams &src, const BitmapParams &dst) { 5282d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint8_t *dst_ptr = (uint8_t *)dst.mBits 5292d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp; 5302d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5312d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_y = 5322d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft * src.mBpp; 5332d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5342d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_u = 5352d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang (const uint8_t *)src.mBits + src.mStride * src.mHeight 5362d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang + (src.mCropTop / 2) * (src.mStride / 2) + (src.mCropLeft / 2) * src.mBpp; 5372d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5382d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_v = 5392d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_u + (src.mStride / 2) * (src.mHeight / 2); 5402d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5412d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang // Converting two lines at a time, slightly faster 5422d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang for (size_t y = 0; y < src.cropHeight(); y += 2) { 5432d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32_t *dst_top = (uint32_t *) dst_ptr; 5442d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32_t *dst_bot = (uint32_t *) (dst_ptr + dst.mStride); 5452d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_ytop = (uint16_t*) src_y; 5462d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_ybot = (uint16_t*) (src_y + src.mStride); 5472d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_u = (uint16_t*) src_u; 5482d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_v = (uint16_t*) src_v; 5492d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5502d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32_t u01, v01, y01, y23, y45, y67, uv0, uv1; 5512d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang size_t x = 0; 5522d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang for (; x < src.cropWidth() - 3; x += 4) { 5532d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang u01 = *((uint32_t*)ptr_u); ptr_u += 2; 5542d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang v01 = *((uint32_t*)ptr_v); ptr_v += 2; 5552d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5562d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang y01 = *((uint32_t*)ptr_ytop); ptr_ytop += 2; 5572d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang y23 = *((uint32_t*)ptr_ytop); ptr_ytop += 2; 5582d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang y45 = *((uint32_t*)ptr_ybot); ptr_ybot += 2; 5592d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang y67 = *((uint32_t*)ptr_ybot); ptr_ybot += 2; 5602d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5612d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20); 5622d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uv1 = (u01 >> 16) | ((v01 >> 16) << 20); 5632d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5642d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_top++ = ((y01 & 0x3FF) << 10) | uv0; 5652d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_top++ = ((y01 >> 16) << 10) | uv0; 5662d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_top++ = ((y23 & 0x3FF) << 10) | uv1; 5672d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_top++ = ((y23 >> 16) << 10) | uv1; 5682d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5692d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_bot++ = ((y45 & 0x3FF) << 10) | uv0; 5702d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_bot++ = ((y45 >> 16) << 10) | uv0; 5712d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_bot++ = ((y67 & 0x3FF) << 10) | uv1; 5722d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_bot++ = ((y67 >> 16) << 10) | uv1; 5732d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 5742d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5752d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang // There should be at most 2 more pixels to process. Note that we don't 5762d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang // need to consider odd case as the buffer is always aligned to even. 5772d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang if (x < src.cropWidth()) { 5782d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang u01 = *ptr_u; 5792d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang v01 = *ptr_v; 5802d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang y01 = *((uint32_t*)ptr_ytop); 5812d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang y45 = *((uint32_t*)ptr_ybot); 5822d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uv0 = (u01 & 0x3FF) | ((v01 & 0x3FF) << 20); 5832d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_top++ = ((y01 & 0x3FF) << 10) | uv0; 5842d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_top++ = ((y01 >> 16) << 10) | uv0; 5852d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_bot++ = ((y45 & 0x3FF) << 10) | uv0; 5862d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *dst_bot++ = ((y45 >> 16) << 10) | uv0; 5872d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 5882d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5892d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_y += src.mStride * 2; 5902d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_u += src.mStride / 2; 5912d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_v += src.mStride / 2; 5922d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang dst_ptr += dst.mStride * 2; 5932d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 5942d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5952d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang return OK; 5962d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang} 5972d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 5982d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#else 5992d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6004fdc4ce9d1a9d94801faf904ebf4f11e009fdec7Chong Zhangstatus_t ColorConverter::convertYUV420Planar16ToY410( 6012d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const BitmapParams &src, const BitmapParams &dst) { 6022d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint8_t *out = (uint8_t *)dst.mBits 6032d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp; 6042d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6052d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_y = 6062d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft * src.mBpp; 6072d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6082d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_u = 6092d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang (const uint8_t *)src.mBits + src.mStride * src.mHeight 6102d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang + (src.mCropTop / 2) * (src.mStride / 2) + (src.mCropLeft / 2) * src.mBpp; 6112d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6122d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_v = 6132d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_u + (src.mStride / 2) * (src.mHeight / 2); 6142d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6152d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang for (size_t y = 0; y < src.cropHeight(); y++) { 6162d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_y = (uint16_t*) src_y; 6172d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_u = (uint16_t*) src_u; 6182d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_v = (uint16_t*) src_v; 6192d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32_t *ptr_out = (uint32_t *) out; 6202d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6212d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang // Process 16-pixel at a time. 6222d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32_t *ptr_limit = ptr_out + (src.cropWidth() & ~15); 6232d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang while (ptr_out < ptr_limit) { 6242d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16x4_t u0123 = vld1_u16(ptr_u); ptr_u += 4; 6252d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16x4_t u4567 = vld1_u16(ptr_u); ptr_u += 4; 6262d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16x4_t v0123 = vld1_u16(ptr_v); ptr_v += 4; 6272d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16x4_t v4567 = vld1_u16(ptr_v); ptr_v += 4; 6282d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16x4_t y0123 = vld1_u16(ptr_y); ptr_y += 4; 6292d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16x4_t y4567 = vld1_u16(ptr_y); ptr_y += 4; 6302d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16x4_t y89ab = vld1_u16(ptr_y); ptr_y += 4; 6312d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16x4_t ycdef = vld1_u16(ptr_y); ptr_y += 4; 6322d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6332d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32x2_t uvtempl; 6342d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32x4_t uvtempq; 6352d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6362d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uvtempq = vaddw_u16(vshll_n_u16(v0123, 20), u0123); 6372d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6382d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uvtempl = vget_low_u32(uvtempq); 6392d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32x4_t uv0011 = vreinterpretq_u32_u64( 6402d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang vaddw_u32(vshll_n_u32(uvtempl, 32), uvtempl)); 6412d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6422d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uvtempl = vget_high_u32(uvtempq); 6432d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32x4_t uv2233 = vreinterpretq_u32_u64( 6442d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang vaddw_u32(vshll_n_u32(uvtempl, 32), uvtempl)); 6452d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6462d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uvtempq = vaddw_u16(vshll_n_u16(v4567, 20), u4567); 6472d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6482d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uvtempl = vget_low_u32(uvtempq); 6492d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32x4_t uv4455 = vreinterpretq_u32_u64( 6502d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang vaddw_u32(vshll_n_u32(uvtempl, 32), uvtempl)); 6512d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6522d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uvtempl = vget_high_u32(uvtempq); 6532d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32x4_t uv6677 = vreinterpretq_u32_u64( 6542d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang vaddw_u32(vshll_n_u32(uvtempl, 32), uvtempl)); 6552d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6562d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32x4_t dsttemp; 6572d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6582d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang dsttemp = vorrq_u32(uv0011, vshll_n_u16(y0123, 10)); 6592d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang vst1q_u32(ptr_out, dsttemp); ptr_out += 4; 6602d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6612d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang dsttemp = vorrq_u32(uv2233, vshll_n_u16(y4567, 10)); 6622d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang vst1q_u32(ptr_out, dsttemp); ptr_out += 4; 6632d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6642d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang dsttemp = vorrq_u32(uv4455, vshll_n_u16(y89ab, 10)); 6652d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang vst1q_u32(ptr_out, dsttemp); ptr_out += 4; 6662d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6672d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang dsttemp = vorrq_u32(uv6677, vshll_n_u16(ycdef, 10)); 6682d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang vst1q_u32(ptr_out, dsttemp); ptr_out += 4; 6692d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 6702d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6712d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_y += src.mStride; 6722d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang if (y & 1) { 6732d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_u += src.mStride / 2; 6742d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_v += src.mStride / 2; 6752d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 6762d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang out += dst.mStride; 6772d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 6782d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6792d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang // Process the left-overs out-of-loop, 2-pixel at a time. Note that we don't 6802d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang // need to consider odd case as the buffer is always aligned to even. 6812d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang if (src.cropWidth() & 15) { 6822d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang size_t xstart = (src.cropWidth() & ~15); 6832d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6842d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint8_t *out = (uint8_t *)dst.mBits + dst.mCropTop * dst.mStride 6852d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang + (dst.mCropLeft + xstart) * dst.mBpp; 6862d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6872d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_y = (const uint8_t *)src.mBits + src.mCropTop * src.mStride 6882d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang + (src.mCropLeft + xstart) * src.mBpp; 6892d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6902d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_u = (const uint8_t *)src.mBits + src.mStride * src.mHeight 6912d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang + (src.mCropTop / 2) * (src.mStride / 2) 6922d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang + ((src.mCropLeft + xstart) / 2) * src.mBpp; 6932d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6942d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang const uint8_t *src_v = src_u + (src.mStride / 2) * (src.mHeight / 2); 6952d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 6962d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang for (size_t y = 0; y < src.cropHeight(); y++) { 6972d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_y = (uint16_t*) src_y; 6982d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_u = (uint16_t*) src_u; 6992d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t *ptr_v = (uint16_t*) src_v; 7002d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32_t *ptr_out = (uint32_t *) out; 7012d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang for (size_t x = xstart; x < src.cropWidth(); x += 2) { 7022d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t u = *ptr_u++; 7032d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint16_t v = *ptr_v++; 7042d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32_t y01 = *((uint32_t*)ptr_y); ptr_y += 2; 7052d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang uint32_t uv = u | (((uint32_t)v) << 20); 7062d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *ptr_out++ = ((y01 & 0x3FF) << 10) | uv; 7072d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang *ptr_out++ = ((y01 >> 16) << 10) | uv; 7082d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 7092d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_y += src.mStride; 7102d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang if (y & 1) { 7112d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_u += src.mStride / 2; 7122d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang src_v += src.mStride / 2; 7132d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 7142d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang out += dst.mStride; 7152d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 7162d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 7172d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 7182d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang return OK; 7192d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang} 7202d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 7212d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang#endif // USE_NEON_Y410 7222d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 7231472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convertQCOMYUV420SemiPlanar( 724f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const BitmapParams &src, const BitmapParams &dst) { 7252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint8_t *kAdjustedClip = initClip(); 7262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 7274e260ab948787c2a814543077832847deae890fdJames Dong uint16_t *dst_ptr = (uint16_t *)dst.mBits 7284e260ab948787c2a814543077832847deae890fdJames Dong + dst.mCropTop * dst.mWidth + dst.mCropLeft; 729f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 730f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const uint8_t *src_y = 731f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; 7322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 7332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber const uint8_t *src_u = 734f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src_y + src.mWidth * src.mHeight 735f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber + src.mCropTop * src.mWidth + src.mCropLeft; 7362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 737f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 738f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 7392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed y1 = (signed)src_y[x] - 16; 7402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 7412a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 7422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u = (signed)src_u[x & ~1] - 128; 7432a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v = (signed)src_u[(x & ~1) + 1] - 128; 7442a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 7452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_b = u * 517; 7462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed u_g = -u * 100; 7472a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_g = -v * 208; 7482a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed v_r = v * 409; 7492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 7502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp1 = y1 * 298; 7512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b1 = (tmp1 + u_b) / 256; 7522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 7532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r1 = (tmp1 + v_r) / 256; 7542a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 7552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed tmp2 = y2 * 298; 7562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed b2 = (tmp2 + u_b) / 256; 7572a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 7581c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed r2 = (tmp2 + v_r) / 256; 7591c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 7601c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber uint32_t rgb1 = 7611c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber ((kAdjustedClip[b1] >> 3) << 11) 7621c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 7631c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber | (kAdjustedClip[r1] >> 3); 7641c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 7651c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber uint32_t rgb2 = 7661c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber ((kAdjustedClip[b2] >> 3) << 11) 7671c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 7681c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber | (kAdjustedClip[r2] >> 3); 7691c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 7704e260ab948787c2a814543077832847deae890fdJames Dong if (x + 1 < src.cropWidth()) { 7714e260ab948787c2a814543077832847deae890fdJames Dong *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 7724e260ab948787c2a814543077832847deae890fdJames Dong } else { 7734e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr[x] = rgb1; 7744e260ab948787c2a814543077832847deae890fdJames Dong } 7751c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber } 7761c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 777f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_y += src.mWidth; 7781c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 7791c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber if (y & 1) { 780f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_u += src.mWidth; 7811c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber } 7821c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 7834e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr += dst.mWidth; 7841c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber } 7851472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 7861472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return OK; 7871c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber} 7881c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 7891472eb39f7516faa26de200d8592464c8aaac38eAndreas Huberstatus_t ColorConverter::convertYUV420SemiPlanar( 790f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const BitmapParams &src, const BitmapParams &dst) { 791f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber // XXX Untested 7921c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 7931c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber uint8_t *kAdjustedClip = initClip(); 7941c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 7954e260ab948787c2a814543077832847deae890fdJames Dong uint16_t *dst_ptr = (uint16_t *)dst.mBits 7964e260ab948787c2a814543077832847deae890fdJames Dong + dst.mCropTop * dst.mWidth + dst.mCropLeft; 797f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 798f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber const uint8_t *src_y = 799f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; 8001c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 8011c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber const uint8_t *src_u = 802f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber (const uint8_t *)src_y + src.mWidth * src.mHeight 803f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber + src.mCropTop * src.mWidth + src.mCropLeft; 8041c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 805f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 806f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 8071c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed y1 = (signed)src_y[x] - 16; 8081c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 8091c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 8101c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed v = (signed)src_u[x & ~1] - 128; 8111c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed u = (signed)src_u[(x & ~1) + 1] - 128; 8121c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 8131c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed u_b = u * 517; 8141c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed u_g = -u * 100; 8151c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed v_g = -v * 208; 8161c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed v_r = v * 409; 8171c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 8181c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed tmp1 = y1 * 298; 8191c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed b1 = (tmp1 + u_b) / 256; 8201c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 8211c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed r1 = (tmp1 + v_r) / 256; 8221c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber 8231c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed tmp2 = y2 * 298; 8241c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed b2 = (tmp2 + u_b) / 256; 8251c8ed2e906576fd8d7fa03f577bdec518cbe13d7Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 8262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber signed r2 = (tmp2 + v_r) / 256; 8272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 8282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb1 = 8292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[b1] >> 3) << 11) 8302a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 8312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[r1] >> 3); 8322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 8332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber uint32_t rgb2 = 8342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ((kAdjustedClip[b2] >> 3) << 11) 8352a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 8362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber | (kAdjustedClip[r2] >> 3); 8372a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 8384e260ab948787c2a814543077832847deae890fdJames Dong if (x + 1 < src.cropWidth()) { 8394e260ab948787c2a814543077832847deae890fdJames Dong *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 8404e260ab948787c2a814543077832847deae890fdJames Dong } else { 8414e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr[x] = rgb1; 8424e260ab948787c2a814543077832847deae890fdJames Dong } 8432a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 8442a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 845f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_y += src.mWidth; 8462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 8472a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (y & 1) { 848f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber src_u += src.mWidth; 8492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 8502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 8514e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr += dst.mWidth; 8522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 8531472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber 8541472eb39f7516faa26de200d8592464c8aaac38eAndreas Huber return OK; 8552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 8562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 857cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajanstatus_t ColorConverter::convertTIYUV420PackedSemiPlanar( 858cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan const BitmapParams &src, const BitmapParams &dst) { 8593571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber uint8_t *kAdjustedClip = initClip(); 860cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 8614e260ab948787c2a814543077832847deae890fdJames Dong uint16_t *dst_ptr = (uint16_t *)dst.mBits 8624e260ab948787c2a814543077832847deae890fdJames Dong + dst.mCropTop * dst.mWidth + dst.mCropLeft; 863cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 864e14a36f37035c2655df13838c15fdb61e76c3e65Angela Stegmaier const uint8_t *src_y = 865e14a36f37035c2655df13838c15fdb61e76c3e65Angela Stegmaier (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft; 866cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 8673571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber const uint8_t *src_u = 8683571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber (const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2); 869cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 8703571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber for (size_t y = 0; y < src.cropHeight(); ++y) { 8713571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber for (size_t x = 0; x < src.cropWidth(); x += 2) { 8723571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber signed y1 = (signed)src_y[x] - 16; 8733571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 874cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 8753571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber signed u = (signed)src_u[x & ~1] - 128; 8763571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber signed v = (signed)src_u[(x & ~1) + 1] - 128; 877cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 878cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed u_b = u * 517; 879cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed u_g = -u * 100; 880cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed v_g = -v * 208; 881cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed v_r = v * 409; 882cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 883cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed tmp1 = y1 * 298; 884cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed b1 = (tmp1 + u_b) / 256; 885cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed g1 = (tmp1 + v_g + u_g) / 256; 886cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed r1 = (tmp1 + v_r) / 256; 887cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 888cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed tmp2 = y2 * 298; 889cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed b2 = (tmp2 + u_b) / 256; 890cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed g2 = (tmp2 + v_g + u_g) / 256; 891cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan signed r2 = (tmp2 + v_r) / 256; 892cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 893cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan uint32_t rgb1 = 894cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan ((kAdjustedClip[r1] >> 3) << 11) 895cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan | ((kAdjustedClip[g1] >> 2) << 5) 896cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan | (kAdjustedClip[b1] >> 3); 897cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 898cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan uint32_t rgb2 = 899cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan ((kAdjustedClip[r2] >> 3) << 11) 9003571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 9013571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber | (kAdjustedClip[b2] >> 3); 902cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 9034e260ab948787c2a814543077832847deae890fdJames Dong if (x + 1 < src.cropWidth()) { 9044e260ab948787c2a814543077832847deae890fdJames Dong *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1; 9054e260ab948787c2a814543077832847deae890fdJames Dong } else { 9064e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr[x] = rgb1; 9074e260ab948787c2a814543077832847deae890fdJames Dong } 908cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan } 909cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 9103571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber src_y += src.mWidth; 9113571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber 9123571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber if (y & 1) { 9133571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber src_u += src.mWidth; 914cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan } 915cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 9164e260ab948787c2a814543077832847deae890fdJames Dong dst_ptr += dst.mWidth; 917cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan } 9183571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber 919cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan return OK; 920cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan} 921cb62bc3fe54222cf05824e6f98fefafee552049aAnu Sundararajan 9222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberuint8_t *ColorConverter::initClip() { 9232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber static const signed kClipMin = -278; 9242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber static const signed kClipMax = 535; 9252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 9262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (mClip == NULL) { 9272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClip = new uint8_t[kClipMax - kClipMin + 1]; 9282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 9292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber for (signed i = kClipMin; i <= kClipMax; ++i) { 9302a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i; 9312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 9322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 9332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 9342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return &mClip[-kClipMin]; 9352a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 9362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 9372a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} // namespace android 938