а индексировать кто будет долбаеб
This commit is contained in:
@@ -55,7 +55,6 @@ SourceArt/**/*.tga
|
||||
|
||||
# Binary Files
|
||||
Binaries
|
||||
Plugins/**/Binaries/*
|
||||
|
||||
# Builds
|
||||
Build/**
|
||||
|
||||
@@ -38,5 +38,5 @@ Version=1
|
||||
+EngineTargetsSettings=(Name="Keywords",Guid=AE89AECB47475F420D0D69A5547515DC,TargetDependencies=(33482D004789784C9DA695A682ACCA1B,AC8BFD2A41A2FB2893BB8EA0AF903E6D),AdditionalManifestDependencies=,RequiredModuleNames=,GatherFromTextFiles=(IsEnabled=False,SearchDirectories=,ExcludePathWildcards=,FileExtensions=((Pattern="h"),(Pattern="cpp"),(Pattern="ini")),ShouldGatherFromEditorOnlyData=False),GatherFromPackages=(IsEnabled=False,IncludePathWildcards=,ExcludePathWildcards=,FileExtensions=((Pattern="umap"),(Pattern="uasset")),Collections=,ExcludeClasses=,ShouldExcludeDerivedClasses=False,ShouldGatherFromEditorOnlyData=True,SkipGatherCache=False),GatherFromMetaData=(IsEnabled=True,IncludePathWildcards=((Pattern="Source/Editor/*"),(Pattern="Source/Runtime/*"),(Pattern="Source/Developer/*")),ExcludePathWildcards=((Pattern="Source/Developer/NoRedist/CommunityPortalServices/*")),KeySpecifications=((MetaDataKey=(Name="Keywords"),TextNamespace="UObjectKeywords",TextKeyPattern=(Pattern="{FieldPath}"))),ShouldGatherFromEditorOnlyData=True),ExportSettings=(CollapseMode=IdenticalTextIdAndSource,ShouldPersistCommentsOnExport=False,ShouldAddSourceLocationsAsComments=True),CompileSettings=(SkipSourceCheck=False,ValidateFormatPatterns=True,ValidateSafeWhitespace=False),ImportDialogueSettings=(RawAudioPath=(Path=""),ImportedDialogueFolder="ImportedDialogue",bImportNativeAsSource=False),NativeCultureIndex=0,SupportedCulturesStatistics=((CultureName="en"),(CultureName="es"),(CultureName="ja"),(CultureName="ko"),(CultureName="pt-BR"),(CultureName="zh-CN")))
|
||||
+EngineTargetsSettings=(Name="Category",Guid=14B8DEE642A6A7AFEB5A28B959EC373A,TargetDependencies=,AdditionalManifestDependencies=,RequiredModuleNames=,GatherFromTextFiles=(IsEnabled=False,SearchDirectories=,ExcludePathWildcards=,FileExtensions=((Pattern="h"),(Pattern="cpp"),(Pattern="ini")),ShouldGatherFromEditorOnlyData=False),GatherFromPackages=(IsEnabled=False,IncludePathWildcards=,ExcludePathWildcards=,FileExtensions=((Pattern="umap"),(Pattern="uasset")),Collections=,ExcludeClasses=,ShouldExcludeDerivedClasses=False,ShouldGatherFromEditorOnlyData=False,SkipGatherCache=False),GatherFromMetaData=(IsEnabled=True,IncludePathWildcards=((Pattern="Source/Editor/*"),(Pattern="Source/Runtime/*"),(Pattern="Source/Developer/*")),ExcludePathWildcards=((Pattern="Source/Developer/NoRedist/CommunityPortalServices/*")),KeySpecifications=((MetaDataKey=(Name="Category"),TextNamespace="UObjectCategory",TextKeyPattern=(Pattern="{FieldPath}"))),ShouldGatherFromEditorOnlyData=True),ExportSettings=(CollapseMode=IdenticalTextIdAndSource,ShouldPersistCommentsOnExport=False,ShouldAddSourceLocationsAsComments=True),CompileSettings=(SkipSourceCheck=False,ValidateFormatPatterns=True,ValidateSafeWhitespace=False),ImportDialogueSettings=(RawAudioPath=(Path=""),ImportedDialogueFolder="ImportedDialogue",bImportNativeAsSource=False),NativeCultureIndex=0,SupportedCulturesStatistics=((CultureName="en"),(CultureName="es"),(CultureName="ja"),(CultureName="ko"),(CultureName="pt-BR"),(CultureName="zh-CN")))
|
||||
-GameTargetsSettings=(Name="Game",Guid=AE0EA34A45461A25BA65A391026F19F8,TargetDependencies=(33482D004789784C9DA695A682ACCA1B,AC8BFD2A41A2FB2893BB8EA0AF903E6D),AdditionalManifestDependencies=,RequiredModuleNames=,GatherFromTextFiles=(IsEnabled=False,SearchDirectories=,ExcludePathWildcards=,FileExtensions=((Pattern="h"),(Pattern="cpp"),(Pattern="ini"))),GatherFromPackages=(IsEnabled=False,IncludePathWildcards=,ExcludePathWildcards=,FileExtensions=((Pattern="umap"),(Pattern="uasset")),ShouldGatherFromEditorOnlyData=False),GatherFromMetaData=(IsEnabled=False,IncludePathWildcards=,ExcludePathWildcards=,KeySpecifications=,ShouldGatherFromEditorOnlyData=False),NativeCultureIndex=-1,SupportedCulturesStatistics=((CultureName="en")))
|
||||
+GameTargetsSettings=(Name="Game",Guid=AE0EA34A45461A25BA65A391026F19F8,TargetDependencies=(33482D004789784C9DA695A682ACCA1B,AC8BFD2A41A2FB2893BB8EA0AF903E6D),AdditionalManifestDependencies=,RequiredModuleNames=,GatherFromTextFiles=(IsEnabled=False,SearchDirectories=,ExcludePathWildcards=,FileExtensions=((Pattern="h"),(Pattern="cpp"),(Pattern="ini")),ShouldGatherFromEditorOnlyData=False),GatherFromPackages=(IsEnabled=True,IncludePathWildcards=((PathRoot=Project,Pattern="*")),ExcludePathWildcards=,FileExtensions=((Pattern="umap"),(Pattern="uasset")),Collections=,ExcludeClasses=,ShouldExcludeDerivedClasses=False,ShouldGatherFromEditorOnlyData=False,SkipGatherCache=False),GatherFromMetaData=(IsEnabled=False,IncludePathWildcards=,ExcludePathWildcards=,KeySpecifications=,ShouldGatherFromEditorOnlyData=False),ExportSettings=(CollapseMode=IdenticalTextIdAndSource,ShouldPersistCommentsOnExport=False,ShouldAddSourceLocationsAsComments=True),CompileSettings=(SkipSourceCheck=False,ValidateFormatPatterns=True,ValidateSafeWhitespace=False),ImportDialogueSettings=(RawAudioPath=(Path=""),ImportedDialogueFolder="ImportedDialogue",bImportNativeAsSource=False),NativeCultureIndex=1,SupportedCulturesStatistics=((CultureName="en"),(CultureName="ar")))
|
||||
+GameTargetsSettings=(Name="Game",Guid=AE0EA34A45461A25BA65A391026F19F8,TargetDependencies=(33482D004789784C9DA695A682ACCA1B,AC8BFD2A41A2FB2893BB8EA0AF903E6D),AdditionalManifestDependencies=,RequiredModuleNames=,GatherFromTextFiles=(IsEnabled=False,SearchDirectories=,ExcludePathWildcards=,FileExtensions=((Pattern="h"),(Pattern="cpp"),(Pattern="ini")),ShouldGatherFromEditorOnlyData=False),GatherFromPackages=(IsEnabled=True,IncludePathWildcards=((PathRoot=Project,Pattern="Content/*")),ExcludePathWildcards=,FileExtensions=((Pattern="umap"),(Pattern="uasset")),Collections=,ExcludeClasses=,ShouldExcludeDerivedClasses=False,ShouldGatherFromEditorOnlyData=False,SkipGatherCache=False),GatherFromMetaData=(IsEnabled=False,IncludePathWildcards=,ExcludePathWildcards=,KeySpecifications=,ShouldGatherFromEditorOnlyData=False),ExportSettings=(CollapseMode=IdenticalTextIdAndSource,ShouldPersistCommentsOnExport=False,ShouldAddSourceLocationsAsComments=True),CompileSettings=(SkipSourceCheck=False,ValidateFormatPatterns=True,ValidateSafeWhitespace=False),ImportDialogueSettings=(RawAudioPath=(Path=""),ImportedDialogueFolder="ImportedDialogue",bImportNativeAsSource=False),NativeCultureIndex=0,SupportedCulturesStatistics=((CultureName="en"),(CultureName="ar")))
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ ResourceName=Game.locres
|
||||
bSkipSourceCheck=false
|
||||
bValidateFormatPatterns=true
|
||||
bValidateSafeWhitespace=false
|
||||
NativeCulture=ar
|
||||
NativeCulture=en
|
||||
CulturesToGenerate=en
|
||||
CulturesToGenerate=ar
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[CommonSettings]
|
||||
SourcePath=Content/Localization/Game
|
||||
DestinationPath=Content/Localization/Game
|
||||
NativeCulture=ar
|
||||
NativeCulture=en
|
||||
CulturesToGenerate=en
|
||||
CulturesToGenerate=ar
|
||||
ManifestName=Game.manifest
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[CommonSettings]
|
||||
SourcePath=Content/Localization/Game
|
||||
DestinationPath=Content/Localization/Game
|
||||
NativeCulture=ar
|
||||
NativeCulture=en
|
||||
CulturesToGenerate=en
|
||||
CulturesToGenerate=ar
|
||||
ManifestName=Game.manifest
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
[CommonSettings]
|
||||
ManifestDependencies=../../UE4/UE_4.25/Engine/Content/Localization/Engine/Engine.manifest
|
||||
ManifestDependencies=../../UE4/UE_4.25/Engine/Content/Localization/Editor/Editor.manifest
|
||||
ManifestDependencies=../../Engines/UE_4.25/Engine/Content/Localization/Engine/Engine.manifest
|
||||
ManifestDependencies=../../Engines/UE_4.25/Engine/Content/Localization/Editor/Editor.manifest
|
||||
SourcePath=Content/Localization/Game
|
||||
DestinationPath=Content/Localization/Game
|
||||
ManifestName=Game.manifest
|
||||
ArchiveName=Game.archive
|
||||
NativeCulture=ar
|
||||
NativeCulture=en
|
||||
CulturesToGenerate=en
|
||||
CulturesToGenerate=ar
|
||||
|
||||
[GatherTextStep0]
|
||||
CommandletClass=GatherTextFromAssets
|
||||
IncludePathFilters=%LOCPROJECTROOT%*
|
||||
IncludePathFilters=%LOCPROJECTROOT%Content/*
|
||||
ExcludePathFilters=Content/Localization/*
|
||||
PackageFileNameFilters=*.umap
|
||||
PackageFileNameFilters=*.uasset
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[CommonSettings]
|
||||
SourcePath=Content/Localization/Game
|
||||
DestinationPath=Content/Localization/Game
|
||||
NativeCulture=ar
|
||||
NativeCulture=en
|
||||
CulturesToGenerate=en
|
||||
CulturesToGenerate=ar
|
||||
ManifestName=Game.manifest
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
SourcePath=Content/Localization/Game
|
||||
ManifestName=Game.manifest
|
||||
ArchiveName=Game.archive
|
||||
NativeCulture=ar
|
||||
NativeCulture=en
|
||||
CulturesToGenerate=en
|
||||
CulturesToGenerate=ar
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[CommonSettings]
|
||||
SourcePath=Content/Localization/Game
|
||||
DestinationPath=Content/Localization/Game
|
||||
NativeCulture=ar
|
||||
NativeCulture=en
|
||||
CulturesToGenerate=en
|
||||
CulturesToGenerate=ar
|
||||
ManifestName=Game.manifest
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
[{"id":1002,"name":"Reception","editable":false,"quickSearch":true},{"id":1003,"name":"Pharmacy","editable":false,"quickSearch":true},{"id":1004,"name":"Common area","editable":false,"quickSearch":true},{"id":1005,"name":"Prayer Room","editable":false,"quickSearch":true},{"id":1006,"name":"Catering","editable":false,"quickSearch":true},{"id":1007,"name":"Shops","editable":false,"quickSearch":true},{"id":1008,"name":"Toilets","editable":false,"quickSearch":true},{"id":1009,"name":"Patient rooms","editable":false,"quickSearch":true},{"id":1010,"name":"Medical rooms","editable":false,"quickSearch":true},{"id":1011,"name":"Staff rooms","editable":false,"quickSearch":true},{"id":1012,"name":"Tech rooms","editable":false,"quickSearch":true},{"id":1013,"name":"Utility rooms","editable":false,"quickSearch":true},{"id":1014,"name":"VIP rooms","editable":false,"quickSearch":true},{"id":1025,"name":"External buildings","editable":false,"quickSearch":true},{"id":100000,"name":"Elev. lobby","editable":false,"quickSearch":true},{"id":100001,"name":"Doctor on call","editable":false,"quickSearch":false},{"id":100002,"name":"Nurse station","editable":false,"quickSearch":false},{"id":100003,"name":"Lab","editable":false,"quickSearch":false},{"id":100004,"name":"Corridor","editable":false,"quickSearch":false},{"id":100005,"name":"Pantry","editable":false,"quickSearch":false},{"id":100006,"name":"Waiting area","editable":false,"quickSearch":true},{"id":100007,"name":"Store","editable":false,"quickSearch":false},{"id":100008,"name":"Anaesthetic room","editable":false,"quickSearch":false},{"id":100009,"name":"Dialysis room","editable":false,"quickSearch":false},{"id":100010,"name":"Treatment room","editable":false,"quickSearch":false},{"id":100011,"name":"Isolation room","editable":false,"quickSearch":false},{"id":100012,"name":"Vip suite","editable":false,"quickSearch":false},{"id":100013,"name":"Lobby","editable":false,"quickSearch":false},{"id":100014,"name":"Dinning area","editable":false,"quickSearch":true},{"id":100015,"name":"MRI room","editable":false,"quickSearch":false},{"id":100016,"name":"Chest pain unit","editable":false,"quickSearch":false},{"id":100017,"name":"Exam room","editable":false,"quickSearch":false},{"id":100018,"name":"Records room","editable":false,"quickSearch":false},{"id":100019,"name":"CT scan room","editable":false,"quickSearch":false},{"id":100020,"name":"Xray room","editable":false,"quickSearch":false},{"id":100021,"name":"Billing office","editable":false,"quickSearch":true},{"id":100022,"name":"Seminar room","editable":false,"quickSearch":false},{"id":100023,"name":"Auditorioum room","editable":false,"quickSearch":true},{"id":100024,"name":"Lecture room","editable":false,"quickSearch":false},{"id":100025,"name":"Warehouse","editable":false,"quickSearch":false},{"id":100026,"name":"Electrical room","editable":false,"quickSearch":false},{"id":100027,"name":"Wheel chair storage room","editable":false,"quickSearch":true},{"id":100028,"name":"Rehab room","editable":false,"quickSearch":false},{"id":100029,"name":"CCTV room","editable":false,"quickSearch":false},{"id":100030,"name":"Bakery","editable":false,"quickSearch":false}]
|
||||
[{"id":1002,"name":"Reception","editable":false,"quickSearch":true},{"id":1003,"name":"Pharmacy","editable":false,"quickSearch":true},{"id":1004,"name":"Common area","editable":false,"quickSearch":true},{"id":1005,"name":"Prayer Room","editable":false,"quickSearch":true},{"id":1006,"name":"Catering","editable":false,"quickSearch":true},{"id":1007,"name":"Shops","editable":false,"quickSearch":true},{"id":1008,"name":"Toilets","editable":false,"quickSearch":true},{"id":1009,"name":"Patient rooms","editable":false,"quickSearch":true},{"id":1010,"name":"Medical rooms","editable":false,"quickSearch":true},{"id":1011,"name":"Staff rooms","editable":false,"quickSearch":true},{"id":1012,"name":"Tech rooms","editable":false,"quickSearch":true},{"id":1013,"name":"Utility rooms","editable":false,"quickSearch":true},{"id":1014,"name":"VIP rooms","editable":false,"quickSearch":true},{"id":1025,"name":"External buildings","editable":false,"quickSearch":true},{"id":1035,"name":"1234","editable":true,"quickSearch":false},{"id":100000,"name":"Elev. lobby","editable":false,"quickSearch":true},{"id":100001,"name":"Doctor on call","editable":false,"quickSearch":false},{"id":100002,"name":"Nurse station","editable":false,"quickSearch":false},{"id":100003,"name":"Lab","editable":false,"quickSearch":false},{"id":100004,"name":"Corridor","editable":false,"quickSearch":false},{"id":100005,"name":"Pantry","editable":false,"quickSearch":false},{"id":100006,"name":"Waiting area","editable":false,"quickSearch":true},{"id":100007,"name":"Store","editable":false,"quickSearch":false},{"id":100008,"name":"Anaesthetic room","editable":false,"quickSearch":false},{"id":100009,"name":"Dialysis room","editable":false,"quickSearch":false},{"id":100010,"name":"Treatment room","editable":false,"quickSearch":false},{"id":100011,"name":"Isolation room","editable":false,"quickSearch":false},{"id":100012,"name":"Vip suite","editable":false,"quickSearch":false},{"id":100013,"name":"Lobby","editable":false,"quickSearch":false},{"id":100014,"name":"Dinning area","editable":false,"quickSearch":true},{"id":100015,"name":"MRI room","editable":false,"quickSearch":false},{"id":100016,"name":"Chest pain unit","editable":false,"quickSearch":false},{"id":100017,"name":"Exam room","editable":false,"quickSearch":false},{"id":100018,"name":"Records room","editable":false,"quickSearch":false},{"id":100019,"name":"CT scan room","editable":false,"quickSearch":false},{"id":100020,"name":"Xray room","editable":false,"quickSearch":false},{"id":100021,"name":"Billing office","editable":false,"quickSearch":true},{"id":100022,"name":"Seminar room","editable":false,"quickSearch":false},{"id":100023,"name":"Auditorioum room","editable":false,"quickSearch":true},{"id":100024,"name":"Lecture room","editable":false,"quickSearch":false},{"id":100025,"name":"Warehouse","editable":false,"quickSearch":false},{"id":100026,"name":"Electrical room","editable":false,"quickSearch":false},{"id":100027,"name":"Wheel chair storage room","editable":false,"quickSearch":true},{"id":100028,"name":"Rehab room","editable":false,"quickSearch":false},{"id":100029,"name":"CCTV room","editable":false,"quickSearch":false},{"id":100030,"name":"Bakery","editable":false,"quickSearch":false}]
|
||||
@@ -1 +1 @@
|
||||
[{"id":1,"name":"GM1","reception":"G-1C37F","idHIS":"11111","idQMS":"qqqqq","qmsSOW":"http://localhost:1234"},{"id":2,"name":"deparment 2","reception":"G-1C10","idHIS":"22222","idQMS":"qqqqq","qmsSOW":"http://localhost:1234"},{"id":4,"name":"deparment 4","reception":"000003","idHIS":"44444","idQMS":"qqqqq","qmsSOW":"http://localhost:1234"},{"id":5,"name":"deparment 5","reception":"G-1C40","idHIS":"55555","idQMS":"qqqqq","qmsSOW":"http://localhost:1234"},{"id":1002,"name":"DIT","reception":"G-3A06","idHIS":"","idQMS":"","qmsSOW":""},{"id":1003,"name":"General Medicine","reception":"G-1C40","idHIS":"77777","idQMS":"1111","qmsSOW":""}]
|
||||
[{"id":1,"name":"GM1","reception":"G-1C37F","idHIS":"11111","idQMS":"qqqqq","qmsSOW":"http://localhost:1234"},{"id":2,"name":"deparment 2","reception":"G-1C10","idHIS":"22222","idQMS":"qqqqq","qmsSOW":"http://localhost:1234"},{"id":4,"name":"deparment 4","reception":"000003","idHIS":"44444","idQMS":"qqqqq","qmsSOW":"http://localhost:1234"},{"id":5,"name":"deparment 5","reception":"G-1C40","idHIS":"55555","idQMS":"qqqqq","qmsSOW":"http://localhost:1234"},{"id":1002,"name":"DIT","reception":"G-3A06","idHIS":"","idQMS":"","qmsSOW":""},{"id":1003,"name":"General Medicine","reception":"G-1C40","idHIS":"77777","idQMS":"1111","qmsSOW":""},{"id":1006,"name":"HR","reception":"000002","idHIS":"","idQMS":"","qmsSOW":""}]
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,2 +1,2 @@
|
||||
Date/Time,Word Count,ar,en
|
||||
2021.10.25-16.13.48,440,440,0
|
||||
2022.10.14-12.47.44,599,0,599
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
rtsp://127.0.0.1:8554/
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
Binaries/
|
||||
Intermediate/
|
||||
plugins.dat
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
set -x
|
||||
|
||||
# Control if ./Plugins/VlcMedia/ folder exists.
|
||||
if [ ! -d "./Plugins/VlcMedia/" ]; then
|
||||
printf "./Plugins/VlcMedia/ folder doesn't exist.\nRun bash script from Project (GAME) folder\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# clean-up and configure the VlcMedia plugin
|
||||
installDir=$PWD
|
||||
installDir+="/Plugins/VlcMedia/ThirdParty/vlc/Linux/x86_64-unknown-linux-gnu/"
|
||||
rm -rf $installDir
|
||||
mkdir -p $installDir
|
||||
rm -rf ./protobuf/
|
||||
rm -rf ./vlc/
|
||||
|
||||
# update Ubuntu and remove vlc
|
||||
sudo apt purge vlc
|
||||
sudo snap remove vlc
|
||||
sudo add-apt-repository --remove ppa:videolan/master-daily
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
sudo apt autoremove
|
||||
|
||||
# To build vlc from source, the following tools are needed
|
||||
sudo apt install autoconf automake libtool curl make g++ unzip
|
||||
sudo apt install git build-essential pkg-config libtool autopoint gettext
|
||||
sudo apt install subversion yasm cvs cmake ragel
|
||||
sudo apt install gperf default-jdk ant flex flex-old bison
|
||||
sudo apt install libcaca-dev libncursesw5-dev libasound2-dev lua5.2-dev libxcb-keysyms1-dev
|
||||
sudo apt install lua5.2 openjdk-8-jdk ant nasm libxcb-composite0 libxcb-composite0-dev
|
||||
sudo apt install libxcb-xv0 libxcb-xv0-dev wayland-protocols
|
||||
|
||||
# Protocol Buffers - Google's data interchange format
|
||||
git clone git://github.com/google/protobuf.git
|
||||
cd protobuf
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
make check
|
||||
sudo make install
|
||||
make clean
|
||||
sudo ldconfig # refresh shared library cache
|
||||
cd ..
|
||||
|
||||
# install vlc and make it available to the VlcMedia plugin
|
||||
git clone git://git.videolan.org/vlc.git
|
||||
cd vlc
|
||||
git checkout tags/4.0.0-dev -b 4.0.0-dev
|
||||
./bootstrap
|
||||
# VLC contribs system, included in the VLC source
|
||||
cd contrib
|
||||
mkdir native
|
||||
cd native
|
||||
../bootstrap
|
||||
|
||||
make # Create VLC contribs system code to Hotfix it
|
||||
# Hotfix for `ERROR: libmp3lame >= 3.98.3 not found` problem.
|
||||
# CREDIT # https://stackoverflow.com/a/46756012/4510033
|
||||
sed -i -e 's/\(3.98.3..lame.lame.h.lame.set.VBR.quality..lmp3lame\)/\1 -lm/' ./ffmpeg/configure
|
||||
|
||||
make
|
||||
cd ..
|
||||
cd ..
|
||||
|
||||
./configure --disable-srt --disable-dca --disable-libass --disable-css --disable-upnp --disable-chromaprint --disable-freetype --prefix=$installDir
|
||||
make
|
||||
make install
|
||||
make clean
|
||||
cd ..
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
set -x
|
||||
|
||||
# Control if ./Plugins/VlcMedia/ folder exists.
|
||||
if [ ! -d "./Plugins/VlcMedia/" ]; then
|
||||
printf "./Plugins/VlcMedia/ folder doesn't exist.\nRun bash script from Project (GAME) folder\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# clean-up and configure the VlcMedia plugin
|
||||
installDir=$PWD
|
||||
installDir+="/Plugins/VlcMedia/ThirdParty/vlc/Linux/x86_64-unknown-linux-gnu/"
|
||||
rm -rf $installDir
|
||||
mkdir -p $installDir
|
||||
#rm -rf ./protobuf/
|
||||
#rm -rf ./vlc/
|
||||
|
||||
# update Ubuntu and remove vlc
|
||||
sudo apt purge vlc
|
||||
sudo snap remove vlc
|
||||
sudo add-apt-repository --remove ppa:videolan/master-daily
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
sudo apt autoremove
|
||||
|
||||
# To build vlc from source, the following tools are needed
|
||||
sudo apt install autoconf automake libtool curl make g++ unzip
|
||||
sudo apt install git build-essential pkg-config libtool autopoint gettext
|
||||
sudo apt install subversion yasm cvs cmake ragel
|
||||
sudo apt install gperf default-jdk ant flex flex-old bison
|
||||
sudo apt install libcaca-dev libncursesw5-dev libasound2-dev lua5.2-dev libxcb-keysyms1-dev
|
||||
sudo apt install lua5.2 openjdk-8-jdk ant nasm libxcb-composite0 libxcb-composite0-dev
|
||||
sudo apt install libxcb-xv0 libxcb-xv0-dev wayland-protocols
|
||||
|
||||
# Protocol Buffers - Google's data interchange format
|
||||
#git clone git://github.com/google/protobuf.git
|
||||
cd protobuf
|
||||
./autogen.sh
|
||||
./configure
|
||||
make clean
|
||||
make
|
||||
make check
|
||||
sudo make install
|
||||
make clean
|
||||
sudo ldconfig # refresh shared library cache
|
||||
cd ..
|
||||
|
||||
# install vlc and make it available to the VlcMedia plugin
|
||||
#git clone git://git.videolan.org/vlc.git
|
||||
cd vlc
|
||||
#git checkout tags/4.0.0-dev -b 4.0.0-dev
|
||||
./bootstrap
|
||||
# VLC contribs system, included in the VLC source
|
||||
cd contrib
|
||||
mkdir native
|
||||
cd native
|
||||
../bootstrap
|
||||
|
||||
make # Create VLC contribs system code to Hotfix it
|
||||
# Hotfix for `ERROR: libmp3lame >= 3.98.3 not found` problem.
|
||||
# CREDIT # https://stackoverflow.com/a/46756012/4510033
|
||||
sed -i -e 's/\(3.98.3..lame.lame.h.lame.set.VBR.quality..lmp3lame\)/\1 -lm/' ./ffmpeg/configure
|
||||
|
||||
make
|
||||
cd ..
|
||||
cd ..
|
||||
|
||||
./configure --disable-srt --disable-dca --disable-libass --disable-css --disable-upnp --disable-chromaprint --disable-freetype --prefix=$installDir
|
||||
make clean
|
||||
make
|
||||
make install
|
||||
make clean
|
||||
cd ..
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
Copyright 2015 Epic Games, Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,101 @@
|
||||
# VlcMedia
|
||||
|
||||
Unreal Engine 4 Media Framework plug-in using the Video LAN Codec (libvlc).
|
||||
|
||||
|
||||
## About
|
||||
|
||||
This plug-in is still under development and likely has a lot of remaining issues
|
||||
to be fixed. Use in production is not yet recommended.
|
||||
|
||||
Make sure to pull the *Tag* that matches your Unreal Engine version. If you sync
|
||||
to *Master* the code may not compile, because it may depend on Engine changes
|
||||
that are not yet available in the UE4 Master branch.
|
||||
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
This plug-in was last built against **Unreal Engine 4.19** and tested
|
||||
against the following platforms:
|
||||
|
||||
- Linux (Ubuntu 16.04)
|
||||
- ~~Mac~~
|
||||
- Windows
|
||||
|
||||
**IMPORTANT**: Please note that this repository contains pre-compiled binaries
|
||||
for libvlc and its plug-ins, which are licensed under LGPL. This means that you
|
||||
cannot create monolithic builds of your game without violating LGPL, the UE4
|
||||
EULA or both. The libvlc libraries must remain dynamic libraries that are bound
|
||||
at run-time - static linking is not allowed - and the licensing related files in
|
||||
*/ThirdParty/vlc* must be retained.
|
||||
|
||||
This also means that this plug-in cannot work on platforms that do not support
|
||||
dynamically linked libraries (i.e. iOS, HTML5) or do not currently implement
|
||||
support for it (i.e. Android, XboxOne).
|
||||
|
||||
Epic is in the process of adding plug-in support to monolithic builds, but there
|
||||
is no ETA yet. Once this is supported, you will be able to distribute monolithic
|
||||
game and server builds with VlcMedia, provided that the libvlc libraries and
|
||||
plug-ins remain as separate DLLs.
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
A relatively recent version of libvlc is required. The latest stable release
|
||||
(currently 2.2.1) is not sufficient.
|
||||
|
||||
For Mac and Windows, the following nightly builds are currently included:
|
||||
* macOS: vlc-4.0.0-20180319-0303-dev
|
||||
* Win32: vlc-4.0.0-20180319-0303-dev-win32
|
||||
* Win64: vlc-4.0.0-20180319-1331-dev-win64
|
||||
|
||||
Nightly builds can be downloaded from the VideoLAN web site (see below).
|
||||
|
||||
For debugging on Win32 and Win64, you can download debug builds and replace the
|
||||
corresponding files and folders in the *VlcMedia/ThirdParty/vlc/* directory.
|
||||
|
||||
### Linux (Ubuntu 16.04)
|
||||
|
||||
A suitable version of **libvlc** must be installed or compiled from source. If
|
||||
you ship your game on Linux, you will likely want to include libvlc with it, so
|
||||
that users don't have to install it themselves. We will eventually include those
|
||||
binaries in this repository, although it is not clear what distros should be
|
||||
supported and where the builds are coming from. A better workflow needs to be
|
||||
established for this (https://github.com/ue4plugins/VlcMedia/issues/17).
|
||||
|
||||
To clean up, clone, make and install VLC (including libvlc) into your project,
|
||||
run the *VlcMedia/Build/Vlc4LinuxCloneMakeInstall.sh* script from within your
|
||||
project's root folder. If you later need to make and re-install VLC from the
|
||||
existing VLC code, run the *Vlc4LinuxMakeInstall.sh* script instead.
|
||||
|
||||
### Mac, Windows
|
||||
|
||||
All required libraries and plug-ins are included in the *ThirdParty* directory
|
||||
and work out of the box.
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
This plug-in requires Visual Studio and either a C++ code project or the full
|
||||
Unreal Engine 4 source code from GitHub. If you are new to programming in UE4,
|
||||
please see the official [Programming Guide](https://docs.unrealengine.com/latest/INT/Programming/index.html)!
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
You can use this plug-in as a project plug-in, or an Engine plug-in.
|
||||
|
||||
If you use it as a project plug-in, clone this repository into your project's
|
||||
*/Plugins* directory and compile your game in Visual Studio. A C++ code project
|
||||
is required for this to work.
|
||||
|
||||
If you use it as an Engine plug-in, clone this repository into the
|
||||
*/Engine/Plugins/Media* directory and compile your game. Full Unreal Engine 4
|
||||
source code from GitHub is required for this.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
* [VideoLAN Homepage](http://videolan.org)
|
||||
* [VideoLAN Nightly Builds](http://nightlies.videolan.org/)
|
||||
* [Introduction to UE4 Plugins](https://wiki.unrealengine.com/An_Introduction_to_UE4_Plugins)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,169 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "IMediaAudioSample.h"
|
||||
#include "MediaObjectPool.h"
|
||||
#include "Misc/Timespan.h"
|
||||
#include "Templates/SharedPointer.h"
|
||||
|
||||
|
||||
/**
|
||||
* Audio sample generated by VLC player.
|
||||
*/
|
||||
class FVlcMediaAudioSample
|
||||
: public IMediaAudioSample
|
||||
, public IMediaPoolable
|
||||
{
|
||||
public:
|
||||
|
||||
/** Default constructor. */
|
||||
FVlcMediaAudioSample()
|
||||
: Buffer(nullptr)
|
||||
, BufferSize(0)
|
||||
, Channels(0)
|
||||
, Duration(FTimespan::Zero())
|
||||
, Frames(0)
|
||||
, SampleFormat(EMediaAudioSampleFormat::Undefined)
|
||||
, SampleRate(0)
|
||||
, Time(FTimespan::Zero())
|
||||
{ }
|
||||
|
||||
/** Virtual destructor. */
|
||||
virtual ~FVlcMediaAudioSample()
|
||||
{
|
||||
FreeBuffer();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Initialize the sample.
|
||||
*
|
||||
* @param InBuffer The raw audio sample buffer.
|
||||
* @param InBufferSize The size of the buffer (in bytes).
|
||||
* @param InFrames Number of frames in the buffer.
|
||||
* @param InChannels Number of audio channels.
|
||||
* @param InSampleFormat The sample format.
|
||||
* @param InSampleRate The sample rate.
|
||||
* @param InTime The sample time (in the player's local clock).
|
||||
* @param InDuration The duration for which the sample is valid.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool Initialize(
|
||||
void* InBuffer,
|
||||
uint32 InBufferSize,
|
||||
uint32 InFrames,
|
||||
uint32 InChannels,
|
||||
EMediaAudioSampleFormat InSampleFormat,
|
||||
uint32 InSampleRate,
|
||||
FTimespan InTime,
|
||||
FTimespan InDuration)
|
||||
{
|
||||
if ((InBuffer == nullptr) || (InBufferSize == 0) || (InSampleFormat == EMediaAudioSampleFormat::Undefined))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (InBufferSize > BufferSize)
|
||||
{
|
||||
Buffer = FMemory::Realloc(Buffer, InBufferSize);
|
||||
BufferSize = InBufferSize;
|
||||
}
|
||||
|
||||
FMemory::Memcpy(Buffer, InBuffer, InBufferSize);
|
||||
|
||||
Channels = InChannels;
|
||||
Duration = InDuration;
|
||||
Frames = InFrames;
|
||||
SampleFormat = InSampleFormat;
|
||||
SampleRate = InSampleRate;
|
||||
Time = InTime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//~ IMediaAudioSample interface
|
||||
|
||||
virtual const void* GetBuffer() override
|
||||
{
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
virtual uint32 GetChannels() const override
|
||||
{
|
||||
return Channels;
|
||||
}
|
||||
|
||||
virtual uint32 GetFrames() const override
|
||||
{
|
||||
return Frames;
|
||||
}
|
||||
|
||||
virtual FTimespan GetDuration() const override
|
||||
{
|
||||
return Duration;
|
||||
}
|
||||
|
||||
virtual EMediaAudioSampleFormat GetFormat() const override
|
||||
{
|
||||
return SampleFormat;
|
||||
}
|
||||
|
||||
virtual uint32 GetSampleRate() const override
|
||||
{
|
||||
return SampleRate;
|
||||
}
|
||||
|
||||
virtual FTimespan GetTime() const override
|
||||
{
|
||||
return Time;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Free the sample buffer. */
|
||||
void FreeBuffer()
|
||||
{
|
||||
if (Buffer != nullptr)
|
||||
{
|
||||
FMemory::Free(Buffer);
|
||||
|
||||
Buffer = nullptr;
|
||||
BufferSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** The sample's frame buffer. */
|
||||
void* Buffer;
|
||||
|
||||
/** Allocated size of the buffer (in bytes). */
|
||||
SIZE_T BufferSize;
|
||||
|
||||
/** Number of audio channels. */
|
||||
uint32 Channels;
|
||||
|
||||
/** Duration for which the sample is valid. */
|
||||
FTimespan Duration;
|
||||
|
||||
/** Number of frames in the buffer. */
|
||||
uint32 Frames;
|
||||
|
||||
/** The sample format. */
|
||||
EMediaAudioSampleFormat SampleFormat;
|
||||
|
||||
/** Audio sample rate (in samples per second). */
|
||||
uint32 SampleRate;
|
||||
|
||||
/** Play time for which the sample was generated. */
|
||||
FTimespan Time;
|
||||
};
|
||||
|
||||
|
||||
/** Implements a pool for VLC audio sample objects. */
|
||||
class FVlcMediaAudioSamplePool : public TMediaObjectPool<FVlcMediaAudioSample> { };
|
||||
@@ -0,0 +1,462 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VlcMediaCallbacks.h"
|
||||
#include "VlcMediaPrivate.h"
|
||||
|
||||
#include "IMediaAudioSample.h"
|
||||
#include "IMediaOptions.h"
|
||||
#include "IMediaTextureSample.h"
|
||||
#include "MediaSamples.h"
|
||||
|
||||
#include "Vlc.h"
|
||||
#include "VlcMediaAudioSample.h"
|
||||
#include "VlcMediaTextureSample.h"
|
||||
|
||||
|
||||
/* FVlcMediaOutput structors
|
||||
*****************************************************************************/
|
||||
|
||||
FVlcMediaCallbacks::FVlcMediaCallbacks()
|
||||
: AudioChannels(0)
|
||||
, AudioSampleFormat(EMediaAudioSampleFormat::Int16)
|
||||
, AudioSamplePool(new FVlcMediaAudioSamplePool)
|
||||
, AudioSampleRate(0)
|
||||
, AudioSampleSize(0)
|
||||
, CurrentTime(FTimespan::Zero())
|
||||
, Player(nullptr)
|
||||
, Samples(new FMediaSamples)
|
||||
, VideoBufferDim(FIntPoint::ZeroValue)
|
||||
, VideoBufferStride(0)
|
||||
, VideoFrameDuration(FTimespan::Zero())
|
||||
, VideoOutputDim(FIntPoint::ZeroValue)
|
||||
, VideoPreviousTime(FTimespan::MinValue())
|
||||
, VideoSampleFormat(EMediaTextureSampleFormat::CharAYUV)
|
||||
, VideoSamplePool(new FVlcMediaTextureSamplePool)
|
||||
{ }
|
||||
|
||||
|
||||
FVlcMediaCallbacks::~FVlcMediaCallbacks()
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
delete AudioSamplePool;
|
||||
AudioSamplePool = nullptr;
|
||||
|
||||
delete Samples;
|
||||
Samples = nullptr;
|
||||
|
||||
delete VideoSamplePool;
|
||||
VideoSamplePool = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/* FVlcMediaOutput interface
|
||||
*****************************************************************************/
|
||||
|
||||
IMediaSamples& FVlcMediaCallbacks::GetSamples()
|
||||
{
|
||||
return *Samples;
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::Initialize(FLibvlcMediaPlayer& InPlayer)
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
Player = &InPlayer;
|
||||
|
||||
// register callbacks
|
||||
FVlc::AudioSetFormatCallbacks(
|
||||
Player,
|
||||
&FVlcMediaCallbacks::StaticAudioSetupCallback,
|
||||
&FVlcMediaCallbacks::StaticAudioCleanupCallback
|
||||
);
|
||||
|
||||
FVlc::AudioSetCallbacks(
|
||||
Player,
|
||||
&FVlcMediaCallbacks::StaticAudioPlayCallback,
|
||||
&FVlcMediaCallbacks::StaticAudioPauseCallback,
|
||||
&FVlcMediaCallbacks::StaticAudioResumeCallback,
|
||||
&FVlcMediaCallbacks::StaticAudioFlushCallback,
|
||||
&FVlcMediaCallbacks::StaticAudioDrainCallback,
|
||||
this
|
||||
);
|
||||
|
||||
FVlc::VideoSetFormatCallbacks(
|
||||
Player,
|
||||
&FVlcMediaCallbacks::StaticVideoSetupCallback,
|
||||
&FVlcMediaCallbacks::StaticVideoCleanupCallback
|
||||
);
|
||||
|
||||
FVlc::VideoSetCallbacks(
|
||||
Player,
|
||||
&FVlcMediaCallbacks::StaticVideoLockCallback,
|
||||
&FVlcMediaCallbacks::StaticVideoUnlockCallback,
|
||||
&FVlcMediaCallbacks::StaticVideoDisplayCallback,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::Shutdown()
|
||||
{
|
||||
if (Player == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// unregister callbacks
|
||||
FVlc::AudioSetCallbacks(Player, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
FVlc::AudioSetFormatCallbacks(Player, nullptr, nullptr);
|
||||
|
||||
FVlc::VideoSetCallbacks(Player, nullptr, nullptr, nullptr, nullptr);
|
||||
FVlc::VideoSetFormatCallbacks(Player, nullptr, nullptr);
|
||||
|
||||
AudioSamplePool->Reset();
|
||||
VideoSamplePool->Reset();
|
||||
|
||||
CurrentTime = FTimespan::Zero();
|
||||
Player = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/* FVlcMediaOutput static functions
|
||||
*****************************************************************************/
|
||||
|
||||
void FVlcMediaCallbacks::StaticAudioCleanupCallback(void* Opaque)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticAudioCleanupCallback"), Opaque);
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::StaticAudioDrainCallback(void* Opaque)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticAudioDrainCallback"), Opaque);
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::StaticAudioFlushCallback(void* Opaque, int64 Timestamp)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticAudioFlushCallback"), Opaque);
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::StaticAudioPauseCallback(void* Opaque, int64 Timestamp)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticAudioPauseCallback (Timestamp = %i)"), Opaque, Timestamp);
|
||||
|
||||
// do nothing; pausing is handled in Update
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::StaticAudioPlayCallback(void* Opaque, void* Samples, uint32 Count, int64 Timestamp)
|
||||
{
|
||||
auto Callbacks = (FVlcMediaCallbacks*)Opaque;
|
||||
|
||||
if (Callbacks == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticAudioPlayCallback (Count = %i, Timestamp = %i, Queue = %i)"),
|
||||
Opaque,
|
||||
Count,
|
||||
Timestamp,
|
||||
Callbacks->Samples->NumAudio()
|
||||
);
|
||||
|
||||
// create & add sample to queue
|
||||
auto AudioSample = Callbacks->AudioSamplePool->AcquireShared();
|
||||
|
||||
const FTimespan Delay = FTimespan::FromMicroseconds(FVlc::Delay(Timestamp));
|
||||
const FTimespan Duration = FTimespan::FromMicroseconds((Count * 1000000) / Callbacks->AudioSampleRate);
|
||||
const SIZE_T SamplesSize = Count * Callbacks->AudioSampleSize * Callbacks->AudioChannels;
|
||||
|
||||
if (AudioSample->Initialize(
|
||||
Samples,
|
||||
SamplesSize,
|
||||
Count,
|
||||
Callbacks->AudioChannels,
|
||||
Callbacks->AudioSampleFormat,
|
||||
Callbacks->AudioSampleRate,
|
||||
Callbacks->CurrentTime + Delay,
|
||||
Duration))
|
||||
{
|
||||
Callbacks->Samples->AddAudio(AudioSample);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::StaticAudioResumeCallback(void* Opaque, int64 Timestamp)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticAudioResumeCallback (Timestamp = %i)"), Opaque, Timestamp);
|
||||
|
||||
// do nothing; resuming is handled in Update
|
||||
}
|
||||
|
||||
|
||||
int FVlcMediaCallbacks::StaticAudioSetupCallback(void** Opaque, ANSICHAR* Format, uint32* Rate, uint32* Channels)
|
||||
{
|
||||
auto Callbacks = *(FVlcMediaCallbacks**)Opaque;
|
||||
|
||||
if (Callbacks == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticAudioSetupCallback (Format = %s, Rate = %i, Channels = %i)"),
|
||||
Opaque,
|
||||
ANSI_TO_TCHAR(Format),
|
||||
*Rate,
|
||||
*Channels
|
||||
);
|
||||
|
||||
// setup audio format
|
||||
if (*Channels > 8)
|
||||
{
|
||||
*Channels = 8;
|
||||
}
|
||||
|
||||
if (FMemory::Memcmp(Format, "S8 ", 4) == 0)
|
||||
{
|
||||
Callbacks->AudioSampleFormat = EMediaAudioSampleFormat::Int8;
|
||||
Callbacks->AudioSampleSize = 1;
|
||||
}
|
||||
else if (FMemory::Memcmp(Format, "S16N", 4) == 0)
|
||||
{
|
||||
Callbacks->AudioSampleFormat = EMediaAudioSampleFormat::Int16;
|
||||
Callbacks->AudioSampleSize = 2;
|
||||
}
|
||||
else if (FMemory::Memcmp(Format, "S32N", 4) == 0)
|
||||
{
|
||||
Callbacks->AudioSampleFormat = EMediaAudioSampleFormat::Int32;
|
||||
Callbacks->AudioSampleSize = 4;
|
||||
}
|
||||
else if (FMemory::Memcmp(Format, "FL32", 4) == 0)
|
||||
{
|
||||
Callbacks->AudioSampleFormat = EMediaAudioSampleFormat::Float;
|
||||
Callbacks->AudioSampleSize = 4;
|
||||
}
|
||||
else if (FMemory::Memcmp(Format, "FL64", 4) == 0)
|
||||
{
|
||||
Callbacks->AudioSampleFormat = EMediaAudioSampleFormat::Double;
|
||||
Callbacks->AudioSampleSize = 8;
|
||||
}
|
||||
else if (FMemory::Memcmp(Format, "U8 ", 4) == 0)
|
||||
{
|
||||
// unsigned integer fall back
|
||||
FMemory::Memcpy(Format, "S8 ", 4);
|
||||
Callbacks->AudioSampleFormat = EMediaAudioSampleFormat::Int8;
|
||||
Callbacks->AudioSampleSize = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unsupported format fall back
|
||||
FMemory::Memcpy(Format, "S16N", 4);
|
||||
Callbacks->AudioSampleFormat = EMediaAudioSampleFormat::Int16;
|
||||
Callbacks->AudioSampleSize = 2;
|
||||
}
|
||||
|
||||
Callbacks->AudioChannels = *Channels;
|
||||
Callbacks->AudioSampleRate = *Rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::StaticVideoCleanupCallback(void *Opaque)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::StaticVideoDisplayCallback(void* Opaque, void* Picture)
|
||||
{
|
||||
auto Callbacks = (FVlcMediaCallbacks*)Opaque;
|
||||
auto VideoSample = (FVlcMediaTextureSample*)Picture;
|
||||
|
||||
if ((Callbacks == nullptr) || (VideoSample == nullptr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticVideoDisplayCallback (CurrentTime = %s, Queue = %i)"),
|
||||
Opaque, *Callbacks->CurrentTime.ToString(),
|
||||
Callbacks->Samples->NumVideoSamples()
|
||||
);
|
||||
|
||||
VideoSample->SetTime(Callbacks->CurrentTime);
|
||||
|
||||
// add sample to queue
|
||||
Callbacks->Samples->AddVideo(Callbacks->VideoSamplePool->ToShared(VideoSample));
|
||||
}
|
||||
|
||||
|
||||
void* FVlcMediaCallbacks::StaticVideoLockCallback(void* Opaque, void** Planes)
|
||||
{
|
||||
auto Callbacks = (FVlcMediaCallbacks*)Opaque;
|
||||
check(Callbacks != nullptr);
|
||||
|
||||
FMemory::Memzero(Planes, FVlc::MaxPlanes * sizeof(void*));
|
||||
|
||||
// skip if already processed
|
||||
if (Callbacks->VideoPreviousTime == Callbacks->CurrentTime)
|
||||
{
|
||||
// VLC currently requires a valid buffer or it will crash
|
||||
Planes[0] = FMemory::Malloc(Callbacks->VideoBufferStride * Callbacks->VideoBufferDim.Y, 32);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticVideoLockCallback (CurrentTime = %s)"),
|
||||
Opaque,
|
||||
*Callbacks->CurrentTime.ToString()
|
||||
);
|
||||
|
||||
// create & initialize video sample
|
||||
auto VideoSample = Callbacks->VideoSamplePool->Acquire();
|
||||
|
||||
if (VideoSample == nullptr)
|
||||
{
|
||||
// VLC currently requires a valid buffer or it will crash
|
||||
Planes[0] = FMemory::Malloc(Callbacks->VideoBufferStride * Callbacks->VideoBufferDim.Y, 32);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!VideoSample->Initialize(
|
||||
Callbacks->VideoBufferDim,
|
||||
Callbacks->VideoOutputDim,
|
||||
Callbacks->VideoSampleFormat,
|
||||
Callbacks->VideoBufferStride,
|
||||
Callbacks->VideoFrameDuration))
|
||||
{
|
||||
// VLC currently requires a valid buffer or it will crash
|
||||
Planes[0] = FMemory::Malloc(Callbacks->VideoBufferStride * Callbacks->VideoBufferDim.Y, 32);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Callbacks->VideoPreviousTime = Callbacks->CurrentTime;
|
||||
Planes[0] = VideoSample->GetMutableBuffer();
|
||||
|
||||
return VideoSample; // passed as Picture into unlock & display callbacks
|
||||
|
||||
}
|
||||
|
||||
|
||||
unsigned FVlcMediaCallbacks::StaticVideoSetupCallback(void** Opaque, char* Chroma, unsigned* Width, unsigned* Height, unsigned* Pitches, unsigned* Lines)
|
||||
{
|
||||
auto Callbacks = *(FVlcMediaCallbacks**)Opaque;
|
||||
|
||||
if (Callbacks == nullptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticVideoSetupCallback (Chroma = %s, Dim = %ix%i)"),
|
||||
Opaque,
|
||||
ANSI_TO_TCHAR(Chroma),
|
||||
*Width,
|
||||
*Height
|
||||
);
|
||||
|
||||
// get video output size
|
||||
if (FVlc::VideoGetSize(Callbacks->Player, 0, (uint32*)&Callbacks->VideoOutputDim.X, (uint32*)&Callbacks->VideoOutputDim.Y) != 0)
|
||||
{
|
||||
Callbacks->VideoBufferDim = FIntPoint::ZeroValue;
|
||||
Callbacks->VideoOutputDim = FIntPoint::ZeroValue;
|
||||
Callbacks->VideoBufferStride = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Callbacks->VideoOutputDim.GetMin() <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// determine decoder & sample formats
|
||||
Callbacks->VideoBufferDim = FIntPoint(*Width, *Height);
|
||||
|
||||
if (FCStringAnsi::Stricmp(Chroma, "AYUV") == 0)
|
||||
{
|
||||
Callbacks->VideoSampleFormat = EMediaTextureSampleFormat::CharAYUV;
|
||||
Callbacks->VideoBufferStride = *Width * 4;
|
||||
}
|
||||
else if (FCStringAnsi::Stricmp(Chroma, "RV32") == 0)
|
||||
{
|
||||
Callbacks->VideoSampleFormat = EMediaTextureSampleFormat::CharBGRA;
|
||||
Callbacks->VideoBufferStride = *Width * 4;
|
||||
}
|
||||
else if ((FCStringAnsi::Stricmp(Chroma, "UYVY") == 0) ||
|
||||
(FCStringAnsi::Stricmp(Chroma, "Y422") == 0) ||
|
||||
(FCStringAnsi::Stricmp(Chroma, "UYNV") == 0) ||
|
||||
(FCStringAnsi::Stricmp(Chroma, "HDYC") == 0))
|
||||
{
|
||||
Callbacks->VideoSampleFormat = EMediaTextureSampleFormat::CharUYVY;
|
||||
Callbacks->VideoBufferStride = *Width * 2;
|
||||
}
|
||||
else if ((FCStringAnsi::Stricmp(Chroma, "YUY2") == 0) ||
|
||||
(FCStringAnsi::Stricmp(Chroma, "V422") == 0) ||
|
||||
(FCStringAnsi::Stricmp(Chroma, "YUYV") == 0))
|
||||
{
|
||||
Callbacks->VideoSampleFormat = EMediaTextureSampleFormat::CharYUY2;
|
||||
Callbacks->VideoBufferStride = *Width * 2;
|
||||
}
|
||||
else if (FCStringAnsi::Stricmp(Chroma, "YVYU") == 0)
|
||||
{
|
||||
Callbacks->VideoSampleFormat = EMediaTextureSampleFormat::CharYVYU;
|
||||
Callbacks->VideoBufferStride = *Width * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reconfigure output for natively supported format
|
||||
FLibvlcChromaDescription* ChromaDescr = FVlc::FourccGetChromaDescription(*(FLibvlcFourcc*)Chroma);
|
||||
|
||||
if (ChromaDescr->PlaneCount == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ChromaDescr->PlaneCount > 1)
|
||||
{
|
||||
FMemory::Memcpy(Chroma, "YUY2", 4);
|
||||
|
||||
Callbacks->VideoBufferDim = FIntPoint(Align(Callbacks->VideoOutputDim.X, 16) / 2, Align(Callbacks->VideoOutputDim.Y, 16));
|
||||
Callbacks->VideoSampleFormat = EMediaTextureSampleFormat::CharYUY2;
|
||||
Callbacks->VideoBufferStride = Callbacks->VideoBufferDim.X * 4;
|
||||
*Height = Callbacks->VideoBufferDim.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
FMemory::Memcpy(Chroma, "RV32", 4);
|
||||
|
||||
Callbacks->VideoBufferDim = Callbacks->VideoOutputDim;
|
||||
Callbacks->VideoSampleFormat = EMediaTextureSampleFormat::CharBGRA;
|
||||
Callbacks->VideoBufferStride = Callbacks->VideoBufferDim.X * 4;
|
||||
}
|
||||
}
|
||||
|
||||
// get other video properties
|
||||
//Callbacks->VideoFrameDuration = FTimespan::FromSeconds(1.0 / FVlc::MediaPlayerGetFps(Callbacks->Player));
|
||||
Callbacks->VideoFrameDuration = FTimespan::FromMilliseconds(1);
|
||||
|
||||
// initialize decoder
|
||||
Lines[0] = Callbacks->VideoBufferDim.Y;
|
||||
Pitches[0] = Callbacks->VideoBufferStride;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaCallbacks::StaticVideoUnlockCallback(void* Opaque, void* Picture, void* const* Planes)
|
||||
{
|
||||
if ((Opaque != nullptr) && (Picture != nullptr))
|
||||
{
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Callbacks %llx: StaticVideoUnlockCallback"), Opaque);
|
||||
}
|
||||
|
||||
// discard temporary buffer for VLC crash workaround
|
||||
if ((Picture == nullptr) && (Planes != nullptr) && (Planes[0] != nullptr))
|
||||
{
|
||||
FMemory::Free(Planes[0]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "IMediaAudioSample.h"
|
||||
#include "IMediaTextureSample.h"
|
||||
|
||||
class FMediaSamples;
|
||||
class FVlcMediaAudioSamplePool;
|
||||
class FVlcMediaTextureSamplePool;
|
||||
class IMediaOptions;
|
||||
class IMediaAudioSink;
|
||||
class IMediaOverlaySink;
|
||||
class IMediaSamples;
|
||||
class IMediaTextureSink;
|
||||
|
||||
struct FLibvlcMediaPlayer;
|
||||
|
||||
|
||||
/**
|
||||
* Handles VLC callbacks.
|
||||
*/
|
||||
class FVlcMediaCallbacks
|
||||
{
|
||||
public:
|
||||
|
||||
/** Default constructor. */
|
||||
FVlcMediaCallbacks();
|
||||
|
||||
/** Virtual destructor. */
|
||||
~FVlcMediaCallbacks();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get the output media samples.
|
||||
*
|
||||
* @return Media samples interface.
|
||||
*/
|
||||
IMediaSamples& GetSamples();
|
||||
|
||||
/**
|
||||
* Initialize the handler for the specified media player.
|
||||
*
|
||||
* @param InPlayer The media player that owns this handler.
|
||||
*/
|
||||
void Initialize(FLibvlcMediaPlayer& InPlayer);
|
||||
|
||||
/**
|
||||
* Set the player's current time.
|
||||
*
|
||||
* @param Time The player's play time.
|
||||
*/
|
||||
void SetCurrentTime(FTimespan Time)
|
||||
{
|
||||
CurrentTime = Time;
|
||||
}
|
||||
|
||||
/** Shut down the callback handler. */
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
|
||||
/** Handles audio cleanup callbacks from VLC.*/
|
||||
static void StaticAudioCleanupCallback(void* Opaque);
|
||||
|
||||
/** Handles audio drain callbacks from VLC. */
|
||||
static void StaticAudioDrainCallback(void* Opaque);
|
||||
|
||||
/** Handles audio flush callbacks from VLC. */
|
||||
static void StaticAudioFlushCallback(void* Opaque, int64 Timestamp);
|
||||
|
||||
/** Handles audio pause callbacks from VLC. */
|
||||
static void StaticAudioPauseCallback(void* Opaque, int64 Timestamp);
|
||||
|
||||
/** Handles audio play callbacks from VLC. */
|
||||
static void StaticAudioPlayCallback(void* Opaque, void* Samples, uint32 Count, int64 Timestamp);
|
||||
|
||||
/** Handles audio resume callbacks from VLC. */
|
||||
static void StaticAudioResumeCallback(void* Opaque, int64 Timestamp);
|
||||
|
||||
/** Handles audio setup callbacks from VLC. */
|
||||
static int StaticAudioSetupCallback(void** Opaque, ANSICHAR* Format, uint32* Rate, uint32* Channels);
|
||||
|
||||
/** Handles video cleanup callbacks from VLC. */
|
||||
static void StaticVideoCleanupCallback(void *Opaque);
|
||||
|
||||
/** Handles display callbacks from VLC. */
|
||||
static void StaticVideoDisplayCallback(void* Opaque, void* Picture);
|
||||
|
||||
/** Handles buffer lock callbacks from VLC. */
|
||||
static void* StaticVideoLockCallback(void* Opaque, void** Planes);
|
||||
|
||||
/** Handles video setup callbacks from VLC. */
|
||||
static unsigned StaticVideoSetupCallback(void** Opaque, char* Chroma, unsigned* Width, unsigned* Height, unsigned* Pitches, unsigned* Lines);
|
||||
|
||||
/** Handles buffer unlock callbacks from VLC. */
|
||||
static void StaticVideoUnlockCallback(void* Opaque, void* Picture, void* const* Planes);
|
||||
|
||||
private:
|
||||
|
||||
/** Current number of channels in audio samples( accessed by VLC thread only). */
|
||||
uint32 AudioChannels;
|
||||
|
||||
/** Current audio sample format (accessed by VLC thread only). */
|
||||
EMediaAudioSampleFormat AudioSampleFormat;
|
||||
|
||||
/** Audio sample object pool. */
|
||||
FVlcMediaAudioSamplePool* AudioSamplePool;
|
||||
|
||||
/** Current audio sample rate (accessed by VLC thread only). */
|
||||
uint32 AudioSampleRate;
|
||||
|
||||
/** Size of a single audio sample (in bytes). */
|
||||
SIZE_T AudioSampleSize;
|
||||
|
||||
/** The player's current time. */
|
||||
FTimespan CurrentTime;
|
||||
|
||||
/** The VLC media player object. */
|
||||
FLibvlcMediaPlayer* Player;
|
||||
|
||||
/** The output media samples. */
|
||||
FMediaSamples* Samples;
|
||||
|
||||
/** Current video buffer dimensions (accessed by VLC thread only; may be larger than VideoOutputDim). */
|
||||
FIntPoint VideoBufferDim;
|
||||
|
||||
/** Number of bytes per row of video pixels. */
|
||||
uint32 VideoBufferStride;
|
||||
|
||||
/** Current duration of video frames. */
|
||||
FTimespan VideoFrameDuration;
|
||||
|
||||
/** Current video output dimensions (accessed by VLC thread only). */
|
||||
FIntPoint VideoOutputDim;
|
||||
|
||||
/** Play time of the previous frame. */
|
||||
FTimespan VideoPreviousTime;
|
||||
|
||||
/** Current video sample format (accessed by VLC thread only). */
|
||||
EMediaTextureSampleFormat VideoSampleFormat;
|
||||
|
||||
/** Video sample object pool. */
|
||||
FVlcMediaTextureSamplePool* VideoSamplePool;
|
||||
};
|
||||
@@ -0,0 +1,534 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VlcMediaPlayer.h"
|
||||
#include "VlcMediaPrivate.h"
|
||||
|
||||
#include "IMediaEventSink.h"
|
||||
#include "IMediaOptions.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Serialization/ArrayReader.h"
|
||||
|
||||
#include "Vlc.h"
|
||||
#include "VlcMediaUtils.h"
|
||||
|
||||
|
||||
/* FVlcMediaPlayer structors
|
||||
*****************************************************************************/
|
||||
|
||||
FVlcMediaPlayer::FVlcMediaPlayer(IMediaEventSink& InEventSink, FLibvlcInstance* InVlcInstance)
|
||||
: CurrentRate(0.0f)
|
||||
, CurrentTime(FTimespan::Zero())
|
||||
, EventSink(InEventSink)
|
||||
, MediaSource(InVlcInstance)
|
||||
, Player(nullptr)
|
||||
, ShouldLoop(false)
|
||||
{ }
|
||||
|
||||
|
||||
FVlcMediaPlayer::~FVlcMediaPlayer()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
/* IMediaControls interface
|
||||
*****************************************************************************/
|
||||
|
||||
bool FVlcMediaPlayer::CanControl(EMediaControl Control) const
|
||||
{
|
||||
if (Player == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Control == EMediaControl::Pause)
|
||||
{
|
||||
return (FVlc::MediaPlayerCanPause(Player) != 0);
|
||||
}
|
||||
|
||||
if (Control == EMediaControl::Resume)
|
||||
{
|
||||
return (FVlc::MediaPlayerGetState(Player) != ELibvlcState::Playing);
|
||||
}
|
||||
|
||||
if ((Control == EMediaControl::Scrub) || (Control == EMediaControl::Seek))
|
||||
{
|
||||
return (FVlc::MediaPlayerIsSeekable(Player) != 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
FTimespan FVlcMediaPlayer::GetDuration() const
|
||||
{
|
||||
return MediaSource.GetDuration();
|
||||
}
|
||||
|
||||
|
||||
float FVlcMediaPlayer::GetRate() const
|
||||
{
|
||||
return CurrentRate;
|
||||
}
|
||||
|
||||
|
||||
EMediaState FVlcMediaPlayer::GetState() const
|
||||
{
|
||||
if (Player == nullptr)
|
||||
{
|
||||
return EMediaState::Closed;
|
||||
}
|
||||
|
||||
ELibvlcState State = FVlc::MediaPlayerGetState(Player);
|
||||
|
||||
switch (State)
|
||||
{
|
||||
case ELibvlcState::Error:
|
||||
return EMediaState::Error;
|
||||
|
||||
case ELibvlcState::Buffering:
|
||||
case ELibvlcState::Opening:
|
||||
return EMediaState::Preparing;
|
||||
|
||||
case ELibvlcState::Paused:
|
||||
return EMediaState::Paused;
|
||||
|
||||
case ELibvlcState::Playing:
|
||||
return EMediaState::Playing;
|
||||
|
||||
case ELibvlcState::Ended:
|
||||
case ELibvlcState::NothingSpecial:
|
||||
case ELibvlcState::Stopped:
|
||||
return EMediaState::Stopped;
|
||||
}
|
||||
|
||||
return EMediaState::Error; // should never get here
|
||||
}
|
||||
|
||||
|
||||
EMediaStatus FVlcMediaPlayer::GetStatus() const
|
||||
{
|
||||
return (GetState() == EMediaState::Preparing) ? EMediaStatus::Buffering : EMediaStatus::None;
|
||||
}
|
||||
|
||||
|
||||
TRangeSet<float> FVlcMediaPlayer::GetSupportedRates(EMediaRateThinning Thinning) const
|
||||
{
|
||||
TRangeSet<float> Result;
|
||||
|
||||
if (Thinning == EMediaRateThinning::Thinned)
|
||||
{
|
||||
Result.Add(TRange<float>::Inclusive(0.0f, 10.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.Add(TRange<float>::Inclusive(0.0f, 1.0f));
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
FTimespan FVlcMediaPlayer::GetTime() const
|
||||
{
|
||||
return CurrentTime;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaPlayer::IsLooping() const
|
||||
{
|
||||
return ShouldLoop;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaPlayer::Seek(const FTimespan& Time)
|
||||
{
|
||||
ELibvlcState State = FVlc::MediaPlayerGetState(Player);
|
||||
|
||||
if ((State == ELibvlcState::Opening) ||
|
||||
(State == ELibvlcState::Buffering) ||
|
||||
(State == ELibvlcState::Error))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Time != CurrentTime)
|
||||
{
|
||||
FVlc::MediaPlayerSetTime(Player, Time.GetTotalMilliseconds());
|
||||
CurrentTime = Time;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaPlayer::SetLooping(bool Looping)
|
||||
{
|
||||
ShouldLoop = Looping;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaPlayer::SetRate(float Rate)
|
||||
{
|
||||
if (Player == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((FVlc::MediaPlayerSetRate(Player, Rate) == -1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FMath::IsNearlyZero(Rate))
|
||||
{
|
||||
if (FVlc::MediaPlayerGetState(Player) == ELibvlcState::Playing)
|
||||
{
|
||||
if (FVlc::MediaPlayerCanPause(Player) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FVlc::MediaPlayerPause(Player);
|
||||
}
|
||||
}
|
||||
else if (FVlc::MediaPlayerGetState(Player) != ELibvlcState::Playing)
|
||||
{
|
||||
if (FVlc::MediaPlayerPlay(Player) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* IMediaPlayer interface
|
||||
*****************************************************************************/
|
||||
|
||||
void FVlcMediaPlayer::Close()
|
||||
{
|
||||
if (Player == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// detach callback handlers
|
||||
Callbacks.Shutdown();
|
||||
Tracks.Shutdown();
|
||||
View.Shutdown();
|
||||
|
||||
// release player
|
||||
FVlc::MediaPlayerStop(Player);
|
||||
FVlc::MediaPlayerRelease(Player);
|
||||
Player = nullptr;
|
||||
|
||||
// reset fields
|
||||
CurrentRate = 0.0f;
|
||||
CurrentTime = FTimespan::Zero();
|
||||
MediaSource.Close();
|
||||
Info.Empty();
|
||||
|
||||
// notify listeners
|
||||
EventSink.ReceiveMediaEvent(EMediaEvent::TracksChanged);
|
||||
EventSink.ReceiveMediaEvent(EMediaEvent::MediaClosed);
|
||||
}
|
||||
|
||||
|
||||
IMediaCache& FVlcMediaPlayer::GetCache()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
IMediaControls& FVlcMediaPlayer::GetControls()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
FString FVlcMediaPlayer::GetInfo() const
|
||||
{
|
||||
return Info;
|
||||
}
|
||||
|
||||
|
||||
FName FVlcMediaPlayer::GetPlayerName() const
|
||||
{
|
||||
static FName PlayerName(TEXT("VlcMedia"));
|
||||
return PlayerName;
|
||||
}
|
||||
|
||||
|
||||
IMediaSamples& FVlcMediaPlayer::GetSamples()
|
||||
{
|
||||
return Callbacks.GetSamples();
|
||||
}
|
||||
|
||||
|
||||
FString FVlcMediaPlayer::GetStats() const
|
||||
{
|
||||
FLibvlcMedia* Media = MediaSource.GetMedia();
|
||||
|
||||
if (Media == nullptr)
|
||||
{
|
||||
return TEXT("No media opened.");
|
||||
}
|
||||
|
||||
FLibvlcMediaStats Stats;
|
||||
|
||||
if (!FVlc::MediaGetStats(Media, &Stats))
|
||||
{
|
||||
return TEXT("Stats currently not available.");
|
||||
}
|
||||
|
||||
FString StatsString;
|
||||
{
|
||||
StatsString += TEXT("General\n");
|
||||
StatsString += FString::Printf(TEXT(" Decoded Video: %i\n"), Stats.DecodedVideo);
|
||||
StatsString += FString::Printf(TEXT(" Decoded Audio: %i\n"), Stats.DecodedAudio);
|
||||
StatsString += FString::Printf(TEXT(" Displayed Pictures: %i\n"), Stats.DisplayedPictures);
|
||||
StatsString += FString::Printf(TEXT(" Lost Pictures: %i\n"), Stats.LostPictures);
|
||||
StatsString += FString::Printf(TEXT(" Played A-Buffers: %i\n"), Stats.PlayedAbuffers);
|
||||
StatsString += FString::Printf(TEXT(" Lost Lost A-Buffers: %i\n"), Stats.LostAbuffers);
|
||||
StatsString += TEXT("\n");
|
||||
|
||||
StatsString += TEXT("Input\n");
|
||||
StatsString += FString::Printf(TEXT(" Bit Rate: %i\n"), Stats.InputBitrate);
|
||||
StatsString += FString::Printf(TEXT(" Bytes Read: %i\n"), Stats.ReadBytes);
|
||||
StatsString += TEXT("\n");
|
||||
|
||||
StatsString += TEXT("Demux\n");
|
||||
StatsString += FString::Printf(TEXT(" Bit Rate: %f\n"), Stats.DemuxBitrate);
|
||||
StatsString += FString::Printf(TEXT(" Bytes Read: %i\n"), Stats.DemuxReadBytes);
|
||||
StatsString += FString::Printf(TEXT(" Corrupted: %i\n"), Stats.DemuxCorrupted);
|
||||
StatsString += FString::Printf(TEXT(" Discontinuity: %i\n"), Stats.DemuxDiscontinuity);
|
||||
StatsString += TEXT("\n");
|
||||
|
||||
StatsString += TEXT("Network\n");
|
||||
StatsString += FString::Printf(TEXT(" Bitrate: %f\n"), Stats.SendBitrate);
|
||||
StatsString += FString::Printf(TEXT(" Sent Bytes: %i\n"), Stats.SentBytes);
|
||||
StatsString += FString::Printf(TEXT(" Sent Packets: %i\n"), Stats.SentPackets);
|
||||
StatsString += TEXT("\n");
|
||||
}
|
||||
|
||||
return StatsString;
|
||||
}
|
||||
|
||||
|
||||
IMediaTracks& FVlcMediaPlayer::GetTracks()
|
||||
{
|
||||
return Tracks;
|
||||
}
|
||||
|
||||
|
||||
FString FVlcMediaPlayer::GetUrl() const
|
||||
{
|
||||
return MediaSource.GetCurrentUrl();
|
||||
}
|
||||
|
||||
|
||||
IMediaView& FVlcMediaPlayer::GetView()
|
||||
{
|
||||
return View;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaPlayer::Open(const FString& Url, const IMediaOptions* Options)
|
||||
{
|
||||
Close();
|
||||
|
||||
if (Url.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Url.StartsWith(TEXT("file://")))
|
||||
{
|
||||
// open local files via platform file system
|
||||
TSharedPtr<FArchive, ESPMode::ThreadSafe> Archive;
|
||||
const TCHAR* FilePath = &Url[7];
|
||||
|
||||
if ((Options != nullptr) && Options->GetMediaOption("PrecacheFile", false))
|
||||
{
|
||||
FArrayReader* Reader = new FArrayReader;
|
||||
|
||||
if (FFileHelper::LoadFileToArray(*Reader, FilePath))
|
||||
{
|
||||
Archive = MakeShareable(Reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete Reader;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Archive = MakeShareable(IFileManager::Get().CreateFileReader(FilePath));
|
||||
}
|
||||
|
||||
if (!Archive.IsValid())
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to open media file: %s"), FilePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MediaSource.OpenArchive(Archive.ToSharedRef(), Url))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!MediaSource.OpenUrl(Url))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return InitializePlayer();
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaPlayer::Open(const TSharedRef<FArchive, ESPMode::ThreadSafe>& Archive, const FString& OriginalUrl, const IMediaOptions* /*Options*/)
|
||||
{
|
||||
Close();
|
||||
|
||||
if (OriginalUrl.IsEmpty() || !MediaSource.OpenArchive(Archive, OriginalUrl))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return InitializePlayer();
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaPlayer::TickInput(FTimespan DeltaTime, FTimespan /*Timecode*/)
|
||||
{
|
||||
if (Player == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// process events
|
||||
ELibvlcEventType Event;
|
||||
|
||||
while (Events.Dequeue(Event))
|
||||
{
|
||||
switch (Event)
|
||||
{
|
||||
case ELibvlcEventType::MediaParsedChanged:
|
||||
Tracks.Initialize(*Player, Info);
|
||||
Callbacks.Initialize(*Player);
|
||||
View.Initialize(*Player);
|
||||
EventSink.ReceiveMediaEvent(EMediaEvent::TracksChanged);
|
||||
break;
|
||||
|
||||
case ELibvlcEventType::MediaPlayerEndReached:
|
||||
// begin hack: this causes a short delay, but there seems to be no
|
||||
// other way. looping via VLC Media List players is also broken :(
|
||||
FVlc::MediaPlayerStop(Player);
|
||||
// end hack
|
||||
|
||||
Callbacks.GetSamples().FlushSamples();
|
||||
EventSink.ReceiveMediaEvent(EMediaEvent::PlaybackEndReached);
|
||||
|
||||
if (ShouldLoop && (CurrentRate != 0.0f))
|
||||
{
|
||||
CurrentTime = FTimespan::Zero();
|
||||
SetRate(CurrentRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
EventSink.ReceiveMediaEvent(EMediaEvent::PlaybackSuspended);
|
||||
}
|
||||
break;
|
||||
|
||||
case ELibvlcEventType::MediaPlayerPaused:
|
||||
EventSink.ReceiveMediaEvent(EMediaEvent::PlaybackSuspended);
|
||||
break;
|
||||
|
||||
case ELibvlcEventType::MediaPlayerPlaying:
|
||||
EventSink.ReceiveMediaEvent(EMediaEvent::PlaybackResumed);
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const ELibvlcState State = FVlc::MediaPlayerGetState(Player);
|
||||
|
||||
// update current time & rate
|
||||
if (State == ELibvlcState::Playing)
|
||||
{
|
||||
CurrentRate = FVlc::MediaPlayerGetRate(Player);
|
||||
CurrentTime += DeltaTime * CurrentRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentRate = 0.0f;
|
||||
}
|
||||
|
||||
Callbacks.SetCurrentTime(CurrentTime);
|
||||
}
|
||||
|
||||
|
||||
/* FVlcMediaPlayer implementation
|
||||
*****************************************************************************/
|
||||
|
||||
bool FVlcMediaPlayer::InitializePlayer()
|
||||
{
|
||||
// create player for media source
|
||||
Player = FVlc::MediaPlayerNewFromMedia(MediaSource.GetMedia());
|
||||
|
||||
if (Player == nullptr)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to initialize media player: %s"), ANSI_TO_TCHAR(FVlc::Errmsg()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// attach to event managers
|
||||
FLibvlcEventManager* MediaEventManager = FVlc::MediaEventManager(MediaSource.GetMedia());
|
||||
FLibvlcEventManager* PlayerEventManager = FVlc::MediaPlayerEventManager(Player);
|
||||
|
||||
if ((MediaEventManager == nullptr) || (PlayerEventManager == nullptr))
|
||||
{
|
||||
FVlc::MediaPlayerRelease(Player);
|
||||
Player = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FVlc::EventAttach(MediaEventManager, ELibvlcEventType::MediaParsedChanged, &FVlcMediaPlayer::StaticEventCallback, this);
|
||||
FVlc::EventAttach(PlayerEventManager, ELibvlcEventType::MediaPlayerEndReached, &FVlcMediaPlayer::StaticEventCallback, this);
|
||||
FVlc::EventAttach(PlayerEventManager, ELibvlcEventType::MediaPlayerPlaying, &FVlcMediaPlayer::StaticEventCallback, this);
|
||||
FVlc::EventAttach(PlayerEventManager, ELibvlcEventType::MediaPlayerPositionChanged, &FVlcMediaPlayer::StaticEventCallback, this);
|
||||
FVlc::EventAttach(PlayerEventManager, ELibvlcEventType::MediaPlayerStopped, &FVlcMediaPlayer::StaticEventCallback, this);
|
||||
|
||||
// initialize player
|
||||
CurrentRate = 0.0f;
|
||||
CurrentTime = FTimespan::Zero();
|
||||
|
||||
EventSink.ReceiveMediaEvent(EMediaEvent::MediaOpened);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* FVlcMediaPlayer static functions
|
||||
*****************************************************************************/
|
||||
|
||||
void FVlcMediaPlayer::StaticEventCallback(FLibvlcEvent* Event, void* UserData)
|
||||
{
|
||||
if (Event == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Player %llx: Event [%s]"), UserData, *VlcMedia::EventToString(Event));
|
||||
|
||||
if (UserData != nullptr)
|
||||
{
|
||||
((FVlcMediaPlayer*)UserData)->Events.Enqueue(Event->Type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Containers/Queue.h"
|
||||
#include "IMediaCache.h"
|
||||
#include "IMediaControls.h"
|
||||
#include "IMediaPlayer.h"
|
||||
#include "IMediaSamples.h"
|
||||
|
||||
#include "VlcMediaCallbacks.h"
|
||||
#include "VlcMediaSource.h"
|
||||
#include "VlcMediaTracks.h"
|
||||
#include "VlcMediaView.h"
|
||||
|
||||
class IMediaEventSink;
|
||||
class IMediaOutput;
|
||||
|
||||
enum class ELibvlcEventType;
|
||||
|
||||
struct FLibvlcEvent;
|
||||
struct FLibvlcEventManager;
|
||||
struct FLibvlcInstance;
|
||||
struct FLibvlcMediaPlayer;
|
||||
|
||||
|
||||
/**
|
||||
* Implements a media player using the Video LAN Codec (VLC) framework.
|
||||
*/
|
||||
class FVlcMediaPlayer
|
||||
: public IMediaPlayer
|
||||
, protected IMediaCache
|
||||
, protected IMediaControls
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create and initialize a new instance.
|
||||
*
|
||||
* @param InEventSink The object that receives media events from this player.
|
||||
* @param InInstance The LibVLC instance to use.
|
||||
*/
|
||||
FVlcMediaPlayer(IMediaEventSink& InEventSink, FLibvlcInstance* InInstance);
|
||||
|
||||
/** Virtual destructor. */
|
||||
virtual ~FVlcMediaPlayer();
|
||||
|
||||
public:
|
||||
|
||||
//~ IMediaPlayer interface
|
||||
|
||||
virtual void Close() override;
|
||||
virtual IMediaCache& GetCache() override;
|
||||
virtual IMediaControls& GetControls() override;
|
||||
virtual FString GetInfo() const override;
|
||||
virtual FName GetPlayerName() const override;
|
||||
virtual IMediaSamples& GetSamples() override;
|
||||
virtual FString GetStats() const override;
|
||||
virtual IMediaTracks& GetTracks() override;
|
||||
virtual FString GetUrl() const override;
|
||||
virtual IMediaView& GetView() override;
|
||||
virtual bool Open(const FString& Url, const IMediaOptions* Options) override;
|
||||
virtual bool Open(const TSharedRef<FArchive, ESPMode::ThreadSafe>& Archive, const FString& OriginalUrl, const IMediaOptions* Options) override;
|
||||
virtual void TickInput(FTimespan DeltaTime, FTimespan Timecode) override;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Initialize the media player.
|
||||
*
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool InitializePlayer();
|
||||
|
||||
protected:
|
||||
|
||||
//~ IMediaControls interface
|
||||
|
||||
virtual bool CanControl(EMediaControl Control) const override;
|
||||
virtual FTimespan GetDuration() const override;
|
||||
virtual float GetRate() const override;
|
||||
virtual EMediaState GetState() const override;
|
||||
virtual EMediaStatus GetStatus() const override;
|
||||
virtual TRangeSet<float> GetSupportedRates(EMediaRateThinning Thinning) const override;
|
||||
virtual FTimespan GetTime() const override;
|
||||
virtual bool IsLooping() const override;
|
||||
virtual bool Seek(const FTimespan& Time) override;
|
||||
virtual bool SetLooping(bool Looping) override;
|
||||
virtual bool SetRate(float Rate) override;
|
||||
|
||||
private:
|
||||
|
||||
/** Handles event callbacks. */
|
||||
static void StaticEventCallback(FLibvlcEvent* Event, void* UserData);
|
||||
|
||||
private:
|
||||
|
||||
/** VLC callback manager. */
|
||||
FVlcMediaCallbacks Callbacks;
|
||||
|
||||
/** Current playback rate. */
|
||||
float CurrentRate;
|
||||
|
||||
/** Current playback time (to work around VLC's broken time tracking). */
|
||||
FTimespan CurrentTime;
|
||||
|
||||
/** The media event handler. */
|
||||
IMediaEventSink& EventSink;
|
||||
|
||||
/** Collection of received player events. */
|
||||
TQueue<ELibvlcEventType, EQueueMode::Mpsc> Events;
|
||||
|
||||
/** Media information string. */
|
||||
FString Info;
|
||||
|
||||
/** The media source (from URL or archive). */
|
||||
FVlcMediaSource MediaSource;
|
||||
|
||||
/** The VLC media player object. */
|
||||
FLibvlcMediaPlayer* Player;
|
||||
|
||||
/** Whether playback should be looping. */
|
||||
bool ShouldLoop;
|
||||
|
||||
/** Track collection. */
|
||||
FVlcMediaTracks Tracks;
|
||||
|
||||
/** View settings. */
|
||||
FVlcMediaView View;
|
||||
};
|
||||
@@ -0,0 +1,189 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VlcMediaSource.h"
|
||||
#include "VlcMediaPrivate.h"
|
||||
|
||||
#include "Vlc.h"
|
||||
|
||||
|
||||
/* FVlcMediaReader structors
|
||||
*****************************************************************************/
|
||||
|
||||
FVlcMediaSource::FVlcMediaSource(FLibvlcInstance* InVlcInstance)
|
||||
: Media(nullptr)
|
||||
, VlcInstance(InVlcInstance)
|
||||
{ }
|
||||
|
||||
|
||||
/* FVlcMediaReader interface
|
||||
*****************************************************************************/
|
||||
|
||||
FTimespan FVlcMediaSource::GetDuration() const
|
||||
{
|
||||
if (Media == nullptr)
|
||||
{
|
||||
return FTimespan::Zero();
|
||||
}
|
||||
|
||||
int64 Duration = FVlc::MediaGetDuration(Media);
|
||||
|
||||
if (Duration < 0)
|
||||
{
|
||||
return FTimespan::Zero();
|
||||
}
|
||||
|
||||
return FTimespan(Duration * ETimespan::TicksPerMillisecond);
|
||||
}
|
||||
|
||||
|
||||
FLibvlcMedia* FVlcMediaSource::OpenArchive(const TSharedRef<FArchive, ESPMode::ThreadSafe>& Archive, const FString& OriginalUrl)
|
||||
{
|
||||
check(Media == nullptr);
|
||||
|
||||
if (Archive->TotalSize() > 0)
|
||||
{
|
||||
Data = Archive;
|
||||
Media = FVlc::MediaNewCallbacks(
|
||||
VlcInstance,
|
||||
nullptr,
|
||||
&FVlcMediaSource::HandleMediaRead,
|
||||
&FVlcMediaSource::HandleMediaSeek,
|
||||
&FVlcMediaSource::HandleMediaClose,
|
||||
this
|
||||
);
|
||||
|
||||
if (Media == nullptr)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to open media from archive: %s (%s)"), *OriginalUrl, ANSI_TO_TCHAR(FVlc::Errmsg()));
|
||||
Data.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentUrl = OriginalUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return Media;
|
||||
}
|
||||
|
||||
|
||||
FLibvlcMedia* FVlcMediaSource::OpenUrl(const FString& Url)
|
||||
{
|
||||
check(Media == nullptr);
|
||||
|
||||
Media = FVlc::MediaNewLocation(VlcInstance, TCHAR_TO_ANSI(*Url));
|
||||
|
||||
if (Media == nullptr)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to open media from URL: %s (%s)"), *Url, ANSI_TO_TCHAR(FVlc::Errmsg()));
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentUrl = Url;
|
||||
}
|
||||
|
||||
return Media;
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaSource::Close()
|
||||
{
|
||||
if (Media != nullptr)
|
||||
{
|
||||
FVlc::MediaRelease(Media);
|
||||
Media = nullptr;
|
||||
}
|
||||
|
||||
Data.Reset();
|
||||
CurrentUrl.Reset();
|
||||
}
|
||||
|
||||
|
||||
/* FVlcMediaReader static functions
|
||||
*****************************************************************************/
|
||||
|
||||
int FVlcMediaSource::HandleMediaOpen(void* Opaque, void** OutData, uint64* OutSize)
|
||||
{
|
||||
auto Reader = (FVlcMediaSource*)Opaque;
|
||||
|
||||
if ((Reader == nullptr) || !Reader->Data.IsValid())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
*OutSize = Reader->Data->TotalSize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SSIZE_T FVlcMediaSource::HandleMediaRead(void* Opaque, void* Buffer, SIZE_T Length)
|
||||
{
|
||||
auto Reader = (FVlcMediaSource*)Opaque;
|
||||
|
||||
if (Reader == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
TSharedPtr<FArchive, ESPMode::ThreadSafe> Data = Reader->Data;
|
||||
|
||||
if (!Reader->Data.IsValid())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
SIZE_T DataSize = (SIZE_T)Data->TotalSize();
|
||||
SIZE_T BytesToRead = FMath::Min(Length, DataSize);
|
||||
SIZE_T DataPosition = Reader->Data->Tell();
|
||||
|
||||
if ((DataSize - BytesToRead) < DataPosition)
|
||||
{
|
||||
BytesToRead = DataSize - DataPosition;
|
||||
}
|
||||
|
||||
if (BytesToRead > 0)
|
||||
{
|
||||
Data->Serialize(Buffer, BytesToRead);
|
||||
}
|
||||
|
||||
return (SSIZE_T)BytesToRead;
|
||||
}
|
||||
|
||||
|
||||
int FVlcMediaSource::HandleMediaSeek(void* Opaque, uint64 Offset)
|
||||
{
|
||||
auto Reader = (FVlcMediaSource*)Opaque;
|
||||
|
||||
if (Reader == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
TSharedPtr<FArchive, ESPMode::ThreadSafe> Data = Reader->Data;
|
||||
|
||||
if (!Reader->Data.IsValid())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((uint64)Data->TotalSize() <= Offset)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reader->Data->Seek(Offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaSource::HandleMediaClose(void* Opaque)
|
||||
{
|
||||
auto Reader = (FVlcMediaSource*)Opaque;
|
||||
|
||||
if (Reader != nullptr)
|
||||
{
|
||||
Reader->Data->Seek(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
|
||||
struct FLibvlcInstance;
|
||||
struct FLibvlcMedia;
|
||||
|
||||
|
||||
/**
|
||||
* Implements a media source, such as a movie file or URL.
|
||||
*/
|
||||
class FVlcMediaSource
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create and initialize a new instance.
|
||||
*
|
||||
* @param InInstance The LibVLC instance to use.
|
||||
*/
|
||||
FVlcMediaSource(FLibvlcInstance* InVlcInstance);
|
||||
|
||||
public:
|
||||
|
||||
/** Get the media object. */
|
||||
FLibvlcMedia* GetMedia() const
|
||||
{
|
||||
return Media;
|
||||
}
|
||||
|
||||
/** Get the URL of the currently open media source. */
|
||||
const FString& GetCurrentUrl() const
|
||||
{
|
||||
return CurrentUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the duration of the media source.
|
||||
*
|
||||
* @return Media duration.
|
||||
*/
|
||||
FTimespan GetDuration() const;
|
||||
|
||||
/**
|
||||
* Open a media source using the given archive.
|
||||
*
|
||||
* You must call Close() if this media source is open prior to calling this method.
|
||||
*
|
||||
* @param Archive The archive to read media data from.
|
||||
* @return The media object.
|
||||
* @see OpenUrl, Close
|
||||
*/
|
||||
FLibvlcMedia* OpenArchive(const TSharedRef<FArchive, ESPMode::ThreadSafe>& Archive, const FString& OriginalUrl);
|
||||
|
||||
/**
|
||||
* Open a media source from the specified URL.
|
||||
*
|
||||
* You must call Close() if this media source is open prior to calling this method.
|
||||
*
|
||||
* @param Url The media resource locator.
|
||||
* @return The media object.
|
||||
* @see OpenArchive, Close
|
||||
*/
|
||||
FLibvlcMedia* OpenUrl(const FString& Url);
|
||||
|
||||
/**
|
||||
* Close the media source.
|
||||
*
|
||||
* @see OpenArchive, OpenUrl
|
||||
*/
|
||||
void Close();
|
||||
|
||||
private:
|
||||
|
||||
/** Handles open callbacks from VLC. */
|
||||
static int HandleMediaOpen(void* Opaque, void** OutData, uint64* OutSize);
|
||||
|
||||
/** Handles read callbacks from VLC. */
|
||||
static SSIZE_T HandleMediaRead(void* Opaque, void* Buffer, SIZE_T Length);
|
||||
|
||||
/** Handles seek callbacks from VLC. */
|
||||
static int HandleMediaSeek(void* Opaque, uint64 Offset);
|
||||
|
||||
/** Handles close callbacks from VLC. */
|
||||
static void HandleMediaClose(void* Opaque);
|
||||
|
||||
private:
|
||||
|
||||
/** The file or memory archive to stream from (for local media only). */
|
||||
TSharedPtr<FArchive, ESPMode::ThreadSafe> Data;
|
||||
|
||||
/** The media object. */
|
||||
FLibvlcMedia* Media;
|
||||
|
||||
/** Currently opened media. */
|
||||
FString CurrentUrl;
|
||||
|
||||
/** The LibVLC instance. */
|
||||
FLibvlcInstance* VlcInstance;
|
||||
};
|
||||
@@ -0,0 +1,206 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "IMediaTextureSample.h"
|
||||
#include "MediaObjectPool.h"
|
||||
#include "Math/IntPoint.h"
|
||||
#include "Misc/Timespan.h"
|
||||
#include "Templates/SharedPointer.h"
|
||||
|
||||
|
||||
/**
|
||||
* Texture sample generated by VlcMedia player.
|
||||
*/
|
||||
class FVlcMediaTextureSample
|
||||
: public IMediaTextureSample
|
||||
, public IMediaPoolable
|
||||
{
|
||||
public:
|
||||
|
||||
/** Default constructor. */
|
||||
FVlcMediaTextureSample()
|
||||
: Buffer(nullptr)
|
||||
, BufferSize(0)
|
||||
, Dim(FIntPoint::ZeroValue)
|
||||
, Duration(FTimespan::Zero())
|
||||
, OutputDim(FIntPoint::ZeroValue)
|
||||
, SampleFormat(EMediaTextureSampleFormat::Undefined)
|
||||
, Stride(0)
|
||||
, Time(FTimespan::Zero())
|
||||
{ }
|
||||
|
||||
/** Virtual destructor. */
|
||||
virtual ~FVlcMediaTextureSample()
|
||||
{
|
||||
FreeBuffer();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get a writable pointer to the sample buffer.
|
||||
*
|
||||
* @return The buffer.
|
||||
* @see Initialize
|
||||
*/
|
||||
void* GetMutableBuffer()
|
||||
{
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the sample.
|
||||
*
|
||||
* @param InDim The sample buffer's width and height (in pixels).
|
||||
* @param InOutputDim The sample's output width and height (in pixels).
|
||||
* @param InSampleFormat The sample format.
|
||||
* @param InStride Number of bytes per pixel row.
|
||||
* @param InDuration The duration for which the sample is valid.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool Initialize(
|
||||
const FIntPoint& InDim,
|
||||
const FIntPoint& InOutputDim,
|
||||
EMediaTextureSampleFormat InSampleFormat,
|
||||
uint32 InStride,
|
||||
FTimespan InDuration)
|
||||
{
|
||||
if (InSampleFormat == EMediaTextureSampleFormat::Undefined)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const SIZE_T RequiredBufferSize = InStride * InDim.Y;
|
||||
|
||||
if (RequiredBufferSize == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RequiredBufferSize > BufferSize)
|
||||
{
|
||||
Buffer = FMemory::Realloc(Buffer, RequiredBufferSize, 32);
|
||||
BufferSize = RequiredBufferSize;
|
||||
}
|
||||
|
||||
Dim = InDim;
|
||||
Duration = InDuration;
|
||||
OutputDim = InOutputDim;
|
||||
SampleFormat = InSampleFormat;
|
||||
Stride = InStride;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time for which the sample was generated.
|
||||
*
|
||||
* @param InTime The time to set (in the player's clock).
|
||||
*/
|
||||
void SetTime(FTimespan InTime)
|
||||
{
|
||||
Time = InTime;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//~ IMediaTextureSample interface
|
||||
|
||||
virtual const void* GetBuffer() override
|
||||
{
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
virtual FIntPoint GetDim() const override
|
||||
{
|
||||
return Dim;
|
||||
}
|
||||
|
||||
virtual FTimespan GetDuration() const override
|
||||
{
|
||||
return Duration;
|
||||
}
|
||||
|
||||
virtual EMediaTextureSampleFormat GetFormat() const override
|
||||
{
|
||||
return SampleFormat;
|
||||
}
|
||||
|
||||
virtual FIntPoint GetOutputDim() const override
|
||||
{
|
||||
return OutputDim;
|
||||
}
|
||||
|
||||
virtual uint32 GetStride() const override
|
||||
{
|
||||
return Stride;
|
||||
}
|
||||
|
||||
#if WITH_ENGINE
|
||||
virtual FRHITexture* GetTexture() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
#endif //WITH_ENGINE
|
||||
|
||||
virtual FTimespan GetTime() const override
|
||||
{
|
||||
return Time;
|
||||
}
|
||||
|
||||
virtual bool IsCacheable() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool IsOutputSrgb() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Free the sample buffer. */
|
||||
void FreeBuffer()
|
||||
{
|
||||
if (Buffer != nullptr)
|
||||
{
|
||||
FMemory::Free(Buffer);
|
||||
|
||||
Buffer = nullptr;
|
||||
BufferSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** The sample's frame buffer. */
|
||||
void* Buffer;
|
||||
|
||||
/** Allocated size of the buffer (in bytes). */
|
||||
SIZE_T BufferSize;
|
||||
|
||||
/** Width and height of the texture sample. */
|
||||
FIntPoint Dim;
|
||||
|
||||
/** Duration for which the sample is valid. */
|
||||
FTimespan Duration;
|
||||
|
||||
/** Width and height of the output. */
|
||||
FIntPoint OutputDim;
|
||||
|
||||
/** The sample format. */
|
||||
EMediaTextureSampleFormat SampleFormat;
|
||||
|
||||
/** Number of bytes per pixel row. */
|
||||
uint32 Stride;
|
||||
|
||||
/** Play time for which the sample was generated. */
|
||||
FTimespan Time;
|
||||
};
|
||||
|
||||
|
||||
/** Implements a pool for VLC texture sample objects. */
|
||||
class FVlcMediaTextureSamplePool : public TMediaObjectPool<FVlcMediaTextureSample> { };
|
||||
@@ -0,0 +1,443 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VlcMediaTracks.h"
|
||||
#include "Vlc.h"
|
||||
|
||||
#include "MediaHelpers.h"
|
||||
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FVlcMediaTracks"
|
||||
|
||||
|
||||
/* FVlcMediaTracks structors
|
||||
*****************************************************************************/
|
||||
|
||||
FVlcMediaTracks::FVlcMediaTracks()
|
||||
: Player(nullptr)
|
||||
{ }
|
||||
|
||||
|
||||
/* FVlcMediaTracks interface
|
||||
*****************************************************************************/
|
||||
|
||||
void FVlcMediaTracks::Initialize(FLibvlcMediaPlayer& InPlayer, FString& OutInfo)
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Tracks: %p: Initializing tracks"), this);
|
||||
|
||||
Player = &InPlayer;
|
||||
|
||||
int32 Width = FVlc::VideoGetWidth(Player);
|
||||
int32 Height = FVlc::VideoGetHeight(Player);
|
||||
int32 StreamCount = 0;
|
||||
|
||||
// @todo gmp: fix audio specs
|
||||
FVlc::AudioSetFormat(Player, "S16N", 44100, 2);
|
||||
FVlc::VideoSetFormat(Player, "RV32", Width, Height, Width * 4);
|
||||
|
||||
// initialize audio tracks
|
||||
FLibvlcTrackDescription* AudioTrackDescr = FVlc::AudioGetTrackDescription(Player);
|
||||
{
|
||||
while (AudioTrackDescr != nullptr)
|
||||
{
|
||||
if (AudioTrackDescr->Id != -1)
|
||||
{
|
||||
FTrack Track;
|
||||
{
|
||||
Track.Id = AudioTrackDescr->Id;
|
||||
Track.Name = ANSI_TO_TCHAR(AudioTrackDescr->Name);
|
||||
Track.DisplayName = Track.Name.IsEmpty()
|
||||
? FText::Format(LOCTEXT("AudioTrackFormat", "Audio Track {0}"), FText::AsNumber(AudioTracks.Num()))
|
||||
: FText::FromString(Track.Name);
|
||||
}
|
||||
|
||||
AudioTracks.Add(Track);
|
||||
|
||||
OutInfo += FString::Printf(TEXT("Stream %i\n"), StreamCount);
|
||||
OutInfo += TEXT(" Type: Audio\n");
|
||||
OutInfo += FString::Printf(TEXT(" Name: %s\n"), *Track.Name);
|
||||
OutInfo += TEXT("\n");
|
||||
|
||||
++StreamCount;
|
||||
}
|
||||
|
||||
AudioTrackDescr = AudioTrackDescr->Next;
|
||||
}
|
||||
}
|
||||
FVlc::TrackDescriptionListRelease(AudioTrackDescr);
|
||||
|
||||
// initialize caption tracks
|
||||
FLibvlcTrackDescription* CaptionTrackDescr = FVlc::VideoGetSpuDescription(Player);
|
||||
{
|
||||
while (CaptionTrackDescr != nullptr)
|
||||
{
|
||||
if (CaptionTrackDescr->Id != -1)
|
||||
{
|
||||
FTrack Track;
|
||||
{
|
||||
Track.Id = CaptionTrackDescr->Id;
|
||||
Track.Name = ANSI_TO_TCHAR(CaptionTrackDescr->Name);
|
||||
Track.DisplayName = Track.Name.IsEmpty()
|
||||
? FText::Format(LOCTEXT("CaptionTrackFormat", "Caption Track {0}"), FText::AsNumber(CaptionTracks.Num()))
|
||||
: FText::FromString(Track.Name);
|
||||
}
|
||||
|
||||
CaptionTracks.Add(Track);
|
||||
|
||||
OutInfo += FString::Printf(TEXT("Stream %i\n"), StreamCount);
|
||||
OutInfo += TEXT(" Type: Caption\n");
|
||||
OutInfo += FString::Printf(TEXT(" Name: %s\n"), *Track.Name);
|
||||
OutInfo += TEXT("\n");
|
||||
|
||||
++StreamCount;
|
||||
}
|
||||
|
||||
CaptionTrackDescr = CaptionTrackDescr->Next;
|
||||
}
|
||||
}
|
||||
FVlc::TrackDescriptionListRelease(CaptionTrackDescr);
|
||||
|
||||
// initialize video tracks
|
||||
FLibvlcTrackDescription* VideoTrackDescr = FVlc::VideoGetTrackDescription(Player);
|
||||
{
|
||||
while (VideoTrackDescr != nullptr)
|
||||
{
|
||||
if (VideoTrackDescr->Id != -1)
|
||||
{
|
||||
FTrack Track;
|
||||
{
|
||||
Track.Id = VideoTrackDescr->Id;
|
||||
Track.Name = ANSI_TO_TCHAR(VideoTrackDescr->Name);
|
||||
Track.DisplayName = Track.Name.IsEmpty()
|
||||
? FText::Format(LOCTEXT("VideoTrackFormat", "Video Track {0}"), FText::AsNumber(VideoTracks.Num()))
|
||||
: FText::FromString(Track.Name);
|
||||
}
|
||||
|
||||
VideoTracks.Add(Track);
|
||||
|
||||
OutInfo += FString::Printf(TEXT("Stream %i\n"), StreamCount);
|
||||
OutInfo += TEXT(" Type: Video\n");
|
||||
OutInfo += FString::Printf(TEXT(" Name: %s\n"), *Track.Name);
|
||||
OutInfo += TEXT("\n");
|
||||
|
||||
++StreamCount;
|
||||
}
|
||||
|
||||
VideoTrackDescr = VideoTrackDescr->Next;
|
||||
}
|
||||
}
|
||||
FVlc::TrackDescriptionListRelease(VideoTrackDescr);
|
||||
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Tracks %p: Found %i streams"), this, StreamCount);
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaTracks::Shutdown()
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Tracks: %p: Shutting down tracks"), this);
|
||||
|
||||
if (Player != nullptr)
|
||||
{
|
||||
AudioTracks.Reset();
|
||||
VideoTracks.Reset();
|
||||
Player = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* IMediaTracks interface
|
||||
*****************************************************************************/
|
||||
|
||||
bool FVlcMediaTracks::GetAudioTrackFormat(int32 TrackIndex, int32 FormatIndex, FMediaAudioTrackFormat& OutFormat) const
|
||||
{
|
||||
if (!AudioTracks.IsValidIndex(TrackIndex) || (FormatIndex != 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// @todo gmp: fix audio format
|
||||
OutFormat.BitsPerSample = 0;
|
||||
OutFormat.NumChannels = 2;
|
||||
OutFormat.SampleRate = 44100;
|
||||
OutFormat.TypeName = TEXT("PCM");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int32 FVlcMediaTracks::GetNumTracks(EMediaTrackType TrackType) const
|
||||
{
|
||||
switch (TrackType)
|
||||
{
|
||||
case EMediaTrackType::Audio:
|
||||
return AudioTracks.Num();
|
||||
|
||||
case EMediaTrackType::Caption:
|
||||
return CaptionTracks.Num();
|
||||
|
||||
case EMediaTrackType::Video:
|
||||
return VideoTracks.Num();
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32 FVlcMediaTracks::GetNumTrackFormats(EMediaTrackType TrackType, int32 TrackIndex) const
|
||||
{
|
||||
return ((TrackIndex >= 0) && (TrackIndex < GetNumTracks(TrackType))) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
int32 FVlcMediaTracks::GetSelectedTrack(EMediaTrackType TrackType) const
|
||||
{
|
||||
if (Player == nullptr)
|
||||
{
|
||||
return INDEX_NONE;
|
||||
}
|
||||
|
||||
const TArray<FTrack>* Tracks = nullptr;
|
||||
int32 TrackId = INDEX_NONE;
|
||||
|
||||
switch (TrackType)
|
||||
{
|
||||
case EMediaTrackType::Audio:
|
||||
Tracks = &AudioTracks;
|
||||
TrackId = FVlc::AudioGetTrack(Player);
|
||||
break;
|
||||
|
||||
case EMediaTrackType::Caption:
|
||||
Tracks = &CaptionTracks;
|
||||
TrackId = FVlc::VideoGetSpu(Player);
|
||||
break;
|
||||
|
||||
case EMediaTrackType::Video:
|
||||
Tracks = &VideoTracks;
|
||||
TrackId = FVlc::VideoGetTrack(Player);
|
||||
break;
|
||||
}
|
||||
|
||||
if (TrackId != INDEX_NONE)
|
||||
{
|
||||
check(Tracks != nullptr);
|
||||
|
||||
for (int32 TrackIndex = 0; TrackIndex < Tracks->Num(); ++TrackIndex)
|
||||
{
|
||||
if ((*Tracks)[TrackIndex].Id == TrackId)
|
||||
{
|
||||
return TrackIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return INDEX_NONE;
|
||||
}
|
||||
|
||||
|
||||
FText FVlcMediaTracks::GetTrackDisplayName(EMediaTrackType TrackType, int32 TrackIndex) const
|
||||
{
|
||||
switch (TrackType)
|
||||
{
|
||||
case EMediaTrackType::Audio:
|
||||
if (AudioTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
return AudioTracks[TrackIndex].DisplayName;
|
||||
}
|
||||
break;
|
||||
|
||||
case EMediaTrackType::Caption:
|
||||
if (CaptionTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
return CaptionTracks[TrackIndex].DisplayName;
|
||||
}
|
||||
break;
|
||||
|
||||
case EMediaTrackType::Video:
|
||||
if (VideoTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
return VideoTracks[TrackIndex].DisplayName;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FText::GetEmpty();
|
||||
}
|
||||
|
||||
|
||||
int32 FVlcMediaTracks::GetTrackFormat(EMediaTrackType TrackType, int32 TrackIndex) const
|
||||
{
|
||||
return (GetSelectedTrack(TrackType) != INDEX_NONE) ? 0 : INDEX_NONE;
|
||||
}
|
||||
|
||||
|
||||
FString FVlcMediaTracks::GetTrackLanguage(EMediaTrackType TrackType, int32 TrackIndex) const
|
||||
{
|
||||
return TEXT("und"); // libvlc currently doesn't provide language codes
|
||||
}
|
||||
|
||||
|
||||
FString FVlcMediaTracks::GetTrackName(EMediaTrackType TrackType, int32 TrackIndex) const
|
||||
{
|
||||
switch (TrackType)
|
||||
{
|
||||
case EMediaTrackType::Audio:
|
||||
if (AudioTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
return AudioTracks[TrackIndex].Name;
|
||||
}
|
||||
break;
|
||||
|
||||
case EMediaTrackType::Caption:
|
||||
if (CaptionTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
return CaptionTracks[TrackIndex].Name;
|
||||
}
|
||||
break;
|
||||
|
||||
case EMediaTrackType::Video:
|
||||
if (VideoTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
return VideoTracks[TrackIndex].Name;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FString();
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaTracks::GetVideoTrackFormat(int32 TrackIndex, int32 FormatIndex, FMediaVideoTrackFormat& OutFormat) const
|
||||
{
|
||||
if (!VideoTracks.IsValidIndex(TrackIndex) || (FormatIndex != 0) || (Player == nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// @todo gmp: fix video specs
|
||||
OutFormat.Dim = FIntPoint(FVlc::VideoGetWidth(Player), FVlc::VideoGetHeight(Player));
|
||||
OutFormat.FrameRate = FVlc::MediaPlayerGetFps(Player);
|
||||
OutFormat.FrameRates = TRange<float>(OutFormat.FrameRate);
|
||||
OutFormat.TypeName = TEXT("Default");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaTracks::SelectTrack(EMediaTrackType TrackType, int32 TrackIndex)
|
||||
{
|
||||
if (Player == nullptr)
|
||||
{
|
||||
return false; // not initialized
|
||||
}
|
||||
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Tracks %p: Selecting %s track %i"), this, *MediaUtils::TrackTypeToString(TrackType), TrackIndex);
|
||||
|
||||
int32 TrackId = INDEX_NONE;
|
||||
|
||||
switch (TrackType)
|
||||
{
|
||||
case EMediaTrackType::Audio:
|
||||
if (AudioTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
TrackId = AudioTracks[TrackIndex].Id;
|
||||
}
|
||||
else if (TrackIndex == INDEX_NONE)
|
||||
{
|
||||
TrackId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // invalid track
|
||||
}
|
||||
|
||||
if (FVlc::AudioSetTrack(Player, TrackId) != 0)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Tracks %p: Failed to %s audio track %i (id %i)"), this, (TrackId == -1) ? TEXT("disable") : TEXT("enable"), TrackIndex, TrackId);
|
||||
return false;
|
||||
}
|
||||
|
||||
case EMediaTrackType::Caption:
|
||||
if (CaptionTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
TrackId = CaptionTracks[TrackIndex].Id;
|
||||
}
|
||||
else if (TrackIndex == INDEX_NONE)
|
||||
{
|
||||
TrackId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // invalid track
|
||||
}
|
||||
|
||||
if (FVlc::VideoSetSpu(Player, TrackId) != 0)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Tracks %p: Failed to %s caption track %i (id %i)"), this, (TrackId == -1) ? TEXT("disable") : TEXT("enable"), TrackIndex, TrackId);
|
||||
return false;
|
||||
}
|
||||
|
||||
case EMediaTrackType::Video:
|
||||
if (VideoTracks.IsValidIndex(TrackIndex))
|
||||
{
|
||||
TrackId = VideoTracks[TrackIndex].Id;
|
||||
}
|
||||
else if (TrackIndex == INDEX_NONE)
|
||||
{
|
||||
TrackId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // invalid track
|
||||
}
|
||||
|
||||
if ((TrackId != -1) && (FVlc::VideoSetTrack(Player, -1) != 0))
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Tracks %p: Failed to disable video decoding"), this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FVlc::VideoSetTrack(Player, TrackId) != 0)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("Tracks %p: Failed to %s video track %i (id %i)"), this, (TrackId == -1) ? TEXT("disable") : TEXT("enable"), TrackIndex, TrackId);
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false; // unsupported track type
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaTracks::SetTrackFormat(EMediaTrackType TrackType, int32 TrackIndex, int32 FormatIndex)
|
||||
{
|
||||
if ((Player == nullptr) || (FormatIndex != 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (TrackType)
|
||||
{
|
||||
case EMediaTrackType::Audio:
|
||||
return AudioTracks.IsValidIndex(TrackIndex);
|
||||
|
||||
case EMediaTrackType::Caption:
|
||||
return CaptionTracks.IsValidIndex(TrackIndex);
|
||||
|
||||
case EMediaTrackType::Video:
|
||||
return VideoTracks.IsValidIndex(TrackIndex);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,73 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Containers/Array.h"
|
||||
#include "Containers/UnrealString.h"
|
||||
#include "IMediaTracks.h"
|
||||
#include "Internationalization/Text.h"
|
||||
|
||||
struct FLibvlcMediaPlayer;
|
||||
|
||||
|
||||
/**
|
||||
* Implements the track collection for VLC based media players.
|
||||
*/
|
||||
class FVlcMediaTracks
|
||||
: public IMediaTracks
|
||||
{
|
||||
struct FTrack
|
||||
{
|
||||
FText DisplayName;
|
||||
int32 Id;
|
||||
FString Name;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor. */
|
||||
FVlcMediaTracks();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Initialize this object for the specified VLC media player.
|
||||
*
|
||||
* @param InPlayer The VLC media player.
|
||||
* @param OutInfo Will contain information about the available media tracks.
|
||||
*/
|
||||
void Initialize(FLibvlcMediaPlayer& InPlayer, FString& OutInfo);
|
||||
|
||||
/** Shut down this object. */
|
||||
void Shutdown();
|
||||
|
||||
public:
|
||||
|
||||
//~ IMediaTracks interface
|
||||
|
||||
virtual bool GetAudioTrackFormat(int32 TrackIndex, int32 FormatIndex, FMediaAudioTrackFormat& OutFormat) const override;
|
||||
virtual int32 GetNumTracks(EMediaTrackType TrackType) const override;
|
||||
virtual int32 GetNumTrackFormats(EMediaTrackType TrackType, int32 TrackIndex) const override;
|
||||
virtual int32 GetSelectedTrack(EMediaTrackType TrackType) const override;
|
||||
virtual FText GetTrackDisplayName(EMediaTrackType TrackType, int32 TrackIndex) const override;
|
||||
virtual int32 GetTrackFormat(EMediaTrackType TrackType, int32 TrackIndex) const override;
|
||||
virtual FString GetTrackLanguage(EMediaTrackType TrackType, int32 TrackIndex) const override;
|
||||
virtual FString GetTrackName(EMediaTrackType TrackType, int32 TrackIndex) const override;
|
||||
virtual bool GetVideoTrackFormat(int32 TrackIndex, int32 FormatIndex, FMediaVideoTrackFormat& OutFormat) const override;
|
||||
virtual bool SelectTrack(EMediaTrackType TrackType, int32 TrackIndex) override;
|
||||
virtual bool SetTrackFormat(EMediaTrackType TrackType, int32 TrackIndex, int32 FormatIndex) override;
|
||||
|
||||
private:
|
||||
|
||||
/** Audio track descriptors. */
|
||||
TArray<FTrack> AudioTracks;
|
||||
|
||||
/** Caption track descriptors. */
|
||||
TArray<FTrack> CaptionTracks;
|
||||
|
||||
/** The VLC media player object. */
|
||||
FLibvlcMediaPlayer* Player;
|
||||
|
||||
/** Video track descriptors. */
|
||||
TArray<FTrack> VideoTracks;
|
||||
};
|
||||
@@ -0,0 +1,138 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VlcMediaView.h"
|
||||
#include "VlcMediaPrivate.h"
|
||||
|
||||
#include "Vlc.h"
|
||||
|
||||
|
||||
/* FVlcMediaView structors
|
||||
*****************************************************************************/
|
||||
|
||||
FVlcMediaView::FVlcMediaView()
|
||||
: CurrentFieldOfView(90.0f)
|
||||
, CurrentOrientation(EForceInit::ForceInit)
|
||||
, Player(nullptr)
|
||||
{
|
||||
Viewpoint = FVlc::VideoNewViewpoint();
|
||||
|
||||
if (Viewpoint == nullptr)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to create viewpoint structure; 360 view controls will be unavailable."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FVlcMediaView::~FVlcMediaView()
|
||||
{
|
||||
if (Viewpoint != nullptr)
|
||||
{
|
||||
FVlc::Free(Viewpoint);
|
||||
Viewpoint = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* FVlcMediaView interface
|
||||
*****************************************************************************/
|
||||
|
||||
void FVlcMediaView::Initialize(FLibvlcMediaPlayer& InPlayer)
|
||||
{
|
||||
Player = &InPlayer;
|
||||
}
|
||||
|
||||
|
||||
void FVlcMediaView::Shutdown()
|
||||
{
|
||||
Player = nullptr;
|
||||
}
|
||||
|
||||
|
||||
/* IMediaView interface
|
||||
*****************************************************************************/
|
||||
|
||||
bool FVlcMediaView::GetViewField(float& OutHorizontal, float& OutVertical) const
|
||||
{
|
||||
OutHorizontal = CurrentFieldOfView;
|
||||
OutVertical = CurrentFieldOfView;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaView::GetViewOrientation(FQuat& OutOrientation) const
|
||||
{
|
||||
OutOrientation = CurrentOrientation;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaView::SetViewField(float Horizontal, float Vertical, bool Absolute)
|
||||
{
|
||||
if ((Player == nullptr) || (Viewpoint == nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Absolute)
|
||||
{
|
||||
Horizontal = CurrentFieldOfView + Horizontal;
|
||||
}
|
||||
|
||||
FVector Euler = CurrentOrientation.Euler();
|
||||
|
||||
Viewpoint->Roll = Euler.X;
|
||||
Viewpoint->Pitch = Euler.Y;
|
||||
Viewpoint->Yaw = Euler.Z;
|
||||
Viewpoint->FieldOfView = FMath::ClampAngle(Horizontal, 10.0f, 360.0f);
|
||||
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Setting viewpoint to %f %f %f / %f."), Viewpoint->Roll, Viewpoint->Pitch, Viewpoint->Roll, Viewpoint->FieldOfView);
|
||||
|
||||
if (FVlc::VideoUpdateViewpoint(Player, Viewpoint, true) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CurrentFieldOfView = Horizontal;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FVlcMediaView::SetViewOrientation(const FQuat& Orientation, bool Absolute)
|
||||
{
|
||||
if ((Player == nullptr) || (Viewpoint == nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
FQuat NewOrientation;
|
||||
|
||||
if (Absolute)
|
||||
{
|
||||
NewOrientation = Orientation;
|
||||
}
|
||||
else
|
||||
{
|
||||
NewOrientation = Orientation * CurrentOrientation;
|
||||
}
|
||||
|
||||
FVector Euler = NewOrientation.Euler();
|
||||
|
||||
Viewpoint->Roll = Euler.X;
|
||||
Viewpoint->Pitch = Euler.Y;
|
||||
Viewpoint->Yaw = Euler.Z;
|
||||
Viewpoint->FieldOfView = CurrentFieldOfView;
|
||||
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("Setting viewpoint to %f %f %f / %f."), Viewpoint->Roll, Viewpoint->Pitch, Viewpoint->Roll, Viewpoint->FieldOfView);
|
||||
|
||||
if (FVlc::VideoUpdateViewpoint(Player, Viewpoint, true) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CurrentOrientation = NewOrientation;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IMediaView.h"
|
||||
|
||||
struct FLibvlcMediaPlayer;
|
||||
struct FLibvlcVideoViewpoint;
|
||||
|
||||
|
||||
/**
|
||||
* Implements VLC video view settings.
|
||||
*/
|
||||
class FVlcMediaView
|
||||
: public IMediaView
|
||||
{
|
||||
public:
|
||||
|
||||
/** Default constructor. */
|
||||
FVlcMediaView();
|
||||
|
||||
/** Virtual destructor. */
|
||||
virtual ~FVlcMediaView();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Initialize this object for the specified VLC media player.
|
||||
*
|
||||
* @param InPlayer The VLC media player.
|
||||
*/
|
||||
void Initialize(FLibvlcMediaPlayer& InPlayer);
|
||||
|
||||
/** Shut down this object. */
|
||||
void Shutdown();
|
||||
|
||||
public:
|
||||
|
||||
//~ IMediaView interface
|
||||
|
||||
virtual bool GetViewField(float& OutHorizontal, float& OutVertical) const override;
|
||||
virtual bool GetViewOrientation(FQuat& OutOrientation) const override;
|
||||
virtual bool SetViewField(float Horizontal, float Vertical, bool Absolute) override;
|
||||
virtual bool SetViewOrientation(const FQuat& Orientation, bool Absolute) override;
|
||||
|
||||
private:
|
||||
|
||||
/** The current field of view (horizontal & vertical). */
|
||||
float CurrentFieldOfView;
|
||||
|
||||
/** The current view orientation. */
|
||||
FQuat CurrentOrientation;
|
||||
|
||||
/** The VLC media player object. */
|
||||
FLibvlcMediaPlayer* Player;
|
||||
|
||||
/** The VLC video viewpoint. */
|
||||
FLibvlcVideoViewpoint* Viewpoint;
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VlcMediaUtils.h"
|
||||
#include "VlcTypes.h"
|
||||
|
||||
|
||||
namespace VlcMedia
|
||||
{
|
||||
FString EventToString(FLibvlcEvent* Event)
|
||||
{
|
||||
switch (Event->Type)
|
||||
{
|
||||
case ELibvlcEventType::MediaMetaChanged: return TEXT("Media Data Changed");
|
||||
case ELibvlcEventType::MediaSubItemAdded: return TEXT("Media Sub Item Added");
|
||||
case ELibvlcEventType::MediaDurationChanged: return TEXT("Media Duration Changed");
|
||||
case ELibvlcEventType::MediaParsedChanged: return TEXT("Media Parsed Changed");
|
||||
case ELibvlcEventType::MediaFreed: return TEXT("Media Freed");
|
||||
case ELibvlcEventType::MediaStateChanged: return FString::Printf(TEXT("Media State Changed: %s"), *StateToString(Event->Descriptor.MediaStateChanged.NewState));
|
||||
case ELibvlcEventType::MediaSubItemTreeAdded: return TEXT("Media Sub Item Tree Added");
|
||||
|
||||
case ELibvlcEventType::MediaPlayerMediaChanged: return TEXT("Player Media Changed");
|
||||
case ELibvlcEventType::MediaPlayerNothingSpecial: return TEXT("Player Nothing Special");
|
||||
case ELibvlcEventType::MediaPlayerOpening: return TEXT("Player Opening");
|
||||
case ELibvlcEventType::MediaPlayerBuffering: return FString::Printf(TEXT("Player Buffering: %f"), Event->Descriptor.MediaPlayerBuffering.NewCache);
|
||||
case ELibvlcEventType::MediaPlayerPlaying: return TEXT("Player Playing");
|
||||
case ELibvlcEventType::MediaPlayerPaused: return TEXT("Player Paused");
|
||||
case ELibvlcEventType::MediaPlayerStopped: return TEXT("Player Stopped");
|
||||
case ELibvlcEventType::MediaPlayerForward: return TEXT("Player Forward");
|
||||
case ELibvlcEventType::MediaPlayerBackward: return TEXT("Player Backward");
|
||||
case ELibvlcEventType::MediaPlayerEndReached: return TEXT("Player End Reached");
|
||||
case ELibvlcEventType::MediaPlayerEncounteredError: return TEXT("Player Encountered Error");
|
||||
case ELibvlcEventType::MediaPlayerTimeChanged: return FString::Printf(TEXT("Player Time Changed: %s"), *FTimespan::FromMilliseconds(Event->Descriptor.MediaPlayerTimeChanged.NewTime).ToString());
|
||||
case ELibvlcEventType::MediaPlayerPositionChanged: return FString::Printf(TEXT("Position Changed: %f"), Event->Descriptor.MediaPlayerPositionChanged.NewPosition);
|
||||
case ELibvlcEventType::MediaPlayerSeekableChanged: return FString::Printf(TEXT("Player Seekable Changed: %s"), Event->Descriptor.MediaPlayerSeekableChanged.new_seekable ? *GTrue.ToString() : *GFalse.ToString());
|
||||
case ELibvlcEventType::MediaPlayerPausableChanged: return FString::Printf(TEXT("Player Pausable Changed: %s"), Event->Descriptor.MediaPlayerPausableChanged.NewPausable ? *GTrue.ToString() : *GFalse.ToString());
|
||||
case ELibvlcEventType::MediaPlayerTitleChanged: return FString::Printf(TEXT("Player Title Changed: %s"), Event->Descriptor.MediaPlayerTitleChanged.NewTitle);
|
||||
case ELibvlcEventType::MediaPlayerSnapshotTaken: return TEXT("Player Snapshot Taken");
|
||||
case ELibvlcEventType::MediaPlayerLengthChanged: return FString::Printf(TEXT("Player Length Changed: %i"), Event->Descriptor.MediaPlayerLengthChanged.NewLength);
|
||||
case ELibvlcEventType::MediaPlayerVout: return FString::Printf(TEXT("Player Vout: %i"), Event->Descriptor.MediaPlayerVout.NewCount);
|
||||
case ELibvlcEventType::MediaPlayerScrambledChanged: return FString::Printf(TEXT("Player Scambled Changed: %s"), Event->Descriptor.MediaPlayerScrambledChanged.NewScrambled ? *GTrue.ToString() : *GFalse.ToString());
|
||||
case ELibvlcEventType::MediaPlayerESAdded: return TEXT("Player ES Added");
|
||||
case ELibvlcEventType::MediaPlayerESDeleted: return TEXT("Player ES Deleted");
|
||||
case ELibvlcEventType::MediaPlayerESSelected: return TEXT("Player ES Selected");
|
||||
|
||||
case ELibvlcEventType::MediaListItemAdded: return TEXT("Media List Item Added");
|
||||
case ELibvlcEventType::MediaListWillAddItem: return TEXT("Media List Will Add Item");
|
||||
case ELibvlcEventType::MediaListItemDeleted: return TEXT("Media List Item Deleted");
|
||||
case ELibvlcEventType::MediaListWillDeleteItem: return TEXT("Media List Will Delete Item");
|
||||
case ELibvlcEventType::MediaListEndReached: return TEXT("Media List End Reached");
|
||||
|
||||
case ELibvlcEventType::MediaListViewItemAdded: return TEXT("Media List View Item Added");
|
||||
case ELibvlcEventType::MediaListViewWillAddItem: return TEXT("Media List View Will Add Item");
|
||||
case ELibvlcEventType::MediaListViewItemDeleted: return TEXT("Media List View Item Deleted");
|
||||
case ELibvlcEventType::MediaListViewWillDeleteItem: return TEXT("Media List View Will Delete Item");
|
||||
|
||||
case ELibvlcEventType::MediaListPlayerPlayed: return TEXT("Media List Player Played");
|
||||
case ELibvlcEventType::MediaListPlayerNextItemSet: return TEXT("Media List Player Next Item Set");
|
||||
case ELibvlcEventType::MediaListPlayerStopped: return TEXT("Media List Player Stopped");
|
||||
|
||||
case ELibvlcEventType::MediaDiscovererStarted: return TEXT("Media Discovery Started");
|
||||
case ELibvlcEventType::MediaDiscovererEnded: return TEXT("Media Discovery Ended");
|
||||
|
||||
case ELibvlcEventType::VlmMediaAdded: return TEXT("VLM Media Added");
|
||||
case ELibvlcEventType::VlmMediaRemoved: return TEXT("VLM Media Removed");
|
||||
case ELibvlcEventType::VlmMediaChanged: return TEXT("VLM Media Changed");
|
||||
case ELibvlcEventType::VlmMediaInstanceStarted: return TEXT("VLM Instance Started");
|
||||
case ELibvlcEventType::VlmMediaInstanceStopped: return TEXT("VLM Instance Stopped");
|
||||
case ELibvlcEventType::VlmMediaInstanceStatusInit: return TEXT("VLM Instance Status Init");
|
||||
case ELibvlcEventType::VlmMediaInstanceStatusOpening: return TEXT("VLM Instance Status Opening");
|
||||
case ELibvlcEventType::VlmMediaInstanceStatusPlaying: return TEXT("VLM Instance Status Playing");
|
||||
case ELibvlcEventType::VlmMediaInstanceStatusPause: return TEXT("VLM Instance Status Paused");
|
||||
case ELibvlcEventType::VlmMediaInstanceStatusEnd: return TEXT("VLM Instance Status End");
|
||||
case ELibvlcEventType::VlmMediaInstanceStatusError: return TEXT("VLM Instance Status Error");
|
||||
|
||||
default:
|
||||
return FString::Printf(TEXT("Unknown event %i"), (int32)Event->Type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FString StateToString(ELibvlcState State)
|
||||
{
|
||||
switch (State)
|
||||
{
|
||||
case ELibvlcState::NothingSpecial: return TEXT("Nothing Special");
|
||||
case ELibvlcState::Opening: return TEXT("Opening");
|
||||
case ELibvlcState::Buffering: return TEXT("Buffering");
|
||||
case ELibvlcState::Playing: return TEXT("Playing");
|
||||
case ELibvlcState::Paused: return TEXT("Paused");
|
||||
case ELibvlcState::Stopped: return TEXT("Stopped");
|
||||
case ELibvlcState::Ended: return TEXT("Ended");
|
||||
case ELibvlcState::Error: return TEXT("Error");
|
||||
default:
|
||||
return FString::Printf(TEXT("Unknown state %i"), (int32)State);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
|
||||
enum class ELibvlcState;
|
||||
struct FLibvlcEvent;
|
||||
|
||||
|
||||
namespace VlcMedia
|
||||
{
|
||||
/**
|
||||
* Convert a LibVLC event to string.
|
||||
*
|
||||
* @param Event The event code to convert.
|
||||
* @return The corresponding string.
|
||||
*/
|
||||
FString EventToString(FLibvlcEvent* Event);
|
||||
|
||||
/**
|
||||
* Convert a LibVLC state to string.
|
||||
*
|
||||
* @param Event The state code to convert.
|
||||
* @return The corresponding string.
|
||||
*/
|
||||
FString StateToString(ELibvlcState State);
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "Vlc.h"
|
||||
#include "VlcMediaPrivate.h"
|
||||
|
||||
#include "HAL/PlatformProcess.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include "Misc/Paths.h"
|
||||
|
||||
|
||||
#define VLC_DEFINE(Func) \
|
||||
FLibvlc##Func##Proc FVlc::Func = nullptr;
|
||||
|
||||
#define VLC_IMPORT(Name, Func) \
|
||||
Func = (FLibvlc##Func##Proc)FPlatformProcess::GetDllExport(LibHandle, TEXT(#Name)); \
|
||||
if (Func == nullptr) \
|
||||
{ \
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to import VLC function %s"), TEXT(#Name)); \
|
||||
Shutdown(); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define VLCCORE_IMPORT(Name, Func) \
|
||||
Func = (FLibvlc##Func##Proc)FPlatformProcess::GetDllExport(CoreHandle, TEXT(#Name)); \
|
||||
if (Func == nullptr) \
|
||||
{ \
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to import VLC Core function %s"), TEXT(#Name)); \
|
||||
Shutdown(); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
|
||||
/* Static initialization
|
||||
*****************************************************************************/
|
||||
|
||||
void* FVlc::CoreHandle = nullptr;
|
||||
void* FVlc::LibHandle = nullptr;
|
||||
FString FVlc::PluginDir;
|
||||
|
||||
|
||||
VLC_DEFINE(New)
|
||||
VLC_DEFINE(Release)
|
||||
VLC_DEFINE(Retain)
|
||||
|
||||
VLC_DEFINE(Errmsg)
|
||||
VLC_DEFINE(Clearerr)
|
||||
|
||||
VLC_DEFINE(EventAttach)
|
||||
VLC_DEFINE(EventDetach)
|
||||
VLC_DEFINE(EventTypeName)
|
||||
|
||||
VLC_DEFINE(LogGetContext)
|
||||
VLC_DEFINE(LogSet)
|
||||
VLC_DEFINE(LogUnset)
|
||||
|
||||
VLC_DEFINE(Free)
|
||||
VLC_DEFINE(GetChangeset)
|
||||
VLC_DEFINE(GetCompiler)
|
||||
VLC_DEFINE(GetVersion)
|
||||
|
||||
VLC_DEFINE(Clock)
|
||||
|
||||
VLC_DEFINE(MediaEventManager)
|
||||
VLC_DEFINE(MediaGetDuration)
|
||||
VLC_DEFINE(MediaGetStats)
|
||||
VLC_DEFINE(MediaNewCallbacks)
|
||||
VLC_DEFINE(MediaNewLocation)
|
||||
VLC_DEFINE(MediaNewPath)
|
||||
VLC_DEFINE(MediaParseAsync)
|
||||
VLC_DEFINE(MediaRelease)
|
||||
VLC_DEFINE(MediaRetain)
|
||||
VLC_DEFINE(MediaTracksGet)
|
||||
VLC_DEFINE(MediaTracksRelease)
|
||||
|
||||
VLC_DEFINE(MediaPlayerEventManager)
|
||||
VLC_DEFINE(MediaPlayerGetMedia)
|
||||
VLC_DEFINE(MediaPlayerNew)
|
||||
VLC_DEFINE(MediaPlayerNewFromMedia)
|
||||
VLC_DEFINE(MediaPlayerRelease)
|
||||
VLC_DEFINE(MediaPlayerRetain)
|
||||
VLC_DEFINE(MediaPlayerSetMedia)
|
||||
|
||||
VLC_DEFINE(MediaPlayerCanPause)
|
||||
VLC_DEFINE(MediaPlayerGetFps)
|
||||
VLC_DEFINE(MediaPlayerGetLength)
|
||||
VLC_DEFINE(MediaPlayerGetPosition)
|
||||
VLC_DEFINE(MediaPlayerGetRate)
|
||||
VLC_DEFINE(MediaPlayerGetState)
|
||||
VLC_DEFINE(MediaPlayerGetTime)
|
||||
VLC_DEFINE(MediaPlayerIsSeekable)
|
||||
VLC_DEFINE(MediaPlayerSetPosition)
|
||||
VLC_DEFINE(MediaPlayerSetRate)
|
||||
VLC_DEFINE(MediaPlayerSetTime)
|
||||
|
||||
VLC_DEFINE(MediaPlayerIsPlaying)
|
||||
VLC_DEFINE(MediaPlayerPause)
|
||||
VLC_DEFINE(MediaPlayerPlay)
|
||||
VLC_DEFINE(MediaPlayerSetPause)
|
||||
VLC_DEFINE(MediaPlayerStop)
|
||||
VLC_DEFINE(MediaPlayerWillPlay)
|
||||
|
||||
VLC_DEFINE(AudioGetTrack)
|
||||
VLC_DEFINE(AudioSetCallbacks)
|
||||
VLC_DEFINE(AudioSetFormat)
|
||||
VLC_DEFINE(AudioSetFormatCallbacks)
|
||||
VLC_DEFINE(AudioSetTrack)
|
||||
|
||||
VLC_DEFINE(VideoGetHeight)
|
||||
VLC_DEFINE(VideoGetSize)
|
||||
VLC_DEFINE(VideoGetSpu)
|
||||
VLC_DEFINE(VideoGetSpuCount)
|
||||
VLC_DEFINE(VideoGetTrack)
|
||||
VLC_DEFINE(VideoNewViewpoint)
|
||||
VLC_DEFINE(VideoGetWidth)
|
||||
VLC_DEFINE(VideoSetCallbacks)
|
||||
VLC_DEFINE(VideoSetFormat)
|
||||
VLC_DEFINE(VideoSetFormatCallbacks)
|
||||
VLC_DEFINE(VideoSetSpu)
|
||||
VLC_DEFINE(VideoSetTrack)
|
||||
VLC_DEFINE(VideoUpdateViewpoint)
|
||||
|
||||
VLC_DEFINE(AudioGetTrackDescription)
|
||||
VLC_DEFINE(VideoGetSpuDescription)
|
||||
VLC_DEFINE(VideoGetTrackDescription)
|
||||
VLC_DEFINE(TrackDescriptionListRelease)
|
||||
|
||||
VLC_DEFINE(FourccGetChromaDescription)
|
||||
|
||||
|
||||
/* FVlc static functions
|
||||
*****************************************************************************/
|
||||
|
||||
FString FVlc::GetPluginDir()
|
||||
{
|
||||
return PluginDir;
|
||||
}
|
||||
|
||||
|
||||
bool FVlc::Initialize()
|
||||
{
|
||||
// determine directory paths
|
||||
const FString BaseDir = IPluginManager::Get().FindPlugin("VlcMedia")->GetBaseDir();
|
||||
const FString VlcDir = FPaths::Combine(*BaseDir, TEXT("ThirdParty"), TEXT("vlc"));
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
const FString LibDir = FPaths::Combine(*VlcDir, TEXT("Linux"), TEXT("x86_64-unknown-linux-gnu"), TEXT("lib"));
|
||||
#elif PLATFORM_MAC
|
||||
const FString LibDir = FPaths::Combine(*VlcDir, TEXT("Mac"));
|
||||
#elif PLATFORM_WINDOWS
|
||||
#if PLATFORM_64BITS
|
||||
const FString LibDir = FPaths::Combine(*VlcDir, TEXT("Win64"));
|
||||
#else
|
||||
const FString LibDir = FPaths::Combine(*VlcDir, TEXT("Win32"));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// load required libraries in the correct order
|
||||
if (!LoadDependency(LibDir, TEXT("libvlccore"), CoreHandle))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LoadDependency(LibDir, TEXT("libvlc"), LibHandle))
|
||||
{
|
||||
FreeDependency(CoreHandle);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
PluginDir = FPaths::ConvertRelativePathToFull(FPaths::Combine(*LibDir, TEXT("plugins")));
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
PluginDir = FPaths::ConvertRelativePathToFull(FPaths::Combine(*LibDir, TEXT("vlc"), TEXT("plugins")));
|
||||
#endif
|
||||
|
||||
// import library functions
|
||||
VLC_IMPORT(libvlc_new, New)
|
||||
VLC_IMPORT(libvlc_release, Release)
|
||||
VLC_IMPORT(libvlc_retain, Retain)
|
||||
|
||||
VLC_IMPORT(libvlc_errmsg, Errmsg)
|
||||
VLC_IMPORT(libvlc_clearerr, Clearerr)
|
||||
|
||||
VLC_IMPORT(libvlc_event_attach, EventAttach)
|
||||
VLC_IMPORT(libvlc_event_detach, EventDetach)
|
||||
VLC_IMPORT(libvlc_event_type_name, EventTypeName)
|
||||
|
||||
VLC_IMPORT(libvlc_log_get_context, LogGetContext)
|
||||
VLC_IMPORT(libvlc_log_set, LogSet)
|
||||
VLC_IMPORT(libvlc_log_unset, LogUnset)
|
||||
|
||||
VLC_IMPORT(libvlc_free, Free)
|
||||
VLC_IMPORT(libvlc_get_changeset, GetChangeset)
|
||||
VLC_IMPORT(libvlc_get_compiler, GetCompiler)
|
||||
VLC_IMPORT(libvlc_get_version, GetVersion)
|
||||
|
||||
VLC_IMPORT(libvlc_clock, Clock)
|
||||
|
||||
VLC_IMPORT(libvlc_media_event_manager, MediaEventManager)
|
||||
VLC_IMPORT(libvlc_media_get_duration, MediaGetDuration)
|
||||
VLC_IMPORT(libvlc_media_get_stats, MediaGetStats)
|
||||
VLC_IMPORT(libvlc_media_new_callbacks, MediaNewCallbacks)
|
||||
VLC_IMPORT(libvlc_media_new_location, MediaNewLocation)
|
||||
VLC_IMPORT(libvlc_media_new_path, MediaNewPath)
|
||||
VLC_IMPORT(libvlc_media_parse_async, MediaParseAsync)
|
||||
VLC_IMPORT(libvlc_media_release, MediaRelease)
|
||||
VLC_IMPORT(libvlc_media_retain, MediaRetain)
|
||||
VLC_IMPORT(libvlc_media_tracks_get, MediaTracksGet)
|
||||
VLC_IMPORT(libvlc_media_tracks_release, MediaTracksRelease)
|
||||
|
||||
VLC_IMPORT(libvlc_media_player_event_manager, MediaPlayerEventManager)
|
||||
VLC_IMPORT(libvlc_media_player_get_media, MediaPlayerGetMedia)
|
||||
VLC_IMPORT(libvlc_media_player_new, MediaPlayerNew)
|
||||
VLC_IMPORT(libvlc_media_player_new_from_media, MediaPlayerNewFromMedia)
|
||||
VLC_IMPORT(libvlc_media_player_release, MediaPlayerRelease)
|
||||
VLC_IMPORT(libvlc_media_player_retain, MediaPlayerRetain)
|
||||
VLC_IMPORT(libvlc_media_player_set_media, MediaPlayerSetMedia)
|
||||
|
||||
VLC_IMPORT(libvlc_media_player_can_pause, MediaPlayerCanPause)
|
||||
VLC_IMPORT(libvlc_media_player_get_fps, MediaPlayerGetFps)
|
||||
VLC_IMPORT(libvlc_media_player_get_length, MediaPlayerGetLength)
|
||||
VLC_IMPORT(libvlc_media_player_get_position, MediaPlayerGetPosition)
|
||||
VLC_IMPORT(libvlc_media_player_get_rate, MediaPlayerGetRate)
|
||||
VLC_IMPORT(libvlc_media_player_get_state, MediaPlayerGetState)
|
||||
VLC_IMPORT(libvlc_media_player_get_time, MediaPlayerGetTime)
|
||||
VLC_IMPORT(libvlc_media_player_is_seekable, MediaPlayerIsSeekable)
|
||||
VLC_IMPORT(libvlc_media_player_set_position, MediaPlayerSetPosition)
|
||||
VLC_IMPORT(libvlc_media_player_set_rate, MediaPlayerSetRate)
|
||||
VLC_IMPORT(libvlc_media_player_set_time, MediaPlayerSetTime)
|
||||
|
||||
VLC_IMPORT(libvlc_media_player_is_playing, MediaPlayerIsPlaying)
|
||||
VLC_IMPORT(libvlc_media_player_pause, MediaPlayerPause)
|
||||
VLC_IMPORT(libvlc_media_player_play, MediaPlayerPlay)
|
||||
VLC_IMPORT(libvlc_media_player_set_pause, MediaPlayerSetPause)
|
||||
VLC_IMPORT(libvlc_media_player_stop, MediaPlayerStop)
|
||||
VLC_IMPORT(libvlc_media_player_will_play, MediaPlayerWillPlay)
|
||||
|
||||
VLC_IMPORT(libvlc_audio_get_track, AudioGetTrack)
|
||||
VLC_IMPORT(libvlc_audio_set_callbacks, AudioSetCallbacks)
|
||||
VLC_IMPORT(libvlc_audio_set_format, AudioSetFormat)
|
||||
VLC_IMPORT(libvlc_audio_set_format_callbacks, AudioSetFormatCallbacks)
|
||||
VLC_IMPORT(libvlc_audio_set_track, AudioSetTrack)
|
||||
|
||||
VLC_IMPORT(libvlc_video_get_height, VideoGetHeight)
|
||||
VLC_IMPORT(libvlc_video_get_size, VideoGetSize)
|
||||
VLC_IMPORT(libvlc_video_get_spu, VideoGetSpu)
|
||||
VLC_IMPORT(libvlc_video_get_spu_count, VideoGetSpuCount)
|
||||
VLC_IMPORT(libvlc_video_get_track, VideoGetTrack)
|
||||
VLC_IMPORT(libvlc_video_get_width, VideoGetWidth)
|
||||
VLC_IMPORT(libvlc_video_new_viewpoint, VideoNewViewpoint)
|
||||
VLC_IMPORT(libvlc_video_set_callbacks, VideoSetCallbacks)
|
||||
VLC_IMPORT(libvlc_video_set_format, VideoSetFormat)
|
||||
VLC_IMPORT(libvlc_video_set_format_callbacks, VideoSetFormatCallbacks)
|
||||
VLC_IMPORT(libvlc_video_set_spu, VideoSetSpu)
|
||||
VLC_IMPORT(libvlc_video_set_track, VideoSetTrack)
|
||||
VLC_IMPORT(libvlc_video_update_viewpoint, VideoUpdateViewpoint)
|
||||
|
||||
VLC_IMPORT(libvlc_audio_get_track_description, AudioGetTrackDescription)
|
||||
VLC_IMPORT(libvlc_video_get_spu_description, VideoGetSpuDescription)
|
||||
VLC_IMPORT(libvlc_video_get_track_description, VideoGetTrackDescription)
|
||||
VLC_IMPORT(libvlc_track_description_release, TrackDescriptionListRelease)
|
||||
|
||||
// import core functions
|
||||
VLCCORE_IMPORT(vlc_fourcc_GetChromaDescription, FourccGetChromaDescription)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FVlc::Shutdown()
|
||||
{
|
||||
PluginDir.Empty();
|
||||
|
||||
FreeDependency(LibHandle);
|
||||
FreeDependency(CoreHandle);
|
||||
}
|
||||
|
||||
|
||||
/* FVlc static functions
|
||||
*****************************************************************************/
|
||||
|
||||
void FVlc::FreeDependency(void*& Handle)
|
||||
{
|
||||
if (Handle != nullptr)
|
||||
{
|
||||
FPlatformProcess::FreeDllHandle(Handle);
|
||||
Handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FVlc::LoadDependency(const FString& Dir, const FString& Name, void*& Handle)
|
||||
{
|
||||
FString Lib = Name + TEXT(".") + FPlatformProcess::GetModuleExtension();
|
||||
FString Path = Dir.IsEmpty() ? *Lib : FPaths::Combine(*Dir, *Lib);
|
||||
|
||||
Handle = FPlatformProcess::GetDllHandle(*Path);
|
||||
|
||||
if (Handle == nullptr)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to load required library %s. Plug-in will not be functional."), *Lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "VlcImports.h"
|
||||
#include "VlcTypes.h"
|
||||
|
||||
|
||||
class FVlc
|
||||
{
|
||||
public:
|
||||
|
||||
static const uint32 MaxPlanes = 5;
|
||||
|
||||
public:
|
||||
|
||||
static FString GetPluginDir();
|
||||
static bool Initialize();
|
||||
static void Shutdown();
|
||||
|
||||
public:
|
||||
|
||||
static FLibvlcNewProc New;
|
||||
static FLibvlcReleaseProc Release;
|
||||
static FLibvlcRetainProc Retain;
|
||||
|
||||
static FLibvlcErrmsgProc Errmsg;
|
||||
static FLibvlcClearerrProc Clearerr;
|
||||
|
||||
static FLibvlcEventAttachProc EventAttach;
|
||||
static FLibvlcEventAttachProc EventDetach;
|
||||
static FLibvlcEventTypeNameProc EventTypeName;
|
||||
|
||||
static FLibvlcLogGetContextProc LogGetContext;
|
||||
static FLibvlcLogSetProc LogSet;
|
||||
static FLibvlcLogUnsetProc LogUnset;
|
||||
|
||||
static FLibvlcFreeProc Free;
|
||||
static FLibvlcGetChangesetProc GetChangeset;
|
||||
static FLibvlcGetCompilerProc GetCompiler;
|
||||
static FLibvlcGetVersionProc GetVersion;
|
||||
|
||||
static FLibvlcClockProc Clock;
|
||||
|
||||
static FLibvlcMediaEventManagerProc MediaEventManager;
|
||||
static FLibvlcMediaGetDurationProc MediaGetDuration;
|
||||
static FLibvlcMediaGetStatsProc MediaGetStats;
|
||||
static FLibvlcMediaNewCallbacksProc MediaNewCallbacks;
|
||||
static FLibvlcMediaNewLocationProc MediaNewLocation;
|
||||
static FLibvlcMediaNewPathProc MediaNewPath;
|
||||
static FLibvlcMediaParseAsyncProc MediaParseAsync;
|
||||
static FLibvlcMediaReleaseProc MediaRelease;
|
||||
static FLibvlcMediaRetainProc MediaRetain;
|
||||
static FLibvlcMediaTracksGetProc MediaTracksGet;
|
||||
static FLibvlcMediaTracksReleaseProc MediaTracksRelease;
|
||||
|
||||
static FLibvlcMediaPlayerEventManagerProc MediaPlayerEventManager;
|
||||
static FLibvlcMediaPlayerGetMediaProc MediaPlayerGetMedia;
|
||||
static FLibvlcMediaPlayerNewProc MediaPlayerNew;
|
||||
static FLibvlcMediaPlayerNewFromMediaProc MediaPlayerNewFromMedia;
|
||||
static FLibvlcMediaPlayerReleaseProc MediaPlayerRelease;
|
||||
static FLibvlcMediaPlayerRetainProc MediaPlayerRetain;
|
||||
static FLibvlcMediaPlayerSetMediaProc MediaPlayerSetMedia;
|
||||
|
||||
static FLibvlcMediaPlayerCanPauseProc MediaPlayerCanPause;
|
||||
static FLibvlcMediaPlayerGetFpsProc MediaPlayerGetFps;
|
||||
static FLibvlcMediaPlayerGetLengthProc MediaPlayerGetLength;
|
||||
static FLibvlcMediaPlayerGetPositionProc MediaPlayerGetPosition;
|
||||
static FLibvlcMediaPlayerGetRateProc MediaPlayerGetRate;
|
||||
static FLibvlcMediaPlayerGetStateProc MediaPlayerGetState;
|
||||
static FLibvlcMediaPlayerGetTimeProc MediaPlayerGetTime;
|
||||
static FLibvlcMediaPlayerIsSeekableProc MediaPlayerIsSeekable;
|
||||
static FLibvlcMediaPlayerSetPositionProc MediaPlayerSetPosition;
|
||||
static FLibvlcMediaPlayerSetRateProc MediaPlayerSetRate;
|
||||
static FLibvlcMediaPlayerSetTimeProc MediaPlayerSetTime;
|
||||
|
||||
static FLibvlcMediaPlayerIsPlayingProc MediaPlayerIsPlaying;
|
||||
static FLibvlcMediaPlayerPauseProc MediaPlayerPause;
|
||||
static FLibvlcMediaPlayerPlayProc MediaPlayerPlay;
|
||||
static FLibvlcMediaPlayerSetPauseProc MediaPlayerSetPause;
|
||||
static FLibvlcMediaPlayerStopProc MediaPlayerStop;
|
||||
static FLibvlcMediaPlayerWillPlayProc MediaPlayerWillPlay;
|
||||
|
||||
static FLibvlcAudioGetTrackProc AudioGetTrack;
|
||||
static FLibvlcAudioSetCallbacksProc AudioSetCallbacks;
|
||||
static FLibvlcAudioSetFormatProc AudioSetFormat;
|
||||
static FLibvlcAudioSetFormatCallbacksProc AudioSetFormatCallbacks;
|
||||
static FLibvlcAudioSetTrackProc AudioSetTrack;
|
||||
|
||||
static FLibvlcVideoGetHeightProc VideoGetHeight;
|
||||
static FLibvlcVideoGetSizeProc VideoGetSize;
|
||||
static FLibvlcVideoGetSpuProc VideoGetSpu;
|
||||
static FLibvlcVideoGetSpuCountProc VideoGetSpuCount;
|
||||
static FLibvlcVideoGetTrackProc VideoGetTrack;
|
||||
static FLibvlcVideoGetWidthProc VideoGetWidth;
|
||||
static FLibvlcVideoNewViewpointProc VideoNewViewpoint;
|
||||
static FLibvlcVideoSetCallbacksProc VideoSetCallbacks;
|
||||
static FLibvlcVideoSetFormatProc VideoSetFormat;
|
||||
static FLibvlcVideoSetFormatCallbacksProc VideoSetFormatCallbacks;
|
||||
static FLibvlcVideoSetSpuProc VideoSetSpu;
|
||||
static FLibvlcVideoSetTrackProc VideoSetTrack;
|
||||
static FLibvlcVideoUpdateViewpointProc VideoUpdateViewpoint;
|
||||
|
||||
static FLibvlcAudioGetTrackDescriptionProc AudioGetTrackDescription;
|
||||
static FLibvlcVideoGetSpuDescriptionProc VideoGetSpuDescription;
|
||||
static FLibvlcVideoGetTrackDescriptionProc VideoGetTrackDescription;
|
||||
static FLibvlcTrackDescriptionListReleaseProc TrackDescriptionListRelease;
|
||||
|
||||
static FLibvlcFourccGetChromaDescriptionProc FourccGetChromaDescription;
|
||||
|
||||
public:
|
||||
|
||||
static int64 Delay(int64 Timestamp)
|
||||
{
|
||||
return Timestamp - Clock();
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
static void FreeDependency(void*& Handle);
|
||||
static bool LoadDependency(const FString& Dir, const FString& Name, void*& Handle);
|
||||
|
||||
private:
|
||||
|
||||
static void* CoreHandle;
|
||||
static void* LibHandle;
|
||||
static FString PluginDir;
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
static void* GccHandle;
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,175 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "VlcTypes.h"
|
||||
|
||||
|
||||
// library instance
|
||||
typedef FLibvlcInstance* (*FLibvlcNewProc)(int32 /*Argc*/, const ANSICHAR* const* /*Argv*/);
|
||||
typedef void (*FLibvlcReleaseProc)(FLibvlcInstance* /*Instance*/);
|
||||
typedef void (*FLibvlcRetainProc)(FLibvlcInstance* /*Instance*/);
|
||||
|
||||
// error handling
|
||||
typedef const char* (*FLibvlcErrmsgProc)();
|
||||
typedef void (*FLibvlcClearerrProc)();
|
||||
|
||||
// events
|
||||
typedef void (*FLibvlcCallback)(FLibvlcEvent* /*Event*/, void* /*UserData*/);
|
||||
typedef int32 (*FLibvlcEventAttachProc)(FLibvlcEventManager* /*EventManager*/, ELibvlcEventType /*EventType*/, FLibvlcCallback /*Callback*/, void* /*UserData*/);
|
||||
typedef int32 (*FLibvlcEventDetachProc)(FLibvlcEventManager* /*EventManager*/, ELibvlcEventType /*EventType*/, FLibvlcCallback /*Callback*/, void* /*UserData*/);
|
||||
typedef const ANSICHAR* (*FLibvlcEventTypeNameProc)(ELibvlcEventType /*EventType*/);
|
||||
|
||||
// logging
|
||||
typedef void (*FLibvlcLogCb)(void* /*Data*/, ELibvlcLogLevel /*Level*/, FLibvlcLog* /*Context*/, const char* /*Format*/, va_list /*Args*/);
|
||||
typedef void (*FLibvlcLogGetContextProc)(FLibvlcLog* /*Context*/, const char** /*Module*/, const char** /*File*/, unsigned* /*Line*/);
|
||||
typedef void (*FLibvlcLogSetProc)(FLibvlcInstance* /*Instance*/, FLibvlcLogCb /*Callback*/, void* /*Data*/);
|
||||
typedef void (*FLibvlcLogUnsetProc)(FLibvlcInstance* /*Instance*/);
|
||||
|
||||
// misc
|
||||
typedef void (*FLibvlcFreeProc)(void* /*Pointer*/);
|
||||
typedef char* (*FLibvlcGetChangesetProc)();
|
||||
typedef char* (*FLibvlcGetCompilerProc)();
|
||||
typedef char* (*FLibvlcGetVersionProc)();
|
||||
|
||||
// time
|
||||
typedef int64 (*FLibvlcClockProc)();
|
||||
|
||||
// media callbacks
|
||||
typedef void (*FLibvlcMediaCloseCb)(void* /*Opaque*/);
|
||||
typedef int32 (*FLibvlcMediaOpenCb)(void* /*Opaque*/, void** /*OutData*/, uint64* /*OutSize*/);
|
||||
typedef SSIZE_T (*FLibvlcMediaReadCb)(void* /*Opaque*/, void* /*Buffer*/, SIZE_T /*Length*/);
|
||||
typedef int32 (*FLibvlcMediaSeekCb)(void* /*Opaque*/, uint64 /*Offset*/);
|
||||
|
||||
// media
|
||||
typedef FLibvlcEventManager* (*FLibvlcMediaEventManagerProc)(FLibvlcMedia* /*Media*/);
|
||||
typedef int64 (*FLibvlcMediaGetDurationProc)(FLibvlcMedia* /*Media*/);
|
||||
typedef int (*FLibvlcMediaGetStatsProc)(FLibvlcMedia* /*Media*/, FLibvlcMediaStats* /*Stats*/);
|
||||
|
||||
typedef FLibvlcMedia* (*FLibvlcMediaNewCallbacksProc)(
|
||||
FLibvlcInstance* /*Instance*/,
|
||||
FLibvlcMediaOpenCb /*OpenCb*/,
|
||||
FLibvlcMediaReadCb /*ReadCb*/,
|
||||
FLibvlcMediaSeekCb /*SeekCb*/,
|
||||
FLibvlcMediaCloseCb /*CloseCb*/,
|
||||
void* /*Opaque*/);
|
||||
|
||||
typedef FLibvlcMedia* (*FLibvlcMediaNewLocationProc)(FLibvlcInstance* /*Instance*/, const ANSICHAR* /*Location*/);
|
||||
typedef FLibvlcMedia* (*FLibvlcMediaNewPathProc)(FLibvlcInstance* /*Instance*/, const ANSICHAR* /*Path*/);
|
||||
typedef void (*FLibvlcMediaParseAsyncProc)(FLibvlcMedia* /*Media*/);
|
||||
typedef void (*FLibvlcMediaReleaseProc)(FLibvlcMedia* /*Media*/);
|
||||
typedef void (*FLibvlcMediaRetainProc)(FLibvlcMedia* /*Media*/);
|
||||
typedef uint32 (*FLibvlcMediaTracksGetProc)(FLibvlcMedia* /*Media*/, FLibvlcMediaTrack*** /*OutTracks*/);
|
||||
typedef void (*FLibvlcMediaTracksReleaseProc)(FLibvlcMediaTrack** /*Tracks*/, uint32 /*Count*/);
|
||||
|
||||
// media player
|
||||
typedef FLibvlcEventManager* (*FLibvlcMediaPlayerEventManagerProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef FLibvlcMedia* (*FLibvlcMediaPlayerGetMediaProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef FLibvlcMediaPlayer* (*FLibvlcMediaPlayerNewProc)(FLibvlcInstance* /*Instance*/);
|
||||
typedef FLibvlcMediaPlayer* (*FLibvlcMediaPlayerNewFromMediaProc)(FLibvlcMedia* /*Media*/);
|
||||
typedef void (*FLibvlcMediaPlayerReleaseProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef void (*FLibvlcMediaPlayerRetainProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef void (*FLibvlcMediaPlayerSetMediaProc)(FLibvlcMediaPlayer* /*Player*/, FLibvlcMedia* /*Media*/);
|
||||
|
||||
// media player status
|
||||
typedef int32 (*FLibvlcMediaPlayerCanPauseProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef float (*FLibvlcMediaPlayerGetFpsProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int64 (*FLibvlcMediaPlayerGetLengthProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef float (*FLibvlcMediaPlayerGetPositionProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef float (*FLibvlcMediaPlayerGetRateProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef ELibvlcState (*FLibvlcMediaPlayerGetStateProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int64 (*FLibvlcMediaPlayerGetTimeProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int32 (*FLibvlcMediaPlayerIsSeekableProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef void (*FLibvlcMediaPlayerSetPositionProc)(FLibvlcMediaPlayer* /*Player*/, float /*Position*/);
|
||||
typedef int32 (*FLibvlcMediaPlayerSetRateProc)(FLibvlcMediaPlayer* /*Player*/, float /*Rate*/);
|
||||
typedef void (*FLibvlcMediaPlayerSetTimeProc)(FLibvlcMediaPlayer* /*Player*/, int64 /*Time*/);
|
||||
|
||||
// media player control
|
||||
typedef int32 (*FLibvlcMediaPlayerIsPlayingProc)(const FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef void (*FLibvlcMediaPlayerPauseProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int32 (*FLibvlcMediaPlayerPlayProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef void (*FLibvlcMediaPlayerSetPauseProc)(FLibvlcMediaPlayer* /*Player*/, int32 /*DoPause*/);
|
||||
typedef void (*FLibvlcMediaPlayerStopProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int32 (*FLibvlcMediaPlayerWillPlayProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
|
||||
// audio
|
||||
typedef void (*FLibvlcAudioDrainCb)(void* /*Opaque*/);
|
||||
typedef void (*FLibvlcAudioFlushCb)(void* /*Opaque*/, int64 /*Timestamp*/);
|
||||
typedef void (*FLibvlcAudioPauseCb)(void* /*Opaque*/, int64 /*Timestamp*/);
|
||||
typedef void (*FLibvlcAudioPlayCb)(void* /*Opaque*/, void* /*Samples*/, uint32 /*Count*/, int64 /*Timestamp*/);
|
||||
typedef void (*FLibvlcAudioResumeCb)(void* /*Opaque*/, int64 /*Timestamp*/);
|
||||
|
||||
typedef void (*FLibvlcAudioSetCallbacksProc)(
|
||||
FLibvlcMediaPlayer* /*Player*/,
|
||||
FLibvlcAudioPlayCb /*Play*/,
|
||||
FLibvlcAudioPauseCb /*Pause*/,
|
||||
FLibvlcAudioResumeCb /*Resume*/,
|
||||
FLibvlcAudioFlushCb /*Flush*/,
|
||||
FLibvlcAudioDrainCb /*Drain*/,
|
||||
void* /*Opaque*/);
|
||||
|
||||
typedef void (*FLibvlcAudioSetFormatProc)(
|
||||
FLibvlcMediaPlayer* /*Player*/,
|
||||
const ANSICHAR* /*Format*/,
|
||||
uint32 Rate,
|
||||
uint32 Channels);
|
||||
|
||||
typedef int32 (*FLibvlcAudioSetupCb)(void** /*Opaque*/, ANSICHAR* /*Format*/, uint32* /*Rate*/, uint32* /*Channels*/);
|
||||
typedef void (*FLibvlcAudioCleanupCb)(void* /*Opaque*/);
|
||||
|
||||
typedef void (*FLibvlcAudioSetFormatCallbacksProc)(
|
||||
FLibvlcMediaPlayer* /*Player*/,
|
||||
FLibvlcAudioSetupCb /*Setup*/,
|
||||
FLibvlcAudioCleanupCb /*Cleanup*/);
|
||||
|
||||
typedef int32 (*FLibvlcAudioGetTrackProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int32 (*FLibvlcAudioSetTrackProc)(FLibvlcMediaPlayer* /*Player*/, int32 /*TrackId*/);
|
||||
|
||||
// video
|
||||
typedef void* (*FLibvlcVideoLockCb)(void* /*Opaque*/, void** /*Planes*/);
|
||||
typedef void (*FlibvlcVideoUnlockCb)(void* /*Opaque*/, void* /*Picture*/, void* const* /*Planes*/);
|
||||
typedef void (*FlibvlcVideoDisplayCb)(void* /*Opaque*/, void* /*Picture*/);
|
||||
|
||||
typedef void (*FLibvlcVideoSetCallbacksProc)(
|
||||
FLibvlcMediaPlayer* /*Player*/,
|
||||
FLibvlcVideoLockCb /*Lock*/,
|
||||
FlibvlcVideoUnlockCb /*Unlock*/,
|
||||
FlibvlcVideoDisplayCb /*Display*/,
|
||||
void* /*Opaque*/);
|
||||
|
||||
typedef void (*FLibvlcVideoSetFormatProc)(
|
||||
FLibvlcMediaPlayer* /*Player*/,
|
||||
const ANSICHAR* /*Chroma*/,
|
||||
uint32 /*Width*/,
|
||||
uint32 /*Height*/,
|
||||
uint32 /*Pitch*/);
|
||||
|
||||
typedef void (*FLibvlcVideoCleanupCb)(void* /*Opaque*/);
|
||||
typedef uint32 (*FLibvlcVideoFormatCb)(void** /*Opaque*/, ANSICHAR* /*Chroma*/, uint32* /*Width*/, uint32* /*Height*/, uint32* /*Pitches*/, uint32* /*Lines*/);
|
||||
|
||||
typedef void (*FLibvlcVideoSetFormatCallbacksProc)(
|
||||
FLibvlcMediaPlayer* /*Player*/,
|
||||
FLibvlcVideoFormatCb /*Setup*/,
|
||||
FLibvlcVideoCleanupCb /*Cleanup*/
|
||||
);
|
||||
|
||||
typedef int32 (*FLibvlcVideoGetHeightProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int32 (*FLibvlcVideoGetSizeProc)(FLibvlcMediaPlayer* /*Player*/, uint32 /*VideoNum*/, uint32* /*Width*/, uint32* /*Height*/);
|
||||
typedef int32 (*FLibvlcVideoGetSpuProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int32 (*FLibvlcVideoGetSpuCountProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int32 (*FLibvlcVideoGetTrackProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef int32(*FLibvlcVideoGetWidthProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef FLibvlcVideoViewpoint* (*FLibvlcVideoNewViewpointProc)();
|
||||
typedef int32 (*FLibvlcVideoSetSpuProc)(FLibvlcMediaPlayer* /*Player*/, int32 /*SpuId*/);
|
||||
typedef int32 (*FLibvlcVideoSetTrackProc)(FLibvlcMediaPlayer* /*Player*/, int32 /*TrackId*/);
|
||||
typedef int32 (*FLibvlcVideoUpdateViewpointProc)(FLibvlcMediaPlayer* /*Player*/, FLibvlcVideoViewpoint* /*Viewpoint*/, bool /*Absolute*/);
|
||||
|
||||
// tracks
|
||||
typedef FLibvlcTrackDescription* (*FLibvlcAudioGetTrackDescriptionProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef FLibvlcTrackDescription* (*FLibvlcVideoGetSpuDescriptionProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef FLibvlcTrackDescription* (*FLibvlcVideoGetTrackDescriptionProc)(FLibvlcMediaPlayer* /*Player*/);
|
||||
typedef void(*FLibvlcTrackDescriptionListReleaseProc)(FLibvlcTrackDescription* /*Desription*/);
|
||||
|
||||
// FourCC
|
||||
typedef FLibvlcChromaDescription* (*FLibvlcFourccGetChromaDescriptionProc)(FLibvlcFourcc /*Fourcc*/);
|
||||
@@ -0,0 +1,392 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
|
||||
/** Enumerates event types. */
|
||||
enum class ELibvlcEventType
|
||||
{
|
||||
MediaMetaChanged = 0,
|
||||
MediaSubItemAdded,
|
||||
MediaDurationChanged,
|
||||
MediaParsedChanged,
|
||||
MediaFreed,
|
||||
MediaStateChanged,
|
||||
MediaSubItemTreeAdded,
|
||||
|
||||
MediaPlayerMediaChanged = 0x100,
|
||||
MediaPlayerNothingSpecial,
|
||||
MediaPlayerOpening,
|
||||
MediaPlayerBuffering,
|
||||
MediaPlayerPlaying,
|
||||
MediaPlayerPaused,
|
||||
MediaPlayerStopped,
|
||||
MediaPlayerForward,
|
||||
MediaPlayerBackward,
|
||||
MediaPlayerEndReached,
|
||||
MediaPlayerEncounteredError,
|
||||
MediaPlayerTimeChanged,
|
||||
MediaPlayerPositionChanged,
|
||||
MediaPlayerSeekableChanged,
|
||||
MediaPlayerPausableChanged,
|
||||
MediaPlayerTitleChanged,
|
||||
MediaPlayerSnapshotTaken,
|
||||
MediaPlayerLengthChanged,
|
||||
MediaPlayerVout,
|
||||
MediaPlayerScrambledChanged,
|
||||
MediaPlayerESAdded,
|
||||
MediaPlayerESDeleted,
|
||||
MediaPlayerESSelected,
|
||||
|
||||
MediaListItemAdded = 0x200,
|
||||
MediaListWillAddItem,
|
||||
MediaListItemDeleted,
|
||||
MediaListWillDeleteItem,
|
||||
MediaListEndReached,
|
||||
|
||||
MediaListViewItemAdded = 0x300,
|
||||
MediaListViewWillAddItem,
|
||||
MediaListViewItemDeleted,
|
||||
MediaListViewWillDeleteItem,
|
||||
|
||||
MediaListPlayerPlayed = 0x400,
|
||||
MediaListPlayerNextItemSet,
|
||||
MediaListPlayerStopped,
|
||||
|
||||
MediaDiscovererStarted = 0x500,
|
||||
MediaDiscovererEnded,
|
||||
|
||||
VlmMediaAdded = 0x600,
|
||||
VlmMediaRemoved,
|
||||
VlmMediaChanged,
|
||||
VlmMediaInstanceStarted,
|
||||
VlmMediaInstanceStopped,
|
||||
VlmMediaInstanceStatusInit,
|
||||
VlmMediaInstanceStatusOpening,
|
||||
VlmMediaInstanceStatusPlaying,
|
||||
VlmMediaInstanceStatusPause,
|
||||
VlmMediaInstanceStatusEnd,
|
||||
VlmMediaInstanceStatusError
|
||||
};
|
||||
|
||||
|
||||
/** Enumerates logging levels. */
|
||||
enum class ELibvlcLogLevel
|
||||
{
|
||||
Debug = 0,
|
||||
Notice = 2,
|
||||
Warning = 3,
|
||||
Error = 4
|
||||
};
|
||||
|
||||
|
||||
/** Enumerates meta data types. */
|
||||
enum class ELibvlcMeta
|
||||
{
|
||||
Title,
|
||||
Artist,
|
||||
Genre,
|
||||
Copyright,
|
||||
Album,
|
||||
TrackNumber,
|
||||
Description,
|
||||
Rating,
|
||||
Date,
|
||||
Setting,
|
||||
URL,
|
||||
Language,
|
||||
NowPlaying,
|
||||
Publisher,
|
||||
EncodedBy,
|
||||
ArtworkURL,
|
||||
TrackID,
|
||||
TrackTotal,
|
||||
Director,
|
||||
Season,
|
||||
Episode,
|
||||
ShowName,
|
||||
Actors,
|
||||
AlbumArtist,
|
||||
DiscNumber
|
||||
};
|
||||
|
||||
|
||||
/** Enumerates possible media player states. */
|
||||
enum class ELibvlcState
|
||||
{
|
||||
NothingSpecial = 0,
|
||||
Opening,
|
||||
Buffering,
|
||||
Playing,
|
||||
Paused,
|
||||
Stopped,
|
||||
Ended,
|
||||
Error
|
||||
};
|
||||
|
||||
|
||||
/** Enumerates known track types. */
|
||||
enum class ELibvlcTrackType
|
||||
{
|
||||
Unknown,
|
||||
Audio,
|
||||
Video,
|
||||
Text
|
||||
};
|
||||
|
||||
|
||||
/** Opaque structure representing a LibVLC event manager. */
|
||||
typedef struct FLibvlcEventManager FLibvlcEventManager;
|
||||
|
||||
/** Opaque structure representing a LibVLC instance. */
|
||||
typedef struct FLibvlcInstance FLibvlcInstance;
|
||||
|
||||
/** Opaque structure representing a LibVLC log context. */
|
||||
typedef struct FLibvlcLog FLibvlcLog;
|
||||
|
||||
/** Opaque structure representing a media instance. */
|
||||
typedef struct FLibvlcMedia FLibvlcMedia;
|
||||
|
||||
/** Opaque structure representing a LibVLC media player. */
|
||||
typedef struct FLibvlcMediaPlayer FLibvlcMediaPlayer;
|
||||
|
||||
/** FourCC code type. */
|
||||
typedef uint32 FLibvlcFourcc;
|
||||
|
||||
|
||||
/**
|
||||
* Structure for chroma format descriptions (libvlc_chroma_description_t).
|
||||
*/
|
||||
struct FLibvlcChromaDescription
|
||||
{
|
||||
uint32 PlaneCount;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32 Num;
|
||||
uint32 Den;
|
||||
} W;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 Num;
|
||||
uint32 Den;
|
||||
} H;
|
||||
} P[4];
|
||||
|
||||
uint32 PixelSize;
|
||||
uint32 PixelBits;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Structure for VLC events (libvlc_event_t).
|
||||
*/
|
||||
struct FLibvlcEvent
|
||||
{
|
||||
/** The type of event (see ELibvlcEvents) */
|
||||
ELibvlcEventType Type;
|
||||
|
||||
/** The object emitting the event. */
|
||||
void *Obj;
|
||||
|
||||
union
|
||||
{
|
||||
// media descriptor
|
||||
struct
|
||||
{
|
||||
ELibvlcMeta MetaType;
|
||||
} MediaMetaChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* NewChild;
|
||||
} MediaSubitemAdded;
|
||||
|
||||
struct
|
||||
{
|
||||
int64 NewDuration;
|
||||
} MediaDurationChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
int32 NewStatus;
|
||||
} MediaParsedChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* Md;
|
||||
} MediaFreed;
|
||||
|
||||
struct
|
||||
{
|
||||
ELibvlcState NewState;
|
||||
} MediaStateChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* Item;
|
||||
} MediaSubitemtreeAdded;
|
||||
|
||||
// media instance
|
||||
struct
|
||||
{
|
||||
float NewCache;
|
||||
} MediaPlayerBuffering;
|
||||
|
||||
struct
|
||||
{
|
||||
float NewPosition;
|
||||
} MediaPlayerPositionChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
int64 NewTime;
|
||||
} MediaPlayerTimeChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
int32 NewTitle;
|
||||
} MediaPlayerTitleChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
int32 new_seekable;
|
||||
} MediaPlayerSeekableChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
int32 NewPausable;
|
||||
} MediaPlayerPausableChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
int32 NewScrambled;
|
||||
} MediaPlayerScrambledChanged;
|
||||
|
||||
struct
|
||||
{
|
||||
int32 NewCount;
|
||||
} MediaPlayerVout;
|
||||
|
||||
// media list
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* Item;
|
||||
int32 Index;
|
||||
} MediaListItemAdded;
|
||||
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* Item;
|
||||
int32 Index;
|
||||
} MediaListWillAddItem;
|
||||
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* Item;
|
||||
int32 Index;
|
||||
} MediaListItemDeleted;
|
||||
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* Item;
|
||||
int32 Index;
|
||||
} MediaListWillDeleteItem;
|
||||
|
||||
// media list player
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* Item;
|
||||
} MediaListPlayerNextItemSet;
|
||||
|
||||
// snapshot taken
|
||||
struct
|
||||
{
|
||||
ANSICHAR* Filename;
|
||||
} MediaPlayerSnapshotTaken;
|
||||
|
||||
// Length changed
|
||||
struct
|
||||
{
|
||||
int64 NewLength;
|
||||
} MediaPlayerLengthChanged;
|
||||
|
||||
// VLM media
|
||||
struct
|
||||
{
|
||||
const ANSICHAR* MediaName;
|
||||
const ANSICHAR* InstanceName;
|
||||
} VlmMediaEvent;
|
||||
|
||||
// extra MediaPlayer
|
||||
struct
|
||||
{
|
||||
FLibvlcMedia* NewMedia;
|
||||
} MediaPlayerMediaChanged;
|
||||
} Descriptor;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Structure for VLC media statistics (libvlc_media_stats).
|
||||
*/
|
||||
struct FLibvlcMediaStats
|
||||
{
|
||||
int32 ReadBytes;
|
||||
float InputBitrate;
|
||||
int32 DemuxReadBytes;
|
||||
float DemuxBitrate;
|
||||
int32 DemuxCorrupted;
|
||||
int32 DemuxDiscontinuity;
|
||||
int32 DecodedVideo;
|
||||
int32 DecodedAudio;
|
||||
int32 DisplayedPictures;
|
||||
int32 LostPictures;
|
||||
int32 PlayedAbuffers;
|
||||
int32 LostAbuffers;
|
||||
int32 SentPackets;
|
||||
int32 SentBytes;
|
||||
float SendBitrate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Structure for VLC media tracks (libvlc_media_track).
|
||||
*/
|
||||
struct FLibvlcMediaTrack
|
||||
{
|
||||
uint32 Codec;
|
||||
uint32 OriginalFourCC;
|
||||
int32 Id;
|
||||
ELibvlcTrackType Type;
|
||||
int32 Profile;
|
||||
int32 Level;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Structure for VLC media track descriptions (libvlc_track_t).
|
||||
*/
|
||||
struct FLibvlcTrackDescription
|
||||
{
|
||||
int32 Id;
|
||||
ANSICHAR* Name;
|
||||
FLibvlcTrackDescription* Next;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Structure for VLC video viewpoints (libvlc_video_viewpoint_t).
|
||||
*/
|
||||
struct FLibvlcVideoViewpoint
|
||||
{
|
||||
float Yaw;
|
||||
float Pitch;
|
||||
float Roll;
|
||||
float FieldOfView;
|
||||
};
|
||||
@@ -0,0 +1,245 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "IVlcMediaModule.h"
|
||||
#include "VlcMediaPrivate.h"
|
||||
|
||||
#include "HAL/FileManager.h"
|
||||
#include "Misc/OutputDeviceFile.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "UObject/Class.h"
|
||||
#include "UObject/UObjectGlobals.h"
|
||||
#include "UObject/WeakObjectPtr.h"
|
||||
|
||||
#include "Vlc.h"
|
||||
#include "VlcMediaPlayer.h"
|
||||
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogVlcMedia);
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FVlcMediaModule"
|
||||
|
||||
|
||||
/**
|
||||
* Implements the VlcMedia module.
|
||||
*/
|
||||
class FVlcMediaModule
|
||||
: public IVlcMediaModule
|
||||
{
|
||||
public:
|
||||
|
||||
/** Default constructor. */
|
||||
FVlcMediaModule()
|
||||
: Initialized(false)
|
||||
{ }
|
||||
|
||||
public:
|
||||
|
||||
//~ IVlcMediaModule interface
|
||||
|
||||
virtual TSharedPtr<IMediaPlayer, ESPMode::ThreadSafe> CreatePlayer(IMediaEventSink& EventSink) override
|
||||
{
|
||||
if (!Initialized)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return MakeShared<FVlcMediaPlayer, ESPMode::ThreadSafe>(EventSink, VlcInstance);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//~ IModuleInterface interface
|
||||
|
||||
virtual void StartupModule() override
|
||||
{
|
||||
// initialize LibVLC
|
||||
if (!FVlc::Initialize())
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Error, TEXT("Failed to initialize LibVLC"));
|
||||
return;
|
||||
}
|
||||
|
||||
UE_LOG(LogVlcMedia, Log, TEXT("Initialized LibVLC %s (%s - %s)"),
|
||||
ANSI_TO_TCHAR(FVlc::GetVersion()),
|
||||
ANSI_TO_TCHAR(FVlc::GetChangeset()),
|
||||
ANSI_TO_TCHAR(FVlc::GetCompiler())
|
||||
);
|
||||
|
||||
#if UE_BUILD_DEBUG
|
||||
// backup old log file
|
||||
const FString LogFilePath = FPaths::Combine(FPaths::ProjectLogDir(), TEXT("vlc.log"));
|
||||
FOutputDeviceFile::CreateBackupCopy(*LogFilePath);
|
||||
IFileManager::Get().Delete(*LogFilePath);
|
||||
#endif
|
||||
|
||||
const auto Settings = GetDefault<UVlcMediaSettings>();
|
||||
|
||||
// create LibVLC instance
|
||||
const ANSICHAR* Args[] =
|
||||
{
|
||||
// caching
|
||||
TCHAR_TO_ANSI(*(FString::Printf(TEXT("--disc-caching=%i"), (int32)Settings->DiscCaching.GetTotalMilliseconds()))),
|
||||
TCHAR_TO_ANSI(*(FString::Printf(TEXT("--file-caching=%i"), (int32)Settings->FileCaching.GetTotalMilliseconds()))),
|
||||
TCHAR_TO_ANSI(*(FString::Printf(TEXT("--live-caching=%i"), (int32)Settings->LiveCaching.GetTotalMilliseconds()))),
|
||||
TCHAR_TO_ANSI(*(FString::Printf(TEXT("--network-caching=%i"), (int32)Settings->NetworkCaching.GetTotalMilliseconds()))),
|
||||
|
||||
// config
|
||||
"--ignore-config",
|
||||
|
||||
// logging
|
||||
#if UE_BUILD_DEBUG
|
||||
"--file-logging",
|
||||
TCHAR_TO_ANSI(*(FString(TEXT("--logfile=")) + LogFilePath)),
|
||||
#endif
|
||||
|
||||
#if (UE_BUILD_DEBUG || UE_BUILD_DEVELOPMENT)
|
||||
"--verbose=2",
|
||||
#else
|
||||
"--quiet",
|
||||
#endif
|
||||
|
||||
// output
|
||||
"--aout", "amem",
|
||||
"--intf", "dummy",
|
||||
"--text-renderer", "dummy",
|
||||
"--vout", "vmem",
|
||||
|
||||
// performance
|
||||
"--drop-late-frames",
|
||||
|
||||
// undesired features
|
||||
"--no-disable-screensaver",
|
||||
"--no-plugins-cache",
|
||||
"--no-snapshot-preview",
|
||||
"--no-video-title-show",
|
||||
|
||||
#if (UE_BUILD_SHIPPING || UE_BUILD_TEST)
|
||||
"--no-stats",
|
||||
#endif
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
"--no-xlib",
|
||||
#endif
|
||||
};
|
||||
|
||||
int Argc = sizeof(Args) / sizeof(*Args);
|
||||
VlcInstance = FVlc::New(Argc, Args);
|
||||
|
||||
if (VlcInstance == nullptr)
|
||||
{
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("Failed to create VLC instance (%s)"), ANSI_TO_TCHAR(FVlc::Errmsg()));
|
||||
FVlc::Shutdown();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// register logging callback
|
||||
FVlc::LogSet(VlcInstance, &FVlcMediaModule::HandleVlcLog, nullptr);
|
||||
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
virtual void ShutdownModule() override
|
||||
{
|
||||
if (!Initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Initialized = false;
|
||||
|
||||
// unregister logging callback
|
||||
FVlc::LogUnset(VlcInstance);
|
||||
|
||||
// release LibVLC instance
|
||||
FVlc::Release((FLibvlcInstance*)VlcInstance);
|
||||
VlcInstance = nullptr;
|
||||
|
||||
// shut down LibVLC
|
||||
FVlc::Shutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** Handles log messages from LibVLC. */
|
||||
static void HandleVlcLog(void* /*Data*/, ELibvlcLogLevel Level, FLibvlcLog* Context, const char* Format, va_list Args)
|
||||
{
|
||||
#if (UE_BUILD_DEBUG || UE_BUILD_DEVELOPMENT)
|
||||
const auto Settings = GetDefault<UVlcMediaSettings>();
|
||||
|
||||
// filter unwanted messages
|
||||
if ((uint8)Level < (uint8)Settings->LogLevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FString LogContext;
|
||||
|
||||
// get context information
|
||||
if (Context != nullptr)
|
||||
{
|
||||
const char* Module = nullptr;
|
||||
const char* File = nullptr;
|
||||
unsigned Line = 0;
|
||||
|
||||
FVlc::LogGetContext(Context, &Module, &File, &Line);
|
||||
LogContext = FString::Printf(TEXT("%s: "), (Module != nullptr) ? ANSI_TO_TCHAR(Module) : TEXT("unknown module"));
|
||||
|
||||
if (Settings->ShowLogContext)
|
||||
{
|
||||
LogContext += FString::Printf(TEXT("%s, line %s: "),
|
||||
(File != nullptr) ? ANSI_TO_TCHAR(File) : TEXT("unknown file"),
|
||||
(Line != 0) ? *FString::Printf(TEXT("%i"), Line) : TEXT("n/a")
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogContext = TEXT("generic: ");
|
||||
}
|
||||
|
||||
// forward message to log
|
||||
ANSICHAR Message[1024];
|
||||
|
||||
FCStringAnsi::GetVarArgs(Message, ARRAY_COUNT(Message), ARRAY_COUNT(Message) - 1, Format, Args);
|
||||
|
||||
switch (Level)
|
||||
{
|
||||
case ELibvlcLogLevel::Debug:
|
||||
UE_LOG(LogVlcMedia, VeryVerbose, TEXT("%s%s"), *LogContext, ANSI_TO_TCHAR(Message));
|
||||
break;
|
||||
|
||||
case ELibvlcLogLevel::Error:
|
||||
UE_LOG(LogVlcMedia, Error, TEXT("%s%s"), *LogContext, ANSI_TO_TCHAR(Message));
|
||||
break;
|
||||
|
||||
case ELibvlcLogLevel::Notice:
|
||||
UE_LOG(LogVlcMedia, Verbose, TEXT("%s%s"), *LogContext, ANSI_TO_TCHAR(Message));
|
||||
break;
|
||||
|
||||
case ELibvlcLogLevel::Warning:
|
||||
UE_LOG(LogVlcMedia, Warning, TEXT("%s%s"), *LogContext, ANSI_TO_TCHAR(Message));
|
||||
break;
|
||||
|
||||
default:
|
||||
UE_LOG(LogVlcMedia, Log, TEXT("%s%s"), *LogContext, ANSI_TO_TCHAR(Message));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** Whether the module has been initialized. */
|
||||
bool Initialized;
|
||||
|
||||
/** The LibVLC instance. */
|
||||
FLibvlcInstance* VlcInstance;
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_MODULE(FVlcMediaModule, VlcMedia);
|
||||
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Logging/LogMacros.h"
|
||||
|
||||
#include "../../VlcMediaFactory/Public/VlcMediaSettings.h"
|
||||
|
||||
|
||||
/** Declares a log category for this module. */
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogVlcMedia, Log, All);
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "Templates/SharedPointer.h"
|
||||
|
||||
class IMediaEventSink;
|
||||
class IMediaPlayer;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for the VlcMedia module.
|
||||
*/
|
||||
class IVlcMediaModule
|
||||
: public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create a VideoLAN based media player.
|
||||
*
|
||||
* @param EventSink The object that receives media events from the player.
|
||||
* @return A new media player, or nullptr if a player couldn't be created.
|
||||
*/
|
||||
virtual TSharedPtr<IMediaPlayer, ESPMode::ThreadSafe> CreatePlayer(IMediaEventSink& EventSink) = 0;
|
||||
|
||||
public:
|
||||
|
||||
/** Virtual destructor. */
|
||||
virtual ~IVlcMediaModule() { }
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace UnrealBuildTool.Rules
|
||||
{
|
||||
using System.IO;
|
||||
|
||||
public class VlcMedia : ModuleRules
|
||||
{
|
||||
public VlcMedia(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Media",
|
||||
});
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"MediaUtils",
|
||||
"Projects",
|
||||
"RenderCore",
|
||||
"VlcMediaFactory",
|
||||
});
|
||||
|
||||
PrivateIncludePathModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Media",
|
||||
});
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"VlcMedia/Private",
|
||||
"VlcMedia/Private/Player",
|
||||
"VlcMedia/Private/Shared",
|
||||
"VlcMedia/Private/Vlc",
|
||||
});
|
||||
|
||||
// add VLC libraries
|
||||
string BaseDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", ".."));
|
||||
string VlcDirectory = Path.Combine(BaseDirectory, "ThirdParty", "vlc", Target.Platform.ToString());
|
||||
|
||||
if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
VlcDirectory = Path.Combine(VlcDirectory, Target.Architecture, "lib");
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlc.so"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlc.so.5"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlc.so.5.6.0"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlccore.so"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlccore.so.9"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlccore.so.9.0.0"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Mac)
|
||||
{
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlc.dylib"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlc.5.dylib"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlccore.dylib"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlccore.9.dylib"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Win32)
|
||||
{
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlc.dll"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlccore.dll"));
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlc.dll"));
|
||||
RuntimeDependencies.Add(Path.Combine(VlcDirectory, "libvlccore.dll"));
|
||||
}
|
||||
|
||||
// add VLC plug-ins
|
||||
string PluginDirectory = Path.Combine(VlcDirectory, "plugins");
|
||||
|
||||
if (Target.Platform == UnrealTargetPlatform.Linux)
|
||||
{
|
||||
PluginDirectory = Path.Combine(VlcDirectory, "vlc", "plugins");
|
||||
}
|
||||
|
||||
if (Directory.Exists(PluginDirectory))
|
||||
{
|
||||
foreach (string Plugin in Directory.EnumerateFiles(PluginDirectory, "*.*", SearchOption.AllDirectories))
|
||||
{
|
||||
RuntimeDependencies.Add(Path.Combine(PluginDirectory, Plugin));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VlcFileMediaSourceFactory.h"
|
||||
|
||||
#include "FileMediaSource.h"
|
||||
#include "Misc/Paths.h"
|
||||
|
||||
|
||||
/* UVlcFileMediaSourceFactory structors
|
||||
*****************************************************************************/
|
||||
|
||||
UVlcFileMediaSourceFactory::UVlcFileMediaSourceFactory(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
Formats.Add(TEXT("3g2;3GPP2 Multimedia"));
|
||||
Formats.Add(TEXT("3ga;3GPP Audio"));
|
||||
Formats.Add(TEXT("3gp;3GP Video Stream"));
|
||||
Formats.Add(TEXT("3gp2;3GPP Multimedia"));
|
||||
Formats.Add(TEXT("3gpp;3GPP Media"));
|
||||
Formats.Add(TEXT("669;UNIS Composer 669 Module"));
|
||||
Formats.Add(TEXT("a52;Dolby Digital AC-3 Audio"));
|
||||
Formats.Add(TEXT("aac;MPEG-2 Advanced Audio Coding"));
|
||||
Formats.Add(TEXT("ac3;Audio Codec 3"));
|
||||
Formats.Add(TEXT("adt;Audio Data Transport Stream"));
|
||||
Formats.Add(TEXT("adts;Audio Data Transport Stream"));
|
||||
Formats.Add(TEXT("aif;Audio Interchange File Format"));
|
||||
Formats.Add(TEXT("aifc;Compressed Audio Interchange File"));
|
||||
Formats.Add(TEXT("aiff;Audio Interchange File Format"));
|
||||
Formats.Add(TEXT("amb;Ambisonics B-Format"));
|
||||
Formats.Add(TEXT("amr;Adaptive Multi-Rate Codec"));
|
||||
Formats.Add(TEXT("amv;Anime Music Video"));
|
||||
Formats.Add(TEXT("aob;DVD-Audio Audio Object"));
|
||||
Formats.Add(TEXT("ape;AVS Plugin Effects File"));
|
||||
Formats.Add(TEXT("asf;ASF Media"));
|
||||
Formats.Add(TEXT("au;Sun Microsystems Audio"));
|
||||
Formats.Add(TEXT("avi;Audio Video Interleave File"));
|
||||
Formats.Add(TEXT("awb;AMR-WB Audio"));
|
||||
Formats.Add(TEXT("bik;Bink Video"));
|
||||
Formats.Add(TEXT("bin;Binary File"));
|
||||
Formats.Add(TEXT("caf;Core Audio"));
|
||||
Formats.Add(TEXT("crf;CRF Video"));
|
||||
Formats.Add(TEXT("divx;DivX-Encoded Movie"));
|
||||
Formats.Add(TEXT("drc;DRM Rights Object"));
|
||||
Formats.Add(TEXT("dts;Digital Theater System"));
|
||||
Formats.Add(TEXT("dv;Digital Video"));
|
||||
Formats.Add(TEXT("evo;SeeVogh Player Video Recording"));
|
||||
Formats.Add(TEXT("f4v;Flash MP4 Video"));
|
||||
Formats.Add(TEXT("flac;Free Lossless Audio Codec"));
|
||||
Formats.Add(TEXT("flv;Adobe Flash Video"));
|
||||
Formats.Add(TEXT("gvi;Google Video"));
|
||||
Formats.Add(TEXT("gxf;General eXchange Format"));
|
||||
Formats.Add(TEXT("iso;Disc Image"));
|
||||
Formats.Add(TEXT("it;Impulse Tracker Module"));
|
||||
Formats.Add(TEXT("kar;Karaoke MIDI"));
|
||||
Formats.Add(TEXT("m1v;MPEG-1 Video"));
|
||||
Formats.Add(TEXT("m2t;HDV Video"));
|
||||
Formats.Add(TEXT("m2ts;Blu-ray BDAV Video"));
|
||||
Formats.Add(TEXT("m2v;MPEG-2 Video"));
|
||||
Formats.Add(TEXT("m4a;MPEG-4 Audio"));
|
||||
Formats.Add(TEXT("m4b;MPEG-4 Audio Book"));
|
||||
Formats.Add(TEXT("m4p;iTunes Music Store Audio"));
|
||||
Formats.Add(TEXT("m5p;MachFive Preset File"));
|
||||
Formats.Add(TEXT("m4v;iTunes Video"));
|
||||
Formats.Add(TEXT("mid;MIDI File"));
|
||||
Formats.Add(TEXT("mka;Matroska Audio"));
|
||||
Formats.Add(TEXT("mkv;Matroska Video"));
|
||||
Formats.Add(TEXT("mlp;Meridian Lossless Packing Audio"));
|
||||
Formats.Add(TEXT("mod;Amiga Music Module"));
|
||||
Formats.Add(TEXT("mov;Apple QuickTime Movie"));
|
||||
Formats.Add(TEXT("mp1;MPEG-1 Layer 1 Audio"));
|
||||
Formats.Add(TEXT("mp2;MPEG-1 Audio"));
|
||||
Formats.Add(TEXT("mp2v;MPEG-2 Video"));
|
||||
Formats.Add(TEXT("mp3;MPEG-2 Audio"));
|
||||
Formats.Add(TEXT("mp4;MPEG-4 Movie"));
|
||||
Formats.Add(TEXT("mp4v;MPEG-4 Video"));
|
||||
Formats.Add(TEXT("mpa;MPEG-2 Audio"));
|
||||
Formats.Add(TEXT("mpc;Musepack Compressed Audio"));
|
||||
Formats.Add(TEXT("mpe;MPEG Movie"));
|
||||
Formats.Add(TEXT("mpeg;MPEG Movie"));
|
||||
Formats.Add(TEXT("mpeg1;MPEG-1 Video"));
|
||||
Formats.Add(TEXT("mpeg2;MPEG-2 Video"));
|
||||
Formats.Add(TEXT("mpeg4;MPEG-4 Video"));
|
||||
Formats.Add(TEXT("mpg;MPEG-2 Movie"));
|
||||
Formats.Add(TEXT("mpga;MPEG-1 Layer 3 Audio"));
|
||||
Formats.Add(TEXT("mpv2;MPEG-2 Video Stream"));
|
||||
Formats.Add(TEXT("mts;AVCHD Video"));
|
||||
Formats.Add(TEXT("mtv;MTV Video Format"));
|
||||
Formats.Add(TEXT("mus;Finale Notation File"));
|
||||
Formats.Add(TEXT("mxf;Material Exchange Format"));
|
||||
Formats.Add(TEXT("mxg;Miinoto Exchangeable Group File"));
|
||||
Formats.Add(TEXT("nsc;Windows Media Station"));
|
||||
Formats.Add(TEXT("nsv;Nullsoft Streaming Video"));
|
||||
Formats.Add(TEXT("nut;NUT Multimedia Container"));
|
||||
Formats.Add(TEXT("nuv;NuppelVideo File"));
|
||||
Formats.Add(TEXT("oga;Ogg Vorbis Audio"));
|
||||
Formats.Add(TEXT("ogg;Ogg Multimedia"));
|
||||
Formats.Add(TEXT("ogm;Ogg Multimedia"));
|
||||
Formats.Add(TEXT("ogv;Ogg Video"));
|
||||
Formats.Add(TEXT("ogx;Ogg Vorbis Multiplexed Media"));
|
||||
Formats.Add(TEXT("oma;Sony OpenMG Music"));
|
||||
Formats.Add(TEXT("opus;Opus Audio"));
|
||||
Formats.Add(TEXT("qcp;PureVoice Audio"));
|
||||
Formats.Add(TEXT("ps;Program Stream Container"));
|
||||
Formats.Add(TEXT("ra;Real Audio"));
|
||||
Formats.Add(TEXT("ram;Real Audio Metadata"));
|
||||
Formats.Add(TEXT("rec;Topfield PVR Recording"));
|
||||
Formats.Add(TEXT("rm;Real Media"));
|
||||
Formats.Add(TEXT("rmi;RMID MIDI"));
|
||||
Formats.Add(TEXT("rmvb;Real Media VBR"));
|
||||
Formats.Add(TEXT("rpl;Toribash Replay File"));
|
||||
Formats.Add(TEXT("rv;Real Video"));
|
||||
Formats.Add(TEXT("s3m;ScreamTracker 3 Module"));
|
||||
Formats.Add(TEXT("sdp;Session Description Protocol"));
|
||||
Formats.Add(TEXT("sid;Commodore C64 SID File"));
|
||||
Formats.Add(TEXT("spx;Speex Audio"));
|
||||
Formats.Add(TEXT("ts;MPEG-2 Transport Stream"));
|
||||
Formats.Add(TEXT("tak;Tom's Lossless Audio Kompressor"));
|
||||
Formats.Add(TEXT("thd;Dolby TrueHD Audio Stream"));
|
||||
Formats.Add(TEXT("thp;Wii/GameCube Video"));
|
||||
Formats.Add(TEXT("tod;JVC Everio Video Capture"));
|
||||
Formats.Add(TEXT("tta;True Audio Codec"));
|
||||
Formats.Add(TEXT("tts;Telerik Trainer Session"));
|
||||
Formats.Add(TEXT("txd;TXD File"));
|
||||
Formats.Add(TEXT("ty;Tivo Container"));
|
||||
Formats.Add(TEXT("vid;Generic Video"));
|
||||
Formats.Add(TEXT("vob;DVD Video Object"));
|
||||
Formats.Add(TEXT("voc;Creative Labs Audio"));
|
||||
Formats.Add(TEXT("vqf;TwinVQ Audio"));
|
||||
Formats.Add(TEXT("vro;DVD Video Recording Format"));
|
||||
Formats.Add(TEXT("w64;Sony Wave64 Audio"));
|
||||
Formats.Add(TEXT("wav;Wave Audio"));
|
||||
Formats.Add(TEXT("webm;WebM Video"));
|
||||
Formats.Add(TEXT("wm;Windows Media"));
|
||||
Formats.Add(TEXT("wma;Windows Media Audio"));
|
||||
Formats.Add(TEXT("wmv;Windows Media Video"));
|
||||
Formats.Add(TEXT("wtv;Windows Recorded TV Show"));
|
||||
Formats.Add(TEXT("wv;WavPack Audio"));
|
||||
Formats.Add(TEXT("xa;PlayStation Audio"));
|
||||
Formats.Add(TEXT("xesc;Expression Encoder Screen Capture"));
|
||||
Formats.Add(TEXT("xm;Fasttracker 2 Extended Module"));
|
||||
|
||||
SupportedClass = UFileMediaSource::StaticClass();
|
||||
bEditorImport = true;
|
||||
}
|
||||
|
||||
|
||||
/* UFactory overrides
|
||||
*****************************************************************************/
|
||||
|
||||
bool UVlcFileMediaSourceFactory::FactoryCanImport(const FString& Filename)
|
||||
{
|
||||
// @hack: disable file extensions that are used in other factories
|
||||
// @todo gmp: add support for multiple factories per file extension
|
||||
const FString FileExtension = FPaths::GetExtension(Filename);
|
||||
|
||||
return (FileExtension.ToUpper() != FString("WAV"));
|
||||
}
|
||||
|
||||
|
||||
UObject* UVlcFileMediaSourceFactory::FactoryCreateFile(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms, FFeedbackContext* Warn, bool& bOutOperationCanceled)
|
||||
{
|
||||
UFileMediaSource* MediaSource = NewObject<UFileMediaSource>(InParent, InClass, InName, Flags);
|
||||
MediaSource->SetFilePath(CurrentFilename);
|
||||
|
||||
return MediaSource;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Factories/Factory.h"
|
||||
#include "VlcFileMediaSourceFactory.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* Implements a factory for UFileMediaSource objects.
|
||||
*/
|
||||
UCLASS(hidecategories=Object)
|
||||
class UVlcFileMediaSourceFactory
|
||||
: public UFactory
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
|
||||
//~ UFactory Interface
|
||||
|
||||
virtual bool FactoryCanImport(const FString& Filename) override;
|
||||
virtual UObject* FactoryCreateFile(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms, FFeedbackContext* Warn, bool& bOutOperationCanceled) override;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
|
||||
/**
|
||||
* Implements the VlcMediaEditor module.
|
||||
*/
|
||||
class FVlcMediaEditorModule
|
||||
: public IModuleInterface
|
||||
{
|
||||
public:
|
||||
|
||||
//~ IModuleInterface interface
|
||||
|
||||
virtual void StartupModule() override { }
|
||||
virtual void ShutdownModule() override { }
|
||||
};
|
||||
|
||||
|
||||
IMPLEMENT_MODULE(FVlcMediaEditorModule, VlcMediaEditor);
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Runtime/Core/Public/Core.h"
|
||||
#include "Runtime/CoreUObject/Public/CoreUObject.h"
|
||||
#include "Runtime/MediaAssets/Public/FileMediaSource.h"
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
namespace UnrealBuildTool.Rules
|
||||
{
|
||||
public class VlcMediaEditor : ModuleRules
|
||||
{
|
||||
public VlcMediaEditor(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"MediaAssets",
|
||||
"UnrealEd",
|
||||
});
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"VlcMediaEditor/Private",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "Containers/Array.h"
|
||||
#include "Containers/UnrealString.h"
|
||||
#include "IMediaPlayerFactory.h"
|
||||
#include "IMediaModule.h"
|
||||
#include "IMediaOptions.h"
|
||||
#include "Internationalization/Internationalization.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Modules/ModuleInterface.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "UObject/Class.h"
|
||||
#include "UObject/NameTypes.h"
|
||||
#include "UObject/UObjectGlobals.h"
|
||||
#include "UObject/WeakObjectPtr.h"
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "ISettingsModule.h"
|
||||
#include "ISettingsSection.h"
|
||||
#include "VlcMediaSettings.h"
|
||||
#endif
|
||||
|
||||
#include "../../VlcMedia/Public/IVlcMediaModule.h"
|
||||
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FVlcMediaFactoryModule"
|
||||
|
||||
|
||||
/**
|
||||
* Implements the VlcMediaFactory module.
|
||||
*/
|
||||
class FVlcMediaFactoryModule
|
||||
: public IMediaPlayerFactory
|
||||
, public IModuleInterface
|
||||
{
|
||||
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("PrecacheFileWarning", "Precaching is supported for local files only"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual TSharedPtr<IMediaPlayer, ESPMode::ThreadSafe> CreatePlayer(IMediaEventSink& EventSink) override
|
||||
{
|
||||
auto VlcMediaModule = FModuleManager::LoadModulePtr<IVlcMediaModule>("VlcMedia");
|
||||
return (VlcMediaModule != nullptr) ? VlcMediaModule->CreatePlayer(EventSink) : nullptr;
|
||||
}
|
||||
|
||||
virtual FText GetDisplayName() const override
|
||||
{
|
||||
return LOCTEXT("MediaPlayerDisplayName", "VideoLAN Player");
|
||||
}
|
||||
|
||||
virtual FName GetPlayerName() const override
|
||||
{
|
||||
static FName PlayerName(TEXT("VlcMedia"));
|
||||
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::Video360) ||
|
||||
(Feature == EMediaFeature::VideoSamples) ||
|
||||
(Feature == EMediaFeature::VideoTracks));
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//~ IModuleInterface interface
|
||||
|
||||
virtual void StartupModule() override
|
||||
{
|
||||
// supported file extensions
|
||||
SupportedFileExtensions.Add(TEXT("3g2"));
|
||||
SupportedFileExtensions.Add(TEXT("3ga"));
|
||||
SupportedFileExtensions.Add(TEXT("3gp"));
|
||||
SupportedFileExtensions.Add(TEXT("3gp2"));
|
||||
SupportedFileExtensions.Add(TEXT("3gpp"));
|
||||
SupportedFileExtensions.Add(TEXT("669"));
|
||||
SupportedFileExtensions.Add(TEXT("a52"));
|
||||
SupportedFileExtensions.Add(TEXT("aac"));
|
||||
SupportedFileExtensions.Add(TEXT("ac3"));
|
||||
SupportedFileExtensions.Add(TEXT("adt"));
|
||||
SupportedFileExtensions.Add(TEXT("adts"));
|
||||
SupportedFileExtensions.Add(TEXT("aif"));
|
||||
SupportedFileExtensions.Add(TEXT("aifc"));
|
||||
SupportedFileExtensions.Add(TEXT("aiff"));
|
||||
SupportedFileExtensions.Add(TEXT("amb"));
|
||||
SupportedFileExtensions.Add(TEXT("amr"));
|
||||
SupportedFileExtensions.Add(TEXT("amv"));
|
||||
SupportedFileExtensions.Add(TEXT("aob"));
|
||||
SupportedFileExtensions.Add(TEXT("ape"));
|
||||
SupportedFileExtensions.Add(TEXT("asf"));
|
||||
SupportedFileExtensions.Add(TEXT("au"));
|
||||
SupportedFileExtensions.Add(TEXT("avi"));
|
||||
SupportedFileExtensions.Add(TEXT("awb"));
|
||||
SupportedFileExtensions.Add(TEXT("bik"));
|
||||
SupportedFileExtensions.Add(TEXT("bin"));
|
||||
SupportedFileExtensions.Add(TEXT("caf"));
|
||||
SupportedFileExtensions.Add(TEXT("crf"));
|
||||
SupportedFileExtensions.Add(TEXT("divx"));
|
||||
SupportedFileExtensions.Add(TEXT("drc"));
|
||||
SupportedFileExtensions.Add(TEXT("dts"));
|
||||
SupportedFileExtensions.Add(TEXT("dv"));
|
||||
SupportedFileExtensions.Add(TEXT("evo"));
|
||||
SupportedFileExtensions.Add(TEXT("f4v"));
|
||||
SupportedFileExtensions.Add(TEXT("flac"));
|
||||
SupportedFileExtensions.Add(TEXT("flv"));
|
||||
SupportedFileExtensions.Add(TEXT("gvi"));
|
||||
SupportedFileExtensions.Add(TEXT("gxf"));
|
||||
SupportedFileExtensions.Add(TEXT("iso"));
|
||||
SupportedFileExtensions.Add(TEXT("it"));
|
||||
SupportedFileExtensions.Add(TEXT("kar"));
|
||||
SupportedFileExtensions.Add(TEXT("m1v"));
|
||||
SupportedFileExtensions.Add(TEXT("m2t"));
|
||||
SupportedFileExtensions.Add(TEXT("m2ts"));
|
||||
SupportedFileExtensions.Add(TEXT("m2v"));
|
||||
SupportedFileExtensions.Add(TEXT("m4a"));
|
||||
SupportedFileExtensions.Add(TEXT("m4b"));
|
||||
SupportedFileExtensions.Add(TEXT("m4p"));
|
||||
SupportedFileExtensions.Add(TEXT("m4v"));
|
||||
SupportedFileExtensions.Add(TEXT("m5p"));
|
||||
SupportedFileExtensions.Add(TEXT("mid"));
|
||||
SupportedFileExtensions.Add(TEXT("mka"));
|
||||
SupportedFileExtensions.Add(TEXT("mkv"));
|
||||
SupportedFileExtensions.Add(TEXT("mlp"));
|
||||
SupportedFileExtensions.Add(TEXT("mod"));
|
||||
SupportedFileExtensions.Add(TEXT("mov"));
|
||||
SupportedFileExtensions.Add(TEXT("mp1"));
|
||||
SupportedFileExtensions.Add(TEXT("mp2"));
|
||||
SupportedFileExtensions.Add(TEXT("mp2v"));
|
||||
SupportedFileExtensions.Add(TEXT("mp3"));
|
||||
SupportedFileExtensions.Add(TEXT("mp4"));
|
||||
SupportedFileExtensions.Add(TEXT("mp4v"));
|
||||
SupportedFileExtensions.Add(TEXT("mpa"));
|
||||
SupportedFileExtensions.Add(TEXT("mpc"));
|
||||
SupportedFileExtensions.Add(TEXT("mpe"));
|
||||
SupportedFileExtensions.Add(TEXT("mpeg"));
|
||||
SupportedFileExtensions.Add(TEXT("mpeg1"));
|
||||
SupportedFileExtensions.Add(TEXT("mpeg2"));
|
||||
SupportedFileExtensions.Add(TEXT("mpeg4"));
|
||||
SupportedFileExtensions.Add(TEXT("mpg"));
|
||||
SupportedFileExtensions.Add(TEXT("mpga"));
|
||||
SupportedFileExtensions.Add(TEXT("mpv2"));
|
||||
SupportedFileExtensions.Add(TEXT("mts"));
|
||||
SupportedFileExtensions.Add(TEXT("mtv"));
|
||||
SupportedFileExtensions.Add(TEXT("mus"));
|
||||
SupportedFileExtensions.Add(TEXT("mxf"));
|
||||
SupportedFileExtensions.Add(TEXT("mxg"));
|
||||
SupportedFileExtensions.Add(TEXT("nsc"));
|
||||
SupportedFileExtensions.Add(TEXT("nsv"));
|
||||
SupportedFileExtensions.Add(TEXT("nut"));
|
||||
SupportedFileExtensions.Add(TEXT("nuv"));
|
||||
SupportedFileExtensions.Add(TEXT("oga"));
|
||||
SupportedFileExtensions.Add(TEXT("ogg"));
|
||||
SupportedFileExtensions.Add(TEXT("ogm"));
|
||||
SupportedFileExtensions.Add(TEXT("ogv"));
|
||||
SupportedFileExtensions.Add(TEXT("ogx"));
|
||||
SupportedFileExtensions.Add(TEXT("oma"));
|
||||
SupportedFileExtensions.Add(TEXT("opus"));
|
||||
SupportedFileExtensions.Add(TEXT("qcp"));
|
||||
SupportedFileExtensions.Add(TEXT("ps"));
|
||||
SupportedFileExtensions.Add(TEXT("ra"));
|
||||
SupportedFileExtensions.Add(TEXT("ram"));
|
||||
SupportedFileExtensions.Add(TEXT("rec"));
|
||||
SupportedFileExtensions.Add(TEXT("rm"));
|
||||
SupportedFileExtensions.Add(TEXT("rmi"));
|
||||
SupportedFileExtensions.Add(TEXT("rmvb"));
|
||||
SupportedFileExtensions.Add(TEXT("rpl"));
|
||||
SupportedFileExtensions.Add(TEXT("rv"));
|
||||
SupportedFileExtensions.Add(TEXT("s3m"));
|
||||
SupportedFileExtensions.Add(TEXT("sdp"));
|
||||
SupportedFileExtensions.Add(TEXT("sid"));
|
||||
SupportedFileExtensions.Add(TEXT("spx"));
|
||||
SupportedFileExtensions.Add(TEXT("ts"));
|
||||
SupportedFileExtensions.Add(TEXT("tak"));
|
||||
SupportedFileExtensions.Add(TEXT("thd"));
|
||||
SupportedFileExtensions.Add(TEXT("thp"));
|
||||
SupportedFileExtensions.Add(TEXT("tod"));
|
||||
SupportedFileExtensions.Add(TEXT("tta"));
|
||||
SupportedFileExtensions.Add(TEXT("rp"));
|
||||
SupportedFileExtensions.Add(TEXT("rs"));
|
||||
SupportedFileExtensions.Add(TEXT("tta"));
|
||||
SupportedFileExtensions.Add(TEXT("tts"));
|
||||
SupportedFileExtensions.Add(TEXT("txd"));
|
||||
SupportedFileExtensions.Add(TEXT("ty"));
|
||||
SupportedFileExtensions.Add(TEXT("vid"));
|
||||
SupportedFileExtensions.Add(TEXT("vob"));
|
||||
SupportedFileExtensions.Add(TEXT("voc"));
|
||||
SupportedFileExtensions.Add(TEXT("vqf"));
|
||||
SupportedFileExtensions.Add(TEXT("vro"));
|
||||
SupportedFileExtensions.Add(TEXT("w64"));
|
||||
SupportedFileExtensions.Add(TEXT("wav"));
|
||||
SupportedFileExtensions.Add(TEXT("webm"));
|
||||
SupportedFileExtensions.Add(TEXT("wm"));
|
||||
SupportedFileExtensions.Add(TEXT("wma"));
|
||||
SupportedFileExtensions.Add(TEXT("wmv"));
|
||||
SupportedFileExtensions.Add(TEXT("wtv"));
|
||||
SupportedFileExtensions.Add(TEXT("wv"));
|
||||
SupportedFileExtensions.Add(TEXT("xa"));
|
||||
SupportedFileExtensions.Add(TEXT("xesc"));
|
||||
SupportedFileExtensions.Add(TEXT("xm"));
|
||||
|
||||
// supported platforms
|
||||
SupportedPlatforms.Add(TEXT("Linux"));
|
||||
SupportedPlatforms.Add(TEXT("Mac"));
|
||||
SupportedPlatforms.Add(TEXT("Windows"));
|
||||
SupportedPlatforms.Add(TEXT("WinRT"));
|
||||
|
||||
// supported schemes
|
||||
SupportedUriSchemes.Add(TEXT("cdda"));
|
||||
SupportedUriSchemes.Add(TEXT("dccp"));
|
||||
SupportedUriSchemes.Add(TEXT("dshow"));
|
||||
SupportedUriSchemes.Add(TEXT("dvd"));
|
||||
SupportedUriSchemes.Add(TEXT("file"));
|
||||
SupportedUriSchemes.Add(TEXT("dvd"));
|
||||
SupportedUriSchemes.Add(TEXT("ftp"));
|
||||
SupportedUriSchemes.Add(TEXT("http"));
|
||||
SupportedUriSchemes.Add(TEXT("https"));
|
||||
SupportedUriSchemes.Add(TEXT("icyx"));
|
||||
SupportedUriSchemes.Add(TEXT("itpc"));
|
||||
SupportedUriSchemes.Add(TEXT("mms"));
|
||||
SupportedUriSchemes.Add(TEXT("mmsh"));
|
||||
SupportedUriSchemes.Add(TEXT("mmst"));
|
||||
SupportedUriSchemes.Add(TEXT("mmsu"));
|
||||
SupportedUriSchemes.Add(TEXT("mtp"));
|
||||
SupportedUriSchemes.Add(TEXT("pnm"));
|
||||
SupportedUriSchemes.Add(TEXT("realrtsp"));
|
||||
SupportedUriSchemes.Add(TEXT("rtmp"));
|
||||
SupportedUriSchemes.Add(TEXT("rtp"));
|
||||
SupportedUriSchemes.Add(TEXT("rtsp"));
|
||||
SupportedUriSchemes.Add(TEXT("sap"));
|
||||
SupportedUriSchemes.Add(TEXT("smb"));
|
||||
SupportedUriSchemes.Add(TEXT("screen"));
|
||||
SupportedUriSchemes.Add(TEXT("unsv"));
|
||||
SupportedUriSchemes.Add(TEXT("v4l2"));
|
||||
SupportedUriSchemes.Add(TEXT("vcd"));
|
||||
|
||||
#if WITH_EDITOR
|
||||
// register settings
|
||||
ISettingsModule* SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings");
|
||||
|
||||
if (SettingsModule != nullptr)
|
||||
{
|
||||
ISettingsSectionPtr SettingsSection = SettingsModule->RegisterSettings("Project", "Plugins", "VlcMedia",
|
||||
LOCTEXT("VlcMediaSettingsName", "VLC Media"),
|
||||
LOCTEXT("VlcMediaSettingsDescription", "Configure the VLC Media plug-in."),
|
||||
GetMutableDefault<UVlcMediaSettings>()
|
||||
);
|
||||
}
|
||||
#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", "VlcMedia");
|
||||
}
|
||||
#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(FVlcMediaFactoryModule, VlcMediaFactory);
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if WITH_EDITOR
|
||||
#include "Developer/Settings/Public/ISettingsModule.h"
|
||||
#include "Developer/Settings/Public/ISettingsSection.h"
|
||||
#endif
|
||||
|
||||
#include "Runtime/Core/Public/Core.h"
|
||||
#include "Runtime/Core/Public/Modules/ModuleManager.h"
|
||||
#include "Runtime/CoreUObject/Public/CoreUObject.h"
|
||||
#include "Runtime/Media/Public/IMediaModule.h"
|
||||
#include "Runtime/Media/Public/IMediaOptions.h"
|
||||
|
||||
#include "../../VlcMedia/Public/IVlcMediaModule.h"
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VlcMediaSettings.h"
|
||||
|
||||
|
||||
UVlcMediaSettings::UVlcMediaSettings()
|
||||
: DiscCaching(FTimespan::FromMilliseconds(300.0))
|
||||
, FileCaching(FTimespan::FromMilliseconds(300.0))
|
||||
, LiveCaching(FTimespan::FromMilliseconds(300.0))
|
||||
, NetworkCaching(FTimespan::FromMilliseconds(1000.0))
|
||||
, LogLevel(EVlcMediaLogLevel::Warning)
|
||||
, ShowLogContext(false)
|
||||
{ }
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
|
||||
#include "VlcMediaSettings.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* Available levels for LibVLC log messages.
|
||||
*/
|
||||
UENUM()
|
||||
enum class EVlcMediaLogLevel : uint8
|
||||
{
|
||||
/** Error messages. */
|
||||
Error = 0,
|
||||
|
||||
/** Warnings and potential errors. */
|
||||
Warning = 1,
|
||||
|
||||
/** Debug messages. */
|
||||
Debug = 2,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Settings for the VlcMedia plug-in.
|
||||
*/
|
||||
UCLASS(config=Engine)
|
||||
class VLCMEDIAFACTORY_API UVlcMediaSettings
|
||||
: public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor. */
|
||||
UVlcMediaSettings();
|
||||
|
||||
public:
|
||||
|
||||
/** Caching duration for optical media (default = 300 ms). */
|
||||
UPROPERTY(config, EditAnywhere, Category=Caching)
|
||||
FTimespan DiscCaching;
|
||||
|
||||
/** Caching duration for local files (default = 300 ms). */
|
||||
UPROPERTY(config, EditAnywhere, Category=Caching)
|
||||
FTimespan FileCaching;
|
||||
|
||||
/** Caching duration for cameras and microphones (default = 300 ms). */
|
||||
UPROPERTY(config, EditAnywhere, Category=Caching)
|
||||
FTimespan LiveCaching;
|
||||
|
||||
/** Caching duration for network resources (default = 1000 ms). */
|
||||
UPROPERTY(config, EditAnywhere, Category=Caching)
|
||||
FTimespan NetworkCaching;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Log level for LibVLC log messages to be forwarded to UE4 log file (default = Warning).
|
||||
*
|
||||
* This setting is used only in Debug and Development builds.
|
||||
* No log entries will written in Shipping and Test builds.
|
||||
*/
|
||||
UPROPERTY(config, EditAnywhere, Category=Debugging)
|
||||
EVlcMediaLogLevel LogLevel;
|
||||
|
||||
/** Whether to include file name & line number in LibVLC log messages. */
|
||||
UPROPERTY(config, EditAnywhere, Category=Debugging)
|
||||
bool ShowLogContext;
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
namespace UnrealBuildTool.Rules
|
||||
{
|
||||
public class VlcMediaFactory : ModuleRules
|
||||
{
|
||||
public VlcMediaFactory(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
DynamicallyLoadedModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Media",
|
||||
});
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[] {
|
||||
"MediaAssets",
|
||||
});
|
||||
|
||||
PrivateIncludePathModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Media",
|
||||
"VlcMedia",
|
||||
});
|
||||
|
||||
PrivateIncludePaths.AddRange(
|
||||
new string[] {
|
||||
"VlcMediaFactory/Private",
|
||||
});
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
});
|
||||
|
||||
if (Target.Type == TargetRules.TargetType.Editor)
|
||||
{
|
||||
DynamicallyLoadedModuleNames.Add("Settings");
|
||||
PrivateIncludePathModuleNames.Add("Settings");
|
||||
}
|
||||
|
||||
if ((Target.Platform == UnrealTargetPlatform.Mac) ||
|
||||
(Target.Platform == UnrealTargetPlatform.Linux) ||
|
||||
(Target.Platform == UnrealTargetPlatform.Win32) ||
|
||||
(Target.Platform == UnrealTargetPlatform.Win64))
|
||||
{
|
||||
DynamicallyLoadedModuleNames.Add("VlcMedia");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+852
@@ -0,0 +1,852 @@
|
||||
VideoLAN and the VLC team would like to acknowledge the following contributors:
|
||||
|
||||
Programming
|
||||
-----------
|
||||
Rémi Denis-Courmont
|
||||
Jean-Baptiste Kempf
|
||||
Laurent Aimar
|
||||
Gildas Bazin
|
||||
Felix Paul Kühne
|
||||
Rafaël Carré
|
||||
Pierre d'Herbemont
|
||||
Rémi Duraffort
|
||||
Derk-Jan Hartman
|
||||
Antoine Cellerier
|
||||
Samuel Hocevar
|
||||
Jean-Paul Saman
|
||||
Christophe Mutricy
|
||||
Clément Stenac
|
||||
Christophe Massiot
|
||||
Ilkka Ollakka
|
||||
Pierre Ynard
|
||||
François Cartegnie
|
||||
Damien Fouilleul
|
||||
Sigmund Augdal Helberg
|
||||
Erwan Tulou
|
||||
David Fuhrmann
|
||||
Olivier Teulière
|
||||
Cyril Deguet
|
||||
Eric Petit
|
||||
Filippo Carone
|
||||
Rocky Bernstein
|
||||
Hugo Beauzée-Luyssen
|
||||
Olivier Aubert
|
||||
Pavlov Konstantin
|
||||
Jakob Leben
|
||||
Benjamin Pracht
|
||||
Jean-Philippe André
|
||||
Steve Lhomme
|
||||
Stéphane Borel
|
||||
JP Dinger
|
||||
Geoffroy Couprie
|
||||
Martin Storsjö
|
||||
Marian Ďurkovič
|
||||
Ludovic Fauvet
|
||||
Yoann Peronneau
|
||||
Sébastien Escudier
|
||||
Jon Lech Johansen
|
||||
KO Myung-Hun
|
||||
Edward Wang
|
||||
Dennis van Amerongen
|
||||
Faustino Osuna
|
||||
Mirsal Ennaime
|
||||
Denis Charmet
|
||||
Jérôme Decoodt
|
||||
Loïc Minier
|
||||
David Flynn
|
||||
Frédéric Yhuel
|
||||
Kaarlo Raiha
|
||||
Mark Moriarty
|
||||
Christopher Mueller
|
||||
Fabio Ritrovato
|
||||
Tony Castley
|
||||
Srikanth Raju
|
||||
Michel Kaempf
|
||||
Jean-Marc Dressler
|
||||
Johan Bilien
|
||||
Vincent Seguin
|
||||
Simon Latapie
|
||||
Bernie Purcell
|
||||
Henri Fallon
|
||||
Sebastien Zwickert
|
||||
Christoph Miebach
|
||||
Adrien Maglo
|
||||
Emmanuel Puig
|
||||
Renaud Dartus
|
||||
Alexis de Lattre
|
||||
Vincent Penquerc'h
|
||||
Arnaud de Bossoreille de Ribou
|
||||
Mohammed Adnène Trojette
|
||||
Boris Dorès
|
||||
Jai Menon
|
||||
Anil Daoud
|
||||
Daniel Mierswa
|
||||
Naohiro Koriyama
|
||||
Rob Jonson
|
||||
Pierre Baillet
|
||||
Dominique Leuenberger
|
||||
Andre Pang
|
||||
Zoran Turalija
|
||||
Akash Mehrotra
|
||||
André Weber
|
||||
Anthony Loiseau
|
||||
Lukas Durfina
|
||||
Xavier Marchesini
|
||||
Cyril Mathé
|
||||
Devin Heitmueller
|
||||
Juho Vähä-Herttua
|
||||
Ken Self
|
||||
Alexis Ballier
|
||||
Juha Jeronen
|
||||
Nicolas Chauvet
|
||||
Richard Hosking
|
||||
Éric Lassauge
|
||||
Marc Ariberti
|
||||
Sébastien Toque
|
||||
Tobias Güntner
|
||||
Benoit Steiner
|
||||
Michel Lespinasse
|
||||
Carlo Calabrò
|
||||
Cheng Sun
|
||||
Michał Trzebiatowski
|
||||
Brad Smith
|
||||
Brendon Justin
|
||||
Alexey Sokolov
|
||||
Basos G
|
||||
Philippe Morin
|
||||
Steinar H. Gunderson
|
||||
Vicente Jimenez Aguilar
|
||||
Yuval Tze
|
||||
Yves Duret
|
||||
Benjamin Drung
|
||||
Michael Hanselmann
|
||||
Alex Merry
|
||||
Damien Lucas
|
||||
Grigori Goronzy
|
||||
Richard Shepherd
|
||||
Gaël Hendryckx
|
||||
Michael Feurstein
|
||||
Stephan Assmus
|
||||
Adrien Grand
|
||||
Colin Guthrie
|
||||
David Menestrina
|
||||
Dominique Martinet
|
||||
Gleb Pinigin
|
||||
Jason Luka
|
||||
Luc Saillard
|
||||
Luca Barbato
|
||||
Mario Speiß
|
||||
Pankaj Yadav
|
||||
Ramiro Polla
|
||||
Ronald Wright
|
||||
Rui Zhang
|
||||
Can Wu
|
||||
Christophe Courtaut
|
||||
FUJISAWA Tooru
|
||||
Hannes Domani
|
||||
Manol Manolov
|
||||
Timothy B. Terriberry
|
||||
Antoine Lejeune
|
||||
Arnaud Schauly
|
||||
Branko Kokanovic
|
||||
Dylan Yudaken
|
||||
Florian G. Pflug
|
||||
François Revol
|
||||
G Finch
|
||||
Keary Griffin
|
||||
Konstanty Bialkowski
|
||||
Ming Hu
|
||||
Philippe Coent
|
||||
Przemyslaw Fiala
|
||||
Tanguy Krotoff
|
||||
Vianney BOYER
|
||||
Casian Andrei
|
||||
Chris Smowton
|
||||
David Kaplan
|
||||
Eugenio Jarosiewicz
|
||||
Fabian Keil
|
||||
Guillaume Poussel
|
||||
John Peterson
|
||||
Justus Piater
|
||||
Mark Lee
|
||||
Martin T. H. Sandsmark
|
||||
Rune Botten
|
||||
Søren Bøg
|
||||
Toralf Niebuhr
|
||||
Tristan Matthews
|
||||
Angelo Haller
|
||||
Aurélien Nephtali
|
||||
Austin Burrow
|
||||
Bill C. Riemers
|
||||
Colin Delacroix
|
||||
Cristian Maglie
|
||||
Elminster2031
|
||||
Jakub Wieczorek
|
||||
John Freed
|
||||
Mark Hassman
|
||||
Martin Briza
|
||||
Mike Houben
|
||||
Romain Goyet
|
||||
Adrian Yanes
|
||||
Alexander Lakhin
|
||||
Anatoliy Anischovich
|
||||
Barry Wardell
|
||||
Ben Hutchings
|
||||
Besnard Jean-Baptiste
|
||||
Brian Weaver
|
||||
Clement Chesnin
|
||||
David Geldreich
|
||||
Diego Elio Pettenò
|
||||
Diego Fernando Nieto
|
||||
Georgi Chorbadzhiyski
|
||||
Jon Stacey
|
||||
Jonathan Rosser
|
||||
Joris van Rooij
|
||||
Kaloyan Kovachev
|
||||
Katsushi Kobayashi
|
||||
Kelly Anderson
|
||||
Loren Merritt
|
||||
Maciej Blizinski
|
||||
Mark Bidewell
|
||||
Miguel Angel Cabrera Moya
|
||||
Niles Bindel
|
||||
Samuel Pitoiset
|
||||
Scott Caudle
|
||||
Sean Robinson
|
||||
Sergey Radionov
|
||||
Simon Hailes
|
||||
Stephen Parry
|
||||
Sukrit Sangwan
|
||||
Thierry Reding
|
||||
Xavier Martin
|
||||
Alex Converse
|
||||
Alexander Bethke
|
||||
Alexandre Ratchov
|
||||
Andres Krapf
|
||||
Andrey Utkin
|
||||
Andri Pálsson
|
||||
Andy Chenee
|
||||
Anuradha Suraparaju
|
||||
Benjamin Poulain
|
||||
Brieuc Jeunhomme
|
||||
Chris Clayton
|
||||
Clément Lecigne
|
||||
Cédric Cocquebert
|
||||
Daniel Peng
|
||||
Danny Wood
|
||||
David K
|
||||
Edouard Gomez
|
||||
Emmanuel de Roux
|
||||
Frode Tennebø
|
||||
GBX
|
||||
Gaurav Narula
|
||||
Geraud CONTINSOUZAS
|
||||
Hugues Fruchet
|
||||
Jan Winter
|
||||
Jean-François Massol
|
||||
Jean-Philippe Grimaldi
|
||||
Josh Watzman
|
||||
Kai Lauterbach
|
||||
Konstantin Bogdanov
|
||||
Kuan-Chung Chiu
|
||||
Kuang Rufan
|
||||
Matthias Dahl
|
||||
Michael McEll
|
||||
Michael Ploujnikov
|
||||
Mike Schrag
|
||||
Nickolai Zeldovich
|
||||
Nicolas Bertrand
|
||||
Niklas Hayer
|
||||
Olafs Vandāns
|
||||
Olivier Gambier
|
||||
Paul Corke
|
||||
Ron Frederick
|
||||
Rov Juvano
|
||||
Sabourin Gilles
|
||||
Sam Lade
|
||||
Sandeep Kumar
|
||||
Sasha Koruga
|
||||
Sreng Jean
|
||||
Sven Petai
|
||||
Tomas Krotil
|
||||
Tomer Barletz
|
||||
Tristan Leteurtre
|
||||
Vittorio Giovara
|
||||
Wang Bo
|
||||
maxime Ripard
|
||||
xxcv
|
||||
Adam Hoka
|
||||
Adrian Knoth
|
||||
Adrien Cunin
|
||||
Alan Fischer
|
||||
Alan McCosh
|
||||
Alex Helfet
|
||||
Alexander Terentyev
|
||||
Alexandre Ferreira
|
||||
Alina Friedrichsen
|
||||
An L. Ber
|
||||
Andreas Schlick
|
||||
Andrew Schubert
|
||||
Andrey Makhnutin
|
||||
Arnaud Vallat
|
||||
Asad Mehmood
|
||||
Ashok Bhat
|
||||
Austin English
|
||||
Baptiste Coudurier
|
||||
Benoit Calvez
|
||||
Björn Stenberg
|
||||
Blake Livingston
|
||||
Brandon Brooks
|
||||
Brian Johnson
|
||||
Brian Kurle
|
||||
Cezar Elnazli
|
||||
Chris White
|
||||
Christian Masus
|
||||
Christoph Pfister
|
||||
Christoph Seibert
|
||||
Christopher Key
|
||||
Christopher Rath
|
||||
Claudio Ortelli
|
||||
Cody Russell
|
||||
Cristian Morales Vega
|
||||
Dan Rosenberg
|
||||
Daniel Marth
|
||||
Daniel Tisza
|
||||
Detlef Schroeder
|
||||
Diego Biurrun
|
||||
Dominik 'Rathann' Mierzejewski
|
||||
Duncan Salerno
|
||||
Edward Sheldrake
|
||||
Elliot Murphy
|
||||
Eren Inan Canpolat
|
||||
Ernest E. Teem III
|
||||
Etienne Membrives
|
||||
Fargier Sylvain
|
||||
Fathi Boudra
|
||||
Felix Geyer
|
||||
Filipe Azevedo
|
||||
Finn Hughes
|
||||
Florian Hubold
|
||||
Florian Roeske
|
||||
Frank Enderle
|
||||
Frédéric Crozat
|
||||
Georg Seifert
|
||||
Gertjan Van Droogenbroeck
|
||||
Gilles Chanteperdrix
|
||||
Greg Farrell
|
||||
Gregory Maxwell
|
||||
Gwenole Beauchesne
|
||||
Götz Waschk
|
||||
Hans-Kristian Arntzen
|
||||
Harry Sintonen
|
||||
Iain Wade
|
||||
Ibraheem Paredath
|
||||
Isamu Arimoto
|
||||
Ismael Luceno
|
||||
James Bates
|
||||
James Bond
|
||||
James Turner
|
||||
Janne Grunau
|
||||
Janne Kujanpää
|
||||
Jarmo Torvinen
|
||||
Jason Scheunemann
|
||||
Jeff Lu
|
||||
Jeroen Ost
|
||||
Joe Taber
|
||||
Johann Ransay
|
||||
Johannes Weißl
|
||||
John Hendrikx
|
||||
John Stebbins
|
||||
Jonas Gehring
|
||||
Joseph S. Atkinson
|
||||
Juergen Lock
|
||||
Julien 'Lta' BALLET
|
||||
Julien / Gellule
|
||||
Julien Humbert
|
||||
Kamil Baldyga
|
||||
Kamil Klimek
|
||||
Karlheinz Wohlmuth
|
||||
Kevin Anthony
|
||||
Kevin DuBois
|
||||
Lari Natri
|
||||
Lorenzo Pistone
|
||||
Lucas C. Villa Real
|
||||
Lukáš Lalinský
|
||||
Mal Graty
|
||||
Malte Tancred
|
||||
Martin Pöhlmann
|
||||
Martin Zeman
|
||||
Marton Balint
|
||||
Mathew King
|
||||
Mathieu Sonet
|
||||
Matthew A. Townsend
|
||||
Matthias Bauer
|
||||
Mika Tiainen
|
||||
Mike Cardillo
|
||||
Mounir Lamouri (volkmar)
|
||||
Natanael Copa
|
||||
Nathan Phillip Brink
|
||||
Nick Briggs
|
||||
Nick Pope
|
||||
Nil Geiswiller
|
||||
Pascal Thomet
|
||||
Pere Orga
|
||||
Peter Bak Nielsen
|
||||
Phil Roffe and David Grellscheid
|
||||
Philip Sequeira
|
||||
Pierre Souchay
|
||||
Piotr Fusik
|
||||
Pádraig Brady
|
||||
R.M
|
||||
Ralph Giles
|
||||
Ramon Gabarró
|
||||
Robert Forsman
|
||||
Robert Jedrzejczyk
|
||||
Robert Paciorek
|
||||
Rolf Ahrenberg
|
||||
Roman Pen
|
||||
Ruud Althuizen
|
||||
Samuli Suominen
|
||||
Scott Lyons
|
||||
Sebastian Birk
|
||||
Sergey Puzanov
|
||||
Sergio Ammirata
|
||||
Sharad Dixit
|
||||
Song Ye Wen
|
||||
Stephan Krempel
|
||||
Steven Kramer
|
||||
Steven Sheehy
|
||||
Sveinung Kvilhaugsvik
|
||||
Sylvain Cadhillac
|
||||
Sylver Bruneau
|
||||
Takahito HIRANO
|
||||
Theron Lewis
|
||||
Thijs Alkemade
|
||||
Tillmann Karras
|
||||
Timo Paulssen
|
||||
Timo Rothenpieler
|
||||
Tobias Rapp
|
||||
Tomasen
|
||||
Tony Vankrunkelsven
|
||||
Tristan Heaven
|
||||
Varphone Wong
|
||||
Vasily Fomin
|
||||
Vikram Narayanan
|
||||
Yannick Bréhon
|
||||
Yavor Doganov
|
||||
Yohann Martineau
|
||||
dharani.prabhu.s
|
||||
suheaven
|
||||
wucan
|
||||
김정은
|
||||
Adam Sampson
|
||||
Alexander Gall
|
||||
Alex Antropoff
|
||||
Alexis Guillard
|
||||
Alex Izvorski
|
||||
Amir Gouini
|
||||
Andrea Guzzo
|
||||
Andrew Flintham
|
||||
Andrew Zaikin
|
||||
Andy Lindsay
|
||||
Arai/Fujisawa Tooru
|
||||
Arkadiusz Miskiewicz
|
||||
Arnaud Gomes-do-Vale
|
||||
Arwed v. Merkatz
|
||||
Barak Ori
|
||||
Basil Achermann
|
||||
Benjamin Mironer
|
||||
Bill
|
||||
Bob Maguire
|
||||
Brian C. Wiles
|
||||
Brian Raymond
|
||||
Brian Robb
|
||||
Carsten Gottbehüt
|
||||
Carsten Haitzler
|
||||
Charles Hordis
|
||||
Chris Clepper
|
||||
Christian Henz
|
||||
Christof Baumgaertner
|
||||
Christophe Burgalat
|
||||
Christopher Johnson
|
||||
Cian Duffy
|
||||
Colin Simmonds
|
||||
Damian Ivereigh
|
||||
Daniel Fischer
|
||||
Daniel Stränger
|
||||
Danko Dolch
|
||||
Dennis Lou
|
||||
Dermot McGahon
|
||||
Douglas West
|
||||
Dugal Harris
|
||||
Emmanuel Blindauer
|
||||
Enrico Gueli
|
||||
Enrique Osuna
|
||||
Eren Türkay
|
||||
Eric Dudiak
|
||||
Espen Skoglund
|
||||
Ethan C. Baldridge
|
||||
François Seingier
|
||||
Frans van Veen
|
||||
Frédéric Ruget
|
||||
Gerald Hansink
|
||||
Gisle Vanem
|
||||
Glen Gray
|
||||
Goetz Waschk
|
||||
Gregory Hazel
|
||||
Gustaf Neumann
|
||||
Hang Su
|
||||
Hans Lambermont
|
||||
Hans-Peter Jansen
|
||||
Harris Dugal
|
||||
Heiko Panther
|
||||
Igor Helman
|
||||
Isaac Osunkunle
|
||||
Jan David Mol
|
||||
Jan Gerber
|
||||
Jan Van Boghout
|
||||
Jasper Alias
|
||||
Jean-Alexis Montignies
|
||||
Jean-Baptiste Le Stang
|
||||
Jeffrey Baker
|
||||
Jeroen Massar
|
||||
Jérôme Guilbaud
|
||||
Johannes Buchner
|
||||
Johen Michael Zorko
|
||||
Johnathan Rosser
|
||||
John Dalgliesh
|
||||
John Paul Lorenti
|
||||
Jörg
|
||||
Joseph Tulou
|
||||
Julien Blache
|
||||
Julien Plissonneau Duquène
|
||||
Julien Robert
|
||||
Kenneth Ostby
|
||||
Kenneth Self
|
||||
Kevin H. Patterson
|
||||
Koehler, Vitally
|
||||
K. Staring
|
||||
Lahiru Lakmal Priyadarshana
|
||||
Laurent Mutricy
|
||||
Leo Spalteholz
|
||||
Loox Thefuture
|
||||
Marc Nolette
|
||||
Marco Munderloh
|
||||
Mark Gritter
|
||||
Markus Kern
|
||||
Markus Kuespert
|
||||
Martin Hamrle
|
||||
Martin Kahr
|
||||
Mateus Krepsky Ludwich
|
||||
Mathias Kretschmer
|
||||
Mats Rojestal
|
||||
Matthias P. Nowak
|
||||
Matthieu Lochegnies
|
||||
Michael Mondragon
|
||||
Michael S. Feurstein
|
||||
Michel Lanners
|
||||
Mickael Hoerdt
|
||||
Miguel Angel Cabrera
|
||||
Mikko Hirvonen
|
||||
Moritz Bunkus
|
||||
Nilmoni Deb
|
||||
Olivier Houchard
|
||||
Olivier Pomel
|
||||
Ondrej Kuda aka Albert
|
||||
Øyvind Kolbu
|
||||
Pascal Levesque
|
||||
Patrick Horn
|
||||
Patrick McLean
|
||||
Pauline Castets
|
||||
Paul Mackerras
|
||||
Peter Surda
|
||||
Petr Vacek
|
||||
Philippe Van Hecke
|
||||
Pierre-Luc Beaudoin
|
||||
Pierre Marc Dumuid
|
||||
Régis Duchesne
|
||||
Remco Poortinga
|
||||
Rene Gollent
|
||||
Rob Casey
|
||||
Robson Braga Araujo
|
||||
Roine Gustafsson
|
||||
Roman Bednarek
|
||||
Rudolf Cornelissen
|
||||
Sašo Kiselkov
|
||||
Sebastian Jenny
|
||||
Shane Harper
|
||||
Stefán Freyr Stefánsson
|
||||
Steve Brown
|
||||
Steven M. Schultz
|
||||
Tapio Hiltunen
|
||||
Thomas L. Wood
|
||||
Thomas Mühlgrabner
|
||||
Thomas Parmelan
|
||||
Tim 'O Callagha
|
||||
Tim Schuerewegen
|
||||
Tong Ka Man
|
||||
Torsten Spindler
|
||||
Udo Richter
|
||||
Vincent Dimar
|
||||
Vincent Penne
|
||||
Vitalijus Slavinskas
|
||||
Vitaly V. Bursov
|
||||
Vladimir Chernyshov
|
||||
Wade Majors
|
||||
Wallace Wadge
|
||||
Watanabe Go
|
||||
William Hawkins
|
||||
Xavier Maillard
|
||||
Ye zhang
|
||||
Yuehua Zhao
|
||||
|
||||
Artwork
|
||||
-------
|
||||
Damien Erambert
|
||||
Daniel Dreibrodt, aka aLtgLasS
|
||||
David Weber
|
||||
Davor Orel
|
||||
Dominic Spitaler
|
||||
Eurodata Computer Club
|
||||
Geoffrey Roussel
|
||||
Joeri van Dooren
|
||||
kty0ne
|
||||
Max Rudberg
|
||||
Richard Øiestad
|
||||
Simon Damkjær Andersen
|
||||
Tom Bigelajzen
|
||||
Vincent van den Heuvel
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
Bill Eldridge
|
||||
|
||||
Localization
|
||||
------------
|
||||
Abdul Fousan - Tamil
|
||||
A. Decorte - Friulian
|
||||
A. Regnander - Swedish
|
||||
Adem Gunes - Turkish
|
||||
Adi Nugroho - Tagalog
|
||||
Adnan Memija - Bosnian
|
||||
airplanez - Korean
|
||||
Ajith Manjula - Sinhala
|
||||
Aled Powell - Welsh
|
||||
Alexander Didebulidze - Georgian
|
||||
Alexander Henket - Dutch
|
||||
Alexander Jansen - Norwegian Bokmål
|
||||
Alexander Lakhin - Russian
|
||||
Alexey Lugin - Ukrainian
|
||||
Alexey Salmin - Russian
|
||||
Alfred John - Acoli
|
||||
Amanpreet Singh Alam - Punjabi
|
||||
André de Barros Martins Ribeiro - Brazilian portuguese
|
||||
Andrey Brilevskiy - Russian
|
||||
Andrey Wolk - Russian
|
||||
Andri Pálsson - Icelandic
|
||||
Andriy Bandura - Ukrainian
|
||||
Anh Phan - Vietnamese
|
||||
Aniket Eknath Kudale - Marathi
|
||||
Animesh Swar - Nepalese
|
||||
Aputsiaĸ Niels Janussen - Danish
|
||||
Ara Bextiyar - Sorani (Kurdish)
|
||||
Ari Constâncio - Portuguese
|
||||
Arkadiusz Lipiec - Polish
|
||||
Ask Hjorth Larsen - Danish
|
||||
Audrey Prevost - French
|
||||
Auk Piseth - Khmer
|
||||
Bayarsaikhan Enkhtaivan Баярсайхан Энхтайван - Mongolian
|
||||
Biraj Karmakar - Bengali (India)
|
||||
Bruno Queirós - Portuguese
|
||||
Bruno Vella - Italian
|
||||
Caner Başaran - Turkish
|
||||
Carlo Calabrò - Italian
|
||||
Chandan Kumar - Hindi
|
||||
Chesús Daniel Trigo - Aragonese
|
||||
Christoph Miebach - German
|
||||
Chynggyz Jumaliev - Kirgyz
|
||||
Circo Radu - Romanian
|
||||
Cristian Secară - Romanian
|
||||
Daniel Nylander - Swedish
|
||||
Daniel Winzen - German
|
||||
David González - Spanish
|
||||
David Planella - Catalan
|
||||
Dean Lee - Simplified Chinese
|
||||
Denis Arnaud - Breton
|
||||
Derk-Jan Hartman - Dutch
|
||||
DirektX - Hungarian
|
||||
Dominko Aždajić - Croatian
|
||||
Dylan Aïssi - French
|
||||
Đorđe Vasiljević - Serbian
|
||||
Eduard Babayan - Armenian
|
||||
Eero - Estonian
|
||||
Eirik U. Birkeland - Norwegian Nynorsk
|
||||
Elizabeth Da Conceicao Baptista - Tetum
|
||||
Emilio Sepúlveda - Interlingua
|
||||
Emin Mastizada - Azerbaijani
|
||||
Éric Lassauge - French
|
||||
Farzaneh Sarafraz - Persian
|
||||
Florence Tushabe - Chiga
|
||||
Fouzia Bourai - Arabic
|
||||
Frank Chao - Traditional Chinese
|
||||
Freyr Gunnar Ólafsson - Icelandic
|
||||
Friedel Wolff - Afrikaans
|
||||
Fumio Nakayama - Japanese
|
||||
Gabor Kelemen - Hungarian
|
||||
Gaurav Kumar - Hindi
|
||||
Gaëtan Rousseaux - Walloon
|
||||
Ghjuvan Pasquinu - Corsican
|
||||
Goce Manevski - Macedonian
|
||||
Golam Maruf Oovee - Bengali
|
||||
Gonçalo Cordeiro - Galician
|
||||
Gorana Milicevic - Serbian
|
||||
Goswami Hardikpuri Kishorpuri - Gujarati
|
||||
Haakon Meland Eriksen - Norwegian
|
||||
Han HoJoong - Korean
|
||||
Hardik Kishorpuri Goswami - Gujarati
|
||||
Hemanta Nandi - Bengali (India)
|
||||
Huw Waters - Welsh
|
||||
H.Shalitha Vikum - Sinhala
|
||||
Ibrahima Sarr - Fulah
|
||||
Ingmārs Dīriņš - Latvian
|
||||
Israt Jahan - Bengali
|
||||
Ivar Smolin - Estonian
|
||||
Iván Seoane Pardo - Galician
|
||||
Ivo Ivanov - Bulgarian
|
||||
Iñaki Larrañaga Murgoitio - Basque
|
||||
Iñigo Varela - Asturian; Bable
|
||||
Jakub Žáček - Czech
|
||||
James Olweny - Ganda
|
||||
Jamil Ahmed - Bengali
|
||||
Javier Varela - Spanish
|
||||
Jean-Pierre Kuypers - French
|
||||
Jens Seidel - German
|
||||
Joao Almeida - Portuguese
|
||||
Joel Arvidsson - Swedish
|
||||
jogijs - Latvian
|
||||
Jonas Larsen - Danish
|
||||
Jon Stødle - Norwegian Nynorsk
|
||||
Jouni Kähkönen - Finnish
|
||||
Juha Jeronen - Finnish
|
||||
Julen Ruiz Aizpuru - Basque
|
||||
Kai Hermann - German
|
||||
Kamil Páral - Czech
|
||||
Kang Jeong-Hee - Korean
|
||||
Kasper Tvede - Danish
|
||||
Kaya Zeren - Turkish
|
||||
Kenneth Nielsen - Danish
|
||||
Khin Mi Mi Aung - Burmese
|
||||
Khoem Sokhem - Khmer
|
||||
Kola - Albanian
|
||||
Kypchak Kypchak - Kazakh
|
||||
Laurent Jonqueres - Occitan
|
||||
Loba Yeasmeen - Bengali
|
||||
Lorena Gomes - Catalan
|
||||
Lorenzo Porta - Italian
|
||||
Luqman Hakim - Indonesian
|
||||
L. Balasubramaniam - Hindi
|
||||
Mahrazi Mohd Kamal - Malay
|
||||
Manolis Stefanis - Modern Greek
|
||||
Manuela Silva/Alfredo Silva - Portuguese
|
||||
Marián Hikaník - Slovak
|
||||
Mario Siegmann - German
|
||||
Marko Uskokovic - Serbian
|
||||
Martin Srebotnjak - Slovenian
|
||||
Martin Zicha - Czech
|
||||
Matej Urbančič - Slovenian
|
||||
Mathias C. Berens, welcome-soft - German
|
||||
Mattias Põldaru - Estonian
|
||||
Md. Rezwan Shahid - Bengali
|
||||
Meelad Zakaria - Persian
|
||||
Michael Bauer - Scottish Gaelic
|
||||
Michal Halenka - Czech
|
||||
Michał Trzebiatowski - Polish
|
||||
Miguel Sousa - Portuguese
|
||||
Mihkel Kirjutas - Estonian
|
||||
Mindaugas Baranauskas - Lithuanian
|
||||
Miroslav Oujeský - Czech
|
||||
Morten Brix Pedersen - Danish
|
||||
Mustafa Sandal - Czech
|
||||
Myckel Habets - Dutch
|
||||
Namhyung Kim - Korean
|
||||
Niels Fanøe - Danish
|
||||
Niklas 'Nille' Åkerström - Swedish
|
||||
Olav Dahlum - Norwegian Bokmål
|
||||
Oleksandr Natalenko - Ukrainian
|
||||
Omer Ensari - Kurmanji (Kurdish)
|
||||
Osama Khalid - Arabic
|
||||
Otto Kekäläinen - Finnish
|
||||
Paras Nath Chaudhary - Nepali
|
||||
Pasindu Kavinda - Sinhala
|
||||
Pau Iranzo - Catalan
|
||||
Paula Iglesias - Galician
|
||||
Pedro Valadares - Portuguese
|
||||
Peter Jespersen - Danish
|
||||
Petr Šimáček - Czech
|
||||
Phan Anh - Vietnamese
|
||||
Philipp Weissenbacher - German
|
||||
Pittayakom Saingtong - Thai
|
||||
Prasannajit Acharya - Oriya
|
||||
Praveen Illa - Telugu
|
||||
Predrag Ljubenović - Serbian
|
||||
Pyae Sone - Burmese
|
||||
Rajnikant Kumbhar - Marathi
|
||||
Ricardo Perdigão - Portuguese
|
||||
Ricardo Pérez López - Spanish
|
||||
Roustam Ghizdatov - Russian
|
||||
Ruei-Yuan Lu - Traditional Chinese
|
||||
Saad Liaquat Kiani - Urdu
|
||||
Sadia Afroz - Bengali
|
||||
Said Marjan Zazai - Pashto
|
||||
Salar Khalilzadeh - Persian
|
||||
Sam Askari - Spanish
|
||||
Sam Hocevar - British
|
||||
Samuel Hocevar - French
|
||||
Saúl Ortega - Spanish
|
||||
Savvas Nesseris - Modern Greek
|
||||
Sayan Chowdhury - Hindi
|
||||
Seanán Ó Coistín - Irish
|
||||
Semsudin Abdic - Bosnian
|
||||
Shambhu Kumar - Hindi
|
||||
Shantanu Sarkar - Hindi
|
||||
Shashi Ranjan - Hindi
|
||||
Siarhei Daryichau Дар'ічаў Сяргей - Belarusian
|
||||
Sidney Doria - Brazilian Portuguese
|
||||
Sigmund Augdal - Norwegian Bokmål
|
||||
Simos Xenitellis - Modern Greek
|
||||
Sipho Sibiya - Zulu
|
||||
Sok Sophea - Khmer
|
||||
Solomon Gizaw - Amharic
|
||||
Sreejith P - Malayalam
|
||||
Suraj Kawade - Marathi
|
||||
Stian Jørgensrud - Norwegian Bokmål
|
||||
Sveinn í Felli - Icelandic
|
||||
Tadashi Jokagi - Japanese
|
||||
Tarsem Singh - Hindi
|
||||
Thanakrit Chomphuming - Thai
|
||||
Tero Pelander - Finnish
|
||||
Thomas De Rocker - Dutch
|
||||
Thomas Graf - gettext support, German
|
||||
Tomáš Chvátal - Czech
|
||||
Tòni Galhard - Occitan
|
||||
Umesh Agarwal - Bengali (India)
|
||||
Umidjon Almasov - Uzbek
|
||||
Václav Pavlíček - Czech
|
||||
Valek Filippov - Russian
|
||||
Vicente Jimenez Aguilar - Spanish
|
||||
Vincenzo Reale - Italian
|
||||
Vít Pelčák - Czech
|
||||
viyyer - Hindi
|
||||
Vladimir Yermolayev - Russian
|
||||
Vojtěch Smejkal - Czech
|
||||
Wei Mingzhi - Simplified Chinese
|
||||
Xènia Albà Cantero - Catalan
|
||||
Xuacu Saturio - Asturian
|
||||
Yaron Shahrabani - Hebrew
|
||||
Yaşar Tay - Turkish
|
||||
Yhal Htet Aung - Burmese
|
||||
Yogesh K S - Kannada
|
||||
Yoyo - Simplified Chinese
|
||||
Yuksel Yildirim - Turkish
|
||||
Zabeeh Khan - Pashto
|
||||
Zhang Tong - Chinese
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
Binary file not shown.
+4889
File diff suppressed because it is too large
Load Diff
+57
@@ -0,0 +1,57 @@
|
||||
README for the VLC media player
|
||||
===============================
|
||||
|
||||
VLC is a popular libre and open source media player and multimedia engine,
|
||||
used by a large number of individuals, professionals, companies and
|
||||
institutions. Using open source technologies and libraries, VLC has been
|
||||
ported to most computing platforms, including GNU/Linux, Windows, Mac OS X,
|
||||
BSD, iOS and Android.
|
||||
VLC can play most multimedia files, discs, streams, allows playback from
|
||||
devices, and is able to convert to or stream in various formats.
|
||||
The VideoLAN project was started at the university École Centrale Paris who
|
||||
relicensed VLC under the GPLv2 license in February 2001. Since then, VLC has
|
||||
been downloaded close to one billion times.
|
||||
|
||||
Links:
|
||||
======
|
||||
|
||||
The VLC web site . . . . . http://www.videolan.org/
|
||||
Support . . . . . . . . . . http://www.videolan.org/support/
|
||||
Forums . . . . . . . . . . http://forum.videolan.org/
|
||||
Wiki . . . . . . . . . . . http://wiki.videolan.org/
|
||||
The Developers site . . . . http://wiki.videolan.org/Developers_Corner
|
||||
VLC hacking guide . . . . . http://wiki.videolan.org/Hacker_Guide
|
||||
Bugtracker . . . . . . . . http://trac.videolan.org/vlc/
|
||||
The VideoLAN web site . . . http://www.videolan.org/
|
||||
|
||||
Source Code Content:
|
||||
===================
|
||||
ABOUT-NLS - Notes on the Free Translation Project.
|
||||
AUTHORS - VLC authors.
|
||||
COPYING - The GPL license.
|
||||
COPYING.LIB - The LGPL license.
|
||||
INSTALL - Installation and building instructions.
|
||||
NEWS - Important modifications between the releases.
|
||||
README - This file.
|
||||
THANKS - VLC contributors.
|
||||
|
||||
bin/ - VLC binaries.
|
||||
bindings/ - libVLC bindings to other languages.
|
||||
compat/ - compatibility library for operating systems missing
|
||||
essential functionalities.
|
||||
contrib/ - Facilities for retrieving external libraries and building
|
||||
them for systems that don't have the right versions.
|
||||
doc/ - Miscellaneous documentation.
|
||||
extras/analyser - Code analyser and editor specific files.
|
||||
extras/buildsystem - different buildsystems specific files.
|
||||
extras/misc - Files that don't fit in the other extras/ categories.
|
||||
extras/package - VLC packaging specific files such as spec files.
|
||||
extras/tools/ - Facilities for retrieving external building tools needed
|
||||
for systems that don't have the right versions.
|
||||
include/ - Header files.
|
||||
lib/ - libVLC source code.
|
||||
modules/ - VLC plugins and modules. Most of the code is here.
|
||||
po/ - VLC translations.
|
||||
share/ - Common Resources files.
|
||||
src/ - libvlccore source code.
|
||||
test/ - testing system.
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
Some VLC plugins use external libraries and make extensive use of the
|
||||
following persons' or companies' code:
|
||||
|
||||
FAAD2 - Copyright (c) Nero AG, www.nero.com" - GPLv2 or later
|
||||
FFmpeg - Copyright (c) 2000-2017 the FFmpeg developers - LGPLv2.1 or later
|
||||
FluidLite - Copyright (c) 2016 Robin Lobel - LGPLv2.1 or later
|
||||
FluidSynth - Copyright (c) 2003-2010 Peter Hanappe, Conrad Berhörster, Antoine
|
||||
Schmitt, Pedro López-Cabanillas, Josh Green, David Henningsson - LGPLv2.1 or
|
||||
later
|
||||
Fontconfig - Copyright (c) 2000,2001,2002,2003,2004,2006,2007 Keith Packard,
|
||||
(c) 2005 Patrick Lam, (c) 2009 Roozbeh Pournader, (c) 2008,2009 Red Hat,
|
||||
Inc., (c) 2008 Danilo Šegan, (c) 2012 Google, Inc. - MIT License
|
||||
freetype - David Turner, Robert Wilhelm, and Werner Lemberg - FreeType License
|
||||
GSM - Copyright (c) 1992 - 1994, 2009 Jutta Degener & Carsten Bormann - GSM
|
||||
permissive license
|
||||
GNU FriBidi - Copyright (c) 2004-2012 Behdad Esfahbod, Dov Grobgeld, Roozbeh
|
||||
Pournader - LGPLv2.1 or later
|
||||
GnuTLS - Copyright (C) 2000-2012 Free Software Foundation, Inc. - LGPLv2.1 or
|
||||
later
|
||||
harfbuzz - Copyright (c) 2010, 2011, 2012 Google, Inc., (c) 2012 Mozilla
|
||||
Foundation, (c) 2011 Codethink Limited, (c) 2008, 2010 Nokia Corporation
|
||||
and/or its subsidiary(-ies), (c) 2009 Keith Stribley, (c) 2009 Martin Hosken
|
||||
and SIL International, (c) 2007 Chris Wilson, (c) 2006 Behdad Esfahbod,
|
||||
(c) 2005 David Turner, (c) 2004, 2007, 2008, 2009, 2010 Red Hat, Inc.,
|
||||
(c) 1998-2004 David Turner and Werner Lemberg - Old MIT License
|
||||
liba52 - Aaron Holtzman & Michel Lespinasse, et al. - GPLv2 or later
|
||||
libav - Copyright (c) 2000 - 2015 the libav developers - LGPLv2.1 or later
|
||||
libass - Copyright (c) 2006-2015 Grigori Goronzy et al. - ISC License
|
||||
libbluray - Copyright (c) 2009-2015 VideoLAN and authors - LGPLv2.1 or later
|
||||
libcaca - Copyright (c) 2004 Sam Hocevar - WTFPL / LGPLv2.1 or later /
|
||||
GPLv2 or later / ISC
|
||||
libdca - Copyright (c) 2004-2007 VideoLAN and authors - GPLv2 or later
|
||||
libdvbpsi - Copyright (c) 2001-2017 VideoLAN and authors - LGPLv2.1 or later
|
||||
libdvdcss - Copyright (c) 2001-2017 VideoLAN and authors - GPLv2 or later
|
||||
libdvdread - GPLv2 or later
|
||||
libdvdnav - GPLv2 or later
|
||||
libebml - Copyright (c) 2002-2015 Steve Lhomme - LGPLv2.1 or later
|
||||
libFLAC - Copyright (c) 2001 - 2014 Josh Coalson et al. - Xiph.org BSD license
|
||||
libgme - LGPLv2.1 or later
|
||||
libgpg-error - Copyright 2003, 2004, 2005, 2006, 2007, 2013 g10 Code GmbH
|
||||
- LGPLv2.1 or later
|
||||
libkate - Copyright (c) 2008-2011 Vincent Penquerc'h - 3-clause BSD License
|
||||
liblive555 - Copyright (c) 1996-2015 Live Networks, Inc. - LGPLv2.1 or later
|
||||
libmad - Copyright (c) 2000-2004 Robert Leslie, et al. - GPLv2 or later
|
||||
libmatroska - Copyright (c) 2002-2015 Steve Lhomme - LGPLv2.1 or later
|
||||
libmpeg2 - Aaron Holtzman & Michel Lespinasse, et al. - GPLv2 or later
|
||||
libmodplug - Oliver Lapicque, Konstanty - Public domain
|
||||
libogg, libvorbis - Copyright (c) 2002-2015 Xiph.org Foundation - Xiph.org BSD
|
||||
license
|
||||
libpostproc - Copyright (C) 2001-2015 Michael Niedermayer, et al. - GPLv2 or
|
||||
later
|
||||
libpng - Copyright (c) 2004, 2006-2014 Glenn Randers-Perhson, et al. - libpng
|
||||
license
|
||||
libsamplerate - Copyright (c) 2002-2011 Erik de Castro Lopo - GPLv2 or later
|
||||
libschroedinger - Copyright (c) 2006 BBC and Fluendo - MIT License
|
||||
libsdl - Copyright (c) 1997-2014 Sam Lantinga et al. - LGPLv2.1 or later
|
||||
libshout - Copyright (c) 2012 - LGPLv2.1 or later
|
||||
libtheora - Copyright (c) Xiph.org Foundation - Xiph.org BSD license
|
||||
libtiff - Copyright (c) 1988-1997 Sam Leffler, (c) 1991-1997 Silicon Graphics,
|
||||
Inc. - BSD-like
|
||||
libtwolame - Copyright (c) 2001-2004 Michael Cheng, (c) 2004-2006 The TwoLAME
|
||||
Project - LGPLv2.1 or later
|
||||
libupnp - Copyright (c) 2000-2003 Intel Corporation - 3-clause BSD License
|
||||
libvpx - Copyright (c) 2010-2015, Google Inc. - 3-clause BSD License
|
||||
libxml2 - Copyright (c) 1998-2014 Daniel Veillard - MIT License
|
||||
lua - Copyright (c) 1994-2008 Lua.org, PUC-Rio. - MIT License
|
||||
Musepack decoder library - Copyright (c) 2005-2011, The Musepack Development
|
||||
Team - 3-clause BSD License
|
||||
OpenJPEG - Copyright (c) 2002-2014, Communcations and Remote Sensing
|
||||
Laboratory, UCL, Belgium - ISC License
|
||||
Opus - Copyright 2001-2013 Xiph.Org, Skype Limited, Octasic, Jean-Marc Valin,
|
||||
Timothy B. Terriberry, CSIRO, Gregory Maxwell, Mark Borgerding,
|
||||
Erik de Castro Lopo - Xiph.org BSD License
|
||||
Sparkle — Andy Matuschak et al. - MIT License
|
||||
Speex, Speexdsp - Copyright (c) 1992-2015 Xiph.org Foundation, Jean-Marc Valin,
|
||||
Analog Devices Inc. Commonwealth Scientific and Industrial Research
|
||||
Organisation, David Row, Jutta Degener, Carsten Bormann - 3-clause BSD
|
||||
License
|
||||
taglib - Copyright (c) 2004-2016 Scott Wheeler, et al. - LGPLv2.1 or later
|
||||
x264 - Copyright (c) 2004-2017 VideoLAN and authors - GPLv2 or later
|
||||
x265 - Copyright (c) 2004-2015 x265 project - GPLv2 or later
|
||||
Zapping VBI library - Copyright (c) 2000-2003 Michael H. Schimek, Iñaki García
|
||||
Etxebarria - LGPLv2.1 or later
|
||||
zlib - Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler - zlib license
|
||||
|
||||
The VideoLAN team would like to thank the following donators:
|
||||
|
||||
Julian Cain, who made a $1000 donation
|
||||
The French website MacBidouille gave €500 to help us buy a PowerMac G5
|
||||
The French magazine à vos MAC gave €500 to help us buy a PowerMac G5
|
||||
Laurent Dupuy, who made a €540 donation
|
||||
The French company Cybervia (Actech) gave €2000 to pay for webserver hosting
|
||||
Dennis Perov - Hardware donation
|
||||
|
||||
...the following active members of our user community:
|
||||
|
||||
Alan Wright
|
||||
David J LaBarre "DJ"
|
||||
Eric Adler
|
||||
Julien Bouquillon
|
||||
|
||||
...and code auditors and testers:
|
||||
|
||||
David Thiel
|
||||
Philippe A. aka "Lotesdelère"
|
||||
Sebastien Chaumat
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"FileVersion" : 3,
|
||||
|
||||
"FriendlyName" : "VLC Media Player",
|
||||
"Version" : 14,
|
||||
"VersionName" : "14.0",
|
||||
"CreatedBy" : "Epic Games Inc",
|
||||
"CreatedByURL" : "http://epicgames.com",
|
||||
"DocsURL" : "https://github.com/ue4plugins/VlcMedia",
|
||||
"Description" : "Implements a media player using the Video LAN Codec (libvlc).",
|
||||
"Category" : "Media Players",
|
||||
"EnabledByDefault" : true,
|
||||
"IsBetaVersion": true,
|
||||
|
||||
"Modules" :
|
||||
[
|
||||
{
|
||||
"Name" : "VlcMedia",
|
||||
"Type" : "RuntimeNoCommandlet",
|
||||
"LoadingPhase" : "PreLoadingScreen",
|
||||
"WhitelistPlatforms" : [ "Linux", "Mac", "Win32", "Win64" ]
|
||||
},
|
||||
{
|
||||
"Name" : "VlcMediaEditor",
|
||||
"Type" : "Editor",
|
||||
"LoadingPhase" : "PostEngineInit"
|
||||
},
|
||||
{
|
||||
"Name" : "VlcMediaFactory",
|
||||
"Type" : "Editor",
|
||||
"LoadingPhase" : "PostEngineInit"
|
||||
},
|
||||
{
|
||||
"Name": "VlcMediaFactory",
|
||||
"Type": "RuntimeNoCommandlet",
|
||||
"LoadingPhase" : "PostEngineInit",
|
||||
"WhitelistPlatforms" : [ "Linux", "Mac", "Win32", "Win64" ]
|
||||
}
|
||||
],
|
||||
|
||||
"CanContainContent" : false
|
||||
}
|
||||
Reference in New Issue
Block a user