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:
Mark McDowall 2013-11-21 08:13:40 -08:00 committed by Mark McDowall
parent 02c68bd387
commit 4f0cefa431
8 changed files with 84 additions and 79 deletions

View File

@ -3,6 +3,7 @@ $outputFolder = '.\_output'
$outputFolderMono = '.\_output_mono' $outputFolderMono = '.\_output_mono'
$testPackageFolder = '.\_tests\' $testPackageFolder = '.\_tests\'
$testSearchPattern = '*.Test\bin\x86\Release' $testSearchPattern = '*.Test\bin\x86\Release'
$sourceFolder = '.\src'
Function Build() Function Build()
{ {
@ -84,6 +85,9 @@ Function PackageMono()
get-childitem $outputFolderMono -File -Filter sqlite3.* -Recurse | foreach ($_) {remove-item $_.fullname} get-childitem $outputFolderMono -File -Filter sqlite3.* -Recurse | foreach ($_) {remove-item $_.fullname}
get-childitem $outputFolderMono -File -Filter MediaInfo.* -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 Write-Host Renaming NzbDrone.Console.exe to NzbDrone.exe
get-childitem $outputFolderMono -File -Filter NzbDrone.exe -Recurse | foreach ($_) {remove-item $_.fullname} get-childitem $outputFolderMono -File -Filter NzbDrone.exe -Recurse | foreach ($_) {remove-item $_.fullname}
Rename-Item "$outputFolderMono\NzbDrone.Console.exe" "NzbDrone.exe" Rename-Item "$outputFolderMono\NzbDrone.Console.exe" "NzbDrone.exe"
@ -103,7 +107,7 @@ Function PackageTests()
{ {
Write-Host Packaging Tests Write-Host Packaging Tests
Write-Host "##teamcity[progressStart 'Creating Mono Package']" Write-Host "##teamcity[progressStart 'Creating Test Package']"
if(Test-Path $testPackageFolder) if(Test-Path $testPackageFolder)
{ {
@ -117,8 +121,8 @@ Function PackageTests()
.\src\.nuget\NuGet.exe install NUnit.Runners -Version 2.6.1 -Output $testPackageFolder .\src\.nuget\NuGet.exe install NUnit.Runners -Version 2.6.1 -Output $testPackageFolder
Copy-Item $outputFolder\*.dll -Destination $testPackageFolder -Force Copy-Item $outputFolder\*.dll -Destination $testPackageFolder -Force
Copy-Item $outputFolder\*.pdb -Destination $testPackageFolder -Force Copy-Item $outputFolder\*.pdb -Destination $testPackageFolder -Force
Copy-Item .\*.sh -Destination $testPackageFolder -Force Copy-Item .\*.sh -Destination $testPackageFolder -Force
@ -126,7 +130,10 @@ Function PackageTests()
CleanFolder $testPackageFolder 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
View File

@ -8,5 +8,5 @@ Vcs-Browser: https://github.com/NzbDrone/NzbDrone
Package: nzbdrone Package: nzbdrone
Architecture: all 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 Description: NZBDrone is a PVR for newsgroup users

View 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>

View File

@ -85,21 +85,8 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
} }
[Test] [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); GivenRuntime(120);
GivenFileSize(1000.Megabytes()); GivenFileSize(1000.Megabytes());
@ -111,7 +98,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
[Test] [Test]
public void should_return_false_if_runtime_is_less_than_minimum() public void should_return_false_if_runtime_is_less_than_minimum()
{ {
WindowsOnly();
GivenRuntime(60); GivenRuntime(60);
Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse(); Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse();
@ -120,32 +106,30 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
[Test] [Test]
public void should_return_true_if_runtime_greater_than_than_minimum() public void should_return_true_if_runtime_greater_than_than_minimum()
{ {
WindowsOnly();
GivenRuntime(120); GivenRuntime(120);
Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue(); Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue();
} }
[Test] [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(1000.Megabytes());
GivenFileSize(20.Megabytes()); Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue();
Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse();
} }
[Test] [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(); Mocker.GetMock<IVideoFileInfoReader>()
.Setup(s => s.GetRunTime(It.IsAny<String>()))
GivenRuntime(120); .Throws<DllNotFoundException>();
GivenFileSize(120.Megabytes());
_localEpisode.Quality = new QualityModel(Quality.Bluray1080p);
GivenFileSize(1.Megabytes());
Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse(); Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse();
} }
} }

View File

@ -1,6 +1,8 @@
using System.IO; using System.IO;
using FluentAssertions; using FluentAssertions;
using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.MediaFiles.MediaInfo; using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.Categories; using NzbDrone.Test.Common.Categories;
@ -11,6 +13,14 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
[DiskAccessTest] [DiskAccessTest]
public class VideoFileInfoReaderFixture : CoreTest<VideoFileInfoReader> public class VideoFileInfoReaderFixture : CoreTest<VideoFileInfoReader>
{ {
[SetUp]
public void Setup()
{
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.FileExists(It.IsAny<string>()))
.Returns(true);
}
[Test] [Test]
public void get_runtime() public void get_runtime()
{ {

View File

@ -61,7 +61,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
return true; return true;
} }
if (OsInfo.IsWindows) try
{ {
var runTime = _videoFileInfoReader.GetRunTime(localEpisode.Path); 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); _logger.Trace("[{0}] appears to be a sample. Size: {1} Runtime: {2}", localEpisode.Path, localEpisode.Size, runTime);
return false; 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) private bool CheckSize(LocalEpisode localEpisode)
@ -90,12 +95,14 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
{ {
if (localEpisode.Size < SampleSizeLimit * 2) if (localEpisode.Size < SampleSizeLimit * 2)
{ {
_logger.Trace("1080p file is less than sample limit");
return false; return false;
} }
} }
if (localEpisode.Size < SampleSizeLimit) if (localEpisode.Size < SampleSizeLimit)
{ {
_logger.Trace("File is less than sample limit");
return false; return false;
} }

View File

@ -1,4 +1,6 @@
namespace NzbDrone.Core.MediaFiles.MediaInfo using System;
namespace NzbDrone.Core.MediaFiles.MediaInfo
{ {
public class MediaInfoModel public class MediaInfoModel
{ {
@ -8,7 +10,7 @@
public int Height { get; set; } public int Height { get; set; }
public string AudioFormat { get; set; } public string AudioFormat { get; set; }
public int AudioBitrate { get; set; } public int AudioBitrate { get; set; }
public int RunTime { get; set; } public TimeSpan RunTime { get; set; }
public int AudioStreamCount { get; set; } public int AudioStreamCount { get; set; }
public int AudioChannels { get; set; } public int AudioChannels { get; set; }
public string AudioProfile { get; set; } public string AudioProfile { get; set; }

View File

@ -30,10 +30,11 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
if (!_diskProvider.FileExists(filename)) if (!_diskProvider.FileExists(filename))
throw new FileNotFoundException("Media file does not exist: " + filename); throw new FileNotFoundException("Media file does not exist: " + filename);
var mediaInfo = new MediaInfoLib.MediaInfo(); MediaInfoLib.MediaInfo mediaInfo = null;
try try
{ {
mediaInfo = new MediaInfoLib.MediaInfo();
_logger.Trace("Getting media info from {0}", filename); _logger.Trace("Getting media info from {0}", filename);
mediaInfo.Option("ParseSpeed", "0.2"); mediaInfo.Option("ParseSpeed", "0.2");
@ -56,26 +57,26 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
Int32.TryParse(mediaInfo.Get(StreamKind.Video, 0, "BitRate"), out videoBitRate); Int32.TryParse(mediaInfo.Get(StreamKind.Video, 0, "BitRate"), out videoBitRate);
string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate"); string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate");
int ABindex = aBitRate.IndexOf(" /"); int aBindex = aBitRate.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase);
if (ABindex > 0) if (aBindex > 0)
aBitRate = aBitRate.Remove(ABindex); aBitRate = aBitRate.Remove(aBindex);
Int32.TryParse(aBitRate, out audioBitRate); Int32.TryParse(aBitRate, out audioBitRate);
Int32.TryParse(mediaInfo.Get(StreamKind.Video, 0, "PlayTime"), out runTime); Int32.TryParse(mediaInfo.Get(StreamKind.Video, 0, "PlayTime"), out runTime);
Int32.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "StreamCount"), out streamCount); Int32.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "StreamCount"), out streamCount);
string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)"); string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)");
int ACindex = audioChannelsStr.IndexOf(" /"); int aCindex = audioChannelsStr.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase);
if (ACindex > 0) if (aCindex > 0)
audioChannelsStr = audioChannelsStr.Remove(ACindex); audioChannelsStr = audioChannelsStr.Remove(aCindex);
string audioLanguages = mediaInfo.Get(StreamKind.General, 0, "Audio_Language_List"); string audioLanguages = mediaInfo.Get(StreamKind.General, 0, "Audio_Language_List");
decimal videoFrameRate = Decimal.Parse(mediaInfo.Get(StreamKind.Video, 0, "FrameRate")); decimal videoFrameRate = Decimal.Parse(mediaInfo.Get(StreamKind.Video, 0, "FrameRate"));
string audioProfile = mediaInfo.Get(StreamKind.Audio, 0, "Format_Profile"); string audioProfile = mediaInfo.Get(StreamKind.Audio, 0, "Format_Profile");
int APindex = audioProfile.IndexOf(" /"); int aPindex = audioProfile.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase);
if (APindex > 0) if (aPindex > 0)
audioProfile = audioProfile.Remove(APindex); audioProfile = audioProfile.Remove(aPindex);
Int32.TryParse(audioChannelsStr, out audioChannels); Int32.TryParse(audioChannelsStr, out audioChannels);
var mediaInfoModel = new MediaInfoModel var mediaInfoModel = new MediaInfoModel
@ -84,9 +85,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
VideoBitrate = videoBitRate, VideoBitrate = videoBitRate,
Height = height, Height = height,
Width = width, Width = width,
AudioFormat = mediaInfo.Get(StreamKind.Audio, 0, "Format"), AudioFormat = mediaInfo.Get(StreamKind.Audio, 0, "Format"),
AudioBitrate = audioBitRate, AudioBitrate = audioBitRate,
RunTime = (runTime / 1000), //InSeconds RunTime = TimeSpan.FromMilliseconds(runTime),
AudioStreamCount = streamCount, AudioStreamCount = streamCount,
AudioChannels = audioChannels, AudioChannels = audioChannels,
AudioProfile = audioProfile.Trim(), AudioProfile = audioProfile.Trim(),
@ -100,34 +102,10 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return mediaInfoModel; return mediaInfoModel;
} }
} }
catch (Exception ex) catch (DllNotFoundException ex)
{ {
_logger.ErrorException("Unable to parse media info from file: " + filename, ex); _logger.ErrorException("mediainfo is required but was not found", ex);
mediaInfo.Close(); throw;
}
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);
}
} }
catch (Exception ex) 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;
} }
} }
} }