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 41namespace android { 42 43namespace { 44 45class Buffer2D : public C2Buffer { 46public: 47 explicit Buffer2D(C2ConstGraphicBlock block) : C2Buffer({ block }) {} 48}; 49 50} // namespace 51 52C2OMXNode::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 62status_t C2OMXNode::freeNode() { 63 mComp.reset(); 64 return OK; 65} 66 67status_t C2OMXNode::sendCommand(OMX_COMMANDTYPE cmd, OMX_S32 param) { 68 (void)cmd; 69 (void)param; 70 return ERROR_UNSUPPORTED; 71} 72 73status_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 101status_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 108status_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 115status_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 122status_t C2OMXNode::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) { 123 (void)portIndex; 124 (void)mode; 125 return ERROR_UNSUPPORTED; 126} 127 128status_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 138status_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 148status_t C2OMXNode::getGraphicBufferUsage(OMX_U32 portIndex, OMX_U32* usage) { 149 (void)portIndex; 150 *usage = 0; 151 return ERROR_UNSUPPORTED; 152} 153 154status_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 165status_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 176status_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 184status_t C2OMXNode::freeBuffer(OMX_U32 portIndex, buffer_id buffer) { 185 (void)portIndex; 186 (void)buffer; 187 return ERROR_UNSUPPORTED; 188} 189 190status_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 198status_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 265status_t C2OMXNode::getExtensionIndex( 266 const char *parameterName, OMX_INDEXTYPE *index) { 267 (void)parameterName; 268 *index = OMX_IndexMax; 269 return ERROR_UNSUPPORTED; 270} 271 272status_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 283sp<IOMXBufferSource> C2OMXNode::getSource() { 284 return mBufferSource; 285} 286 287void C2OMXNode::setFrameSize(uint32_t width, uint32_t height) { 288 mWidth = width; 289 mHeight = height; 290} 291 292} // namespace android 293