示例#1
0
        public Media.Container.Node ReadUnit(TransportStreamUnit.PacketIdentifier name, long offset = 0)
        {
            long positionStart = Position;

            Media.Container.Node result = ReadUnits(offset, Length - offset, name).FirstOrDefault();

            Position = positionStart;

            return(result);
        }
示例#2
0
 public static string ToTextualConvention(TransportStreamReader reader, byte[] identifier)
 {
     TransportStreamUnit.PacketIdentifier result = TransportStreamUnit.GetPacketIdentifier(identifier, reader.UnitOverhead);
     if (TransportStreamUnit.IsReserved(result))
     {
         return("Reserved");
     }
     if (TransportStreamUnit.IsDVBMetaData(result))
     {
         return("DVBMetaData");
     }
     if (TransportStreamUnit.IsUserDefined(result))
     {
         return("UserDefined");
     }
     return(result.ToString());
 }
示例#3
0
        internal protected virtual void ParseDescriptionTable(Container.Node node)
        {
            int offset = ReadPointerField(node);

            //Get the table id
            TransportStreamUnit.TableIdentifier tableId = (TransportStreamUnit.TableIdentifier)node.Data[offset++];

            if (tableId != TransportStreamUnit.TableIdentifier.ProgramAssociation)
            {
                return;
            }

            TransportStreamUnit.PacketIdentifier pcrPid = (TransportStreamUnit.PacketIdentifier)(Common.Binary.ReadU16(node.Data, offset, Common.Binary.IsLittleEndian) & TransportStreamUnit.PacketIdentifierMask);

            int infoLength = Common.Binary.ReadU16(node.Data, ref offset, Common.Binary.IsLittleEndian) & 0x0FFF;

            //Determine where to end (don't count the crc)
            int end = (infoLength + 3) - 4;

            while (offset < end)
            {
                byte esType = node.Data[offset++];

                //Could store two bytes and have methods to extract with masks.

                TransportStreamUnit.PacketIdentifier esPid = (TransportStreamUnit.PacketIdentifier)(Common.Binary.ReadU16(node.Data, offset, Common.Binary.IsLittleEndian) & TransportStreamUnit.PacketIdentifierMask);

                ushort descLength = (ushort)(Common.Binary.ReadU16(node.Data, offset, Common.Binary.IsLittleEndian) & 0x0FFF);

                var entry = new Tuple <TransportStreamUnit.PacketIdentifier, ushort>(esPid, descLength);

                m_ProgramDescriptions.AddOrUpdate(esType, entry, (a, old) => entry);

                offset += 2;
            }

            //CRC
        }
示例#4
0
        //Static and take reader?
        //Maps from Program to PacketIdentifer?
        internal protected virtual void ParseProgramAssociationTable(Container.Node node)
        {
            int offset = ReadPointerField(node);

            //Get the table id
            TransportStreamUnit.TableIdentifier tableId = (TransportStreamUnit.TableIdentifier)node.Data[offset++];

            if (tableId != TransportStreamUnit.TableIdentifier.ProgramAssociation)
            {
                return;
            }

            /*
             *  Program Association Table (PAT) section syntax
             *  syntax	bit index	# of bits	mnemonic
             *  table_id	0	8	uimsbf
             *  section_syntax_indicator	8	1	bslbf
             *  '0'	9	1	bslbf
             *  reserved	10	2	bslbf
             *  section_length	12	12	uimsbf
             *  transport_stream_id	24	16	uimsbf
             *  reserved	40	2	bslbf
             *  version_number	42	5	uimsbf
             *  current_next_indicator	47	1	bslbf
             *  section_number	48	8	bslbf
             *  last_section_number	56	8	bslbf
             *  for i = 0 to N
             *    program_number	56 + (i * 4)	16	uimsbf
             *    reserved	72 + (i * 4)	3	bslbf
             *    if program_number = 0
             *      network_PID	75 + (i * 4)	13	uimsbf
             *    else
             *      program_map_pid	75 + (i * 4)	13	uimsbf
             *    end if
             *  next
             *  CRC_32	88 + (i * 4)	32	rpchof
             *  Table section legend
             */


            //section syntax indicator, 0 bit, and 2 reserved bits.

            //Section Length The number of bytes that follow for the syntax section (with CRC value) and/or table data. These bytes must not exceed a value of 1021.
            // section_length field is a 12-bit field that gives the length of the table section beyond this field
            //Since it is carried starting at bit index 12 in the section (the second and third bytes), the actual size of the table section is section_length + 3.
            ushort sectionLength = (ushort)(Common.Binary.ReadU16(node.Data, ref offset, Common.Binary.IsLittleEndian) & 0x0FFF);

            //transport_stream_id	24	16	uimsbf
            ushort transportStreamId = (ushort)(Common.Binary.ReadU16(node.Data, ref offset, Common.Binary.IsLittleEndian) & 0x0FFF);

            //Skip reserved, version number and current/next indicator.
            ++offset;

            //Skip section number
            ++offset;

            //Skip last section number
            ++offset;

            //Determine where to end (don't count the crc)
            int end = (sectionLength + 3) - 4;

            //4 bytes per ProgramInfo in node.Data
            while (offset < end)
            {
                //2 Bytes ProgramNumber
                ushort programNumber = Common.Binary.ReadU16(node.Data, offset, Common.Binary.IsLittleEndian);

                //3 bits reserved

                //2 Bytes ProgramID
                TransportStreamUnit.PacketIdentifier pid = TransportStreamUnit.GetPacketIdentifier(node.Data, offset + 2);

                //Add or update the entry
                m_ProgramAssociations.AddOrUpdate(programNumber, pid, (id, old) => pid);

                //Move the offset
                offset += 4;
            }

            //CRC
        }
示例#5
0
        /// <summary>
        /// Enumerates each unit found in the TransportStream.
        /// When a unit is found it is either added to the Streams or it is parsed to obtain information.
        /// </summary>
        /// <returns></returns>
        public override IEnumerator <Container.Node> GetEnumerator()
        {
            //Ensure a Unit remains
            while (Remaining >= TransportUnitSize)
            {
                //Read a unit
                Container.Node next = ReadNext();

                //No more units stops the enumeration
                if (next == null)
                {
                    yield break;
                }

                //Return the unit for external handling
                yield return(next);

                //Get the type of packet this is
                TransportStreamUnit.PacketIdentifier pid = GetPacketIdentifier(this, next.Identifier);

                //Need to parse the packet to ensure that GetTracks can always be updated.
                switch (pid)
                {
                case TransportStreamUnit.PacketIdentifier.ProgramAssociationTable:
                {
                    /*
                     *
                     * The Program Association Table (PAT) is the entry point for the Program Specific Information (PSI) tables.
                     *
                     * It is always carried in packets with PID (packet ID) = 0.  For each assigned program number, the PAT lists the PID for packets containing that program's PMT.
                     *
                     * The PMT lists all the PIDs for packets containing elements of a particular program (audio, video, aux data, and Program Clock Reference (PCR)).
                     *
                     * The PAT also contains the PIDs for the NIT(s).
                     *
                     * The NIT is an optional table that maps channel frequencies, transponder numbers, and other guide information for programs.
                     *
                     */

                    ParseProgramAssociationTable(next);

                    goto default;
                }

                case TransportStreamUnit.PacketIdentifier.DescriptionTable:     // TableIdentifier.ProgramMap
                {
                    //Parse the table
                    ParseDescriptionTable(next);

                    goto default;
                }

                //case PacketIdentifier.Program
                case TransportStreamUnit.PacketIdentifier.ConditionalAccessTable:
                case TransportStreamUnit.PacketIdentifier.SelectionInformationTable:
                case TransportStreamUnit.PacketIdentifier.NetworkInformationTable:
                {
                    //Todo
                    goto default;
                }

                default:
                {
                    //Include the PId with the StreamId
                    m_ProgramIds.Add(pid);
                    break;
                }
                }

                //Done with the unit
                Skip(next.DataSize);
            }
        }