public TSDescriptor Clone() { var descriptor = new TSDescriptor(Name, (byte)Value.Length); Value.CopyTo(descriptor.Value, 0); return(descriptor); }
public TSDescriptor Clone() { TSDescriptor descriptor = new TSDescriptor(Name, (byte)Value.Length); Value.CopyTo(descriptor.Value, 0); return descriptor; }
public void Scan(List<TSPlaylistFile> playlists, bool isFullScan) { if (playlists == null || playlists.Count == 0) { return; } Playlists = playlists; int dataSize = 16384; FileStream fileStream = null; try { string fileName; if (BDInfoSettings.EnableSSIF && InterleavedFile != null) { fileName = InterleavedFile.FileInfo.FullName; } else { fileName = FileInfo.FullName; } fileStream = new FileStream( fileName, FileMode.Open, FileAccess.Read, FileShare.Read, dataSize, false); Size = 0; Length = 0; Streams.Clear(); StreamStates.Clear(); StreamDiagnostics.Clear(); TSPacketParser parser = new TSPacketParser(); long fileLength = (uint)fileStream.Length; byte[] buffer = new byte[dataSize]; int bufferLength = 0; while ((bufferLength = fileStream.Read(buffer, 0, buffer.Length)) > 0) { int offset = 0; for (int i = 0; i < bufferLength; i++) { if (parser.SyncState == false) { if (parser.TimeCodeParse > 0) { parser.TimeCodeParse--; switch (parser.TimeCodeParse) { case 3: parser.TimeCode = 0; parser.TimeCode |= ((uint)buffer[i] & 0x3F) << 24; break; case 2: parser.TimeCode |= ((uint)buffer[i] & 0xFF) << 16; break; case 1: parser.TimeCode |= ((uint)buffer[i] & 0xFF) << 8; break; case 0: parser.TimeCode |= ((uint)buffer[i] & 0xFF); break; } } else if (buffer[i] == 0x47) { parser.SyncState = true; parser.PacketLength = 187; parser.TimeCodeParse = 4; parser.HeaderParse = 3; } } else if (parser.HeaderParse > 0) { parser.PacketLength--; parser.HeaderParse--; switch (parser.HeaderParse) { case 2: { parser.TransportErrorIndicator = (byte)((buffer[i] >> 7) & 0x1); parser.PayloadUnitStartIndicator = (byte)((buffer[i] >> 6) & 0x1); parser.TransportPriority = (byte)((buffer[i] >> 5) & 0x1); parser.PID = (ushort)((buffer[i] & 0x1f) << 8); } break; case 1: { parser.PID |= (ushort)buffer[i]; if (Streams.ContainsKey(parser.PID)) { parser.Stream = Streams[parser.PID]; } else { parser.Stream = null; } if (!StreamStates.ContainsKey(parser.PID)) { StreamStates[parser.PID] = new TSStreamState(); } parser.StreamState = StreamStates[parser.PID]; parser.StreamState.TotalPackets++; parser.StreamState.WindowPackets++; parser.TotalPackets++; } break; case 0: { parser.TransportScramblingControl = (byte)((buffer[i] >> 6) & 0x3); parser.AdaptionFieldControl = (byte)((buffer[i] >> 4) & 0x3); if ((parser.AdaptionFieldControl & 0x2) == 0x2) { parser.AdaptionFieldState = true; } if (parser.PayloadUnitStartIndicator == 1) { if (parser.PID == 0) { parser.PATSectionStart = true; } else if (parser.PID == parser.PMTPID) { parser.PMTSectionStart = true; } else if (parser.StreamState != null && parser.StreamState.TransferState) { parser.StreamState.TransferState = false; parser.StreamState.TransferCount++; bool isFinished = ScanStream( parser.Stream, parser.StreamState, parser.StreamState.StreamBuffer); if (!isFullScan && isFinished) { return; } } } } break; } } else if (parser.AdaptionFieldState) { parser.PacketLength--; parser.AdaptionFieldParse = buffer[i]; parser.AdaptionFieldLength = buffer[i]; parser.AdaptionFieldState = false; } else if (parser.AdaptionFieldParse > 0) { parser.PacketLength--; parser.AdaptionFieldParse--; if ((parser.AdaptionFieldLength - parser.AdaptionFieldParse) == 1) { if ((buffer[i] & 0x10) == 0x10) { parser.PCRParse = 6; parser.PCR = 0; } } else if (parser.PCRParse > 0) { parser.PCRParse--; parser.PCR = (parser.PCR << 8) + (ulong)buffer[i]; if (parser.PCRParse == 0) { parser.PreviousPCR = parser.PCR; parser.PCR = (parser.PCR & 0x1FF) + ((parser.PCR >> 15) * 300); } parser.PCRCount++; } if (parser.PacketLength == 0) { parser.SyncState = false; } } else if (parser.PID == 0) { if (parser.PATTransferState) { if ((bufferLength - i) > parser.PATSectionLength) { offset = parser.PATSectionLength; } else { offset = (bufferLength - i); } if (parser.PacketLength <= offset) { offset = parser.PacketLength; } for (int k = 0; k < offset; k++) { parser.PAT[parser.PATOffset++] = buffer[i++]; parser.PATSectionLength--; parser.PacketLength--; } --i; if (parser.PATSectionLength == 0) { parser.PATTransferState = false; if (parser.PATSectionNumber == parser.PATLastSectionNumber) { for (int k = 0; k < (parser.PATOffset - 4); k += 4) { uint programNumber = (uint) ((parser.PAT[k] << 8) + parser.PAT[k + 1]); ushort programPID = (ushort) (((parser.PAT[k + 2] & 0x1F) << 8) + parser.PAT[k + 3]); if (programNumber == 1) { parser.PMTPID = programPID; } } } } } else { --parser.PacketLength; if (parser.PATSectionStart) { parser.PATPointerField = buffer[i]; if (parser.PATPointerField == 0) { parser.PATSectionLengthParse = 3; } parser.PATSectionStart = false; } else if (parser.PATPointerField > 0) { --parser.PATPointerField; if (parser.PATPointerField == 0) { parser.PATSectionLengthParse = 3; } } else if (parser.PATSectionLengthParse > 0) { --parser.PATSectionLengthParse; switch (parser.PATSectionLengthParse) { case 2: break; case 1: parser.PATSectionLength = (ushort) ((buffer[i] & 0xF) << 8); break; case 0: parser.PATSectionLength |= buffer[i]; if (parser.PATSectionLength > 1021) { parser.PATSectionLength = 0; } else { parser.PATSectionParse = 5; } break; } } else if (parser.PATSectionParse > 0) { --parser.PATSectionLength; --parser.PATSectionParse; switch (parser.PATSectionParse) { case 4: parser.TransportStreamId = (ushort) (buffer[i] << 8); break; case 3: parser.TransportStreamId |= buffer[i]; break; case 2: break; case 1: parser.PATSectionNumber = buffer[i]; if (parser.PATSectionNumber == 0) { parser.PATOffset = 0; } break; case 0: parser.PATLastSectionNumber = buffer[i]; parser.PATTransferState = true; break; } } } if (parser.PacketLength == 0) { parser.SyncState = false; } } else if (parser.PID == parser.PMTPID) { if (parser.PMTTransferState) { if ((bufferLength - i) >= parser.PMTSectionLength) { offset = parser.PMTSectionLength; } else { offset = (bufferLength - i); } if (parser.PacketLength <= offset) { offset = parser.PacketLength; } if (!parser.PMT.ContainsKey(parser.PID)) { parser.PMT[parser.PID] = new byte[1024]; } byte[] PMT = parser.PMT[parser.PID]; for (int k = 0; k < offset; k++) { PMT[parser.PMTOffset++] = buffer[i++]; --parser.PMTSectionLength; --parser.PacketLength; } --i; if (parser.PMTSectionLength == 0) { parser.PMTTransferState = false; if (parser.PMTSectionNumber == parser.PMTLastSectionNumber) { for (int k = 0; k < (parser.PMTOffset - 4); k += 5) { byte streamType = PMT[k]; ushort streamPID = (ushort) (((PMT[k + 1] & 0x1F) << 8) + PMT[k + 2]); ushort streamInfoLength = (ushort) (((PMT[k + 3] & 0xF) << 8) + PMT[k + 4]); if (!Streams.ContainsKey(streamPID)) { List<TSDescriptor> streamDescriptors = new List<TSDescriptor>(); if (streamInfoLength > 0) { for (int d = 0; d < streamInfoLength; d++) { byte name = PMT[k + d + 5]; byte length = PMT[k + d + 6]; TSDescriptor descriptor = new TSDescriptor(name, length); for (int v = 0; v < length; v++) { descriptor.Value[v] = PMT[k + d + v + 7]; } streamDescriptors.Add(descriptor); d += (length + 1); } } CreateStream(streamPID, streamType, streamDescriptors); } k += streamInfoLength; } } } } else { --parser.PacketLength; if (parser.PMTSectionStart) { parser.PMTPointerField = buffer[i]; if (parser.PMTPointerField == 0) { parser.PMTSectionLengthParse = 3; } parser.PMTSectionStart = false; } else if (parser.PMTPointerField > 0) { --parser.PMTPointerField; if (parser.PMTPointerField == 0) { parser.PMTSectionLengthParse = 3; } } else if (parser.PMTSectionLengthParse > 0) { --parser.PMTSectionLengthParse; switch (parser.PMTSectionLengthParse) { case 2: if (buffer[i] != 0x2) { parser.PMTSectionLengthParse = 0; } break; case 1: parser.PMTSectionLength = (ushort) ((buffer[i] & 0xF) << 8); break; case 0: parser.PMTSectionLength |= buffer[i]; if (parser.PMTSectionLength > 1021) { parser.PMTSectionLength = 0; } else { parser.PMTSectionParse = 9; } break; } } else if (parser.PMTSectionParse > 0) { --parser.PMTSectionLength; --parser.PMTSectionParse; switch (parser.PMTSectionParse) { case 8: case 7: case 6: break; case 5: parser.PMTSectionNumber = buffer[i]; if (parser.PMTSectionNumber == 0) { parser.PMTOffset = 0; } break; case 4: parser.PMTLastSectionNumber = buffer[i]; break; case 3: parser.PCRPID = (ushort) ((buffer[i] & 0x1F) << 8); break; case 2: parser.PCRPID |= buffer[i]; break; case 1: parser.PMTProgramInfoLength = (ushort) ((buffer[i] & 0xF) << 8); break; case 0: parser.PMTProgramInfoLength |= buffer[i]; if (parser.PMTProgramInfoLength == 0) { parser.PMTTransferState = true; } else { parser.PMTProgramDescriptorLengthParse = 2; } break; } } else if (parser.PMTProgramInfoLength > 0) { --parser.PMTSectionLength; --parser.PMTProgramInfoLength; if (parser.PMTProgramDescriptorLengthParse > 0) { --parser.PMTProgramDescriptorLengthParse; switch (parser.PMTProgramDescriptorLengthParse) { case 1: parser.PMTProgramDescriptor = buffer[i]; break; case 0: parser.PMTProgramDescriptorLength = buffer[i]; parser.PMTProgramDescriptors.Add( new TSDescriptor( parser.PMTProgramDescriptor, parser.PMTProgramDescriptorLength)); break; } } else if (parser.PMTProgramDescriptorLength > 0) { --parser.PMTProgramDescriptorLength; TSDescriptor descriptor = parser.PMTProgramDescriptors[ parser.PMTProgramDescriptors.Count - 1]; int valueIndex = descriptor.Value.Length - parser.PMTProgramDescriptorLength - 1; descriptor.Value[valueIndex] = buffer[i]; if (parser.PMTProgramDescriptorLength == 0 && parser.PMTProgramInfoLength > 0) { parser.PMTProgramDescriptorLengthParse = 2; } } if (parser.PMTProgramInfoLength == 0) { parser.PMTTransferState = true; } } } if (parser.PacketLength == 0) { parser.SyncState = false; } } else if (parser.Stream != null && parser.StreamState != null && parser.TransportScramblingControl == 0) { TSStream stream = parser.Stream; TSStreamState streamState = parser.StreamState; streamState.Parse = (streamState.Parse << 8) + buffer[i]; if (streamState.TransferState) { if ((bufferLength - i) >= streamState.PacketLength && streamState.PacketLength > 0) { offset = streamState.PacketLength; } else { offset = (bufferLength - i); } if (parser.PacketLength <= offset) { offset = parser.PacketLength; } streamState.TransferLength = offset; if (!stream.IsInitialized || stream.IsVideoStream) { streamState.StreamBuffer.Add( buffer, i, offset); } else { streamState.StreamBuffer.TransferLength += offset; } i += (int)(streamState.TransferLength - 1); streamState.PacketLength -= streamState.TransferLength; parser.PacketLength -= (byte)streamState.TransferLength; streamState.TotalBytes += (ulong)streamState.TransferLength; streamState.WindowBytes += (ulong)streamState.TransferLength; if (streamState.PacketLength == 0) { streamState.TransferState = false; streamState.TransferCount++; bool isFinished = ScanStream( stream, streamState, streamState.StreamBuffer); if (!isFullScan && isFinished) { return; } } } else { --parser.PacketLength; bool headerFound = false; if (stream.IsVideoStream && streamState.Parse == 0x000001FD) { headerFound = true; } if (stream.IsVideoStream && streamState.Parse >= 0x000001E0 && streamState.Parse <= 0x000001EF) { headerFound = true; } if (stream.IsAudioStream && streamState.Parse == 0x000001BD) { headerFound = true; } if (stream.IsAudioStream && (streamState.Parse == 0x000001FA || streamState.Parse == 0x000001FD)) { headerFound = true; } if (!stream.IsVideoStream && !stream.IsAudioStream && (streamState.Parse == 0x000001FA || streamState.Parse == 0x000001FD || streamState.Parse == 0x000001BD || (streamState.Parse >= 0x000001E0 && streamState.Parse <= 0x000001EF))) { headerFound = true; } if (headerFound) { streamState.PacketLengthParse = 2; #if DEBUG streamState.PESHeaderIndex = 0; streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)((streamState.Parse >> 24) & 0xFF); streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)((streamState.Parse >> 16) & 0xFF); streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)((streamState.Parse >> 8) & 0xFF); streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif } else if (streamState.PacketLengthParse > 0) { --streamState.PacketLengthParse; switch (streamState.PacketLengthParse) { case 1: #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 0: streamState.PacketLength = (int)(streamState.Parse & 0xFFFF); streamState.PacketParse = 3; #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; } } else if (streamState.PacketParse > 0) { --streamState.PacketLength; --streamState.PacketParse; switch (streamState.PacketParse) { case 2: #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 1: streamState.PESHeaderFlags = (byte)(streamState.Parse & 0xFF); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 0: streamState.PESHeaderLength = (byte)(streamState.Parse & 0xFF); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif if ((streamState.PESHeaderFlags & 0xC0) == 0x80) { streamState.PTSParse = 5; } else if ((streamState.PESHeaderFlags & 0xC0) == 0xC0) { streamState.DTSParse = 10; } if (streamState.PESHeaderLength == 0) { streamState.TransferState = true; } break; } } else if (streamState.PTSParse > 0) { --streamState.PacketLength; --streamState.PESHeaderLength; --streamState.PTSParse; switch (streamState.PTSParse) { case 4: streamState.PTSTemp = ((streamState.Parse & 0xE) << 29); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xff); #endif break; case 3: streamState.PTSTemp |= ((streamState.Parse & 0xFF) << 22); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 2: streamState.PTSTemp |= ((streamState.Parse & 0xFE) << 14); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 1: streamState.PTSTemp |= ((streamState.Parse & 0xFF) << 7); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 0: streamState.PTSTemp |= ((streamState.Parse & 0xFE) >> 1); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xff); #endif streamState.PTS = streamState.PTSTemp; if (streamState.PTS > streamState.PTSLast) { if (streamState.PTSLast > 0) { streamState.PTSTransfer = (streamState.PTS - streamState.PTSLast); } streamState.PTSLast = streamState.PTS; } streamState.PTSDiff = streamState.PTS - streamState.DTSPrev; if (streamState.PTSCount > 0 && stream.IsVideoStream) { UpdateStreamBitrates(stream.PID, streamState.PTS, streamState.PTSDiff); if (streamState.DTSTemp < parser.PTSFirst) { parser.PTSFirst = streamState.DTSTemp; } if (streamState.DTSTemp > parser.PTSLast) { parser.PTSLast = streamState.DTSTemp; } Length = (double)(parser.PTSLast - parser.PTSFirst) / 90000; } streamState.DTSPrev = streamState.PTS; streamState.PTSCount++; if (streamState.PESHeaderLength == 0) { streamState.TransferState = true; } break; } } else if (streamState.DTSParse > 0) { --streamState.PacketLength; --streamState.PESHeaderLength; --streamState.DTSParse; switch (streamState.DTSParse) { case 9: streamState.PTSTemp = ((streamState.Parse & 0xE) << 29); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 8: streamState.PTSTemp |= ((streamState.Parse & 0xFF) << 22); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 7: streamState.PTSTemp |= ((streamState.Parse & 0xFE) << 14); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xff); #endif break; case 6: streamState.PTSTemp |= ((streamState.Parse & 0xFF) << 7); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 5: streamState.PTSTemp |= ((streamState.Parse & 0xFE) >> 1); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xff); #endif streamState.PTS = streamState.PTSTemp; if (streamState.PTS > streamState.PTSLast) { streamState.PTSLast = streamState.PTS; } break; case 4: streamState.DTSTemp = ((streamState.Parse & 0xE) << 29); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xff); #endif break; case 3: streamState.DTSTemp |= ((streamState.Parse & 0xFF) << 22); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xff); #endif break; case 2: streamState.DTSTemp |= ((streamState.Parse & 0xFE) << 14); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xff); #endif break; case 1: streamState.DTSTemp |= ((streamState.Parse & 0xFF) << 7); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif break; case 0: streamState.DTSTemp |= ((streamState.Parse & 0xFE) >> 1); #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xff); #endif streamState.PTSDiff = streamState.DTSTemp - streamState.DTSPrev; if (streamState.PTSCount > 0 && stream.IsVideoStream) { UpdateStreamBitrates(stream.PID, streamState.DTSTemp, streamState.PTSDiff); if (streamState.DTSTemp < parser.PTSFirst) { parser.PTSFirst = streamState.DTSTemp; } if (streamState.DTSTemp > parser.PTSLast) { parser.PTSLast = streamState.DTSTemp; } Length = (double)(parser.PTSLast - parser.PTSFirst) / 90000; } streamState.DTSPrev = streamState.DTSTemp; streamState.PTSCount++; if (streamState.PESHeaderLength == 0) { streamState.TransferState = true; } break; } } else if (streamState.PESHeaderLength > 0) { --streamState.PacketLength; --streamState.PESHeaderLength; #if DEBUG streamState.PESHeader[streamState.PESHeaderIndex++] = (byte)(streamState.Parse & 0xFF); #endif if (streamState.PESHeaderLength == 0) { streamState.TransferState = true; } } } if (parser.PacketLength == 0) { parser.SyncState = false; } } else { parser.PacketLength--; if ((bufferLength - i) >= parser.PacketLength) { i = i + parser.PacketLength; parser.PacketLength = 0; } else { parser.PacketLength -= (byte)((bufferLength - i) + 1); i = bufferLength; } if (parser.PacketLength == 0) { parser.SyncState = false; } } } Size += bufferLength; } ulong PTSLast = 0; ulong PTSDiff = 0; foreach (TSStream stream in Streams.Values) { if (!stream.IsVideoStream) continue; if (StreamStates.ContainsKey(stream.PID) && StreamStates[stream.PID].PTSLast > PTSLast) { PTSLast = StreamStates[stream.PID].PTSLast; PTSDiff = PTSLast - StreamStates[stream.PID].DTSPrev; } UpdateStreamBitrates(stream.PID, PTSLast, PTSDiff); } } finally { if (fileStream != null) { fileStream.Close(); } } }