blob: 0f43043bf4aa271f4c4d68ac1e92fd16cbfefc09 [file] [log] [blame]
Dharmaray Kundargi643290d2011-01-16 16:02:42 -08001/*
2 * Copyright (C) 2011 NXP Software
3 * Copyright (C) 2011 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19#define LOG_NDEBUG 1
20#define LOG_TAG "PreviewRenderer"
21#include <utils/Log.h>
22
23#include "PreviewRenderer.h"
24
25#include <binder/MemoryHeapBase.h>
26#include <binder/MemoryHeapPmem.h>
27#include <media/stagefright/MediaDebug.h>
28#include <surfaceflinger/Surface.h>
29
30namespace android {
31
32PreviewRenderer::PreviewRenderer(
33 OMX_COLOR_FORMATTYPE colorFormat,
34 const sp<Surface> &surface,
35 size_t displayWidth, size_t displayHeight,
36 size_t decodedWidth, size_t decodedHeight,
37 int32_t rotationDegrees)
38 : mColorFormat(colorFormat),
39 mConverter(NULL),
40 mYUVMode(None),
41 mSurface(surface),
42 mDisplayWidth(displayWidth),
43 mDisplayHeight(displayHeight),
44 mDecodedWidth(decodedWidth),
45 mDecodedHeight(decodedHeight) {
46 LOGV("input format = %d", mColorFormat);
47 LOGV("display = %d x %d, decoded = %d x %d",
48 mDisplayWidth, mDisplayHeight, mDecodedWidth, mDecodedHeight);
49
50 mDecodedWidth = mDisplayWidth;
51 mDecodedHeight = mDisplayHeight;
52
53 int halFormat;
54 switch (mColorFormat) {
55 case OMX_COLOR_FormatYUV420Planar:
56 {
57 halFormat = HAL_PIXEL_FORMAT_YV12;
58 mYUVMode = None;
59 break;
60 }
61 default:
62 halFormat = HAL_PIXEL_FORMAT_RGB_565;
63
64 mConverter = new ColorConverter(
65 mColorFormat, OMX_COLOR_Format16bitRGB565);
66 CHECK(mConverter->isValid());
67 break;
68 }
69
70 CHECK(mSurface.get() != NULL);
71 CHECK(mDecodedWidth > 0);
72 CHECK(mDecodedHeight > 0);
73 CHECK(mConverter == NULL || mConverter->isValid());
74
75 CHECK_EQ(0,
76 native_window_set_usage(
77 mSurface.get(),
78 GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
79 | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
80
81 CHECK_EQ(0, native_window_set_buffer_count(mSurface.get(), 2));
82
83 // Width must be multiple of 32???
84 CHECK_EQ(0, native_window_set_buffers_geometry(
85 mSurface.get(), mDecodedWidth, mDecodedHeight,
86 halFormat));
87
88 uint32_t transform;
89 switch (rotationDegrees) {
90 case 0: transform = 0; break;
91 case 90: transform = HAL_TRANSFORM_ROT_90; break;
92 case 180: transform = HAL_TRANSFORM_ROT_180; break;
93 case 270: transform = HAL_TRANSFORM_ROT_270; break;
94 default: transform = 0; break;
95 }
96
97 if (transform) {
98 CHECK_EQ(0, native_window_set_buffers_transform(
99 mSurface.get(), transform));
100 }
101}
102
103PreviewRenderer::~PreviewRenderer() {
104 delete mConverter;
105 mConverter = NULL;
106}
107
108
109//
110// Provides a buffer and associated stride
111// This buffer is allocated by the SurfaceFlinger
112//
113// For optimal display performances, you should :
114// 1) call getBufferYV12()
115// 2) fill the buffer with your data
116// 3) call renderYV12() to take these changes into account
117//
118// For each call to getBufferYV12(), you must also call renderYV12()
119// Expected format in the buffer is YV12 formats (similar to YUV420 planar fromat)
120// for more details on this YV12 cf hardware/libhardware/include/hardware/hardware.h
121//
122void PreviewRenderer::getBufferYV12(uint8_t **data, size_t *stride) {
123 int err = OK;
124 LOGV("getBuffer START");
125
126 if ((err = mSurface->dequeueBuffer(mSurface.get(), &mBuf)) != 0) {
127 LOGW("Surface::dequeueBuffer returned error %d", err);
128 return;
129 }
130
131 CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), mBuf));
132
133 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
134
135 Rect bounds(mDecodedWidth, mDecodedHeight);
136
137 void *dst;
138 CHECK_EQ(0, mapper.lock(
139 mBuf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));
140 LOGV("Buffer locked");
141
142 *data = (uint8_t*)dst;
143 *stride = mBuf->stride;
144
145 LOGV("getBuffer END %p %d", dst, mBuf->stride);
146}
147
148
149//
150// Display the content of the buffer provided by last call to getBufferYV12()
151//
152// See getBufferYV12() for details.
153//
154void PreviewRenderer::renderYV12() {
155 LOGV("renderYV12() START");
156 int err = OK;
157
158 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
159
160 if (mBuf!= NULL) {
161 CHECK_EQ(0, mapper.unlock(mBuf->handle));
162
163 if ((err = mSurface->queueBuffer(mSurface.get(), mBuf)) != 0) {
164 LOGW("Surface::queueBuffer returned error %d", err);
165 }
166 }
167 mBuf = NULL;
168 LOGV("renderYV12() END");
169}
170
171
172
173//
174// Display the given data buffer
175// platformPrivate is not used (kept for backwrad compatibility)
176// Please rather use getbuffer() and the other render()functions (with no params)
177// for optimal display
178//
179void PreviewRenderer::render(
180 const void *data, size_t size, void *platformPrivate) {
181 android_native_buffer_t *buf;
182 int err;
183
184 if ((err = mSurface->dequeueBuffer(mSurface.get(), &buf)) != 0) {
185 LOGW("Surface::dequeueBuffer returned error %d", err);
186 return;
187 }
188
189 CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf));
190
191 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
192
193 Rect bounds(mDecodedWidth, mDecodedHeight);
194
195 void *dst;
196 CHECK_EQ(0, mapper.lock(
197 buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));
198 LOGV("Buffer locked");
199
200 if (mConverter) {
201 LOGV("Convert to RGB565");
202 mConverter->convert(data,
203 mDecodedWidth, mDecodedHeight,
204 0,0,mDecodedWidth, mDecodedHeight,
205 dst, mDecodedWidth, mDecodedHeight,
206 0,0,mDecodedWidth, mDecodedHeight);
207 } else if (mYUVMode == None) {
208 // Input and output are both YUV420sp, but the alignment requirements
209 // are different.
210 LOGV("mYUVMode == None %d x %d", mDecodedWidth, mDecodedHeight);
211 size_t srcYStride = mDecodedWidth;
212 const uint8_t *srcY = (const uint8_t *)data;
213 uint8_t *dstY = (uint8_t *)dst;
214 LOGV("srcY = %p dstY = %p", srcY, dstY);
215 LOGV("srcYStride = %d dstYstride = %d", srcYStride, buf->stride);
216 for (size_t i = 0; i < mDecodedHeight; ++i) {
217 memcpy(dstY, srcY, mDecodedWidth);
218 srcY += srcYStride;
219 dstY += buf->stride;
220 }
221
222 size_t srcUVStride = (mDecodedWidth + 1) / 2;
223 size_t dstUVStride = ALIGN(mDecodedWidth / 2, 32);
224 LOGV("srcUVStride = %d dstUVStride = %d", srcUVStride, dstUVStride);
225
226 // Copy V
227 // Source buffer is YUV, skip U
228 const uint8_t *srcV = (const uint8_t *)data
229 + mDecodedHeight * mDecodedWidth + (mDecodedHeight * mDecodedWidth)/4;
230 // Destination buffer is YVU
231 uint8_t *dstUV = (uint8_t *)dst
232 + buf->stride*mDecodedHeight;
233 LOGV("srcV = %p dstUV = %p", srcV, dstUV);
234 for (size_t i = 0; i < (mDecodedHeight+1)/2; ++i) {
235 memcpy(dstUV, srcV, mDecodedWidth/2);
236 srcV += srcUVStride;
237 dstUV += dstUVStride;
238 }
239
240
241 // Copy V
242 // Source buffer is YUV, go back to end of Y
243 const uint8_t *srcU = (const uint8_t *)data
244 + mDecodedHeight * mDecodedWidth ;
245 // Destination buffer is YVU
246 // Keep writing after V buffer has been filled, U follows immediately
247 LOGV("srcU = %p dstUV = %p", srcU, dstUV);
248 for (size_t i = 0; i < (mDecodedHeight+1)/2; ++i) {
249 memcpy(dstUV, srcU, mDecodedWidth/2);
250 srcU += srcUVStride;
251 dstUV += dstUVStride;
252 }
253 } else {
254 memcpy(dst, data, size);
255 }
256
257 CHECK_EQ(0, mapper.unlock(buf->handle));
258
259 if ((err = mSurface->queueBuffer(mSurface.get(), buf)) != 0) {
260 LOGW("Surface::queueBuffer returned error %d", err);
261 }
262 buf = NULL;
263}
264
265} // namespace android