• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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