summaryrefslogtreecommitdiffstats
path: root/dom/media/platforms/wmf
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:33 +0000
commit086c044dc34dfc0f74fbe41f4ecb402b2cd34884 (patch)
treea4f824bd33cb075dd5aa3eb5a0a94af221bbe83a /dom/media/platforms/wmf
parentAdding debian version 124.0.1-1. (diff)
downloadfirefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.tar.xz
firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.zip
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/platforms/wmf')
-rw-r--r--dom/media/platforms/wmf/MFCDMSession.cpp3
-rw-r--r--dom/media/platforms/wmf/MFMediaEngineAudioStream.cpp2
-rw-r--r--dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp16
-rw-r--r--dom/media/platforms/wmf/MFMediaEngineDecoderModule.h2
-rw-r--r--dom/media/platforms/wmf/MFMediaEngineStream.cpp33
-rw-r--r--dom/media/platforms/wmf/MFMediaEngineStream.h8
-rw-r--r--dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp108
-rw-r--r--dom/media/platforms/wmf/MFMediaEngineVideoStream.h27
-rw-r--r--dom/media/platforms/wmf/MFMediaSource.h2
-rw-r--r--dom/media/platforms/wmf/WMFAudioMFTManager.cpp25
-rw-r--r--dom/media/platforms/wmf/WMFAudioMFTManager.h1
-rw-r--r--dom/media/platforms/wmf/WMFMediaDataEncoder.h5
-rw-r--r--dom/media/platforms/wmf/WMFUtils.cpp34
13 files changed, 199 insertions, 67 deletions
diff --git a/dom/media/platforms/wmf/MFCDMSession.cpp b/dom/media/platforms/wmf/MFCDMSession.cpp
index cec783cbc6..b797898abb 100644
--- a/dom/media/platforms/wmf/MFCDMSession.cpp
+++ b/dom/media/platforms/wmf/MFCDMSession.cpp
@@ -304,8 +304,7 @@ void MFCDMSession::OnSessionKeyMessage(
case MF_MEDIAKEYSESSION_MESSAGETYPE_INDIVIDUALIZATION_REQUEST:
return dom::MediaKeyMessageType::Individualization_request;
default:
- MOZ_ASSERT_UNREACHABLE("Unknown session message type");
- return dom::MediaKeyMessageType::EndGuard_;
+ MOZ_CRASH("Unknown session message type");
}
};
LOG("Notify 'keymessage' for %s", NS_ConvertUTF16toUTF8(*mSessionId).get());
diff --git a/dom/media/platforms/wmf/MFMediaEngineAudioStream.cpp b/dom/media/platforms/wmf/MFMediaEngineAudioStream.cpp
index 4acf26e041..969f817882 100644
--- a/dom/media/platforms/wmf/MFMediaEngineAudioStream.cpp
+++ b/dom/media/platforms/wmf/MFMediaEngineAudioStream.cpp
@@ -93,7 +93,7 @@ HRESULT MFMediaEngineAudioStream::CreateMediaType(const TrackInfo& aInfo,
bool MFMediaEngineAudioStream::HasEnoughRawData() const {
// If more than this much raw audio is queued, we'll hold off request more
// audio.
- return mRawDataQueueForFeedingEngine.Duration() >=
+ return mRawDataQueueForFeedingEngine.PreciseDuration() >=
StaticPrefs::media_wmf_media_engine_raw_data_threshold_audio();
}
diff --git a/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp b/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp
index 5b99fb0f2c..e291ab6a54 100644
--- a/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp
+++ b/dom/media/platforms/wmf/MFMediaEngineDecoderModule.cpp
@@ -6,6 +6,7 @@
#include "MFTDecoder.h"
#include "VideoUtils.h"
+#include "mozilla/gfx/gfxVars.h"
#include "mozilla/MFMediaEngineParent.h"
#include "mozilla/MFMediaEngineUtils.h"
#include "mozilla/RemoteDecoderManagerChild.h"
@@ -99,6 +100,11 @@ media::DecodeSupportSet MFMediaEngineDecoderModule::SupportInternal(
if (!StaticPrefs::media_wmf_media_engine_enabled()) {
return media::DecodeSupportSet{};
}
+ // Only support hardware decoding.
+ if (!gfx::gfxVars::CanUseHardwareVideoDecoding() &&
+ !StaticPrefs::media_wmf_media_engine_bypass_gfx_blocklist()) {
+ return media::DecodeSupportSet{};
+ }
bool supports = false;
WMFStreamType type = GetStreamTypeFromMimeType(aParams.MimeType());
if (type != WMFStreamType::Unknown) {
@@ -107,13 +113,11 @@ media::DecodeSupportSet MFMediaEngineDecoderModule::SupportInternal(
MOZ_LOG(sPDMLog, LogLevel::Debug,
("MFMediaEngine decoder %s requested type '%s'",
supports ? "supports" : "rejects", aParams.MimeType().get()));
- // We only support HEVC hardware decoding.
- if (supports && type == WMFStreamType::HEVC) {
- return media::DecodeSupport::HardwareDecode;
+ if (!supports) {
+ return media::DecodeSupportSet{};
}
- // TODO : find a way to report accurate result.
- return supports ? media::DecodeSupport::SoftwareDecode
- : media::DecodeSupportSet{};
+ return StreamTypeIsVideo(type) ? media::DecodeSupport::HardwareDecode
+ : media::DecodeSupport::SoftwareDecode;
}
static bool CreateMFTDecoderOnMTA(const WMFStreamType& aType) {
diff --git a/dom/media/platforms/wmf/MFMediaEngineDecoderModule.h b/dom/media/platforms/wmf/MFMediaEngineDecoderModule.h
index c23b9010cc..1c8de5a161 100644
--- a/dom/media/platforms/wmf/MFMediaEngineDecoderModule.h
+++ b/dom/media/platforms/wmf/MFMediaEngineDecoderModule.h
@@ -10,6 +10,8 @@
namespace mozilla {
+// MFMediaEngineDecoderModule is used for the media engine playback, which only
+// supports hardware decoding.
class MFMediaEngineDecoderModule final : public PlatformDecoderModule {
public:
static void Init();
diff --git a/dom/media/platforms/wmf/MFMediaEngineStream.cpp b/dom/media/platforms/wmf/MFMediaEngineStream.cpp
index 6dce37ee35..70ffa50142 100644
--- a/dom/media/platforms/wmf/MFMediaEngineStream.cpp
+++ b/dom/media/platforms/wmf/MFMediaEngineStream.cpp
@@ -107,7 +107,11 @@ MFMediaEngineStreamWrapper::NeedsConversion() const {
}
MFMediaEngineStream::MFMediaEngineStream()
- : mIsShutdown(false), mIsSelected(false), mReceivedEOS(false) {
+ : mIsShutdown(false),
+ mIsSelected(false),
+ mRawDataQueueForFeedingEngine(true /* aEnablePreciseDuration */),
+ mRawDataQueueForGeneratingOutput(true /* aEnablePreciseDuration */),
+ mReceivedEOS(false) {
MOZ_COUNT_CTOR(MFMediaEngineStream);
}
@@ -282,17 +286,8 @@ void MFMediaEngineStream::ReplySampleRequestIfPossible() {
while (!mSampleRequestTokens.empty()) {
mSampleRequestTokens.pop();
}
-
- SLOG("Notify end events");
- MOZ_ASSERT(mRawDataQueueForFeedingEngine.GetSize() == 0);
MOZ_ASSERT(mSampleRequestTokens.empty());
- RETURN_VOID_IF_FAILED(mMediaEventQueue->QueueEventParamUnk(
- MEEndOfStream, GUID_NULL, S_OK, nullptr));
- mEndedEvent.Notify(TrackType());
- PROFILER_MARKER_TEXT(
- "MFMediaEngineStream:NotifyEnd", MEDIA_PLAYBACK, {},
- nsPrintfCString("stream=%s, id=%" PRIu64, GetDescriptionName().get(),
- mStreamId));
+ NotifyEndEvent();
return;
}
@@ -318,6 +313,18 @@ void MFMediaEngineStream::ReplySampleRequestIfPossible() {
MEMediaSample, GUID_NULL, S_OK, inputSample.Get()));
}
+void MFMediaEngineStream::NotifyEndEvent() {
+ AssertOnTaskQueue();
+ SLOG("Notify end event");
+ MOZ_ASSERT(mRawDataQueueForFeedingEngine.GetSize() == 0);
+ RETURN_VOID_IF_FAILED(mMediaEventQueue->QueueEventParamUnk(
+ MEEndOfStream, GUID_NULL, S_OK, nullptr));
+ mEndedEvent.Notify(TrackType());
+ PROFILER_MARKER_TEXT("MFMediaEngineStream:NotifyEnd", MEDIA_PLAYBACK, {},
+ nsPrintfCString("stream=%s, id=%" PRIu64,
+ GetDescriptionName().get(), mStreamId));
+}
+
bool MFMediaEngineStream::ShouldServeSamples() const {
AssertOnTaskQueue();
return mParentSource &&
@@ -486,7 +493,7 @@ void MFMediaEngineStream::NotifyNewData(MediaRawData* aSample) {
"], queue size=%zu, queue duration=%" PRId64,
aSample->mTime.ToMicroseconds(), aSample->GetEndTime().ToMicroseconds(),
mRawDataQueueForFeedingEngine.GetSize(),
- mRawDataQueueForFeedingEngine.Duration());
+ mRawDataQueueForFeedingEngine.PreciseDuration());
if (mReceivedEOS) {
SLOG("Receive a new data, cancel old EOS flag");
mReceivedEOS = false;
@@ -501,7 +508,7 @@ void MFMediaEngineStream::SendRequestSampleEvent(bool aIsEnough) {
AssertOnTaskQueue();
SLOGV("data is %s, queue duration=%" PRId64,
aIsEnough ? "enough" : "not enough",
- mRawDataQueueForFeedingEngine.Duration());
+ mRawDataQueueForFeedingEngine.PreciseDuration());
mParentSource->mRequestSampleEvent.Notify(
SampleRequest{TrackType(), aIsEnough});
}
diff --git a/dom/media/platforms/wmf/MFMediaEngineStream.h b/dom/media/platforms/wmf/MFMediaEngineStream.h
index aa3bf7e65d..e11d900498 100644
--- a/dom/media/platforms/wmf/MFMediaEngineStream.h
+++ b/dom/media/platforms/wmf/MFMediaEngineStream.h
@@ -84,7 +84,7 @@ class MFMediaEngineStream
// Return the type of the track, the result should be either audio or video.
virtual TrackInfo::TrackType TrackType() = 0;
- RefPtr<MediaDataDecoder::FlushPromise> Flush();
+ virtual RefPtr<MediaDataDecoder::FlushPromise> Flush();
MediaEventProducer<TrackInfo::TrackType>& EndedEvent() { return mEndedEvent; }
@@ -93,7 +93,7 @@ class MFMediaEngineStream
virtual MFMediaEngineVideoStream* AsVideoStream() { return nullptr; }
- RefPtr<MediaDataDecoder::DecodePromise> OutputData(
+ virtual RefPtr<MediaDataDecoder::DecodePromise> OutputData(
RefPtr<MediaRawData> aSample);
virtual RefPtr<MediaDataDecoder::DecodePromise> Drain();
@@ -133,11 +133,13 @@ class MFMediaEngineStream
// should uses `mRawDataQueueForGeneratingOutput` to generate output.
virtual already_AddRefed<MediaData> OutputDataInternal() = 0;
- void SendRequestSampleEvent(bool aIsEnough);
+ virtual void SendRequestSampleEvent(bool aIsEnough);
HRESULT AddEncryptAttributes(IMFSample* aSample,
const CryptoSample& aCryptoConfig);
+ void NotifyEndEvent();
+
void AssertOnTaskQueue() const;
void AssertOnMFThreadPool() const;
diff --git a/dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp b/dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp
index ca043478f0..0fedcd31b9 100644
--- a/dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp
+++ b/dom/media/platforms/wmf/MFMediaEngineVideoStream.cpp
@@ -49,7 +49,7 @@ void MFMediaEngineVideoStream::SetKnowsCompositor(
this]() {
mKnowsCompositor = knowCompositor;
LOG("Set SetKnowsCompositor=%p", mKnowsCompositor.get());
- ResolvePendingDrainPromiseIfNeeded();
+ ResolvePendingPromisesIfNeeded();
}));
}
@@ -74,7 +74,7 @@ void MFMediaEngineVideoStream::SetDCompSurfaceHandle(HANDLE aDCompSurfaceHandle,
}
}
LOG("Set DCompSurfaceHandle, handle=%p", mDCompSurfaceHandle);
- ResolvePendingDrainPromiseIfNeeded();
+ ResolvePendingPromisesIfNeeded();
}));
}
@@ -209,7 +209,7 @@ HRESULT MFMediaEngineVideoStream::CreateMediaType(const TrackInfo& aInfo,
bool MFMediaEngineVideoStream::HasEnoughRawData() const {
// If more than this much raw video is queued, we'll hold off request more
// video.
- return mRawDataQueueForFeedingEngine.Duration() >=
+ return mRawDataQueueForFeedingEngine.PreciseDuration() >=
StaticPrefs::media_wmf_media_engine_raw_data_threshold_video();
}
@@ -240,6 +240,32 @@ bool MFMediaEngineVideoStream::IsDCompImageReady() {
return true;
}
+RefPtr<MediaDataDecoder::DecodePromise> MFMediaEngineVideoStream::OutputData(
+ RefPtr<MediaRawData> aSample) {
+ if (IsShutdown()) {
+ return MediaDataDecoder::DecodePromise::CreateAndReject(
+ MediaResult(NS_ERROR_FAILURE,
+ RESULT_DETAIL("MFMediaEngineStream is shutdown")),
+ __func__);
+ }
+ AssertOnTaskQueue();
+ NotifyNewData(aSample);
+ MediaDataDecoder::DecodedData outputs;
+ if (RefPtr<MediaData> outputData = OutputDataInternal()) {
+ outputs.AppendElement(outputData);
+ LOGV("Output data [%" PRId64 ",%" PRId64 "]",
+ outputData->mTime.ToMicroseconds(),
+ outputData->GetEndTime().ToMicroseconds());
+ }
+ if (ShouldDelayVideoDecodeBeforeDcompReady()) {
+ LOG("Dcomp isn't ready and we already have enough video data. We will send "
+ "them back together at one when Dcomp is ready");
+ return mVideoDecodeBeforeDcompPromise.Ensure(__func__);
+ }
+ return MediaDataDecoder::DecodePromise::CreateAndResolve(std::move(outputs),
+ __func__);
+}
+
already_AddRefed<MediaData> MFMediaEngineVideoStream::OutputDataInternal() {
AssertOnTaskQueue();
if (mRawDataQueueForGeneratingOutput.GetSize() == 0 || !IsDCompImageReady()) {
@@ -261,28 +287,62 @@ RefPtr<MediaDataDecoder::DecodePromise> MFMediaEngineVideoStream::Drain() {
MediaDataDecoder::DecodedData outputs;
if (!IsDCompImageReady()) {
LOGV("Waiting for dcomp image for draining");
+ // A workaround for a special case where we have sent all input data to the
+ // media engine, and waiting for an output. Sometime media engine would
+ // never return the first frame to us, unless we notify it the end event,
+ // which happens on the case where the video only contains one frame. If we
+ // don't send end event to the media engine, the drain promise would be
+ // pending forever.
+ if (!mSampleRequestTokens.empty() &&
+ mRawDataQueueForFeedingEngine.GetSize() == 0) {
+ NotifyEndEvent();
+ }
return mPendingDrainPromise.Ensure(__func__);
}
return MFMediaEngineStream::Drain();
}
-void MFMediaEngineVideoStream::ResolvePendingDrainPromiseIfNeeded() {
+RefPtr<MediaDataDecoder::FlushPromise> MFMediaEngineVideoStream::Flush() {
+ AssertOnTaskQueue();
+ auto promise = MFMediaEngineStream::Flush();
+ mPendingDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
+ mVideoDecodeBeforeDcompPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED,
+ __func__);
+ return promise;
+}
+
+void MFMediaEngineVideoStream::ResolvePendingPromisesIfNeeded() {
AssertOnTaskQueue();
- if (mPendingDrainPromise.IsEmpty()) {
- return;
- }
if (!IsDCompImageReady()) {
return;
}
- MediaDataDecoder::DecodedData outputs;
- while (RefPtr<MediaData> outputData = OutputDataInternal()) {
- outputs.AppendElement(outputData);
- LOGV("Output data [%" PRId64 ",%" PRId64 "]",
- outputData->mTime.ToMicroseconds(),
- outputData->GetEndTime().ToMicroseconds());
+
+ // Resolve decoding promise first, then drain promise
+ if (!mVideoDecodeBeforeDcompPromise.IsEmpty()) {
+ MediaDataDecoder::DecodedData outputs;
+ while (RefPtr<MediaData> outputData = OutputDataInternal()) {
+ outputs.AppendElement(outputData);
+ LOGV("Output data [%" PRId64 ",%" PRId64 "]",
+ outputData->mTime.ToMicroseconds(),
+ outputData->GetEndTime().ToMicroseconds());
+ }
+ mVideoDecodeBeforeDcompPromise.Resolve(std::move(outputs), __func__);
+ LOG("Resolved video decode before Dcomp promise");
+ }
+
+ // This drain promise could return no data, if all data has been processed in
+ // the decoding promise.
+ if (!mPendingDrainPromise.IsEmpty()) {
+ MediaDataDecoder::DecodedData outputs;
+ while (RefPtr<MediaData> outputData = OutputDataInternal()) {
+ outputs.AppendElement(outputData);
+ LOGV("Output data [%" PRId64 ",%" PRId64 "]",
+ outputData->mTime.ToMicroseconds(),
+ outputData->GetEndTime().ToMicroseconds());
+ }
+ mPendingDrainPromise.Resolve(std::move(outputs), __func__);
+ LOG("Resolved pending drain promise");
}
- mPendingDrainPromise.Resolve(std::move(outputs), __func__);
- LOG("Resolved pending drain promise");
}
MediaDataDecoder::ConversionRequired MFMediaEngineVideoStream::NeedsConversion()
@@ -336,6 +396,20 @@ void MFMediaEngineVideoStream::UpdateConfig(const VideoInfo& aInfo) {
void MFMediaEngineVideoStream::ShutdownCleanUpOnTaskQueue() {
AssertOnTaskQueue();
mPendingDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
+ mVideoDecodeBeforeDcompPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED,
+ __func__);
+}
+
+void MFMediaEngineVideoStream::SendRequestSampleEvent(bool aIsEnough) {
+ AssertOnTaskQueue();
+ MFMediaEngineStream::SendRequestSampleEvent(aIsEnough);
+ // We need more data to be sent in, we should resolve the promise to allow
+ // more input data to be sent.
+ if (!aIsEnough && !mVideoDecodeBeforeDcompPromise.IsEmpty()) {
+ LOG("Resolved pending input promise to allow more input be sent in");
+ mVideoDecodeBeforeDcompPromise.Resolve(MediaDataDecoder::DecodedData{},
+ __func__);
+ }
}
bool MFMediaEngineVideoStream::IsEnded() const {
@@ -352,6 +426,10 @@ bool MFMediaEngineVideoStream::IsEnded() const {
bool MFMediaEngineVideoStream::IsEncrypted() const { return mIsEncrypted; }
+bool MFMediaEngineVideoStream::ShouldDelayVideoDecodeBeforeDcompReady() {
+ return HasEnoughRawData() && !IsDCompImageReady();
+}
+
nsCString MFMediaEngineVideoStream::GetCodecName() const {
switch (mStreamType) {
case WMFStreamType::H264:
diff --git a/dom/media/platforms/wmf/MFMediaEngineVideoStream.h b/dom/media/platforms/wmf/MFMediaEngineVideoStream.h
index df17c264e4..51fbe4876b 100644
--- a/dom/media/platforms/wmf/MFMediaEngineVideoStream.h
+++ b/dom/media/platforms/wmf/MFMediaEngineVideoStream.h
@@ -19,6 +19,7 @@ class DcompSurfaceImage;
} // namespace layers
class MFMediaSource;
+class MediaRawData;
class MFMediaEngineVideoStream final : public MFMediaEngineStream {
public:
@@ -50,8 +51,13 @@ class MFMediaEngineVideoStream final : public MFMediaEngineStream {
// change happens during playback.
void SetConfig(const TrackInfo& aConfig);
+ RefPtr<MediaDataDecoder::DecodePromise> OutputData(
+ RefPtr<MediaRawData> aSample) override;
+
RefPtr<MediaDataDecoder::DecodePromise> Drain() override;
+ RefPtr<MediaDataDecoder::FlushPromise> Flush() override;
+
bool IsEncrypted() const override;
private:
@@ -66,12 +72,25 @@ class MFMediaEngineVideoStream final : public MFMediaEngineStream {
bool IsDCompImageReady();
- void ResolvePendingDrainPromiseIfNeeded();
+ // Those promises are used to handle decode/drain which happens before the
+ // Dcomp surface is ready.
+ void ResolvePendingPromisesIfNeeded();
void ShutdownCleanUpOnTaskQueue() override;
bool IsEnded() const override;
+ // Before Dcomp surface is ready, we can't return any video data due to
+ // lacking of the image, which should only happen on the beginning of the
+ // video playback. In that situation, once we have enough video raw data, we
+ // can stop delaying the decode promise by waiting the Dcomp surface and
+ // resolveing the promise when Dcomp surface is ready. Doing so helps to keep
+ // the decode promise pending, so that the MFR won't keep sending more input
+ // data, which we actually don't need that many.
+ bool ShouldDelayVideoDecodeBeforeDcompReady();
+
+ void SendRequestSampleEvent(bool aIsEnough) override;
+
// Task queue only members.
HANDLE mDCompSurfaceHandle;
bool mNeedRecreateImage;
@@ -98,6 +117,12 @@ class MFMediaEngineVideoStream final : public MFMediaEngineStream {
// have dcomp image.
MozPromiseHolder<MediaDataDecoder::DecodePromise> mPendingDrainPromise;
+ // The promise used to return all video output which are requested before the
+ // Dcomp surface is ready. This should only be used once in entire playback,
+ // typically happening around the beginning of the playback.
+ MozPromiseHolder<MediaDataDecoder::DecodePromise>
+ mVideoDecodeBeforeDcompPromise;
+
// Set when `CreateMediaType()` is called.
bool mIsEncrypted = false;
};
diff --git a/dom/media/platforms/wmf/MFMediaSource.h b/dom/media/platforms/wmf/MFMediaSource.h
index 735d53579e..0e44ef12aa 100644
--- a/dom/media/platforms/wmf/MFMediaSource.h
+++ b/dom/media/platforms/wmf/MFMediaSource.h
@@ -132,8 +132,6 @@ class MFMediaSource : public Microsoft::WRL::RuntimeClass<
void AssertOnManagerThread() const;
void AssertOnMFThreadPool() const;
- void NotifyEndOfStreamInternal(TrackInfo::TrackType aType);
-
bool IsSeekable() const;
// A thread-safe event queue.
diff --git a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
index 6ebcf9a80a..63db5efae8 100644
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.cpp
@@ -55,6 +55,9 @@ WMFAudioMFTManager::WMFAudioMFTManager(const AudioInfo& aConfig)
audioSpecConfig = audioCodecSpecificBinaryBlob->Elements();
configLength = audioCodecSpecificBinaryBlob->Length();
}
+ // If no extradata has been provided, assume this is ADTS. Otherwise,
+ // assume raw AAC packets.
+ mIsADTS = !configLength;
AACAudioSpecificConfigToUserData(aConfig.mExtendedProfile, audioSpecConfig,
configLength, mUserData);
}
@@ -104,7 +107,8 @@ bool WMFAudioMFTManager::Init() {
NS_ENSURE_TRUE(SUCCEEDED(hr), false);
if (mStreamType == WMFStreamType::AAC) {
- hr = inputType->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, 0x0); // Raw AAC packet
+ UINT32 payloadType = mIsADTS ? 1 : 0;
+ hr = inputType->SetUINT32(MF_MT_AAC_PAYLOAD_TYPE, payloadType);
NS_ENSURE_TRUE(SUCCEEDED(hr), false);
hr = inputType->SetBlob(MF_MT_USER_DATA, mUserData.Elements(),
@@ -144,7 +148,8 @@ WMFAudioMFTManager::Input(MediaRawData* aSample) {
nsCString WMFAudioMFTManager::GetCodecName() const {
if (mStreamType == WMFStreamType::AAC) {
return "aac"_ns;
- } else if (mStreamType == WMFStreamType::MP3) {
+ }
+ if (mStreamType == WMFStreamType::MP3) {
return "mp3"_ns;
}
return "unknown"_ns;
@@ -177,8 +182,8 @@ WMFAudioMFTManager::UpdateOutputType() {
}
HRESULT
-WMFAudioMFTManager::Output(int64_t aStreamOffset, RefPtr<MediaData>& aOutData) {
- aOutData = nullptr;
+WMFAudioMFTManager::Output(int64_t aStreamOffset, RefPtr<MediaData>& aOutput) {
+ aOutput = nullptr;
RefPtr<IMFSample> sample;
HRESULT hr;
int typeChangeCount = 0;
@@ -242,8 +247,8 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset, RefPtr<MediaData>& aOutData) {
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
// Output is made of floats.
- int32_t numSamples = currentLength / sizeof(float);
- int32_t numFrames = numSamples / mAudioChannels;
+ uint32_t numSamples = currentLength / sizeof(float);
+ uint32_t numFrames = numSamples / mAudioChannels;
MOZ_ASSERT(numFrames >= 0);
MOZ_ASSERT(numSamples >= 0);
if (numFrames == 0) {
@@ -275,10 +280,10 @@ WMFAudioMFTManager::Output(int64_t aStreamOffset, RefPtr<MediaData>& aOutData) {
return MF_E_TRANSFORM_NEED_MORE_INPUT;
}
- aOutData = new AudioData(aStreamOffset, pts, std::move(audioData),
- mAudioChannels, mAudioRate, mChannelsMap);
- MOZ_DIAGNOSTIC_ASSERT(duration == aOutData->mDuration, "must be equal");
- mLastOutputDuration = aOutData->mDuration;
+ aOutput = new AudioData(aStreamOffset, pts, std::move(audioData),
+ mAudioChannels, mAudioRate, mChannelsMap);
+ MOZ_DIAGNOSTIC_ASSERT(duration == aOutput->mDuration, "must be equal");
+ mLastOutputDuration = aOutput->mDuration;
#ifdef LOG_SAMPLE_DECODE
LOG("Decoded audio sample! timestamp=%lld duration=%lld currentLength=%u",
diff --git a/dom/media/platforms/wmf/WMFAudioMFTManager.h b/dom/media/platforms/wmf/WMFAudioMFTManager.h
index b5dc379396..f772593545 100644
--- a/dom/media/platforms/wmf/WMFAudioMFTManager.h
+++ b/dom/media/platforms/wmf/WMFAudioMFTManager.h
@@ -58,6 +58,7 @@ class WMFAudioMFTManager : public MFTManager {
media::TimeUnit mLastOutputDuration = media::TimeUnit::Zero();
bool mFirstFrame = true;
+ bool mIsADTS = false;
uint64_t mTotalMediaFrames = 0;
uint32_t mEncoderDelay = 0;
diff --git a/dom/media/platforms/wmf/WMFMediaDataEncoder.h b/dom/media/platforms/wmf/WMFMediaDataEncoder.h
index 13848b47ad..31a63c8347 100644
--- a/dom/media/platforms/wmf/WMFMediaDataEncoder.h
+++ b/dom/media/platforms/wmf/WMFMediaDataEncoder.h
@@ -202,7 +202,9 @@ class WMFMediaDataEncoder final : public MediaDataEncoder {
MOZ_ASSERT(mEncoder);
const layers::PlanarYCbCrImage* image = aData->mImage->AsPlanarYCbCrImage();
- MOZ_ASSERT(image);
+ // TODO: Take care non planar Y-Cb-Cr image (Bug 1881647).
+ NS_ENSURE_TRUE(image, nullptr);
+
const layers::PlanarYCbCrData* yuv = image->GetData();
auto ySize = yuv->YDataSize();
auto cbcrSize = yuv->CbCrDataSize();
@@ -223,6 +225,7 @@ class WMFMediaDataEncoder final : public MediaDataEncoder {
LockBuffer lockBuffer(buffer);
NS_ENSURE_TRUE(SUCCEEDED(lockBuffer.Result()), nullptr);
+ // TODO: Take care non I420 image (Bug 1881647).
bool ok = libyuv::I420ToNV12(
yuv->mYChannel, yuv->mYStride, yuv->mCbChannel,
yuv->mCbCrStride, yuv->mCrChannel, yuv->mCbCrStride,
diff --git a/dom/media/platforms/wmf/WMFUtils.cpp b/dom/media/platforms/wmf/WMFUtils.cpp
index d096979919..dda9df808e 100644
--- a/dom/media/platforms/wmf/WMFUtils.cpp
+++ b/dom/media/platforms/wmf/WMFUtils.cpp
@@ -177,7 +177,8 @@ Maybe<gfx::YUVColorSpace> GetYUVColorSpace(IMFMediaType* aType) {
}
int32_t MFOffsetToInt32(const MFOffset& aOffset) {
- return int32_t(aOffset.value + (aOffset.fract / 65536.0f));
+ return AssertedCast<int32_t>(AssertedCast<float>(aOffset.value) +
+ (AssertedCast<float>(aOffset.fract) / 65536.0f));
}
TimeUnit GetSampleDuration(IMFSample* aSample) {
@@ -204,7 +205,7 @@ GetPictureRegion(IMFMediaType* aMediaType, gfx::IntRect& aOutPictureRegion) {
// Determine if "pan and scan" is enabled for this media. If it is, we
// only display a region of the video frame, not the entire frame.
BOOL panScan =
- MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE);
+ !!MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE);
// If pan and scan mode is enabled. Try to get the display region.
HRESULT hr = E_FAIL;
@@ -300,11 +301,14 @@ const char* MFTMessageTypeToStr(MFT_MESSAGE_TYPE aMsg) {
GUID AudioMimeTypeToMediaFoundationSubtype(const nsACString& aMimeType) {
if (aMimeType.EqualsLiteral("audio/mpeg")) {
return MFAudioFormat_MP3;
- } else if (MP4Decoder::IsAAC(aMimeType)) {
+ }
+ if (MP4Decoder::IsAAC(aMimeType)) {
return MFAudioFormat_AAC;
- } else if (aMimeType.EqualsLiteral("audio/vorbis")) {
+ }
+ if (aMimeType.EqualsLiteral("audio/vorbis")) {
return MFAudioFormat_Vorbis;
- } else if (aMimeType.EqualsLiteral("audio/opus")) {
+ }
+ if (aMimeType.EqualsLiteral("audio/opus")) {
return MFAudioFormat_Opus;
}
NS_WARNING("Unsupport audio mimetype");
@@ -314,17 +318,19 @@ GUID AudioMimeTypeToMediaFoundationSubtype(const nsACString& aMimeType) {
GUID VideoMimeTypeToMediaFoundationSubtype(const nsACString& aMimeType) {
if (MP4Decoder::IsH264(aMimeType)) {
return MFVideoFormat_H264;
- } else if (VPXDecoder::IsVP8(aMimeType)) {
+ }
+ if (VPXDecoder::IsVP8(aMimeType)) {
return MFVideoFormat_VP80;
- } else if (VPXDecoder::IsVP9(aMimeType)) {
+ }
+ if (VPXDecoder::IsVP9(aMimeType)) {
return MFVideoFormat_VP90;
}
#ifdef MOZ_AV1
- else if (AOMDecoder::IsAV1(aMimeType)) {
+ if (AOMDecoder::IsAV1(aMimeType)) {
return MFVideoFormat_AV1;
}
#endif
- else if (MP4Decoder::IsHEVC(aMimeType)) {
+ if (MP4Decoder::IsHEVC(aMimeType)) {
return MFVideoFormat_HEVC;
}
NS_WARNING("Unsupport video mimetype");
@@ -368,7 +374,9 @@ void AACAudioSpecificConfigToUserData(uint8_t aAACProfileLevelIndication,
// the rest can be all 0x00.
BYTE heeInfo[heeInfoLen] = {0};
WORD* w = (WORD*)heeInfo;
- w[0] = 0x0; // Payload type raw AAC packet
+ // If extradata has been provided, assume raw AAC packets (0). Otherwise,
+ // assume ADTS (1)
+ w[0] = aConfigLength ? 0 : 1;
w[1] = aAACProfileLevelIndication;
aOutUserData.AppendElements(heeInfo, heeInfoLen);
@@ -377,10 +385,10 @@ void AACAudioSpecificConfigToUserData(uint8_t aAACProfileLevelIndication,
// The AudioSpecificConfig is TTTTTFFF|FCCCCGGG
// (T=ObjectType, F=Frequency, C=Channel, G=GASpecificConfig)
// If frequency = 0xf, then the frequency is explicitly defined on 24 bits.
- int8_t frequency =
+ uint8_t frequency =
(aAudioSpecConfig[0] & 0x7) << 1 | (aAudioSpecConfig[1] & 0x80) >> 7;
- int8_t channels = (aAudioSpecConfig[1] & 0x78) >> 3;
- int8_t gasc = aAudioSpecConfig[1] & 0x7;
+ uint8_t channels = (aAudioSpecConfig[1] & 0x78) >> 3;
+ uint8_t gasc = aAudioSpecConfig[1] & 0x7;
if (frequency != 0xf && channels && !gasc) {
// We enter this condition if the AudioSpecificConfig should theorically
// be 2 bytes long but it's not.