/// <summary> /// Adds the dlna headers. /// </summary> /// <param name="state">The state.</param> /// <param name="responseHeaders">The response headers.</param> /// <param name="profileManager">The <see cref="IDeviceProfileManager"/> instance.</param> /// <param name="isStaticallyStreamed">if set to <c>true</c> [is statically streamed].</param> /// <param name="startTimeTicks">The start time in ticks.</param> /// <param name="request">The <see cref="HttpRequest"/>.</param> private static void AddDlnaHeaders( StreamState state, IHeaderDictionary responseHeaders, IDeviceProfileManager profileManager, bool isStaticallyStreamed, long?startTimeTicks, HttpRequest request) { if (state == null) { throw new ArgumentNullException(nameof(state)); } if (responseHeaders == null) { throw new ArgumentNullException(nameof(responseHeaders)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } var enableDlnaHeaders = request.Query.TryGetValue("dlna", out _) || !string.Equals(request.Headers["GetContentFeatures.DLNA.ORG"], "1", StringComparison.Ordinal); if (!enableDlnaHeaders) { return; } var profile = state.DeviceProfile; StringValues transferMode = request.Headers["transferMode.dlna.org"]; responseHeaders.Add("transferMode.dlna.org", string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode.ToString()); responseHeaders.Add("realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"); if (state.RunTimeTicks.HasValue) { if (string.Equals(request.Headers["getMediaInfo.sec"], "1", StringComparison.OrdinalIgnoreCase)) { var ms = TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds; responseHeaders.Add("MediaInfo.sec", string.Format( CultureInfo.InvariantCulture, "SEC_Duration={0};", Convert.ToInt32(ms))); } if (!isStaticallyStreamed && profile != null) { AddTimeSeekResponseHeaders(state, responseHeaders, startTimeTicks); } } // if the profile hasn't been assigned see if there is one that matches. profile ??= profileManager.GetProfile( request.Headers, request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback, null); var audioCodec = state.ActualOutputAudioCodec; if (!state.IsVideoRequest) { responseHeaders.Add("contentFeatures.dlna.org", ContentFeatureBuilder.BuildAudioHeader( profile, state.OutputContainer, audioCodec, state.OutputAudioBitrate, state.OutputAudioSampleRate, state.OutputAudioChannels, state.OutputAudioBitDepth, isStaticallyStreamed, state.RunTimeTicks, state.TranscodeSeekInfo)); } else { var videoCodec = state.ActualOutputVideoCodec; responseHeaders.Add( "contentFeatures.dlna.org", ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty); } }
/// <summary> /// Applies the device profile to the streamstate. /// </summary> /// <param name="state">A <see cref="StreamState"/> instance.</param> /// <param name="deviceManager">The <see cref="IDeviceManager"/> instance.</param> /// <param name="profileManager">The <see cref="IDeviceProfileManager"/> instance.</param> /// <param name="request">A <see cref="HttpRequest"/> instance.</param> /// <param name="deviceProfileId">Optional. Device profile id. </param> /// <param name="static">True if static.</param> private static void ApplyDeviceProfileSettings( StreamState state, IDeviceManager deviceManager, IDeviceProfileManager profileManager, HttpRequest request, string?deviceProfileId, bool? @static) { if (state == null) { throw new ArgumentNullException(nameof(state)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } if (deviceManager == null) { throw new ArgumentNullException(nameof(deviceManager)); } if (!string.IsNullOrWhiteSpace(deviceProfileId)) { state.DeviceProfile = profileManager.GetProfile(Guid.Parse(deviceProfileId)); if (state.DeviceProfile == null) { var caps = deviceManager.GetCapabilities(deviceProfileId); state.DeviceProfile = profileManager.GetProfile( request.Headers, request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback, caps?.DeviceProfile); } } var profile = state.DeviceProfile; if (profile == null) { // Don't use settings from the default profile. // Only use a specific profile if it was requested. return; } var audioCodec = state.ActualOutputAudioCodec; var videoCodec = state.ActualOutputVideoCodec; var mediaProfile = !state.IsVideoRequest ? profile.GetAudioMediaProfile(state.OutputContainer, audioCodec, state.OutputAudioChannels, state.OutputAudioBitrate, state.OutputAudioSampleRate, state.OutputAudioBitDepth) : profile.GetVideoMediaProfile( state.OutputContainer, audioCodec, videoCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TargetTimestamp, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC); if (mediaProfile != null) { state.MimeType = mediaProfile.MimeType; } if (@static.HasValue && @static.Value) { return; } var transcodingProfile = !state.IsVideoRequest ? profile.GetAudioTranscodingProfile(state.OutputContainer, audioCodec) : profile.GetVideoTranscodingProfile(state.OutputContainer, audioCodec, videoCodec); if (transcodingProfile == null) { return; } state.EstimateContentLength = transcodingProfile.EstimateContentLength; // state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; if (state.VideoRequest == null) { return; } state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; state.VideoRequest.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; }