forked from mirrors/gecko-dev
CLOSED TREE Backed out changeset 210012222277 (bug 1826761) Backed out changeset e364bb149efa (bug 1826760) Backed out changeset e456e2f9966c (bug 1826759) Backed out changeset 2b6ff545f4a3 (bug 1826758) Backed out changeset 95fe1de8ba00 (bug 1826757) Backed out changeset f8af52d7f2a1 (bug 1826756) Backed out changeset 2646e773f098 (bug 1826754) Backed out changeset 58d5d74b1835 (bug 1826753) Backed out changeset 8567e6595acc (bug 1826752)
123 lines
4.6 KiB
C++
123 lines
4.6 KiB
C++
/* 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>() ||
|
|
info.mCodecSpecificConfig.is<AudioCodecSpecificBinaryBlob>());
|
|
RefPtr<MediaByteBuffer> blob;
|
|
if (info.mCodecSpecificConfig.is<AacCodecSpecificData>()) {
|
|
blob = info.mCodecSpecificConfig.as<AacCodecSpecificData>()
|
|
.mDecoderConfigDescriptorBinaryBlob;
|
|
} else {
|
|
blob = info.mCodecSpecificConfig.as<AudioCodecSpecificBinaryBlob>()
|
|
.mBinaryBlob;
|
|
}
|
|
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 ", encrypted=%d",
|
|
GUIDToStr(subType), info.mChannels, info.mRate, bitDepth,
|
|
mAudioInfo.mCrypto.IsEncrypted());
|
|
|
|
*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();
|
|
}
|
|
|
|
nsCString MFMediaEngineAudioStream::GetCodecName() const {
|
|
WMFStreamType type = GetStreamTypeFromMimeType(mAudioInfo.mMimeType);
|
|
switch (type) {
|
|
case WMFStreamType::MP3:
|
|
return "mp3"_ns;
|
|
case WMFStreamType::AAC:
|
|
return "aac"_ns;
|
|
case WMFStreamType::OPUS:
|
|
return "opus"_ns;
|
|
case WMFStreamType::VORBIS:
|
|
return "vorbis"_ns;
|
|
default:
|
|
return "unknown"_ns;
|
|
}
|
|
}
|
|
|
|
bool MFMediaEngineAudioStream::IsEncrypted() const {
|
|
return mAudioInfo.mCrypto.IsEncrypted();
|
|
}
|
|
|
|
#undef LOGV
|
|
|
|
} // namespace mozilla
|