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
|