Exemplo n.º 1
0
            public void WritePMT(int pid, ProgramMapTable pmt)
            {
                var program_info = new MemoryStream();

                using (program_info) {
                    foreach (var entry in pmt.ProgramInfo)
                    {
                        program_info.WriteByte(entry.Tag);
                        program_info.WriteByte(entry.Data.Length);
                        program_info.Write(entry.Data, 0, entry.Data.Length);
                    }
                }

                var body = new MemoryStream();

                using (body) {
                    body.WriteUInt16BE(pmt.ProgramNumber);
                    body.WriteByte((3 << 6) | (pmt.Version << 1) | (pmt.CurrentNextIndicator ? 1 : 0));
                    body.WriteByte(pmt.SectionNumber);
                    body.WriteByte(pmt.LastSectionNumber);
                    body.WriteUInt16BE((7 << 13) | (pmt.PCRPID & 0x1FFF));
                    var program_info_ary = program_info.ToArray();
                    body.WriteUInt16BE((15 << 12) | program_info_ary.Length);
                    body.Write(program_info_ary, 0, program_info_ary.Length);
                    foreach (var entry in pmt.Table)
                    {
                        body.WriteByte(entry.StreamType);
                        body.WriteUInt16BE((7 << 13) | (entry.PID & 0x1FFF));
                        body.WriteUInt16BE((15 << 12) | (entry.ESInfo.Length & 0xFFF));
                        body.Write(entry.ESInfo, 0, entry.ESInfo.Length);
                    }
                }
                WriteSection(pid, 0x02, body.ToArray());
            }
Exemplo n.º 2
0
 private void Clear()
 {
     pps        = new NALUnit[0];
     sps        = new NALUnit[0];
     spsExt     = new NALUnit[0];
     pat        = new ProgramAssociationTable();
     pmt        = new ProgramMapTable();
     adtsHeader = ADTSHeader.Default;
     nalSizeLen = 0;
     ptsBase    = -1;
 }
Exemplo n.º 3
0
        private void ProcessQueueWorkerThread()
        {
            var dataBuffer = new byte[12 + (188 * 7)];

            while (_pendingExit != true)
            {
                try
                {
                    lock (_ringBuffer)
                    {
                        int   dataSize;
                        ulong timestamp;

                        if (_ringBuffer.BufferFullness < 10)
                        {
                            Thread.Sleep(1);
                            continue;
                        }

                        var capacity = _ringBuffer.Remove(ref dataBuffer, out dataSize, out timestamp);

                        if (capacity > 0)
                        {
                            dataBuffer = new byte[capacity];
                            continue;
                        }

                        if (dataBuffer == null)
                        {
                            continue;
                        }

                        var packets = Factory.GetTsPacketsFromData(dataBuffer, dataSize);

                        //use decoder to register default program (muxing always happens on default program)
                        if (_mainStreamDecoder.GetSelectedPmt() == null)
                        {
                            _mainStreamDecoder.AddPackets(packets);
                        }
                        else
                        {
                            if (_mainStreamTargetPmt == null && _subStreamSourcePmt != null)
                            {
                                _mainStreamTargetPmt = _mainStreamDecoder.GetSelectedPmt();

                                var pmtSpaceNeeded = 0;
                                foreach (var esinfo in _subStreamSourcePmt.EsStreams)
                                {
                                    if (_subPids.Contains(esinfo.ElementaryPid))
                                    {
                                        pmtSpaceNeeded += esinfo.SourceData.Length;
                                    }
                                }

                                if ((_mainStreamTargetPmt.SectionLength + pmtSpaceNeeded) > (TsPacketSize - 12))
                                {
                                    throw new InvalidDataException(
                                              "Cannot add to PMT - no room (packet spanned PMT not supported)");
                                }
                            }
                        }

                        //check for any PMT packets, and adjust them to reflect the new muxed reality...
                        foreach (var packet in packets)
                        {
                            if (_mainStreamTargetPmt != null && packet.Pid == _mainStreamTargetPmt.Pid)
                            {
                                //this is the PMT for the target program on the target stream - patch in the substream PID entries
                                foreach (var esinfo in _subStreamSourcePmt.EsStreams)
                                {
                                    if (_subPids.Contains(esinfo.ElementaryPid))
                                    {
                                        //locate current SectionLength bytes in databuffer
                                        var pos = packet.SourceBufferIndex +
                                                  4;         //advance to start of PMT data structure (past TS header)
                                        var pointerField = dataBuffer[pos];
                                        pos += pointerField; //advance by pointer field
                                        var SectionLength =
                                            (short)(((dataBuffer[pos + 2] & 0x3) << 8) +
                                                    dataBuffer[pos + 3]);  //get current length

                                        //increase length value by esinfo length
                                        var extendedSectionLength =
                                            (short)(SectionLength + (short)esinfo.SourceData.Length);

                                        //set back new length into databuffer
                                        var bytes = BitConverter.GetBytes(extendedSectionLength);
                                        dataBuffer[pos + 2] =
                                            (byte)((dataBuffer[pos + 2] & 0xFC) + (byte)(bytes[1] & 0x3));
                                        dataBuffer[pos + 3] = bytes[0];

                                        //copy esinfo source data to end of program block in pmt
                                        Buffer.BlockCopy(esinfo.SourceData, 0, dataBuffer,
                                                         packet.SourceBufferIndex + 4 + pointerField + SectionLength,
                                                         esinfo.SourceData.Length);

                                        //correct CRC after each extension
                                        var crcBytes = BitConverter.GetBytes(GenerateCRC(ref dataBuffer, pos + 1,
                                                                                         extendedSectionLength - 1));
                                        dataBuffer[packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength]
                                            = crcBytes[3];
                                        dataBuffer[
                                            packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength +
                                            1] =
                                            crcBytes[2];
                                        dataBuffer[
                                            packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength +
                                            2] =
                                            crcBytes[1];
                                        dataBuffer[
                                            packet.SourceBufferIndex + 4 + pointerField + extendedSectionLength +
                                            3] =
                                            crcBytes[0];
                                    }
                                }
                            }
                        }

                        //insert any queued filtered sub PID packets
                        if (_subPidBuffer.BufferFullness > 0)
                        {
                            foreach (var packet in packets)
                            {
                                if (packet.Pid == (short)PidType.NullPid)
                                {
                                    //candidate for wiping with any data queued up for muxing in
                                    byte[] subPidPacketBuffer = new byte[TsPacketSize];
                                    int    subPidDataSize     = 0;
                                    ulong  subPidTimeStamp    = 0;

                                    //see if there is any data waiting to get switched into the mux...
                                    lock (_subPidBuffer)
                                    {
                                        if (_subPidBuffer.BufferFullness < 1)
                                        {
                                            break; //double check here because prior check was not thread safe
                                        }
                                        var subPidPacketDataReturned = _subPidBuffer.Remove(ref subPidPacketBuffer,
                                                                                            out subPidDataSize, out subPidTimeStamp);
                                        if (subPidPacketDataReturned != 0 && subPidPacketDataReturned != TsPacketSize)
                                        {
                                            PrintToConsole("Sub PID data seems to not be size of TS packet!");
                                            return;
                                        }
                                    }

                                    if (packet.SourceBufferIndex % 188 != 0)
                                    {
                                        PrintToConsole("Misaligned packet");
                                        return;
                                    }

                                    Buffer.BlockCopy(subPidPacketBuffer, 0, dataBuffer, packet.SourceBufferIndex,
                                                     TsPacketSize);
                                }
                            }
                        }
                        var packetReadyEventArgs = new PacketReadyEventArgs();
                        packetReadyEventArgs.UdpPacketData = new byte[dataSize];
                        Buffer.BlockCopy(dataBuffer, 0, packetReadyEventArgs.UdpPacketData, 0, dataSize);
                        OnPacketReady(packetReadyEventArgs);
                    }
                }
                catch (Exception ex)
                {
                    PrintToConsole($@"Unhandled exception within network receiver: {ex.Message}");
                }
            }

            //Logger.Log(new TelemetryLogEventInfo { Level = LogLevel.Info, Message = "Stopping analysis thread due to exit request." });
        }
Exemplo n.º 4
0
        public async Task ReadAsync(IContentSink sink, Stream stream, CancellationToken cancel_token)
        {
            int      streamIndex       = -1;
            long     contentPosition   = 0;
            DateTime streamOrigin      = DateTime.Now;
            DateTime latestContentTime = DateTime.Now;

            byte[] bytes188    = new byte[188];
            byte[] latestHead  = new byte[0];
            byte[] contentData = null;

            streamIndex  = Channel.GenerateStreamID();
            streamOrigin = DateTime.Now;
            sink.OnContentHeader(new Content(streamIndex, TimeSpan.Zero, contentPosition, new byte[] {}, PCPChanPacketContinuation.None));

            try
            {
                while (!cancel_token.IsCancellationRequested)
                {
                    bytes188 = await stream.ReadBytesAsync(188, cancel_token).ConfigureAwait(false);

                    TSPacket packet = new TSPacket(bytes188);
                    if (packet.sync_byte != 0x47)
                    {
                        throw new Exception();
                    }
                    if (packet.payload_unit_start_indicator > 0)
                    {
                        if (packet.PID == patID)
                        {
                            pmtID = packet.PMTID;
                            head  = new MemoryStream();
                            if (!addHead(bytes188))
                            {
                                throw new Exception();
                            }
                            continue;
                        }
                        if (packet.PID == pmtID)
                        {
                            var pmt = new ProgramMapTable(packet, bytes188);
                            pcrPID = pmt.PCRPID;
                            if (!addHead(bytes188))
                            {
                                throw new Exception();
                            }
                            head.Close();
                            byte[] newHead = head.ToArray();
                            if (!Enumerable.SequenceEqual(newHead, latestHead))
                            {
                                streamIndex     = Channel.GenerateStreamID();
                                contentPosition = 0;
                                sink.OnContentHeader(new Content(streamIndex, DateTime.Now - streamOrigin, contentPosition, newHead, PCPChanPacketContinuation.None));
                                contentPosition += newHead.Length;
                                latestHead       = newHead;
                            }
                            continue;
                        }
                        if (packet.PID == pcrPID && packet.program_clock_reference > 0.0)
                        {
                            if (packet.program_clock_reference < rateCounter.lastPCR)
                            {
                                rateCounter.lastPCR   = packet.program_clock_reference;
                                rateCounter.byteCount = 0;
                                recvRate = 0.0;
                            }
                            else if (rateCounter.lastPCR + 10.0 < packet.program_clock_reference)
                            {
                                var bitrate = 8 * rateCounter.byteCount / (packet.program_clock_reference - rateCounter.lastPCR);
                                UpdateRecvRate(sink, bitrate);
                                rateCounter.lastPCR   = packet.program_clock_reference;
                                rateCounter.byteCount = 0;
                            }
                        }
                        if ((DateTime.Now - latestContentTime).Milliseconds > 50)
                        {
                            TryParseContent(packet, out contentData);
                            if (contentData != null)
                            {
                                sink.OnContent(new Content(streamIndex, DateTime.Now - streamOrigin, contentPosition, contentData, PCPChanPacketContinuation.None));
                                contentPosition  += contentData.Length;
                                latestContentTime = DateTime.Now;
                            }
                        }
                    }
                    if (!addCache(bytes188))
                    {
                        throw new Exception();
                    }
                    rateCounter.byteCount += 188;
                }
            }
            catch (EndOfStreamException)
            { }
            catch (Exception)
            { }
        }
Exemplo n.º 5
0
        private void ProcessSubQueueWorkerThread()
        {
            var dataBuffer = new byte[12 + (188 * 7)];

            while (_pendingExit != true)
            {
                try
                {
                    if (_subRingBuffer.BufferFullness < 1)
                    {
                        Thread.Sleep(1);
                        continue;
                    }

                    lock (_subRingBuffer)
                    {
                        if (_subRingBuffer.BufferFullness < 1)
                        {
                            continue;
                        }

                        int   dataSize;
                        ulong timestamp;

                        var capacity = _subRingBuffer.Remove(ref dataBuffer, out dataSize, out timestamp);

                        if (capacity > 0)
                        {
                            dataBuffer = new byte[capacity];
                            continue;
                        }

                        if (dataBuffer == null)
                        {
                            continue;
                        }

                        //check to see if there are any specific TS packets by PIDs we want to select

                        var packets = Factory.GetTsPacketsFromData(dataBuffer, dataSize, true, true);

                        foreach (var packet in packets)
                        {
                            if (_subStreamDecoder.GetSelectedPmt() == null)
                            {
                                _subStreamDecoder.AddPackets(packets);
                            }
                            else
                            {
                                if (_subStreamSourcePmt == null)
                                {
                                    _subStreamSourcePmt = _subStreamDecoder.GetSelectedPmt();
                                }
                            }

                            if (_subPids.Contains(packet.Pid))
                            {
                                //this pid is selected for mapping across... add to PID buffer to merge replacing NULL pid
                                var buffer = new byte[packet.SourceData.Length];
                                Buffer.BlockCopy(packet.SourceData, 0, buffer, 0, packet.SourceData.Length);
                                _subPidBuffer.Add(ref buffer);
                            }
                        }

                        //lock (_outputUdpClient)
                        //{
                        //    _outputUdpClient.Send(dataBuffer, dataSize);
                        //}
                    }
                }
                catch (Exception ex)
                {
                    PrintToConsole($@"Unhandled exception within network receiver: {ex.Message}");
                }
            }

            //Logger.Log(new TelemetryLogEventInfo { Level = LogLevel.Info, Message = "Stopping analysis thread due to exit request." });
        }