瀏覽代碼

detect anamorphic video

Luke Pulverenti 11 年之前
父節點
當前提交
3b30a2aee0

+ 4 - 2
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -1788,7 +1788,8 @@ namespace MediaBrowser.Api.Playback
                 state.TargetVideoLevel,
                 state.TargetFramerate,
                 state.TargetPacketLength,
-                state.TargetTimestamp);
+                state.TargetTimestamp,
+                state.IsTargetAnamorphic);
 
             if (mediaProfile != null)
             {
@@ -1885,7 +1886,8 @@ namespace MediaBrowser.Api.Playback
                     state.TargetVideoLevel,
                     state.TargetFramerate,
                     state.TargetPacketLength,
-                    state.TranscodeSeekInfo
+                    state.TranscodeSeekInfo,
+                    state.IsTargetAnamorphic
                     );
             }
 

+ 1 - 1
MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs

@@ -313,7 +313,7 @@ namespace MediaBrowser.Api.Playback.Hls
             // See if we can save come cpu cycles by avoiding encoding
             if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
             {
-                return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf h264_mp4toannexb" : "-codec:v:0 copy";
+                return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf h264_mp4toannexb -bsf dump_extra" : "-codec:v:0 copy";
             }
 
             var keyFrameArg = state.ReadInputAtNativeFramerate ?

+ 1 - 1
MediaBrowser.Api/Playback/Hls/VideoHlsService.cs

@@ -160,7 +160,7 @@ namespace MediaBrowser.Api.Playback.Hls
             // See if we can save come cpu cycles by avoiding encoding
             if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
             {
-                return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf h264_mp4toannexb" : "-codec:v:0 copy";
+                return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf h264_mp4toannexb -bsf dump_extra" : "-codec:v:0 copy";
             }
 
             var keyFrameArg = state.ReadInputAtNativeFramerate ?

+ 1 - 1
MediaBrowser.Api/Playback/Progressive/VideoService.cs

@@ -140,7 +140,7 @@ namespace MediaBrowser.Api.Playback.Progressive
             // See if we can save come cpu cycles by avoiding encoding
             if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
             {
-                return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
+                return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb -bsf dump_extra" : args;
             }
 
             const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";

+ 12 - 1
MediaBrowser.Api/Playback/StreamState.cs

@@ -2,7 +2,6 @@
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Drawing;
-using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
@@ -330,5 +329,17 @@ namespace MediaBrowser.Api.Playback
             }
         }
 
+        public bool? IsTargetAnamorphic
+        {
+            get
+            {
+                if (Request.Static)
+                {
+                    return VideoStream == null ? null : VideoStream.IsAnamorphic;
+                }
+
+                return false;
+            }
+        }
     }
 }

+ 3 - 0
MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs

@@ -126,6 +126,9 @@ namespace MediaBrowser.Controller.MediaEncoding
                 stream.RealFrameRate = GetFrameRate(streamInfo.r_frame_rate);
 
                 stream.BitDepth = GetBitDepth(stream.PixelFormat);
+
+                stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1",
+                    StringComparison.OrdinalIgnoreCase);
             }
             else
             {

+ 0 - 2
MediaBrowser.Dlna/ConnectionManager/ControlHandler.cs

@@ -6,13 +6,11 @@ using MediaBrowser.Model.Dlna;
 using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Generic;
-using System.Globalization;
 
 namespace MediaBrowser.Dlna.ConnectionManager
 {
     public class ControlHandler : BaseControlHandler
     {
-        private readonly CultureInfo _usCulture = new CultureInfo("en-US");
         private readonly DeviceProfile _profile;
 
         public ControlHandler(ILogger logger, DeviceProfile profile, IServerConfigurationManager config)

+ 4 - 2
MediaBrowser.Dlna/Didl/DidlBuilder.cs

@@ -179,7 +179,8 @@ namespace MediaBrowser.Dlna.Didl
                 streamInfo.TargetVideoLevel,
                 streamInfo.TargetFramerate,
                 streamInfo.TargetPacketLength,
-                streamInfo.TargetTimestamp);
+                streamInfo.TargetTimestamp,
+                streamInfo.IsTargetAnamorphic);
 
             var filename = url.Substring(0, url.IndexOf('?'));
 
@@ -203,7 +204,8 @@ namespace MediaBrowser.Dlna.Didl
                 streamInfo.TargetVideoLevel,
                 streamInfo.TargetFramerate,
                 streamInfo.TargetPacketLength,
-                streamInfo.TranscodeSeekInfo);
+                streamInfo.TranscodeSeekInfo,
+                streamInfo.IsTargetAnamorphic);
 
             res.SetAttribute("protocolInfo", String.Format(
                 "http-get:*:{0}:{1}",

+ 2 - 1
MediaBrowser.Dlna/PlayTo/PlayToController.cs

@@ -514,7 +514,8 @@ namespace MediaBrowser.Dlna.PlayTo
                     streamInfo.TargetVideoLevel,
                     streamInfo.TargetFramerate,
                     streamInfo.TargetPacketLength,
-                    streamInfo.TranscodeSeekInfo);
+                    streamInfo.TranscodeSeekInfo,
+                    streamInfo.IsTargetAnamorphic);
             }
 
             return null;

+ 1 - 1
MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs

@@ -83,7 +83,7 @@ namespace MediaBrowser.Dlna.Profiles
                     Container = "ts",
                     Type = DlnaProfileType.Video,
                     VideoCodec = "mpeg1video,mpeg2video,h264,vc1",
-                    AudioCodec = "ac3,dca,mp2,mp3"
+                    AudioCodec = "ac3,dca,mp2,mp3,aac"
                 },
 
                 new DirectPlayProfile

+ 14 - 0
MediaBrowser.Dlna/Profiles/WindowsPhoneProfile.cs

@@ -93,6 +93,20 @@ namespace MediaBrowser.Dlna.Profiles
 
             CodecProfiles = new[]
             {
+                new CodecProfile
+                {
+                    Type = CodecType.Video,
+                    Conditions = new []
+                    {
+                        new ProfileCondition
+                        {
+                            Condition = ProfileConditionType.NotEquals,
+                            Property = ProfileConditionValue.IsAnamorphic,
+                            Value = "true"
+                        }
+                    }
+                },
+
                 new CodecProfile
                 {
                     Type = CodecType.Video,

+ 1 - 1
MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml

@@ -34,7 +34,7 @@
     <DirectPlayProfile container="avi" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
     <DirectPlayProfile container="mpeg" audioCodec="ac3,dca,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video" type="Video" />
     <DirectPlayProfile container="mkv" audioCodec="ac3,dca,aac,mp2,mp3,pcm" videoCodec="mpeg1video,mpeg2video,mpeg4,h264,vc1" type="Video" />
-    <DirectPlayProfile container="ts" audioCodec="ac3,dca,mp2,mp3" videoCodec="mpeg1video,mpeg2video,h264,vc1" type="Video" />
+    <DirectPlayProfile container="ts" audioCodec="ac3,dca,mp2,mp3,aac" videoCodec="mpeg1video,mpeg2video,h264,vc1" type="Video" />
     <DirectPlayProfile container="mp4,mov" audioCodec="ac3,aac,mp2,mp3" videoCodec="h264,mpeg4" type="Video" />
     <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="vc1" type="Video" />
     <DirectPlayProfile container="asf" audioCodec="mp2,ac3" videoCodec="mpeg2video" type="Video" />

+ 3 - 1
MediaBrowser.Dlna/Service/BaseControlHandler.cs

@@ -92,7 +92,9 @@ namespace MediaBrowser.Dlna.Service
                 Xml = xml,
                 IsSuccessful = true
             };
-            Logger.Debug(xml);
+
+            //Logger.Debug(xml);
+
             controlResponse.Headers.Add("EXT", string.Empty);
 
             return controlResponse;

+ 29 - 1
MediaBrowser.Model/Dlna/ConditionProcessor.cs

@@ -17,7 +17,8 @@ namespace MediaBrowser.Model.Dlna
             double? videoLevel,
             double? videoFramerate,
             int? packetLength,
-            TransportStreamTimestamp? timestamp)
+            TransportStreamTimestamp? timestamp,
+            bool? isAnamorphic)
         {
             switch (condition.Property)
             {
@@ -27,6 +28,8 @@ namespace MediaBrowser.Model.Dlna
                 case ProfileConditionValue.Has64BitOffsets:
                     // TODO: Implement
                     return true;
+                case ProfileConditionValue.IsAnamorphic:
+                    return IsConditionSatisfied(condition, isAnamorphic);
                 case ProfileConditionValue.VideoFramerate:
                     return IsConditionSatisfied(condition, videoFramerate);
                 case ProfileConditionValue.VideoLevel:
@@ -147,6 +150,31 @@ namespace MediaBrowser.Model.Dlna
                     throw new InvalidOperationException("Unexpected ProfileConditionType");
             }
         }
+
+        private bool IsConditionSatisfied(ProfileCondition condition, bool? currentValue)
+        {
+            if (!currentValue.HasValue)
+            {
+                // If the value is unknown, it satisfies if not marked as required
+                return !condition.IsRequired;
+            }
+
+            bool expected;
+            if (BoolHelper.TryParseCultureInvariant(condition.Value, out expected))
+            {
+                switch (condition.Condition)
+                {
+                    case ProfileConditionType.Equals:
+                        return currentValue.Value == expected;
+                    case ProfileConditionType.NotEquals:
+                        return currentValue.Value != expected;
+                    default:
+                        throw new InvalidOperationException("Unexpected ProfileConditionType");
+                }
+            }
+
+            return false;
+        }
         
         private bool IsConditionSatisfied(ProfileCondition condition, double? currentValue)
         {

+ 4 - 2
MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs

@@ -108,7 +108,8 @@ namespace MediaBrowser.Model.Dlna
             double? videoLevel,
             double? videoFramerate,
             int? packetLength,
-            TranscodeSeekInfo transcodeSeekInfo)
+            TranscodeSeekInfo transcodeSeekInfo,
+            bool? isAnamorphic)
         {
             // 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
             string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks.HasValue, isDirectStream, transcodeSeekInfo);
@@ -145,7 +146,8 @@ namespace MediaBrowser.Model.Dlna
                 videoLevel,
                 videoFramerate,
                 packetLength,
-                timestamp);
+                timestamp,
+                isAnamorphic);
 
             string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
 

+ 3 - 2
MediaBrowser.Model/Dlna/DeviceProfile.cs

@@ -269,7 +269,8 @@ namespace MediaBrowser.Model.Dlna
             double? videoLevel,
             double? videoFramerate,
             int? packetLength,
-            TransportStreamTimestamp timestamp)
+            TransportStreamTimestamp timestamp,
+            bool? isAnamorphic)
         {
             container = (container ?? string.Empty).TrimStart('.');
 
@@ -303,7 +304,7 @@ namespace MediaBrowser.Model.Dlna
                 var anyOff = false;
                 foreach (ProfileCondition c in i.Conditions)
                 {
-                    if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))
+                    if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic))
                     {
                         anyOff = true;
                         break;

+ 14 - 13
MediaBrowser.Model/Dlna/ProfileConditionValue.cs

@@ -2,18 +2,19 @@
 {
     public enum ProfileConditionValue
     {
-        AudioChannels,
-        AudioBitrate,
-        AudioProfile,
-        Width,
-        Height,
-        Has64BitOffsets,
-        PacketLength,
-        VideoBitDepth,
-        VideoBitrate,
-        VideoFramerate,
-        VideoLevel,
-        VideoProfile,
-        VideoTimestamp
+        AudioChannels = 0,
+        AudioBitrate = 1,
+        AudioProfile = 2,
+        Width = 3,
+        Height = 4,
+        Has64BitOffsets = 5,
+        PacketLength = 6,
+        VideoBitDepth = 7,
+        VideoBitrate = 8,
+        VideoFramerate = 9,
+        VideoLevel = 10,
+        VideoProfile = 11,
+        VideoTimestamp = 12,
+        IsAnamorphic = 13
     }
 }

+ 4 - 2
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -370,6 +370,7 @@ namespace MediaBrowser.Model.Dlna
             double? videoLevel = videoStream == null ? null : videoStream.Level;
             string videoProfile = videoStream == null ? null : videoStream.Profile;
             float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
+            bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic;
 
             int? audioBitrate = audioStream == null ? null : audioStream.BitRate;
             int? audioChannels = audioStream == null ? null : audioStream.Channels;
@@ -381,7 +382,7 @@ namespace MediaBrowser.Model.Dlna
             // Check container conditions
             foreach (ProfileCondition i in conditions)
             {
-                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))
+                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic))
                 {
                     return null;
                 }
@@ -403,7 +404,7 @@ namespace MediaBrowser.Model.Dlna
 
             foreach (ProfileCondition i in conditions)
             {
-                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))
+                if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic))
                 {
                     return null;
                 }
@@ -520,6 +521,7 @@ namespace MediaBrowser.Model.Dlna
                             break;
                         }
                     case ProfileConditionValue.AudioProfile:
+                    case ProfileConditionValue.IsAnamorphic:
                     case ProfileConditionValue.Has64BitOffsets:
                     case ProfileConditionValue.PacketLength:
                     case ProfileConditionValue.VideoTimestamp:

+ 13 - 0
MediaBrowser.Model/Dlna/StreamInfo.cs

@@ -348,6 +348,19 @@ namespace MediaBrowser.Model.Dlna
             }
         }
 
+        public bool? IsTargetAnamorphic
+        {
+            get
+            {
+                if (IsDirectStream)
+                {
+                    return TargetVideoStream == null ? null : TargetVideoStream.IsAnamorphic;
+                }
+
+                return false;
+            }
+        }
+
         public int? TargetWidth
         {
             get

+ 8 - 2
MediaBrowser.Model/Entities/MediaStream.cs

@@ -33,7 +33,7 @@ namespace MediaBrowser.Model.Entities
         /// </summary>
         /// <value>The channel layout.</value>
         public string ChannelLayout { get; set; }
-        
+
         /// <summary>
         /// Gets or sets the bit rate.
         /// </summary>
@@ -155,11 +155,17 @@ namespace MediaBrowser.Model.Entities
         /// </summary>
         /// <value>The pixel format.</value>
         public string PixelFormat { get; set; }
-        
+
         /// <summary>
         /// Gets or sets the level.
         /// </summary>
         /// <value>The level.</value>
         public double? Level { get; set; }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is anamorphic.
+        /// </summary>
+        /// <value><c>true</c> if this instance is anamorphic; otherwise, <c>false</c>.</value>
+        public bool? IsAnamorphic { get; set; }
     }
 }

+ 14 - 0
MediaBrowser.Model/Extensions/DoubleHelper.cs

@@ -18,4 +18,18 @@ namespace MediaBrowser.Model.Extensions
             return double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out result);
         }
     }
+
+    public static class BoolHelper
+    {
+        /// <summary>
+        /// Tries the parse culture invariant.
+        /// </summary>
+        /// <param name="s">The s.</param>
+        /// <param name="result">The result.</param>
+        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
+        public static bool TryParseCultureInvariant(string s, out bool result)
+        {
+            return bool.TryParse(s, out result);
+        }
+    }
 }

+ 6 - 0
MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs

@@ -116,6 +116,12 @@ namespace MediaBrowser.Server.Implementations.Library
                         return true;
                     }
                 }
+
+                // Ignore samples
+                if (filename.IndexOf(".sample.", StringComparison.OrdinalIgnoreCase) != -1)
+                {
+                    return true;
+                }
             }
 
             return false;

+ 40 - 1
MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs

@@ -58,6 +58,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
 
             AddPixelFormatColumnCommand();
             AddBitDepthCommand();
+            AddIsAnamorphicColumn();
 
             PrepareStatements();
 
@@ -126,6 +127,37 @@ namespace MediaBrowser.Server.Implementations.Persistence
             _connection.RunQueries(new[] { builder.ToString() }, _logger);
         }
 
+        private void AddIsAnamorphicColumn()
+        {
+            using (var cmd = _connection.CreateCommand())
+            {
+                cmd.CommandText = "PRAGMA table_info(mediastreams)";
+
+                using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+                {
+                    while (reader.Read())
+                    {
+                        if (!reader.IsDBNull(1))
+                        {
+                            var name = reader.GetString(1);
+
+                            if (string.Equals(name, "IsAnamorphic", StringComparison.OrdinalIgnoreCase))
+                            {
+                                return;
+                            }
+                        }
+                    }
+                }
+            }
+
+            var builder = new StringBuilder();
+
+            builder.AppendLine("alter table mediastreams");
+            builder.AppendLine("add column IsAnamorphic BIT NULL");
+
+            _connection.RunQueries(new[] { builder.ToString() }, _logger);
+        }
+
         private readonly string[] _saveColumns =
         {
             "ItemId",
@@ -150,7 +182,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
             "RealFrameRate",
             "Level",
             "PixelFormat",
-            "BitDepth"
+            "BitDepth",
+            "IsAnamorphic"
         };
 
         /// <summary>
@@ -319,6 +352,11 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 item.BitDepth = reader.GetInt32(22);
             }
 
+            if (!reader.IsDBNull(23))
+            {
+                item.IsAnamorphic = reader.GetBoolean(23);
+            }
+
             return item;
         }
 
@@ -382,6 +420,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
                     _saveStreamCommand.GetParameter(20).Value = stream.Level;
                     _saveStreamCommand.GetParameter(21).Value = stream.PixelFormat;
                     _saveStreamCommand.GetParameter(22).Value = stream.BitDepth;
+                    _saveStreamCommand.GetParameter(23).Value = stream.IsAnamorphic;
 
                     _saveStreamCommand.Transaction = transaction;
                     _saveStreamCommand.ExecuteNonQuery();