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>
24475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu#include <media/stagefright/foundation/AMessage.h>
259eeafeb52fecf90882e9b44eeefcb7c3e16aa915Mathias Agopian#include <system/window.h>
265daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber#include <ui/GraphicBufferMapper.h>
278ba01021b573889802e67e029225a96f0dfa471aAndy McFadden#include <gui/IGraphicBufferProducer.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
36475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wustatic int ALIGN(int x, int y) {
37475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    // y must be a power of 2.
38475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    return (x + y - 1) & ~(y - 1);
39475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu}
40475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
41475da7ef08c05a482ced8d318832cf5aa1141affRonghua WuSoftwareRenderer::SoftwareRenderer(const sp<ANativeWindow> &nativeWindow)
42475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    : mColorFormat(OMX_COLOR_FormatUnused),
43475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mConverter(NULL),
445daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber      mYUVMode(None),
45475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mNativeWindow(nativeWindow),
46475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mWidth(0),
47475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mHeight(0),
48475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mCropLeft(0),
49475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mCropTop(0),
50475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mCropRight(0),
51475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mCropBottom(0),
52475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mCropWidth(0),
53475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu      mCropHeight(0) {
54475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu}
55475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
56475da7ef08c05a482ced8d318832cf5aa1141affRonghua WuSoftwareRenderer::~SoftwareRenderer() {
57475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    delete mConverter;
58475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    mConverter = NULL;
59475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu}
60475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
61475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wuvoid SoftwareRenderer::resetFormatIfChanged(const sp<AMessage> &format) {
62475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    CHECK(format != NULL);
63475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
64475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    int32_t colorFormatNew;
65475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    CHECK(format->findInt32("color-format", &colorFormatNew));
66475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
67475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    int32_t widthNew, heightNew;
68a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu    CHECK(format->findInt32("stride", &widthNew));
69a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu    CHECK(format->findInt32("slice-height", &heightNew));
70475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
71475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    int32_t cropLeftNew, cropTopNew, cropRightNew, cropBottomNew;
72475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    if (!format->findRect(
73475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu            "crop", &cropLeftNew, &cropTopNew, &cropRightNew, &cropBottomNew)) {
74475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        cropLeftNew = cropTopNew = 0;
75475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        cropRightNew = widthNew - 1;
76475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        cropBottomNew = heightNew - 1;
77f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    }
78f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
79475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    if (static_cast<int32_t>(mColorFormat) == colorFormatNew &&
80475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        mWidth == widthNew &&
81475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        mHeight == heightNew &&
82475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        mCropLeft == cropLeftNew &&
83475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        mCropTop == cropTopNew &&
84475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        mCropRight == cropRightNew &&
85475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        mCropBottom == cropBottomNew) {
86475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        // Nothing changed, no need to reset renderer.
87475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        return;
88475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    }
89475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
90475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    mColorFormat = static_cast<OMX_COLOR_FORMATTYPE>(colorFormatNew);
91475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    mWidth = widthNew;
92475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    mHeight = heightNew;
93475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    mCropLeft = cropLeftNew;
94475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    mCropTop = cropTopNew;
95475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    mCropRight = cropRightNew;
96475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    mCropBottom = cropBottomNew;
97475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
983571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    mCropWidth = mCropRight - mCropLeft + 1;
993571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    mCropHeight = mCropBottom - mCropTop + 1;
1003571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
1015daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    int halFormat;
1025e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber    size_t bufWidth, bufHeight;
1035e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
104e2c8023444bf96739ff0e4cbaebc086bb73d3bf0Lajos Molnar    switch (mColorFormat) {
1055e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        case OMX_COLOR_FormatYUV420Planar:
1063571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
1079578a90c214e430334b8696999f921290c35d067Lajos Molnar        case OMX_COLOR_FormatYUV420SemiPlanar:
1085e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        {
1099dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber            if (!runningInEmulator()) {
1109dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber                halFormat = HAL_PIXEL_FORMAT_YV12;
1119dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber                bufWidth = (mCropWidth + 1) & ~1;
1129dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber                bufHeight = (mCropHeight + 1) & ~1;
1139dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber                break;
1149dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber            }
1159dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber
1169dc4c66f36ca0158b470c78b0929cd9dd929a375Andreas Huber            // fall through.
1175e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        }
1185e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
1195daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        default:
1205daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            halFormat = HAL_PIXEL_FORMAT_RGB_565;
1213571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            bufWidth = mCropWidth;
1223571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            bufHeight = mCropHeight;
1235daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1245daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            mConverter = new ColorConverter(
1255daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                    mColorFormat, OMX_COLOR_Format16bitRGB565);
1265daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            CHECK(mConverter->isValid());
1275daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            break;
12889e7fff6a5d7410815f42b4a55958a59d4463180Andreas Huber    }
12989e7fff6a5d7410815f42b4a55958a59d4463180Andreas Huber
1301173118eace0e9e347cb007f0da817cee87579edGlenn Kasten    CHECK(mNativeWindow != NULL);
1313571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    CHECK(mCropWidth > 0);
1323571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    CHECK(mCropHeight > 0);
1335daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK(mConverter == NULL || mConverter->isValid());
1345daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1355daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0,
1365daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            native_window_set_usage(
1371173118eace0e9e347cb007f0da817cee87579edGlenn Kasten            mNativeWindow.get(),
1385daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber            GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
139103487c0cb5c06f47225484486a98bc84745a059Andreas Huber            | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1419bc7af17974f448291a44912566ec7472a0d798bMathias Agopian    CHECK_EQ(0,
1429bc7af17974f448291a44912566ec7472a0d798bMathias Agopian            native_window_set_scaling_mode(
1439bc7af17974f448291a44912566ec7472a0d798bMathias Agopian            mNativeWindow.get(),
1449bc7af17974f448291a44912566ec7472a0d798bMathias Agopian            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
1459bc7af17974f448291a44912566ec7472a0d798bMathias Agopian
1465daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    // Width must be multiple of 32???
147475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    CHECK_EQ(0, native_window_set_buffers_dimensions(
1481173118eace0e9e347cb007f0da817cee87579edGlenn Kasten                mNativeWindow.get(),
1495e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber                bufWidth,
150475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu                bufHeight));
151475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    CHECK_EQ(0, native_window_set_buffers_format(
152475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu                mNativeWindow.get(),
1535daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                halFormat));
154ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
15525a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar    // NOTE: native window uses extended right-bottom coordinate
15625a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar    android_native_rect_t crop;
15725a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar    crop.left = mCropLeft;
15825a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar    crop.top = mCropTop;
15925a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar    crop.right = mCropRight + 1;
16025a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar    crop.bottom = mCropBottom + 1;
16125a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar    ALOGV("setting crop: [%d, %d, %d, %d] for size [%zu, %zu]",
16225a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar          crop.left, crop.top, crop.right, crop.bottom, bufWidth, bufHeight);
16325a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar
16425a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar    CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop));
16525a147aaad0ce30da8db763054d963ceaedb4065Lajos Molnar
166475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    int32_t rotationDegrees;
167475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    if (!format->findInt32("rotation-degrees", &rotationDegrees)) {
168475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        rotationDegrees = 0;
169475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    }
170ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t transform;
171ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    switch (rotationDegrees) {
172ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        case 0: transform = 0; break;
173ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        case 90: transform = HAL_TRANSFORM_ROT_90; break;
174ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        case 180: transform = HAL_TRANSFORM_ROT_180; break;
175ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        case 270: transform = HAL_TRANSFORM_ROT_270; break;
176ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        default: transform = 0; break;
177ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
178ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
179475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    CHECK_EQ(0, native_window_set_buffers_transform(
180475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu                mNativeWindow.get(), transform));
1815e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber}
1825e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid SoftwareRenderer::render(
184475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        const void *data, size_t /*size*/, int64_t timestampNs,
185475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu        void* /*platformPrivate*/, const sp<AMessage>& format) {
186475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu    resetFormatIfChanged(format);
187475da7ef08c05a482ced8d318832cf5aa1141affRonghua Wu
1888ce2364512f7c32c824f5ec5719688830ba72427Iliyan Malchev    ANativeWindowBuffer *buf;
1895de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber    int err;
1901e5b2b3361ddd07259bf4b29820ca4aa5f3a861bJamie Gennis    if ((err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(),
1911e5b2b3361ddd07259bf4b29820ca4aa5f3a861bJamie Gennis            &buf)) != 0) {
1925ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Surface::dequeueBuffer returned error %d", err);
1935de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber        return;
1945de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber    }
1955de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber
1965daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    GraphicBufferMapper &mapper = GraphicBufferMapper::get();
1975daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
1983571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    Rect bounds(mCropWidth, mCropHeight);
1995daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
2005daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    void *dst;
2015daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mapper.lock(
2025daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber                buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));
2035daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber
2045daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    if (mConverter) {
2055daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber        mConverter->convert(
206f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                data,
207f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                mWidth, mHeight,
2083571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber                mCropLeft, mCropTop, mCropRight, mCropBottom,
209f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                dst,
210f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                buf->stride, buf->height,
2113571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber                0, 0, mCropWidth - 1, mCropHeight - 1);
2123571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber    } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
2135e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        const uint8_t *src_y = (const uint8_t *)data;
2145e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
2155e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
2165e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
2175e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        uint8_t *dst_y = (uint8_t *)dst;
2185e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        size_t dst_y_size = buf->stride * buf->height;
2195e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
2205e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        size_t dst_c_size = dst_c_stride * buf->height / 2;
2215e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        uint8_t *dst_v = dst_y + dst_y_size;
2225e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        uint8_t *dst_u = dst_v + dst_c_size;
2235e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
2243571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        for (int y = 0; y < mCropHeight; ++y) {
2253571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            memcpy(dst_y, src_y, mCropWidth);
2265e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
2275e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            src_y += mWidth;
2285e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            dst_y += buf->stride;
2295e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        }
2305e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
2313571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
2323571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
2333571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            memcpy(dst_v, src_v, (mCropWidth + 1) / 2);
2345e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber
2355e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            src_u += mWidth / 2;
2365e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            src_v += mWidth / 2;
2375e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            dst_u += dst_c_stride;
2385e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber            dst_v += dst_c_stride;
2395e97c8861ef81d07cf1e304c1c1bed09b84513d4Andreas Huber        }
2409578a90c214e430334b8696999f921290c35d067Lajos Molnar    } else if (mColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
2419578a90c214e430334b8696999f921290c35d067Lajos Molnar            || mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
2423571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        const uint8_t *src_y =
2433571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            (const uint8_t *)data;
2443571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2453571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        const uint8_t *src_uv =
2463571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
2473571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2483571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        uint8_t *dst_y = (uint8_t *)dst;
2493571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2503571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        size_t dst_y_size = buf->stride * buf->height;
2513571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
2523571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        size_t dst_c_size = dst_c_stride * buf->height / 2;
2533571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        uint8_t *dst_v = dst_y + dst_y_size;
2543571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        uint8_t *dst_u = dst_v + dst_c_size;
2553571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2563571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        for (int y = 0; y < mCropHeight; ++y) {
2573571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            memcpy(dst_y, src_y, mCropWidth);
2583571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2593571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            src_y += mWidth;
2603571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            dst_y += buf->stride;
2613571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        }
2623571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2633571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
2643571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            size_t tmp = (mCropWidth + 1) / 2;
2653571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            for (size_t x = 0; x < tmp; ++x) {
2663571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber                dst_u[x] = src_uv[2 * x];
2673571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber                dst_v[x] = src_uv[2 * x + 1];
2683571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            }
2693571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber
2703571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            src_uv += mWidth;
2713571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            dst_u += dst_c_stride;
2723571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber            dst_v += dst_c_stride;
2733571d50a2582bc9c63f09cd81b4f490ea3522bd9Andreas Huber        }
2749578a90c214e430334b8696999f921290c35d067Lajos Molnar    } else {
2759578a90c214e430334b8696999f921290c35d067Lajos Molnar        LOG_ALWAYS_FATAL("bad color format %#x", mColorFormat);
2765daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    }
2774265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
2785daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    CHECK_EQ(0, mapper.unlock(buf->handle));
2794265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
280908ea6603c64e29e40277a74c9fb0e776c097830Lajos Molnar    if ((err = native_window_set_buffers_timestamp(mNativeWindow.get(),
281908ea6603c64e29e40277a74c9fb0e776c097830Lajos Molnar            timestampNs)) != 0) {
282908ea6603c64e29e40277a74c9fb0e776c097830Lajos Molnar        ALOGW("Surface::set_buffers_timestamp returned error %d", err);
283908ea6603c64e29e40277a74c9fb0e776c097830Lajos Molnar    }
284908ea6603c64e29e40277a74c9fb0e776c097830Lajos Molnar
2851e5b2b3361ddd07259bf4b29820ca4aa5f3a861bJamie Gennis    if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf,
2861e5b2b3361ddd07259bf4b29820ca4aa5f3a861bJamie Gennis            -1)) != 0) {
2875ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Surface::queueBuffer returned error %d", err);
2885de4999e6dd8a3f2740d20e30e8a3fccdcb76362Andreas Huber    }
2895daeb129a2c2ba3d14ccd94af283b5f561c783eaAndreas Huber    buf = NULL;
2904265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber}
2914265a834394bfe14a008a2ac58fbbe388566ad07Andreas Huber
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
293