Example #1
0
        unsafe void process_psi_pat(TsStream s, FrameReader fr)
        {
            long len = fr.Length - 4;
            long n   = len / 4;

            if (len < 0 || 0 != (len % 4))
            {
                throw new NotSupportedException();
            }

            for (int i = 0; i < n; i++)
            {
                ushort channel = fr.read_ushort();
                ushort pid     = fr.read_ushort();
                if ((pid & 0xe000) != 0xe000)
                {
                    throw new NotSupportedException();
                }

                pid &= 0x1fff;

                if (demuxer_channel == 0 || demuxer_channel == channel)
                {
                    if (!streams.ContainsKey(pid))
                    {
                        streams.Add(pid, new TsStream());
                    }
                    TsStream ss = streams[pid];
                    ss.channel = channel;
                    ss.type    = 0xff;
                }
            }
        }
Example #2
0
        unsafe void process_psi(TsStream s, FrameReader fr, UInt16 pid, int table)
        {
            if (0 == pid)
            {
                process_psi_pat(s, fr); // Program Association Table
                return;
            }
            //if (1 == pid)
            //{
            //    process_cat(s, ptr, end_ptr); // Conditional Access Table
            //    return;
            //}
            //if (0x11 == pid)
            //{
            //    process_sdt(s, ptr, end_ptr);
            //    return;
            //}

            if (table == 0x02)
            {
                process_psi_pmt(s, fr); // Program Map Table
                return;
            }
        }
Example #3
0
        unsafe void demux_ts_packet(FrameReader fr, out TsStream dataStream)
        {
            dataStream = null;

            uint timecode = fr.read_uint() & 0x3fffffff;

            byte sync = fr.read_byte(); // ts sync byte

            if (sync != 0x47)
            {
                throw new FormatException("invalid packet");
            }

            ushort pid             = fr.read_ushort();
            bool   transport_error = (pid & 0x8000) != 0;
            bool   payload_unit_start_indicator = (pid & 0x4000) != 0;

            pid &= 0x1fff;
            if (transport_error)
            {
                throw new FormatException("invalid packet ");
            }

            byte flags = fr.read_byte();
            bool adaptation_field_exist = (flags & 0x20) != 0;
            bool payload_data_exist     = (flags & 0x10) != 0;
            byte continuity_counter     = (byte)(flags & 0x0f);

            if (pid == 0x1fff || !payload_data_exist)
            {
                return;
            }

            // skip adaptation field
            if (adaptation_field_exist)
            {
                fr.skip(fr.read_byte());
            }

            if (!streams.ContainsKey(pid))
            {
                streams.Add(pid, new TsStream());
            }
            TsStream s = streams[pid];

            if (0 == pid || (s.channel != 0xffff && s.type == 0xff))
            {
                // PSI (Program Specific Information)
                if (payload_unit_start_indicator)
                {
                    // begin of PSI table
                    byte pointerLen = fr.read_byte();
                    fr.skip(pointerLen);
                    byte   tableId       = fr.read_byte();
                    ushort sectionHeader = fr.read_ushort();
                    bool   syntaxFlag    = ((sectionHeader >> 15) & 1) != 0;
                    bool   privateFlag   = ((sectionHeader >> 14) & 1) != 0;
                    int    reservedBits  = (sectionHeader >> 12) & 3;
                    if (reservedBits != 3)
                    {
                        throw new NotSupportedException();
                    }
                    int l = sectionHeader & 0x0fff;
                    if (syntaxFlag)
                    {
                        ushort extId            = fr.read_ushort();
                        byte   tmp8             = fr.read_byte();
                        int    reserved3        = (tmp8 >> 6);
                        int    version          = (tmp8 >> 1) & 31;
                        bool   current_flag     = (tmp8 & 1) != 0;
                        byte   section_num      = fr.read_byte();
                        byte   last_section_num = fr.read_byte();
                        l -= 5;
                    }

                    int len = (int)fr.Length;
                    if (l <= len)
                    {
                        fr.Length = l;
                        process_psi(s, fr, pid, tableId);
                        return;
                    }

                    if (l > s.psi.Length)
                    {
                        throw new FormatException("invalid packet ");
                        fixed(byte *psip = &s.psi[0])
                        fr.read_bytes(psip, len);

                        s.psi_offset = len;
                        s.psi_table  = tableId;
                        s.psi_len    = l;
                        return;
                }

                // next part of PSI
                if (0 == s.psi_offset)
                {
                    throw new FormatException("invalid packet ");
                }

                {
                    int len = (int)fr.Length;
                    if (len > s.psi.Length - s.psi_offset)
                        throw new FormatException("invalid packet ");
                    fixed(byte *psip = &s.psi[s.psi_offset])
                    fr.read_bytes(psip, len);

                    s.psi_offset += len;
                }

                if (s.psi_offset < s.psi_len)
                    return;

                fixed(byte *psip = &s.psi[0])
                {
                    var psiFr = new FrameReader(psip, psip + s.psi_len);

                    process_psi(s, psiFr, pid, s.psi_table);
                }

                return;
            }

            if (s.type != 0xff)
            {
                // PES

                if (payload_unit_start_indicator)
                {
                    s.psi_offset = 0;
                    s.psi_len    = 9;
                }

                while (s.psi_offset < s.psi_len)
                {
                    int len = Math.Min((int)fr.Length, s.psi_len - s.psi_offset);
                    if (len <= 0)
                        return;

                    fixed(byte *psip = &s.psi[s.psi_offset])
                    fr.read_bytes(psip, len);

                    s.psi_offset += len;
                    if (s.psi_len == 9)
                        s.psi_len += s.psi[8];
}
                }

                if (s.psi_len != 0)
                {
                    fixed(byte *psip = &s.psi[0])
                    {
                        var pesFr = new FrameReader(psip, psip + s.psi_len);

                        process_pes_header(s, pesFr);
                    }

                    s.psi_len    = 0;
                    s.psi_offset = 0;
                }

                if (s.frame_num == 0)
                    return; }

                //if(es_parse)
                //{
                //    switch(s.type)
                //    {
                //    case 0x1b:
                //        s.frame_num_h264.parse(fr);
                //        break;
                //    case 0x06:
                //    case 0x81:
                //    case 0x83:
                //        s.frame_num_ac3.parse(fr);
                //        break;
                //    }
                //}

                if (s.is_opened)
                {
                    if (s.at_packet_header)
                    {
                        BdHeader(s, fr);
                        s.at_packet_header = false;
                    }

                    dataStream = s;
                }
            }
Example #4
0
        unsafe void BdHeader(TsStream s, FrameReader fr)
        {
            uint h = fr.read_uint();
            int  pi_channels;
            int  pi_channels_padding;
            int  pi_bits;
            int  pi_rate;

            switch ((h & 0xf000) >> 12)
            {
            case 1:
                pi_channels = 1;
                break;

            case 3:
                pi_channels = 2;
                break;

            case 4:
                pi_channels = 3;
                //{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
                //  AOUT_CHAN_CENTER, 0 };
                break;

            case 5:
                pi_channels = 3;
                //{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
                //  AOUT_CHAN_REARCENTER, 0 };
                break;

            case 6:
                pi_channels = 4;
                //{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
                //  AOUT_CHAN_CENTER, AOUT_CHAN_REARCENTER, 0 };
                break;

            case 7:
                pi_channels = 4;
                //{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
                //  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 };
                break;

            case 8:
                pi_channels = 5;
                //{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
                //  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, 0 };
                break;

            case 9:
                pi_channels = 6;
                //{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
                //  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_LFE, 0 };
                break;

            case 10:
                pi_channels = 7;
                //{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
                //  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
                //  AOUT_CHAN_MIDDLERIGHT, 0 };
                break;

            case 11:
                pi_channels = 8;
                //{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER,
                //  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
                //  AOUT_CHAN_MIDDLERIGHT, AOUT_CHAN_LFE, 0 };
                break;

            default:
                throw new NotSupportedException();
            }
            pi_channels_padding = pi_channels & 1;

            switch ((h >> 6) & 0x03)
            {
            case 1:
                pi_bits = 16;
                break;

            case 2:
                pi_bits = 20;
                break;

            case 3:
                pi_bits = 24;
                break;

            default:
                throw new NotSupportedException();
            }

            switch ((h >> 8) & 0x0f)
            {
            case 1:
                pi_rate = 48000;
                break;

            case 4:
                pi_rate = 96000;
                break;

            case 5:
                pi_rate = 192000;
                break;

            default:
                throw new NotSupportedException();
            }

            if (s.pcm == null)
            {
                s.pcm = new AudioPCMConfig(pi_bits, pi_channels, pi_rate);
            }
        }
Example #5
0
        unsafe void process_pes_header(TsStream s, FrameReader fr)
        {
            // Packet start code prefix
            if (fr.read_byte() != 0 || fr.read_byte() != 0 || fr.read_byte() != 1)
            {
                throw new NotSupportedException();
            }

            s.ts_stream_id = fr.read_byte();

            int pes_len  = (int)fr.read_ushort();
            int pes_type = (fr.read_byte() >> 6) & 3;

            // pes_type == 2; /* mpeg2 PES */

            byte flags1 = fr.read_byte();

            s.frame_size = fr.read_byte();
            s.frame_num++;
            s.at_packet_header = true;

            switch (flags1 & 0xc0)
            {
            case 0x80:              // PTS only
            {
                ulong pts = fr.read_pts();

                if (s.dts > 0 && pts > s.dts)
                {
                    s.frame_length = (uint)(pts - s.dts);
                }
                s.dts = pts;

                if (pts > s.last_pts)
                {
                    s.last_pts = pts;
                }

                if (s.first_pts == 0)
                {
                    s.first_pts = pts;
                }
            }
            break;

            case 0xc0:              // PTS,DTS
            {
                ulong pts = fr.read_pts();
                ulong dts = fr.read_pts();

                if (s.dts > 0 && dts > s.dts)
                {
                    s.frame_length = (uint)(dts - s.dts);
                }
                s.dts = dts;

                if (pts > s.last_pts)
                {
                    s.last_pts = pts;
                }

                if (s.first_dts == 0)
                {
                    s.first_dts = dts;
                }
            }
            break;
            }
        }
Example #6
0
        unsafe void process_psi_pmt(TsStream s, FrameReader fr)
        {
            // PMT (Program Map Table)
            ushort pcr_pid  = fr.read_ushort();
            ushort info_len = (ushort)(fr.read_ushort() & 0x0fff);

            fr.skip(info_len);

            // CRC
            fr.Length -= 4;

            while (fr.Length > 0)
            {
                byte   type   = fr.read_byte();
                ushort es_pid = fr.read_ushort();

                if ((es_pid & 0xe000) != 0xe000)
                {
                    throw new IndexOutOfRangeException();
                }

                es_pid &= 0x1fff;

                info_len = (ushort)(fr.read_ushort() & 0x0fff);

                while (info_len > 0)
                {
                    byte tag = fr.read_byte();
                    switch (tag)
                    {
                    case 0x05:     // registration descriptor
                    {
                        byte len = fr.read_byte();
                        uint rid = fr.read_uint();
                        if (rid == 0x48444D56 /* "HDMV" */ && type == 0x80 /* LPCM */)
                        {
                            if (!streams.ContainsKey(es_pid))
                            {
                                streams.Add(es_pid, new TsStream());
                                TsStream ss = streams[es_pid];
                                if (ss.channel != s.channel || ss.type != type)
                                {
                                    ss.channel   = s.channel;
                                    ss.type      = type;
                                    ss.streamId  = s.streamId;
                                    ss.is_opened = true;
                                    s.streamId++;
                                }
                            }
                        }
                        fr.skip(len - 4);
                        info_len -= (ushort)(len + 2);
                        break;
                    }

                    default:
                    {
                        fr.skip(info_len - 1);
                        info_len = 0;
                        break;
                    }
                    }
                }
            }

            if (fr.Length > 0)
            {
                throw new IndexOutOfRangeException();
            }
        }