summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/wmf/MFMediaEngineAudioStream.cpp
blob: 57de0f8d67a150a2b8fd4cd303da75e524caa434 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "MFMediaEngineAudioStream.h"

#include "MFMediaEngineUtils.h"

namespace mozilla {

#define LOGV(msg, ...)                          \
  MOZ_LOG(gMFMediaEngineLog, LogLevel::Verbose, \
          ("MFMediaStream=%p (%s), " msg, this, \
           this->GetDescriptionName().get(), ##__VA_ARGS__))

using Microsoft::WRL::ComPtr;
using Microsoft::WRL::MakeAndInitialize;

/* static */
MFMediaEngineAudioStream* MFMediaEngineAudioStream::Create(
    uint64_t aStreamId, const TrackInfo& aInfo, MFMediaSource* aParentSource) {
  MOZ_ASSERT(aInfo.IsAudio());
  MFMediaEngineAudioStream* stream;
  if (FAILED(MakeAndInitialize<MFMediaEngineAudioStream>(
          &stream, aStreamId, aInfo, aParentSource))) {
    return nullptr;
  }
  return stream;
}

HRESULT MFMediaEngineAudioStream::CreateMediaType(const TrackInfo& aInfo,
                                                  IMFMediaType** aMediaType) {
  const AudioInfo& info = *aInfo.GetAsAudioInfo();
  mAudioInfo = info;
  GUID subType = AudioMimeTypeToMediaFoundationSubtype(info.mMimeType);
  NS_ENSURE_TRUE(subType != GUID_NULL, MF_E_TOPO_CODEC_NOT_FOUND);

  // https://docs.microsoft.com/en-us/windows/win32/medfound/media-type-attributes
  ComPtr<IMFMediaType> mediaType;
  RETURN_IF_FAILED(wmf::MFCreateMediaType(&mediaType));
  RETURN_IF_FAILED(mediaType->SetGUID(MF_MT_SUBTYPE, subType));
  RETURN_IF_FAILED(mediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
  RETURN_IF_FAILED(
      mediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, info.mChannels));
  RETURN_IF_FAILED(
      mediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, info.mRate));
  uint64_t bitDepth = info.mBitDepth != 0 ? info.mBitDepth : 16;
  RETURN_IF_FAILED(mediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bitDepth));
  if (subType == MFAudioFormat_AAC) {
    if (mAACUserData.IsEmpty()) {
      MOZ_ASSERT(info.mCodecSpecificConfig.is<AacCodecSpecificData>());
      const auto& blob = info.mCodecSpecificConfig.as<AacCodecSpecificData>()
                             .mDecoderConfigDescriptorBinaryBlob;
      AACAudioSpecificConfigToUserData(info.mExtendedProfile, blob->Elements(),
                                       blob->Length(), mAACUserData);
      LOGV("Generated AAC user data");
    }
    RETURN_IF_FAILED(
        mediaType->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0x0));  // Raw AAC packet
    RETURN_IF_FAILED(mediaType->SetBlob(
        MF_MT_USER_DATA, mAACUserData.Elements(), mAACUserData.Length()));
  }
  LOGV("Created audio type, subtype=%s, channel=%" PRIu32 ", rate=%" PRIu32
       ", bitDepth=%" PRIu64,
       GUIDToStr(subType), info.mChannels, info.mRate, bitDepth);

  *aMediaType = mediaType.Detach();
  return S_OK;
}

bool MFMediaEngineAudioStream::HasEnoughRawData() const {
  // If more than this much raw audio is queued, we'll hold off request more
  // audio.
  return mRawDataQueueForFeedingEngine.Duration() >=
         StaticPrefs::media_wmf_media_engine_raw_data_threshold_audio();
}

already_AddRefed<MediaData> MFMediaEngineAudioStream::OutputDataInternal() {
  AssertOnTaskQueue();
  if (mRawDataQueueForGeneratingOutput.GetSize() == 0) {
    return nullptr;
  }
  // The media engine doesn't provide a way to allow us to access decoded audio
  // frames, and the audio playback will be handled internally inside the media
  // engine. So we simply return fake audio data.
  RefPtr<MediaRawData> input = mRawDataQueueForGeneratingOutput.PopFront();
  RefPtr<MediaData> output =
      new AudioData(input->mOffset, input->mTime, AlignedAudioBuffer{},
                    mAudioInfo.mChannels, mAudioInfo.mRate);
  return output.forget();
}

#undef LOGV

}  // namespace mozilla