Example #1
0
        /**
         *
         */
        public void AddTsPacket(TsPacketMetadata tsPacket, byte[] packetBuffer, Int64 packetOffsetInBuffer)
        {
            List <TsPacketMetadata> singlePacketMetadataList = new List <TsPacketMetadata>();

            singlePacketMetadataList.Add(tsPacket);

            channelDataCallback(pid, packetBuffer, packetOffsetInBuffer, (Int64)tsPacket.PacketSize, singlePacketMetadataList);
        }//AddTsPacket
Example #2
0
 public override void ProcessTsPacket(TsPacketMetadata tsPacketMetadata, byte[] packetBuffer, Int64 packetOffsetInBuffer)
 {
     //In search mode, we may need to skip several TS packets according to the request.
     if (tsPacketMetadata.PacketNumber >= searchRequest.CountOfSkipTsPacket)
     {
         //Invoke the stream parser to process a TS packet.
         streamDemux.ProcessTsPacket(tsPacketMetadata, packetBuffer, packetOffsetInBuffer);
     }
 }
Example #3
0
        }//AddTsPacket

        /**
         * Add the data into the channel buffer.
         *
         * @param tsPacketMetadata packet information.
         * @param newData byte array containing the data to be added into the channel buffer.
         * @param leftDataLengthInBit how many bits left in the byte array.\n
         *        On input, it indicates how many bits left in the byte array.\n
         *        On output, it indicates how many bits left in the byte array after reading out requested data from the byte array.
         * @param newDataOffsetInBit offset of the position to read in the data from the byte array.\n
         *        On input, it indicates the offset to read in data.\n
         *        On output, it indicates the offset after reading out requested data from the byte array.
         * @param newDataLengthInBit how many bits to be read out from the byte array.
         *
         * @retval result
         */
        public void AddPesData(TsPacketMetadata tsPacketMetadata, Int64 startIndicator, byte[] newData, Int64 newDataOffsetInBit, Int64 newDataLengthInBit)
        {
            Result result = new Result();

            //Convert bits to bytes.
            Int64 newDataLengthInByte = newDataLengthInBit / 8;
            Int64 newDataOffsetInByte = newDataOffsetInBit / 8;

            if (null == dataBuffer)
            {
                bufferSize = 8 * 1024;
                dataBuffer = new byte[bufferSize];//Allocate 8 K bytes as the intial buffer.
            }

            if (1 == startIndicator)
            {
                //Start indicator is set to 1. We will notify all existing data as a PES packet.
                if (currentDataLength != 0)
                {
                    channelDataCallback(pid, dataBuffer, 0, currentDataLength, packetMetadataList);

                    //Clean up everything so that we are ready to accept new packet.
                    Reset();
                }
            }//if (1 == startIndicator)

            //Save the packetMetadata.
            packetMetadataList.Add(tsPacketMetadata);

            if (result.Fine)
            {
                //If no enough space to save the data.
                if ((currentDataLength + newDataLengthInByte) > bufferSize)
                {
                    //No enough buffer. Allocate a larger buffer to save the content. Increase 8K each time.
                    Int64 newBufferSize = bufferSize + 8 * 1024;

                    byte[] newBuffer = new byte[newBufferSize];

                    Array.Copy(dataBuffer, newBuffer, currentDataLength);//Copy from the old one into the new one.

                    dataBuffer = newBuffer;
                    bufferSize = newBufferSize;
                }//if ((currentDataLength + newDataLengthInByte) > bufferSize)

                //Now, we must have enough buffer to hold the incoming data.
                Array.Copy(newData, newDataOffsetInByte, dataBuffer, currentDataLength, newDataLengthInByte);//Note that the forth parameter is indeed the offset!

                //Increase the lenght of current data after appending the new data.
                currentDataLength += newDataLengthInByte;
            }
        }//AddPesData
Example #4
0
        public void NewTsPacket(TsPacketMetadata tsPacketMetadata, UInt16 pid)
        {
            PidBitrate pidBitrate = null;

            if (!pidBitrateList.TryGetValue(pid, out pidBitrate))
            {
                //Create a new one.
                pidBitrate = new PidBitrate(pid);
                pidBitrateList.Add(pid, pidBitrate);
            }

            //Increase the exsiting size.
            pidBitrate.AddTsPacket(tsPacketMetadata);
        }
Example #5
0
        public void ParseAdaptationField(TsPacketMetadata tsPacketMetadata, UInt16 pid, byte[] packetBuffer, Result result, Int64 dataLeftInBit, Int64 bitOffset, Int64 adaptationFieldControl)
        {
            Int64 pcr = 0;
            Int64 discontinuityIndicator = 0;

            MuxBitrate streamBitrate = null;

            bool pcrFound = GetPCR(tsPacketMetadata, packetBuffer, dataLeftInBit, bitOffset, adaptationFieldControl, ref pcr, ref discontinuityIndicator);

            if (pcrFound)
            {
                if (!streamBitrateList.TryGetValue(pid, out streamBitrate))
                {
                    streamBitrate = new MuxBitrate(pid);
                    streamBitrateList.Add(pid, streamBitrate);
                }

                if (!streamBitrate.BitrateAvailable)
                {
                    if (1 == discontinuityIndicator)
                    {
                        //Discontinuity is detected, the new PCR will be used as the first PCR.
                        streamBitrate.SaveFirstPcr(pcr, tsPacketMetadata.FileOffset);
                    }//if (1 == discontinuityIndicator)
                    else
                    {
                        if (streamBitrate.FirsPcrReady())
                        {
                            //Save second PCR if the first one is available.
                            streamBitrate.SaveSecondPcr(pcr, tsPacketMetadata.FileOffset);
                        }
                        else
                        {
                            //Save as the first one.
                            streamBitrate.SaveFirstPcr(pcr, tsPacketMetadata.FileOffset);
                        }
                    } //else
                }     //if (!streamBitrate.BitrateAvailable)
            }         //if (pcrFound)
        }
Example #6
0
        public override void ProcessTsPacket(TsPacketMetadata tsPacketMetadata, byte[] packetBuffer, Int64 packetOffsetInBuffer)
        {
            Result result = new Result();
            //Int64 dataLeftInBit = (Int64)tsPacketMetadata.PacketSize;
            Int64 dataLeftInBit = (Int64)TsPacketSize.SIZE_188 * 8; //Important!!!!No matter 188 or 204 bytes, the valid data will always be 188 bytes.16 bytes are checksum that is not useful for parsing.

            Int64 bitOffset = packetOffsetInBuffer * 8;             //Key point to set the beginning offset!!!!!


            if (result.Fine)
            {
                //8-bit sync_byte.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 8);
            }

            if (result.Fine)
            {
                //1-bit transport_error_indicator.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 payloadUnitStartIndicator = 0;

            if (result.Fine)
            {
                //1-bit payload_unit_start_indicator.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 1, ref payloadUnitStartIndicator);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 1) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //1-bit transport_priority.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 pid = 0;

            if (result.Fine)
            {
                //13-bit PID.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 13, ref pid);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 13) + Environment.NewLine);
            }

            //To update the PID according to the request.
            if (result.Fine)
            {
                PidUpdate pidUpdate = null;

                //If this pid needs update.
                if (pidUpdateList.TryGetValue((UInt16)pid, out pidUpdate))
                {
                    //To update the PID.
                    packetBuffer[packetOffsetInBuffer + 1] = (byte)((packetBuffer[packetOffsetInBuffer + 1] & (byte)0xE0) | (pidUpdate.NewPid >> 8)); //To update the high 5 bits of PID.
                    packetBuffer[packetOffsetInBuffer + 2] = (byte)(pidUpdate.NewPid & 0xFF);                                                         //To update the low 8 bits of PID.

                    //Write to output file now.
                    outputFileStream.Write(packetBuffer, (int)packetOffsetInBuffer, (int)tsPacketMetadata.PacketSize);
                }
                else
                {
                    //Write the original packet directly.
                    outputFileStream.Write(packetBuffer, (int)packetOffsetInBuffer, (int)tsPacketMetadata.PacketSize);
                }
            }
        }
Example #7
0
        public override void ProcessTsPacket(TsPacketMetadata tsPacketMetadata, byte[] packetBuffer, Int64 packetOffsetInBuffer)
        {
            Result result = new Result();
            //Int64 dataLeftInBit = (Int64)tsPacketMetadata.PacketSize;
            Int64 dataLeftInBit = (Int64)TsPacketSize.SIZE_188 * 8; //Important!!!!No matter 188 or 204 bytes, the valid data will always be 188 bytes.16 bytes are checksum that is not useful for parsing.

            Int64 bitOffset = packetOffsetInBuffer * 8;             //Key point to set the beginning offset!!!!!


            if (result.Fine)
            {
                //8-bit sync_byte.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 8);
            }

            if (result.Fine)
            {
                //1-bit transport_error_indicator.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 payloadUnitStartIndicator = 0;

            if (result.Fine)
            {
                //1-bit payload_unit_start_indicator.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 1, ref payloadUnitStartIndicator);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 1) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //1-bit transport_priority.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 pid = 0;

            if (result.Fine)
            {
                //13-bit PID.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 13, ref pid);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 13) + Environment.NewLine);
            }

            //Notify to ManagerPidBitrate to calculate realtime bitrate.
            if (result.Fine)
            {
                managerPidBitrate.NewTsPacket(tsPacketMetadata, (UInt16)pid);
            }

            if ((totalLengthOfDataParsed - previousTotalLengthOfDataParsed) * 8 >= (streamBitrate))
            {
                //Time to fetch current bitstream.
                SortedDictionary <UInt16, PidBitrate> currentBitrate = managerPidBitrate.FetchCurrentBitrates();
                KeyValuePair <DateTime, SortedDictionary <UInt16, PidBitrate> > bitrateForNow =
                    new KeyValuePair <DateTime, SortedDictionary <ushort, PidBitrate> >(DateTime.Now, currentBitrate);
                //Send it to the form now.
                messageCallback(MessageId.MESSAGE_PID_BITRATE_DATA, bitrateForNow);

                //Save the new value as the previous one.
                previousTotalLengthOfDataParsed = totalLengthOfDataParsed;
            }
        }
Example #8
0
        public override void ProcessTsPacket(TsPacketMetadata tsPacketMetadata, byte[] packetBuffer, Int64 packetOffsetInBuffer)
        {
            Result result = new Result();
            //Int64 dataLeftInBit = (Int64)tsPacketMetadata.PacketSize;
            Int64 dataLeftInBit = (Int64)TsPacketSize.SIZE_188 * 8; //Important!!!!No matter 188 or 204 bytes, the valid data will always be 188 bytes.16 bytes are checksum that is not useful for parsing.

            Int64 bitOffset = packetOffsetInBuffer * 8;             //Key point to set the beginning offset!!!!!


            if (result.Fine)
            {
                //8-bit sync_byte.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 8);
            }

            if (result.Fine)
            {
                //1-bit transport_error_indicator.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 payloadUnitStartIndicator = 0;

            if (result.Fine)
            {
                //1-bit payload_unit_start_indicator.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 1, ref payloadUnitStartIndicator);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 1) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //1-bit transport_priority.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 pid = 0;

            if (result.Fine)
            {
                //13-bit PID.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 13, ref pid);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 13) + Environment.NewLine);
            }


            Int64 scrambled = 0;

            if (result.Fine)
            {
                //1-bit scrambling indicator. If 1, scrambled, else clear.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 1, ref scrambled);
            }

            Int64 evenOdd = 0;

            if (result.Fine)
            {
                //1-bit even/odd indicator.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 1, ref evenOdd);
            }

            if ((totalLengthOfDataParsed - previousTotalLengthOfDataParsed) * 8 >= (muxBitrate * cwPeriod))//Need to do a CW cycle.
            {
                //To switch the CW.
                //Get the control word.
                int realControlWordId = currentControlWord;

                currentControlWord++;                                     //Increase so that we can pick up next control word.

                realControlWordId = realControlWordId % controlWordCount; //We like to loop back if necessary.

                byte[] csaKey = new byte[8];
                Array.Copy(controlWordSerials, realControlWordId * 8, csaKey, 0, 8);//Copy the key into a new buffer.

                //Set the CW.
                csaDescrambler.SetCW(csaKey, doEntropy);

                //Switch even/odd flag.
                evenOddFlag = (evenOddFlag + 1) % 2;

                //Save the new value as the previous one.
                previousTotalLengthOfDataParsed = totalLengthOfDataParsed;
            }

            //To process the PID according to the request.
            if (result.Fine)
            {
                PidUpdate pidToProcess = null;

                //If this pid needs to be extracted.
                if (pidUpdateList.TryGetValue((UInt16)pid, out pidToProcess))
                {
                    //Scramble the packet in place.
                    csaDescrambler.EncryptTSPacket(packetBuffer, (int)packetOffsetInBuffer, (int)TsPacketSize.SIZE_188, evenOddFlag);
                }

                //Write the output no matter clear or descrambled.
                outputFileStream.Write(packetBuffer, (int)packetOffsetInBuffer, (int)tsPacketMetadata.PacketSize);
            }
        }
Example #9
0
        public Result ProcessTsPacket(TsPacketMetadata tsPacketMetadata, byte[] packetBuffer, Int64 packetOffsetInBuffer)
        {
            Result result = new Result();
            //Int64 dataLeftInBit = (Int64)tsPacketMetadata.PacketSize;
            Int64 dataLeftInBit = (Int64)TsPacketSize.SIZE_188 * 8; //Important!!!!No matter 188 or 204 bytes, the valid data will always be 188 bytes.16 bytes are checksum that is not useful for parsing.

            Int64 bitOffset = packetOffsetInBuffer * 8;             //Key point to set the beginning offset!!!!!

            //Important!!! Pass a copy of the TS packe to the demux module, so that it can assemble ts packet into section or PES packet.
            streamDemux.ProcessTsPacket(tsPacketMetadata, packetBuffer, packetOffsetInBuffer);


            if (result.Fine)
            {
                //8-bit sync_byte.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 8);
            }

            if (result.Fine)
            {
                //1-bit transport_error_indicator.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 payloadUnitStartIndicator = 0;

            if (result.Fine)
            {
                //1-bit payload_unit_start_indicator.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 1, ref payloadUnitStartIndicator);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 1) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //1-bit transport_priority.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 pid = 0;

            if (result.Fine)
            {
                //13-bit PID.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 13, ref pid);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 13) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //2-bit transport_scrambling_control.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 2);
            }

            Int64 adaptationFieldControl = 0;

            if (result.Fine)
            {
                //2-bit adaptation_field_control.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 2, ref adaptationFieldControl);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 2) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //4-bit continuity_counter.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 4);
            }

            //To parse adaption fields.
            Int64 adaptationFieldLength = 0;

            if (result.Fine)
            {
                //If adaptationFieldControl is 0b10(Adaptation_field only, no payload) or 0b11(Adaptation_field followed by payload),there is a adaption_field. We need to skip the adaption fields.
                if ((0x2 == adaptationFieldControl) || (0x3 == adaptationFieldControl))
                {
                    //8-bit adaptation_field_length
                    result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 8, ref adaptationFieldLength);

                    if (result.Fine)
                    {
                        /*Parse adaptation field to get PCR etc.*/
                        streamBitrateManager.ParseAdaptationField(tsPacketMetadata, (UInt16)pid, packetBuffer, result, dataLeftInBit, bitOffset, adaptationFieldControl);
                    }

                    //Skip adaption fields according to the adaption_field_length.
                    if (result.Fine)
                    {
                        result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, (adaptationFieldLength * 8));
                    }
                }
            }

            if (result.Fine)
            {
                //Notify a new packet to PidManager so that it can do the statistics.
                pidManager.AddPacket((UInt16)pid);
            }

            return(result);
        }
Example #10
0
        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();
        }
Example #11
0
 //To be overrided by  by base class.
 public virtual void ProcessTsPacket(TsPacketMetadata tsPacketMetadata, byte[] packetBuffer, Int64 packetOffsetInBuffer)
 {
 }
Example #12
0
        private bool GetPCR(TsPacketMetadata tsPacketMetadata, byte[] data, Int64 dataLeftInBit, Int64 bitOffset, Int64 adaptationFieldLength, ref Int64 pcr, ref Int64 discontinuityIndicator)
        {
            bool   pcrValid   = false;
            Int64  fieldValue = 0;
            Result result     = new Result();

            adaptationFieldLength = adaptationFieldLength * 8;//Convert to bits.

            if (adaptationFieldLength <= 0)
            {
                result.SetResult(ResultCode.DATA_MISMATCH);
            }

            if (result.Fine)
            {
                //discontinuity_indicator
                result = Utility.ByteArrayReadBits(data, ref dataLeftInBit, ref bitOffset, 1, ref discontinuityIndicator);
            }

            if (result.Fine)
            {
                //random_access_indicator,elementary_stream_priority_indicator
                result = Utility.ByteArrayReadBits(data, ref dataLeftInBit, ref bitOffset, 2, ref fieldValue);
            }

            Int64 pcrFlag = 0;

            if (result.Fine)
            {
                result = Utility.ByteArrayReadBits(data, ref dataLeftInBit, ref bitOffset, 1, ref pcrFlag);//PCR_flag
            }

            if (result.Fine)
            {
                //OPCR_flag,splicing_point_flag,transport_private_data_flag,adaptation_field_extension_flag
                result = Utility.ByteArrayReadBits(data, ref dataLeftInBit, ref bitOffset, 4, ref fieldValue);
            }

            if (result.Fine && (1 == pcrFlag))
            {
                Int64 programClockReferenceBase = 0;
                if (result.Fine)
                {
                    result = Utility.ByteArrayReadBits(data, ref dataLeftInBit, ref bitOffset, 33, ref programClockReferenceBase);//program_clock_reference_base
                }

                if (result.Fine)
                {
                    //Reserved
                    result = Utility.ByteArrayReadBits(data, ref dataLeftInBit, ref bitOffset, 1, ref fieldValue);
                }

                Int64 programClockReferenceExtension = 0;
                if (result.Fine)
                {
                    //program_clock_reference_extension
                    result = Utility.ByteArrayReadBits(data, ref dataLeftInBit, ref bitOffset, 9, ref programClockReferenceExtension);
                }

                if (result.Fine)
                {
                    //Convert to complete PCR.
                    pcrValid = true;

                    pcr = programClockReferenceBase * 300 + programClockReferenceExtension;
                }
            }

            return(pcrValid);
        }
Example #13
0
 public override void ProcessTsPacket(TsPacketMetadata tsPacketMetadata, byte[] packetBuffer, Int64 packetOffsetInBuffer)
 {
     //Invoke the stream parser to process a TS packet.
     streamParserCore.ProcessTsPacket(tsPacketMetadata, packetBuffer, packetOffsetInBuffer);
 }
Example #14
0
 public void AddTsPacket(TsPacketMetadata tsPacketMetadata)
 {
     totalSize += (Int64)tsPacketMetadata.PacketSize;
 }
Example #15
0
        /**
         * Add the data into the channel buffer.
         *
         * @param tsPacketMetadata packet information.
         * @param newData byte array containing the data to be added into the channel buffer.
         * @param leftDataLengthInBit how many bits left in the byte array.\n
         *        On input, it indicates how many bits left in the byte array.\n
         *        On output, it indicates how many bits left in the byte array after reading out requested data from the byte array.
         * @param newDataOffsetInBit offset of the position to read in the data from the byte array.\n
         *        On input, it indicates the offset to read in data.\n
         *        On output, it indicates the offset after reading out requested data from the byte array.
         * @param newDataLengthInBit how many bits to be read out from the byte array.
         *
         * @retval result
         */
        public void AddSectionData(TsPacketMetadata tsPacketMetadata, byte[] newData, ref Int64 leftDataLengthInBit, ref Int64 newDataOffsetInBit, Int64 newDataLengthInBit)
        {
            Result result = new Result();

            if (newDataLengthInBit > 0)
            {
                if (null == dataBuffer)
                {
                    this.bufferSize = 5 * 1024;
                    dataBuffer      = new byte[bufferSize];
                }

                //Convert bits to bytes.
                Int64 newDataLengthInByte = newDataLengthInBit / 8;
                Int64 newDataOffsetInByte = newDataOffsetInBit / 8;

                //Save the packetMetadata.
                packetMetadataList.Add(tsPacketMetadata);

                if (result.Fine)
                {
                    //Check whether there is enough data left in the buffer.
                    if (newDataLengthInBit > leftDataLengthInBit)
                    {
                        result.SetResult(ResultCode.INSUFFICIENT_DATA);

                        //Report an error.
                        GetContext().WriteLog("Invalid data length has been detected!" + Environment.NewLine);
                    }
                }

                if (result.Fine)
                {
                    //If no enough space to save the data.
                    if ((currentDataLength + currentOffset + newDataLengthInByte) > bufferSize)
                    {
                        //Copy the data to the beginning of the buffer first.
                        Array.Copy(dataBuffer, currentOffset, dataBuffer, 0, currentDataLength);
                        currentOffset = 0;
                    }

                    //Have a check again!
                    if ((currentDataLength + currentOffset + newDataLengthInByte) > bufferSize)
                    {
                        //result.SetResult(ResultCode.INSUFFICIENT_DATA);
                        //GetContext().WriteLog("Error:Insufficient channel buffer!" + Environment.NewLine);

                        //No enough buffer. Allocate a larger buffer to save the content. Increase 4 bytes each time.
                        Int64 newBufferSize = bufferSize + 4 * 1024;//We need this because to endure some "bad" streams!!!!!!!!!!!!!!!!!!

                        byte[] newBuffer = new byte[newBufferSize];

                        Array.Copy(dataBuffer, newBuffer, currentDataLength);//Copy from the old one into the new one.

                        dataBuffer = newBuffer;
                        bufferSize = newBufferSize;
                    }

                    //Enough space.Save the data into the space.
                    Array.Copy(newData, newDataOffsetInByte, dataBuffer, currentOffset + currentDataLength, newDataLengthInByte);//Note that the forth parameter is offset + length!

                    //Increase the data length!
                    currentDataLength += newDataLengthInByte;

                    //Decrease the left data length.
                    leftDataLengthInBit -= newDataLengthInBit;

                    //Increase the offset.
                    newDataOffsetInBit += newDataLengthInBit;

                    if (dataType == DataType.SECTION)
                    {
                        CheckSectionAvailable();//Notify any available section if any!
                    }
                }
            }
        }
Example #16
0
        public Result ProcessTsPacket(TsPacketMetadata tsPacketMetadata, byte[] packetBuffer, Int64 packetOffsetInBuffer)
        {
            Result result = new Result();
            //Int64 dataLeftInBit = (Int64)tsPacketMetadata.PacketSize;
            Int64 dataLeftInBit = (Int64)TsPacketSize.SIZE_188 * 8; //Important!!!!No matter 188 or 204 bytes, the valid data will always be 188 bytes.16 bytes are checksum that is not useful for parsing.

            Int64 bitOffset = packetOffsetInBuffer * 8;             //Key point to set the beginning offset!!!!!


            if (result.Fine)
            {
                //8-bit sync_byte.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 8);
            }

            if (result.Fine)
            {
                //1-bit transport_error_indicator.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 payloadUnitStartIndicator = 0;

            if (result.Fine)
            {
                //1-bit payload_unit_start_indicator.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 1, ref payloadUnitStartIndicator);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 1) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //1-bit transport_priority.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 1);
            }

            Int64 pid = 0;

            if (result.Fine)
            {
                //13-bit PID.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 13, ref pid);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 13) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //2-bit transport_scrambling_control.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 2);
            }

            Int64 adaptationFieldControl = 0;

            if (result.Fine)
            {
                //2-bit adaptation_field_control.
                result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 2, ref adaptationFieldControl);
                //GetContext().WriteLog(Utility.GetValueBinaryString(fieldValue, 2) + Environment.NewLine);
            }

            if (result.Fine)
            {
                //4-bit continuity_counter.
                result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, 4);
            }

            //To parse adaption fields.
            Int64 adaptationFieldLength = 0;

            if (result.Fine)
            {
                //If adaptationFieldControl is 0b10(Adaptation_field only, no payload) or 0b11(Adaptation_field followed by payload),there is a adaption_field. We need to skip the adaption fields.
                if ((0x2 == adaptationFieldControl) || (0x3 == adaptationFieldControl))
                {
                    //8-bit adaptation_field_length
                    result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 8, ref adaptationFieldLength);

                    //Skip adaption fields according to the adaption_field_length.
                    if (result.Fine)
                    {
                        result = Utility.ByteArraySkipBits(ref dataLeftInBit, ref bitOffset, (adaptationFieldLength * 8));
                    }
                }
            }

            //If the packet is what we want.
            if (result.Fine)
            {
                DataType pidDataType = GetChannelType((UInt16)pid);
                if (DataType.SECTION == pidDataType)
                {
                    Channel channelDataStore = null;
                    //Check start indicator.
                    if (0 == payloadUnitStartIndicator)
                    {
                        //No complete section is expected.

                        /*
                         * At the first beginning of parsing, we may receive some TS packets with payloadUnitStartIndicator ZERO.
                         * We will ignore these packets if there is nothing in the buffer, because these packets are not expected contain the start of a section.
                         * Having these kinds of TS packets is useless.
                         */
                        if (channelList.TryGetValue((UInt16)pid, out channelDataStore))
                        {
                            //We already get the item in the channel list. Save it into the ChannelDataStore.
                            channelDataStore.AddSectionData(tsPacketMetadata, packetBuffer, ref dataLeftInBit, ref bitOffset, dataLeftInBit);
                        }
                    }
                    else
                    {
                        //Start indicator is set to 1. A new section is expected. Get the pointer field.

                        //8-bit pointer_field.
                        Int64 pointerField = 0;
                        result = Utility.ByteArrayReadBits(packetBuffer, ref dataLeftInBit, ref bitOffset, 8, ref pointerField);

                        if (result.Fine)
                        {
                            if (!channelList.TryGetValue((UInt16)pid, out channelDataStore))
                            {
                                //No existing Channel. Create a new one to store section.
                                channelDataStore = new Channel(owner, (UInt16)pid, HandleDataFromChannel, DataType.SECTION);

                                //Insert to the channel list.
                                channelList.Add((UInt16)pid, channelDataStore);
                            }
                        }

                        //Save the data belonged to the previous section and have a clean-up first.
                        if (result.Fine)
                        {
                            //Save the data with length indicated pointer_field. The data belongs to the previous section.
                            channelDataStore.AddSectionData(tsPacketMetadata, packetBuffer, ref dataLeftInBit, ref bitOffset, pointerField * 8);//Pay attention to the third parameter.

                            if (result.Fine)
                            {
                                //Clean up data NO MATTER HOW in case we may have received some invalid data that may disturb the parsing!!!!!!!!!!!!!!!!!!!!!!
                                channelDataStore.Reset();
                            }
                        }

                        if (result.Fine)
                        {
                            //Save the data belonged to the new section.
                            channelDataStore.AddSectionData(tsPacketMetadata, packetBuffer, ref dataLeftInBit, ref bitOffset, dataLeftInBit);
                        }
                    }
                }//PID for section filtering.
                else if (DataType.PES_PACKET == pidDataType)
                {
                    Channel channelDataStore = null;
                    //Check start indicator.
                    if (0 == payloadUnitStartIndicator)
                    {
                        //No complete PES is expected.

                        /*
                         * At the first beginning of parsing, we may receive some TS packets with payloadUnitStartIndicator ZERO.
                         * We will ignore these packets if there is nothing in the buffer, because these packets will not contain the start of a PES.
                         * Having these kinds of TS packets is useless.
                         */
                        if (channelList.TryGetValue((UInt16)pid, out channelDataStore))//Existing Channel for this PID.
                        {
                            //We already get the item in the channel list. Save it into the ChannelDataStore.
                            channelDataStore.AddPesData(tsPacketMetadata, payloadUnitStartIndicator, packetBuffer, bitOffset, dataLeftInBit);
                        }
                    }
                    else
                    {
                        //Start indicator is set to 1. A new PES is expected. Send out all existing data as a PES packet.

                        if (result.Fine)
                        {
                            if (!channelList.TryGetValue((UInt16)pid, out channelDataStore))//No existing Channel for this PID.
                            {
                                //No existing ChannelDataStore. Create a new one to store PES data.
                                channelDataStore = new Channel(owner, (UInt16)pid, HandleDataFromChannel, DataType.PES_PACKET);

                                //Insert to the channel list.
                                channelList.Add((UInt16)pid, channelDataStore);
                            }
                        }

                        if (result.Fine)
                        {
                            //Save the data belonged to the new PES.
                            channelDataStore.AddPesData(tsPacketMetadata, payloadUnitStartIndicator, packetBuffer, bitOffset, dataLeftInBit);
                        }
                    }
                }//PID for PES filtering.
                else if (DataType.TS_PACKET == pidDataType)
                {
                    Channel channelDataStore = null;

                    if (!channelList.TryGetValue((UInt16)pid, out channelDataStore))
                    {
                        //No existing Channel. Create a new one to store the TS.
                        channelDataStore = new Channel(owner, (UInt16)pid, HandleDataFromChannel, DataType.TS_PACKET);

                        //Insert to the channel list.
                        channelList.Add((UInt16)pid, channelDataStore);
                    }

                    //Add it into the channel buffer.
                    channelDataStore.AddTsPacket(tsPacketMetadata, packetBuffer, packetOffsetInBuffer);
                }//PID for TS packet filtering.
            }


            return(result);
        }