@@ -25,6 +25,7 @@ namespace ErsatzTV.Controllers;
|
||||
[ServiceFilter(typeof(ConditionalIptvAuthorizeFilter))]
|
||||
public class IptvController : StreamingControllerBase
|
||||
{
|
||||
private readonly IDirectStreamSessionTracker _directStreamSessionTracker;
|
||||
private readonly IFFmpegSegmenterService _ffmpegSegmenterService;
|
||||
private readonly ILogger<IptvController> _logger;
|
||||
private readonly IMediator _mediator;
|
||||
@@ -33,9 +34,11 @@ public class IptvController : StreamingControllerBase
|
||||
IMediator mediator,
|
||||
IGraphicsEngine graphicsEngine,
|
||||
ILogger<IptvController> logger,
|
||||
IFFmpegSegmenterService ffmpegSegmenterService)
|
||||
IFFmpegSegmenterService ffmpegSegmenterService,
|
||||
IDirectStreamSessionTracker directStreamSessionTracker)
|
||||
: base(graphicsEngine, logger)
|
||||
{
|
||||
_directStreamSessionTracker = directStreamSessionTracker;
|
||||
_mediator = mediator;
|
||||
_logger = logger;
|
||||
_ffmpegSegmenterService = ffmpegSegmenterService;
|
||||
@@ -150,7 +153,14 @@ public class IptvController : StreamingControllerBase
|
||||
}
|
||||
|
||||
process.Start();
|
||||
return new FileStreamResult(process.StandardOutput.BaseStream, "video/mp2t");
|
||||
return mode == "ts-legacy"
|
||||
? new TrackedFileStreamResult(
|
||||
process.StandardOutput.BaseStream,
|
||||
"video/mp2t",
|
||||
_directStreamSessionTracker,
|
||||
channelNumber,
|
||||
StreamingMode.TransportStream)
|
||||
: new FileStreamResult(process.StandardOutput.BaseStream, "video/mp2t");
|
||||
},
|
||||
error => BadRequest(error.Value)));
|
||||
}
|
||||
@@ -353,7 +363,11 @@ public class IptvController : StreamingControllerBase
|
||||
|
||||
Either<BaseError, PlayoutItemProcessModel> result = await _mediator.Send(request);
|
||||
|
||||
return GetProcessResponse(result, channelNumber, StreamingMode.HttpLiveStreamingDirect);
|
||||
return GetProcessResponse(
|
||||
result,
|
||||
channelNumber,
|
||||
StreamingMode.HttpLiveStreamingDirect,
|
||||
_directStreamSessionTracker);
|
||||
}
|
||||
|
||||
private string AccessTokenQuery() => string.IsNullOrWhiteSpace(Request.Query["access_token"])
|
||||
|
||||
@@ -16,7 +16,8 @@ public abstract class StreamingControllerBase(IGraphicsEngine graphicsEngine, IL
|
||||
protected IActionResult GetProcessResponse(
|
||||
Either<BaseError, PlayoutItemProcessModel> result,
|
||||
string channelNumber,
|
||||
StreamingMode mode)
|
||||
StreamingMode mode,
|
||||
IDirectStreamSessionTracker directStreamSessionTracker = null)
|
||||
{
|
||||
foreach (BaseError error in result.LeftToSeq())
|
||||
{
|
||||
@@ -30,14 +31,18 @@ public abstract class StreamingControllerBase(IGraphicsEngine graphicsEngine, IL
|
||||
|
||||
foreach (PlayoutItemProcessModel processModel in result.RightToSeq())
|
||||
{
|
||||
return StartPlayout(processModel);
|
||||
return StartPlayout(processModel, channelNumber, mode, directStreamSessionTracker);
|
||||
}
|
||||
|
||||
// this will never happen
|
||||
return new NotFoundResult();
|
||||
}
|
||||
|
||||
private FileStreamResult StartPlayout(PlayoutItemProcessModel processModel)
|
||||
private FileStreamResult StartPlayout(
|
||||
PlayoutItemProcessModel processModel,
|
||||
string channelNumber,
|
||||
StreamingMode mode,
|
||||
IDirectStreamSessionTracker directStreamSessionTracker)
|
||||
{
|
||||
// for process counter
|
||||
var ffmpegProcess = new FFmpegProcess();
|
||||
@@ -86,6 +91,10 @@ public abstract class StreamingControllerBase(IGraphicsEngine graphicsEngine, IL
|
||||
null,
|
||||
TaskScheduler.Default);
|
||||
|
||||
return new FileStreamResult(pipe.Reader.AsStream(), "video/mp2t");
|
||||
Stream stream = pipe.Reader.AsStream();
|
||||
|
||||
return directStreamSessionTracker is null
|
||||
? new FileStreamResult(stream, "video/mp2t")
|
||||
: new TrackedFileStreamResult(stream, "video/mp2t", directStreamSessionTracker, channelNumber, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Interfaces.Streaming;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace ErsatzTV.Controllers;
|
||||
|
||||
public class TrackedFileStreamResult(
|
||||
Stream fileStream,
|
||||
string contentType,
|
||||
IDirectStreamSessionTracker directStreamSessionTracker,
|
||||
string channelNumber,
|
||||
StreamingMode streamingMode) : FileStreamResult(fileStream, contentType)
|
||||
{
|
||||
public override async Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
using IDisposable registration = directStreamSessionTracker.Register(channelNumber, streamingMode);
|
||||
|
||||
await base.ExecuteResultAsync(context);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user