Merge change 25158 into eclair

* changes:
  Another software color conversion implementation, this time OMX_QCOM_COLOR_FormatYVU420SemiPlanar => rgb565.
diff --git a/include/media/stagefright/SoftwareRenderer.h b/include/media/stagefright/SoftwareRenderer.h
index b61858c..1545493 100644
--- a/include/media/stagefright/SoftwareRenderer.h
+++ b/include/media/stagefright/SoftwareRenderer.h
@@ -45,6 +45,7 @@
 
     void renderCbYCrY(const void *data, size_t size);
     void renderYUV420Planar(const void *data, size_t size);
+    void renderQCOMYUV420SemiPlanar(const void *data, size_t size);
 
     OMX_COLOR_FORMATTYPE mColorFormat;
     sp<ISurface> mISurface;
diff --git a/media/libstagefright/omx/SoftwareRenderer.cpp b/media/libstagefright/omx/SoftwareRenderer.cpp
index a1c478f..4ed6869 100644
--- a/media/libstagefright/omx/SoftwareRenderer.cpp
+++ b/media/libstagefright/omx/SoftwareRenderer.cpp
@@ -65,6 +65,8 @@
 
 void SoftwareRenderer::render(
         const void *data, size_t size, void *platformPrivate) {
+    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
     switch (mColorFormat) {
         case OMX_COLOR_FormatYUV420Planar:
             return renderYUV420Planar(data, size);
@@ -72,6 +74,9 @@
         case OMX_COLOR_FormatCbYCrY:
             return renderCbYCrY(data, size);
 
+        case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+            return renderQCOMYUV420SemiPlanar(data, size);
+
         default:
         {
             LOGW("Cannot render color format %ld", mColorFormat);
@@ -242,6 +247,76 @@
     mIndex = 1 - mIndex;
 }
 
+void SoftwareRenderer::renderQCOMYUV420SemiPlanar(
+        const void *data, size_t size) {
+    if (size != (mDecodedHeight * mDecodedWidth * 3) / 2) {
+        LOGE("size is %d, expected %d",
+                size, (mDecodedHeight * mDecodedWidth * 3) / 2);
+    }
+    CHECK(size >= (mDecodedWidth * mDecodedHeight * 3) / 2);
+
+    uint8_t *kAdjustedClip = initClip();
+
+    size_t offset = mIndex * mFrameSize;
+
+    void *dst = (uint8_t *)mMemoryHeap->getBase() + offset;
+
+    uint32_t *dst_ptr = (uint32_t *)dst;
+
+    const uint8_t *src_y = (const uint8_t *)data;
+
+    const uint8_t *src_u =
+        (const uint8_t *)src_y + mDecodedWidth * mDecodedHeight;
+
+    for (size_t y = 0; y < mDecodedHeight; ++y) {
+        for (size_t x = 0; x < mDecodedWidth; x += 2) {
+            signed y1 = (signed)src_y[x] - 16;
+            signed y2 = (signed)src_y[x + 1] - 16;
+
+            signed u = (signed)src_u[x & ~1] - 128;
+            signed v = (signed)src_u[(x & ~1) + 1] - 128;
+
+            signed u_b = u * 517;
+            signed u_g = -u * 100;
+            signed v_g = -v * 208;
+            signed v_r = v * 409;
+
+            signed tmp1 = y1 * 298;
+            signed b1 = (tmp1 + u_b) / 256;
+            signed g1 = (tmp1 + v_g + u_g) / 256;
+            signed r1 = (tmp1 + v_r) / 256;
+
+            signed tmp2 = y2 * 298;
+            signed b2 = (tmp2 + u_b) / 256;
+            signed g2 = (tmp2 + v_g + u_g) / 256;
+            signed r2 = (tmp2 + v_r) / 256;
+
+            uint32_t rgb1 =
+                ((kAdjustedClip[b1] >> 3) << 11)
+                | ((kAdjustedClip[g1] >> 2) << 5)
+                | (kAdjustedClip[r1] >> 3);
+
+            uint32_t rgb2 =
+                ((kAdjustedClip[b2] >> 3) << 11)
+                | ((kAdjustedClip[g2] >> 2) << 5)
+                | (kAdjustedClip[r2] >> 3);
+
+            dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+        }
+
+        src_y += mDecodedWidth;
+
+        if (y & 1) {
+            src_u += mDecodedWidth;
+        }
+
+        dst_ptr += mDecodedWidth / 2;
+    }
+
+    mISurface->postBuffer(offset);
+    mIndex = 1 - mIndex;
+}
+
 uint8_t *SoftwareRenderer::initClip() {
     static const signed kClipMin = -278;
     static const signed kClipMax = 535;