tor-browser

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

OmxPlatformLayer.cpp (10113B)


      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 "OmxPlatformLayer.h"
      8 
      9 #include "OMX_Component.h"
     10 #include "OMX_VideoExt.h"  // For VP8.
     11 #include "OmxDataDecoder.h"
     12 
     13 #ifdef MOZ_OMX
     14 #  include "PureOmxPlatformLayer.h"
     15 #endif
     16 
     17 #include "VPXDecoder.h"
     18 
     19 #ifdef LOG
     20 #  undef LOG
     21 #endif
     22 
     23 #define LOG(arg, ...)                        \
     24  MOZ_LOG(sPDMLog, mozilla::LogLevel::Debug, \
     25          ("OmxPlatformLayer -- %s: " arg, __func__, ##__VA_ARGS__))
     26 
     27 #define RETURN_IF_ERR(err)     \
     28  if (err != OMX_ErrorNone) {  \
     29    LOG("error: 0x%08x", err); \
     30    return err;                \
     31  }
     32 
     33 // Common OMX decoder configuration code.
     34 namespace mozilla {
     35 
     36 // This helper class encapsulates the details of component parameters setting
     37 // for different OMX audio & video codecs.
     38 template <typename ParamType>
     39 class OmxConfig {
     40 public:
     41  virtual ~OmxConfig() = default;
     42  // Subclasses should implement this method to configure the codec.
     43  virtual OMX_ERRORTYPE Apply(OmxPlatformLayer& aOmx,
     44                              const ParamType& aParam) = 0;
     45 };
     46 
     47 typedef OmxConfig<AudioInfo> OmxAudioConfig;
     48 typedef OmxConfig<VideoInfo> OmxVideoConfig;
     49 
     50 template <typename ConfigType>
     51 UniquePtr<ConfigType> ConfigForMime(const nsACString&);
     52 
     53 static OMX_ERRORTYPE ConfigAudioOutputPort(OmxPlatformLayer& aOmx,
     54                                           const AudioInfo& aInfo) {
     55  OMX_PARAM_PORTDEFINITIONTYPE def;
     56  InitOmxParameter(&def);
     57  def.nPortIndex = aOmx.OutputPortIndex();
     58  OMX_ERRORTYPE err =
     59      aOmx.GetParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
     60  RETURN_IF_ERR(err);
     61 
     62  def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
     63  err = aOmx.SetParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
     64  RETURN_IF_ERR(err);
     65 
     66  OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
     67  InitOmxParameter(&pcmParams);
     68  pcmParams.nPortIndex = def.nPortIndex;
     69  err =
     70      aOmx.GetParameter(OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
     71  RETURN_IF_ERR(err);
     72 
     73  pcmParams.nChannels = aInfo.mChannels;
     74  pcmParams.eNumData = OMX_NumericalDataSigned;
     75  pcmParams.bInterleaved = OMX_TRUE;
     76  pcmParams.nBitPerSample = 16;
     77  pcmParams.nSamplingRate = aInfo.mRate;
     78  pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
     79  err =
     80      aOmx.SetParameter(OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
     81  RETURN_IF_ERR(err);
     82 
     83  LOG("Config OMX_IndexParamAudioPcm, channel %lu, sample rate %lu",
     84      pcmParams.nChannels, pcmParams.nSamplingRate);
     85 
     86  return OMX_ErrorNone;
     87 }
     88 
     89 class OmxAacConfig : public OmxAudioConfig {
     90 public:
     91  OMX_ERRORTYPE Apply(OmxPlatformLayer& aOmx, const AudioInfo& aInfo) override {
     92    OMX_AUDIO_PARAM_AACPROFILETYPE aacProfile;
     93    InitOmxParameter(&aacProfile);
     94    aacProfile.nPortIndex = aOmx.InputPortIndex();
     95    OMX_ERRORTYPE err = aOmx.GetParameter(OMX_IndexParamAudioAac, &aacProfile,
     96                                          sizeof(aacProfile));
     97    RETURN_IF_ERR(err);
     98 
     99    aacProfile.nChannels = aInfo.mChannels;
    100    aacProfile.nSampleRate = aInfo.mRate;
    101    aacProfile.eAACProfile =
    102        static_cast<OMX_AUDIO_AACPROFILETYPE>(aInfo.mProfile);
    103    err = aOmx.SetParameter(OMX_IndexParamAudioAac, &aacProfile,
    104                            sizeof(aacProfile));
    105    RETURN_IF_ERR(err);
    106 
    107    LOG("Config OMX_IndexParamAudioAac, channel %lu, sample rate %lu, profile "
    108        "%d",
    109        aacProfile.nChannels, aacProfile.nSampleRate, aacProfile.eAACProfile);
    110 
    111    return ConfigAudioOutputPort(aOmx, aInfo);
    112  }
    113 };
    114 
    115 class OmxMp3Config : public OmxAudioConfig {
    116 public:
    117  OMX_ERRORTYPE Apply(OmxPlatformLayer& aOmx, const AudioInfo& aInfo) override {
    118    OMX_AUDIO_PARAM_MP3TYPE mp3Param;
    119    InitOmxParameter(&mp3Param);
    120    mp3Param.nPortIndex = aOmx.InputPortIndex();
    121    OMX_ERRORTYPE err =
    122        aOmx.GetParameter(OMX_IndexParamAudioMp3, &mp3Param, sizeof(mp3Param));
    123    RETURN_IF_ERR(err);
    124 
    125    mp3Param.nChannels = aInfo.mChannels;
    126    mp3Param.nSampleRate = aInfo.mRate;
    127    err =
    128        aOmx.SetParameter(OMX_IndexParamAudioMp3, &mp3Param, sizeof(mp3Param));
    129    RETURN_IF_ERR(err);
    130 
    131    LOG("Config OMX_IndexParamAudioMp3, channel %lu, sample rate %lu",
    132        mp3Param.nChannels, mp3Param.nSampleRate);
    133 
    134    return ConfigAudioOutputPort(aOmx, aInfo);
    135  }
    136 };
    137 
    138 enum OmxAmrSampleRate {
    139  kNarrowBand = 8000,
    140  kWideBand = 16000,
    141 };
    142 
    143 template <OmxAmrSampleRate R>
    144 class OmxAmrConfig : public OmxAudioConfig {
    145 public:
    146  OMX_ERRORTYPE Apply(OmxPlatformLayer& aOmx, const AudioInfo& aInfo) override {
    147    OMX_AUDIO_PARAM_AMRTYPE def;
    148    InitOmxParameter(&def);
    149    def.nPortIndex = aOmx.InputPortIndex();
    150    OMX_ERRORTYPE err =
    151        aOmx.GetParameter(OMX_IndexParamAudioAmr, &def, sizeof(def));
    152    RETURN_IF_ERR(err);
    153 
    154    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
    155    err = aOmx.SetParameter(OMX_IndexParamAudioAmr, &def, sizeof(def));
    156    RETURN_IF_ERR(err);
    157 
    158    MOZ_ASSERT(aInfo.mChannels == 1);
    159    MOZ_ASSERT(aInfo.mRate == R);
    160 
    161    return ConfigAudioOutputPort(aOmx, aInfo);
    162  }
    163 };
    164 
    165 template <>
    166 UniquePtr<OmxAudioConfig> ConfigForMime(const nsACString& aMimeType) {
    167  UniquePtr<OmxAudioConfig> conf;
    168 
    169  if (OmxPlatformLayer::SupportsMimeType(aMimeType)) {
    170    if (aMimeType.EqualsLiteral("audio/mp4a-latm")) {
    171      conf.reset(new OmxAacConfig());
    172    } else if (aMimeType.EqualsLiteral("audio/mp3") ||
    173               aMimeType.EqualsLiteral("audio/mpeg")) {
    174      conf.reset(new OmxMp3Config());
    175    } else if (aMimeType.EqualsLiteral("audio/3gpp")) {
    176      conf.reset(new OmxAmrConfig<OmxAmrSampleRate::kNarrowBand>());
    177    } else if (aMimeType.EqualsLiteral("audio/amr-wb")) {
    178      conf.reset(new OmxAmrConfig<OmxAmrSampleRate::kWideBand>());
    179    }
    180  }
    181  return conf;
    182 }
    183 
    184 // There should be a better way to calculate it.
    185 #define MIN_VIDEO_INPUT_BUFFER_SIZE 64 * 1024
    186 
    187 class OmxCommonVideoConfig : public OmxVideoConfig {
    188 public:
    189  explicit OmxCommonVideoConfig() : OmxVideoConfig() {}
    190 
    191  OMX_ERRORTYPE Apply(OmxPlatformLayer& aOmx, const VideoInfo& aInfo) override {
    192    OMX_ERRORTYPE err = OMX_ErrorNone;
    193    OMX_PARAM_PORTDEFINITIONTYPE def;
    194 
    195    // Set up in/out port definition.
    196    nsTArray<uint32_t> ports;
    197    aOmx.GetPortIndices(ports);
    198    for (auto idx : ports) {
    199      InitOmxParameter(&def);
    200      def.nPortIndex = idx;
    201      err = aOmx.GetParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
    202      RETURN_IF_ERR(err);
    203 
    204      def.format.video.nFrameWidth = aInfo.mDisplay.width;
    205      def.format.video.nFrameHeight = aInfo.mDisplay.height;
    206      def.format.video.nStride = aInfo.mImage.width;
    207      def.format.video.nSliceHeight = aInfo.mImage.height;
    208 
    209      if (def.eDir == OMX_DirInput) {
    210        def.format.video.eCompressionFormat = aOmx.CompressionFormat();
    211        def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
    212        if (def.nBufferSize < MIN_VIDEO_INPUT_BUFFER_SIZE) {
    213          def.nBufferSize = aInfo.mImage.width * aInfo.mImage.height;
    214          LOG("Change input buffer size to %lu", def.nBufferSize);
    215        }
    216      } else {
    217        def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
    218      }
    219 
    220      err = aOmx.SetParameter(OMX_IndexParamPortDefinition, &def, sizeof(def));
    221    }
    222    return err;
    223  }
    224 };
    225 
    226 template <>
    227 UniquePtr<OmxVideoConfig> ConfigForMime(const nsACString& aMimeType) {
    228  UniquePtr<OmxVideoConfig> conf;
    229 
    230  if (OmxPlatformLayer::SupportsMimeType(aMimeType)) {
    231    conf.reset(new OmxCommonVideoConfig());
    232  }
    233  return conf;
    234 }
    235 
    236 OMX_ERRORTYPE
    237 OmxPlatformLayer::Config() {
    238  MOZ_ASSERT(mInfo);
    239 
    240  OMX_PORT_PARAM_TYPE portParam;
    241  InitOmxParameter(&portParam);
    242  if (mInfo->IsAudio()) {
    243    GetParameter(OMX_IndexParamAudioInit, &portParam, sizeof(portParam));
    244    mStartPortNumber = portParam.nStartPortNumber;
    245    UniquePtr<OmxAudioConfig> conf(
    246        ConfigForMime<OmxAudioConfig>(mInfo->mMimeType));
    247    MOZ_RELEASE_ASSERT(conf.get());
    248    return conf->Apply(*this, *(mInfo->GetAsAudioInfo()));
    249  } else if (mInfo->IsVideo()) {
    250    GetParameter(OMX_IndexParamVideoInit, &portParam, sizeof(portParam));
    251    UniquePtr<OmxVideoConfig> conf(
    252        ConfigForMime<OmxVideoConfig>(mInfo->mMimeType));
    253    MOZ_RELEASE_ASSERT(conf.get());
    254    return conf->Apply(*this, *(mInfo->GetAsVideoInfo()));
    255  } else {
    256    MOZ_ASSERT_UNREACHABLE("non-AV data (text?) is not supported.");
    257    return OMX_ErrorNotImplemented;
    258  }
    259 }
    260 
    261 OMX_VIDEO_CODINGTYPE
    262 OmxPlatformLayer::CompressionFormat() {
    263  MOZ_ASSERT(mInfo);
    264 
    265  if (mInfo->mMimeType.EqualsLiteral("video/avc")) {
    266    return OMX_VIDEO_CodingAVC;
    267  } else if (mInfo->mMimeType.EqualsLiteral("video/mp4v-es") ||
    268             mInfo->mMimeType.EqualsLiteral("video/mp4")) {
    269    return OMX_VIDEO_CodingMPEG4;
    270  } else if (mInfo->mMimeType.EqualsLiteral("video/3gpp")) {
    271    return OMX_VIDEO_CodingH263;
    272  } else if (VPXDecoder::IsVP8(mInfo->mMimeType)) {
    273    return static_cast<OMX_VIDEO_CODINGTYPE>(OMX_VIDEO_CodingVP8);
    274  } else {
    275    MOZ_ASSERT_UNREACHABLE("Unsupported compression format");
    276    return OMX_VIDEO_CodingUnused;
    277  }
    278 }
    279 
    280 // Implementations for different platforms will be defined in their own files.
    281 #if defined(MOZ_OMX)
    282 
    283 bool OmxPlatformLayer::SupportsMimeType(const nsACString& aMimeType) {
    284  return PureOmxPlatformLayer::SupportsMimeType(aMimeType);
    285 }
    286 
    287 OmxPlatformLayer* OmxPlatformLayer::Create(
    288    OmxDataDecoder* aDataDecoder, OmxPromiseLayer* aPromiseLayer,
    289    TaskQueue* aTaskQueue, layers::ImageContainer* aImageContainer) {
    290  return new PureOmxPlatformLayer(aDataDecoder, aPromiseLayer, aTaskQueue,
    291                                  aImageContainer);
    292 }
    293 
    294 #else  // For platforms without OMX IL support.
    295 
    296 bool OmxPlatformLayer::SupportsMimeType(const nsACString& aMimeType) {
    297  return false;
    298 }
    299 
    300 OmxPlatformLayer* OmxPlatformLayer::Create(
    301    OmxDataDecoder* aDataDecoder, OmxPromiseLayer* aPromiseLayer,
    302    TaskQueue* aTaskQueue, layers::ImageContainer* aImageContainer) {
    303  return nullptr;
    304 }
    305 
    306 #endif
    307 }  // namespace mozilla