diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-09-20 11:48:23 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-09-20 11:48:23 -0400 |
| commit | f6769b73f2a82273e67689e8bc1c9d7b005ee866 (patch) | |
| tree | a8a947f475e47632e61d0b91f421faa245f7198a /MediaBrowser.MediaInfo | |
| parent | ab207209b8138dccfea82d0fcd39866ff7e2fe9c (diff) | |
add MediaInfo to improve media analysis for video files
Diffstat (limited to 'MediaBrowser.MediaInfo')
| -rw-r--r-- | MediaBrowser.MediaInfo/MediaBrowser.MediaInfo.csproj | 60 | ||||
| -rw-r--r-- | MediaBrowser.MediaInfo/MediaInfoLib.cs | 58 | ||||
| -rw-r--r-- | MediaBrowser.MediaInfo/Native.cs | 275 | ||||
| -rw-r--r-- | MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs | 36 |
4 files changed, 429 insertions, 0 deletions
diff --git a/MediaBrowser.MediaInfo/MediaBrowser.MediaInfo.csproj b/MediaBrowser.MediaInfo/MediaBrowser.MediaInfo.csproj new file mode 100644 index 0000000000..52941422de --- /dev/null +++ b/MediaBrowser.MediaInfo/MediaBrowser.MediaInfo.csproj @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{6E4145E4-C6D4-4E4D-94F2-87188DB6E239}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>MediaBrowser.MediaInfo</RootNamespace> + <AssemblyName>MediaBrowser.MediaInfo</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="MediaInfoLib.cs" /> + <Compile Include="Native.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <Content Include="..\ThirdParty\MediaInfo\windows\x86\MediaInfo.dll"> + <Link>MediaInfo.dll</Link> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/MediaBrowser.MediaInfo/MediaInfoLib.cs b/MediaBrowser.MediaInfo/MediaInfoLib.cs new file mode 100644 index 0000000000..64842edcbe --- /dev/null +++ b/MediaBrowser.MediaInfo/MediaInfoLib.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace MediaBrowser.MediaInfo +{ + public class MediaInfoLib + { + public MediaInfoResult GetVideoInfo(string path) + { + var lib = new MediaInfo(); + + lib.Open(path); + + var result = new MediaInfoResult(); + + // TODO: Don't hardcode + var videoStreamIndex = 0; + + var text = GetValue(lib, videoStreamIndex, new[] { "ScanType", "Scan type", "ScanType/String" }); + if (!string.IsNullOrWhiteSpace(text)) + { + result.IsInterlaced = text.IndexOf("interlac", StringComparison.OrdinalIgnoreCase) != -1; + } + + int bitDepth; + text = GetValue(lib, videoStreamIndex, new[] { "BitDepth", "BitDepth/String" }); + + if (!string.IsNullOrWhiteSpace(text) && int.TryParse(text.Split(' ').First(), NumberStyles.Any, CultureInfo.InvariantCulture, out bitDepth)) + { + result.BitDepth = bitDepth; + } + + int refFrames; + text = GetValue(lib, videoStreamIndex, new[] { "Format_Settings_RefFrames", "Format_Settings_RefFrames/String" }); + + if (!string.IsNullOrWhiteSpace(text) && int.TryParse(text.Split(' ').First(), NumberStyles.Any, CultureInfo.InvariantCulture, out refFrames)) + { + result.RefFrames = refFrames; + } + + return result; + } + + private string GetValue(MediaInfo lib, int index, IEnumerable<string> names) + { + return names.Select(i => lib.Get(StreamKind.Video, index, i)).FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); + } + } + + public class MediaInfoResult + { + public bool? IsInterlaced { get; set; } + public int? BitDepth { get; set; } + public int? RefFrames { get; set; } + } +} diff --git a/MediaBrowser.MediaInfo/Native.cs b/MediaBrowser.MediaInfo/Native.cs new file mode 100644 index 0000000000..5bc7ae368f --- /dev/null +++ b/MediaBrowser.MediaInfo/Native.cs @@ -0,0 +1,275 @@ +using System; +using System.Runtime.InteropServices; + +namespace MediaBrowser.MediaInfo +{ + public enum StreamKind + { + General, + Video, + Audio, + Text, + Other, + Image, + Menu, + } + + public enum InfoKind + { + Name, + Text, + Measure, + Options, + NameText, + MeasureText, + Info, + HowTo + } + + public enum InfoOptions + { + ShowInInform, + Support, + ShowInSupported, + TypeOfValue + } + + public enum InfoFileOptions + { + FileOption_Nothing = 0x00, + FileOption_NoRecursive = 0x01, + FileOption_CloseAll = 0x02, + FileOption_Max = 0x04 + }; + + public enum Status + { + None = 0x00, + Accepted = 0x01, + Filled = 0x02, + Updated = 0x04, + Finalized = 0x08, + } + + public class MediaInfo + { + //Import of DLL functions. DO NOT USE until you know what you do (MediaInfo DLL do NOT use CoTaskMemAlloc to allocate memory) + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_New(); + [DllImport("MediaInfo")] + private static extern void MediaInfo_Delete(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_Open(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string FileName); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoA_Open(IntPtr Handle, IntPtr FileName); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_Open_Buffer_Init(IntPtr Handle, Int64 File_Size, Int64 File_Offset); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoA_Open(IntPtr Handle, Int64 File_Size, Int64 File_Offset); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_Open_Buffer_Continue(IntPtr Handle, IntPtr Buffer, IntPtr Buffer_Size); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoA_Open_Buffer_Continue(IntPtr Handle, Int64 File_Size, byte[] Buffer, IntPtr Buffer_Size); + [DllImport("MediaInfo")] + private static extern Int64 MediaInfo_Open_Buffer_Continue_GoTo_Get(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern Int64 MediaInfoA_Open_Buffer_Continue_GoTo_Get(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_Open_Buffer_Finalize(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoA_Open_Buffer_Finalize(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern void MediaInfo_Close(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_Inform(IntPtr Handle, IntPtr Reserved); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoA_Inform(IntPtr Handle, IntPtr Reserved); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_GetI(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber, IntPtr Parameter, IntPtr KindOfInfo); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoA_GetI(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber, IntPtr Parameter, IntPtr KindOfInfo); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_Get(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber, [MarshalAs(UnmanagedType.LPWStr)] string Parameter, IntPtr KindOfInfo, IntPtr KindOfSearch); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoA_Get(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber, IntPtr Parameter, IntPtr KindOfInfo, IntPtr KindOfSearch); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_Option(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string Option, [MarshalAs(UnmanagedType.LPWStr)] string Value); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoA_Option(IntPtr Handle, IntPtr Option, IntPtr Value); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_State_Get(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfo_Count_Get(IntPtr Handle, IntPtr StreamKind, IntPtr StreamNumber); + + //MediaInfo class + public MediaInfo() + { + try + { + Handle = MediaInfo_New(); + } + catch + { + Handle = (IntPtr)0; + } + if (Environment.OSVersion.ToString().IndexOf("Windows") == -1) + MustUseAnsi = true; + else + MustUseAnsi = false; + } + ~MediaInfo() { if (Handle == (IntPtr)0) return; MediaInfo_Delete(Handle); } + public int Open(String FileName) + { + if (Handle == (IntPtr)0) + return 0; + if (MustUseAnsi) + { + IntPtr FileName_Ptr = Marshal.StringToHGlobalAnsi(FileName); + int ToReturn = (int)MediaInfoA_Open(Handle, FileName_Ptr); + Marshal.FreeHGlobal(FileName_Ptr); + return ToReturn; + } + else + return (int)MediaInfo_Open(Handle, FileName); + } + public int Open_Buffer_Init(Int64 File_Size, Int64 File_Offset) + { + if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_Open_Buffer_Init(Handle, File_Size, File_Offset); + } + public int Open_Buffer_Continue(IntPtr Buffer, IntPtr Buffer_Size) + { + if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_Open_Buffer_Continue(Handle, Buffer, Buffer_Size); + } + public Int64 Open_Buffer_Continue_GoTo_Get() + { + if (Handle == (IntPtr)0) return 0; return (Int64)MediaInfo_Open_Buffer_Continue_GoTo_Get(Handle); + } + public int Open_Buffer_Finalize() + { + if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_Open_Buffer_Finalize(Handle); + } + public void Close() { if (Handle == (IntPtr)0) return; MediaInfo_Close(Handle); } + public String Inform() + { + if (Handle == (IntPtr)0) + return "Unable to load MediaInfo library"; + if (MustUseAnsi) + return Marshal.PtrToStringAnsi(MediaInfoA_Inform(Handle, (IntPtr)0)); + else + return Marshal.PtrToStringUni(MediaInfo_Inform(Handle, (IntPtr)0)); + } + public String Get(StreamKind StreamKind, int StreamNumber, String Parameter, InfoKind KindOfInfo, InfoKind KindOfSearch) + { + if (Handle == (IntPtr)0) + return "Unable to load MediaInfo library"; + if (MustUseAnsi) + { + IntPtr Parameter_Ptr = Marshal.StringToHGlobalAnsi(Parameter); + String ToReturn = Marshal.PtrToStringAnsi(MediaInfoA_Get(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber, Parameter_Ptr, (IntPtr)KindOfInfo, (IntPtr)KindOfSearch)); + Marshal.FreeHGlobal(Parameter_Ptr); + return ToReturn; + } + else + return Marshal.PtrToStringUni(MediaInfo_Get(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber, Parameter, (IntPtr)KindOfInfo, (IntPtr)KindOfSearch)); + } + public String Get(StreamKind StreamKind, int StreamNumber, int Parameter, InfoKind KindOfInfo) + { + if (Handle == (IntPtr)0) + return "Unable to load MediaInfo library"; + if (MustUseAnsi) + return Marshal.PtrToStringAnsi(MediaInfoA_GetI(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber, (IntPtr)Parameter, (IntPtr)KindOfInfo)); + else + return Marshal.PtrToStringUni(MediaInfo_GetI(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber, (IntPtr)Parameter, (IntPtr)KindOfInfo)); + } + public String Option(String Option, String Value) + { + if (Handle == (IntPtr)0) + return "Unable to load MediaInfo library"; + if (MustUseAnsi) + { + IntPtr Option_Ptr = Marshal.StringToHGlobalAnsi(Option); + IntPtr Value_Ptr = Marshal.StringToHGlobalAnsi(Value); + String ToReturn = Marshal.PtrToStringAnsi(MediaInfoA_Option(Handle, Option_Ptr, Value_Ptr)); + Marshal.FreeHGlobal(Option_Ptr); + Marshal.FreeHGlobal(Value_Ptr); + return ToReturn; + } + else + return Marshal.PtrToStringUni(MediaInfo_Option(Handle, Option, Value)); + } + public int State_Get() { if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_State_Get(Handle); } + public int Count_Get(StreamKind StreamKind, int StreamNumber) { if (Handle == (IntPtr)0) return 0; return (int)MediaInfo_Count_Get(Handle, (IntPtr)StreamKind, (IntPtr)StreamNumber); } + private IntPtr Handle; + private bool MustUseAnsi; + + //Default values, if you know how to set default values in C#, say me + public String Get(StreamKind StreamKind, int StreamNumber, String Parameter, InfoKind KindOfInfo) { return Get(StreamKind, StreamNumber, Parameter, KindOfInfo, InfoKind.Name); } + public String Get(StreamKind StreamKind, int StreamNumber, String Parameter) { return Get(StreamKind, StreamNumber, Parameter, InfoKind.Text, InfoKind.Name); } + public String Get(StreamKind StreamKind, int StreamNumber, int Parameter) { return Get(StreamKind, StreamNumber, Parameter, InfoKind.Text); } + public String Option(String Option_) { return Option(Option_, ""); } + public int Count_Get(StreamKind StreamKind) { return Count_Get(StreamKind, -1); } + } + + + + + + + + + + + + + + + + + + public class MediaInfoList + { + //Import of DLL functions. DO NOT USE until you know what you do (MediaInfo DLL do NOT use CoTaskMemAlloc to allocate memory) + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoList_New(); + [DllImport("MediaInfo")] + private static extern void MediaInfoList_Delete(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoList_Open(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string FileName, IntPtr Options); + [DllImport("MediaInfo")] + private static extern void MediaInfoList_Close(IntPtr Handle, IntPtr FilePos); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoList_Inform(IntPtr Handle, IntPtr FilePos, IntPtr Reserved); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoList_GetI(IntPtr Handle, IntPtr FilePos, IntPtr StreamKind, IntPtr StreamNumber, IntPtr Parameter, IntPtr KindOfInfo); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoList_Get(IntPtr Handle, IntPtr FilePos, IntPtr StreamKind, IntPtr StreamNumber, [MarshalAs(UnmanagedType.LPWStr)] string Parameter, IntPtr KindOfInfo, IntPtr KindOfSearch); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoList_Option(IntPtr Handle, [MarshalAs(UnmanagedType.LPWStr)] string Option, [MarshalAs(UnmanagedType.LPWStr)] string Value); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoList_State_Get(IntPtr Handle); + [DllImport("MediaInfo")] + private static extern IntPtr MediaInfoList_Count_Get(IntPtr Handle, IntPtr FilePos, IntPtr StreamKind, IntPtr StreamNumber); + + //MediaInfo class + public MediaInfoList() { Handle = MediaInfoList_New(); } + ~MediaInfoList() { MediaInfoList_Delete(Handle); } + public int Open(String FileName, InfoFileOptions Options) { return (int)MediaInfoList_Open(Handle, FileName, (IntPtr)Options); } + public void Close(int FilePos) { MediaInfoList_Close(Handle, (IntPtr)FilePos); } + public String Inform(int FilePos) { return Marshal.PtrToStringUni(MediaInfoList_Inform(Handle, (IntPtr)FilePos, (IntPtr)0)); } + public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, String Parameter, InfoKind KindOfInfo, InfoKind KindOfSearch) { return Marshal.PtrToStringUni(MediaInfoList_Get(Handle, (IntPtr)FilePos, (IntPtr)StreamKind, (IntPtr)StreamNumber, Parameter, (IntPtr)KindOfInfo, (IntPtr)KindOfSearch)); } + public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, int Parameter, InfoKind KindOfInfo) { return Marshal.PtrToStringUni(MediaInfoList_GetI(Handle, (IntPtr)FilePos, (IntPtr)StreamKind, (IntPtr)StreamNumber, (IntPtr)Parameter, (IntPtr)KindOfInfo)); } + public String Option(String Option, String Value) { return Marshal.PtrToStringUni(MediaInfoList_Option(Handle, Option, Value)); } + public int State_Get() { return (int)MediaInfoList_State_Get(Handle); } + public int Count_Get(int FilePos, StreamKind StreamKind, int StreamNumber) { return (int)MediaInfoList_Count_Get(Handle, (IntPtr)FilePos, (IntPtr)StreamKind, (IntPtr)StreamNumber); } + private IntPtr Handle; + + //Default values, if you know how to set default values in C#, say me + public void Open(String FileName) { Open(FileName, 0); } + public void Close() { Close(-1); } + public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, String Parameter, InfoKind KindOfInfo) { return Get(FilePos, StreamKind, StreamNumber, Parameter, KindOfInfo, InfoKind.Name); } + public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, String Parameter) { return Get(FilePos, StreamKind, StreamNumber, Parameter, InfoKind.Text, InfoKind.Name); } + public String Get(int FilePos, StreamKind StreamKind, int StreamNumber, int Parameter) { return Get(FilePos, StreamKind, StreamNumber, Parameter, InfoKind.Text); } + public String Option(String Option_) { return Option(Option_, ""); } + public int Count_Get(int FilePos, StreamKind StreamKind) { return Count_Get(FilePos, StreamKind, -1); } + } +} diff --git a/MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs b/MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..5debd4f611 --- /dev/null +++ b/MediaBrowser.MediaInfo/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MediaBrowser.MediaInfo")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MediaBrowser.MediaInfo")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8ef5ed2a-0460-4fb4-ba3f-fc2ba057f009")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] |
