create separate media encoding project

pull/702/head
Luke Pulverenti 10 years ago
parent ac81b4e3ca
commit 39ea2adbc5

@ -316,6 +316,7 @@ namespace MediaBrowser.Api.Playback
/// </summary> /// </summary>
/// <param name="state">The state.</param> /// <param name="state">The state.</param>
/// <param name="videoCodec">The video codec.</param> /// <param name="videoCodec">The video codec.</param>
/// <param name="isHls">if set to <c>true</c> [is HLS].</param>
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls) protected string GetVideoQualityParam(StreamState state, string videoCodec, bool isHls)
{ {
@ -340,20 +341,17 @@ namespace MediaBrowser.Api.Playback
break; break;
} }
if (!isHls) switch (qualitySetting)
{ {
switch (qualitySetting) case EncodingQuality.HighSpeed:
{ param += " -crf 23";
case EncodingQuality.HighSpeed: break;
param += " -crf 23"; case EncodingQuality.HighQuality:
break; param += " -crf 20";
case EncodingQuality.HighQuality: break;
param += " -crf 20"; case EncodingQuality.MaxQuality:
break; param += " -crf 18";
case EncodingQuality.MaxQuality: break;
param += " -crf 18";
break;
}
} }
} }
@ -1032,11 +1030,6 @@ namespace MediaBrowser.Api.Playback
{ {
var hasFixedResolution = state.VideoRequest.HasFixedResolution; var hasFixedResolution = state.VideoRequest.HasFixedResolution;
if (isHls)
{
return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
}
if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase)) if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
{ {
if (hasFixedResolution) if (hasFixedResolution)
@ -1047,7 +1040,6 @@ namespace MediaBrowser.Api.Playback
// With vpx when crf is used, b:v becomes a max rate // With vpx when crf is used, b:v becomes a max rate
// https://trac.ffmpeg.org/wiki/vpxEncodingGuide // https://trac.ffmpeg.org/wiki/vpxEncodingGuide
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
//return string.Format(" -minrate:v ({0}*.95) -maxrate:v ({0}*1.05) -bufsize:v {0} -b:v {0}", bitrate.Value.ToString(UsCulture));
} }
if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) if (string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase))
@ -1055,13 +1047,17 @@ namespace MediaBrowser.Api.Playback
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
} }
// H264 // H264
if (hasFixedResolution) if (hasFixedResolution)
{ {
if (isHls)
{
return string.Format(" -b:v {0} -maxrate ({0}*.80) -bufsize {0}", bitrate.Value.ToString(UsCulture));
}
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture)); return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
} }
return string.Format(" -maxrate {0} -bufsize {1}", return string.Format(" -maxrate {0} -bufsize {1}",
bitrate.Value.ToString(UsCulture), bitrate.Value.ToString(UsCulture),
(bitrate.Value * 2).ToString(UsCulture)); (bitrate.Value * 2).ToString(UsCulture));

@ -200,7 +200,7 @@ namespace MediaBrowser.Api.Playback.Hls
builder.AppendLine("#EXTM3U"); builder.AppendLine("#EXTM3U");
// Pad a little to satisfy the apple hls validator // Pad a little to satisfy the apple hls validator
var paddedBitrate = Convert.ToInt32(bitrate * 1.05); var paddedBitrate = Convert.ToInt32(bitrate * 1.15);
// Main stream // Main stream
builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture)); builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture));

@ -266,6 +266,11 @@ namespace MediaBrowser.Api.Playback.Progressive
return result; return result;
} }
/// <summary>
/// Gets the length of the estimated content.
/// </summary>
/// <param name="state">The state.</param>
/// <returns>System.Nullable{System.Int64}.</returns>
private long? GetEstimatedContentLength(StreamState state) private long? GetEstimatedContentLength(StreamState state)
{ {
var totalBitrate = 0; var totalBitrate = 0;

@ -24,16 +24,23 @@ namespace MediaBrowser.Controller.MediaEncoding
string Version { get; } string Version { get; }
/// <summary> /// <summary>
/// Extracts the image. /// Extracts the audio image.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken);
/// <summary>
/// Extracts the video image.
/// </summary> /// </summary>
/// <param name="inputFiles">The input files.</param> /// <param name="inputFiles">The input files.</param>
/// <param name="type">The type.</param> /// <param name="type">The type.</param>
/// <param name="isAudio">if set to <c>true</c> [is audio].</param>
/// <param name="threedFormat">The threed format.</param> /// <param name="threedFormat">The threed format.</param>
/// <param name="offset">The offset.</param> /// <param name="offset">The offset.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns> /// <returns>Task{Stream}.</returns>
Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); Task<Stream> ExtractVideoImage(string[] inputFiles, InputType type, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Extracts the text subtitle. /// Extracts the text subtitle.

@ -197,7 +197,7 @@ namespace MediaBrowser.Dlna
throw new ArgumentNullException("headers"); throw new ArgumentNullException("headers");
} }
return GetProfiles().FirstOrDefault(i => IsMatch(headers, i.Identification)); return GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification));
} }
private bool IsMatch(IDictionary<string, string> headers, DeviceIdentification profileInfo) private bool IsMatch(IDictionary<string, string> headers, DeviceIdentification profileInfo)

@ -631,7 +631,7 @@ namespace MediaBrowser.Dlna.PlayTo
RendererCommands = TransportCommands.Create(document); RendererCommands = TransportCommands.Create(document);
} }
internal TransportCommands AvCommands private TransportCommands AvCommands
{ {
get; get;
set; set;

@ -57,24 +57,6 @@ namespace MediaBrowser.Dlna.Profiles
Type = DlnaProfileType.Video Type = DlnaProfileType.Video
} }
}; };
CodecProfiles = new[]
{
new CodecProfile
{
Type = CodecType.VideoCodec,
Conditions = new []
{
new ProfileCondition
{
Condition = ProfileConditionType.LessThanEqual,
Property = ProfileConditionValue.VideoLevel,
Value = "3",
IsRequired = false
}
}
}
};
} }
} }
} }

@ -229,13 +229,6 @@ namespace MediaBrowser.Dlna.Profiles
Property = ProfileConditionValue.VideoBitrate, Property = ProfileConditionValue.VideoBitrate,
Value = "10240000", Value = "10240000",
IsRequired = false IsRequired = false
},
new ProfileCondition
{
Condition = ProfileConditionType.LessThanEqual,
Property = ProfileConditionValue.VideoLevel,
Value = "3",
IsRequired = false
} }
} }
}, },
@ -271,13 +264,6 @@ namespace MediaBrowser.Dlna.Profiles
Property = ProfileConditionValue.VideoBitrate, Property = ProfileConditionValue.VideoBitrate,
Value = "15360000", Value = "15360000",
IsRequired = false IsRequired = false
},
new ProfileCondition
{
Condition = ProfileConditionType.LessThanEqual,
Property = ProfileConditionValue.VideoLevel,
Value = "3",
IsRequired = false
} }
} }
}, },

@ -30,12 +30,5 @@
</TranscodingProfile> </TranscodingProfile>
</TranscodingProfiles> </TranscodingProfiles>
<ContainerProfiles /> <ContainerProfiles />
<CodecProfiles>
<CodecProfile type="VideoCodec">
<Conditions>
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions>
</CodecProfile>
</CodecProfiles>
<MediaProfiles /> <MediaProfiles />
</Profile> </Profile>

@ -34,12 +34,5 @@
</TranscodingProfile> </TranscodingProfile>
</TranscodingProfiles> </TranscodingProfiles>
<ContainerProfiles /> <ContainerProfiles />
<CodecProfiles>
<CodecProfile type="VideoCodec">
<Conditions>
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions>
</CodecProfile>
</CodecProfiles>
<MediaProfiles /> <MediaProfiles />
</Profile> </Profile>

@ -34,12 +34,5 @@
</TranscodingProfile> </TranscodingProfile>
</TranscodingProfiles> </TranscodingProfiles>
<ContainerProfiles /> <ContainerProfiles />
<CodecProfiles>
<CodecProfile type="VideoCodec">
<Conditions>
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions>
</CodecProfile>
</CodecProfiles>
<MediaProfiles /> <MediaProfiles />
</Profile> </Profile>

@ -73,7 +73,6 @@
<ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" /> <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="false" /> <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="false" />
<ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="10240000" isRequired="false" /> <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="10240000" isRequired="false" />
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions> </Conditions>
</CodecProfile> </CodecProfile>
<CodecProfile type="VideoCodec" codec="wmv2,wmv3,vc1"> <CodecProfile type="VideoCodec" codec="wmv2,wmv3,vc1">
@ -82,7 +81,6 @@
<ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" /> <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
<ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="false" /> <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="false" />
<ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="15360000" isRequired="false" /> <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="15360000" isRequired="false" />
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions> </Conditions>
</CodecProfile> </CodecProfile>
<CodecProfile type="VideoAudioCodec" codec="ac3,wmav2,wmapro"> <CodecProfile type="VideoAudioCodec" codec="ac3,wmav2,wmapro">

@ -32,13 +32,6 @@
</TranscodingProfile> </TranscodingProfile>
</TranscodingProfiles> </TranscodingProfiles>
<ContainerProfiles /> <ContainerProfiles />
<CodecProfiles>
<CodecProfile type="VideoCodec">
<Conditions>
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions>
</CodecProfile>
</CodecProfiles>
<MediaProfiles> <MediaProfiles>
<MediaProfile container="avi" type="Video" mimeType="video/x-msvideo"> <MediaProfile container="avi" type="Video" mimeType="video/x-msvideo">
<Conditions /> <Conditions />

@ -36,12 +36,5 @@
</TranscodingProfile> </TranscodingProfile>
</TranscodingProfiles> </TranscodingProfiles>
<ContainerProfiles /> <ContainerProfiles />
<CodecProfiles>
<CodecProfile type="VideoCodec">
<Conditions>
<ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="false" />
</Conditions>
</CodecProfile>
</CodecProfiles>
<MediaProfiles /> <MediaProfiles />
</Profile> </Profile>

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace MediaBrowser.Server.Implementations.BdInfo namespace MediaBrowser.MediaEncoding.BdInfo
{ {
/// <summary> /// <summary>
/// Class BdInfoExaminer /// Class BdInfoExaminer

@ -6,17 +6,15 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.MediaEncoder namespace MediaBrowser.MediaEncoding.Encoder
{ {
/// <summary> /// <summary>
/// Class MediaEncoder /// Class MediaEncoder
@ -53,6 +51,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// The FF probe resource pool /// The FF probe resource pool
/// </summary> /// </summary>
private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(2, 2); private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(2, 2);
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
public string FFMpegPath { get; private set; } public string FFMpegPath { get; private set; }
@ -62,7 +61,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
public string Version { get; private set; } public string Version { get; private set; }
public MediaEncoder(ILogger logger, IApplicationPaths appPaths, public MediaEncoder(ILogger logger, IApplicationPaths appPaths,
IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version, IFileSystem fileSystem) IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version,
IFileSystem fileSystem)
{ {
_logger = logger; _logger = logger;
_appPaths = appPaths; _appPaths = appPaths;
@ -85,7 +85,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <summary> /// <summary>
/// The _semaphoreLocks /// The _semaphoreLocks
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreLocks = new ConcurrentDictionary<string, SemaphoreSlim>(); private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreLocks =
new ConcurrentDictionary<string, SemaphoreSlim>();
/// <summary> /// <summary>
/// Gets the lock. /// Gets the lock.
@ -106,10 +107,10 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, InputType type, bool isAudio, public Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, InputType type, bool isAudio,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
return GetMediaInfoInternal(GetInputArgument(inputFiles, type), !isAudio, return GetMediaInfoInternal(GetInputArgument(inputFiles, type), !isAudio,
GetProbeSizeArgument(type), cancellationToken); GetProbeSizeArgument(type), cancellationToken);
} }
/// <summary> /// <summary>
@ -172,8 +173,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <returns>Task{MediaInfoResult}.</returns> /// <returns>Task{MediaInfoResult}.</returns>
/// <exception cref="System.ApplicationException"></exception> /// <exception cref="System.ApplicationException"></exception>
private async Task<InternalMediaInfoResult> GetMediaInfoInternal(string inputPath, bool extractChapters, private async Task<InternalMediaInfoResult> GetMediaInfoInternal(string inputPath, bool extractChapters,
string probeSizeArgument, string probeSizeArgument,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var args = extractChapters var args = extractChapters
? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format" ? "{0} -i {1} -threads 0 -v info -print_format json -show_streams -show_chapters -show_format"
@ -191,7 +192,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
RedirectStandardError = true, RedirectStandardError = true,
FileName = FFProbePath, FileName = FFProbePath,
Arguments = string.Format(args, Arguments = string.Format(args,
probeSizeArgument, inputPath).Trim(), probeSizeArgument, inputPath).Trim(),
WindowStyle = ProcessWindowStyle.Hidden, WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false ErrorDialog = false
@ -225,7 +226,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{ {
process.BeginErrorReadLine(); process.BeginErrorReadLine();
result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream); result =
_jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
} }
catch catch
{ {
@ -295,7 +297,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <param name="language">The language.</param> /// <param name="language">The language.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language, CancellationToken cancellationToken) public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language,
CancellationToken cancellationToken)
{ {
var semaphore = GetLock(outputPath); var semaphore = GetLock(outputPath);
@ -340,33 +343,35 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
} }
var encodingParam = string.IsNullOrEmpty(language) ? string.Empty : var encodingParam = string.IsNullOrEmpty(language)
GetSubtitleLanguageEncodingParam(language) + " "; ? string.Empty
: GetSubtitleLanguageEncodingParam(language) + " ";
var process = new Process var process = new Process
{
StartInfo = new ProcessStartInfo
{ {
StartInfo = new ProcessStartInfo RedirectStandardOutput = false,
{ RedirectStandardError = true,
RedirectStandardOutput = false,
RedirectStandardError = true, CreateNoWindow = true,
UseShellExecute = false,
CreateNoWindow = true, FileName = FFMpegPath,
UseShellExecute = false, Arguments =
FileName = FFMpegPath, string.Format("{0} -i \"{1}\" -c:s ass \"{2}\"", encodingParam, inputPath, outputPath),
Arguments =
string.Format("{0} -i \"{1}\" -c:s ass \"{2}\"", encodingParam, inputPath, outputPath), WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false
WindowStyle = ProcessWindowStyle.Hidden, }
ErrorDialog = false };
}
};
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt"); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt");
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read,
true);
try try
{ {
@ -525,7 +530,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
/// <exception cref="System.ArgumentException">Must use inputPath list overload</exception> /// <exception cref="System.ArgumentException">Must use inputPath list overload</exception>
public async Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex, bool copySubtitleStream, string outputPath, CancellationToken cancellationToken) public async Task ExtractTextSubtitle(string[] inputFiles, InputType type, int subtitleStreamIndex,
bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
{ {
var semaphore = GetLock(outputPath); var semaphore = GetLock(outputPath);
@ -535,7 +541,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{ {
if (!File.Exists(outputPath)) if (!File.Exists(outputPath))
{ {
await ExtractTextSubtitleInternal(GetInputArgument(inputFiles, type), subtitleStreamIndex, copySubtitleStream, outputPath, cancellationToken).ConfigureAwait(false); await
ExtractTextSubtitleInternal(GetInputArgument(inputFiles, type), subtitleStreamIndex,
copySubtitleStream, outputPath, cancellationToken).ConfigureAwait(false);
} }
} }
finally finally
@ -559,7 +567,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// or /// or
/// cancellationToken</exception> /// cancellationToken</exception>
/// <exception cref="System.ApplicationException"></exception> /// <exception cref="System.ApplicationException"></exception>
private async Task ExtractTextSubtitleInternal(string inputPath, int subtitleStreamIndex, bool copySubtitleStream, string outputPath, CancellationToken cancellationToken) private async Task ExtractTextSubtitleInternal(string inputPath, int subtitleStreamIndex,
bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
{ {
if (string.IsNullOrEmpty(inputPath)) if (string.IsNullOrEmpty(inputPath))
{ {
@ -571,11 +580,13 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
throw new ArgumentNullException("outputPath"); throw new ArgumentNullException("outputPath");
} }
string processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s ass \"{2}\"", inputPath, subtitleStreamIndex, outputPath); string processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s ass \"{2}\"", inputPath,
subtitleStreamIndex, outputPath);
if (copySubtitleStream) if (copySubtitleStream)
{ {
processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s copy \"{2}\"", inputPath, subtitleStreamIndex, outputPath); processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s copy \"{2}\"", inputPath,
subtitleStreamIndex, outputPath);
} }
var process = new Process var process = new Process
@ -600,7 +611,8 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-extract-" + Guid.NewGuid() + ".txt"); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-extract-" + Guid.NewGuid() + ".txt");
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read,
true);
try try
{ {
@ -715,7 +727,18 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
} }
} }
public async Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio, public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
{
return ExtractImage(new[] { path }, InputType.File, true, null, null, cancellationToken);
}
public Task<Stream> ExtractVideoImage(string[] inputFiles, InputType type, Video3DFormat? threedFormat,
TimeSpan? offset, CancellationToken cancellationToken)
{
return ExtractImage(inputFiles, type, false, threedFormat, offset, cancellationToken);
}
private async Task<Stream> ExtractImage(string[] inputFiles, InputType type, bool isAudio,
Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
{ {
var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool; var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool;
@ -773,7 +796,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
} }
// Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case.
var args = useIFrame ? string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2},thumbnail\" -f image2 \"{1}\"", inputPath, "-", vf) : var args = useIFrame ? string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2},thumbnail=80\" -f image2 \"{1}\"", inputPath, "-", vf) :
string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf); string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf);
var probeSize = GetProbeSizeArgument(type); var probeSize = GetProbeSizeArgument(type);
@ -834,7 +857,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
_logger.ErrorException("Error killing process", ex); _logger.ErrorException("Error killing process", ex);
} }
} }
resourcePool.Release(); resourcePool.Release();
var exitCode = ranToCompletion ? process.ExitCode : -1; var exitCode = ranToCompletion ? process.ExitCode : -1;

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.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>{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MediaBrowser.MediaEncoding</RootNamespace>
<AssemblyName>MediaBrowser.MediaEncoding</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</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="BDInfo">
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\BDInfo.dll</HintPath>
</Reference>
<Reference Include="DvdLib">
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
</Reference>
<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="BdInfo\BdInfoExaminer.cs" />
<Compile Include="Encoder\MediaEncoder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
<Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project>
<Name>MediaBrowser.Common</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
<Name>MediaBrowser.Controller</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.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>

@ -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.MediaEncoding")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MediaBrowser.MediaEncoding")]
[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("05f49ab9-2a90-4332-9d41-7817a9cccd90")]
// 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")]

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
</packages>

@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.MediaInfo
{ {
Directory.CreateDirectory(Path.GetDirectoryName(path)); Directory.CreateDirectory(Path.GetDirectoryName(path));
using (var stream = await _mediaEncoder.ExtractImage(new[] { item.Path }, InputType.File, true, null, null, cancellationToken).ConfigureAwait(false)) using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, cancellationToken).ConfigureAwait(false))
{ {
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{ {

@ -113,8 +113,6 @@ namespace MediaBrowser.Providers.MediaInfo
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
cancellationToken.ThrowIfCancellationRequested();
var idString = item.Id.ToString("N"); var idString = item.Id.ToString("N");
var cachePath = Path.Combine(_appPaths.CachePath, var cachePath = Path.Combine(_appPaths.CachePath,
"ffprobe-video", "ffprobe-video",

@ -93,7 +93,7 @@ namespace MediaBrowser.Providers.MediaInfo
var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, item.LocationType == LocationType.Remote, item.VideoType, item.IsoType, isoMount, item.PlayableStreamFileNames, out type); var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, item.LocationType == LocationType.Remote, item.VideoType, item.IsoType, isoMount, item.PlayableStreamFileNames, out type);
var stream = await _mediaEncoder.ExtractImage(inputPath, type, false, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); var stream = await _mediaEncoder.ExtractVideoImage(inputPath, type, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
return new DynamicImageResponse return new DynamicImageResponse
{ {

@ -249,17 +249,24 @@ namespace MediaBrowser.Server.Implementations.IO
// Creating a FileSystemWatcher over the LAN can take hundreds of milliseconds, so wrap it in a Task to do them all in parallel // Creating a FileSystemWatcher over the LAN can take hundreds of milliseconds, so wrap it in a Task to do them all in parallel
Task.Run(() => Task.Run(() =>
{ {
var newWatcher = new FileSystemWatcher(path, "*") { IncludeSubdirectories = true, InternalBufferSize = 32767 }; try
{
var newWatcher = new FileSystemWatcher(path, "*")
{
IncludeSubdirectories = true,
InternalBufferSize = 32767
};
newWatcher.Created += watcher_Changed; newWatcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.DirectoryName |
newWatcher.Deleted += watcher_Changed; NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size;
newWatcher.Renamed += watcher_Changed;
newWatcher.Changed += watcher_Changed;
newWatcher.Error += watcher_Error; newWatcher.Created += watcher_Changed;
newWatcher.Deleted += watcher_Changed;
newWatcher.Renamed += watcher_Changed;
newWatcher.Changed += watcher_Changed;
newWatcher.Error += watcher_Error;
try
{
if (_fileSystemWatchers.TryAdd(path, newWatcher)) if (_fileSystemWatchers.TryAdd(path, newWatcher))
{ {
newWatcher.EnableRaisingEvents = true; newWatcher.EnableRaisingEvents = true;
@ -272,11 +279,7 @@ namespace MediaBrowser.Server.Implementations.IO
} }
} }
catch (IOException ex) catch (Exception ex)
{
Logger.ErrorException("Error watching path: {0}", ex, path);
}
catch (PlatformNotSupportedException ex)
{ {
Logger.ErrorException("Error watching path: {0}", ex, path); Logger.ErrorException("Error watching path: {0}", ex, path);
} }
@ -346,7 +349,9 @@ namespace MediaBrowser.Server.Implementations.IO
{ {
try try
{ {
OnWatcherChanged(e); Logger.Debug("Watcher sees change of type " + e.ChangeType + " to " + e.FullPath);
ReportFileSystemChanged(e.FullPath);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -354,13 +359,6 @@ namespace MediaBrowser.Server.Implementations.IO
} }
} }
private void OnWatcherChanged(FileSystemEventArgs e)
{
Logger.Debug("Watcher sees change of type " + e.ChangeType + " to " + e.FullPath);
ReportFileSystemChanged(e.FullPath);
}
public void ReportFileSystemChanged(string path) public void ReportFileSystemChanged(string path)
{ {
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
@ -370,12 +368,9 @@ namespace MediaBrowser.Server.Implementations.IO
var filename = Path.GetFileName(path); var filename = Path.GetFileName(path);
// Ignore certain files var monitorPath = !(!string.IsNullOrEmpty(filename) && _alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase));
if (!string.IsNullOrEmpty(filename) && _alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase))
{
return;
}
// Ignore certain files
var tempIgnorePaths = _tempIgnoredPaths.Keys.ToList(); var tempIgnorePaths = _tempIgnoredPaths.Keys.ToList();
// If the parent of an ignored path has a change event, ignore that too // If the parent of an ignored path has a change event, ignore that too
@ -416,12 +411,15 @@ namespace MediaBrowser.Server.Implementations.IO
})) }))
{ {
return; monitorPath = false;
} }
// Avoid implicitly captured closure if (monitorPath)
var affectedPath = path; {
_affectedPaths.AddOrUpdate(path, path, (key, oldValue) => affectedPath); // Avoid implicitly captured closure
var affectedPath = path;
_affectedPaths.AddOrUpdate(path, path, (key, oldValue) => affectedPath);
}
lock (_timerLock) lock (_timerLock)
{ {

@ -48,14 +48,6 @@
<Reference Include="Alchemy"> <Reference Include="Alchemy">
<HintPath>..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll</HintPath> <HintPath>..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll</HintPath>
</Reference> </Reference>
<Reference Include="BDInfo, Version=1.0.5167.21152, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\BDInfo.dll</HintPath>
</Reference>
<Reference Include="DvdLib, Version=1.0.5167.21152, Culture=neutral, PublicKeyToken=7a2f3f5ec8d93575, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
</Reference>
<Reference Include="Mono.Nat, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Mono.Nat, Version=1.2.3.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Mono.Nat.1.2.3\lib\Net40\Mono.Nat.dll</HintPath> <HintPath>..\packages\Mono.Nat.1.2.3\lib\Net40\Mono.Nat.dll</HintPath>
@ -105,7 +97,6 @@
<Compile Include="..\SharedVersion.cs"> <Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link> <Link>Properties\SharedVersion.cs</Link>
</Compile> </Compile>
<Compile Include="BdInfo\BdInfoExaminer.cs" />
<Compile Include="Channels\ChannelImageProvider.cs" /> <Compile Include="Channels\ChannelImageProvider.cs" />
<Compile Include="Channels\ChannelItemImageProvider.cs" /> <Compile Include="Channels\ChannelItemImageProvider.cs" />
<Compile Include="Channels\ChannelManager.cs" /> <Compile Include="Channels\ChannelManager.cs" />
@ -191,7 +182,6 @@
<Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" /> <Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" />
<Compile Include="Localization\LocalizationManager.cs" /> <Compile Include="Localization\LocalizationManager.cs" />
<Compile Include="MediaEncoder\EncodingManager.cs" /> <Compile Include="MediaEncoder\EncodingManager.cs" />
<Compile Include="MediaEncoder\MediaEncoder.cs" />
<Compile Include="News\NewsEntryPoint.cs" /> <Compile Include="News\NewsEntryPoint.cs" />
<Compile Include="News\NewsService.cs" /> <Compile Include="News\NewsService.cs" />
<Compile Include="Persistence\SqliteChapterRepository.cs" /> <Compile Include="Persistence\SqliteChapterRepository.cs" />

@ -178,7 +178,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
{ {
Directory.CreateDirectory(Path.GetDirectoryName(path)); Directory.CreateDirectory(Path.GetDirectoryName(path));
using (var stream = await _encoder.ExtractImage(inputPath, type, false, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false)) using (var stream = await _encoder.ExtractVideoImage(inputPath, type, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false))
{ {
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true)) using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{ {

@ -37,6 +37,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
var createTableCommand var createTableCommand
= "create table if not exists mediastreams "; = "create table if not exists mediastreams ";
// Add PixelFormat column
createTableCommand += "(ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PRIMARY KEY (ItemId, StreamIndex))"; createTableCommand += "(ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PRIMARY KEY (ItemId, StreamIndex))";
string[] queries = { string[] queries = {

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Alchemy" version="2.2.1" targetFramework="net45" /> <package id="Alchemy" version="2.2.1" targetFramework="net45" />
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.3" targetFramework="net45" /> <package id="Mono.Nat" version="1.2.3" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" /> <package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="System.Data.SQLite.Core" version="1.0.91.3" targetFramework="net45" /> <package id="System.Data.SQLite.Core" version="1.0.91.3" targetFramework="net45" />

@ -33,13 +33,14 @@ using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Themes; using MediaBrowser.Controller.Themes;
using MediaBrowser.Dlna; using MediaBrowser.Dlna;
using MediaBrowser.Dlna.PlayTo; using MediaBrowser.Dlna.PlayTo;
using MediaBrowser.MediaEncoding.BdInfo;
using MediaBrowser.MediaEncoding.Encoder;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using MediaBrowser.Model.Updates; using MediaBrowser.Model.Updates;
using MediaBrowser.Providers.Manager; using MediaBrowser.Providers.Manager;
using MediaBrowser.Server.Implementations; using MediaBrowser.Server.Implementations;
using MediaBrowser.Server.Implementations.BdInfo;
using MediaBrowser.Server.Implementations.Channels; using MediaBrowser.Server.Implementations.Channels;
using MediaBrowser.Server.Implementations.Collections; using MediaBrowser.Server.Implementations.Collections;
using MediaBrowser.Server.Implementations.Configuration; using MediaBrowser.Server.Implementations.Configuration;
@ -815,7 +816,10 @@ namespace MediaBrowser.ServerApplication
// Server implementations // Server implementations
list.Add(typeof(ServerApplicationPaths).Assembly); list.Add(typeof(ServerApplicationPaths).Assembly);
// Dlna implementations // MediaEncoding
list.Add(typeof(MediaEncoder).Assembly);
// Dlna
list.Add(typeof(PlayToServerEntryPoint).Assembly); list.Add(typeof(PlayToServerEntryPoint).Assembly);
list.AddRange(Assemblies.GetAssembliesWithParts()); list.AddRange(Assemblies.GetAssembliesWithParts());

@ -195,6 +195,10 @@
<Project>{734098eb-6dc1-4dd0-a1ca-3140dcd2737c}</Project> <Project>{734098eb-6dc1-4dd0-a1ca-3140dcd2737c}</Project>
<Name>MediaBrowser.Dlna</Name> <Name>MediaBrowser.Dlna</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj">
<Project>{0bd82fa6-eb8a-4452-8af5-74f9c3849451}</Project>
<Name>MediaBrowser.MediaEncoding</Name>
</ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj"> <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project> <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name> <Name>MediaBrowser.Model</Name>

@ -41,6 +41,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ServerApplicat
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaBrowser.Dlna\MediaBrowser.Dlna.csproj", "{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaBrowser.Dlna\MediaBrowser.Dlna.csproj", "{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -247,6 +249,20 @@ Global
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Win32.ActiveCfg = Release|Any CPU {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Win32.ActiveCfg = Release|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x64.ActiveCfg = Release|Any CPU {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x64.ActiveCfg = Release|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.ActiveCfg = Release|Any CPU {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.ActiveCfg = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Win32.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x64.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.Build.0 = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Win32.ActiveCfg = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x64.ActiveCfg = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

Loading…
Cancel
Save