PureOmxPlatformLayer.cpp (12862B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "PureOmxPlatformLayer.h" 8 9 #include "OmxCoreLibLinker.h" 10 #include "OmxDataDecoder.h" 11 #include "OmxPromiseLayer.h" 12 13 #ifdef LOG 14 # undef LOG 15 #endif 16 17 #define LOG(arg, ...) \ 18 MOZ_LOG( \ 19 sPDMLog, mozilla::LogLevel::Debug, \ 20 ("PureOmxPlatformLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) 21 #define LOG_BUF(arg, ...) \ 22 MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, \ 23 ("PureOmxBufferData(%p)::%s: " arg, this, __func__, ##__VA_ARGS__)) 24 25 namespace mozilla { 26 27 #define OMX_FUNC(func) extern typeof(func)* func; 28 #include "OmxFunctionList.h" 29 #undef OMX_FUNC 30 31 PureOmxBufferData::PureOmxBufferData( 32 const PureOmxPlatformLayer& aPlatformLayer, 33 const OMX_PARAM_PORTDEFINITIONTYPE& aPortDef) 34 : BufferData(nullptr), mPlatformLayer(aPlatformLayer), mPortDef(aPortDef) { 35 LOG_BUF(""); 36 37 if (ShouldUseEGLImage()) { 38 // TODO 39 LOG_BUF( 40 "OMX_UseEGLImage() seems available but using it isn't implemented " 41 "yet."); 42 } 43 44 OMX_ERRORTYPE err; 45 err = OMX_AllocateBuffer(mPlatformLayer.GetComponent(), &mBuffer, 46 mPortDef.nPortIndex, this, mPortDef.nBufferSize); 47 if (err != OMX_ErrorNone) { 48 LOG_BUF("Failed to allocate the buffer!: 0x%08x", err); 49 } 50 } 51 52 PureOmxBufferData::~PureOmxBufferData() { 53 LOG_BUF(""); 54 ReleaseBuffer(); 55 } 56 57 void PureOmxBufferData::ReleaseBuffer() { 58 LOG_BUF(""); 59 60 if (mBuffer) { 61 OMX_ERRORTYPE err; 62 err = OMX_FreeBuffer(mPlatformLayer.GetComponent(), mPortDef.nPortIndex, 63 mBuffer); 64 if (err != OMX_ErrorNone) { 65 LOG_BUF("Failed to free the buffer!: 0x%08x", err); 66 } 67 mBuffer = nullptr; 68 } 69 } 70 71 bool PureOmxBufferData::ShouldUseEGLImage() { 72 OMX_ERRORTYPE err; 73 err = OMX_UseEGLImage(mPlatformLayer.GetComponent(), nullptr, 74 mPortDef.nPortIndex, nullptr, nullptr); 75 return (err != OMX_ErrorNotImplemented); 76 } 77 78 /* static */ 79 bool PureOmxPlatformLayer::Init(void) { 80 if (!OmxCoreLibLinker::Link()) { 81 return false; 82 } 83 84 OMX_ERRORTYPE err = OMX_Init(); 85 if (err != OMX_ErrorNone) { 86 MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, 87 ("PureOmxPlatformLayer::%s: Failed to initialize OMXCore: 0x%08x", 88 __func__, err)); 89 return false; 90 } 91 92 return true; 93 } 94 95 /* static */ 96 OMX_CALLBACKTYPE PureOmxPlatformLayer::sCallbacks = { 97 EventHandler, EmptyBufferDone, FillBufferDone}; 98 99 PureOmxPlatformLayer::PureOmxPlatformLayer( 100 OmxDataDecoder* aDataDecoder, OmxPromiseLayer* aPromiseLayer, 101 TaskQueue* aTaskQueue, layers::ImageContainer* aImageContainer) 102 : mComponent(nullptr), 103 mDataDecoder(aDataDecoder), 104 mPromiseLayer(aPromiseLayer), 105 mTaskQueue(aTaskQueue), 106 mImageContainer(aImageContainer) { 107 LOG(""); 108 } 109 110 PureOmxPlatformLayer::~PureOmxPlatformLayer() { LOG(""); } 111 112 OMX_ERRORTYPE 113 PureOmxPlatformLayer::InitOmxToStateLoaded(const TrackInfo* aInfo) { 114 LOG(""); 115 116 if (!aInfo) { 117 return OMX_ErrorUndefined; 118 } 119 mInfo = aInfo; 120 121 return CreateComponent(); 122 } 123 124 OMX_ERRORTYPE 125 PureOmxPlatformLayer::EmptyThisBuffer(BufferData* aData) { 126 LOG(""); 127 return OMX_EmptyThisBuffer(mComponent, aData->mBuffer); 128 } 129 130 OMX_ERRORTYPE 131 PureOmxPlatformLayer::FillThisBuffer(BufferData* aData) { 132 LOG(""); 133 return OMX_FillThisBuffer(mComponent, aData->mBuffer); 134 } 135 136 OMX_ERRORTYPE 137 PureOmxPlatformLayer::SendCommand(OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, 138 OMX_PTR aCmdData) { 139 LOG("aCmd: 0x%08x", aCmd); 140 if (!mComponent) { 141 return OMX_ErrorUndefined; 142 } 143 return OMX_SendCommand(mComponent, aCmd, aParam1, aCmdData); 144 } 145 146 nsresult PureOmxPlatformLayer::FindPortDefinition( 147 OMX_DIRTYPE aType, OMX_PARAM_PORTDEFINITIONTYPE& portDef) { 148 nsTArray<uint32_t> portIndex; 149 GetPortIndices(portIndex); 150 for (auto idx : portIndex) { 151 InitOmxParameter(&portDef); 152 portDef.nPortIndex = idx; 153 154 OMX_ERRORTYPE err; 155 err = GetParameter(OMX_IndexParamPortDefinition, &portDef, 156 sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); 157 if (err != OMX_ErrorNone) { 158 return NS_ERROR_FAILURE; 159 } else if (portDef.eDir == aType) { 160 LOG("Found OMX_IndexParamPortDefinition: port: %d, type: %d", 161 portDef.nPortIndex, portDef.eDir); 162 return NS_OK; 163 } 164 } 165 return NS_ERROR_FAILURE; 166 } 167 168 nsresult PureOmxPlatformLayer::AllocateOmxBuffer(OMX_DIRTYPE aType, 169 BUFFERLIST* aBufferList) { 170 LOG("aType: %d", aType); 171 172 OMX_PARAM_PORTDEFINITIONTYPE portDef; 173 nsresult result = FindPortDefinition(aType, portDef); 174 if (result != NS_OK) { 175 return result; 176 } 177 178 LOG("nBufferCountActual: %d, nBufferSize: %d", portDef.nBufferCountActual, 179 portDef.nBufferSize); 180 181 for (OMX_U32 i = 0; i < portDef.nBufferCountActual; ++i) { 182 RefPtr<PureOmxBufferData> buffer = new PureOmxBufferData(*this, portDef); 183 aBufferList->AppendElement(buffer); 184 } 185 186 return NS_OK; 187 } 188 189 nsresult PureOmxPlatformLayer::ReleaseOmxBuffer(OMX_DIRTYPE aType, 190 BUFFERLIST* aBufferList) { 191 LOG("aType: 0x%08x", aType); 192 193 uint32_t len = aBufferList->Length(); 194 for (uint32_t i = 0; i < len; i++) { 195 PureOmxBufferData* buffer = 196 static_cast<PureOmxBufferData*>(aBufferList->ElementAt(i).get()); 197 198 // All raw OpenMAX buffers have to be released here to flush 199 // OMX_CommandStateSet for switching the state to OMX_StateLoaded. 200 // See OmxDataDecoder::DoAsyncShutdown() for more detail. 201 buffer->ReleaseBuffer(); 202 } 203 aBufferList->Clear(); 204 205 return NS_OK; 206 } 207 208 OMX_ERRORTYPE 209 PureOmxPlatformLayer::GetState(OMX_STATETYPE* aType) { 210 LOG(""); 211 212 if (mComponent) { 213 return OMX_GetState(mComponent, aType); 214 } 215 216 return OMX_ErrorUndefined; 217 } 218 219 OMX_ERRORTYPE 220 PureOmxPlatformLayer::GetParameter(OMX_INDEXTYPE aParamIndex, 221 OMX_PTR aComponentParameterStructure, 222 OMX_U32 aComponentParameterSize) { 223 LOG("aParamIndex: 0x%08x", aParamIndex); 224 225 if (!mComponent) { 226 return OMX_ErrorUndefined; 227 } 228 229 return OMX_GetParameter(mComponent, aParamIndex, 230 aComponentParameterStructure); 231 } 232 233 OMX_ERRORTYPE 234 PureOmxPlatformLayer::SetParameter(OMX_INDEXTYPE aParamIndex, 235 OMX_PTR aComponentParameterStructure, 236 OMX_U32 aComponentParameterSize) { 237 LOG("aParamIndex: 0x%08x", aParamIndex); 238 239 if (!mComponent) { 240 return OMX_ErrorUndefined; 241 } 242 243 return OMX_SetParameter(mComponent, aParamIndex, 244 aComponentParameterStructure); 245 } 246 247 nsresult PureOmxPlatformLayer::Shutdown() { 248 LOG(""); 249 if (mComponent) { 250 OMX_FreeHandle(mComponent); 251 mComponent = nullptr; 252 } 253 mPromiseLayer = nullptr; 254 mDataDecoder = nullptr; 255 return NS_OK; 256 } 257 258 /* static */ 259 OMX_ERRORTYPE PureOmxPlatformLayer::EventHandler(OMX_HANDLETYPE hComponent, 260 OMX_PTR pAppData, 261 OMX_EVENTTYPE eEventType, 262 OMX_U32 nData1, OMX_U32 nData2, 263 OMX_PTR pEventData) { 264 PureOmxPlatformLayer* self = static_cast<PureOmxPlatformLayer*>(pAppData); 265 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 266 "mozilla::PureOmxPlatformLayer::EventHandler", 267 [self, eEventType, nData1, nData2, pEventData]() { 268 self->EventHandler(eEventType, nData1, nData2, pEventData); 269 }); 270 nsresult rv = self->mTaskQueue->Dispatch(r.forget()); 271 return NS_SUCCEEDED(rv) ? OMX_ErrorNone : OMX_ErrorUndefined; 272 } 273 274 /* static */ 275 OMX_ERRORTYPE PureOmxPlatformLayer::EmptyBufferDone( 276 OMX_HANDLETYPE hComponent, OMX_IN OMX_PTR pAppData, 277 OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 278 PureOmxPlatformLayer* self = static_cast<PureOmxPlatformLayer*>(pAppData); 279 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 280 "mozilla::PureOmxPlatformLayer::EmptyBufferDone", 281 [self, pBuffer]() { self->EmptyBufferDone(pBuffer); }); 282 nsresult rv = self->mTaskQueue->Dispatch(r.forget()); 283 return NS_SUCCEEDED(rv) ? OMX_ErrorNone : OMX_ErrorUndefined; 284 } 285 286 /* static */ 287 OMX_ERRORTYPE PureOmxPlatformLayer::FillBufferDone( 288 OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, 289 OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) { 290 PureOmxPlatformLayer* self = static_cast<PureOmxPlatformLayer*>(pAppData); 291 nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( 292 "mozilla::PureOmxPlatformLayer::FillBufferDone", 293 [self, pBuffer]() { self->FillBufferDone(pBuffer); }); 294 nsresult rv = self->mTaskQueue->Dispatch(r.forget()); 295 return NS_SUCCEEDED(rv) ? OMX_ErrorNone : OMX_ErrorUndefined; 296 } 297 298 OMX_ERRORTYPE 299 PureOmxPlatformLayer::EventHandler(OMX_EVENTTYPE eEventType, OMX_U32 nData1, 300 OMX_U32 nData2, OMX_PTR pEventData) { 301 bool handled = mPromiseLayer->Event(eEventType, nData1, nData2); 302 LOG("eEventType: 0x%08x, handled: %d", eEventType, handled); 303 return OMX_ErrorNone; 304 } 305 306 OMX_ERRORTYPE 307 PureOmxPlatformLayer::EmptyBufferDone(OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) { 308 PureOmxBufferData* buffer = 309 static_cast<PureOmxBufferData*>(pBuffer->pAppPrivate); 310 OMX_DIRTYPE portDirection = buffer->GetPortDirection(); 311 LOG("PortDirection: %d", portDirection); 312 mPromiseLayer->EmptyFillBufferDone(portDirection, buffer); 313 return OMX_ErrorNone; 314 } 315 316 OMX_ERRORTYPE 317 PureOmxPlatformLayer::FillBufferDone(OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer) { 318 PureOmxBufferData* buffer = 319 static_cast<PureOmxBufferData*>(pBuffer->pAppPrivate); 320 OMX_DIRTYPE portDirection = buffer->GetPortDirection(); 321 LOG("PortDirection: %d", portDirection); 322 mPromiseLayer->EmptyFillBufferDone(portDirection, buffer); 323 return OMX_ErrorNone; 324 } 325 326 bool PureOmxPlatformLayer::SupportsMimeType(const nsACString& aMimeType) { 327 return FindStandardComponent(aMimeType, nullptr); 328 } 329 330 static bool GetStandardComponentRole(const nsACString& aMimeType, 331 nsACString& aRole) { 332 if (aMimeType.EqualsLiteral("video/avc") || 333 aMimeType.EqualsLiteral("video/mp4") || 334 aMimeType.EqualsLiteral("video/mp4v-es")) { 335 aRole.Assign("video_decoder.avc"); 336 return true; 337 } else if (aMimeType.EqualsLiteral("audio/mp4a-latm") || 338 aMimeType.EqualsLiteral("audio/mp4") || 339 aMimeType.EqualsLiteral("audio/aac")) { 340 aRole.Assign("audio_decoder.aac"); 341 return true; 342 } 343 return false; 344 } 345 346 /* static */ 347 bool PureOmxPlatformLayer::FindStandardComponent(const nsACString& aMimeType, 348 nsACString* aComponentName) { 349 nsAutoCString role; 350 if (!GetStandardComponentRole(aMimeType, role)) return false; 351 352 OMX_U32 nComponents = 0; 353 OMX_ERRORTYPE err; 354 err = OMX_GetComponentsOfRole(const_cast<OMX_STRING>(role.Data()), 355 &nComponents, nullptr); 356 if (err != OMX_ErrorNone || nComponents <= 0) { 357 return false; 358 } 359 if (!aComponentName) { 360 return true; 361 } 362 363 // TODO: 364 // Only the first component will be used. 365 // We should detect the most preferred component. 366 OMX_U8* componentNames[1]; 367 UniquePtr<OMX_U8[]> componentName; 368 componentName = MakeUniqueFallible<OMX_U8[]>(OMX_MAX_STRINGNAME_SIZE); 369 componentNames[0] = componentName.get(); 370 nComponents = 1; 371 err = OMX_GetComponentsOfRole(const_cast<OMX_STRING>(role.Data()), 372 &nComponents, componentNames); 373 if (err == OMX_ErrorNone) { 374 MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, 375 ("PureOmxPlatformLayer::%s: A component has been found for %s: %s", 376 __func__, aMimeType.Data(), componentNames[0])); 377 aComponentName->Assign(reinterpret_cast<char*>(componentNames[0])); 378 } 379 380 return err == OMX_ErrorNone; 381 } 382 383 OMX_ERRORTYPE 384 PureOmxPlatformLayer::CreateComponent(const nsACString* aComponentName) { 385 nsAutoCString componentName; 386 if (aComponentName) { 387 componentName = *aComponentName; 388 } else if (!FindStandardComponent(mInfo->mMimeType, &componentName)) { 389 return OMX_ErrorComponentNotFound; 390 } 391 392 OMX_ERRORTYPE err; 393 err = OMX_GetHandle(&mComponent, const_cast<OMX_STRING>(componentName.Data()), 394 this, &sCallbacks); 395 396 const char* mime = mInfo->mMimeType.Data(); 397 if (err == OMX_ErrorNone) { 398 LOG("Succeeded to create the component for %s", mime); 399 } else { 400 LOG("Failed to create the component for %s: 0x%08x", mime, err); 401 } 402 403 return err; 404 } 405 406 } // namespace mozilla