tor-browser

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

OmxPromiseLayer.cpp (12115B)


      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 "OmxPromiseLayer.h"
      8 
      9 #include "ImageContainer.h"
     10 #include "OmxDataDecoder.h"
     11 #include "OmxPlatformLayer.h"
     12 
     13 #ifdef LOG
     14 #  undef LOG
     15 #endif
     16 
     17 #define LOG(arg, ...)                        \
     18  MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, \
     19          ("OmxPromiseLayer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
     20 
     21 namespace mozilla {
     22 
     23 OmxPromiseLayer::OmxPromiseLayer(TaskQueue* aTaskQueue,
     24                                 OmxDataDecoder* aDataDecoder,
     25                                 layers::ImageContainer* aImageContainer)
     26    : mTaskQueue(aTaskQueue) {
     27  mPlatformLayer.reset(OmxPlatformLayer::Create(aDataDecoder, this, aTaskQueue,
     28                                                aImageContainer));
     29  MOZ_ASSERT(!!mPlatformLayer);
     30 }
     31 
     32 RefPtr<OmxPromiseLayer::OmxCommandPromise> OmxPromiseLayer::Init(
     33    const TrackInfo* aInfo) {
     34  MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     35 
     36  OMX_ERRORTYPE err = mPlatformLayer->InitOmxToStateLoaded(aInfo);
     37  if (err != OMX_ErrorNone) {
     38    OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandStateSet);
     39    return OmxCommandPromise::CreateAndReject(failure, __func__);
     40  }
     41 
     42  OMX_STATETYPE state = GetState();
     43  if (state == OMX_StateLoaded) {
     44    return OmxCommandPromise::CreateAndResolve(OMX_CommandStateSet, __func__);
     45  }
     46  if (state == OMX_StateIdle) {
     47    return SendCommand(OMX_CommandStateSet, OMX_StateIdle, nullptr);
     48  }
     49 
     50  OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandStateSet);
     51  return OmxCommandPromise::CreateAndReject(failure, __func__);
     52 }
     53 
     54 OMX_ERRORTYPE
     55 OmxPromiseLayer::Config() {
     56  MOZ_ASSERT(GetState() == OMX_StateLoaded);
     57 
     58  return mPlatformLayer->Config();
     59 }
     60 
     61 RefPtr<OmxPromiseLayer::OmxBufferPromise> OmxPromiseLayer::FillBuffer(
     62    BufferData* aData) {
     63  MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     64  LOG("buffer %p", aData->mBuffer);
     65 
     66  RefPtr<OmxBufferPromise> p = aData->mPromise.Ensure(__func__);
     67 
     68  OMX_ERRORTYPE err = mPlatformLayer->FillThisBuffer(aData);
     69 
     70  if (err != OMX_ErrorNone) {
     71    OmxBufferFailureHolder failure(err, aData);
     72    aData->mPromise.Reject(std::move(failure), __func__);
     73  } else {
     74    aData->mStatus = BufferData::BufferStatus::OMX_COMPONENT;
     75    GetBufferHolders(OMX_DirOutput)->AppendElement(aData);
     76  }
     77 
     78  return p;
     79 }
     80 
     81 RefPtr<OmxPromiseLayer::OmxBufferPromise> OmxPromiseLayer::EmptyBuffer(
     82    BufferData* aData) {
     83  MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
     84  LOG("buffer %p, size %lu", aData->mBuffer, aData->mBuffer->nFilledLen);
     85 
     86  RefPtr<OmxBufferPromise> p = aData->mPromise.Ensure(__func__);
     87 
     88  OMX_ERRORTYPE err = mPlatformLayer->EmptyThisBuffer(aData);
     89 
     90  if (err != OMX_ErrorNone) {
     91    OmxBufferFailureHolder failure(err, aData);
     92    aData->mPromise.Reject(std::move(failure), __func__);
     93  } else {
     94    if (aData->mRawData) {
     95      mRawDatas.AppendElement(std::move(aData->mRawData));
     96    }
     97    aData->mStatus = BufferData::BufferStatus::OMX_COMPONENT;
     98    GetBufferHolders(OMX_DirInput)->AppendElement(aData);
     99  }
    100 
    101  return p;
    102 }
    103 
    104 OmxPromiseLayer::BUFFERLIST* OmxPromiseLayer::GetBufferHolders(
    105    OMX_DIRTYPE aType) {
    106  MOZ_ASSERT(aType == OMX_DirInput || aType == OMX_DirOutput);
    107 
    108  if (aType == OMX_DirInput) {
    109    return &mInbufferHolders;
    110  }
    111 
    112  return &mOutbufferHolders;
    113 }
    114 
    115 already_AddRefed<MediaRawData> OmxPromiseLayer::FindAndRemoveRawData(
    116    OMX_TICKS aTimecode) {
    117  for (auto raw : mRawDatas) {
    118    if (raw->mTime.ToMicroseconds() == aTimecode) {
    119      mRawDatas.RemoveElement(raw);
    120      return raw.forget();
    121    }
    122  }
    123  return nullptr;
    124 }
    125 
    126 already_AddRefed<BufferData> OmxPromiseLayer::FindAndRemoveBufferHolder(
    127    OMX_DIRTYPE aType, BufferData::BufferID aId) {
    128  MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
    129 
    130  RefPtr<BufferData> holder;
    131  BUFFERLIST* holders = GetBufferHolders(aType);
    132 
    133  for (uint32_t i = 0; i < holders->Length(); i++) {
    134    if (holders->ElementAt(i)->ID() == aId) {
    135      holder = holders->ElementAt(i);
    136      holders->RemoveElementAt(i);
    137      return holder.forget();
    138    }
    139  }
    140 
    141  return nullptr;
    142 }
    143 
    144 already_AddRefed<BufferData> OmxPromiseLayer::FindBufferById(
    145    OMX_DIRTYPE aType, BufferData::BufferID aId) {
    146  MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
    147 
    148  RefPtr<BufferData> holder;
    149  BUFFERLIST* holders = GetBufferHolders(aType);
    150 
    151  for (uint32_t i = 0; i < holders->Length(); i++) {
    152    if (holders->ElementAt(i)->ID() == aId) {
    153      holder = holders->ElementAt(i);
    154      return holder.forget();
    155    }
    156  }
    157 
    158  return nullptr;
    159 }
    160 
    161 void OmxPromiseLayer::EmptyFillBufferDone(OMX_DIRTYPE aType,
    162                                          BufferData* aData) {
    163  if (aData) {
    164    LOG("type %d, buffer %p", aType, aData->mBuffer);
    165    if (aType == OMX_DirOutput) {
    166      aData->mRawData = nullptr;
    167      aData->mRawData = FindAndRemoveRawData(aData->mBuffer->nTimeStamp);
    168    }
    169    aData->mStatus = BufferData::BufferStatus::OMX_CLIENT;
    170    aData->mPromise.Resolve(aData, __func__);
    171  } else {
    172    LOG("type %d, no buffer", aType);
    173  }
    174 }
    175 
    176 void OmxPromiseLayer::EmptyFillBufferDone(OMX_DIRTYPE aType,
    177                                          BufferData::BufferID aID) {
    178  RefPtr<BufferData> holder = FindAndRemoveBufferHolder(aType, aID);
    179  EmptyFillBufferDone(aType, holder);
    180 }
    181 
    182 RefPtr<OmxPromiseLayer::OmxCommandPromise> OmxPromiseLayer::SendCommand(
    183    OMX_COMMANDTYPE aCmd, OMX_U32 aParam1, OMX_PTR aCmdData) {
    184  if (aCmd == OMX_CommandFlush) {
    185    // It doesn't support another flush commands before previous one is
    186    // completed.
    187    MOZ_RELEASE_ASSERT(!mFlushCommands.Length());
    188 
    189    // Some coomponents don't send event with OMX_ALL, they send flush complete
    190    // event with input port and another event for output port.
    191    // In prupose of better compatibility, we interpret the OMX_ALL to
    192    // OMX_DirInput and OMX_DirOutput flush separately.
    193    OMX_DIRTYPE types[] = {OMX_DIRTYPE::OMX_DirInput,
    194                           OMX_DIRTYPE::OMX_DirOutput};
    195    for (const auto type : types) {
    196      if ((aParam1 == type) || (aParam1 == OMX_ALL)) {
    197        mFlushCommands.AppendElement(FlushCommand({type, aCmdData}));
    198      }
    199 
    200      if (type == OMX_DirInput) {
    201        // Clear all buffered raw data.
    202        mRawDatas.Clear();
    203      }
    204    }
    205 
    206    // Don't overlay more than one flush command, some components can't overlay
    207    // flush commands. So here we send another flush after receiving the
    208    // previous flush completed event.
    209    if (mFlushCommands.Length()) {
    210      OMX_ERRORTYPE err = mPlatformLayer->SendCommand(
    211          OMX_CommandFlush, mFlushCommands.ElementAt(0).type,
    212          mFlushCommands.ElementAt(0).cmd);
    213      if (err != OMX_ErrorNone) {
    214        OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
    215        return OmxCommandPromise::CreateAndReject(failure, __func__);
    216      }
    217    } else {
    218      LOG("OMX_CommandFlush parameter error");
    219      OmxCommandFailureHolder failure(OMX_ErrorNotReady, OMX_CommandFlush);
    220      return OmxCommandPromise::CreateAndReject(failure, __func__);
    221    }
    222  } else {
    223    OMX_ERRORTYPE err = mPlatformLayer->SendCommand(aCmd, aParam1, aCmdData);
    224    if (err != OMX_ErrorNone) {
    225      OmxCommandFailureHolder failure(OMX_ErrorNotReady, aCmd);
    226      return OmxCommandPromise::CreateAndReject(failure, __func__);
    227    }
    228  }
    229 
    230  RefPtr<OmxCommandPromise> p;
    231  if (aCmd == OMX_CommandStateSet) {
    232    p = mCommandStatePromise.Ensure(__func__);
    233  } else if (aCmd == OMX_CommandFlush) {
    234    p = mFlushPromise.Ensure(__func__);
    235  } else if (aCmd == OMX_CommandPortEnable) {
    236    p = mPortEnablePromise.Ensure(__func__);
    237  } else if (aCmd == OMX_CommandPortDisable) {
    238    p = mPortDisablePromise.Ensure(__func__);
    239  } else {
    240    LOG("error unsupport command");
    241    MOZ_ASSERT(0);
    242  }
    243 
    244  return p;
    245 }
    246 
    247 bool OmxPromiseLayer::Event(OMX_EVENTTYPE aEvent, OMX_U32 aData1,
    248                            OMX_U32 aData2) {
    249  OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE)aData1;
    250  switch (aEvent) {
    251    case OMX_EventCmdComplete: {
    252      if (cmd == OMX_CommandStateSet) {
    253        mCommandStatePromise.Resolve(OMX_CommandStateSet, __func__);
    254      } else if (cmd == OMX_CommandFlush) {
    255        MOZ_RELEASE_ASSERT(mFlushCommands.ElementAt(0).type == aData2);
    256        LOG("OMX_CommandFlush completed port type %lu", aData2);
    257        mFlushCommands.RemoveElementAt(0);
    258 
    259        // Sending next flush command.
    260        if (mFlushCommands.Length()) {
    261          OMX_ERRORTYPE err = mPlatformLayer->SendCommand(
    262              OMX_CommandFlush, mFlushCommands.ElementAt(0).type,
    263              mFlushCommands.ElementAt(0).cmd);
    264          if (err != OMX_ErrorNone) {
    265            OmxCommandFailureHolder failure(OMX_ErrorNotReady,
    266                                            OMX_CommandFlush);
    267            mFlushPromise.Reject(failure, __func__);
    268          }
    269        } else {
    270          mFlushPromise.Resolve(OMX_CommandFlush, __func__);
    271        }
    272      } else if (cmd == OMX_CommandPortDisable) {
    273        mPortDisablePromise.Resolve(OMX_CommandPortDisable, __func__);
    274      } else if (cmd == OMX_CommandPortEnable) {
    275        mPortEnablePromise.Resolve(OMX_CommandPortEnable, __func__);
    276      }
    277      break;
    278    }
    279    case OMX_EventError: {
    280      if (cmd == OMX_CommandStateSet) {
    281        OmxCommandFailureHolder failure(OMX_ErrorUndefined,
    282                                        OMX_CommandStateSet);
    283        mCommandStatePromise.Reject(failure, __func__);
    284      } else if (cmd == OMX_CommandFlush) {
    285        OmxCommandFailureHolder failure(OMX_ErrorUndefined, OMX_CommandFlush);
    286        mFlushPromise.Reject(failure, __func__);
    287      } else if (cmd == OMX_CommandPortDisable) {
    288        OmxCommandFailureHolder failure(OMX_ErrorUndefined,
    289                                        OMX_CommandPortDisable);
    290        mPortDisablePromise.Reject(failure, __func__);
    291      } else if (cmd == OMX_CommandPortEnable) {
    292        OmxCommandFailureHolder failure(OMX_ErrorUndefined,
    293                                        OMX_CommandPortEnable);
    294        mPortEnablePromise.Reject(failure, __func__);
    295      } else {
    296        return false;
    297      }
    298      break;
    299    }
    300    default: {
    301      return false;
    302    }
    303  }
    304  return true;
    305 }
    306 
    307 nsresult OmxPromiseLayer::AllocateOmxBuffer(OMX_DIRTYPE aType,
    308                                            BUFFERLIST* aBuffers) {
    309  return mPlatformLayer->AllocateOmxBuffer(aType, aBuffers);
    310 }
    311 
    312 nsresult OmxPromiseLayer::ReleaseOmxBuffer(OMX_DIRTYPE aType,
    313                                           BUFFERLIST* aBuffers) {
    314  return mPlatformLayer->ReleaseOmxBuffer(aType, aBuffers);
    315 }
    316 
    317 OMX_STATETYPE
    318 OmxPromiseLayer::GetState() {
    319  OMX_STATETYPE state;
    320  OMX_ERRORTYPE err = mPlatformLayer->GetState(&state);
    321  return err == OMX_ErrorNone ? state : OMX_StateInvalid;
    322 }
    323 
    324 OMX_ERRORTYPE
    325 OmxPromiseLayer::GetParameter(OMX_INDEXTYPE aParamIndex,
    326                              OMX_PTR aComponentParameterStructure,
    327                              OMX_U32 aComponentParameterSize) {
    328  return mPlatformLayer->GetParameter(aParamIndex, aComponentParameterStructure,
    329                                      aComponentParameterSize);
    330 }
    331 
    332 OMX_ERRORTYPE
    333 OmxPromiseLayer::SetParameter(OMX_INDEXTYPE aParamIndex,
    334                              OMX_PTR aComponentParameterStructure,
    335                              OMX_U32 aComponentParameterSize) {
    336  return mPlatformLayer->SetParameter(aParamIndex, aComponentParameterStructure,
    337                                      aComponentParameterSize);
    338 }
    339 
    340 OMX_U32
    341 OmxPromiseLayer::InputPortIndex() { return mPlatformLayer->InputPortIndex(); }
    342 
    343 OMX_U32
    344 OmxPromiseLayer::OutputPortIndex() { return mPlatformLayer->OutputPortIndex(); }
    345 
    346 nsresult OmxPromiseLayer::Shutdown() {
    347  LOG("");
    348  MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
    349  MOZ_ASSERT(!GetBufferHolders(OMX_DirInput)->Length());
    350  MOZ_ASSERT(!GetBufferHolders(OMX_DirOutput)->Length());
    351  return mPlatformLayer->Shutdown();
    352 }
    353 
    354 }  // namespace mozilla