tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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