You've already forked Sonarr
							
							
				mirror of
				https://github.com/Sonarr/Sonarr.git
				synced 2025-10-31 00:07:55 +02:00 
			
		
		
		
	dllmap added for MediaInfo.DLL
Fall back to filesize check if mediainfo is not available Ubuntu package depends on sqlite3 and mediainfo New: mediainfo now used on mono to check runtime when available
This commit is contained in:
		
							
								
								
									
										15
									
								
								build.ps1
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								build.ps1
									
									
									
									
									
								
							| @@ -3,6 +3,7 @@ $outputFolder = '.\_output' | ||||
| $outputFolderMono = '.\_output_mono' | ||||
| $testPackageFolder = '.\_tests\' | ||||
| $testSearchPattern = '*.Test\bin\x86\Release' | ||||
| $sourceFolder = '.\src' | ||||
|  | ||||
| Function Build() | ||||
| { | ||||
| @@ -84,6 +85,9 @@ Function PackageMono() | ||||
|     get-childitem $outputFolderMono -File -Filter sqlite3.* -Recurse  | foreach ($_) {remove-item $_.fullname} | ||||
|     get-childitem $outputFolderMono -File -Filter MediaInfo.* -Recurse  | foreach ($_) {remove-item $_.fullname} | ||||
|  | ||||
|     Write-Host "Adding MediaInfoDotNet.dll.config (for dllmap)" | ||||
|     Copy-Item "$sourceFolder\MediaInfoDotNet.dll.config" $outputFolderMono | ||||
|  | ||||
|     Write-Host Renaming NzbDrone.Console.exe to NzbDrone.exe | ||||
|     get-childitem $outputFolderMono -File -Filter NzbDrone.exe -Recurse  | foreach ($_) {remove-item $_.fullname} | ||||
|     Rename-Item "$outputFolderMono\NzbDrone.Console.exe" "NzbDrone.exe" | ||||
| @@ -103,7 +107,7 @@ Function PackageTests() | ||||
| { | ||||
|  | ||||
|     Write-Host Packaging Tests | ||||
|     Write-Host "##teamcity[progressStart 'Creating Mono Package']" | ||||
|     Write-Host "##teamcity[progressStart 'Creating Test Package']" | ||||
|    | ||||
|     if(Test-Path $testPackageFolder) | ||||
|     { | ||||
| @@ -117,8 +121,8 @@ Function PackageTests() | ||||
|  | ||||
|     .\src\.nuget\NuGet.exe install NUnit.Runners -Version 2.6.1 -Output $testPackageFolder    | ||||
|  | ||||
|     Copy-Item $outputFolder\*.dll  -Destination $testPackageFolder -Force | ||||
|     Copy-Item $outputFolder\*.pdb  -Destination $testPackageFolder -Force | ||||
|     Copy-Item $outputFolder\*.dll -Destination $testPackageFolder -Force | ||||
|     Copy-Item $outputFolder\*.pdb -Destination $testPackageFolder -Force | ||||
|  | ||||
|     Copy-Item .\*.sh               -Destination $testPackageFolder -Force | ||||
|  | ||||
| @@ -126,7 +130,10 @@ Function PackageTests() | ||||
|  | ||||
|     CleanFolder $testPackageFolder | ||||
|  | ||||
|     Write-Host "##teamcity[progressFinish 'Creating Mono Package']" | ||||
|     Write-Host "Adding MediaInfoDotNet.dll.config (for dllmap)" | ||||
|     Copy-Item "$sourceFolder\MediaInfoDotNet.dll.config" -Destination $testPackageFolder -Force | ||||
|  | ||||
|     Write-Host "##teamcity[progressFinish 'Creating Test Package']" | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							| @@ -8,5 +8,5 @@ Vcs-Browser: https://github.com/NzbDrone/NzbDrone | ||||
|  | ||||
| Package: nzbdrone | ||||
| Architecture: all | ||||
| Depends: libmono-cil-dev (>= 2.10.1) | ||||
| Depends: libmono-cil-dev (>= 2.10.1), sqlite3 (>= 3.7), mediainfo (>= 0.7.52) | ||||
| Description: NZBDrone is a PVR for newsgroup users | ||||
|   | ||||
							
								
								
									
										5
									
								
								src/MediaInfoDotNet.dll.config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/MediaInfoDotNet.dll.config
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <configuration> | ||||
|     <dllmap os="osx" dll="MediaInfo.dll" target="libmediainfo.dylib"/> | ||||
|     <dllmap os="linux" dll="MediaInfo.dll" target="libmediainfo.so.0" /> | ||||
| </configuration> | ||||
| @@ -85,21 +85,8 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void should_not_run_runtime_check_on_linux() | ||||
|         public void should_use_runtime() | ||||
|         { | ||||
|             LinuxOnly(); | ||||
|             GivenFileSize(1000.Megabytes()); | ||||
| 
 | ||||
|             Subject.IsSatisfiedBy(_localEpisode); | ||||
|              | ||||
|             Mocker.GetMock<IVideoFileInfoReader>().Verify(v => v.GetRunTime(It.IsAny<String>()), Times.Never()); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void should_run_runtime_check_on_windows() | ||||
|         { | ||||
|             WindowsOnly(); | ||||
| 
 | ||||
|             GivenRuntime(120); | ||||
|             GivenFileSize(1000.Megabytes()); | ||||
| 
 | ||||
| @@ -111,7 +98,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications | ||||
|         [Test] | ||||
|         public void should_return_false_if_runtime_is_less_than_minimum() | ||||
|         { | ||||
|             WindowsOnly(); | ||||
|             GivenRuntime(60); | ||||
| 
 | ||||
|             Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse(); | ||||
| @@ -120,32 +106,30 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications | ||||
|         [Test] | ||||
|         public void should_return_true_if_runtime_greater_than_than_minimum() | ||||
|         { | ||||
|             WindowsOnly(); | ||||
|             GivenRuntime(120); | ||||
| 
 | ||||
|             Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue(); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void should_return_false_if_file_size_is_under_minimum() | ||||
|         public void should_fall_back_to_file_size_if_mediainfo_dll_not_found_acceptable_size() | ||||
|         { | ||||
|             LinuxOnly(); | ||||
|             Mocker.GetMock<IVideoFileInfoReader>() | ||||
|                   .Setup(s => s.GetRunTime(It.IsAny<String>())) | ||||
|                   .Throws<DllNotFoundException>(); | ||||
| 
 | ||||
|             GivenRuntime(120); | ||||
|             GivenFileSize(20.Megabytes()); | ||||
| 
 | ||||
|             Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse(); | ||||
|             GivenFileSize(1000.Megabytes()); | ||||
|             Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue(); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void should_return_false_if_file_size_is_under_minimum_for_larger_limits() | ||||
|         public void should_fall_back_to_file_size_if_mediainfo_dll_not_found_undersize() | ||||
|         { | ||||
|             LinuxOnly(); | ||||
| 
 | ||||
|             GivenRuntime(120); | ||||
|             GivenFileSize(120.Megabytes()); | ||||
|             _localEpisode.Quality = new QualityModel(Quality.Bluray1080p); | ||||
|             Mocker.GetMock<IVideoFileInfoReader>() | ||||
|                   .Setup(s => s.GetRunTime(It.IsAny<String>())) | ||||
|                   .Throws<DllNotFoundException>(); | ||||
| 
 | ||||
|             GivenFileSize(1.Megabytes()); | ||||
|             Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse(); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| using System.IO; | ||||
| using FluentAssertions; | ||||
| using Moq; | ||||
| using NUnit.Framework; | ||||
| using NzbDrone.Common; | ||||
| using NzbDrone.Core.MediaFiles.MediaInfo; | ||||
| using NzbDrone.Core.Test.Framework; | ||||
| using NzbDrone.Test.Common.Categories; | ||||
| @@ -11,6 +13,14 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo | ||||
|     [DiskAccessTest] | ||||
|     public class VideoFileInfoReaderFixture : CoreTest<VideoFileInfoReader> | ||||
|     { | ||||
|         [SetUp] | ||||
|         public void Setup() | ||||
|         { | ||||
|             Mocker.GetMock<IDiskProvider>() | ||||
|                   .Setup(s => s.FileExists(It.IsAny<string>())) | ||||
|                   .Returns(true); | ||||
|         } | ||||
| 
 | ||||
|         [Test] | ||||
|         public void get_runtime() | ||||
|         { | ||||
|   | ||||
| @@ -61,7 +61,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             if (OsInfo.IsWindows) | ||||
|             try | ||||
|             { | ||||
|                 var runTime = _videoFileInfoReader.GetRunTime(localEpisode.Path); | ||||
| 
 | ||||
| @@ -76,12 +76,17 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications | ||||
|                     _logger.Trace("[{0}] appears to be a sample. Size: {1} Runtime: {2}", localEpisode.Path, localEpisode.Size, runTime); | ||||
|                     return false; | ||||
|                 } | ||||
| 
 | ||||
|                 _logger.Trace("Runtime is over 2 minutes, skipping file size check"); | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             return CheckSize(localEpisode); | ||||
|             catch (DllNotFoundException) | ||||
|             { | ||||
|                 _logger.Trace("Falling back to file size detection"); | ||||
| 
 | ||||
|                 return CheckSize(localEpisode); | ||||
|             } | ||||
| 
 | ||||
|             _logger.Trace("Runtime is over 90 seconds"); | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         private bool CheckSize(LocalEpisode localEpisode) | ||||
| @@ -90,12 +95,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications | ||||
|             { | ||||
|                 if (localEpisode.Size < SampleSizeLimit * 2) | ||||
|                 { | ||||
|                     _logger.Trace("1080p file is less than sample limit"); | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (localEpisode.Size < SampleSizeLimit) | ||||
|             { | ||||
|                 _logger.Trace("File is less than sample limit"); | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| namespace NzbDrone.Core.MediaFiles.MediaInfo | ||||
| using System; | ||||
| 
 | ||||
| namespace NzbDrone.Core.MediaFiles.MediaInfo | ||||
| { | ||||
|     public class MediaInfoModel | ||||
|     { | ||||
| @@ -8,7 +10,7 @@ | ||||
|         public int Height { get; set; } | ||||
|         public string AudioFormat { get; set; } | ||||
|         public int AudioBitrate { get; set; } | ||||
|         public int RunTime { get; set; } | ||||
|         public TimeSpan RunTime { get; set; } | ||||
|         public int AudioStreamCount { get; set; } | ||||
|         public int AudioChannels { get; set; } | ||||
|         public string AudioProfile { get; set; } | ||||
|   | ||||
| @@ -30,10 +30,11 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo | ||||
|             if (!_diskProvider.FileExists(filename)) | ||||
|                 throw new FileNotFoundException("Media file does not exist: " + filename); | ||||
| 
 | ||||
|             var mediaInfo = new MediaInfoLib.MediaInfo(); | ||||
|             MediaInfoLib.MediaInfo mediaInfo = null; | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
|                 mediaInfo = new MediaInfoLib.MediaInfo(); | ||||
|                 _logger.Trace("Getting media info from {0}", filename); | ||||
| 
 | ||||
|                 mediaInfo.Option("ParseSpeed", "0.2"); | ||||
| @@ -56,26 +57,26 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo | ||||
|                     Int32.TryParse(mediaInfo.Get(StreamKind.Video, 0, "BitRate"), out videoBitRate); | ||||
| 
 | ||||
|                     string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate"); | ||||
|                     int ABindex = aBitRate.IndexOf(" /"); | ||||
|                     if (ABindex > 0) | ||||
|                         aBitRate = aBitRate.Remove(ABindex); | ||||
|                     int aBindex = aBitRate.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase); | ||||
|                     if (aBindex > 0) | ||||
|                         aBitRate = aBitRate.Remove(aBindex); | ||||
| 
 | ||||
|                     Int32.TryParse(aBitRate, out audioBitRate); | ||||
|                     Int32.TryParse(mediaInfo.Get(StreamKind.Video, 0, "PlayTime"), out runTime); | ||||
|                     Int32.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "StreamCount"), out streamCount); | ||||
| 
 | ||||
|                     string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)"); | ||||
|                     int ACindex = audioChannelsStr.IndexOf(" /"); | ||||
|                     if (ACindex > 0) | ||||
|                         audioChannelsStr = audioChannelsStr.Remove(ACindex); | ||||
|                     int aCindex = audioChannelsStr.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase); | ||||
|                     if (aCindex > 0) | ||||
|                         audioChannelsStr = audioChannelsStr.Remove(aCindex); | ||||
| 
 | ||||
|                     string audioLanguages = mediaInfo.Get(StreamKind.General, 0, "Audio_Language_List"); | ||||
|                     decimal videoFrameRate = Decimal.Parse(mediaInfo.Get(StreamKind.Video, 0, "FrameRate")); | ||||
|                     string audioProfile = mediaInfo.Get(StreamKind.Audio, 0, "Format_Profile"); | ||||
| 
 | ||||
|                     int APindex = audioProfile.IndexOf(" /"); | ||||
|                     if (APindex > 0) | ||||
|                         audioProfile = audioProfile.Remove(APindex); | ||||
|                     int aPindex = audioProfile.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase); | ||||
|                     if (aPindex > 0) | ||||
|                         audioProfile = audioProfile.Remove(aPindex); | ||||
| 
 | ||||
|                     Int32.TryParse(audioChannelsStr, out audioChannels); | ||||
|                     var mediaInfoModel = new MediaInfoModel | ||||
| @@ -84,9 +85,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo | ||||
|                                                     VideoBitrate = videoBitRate, | ||||
|                                                     Height = height, | ||||
|                                                     Width = width, | ||||
| 
 | ||||
|                                                     AudioFormat = mediaInfo.Get(StreamKind.Audio, 0, "Format"), | ||||
|                                                     AudioBitrate = audioBitRate, | ||||
|                                                     RunTime = (runTime / 1000), //InSeconds | ||||
|                                                     RunTime = TimeSpan.FromMilliseconds(runTime), | ||||
|                                                     AudioStreamCount = streamCount, | ||||
|                                                     AudioChannels = audioChannels, | ||||
|                                                     AudioProfile = audioProfile.Trim(), | ||||
| @@ -100,34 +102,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo | ||||
|                     return mediaInfoModel; | ||||
|                 } | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             catch (DllNotFoundException ex) | ||||
|             { | ||||
|                 _logger.ErrorException("Unable to parse media info from file: " + filename, ex); | ||||
|                 mediaInfo.Close(); | ||||
|             } | ||||
| 
 | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         public TimeSpan GetRunTime(string filename) | ||||
|         { | ||||
|             MediaInfoLib.MediaInfo mediaInfo = null; | ||||
|             try | ||||
|             { | ||||
|                 mediaInfo = new MediaInfoLib.MediaInfo(); | ||||
|                 _logger.Trace("Getting media info from {0}", filename); | ||||
| 
 | ||||
|                 mediaInfo.Option("ParseSpeed", "0.2"); | ||||
|                 int open = mediaInfo.Open(filename); | ||||
| 
 | ||||
|                 if (open != 0) | ||||
|                 { | ||||
|                     int runTime; | ||||
|                     Int32.TryParse(mediaInfo.Get(StreamKind.Video, 0, "PlayTime"), out runTime); | ||||
| 
 | ||||
|                     mediaInfo.Close(); | ||||
|                     return TimeSpan.FromMilliseconds(runTime); | ||||
|                 } | ||||
|                 _logger.ErrorException("mediainfo is required but was not found", ex); | ||||
|                 throw; | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
| @@ -141,7 +119,19 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return new TimeSpan(); | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         public TimeSpan GetRunTime(string filename) | ||||
|         { | ||||
|             var info = GetMediaInfo(filename); | ||||
| 
 | ||||
|             if (info == null) | ||||
|             { | ||||
|                 return new TimeSpan(); | ||||
|             } | ||||
| 
 | ||||
|             return info.RunTime; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user