public override DataReader With(DataProvider dataProvider, PresentPacketDelegate presentPacket)
        {
            Log.Enter($"{dataProvider.GetType()}, {presentPacket.GetType()}");

            if (ErrorHandler == null)
            {
                Log.Warn($"{nameof(ErrorHandler)} not set before start");
            }

            _readSessionCts   = new CancellationTokenSource();
            _readLoopTaskTask = Task.Factory.StartNew(
                () => ReadLoop(dataProvider, presentPacket, _readSessionCts.Token),
                TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach);
            Log.Info("DataReader starting");

            Log.Exit();
            return(this);
        }
Ejemplo n.º 2
0
 public abstract DataReader With(DataProvider dataProvider, PresentPacketDelegate presentPacket);
        private async Task ReadLoop(DataProvider dataProvider, PresentPacketDelegate presentPacket, CancellationToken token)
        {
            Log.Enter();

            var    scheduler = new GenericScheduler();
            Packet packet    = null;

            try
            {
                Log.Info("Started");

                while (!token.IsCancellationRequested)
                {
                    packet = await dataProvider.NextPacket(token);

                    if (packet == null)
                    {
                        // null packet indicates end of all streams.
                        presentPacket(null);
                        return;
                    }

                    var scheduleAfter = scheduler.Schedule(packet);
                    if (scheduleAfter != default)
                    {
                        Log.Verbose($"{packet.Pts} {packet.StreamType} delaying {scheduleAfter}");
                        await Task.Delay(scheduleAfter, token);
                    }

                    PresentPacketResult result = presentPacket(packet);
                    while (result != PresentPacketResult.Success)
                    {
                        if (result == PresentPacketResult.Fail)
                        {
                            throw new Exception($"PresentPacket failed {packet.Pts} {packet.StreamType}");
                        }

                        // PresentPacketResult.Retry
                        Log.Warn($"{packet.Pts} {packet.StreamType} Resubmit {ResubmitDelay}");
                        await Task.Delay(ResubmitDelay, token);

                        result = presentPacket(packet);
                    }

                    packet.Dispose();
                    packet = null;
                }
            }
            catch (OperationCanceledException)
            {
                Log.Info("Cancelled");
            }
            catch (Exception e)
            {
                var errorMsg = e.ToString();
                Log.Fatal(errorMsg);

                // Not much point in trying to resubmit a packet..
                packet?.Dispose();
                packet = null;

                ErrorHandler?.Invoke(errorMsg);
            }
            finally
            {
                // Abandoned packet
                if (packet != null)
                {
                    // Last chance scenario. Try pushing it. If cancellation was requested, we'll loose one packet less
                    if (presentPacket(packet) != PresentPacketResult.Success)
                    {
                        Log.Warn($"{packet.Pts} {packet.StreamType} Abandoned");
                    }

                    packet.Dispose();
                }

                Log.Info("Disposing packet scheduler");
                scheduler.Dispose();

                Log.Exit();
            }
        }