2014-05-04 16:19:46 +02:00
using MediaBrowser.Model.MediaInfo ;
2015-05-06 14:56:26 +02:00
using System ;
2014-04-24 07:08:10 +02:00
using System.Collections.Generic ;
2014-04-23 04:47:46 +02:00
namespace MediaBrowser.Model.Dlna
{
public class ContentFeatureBuilder
{
private readonly DeviceProfile _profile ;
public ContentFeatureBuilder ( DeviceProfile profile )
{
_profile = profile ;
}
2014-04-24 07:08:10 +02:00
public string BuildImageHeader ( string container ,
int? width ,
2014-08-06 06:18:13 +02:00
int? height ,
2014-08-08 06:36:51 +02:00
bool isDirectStream ,
string orgPn = null )
2014-04-24 07:08:10 +02:00
{
2014-05-08 22:44:17 +02:00
string orgOp = ";DLNA.ORG_OP=" + DlnaMaps . GetImageOrgOpValue ( ) ;
2014-04-24 07:08:10 +02:00
// 0 = native, 1 = transcoded
2014-08-06 06:18:13 +02:00
var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1" ;
2014-04-24 07:08:10 +02:00
2014-08-08 06:36:51 +02:00
DlnaFlags flagValue = DlnaFlags . BackgroundTransferMode |
2014-08-07 04:51:09 +02:00
DlnaFlags . InteractiveTransferMode |
2014-04-24 07:08:10 +02:00
DlnaFlags . DlnaV15 ;
2014-08-07 04:51:09 +02:00
2014-05-08 22:44:17 +02:00
string dlnaflags = string . Format ( ";DLNA.ORG_FLAGS={0}" ,
2014-05-09 21:43:06 +02:00
DlnaMaps . FlagsToString ( flagValue ) ) ;
2014-04-24 07:08:10 +02:00
2014-05-08 22:44:17 +02:00
ResponseProfile mediaProfile = _profile . GetImageMediaProfile ( container ,
2014-04-24 07:08:10 +02:00
width ,
height ) ;
2014-08-08 06:36:51 +02:00
if ( string . IsNullOrEmpty ( orgPn ) )
{
orgPn = mediaProfile = = null ? null : mediaProfile . OrgPn ;
}
2014-04-24 07:08:10 +02:00
if ( string . IsNullOrEmpty ( orgPn ) )
{
orgPn = GetImageOrgPnValue ( container , width , height ) ;
}
2014-05-08 22:44:17 +02:00
string contentFeatures = string . IsNullOrEmpty ( orgPn ) ? string . Empty : "DLNA.ORG_PN=" + orgPn ;
2014-04-24 07:08:10 +02:00
return ( contentFeatures + orgOp + orgCi + dlnaflags ) . Trim ( ';' ) ;
}
public string BuildAudioHeader ( string container ,
2014-04-23 04:47:46 +02:00
string audioCodec ,
2014-04-24 07:08:10 +02:00
int? audioBitrate ,
int? audioSampleRate ,
int? audioChannels ,
bool isDirectStream ,
long? runtimeTicks ,
2014-04-23 04:47:46 +02:00
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
2014-05-08 22:44:17 +02:00
string orgOp = ";DLNA.ORG_OP=" + DlnaMaps . GetOrgOpValue ( runtimeTicks . HasValue , isDirectStream , transcodeSeekInfo ) ;
2014-04-23 04:47:46 +02:00
// 0 = native, 1 = transcoded
2014-05-08 22:44:17 +02:00
string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1" ;
2014-04-23 04:47:46 +02:00
2014-05-08 22:44:17 +02:00
DlnaFlags flagValue = DlnaFlags . StreamingTransferMode |
2014-04-23 04:47:46 +02:00
DlnaFlags . BackgroundTransferMode |
2014-08-07 04:51:09 +02:00
DlnaFlags . InteractiveTransferMode |
2014-04-23 04:47:46 +02:00
DlnaFlags . DlnaV15 ;
2014-08-08 06:36:51 +02:00
//if (isDirectStream)
//{
// flagValue = flagValue | DlnaFlags.ByteBasedSeek;
//}
2014-08-07 04:51:09 +02:00
//else if (runtimeTicks.HasValue)
//{
// flagValue = flagValue | DlnaFlags.TimeBasedSeek;
//}
2014-04-23 04:47:46 +02:00
2014-05-08 22:44:17 +02:00
string dlnaflags = string . Format ( ";DLNA.ORG_FLAGS={0}" ,
2014-05-09 21:43:06 +02:00
DlnaMaps . FlagsToString ( flagValue ) ) ;
2014-04-23 04:47:46 +02:00
2014-05-08 22:44:17 +02:00
ResponseProfile mediaProfile = _profile . GetAudioMediaProfile ( container ,
2014-04-24 07:08:10 +02:00
audioCodec ,
audioChannels ,
audioBitrate ) ;
2014-04-23 04:47:46 +02:00
2014-05-08 22:44:17 +02:00
string orgPn = mediaProfile = = null ? null : mediaProfile . OrgPn ;
2014-04-23 04:47:46 +02:00
if ( string . IsNullOrEmpty ( orgPn ) )
{
orgPn = GetAudioOrgPnValue ( container , audioBitrate , audioSampleRate , audioChannels ) ;
}
2014-05-08 22:44:17 +02:00
string contentFeatures = string . IsNullOrEmpty ( orgPn ) ? string . Empty : "DLNA.ORG_PN=" + orgPn ;
2014-04-23 04:47:46 +02:00
return ( contentFeatures + orgOp + orgCi + dlnaflags ) . Trim ( ';' ) ;
}
2014-07-31 04:09:23 +02:00
public List < string > BuildVideoHeader ( string container ,
2014-04-24 07:08:10 +02:00
string videoCodec ,
string audioCodec ,
int? width ,
int? height ,
int? bitDepth ,
int? videoBitrate ,
TransportStreamTimestamp timestamp ,
bool isDirectStream ,
long? runtimeTicks ,
string videoProfile ,
double? videoLevel ,
2014-06-23 18:05:19 +02:00
float? videoFramerate ,
2014-04-24 07:08:10 +02:00
int? packetLength ,
2014-06-22 18:25:47 +02:00
TranscodeSeekInfo transcodeSeekInfo ,
2014-09-09 03:15:31 +02:00
bool? isAnamorphic ,
2015-03-30 18:16:34 +02:00
int? refFrames ,
int? numVideoStreams ,
2015-10-19 18:05:03 +02:00
int? numAudioStreams ,
2016-10-03 08:28:45 +02:00
string videoCodecTag ,
2016-12-14 21:58:55 +01:00
bool? isAvc )
2014-04-23 04:47:46 +02:00
{
// 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
2014-05-08 22:44:17 +02:00
string orgOp = ";DLNA.ORG_OP=" + DlnaMaps . GetOrgOpValue ( runtimeTicks . HasValue , isDirectStream , transcodeSeekInfo ) ;
2014-04-23 04:47:46 +02:00
// 0 = native, 1 = transcoded
2014-05-08 22:44:17 +02:00
string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1" ;
2014-04-23 04:47:46 +02:00
2014-05-08 22:44:17 +02:00
DlnaFlags flagValue = DlnaFlags . StreamingTransferMode |
2014-04-23 04:47:46 +02:00
DlnaFlags . BackgroundTransferMode |
2014-08-07 04:51:09 +02:00
DlnaFlags . InteractiveTransferMode |
2014-04-23 04:47:46 +02:00
DlnaFlags . DlnaV15 ;
2014-08-08 06:36:51 +02:00
//if (isDirectStream)
//{
// flagValue = flagValue | DlnaFlags.ByteBasedSeek;
//}
2014-08-07 04:51:09 +02:00
//else if (runtimeTicks.HasValue)
//{
// flagValue = flagValue | DlnaFlags.TimeBasedSeek;
//}
2014-04-23 04:47:46 +02:00
2014-05-08 22:44:17 +02:00
string dlnaflags = string . Format ( ";DLNA.ORG_FLAGS={0}" ,
2014-05-09 21:43:06 +02:00
DlnaMaps . FlagsToString ( flagValue ) ) ;
2014-04-23 04:47:46 +02:00
2014-05-08 22:44:17 +02:00
ResponseProfile mediaProfile = _profile . GetVideoMediaProfile ( container ,
2014-04-24 07:08:10 +02:00
audioCodec ,
videoCodec ,
width ,
height ,
bitDepth ,
videoBitrate ,
videoProfile ,
videoLevel ,
videoFramerate ,
packetLength ,
2014-06-22 18:25:47 +02:00
timestamp ,
2014-09-09 03:15:31 +02:00
isAnamorphic ,
2015-03-30 18:16:34 +02:00
refFrames ,
numVideoStreams ,
2015-10-19 18:05:03 +02:00
numAudioStreams ,
2016-10-03 08:28:45 +02:00
videoCodecTag ,
2016-12-14 21:58:55 +01:00
isAvc ) ;
2014-04-24 07:08:10 +02:00
2014-07-31 04:09:23 +02:00
List < string > orgPnValues = new List < string > ( ) ;
2014-04-24 07:08:10 +02:00
2014-07-31 04:09:23 +02:00
if ( mediaProfile ! = null & & ! string . IsNullOrEmpty ( mediaProfile . OrgPn ) )
{
2015-05-06 14:56:26 +02:00
orgPnValues . AddRange ( mediaProfile . OrgPn . Split ( new [ ] { ',' } , StringSplitOptions . RemoveEmptyEntries ) ) ;
2014-07-31 04:09:23 +02:00
}
else
2014-04-23 04:47:46 +02:00
{
2014-05-09 06:38:12 +02:00
foreach ( string s in GetVideoOrgPnValue ( container , videoCodec , audioCodec , width , height , timestamp ) )
{
2014-07-31 04:09:23 +02:00
orgPnValues . Add ( s ) ;
2014-05-09 06:38:12 +02:00
break ;
}
}
2014-04-24 07:08:10 +02:00
2014-07-31 04:09:23 +02:00
List < string > contentFeatureList = new List < string > ( ) ;
foreach ( string orgPn in orgPnValues )
2014-05-09 06:38:12 +02:00
{
2014-07-31 04:09:23 +02:00
string contentFeatures = string . IsNullOrEmpty ( orgPn ) ? string . Empty : "DLNA.ORG_PN=" + orgPn ;
var value = ( contentFeatures + orgOp + orgCi + dlnaflags ) . Trim ( ';' ) ;
contentFeatureList . Add ( value ) ;
2014-04-23 04:47:46 +02:00
}
2014-07-31 04:09:23 +02:00
if ( orgPnValues . Count = = 0 )
{
string contentFeatures = string . Empty ;
2014-04-23 04:47:46 +02:00
2014-07-31 04:09:23 +02:00
var value = ( contentFeatures + orgOp + orgCi + dlnaflags ) . Trim ( ';' ) ;
contentFeatureList . Add ( value ) ;
}
return contentFeatureList ;
2014-04-23 04:47:46 +02:00
}
2014-04-24 07:08:10 +02:00
private string GetImageOrgPnValue ( string container , int? width , int? height )
{
2014-05-08 22:44:17 +02:00
MediaFormatProfile ? format = new MediaFormatProfileResolver ( )
2014-04-24 07:08:10 +02:00
. ResolveImageFormat ( container ,
width ,
height ) ;
return format . HasValue ? format . Value . ToString ( ) : null ;
}
2014-04-23 04:47:46 +02:00
private string GetAudioOrgPnValue ( string container , int? audioBitrate , int? audioSampleRate , int? audioChannels )
{
2014-05-08 22:44:17 +02:00
MediaFormatProfile ? format = new MediaFormatProfileResolver ( )
2014-04-23 04:47:46 +02:00
. ResolveAudioFormat ( container ,
audioBitrate ,
audioSampleRate ,
audioChannels ) ;
return format . HasValue ? format . Value . ToString ( ) : null ;
}
2014-05-09 06:38:12 +02:00
private List < string > GetVideoOrgPnValue ( string container , string videoCodec , string audioCodec , int? width , int? height , TransportStreamTimestamp timestamp )
2014-04-23 04:47:46 +02:00
{
2014-05-09 06:38:12 +02:00
List < string > list = new List < string > ( ) ;
foreach ( MediaFormatProfile i in new MediaFormatProfileResolver ( ) . ResolveVideoFormat ( container , videoCodec , audioCodec , width , height , timestamp ) )
list . Add ( i . ToString ( ) ) ;
return list ;
2014-04-23 04:47:46 +02:00
}
}
}