tor-browser

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

MFMediaEngineAudioStream.cpp (5328B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "MFMediaEngineAudioStream.h"
      6 
      7 #include <mfapi.h>
      8 #include <mferror.h>
      9 
     10 #include "MFMediaEngineUtils.h"
     11 #include "WMFUtils.h"
     12 #include "mozilla/StaticPrefs_media.h"
     13 
     14 namespace mozilla {
     15 
     16 #define LOG(msg, ...)                           \
     17  MOZ_LOG(gMFMediaEngineLog, LogLevel::Debug,   \
     18          ("MFMediaStream=%p (%s), " msg, this, \
     19           this->GetDescriptionName().get(), ##__VA_ARGS__))
     20 
     21 using Microsoft::WRL::ComPtr;
     22 using Microsoft::WRL::MakeAndInitialize;
     23 
     24 /* static */
     25 MFMediaEngineAudioStream* MFMediaEngineAudioStream::Create(
     26    uint64_t aStreamId, const TrackInfo& aInfo, bool aIsEncryptedCustomInit,
     27    MFMediaSource* aParentSource) {
     28  MOZ_ASSERT(aInfo.IsAudio());
     29  MFMediaEngineAudioStream* stream;
     30  if (FAILED(MakeAndInitialize<MFMediaEngineAudioStream>(
     31          &stream, aStreamId, aInfo, aIsEncryptedCustomInit, aParentSource))) {
     32    return nullptr;
     33  }
     34  return stream;
     35 }
     36 
     37 HRESULT MFMediaEngineAudioStream::CreateMediaType(const TrackInfo& aInfo,
     38                                                  IMFMediaType** aMediaType) {
     39  const AudioInfo& info = *aInfo.GetAsAudioInfo();
     40  mAudioInfo = info;
     41  GUID subType = AudioMimeTypeToMediaFoundationSubtype(info.mMimeType);
     42  NS_ENSURE_TRUE(subType != GUID_NULL, MF_E_TOPO_CODEC_NOT_FOUND);
     43 
     44  // https://docs.microsoft.com/en-us/windows/win32/medfound/media-type-attributes
     45  ComPtr<IMFMediaType> mediaType;
     46  RETURN_IF_FAILED(wmf::MFCreateMediaType(&mediaType));
     47  RETURN_IF_FAILED(mediaType->SetGUID(MF_MT_SUBTYPE, subType));
     48  RETURN_IF_FAILED(mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
     49  RETURN_IF_FAILED(
     50      mediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, info.mChannels));
     51  RETURN_IF_FAILED(
     52      mediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, info.mRate));
     53  uint64_t bitDepth = info.mBitDepth != 0 ? info.mBitDepth : 16;
     54  RETURN_IF_FAILED(mediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bitDepth));
     55  if (subType == MFAudioFormat_AAC) {
     56    if (mAACUserData.IsEmpty()) {
     57      MOZ_ASSERT(info.mCodecSpecificConfig.is<AacCodecSpecificData>() ||
     58                 info.mCodecSpecificConfig.is<AudioCodecSpecificBinaryBlob>());
     59      RefPtr<MediaByteBuffer> blob;
     60      if (info.mCodecSpecificConfig.is<AacCodecSpecificData>()) {
     61        blob = info.mCodecSpecificConfig.as<AacCodecSpecificData>()
     62                   .mDecoderConfigDescriptorBinaryBlob;
     63      } else {
     64        blob = info.mCodecSpecificConfig.as<AudioCodecSpecificBinaryBlob>()
     65                   .mBinaryBlob;
     66      }
     67      AACAudioSpecificConfigToUserData(info.mExtendedProfile, blob->Elements(),
     68                                       blob->Length(), mAACUserData);
     69      LOG("Generated AAC user data");
     70    }
     71    RETURN_IF_FAILED(
     72        mediaType->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0x0));  // Raw AAC packet
     73    RETURN_IF_FAILED(mediaType->SetBlob(
     74        MF_MT_USER_DATA, mAACUserData.Elements(), mAACUserData.Length()));
     75  }
     76  LOG("Created audio type, subtype=%s, channel=%" PRIu32 ", rate=%" PRIu32
     77      ", bitDepth=%" PRIu64 ", encrypted=%d",
     78      GUIDToStr(subType), info.mChannels, info.mRate, bitDepth,
     79      mAudioInfo.mCrypto.IsEncrypted());
     80 
     81  if (IsEncrypted()) {
     82    ComPtr<IMFMediaType> protectedMediaType;
     83    RETURN_IF_FAILED(wmf::MFWrapMediaType(mediaType.Get(),
     84                                          MFMediaType_Protected, subType,
     85                                          protectedMediaType.GetAddressOf()));
     86    LOG("Wrap MFMediaType_Audio into MFMediaType_Protected");
     87    *aMediaType = protectedMediaType.Detach();
     88  } else {
     89    *aMediaType = mediaType.Detach();
     90  }
     91  return S_OK;
     92 }
     93 
     94 bool MFMediaEngineAudioStream::HasEnoughRawData() const {
     95  // If more than this much raw audio is queued, we'll hold off request more
     96  // audio.
     97  return mRawDataQueueForFeedingEngine.PreciseDuration() >=
     98         StaticPrefs::media_wmf_media_engine_raw_data_threshold_audio();
     99 }
    100 
    101 already_AddRefed<MediaData> MFMediaEngineAudioStream::OutputDataInternal() {
    102  AssertOnTaskQueue();
    103  if (mRawDataQueueForGeneratingOutput.GetSize() == 0) {
    104    return nullptr;
    105  }
    106  // The media engine doesn't provide a way to allow us to access decoded audio
    107  // frames, and the audio playback will be handled internally inside the media
    108  // engine. So we simply return fake audio data.
    109  RefPtr<MediaRawData> input = mRawDataQueueForGeneratingOutput.PopFront();
    110  RefPtr<MediaData> output =
    111      new AudioData(input->mOffset, input->mTime, AlignedAudioBuffer{},
    112                    mAudioInfo.mChannels, mAudioInfo.mRate);
    113  return output.forget();
    114 }
    115 
    116 nsCString MFMediaEngineAudioStream::GetCodecName() const {
    117  WMFStreamType type = GetStreamTypeFromMimeType(mAudioInfo.mMimeType);
    118  switch (type) {
    119    case WMFStreamType::MP3:
    120      return "mp3"_ns;
    121    case WMFStreamType::AAC:
    122      return "aac"_ns;
    123    case WMFStreamType::OPUS:
    124      return "opus"_ns;
    125    case WMFStreamType::VORBIS:
    126      return "vorbis"_ns;
    127    default:
    128      return "unknown"_ns;
    129  }
    130 }
    131 
    132 bool MFMediaEngineAudioStream::IsEncrypted() const {
    133  return mAudioInfo.mCrypto.IsEncrypted() || mIsEncryptedCustomInit;
    134 }
    135 
    136 #undef LOG
    137 
    138 }  // namespace mozilla