Merge pull request #2219 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2016-10-11 02:47:51 -04:00 committed by GitHub
commit 88150e461c
34 changed files with 362 additions and 136 deletions

View File

@ -819,10 +819,10 @@ namespace MediaBrowser.Api.Playback
{ {
if (state.PlayableStreamFileNames.Count > 0) if (state.PlayableStreamFileNames.Count > 0)
{ {
return MediaEncoder.GetProbeSizeArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol); return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
} }
return MediaEncoder.GetProbeSizeArgument(new[] { state.MediaPath }, state.InputProtocol); return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(new[] { state.MediaPath }, state.InputProtocol);
} }
/// <summary> /// <summary>

View File

@ -45,6 +45,15 @@ namespace MediaBrowser.Controller.Entities
return false; return false;
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return false;
}
}
/// <summary> /// <summary>
/// The _virtual children /// The _virtual children
/// </summary> /// </summary>

View File

@ -17,6 +17,9 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary> /// </summary>
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer
{ {
public List<string> AlbumArtists { get; set; }
public List<string> Artists { get; set; }
public MusicAlbum() public MusicAlbum()
{ {
Artists = new List<string>(); Artists = new List<string>();
@ -48,6 +51,15 @@ namespace MediaBrowser.Controller.Entities.Audio
} }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return false;
}
}
[IgnoreDataMember] [IgnoreDataMember]
public override bool SupportsCumulativeRunTimeTicks public override bool SupportsCumulativeRunTimeTicks
{ {
@ -83,8 +95,6 @@ namespace MediaBrowser.Controller.Entities.Audio
get { return false; } get { return false; }
} }
public List<string> AlbumArtists { get; set; }
/// <summary> /// <summary>
/// Gets the tracks. /// Gets the tracks.
/// </summary> /// </summary>
@ -103,8 +113,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return Tracks; return Tracks;
} }
public List<string> Artists { get; set; }
public override List<string> GetUserDataKeys() public override List<string> GetUserDataKeys()
{ {
var list = base.GetUserDataKeys(); var list = base.GetUserDataKeys();

View File

@ -48,6 +48,15 @@ namespace MediaBrowser.Controller.Entities.Audio
get { return true; } get { return true; }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return false;
}
}
public override bool CanDelete() public override bool CanDelete()
{ {
return !IsAccessedByName; return !IsAccessedByName;

View File

@ -129,6 +129,15 @@ namespace MediaBrowser.Controller.Entities
get { return false; } get { return false; }
} }
[IgnoreDataMember]
public virtual bool SupportsPlayedStatus
{
get
{
return false;
}
}
public bool DetectIsInMixedFolder() public bool DetectIsInMixedFolder()
{ {
if (SupportsIsInMixedFolderDetection) if (SupportsIsInMixedFolderDetection)

View File

@ -38,6 +38,15 @@ namespace MediaBrowser.Controller.Entities
} }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return false;
}
}
public override bool CanDelete() public override bool CanDelete()
{ {
return false; return false;

View File

@ -61,6 +61,15 @@ namespace MediaBrowser.Controller.Entities
get { return false; } get { return false; }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return true;
}
}
/// <summary> /// <summary>
/// Gets a value indicating whether this instance is folder. /// Gets a value indicating whether this instance is folder.
/// </summary> /// </summary>

View File

@ -26,6 +26,15 @@ namespace MediaBrowser.Controller.Entities
} }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return false;
}
}
/// <summary> /// <summary>
/// Gets or sets the game system. /// Gets or sets the game system.
/// </summary> /// </summary>

View File

@ -20,5 +20,7 @@ namespace MediaBrowser.Controller.Entities
Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user); Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user);
bool EnableRememberingTrackSelections { get; } bool EnableRememberingTrackSelections { get; }
bool SupportsPlayedStatus { get; }
} }
} }

View File

@ -29,13 +29,13 @@ namespace MediaBrowser.Controller.Entities
{ {
get get
{ {
return Album; return AlbumEntity;
} }
} }
[IgnoreDataMember] [IgnoreDataMember]
public PhotoAlbum Album public PhotoAlbum AlbumEntity
{ {
get get
{ {

View File

@ -16,6 +16,15 @@ namespace MediaBrowser.Controller.Entities
} }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return false;
}
}
protected override bool GetBlockUnratedValue(UserPolicy config) protected override bool GetBlockUnratedValue(UserPolicy config)
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Other); return config.BlockUnratedItems.Contains(UnratedItem.Other);

View File

@ -33,6 +33,15 @@ namespace MediaBrowser.Controller.Entities
} }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return false;
}
}
private void ClearCache() private void ClearCache()
{ {
lock (_childIdsLock) lock (_childIdsLock)

View File

@ -44,6 +44,15 @@ namespace MediaBrowser.Controller.Entities
return list; return list;
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return false;
}
}
public override int GetChildCount(User user) public override int GetChildCount(User user)
{ {
return GetChildren(user, true).Count(); return GetChildren(user, true).Count();

View File

@ -44,6 +44,15 @@ namespace MediaBrowser.Controller.Entities
} }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return true;
}
}
public override string CreatePresentationUniqueKey() public override string CreatePresentationUniqueKey()
{ {
if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) if (!string.IsNullOrWhiteSpace(PrimaryVersionId))

View File

@ -54,6 +54,15 @@ namespace MediaBrowser.Controller.LiveTv
} }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return Status == RecordingStatus.Completed && base.SupportsPlayedStatus;
}
}
[IgnoreDataMember] [IgnoreDataMember]
public override LocationType LocationType public override LocationType LocationType
{ {

View File

@ -84,7 +84,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="inputFiles">The input files.</param> /// <param name="inputFiles">The input files.</param>
/// <param name="protocol">The protocol.</param> /// <param name="protocol">The protocol.</param>
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
string GetProbeSizeArgument(string[] inputFiles, MediaProtocol protocol); string GetProbeSizeAndAnalyzeDurationArgument(string[] inputFiles, MediaProtocol protocol);
/// <summary> /// <summary>
/// Gets the input argument. /// Gets the input argument.

View File

@ -15,6 +15,7 @@ namespace MediaBrowser.Controller.MediaEncoding
public IIsoMount MountedIso { get; set; } public IIsoMount MountedIso { get; set; }
public VideoType VideoType { get; set; } public VideoType VideoType { get; set; }
public List<string> PlayableStreamFileNames { get; set; } public List<string> PlayableStreamFileNames { get; set; }
public int AnalyzeDurationSections { get; set; }
public MediaInfoRequest() public MediaInfoRequest()
{ {

View File

@ -31,6 +31,15 @@ namespace MediaBrowser.Controller.Playlists
} }
} }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
get
{
return string.Equals(MediaType, "Video", StringComparison.OrdinalIgnoreCase);
}
}
[IgnoreDataMember] [IgnoreDataMember]
public override bool AlwaysScanInternalMetadataPath public override bool AlwaysScanInternalMetadataPath
{ {

View File

@ -431,10 +431,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
{ {
if (state.PlayableStreamFileNames.Count > 0) if (state.PlayableStreamFileNames.Count > 0)
{ {
return MediaEncoder.GetProbeSizeArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol); return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(state.PlayableStreamFileNames.ToArray(), state.InputProtocol);
} }
return MediaEncoder.GetProbeSizeArgument(new[] { state.MediaPath }, state.InputProtocol); return MediaEncoder.GetProbeSizeAndAnalyzeDurationArgument(new[] { state.MediaPath }, state.InputProtocol);
} }
/// <summary> /// <summary>

View File

@ -26,6 +26,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
return string.Format("\"{0}\"", url); return string.Format("\"{0}\"", url);
} }
if (protocol == MediaProtocol.Udp)
{
var url = inputFiles.First();
return string.Format("\"{0}\"", url);
}
return GetConcatInputArgument(inputFiles); return GetConcatInputArgument(inputFiles);
} }
@ -74,9 +80,14 @@ namespace MediaBrowser.MediaEncoding.Encoder
return path.Replace("\"", "\\\""); return path.Replace("\"", "\\\"");
} }
public static string GetProbeSizeArgument(bool isDvd) public static string GetProbeSizeArgument(int numInputFiles)
{ {
return isDvd ? "-probesize 1G -analyzeduration 200M" : ""; return numInputFiles > 1 ? "-probesize 1G" : "";
}
public static string GetAnalyzeDurationArgument(int numInputFiles)
{
return numInputFiles > 1 ? "-analyzeduration 200M" : "";
} }
} }
} }

View File

@ -426,10 +426,24 @@ namespace MediaBrowser.MediaEncoding.Encoder
var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.InputPath, request.Protocol, request.MountedIso, request.PlayableStreamFileNames); var inputFiles = MediaEncoderHelpers.GetInputArgument(FileSystem, request.InputPath, request.Protocol, request.MountedIso, request.PlayableStreamFileNames);
var probeSizeArgument = GetProbeSizeArgument(inputFiles, request.Protocol); var probeSize = EncodingUtils.GetProbeSizeArgument(inputFiles.Length);
string analyzeDuration;
if (request.AnalyzeDurationSections > 0)
{
analyzeDuration = "-analyzeduration " +
(request.AnalyzeDurationSections*1000000).ToString(CultureInfo.InvariantCulture);
}
else
{
analyzeDuration = EncodingUtils.GetAnalyzeDurationArgument(inputFiles.Length);
}
probeSize = probeSize + " " + analyzeDuration;
probeSize = probeSize.Trim();
return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters,
probeSizeArgument, request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken); probeSize, request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken);
} }
/// <summary> /// <summary>
@ -450,9 +464,23 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <param name="inputFiles">The input files.</param> /// <param name="inputFiles">The input files.</param>
/// <param name="protocol">The protocol.</param> /// <param name="protocol">The protocol.</param>
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
public string GetProbeSizeArgument(string[] inputFiles, MediaProtocol protocol) public string GetProbeSizeAndAnalyzeDurationArgument(string[] inputFiles, MediaProtocol protocol)
{ {
return EncodingUtils.GetProbeSizeArgument(inputFiles.Length > 1); var results = new List<string>();
var probeSize = EncodingUtils.GetProbeSizeArgument(inputFiles.Length);
var analyzeDuration = EncodingUtils.GetAnalyzeDurationArgument(inputFiles.Length);
if (!string.IsNullOrWhiteSpace(probeSize))
{
results.Add(probeSize);
}
if (!string.IsNullOrWhiteSpace(analyzeDuration))
{
results.Add(analyzeDuration);
}
return string.Join(" ", results.ToArray());
} }
/// <summary> /// <summary>
@ -871,7 +899,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
var args = useIFrame ? string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) : var args = useIFrame ? string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}{4}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg, thumbnail) :
string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg); string.Format("-i {0}{3} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg);
var probeSize = GetProbeSizeArgument(new[] { inputPath }, protocol); var probeSize = GetProbeSizeAndAnalyzeDurationArgument(new[] { inputPath }, protocol);
if (!string.IsNullOrEmpty(probeSize)) if (!string.IsNullOrEmpty(probeSize))
{ {
@ -982,7 +1010,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf); var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf);
var probeSize = GetProbeSizeArgument(new[] { inputArgument }, protocol); var probeSize = GetProbeSizeAndAnalyzeDurationArgument(new[] { inputArgument }, protocol);
if (!string.IsNullOrEmpty(probeSize)) if (!string.IsNullOrEmpty(probeSize))
{ {

View File

@ -5,6 +5,7 @@ namespace MediaBrowser.Model.MediaInfo
File = 0, File = 0,
Http = 1, Http = 1,
Rtmp = 2, Rtmp = 2,
Rtsp = 3 Rtsp = 3,
Udp = 4
} }
} }

View File

@ -598,7 +598,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.Altitude = item.Altitude; dto.Altitude = item.Altitude;
dto.IsoSpeedRating = item.IsoSpeedRating; dto.IsoSpeedRating = item.IsoSpeedRating;
var album = item.Album; var album = item.AlbumEntity;
if (album != null) if (album != null)
{ {

View File

@ -269,9 +269,10 @@ namespace MediaBrowser.Server.Implementations.Library
positionTicks = 0; positionTicks = 0;
} }
if (item is Audio) if (!item.SupportsPlayedStatus)
{ {
positionTicks = 0; positionTicks = 0;
data.Played = false;
} }
data.PlaybackPositionTicks = positionTicks; data.PlaybackPositionTicks = positionTicks;

View File

@ -27,6 +27,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml; using System.Xml;
using CommonIO; using CommonIO;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
@ -59,8 +60,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public static EmbyTV Current; public static EmbyTV Current;
public event EventHandler DataSourceChanged { add { } remove { } } public event EventHandler DataSourceChanged;
public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged { add { } remove { } } public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged;
private readonly ConcurrentDictionary<string, ActiveRecordingInfo> _activeRecordings = private readonly ConcurrentDictionary<string, ActiveRecordingInfo> _activeRecordings =
new ConcurrentDictionary<string, ActiveRecordingInfo>(StringComparer.OrdinalIgnoreCase); new ConcurrentDictionary<string, ActiveRecordingInfo>(StringComparer.OrdinalIgnoreCase);
@ -1009,7 +1010,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken) public async Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken)
{ {
ActiveRecordingInfo info; ActiveRecordingInfo info;
@ -1017,9 +1018,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
if (_activeRecordings.TryGetValue(recordingId, out info)) if (_activeRecordings.TryGetValue(recordingId, out info))
{ {
return Task.FromResult(new List<MediaSourceInfo> var stream = new MediaSourceInfo
{
new MediaSourceInfo
{ {
Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream", Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream",
Id = recordingId, Id = recordingId,
@ -1031,8 +1030,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
RequiresClosing = false, RequiresClosing = false,
Protocol = Model.MediaInfo.MediaProtocol.Http, Protocol = Model.MediaInfo.MediaProtocol.Http,
BufferMs = 0 BufferMs = 0
} };
});
var isAudio = false;
await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
return new List<MediaSourceInfo>
{
stream
};
} }
throw new FileNotFoundException(); throw new FileNotFoundException();
@ -1258,6 +1264,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
string liveStreamId = null; string liveStreamId = null;
OnRecordingStatusChanged();
try try
{ {
var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false); var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
@ -1353,6 +1361,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{ {
_timerProvider.Delete(timer); _timerProvider.Delete(timer);
} }
OnRecordingStatusChanged();
}
private void OnRecordingStatusChanged()
{
EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
{
}, _logger);
} }
private async void EnforceKeepUpTo(TimerInfo timer) private async void EnforceKeepUpTo(TimerInfo timer)

View File

@ -0,0 +1,110 @@
using System;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.LiveTv
{
public class LiveStreamHelper
{
private readonly IMediaEncoder _mediaEncoder;
private readonly ILogger _logger;
public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger)
{
_mediaEncoder = mediaEncoder;
_logger = logger;
}
public async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
{
var originalRuntime = mediaSource.RunTimeTicks;
var now = DateTime.UtcNow;
var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
{
InputPath = mediaSource.Path,
Protocol = mediaSource.Protocol,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false,
AnalyzeDurationSections = 2
}, cancellationToken).ConfigureAwait(false);
_logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture));
mediaSource.Bitrate = info.Bitrate;
mediaSource.Container = info.Container;
mediaSource.Formats = info.Formats;
mediaSource.MediaStreams = info.MediaStreams;
mediaSource.RunTimeTicks = info.RunTimeTicks;
mediaSource.Size = info.Size;
mediaSource.Timestamp = info.Timestamp;
mediaSource.Video3DFormat = info.Video3DFormat;
mediaSource.VideoType = info.VideoType;
mediaSource.DefaultSubtitleStreamIndex = null;
// Null this out so that it will be treated like a live stream
if (!originalRuntime.HasValue)
{
mediaSource.RunTimeTicks = null;
}
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1)
{
mediaSource.DefaultAudioStreamIndex = null;
}
else
{
mediaSource.DefaultAudioStreamIndex = audioStream.Index;
}
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
if (videoStream != null)
{
if (!videoStream.BitRate.HasValue)
{
var width = videoStream.Width ?? 1920;
if (width >= 1900)
{
videoStream.BitRate = 8000000;
}
else if (width >= 1260)
{
videoStream.BitRate = 3000000;
}
else if (width >= 700)
{
videoStream.BitRate = 1000000;
}
}
// This is coming up false and preventing stream copy
videoStream.IsAVC = null;
}
// Try to estimate this
if (!mediaSource.Bitrate.HasValue)
{
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
if (total > 0)
{
mediaSource.Bitrate = total;
}
}
}
}
}

View File

@ -121,9 +121,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var service in _services) foreach (var service in _services)
{ {
service.DataSourceChanged += service_DataSourceChanged; service.DataSourceChanged += service_DataSourceChanged;
service.RecordingStatusChanged += Service_RecordingStatusChanged;
} }
} }
private void Service_RecordingStatusChanged(object sender, RecordingStatusChangedEventArgs e)
{
_lastRecordingRefreshTime = DateTime.MinValue;
}
public List<ITunerHost> TunerHosts public List<ITunerHost> TunerHosts
{ {
get { return _tunerHosts; } get { return _tunerHosts; }
@ -2299,6 +2305,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false); var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false);
info.RecordAnyChannel = true;
info.RecordAnyTime = true;
info.Days = new List<DayOfWeek>
{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
info.Id = null; info.Id = null;
return new Tuple<SeriesTimerInfo, ILiveTvService>(info, service); return new Tuple<SeriesTimerInfo, ILiveTvService>(info, service);

View File

@ -146,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
} }
else else
{ {
await AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false); await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -216,92 +216,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
} }
} }
private async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
{
var originalRuntime = mediaSource.RunTimeTicks;
var now = DateTime.UtcNow;
var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
{
InputPath = mediaSource.Path,
Protocol = mediaSource.Protocol,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false
}, cancellationToken).ConfigureAwait(false);
_logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture));
mediaSource.Bitrate = info.Bitrate;
mediaSource.Container = info.Container;
mediaSource.Formats = info.Formats;
mediaSource.MediaStreams = info.MediaStreams;
mediaSource.RunTimeTicks = info.RunTimeTicks;
mediaSource.Size = info.Size;
mediaSource.Timestamp = info.Timestamp;
mediaSource.Video3DFormat = info.Video3DFormat;
mediaSource.VideoType = info.VideoType;
mediaSource.DefaultSubtitleStreamIndex = null;
// Null this out so that it will be treated like a live stream
if (!originalRuntime.HasValue)
{
mediaSource.RunTimeTicks = null;
}
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1)
{
mediaSource.DefaultAudioStreamIndex = null;
}
else
{
mediaSource.DefaultAudioStreamIndex = audioStream.Index;
}
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
if (videoStream != null)
{
if (!videoStream.BitRate.HasValue)
{
var width = videoStream.Width ?? 1920;
if (width >= 1900)
{
videoStream.BitRate = 8000000;
}
else if (width >= 1260)
{
videoStream.BitRate = 3000000;
}
else if (width >= 700)
{
videoStream.BitRate = 1000000;
}
}
// This is coming up false and preventing stream copy
videoStream.IsAVC = null;
}
// Try to estimate this
if (!mediaSource.Bitrate.HasValue)
{
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
if (total > 0)
{
mediaSource.Bitrate = total;
}
}
}
public Task CloseMediaSource(string liveStreamId) public Task CloseMediaSource(string liveStreamId)
{ {
return _liveTvManager.CloseLiveStream(liveStreamId); return _liveTvManager.CloseLiveStream(liveStreamId);

View File

@ -234,6 +234,7 @@
<Compile Include="LiveTv\EmbyTV\TimerManager.cs" /> <Compile Include="LiveTv\EmbyTV\TimerManager.cs" />
<Compile Include="LiveTv\Listings\SchedulesDirect.cs" /> <Compile Include="LiveTv\Listings\SchedulesDirect.cs" />
<Compile Include="LiveTv\Listings\XmlTvListingsProvider.cs" /> <Compile Include="LiveTv\Listings\XmlTvListingsProvider.cs" />
<Compile Include="LiveTv\LiveStreamHelper.cs" />
<Compile Include="LiveTv\LiveTvConfigurationFactory.cs" /> <Compile Include="LiveTv\LiveTvConfigurationFactory.cs" />
<Compile Include="LiveTv\LiveTvDtoService.cs" /> <Compile Include="LiveTv\LiveTvDtoService.cs" />
<Compile Include="LiveTv\LiveTvManager.cs" /> <Compile Include="LiveTv\LiveTvManager.cs" />

View File

@ -633,10 +633,14 @@ namespace MediaBrowser.Server.Implementations.Session
data.PlayCount++; data.PlayCount++;
data.LastPlayedDate = DateTime.UtcNow; data.LastPlayedDate = DateTime.UtcNow;
if (!(item is Video)) if (!(item is Video) && item.SupportsPlayedStatus)
{ {
data.Played = true; data.Played = true;
} }
else
{
data.Played = false;
}
await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false); await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false);
} }
@ -851,7 +855,7 @@ namespace MediaBrowser.Server.Implementations.Session
{ {
// If the client isn't able to report this, then we'll just have to make an assumption // If the client isn't able to report this, then we'll just have to make an assumption
data.PlayCount++; data.PlayCount++;
data.Played = true; data.Played = item.SupportsPlayedStatus;
data.PlaybackPositionTicks = 0; data.PlaybackPositionTicks = 0;
playedToCompletion = true; playedToCompletion = true;
} }

View File

@ -704,7 +704,7 @@ namespace MediaBrowser.ServerApplication
WindowStyle = ProcessWindowStyle.Hidden, WindowStyle = ProcessWindowStyle.Hidden,
Verb = "runas", Verb = "runas",
ErrorDialog = false, ErrorDialog = false,
Arguments = String.Format("/c sc stop {0} & sc start {0}", BackgroundService.GetExistingServiceName()) Arguments = String.Format("/c sc stop {0} & sc start {0} & sc start {0}", BackgroundService.GetExistingServiceName())
}; };
Process.Start(startInfo); Process.Start(startInfo);
} }

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common.Internal</id> <id>MediaBrowser.Common.Internal</id>
<version>3.0.661</version> <version>3.0.662</version>
<title>MediaBrowser.Common.Internal</title> <title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors> <authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description> <description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Emby 2013</copyright> <copyright>Copyright © Emby 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.661" /> <dependency id="MediaBrowser.Common" version="3.0.662" />
<dependency id="NLog" version="4.3.8" /> <dependency id="NLog" version="4.3.8" />
<dependency id="SimpleInjector" version="3.2.2" /> <dependency id="SimpleInjector" version="3.2.2" />
</dependencies> </dependencies>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common</id> <id>MediaBrowser.Common</id>
<version>3.0.661</version> <version>3.0.662</version>
<title>MediaBrowser.Common</title> <title>MediaBrowser.Common</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Server.Core</id> <id>MediaBrowser.Server.Core</id>
<version>3.0.661</version> <version>3.0.662</version>
<title>Media Browser.Server.Core</title> <title>Media Browser.Server.Core</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Emby Server.</description> <description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright> <copyright>Copyright © Emby 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.661" /> <dependency id="MediaBrowser.Common" version="3.0.662" />
<dependency id="Interfaces.IO" version="1.0.0.5" /> <dependency id="Interfaces.IO" version="1.0.0.5" />
</dependencies> </dependencies>
</metadata> </metadata>