/// <summary> /// Parses PMT structure. /// </summary> /// <param name="program"></param> /// <param name="br"></param> private void ParsePMT(TSPacket tsPacket, TSProgram program) { tsPacket.ParsePMTHeader(); uint streamTypeCode = 0; uint elementary_PID = 0; uint ES_info_length = 0; while (tsPacket.ParseNextPMTStream(ref streamTypeCode, ref elementary_PID, ref ES_info_length)) { // Allocate stream and payload handlers if (_streams == null) _streams = new Dictionary<uint, TSStream>(); TSStream stream; bool discontinuity; HLSTrace.WriteLineLow("PMT: type {0} pid {1} len {2}", streamTypeCode.ToString("X"), elementary_PID.ToString("X"), ES_info_length.ToString("X")); if (_streams.TryGetValue(elementary_PID, out stream)) { discontinuity = false; } else { if (streamTypeCode == AVC_STREAM_TYPE_CODE) { stream = new TSStream(elementary_PID, TSStream.StreamContetType.Video); if (_videoFormatParser == null) _videoFormatParser = new H264Parser(_videoBuffer, _metadata, _stream.HLSStream ); else _videoFormatParser.Flush(); _videoFormatParser.Bitrate = _bitrate; stream.Parser = new PESParser(_videoFormatParser); } else if (streamTypeCode == AAC_STREAM_TYPE_CODE || streamTypeCode == DDPLUS_STREAM_TYPE_CODE) { stream = new TSStream(elementary_PID, TSStream.StreamContetType.Audio); bool discardThisStream = false; foreach (KeyValuePair<uint, TSStream> s in _streams) { if (s.Value.StreamType == TSStream.StreamContetType.Audio) { if (s.Key > elementary_PID) { if (_nullFormatParser == null) _nullFormatParser = new NullParser(null); s.Value.Parser = new PESParser(_nullFormatParser); } else { discardThisStream = true; break; } } } if (discardThisStream) { if (_nullFormatParser == null) _nullFormatParser = new NullParser(null); stream.Parser = new PESParser(_nullFormatParser); stream.StreamType = TSStream.StreamContetType.Unknown; } else { if (null != _audioFormatParser) { _audioFormatParser.Flush(); } if (streamTypeCode == AAC_STREAM_TYPE_CODE) _audioFormatParser = new ADTSParser(_audioBuffer, _stream.HLSStream); else _audioFormatParser = new DDPlusParser(_audioBuffer, _stream.HLSStream); stream.Parser = new PESParser(_audioFormatParser); stream.StreamType = TSStream.StreamContetType.Audio; } } else { stream = new TSStream(elementary_PID, TSStream.StreamContetType.Unknown); HLSTrace.WriteLine("Ignoring unknown stream type {0}", streamTypeCode); if (_nullFormatParser == null) _nullFormatParser = new NullParser(null); stream.Parser = new PESParser(_nullFormatParser); } _streams[elementary_PID] = stream; discontinuity = true; } program.AddStream(stream); stream.Parser.StartSegment(discontinuity); } }
/// <summary> /// Parses a single packet of MPEG-2 Transport Stream. Packet must be exactly 188 bytes long /// and must begin with packet signature. /// </summary> /// <param name="byteBuffer"></param> protected void ParsePacket(byte[] byteBuffer) { TSPacket tsPacket = new TSPacket(byteBuffer); if (tsPacket.HasPayload()) { if (tsPacket._pid == 0) { if (!_parsedPAT) { _parsedPAT = true; if (_programs == null) _programs = new Dictionary<uint, TSProgram>(); tsPacket.ParsePAT(ref _programs); } } else { TSProgram program; if (_programs != null && _programs.TryGetValue(tsPacket._pid, out program)) { if (!program.ParsedPMT) { program.ParsedPMT = true; ParsePMT(tsPacket, program); } } else { TSStream stream; if (_streams != null && _streams.TryGetValue(tsPacket._pid, out stream)) { if ((tsPacket._transport_error_indicator == 0x01) || tsPacket._discontinuity) { stream.Flush(true); HLSTrace.WriteLine("Flush{0}: TEI {1:X} discontinuity {2:X}", tsPacket._pid, tsPacket._transport_error_indicator, tsPacket._discontinuity); } stream.ParseData(byteBuffer, tsPacket._headerSize, byteBuffer.Length - tsPacket._headerSize, (int)tsPacket._continuity_counter); } } } } }