aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api/Playback/BaseStreamingService.cs
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-04-01 18:23:07 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-04-01 18:23:07 -0400
commit21308be83fd8678dc1030c6493762f09828b1d2d (patch)
tree874a75ab8b6ecbe7565edbb42fd56d8c2f800614 /MediaBrowser.Api/Playback/BaseStreamingService.cs
parent4afe2c3f731562efbe42147d1bcbdc0a7542cfeb (diff)
Add latest translations
Diffstat (limited to 'MediaBrowser.Api/Playback/BaseStreamingService.cs')
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs111
1 files changed, 95 insertions, 16 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 6c406a11c..418a9c9ba 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -9,6 +9,7 @@ using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
@@ -247,6 +248,11 @@ namespace MediaBrowser.Api.Playback
}
}
+ if (type == MediaStreamType.Video)
+ {
+ streams = streams.Where(i => !string.Equals(i.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase)).ToList();
+ }
+
if (returnFirstIfNoIndex && type == MediaStreamType.Audio)
{
return streams.FirstOrDefault(i => i.Channels.HasValue && i.Channels.Value > 0) ??
@@ -1018,7 +1024,7 @@ namespace MediaBrowser.Api.Playback
return string.Format(" -b:v {0}", bitrate.Value.ToString(UsCulture));
}
-
+
return string.Format(" -maxrate {0} -bufsize {1}",
bitrate.Value.ToString(UsCulture),
(bitrate.Value * 2).ToString(UsCulture));
@@ -1257,6 +1263,69 @@ namespace MediaBrowser.Api.Playback
}
/// <summary>
+ /// Parses the dlna headers.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ private void ParseDlnaHeaders(StreamRequest request)
+ {
+ if (!request.StartTimeTicks.HasValue)
+ {
+ var timeSeek = GetHeader("TimeSeekRange.dlna.org");
+
+ request.StartTimeTicks = ParseTimeSeekHeader(timeSeek);
+ }
+ }
+
+ /// <summary>
+ /// Parses the time seek header.
+ /// </summary>
+ private long? ParseTimeSeekHeader(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ return null;
+ }
+
+ if (value.IndexOf("npt=", StringComparison.OrdinalIgnoreCase) != 0)
+ {
+ throw new ArgumentException("Invalid timeseek header");
+ }
+ value = value.Substring(4).Split(new[] { '-' }, 2)[0];
+
+ if (value.IndexOf(':') == -1)
+ {
+ // Parses npt times in the format of '417.33'
+ double seconds;
+ if (double.TryParse(value, NumberStyles.Any, UsCulture, out seconds))
+ {
+ return TimeSpan.FromSeconds(seconds).Ticks;
+ }
+
+ throw new ArgumentException("Invalid timeseek header");
+ }
+
+ // Parses npt times in the format of '10:19:25.7'
+ var tokens = value.Split(new[] { ':' }, 3);
+ double secondsSum = 0;
+ var timeFactor = 3600;
+
+ foreach (var time in tokens)
+ {
+ double digit;
+ if (double.TryParse(time, NumberStyles.Any, UsCulture, out digit))
+ {
+ secondsSum += (digit * timeFactor);
+ }
+ else
+ {
+ throw new ArgumentException("Invalid timeseek header");
+ }
+ timeFactor /= 60;
+ }
+ return TimeSpan.FromSeconds(secondsSum).Ticks;
+ }
+
+ /// <summary>
/// Gets the state.
/// </summary>
/// <param name="request">The request.</param>
@@ -1264,6 +1333,8 @@ namespace MediaBrowser.Api.Playback
/// <returns>StreamState.</returns>
protected async Task<StreamState> GetState(StreamRequest request, CancellationToken cancellationToken)
{
+ ParseDlnaHeaders(request);
+
if (!string.IsNullOrWhiteSpace(request.Params))
{
ParseParams(request);
@@ -1509,8 +1580,6 @@ namespace MediaBrowser.Api.Playback
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
{
- var timeSeek = GetHeader("TimeSeekRange.dlna.org");
-
var transferMode = GetHeader("transferMode.dlna.org");
responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*";
@@ -1521,11 +1590,21 @@ namespace MediaBrowser.Api.Playback
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
var orgOp = ";DLNA.ORG_OP=";
- // Time-based seeking currently only possible when transcoding
- orgOp += isStaticallyStreamed ? "0" : "1";
+ if (state.RunTimeTicks.HasValue)
+ {
+ // Time-based seeking currently only possible when transcoding
+ orgOp += isStaticallyStreamed ? "0" : "1";
+
+ // Byte-based seeking only possible when not transcoding
+ orgOp += isStaticallyStreamed || state.TranscodeSeekInfo == TranscodeSeekInfo.Bytes ? "1" : "0";
- // Byte-based seeking only possible when not transcoding
- orgOp += isStaticallyStreamed || state.TranscodeSeekInfo == TranscodeSeekInfo.Bytes ? "1" : "0";
+ AddTimeSeekResponseHeaders(state, responseHeaders);
+ }
+ else
+ {
+ // No seeking is available if we don't know the content runtime
+ orgOp += "00";
+ }
// 0 = native, 1 = transcoded
var orgCi = isStaticallyStreamed ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
@@ -1568,15 +1647,6 @@ namespace MediaBrowser.Api.Playback
{
contentFeatures = "DLNA.ORG_PN=MPEG_PS_PAL";
}
- //else if (string.Equals(extension, ".wmv", StringComparison.OrdinalIgnoreCase))
- //{
- // contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
- //}
- //else if (string.Equals(extension, ".asf", StringComparison.OrdinalIgnoreCase))
- //{
- // // ??
- // contentFeatures = "DLNA.ORG_PN=WMVHIGH_BASE";
- //}
if (!string.IsNullOrEmpty(contentFeatures))
{
@@ -1589,6 +1659,15 @@ namespace MediaBrowser.Api.Playback
}
}
+ private void AddTimeSeekResponseHeaders(StreamState state, IDictionary<string, string> responseHeaders)
+ {
+ var runtimeSeconds = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalSeconds.ToString(UsCulture);
+ var startSeconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds.ToString(UsCulture);
+
+ responseHeaders["TimeSeekRange.dlna.org"] = string.Format("npt={0}-{1}/{1}", startSeconds, runtimeSeconds);
+ responseHeaders["X-AvailableSeekRange"] = string.Format("1 npt={0}-{1}", startSeconds, runtimeSeconds);
+ }
+
/// <summary>
/// Enforces the resolution limit.
/// </summary>