< Summary - Jellyfin

Information
Class: MediaBrowser.Model.Dlna.StreamInfo
Assembly: MediaBrowser.Model
File(s): /srv/git/jellyfin/MediaBrowser.Model/Dlna/StreamInfo.cs
Line coverage
43%
Covered lines: 142
Uncovered lines: 188
Coverable lines: 330
Total lines: 1310
Line coverage: 43%
Branch coverage
37%
Covered branches: 138
Total branches: 372
Branch coverage: 37%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_MediaSourceId()50%22100%
get_IsDirectStream()80%1010100%
get_TargetAudioStream()50%22100%
get_TargetVideoStream()50%22100%
get_TargetAudioSampleRate()0%4260%
get_TargetAudioBitDepth()0%110100%
get_TargetVideoBitDepth()30%12.331071.42%
get_TargetRefFrames()0%110100%
get_TargetFramerate()0%4260%
get_TargetVideoLevel()30%12.331071.42%
get_TargetPacketLength()0%2040%
get_TargetVideoProfile()30%12.331071.42%
get_TargetVideoRangeType()0%156120%
get_TargetVideoCodecTag()0%2040%
get_TargetAudioBitrate()0%4260%
get_TargetAudioChannels()0%110100%
get_TargetAudioCodec()83.33%1212100%
get_TargetVideoCodec()66.66%12.21288.88%
get_TargetSize()0%7280%
get_TargetVideoBitrate()0%4260%
get_TargetTimestamp()0%4260%
get_TargetTotalBitrate()100%210%
get_IsTargetAnamorphic()0%2040%
get_IsTargetInterlaced()0%156120%
get_IsTargetAVC()0%2040%
get_TargetWidth()0%4260%
get_TargetHeight()0%4260%
get_TargetVideoStreamCount()0%620%
get_TargetAudioStreamCount()0%620%
SetOption(...)50%2.06275%
SetOption(...)100%11100%
GetOption(...)100%22100%
GetOption(...)100%22100%
ToUrl(...)100%1616100%
GetUrl(...)62.5%9.73870%
BuildParams(...)81.7%87.558290.62%
GetSubtitleProfiles(...)100%210%
GetSubtitleProfiles(...)0%702260%
AddSubtitleProfiles(...)0%7280%
GetSubtitleStreamInfo(...)0%210140%
GetTargetVideoBitDepth(...)50%2.06275%
GetTargetAudioBitDepth(...)0%620%
GetTargetVideoLevel(...)100%22100%
GetTargetRefFrames(...)50%2.06275%
GetTargetAudioChannels(...)50%8.83657.14%
GetMediaStreamCount(...)0%2040%

File(s)

/srv/git/jellyfin/MediaBrowser.Model/Dlna/StreamInfo.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Globalization;
 4using Jellyfin.Data.Enums;
 5using MediaBrowser.Model.Drawing;
 6using MediaBrowser.Model.Dto;
 7using MediaBrowser.Model.Entities;
 8using MediaBrowser.Model.MediaInfo;
 9using MediaBrowser.Model.Session;
 10
 11namespace MediaBrowser.Model.Dlna;
 12
 13/// <summary>
 14/// Class holding information on a stream.
 15/// </summary>
 16public class StreamInfo
 17{
 18    /// <summary>
 19    /// Initializes a new instance of the <see cref="StreamInfo"/> class.
 20    /// </summary>
 21    public StreamInfo()
 22    {
 23        AudioCodecs = [];
 24        VideoCodecs = [];
 25        SubtitleCodecs = [];
 26        StreamOptions = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 27    }
 28
 29    /// <summary>
 30    /// Gets or sets the item id.
 31    /// </summary>
 32    /// <value>The item id.</value>
 33    public Guid ItemId { get; set; }
 34
 35    /// <summary>
 36    /// Gets or sets the play method.
 37    /// </summary>
 38    /// <value>The play method.</value>
 39    public PlayMethod PlayMethod { get; set; }
 40
 41    /// <summary>
 42    /// Gets or sets the encoding context.
 43    /// </summary>
 44    /// <value>The encoding context.</value>
 45    public EncodingContext Context { get; set; }
 46
 47    /// <summary>
 48    /// Gets or sets the media type.
 49    /// </summary>
 50    /// <value>The media type.</value>
 51    public DlnaProfileType MediaType { get; set; }
 52
 53    /// <summary>
 54    /// Gets or sets the container.
 55    /// </summary>
 56    /// <value>The container.</value>
 57    public string? Container { get; set; }
 58
 59    /// <summary>
 60    /// Gets or sets the sub protocol.
 61    /// </summary>
 62    /// <value>The sub protocol.</value>
 63    public MediaStreamProtocol SubProtocol { get; set; }
 64
 65    /// <summary>
 66    /// Gets or sets the start position ticks.
 67    /// </summary>
 68    /// <value>The start position ticks.</value>
 69    public long StartPositionTicks { get; set; }
 70
 71    /// <summary>
 72    /// Gets or sets the segment length.
 73    /// </summary>
 74    /// <value>The segment length.</value>
 75    public int? SegmentLength { get; set; }
 76
 77    /// <summary>
 78    /// Gets or sets the minimum segments count.
 79    /// </summary>
 80    /// <value>The minimum segments count.</value>
 81    public int? MinSegments { get; set; }
 82
 83    /// <summary>
 84    /// Gets or sets a value indicating whether the stream can be broken on non-keyframes.
 85    /// </summary>
 86    public bool BreakOnNonKeyFrames { get; set; }
 87
 88    /// <summary>
 89    /// Gets or sets a value indicating whether the stream requires AVC.
 90    /// </summary>
 91    public bool RequireAvc { get; set; }
 92
 93    /// <summary>
 94    /// Gets or sets a value indicating whether the stream requires AVC.
 95    /// </summary>
 96    public bool RequireNonAnamorphic { get; set; }
 97
 98    /// <summary>
 99    /// Gets or sets a value indicating whether timestamps should be copied.
 100    /// </summary>
 101    public bool CopyTimestamps { get; set; }
 102
 103    /// <summary>
 104    /// Gets or sets a value indicating whether timestamps should be copied.
 105    /// </summary>
 106    public bool EnableMpegtsM2TsMode { get; set; }
 107
 108    /// <summary>
 109    /// Gets or sets a value indicating whether the subtitle manifest is enabled.
 110    /// </summary>
 111    public bool EnableSubtitlesInManifest { get; set; }
 112
 113    /// <summary>
 114    /// Gets or sets the audio codecs.
 115    /// </summary>
 116    /// <value>The audio codecs.</value>
 117    public IReadOnlyList<string> AudioCodecs { get; set; }
 118
 119    /// <summary>
 120    /// Gets or sets the video codecs.
 121    /// </summary>
 122    /// <value>The video codecs.</value>
 123    public IReadOnlyList<string> VideoCodecs { get; set; }
 124
 125    /// <summary>
 126    /// Gets or sets the audio stream index.
 127    /// </summary>
 128    /// <value>The audio stream index.</value>
 129    public int? AudioStreamIndex { get; set; }
 130
 131    /// <summary>
 132    /// Gets or sets the video stream index.
 133    /// </summary>
 134    /// <value>The subtitle stream index.</value>
 135    public int? SubtitleStreamIndex { get; set; }
 136
 137    /// <summary>
 138    /// Gets or sets the maximum transcoding audio channels.
 139    /// </summary>
 140    /// <value>The maximum transcoding audio channels.</value>
 141    public int? TranscodingMaxAudioChannels { get; set; }
 142
 143    /// <summary>
 144    /// Gets or sets the global maximum audio channels.
 145    /// </summary>
 146    /// <value>The global maximum audio channels.</value>
 147    public int? GlobalMaxAudioChannels { get; set; }
 148
 149    /// <summary>
 150    /// Gets or sets the audio bitrate.
 151    /// </summary>
 152    /// <value>The audio bitrate.</value>
 153    public int? AudioBitrate { get; set; }
 154
 155    /// <summary>
 156    /// Gets or sets the audio sample rate.
 157    /// </summary>
 158    /// <value>The audio sample rate.</value>
 159    public int? AudioSampleRate { get; set; }
 160
 161    /// <summary>
 162    /// Gets or sets the video bitrate.
 163    /// </summary>
 164    /// <value>The video bitrate.</value>
 165    public int? VideoBitrate { get; set; }
 166
 167    /// <summary>
 168    /// Gets or sets the maximum output width.
 169    /// </summary>
 170    /// <value>The output width.</value>
 171    public int? MaxWidth { get; set; }
 172
 173    /// <summary>
 174    /// Gets or sets the maximum output height.
 175    /// </summary>
 176    /// <value>The maximum output height.</value>
 177    public int? MaxHeight { get; set; }
 178
 179    /// <summary>
 180    /// Gets or sets the maximum framerate.
 181    /// </summary>
 182    /// <value>The maximum framerate.</value>
 183    public float? MaxFramerate { get; set; }
 184
 185    /// <summary>
 186    /// Gets or sets the device profile.
 187    /// </summary>
 188    /// <value>The device profile.</value>
 189    public required DeviceProfile DeviceProfile { get; set; }
 190
 191    /// <summary>
 192    /// Gets or sets the device profile id.
 193    /// </summary>
 194    /// <value>The device profile id.</value>
 195    public string? DeviceProfileId { get; set; }
 196
 197    /// <summary>
 198    /// Gets or sets the device id.
 199    /// </summary>
 200    /// <value>The device id.</value>
 201    public string? DeviceId { get; set; }
 202
 203    /// <summary>
 204    /// Gets or sets the runtime ticks.
 205    /// </summary>
 206    /// <value>The runtime ticks.</value>
 207    public long? RunTimeTicks { get; set; }
 208
 209    /// <summary>
 210    /// Gets or sets the transcode seek info.
 211    /// </summary>
 212    /// <value>The transcode seek info.</value>
 213    public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
 214
 215    /// <summary>
 216    /// Gets or sets a value indicating whether content length should be estimated.
 217    /// </summary>
 218    public bool EstimateContentLength { get; set; }
 219
 220    /// <summary>
 221    /// Gets or sets the media source info.
 222    /// </summary>
 223    /// <value>The media source info.</value>
 224    public MediaSourceInfo? MediaSource { get; set; }
 225
 226    /// <summary>
 227    /// Gets or sets the subtitle codecs.
 228    /// </summary>
 229    /// <value>The subtitle codecs.</value>
 230    public IReadOnlyList<string> SubtitleCodecs { get; set; }
 231
 232    /// <summary>
 233    /// Gets or sets the subtitle delivery method.
 234    /// </summary>
 235    /// <value>The subtitle delivery method.</value>
 236    public SubtitleDeliveryMethod SubtitleDeliveryMethod { get; set; }
 237
 238    /// <summary>
 239    /// Gets or sets the subtitle format.
 240    /// </summary>
 241    /// <value>The subtitle format.</value>
 242    public string? SubtitleFormat { get; set; }
 243
 244    /// <summary>
 245    /// Gets or sets the play session id.
 246    /// </summary>
 247    /// <value>The play session id.</value>
 248    public string? PlaySessionId { get; set; }
 249
 250    /// <summary>
 251    /// Gets or sets the transcode reasons.
 252    /// </summary>
 253    /// <value>The transcode reasons.</value>
 254    public TranscodeReason TranscodeReasons { get; set; }
 255
 256    /// <summary>
 257    /// Gets the stream options.
 258    /// </summary>
 259    /// <value>The stream options.</value>
 260    public Dictionary<string, string> StreamOptions { get; private set; }
 261
 262    /// <summary>
 263    /// Gets the media source id.
 264    /// </summary>
 265    /// <value>The media source id.</value>
 792266    public string? MediaSourceId => MediaSource?.Id;
 267
 268    /// <summary>
 269    /// Gets or sets a value indicating whether audio VBR encoding is enabled.
 270    /// </summary>
 271    public bool EnableAudioVbrEncoding { get; set; }
 272
 273    /// <summary>
 274    /// Gets a value indicating whether the stream is direct.
 275    /// </summary>
 2940276    public bool IsDirectStream => MediaSource?.VideoType is not (VideoType.Dvd or VideoType.BluRay)
 2940277        && PlayMethod is PlayMethod.DirectStream or PlayMethod.DirectPlay;
 278
 279    /// <summary>
 280    /// Gets the audio stream that will be used in the output stream.
 281    /// </summary>
 282    /// <value>The audio stream.</value>
 652283    public MediaStream? TargetAudioStream => MediaSource?.GetDefaultAudioStream(AudioStreamIndex);
 284
 285    /// <summary>
 286    /// Gets the video stream that will be used in the output stream.
 287    /// </summary>
 288    /// <value>The video stream.</value>
 966289    public MediaStream? TargetVideoStream => MediaSource?.VideoStream;
 290
 291    /// <summary>
 292    /// Gets the audio sample rate that will be in the output stream.
 293    /// </summary>
 294    /// <value>The target audio sample rate.</value>
 295    public int? TargetAudioSampleRate
 296    {
 297        get
 298        {
 0299            var stream = TargetAudioStream;
 0300            return AudioSampleRate.HasValue && !IsDirectStream
 0301                ? AudioSampleRate
 0302                : stream?.SampleRate;
 303        }
 304    }
 305
 306    /// <summary>
 307    /// Gets the audio bit depth that will be in the output stream.
 308    /// </summary>
 309    /// <value>The target bit depth.</value>
 310    public int? TargetAudioBitDepth
 311    {
 312        get
 313        {
 0314            if (IsDirectStream)
 315            {
 0316                return TargetAudioStream?.BitDepth;
 317            }
 318
 0319            var targetAudioCodecs = TargetAudioCodec;
 0320            var audioCodec = targetAudioCodecs.Count == 0 ? null : targetAudioCodecs[0];
 0321            if (!string.IsNullOrEmpty(audioCodec))
 322            {
 0323                return GetTargetAudioBitDepth(audioCodec);
 324            }
 325
 0326            return TargetAudioStream?.BitDepth;
 327        }
 328    }
 329
 330    /// <summary>
 331    /// Gets the video bit depth that will be in the output stream.
 332    /// </summary>
 333    /// <value>The target video bit depth.</value>
 334    public int? TargetVideoBitDepth
 335    {
 336        get
 337        {
 94338            if (IsDirectStream)
 339            {
 0340                return TargetVideoStream?.BitDepth;
 341            }
 342
 94343            var targetVideoCodecs = TargetVideoCodec;
 94344            var videoCodec = targetVideoCodecs.Count == 0 ? null : targetVideoCodecs[0];
 94345            if (!string.IsNullOrEmpty(videoCodec))
 346            {
 94347                return GetTargetVideoBitDepth(videoCodec);
 348            }
 349
 0350            return TargetVideoStream?.BitDepth;
 351        }
 352    }
 353
 354    /// <summary>
 355    /// Gets the target reference frames that will be in the output stream.
 356    /// </summary>
 357    /// <value>The target reference frames.</value>
 358    public int? TargetRefFrames
 359    {
 360        get
 361        {
 0362            if (IsDirectStream)
 363            {
 0364                return TargetVideoStream?.RefFrames;
 365            }
 366
 0367            var targetVideoCodecs = TargetVideoCodec;
 0368            var videoCodec = targetVideoCodecs.Count == 0 ? null : targetVideoCodecs[0];
 0369            if (!string.IsNullOrEmpty(videoCodec))
 370            {
 0371                return GetTargetRefFrames(videoCodec);
 372            }
 373
 0374            return TargetVideoStream?.RefFrames;
 375        }
 376    }
 377
 378    /// <summary>
 379    /// Gets the target framerate that will be in the output stream.
 380    /// </summary>
 381    /// <value>The target framerate.</value>
 382    public float? TargetFramerate
 383    {
 384        get
 385        {
 0386            var stream = TargetVideoStream;
 0387            return MaxFramerate.HasValue && !IsDirectStream
 0388                ? MaxFramerate
 0389                : stream?.ReferenceFrameRate;
 390        }
 391    }
 392
 393    /// <summary>
 394    /// Gets the target video level that will be in the output stream.
 395    /// </summary>
 396    /// <value>The target video level.</value>
 397    public double? TargetVideoLevel
 398    {
 399        get
 400        {
 94401            if (IsDirectStream)
 402            {
 0403                return TargetVideoStream?.Level;
 404            }
 405
 94406            var targetVideoCodecs = TargetVideoCodec;
 94407            var videoCodec = targetVideoCodecs.Count == 0 ? null : targetVideoCodecs[0];
 94408            if (!string.IsNullOrEmpty(videoCodec))
 409            {
 94410                return GetTargetVideoLevel(videoCodec);
 411            }
 412
 0413            return TargetVideoStream?.Level;
 414        }
 415    }
 416
 417    /// <summary>
 418    /// Gets the target packet length that will be in the output stream.
 419    /// </summary>
 420    /// <value>The target packet length.</value>
 421    public int? TargetPacketLength
 422    {
 423        get
 424        {
 0425            var stream = TargetVideoStream;
 0426            return !IsDirectStream
 0427                ? null
 0428                : stream?.PacketLength;
 429        }
 430    }
 431
 432    /// <summary>
 433    /// Gets the target video profile that will be in the output stream.
 434    /// </summary>
 435    /// <value>The target video profile.</value>
 436    public string? TargetVideoProfile
 437    {
 438        get
 439        {
 94440            if (IsDirectStream)
 441            {
 0442                return TargetVideoStream?.Profile;
 443            }
 444
 94445            var targetVideoCodecs = TargetVideoCodec;
 94446            var videoCodec = targetVideoCodecs.Count == 0 ? null : targetVideoCodecs[0];
 94447            if (!string.IsNullOrEmpty(videoCodec))
 448            {
 94449                return GetOption(videoCodec, "profile");
 450            }
 451
 0452            return TargetVideoStream?.Profile;
 453        }
 454    }
 455
 456    /// <summary>
 457    /// Gets the target video range type that will be in the output stream.
 458    /// </summary>
 459    /// <value>The video range type.</value>
 460    public VideoRangeType TargetVideoRangeType
 461    {
 462        get
 463        {
 0464            if (IsDirectStream)
 465            {
 0466                return TargetVideoStream?.VideoRangeType ?? VideoRangeType.Unknown;
 467            }
 468
 0469            var targetVideoCodecs = TargetVideoCodec;
 0470            var videoCodec = targetVideoCodecs.Count == 0 ? null : targetVideoCodecs[0];
 0471            if (!string.IsNullOrEmpty(videoCodec)
 0472                && Enum.TryParse(GetOption(videoCodec, "rangetype"), true, out VideoRangeType videoRangeType))
 473            {
 0474                return videoRangeType;
 475            }
 476
 0477            return TargetVideoStream?.VideoRangeType ?? VideoRangeType.Unknown;
 478        }
 479    }
 480
 481    /// <summary>
 482    /// Gets the target video codec tag.
 483    /// </summary>
 484    /// <value>The video codec tag.</value>
 485    public string? TargetVideoCodecTag
 486    {
 487        get
 488        {
 0489            var stream = TargetVideoStream;
 0490            return !IsDirectStream
 0491                ? null
 0492                : stream?.CodecTag;
 493        }
 494    }
 495
 496    /// <summary>
 497    /// Gets the audio bitrate that will be in the output stream.
 498    /// </summary>
 499    /// <value>The audio bitrate.</value>
 500    public int? TargetAudioBitrate
 501    {
 502        get
 503        {
 0504            var stream = TargetAudioStream;
 0505            return AudioBitrate.HasValue && !IsDirectStream
 0506                ? AudioBitrate
 0507                : stream?.BitRate;
 508        }
 509    }
 510
 511    /// <summary>
 512    /// Gets the amount of audio channels that will be in the output stream.
 513    /// </summary>
 514    /// <value>The target audio channels.</value>
 515    public int? TargetAudioChannels
 516    {
 517        get
 518        {
 0519            if (IsDirectStream)
 520            {
 0521                return TargetAudioStream?.Channels;
 522            }
 523
 0524            var targetAudioCodecs = TargetAudioCodec;
 0525            var codec = targetAudioCodecs.Count == 0 ? null : targetAudioCodecs[0];
 0526            if (!string.IsNullOrEmpty(codec))
 527            {
 0528                return GetTargetRefFrames(codec);
 529            }
 530
 0531            return TargetAudioStream?.Channels;
 532        }
 533    }
 534
 535    /// <summary>
 536    /// Gets the audio codec that will be in the output stream.
 537    /// </summary>
 538    /// <value>The audio codec.</value>
 539    public IReadOnlyList<string> TargetAudioCodec
 540    {
 541        get
 542        {
 372543            var stream = TargetAudioStream;
 544
 372545            string? inputCodec = stream?.Codec;
 546
 372547            if (IsDirectStream)
 548            {
 232549                return string.IsNullOrEmpty(inputCodec) ? [] : [inputCodec];
 550            }
 551
 718552            foreach (string codec in AudioCodecs)
 553            {
 256554                if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase))
 555                {
 74556                    return string.IsNullOrEmpty(codec) ? [] : [codec];
 557                }
 558            }
 559
 66560            return AudioCodecs;
 74561        }
 562    }
 563
 564    /// <summary>
 565    /// Gets the video codec that will be in the output stream.
 566    /// </summary>
 567    /// <value>The target video codec.</value>
 568    public IReadOnlyList<string> TargetVideoCodec
 569    {
 570        get
 571        {
 702572            var stream = TargetVideoStream;
 573
 702574            string? inputCodec = stream?.Codec;
 575
 702576            if (IsDirectStream)
 577            {
 232578                return string.IsNullOrEmpty(inputCodec) ? [] : [inputCodec];
 579            }
 580
 2250581            foreach (string codec in VideoCodecs)
 582            {
 890583                if (string.Equals(codec, inputCodec, StringComparison.OrdinalIgnoreCase))
 584                {
 470585                    return string.IsNullOrEmpty(codec) ? [] : [codec];
 586                }
 587            }
 588
 0589            return VideoCodecs;
 470590        }
 591    }
 592
 593    /// <summary>
 594    /// Gets the target size of the output stream.
 595    /// </summary>
 596    /// <value>The target size.</value>
 597    public long? TargetSize
 598    {
 599        get
 600        {
 0601            if (IsDirectStream)
 602            {
 0603                return MediaSource?.Size;
 604            }
 605
 0606            if (RunTimeTicks.HasValue)
 607            {
 0608                int? totalBitrate = TargetTotalBitrate;
 609
 0610                double totalSeconds = RunTimeTicks.Value;
 611                // Convert to ms
 0612                totalSeconds /= 10000;
 613                // Convert to seconds
 0614                totalSeconds /= 1000;
 615
 0616                return totalBitrate.HasValue ?
 0617                    Convert.ToInt64(totalBitrate.Value * totalSeconds) :
 0618                    null;
 619            }
 620
 0621            return null;
 622        }
 623    }
 624
 625    /// <summary>
 626    /// Gets the target video bitrate of the output stream.
 627    /// </summary>
 628    /// <value>The video bitrate.</value>
 629    public int? TargetVideoBitrate
 630    {
 631        get
 632        {
 0633            var stream = TargetVideoStream;
 634
 0635            return VideoBitrate.HasValue && !IsDirectStream
 0636                ? VideoBitrate
 0637                : stream?.BitRate;
 638        }
 639    }
 640
 641    /// <summary>
 642    /// Gets the target timestamp of the output stream.
 643    /// </summary>
 644    /// <value>The target timestamp.</value>
 645    public TransportStreamTimestamp TargetTimestamp
 646    {
 647        get
 648        {
 0649            var defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase)
 0650                ? TransportStreamTimestamp.Valid
 0651                : TransportStreamTimestamp.None;
 652
 0653            return !IsDirectStream
 0654                ? defaultValue
 0655                : MediaSource is null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None;
 656        }
 657    }
 658
 659    /// <summary>
 660    /// Gets the target total bitrate of the output stream.
 661    /// </summary>
 662    /// <value>The target total bitrate.</value>
 0663    public int? TargetTotalBitrate => (TargetAudioBitrate ?? 0) + (TargetVideoBitrate ?? 0);
 664
 665    /// <summary>
 666    /// Gets a value indicating whether the output stream is anamorphic.
 667    /// </summary>
 668    public bool? IsTargetAnamorphic
 669    {
 670        get
 671        {
 0672            if (IsDirectStream)
 673            {
 0674                return TargetVideoStream?.IsAnamorphic;
 675            }
 676
 0677            return false;
 678        }
 679    }
 680
 681    /// <summary>
 682    /// Gets a value indicating whether the output stream is interlaced.
 683    /// </summary>
 684    public bool? IsTargetInterlaced
 685    {
 686        get
 687        {
 0688            if (IsDirectStream)
 689            {
 0690                return TargetVideoStream?.IsInterlaced;
 691            }
 692
 0693            var targetVideoCodecs = TargetVideoCodec;
 0694            var videoCodec = targetVideoCodecs.Count == 0 ? null : targetVideoCodecs[0];
 0695            if (!string.IsNullOrEmpty(videoCodec))
 696            {
 0697                if (string.Equals(GetOption(videoCodec, "deinterlace"), "true", StringComparison.OrdinalIgnoreCase))
 698                {
 0699                    return false;
 700                }
 701            }
 702
 0703            return TargetVideoStream?.IsInterlaced;
 704        }
 705    }
 706
 707    /// <summary>
 708    /// Gets a value indicating whether the output stream is AVC.
 709    /// </summary>
 710    public bool? IsTargetAVC
 711    {
 712        get
 713        {
 0714            if (IsDirectStream)
 715            {
 0716                return TargetVideoStream?.IsAVC;
 717            }
 718
 0719            return true;
 720        }
 721    }
 722
 723    /// <summary>
 724    /// Gets the target width of the output stream.
 725    /// </summary>
 726    /// <value>The target width.</value>
 727    public int? TargetWidth
 728    {
 729        get
 730        {
 0731            var videoStream = TargetVideoStream;
 732
 0733            if (videoStream is not null && videoStream.Width.HasValue && videoStream.Height.HasValue)
 734            {
 0735                ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value);
 736
 0737                size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0);
 738
 0739                return size.Width;
 740            }
 741
 0742            return MaxWidth;
 743        }
 744    }
 745
 746    /// <summary>
 747    /// Gets the target height of the output stream.
 748    /// </summary>
 749    /// <value>The target height.</value>
 750    public int? TargetHeight
 751    {
 752        get
 753        {
 0754            var videoStream = TargetVideoStream;
 755
 0756            if (videoStream is not null && videoStream.Width.HasValue && videoStream.Height.HasValue)
 757            {
 0758                ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value);
 759
 0760                size = DrawingUtils.Resize(size, 0, 0, MaxWidth ?? 0, MaxHeight ?? 0);
 761
 0762                return size.Height;
 763            }
 764
 0765            return MaxHeight;
 766        }
 767    }
 768
 769    /// <summary>
 770    /// Gets the target video stream count of the output stream.
 771    /// </summary>
 772    /// <value>The target video stream count.</value>
 773    public int? TargetVideoStreamCount
 774    {
 775        get
 776        {
 0777            if (IsDirectStream)
 778            {
 0779                return GetMediaStreamCount(MediaStreamType.Video, int.MaxValue);
 780            }
 781
 0782            return GetMediaStreamCount(MediaStreamType.Video, 1);
 783        }
 784    }
 785
 786    /// <summary>
 787    /// Gets the target audio stream count of the output stream.
 788    /// </summary>
 789    /// <value>The target audio stream count.</value>
 790    public int? TargetAudioStreamCount
 791    {
 792        get
 793        {
 0794            if (IsDirectStream)
 795            {
 0796                return GetMediaStreamCount(MediaStreamType.Audio, int.MaxValue);
 797            }
 798
 0799            return GetMediaStreamCount(MediaStreamType.Audio, 1);
 800        }
 801    }
 802
 803    /// <summary>
 804    /// Sets a stream option.
 805    /// </summary>
 806    /// <param name="qualifier">The qualifier.</param>
 807    /// <param name="name">The name.</param>
 808    /// <param name="value">The value.</param>
 809    public void SetOption(string? qualifier, string name, string value)
 810    {
 1324811        if (string.IsNullOrEmpty(qualifier))
 812        {
 0813            SetOption(name, value);
 814        }
 815        else
 816        {
 1324817            SetOption(qualifier + "-" + name, value);
 818        }
 1324819    }
 820
 821    /// <summary>
 822    /// Sets a stream option.
 823    /// </summary>
 824    /// <param name="name">The name.</param>
 825    /// <param name="value">The value.</param>
 826    public void SetOption(string name, string value)
 827    {
 1324828        StreamOptions[name] = value;
 1324829    }
 830
 831    /// <summary>
 832    /// Gets a stream option.
 833    /// </summary>
 834    /// <param name="qualifier">The qualifier.</param>
 835    /// <param name="name">The name.</param>
 836    /// <returns>The value.</returns>
 837    public string? GetOption(string? qualifier, string name)
 838    {
 1098839        var value = GetOption(qualifier + "-" + name);
 840
 1098841        if (string.IsNullOrEmpty(value))
 842        {
 668843            value = GetOption(name);
 844        }
 845
 1098846        return value;
 847    }
 848
 849    /// <summary>
 850    /// Gets a stream option.
 851    /// </summary>
 852    /// <param name="name">The name.</param>
 853    /// <returns>The value.</returns>
 854    public string? GetOption(string name)
 855    {
 1766856        if (StreamOptions.TryGetValue(name, out var value))
 857        {
 430858            return value;
 859        }
 860
 1336861        return null;
 862    }
 863
 864    /// <summary>
 865    /// Returns this output stream URL for this class.
 866    /// </summary>
 867    /// <param name="baseUrl">The base Url.</param>
 868    /// <param name="accessToken">The access Token.</param>
 869    /// <returns>A querystring representation of this object.</returns>
 870    public string ToUrl(string baseUrl, string? accessToken)
 871    {
 528872        ArgumentException.ThrowIfNullOrEmpty(baseUrl);
 873
 528874        List<string> list = [];
 31744875        foreach (NameValuePair pair in BuildParams(this, accessToken))
 876        {
 15344877            if (string.IsNullOrEmpty(pair.Value))
 878            {
 879                continue;
 880            }
 881
 882            // Try to keep the url clean by omitting defaults
 9738883            if (string.Equals(pair.Name, "StartTimeTicks", StringComparison.OrdinalIgnoreCase)
 9738884                && string.Equals(pair.Value, "0", StringComparison.OrdinalIgnoreCase))
 885            {
 886                continue;
 887            }
 888
 9462889            if (string.Equals(pair.Name, "SubtitleStreamIndex", StringComparison.OrdinalIgnoreCase)
 9462890                && string.Equals(pair.Value, "-1", StringComparison.OrdinalIgnoreCase))
 891            {
 892                continue;
 893            }
 894
 9434895            if (string.Equals(pair.Name, "Static", StringComparison.OrdinalIgnoreCase)
 9434896                && string.Equals(pair.Value, "false", StringComparison.OrdinalIgnoreCase))
 897            {
 898                continue;
 899            }
 900
 9138901            var encodedValue = pair.Value.Replace(" ", "%20", StringComparison.Ordinal);
 902
 9138903            list.Add(string.Format(CultureInfo.InvariantCulture, "{0}={1}", pair.Name, encodedValue));
 904        }
 905
 528906        string queryString = string.Join('&', list);
 907
 528908        return GetUrl(baseUrl, queryString);
 909    }
 910
 911    private string GetUrl(string baseUrl, string queryString)
 912    {
 528913        ArgumentException.ThrowIfNullOrEmpty(baseUrl);
 914
 528915        string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;
 916
 528917        baseUrl = baseUrl.TrimEnd('/');
 918
 528919        if (MediaType == DlnaProfileType.Audio)
 920        {
 0921            if (SubProtocol == MediaStreamProtocol.hls)
 922            {
 0923                return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/master.m3u8?{2}", baseUrl, ItemId, que
 924            }
 925
 0926            return string.Format(CultureInfo.InvariantCulture, "{0}/audio/{1}/stream{2}?{3}", baseUrl, ItemId, extension
 927        }
 928
 528929        if (SubProtocol == MediaStreamProtocol.hls)
 930        {
 252931            return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, queryS
 932        }
 933
 276934        return string.Format(CultureInfo.InvariantCulture, "{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, q
 935    }
 936
 937    private static List<NameValuePair> BuildParams(StreamInfo item, string? accessToken)
 938    {
 528939        List<NameValuePair> list = [];
 940
 528941        string audioCodecs = item.AudioCodecs.Count == 0 ?
 528942            string.Empty :
 528943            string.Join(',', item.AudioCodecs);
 944
 528945        string videoCodecs = item.VideoCodecs.Count == 0 ?
 528946            string.Empty :
 528947            string.Join(',', item.VideoCodecs);
 948
 528949        list.Add(new NameValuePair("DeviceProfileId", item.DeviceProfileId ?? string.Empty));
 528950        list.Add(new NameValuePair("DeviceId", item.DeviceId ?? string.Empty));
 528951        list.Add(new NameValuePair("MediaSourceId", item.MediaSourceId ?? string.Empty));
 528952        list.Add(new NameValuePair("Static", item.IsDirectStream.ToString(CultureInfo.InvariantCulture).ToLowerInvariant
 528953        list.Add(new NameValuePair("VideoCodec", videoCodecs));
 528954        list.Add(new NameValuePair("AudioCodec", audioCodecs));
 528955        list.Add(new NameValuePair("AudioStreamIndex", item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToSt
 528956        list.Add(new NameValuePair("SubtitleStreamIndex", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMeth
 528957        list.Add(new NameValuePair("VideoBitrate", item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(Culture
 528958        list.Add(new NameValuePair("AudioBitrate", item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(Culture
 528959        list.Add(new NameValuePair("AudioSampleRate", item.AudioSampleRate.HasValue ? item.AudioSampleRate.Value.ToStrin
 960
 528961        list.Add(new NameValuePair("MaxFramerate", item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(Culture
 528962        list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(CultureInfo.Invaria
 528963        list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(CultureInfo.Inva
 964
 528965        long startPositionTicks = item.StartPositionTicks;
 966
 528967        if (item.SubProtocol == MediaStreamProtocol.hls)
 968        {
 252969            list.Add(new NameValuePair("StartTimeTicks", string.Empty));
 970        }
 971        else
 972        {
 276973            list.Add(new NameValuePair("StartTimeTicks", startPositionTicks.ToString(CultureInfo.InvariantCulture)));
 974        }
 975
 528976        list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty));
 528977        list.Add(new NameValuePair("api_key", accessToken ?? string.Empty));
 978
 528979        string? liveStreamId = item.MediaSource?.LiveStreamId;
 528980        list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty));
 981
 528982        list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod !=
 983
 528984        if (!item.IsDirectStream)
 985        {
 296986            if (item.RequireNonAnamorphic)
 987            {
 0988                list.Add(new NameValuePair("RequireNonAnamorphic", item.RequireNonAnamorphic.ToString(CultureInfo.Invari
 989            }
 990
 296991            list.Add(new NameValuePair("TranscodingMaxAudioChannels", item.TranscodingMaxAudioChannels.HasValue ? item.T
 992
 296993            if (item.EnableSubtitlesInManifest)
 994            {
 0995                list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString(CultureI
 996            }
 997
 296998            if (item.EnableMpegtsM2TsMode)
 999            {
 01000                list.Add(new NameValuePair("EnableMpegtsM2TsMode", item.EnableMpegtsM2TsMode.ToString(CultureInfo.Invari
 1001            }
 1002
 2961003            if (item.EstimateContentLength)
 1004            {
 01005                list.Add(new NameValuePair("EstimateContentLength", item.EstimateContentLength.ToString(CultureInfo.Inva
 1006            }
 1007
 2961008            if (item.TranscodeSeekInfo != TranscodeSeekInfo.Auto)
 1009            {
 01010                list.Add(new NameValuePair("TranscodeSeekInfo", item.TranscodeSeekInfo.ToString().ToLowerInvariant()));
 1011            }
 1012
 2961013            if (item.CopyTimestamps)
 1014            {
 241015                list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString(CultureInfo.InvariantCulture).
 1016            }
 1017
 2961018            list.Add(new NameValuePair("RequireAvc", item.RequireAvc.ToString(CultureInfo.InvariantCulture).ToLowerInvar
 1019
 2961020            list.Add(new NameValuePair("EnableAudioVbrEncoding", item.EnableAudioVbrEncoding.ToString(CultureInfo.Invari
 1021        }
 1022
 5281023        list.Add(new NameValuePair("Tag", item.MediaSource?.ETag ?? string.Empty));
 1024
 5281025        string subtitleCodecs = item.SubtitleCodecs.Count == 0 ?
 5281026            string.Empty :
 5281027            string.Join(",", item.SubtitleCodecs);
 1028
 5281029        list.Add(new NameValuePair("SubtitleCodec", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod == 
 1030
 5281031        if (item.SubProtocol == MediaStreamProtocol.hls)
 1032        {
 2521033            list.Add(new NameValuePair("SegmentContainer", item.Container ?? string.Empty));
 1034
 2521035            if (item.SegmentLength.HasValue)
 1036            {
 01037                list.Add(new NameValuePair("SegmentLength", item.SegmentLength.Value.ToString(CultureInfo.InvariantCultu
 1038            }
 1039
 2521040            if (item.MinSegments.HasValue)
 1041            {
 1921042                list.Add(new NameValuePair("MinSegments", item.MinSegments.Value.ToString(CultureInfo.InvariantCulture))
 1043            }
 1044
 2521045            list.Add(new NameValuePair("BreakOnNonKeyFrames", item.BreakOnNonKeyFrames.ToString(CultureInfo.InvariantCul
 1046        }
 1047
 57601048        foreach (var pair in item.StreamOptions)
 1049        {
 23521050            if (string.IsNullOrEmpty(pair.Value))
 1051            {
 1052                continue;
 1053            }
 1054
 1055            // strip spaces to avoid having to encode h264 profile names
 23521056            list.Add(new NameValuePair(pair.Key, pair.Value.Replace(" ", string.Empty, StringComparison.Ordinal)));
 1057        }
 1058
 5281059        if (!item.IsDirectStream)
 1060        {
 2961061            list.Add(new NameValuePair("TranscodeReasons", item.TranscodeReasons.ToString()));
 1062        }
 1063
 5281064        return list;
 1065    }
 1066
 1067    /// <summary>
 1068    /// Gets the subtitle profiles.
 1069    /// </summary>
 1070    /// <param name="transcoderSupport">The transcoder support.</param>
 1071    /// <param name="includeSelectedTrackOnly">If only the selected track should be included.</param>
 1072    /// <param name="baseUrl">The base URL.</param>
 1073    /// <param name="accessToken">The access token.</param>
 1074    /// <returns>The <see cref="SubtitleStreamInfo"/> of the profiles.</returns>
 1075    public IEnumerable<SubtitleStreamInfo> GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelecte
 1076    {
 01077        return GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken);
 1078    }
 1079
 1080    /// <summary>
 1081    /// Gets the subtitle profiles.
 1082    /// </summary>
 1083    /// <param name="transcoderSupport">The transcoder support.</param>
 1084    /// <param name="includeSelectedTrackOnly">If only the selected track should be included.</param>
 1085    /// <param name="enableAllProfiles">If all profiles are enabled.</param>
 1086    /// <param name="baseUrl">The base URL.</param>
 1087    /// <param name="accessToken">The access token.</param>
 1088    /// <returns>The <see cref="SubtitleStreamInfo"/> of the profiles.</returns>
 1089    public IEnumerable<SubtitleStreamInfo> GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelecte
 1090    {
 01091        if (MediaSource is null)
 1092        {
 01093            return [];
 1094        }
 1095
 01096        List<SubtitleStreamInfo> list = [];
 1097
 1098        // HLS will preserve timestamps so we can just grab the full subtitle stream
 01099        long startPositionTicks = SubProtocol == MediaStreamProtocol.hls
 01100            ? 0
 01101            : (PlayMethod == PlayMethod.Transcode && !CopyTimestamps ? StartPositionTicks : 0);
 1102
 1103        // First add the selected track
 01104        if (SubtitleStreamIndex.HasValue)
 1105        {
 01106            foreach (var stream in MediaSource.MediaStreams)
 1107            {
 01108                if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value)
 1109                {
 01110                    AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startP
 1111                }
 1112            }
 1113        }
 1114
 01115        if (!includeSelectedTrackOnly)
 1116        {
 01117            foreach (var stream in MediaSource.MediaStreams)
 1118            {
 01119                if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != Subtitl
 1120                {
 01121                    AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startP
 1122                }
 1123            }
 1124        }
 1125
 01126        return list;
 1127    }
 1128
 1129    private void AddSubtitleProfiles(List<SubtitleStreamInfo> list, MediaStream stream, ITranscoderSupport transcoderSup
 1130    {
 01131        if (enableAllProfiles)
 1132        {
 01133            foreach (var profile in DeviceProfile.SubtitleProfiles)
 1134            {
 01135                var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }, tr
 01136                if (info is not null)
 1137                {
 01138                    list.Add(info);
 1139                }
 1140            }
 1141        }
 1142        else
 1143        {
 01144            var info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitlePro
 01145            if (info is not null)
 1146            {
 01147                list.Add(info);
 1148            }
 1149        }
 01150    }
 1151
 1152    private SubtitleStreamInfo? GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string? accessToken, long star
 1153    {
 01154        if (MediaSource is null)
 1155        {
 01156            return null;
 1157        }
 1158
 01159        var subtitleProfile = StreamBuilder.GetSubtitleProfile(MediaSource, stream, subtitleProfiles, PlayMethod, transc
 01160        var info = new SubtitleStreamInfo
 01161        {
 01162            IsForced = stream.IsForced,
 01163            Language = stream.Language,
 01164            Name = stream.Language ?? "Unknown",
 01165            Format = subtitleProfile.Format,
 01166            Index = stream.Index,
 01167            DeliveryMethod = subtitleProfile.Method,
 01168            DisplayTitle = stream.DisplayTitle
 01169        };
 1170
 01171        if (info.DeliveryMethod == SubtitleDeliveryMethod.External)
 1172        {
 01173            if (MediaSource.Protocol == MediaProtocol.File || !string.Equals(stream.Codec, subtitleProfile.Format, Strin
 1174            {
 01175                info.Url = string.Format(
 01176                    CultureInfo.InvariantCulture,
 01177                    "{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}",
 01178                    baseUrl,
 01179                    ItemId,
 01180                    MediaSourceId,
 01181                    stream.Index.ToString(CultureInfo.InvariantCulture),
 01182                    startPositionTicks.ToString(CultureInfo.InvariantCulture),
 01183                    subtitleProfile.Format);
 1184
 01185                if (!string.IsNullOrEmpty(accessToken))
 1186                {
 01187                    info.Url += "?api_key=" + accessToken;
 1188                }
 1189
 01190                info.IsExternalUrl = false;
 1191            }
 1192            else
 1193            {
 01194                info.Url = stream.Path;
 01195                info.IsExternalUrl = true;
 1196            }
 1197        }
 1198
 01199        return info;
 1200    }
 1201
 1202    /// <summary>
 1203    /// Gets the target video bit depth.
 1204    /// </summary>
 1205    /// <param name="codec">The codec.</param>
 1206    /// <returns>The target video bit depth.</returns>
 1207    public int? GetTargetVideoBitDepth(string? codec)
 1208    {
 941209        var value = GetOption(codec, "videobitdepth");
 1210
 941211        if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
 1212        {
 941213            return result;
 1214        }
 1215
 01216        return null;
 1217    }
 1218
 1219    /// <summary>
 1220    /// Gets the target audio bit depth.
 1221    /// </summary>
 1222    /// <param name="codec">The codec.</param>
 1223    /// <returns>The target audio bit depth.</returns>
 1224    public int? GetTargetAudioBitDepth(string? codec)
 1225    {
 01226        var value = GetOption(codec, "audiobitdepth");
 1227
 01228        if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
 1229        {
 01230            return result;
 1231        }
 1232
 01233        return null;
 1234    }
 1235
 1236    /// <summary>
 1237    /// Gets the target video level.
 1238    /// </summary>
 1239    /// <param name="codec">The codec.</param>
 1240    /// <returns>The target video level.</returns>
 1241    public double? GetTargetVideoLevel(string? codec)
 1242    {
 2941243        var value = GetOption(codec, "level");
 1244
 2941245        if (double.TryParse(value, CultureInfo.InvariantCulture, out var result))
 1246        {
 1621247            return result;
 1248        }
 1249
 1321250        return null;
 1251    }
 1252
 1253    /// <summary>
 1254    /// Gets the target reference frames.
 1255    /// </summary>
 1256    /// <param name="codec">The codec.</param>
 1257    /// <returns>The target reference frames.</returns>
 1258    public int? GetTargetRefFrames(string? codec)
 1259    {
 21260        var value = GetOption(codec, "maxrefframes");
 1261
 21262        if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
 1263        {
 01264            return result;
 1265        }
 1266
 21267        return null;
 1268    }
 1269
 1270    /// <summary>
 1271    /// Gets the target audio channels.
 1272    /// </summary>
 1273    /// <param name="codec">The codec.</param>
 1274    /// <returns>The target audio channels.</returns>
 1275    public int? GetTargetAudioChannels(string? codec)
 1276    {
 1681277        var defaultValue = GlobalMaxAudioChannels ?? TranscodingMaxAudioChannels;
 1278
 1681279        var value = GetOption(codec, "audiochannels");
 1681280        if (string.IsNullOrEmpty(value))
 1281        {
 1681282            return defaultValue;
 1283        }
 1284
 01285        if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
 1286        {
 01287            return Math.Min(result, defaultValue ?? result);
 1288        }
 1289
 01290        return defaultValue;
 1291    }
 1292
 1293    /// <summary>
 1294    /// Gets the media stream count.
 1295    /// </summary>
 1296    /// <param name="type">The type.</param>
 1297    /// <param name="limit">The limit.</param>
 1298    /// <returns>The media stream count.</returns>
 1299    private int? GetMediaStreamCount(MediaStreamType type, int limit)
 1300    {
 01301        var count = MediaSource?.GetStreamCount(type);
 1302
 01303        if (count.HasValue)
 1304        {
 01305            count = Math.Min(count.Value, limit);
 1306        }
 1307
 01308        return count;
 1309    }
 1310}

Methods/Properties

get_MediaSourceId()
get_IsDirectStream()
get_TargetAudioStream()
get_TargetVideoStream()
get_TargetAudioSampleRate()
get_TargetAudioBitDepth()
get_TargetVideoBitDepth()
get_TargetRefFrames()
get_TargetFramerate()
get_TargetVideoLevel()
get_TargetPacketLength()
get_TargetVideoProfile()
get_TargetVideoRangeType()
get_TargetVideoCodecTag()
get_TargetAudioBitrate()
get_TargetAudioChannels()
get_TargetAudioCodec()
get_TargetVideoCodec()
get_TargetSize()
get_TargetVideoBitrate()
get_TargetTimestamp()
get_TargetTotalBitrate()
get_IsTargetAnamorphic()
get_IsTargetInterlaced()
get_IsTargetAVC()
get_TargetWidth()
get_TargetHeight()
get_TargetVideoStreamCount()
get_TargetAudioStreamCount()
SetOption(System.String,System.String,System.String)
SetOption(System.String,System.String)
GetOption(System.String,System.String)
GetOption(System.String)
ToUrl(System.String,System.String)
GetUrl(System.String,System.String)
BuildParams(MediaBrowser.Model.Dlna.StreamInfo,System.String)
GetSubtitleProfiles(MediaBrowser.Model.Dlna.ITranscoderSupport,System.Boolean,System.String,System.String)
GetSubtitleProfiles(MediaBrowser.Model.Dlna.ITranscoderSupport,System.Boolean,System.Boolean,System.String,System.String)
AddSubtitleProfiles(System.Collections.Generic.List`1<MediaBrowser.Model.Dlna.SubtitleStreamInfo>,MediaBrowser.Model.Entities.MediaStream,MediaBrowser.Model.Dlna.ITranscoderSupport,System.Boolean,System.String,System.String,System.Int64)
GetSubtitleStreamInfo(MediaBrowser.Model.Entities.MediaStream,System.String,System.String,System.Int64,MediaBrowser.Model.Dlna.SubtitleProfile[],MediaBrowser.Model.Dlna.ITranscoderSupport)
GetTargetVideoBitDepth(System.String)
GetTargetAudioBitDepth(System.String)
GetTargetVideoLevel(System.String)
GetTargetRefFrames(System.String)
GetTargetAudioChannels(System.String)
GetMediaStreamCount(MediaBrowser.Model.Entities.MediaStreamType,System.Int32)