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 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 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 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 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