示例#1
0
        public WorkerFileDataSearch(StreamParserContext owner, MessageHandlerDelegate messageCallbackFromOwner, SearchRequest searchRequest)
            : base(owner, messageCallbackFromOwner)
        {
            this.sectionManager = new ManagerSection(owner);
            this.streamDemux    = new StreamDemux(owner);
            this.searchRequest  = searchRequest;

            //In search mode. We will not parse standard SI/PSI sections, instead ,we will set up a filter for the expected data.

            Filter filterForSearch = null;

            if (searchRequest.SearchType == DataType.SECTION)
            {
                //To search sections.
                filterForSearch = new Filter(owner, HandleDataFromDemux, searchRequest.SearchType, searchRequest.SelectedPid, searchRequest.FilterMask.Length, searchRequest.FilterMask, searchRequest.FilterMatch);
            }
            else
            {
                //To search TS packet or PES packet.
                filterForSearch = new Filter(owner, HandleDataFromDemux, searchRequest.SearchType, searchRequest.SelectedPid);
            }

            //In order to fitler out what we are expecting.
            streamDemux.AddFilter(filterForSearch);
        }
示例#2
0
        public StreamParserCore(StreamParserContext owner, MessageHandlerDelegate messageCallback)
            : base(owner)
        {
            this.streamDemux = new StreamDemux(owner);

            /**
             * Create all necessary modules even we don't need all them in some cases.
             * In live environment,i.e. IP network or device, we will need all of them.
             */
            sectionManager = new ManagerSection(owner);

            serviceManager = new ManagerService(owner);

            streamBitrateManager = new ManagerMuxBitrate();

            pidManager = new ManagerPid(owner);

            AddDefaultPidType();

            this.messageCallback = messageCallback;

            //Set up filters to receive standard SI/PSI sections.
            EnableStandardFilters(streamDemux);
        }
示例#3
0
        //Enable standard filters to receive SI/PSI sections.
        public void EnableStandardFilters(StreamDemux streamDemux)
        {
            //To filter PAT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.PAT, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.PAT
            }));                                            //Match.

            //To filter CAT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.CAT, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.CAT
            }));                                            //Match.

            //To filter TSDT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.TSDT, //PID.
                                             1,                  //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.TSDT
            }));                                             //Match.

            //To filter NIT for current network and for other network.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.NIT, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xFE
            },                                 //Mask. To filter out table ID 0x40 and 0x41.
                                             new byte[1] {
                (byte)TableId.NIT_ACTUAL
            }));                                                   //Match.

            //To filter SDT for current stream and for other stream.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.BAT_SDT, //PID.
                                             1,                     //Filter depth.
                                             new byte[1] {
                0xFB
            },                                 //Mask.To filter out table ID 0x42 and 0x46.
                                             new byte[1] {
                (byte)TableId.SDT_ACTUAL
            }));                                                   //Match.

            //To filter BAT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.BAT_SDT, //PID.
                                             1,                     //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.BAT
            }));                                            //Match.

            //To filter EIT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.EIT, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xFE
            },                                 //Mask. To filter out table ID 0x4E and 0x4F.
                                             new byte[1] {
                (byte)TableId.EIT_PF_ACTUAL
            }));                                                      //Match.

            //To filter EIT schedule for current stream.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.EIT, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xF0
            },                                 //Mask. To filter out table ID 0x50 to 0x5F.
                                             new byte[1] {
                (byte)TableId.EIT_SCHEDULE_ACTUAL
            }));                                                            //Match.

            //To filter EIT schedule for other stream.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.EIT, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xF0
            },                                 //Mask. To filter out table ID 0x50 to 0x5F.
                                             new byte[1] {
                (byte)TableId.EIT_SCHEDULE_OTHER
            }));                                                           //Match.

            //To filter RST.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.RST, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.RST
            }));                                            //Match.

            //To filter TDT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.TDT_TOT, //PID.
                                             1,                     //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.TDT
            }));                                            //Match.

            //To filter TOT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.TDT_TOT, //PID.
                                             1,                     //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.TOT
            }));                                            //Match.

            //To filter DIT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.DIT, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.DIT
            }));                                            //Match.

            //To filter SIT.
            streamDemux.AddFilter(new Filter(GetContext(), ProcessFilteredData,
                                             DataType.SECTION,
                                             (UInt16)TsPID.SIT, //PID.
                                             1,                 //Filter depth.
                                             new byte[1] {
                0xFF
            },                                 //Mask.
                                             new byte[1] {
                (byte)TableId.SIT
            }));                                            //Match.
        }
示例#4
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();
        }