1 /*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "SecHardwareRenderer"
18 #define LOG_NDEBUG 0
19 #include <utils/Log.h>
20
21 #include "SecHardwareRenderer.h"
22
23 #include <media/stagefright/MediaDebug.h>
24 #include <surfaceflinger/ISurface.h>
25 #include <ui/Overlay.h>
26
27 #include <hardware/hardware.h>
28
29 #include "v4l2_utils.h"
30 #include "utils/Timers.h"
31
32 #define CACHEABLE_BUFFERS 0x1
33
34 #define USE_ZERO_COPY
35 //#define SEC_DEBUG
36
37 namespace android {
38
39 ////////////////////////////////////////////////////////////////////////////////
40
SecHardwareRenderer(const sp<ISurface> & surface,size_t displayWidth,size_t displayHeight,size_t decodedWidth,size_t decodedHeight,OMX_COLOR_FORMATTYPE colorFormat,int32_t rotationDegrees,bool fromHardwareDecoder)41 SecHardwareRenderer::SecHardwareRenderer(
42 const sp<ISurface> &surface,
43 size_t displayWidth, size_t displayHeight,
44 size_t decodedWidth, size_t decodedHeight,
45 OMX_COLOR_FORMATTYPE colorFormat,
46 int32_t rotationDegrees,
47 bool fromHardwareDecoder)
48 : mISurface(surface),
49 mDisplayWidth(displayWidth),
50 mDisplayHeight(displayHeight),
51 mDecodedWidth(decodedWidth),
52 mDecodedHeight(decodedHeight),
53 mColorFormat(colorFormat),
54 mInitCheck(NO_INIT),
55 mFrameSize(mDecodedWidth * mDecodedHeight * 2),
56 mIsFirstFrame(true),
57 mCustomFormat(false),
58 mIndex(0) {
59
60 CHECK(mISurface.get() != NULL);
61 CHECK(mDecodedWidth > 0);
62 CHECK(mDecodedHeight > 0);
63
64 if (colorFormat != OMX_COLOR_FormatCbYCrY
65 && colorFormat != OMX_COLOR_FormatYUV420Planar
66 && colorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
67 LOGE("Invalid colorFormat (0x%x)", colorFormat);
68 return;
69 }
70
71 uint32_t orientation;
72 switch (rotationDegrees) {
73 case 0: orientation = ISurface::BufferHeap::ROT_0; break;
74 case 90: orientation = ISurface::BufferHeap::ROT_90; break;
75 case 180: orientation = ISurface::BufferHeap::ROT_180; break;
76 case 270: orientation = ISurface::BufferHeap::ROT_270; break;
77 default: orientation = ISurface::BufferHeap::ROT_0; break;
78 }
79
80 sp<OverlayRef> ref;
81
82 #if defined (USE_ZERO_COPY)
83 if (fromHardwareDecoder) {
84 ref = mISurface->createOverlay(
85 mDecodedWidth, mDecodedHeight,
86 HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP, orientation);
87 mCustomFormat = true;
88 }
89 #else
90 else
91 {
92 ref = mISurface->createOverlay(
93 mDecodedWidth, mDecodedHeight, HAL_PIXEL_FORMAT_YCbCr_420_P,
94 orientation);
95 }
96 #endif
97
98 if (ref.get() == NULL) {
99 LOGE("Unable to create the overlay!");
100 return;
101 }
102
103 mOverlay = new Overlay(ref);
104 mOverlay->setParameter(CACHEABLE_BUFFERS, 0);
105
106 mNumBuf = mOverlay->getBufferCount();
107
108 if (mCustomFormat) {
109 mFrameSize = 32;
110 mMemoryHeap = new MemoryHeapBase(mNumBuf * mFrameSize);
111 } else {
112 for (size_t i = 0; i < (size_t)mNumBuf; ++i) {
113 void *addr = mOverlay->getBufferAddress((void *)i);
114 mOverlayAddresses.push(addr);
115 }
116 }
117
118 mInitCheck = OK;
119 }
120
~SecHardwareRenderer()121 SecHardwareRenderer::~SecHardwareRenderer() {
122
123 if(mMemoryHeap != NULL)
124 mMemoryHeap.clear();
125
126 if (mOverlay.get() != NULL) {
127 mOverlay->destroy();
128 mOverlay.clear();
129 }
130 }
131
handleYUV420Planar(const void * data,size_t size)132 void SecHardwareRenderer::handleYUV420Planar(
133 const void *data, size_t size) {
134
135 int FrameSize;
136 uint8_t* pPhyYAddr;
137 uint8_t* pPhyCAddr;
138 int AddrSize;
139 size_t offset;
140
141 CHECK(size >= (mDecodedWidth * mDecodedHeight * 3) / 2);
142
143 offset = mIndex * mFrameSize;
144 void *dst = (uint8_t *)mMemoryHeap->getBase() + offset;
145
146 AddrSize = sizeof(void *);
147 memcpy(&FrameSize, data, sizeof(FrameSize));
148 memcpy(&pPhyYAddr, data + sizeof(FrameSize), sizeof(pPhyYAddr));
149 memcpy(&pPhyCAddr, data + sizeof(FrameSize) + (AddrSize * 1), sizeof(pPhyCAddr));
150
151 memcpy(dst , &pPhyYAddr, sizeof(pPhyYAddr));
152 memcpy(dst + sizeof(pPhyYAddr) , &pPhyCAddr, sizeof(pPhyCAddr));
153 memcpy(dst + sizeof(pPhyYAddr) + sizeof(pPhyCAddr), &mIndex, sizeof(mIndex));
154 }
155
render(const void * data,size_t size,void * platformPrivate)156 void SecHardwareRenderer::render(
157 const void *data, size_t size, void *platformPrivate) {
158
159 if (mOverlay.get() == NULL) {
160 return;
161 }
162
163 if (mCustomFormat) {
164 /* zero copy solution case */
165
166 overlay_buffer_t dst = (uint8_t *)mMemoryHeap->getBase() + mIndex*mFrameSize;
167
168 if (mColorFormat == OMX_COLOR_FormatYUV420Planar ||
169 mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
170 handleYUV420Planar(data, size);
171 }
172
173 if (mOverlay->queueBuffer(dst) == ALL_BUFFERS_FLUSHED) {
174 mIsFirstFrame = true;
175 if (mOverlay->queueBuffer((void *)dst) != 0) {
176 return;
177 }
178 }
179
180 if (++mIndex == mNumBuf) {
181 mIndex = 0;
182 }
183
184 overlay_buffer_t overlay_buffer;
185 if (!mIsFirstFrame) {
186 status_t err = mOverlay->dequeueBuffer(&overlay_buffer);
187 if (err == ALL_BUFFERS_FLUSHED) {
188 mIsFirstFrame = true;
189 } else {
190 return;
191 }
192 } else {
193 mIsFirstFrame = false;
194 }
195 } else {
196 /* normal frame case */
197 if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
198 memcpy(mOverlayAddresses[mIndex], data, size);
199 }
200
201 if (mOverlay->queueBuffer((void *)mIndex) == ALL_BUFFERS_FLUSHED) {
202 mIsFirstFrame = true;
203 if (mOverlay->queueBuffer((void *)mIndex) != 0) {
204 return;
205 }
206 }
207
208 if (++mIndex == mNumBuf) {
209 mIndex = 0;
210 }
211
212 overlay_buffer_t overlay_buffer;
213 if (!mIsFirstFrame) {
214 status_t err = mOverlay->dequeueBuffer(&overlay_buffer);
215
216 if (err == ALL_BUFFERS_FLUSHED) {
217 mIsFirstFrame = true;
218 } else {
219 return;
220 }
221 } else {
222 mIsFirstFrame = false;
223 }
224 }
225 }
226
227 } // namespace android
228
229