153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber/* 253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * Copyright (C) 2009 The Android Open Source Project 353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * 453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * you may not use this file except in compliance with the License. 653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * You may obtain a copy of the License at 753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * 853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * 1053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * Unless required by applicable law or agreed to in writing, software 1153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * See the License for the specific language governing permissions and 1453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber * limitations under the License. 1553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber */ 1653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 1753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <media/stagefright/ColorConverter.h> 1853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <media/stagefright/MediaDebug.h> 1953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 2053a76bd0c918082847e52570c307ed3ba325992dAndreas Hubernamespace android { 2153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 2253a76bd0c918082847e52570c307ed3ba325992dAndreas Huberstatic const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00; 2353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 2453a76bd0c918082847e52570c307ed3ba325992dAndreas HuberColorConverter::ColorConverter( 2553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber OMX_COLOR_FORMATTYPE from, OMX_COLOR_FORMATTYPE to) 2653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber : mSrcFormat(from), 2753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber mDstFormat(to), 2853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber mClip(NULL) { 2953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} 3053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 3153a76bd0c918082847e52570c307ed3ba325992dAndreas HuberColorConverter::~ColorConverter() { 3253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber delete[] mClip; 3353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber mClip = NULL; 3453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} 3553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 3653a76bd0c918082847e52570c307ed3ba325992dAndreas Huberbool ColorConverter::isValid() const { 3753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber if (mDstFormat != OMX_COLOR_Format16bitRGB565) { 3853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber return false; 3953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 4053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 4153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber switch (mSrcFormat) { 4253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber case OMX_COLOR_FormatYUV420Planar: 4353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber case OMX_COLOR_FormatCbYCrY: 4453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: 45c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber case OMX_COLOR_FormatYUV420SemiPlanar: 4653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber return true; 4753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 4853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber default: 4953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber return false; 5053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 5153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} 5253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 5353a76bd0c918082847e52570c307ed3ba325992dAndreas Hubervoid ColorConverter::convert( 5453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber size_t width, size_t height, 5553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const void *srcBits, size_t srcSkip, 5653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber void *dstBits, size_t dstSkip) { 5753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK_EQ(mDstFormat, OMX_COLOR_Format16bitRGB565); 5853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 5953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber switch (mSrcFormat) { 6053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber case OMX_COLOR_FormatYUV420Planar: 6153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber convertYUV420Planar( 6253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber width, height, srcBits, srcSkip, dstBits, dstSkip); 6353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber break; 6453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 6553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber case OMX_COLOR_FormatCbYCrY: 6653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber convertCbYCrY( 6753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber width, height, srcBits, srcSkip, dstBits, dstSkip); 6853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber break; 6953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 7053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber case OMX_QCOM_COLOR_FormatYVU420SemiPlanar: 7153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber convertQCOMYUV420SemiPlanar( 7253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber width, height, srcBits, srcSkip, dstBits, dstSkip); 7353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber break; 7453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 75c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber case OMX_COLOR_FormatYUV420SemiPlanar: 76c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber convertYUV420SemiPlanar( 77c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber width, height, srcBits, srcSkip, dstBits, dstSkip); 78c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber break; 79c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 8053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber default: 8153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber { 8253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK(!"Should not be here. Unknown color conversion."); 8353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber break; 8453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 8553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 8653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} 8753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 8853a76bd0c918082847e52570c307ed3ba325992dAndreas Hubervoid ColorConverter::convertCbYCrY( 8953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber size_t width, size_t height, 9053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const void *srcBits, size_t srcSkip, 9153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber void *dstBits, size_t dstSkip) { 9253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats. 9353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK(dstSkip >= width * 2); 9453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK((dstSkip & 3) == 0); 9553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 9653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint8_t *kAdjustedClip = initClip(); 9753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 9853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t *dst_ptr = (uint32_t *)dstBits; 9953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 10053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const uint8_t *src = (const uint8_t *)srcBits; 10153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 10253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber for (size_t y = 0; y < height; ++y) { 10353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber for (size_t x = 0; x < width; x += 2) { 10453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed y1 = (signed)src[2 * x + 1] - 16; 10553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed y2 = (signed)src[2 * x + 3] - 16; 10653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u = (signed)src[2 * x] - 128; 10753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v = (signed)src[2 * x + 2] - 128; 10853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 10953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u_b = u * 517; 11053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u_g = -u * 100; 11153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v_g = -v * 208; 11253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v_r = v * 409; 11353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 11453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed tmp1 = y1 * 298; 11553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed b1 = (tmp1 + u_b) / 256; 11653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 11753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed r1 = (tmp1 + v_r) / 256; 11853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 11953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed tmp2 = y2 * 298; 12053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed b2 = (tmp2 + u_b) / 256; 12153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 12253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed r2 = (tmp2 + v_r) / 256; 12353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 12453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t rgb1 = 12553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber ((kAdjustedClip[r1] >> 3) << 11) 12653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 12753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | (kAdjustedClip[b1] >> 3); 12853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 12953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t rgb2 = 13053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber ((kAdjustedClip[r2] >> 3) << 11) 13153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 13253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | (kAdjustedClip[b2] >> 3); 13353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 13453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber dst_ptr[x / 2] = (rgb2 << 16) | rgb1; 13553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 13653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 13753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber src += width * 2; 13853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber dst_ptr += dstSkip / 4; 13953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 14053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} 14153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 14253a76bd0c918082847e52570c307ed3ba325992dAndreas Hubervoid ColorConverter::convertYUV420Planar( 14353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber size_t width, size_t height, 14453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const void *srcBits, size_t srcSkip, 14553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber void *dstBits, size_t dstSkip) { 14653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats. 14753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK(dstSkip >= width * 2); 14853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK((dstSkip & 3) == 0); 14953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 15053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint8_t *kAdjustedClip = initClip(); 15153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 15253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t *dst_ptr = (uint32_t *)dstBits; 15353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const uint8_t *src_y = (const uint8_t *)srcBits; 15453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 15553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const uint8_t *src_u = 15653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber (const uint8_t *)src_y + width * height; 15753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 15853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const uint8_t *src_v = 15953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber (const uint8_t *)src_u + (width / 2) * (height / 2); 16053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 16153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber for (size_t y = 0; y < height; ++y) { 16253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber for (size_t x = 0; x < width; x += 2) { 16353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // B = 1.164 * (Y - 16) + 2.018 * (U - 128) 16453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // G = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128) 16553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // R = 1.164 * (Y - 16) + 1.596 * (V - 128) 16653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 16753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // B = 298/256 * (Y - 16) + 517/256 * (U - 128) 16853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // G = .................. - 208/256 * (V - 128) - 100/256 * (U - 128) 16953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // R = .................. + 409/256 * (V - 128) 17053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 17153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // min_B = (298 * (- 16) + 517 * (- 128)) / 256 = -277 17253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // min_G = (298 * (- 16) - 208 * (255 - 128) - 100 * (255 - 128)) / 256 = -172 17353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // min_R = (298 * (- 16) + 409 * (- 128)) / 256 = -223 17453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 17553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // max_B = (298 * (255 - 16) + 517 * (255 - 128)) / 256 = 534 17653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // max_G = (298 * (255 - 16) - 208 * (- 128) - 100 * (- 128)) / 256 = 432 17753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // max_R = (298 * (255 - 16) + 409 * (255 - 128)) / 256 = 481 17853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 17953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber // clip range -278 .. 535 18053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 18153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed y1 = (signed)src_y[x] - 16; 18253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed y2 = (signed)src_y[x + 1] - 16; 18353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 18453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u = (signed)src_u[x / 2] - 128; 18553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v = (signed)src_v[x / 2] - 128; 18653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 18753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u_b = u * 517; 18853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u_g = -u * 100; 18953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v_g = -v * 208; 19053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v_r = v * 409; 19153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 19253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed tmp1 = y1 * 298; 19353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed b1 = (tmp1 + u_b) / 256; 19453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 19553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed r1 = (tmp1 + v_r) / 256; 19653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 19753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed tmp2 = y2 * 298; 19853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed b2 = (tmp2 + u_b) / 256; 19953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 20053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed r2 = (tmp2 + v_r) / 256; 20153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 20253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t rgb1 = 20353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber ((kAdjustedClip[r1] >> 3) << 11) 20453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 20553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | (kAdjustedClip[b1] >> 3); 20653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 20753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t rgb2 = 20853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber ((kAdjustedClip[r2] >> 3) << 11) 20953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 21053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | (kAdjustedClip[b2] >> 3); 21153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 21253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber dst_ptr[x / 2] = (rgb2 << 16) | rgb1; 21353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 21453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 21553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber src_y += width; 21653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 21753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber if (y & 1) { 21853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber src_u += width / 2; 21953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber src_v += width / 2; 22053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 22153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 22253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber dst_ptr += dstSkip / 4; 22353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 22453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} 22553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 22653a76bd0c918082847e52570c307ed3ba325992dAndreas Hubervoid ColorConverter::convertQCOMYUV420SemiPlanar( 22753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber size_t width, size_t height, 22853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const void *srcBits, size_t srcSkip, 22953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber void *dstBits, size_t dstSkip) { 23053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats. 23153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK(dstSkip >= width * 2); 23253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber CHECK((dstSkip & 3) == 0); 23353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 23453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint8_t *kAdjustedClip = initClip(); 23553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 23653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t *dst_ptr = (uint32_t *)dstBits; 23753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const uint8_t *src_y = (const uint8_t *)srcBits; 23853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 23953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber const uint8_t *src_u = 24053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber (const uint8_t *)src_y + width * height; 24153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 24253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber for (size_t y = 0; y < height; ++y) { 24353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber for (size_t x = 0; x < width; x += 2) { 24453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed y1 = (signed)src_y[x] - 16; 24553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed y2 = (signed)src_y[x + 1] - 16; 24653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 24753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u = (signed)src_u[x & ~1] - 128; 24853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v = (signed)src_u[(x & ~1) + 1] - 128; 24953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 25053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u_b = u * 517; 25153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed u_g = -u * 100; 25253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v_g = -v * 208; 25353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed v_r = v * 409; 25453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 25553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed tmp1 = y1 * 298; 25653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed b1 = (tmp1 + u_b) / 256; 25753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 25853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed r1 = (tmp1 + v_r) / 256; 25953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 26053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed tmp2 = y2 * 298; 26153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed b2 = (tmp2 + u_b) / 256; 26253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 263c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed r2 = (tmp2 + v_r) / 256; 264c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 265c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber uint32_t rgb1 = 266c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber ((kAdjustedClip[b1] >> 3) << 11) 267c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 268c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber | (kAdjustedClip[r1] >> 3); 269c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 270c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber uint32_t rgb2 = 271c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber ((kAdjustedClip[b2] >> 3) << 11) 272c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 273c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber | (kAdjustedClip[r2] >> 3); 274c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 275c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber dst_ptr[x / 2] = (rgb2 << 16) | rgb1; 276c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber } 277c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 278c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber src_y += width; 279c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 280c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber if (y & 1) { 281c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber src_u += width; 282c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber } 283c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 284c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber dst_ptr += dstSkip / 4; 285c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber } 286c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber} 287c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 288c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Hubervoid ColorConverter::convertYUV420SemiPlanar( 289c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber size_t width, size_t height, 290c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber const void *srcBits, size_t srcSkip, 291c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber void *dstBits, size_t dstSkip) { 292c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats. 293c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber CHECK(dstSkip >= width * 2); 294c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber CHECK((dstSkip & 3) == 0); 295c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 296c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber uint8_t *kAdjustedClip = initClip(); 297c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 298c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber uint32_t *dst_ptr = (uint32_t *)dstBits; 299c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber const uint8_t *src_y = (const uint8_t *)srcBits; 300c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 301c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber const uint8_t *src_u = 302c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber (const uint8_t *)src_y + width * height; 303c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 304c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber for (size_t y = 0; y < height; ++y) { 305c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber for (size_t x = 0; x < width; x += 2) { 306c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed y1 = (signed)src_y[x] - 16; 307c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed y2 = (signed)src_y[x + 1] - 16; 308c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 309c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed v = (signed)src_u[x & ~1] - 128; 310c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed u = (signed)src_u[(x & ~1) + 1] - 128; 311c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 312c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed u_b = u * 517; 313c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed u_g = -u * 100; 314c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed v_g = -v * 208; 315c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed v_r = v * 409; 316c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 317c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed tmp1 = y1 * 298; 318c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed b1 = (tmp1 + u_b) / 256; 319c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed g1 = (tmp1 + v_g + u_g) / 256; 320c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed r1 = (tmp1 + v_r) / 256; 321c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber 322c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed tmp2 = y2 * 298; 323c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed b2 = (tmp2 + u_b) / 256; 324c543a21a4021bf0e2f3817852d75184d01b76d62Andreas Huber signed g2 = (tmp2 + v_g + u_g) / 256; 32553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber signed r2 = (tmp2 + v_r) / 256; 32653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 32753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t rgb1 = 32853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber ((kAdjustedClip[b1] >> 3) << 11) 32953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | ((kAdjustedClip[g1] >> 2) << 5) 33053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | (kAdjustedClip[r1] >> 3); 33153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 33253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber uint32_t rgb2 = 33353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber ((kAdjustedClip[b2] >> 3) << 11) 33453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | ((kAdjustedClip[g2] >> 2) << 5) 33553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber | (kAdjustedClip[r2] >> 3); 33653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 33753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber dst_ptr[x / 2] = (rgb2 << 16) | rgb1; 33853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 33953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 34053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber src_y += width; 34153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 34253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber if (y & 1) { 34353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber src_u += width; 34453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 34553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 34653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber dst_ptr += dstSkip / 4; 34753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 34853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} 34953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 35053a76bd0c918082847e52570c307ed3ba325992dAndreas Huberuint8_t *ColorConverter::initClip() { 35153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber static const signed kClipMin = -278; 35253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber static const signed kClipMax = 535; 35353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 35453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber if (mClip == NULL) { 35553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber mClip = new uint8_t[kClipMax - kClipMin + 1]; 35653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 35753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber for (signed i = kClipMin; i <= kClipMax; ++i) { 35853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber mClip[i - kClipMin] = (i < 0) ? 0 : (i > 255) ? 255 : (uint8_t)i; 35953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 36053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber } 36153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 36253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber return &mClip[-kClipMin]; 36353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} 36453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber 36553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber} // namespace android 366