diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2015-04-10 15:08:09 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2015-04-10 15:08:09 -0400 |
| commit | 2a681f205aba211d9eaec7866ea2f39f469fba90 (patch) | |
| tree | f4317e16a7402c943b6eee319a84f862dbfd2aaf /MediaBrowser.Api/Playback/BaseStreamingService.cs | |
| parent | fbbab13b3134a0d6179e42fd8dbbc629654c1c28 (diff) | |
capture key frame info
Diffstat (limited to 'MediaBrowser.Api/Playback/BaseStreamingService.cs')
| -rw-r--r-- | MediaBrowser.Api/Playback/BaseStreamingService.cs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 62bee1f9b..728fea0e0 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1705,6 +1705,102 @@ namespace MediaBrowser.Api.Playback { state.OutputAudioCodec = "copy"; } + + if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + var segmentLength = GetSegmentLength(state); + if (segmentLength.HasValue) + { + state.SegmentLength = segmentLength.Value; + } + } + } + + private int? GetSegmentLength(StreamState state) + { + var stream = state.VideoStream; + + if (stream == null) + { + return null; + } + + var frames = stream.KeyFrames; + + if (frames == null || frames.Count < 2) + { + return null; + } + + Logger.Debug("Found keyframes at {0}", string.Join(",", frames.ToArray())); + + var intervals = new List<int>(); + for (var i = 1; i < frames.Count; i++) + { + var start = frames[i - 1]; + var end = frames[i]; + intervals.Add(end - start); + } + + Logger.Debug("Found keyframes intervals {0}", string.Join(",", intervals.ToArray())); + + var results = new List<Tuple<int, int>>(); + + for (var i = 1; i <= 10; i++) + { + var idealMs = i*1000; + + if (intervals.Max() < idealMs - 1000) + { + break; + } + + var segments = PredictStreamCopySegments(intervals, idealMs); + var variance = segments.Select(s => Math.Abs(idealMs - s)).Sum(); + + results.Add(new Tuple<int, int>(i, variance)); + } + + if (results.Count == 0) + { + return null; + } + + return results.OrderBy(i => i.Item2).ThenBy(i => i.Item1).Select(i => i.Item1).First(); + } + + private List<int> PredictStreamCopySegments(List<int> intervals, int idealMs) + { + var segments = new List<int>(); + var currentLength = 0; + + foreach (var interval in intervals) + { + if (currentLength == 0 || (currentLength + interval) <= idealMs) + { + currentLength += interval; + } + + else + { + // The segment will either be above or below the ideal. + // Need to figure out which is preferable + var offset1 = Math.Abs(idealMs - currentLength); + var offset2 = Math.Abs(idealMs - (currentLength + interval)); + + if (offset1 <= offset2) + { + segments.Add(currentLength); + currentLength = interval; + } + else + { + currentLength += interval; + } + } + } + Logger.Debug("Predicted actual segment lengths for length {0}: {1}", idealMs, string.Join(",", segments.ToArray())); + return segments; } private void AttachMediaSourceInfo(StreamState state, |
