120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "SoftwareRenderer"
1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2089e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "../include/SoftwareRenderer.h"
2189e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
229dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber#include <cutils/properties.h> // for property_get
23f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber#include <media/stagefright/foundation/ADebug.h>
24f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber#include <media/stagefright/MetaData.h>
259eeafeb52fecf90882e9b44eeefcb7c3e16aa915Mathias Agopian#include <system/window.h>
265daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber#include <ui/GraphicBufferMapper.h>
271173118eace0e9e347cb007f0da817cee87579edGlenn Kasten#include <gui/ISurfaceTexture.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
319dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huberstatic bool runningInEmulator() {
329dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber    char prop[PROPERTY_VALUE_MAX];
339dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber    return (property_get("ro.kernel.qemu", prop, NULL) > 0);
349dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber}
359dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber
3620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberSoftwareRenderer::SoftwareRenderer(
371173118eace0e9e347cb007f0da817cee87579edGlenn Kasten        const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
38f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    : mConverter(NULL),
395daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber      mYUVMode(None),
401173118eace0e9e347cb007f0da817cee87579edGlenn Kasten      mNativeWindow(nativeWindow) {
41f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    int32_t tmp;
42f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    CHECK(meta->findInt32(kKeyColorFormat, &tmp));
43f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    mColorFormat = (OMX_COLOR_FORMATTYPE)tmp;
44f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
45f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    CHECK(meta->findInt32(kKeyWidth, &mWidth));
46f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    CHECK(meta->findInt32(kKeyHeight, &mHeight));
47f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
48f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    if (!meta->findRect(
49f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                kKeyCropRect,
50f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                &mCropLeft, &mCropTop, &mCropRight, &mCropBottom)) {
51f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber        mCropLeft = mCropTop = 0;
52f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber        mCropRight = mWidth - 1;
53f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber        mCropBottom = mHeight - 1;
54f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    }
55f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
563571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    mCropWidth = mCropRight - mCropLeft + 1;
573571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    mCropHeight = mCropBottom - mCropTop + 1;
583571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
59f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    int32_t rotationDegrees;
60f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
61f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber        rotationDegrees = 0;
62f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    }
63a240812f10335fe4c8677da824293b7e04aad7e9Andreas Huber
645daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    int halFormat;
655e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber    size_t bufWidth, bufHeight;
665e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
675daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    switch (mColorFormat) {
685e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        case OMX_COLOR_FormatYUV420Planar:
693571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
705e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        {
719dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber            if (!runningInEmulator()) {
729dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber                halFormat = HAL_PIXEL_FORMAT_YV12;
739dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber                bufWidth = (mCropWidth + 1) & ~1;
749dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber                bufHeight = (mCropHeight + 1) & ~1;
759dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber                break;
769dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber            }
779dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber
789dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber            // fall through.
795e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        }
805e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
815daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        default:
825daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            halFormat = HAL_PIXEL_FORMAT_RGB_565;
833571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            bufWidth = mCropWidth;
843571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            bufHeight = mCropHeight;
855daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
865daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            mConverter = new ColorConverter(
875daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                    mColorFormat, OMX_COLOR_Format16bitRGB565);
885daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            CHECK(mConverter->isValid());
895daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            break;
9089e7fff6a5d7410815f42b4a55958a59d4463180Andreas Huber    }
9189e7fff6a5d7410815f42b4a55958a59d4463180Andreas Huber
921173118eace0e9e347cb007f0da817cee87579edGlenn Kasten    CHECK(mNativeWindow != NULL);
933571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    CHECK(mCropWidth > 0);
943571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    CHECK(mCropHeight > 0);
955daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK(mConverter == NULL || mConverter->isValid());
965daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
975daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0,
985daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            native_window_set_usage(
991173118eace0e9e347cb007f0da817cee87579edGlenn Kasten            mNativeWindow.get(),
1005daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
101103487c0cb5c06f47225484486a98bc84745a059Andreas Huber            | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1039bc7af17974f448291a44912566ec7472a0d798bMathias Agopian    CHECK_EQ(0,
1049bc7af17974f448291a44912566ec7472a0d798bMathias Agopian            native_window_set_scaling_mode(
1059bc7af17974f448291a44912566ec7472a0d798bMathias Agopian            mNativeWindow.get(),
1069bc7af17974f448291a44912566ec7472a0d798bMathias Agopian            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
1079bc7af17974f448291a44912566ec7472a0d798bMathias Agopian
1085daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    // Width must be multiple of 32???
1095daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, native_window_set_buffers_geometry(
1101173118eace0e9e347cb007f0da817cee87579edGlenn Kasten                mNativeWindow.get(),
1115e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber                bufWidth,
1125e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber                bufHeight,
1135daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                halFormat));
114ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
115ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t transform;
116ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    switch (rotationDegrees) {
117ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        case 0: transform = 0; break;
118ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        case 90: transform = HAL_TRANSFORM_ROT_90; break;
119ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        case 180: transform = HAL_TRANSFORM_ROT_180; break;
120ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        case 270: transform = HAL_TRANSFORM_ROT_270; break;
121ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        default: transform = 0; break;
122ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
123ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
124ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (transform) {
125ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ(0, native_window_set_buffers_transform(
1261173118eace0e9e347cb007f0da817cee87579edGlenn Kasten                    mNativeWindow.get(), transform));
127ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
12920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberSoftwareRenderer::~SoftwareRenderer() {
1315daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    delete mConverter;
1325daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    mConverter = NULL;
1335daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber}
1345daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1355e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huberstatic int ALIGN(int x, int y) {
1365e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber    // y must be a power of 2.
1375e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber    return (x + y - 1) & ~(y - 1);
1385e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber}
1395e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid SoftwareRenderer::render(
14120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const void *data, size_t size, void *platformPrivate) {
1428ce2364512f7c32c824f5ec5719688830ba72427Iliyan Malchev    ANativeWindowBuffer *buf;
1435de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber    int err;
1441173118eace0e9e347cb007f0da817cee87579edGlenn Kasten    if ((err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf)) != 0) {
1455ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Surface::dequeueBuffer returned error %d", err);
1465de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber        return;
1475de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber    }
1485de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber
1491173118eace0e9e347cb007f0da817cee87579edGlenn Kasten    CHECK_EQ(0, mNativeWindow->lockBuffer(mNativeWindow.get(), buf));
1505daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1515daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
1525daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1533571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    Rect bounds(mCropWidth, mCropHeight);
1545daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1555daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    void *dst;
1565daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mapper.lock(
1575daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));
1585daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1595daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    if (mConverter) {
1605daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        mConverter->convert(
161f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                data,
162f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                mWidth, mHeight,
1633571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber                mCropLeft, mCropTop, mCropRight, mCropBottom,
164f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                dst,
165f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                buf->stride, buf->height,
1663571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber                0, 0, mCropWidth - 1, mCropHeight - 1);
1673571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
1685e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        const uint8_t *src_y = (const uint8_t *)data;
1695e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
1705e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
1715e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
1725e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        uint8_t *dst_y = (uint8_t *)dst;
1735e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        size_t dst_y_size = buf->stride * buf->height;
1745e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
1755e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        size_t dst_c_size = dst_c_stride * buf->height / 2;
1765e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        uint8_t *dst_v = dst_y + dst_y_size;
1775e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        uint8_t *dst_u = dst_v + dst_c_size;
1785e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
1793571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        for (int y = 0; y < mCropHeight; ++y) {
1803571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            memcpy(dst_y, src_y, mCropWidth);
1815e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
1825e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            src_y += mWidth;
1835e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            dst_y += buf->stride;
1845e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        }
1855e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
1863571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
1873571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
1883571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            memcpy(dst_v, src_v, (mCropWidth + 1) / 2);
1895e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
1905e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            src_u += mWidth / 2;
1915e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            src_v += mWidth / 2;
1925e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            dst_u += dst_c_stride;
1935e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            dst_v += dst_c_stride;
1945e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        }
1953571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    } else {
1963571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        CHECK_EQ(mColorFormat, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar);
1973571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
1983571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        const uint8_t *src_y =
1993571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            (const uint8_t *)data;
2003571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2013571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        const uint8_t *src_uv =
2023571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
2033571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2043571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        uint8_t *dst_y = (uint8_t *)dst;
2053571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2063571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        size_t dst_y_size = buf->stride * buf->height;
2073571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
2083571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        size_t dst_c_size = dst_c_stride * buf->height / 2;
2093571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        uint8_t *dst_v = dst_y + dst_y_size;
2103571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        uint8_t *dst_u = dst_v + dst_c_size;
2113571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2123571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        for (int y = 0; y < mCropHeight; ++y) {
2133571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            memcpy(dst_y, src_y, mCropWidth);
2143571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2153571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            src_y += mWidth;
2163571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            dst_y += buf->stride;
2173571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        }
2183571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2193571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
2203571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            size_t tmp = (mCropWidth + 1) / 2;
2213571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            for (size_t x = 0; x < tmp; ++x) {
2223571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber                dst_u[x] = src_uv[2 * x];
2233571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber                dst_v[x] = src_uv[2 * x + 1];
2243571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            }
2253571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2263571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            src_uv += mWidth;
2273571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            dst_u += dst_c_stride;
2283571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            dst_v += dst_c_stride;
2293571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        }
2305daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    }
2314265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
2325daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mapper.unlock(buf->handle));
2334265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
2341173118eace0e9e347cb007f0da817cee87579edGlenn Kasten    if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf)) != 0) {
2355ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Surface::queueBuffer returned error %d", err);
2365de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber    }
2375daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    buf = NULL;
2384265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber}
2394265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
241