Home | History | Annotate | Download | only in libstagefrighthw
      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