From eca1ba0b12da195dff3c31ffb799e4e3a7b5b5b9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 24 Apr 2014 22:00:19 -0400 Subject: [PATCH] fixes #797 - Determine mpeg2ts timestamp info --- .../Playback/BaseStreamingService.cs | 3 ++ MediaBrowser.Api/Playback/StreamState.cs | 17 +++--- MediaBrowser.Controller/Entities/Video.cs | 8 +++ .../MediaBrowser.Model.Portable.csproj | 3 -- .../MediaBrowser.Model.net35.csproj | 3 -- .../Configuration/ManualLoginCategory.cs | 9 ---- .../Configuration/ServerConfiguration.cs | 6 +-- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 2 + .../Dlna/ContentFeatureBuilder.cs | 2 + MediaBrowser.Model/Dlna/DeviceProfile.cs | 2 + MediaBrowser.Model/Dlna/MediaFormatProfile.cs | 7 --- .../Dlna/MediaFormatProfileResolver.cs | 18 ++++--- MediaBrowser.Model/Dlna/StreamBuilder.cs | 3 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 11 ++-- MediaBrowser.Model/Dto/MediaVersionInfo.cs | 3 ++ MediaBrowser.Model/Entities/MediaStream.cs | 7 --- MediaBrowser.Model/MediaBrowser.Model.csproj | 1 - .../MediaInfo/BlurayDiscInfo.cs | 7 +++ .../MediaInfo/FFProbeVideoInfo.cs | 52 +++++++++++++++++++ .../Dto/DtoService.cs | 3 +- .../Localization/Server/server.json | 13 ++++- 21 files changed, 125 insertions(+), 55 deletions(-) delete mode 100644 MediaBrowser.Model/Configuration/ManualLoginCategory.cs diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index a4abb129b3..ac7dab0803 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1435,6 +1435,9 @@ namespace MediaBrowser.Api.Playback state.PlayableStreamFileNames = video.PlayableStreamFileNames == null ? new List() : video.PlayableStreamFileNames.ToList(); + + state.DeInterlace = string.Equals(video.Container, "wtv", StringComparison.OrdinalIgnoreCase); + state.InputTimestamp = video.Timestamp; } state.RunTimeTicks = item.RunTimeTicks; diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index fe9199244b..0514132592 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Threading; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Api.Playback { @@ -26,7 +27,7 @@ namespace MediaBrowser.Api.Playback { get { return Request as VideoStreamRequest; } } - + /// /// Gets or sets the log file stream. /// @@ -77,19 +78,21 @@ namespace MediaBrowser.Api.Playback public string InputAudioSync { get; set; } public string InputVideoSync { get; set; } - + public bool DeInterlace { get; set; } public bool ReadInputAtNativeFramerate { get; set; } public string InputFormat { get; set; } public string InputVideoCodec { get; set; } public string InputAudioCodec { get; set; } + public TransportStreamTimestamp InputTimestamp { get; set; } + public string MimeType { get; set; } public bool EstimateContentLength { get; set; } public bool EnableMpegtsM2TsMode { get; set; } public TranscodeSeekInfo TranscodeSeekInfo { get; set; } - + public string GetMimeType(string outputPath) { if (!string.IsNullOrEmpty(MimeType)) @@ -269,11 +272,13 @@ namespace MediaBrowser.Api.Playback { get { - var stream = VideoStream; + var defaultValue = string.Equals(OutputContainer, "m2ts", StringComparison.OrdinalIgnoreCase) ? + TransportStreamTimestamp.VALID : + TransportStreamTimestamp.NONE; return !Request.Static - ? TransportStreamTimestamp.VALID - : stream == null ? TransportStreamTimestamp.VALID : stream.Timestamp; + ? defaultValue + : InputTimestamp; } } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 2d926e2363..bfb306b31e 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; +using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; using System; using System.Collections; @@ -11,6 +12,7 @@ using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Controller.Entities { @@ -31,6 +33,12 @@ namespace MediaBrowser.Controller.Entities public string Container { get; set; } public int? TotalBitrate { get; set; } + /// + /// Gets or sets the timestamp. + /// + /// The timestamp. + public TransportStreamTimestamp Timestamp { get; set; } + public Video() { PlayableStreamFileNames = new List(); diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 56baaec0a6..2ccd364d56 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -86,9 +86,6 @@ Configuration\DlnaOptions.cs - - Configuration\ManualLoginCategory.cs - Configuration\MetadataOptions.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index 37fb68ad6d..c3eb6b11d3 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -73,9 +73,6 @@ Configuration\DlnaOptions.cs - - Configuration\ManualLoginCategory.cs - Configuration\MetadataOptions.cs diff --git a/MediaBrowser.Model/Configuration/ManualLoginCategory.cs b/MediaBrowser.Model/Configuration/ManualLoginCategory.cs deleted file mode 100644 index 37b6d6c82f..0000000000 --- a/MediaBrowser.Model/Configuration/ManualLoginCategory.cs +++ /dev/null @@ -1,9 +0,0 @@ - -namespace MediaBrowser.Model.Configuration -{ - public enum ManualLoginCategory - { - Mobile, - MediaBrowserTheater - } -} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index ca5f569ed9..325db34edb 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -168,8 +168,6 @@ namespace MediaBrowser.Model.Configuration /// The dashboard source path. public string DashboardSourcePath { get; set; } - public ManualLoginCategory[] ManualLoginClients { get; set; } - /// /// Gets or sets a value indicating whether [enable tv db updates]. /// @@ -178,6 +176,9 @@ namespace MediaBrowser.Model.Configuration public bool EnableTmdbUpdates { get; set; } public bool EnableFanArtUpdates { get; set; } + public bool RequireManualLoginForMobileApps { get; set; } + public bool RequireManualLoginForOtherApps { get; set; } + /// /// Gets or sets the image saving convention. /// @@ -256,7 +257,6 @@ namespace MediaBrowser.Model.Configuration EnableInternetProviders = true; //initial installs will need these - ManualLoginClients = new ManualLoginCategory[] { }; PathSubstitutions = new PathSubstitution[] { }; MetadataRefreshDays = 30; diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index 292ca21487..2e337982fc 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -1,5 +1,7 @@ using System; using System.Globalization; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna { diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index b2bbe3b14c..f3357dc5ba 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna { diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index f6ca6b48f1..70285078a4 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Serialization; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna { diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfile.cs b/MediaBrowser.Model/Dlna/MediaFormatProfile.cs index 596985bdc0..f3d04335fb 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfile.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfile.cs @@ -110,11 +110,4 @@ namespace MediaBrowser.Model.Dlna MPEG4_H263_3GPP_P0_L10_AMR, MPEG4_H263_MP4_P0_L10_AAC } - - public enum TransportStreamTimestamp - { - NONE, - ZERO, - VALID - } } diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs index 9337a6c95f..589dc33766 100644 --- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs +++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna { @@ -147,14 +149,14 @@ namespace MediaBrowser.Model.Dlna } else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "msmpeg4", StringComparison.OrdinalIgnoreCase)) { - // if (audioCodec == AudioCodec.AAC) - // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_AAC%s", cast(Object[])[ suffix ]))); - // if (audioCodec == AudioCodec.MP3) - // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_MPEG1_L3%s", cast(Object[])[ suffix ]))); - // if (audioCodec == AudioCodec.MP2) - // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_MPEG2_L2%s", cast(Object[])[ suffix ]))); - // if ((audioCodec is null) || (audioCodec == AudioCodec.AC3)) { - // return Collections.singletonList(MediaFormatProfile.valueOf(String.format("MPEG4_P2_TS_ASP_AC3%s", cast(Object[])[ suffix ]))); + if (string.Equals(audioCodec, "aac", StringComparison.OrdinalIgnoreCase)) + return new[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AAC{0}", suffix)) }; + if (string.Equals(audioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) + return new[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG1_L3{0}", suffix)) }; + if (string.Equals(audioCodec, "mp2", StringComparison.OrdinalIgnoreCase)) + return new[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_MPEG2_L2{0}", suffix)) }; + if (string.Equals(audioCodec, "ac3", StringComparison.OrdinalIgnoreCase)) + return new[] { ValueOf(string.Format("MPEG4_P2_TS_ASP_AC3{0}", suffix)) }; } return new List(); diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index f3425d2027..13c698dedf 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna { @@ -285,7 +286,7 @@ namespace MediaBrowser.Model.Dlna var audioBitrate = audioStream == null ? null : audioStream.BitRate; var audioChannels = audioStream == null ? null : audioStream.Channels; - var timestamp = videoStream == null ? TransportStreamTimestamp.NONE : videoStream.Timestamp; + var timestamp = videoStream == null ? TransportStreamTimestamp.NONE : mediaSource.Timestamp; var packetLength = videoStream == null ? null : videoStream.PacketLength; // Check container conditions diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 0ab6805e3b..e49c319476 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna { @@ -339,11 +340,13 @@ namespace MediaBrowser.Model.Dlna { get { - var stream = TargetVideoStream; - - return !IsDirectStream + var defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase) ? TransportStreamTimestamp.VALID - : stream == null ? TransportStreamTimestamp.VALID : stream.Timestamp; + : TransportStreamTimestamp.NONE; + + return !IsDirectStream + ? defaultValue + : MediaSource == null ? defaultValue : MediaSource.Timestamp; } } diff --git a/MediaBrowser.Model/Dto/MediaVersionInfo.cs b/MediaBrowser.Model/Dto/MediaVersionInfo.cs index cfef83d2c2..e2b197213a 100644 --- a/MediaBrowser.Model/Dto/MediaVersionInfo.cs +++ b/MediaBrowser.Model/Dto/MediaVersionInfo.cs @@ -1,5 +1,6 @@ using MediaBrowser.Model.Entities; using System.Collections.Generic; +using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dto { @@ -30,6 +31,8 @@ namespace MediaBrowser.Model.Dto public int? Bitrate { get; set; } + public TransportStreamTimestamp Timestamp { get; set; } + public MediaSourceInfo() { Formats = new List(); diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 920112d02e..d54e3c0ef9 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Diagnostics; -using MediaBrowser.Model.Dlna; namespace MediaBrowser.Model.Entities { @@ -52,12 +51,6 @@ namespace MediaBrowser.Model.Entities /// The length of the packet. public int? PacketLength { get; set; } - /// - /// Gets or sets the timestamp. - /// - /// The timestamp. - public TransportStreamTimestamp Timestamp { get; set; } - /// /// Gets or sets the channels. /// diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 1ae0833fb7..c22688b332 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -62,7 +62,6 @@ - diff --git a/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs b/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs index 963e8dd95e..35000ca398 100644 --- a/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs +++ b/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs @@ -34,4 +34,11 @@ namespace MediaBrowser.Model.MediaInfo /// The chapters. public List Chapters { get; set; } } + + public enum TransportStreamTimestamp + { + NONE, + ZERO, + VALID + } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 2d29286d39..4f47edee0f 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -1,11 +1,13 @@ using DvdLib.Ifo; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; @@ -33,6 +35,7 @@ namespace MediaBrowser.Providers.MediaInfo private readonly IApplicationPaths _appPaths; private readonly IJsonSerializer _json; private readonly IEncodingManager _encodingManager; + private readonly IFileSystem _fileSystem; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); @@ -215,6 +218,8 @@ namespace MediaBrowser.Providers.MediaInfo video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle); + ExtractTimestamp(video); + await _encodingManager.RefreshChapterImages(new ChapterImageRefreshOptions { Chapters = chapters, @@ -568,6 +573,53 @@ namespace MediaBrowser.Providers.MediaInfo } } + private void ExtractTimestamp(Video video) + { + if (video.VideoType == VideoType.VideoFile) + { + if (string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) || + string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) || + string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase)) + { + try + { + video.Timestamp = GetMpegTimestamp(video.Path); + } + catch (Exception ex) + { + _logger.ErrorException("Error extracting timestamp info from {0}", ex, video.Path); + } + } + } + } + + private TransportStreamTimestamp GetMpegTimestamp(string path) + { + var packetBuffer = new byte['Å']; + + using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + fs.Read(packetBuffer, 0, packetBuffer.Length); + } + + if (packetBuffer[0] == 71) + { + return TransportStreamTimestamp.NONE; + } + + if ((packetBuffer[4] == 71) && (packetBuffer['Ä'] == 71)) + { + if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0)) + { + return TransportStreamTimestamp.ZERO; + } + + return TransportStreamTimestamp.VALID; + } + + return TransportStreamTimestamp.NONE; + } + private void FetchFromDvdLib(Video item, IIsoMount mount) { var path = mount == null ? item.Path : mount.MountedPath; diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index d32e6ad0e5..ee6bbb04f0 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1237,7 +1237,8 @@ namespace MediaBrowser.Server.Implementations.Dto VideoType = i.VideoType, Container = i.Container, Size = i.Size, - Formats = (i.FormatName ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList() + Formats = (i.FormatName ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(), + Timestamp = i.Timestamp }; if (string.IsNullOrEmpty(info.Container)) diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 9eb289fe83..01a997cca5 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -276,7 +276,7 @@ "HeaderPleaseSignIn": "Please sign in", "LabelUser": "User:", "LabelPassword": "Password:", - "ButtonManualLogin": "Manual Login:", + "ButtonManualLogin": "Manual Login", "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.", "TabGuide": "Guide", "TabChannels": "Channels", @@ -545,5 +545,14 @@ "LabelDefaultUser": "Default user:", "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.", "TitleDlna": "DLNA", - "HeaderServerSettings": "Server Settings" + "HeaderServerSettings": "Server Settings", + "LabelWeatherDisplayLocation": "Weather display location:", + "LabelWeatherDisplayLocationHelp": "US zip code / City, State, Country / City, Country", + "LabelWeatherDisplayUnit": "Weather display unit:", + "OptionCelsius": "Celsius", + "OptionFahrenheit": "Fahrenheit", + "HeaderRequireManualLogin": "Require manual username entry for:", + "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.", + "OptionOtherApps": "Other apps", + "OptionMobileApps": "Mobile apps" } \ No newline at end of file