private bool SanityCheck(TSHeader header, byte[] tsPacket) { //LogDebug("PesDecoder::OnTsPacket %i", tsPacketCount++); if (tsPacket == null) { Log.Debug("tsPacket null!"); return(false); } // Assume that correct pid is passed! /*if (header.Pid != m_pid) * { * Log.Debug("Header Pid is %i, expected %i", header.Pid, m_pid); * return false; * }*/ if (header.SyncByte != TS_PACKET_SYNC) { Log.Debug("pesdecoder pid:%x sync error", m_pid); return(false); } if (header.TransportError) { m_bStart = false; m_iWritePos = 0; m_iPesLength = 0; Log.Debug("pesdecoder pid:%x transport error", m_pid); return(false); } bool scrambled = (header.TScrambling != 0); if (scrambled) { Log.Debug("pesdecoder scrambled!"); return(false); } if (header.AdaptionFieldOnly()) { Log.Debug("pesdecoder AdaptionFieldOnly!"); return(false); } return(true); }
private bool SanityCheck(TSHeader header, byte[] tsPacket) { //LogDebug("PesDecoder::OnTsPacket %i", tsPacketCount++); if (tsPacket == null) { Log.Debug("tsPacket null!"); return false; } // Assume that correct pid is passed! /*if (header.Pid != m_pid) { Log.Debug("Header Pid is %i, expected %i", header.Pid, m_pid); return false; }*/ if (header.SyncByte != TS_PACKET_SYNC) { Log.Debug("pesdecoder pid:%x sync error", m_pid); return false; } if (header.TransportError) { m_bStart = false; m_iWritePos = 0; m_iPesLength = 0; Log.Debug("pesdecoder pid:%x transport error", m_pid); return false; } bool scrambled = (header.TScrambling != 0); if (scrambled) { Log.Debug("pesdecoder scrambled!"); return false; } if (header.AdaptionFieldOnly()) { Log.Debug("pesdecoder AdaptionFieldOnly!"); return false; } return true; }
///<summary> /// Converts the binary data into a TsHeader ///</summary> ///<param name="data">Binary data</param> ///<returns>Ts Header struct</returns> public TSHeader GetHeader(byte[] data) { TSHeader header = new TSHeader(); header.SyncByte = data[0]; // indicates header is not valid if (data[0] != 0x47) { return(header); // no ts-header, return } header.SyncByte = data[0]; header.TransportError = (data[1] & 0x80) > 0 ? true : false; header.PayloadUnitStart = (data[1] & 0x40) > 0 ? true : false; header.TransportPriority = (data[1] & 0x20) > 0 ? true : false; header.Pid = ((data[1] & 0x1F) << 8) + data[2]; header.TransportScrambling = data[3] & 0xC0; header.AdaptionFieldControl = (data[3] >> 4) & 0x3; header.ContinuityCounter = data[3] & 0x0F; header.AdaptionField = data[4]; header.TableID = data[5]; header.SectionLen = ((data[6] - 0x70) << 8) + data[7]; return(header); }
public void OnTsPacket(byte[] tsPacket, UInt64 presentTime) { try { assert(tsPacket.Length == 188, "PESDECODER: Input TsPacket not 188 bytes long!"); // Log.Debug("PESDECODER ONTSPACKET"); TSHeader header = new TSHeader(tsPacket); if (!SanityCheck(header, tsPacket)) { return; } int pos = header.PayLoadStart; // where in the pes packet does the payload data start? assert(pos >= 0 && pos <= tsPacket.Length - 8, "PESDECODER: pos " + pos + " would cause an IndexOutOfBounds exception!"); if (header.PayloadUnitStart) // if this header starts a new PES packet { //Log.Debug("PESDECODER: PayLoadUnitStart"); hasPayloadStart = true; if (tsPacket[pos + 0] == 0 && tsPacket[pos + 1] == 0 && tsPacket[pos + 2] == 1) { int streamId = tsPacket[pos + 3]; if (m_iStreamId < 0) { //if stream id not set yet, get it from this m_iStreamId = streamId; if (m_iStreamId < 0) { Log.Warn("Stream id less than zero :" + m_iStreamId); } } else if (streamId != m_iStreamId) { assert(streamId == 0xBE, "PES decoder - wrong stream ID received! - " + streamId); } if (m_iWritePos != 0) { //throw new Exception("Buffer is not empty, but new packet is being received!"); Log.Warn("PESDECODER: Buffer is not empty, but new packet is being received!"); } m_iWritePos = 0; m_iPesHeaderLen = tsPacket[pos + 8] + 9; assert(m_iPesHeaderLen == 45, "PES header not 45 as required for teletext PES packets (actual " + m_iPesHeaderLen + ")"); assert(m_pesHeader.Length >= m_iPesHeaderLen, string.Format("PESDecoder: Reported header length is bigger than header buffer! : {0} vs {1}", m_pesHeader.Length, m_iPesHeaderLen)); assert(tsPacket.Length >= pos + m_iPesHeaderLen, "m_iPesHeaderLen too long! tsPacket length is " + tsPacket.Length + " but m_iPesHeaderLen = " + m_iPesHeaderLen + " and pos = " + pos); Array.Copy(tsPacket, pos, m_pesHeader, 0, m_iPesHeaderLen); //above replaces -> memcpy(m_pesHeader,&tsPacket[pos],m_iPesHeaderLen); pos += (m_iPesHeaderLen); m_bStart = true; int a = m_pesHeader[4]; int b = m_pesHeader[5]; m_iPesLength = (a << 8) + b - (m_iPesHeaderLen - 6); // calculate expected actual payload length } } else if (!hasPayloadStart) { //Log.Debug("PACKET DISCARDED: END OF PACKET FOR WHICH WE DONT HAVE START"); return; } assert(m_iWritePos >= 0, "m_iWritePos < 0"); assert(m_iStreamId > 0, "m_iStreamId <= 0"); assert(pos > 0 && pos < 188, "Pos error : " + pos); assert(m_iWritePos + 188 - pos <= MAX_PES_PACKET, "About to exceed buffer size!"); // check that the buffer is not overrunning int bytesToWrite = 188 - pos; assert(bytesToWrite < 188, "Bytes to write too big : " + bytesToWrite); assert(tsPacket.Length >= pos + bytesToWrite, "tsPacketLength " + tsPacket.Length + " pos " + pos + " bytesToWrite " + bytesToWrite); Array.Copy(tsPacket, pos, m_pesBuffer, m_iWritePos, bytesToWrite); m_iWritePos += bytesToWrite; if (m_iPesLength == m_iWritePos) // we have the expected data { // Log.Debug("PESDECODER: GOT COMPLETE PACKET"); // assert(cb != null, "cb is null!"); if (m_iWritePos > 0 && cb != null) { //Log.Debug("PESDECODER: CALLING CALLBACK"); cb(m_iStreamId, m_pesHeader, m_iPesHeaderLen, m_pesBuffer, m_iWritePos, m_bStart, presentTime); m_bStart = false; m_iWritePos = 0; hasPayloadStart = false; } } } catch { // assert failed, error already logged } }
public void OnTsPacket(byte[] tsPacket, UInt64 presentTime) { try { assert(tsPacket.Length == 188, "PESDECODER: Input TsPacket not 188 bytes long!"); // Log.Debug("PESDECODER ONTSPACKET"); TSHeader header = new TSHeader(tsPacket); if (!SanityCheck(header, tsPacket)) { return; } int pos = header.PayLoadStart; // where in the pes packet does the payload data start? assert(pos >= 0 && pos <= tsPacket.Length - 8, "PESDECODER: pos " + pos + " would cause an IndexOutOfBounds exception!"); if (header.PayloadUnitStart) // if this header starts a new PES packet { //Log.Debug("PESDECODER: PayLoadUnitStart"); hasPayloadStart = true; if (tsPacket[pos + 0] == 0 && tsPacket[pos + 1] == 0 && tsPacket[pos + 2] == 1) { int streamId = tsPacket[pos + 3]; if (m_iStreamId < 0) { //if stream id not set yet, get it from this m_iStreamId = streamId; if (m_iStreamId < 0) { Log.Warn("Stream id less than zero :" + m_iStreamId); } } else if (streamId != m_iStreamId) { assert(streamId == 0xBE, "PES decoder - wrong stream ID received! - " + streamId); } if (m_iWritePos != 0) { //throw new Exception("Buffer is not empty, but new packet is being received!"); Log.Warn("PESDECODER: Buffer is not empty, but new packet is being received!"); } m_iWritePos = 0; m_iPesHeaderLen = tsPacket[pos + 8] + 9; if (m_iPesHeaderLen != 45) { //assert(m_iPesHeaderLen == 45, //"PES header not 45 as required for teletext PES packets (actual " + m_iPesHeaderLen + ")"); return; } assert(m_iPesHeaderLen == 45, "PES header not 45 as required for teletext PES packets (actual " + m_iPesHeaderLen + ")"); assert(m_pesHeader.Length >= m_iPesHeaderLen, string.Format("PESDecoder: Reported header length is bigger than header buffer! : {0} vs {1}", m_pesHeader.Length, m_iPesHeaderLen)); assert(tsPacket.Length >= pos + m_iPesHeaderLen, "m_iPesHeaderLen too long! tsPacket length is " + tsPacket.Length + " but m_iPesHeaderLen = " + m_iPesHeaderLen + " and pos = " + pos); Array.Copy(tsPacket, pos, m_pesHeader, 0, m_iPesHeaderLen); //above replaces -> memcpy(m_pesHeader,&tsPacket[pos],m_iPesHeaderLen); pos += (m_iPesHeaderLen); m_bStart = true; int a = m_pesHeader[4]; int b = m_pesHeader[5]; m_iPesLength = (a << 8) + b - (m_iPesHeaderLen - 6); // calculate expected actual payload length } } else if (!hasPayloadStart) { //Log.Debug("PACKET DISCARDED: END OF PACKET FOR WHICH WE DONT HAVE START"); return; } assert(m_iWritePos >= 0, "m_iWritePos < 0"); assert(m_iStreamId > 0, "m_iStreamId <= 0"); assert(pos > 0 && pos < 188, "Pos error : " + pos); assert(m_iWritePos + 188 - pos <= MAX_PES_PACKET, "About to exceed buffer size!"); // check that the buffer is not overrunning int bytesToWrite = 188 - pos; assert(bytesToWrite < 188, "Bytes to write too big : " + bytesToWrite); assert(tsPacket.Length >= pos + bytesToWrite, "tsPacketLength " + tsPacket.Length + " pos " + pos + " bytesToWrite " + bytesToWrite); Array.Copy(tsPacket, pos, m_pesBuffer, m_iWritePos, bytesToWrite); m_iWritePos += bytesToWrite; if (m_iPesLength == m_iWritePos) // we have the expected data { // Log.Debug("PESDECODER: GOT COMPLETE PACKET"); // assert(cb != null, "cb is null!"); if (m_iWritePos > 0 && cb != null) { //Log.Debug("PESDECODER: CALLING CALLBACK"); cb(m_iStreamId, m_pesHeader, m_iPesHeaderLen, m_pesBuffer, m_iWritePos, m_bStart, presentTime); m_bStart = false; m_iWritePos = 0; hasPayloadStart = false; } } } catch { // assert failed, error already logged } }
///<summary> /// Converts the binary data into a TsHeader ///</summary> ///<param name="data">Binary data</param> ///<returns>Ts Header struct</returns> public TSHeader GetHeader(byte[] data) { TSHeader header = new TSHeader(); header.SyncByte = data[0]; // indicates header is not valid if (data[0] != 0x47) return header; // no ts-header, return header.SyncByte = data[0]; header.TransportError = (data[1] & 0x80) > 0 ? true : false; header.PayloadUnitStart = (data[1] & 0x40) > 0 ? true : false; header.TransportPriority = (data[1] & 0x20) > 0 ? true : false; header.Pid = ((data[1] & 0x1F) << 8) + data[2]; header.TransportScrambling = data[3] & 0xC0; header.AdaptionFieldControl = (data[3] >> 4) & 0x3; header.ContinuityCounter = data[3] & 0x0F; header.AdaptionField = data[4]; header.TableID = data[5]; header.SectionLen = ((data[6] - 0x70) << 8) + data[7]; return header; }