public void DoWork(object data) { Result result = new Result(); byte[] tsPacketBuffer = new byte[TS_PACKET_BUFFER_SIZE]; int lengthOfDataReadIn = 0; //Length of data read in from file. Int64 lengthOfDataToParse = 0; //Length of data to be parsed. Int64 validPacketOffset = 0; //Offset of packet in the buffer. TsPacketSize tsPacketSize = TsPacketSize.SIZE_UNKNOWN; Int64 packetNumber = 0; //Number of packet. //Give the child class to do something. OnStart(); GetContext().WriteLog("Start to parse stream file: " + fileStream.Name + ".\n"); //To check current datetime.//TIME_LIMIT DateTime currentTime = DateTime.Now; if (result.Fine) { //Read in some TS packets to detect the TS packet size. lengthOfDataToParse = fileStream.Read(tsPacketBuffer, 0, tsPacketBuffer.Length); //We will detect whether it is a valid transport stream first. result = StreamDemux.DetectPacketSize(tsPacketBuffer, lengthOfDataToParse, ref validPacketOffset, ref tsPacketSize);//validPacketOffset and tsPacketSize will be changed by this function. if (result.Fine) { GetContext().WriteLog("Packet size: " + tsPacketSize + ".\n"); GetContext().WriteLog("Offset of first packet: " + validPacketOffset + ".\n"); GetContext().WriteLog("Stream size: " + fileStream.Length + " bytes.\n"); messageCallback(MessageId.MESSAGE_TS_PACKET_SIZE, (int)tsPacketSize); } else { GetContext().WriteLog("Invalid transport stream.\n"); result.SetResult(ResultCode.FAILURE); } //Skip invalid data bytes. lengthOfDataToParse -= validPacketOffset; } Int64 currentProgress = 0; Int64 savedProgress = 0; Int64 fileSize = fileStream.Length; if (result.Fine) { totalLengthOfDataParsed += validPacketOffset; totalLengthOfDataSkipped += validPacketOffset; /*TIME_LIMIT * if ((currentTime.Year * 12 + currentTime.Month) >= 2015 * 12 + 6) * { * canRun = false; * } * * if ((currentTime.Year * 12 + currentTime.Month) < 2014 * 12 + 5) * { * canRun = false; * } */ //It is a valid transport stream. while (canRun) { currentProgress = totalLengthOfDataParsed * 100 / fileSize; if (currentProgress > savedProgress) { //Progress has been updated. savedProgress = currentProgress; //Update the progress shown in the form by sending a message. OnProgress(savedProgress); } //If left data in the buffer is shorter than the size of a TS packet, we will need to read more data before processing it. if (lengthOfDataToParse < (Int64)tsPacketSize) { //The left data will be moved to the beginning of the buffer. //In case there is any data left, we will copy it to the beginning of the buffer. if (0 != lengthOfDataToParse) { Array.Copy(tsPacketBuffer, tsPacketBuffer.Length - lengthOfDataToParse, tsPacketBuffer, 0, lengthOfDataToParse); } //Console.WriteLine("-----lengthOfDataToParse:" + lengthOfDataToParse + " totalLengthOfDataParsed " + totalLengthOfDataParsed + " ts byte :" + tsPacketBuffer[0]); //Read the data from the file into the buffer. lengthOfDataReadIn = fileStream.Read(tsPacketBuffer, (int)lengthOfDataToParse, (int)(tsPacketBuffer.Length - lengthOfDataToParse)); //To parse all the data in the buffer. lengthOfDataToParse += lengthOfDataReadIn; //Console.WriteLine("===================lengthOfDataToParse:" + lengthOfDataToParse + " totalLengthOfDataParsed " + totalLengthOfDataParsed + " ts byte :" + tsPacketBuffer[0]); //If there is still no valid TS packet after a read operation, we have reached the end of the file. if (lengthOfDataToParse < (Int64)tsPacketSize) { GetContext().WriteLog("Parsing has been successfully done! There are " + lengthOfDataToParse + " bytes left.\n"); break; } //Reset the offset. validPacketOffset = 0; } //Get a TS packet from the block. if (StreamDemux.SYNC_BYTE == tsPacketBuffer[validPacketOffset]) { TsPacketMetadata transportPacket = new TsPacketMetadata(); //It is a valid TS packet. Process this TS packet. transportPacket.PacketSource = TsPacketSource.SOURCE_FILE; transportPacket.FileOffset = totalLengthOfDataParsed; transportPacket.PacketNumber = packetNumber; //Increase the packet number since we have got one valid TS packet. transportPacket.PacketSize = tsPacketSize; //Invoke the function in the child class to process the TS packet. ProcessTsPacket(transportPacket, tsPacketBuffer, validPacketOffset); //Increase the packet number since we have got one valid TS packet. packetNumber++; //Increase the length of data parsed. totalLengthOfDataParsed += (Int64)tsPacketSize; validPacketOffset += (Int64)tsPacketSize; lengthOfDataToParse -= (Int64)tsPacketSize; } else { //The stream is out of the syncrhonization. We will need to re-locate the position in order to find a valid TS packet. GetContext().WriteLog("Out of synchronization at " + totalLengthOfDataParsed + " bytes of the stream file.\n"); String str = String.Format("{0,2:X2} {1,2:X2} {2,2:X2} {3,2:X2} {4,2:X2} {5,2:X2} ", tsPacketBuffer[validPacketOffset], tsPacketBuffer[validPacketOffset + 1], tsPacketBuffer[validPacketOffset + 2], tsPacketBuffer[validPacketOffset + 3], tsPacketBuffer[validPacketOffset + 4], tsPacketBuffer[validPacketOffset + 5]); Console.WriteLine("Out of synchronization at " + totalLengthOfDataParsed + " bytes of the stream file.\n"); Console.WriteLine(str); Int64 validPacketOffsetTemp = validPacketOffset; result = StreamDemux.DetectPacketSize(tsPacketBuffer, lengthOfDataToParse, ref validPacketOffset, ref tsPacketSize);//validPacketOffset and tsPacketSize will be changed by this function. if (result.Fine) { //We can continue since we have successfully located a valid TS packet, but we need to know how many bytes we have skipped while relocating. totalLengthOfDataParsed += (validPacketOffset - validPacketOffsetTemp); lengthOfDataToParse -= (validPacketOffset - validPacketOffsetTemp); totalLengthOfDataSkipped += (validPacketOffset - validPacketOffsetTemp); GetContext().WriteLog("Skip " + (validPacketOffset - validPacketOffsetTemp) + " bytes.\n"); continue; } else { GetContext().WriteLog("Failed to re-locate the valid TS packet. " + (fileStream.Length - totalLengthOfDataParsed) + " bytes are left.\n"); break; } } } //Give a summary at the end. GetContext().WriteLog("Processed packets: " + packetNumber + Environment.NewLine); GetContext().WriteLog("There are totally " + totalLengthOfDataSkipped + " bytes skipped. " + 100 * (float)totalLengthOfDataSkipped / fileStream.Length + "% is invalid.\n"); //Update to 100% no matter how. if (100 != savedProgress) { OnProgress((Int64)100); } } //Close the stream immediately. fileStream.Close(); fileStream = null; parserThread = null; //Give the child class to do something. OnStop(); }
public static Result DetectPacketSize(byte[] tsPacketBuffer, Int64 totalDataLength, ref Int64 validPacketOffset, ref TsPacketSize tsPacketSize) { Result result = new Result(); tsPacketSize = TsPacketSize.SIZE_UNKNOWN; Int64 validPacketOffsetTemp = validPacketOffset; if (totalDataLength < (Int64)TsPacketSize.SIZE_188) { result.SetFailure(); } if (result.Fine) { if ((SYNC_BYTE == tsPacketBuffer[validPacketOffsetTemp]) && (totalDataLength == (Int64)TsPacketSize.SIZE_204)) { tsPacketSize = TsPacketSize.SIZE_204; } else if ((SYNC_BYTE == tsPacketBuffer[validPacketOffsetTemp]) && (totalDataLength == (Int64)TsPacketSize.SIZE_188)) { tsPacketSize = TsPacketSize.SIZE_188; } else { //Else, we may need to locate several packets to detect the size. if ((validPacketOffsetTemp + (Int64)TsPacketSize.SIZE_188 * 2) <= tsPacketBuffer.Length) { //Find the first sync_byte. for (Int64 i = validPacketOffsetTemp; i < (validPacketOffsetTemp + (Int64)TsPacketSize.SIZE_188); ++i) { if ((SYNC_BYTE == tsPacketBuffer[i]) && (SYNC_BYTE == tsPacketBuffer[i + (Int64)TsPacketSize.SIZE_188])) { tsPacketSize = TsPacketSize.SIZE_188; validPacketOffset = i; break; } } } if (tsPacketSize == TsPacketSize.SIZE_UNKNOWN) { if ((validPacketOffsetTemp + (Int64)TsPacketSize.SIZE_204 * 2) <= tsPacketBuffer.Length) { //Find the first sync_byte. for (Int64 i = validPacketOffsetTemp; i < (validPacketOffsetTemp + (Int64)TsPacketSize.SIZE_204); ++i) { if ((SYNC_BYTE == tsPacketBuffer[i]) && (SYNC_BYTE == tsPacketBuffer[i + (Int64)TsPacketSize.SIZE_204])) { tsPacketSize = TsPacketSize.SIZE_204; validPacketOffset = i; break; } } } } } } if (TsPacketSize.SIZE_UNKNOWN == tsPacketSize) { result.SetResult(ResultCode.INVALID_STREAM); } return(result); }