From e5f7b9f18641141354f03e6a8281a347a2555927 Mon Sep 17 00:00:00 2001 From: tobigun Date: Sat, 30 Oct 2010 07:34:30 +0000 Subject: dynamic loading of video- and audio-decoder git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/experimental@2695 b956fd51-792f-4845-bead-9b4dfca2ff2c --- mediaplugin/src/base/UMain.pas | 3 + mediaplugin/src/base/UPathUtils.pas | 2 + mediaplugin/src/media/UAudioConverter.pas | 15 +++++ mediaplugin/src/media/UAudioDecoder_FFmpeg.pas | 83 ++++++++++++------------ mediaplugin/src/media/UMediaPlugin.pas | 90 ++++++++++++++++++++------ mediaplugin/src/media/UVideoDecoder_FFmpeg.pas | 88 ++++++++++++------------- 6 files changed, 174 insertions(+), 107 deletions(-) (limited to 'mediaplugin/src') diff --git a/mediaplugin/src/base/UMain.pas b/mediaplugin/src/base/UMain.pas index 14a543d1..96031f89 100644 --- a/mediaplugin/src/base/UMain.pas +++ b/mediaplugin/src/base/UMain.pas @@ -93,6 +93,7 @@ uses ULuaTextGL, ULuaParty, ULuaScreenSing, + UMediaPlugin, UTime; procedure Main; @@ -183,6 +184,8 @@ begin Log.BenchmarkEnd(1); Log.LogBenchmark('Loading Ini', 1); + LoadMediaPlugins(); + // Sound Log.BenchmarkStart(1); Log.LogStatus('Initialize Sound', 'Initialization'); diff --git a/mediaplugin/src/base/UPathUtils.pas b/mediaplugin/src/base/UPathUtils.pas index 2bfcde42..beb1d64a 100644 --- a/mediaplugin/src/base/UPathUtils.pas +++ b/mediaplugin/src/base/UPathUtils.pas @@ -50,6 +50,7 @@ var CoverPaths: IInterfaceList; LanguagesPath: IPath; PluginPath: IPath; + MediaPluginPath: IPath; VisualsPath: IPath; FontPath: IPath; ResourcesPath: IPath; @@ -170,6 +171,7 @@ begin FindPath(SkinsPath, SharedPath.Append('themes'), false); FindPath(LanguagesPath, SharedPath.Append('languages'), false); FindPath(PluginPath, SharedPath.Append('plugins'), false); + FindPath(MediaPluginPath, SharedPath.Append('media'), false); FindPath(VisualsPath, SharedPath.Append('visuals'), false); FindPath(FontPath, SharedPath.Append('fonts'), false); FindPath(ResourcesPath, SharedPath.Append('resources'), false); diff --git a/mediaplugin/src/media/UAudioConverter.pas b/mediaplugin/src/media/UAudioConverter.pas index aa3e343e..f2388b8f 100644 --- a/mediaplugin/src/media/UAudioConverter.pas +++ b/mediaplugin/src/media/UAudioConverter.pas @@ -194,6 +194,21 @@ end; {$IFDEF UseFFmpegResample} +const +{$IFDEF MSWINDOWS} + ffmpegPlugin = 'ffmpeg_playback.dll'; +{$ENDIF} +{$IFDEF LINUX} + ffmpegPlugin = 'ffmpeg_playback'; +{$ENDIF} +{$IFDEF DARWIN} + ffmpegPlugin = 'ffmpeg_playback.dylib'; + {$linklib ffmpegPlugin} +{$ENDIF} + +function Plugin_register(core: PMediaPluginCore): PMediaPluginInfo; + cdecl; external ffmpegPlugin; + function TAudioConverter_FFmpeg.Init(SrcFormatInfo: TAudioFormatInfo; DstFormatInfo: TAudioFormatInfo): boolean; var CSrcFormatInfo: TCAudioFormatInfo; diff --git a/mediaplugin/src/media/UAudioDecoder_FFmpeg.pas b/mediaplugin/src/media/UAudioDecoder_FFmpeg.pas index 2865a7d8..6047cdd6 100644 --- a/mediaplugin/src/media/UAudioDecoder_FFmpeg.pas +++ b/mediaplugin/src/media/UAudioDecoder_FFmpeg.pas @@ -44,28 +44,45 @@ interface {$I switches.inc} +uses + UMediaPlugin, + UMusic, + UPath; + +type + TAudioDecoder_FFmpeg = class(TInterfacedObject, IAudioDecoder) + private + fPluginInfo: PMediaPluginInfo; + public + constructor Create(Info: PMediaPluginInfo); + + function GetName: string; + + function InitializeDecoder(): boolean; + function FinalizeDecoder(): boolean; + function Open(const Filename: IPath): TAudioDecodeStream; + end; + implementation uses ctypes, Classes, SysUtils, - UMediaPlugin, - UMusic, UIni, UMain, - ULog, - UPath; + ULog; type TFFmpegDecodeStream = class(TAudioDecodeStream) private + fAudioDecoderInfo: PAudioDecoderInfo; fFilename: IPath; fStream: PAudioDecodeStream; fFormatInfo: TAudioFormatInfo; public - constructor Create(); + constructor Create(Info: PAudioDecoderInfo); destructor Destroy(); override; function Open(const Filename: IPath): boolean; @@ -83,28 +100,12 @@ type function ReadData(Buffer: PByteArray; BufferSize: integer): integer; override; end; -type - TAudioDecoder_FFmpeg = class(TInterfacedObject, IAudioDecoder) - private - fPluginInfo: PMediaPluginInfo; - public - constructor Create(); - - function GetName: string; - - function InitializeDecoder(): boolean; - function FinalizeDecoder(): boolean; - function Open(const Filename: IPath): TAudioDecodeStream; - end; - -var - AudioDecoderInfo: PAudioDecoderInfo; - { TFFmpegDecodeStream } -constructor TFFmpegDecodeStream.Create(); +constructor TFFmpegDecodeStream.Create(Info: PAudioDecoderInfo); begin inherited Create(); + fAudioDecoderInfo := Info; fFilename := PATH_NONE; end; @@ -125,13 +126,13 @@ begin Close(); - fStream := AudioDecoderInfo.open(PChar(Filename.ToUTF8())); + fStream := fAudioDecoderInfo.open(PChar(Filename.ToUTF8())); if (fStream = nil) then Exit; fFilename := Filename; - AudioDecoderInfo.getAudioFormatInfo(fStream, Info); + fAudioDecoderInfo.getAudioFormatInfo(fStream, Info); fFormatInfo := TAudioFormatInfo.Create( Info.channels, Info.sampleRate, @@ -146,14 +147,14 @@ begin Self.fFilename := PATH_NONE; if (fStream <> nil) then begin - AudioDecoderInfo.close(fStream); + fAudioDecoderInfo.close(fStream); fStream := nil; end; end; function TFFmpegDecodeStream.GetLength(): real; begin - Result := AudioDecoderInfo.getLength(fStream); + Result := fAudioDecoderInfo.getLength(fStream); end; function TFFmpegDecodeStream.GetAudioFormatInfo(): TAudioFormatInfo; @@ -163,46 +164,46 @@ end; function TFFmpegDecodeStream.IsEOF(): boolean; begin - Result := AudioDecoderInfo.isEOF(fStream); + Result := fAudioDecoderInfo.isEOF(fStream); end; function TFFmpegDecodeStream.IsError(): boolean; begin - Result := AudioDecoderInfo.isError(fStream); + Result := fAudioDecoderInfo.isError(fStream); end; function TFFmpegDecodeStream.GetPosition(): real; begin - Result := AudioDecoderInfo.getPosition(fStream); + Result := fAudioDecoderInfo.getPosition(fStream); end; procedure TFFmpegDecodeStream.SetPosition(Time: real); begin - AudioDecoderInfo.setPosition(fStream, Time); + fAudioDecoderInfo.setPosition(fStream, Time); end; function TFFmpegDecodeStream.GetLoop(): boolean; begin - Result := AudioDecoderInfo.getLoop(fStream); + Result := fAudioDecoderInfo.getLoop(fStream); end; procedure TFFmpegDecodeStream.SetLoop(Enabled: boolean); begin - AudioDecoderInfo.setLoop(fStream, Enabled); + fAudioDecoderInfo.setLoop(fStream, Enabled); end; function TFFmpegDecodeStream.ReadData(Buffer: PByteArray; BufferSize: integer): integer; begin - Result := AudioDecoderInfo.readData(fStream, PCUint8(Buffer), BufferSize); + Result := fAudioDecoderInfo.readData(fStream, PCUint8(Buffer), BufferSize); end; { TAudioDecoder_FFmpeg } -constructor TAudioDecoder_FFmpeg.Create(); +constructor TAudioDecoder_FFmpeg.Create(Info: PMediaPluginInfo); begin inherited Create(); - fPluginInfo := Plugin_register(MediaPluginCore); + fPluginInfo := Info; end; function TAudioDecoder_FFmpeg.GetName: String; @@ -212,14 +213,13 @@ end; function TAudioDecoder_FFmpeg.InitializeDecoder: boolean; begin - fPluginInfo.initialize(); - AudioDecoderInfo := fPluginInfo.audioDecoder; + //fPluginInfo.initialize(); Result := true; end; function TAudioDecoder_FFmpeg.FinalizeDecoder(): boolean; begin - fPluginInfo.finalize(); + //fPluginInfo.finalize(); Result := true; end; @@ -229,7 +229,7 @@ var begin Result := nil; - Stream := TFFmpegDecodeStream.Create(); + Stream := TFFmpegDecodeStream.Create(fPluginInfo.audioDecoder); if (not Stream.Open(Filename)) then begin Stream.Free; @@ -239,7 +239,4 @@ begin Result := Stream; end; -initialization - MediaManager.Add(TAudioDecoder_FFmpeg.Create); - end. diff --git a/mediaplugin/src/media/UMediaPlugin.pas b/mediaplugin/src/media/UMediaPlugin.pas index 2eb0772e..0c0f7fb9 100644 --- a/mediaplugin/src/media/UMediaPlugin.pas +++ b/mediaplugin/src/media/UMediaPlugin.pas @@ -47,9 +47,9 @@ type PMediaPluginCore = ^TMediaPluginCore; TMediaPluginCore = record - version: cint; + version: cint; - log: procedure(level: cint; msg: PChar; context: PChar); cdecl; + log: procedure(level: cint; msg: PChar; context: PChar); cdecl; ticksMillis: function(): cuint32; cdecl; fileOpen: function(utf8Filename: PAnsiChar; mode: cint): PFileStream; cdecl; @@ -138,23 +138,9 @@ type videoDecoder: PVideoDecoderInfo; end; - Plugin_registerFunc = function(core: PMediaPluginCore): PMediaPluginInfo; cdecl; - -const -{$IFDEF MSWINDOWS} - ffmpegPlugin = 'ffmpeg_playback.dll'; -{$ENDIF} -{$IFDEF LINUX} - ffmpegPlugin = 'ffmpeg_playback'; -{$ENDIF} -{$IFDEF DARWIN} - ffmpegPlugin = 'ffmpeg_playback.dylib'; - {$linklib ffmpegPlugin} -{$ENDIF} - -function Plugin_register(core: PMediaPluginCore): PMediaPluginInfo; - cdecl; external ffmpegPlugin; + TPluginRegisterFunc = function(core: PMediaPluginCore): PMediaPluginInfo; cdecl; +procedure LoadMediaPlugins(); function MediaPluginCore: PMediaPluginCore; @@ -164,8 +150,15 @@ procedure AudioFormatInfoToCStruct( implementation uses + SysUtils, SDL, - ULog; + moduleloader, + UFilesystem, + UPath, + UPathUtils, + ULog, + UAudioDecoder_FFmpeg, + UVideoDecoder_FFmpeg; var MediaPluginCore_Instance: TMediaPluginCore; @@ -349,6 +342,65 @@ begin end; end; +procedure LoadMediaPlugins(); +var + LibPath: IPath; + Iter: IFileIterator; + FileInfo: TFileInfo; + ModuleFile: IPath; + Module: TModuleHandle; + RegisterFunc: TPluginRegisterFunc; + PluginInfo: PMediaPluginInfo; +begin + LibPath := MediaPluginPath.Append('*.dll'); + Iter := FileSystem.FileFind(LibPath, faAnyFile); + while (Iter.HasNext) do + begin + FileInfo := Iter.Next(); + ModuleFile := MediaPluginPath.Append(FileInfo.Name); + if (not LoadModule(Module, PChar(ModuleFile.ToNative))) then + begin + Log.LogInfo('Failed to load media plugin: "' + FileInfo.Name.ToNative + '"', + 'LoadMediaPlugins'); + Continue; + end; + RegisterFunc := GetModuleSymbol(Module, 'Plugin_register'); + if (@RegisterFunc = nil) then + begin + Log.LogError('Invalid media plugin: "' + FileInfo.Name.ToNative + '"', + 'LoadMediaPlugins'); + UnloadModule(Module); + Continue; + end; + PluginInfo := RegisterFunc(MediaPluginCore); + if (PluginInfo = nil) then + begin + Log.LogError('Invalid media plugin info: "' + FileInfo.Name.ToNative + '"', + 'LoadMediaPlugins'); + UnloadModule(Module); + Continue; + end; + if (not PluginInfo.initialize()) then + begin + Log.LogError('Failed to initialize media plugin: "' + PluginInfo.name + '"', + 'LoadMediaPlugins'); + UnloadModule(Module); + Continue; + end; + + Log.LogStatus('Loaded media plugin: "' + PluginInfo.name + '"', + 'LoadMediaPlugins'); + + // register modules + if (PluginInfo.audioDecoder <> nil) then + MediaManager.Add(TAudioDecoder_FFmpeg.Create(PluginInfo)); + if (PluginInfo.videoDecoder <> nil) then + MediaManager.Add(TVideoDecoder_FFmpeg.Create(PluginInfo)); + //if (PluginInfo.audioConverter <> nil) then + // MediaManager.Add(); + end; +end; + initialization InitializeMediaPluginCore; diff --git a/mediaplugin/src/media/UVideoDecoder_FFmpeg.pas b/mediaplugin/src/media/UVideoDecoder_FFmpeg.pas index 51916276..b8b72a9d 100644 --- a/mediaplugin/src/media/UVideoDecoder_FFmpeg.pas +++ b/mediaplugin/src/media/UVideoDecoder_FFmpeg.pas @@ -33,27 +33,45 @@ interface {$I switches.inc} +uses + UMediaPlugin, + UMusic, + UPath; + +type + TVideoDecoder_FFmpeg = class( TInterfacedObject, IVideoDecoder ) + private + fPluginInfo: PMediaPluginInfo; + public + constructor Create(Info: PMediaPluginInfo); + + function GetName: String; + + function InitializeDecoder(): boolean; + function FinalizeDecoder: boolean; + + function Open(const FileName: IPath): TVideoDecodeStream; + end; + implementation uses SysUtils, Math, - UMediaPlugin, + ctypes, UCommon, UConfig, - ULog, - UMusic, - UPath; + ULog; type TVideoDecodeStream_FFmpeg = class (TVideoDecodeStream) private - private - fFilename: IPath; - fStream: PVideoDecodeStream; + fVideoDecoderInfo: PVideoDecoderInfo; + fFilename: IPath; + fStream: PVideoDecodeStream; public - constructor Create; + constructor Create(Info: PVideoDecoderInfo); destructor Destroy; override; function Open(const FileName: IPath): boolean; override; @@ -72,31 +90,14 @@ type function GetFrame(Time: Extended): PByteArray; override; end; - TVideoDecoder_FFmpeg = class( TInterfacedObject, IVideoDecoder ) - private - fPluginInfo: PMediaPluginInfo; - public - constructor Create(); - - function GetName: String; - - function InitializeDecoder(): boolean; - function FinalizeDecoder: boolean; - - function Open(const FileName: IPath): TVideoDecodeStream; - end; - -var - VideoDecoderInfo: PVideoDecoderInfo; - {*------------------------------------------------------------------------------ * TVideoPlayback_ffmpeg *------------------------------------------------------------------------------} -constructor TVideoDecoder_FFmpeg.Create(); +constructor TVideoDecoder_FFmpeg.Create(Info: PMediaPluginInfo); begin inherited Create(); - fPluginInfo := Plugin_register(MediaPluginCore); + fPluginInfo := Info; end; function TVideoDecoder_FFmpeg.GetName: String; @@ -106,14 +107,13 @@ end; function TVideoDecoder_FFmpeg.InitializeDecoder(): boolean; begin - fPluginInfo.initialize(); - VideoDecoderInfo := fPluginInfo.videoDecoder; + //fPluginInfo.initialize(); Result := true; end; function TVideoDecoder_FFmpeg.FinalizeDecoder(): boolean; begin - fPluginInfo.finalize(); + //fPluginInfo.finalize(); Result := true; end; @@ -123,7 +123,7 @@ var begin Result := nil; - Stream := TVideoDecodeStream_FFmpeg.Create; + Stream := TVideoDecodeStream_FFmpeg.Create(fPluginInfo.videoDecoder); if (not Stream.Open(FileName)) then begin Stream.Free; @@ -136,9 +136,10 @@ end; {* TVideoDecoder_FFmpeg *} -constructor TVideoDecodeStream_FFmpeg.Create; +constructor TVideoDecodeStream_FFmpeg.Create(Info: PVideoDecoderInfo); begin inherited Create(); + fVideoDecoderInfo := Info; fFilename := PATH_NONE; end; @@ -154,7 +155,7 @@ begin Close(); - fStream := VideoDecoderInfo.open(PChar(Filename.ToUTF8())); + fStream := fVideoDecoderInfo.open(PChar(Filename.ToUTF8())); if (fStream = nil) then Exit; @@ -168,52 +169,49 @@ begin Self.fFilename := PATH_NONE; if (fStream <> nil) then begin - VideoDecoderInfo.close(fStream); + fVideoDecoderInfo.close(fStream); fStream := nil; end; end; function TVideoDecodeStream_FFmpeg.GetFrame(Time: Extended): PByteArray; begin - Result := PByteArray(VideoDecoderInfo.getFrame(fStream, Time)); + Result := PByteArray(fVideoDecoderInfo.getFrame(fStream, Time)); end; procedure TVideoDecodeStream_FFmpeg.SetLoop(Enable: boolean); begin - VideoDecoderInfo.setLoop(fStream, Enable); + fVideoDecoderInfo.setLoop(fStream, Enable); end; function TVideoDecodeStream_FFmpeg.GetLoop(): boolean; begin - Result := VideoDecoderInfo.getLoop(fStream); + Result := fVideoDecoderInfo.getLoop(fStream); end; procedure TVideoDecodeStream_FFmpeg.SetPosition(Time: real); begin - VideoDecoderInfo.setPosition(fStream, Time); + fVideoDecoderInfo.setPosition(fStream, Time); end; function TVideoDecodeStream_FFmpeg.GetPosition: real; begin - Result := VideoDecoderInfo.getPosition(fStream); + Result := fVideoDecoderInfo.getPosition(fStream); end; function TVideoDecodeStream_FFmpeg.GetFrameWidth(): integer; begin - Result := VideoDecoderInfo.getFrameWidth(fStream); + Result := fVideoDecoderInfo.getFrameWidth(fStream); end; function TVideoDecodeStream_FFmpeg.GetFrameHeight(): integer; begin - Result := VideoDecoderInfo.getFrameHeight(fStream); + Result := fVideoDecoderInfo.getFrameHeight(fStream); end; function TVideoDecodeStream_FFmpeg.GetFrameAspect(): real; begin - Result := VideoDecoderInfo.getFrameAspect(fStream); + Result := fVideoDecoderInfo.getFrameAspect(fStream); end; -initialization - MediaManager.Add(TVideoDecoder_FFmpeg.Create); - end. -- cgit v1.2.3