moved media streams to the database

pull/702/head
Luke Pulverenti 11 years ago
parent ebe483db9a
commit 5f0d8000a5

@ -370,44 +370,6 @@ namespace MediaBrowser.Api
UniqueTypes = items.Select(i => i.GetClientTypeName()).Distinct().ToList()
};
var people = items.SelectMany(i => i.People)
.Select(i => i.Name)
.Distinct(StringComparer.OrdinalIgnoreCase)
.Select(i =>
{
try
{
return _libraryManager.GetPerson(i);
}
catch
{
return null;
}
})
.Where(i => i != null)
.ToList();
people = request.UserId.HasValue ? FilterItems(people, request, request.UserId.Value).ToList() : people;
counts.PersonCount = people.Count;
var artists = _libraryManager.GetAllArtists(items)
.Select(i =>
{
try
{
return _libraryManager.GetArtist(i);
}
catch
{
return null;
}
})
.Where(i => i != null)
.ToList();
artists = request.UserId.HasValue ? FilterItems(artists, request, request.UserId.Value).ToList() : artists;
counts.ArtistCount = artists.Count;
return ToOptimizedResult(counts);
}

@ -7,6 +7,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaInfo;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@ -59,7 +60,9 @@ namespace MediaBrowser.Api.Playback
protected IDtoService DtoService { get; private set; }
protected IFileSystem FileSystem { get; private set; }
protected IItemRepository ItemRepository { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
/// </summary>
@ -68,8 +71,9 @@ namespace MediaBrowser.Api.Playback
/// <param name="libraryManager">The library manager.</param>
/// <param name="isoManager">The iso manager.</param>
/// <param name="mediaEncoder">The media encoder.</param>
protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem)
protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository)
{
ItemRepository = itemRepository;
FileSystem = fileSystem;
DtoService = dtoService;
ApplicationPaths = appPaths;
@ -803,6 +807,12 @@ namespace MediaBrowser.Api.Playback
var videoRequest = request as VideoStreamRequest;
var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery
{
ItemId = item.Id
}).ToList();
if (videoRequest != null)
{
if (!videoRequest.VideoCodec.HasValue)
@ -810,13 +820,13 @@ namespace MediaBrowser.Api.Playback
videoRequest.VideoCodec = InferVideoCodec(url);
}
state.VideoStream = GetMediaStream(media.MediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
state.SubtitleStream = GetMediaStream(media.MediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
state.AudioStream = GetMediaStream(media.MediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);
state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video);
state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false);
state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio);
}
else
{
state.AudioStream = GetMediaStream(media.MediaStreams, null, MediaStreamType.Audio, true);
state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
}
return state;

@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO;
using ServiceStack.ServiceHost;
@ -25,16 +26,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary>
public class AudioHlsService : BaseHlsService
{
/// <summary>
/// Initializes a new instance of the <see cref="AudioHlsService" /> class.
/// </summary>
/// <param name="appPaths">The app paths.</param>
/// <param name="userManager">The user manager.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="isoManager">The iso manager.</param>
/// <param name="mediaEncoder">The media encoder.</param>
public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem)
: base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem)
public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository)
: base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository)
{
}

@ -6,6 +6,7 @@ using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO;
using System;
@ -21,6 +22,11 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary>
public abstract class BaseHlsService : BaseStreamingService
{
protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository)
: base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository)
{
}
protected override string GetOutputFilePath(StreamState state)
{
var folder = ApplicationPaths.EncodedMediaCachePath;
@ -30,19 +36,6 @@ namespace MediaBrowser.Api.Playback.Hls
return Path.Combine(folder, GetCommandLineArguments("dummy\\dummy", state, false).GetMD5() + (outputFileExtension ?? string.Empty).ToLower());
}
/// <summary>
/// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
/// </summary>
/// <param name="appPaths">The app paths.</param>
/// <param name="userManager">The user manager.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="isoManager">The iso manager.</param>
/// <param name="mediaEncoder">The media encoder.</param>
protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem)
: base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem)
{
}
/// <summary>
/// Gets the audio arguments.
/// </summary>
@ -260,7 +253,7 @@ namespace MediaBrowser.Api.Playback.Hls
var itsOffsetMs = hlsVideoRequest == null
? 0
: ((GetHlsVideoStream) state.VideoRequest).TimeStampOffsetMs;
: ((GetHlsVideoStream)state.VideoRequest).TimeStampOffsetMs;
var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds);

@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.IO;
using ServiceStack.ServiceHost;
using System;
@ -31,17 +32,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary>
public class VideoHlsService : BaseHlsService
{
/// <summary>
/// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
/// </summary>
/// <param name="appPaths">The app paths.</param>
/// <param name="userManager">The user manager.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="isoManager">The iso manager.</param>
/// <param name="mediaEncoder">The media encoder.</param>
/// <param name="dtoService">The dto service.</param>
public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem)
: base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem)
public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository)
: base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository)
{
}
@ -95,13 +87,13 @@ namespace MediaBrowser.Api.Playback.Hls
{
volParam = ",volume=2.000000";
}
if (state.Request.AudioSampleRate.HasValue)
{
audioSampleRate= state.Request.AudioSampleRate.Value + ":";
audioSampleRate = state.Request.AudioSampleRate.Value + ":";
}
args += string.Format(" -af \"adelay=1,aresample={0}async=1000{1}\"",audioSampleRate, volParam);
args += string.Format(" -af \"adelay=1,aresample={0}async=1000{1}\"", audioSampleRate, volParam);
return args;
}
@ -130,7 +122,7 @@ namespace MediaBrowser.Api.Playback.Hls
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
(state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
var args = "-codec:v:0 " + codec + " -preset superfast" + keyFrameArg;
var bitrate = GetVideoBitrateParam(state);
@ -139,7 +131,7 @@ namespace MediaBrowser.Api.Playback.Hls
{
args += string.Format(" -b:v {0} -maxrate ({0}*.85) -bufsize {0}", bitrate.Value.ToString(UsCulture));
}
// Add resolution params, if specified
if (!hasGraphicalSubs)
{
@ -171,7 +163,7 @@ namespace MediaBrowser.Api.Playback.Hls
{
args += GetInternalGraphicalSubtitleParam(state, codec);
}
return args;
}

@ -12,7 +12,6 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
@ -25,13 +24,11 @@ namespace MediaBrowser.Api.Playback.Progressive
/// </summary>
public abstract class BaseProgressiveStreamingService : BaseStreamingService
{
protected readonly IItemRepository ItemRepository;
protected readonly IImageProcessor ImageProcessor;
protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepository, IDtoService dtoService, IImageProcessor imageProcessor, IFileSystem fileSystem) :
base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem)
base(appPaths, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository)
{
ItemRepository = itemRepository;
ImageProcessor = imageProcessor;
}

@ -226,7 +226,7 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "HasTvdbId", Description = "Optional filter by items that have a tvdb id or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? HasTvdbId { get; set; }
[ApiMember(Name = "IsYearMismatched", Description = "Optional filter by items that are potentially misidentified.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsYearMismatched { get; set; }
}
@ -984,15 +984,9 @@ namespace MediaBrowser.Api.UserLibrary
if (request.HasSubtitles.HasValue)
{
items = items.OfType<Video>().Where(i =>
{
if (request.HasSubtitles.Value)
{
return i.MediaStreams != null && i.MediaStreams.Any(m => m.Type == MediaStreamType.Subtitle);
}
var val = request.HasSubtitles.Value;
return i.MediaStreams == null || i.MediaStreams.All(m => m.Type != MediaStreamType.Subtitle);
});
items = items.OfType<Video>().Where(i => val == i.HasSubtitles);
}
if (request.HasParentalRating.HasValue)

@ -1,5 +1,4 @@
using MediaBrowser.Model.Entities;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
@ -13,7 +12,6 @@ namespace MediaBrowser.Controller.Entities.Audio
{
public Audio()
{
MediaStreams = new List<MediaStream>();
Artists = new List<string>();
}
@ -22,13 +20,13 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
/// <value>The language.</value>
public string Language { get; set; }
/// <summary>
/// Gets or sets the media streams.
/// Gets or sets a value indicating whether this instance has embedded image.
/// </summary>
/// <value>The media streams.</value>
public List<MediaStream> MediaStreams { get; set; }
/// <value><c>true</c> if this instance has embedded image; otherwise, <c>false</c>.</value>
public bool HasEmbeddedImage { get; set; }
/// <summary>
/// Override this to true if class should be grouped under a container in indicies
/// The container class should be defined via IndexContainer

@ -1,7 +1,8 @@

using System.Collections.Generic;
namespace MediaBrowser.Controller.Entities
{
public class Book : BaseItem
public class Book : BaseItem, IHasTags
{
public override string MediaType
{
@ -10,6 +11,11 @@ namespace MediaBrowser.Controller.Entities
return Model.Entities.MediaType.Book;
}
}
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
public List<string> Tags { get; set; }
public string SeriesName { get; set; }
@ -31,5 +37,10 @@ namespace MediaBrowser.Controller.Entities
return !IsInMixedFolder;
}
}
public Book()
{
Tags = new List<string>();
}
}
}

@ -0,0 +1,10 @@

namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// This is essentially a marker interface
/// </summary>
public interface IHasMediaStreams
{
}
}

@ -12,5 +12,10 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The screenshot image paths.</value>
List<string> ScreenshotImagePaths { get; set; }
/// <summary>
/// Validates the screenshots.
/// </summary>
void ValidateScreenshots();
}
}

@ -22,11 +22,28 @@ namespace MediaBrowser.Controller.Entities
public Video()
{
MediaStreams = new List<MediaStream>();
PlayableStreamFileNames = new List<string>();
AdditionalPartIds = new List<Guid>();
}
/// <summary>
/// Gets or sets a value indicating whether this instance has subtitles.
/// </summary>
/// <value><c>true</c> if this instance has subtitles; otherwise, <c>false</c>.</value>
public bool HasSubtitles { get; set; }
/// <summary>
/// Gets or sets the video bit rate.
/// </summary>
/// <value>The video bit rate.</value>
public int? VideoBitRate { get; set; }
/// <summary>
/// Gets or sets the default index of the video stream.
/// </summary>
/// <value>The default index of the video stream.</value>
public int? DefaultVideoStreamIndex { get; set; }
/// <summary>
/// Gets or sets the type of the video.
/// </summary>
@ -45,12 +62,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The video3 D format.</value>
public Video3DFormat? Video3DFormat { get; set; }
/// <summary>
/// Gets or sets the media streams.
/// </summary>
/// <value>The media streams.</value>
public List<MediaStream> MediaStreams { get; set; }
/// <summary>
/// If the video is a folder-rip, this will hold the file list for the largest playlist
/// </summary>
@ -70,7 +81,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The aspect ratio.</value>
public string AspectRatio { get; set; }
/// <summary>
/// Should be overridden to return the proper folder where metadata lives
/// </summary>
@ -122,16 +133,6 @@ namespace MediaBrowser.Controller.Entities
.ToList();
}
/// <summary>
/// The default video stream for this video. Use this to determine media info for this item.
/// </summary>
/// <value>The default video stream.</value>
[IgnoreDataMember]
public MediaStream DefaultVideoStream
{
get { return MediaStreams != null ? MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video) : null; }
}
/// <summary>
/// Gets a value indicating whether [is3 D].
/// </summary>

@ -93,6 +93,7 @@
<Compile Include="Entities\IHasBudget.cs" />
<Compile Include="Entities\IHasCriticRating.cs" />
<Compile Include="Entities\IHasLanguage.cs" />
<Compile Include="Entities\IHasMediaStreams.cs" />
<Compile Include="Entities\IHasProductionLocations.cs" />
<Compile Include="Entities\IHasScreenshots.cs" />
<Compile Include="Entities\IHasSoundtracks.cs" />
@ -124,6 +125,7 @@
<Compile Include="Localization\ILocalizationManager.cs" />
<Compile Include="Notifications\INotificationsRepository.cs" />
<Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
<Compile Include="Persistence\MediaStreamQuery.cs" />
<Compile Include="Providers\IDynamicInfoProvider.cs" />
<Compile Include="Providers\IImageProvider.cs" />
<Compile Include="Providers\NameParser.cs" />

@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.MediaInfo
return Path.Combine(_appPaths.CachePath, "subtitles");
}
}
/// <summary>
/// The first chapter ticks
/// </summary>
@ -112,7 +112,7 @@ namespace MediaBrowser.Controller.MediaInfo
public async Task<bool> PopulateChapterImages(Video video, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
{
// Can't extract images if there are no video streams
if (video.MediaStreams == null || video.MediaStreams.All(m => m.Type != MediaStreamType.Video))
if (!video.DefaultVideoStreamIndex.HasValue)
{
return true;
}
@ -164,7 +164,7 @@ namespace MediaBrowser.Controller.MediaInfo
var parentPath = Path.GetDirectoryName(path);
Directory.CreateDirectory(parentPath);
await _encoder.ExtractImage(inputPath, type, video.Video3DFormat, time, path, cancellationToken).ConfigureAwait(false);
chapter.ImagePath = path;
changesMade = true;
@ -203,7 +203,17 @@ namespace MediaBrowser.Controller.MediaInfo
{
var ticksParam = offset.HasValue ? "_" + offset.Value.Ticks : "";
var stream = input.MediaStreams[subtitleStreamIndex];
var stream = _itemRepo.GetMediaStreams(new MediaStreamQuery
{
ItemId = input.Id,
Index = subtitleStreamIndex
}).FirstOrDefault();
if (stream == null)
{
return null;
}
if (stream.IsExternal)
{

@ -95,6 +95,22 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveChildren(Guid parentId, IEnumerable<Guid> children, CancellationToken cancellationToken);
/// <summary>
/// Gets the media streams.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>IEnumerable{MediaStream}.</returns>
IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query);
/// <summary>
/// Saves the media streams.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="streams">The streams.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken);
}
}

@ -0,0 +1,26 @@
using MediaBrowser.Model.Entities;
using System;
namespace MediaBrowser.Controller.Persistence
{
public class MediaStreamQuery
{
/// <summary>
/// Gets or sets the type.
/// </summary>
/// <value>The type.</value>
public MediaStreamType? Type { get; set; }
/// <summary>
/// Gets or sets the index.
/// </summary>
/// <value>The index.</value>
public int? Index { get; set; }
/// <summary>
/// Gets or sets the item identifier.
/// </summary>
/// <value>The item identifier.</value>
public Guid ItemId { get; set; }
}
}

@ -1,6 +1,5 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using System;
using System.Collections.Generic;
@ -46,6 +45,7 @@ namespace MediaBrowser.Controller.Resolvers
".3gp",
".webm",
".mts",
".m2v",
".rec"
};

@ -143,9 +143,6 @@
<Compile Include="..\MediaBrowser.Model\Entities\DisplayPreferences.cs">
<Link>Entities\DisplayPreferences.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\IHasMediaStreams.cs">
<Link>Entities\IHasMediaStreams.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\IHasProviderIds.cs">
<Link>Entities\IHasProviderIds.cs</Link>
</Compile>

@ -130,9 +130,6 @@
<Compile Include="..\MediaBrowser.Model\Entities\DisplayPreferences.cs">
<Link>Entities\DisplayPreferences.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\IHasMediaStreams.cs">
<Link>Entities\IHasMediaStreams.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\IHasProviderIds.cs">
<Link>Entities\IHasProviderIds.cs</Link>
</Compile>

@ -68,9 +68,6 @@ namespace MediaBrowser.Model.Dto
/// </summary>
/// <value>The unique types.</value>
public List<string> UniqueTypes { get; set; }
public int PersonCount { get; set; }
public int ArtistCount { get; set; }
public ItemCounts()
{

@ -1,26 +0,0 @@
using System.Collections.Generic;
namespace MediaBrowser.Model.Entities
{
/// <summary>
/// This is essentially a marker interface
/// </summary>
public interface IHasMediaStreams
{
/// <summary>
/// Gets or sets the media streams.
/// </summary>
/// <value>The media streams.</value>
List<MediaStream> MediaStreams { get; set; }
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
string Path { get; set; }
/// <summary>
/// Gets or sets the primary image path.
/// </summary>
/// <value>The primary image path.</value>
string PrimaryImagePath { get; }
}
}

@ -19,10 +19,10 @@ namespace MediaBrowser.Model.Entities
public string Language { get; set; }
/// <summary>
/// Gets or sets the type of the scan.
/// Gets or sets a value indicating whether this instance is interlaced.
/// </summary>
/// <value>The type of the scan.</value>
public string ScanType { get; set; }
/// <value><c>true</c> if this instance is interlaced; otherwise, <c>false</c>.</value>
public bool IsInterlaced { get; set; }
/// <summary>
/// Gets or sets the channel layout.

@ -125,7 +125,6 @@
<Compile Include="Entities\ParentalRating.cs" />
<Compile Include="Dto\StreamOptions.cs" />
<Compile Include="Entities\VirtualFolderInfo.cs" />
<Compile Include="Entities\IHasMediaStreams.cs" />
<Compile Include="Extensions\ModelExtensions.cs" />
<Compile Include="IO\IZipClient.cs" />
<Compile Include="Logging\ILogger.cs" />

@ -108,7 +108,12 @@ namespace MediaBrowser.Providers
// Make sure current backdrop paths still exist
item.ValidateBackdrops();
item.ValidateScreenshots();
var hasScreenshots = item as IHasScreenshots;
if (hasScreenshots != null)
{
hasScreenshots.ValidateScreenshots();
}
cancellationToken.ThrowIfCancellationRequested();

@ -127,7 +127,7 @@ namespace MediaBrowser.Providers.MediaInfo
var audio = (Audio)item;
if (string.IsNullOrEmpty(audio.PrimaryImagePath) && audio.MediaStreams.Any(s => s.Type == MediaStreamType.Video))
if (string.IsNullOrEmpty(audio.PrimaryImagePath) && audio.HasEmbeddedImage)
{
try
{

@ -3,6 +3,7 @@ using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
@ -19,9 +20,12 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
public class FFProbeAudioInfoProvider : BaseFFProbeProvider<Audio>
{
public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder, IJsonSerializer jsonSerializer)
private readonly IItemRepository _itemRepo;
public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IMediaEncoder mediaEncoder, IJsonSerializer jsonSerializer, IItemRepository itemRepo)
: base(logManager, configurationManager, mediaEncoder, jsonSerializer)
{
_itemRepo = itemRepo;
}
public override async Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
@ -38,7 +42,7 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
Fetch(myItem, cancellationToken, result);
await Fetch(myItem, cancellationToken, result).ConfigureAwait(false);
SetLastRefreshed(item, DateTime.UtcNow);
@ -51,22 +55,19 @@ namespace MediaBrowser.Providers.MediaInfo
/// <param name="audio">The audio.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="data">The data.</param>
/// <param name="isoMount">The iso mount.</param>
/// <returns>Task.</returns>
protected void Fetch(Audio audio, CancellationToken cancellationToken, MediaInfoResult data)
protected Task Fetch(Audio audio, CancellationToken cancellationToken, MediaInfoResult data)
{
if (data.streams == null)
{
Logger.Error("Audio item has no streams: " + audio.Path);
return;
}
var internalStreams = data.streams ?? new MediaStreamInfo[] { };
audio.MediaStreams = data.streams.Select(s => GetMediaStream(s, data.format))
var mediaStreams = internalStreams.Select(s => GetMediaStream(s, data.format))
.Where(i => i != null)
.ToList();
audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.Video);
// Get the first audio stream
var stream = data.streams.FirstOrDefault(s => s.codec_type.Equals("audio", StringComparison.OrdinalIgnoreCase));
var stream = internalStreams.FirstOrDefault(s => s.codec_type.Equals("audio", StringComparison.OrdinalIgnoreCase));
if (stream != null)
{
@ -90,6 +91,8 @@ namespace MediaBrowser.Providers.MediaInfo
{
FetchDataFromTags(audio, data.format.tags);
}
return _itemRepo.SaveMediaStreams(audio.Id, mediaStreams, cancellationToken);
}
/// <summary>

@ -304,11 +304,17 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
List<MediaStream> mediaStreams;
if (data.streams != null)
{
video.MediaStreams = data.streams.Select(s => GetMediaStream(s, data.format))
.Where(i => i != null)
.ToList();
mediaStreams = data.streams.Select(s => GetMediaStream(s, data.format))
.Where(i => i != null)
.ToList();
}
else
{
mediaStreams = new List<MediaStream>();
}
var chapters = data.Chapters ?? new List<ChapterInfo>();
@ -316,22 +322,28 @@ namespace MediaBrowser.Providers.MediaInfo
if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay))
{
var inputPath = isoMount != null ? isoMount.MountedPath : video.Path;
FetchBdInfo(video, chapters, inputPath, cancellationToken);
FetchBdInfo(video, chapters, mediaStreams, inputPath, cancellationToken);
}
AddExternalSubtitles(video);
AddExternalSubtitles(video, mediaStreams);
FetchWtvInfo(video, force, data);
video.IsHD = video.MediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270);
video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270);
if (chapters.Count == 0 && video.MediaStreams.Any(i => i.Type == MediaStreamType.Video))
if (chapters.Count == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
{
AddDummyChapters(video, chapters);
}
await Kernel.Instance.FFMpegManager.PopulateChapterImages(video, chapters, false, false, cancellationToken).ConfigureAwait(false);
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
video.VideoBitRate = videoStream == null ? null : videoStream.BitRate;
video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index;
video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle);
await Kernel.Instance.FFMpegManager.PopulateChapterImages(video, chapters, false, false, cancellationToken).ConfigureAwait(false);
BaseProviderInfo providerInfo;
var videoFileChanged = false;
@ -341,6 +353,8 @@ namespace MediaBrowser.Providers.MediaInfo
videoFileChanged = CompareDate(video) > providerInfo.LastRefreshed;
}
await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false);
// Only save chapters if forcing, if the video changed, or if there are not already any saved ones
if (force || videoFileChanged || _itemRepo.GetChapter(video.Id, 0) == null)
{
@ -439,7 +453,8 @@ namespace MediaBrowser.Providers.MediaInfo
/// Adds the external subtitles.
/// </summary>
/// <param name="video">The video.</param>
private void AddExternalSubtitles(Video video)
/// <param name="currentStreams">The current streams.</param>
private void AddExternalSubtitles(Video video, List<MediaStream> currentStreams)
{
var useParent = !video.ResolveArgs.IsDirectory;
@ -452,7 +467,7 @@ namespace MediaBrowser.Providers.MediaInfo
? video.Parent.ResolveArgs.FileSystemChildren
: video.ResolveArgs.FileSystemChildren;
var startIndex = video.MediaStreams == null ? 0 : video.MediaStreams.Count;
var startIndex = currentStreams.Count;
var streams = new List<MediaStream>();
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
@ -503,11 +518,7 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
if (video.MediaStreams == null)
{
video.MediaStreams = new List<MediaStream>();
}
video.MediaStreams.AddRange(streams);
currentStreams.AddRange(streams);
}
/// <summary>
@ -556,9 +567,10 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
/// <param name="item">The item.</param>
/// <param name="chapters">The chapters.</param>
/// <param name="mediaStreams">The media streams.</param>
/// <param name="inputPath">The input path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
private void FetchBdInfo(BaseItem item, List<ChapterInfo> chapters, string inputPath, CancellationToken cancellationToken)
private void FetchBdInfo(BaseItem item, List<ChapterInfo> chapters, List<MediaStream> mediaStreams, string inputPath, CancellationToken cancellationToken)
{
var video = (Video)item;
@ -570,7 +582,7 @@ namespace MediaBrowser.Providers.MediaInfo
int? currentWidth = null;
int? currentBitRate = null;
var videoStream = video.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video);
var videoStream = mediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video);
// Grab the values that ffprobe recorded
if (videoStream != null)
@ -581,9 +593,9 @@ namespace MediaBrowser.Providers.MediaInfo
}
// Fill video properties from the BDInfo result
Fetch(video, result, chapters);
Fetch(video, mediaStreams, result, chapters);
videoStream = video.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video);
videoStream = mediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video);
// Use the ffprobe values if these are empty
if (videoStream != null)
@ -608,13 +620,15 @@ namespace MediaBrowser.Providers.MediaInfo
/// Fills video properties from the VideoStream of the largest playlist
/// </summary>
/// <param name="video">The video.</param>
/// <param name="mediaStreams">The media streams.</param>
/// <param name="stream">The stream.</param>
/// <param name="chapters">The chapters.</param>
private void Fetch(Video video, BlurayDiscInfo stream, List<ChapterInfo> chapters)
private void Fetch(Video video, List<MediaStream> mediaStreams, BlurayDiscInfo stream, List<ChapterInfo> chapters)
{
// Check all input for null/empty/zero
video.MediaStreams = stream.MediaStreams;
mediaStreams.Clear();
mediaStreams.AddRange(stream.MediaStreams);
video.MainFeaturePlaylistName = stream.PlaylistName;

@ -128,7 +128,7 @@ namespace MediaBrowser.Providers.MediaInfo
}
// Can't extract if we didn't find a video stream in the file
if (item.MediaStreams.All(m => m.Type != MediaStreamType.Video))
if (!item.DefaultVideoStreamIndex.HasValue)
{
return false;
}

@ -529,8 +529,6 @@ namespace MediaBrowser.Providers.Savers
/// Appends the media info.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="item">The item.</param>
/// <param name="builder">The builder.</param>
public static void AddMediaInfo<T>(T item, StringBuilder builder, IItemRepository itemRepository)
where T : BaseItem, IHasMediaStreams
{
@ -538,105 +536,38 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<MediaInfo>");
foreach (var stream in item.MediaStreams)
{
builder.Append("<" + stream.Type + ">");
if (!string.IsNullOrEmpty(stream.Codec))
{
builder.Append("<Codec>" + SecurityElement.Escape(stream.Codec) + "</Codec>");
builder.Append("<FFCodec>" + SecurityElement.Escape(stream.Codec) + "</FFCodec>");
}
if (stream.BitRate.HasValue)
{
builder.Append("<BitRate>" + stream.BitRate.Value.ToString(UsCulture) + "</BitRate>");
}
if (stream.Width.HasValue)
{
builder.Append("<Width>" + stream.Width.Value.ToString(UsCulture) + "</Width>");
}
if (stream.Height.HasValue)
{
builder.Append("<Height>" + stream.Height.Value.ToString(UsCulture) + "</Height>");
}
if (!string.IsNullOrEmpty(stream.AspectRatio))
{
builder.Append("<AspectRatio>" + SecurityElement.Escape(stream.AspectRatio) + "</AspectRatio>");
}
var framerate = stream.AverageFrameRate ?? stream.RealFrameRate;
if (framerate.HasValue)
{
builder.Append("<FrameRate>" + framerate.Value.ToString(UsCulture) + "</FrameRate>");
}
if (!string.IsNullOrEmpty(stream.Language))
{
builder.Append("<Language>" + SecurityElement.Escape(stream.Language) + "</Language>");
}
builder.Append("<Video>");
if (!string.IsNullOrEmpty(stream.ScanType))
{
builder.Append("<ScanType>" + SecurityElement.Escape(stream.ScanType) + "</ScanType>");
}
if (stream.Channels.HasValue)
{
builder.Append("<Channels>" + stream.Channels.Value.ToString(UsCulture) + "</Channels>");
}
if (stream.SampleRate.HasValue)
{
builder.Append("<SamplingRate>" + stream.SampleRate.Value.ToString(UsCulture) + "</SamplingRate>");
}
if (item.RunTimeTicks.HasValue)
{
var timespan = TimeSpan.FromTicks(item.RunTimeTicks.Value);
builder.Append("<Default>" + SecurityElement.Escape(stream.IsDefault.ToString()) + "</Default>");
builder.Append("<Forced>" + SecurityElement.Escape(stream.IsForced.ToString()) + "</Forced>");
builder.Append("<Duration>" + Convert.ToInt64(timespan.TotalMinutes).ToString(UsCulture) + "</Duration>");
builder.Append("<DurationSeconds>" + Convert.ToInt64(timespan.TotalSeconds).ToString(UsCulture) + "</DurationSeconds>");
}
if (stream.Type == MediaStreamType.Video)
if (video != null && video.Video3DFormat.HasValue)
{
switch (video.Video3DFormat.Value)
{
if (item.RunTimeTicks.HasValue)
{
var timespan = TimeSpan.FromTicks(item.RunTimeTicks.Value);
builder.Append("<Duration>" + Convert.ToInt64(timespan.TotalMinutes).ToString(UsCulture) + "</Duration>");
builder.Append("<DurationSeconds>" + Convert.ToInt64(timespan.TotalSeconds).ToString(UsCulture) + "</DurationSeconds>");
}
if (video != null && video.Video3DFormat.HasValue)
{
switch (video.Video3DFormat.Value)
{
case Video3DFormat.FullSideBySide:
builder.Append("<Format3D>FSBS</Format3D>");
break;
case Video3DFormat.FullTopAndBottom:
builder.Append("<Format3D>FTAB</Format3D>");
break;
case Video3DFormat.HalfSideBySide:
builder.Append("<Format3D>HSBS</Format3D>");
break;
case Video3DFormat.HalfTopAndBottom:
builder.Append("<Format3D>HTAB</Format3D>");
break;
}
}
case Video3DFormat.FullSideBySide:
builder.Append("<Format3D>FSBS</Format3D>");
break;
case Video3DFormat.FullTopAndBottom:
builder.Append("<Format3D>FTAB</Format3D>");
break;
case Video3DFormat.HalfSideBySide:
builder.Append("<Format3D>HSBS</Format3D>");
break;
case Video3DFormat.HalfTopAndBottom:
builder.Append("<Format3D>HTAB</Format3D>");
break;
}
builder.Append("</" + stream.Type + ">");
}
builder.Append("</MediaInfo>");
builder.Append("</Video>");
if (video != null)
{
//AddChapters(video, builder, itemRepository);
}
builder.Append("</MediaInfo>");
}
}
}

@ -102,7 +102,7 @@ namespace MediaBrowser.Server.Implementations.BdInfo
Width = videoStream.Width,
Height = videoStream.Height,
Codec = videoStream.CodecShortName,
ScanType = videoStream.IsInterlaced ? "interlaced" : "progressive",
IsInterlaced = videoStream.IsInterlaced,
Type = MediaStreamType.Video,
Index = streams.Count
};
@ -146,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.BdInfo
{
stream.Channels = audioStream.ChannelCount + 1;
}
streams.Add(stream);
}

@ -1034,7 +1034,11 @@ namespace MediaBrowser.Server.Implementations.Dto
if (iHasMediaStreams != null)
{
dto.MediaStreams = iHasMediaStreams.MediaStreams;
dto.MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery
{
ItemId = item.Id
}).ToList();
}
}

@ -168,6 +168,7 @@
<Compile Include="MediaEncoder\MediaEncoder.cs" />
<Compile Include="Persistence\SqliteChapterRepository.cs" />
<Compile Include="Persistence\SqliteExtensions.cs" />
<Compile Include="Persistence\SqliteMediaStreamsRepository.cs" />
<Compile Include="Persistence\SqliteNotificationsRepository.cs" />
<Compile Include="Persistence\TypeMapper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

@ -56,6 +56,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
private readonly string _criticReviewsPath;
private SqliteChapterRepository _chapterRepository;
private SqliteMediaStreamsRepository _mediaStreamsRepository;
private IDbCommand _deleteChildrenCommand;
private IDbCommand _saveChildrenCommand;
@ -94,6 +95,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
var chapterConnection = SqliteExtensions.ConnectToDb(chapterDbFile, _logger).Result;
_chapterRepository = new SqliteChapterRepository(chapterConnection, logManager);
var mediaStreamsDbFile = Path.Combine(_appPaths.DataPath, "mediainfo.db");
var mediaStreamsConnection = SqliteExtensions.ConnectToDb(mediaStreamsDbFile, _logger).Result;
_mediaStreamsRepository = new SqliteMediaStreamsRepository(mediaStreamsConnection, logManager);
}
/// <summary>
@ -122,6 +129,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
PrepareStatements();
_mediaStreamsRepository.Initialize();
_chapterRepository.Initialize();
}
@ -413,6 +421,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
_chapterRepository.Dispose();
_chapterRepository = null;
}
if (_mediaStreamsRepository != null)
{
_mediaStreamsRepository.Dispose();
_mediaStreamsRepository = null;
}
}
}
@ -511,5 +525,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
_writeLock.Release();
}
}
public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query)
{
return _mediaStreamsRepository.GetMediaStreams(query);
}
public Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken)
{
return _mediaStreamsRepository.SaveMediaStreams(id, streams, cancellationToken);
}
}
}

@ -0,0 +1,377 @@
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Persistence
{
class SqliteMediaStreamsRepository
{
private IDbConnection _connection;
private readonly ILogger _logger;
private IDbCommand _deleteStreamsCommand;
private IDbCommand _saveStreamCommand;
public SqliteMediaStreamsRepository(IDbConnection connection, ILogManager logManager)
{
_connection = connection;
_logger = logManager.GetLogger(GetType().Name);
}
/// <summary>
/// Opens the connection to the database
/// </summary>
/// <returns>Task.</returns>
public void Initialize()
{
var createTableCommand
= "create table if not exists mediastreams ";
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 = {
createTableCommand,
"create index if not exists idx_mediastreams on mediastreams(ItemId, StreamIndex)",
//pragmas
"pragma temp_store = memory"
};
_connection.RunQueries(queries, _logger);
PrepareStatements();
}
private readonly string[] _saveColumns =
{
"ItemId",
"StreamIndex",
"StreamType",
"Codec",
"Language",
"ChannelLayout",
"Profile",
"AspectRatio",
"Path",
"IsInterlaced",
"BitRate",
"Channels",
"SampleRate",
"IsDefault",
"IsForced",
"IsExternal",
"Height",
"Width",
"AverageFrameRate",
"RealFrameRate",
"Level"
};
/// <summary>
/// The _write lock
/// </summary>
private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
/// <summary>
/// Prepares the statements.
/// </summary>
private void PrepareStatements()
{
_deleteStreamsCommand = _connection.CreateCommand();
_deleteStreamsCommand.CommandText = "delete from mediastreams where ItemId=@ItemId";
_deleteStreamsCommand.Parameters.Add(_deleteStreamsCommand, "@ItemId");
_saveStreamCommand = _connection.CreateCommand();
_saveStreamCommand.CommandText = string.Format("replace into mediastreams ({0}) values ({1})",
string.Join(",", _saveColumns),
string.Join(",", _saveColumns.Select(i => "@" + i).ToArray()));
foreach (var col in _saveColumns)
{
_saveStreamCommand.Parameters.Add(_saveStreamCommand, "@" + col);
}
}
public IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
using (var cmd = _connection.CreateCommand())
{
var cmdText = "select " + string.Join(",", _saveColumns) + " from mediastreams where";
cmdText += " ItemId=@ItemId";
cmd.Parameters.Add(cmd, "@ItemId", DbType.Guid).Value = query.ItemId;
if (query.Type.HasValue)
{
cmdText += " AND StreamType=@StreamType";
cmd.Parameters.Add(cmd, "@StreamType", DbType.String).Value = query.Type.Value.ToString();
}
if (query.Index.HasValue)
{
cmdText += " AND StreamIndex=@StreamIndex";
cmd.Parameters.Add(cmd, "@StreamIndex", DbType.Int32).Value = query.Index.Value;
}
cmdText += " order by StreamIndex ASC";
cmd.CommandText = cmdText;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
yield return GetMediaStream(reader);
}
}
}
}
/// <summary>
/// Gets the chapter.
/// </summary>
/// <param name="reader">The reader.</param>
/// <returns>ChapterInfo.</returns>
private MediaStream GetMediaStream(IDataReader reader)
{
var item = new MediaStream
{
Index = reader.GetInt32(1)
};
item.Type = (MediaStreamType)Enum.Parse(typeof(MediaStreamType), reader.GetString(2), true);
if (!reader.IsDBNull(3))
{
item.Codec = reader.GetString(3);
}
if (!reader.IsDBNull(4))
{
item.Language = reader.GetString(4);
}
if (!reader.IsDBNull(5))
{
item.ChannelLayout = reader.GetString(5);
}
if (!reader.IsDBNull(6))
{
item.Profile = reader.GetString(6);
}
if (!reader.IsDBNull(7))
{
item.AspectRatio = reader.GetString(7);
}
if (!reader.IsDBNull(8))
{
item.Path = reader.GetString(8);
}
item.IsInterlaced = reader.GetBoolean(9);
if (!reader.IsDBNull(10))
{
item.BitRate = reader.GetInt32(10);
}
if (!reader.IsDBNull(11))
{
item.Channels = reader.GetInt32(11);
}
if (!reader.IsDBNull(12))
{
item.SampleRate = reader.GetInt32(12);
}
item.IsDefault = reader.GetBoolean(13);
item.IsForced = reader.GetBoolean(14);
item.IsExternal = reader.GetBoolean(15);
if (!reader.IsDBNull(16))
{
item.Width = reader.GetInt32(16);
}
if (!reader.IsDBNull(17))
{
item.Height = reader.GetInt32(17);
}
if (!reader.IsDBNull(18))
{
item.AverageFrameRate = reader.GetFloat(18);
}
if (!reader.IsDBNull(19))
{
item.RealFrameRate = reader.GetFloat(19);
}
if (!reader.IsDBNull(20))
{
item.Level = reader.GetFloat(20);
}
return item;
}
public async Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken)
{
if (id == Guid.Empty)
{
throw new ArgumentNullException("id");
}
if (streams == null)
{
throw new ArgumentNullException("streams");
}
cancellationToken.ThrowIfCancellationRequested();
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
{
transaction = _connection.BeginTransaction();
// First delete chapters
_deleteStreamsCommand.GetParameter(0).Value = id;
_deleteStreamsCommand.Transaction = transaction;
_deleteStreamsCommand.ExecuteNonQuery();
foreach (var stream in streams)
{
cancellationToken.ThrowIfCancellationRequested();
_saveStreamCommand.GetParameter(0).Value = id;
_saveStreamCommand.GetParameter(1).Value = stream.Index;
_saveStreamCommand.GetParameter(2).Value = stream.Type.ToString();
_saveStreamCommand.GetParameter(3).Value = stream.Codec;
_saveStreamCommand.GetParameter(4).Value = stream.Language;
_saveStreamCommand.GetParameter(5).Value = stream.ChannelLayout;
_saveStreamCommand.GetParameter(6).Value = stream.Profile;
_saveStreamCommand.GetParameter(7).Value = stream.AspectRatio;
_saveStreamCommand.GetParameter(8).Value = stream.Path;
_saveStreamCommand.GetParameter(9).Value = stream.IsInterlaced;
_saveStreamCommand.GetParameter(10).Value = stream.BitRate;
_saveStreamCommand.GetParameter(11).Value = stream.Channels;
_saveStreamCommand.GetParameter(12).Value = stream.SampleRate;
_saveStreamCommand.GetParameter(13).Value = stream.IsDefault;
_saveStreamCommand.GetParameter(14).Value = stream.IsForced;
_saveStreamCommand.GetParameter(15).Value = stream.IsExternal;
_saveStreamCommand.GetParameter(16).Value = stream.Width;
_saveStreamCommand.GetParameter(17).Value = stream.Height;
_saveStreamCommand.GetParameter(18).Value = stream.AverageFrameRate;
_saveStreamCommand.GetParameter(19).Value = stream.RealFrameRate;
_saveStreamCommand.GetParameter(20).Value = stream.Level;
_saveStreamCommand.Transaction = transaction;
_saveStreamCommand.ExecuteNonQuery();
}
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
_logger.ErrorException("Failed to save media streams:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
_writeLock.Release();
}
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private readonly object _disposeLock = new object();
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool dispose)
{
if (dispose)
{
try
{
lock (_disposeLock)
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
}
}
catch (Exception ex)
{
_logger.ErrorException("Error disposing database", ex);
}
}
}
}
}

@ -31,36 +31,26 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
private readonly IJsonSerializer _jsonSerializer;
/// <summary>
/// The _app paths
/// </summary>
private readonly IApplicationPaths _appPaths;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteUserDataRepository"/> class.
/// Initializes a new instance of the <see cref="SqliteUserDataRepository" /> class.
/// </summary>
/// <param name="appPaths">The app paths.</param>
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="logManager">The log manager.</param>
/// <exception cref="System.ArgumentNullException">
/// jsonSerializer
/// <exception cref="System.ArgumentNullException">jsonSerializer
/// or
/// appPaths
/// </exception>
public SqliteUserDataRepository(IApplicationPaths appPaths, IJsonSerializer jsonSerializer, ILogManager logManager)
/// appPaths</exception>
public SqliteUserDataRepository(IApplicationPaths appPaths, ILogManager logManager)
{
if (jsonSerializer == null)
{
throw new ArgumentNullException("jsonSerializer");
}
if (appPaths == null)
{
throw new ArgumentNullException("appPaths");
}
_jsonSerializer = jsonSerializer;
_appPaths = appPaths;
_logger = logManager.GetLogger(GetType().Name);
}

@ -101,7 +101,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
// Limit to video files to reduce changes of ffmpeg crash dialog
foreach (var item in newItems
.Where(i => i.LocationType == LocationType.FileSystem && i.VideoType == VideoType.VideoFile && string.IsNullOrEmpty(i.PrimaryImagePath) && i.MediaStreams.Any(m => m.Type == MediaStreamType.Video))
.Where(i => i.LocationType == LocationType.FileSystem && i.VideoType == VideoType.VideoFile && string.IsNullOrEmpty(i.PrimaryImagePath) && i.DefaultVideoStreamIndex.HasValue)
.Take(2))
{
try

@ -1,8 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using System.Linq;
namespace MediaBrowser.Server.Implementations.Sorting
{
@ -21,17 +19,11 @@ namespace MediaBrowser.Server.Implementations.Sorting
private int GetValue(BaseItem item)
{
var video = item as IHasMediaStreams;
var video = item as Video;
if (video != null)
{
var videoStream = video.MediaStreams
.FirstOrDefault(i => i.Type == MediaStreamType.Video);
if (videoStream != null)
{
return videoStream.BitRate ?? 0;
}
return video.VideoBitRate ?? 0;
}
return 0;

@ -394,7 +394,7 @@ namespace MediaBrowser.ServerApplication
/// <returns>Task.</returns>
private async Task ConfigureUserDataRepositories()
{
var repo = new SqliteUserDataRepository(ApplicationPaths, JsonSerializer, LogManager);
var repo = new SqliteUserDataRepository(ApplicationPaths, LogManager);
await repo.Initialize().ConfigureAwait(false);

@ -3,7 +3,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
{
public static class FFMpegDownloadInfo
{
public static string Version = "ffmpeg20131110";
public static string Version = "ffmpeg20131110.1";
public static string[] FfMpegUrls = new[]
{

Loading…
Cancel
Save