2020-04-05 16:10:56 +00:00
#nullable disable
2020-02-04 00:49:27 +00:00
#pragma warning disable CS1591
2019-01-13 20:02:23 +00:00
using System ;
2018-12-27 23:27:57 +00:00
using System.Collections.Generic ;
2019-09-08 19:07:29 +00:00
using System.Globalization ;
2019-01-13 19:26:15 +00:00
using MediaBrowser.Model.MediaInfo ;
2018-12-27 23:27:57 +00:00
namespace MediaBrowser.Model.Dlna
{
public class ContentFeatureBuilder
{
2021-04-02 18:06:38 +00:00
public static string BuildImageHeader (
DeviceProfile profile ,
2019-03-26 21:56:05 +00:00
string container ,
2018-12-27 23:27:57 +00:00
int? width ,
int? height ,
bool isDirectStream ,
string orgPn = null )
{
string orgOp = ";DLNA.ORG_OP=" + DlnaMaps . GetImageOrgOpValue ( ) ;
// 0 = native, 1 = transcoded
var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1" ;
2019-01-13 20:37:13 +00:00
var flagValue = DlnaFlags . BackgroundTransferMode |
2018-12-27 23:27:57 +00:00
DlnaFlags . InteractiveTransferMode |
DlnaFlags . DlnaV15 ;
2018-12-27 21:43:48 +00:00
2020-04-05 16:10:56 +00:00
string dlnaflags = string . Format (
CultureInfo . InvariantCulture ,
";DLNA.ORG_FLAGS={0}" ,
DlnaMaps . FlagsToString ( flagValue ) ) ;
2018-12-27 23:27:57 +00:00
if ( string . IsNullOrEmpty ( orgPn ) )
{
2021-04-02 18:06:38 +00:00
ResponseProfile mediaProfile = profile . GetImageMediaProfile (
container ,
width ,
height ) ;
2019-03-26 21:56:05 +00:00
orgPn = mediaProfile ? . OrgPn ;
2021-04-02 18:06:38 +00:00
if ( string . IsNullOrEmpty ( orgPn ) )
{
orgPn = GetImageOrgPnValue ( container , width , height ) ;
}
2018-12-27 23:27:57 +00:00
}
if ( string . IsNullOrEmpty ( orgPn ) )
{
2021-04-02 18:06:38 +00:00
return orgOp . TrimStart ( ';' ) + orgCi + dlnaflags ;
2018-12-27 23:27:57 +00:00
}
2021-04-02 18:06:38 +00:00
return "DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags ;
2018-12-27 23:27:57 +00:00
}
2021-04-02 18:06:38 +00:00
public static string BuildAudioHeader (
DeviceProfile profile ,
2019-03-26 21:56:05 +00:00
string container ,
2018-12-27 23:27:57 +00:00
string audioCodec ,
int? audioBitrate ,
int? audioSampleRate ,
int? audioChannels ,
int? audioBitDepth ,
bool isDirectStream ,
long? runtimeTicks ,
TranscodeSeekInfo transcodeSeekInfo )
{
// 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 > 0 , isDirectStream , transcodeSeekInfo ) ;
// 0 = native, 1 = transcoded
string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1" ;
2019-01-13 20:37:13 +00:00
var flagValue = DlnaFlags . StreamingTransferMode |
2018-12-27 23:27:57 +00:00
DlnaFlags . BackgroundTransferMode |
DlnaFlags . InteractiveTransferMode |
DlnaFlags . DlnaV15 ;
2020-06-14 09:11:11 +00:00
// if (isDirectStream)
2021-02-20 22:13:04 +00:00
// {
// flagValue = flagValue | DlnaFlags.ByteBasedSeek;
// }
// else if (runtimeTicks.HasValue)
// {
// flagValue = flagValue | DlnaFlags.TimeBasedSeek;
// }
2018-12-27 23:27:57 +00:00
2019-09-08 19:07:29 +00:00
string dlnaflags = string . Format (
CultureInfo . InvariantCulture ,
";DLNA.ORG_FLAGS={0}" ,
DlnaMaps . FlagsToString ( flagValue ) ) ;
2018-12-27 23:27:57 +00:00
2021-04-02 18:06:38 +00:00
ResponseProfile mediaProfile = profile . GetAudioMediaProfile (
2019-09-08 19:07:29 +00:00
container ,
2018-12-27 23:27:57 +00:00
audioCodec ,
audioChannels ,
audioBitrate ,
audioSampleRate ,
audioBitDepth ) ;
2019-09-08 19:07:29 +00:00
string orgPn = mediaProfile ? . OrgPn ;
2018-12-27 23:27:57 +00:00
if ( string . IsNullOrEmpty ( orgPn ) )
{
orgPn = GetAudioOrgPnValue ( container , audioBitrate , audioSampleRate , audioChannels ) ;
}
2021-04-02 18:06:38 +00:00
if ( string . IsNullOrEmpty ( orgPn ) )
{
return orgOp . TrimStart ( ';' ) + orgCi + dlnaflags ;
}
2018-12-27 23:27:57 +00:00
2021-04-02 18:06:38 +00:00
return "DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags ;
2018-12-27 23:27:57 +00:00
}
2021-04-02 18:06:38 +00:00
public static List < string > BuildVideoHeader (
DeviceProfile profile ,
2019-03-26 21:56:05 +00:00
string container ,
2018-12-27 23:27:57 +00:00
string videoCodec ,
string audioCodec ,
int? width ,
int? height ,
int? bitDepth ,
int? videoBitrate ,
TransportStreamTimestamp timestamp ,
bool isDirectStream ,
long? runtimeTicks ,
string videoProfile ,
double? videoLevel ,
float? videoFramerate ,
int? packetLength ,
TranscodeSeekInfo transcodeSeekInfo ,
bool? isAnamorphic ,
bool? isInterlaced ,
int? refFrames ,
int? numVideoStreams ,
int? numAudioStreams ,
string videoCodecTag ,
bool? isAvc )
{
// 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 > 0 , isDirectStream , transcodeSeekInfo ) ;
// 0 = native, 1 = transcoded
string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1" ;
2019-01-13 20:37:13 +00:00
var flagValue = DlnaFlags . StreamingTransferMode |
2018-12-27 23:27:57 +00:00
DlnaFlags . BackgroundTransferMode |
DlnaFlags . InteractiveTransferMode |
DlnaFlags . DlnaV15 ;
2020-06-14 09:11:11 +00:00
// if (isDirectStream)
2021-02-20 22:13:04 +00:00
// {
// flagValue = flagValue | DlnaFlags.ByteBasedSeek;
// }
// else if (runtimeTicks.HasValue)
// {
// flagValue = flagValue | DlnaFlags.TimeBasedSeek;
// }
string dlnaflags = string . Format (
CultureInfo . InvariantCulture ,
";DLNA.ORG_FLAGS={0}" ,
DlnaMaps . FlagsToString ( flagValue ) ) ;
2018-12-27 23:27:57 +00:00
2021-04-02 18:06:38 +00:00
ResponseProfile mediaProfile = profile . GetVideoMediaProfile (
2020-10-12 18:05:11 +00:00
container ,
2018-12-27 23:27:57 +00:00
audioCodec ,
videoCodec ,
width ,
height ,
bitDepth ,
videoBitrate ,
videoProfile ,
videoLevel ,
videoFramerate ,
packetLength ,
timestamp ,
isAnamorphic ,
isInterlaced ,
refFrames ,
numVideoStreams ,
numAudioStreams ,
videoCodecTag ,
isAvc ) ;
2019-01-13 20:37:13 +00:00
var orgPnValues = new List < string > ( ) ;
2018-12-27 23:27:57 +00:00
if ( mediaProfile ! = null & & ! string . IsNullOrEmpty ( mediaProfile . OrgPn ) )
{
2020-11-14 15:28:49 +00:00
orgPnValues . AddRange ( mediaProfile . OrgPn . Split ( ',' , StringSplitOptions . RemoveEmptyEntries ) ) ;
2018-12-27 23:27:57 +00:00
}
else
{
2021-04-02 18:06:38 +00:00
foreach ( var s in GetVideoOrgPnValue ( container , videoCodec , audioCodec , width , height , timestamp ) )
2018-12-27 23:27:57 +00:00
{
2021-04-02 18:06:38 +00:00
orgPnValues . Add ( s . ToString ( ) ) ;
2018-12-27 23:27:57 +00:00
break ;
}
}
2019-01-13 20:37:13 +00:00
var contentFeatureList = new List < string > ( ) ;
2018-12-27 23:27:57 +00:00
foreach ( string orgPn in orgPnValues )
{
2021-04-02 18:06:38 +00:00
if ( string . IsNullOrEmpty ( orgPn ) )
{
contentFeatureList . Add ( orgOp . TrimStart ( ';' ) + orgCi + dlnaflags ) ;
continue ;
}
else
{
contentFeatureList . Add ( "DLNA.ORG_PN=" + orgPn + orgCi + dlnaflags ) ;
}
2018-12-27 23:27:57 +00:00
}
if ( orgPnValues . Count = = 0 )
{
2021-04-02 18:06:38 +00:00
contentFeatureList . Add ( orgOp . TrimStart ( ';' ) + orgCi + dlnaflags ) ;
2018-12-27 23:27:57 +00:00
}
return contentFeatureList ;
}
2019-03-26 21:56:05 +00:00
private static string GetImageOrgPnValue ( string container , int? width , int? height )
2018-12-27 23:27:57 +00:00
{
2021-04-02 18:06:38 +00:00
MediaFormatProfile ? format = MediaFormatProfileResolver . ResolveImageFormat ( container , width , height ) ;
2018-12-27 23:27:57 +00:00
return format . HasValue ? format . Value . ToString ( ) : null ;
}
2019-03-26 21:56:05 +00:00
private static string GetAudioOrgPnValue ( string container , int? audioBitrate , int? audioSampleRate , int? audioChannels )
2018-12-27 23:27:57 +00:00
{
2021-04-02 18:06:38 +00:00
MediaFormatProfile ? format = MediaFormatProfileResolver . ResolveAudioFormat (
2020-10-12 18:05:11 +00:00
container ,
2018-12-27 23:27:57 +00:00
audioBitrate ,
audioSampleRate ,
audioChannels ) ;
return format . HasValue ? format . Value . ToString ( ) : null ;
}
2021-04-02 18:06:38 +00:00
private static MediaFormatProfile [ ] GetVideoOrgPnValue ( string container , string videoCodec , string audioCodec , int? width , int? height , TransportStreamTimestamp timestamp )
2018-12-27 23:27:57 +00:00
{
2021-04-02 18:06:38 +00:00
return MediaFormatProfileResolver . ResolveVideoFormat ( container , videoCodec , audioCodec , width , height , timestamp ) ;
2018-12-27 23:27:57 +00:00
}
}
}