public void Reset_CalledWhileFlushIsInProgress_CancelsFlush() { AsyncContext.Run(async() => { var demuxerStub = Substitute.For <IDemuxer>(); demuxerStub.Completion.Returns(Task.Delay(-1)); using (var controller = new DemuxerController(demuxerStub)) { var flushTask = controller.Flush(); controller.Reset(); try { await flushTask; Assert.Fail(); } catch (TaskCanceledException) { // ignored } catch (OperationCanceledException) { // ignored } } }); }
public void Start_PacketsDemuxed_PublishesPackets(StartType startType) { AsyncContext.Run(async() => { var demuxerStub = Substitute.For <IDemuxer>(); var packet = new Packet { StreamType = StreamType.Video, IsEOS = false, IsKeyFrame = true }; demuxerStub.NextPacket().Returns(Task.FromResult(packet)); demuxerStub.IsInitialized().Returns(true); demuxerStub.Completion.Returns(Task.Delay(500)); using (var controller = new DemuxerController(demuxerStub)) { var packetReadyTask = controller.PacketReady() .Take(2) .Count() .FirstAsync() .ToTask(); StartController(controller, startType); var receivedCount = await packetReadyTask; Assert.That(receivedCount, Is.EqualTo(2)); } }); }
public void Start_DRMInitDataFound_PublishesDRMInitData(StartType startType) { AsyncContext.Run(async() => { var initData = new DRMInitData { StreamType = StreamType.Video, InitData = new byte[1] }; var demuxerStub = CreateDemuxerStub(new ClipConfiguration { DrmInitDatas = new List <DRMInitData> { initData } }, startType); using (var controller = new DemuxerController(demuxerStub)) { var initDataTask = controller.DrmInitDataFound().FirstAsync().ToTask(); StartController(controller, startType); var receivedInitData = await initDataTask; Assert.That(receivedInitData, Is.EqualTo(initData)); } }); }
private static DashMediaPipeline CreateMediaPipeline(StreamType streamType) { var throughputHistory = new ThroughputHistory(); var dashClient = new DashClient(throughputHistory, streamType); var controller = new DemuxerController(new FFmpegDemuxer(new FFmpegGlue())); controller.SetDataSource(dashClient.ChunkReady()); return(new DashMediaPipeline(dashClient, controller, throughputHistory, streamType)); }
private static IDemuxerController CreateDemuxerController(IObservable <byte[]> chunkReady = null) { var demuxer = new FFmpegDemuxer(new FFmpegGlue()); var controller = new DemuxerController(demuxer); if (chunkReady != null) { controller.SetDataSource(chunkReady); } return(controller); }
public void Reset_Called_ResetsDemuxer() { var demuxerMock = Substitute.For <IDemuxer>(); using (var controller = new DemuxerController(demuxerMock)) { controller.Reset(); demuxerMock.Received().Reset(); } }
public void Flush_Called_ResetsDemuxer() { AsyncContext.Run(async() => { var demuxerMock = Substitute.For <IDemuxer>(); using (var controller = new DemuxerController(demuxerMock)) { await controller.Flush(); demuxerMock.Received().Reset(); } }); }
public void Seek_CalledWhenPaused_DoesntDemuxNextPacket() { AsyncContext.Run(async() => { var demuxerMock = Substitute.For <IDemuxer>(); demuxerMock.IsInitialized().Returns(true); using (var controller = new DemuxerController(demuxerMock)) { controller.Pause(); await controller.Seek(TimeSpan.FromSeconds(5), CancellationToken.None); await demuxerMock.DidNotReceive().NextPacket(); } }); }
public void Flush_CalledWhileChunkIsPending_ChunkIsDeliveredToDemuxer() { AsyncContext.Run(async() => { var demuxerMock = Substitute.For <IDemuxer>(); using (var controller = new DemuxerController(demuxerMock)) { var subject = new Subject <byte[]>(); controller.SetDataSource(subject.AsObservable()); subject.OnNext(new byte[0]); demuxerMock.When(demuxer => demuxer.Complete()) .Do(_ => demuxerMock.Received().PushChunk(Arg.Any <byte[]>())); await controller.Flush(); } }); }
public IDataProvider Create(ClipDefinition clip) { if (clip == null) { throw new ArgumentNullException(nameof(clip), "clip cannot be null"); } if (!SupportsClip(clip)) { throw new ArgumentException("unsupported clip type"); } var demuxer = new FFmpegDemuxer(new FFmpegGlue()); var demuxerController = new DemuxerController(demuxer); return(new HLSDataProvider(demuxerController, clip)); }
public void Start_DemuxerInitFails_PublishesDemuxerError(StartType startType) { AsyncContext.Run(async() => { var demuxerStub = CreateFailingDemuxerStub(startType); using (var controller = new DemuxerController(demuxerStub)) { var demuxerErrorTask = controller.DemuxerError().FirstAsync().ToTask(); StartController(controller, startType); var error = await demuxerErrorTask; Assert.That(error, Is.Not.Null); } }); }
public void Reset_CalledWhileDataSourcePublishedChunk_SkipsPublishedChunk() { AsyncContext.Run(async() => { var demuxerMock = Substitute.For <IDemuxer>(); using (var dataSource = new Subject <byte[]>()) using (var controller = new DemuxerController(demuxerMock)) { controller.SetDataSource(dataSource); dataSource.OnNext(new byte[1]); controller.Reset(); await Task.Yield(); demuxerMock.DidNotReceive().PushChunk(Arg.Any <byte[]>()); } }); }
public void Pause_Called_DoesntRetrieveNextPacket(StartType startType) { AsyncContext.Run(async() => { var demuxerMock = Substitute.For <IDemuxer>(); demuxerMock.IsInitialized().Returns(true); using (var controller = new DemuxerController(demuxerMock)) { StartController(controller, startType); controller.Pause(); await Task.Yield(); await demuxerMock.DidNotReceive().NextPacket(); } }); }
public void Seek_Called_ListensForEos() { AsyncContext.Run(async() => { var demuxerStub = Substitute.For <IDemuxer>(); demuxerStub.NextPacket().Returns(Utils.TaskExtensions.Never <Packet>()); demuxerStub.Completion.Returns(Task.CompletedTask); using (var controller = new DemuxerController(demuxerStub)) { var packetReady = controller.PacketReady().FirstAsync().ToTask(); await controller.Seek(TimeSpan.FromSeconds(5), CancellationToken.None); var packet = await packetReady; Assert.That(packet, Is.Null); } }); }
public IDataProvider Create(ClipDefinition clip) { if (clip == null) { throw new ArgumentNullException(nameof(clip), "clip cannot be null"); } if (!SupportsClip(clip)) { throw new ArgumentException("unsupported clip type"); } var rtspClient = new RTSPClient(); var demuxer = new FFmpegDemuxer(new FFmpegGlue()); var demuxerController = new DemuxerController(demuxer); demuxerController.SetDataSource(rtspClient.ChunkReady()); return(new RTSPDataProvider(demuxerController, rtspClient, clip)); }
public void Start_ClipDurationFound_PublishesClipDuration(StartType startType) { AsyncContext.Run(async() => { var expectedDuration = TimeSpan.FromSeconds(10); var demuxerStub = CreateDemuxerStub(new ClipConfiguration { Duration = expectedDuration }, startType); using (var controller = new DemuxerController(demuxerStub)) { var clipDurationTask = controller.ClipDurationFound().FirstAsync().ToTask(); StartController(controller, startType); var duration = await clipDurationTask; Assert.That(duration, Is.EqualTo(expectedDuration)); } }); }
public void SetDataSource_DataSourceCompletes_SignalsEos() { AsyncContext.Run(async() => { var demuxerStub = Substitute.For <IDemuxer>(); var dataSource = new Subject <byte[]>(); using (var controller = new DemuxerController(demuxerStub)) { controller.SetDataSource(dataSource); var packetReadyTask = controller.PacketReady() .FirstAsync() .ToTask(); dataSource.OnNext(null); var isEmpty = await packetReadyTask; Assert.That(isEmpty, Is.Null); } }); }
public void Start_StreamConfigFound_PublishesStreamConfig(StartType startType) { AsyncContext.Run(async() => { var videoConfig = new VideoStreamConfig(); var demuxerStub = CreateDemuxerStub(new ClipConfiguration { StreamConfigs = new List <StreamConfig> { videoConfig } }, startType); using (var controller = new DemuxerController(demuxerStub)) { var streamConfigTask = controller.StreamConfigReady().FirstAsync().ToTask(); StartController(controller, startType); var receivedConfig = await streamConfigTask; Assert.That(receivedConfig, Is.EqualTo(videoConfig)); } }); }
public void Reset_Called_NextPacketNotCalledAfter(StartType startType) { AsyncContext.Run(async() => { var demuxerMock = Substitute.For <IDemuxer>(); var tcs = new TaskCompletionSource <Packet>(); demuxerMock.NextPacket().Returns(tcs.Task); demuxerMock.IsInitialized().Returns(true); using (var controller = new DemuxerController(demuxerMock)) { StartController(controller, startType); await Task.Yield(); // Demuxer.InitFor completes, first Demuxer.NextPacket is called controller.Reset(); tcs.SetResult(new Packet()); await Task.Yield(); // first Demuxer.NextPacket completes and another Demuxer.NextPacket is // not called await demuxerMock.Received(1).NextPacket(); } }); }