detect anamorphic video
This commit is contained in:
parent
414b1251c7
commit
3b30a2aee0
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ?
|
||||
|
|
|
@ -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 ?
|
||||
|
|
|
@ -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))";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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}",
|
||||
|
|
|
@ -514,7 +514,8 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
streamInfo.TargetVideoLevel,
|
||||
streamInfo.TargetFramerate,
|
||||
streamInfo.TargetPacketLength,
|
||||
streamInfo.TranscodeSeekInfo);
|
||||
streamInfo.TranscodeSeekInfo,
|
||||
streamInfo.IsTargetAnamorphic);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,6 +116,12 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore samples
|
||||
if (filename.IndexOf(".sample.", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue
Block a user