2023-07-15 03:07:19 +08:00

226 lines
5.7 KiB
C++

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "FFMPEGMediaFactoryPrivate.h"
#include "Containers/Array.h"
#include "Containers/UnrealString.h"
#include "IMediaModule.h"
#include "IMediaOptions.h"
#include "IMediaPlayerFactory.h"
#include "Internationalization/Internationalization.h"
#include "Misc/Paths.h"
#include "Modules/ModuleInterface.h"
#include "Modules/ModuleManager.h"
#include "UObject/NameTypes.h"
#if PLATFORM_WINDOWS
#include "Windows/WindowsHWrapper.h"
#endif
#if WITH_EDITOR
#include "ISettingsModule.h"
#include "Templates/SharedPointer.h"
#include "UObject/Class.h"
#include "UObject/WeakObjectPtr.h"
#include "FFMPEGMediaSettings.h"
#endif
#include "../../FFMPEGMedia/Public/IFFMPEGMediaModule.h"
DEFINE_LOG_CATEGORY(LogFFMPEGMediaFactory);
#define LOCTEXT_NAMESPACE "FMPEGMediaFactoryModule"
/**
* Implements the WmfMediaFactory module.
*/
class FFFMPEGMediaFactoryModule
: public IMediaPlayerFactory
, public IModuleInterface
{
public:
/** Default constructor. */
FFFMPEGMediaFactoryModule() { }
public:
//~ IMediaPlayerFactory interface
virtual bool CanPlayUrl(const FString& Url, const IMediaOptions* Options, TArray<FText>* OutWarnings, TArray<FText>* OutErrors) const override
{
FString Scheme;
FString Location;
// check scheme
if (!Url.Split(TEXT("://"), &Scheme, &Location, ESearchCase::CaseSensitive))
{
if (OutErrors != nullptr)
{
OutErrors->Add(LOCTEXT("NoSchemeFound", "No URI scheme found"));
}
return false;
}
if (!SupportedUriSchemes.Contains(Scheme))
{
if (OutErrors != nullptr)
{
OutErrors->Add(FText::Format(LOCTEXT("SchemeNotSupported", "The URI scheme '{0}' is not supported"), FText::FromString(Scheme)));
}
return false;
}
// check file extension
if (Scheme == TEXT("file"))
{
const FString Extension = FPaths::GetExtension(Location, false);
if (!SupportedFileExtensions.Contains(Extension))
{
if (OutErrors != nullptr)
{
OutErrors->Add(FText::Format(LOCTEXT("ExtensionNotSupported", "The file extension '{0}' is not supported"), FText::FromString(Extension)));
}
return false;
}
}
// check options
if ((OutWarnings != nullptr) && (Options != nullptr))
{
if (Options->GetMediaOption("PrecacheFile", false) && (Scheme != TEXT("file")))
{
OutWarnings->Add(LOCTEXT("PrecachingNotSupported", "Precaching is supported for local files only"));
}
}
return true;
}
virtual FGuid GetPlayerPluginGUID() const override
{
// {938BEEB4-2E88-450E-9C1C-6109456279B3}
static FGuid PlayerPluginGUID(0x938beeb4, 0x2e88450e, 0x9c1c6109, 0x456279b3);
return PlayerPluginGUID;
}
virtual TSharedPtr<IMediaPlayer, ESPMode::ThreadSafe> CreatePlayer(IMediaEventSink& EventSink) override
{
auto FFMPEGMediaModule = FModuleManager::LoadModulePtr<IFFMPEGMediaModule>("FFMPEGMedia");
return (FFMPEGMediaModule != nullptr) ? FFMPEGMediaModule->CreatePlayer(EventSink) : nullptr;
}
virtual FText GetDisplayName() const override
{
return LOCTEXT("MediaPlayerDisplayName", "FFMPEG");
}
virtual FName GetPlayerName() const override
{
static FName PlayerName(TEXT("FFMPEGMedia"));
return PlayerName;
}
virtual const TArray<FString>& GetSupportedPlatforms() const override
{
return SupportedPlatforms;
}
virtual bool SupportsFeature(EMediaFeature Feature) const override
{
return ((Feature == EMediaFeature::AudioSamples) ||
(Feature == EMediaFeature::AudioTracks) ||
(Feature == EMediaFeature::CaptionTracks) ||
(Feature == EMediaFeature::MetadataTracks) ||
(Feature == EMediaFeature::OverlaySamples) ||
(Feature == EMediaFeature::SubtitleTracks) ||
(Feature == EMediaFeature::VideoSamples) ||
(Feature == EMediaFeature::VideoTracks));
}
public:
//~ IModuleInterface interface
virtual void StartupModule() override
{
auto FFMPEGMediaModule = FModuleManager::LoadModulePtr<IFFMPEGMediaModule>("FFMPEGMedia");
SupportedFileExtensions.Append(FFMPEGMediaModule->GetSupportedFileExtensions());
SupportedUriSchemes.Append(FFMPEGMediaModule->GetSupportedUriSchemes() );
// supported platforms
SupportedPlatforms.Add(TEXT("Windows"));
SupportedPlatforms.Add(TEXT("Mac"));
SupportedPlatforms.Add(TEXT("Android"));
#if WITH_EDITOR
// register settings
ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
if (SettingsModule != nullptr)
{
SettingsModule->RegisterSettings("Project", "Plugins", "FFMPEGMedia",
LOCTEXT("FFMPEGMediaSettingsName", "FFMPEG Media"),
LOCTEXT("FFMPEGMediaSettingsDescription", "Configure the FFMPEG Media plug-in."),
GetMutableDefault<UFFMPEGMediaSettings>()
);
}
#endif //WITH_EDITOR
// register player factory
auto MediaModule = FModuleManager::LoadModulePtr<IMediaModule>("Media");
if (MediaModule != nullptr)
{
MediaModule->RegisterPlayerFactory(*this);
}
}
virtual void ShutdownModule() override
{
// unregister player factory
auto MediaModule = FModuleManager::GetModulePtr<IMediaModule>("Media");
if (MediaModule != nullptr)
{
MediaModule->UnregisterPlayerFactory(*this);
}
#if WITH_EDITOR
// unregister settings
ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
if (SettingsModule != nullptr)
{
SettingsModule->UnregisterSettings("Project", "Plugins", "FFMPEGMedia");
}
#endif //WITH_EDITOR
}
private:
/** List of supported media file types. */
TArray<FString> SupportedFileExtensions;
/** List of platforms that the media player support. */
TArray<FString> SupportedPlatforms;
/** List of supported URI schemes. */
TArray<FString> SupportedUriSchemes;
};
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FFFMPEGMediaFactoryModule, FFMPEGMediaFactory);