Home | History | Annotate | Download | only in sfplugin
      1 /*
      2  * Copyright 2018, 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 #ifdef __LP64__
     18 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
     19 #endif
     20 
     21 //#define LOG_NDEBUG 0
     22 #define LOG_TAG "C2OMXNode"
     23 #include <log/log.h>
     24 
     25 #include <C2AllocatorGralloc.h>
     26 #include <C2BlockInternal.h>
     27 #include <C2Component.h>
     28 #include <C2PlatformSupport.h>
     29 
     30 #include <OMX_Component.h>
     31 #include <OMX_Index.h>
     32 #include <OMX_IndexExt.h>
     33 
     34 #include <media/stagefright/omx/OMXUtils.h>
     35 #include <media/stagefright/MediaErrors.h>
     36 #include <ui/Fence.h>
     37 #include <ui/GraphicBuffer.h>
     38 
     39 #include "C2OMXNode.h"
     40 
     41 namespace android {
     42 
     43 namespace {
     44 
     45 class Buffer2D : public C2Buffer {
     46 public:
     47     explicit Buffer2D(C2ConstGraphicBlock block) : C2Buffer({ block }) {}
     48 };
     49 
     50 }  // namespace
     51 
     52 C2OMXNode::C2OMXNode(const std::shared_ptr<Codec2Client::Component> &comp)
     53     : mComp(comp), mFrameIndex(0), mWidth(0), mHeight(0) {
     54     // TODO: read from intf()
     55     if (!strncmp(comp->getName().c_str(), "c2.android.", 11)) {
     56         mUsage = GRALLOC_USAGE_SW_READ_OFTEN;
     57     } else {
     58         mUsage = GRALLOC_USAGE_HW_VIDEO_ENCODER;
     59     }
     60 }
     61 
     62 status_t C2OMXNode::freeNode() {
     63     mComp.reset();
     64     return OK;
     65 }
     66 
     67 status_t C2OMXNode::sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) {
     68     (void)cmd;
     69     (void)param;
     70     return ERROR_UNSUPPORTED;
     71 }
     72 
     73 status_t C2OMXNode::getParameter(OMX_INDEXTYPE index, void *params, size_t size) {
     74     status_t err = ERROR_UNSUPPORTED;
     75     switch ((uint32_t)index) {
     76         case OMX_IndexParamConsumerUsageBits: {
     77             OMX_U32 *usage = (OMX_U32 *)params;
     78             *usage = mUsage;
     79             err = OK;
     80             break;
     81         }
     82         case OMX_IndexParamPortDefinition: {
     83             if (size < sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
     84                 return BAD_VALUE;
     85             }
     86             OMX_PARAM_PORTDEFINITIONTYPE *pDef = (OMX_PARAM_PORTDEFINITIONTYPE *)params;
     87             // TODO: read these from intf()
     88             pDef->nBufferCountActual = 16;
     89             pDef->eDomain = OMX_PortDomainVideo;
     90             pDef->format.video.nFrameWidth = mWidth;
     91             pDef->format.video.nFrameHeight = mHeight;
     92             err = OK;
     93             break;
     94         }
     95         default:
     96             break;
     97     }
     98     return err;
     99 }
    100 
    101 status_t C2OMXNode::setParameter(OMX_INDEXTYPE index, const void *params, size_t size) {
    102     (void)index;
    103     (void)params;
    104     (void)size;
    105     return ERROR_UNSUPPORTED;
    106 }
    107 
    108 status_t C2OMXNode::getConfig(OMX_INDEXTYPE index, void *config, size_t size) {
    109     (void)index;
    110     (void)config;
    111     (void)size;
    112     return ERROR_UNSUPPORTED;
    113 }
    114 
    115 status_t C2OMXNode::setConfig(OMX_INDEXTYPE index, const void *config, size_t size) {
    116     (void)index;
    117     (void)config;
    118     (void)size;
    119     return ERROR_UNSUPPORTED;
    120 }
    121 
    122 status_t C2OMXNode::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {
    123     (void)portIndex;
    124     (void)mode;
    125     return ERROR_UNSUPPORTED;
    126 }
    127 
    128 status_t C2OMXNode::prepareForAdaptivePlayback(
    129         OMX_U32 portIndex, OMX_BOOL enable,
    130         OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
    131     (void)portIndex;
    132     (void)enable;
    133     (void)maxFrameWidth;
    134     (void)maxFrameHeight;
    135     return ERROR_UNSUPPORTED;
    136 }
    137 
    138 status_t C2OMXNode::configureVideoTunnelMode(
    139         OMX_U32 portIndex, OMX_BOOL tunneled,
    140         OMX_U32 audioHwSync, native_handle_t **sidebandHandle) {
    141     (void)portIndex;
    142     (void)tunneled;
    143     (void)audioHwSync;
    144     *sidebandHandle = nullptr;
    145     return ERROR_UNSUPPORTED;
    146 }
    147 
    148 status_t C2OMXNode::getGraphicBufferUsage(OMX_U32 portIndex, OMX_U32* usage) {
    149     (void)portIndex;
    150     *usage = 0;
    151     return ERROR_UNSUPPORTED;
    152 }
    153 
    154 status_t C2OMXNode::setInputSurface(const sp<IOMXBufferSource> &bufferSource) {
    155     c2_status_t err = GetCodec2PlatformAllocatorStore()->fetchAllocator(
    156             C2PlatformAllocatorStore::GRALLOC,
    157             &mAllocator);
    158     if (err != OK) {
    159         return UNKNOWN_ERROR;
    160     }
    161     mBufferSource = bufferSource;
    162     return OK;
    163 }
    164 
    165 status_t C2OMXNode::allocateSecureBuffer(
    166         OMX_U32 portIndex, size_t size, buffer_id *buffer,
    167         void **bufferData, sp<NativeHandle> *nativeHandle) {
    168     (void)portIndex;
    169     (void)size;
    170     (void)nativeHandle;
    171     *buffer = 0;
    172     *bufferData = nullptr;
    173     return ERROR_UNSUPPORTED;
    174 }
    175 
    176 status_t C2OMXNode::useBuffer(
    177         OMX_U32 portIndex, const OMXBuffer &omxBuf, buffer_id *buffer) {
    178     (void)portIndex;
    179     (void)omxBuf;
    180     *buffer = 0;
    181     return ERROR_UNSUPPORTED;
    182 }
    183 
    184 status_t C2OMXNode::freeBuffer(OMX_U32 portIndex, buffer_id buffer) {
    185     (void)portIndex;
    186     (void)buffer;
    187     return ERROR_UNSUPPORTED;
    188 }
    189 
    190 status_t C2OMXNode::fillBuffer(
    191         buffer_id buffer, const OMXBuffer &omxBuf, int fenceFd) {
    192     (void)buffer;
    193     (void)omxBuf;
    194     (void)fenceFd;
    195     return ERROR_UNSUPPORTED;
    196 }
    197 
    198 status_t C2OMXNode::emptyBuffer(
    199         buffer_id buffer, const OMXBuffer &omxBuf,
    200         OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
    201     // TODO: better fence handling
    202     if (fenceFd >= 0) {
    203         sp<Fence> fence = new Fence(fenceFd);
    204         fence->waitForever(LOG_TAG);
    205     }
    206     std::shared_ptr<Codec2Client::Component> comp = mComp.lock();
    207     if (!comp) {
    208         return NO_INIT;
    209     }
    210 
    211     uint32_t c2Flags = (flags & OMX_BUFFERFLAG_EOS)
    212             ? C2FrameData::FLAG_END_OF_STREAM : 0;
    213     std::shared_ptr<C2GraphicBlock> block;
    214 
    215     C2Handle *handle = nullptr;
    216     if (omxBuf.mBufferType == OMXBuffer::kBufferTypeANWBuffer
    217             && omxBuf.mGraphicBuffer != nullptr) {
    218         std::shared_ptr<C2GraphicAllocation> alloc;
    219         handle = WrapNativeCodec2GrallocHandle(
    220                 native_handle_clone(omxBuf.mGraphicBuffer->handle),
    221                 omxBuf.mGraphicBuffer->width,
    222                 omxBuf.mGraphicBuffer->height,
    223                 omxBuf.mGraphicBuffer->format,
    224                 omxBuf.mGraphicBuffer->usage,
    225                 omxBuf.mGraphicBuffer->stride);
    226         c2_status_t err = mAllocator->priorGraphicAllocation(handle, &alloc);
    227         if (err != OK) {
    228             return UNKNOWN_ERROR;
    229         }
    230         block = _C2BlockFactory::CreateGraphicBlock(alloc);
    231     } else if (!(flags & OMX_BUFFERFLAG_EOS)) {
    232         return BAD_VALUE;
    233     }
    234 
    235     std::unique_ptr<C2Work> work(new C2Work);
    236     work->input.flags = (C2FrameData::flags_t)c2Flags;
    237     work->input.ordinal.timestamp = timestamp;
    238     work->input.ordinal.frameIndex = mFrameIndex++;
    239     work->input.buffers.clear();
    240     if (block) {
    241         std::shared_ptr<C2Buffer> c2Buffer(
    242                 // TODO: fence
    243                 new Buffer2D(block->share(
    244                         C2Rect(block->width(), block->height()), ::C2Fence())),
    245                 [buffer, source = getSource()](C2Buffer *ptr) {
    246                     delete ptr;
    247                     // TODO: fence
    248                     (void)source->onInputBufferEmptied(buffer, -1);
    249                 });
    250         work->input.buffers.push_back(c2Buffer);
    251     }
    252     work->worklets.clear();
    253     work->worklets.emplace_back(new C2Worklet);
    254     std::list<std::unique_ptr<C2Work>> items;
    255     items.push_back(std::move(work));
    256 
    257     c2_status_t err = comp->queue(&items);
    258     if (err != C2_OK) {
    259         return UNKNOWN_ERROR;
    260     }
    261 
    262     return OK;
    263 }
    264 
    265 status_t C2OMXNode::getExtensionIndex(
    266         const char *parameterName, OMX_INDEXTYPE *index) {
    267     (void)parameterName;
    268     *index = OMX_IndexMax;
    269     return ERROR_UNSUPPORTED;
    270 }
    271 
    272 status_t C2OMXNode::dispatchMessage(const omx_message& msg) {
    273     if (msg.type != omx_message::EVENT) {
    274         return ERROR_UNSUPPORTED;
    275     }
    276     if (msg.u.event_data.event != OMX_EventDataSpaceChanged) {
    277         return ERROR_UNSUPPORTED;
    278     }
    279     // TODO: fill intf() with info inside |msg|.
    280     return OK;
    281 }
    282 
    283 sp<IOMXBufferSource> C2OMXNode::getSource() {
    284     return mBufferSource;
    285 }
    286 
    287 void C2OMXNode::setFrameSize(uint32_t width, uint32_t height) {
    288     mWidth = width;
    289     mHeight = height;
    290 }
    291 
    292 }  // namespace android
    293