Bug 1867542 - Reflect PEM changes to PEMFactory. r=jolin

Depends on D195135

Differential Revision: https://phabricator.services.mozilla.com/D195136
This commit is contained in:
Paul Adenot 2023-12-09 19:44:55 +00:00
parent c863ef6478
commit 7c6eecefe0
2 changed files with 141 additions and 27 deletions

View file

@ -6,6 +6,8 @@
#include "PEMFactory.h"
#include "PlatformEncoderModule.h"
#ifdef MOZ_APPLEMEDIA
# include "AppleEncoderModule.h"
#endif
@ -32,15 +34,22 @@ namespace mozilla {
LazyLogModule sPEMLog("PlatformEncoderModule");
#define LOGE(fmt, ...) \
MOZ_LOG(sPEMLog, mozilla::LogLevel::Error, \
("[PEMFactory] %s: " fmt, __func__, ##__VA_ARGS__))
#define LOG(fmt, ...) \
MOZ_LOG(sPEMLog, mozilla::LogLevel::Debug, \
("[PEMFactory] %s: " fmt, __func__, ##__VA_ARGS__))
PEMFactory::PEMFactory() {
gfx::gfxVars::Initialize();
#ifdef MOZ_APPLEMEDIA
RefPtr<PlatformEncoderModule> m(new AppleEncoderModule());
mModules.AppendElement(m);
mCurrentPEMs.AppendElement(m);
#endif
#ifdef MOZ_WIDGET_ANDROID
mModules.AppendElement(new AndroidEncoderModule());
mCurrentPEMs.AppendElement(new AndroidEncoderModule());
#endif
#ifdef XP_WIN
@ -68,38 +77,130 @@ PEMFactory::PEMFactory() {
#endif
}
bool PEMFactory::SupportsMimeType(const nsACString& aMimeType) const {
for (auto m : mModules) {
if (m->SupportsMimeType(aMimeType)) {
return true;
}
}
return false;
}
already_AddRefed<MediaDataEncoder> PEMFactory::CreateEncoder(
const CreateEncoderParams& aParams, const bool aHardwareNotAllowed) {
const TrackInfo& info = aParams.mConfig;
RefPtr<PlatformEncoderModule> m = FindPEM(info);
const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue) {
RefPtr<PlatformEncoderModule> m = FindPEM(aConfig);
if (!m) {
return nullptr;
}
return info.IsVideo() ? m->CreateVideoEncoder(aParams, aHardwareNotAllowed)
: nullptr;
return aConfig.IsVideo() ? m->CreateVideoEncoder(aConfig, aTaskQueue)
: nullptr;
}
RefPtr<PlatformEncoderModule::CreateEncoderPromise>
PEMFactory::CreateEncoderAsync(const EncoderConfig& aConfig,
const RefPtr<TaskQueue>& aTaskQueue) {
return CheckAndMaybeCreateEncoder(aConfig, 0, aTaskQueue);
}
RefPtr<PlatformEncoderModule::CreateEncoderPromise>
PEMFactory::CheckAndMaybeCreateEncoder(const EncoderConfig& aConfig,
uint32_t aIndex,
const RefPtr<TaskQueue>& aTaskQueue) {
for (uint32_t i = aIndex; i < mCurrentPEMs.Length(); i++) {
if (!mCurrentPEMs[i]->Supports(aConfig)) {
continue;
}
return CreateEncoderWithPEM(mCurrentPEMs[i], aConfig, aTaskQueue)
->Then(
GetCurrentSerialEventTarget(), __func__,
[](RefPtr<MediaDataEncoder>&& aEncoder) {
return PlatformEncoderModule::CreateEncoderPromise::
CreateAndResolve(std::move(aEncoder), __func__);
},
[self = RefPtr{this}, i, config = aConfig, aTaskQueue,
&aConfig](const MediaResult& aError) mutable {
// Try the next PEM.
return self->CheckAndMaybeCreateEncoder(aConfig, i + 1,
aTaskQueue);
});
}
return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
nsPrintfCString("Error no encoder found for %d",
static_cast<int>(aConfig.mCodec))
.get()),
__func__);
}
RefPtr<PlatformEncoderModule::CreateEncoderPromise>
PEMFactory::CreateEncoderWithPEM(PlatformEncoderModule* aPEM,
const EncoderConfig& aConfig,
const RefPtr<TaskQueue>& aTaskQueue) {
MOZ_ASSERT(aPEM);
MediaResult result = NS_OK;
if (aConfig.IsAudio()) {
return aPEM->AsyncCreateEncoder(aConfig, aTaskQueue)
->Then(
GetCurrentSerialEventTarget(), __func__,
[config = aConfig](RefPtr<MediaDataEncoder>&& aEncoder) {
RefPtr<MediaDataEncoder> decoder = std::move(aEncoder);
return PlatformEncoderModule::CreateEncoderPromise::
CreateAndResolve(decoder, __func__);
},
[](const MediaResult& aError) {
return PlatformEncoderModule::CreateEncoderPromise::
CreateAndReject(aError, __func__);
});
}
if (!aConfig.IsVideo()) {
return PlatformEncoderModule::CreateEncoderPromise::CreateAndReject(
MediaResult(
NS_ERROR_DOM_MEDIA_FATAL_ERR,
RESULT_DETAIL(
"Encoder configuration error, expected audio or video.")),
__func__);
}
return aPEM->AsyncCreateEncoder(aConfig, aTaskQueue);
}
bool PEMFactory::Supports(const EncoderConfig& aConfig) const {
RefPtr<PlatformEncoderModule> found;
for (const auto& m : mCurrentPEMs) {
if (m->Supports(aConfig)) {
// TODO name
LOG("Checking if %s supports codec %d: yes", m->GetName(),
static_cast<int>(aConfig.mCodec));
return true;
}
LOG("Checking if %s supports codec %d: no", m->GetName(),
static_cast<int>(aConfig.mCodec));
}
return false;
}
bool PEMFactory::SupportsCodec(CodecType aCodec) const {
for (const auto& m : mCurrentPEMs) {
if (m->SupportsCodec(aCodec)) {
// TODO name
LOG("Checking if %s supports codec %d: yes", m->GetName(),
static_cast<int>(aCodec));
return true;
}
LOG("Checking if %s supports codec %d: no", m->GetName(),
static_cast<int>(aCodec));
}
LOG("No PEM support %d", static_cast<int>(aCodec));
return false;
}
already_AddRefed<PlatformEncoderModule> PEMFactory::FindPEM(
const TrackInfo& aTrackInfo) const {
const EncoderConfig& aConfig) const {
RefPtr<PlatformEncoderModule> found;
for (auto m : mModules) {
if (m->SupportsMimeType(aTrackInfo.mMimeType)) {
for (const auto& m : mCurrentPEMs) {
if (m->Supports(aConfig)) {
found = m;
break;
}
}
return found.forget();
}
} // namespace mozilla
#undef LOGE
#undef LOG

View file

@ -11,6 +11,8 @@
namespace mozilla {
using PEMCreateEncoderPromise = PlatformEncoderModule::CreateEncoderPromise;
class PEMFactory final {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PEMFactory)
@ -22,17 +24,28 @@ class PEMFactory final {
// instance. It's expected that there will be multiple
// PlatformEncoderModules alive at the same time.
already_AddRefed<MediaDataEncoder> CreateEncoder(
const CreateEncoderParams& aParams, const bool aHardwareNotAllowed);
const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue);
bool SupportsMimeType(const nsACString& aMimeType) const;
RefPtr<PlatformEncoderModule::CreateEncoderPromise> CreateEncoderAsync(
const EncoderConfig& aConfig, const RefPtr<TaskQueue>& aTaskQueue);
bool Supports(const EncoderConfig& aConfig) const;
bool SupportsCodec(CodecType aCodec) const;
private:
virtual ~PEMFactory() = default;
// Returns the first PEM in our list supporting the mimetype.
already_AddRefed<PlatformEncoderModule> FindPEM(
const TrackInfo& aTrackInfo) const;
RefPtr<PlatformEncoderModule::CreateEncoderPromise>
CheckAndMaybeCreateEncoder(const EncoderConfig& aConfig, uint32_t aIndex,
const RefPtr<TaskQueue>& aTaskQueue);
nsTArray<RefPtr<PlatformEncoderModule>> mModules;
RefPtr<PlatformEncoderModule::CreateEncoderPromise> CreateEncoderWithPEM(
PlatformEncoderModule* aPEM, const EncoderConfig& aConfig,
const RefPtr<TaskQueue>& aTaskQueue);
virtual ~PEMFactory() = default;
// Returns the first PEM in our list supporting the codec.
already_AddRefed<PlatformEncoderModule> FindPEM(
const EncoderConfig& aConfig) const;
nsTArray<RefPtr<PlatformEncoderModule>> mCurrentPEMs;
};
} // namespace mozilla