/*
 * jTsSplitter - java based mpeg2ts splitter.
 * Copyright (C) 2009-2012 Yukikaze
 */
package jtssplitter;

import java.util.ArrayList;
import java.util.Arrays;
import jtssplitter.data.PATData;
import jtssplitter.data.PMTData;
import jtssplitter.data.Descriptor;
import jtssplitter.data.EITData;
import java.io.ByteArrayOutputStream;

/**
 *
 * @author gn64_jp
 */
public class Mpeg2TSPacket {
    //TSのヘッダーを格納する

    public String header;
    public String payload;
    public String adaptation;
    public byte[] header_byte;
    public byte[] payload_byte;
    public byte[] adaptation_byte;
    public byte[] bPAT_payload = null;
    //private ArrayList<TsDate> date=new ArrayList<TsDate>();
    //date.add(new TsDate("Starter"))
    public int type;//
    private int starter;//0-7
    private int transporterror;//本TSパケットの誤りを示す 1bit 8
    private int payloadstart;//セクションの先頭バイトが入っているかどうか1bit 9
    private int transport_priority;//1bit 10
    private int PID = -1;//tsパケットの種類 13bit 11-23
    private int transport_scrambled;//2bit 00is " not scrambled" 24-25
    private int adaptation_field;//2bit 26-27 01:adaptation fieldなしでおｋ 10は絶対いる 11はペイロードはアダプテーションに続く00は予約
    private int continuity_counter;//連続性(PIDごとの通し番号) 4bit 28-31
    //ここからアダプテーションフィールド(最後まで)
    private int adaptation_length;//8bit 32-39
    private int discontinuity;//1bit
    private int random_access;//1bit ランダムアクセスの開始場所となる
    private int ES_priority;//1bit プライオリティ
    private int five_flag;//5bit
    private ArrayList<PATData> pat_list_now = new ArrayList<PATData>();//[0]:番組番号 [1]:PMT PID
    private ArrayList<PATData> pat_list_all = new ArrayList<PATData>();
    private ArrayList<PMTData> pmt_list = new ArrayList<PMTData>();//[0]番組番号 [1]テーブルID
    private int pointer_field;//8bit adaptation fieldの次?
    private String payload_s;
    //ここからオプションフィールド
    //PCR42 OPCR42 
    //ここまでオプションフィールド
    private int staffing_byte;//

    public Mpeg2TSPacket() {
    }

    public int getPIDFirst_byte(byte[] ts) {
        calc cal = new calc();
        byte[] b = new byte[2];
        b[0] = ts[1];
        b[1] = ts[2];
        return cal.byte2int(b, 3, 13);
        //return cal.byte2int(ts,11,13);
    }

    public void readTS_byte(byte[] ts) {
        /**
         * 188バイトのtsから読み出したbyteを与える
         */
        calc cal = new calc();
        String tsbyte = byte2String2(ts);
        boolean begin_payload_unit = cal.byte2int(ts, 9, 1) == 1;
        //header = tsbyte.substring(0, 31);
        payload = tsbyte.substring(32);
        //starter = TSString2Int(tsbyte, 0, 8);
        //transporterror = TSString2Int(tsbyte, 8, 1);
        //payloadstart = TSString2Int(tsbyte, 9, 1);
        //transport_priority = TSString2Int(tsbyte, 10, 1);
        //PID = TSString2Int(tsbyte, 11, 13);
        PID = cal.byte2int(ts, 11, 13);
        adaptation_field = cal.byte2int(ts, 26, 2);
        //continuity_counter = TSString2Int(tsbyte, 28, 4);
        payload = "";
        if (PID != 8191) {
            if (adaptation_field == 1) {
                if (begin_payload_unit) {
                    pointer_field = cal.byte2int(ts, 32, 8);
                    if ((ts.length - 5 - pointer_field) < (5 + pointer_field)) {
                        payload_byte = null;
                    } else {
                        payload_byte = cal.byte2subbyte(ts, 5 + pointer_field, ts.length - 5 - pointer_field);
                    }
                } else {
                    payload_byte = cal.byte2subbyte(ts, 4, ts.length - 4);
                }
            } else if (adaptation_field == 3) {
                adaptation_length = cal.byte2int(ts, 32, 8);
                if ((adaptation_length < 184) & ((ts.length * 8 - adaptation_length * 8) > 48)) {
                    adaptation_length = adaptation_length * 8;
                }
                adaptation_byte = cal.byte2subbyte(ts, 4, 1 + adaptation_length / 8);
                if (begin_payload_unit) {
                    pointer_field = cal.byte2int(ts, 40 + adaptation_length, 8);
                    if ((ts.length - 6 - (adaptation_length / 8) - pointer_field) < (6 + (adaptation_length / 8) + pointer_field)) {
                        payload_byte = null;
                    } else {
                        payload_byte = cal.byte2subbyte(ts, 6 + (adaptation_length / 8) + pointer_field, ts.length - 6 - (adaptation_length / 8) - pointer_field);
                    }
                } else {
                    payload_byte = cal.byte2subbyte(ts, 5 + adaptation_length / 8, ts.length - 5 - adaptation_length / 8);
                }
            } else {
                payload_byte = null;
            }
        }
        if (payload_byte != null) {
            if ((PID == 0) && (begin_payload_unit)) {
                //cal.showPAT(tsbyte);
                if (isPAT(payload_byte)){
                    pat_list_now = readPAT_byte(payload_byte);
                    if (pat_list_now.size()>0){
                        pat_list_all=pat_list_now;
                    }
                    //pat_list_all.addAll(pat_list_now);
                }
            }
            for (int i = 0; i < pat_list_now.size(); i++) {
                if ((PID == pat_list_now.get(i).PID) && (PID != 0)) {
                    pmt_list.addAll(readPMT_byte(payload_byte, pat_list_now.get(i).Program_TABLE));
                }
            }
        }
        tsbyte = "";
    }

    private ArrayList<PATData> readPAT_byte(byte[] payload_temp) {
        /*
         * payloadの文字列を入力して[intテーブル,int PID]のArrayListを返す。
         */
        int tableid;
        int sectionlength;
        calc cal = new calc();
        ArrayList<PATData> program_number = new ArrayList<PATData>();
        tableid = cal.byte2int(payload_temp, 0, 8);
        sectionlength = cal.byte2int(payload_temp, 12, 12);//-40-32;
        int patnum = sectionlength * 8 - 72;
        patnum = patnum / 32;
        for (int i = 0; i < patnum; i++) {
            if (payload_temp.length * 8 > 64 + 32 * i + 96) {
                if (cal.byte2int(payload_temp, 64 + 32 * i + 16, 3) == 7) {
                    PATData patd = new PATData();
                    patd.Program_TABLE = cal.byte2int(payload_temp, 64 + 32 * i, 16);
                    patd.PID = cal.byte2int(payload_temp, 32 * i + 64 + 19, 13);
                    program_number.add(patd);
                }
            }
        }
        return program_number;
    }
    private ArrayList<PMTData> readPMT_byte(byte[] payload_temp, int PAT_TABLE) {
        ArrayList<PMTData> pmt_t = new ArrayList<PMTData>();
        calc cal = new calc();
        int tableid = cal.byte2int(payload_temp, 0, 8);
        int section_length = cal.byte2int(payload_temp, 12, 12);
        int pcr_pid = cal.byte2int(payload_temp, 67, 13);
        int program_info_length = cal.byte2int(payload_temp, 84, 12);
        boolean end = false;
        int cur_point = 96 + program_info_length * 8;
        if ((cur_point > section_length * 8 - 1) || (cur_point > payload_temp.length * 8 - 11)) {
            end = true;
        }
        while (end != true) {
            if (cal.byte2int(payload_temp, cur_point + 8, 3) == 7 && cal.byte2int(payload_temp, cur_point + 24, 4) == 15 && payload_temp.length * 8 > cur_point + 40) {
                int pmt_stream_type = cal.byte2int(payload_temp, cur_point, 8);
                int elementary_PID = cal.byte2int(payload_temp, cur_point + 11, 13);
                //System.out.println(Integer.toString(cur_point)+" :  "+Integer.toString(section_length*8));
                int es_length = cal.byte2int(payload_temp, cur_point + 28, 12);
                /*if (pmt_stream_type==0x02){
                Descriptor des=new Descriptor();
                Object a=des.getDescriptors(payload_temp.substring(cur_point + 40,cur_point + 40+es_length*8));
                }else if(pmt_stream_type==0x0f){
                Descriptor des=new Descriptor();
                Object a=des.getDescriptors(payload_temp.substring(cur_point + 40,cur_point + 40+es_length*8));
                }*/


                PMTData pmtd = new PMTData();
                if ((pmt_stream_type == 0x02) || (pmt_stream_type == 0x0f)||(pmt_stream_type == 0x06)) {
                    pmtd.Stream_Type = pmt_stream_type;
                    pmtd.Program_Table = PAT_TABLE;
                    pmtd.Elementary_PID = elementary_PID;
                    pmtd.PCR_PID = pcr_pid;
                    pmt_t.add(pmtd);
                }
                cur_point = cur_point + 40 + es_length * 8;
                //System.out.println(Integer.toString(cur_point)+" :  "+Integer.toString(section_length*8));
                if ((cur_point > section_length * 8 - 1) || (cur_point > payload_temp.length * 8 - 11)) {
                    end = true;
                }
                if (payload_temp.length * 8 < cur_point + 40){
                    end = true;
                }
            } else {
                end = true;
            }
        }
        return pmt_t;
    }

    public ArrayList<EITData> readEIT(byte[] ts) {
        String payload_temp = getPayload(ts);
        int tableid = TSString2Int(payload_temp, 0, 8);
        int section_length = TSString2Int(payload_temp, 12, 12);
        int program_number = TSString2Int(payload_temp, 24, 16);
        boolean current_next_indicator = (TSString2Int(payload_temp, 47, 1) == 1);
        int section_number = TSString2Int(payload_temp, 48, 8);
        int curpoint = 112;
        ArrayList<EITData> ret = new ArrayList<EITData>();
        while (curpoint < 24 + section_length * 8 - 32) {
            EITData eitd = new EITData();
            eitd.current_newt_indicator = current_next_indicator;
            eitd.event_id = TSString2Int(payload_temp, curpoint, 16);
            eitd.program_number = program_number;
            eitd.section_number = section_number;
            int des_len = TSString2Int(payload_temp, curpoint + 84, 12);
            Descriptor des = new Descriptor();
            eitd.descriptors = des.getDescriptors(payload_temp.substring(curpoint + 96, curpoint + 84 + des_len * 8));
            ret.add(eitd);
            curpoint = curpoint + 84 + des_len * 8;
        }
        return ret;
    }

    private int TSString2Int(String s, int begin, int length) {
        String st = s.substring(begin, begin + length);
        int i = Integer.parseInt(st, 2);
        return i;
    }

    public byte[] splitPAT_byte(byte[] ts, int p_table) {
        /**
         *
         * p_tableで指定された番組テーブルのみを取り出すPATを作る。
         */
        byte[] tbb = new byte[ts.length - 4];
        System.arraycopy(ts, 4, tbb, 0, tbb.length);
        if (bPAT_payload != null) {
            if (Arrays.equals(tbb, bPAT_payload)) {
                byte[] retb = new byte[188];
                System.arraycopy(ts, 0, retb, 0, 4);
                System.arraycopy(bPAT_payload, 0, retb, 4, 184);
                return retb;
            }
        }
        calc cal = new calc();
        header_byte = cal.byte2subbyte(ts, 0, 4);
        byte[] pointer_byte = cal.byte2subbyte(ts, 4, 1);
        payload_byte = cal.byte2subbyte(ts, 4, ts.length - 4);
        starter = cal.byte2int(ts, 0, 8);
        boolean begin_payload_unit = cal.byte2int(ts, 9, 1) == 1;
        transporterror = cal.byte2int(ts, 8, 1);
        payloadstart = cal.byte2int(ts, 9, 1);
        transport_priority = cal.byte2int(ts, 10, 1);
        PID = cal.byte2int(ts, 11, 13);
        adaptation_field = cal.byte2int(ts, 26, 2);
        continuity_counter = cal.byte2int(ts, 28, 4);
        if (adaptation_field == 1) {
            if (begin_payload_unit) {
                pointer_field = cal.byte2int(ts, 32, 8);
                if ((ts.length - 5 - pointer_field) < (5 + pointer_field)) {
                    payload_byte = null;
                } else {
                    payload_byte = cal.byte2subbyte(ts, 5 + pointer_field, ts.length - 5 - pointer_field);
                }
            } else {
                payload_byte = cal.byte2subbyte(ts, 4, ts.length - 4);
            }
        } else if (adaptation_field == 3) {
            adaptation_length = cal.byte2int(ts, 32, 8);
            if ((adaptation_length < 184) & ((ts.length * 8 - adaptation_length * 8) > 48)) {
                adaptation_length = adaptation_length * 8;
            }
            adaptation_byte = cal.byte2subbyte(ts, 4, 1 + adaptation_length / 8);
            if (begin_payload_unit) {
                pointer_field = cal.byte2int(ts, 40 + adaptation_length, 8);
                if ((ts.length - 6 - (adaptation_length / 8) - pointer_field) < (6 + (adaptation_length / 8) + pointer_field)) {
                    payload_byte = null;
                } else {
                    payload_byte = cal.byte2subbyte(ts, 6 + (adaptation_length / 8) + pointer_field, ts.length - 6 - (adaptation_length / 8) - pointer_field);
                }
            } else {
                payload_byte = cal.byte2subbyte(ts, 5 + adaptation_length / 8, ts.length - 5 - adaptation_length / 8);
            }
        } else {
            payload_byte = null;
        }
        if ((PID == 0) && (begin_payload_unit) && (payload_byte != null)) {
            byte[] new_pointer=new byte[1];
            new_pointer[0]=0;
            if (isPAT(payload_byte)){
                //showPAT(ts);
                payload_byte = makePAT_byte(new_pointer, payload_byte, p_table);
                if (payload_byte.length>0){
                    bPAT_payload = payload_byte;
                }
            }
        }
        if ((payload_byte != null)&& (begin_payload_unit)) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(ts.length);
            baos.write(header_byte, 0, header_byte.length);
            baos.write(pointer_byte, 0, pointer_byte.length);
            baos.write(payload_byte, 0, payload_byte.length);
            for (int ir = 0; ir < 188-baos.size(); ir++) {
                baos.write(0xFF);
            }
            
            //showPAT(baos.toByteArray());
            return baos.toByteArray();
        } else {
            return null;
        }
    }

    private byte[] makePAT_byte(byte[] pointer_field, byte[] payload_temp, int Table) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(payload_temp.length);
        int sectionlength;
        calc cal = new calc();
        sectionlength = cal.byte2int(payload_temp, 12, 12); //-40-32;
        int patnum = sectionlength * 8 - 72;
        baos.write(payload_temp, 0, 1);
        int new_section_length = (2 * 32 + 32 + 40) / 8;
        baos.write(cal.joinByte((byte) cal.byte2int(payload_temp, 8, 4), (byte) (new_section_length & 0xF00), 4));
        baos.write((byte) (new_section_length & 0xFF));
        baos.write(payload_temp, 3, 5);
        patnum = patnum / 32;
        int nowt = 8;
        boolean alreadyadd=false;
        for (int i = 0; i < patnum; i++) {
            int[] pat = new int[2];
            pat[0] = cal.byte2int(payload_temp, 64 + 32 * i, 16);
            pat[1] = cal.byte2int(payload_temp, 32 * i + 64 + 19, 13);
            if (pat[0] == 0) {
                baos.write(payload_temp, 8 + 4 * i, 4);
                nowt = nowt + 4;
            } else if ((pat[0] == Table)&&(alreadyadd==false)) {
                baos.write(payload_temp, 8 + 4 * i, 4);
                nowt = nowt + 4;
                alreadyadd=true;
            }
        }
        ByteArrayOutputStream baoscrc = new ByteArrayOutputStream(nowt + 1);
        baoscrc.write(pointer_field[0]);
        baoscrc.write(baos.toByteArray(), 0, baos.size());
        byte[] crc = cal.getCRC32_byte(baoscrc.toByteArray(), 1);
        //byte[] crc = getCRC32_byte(baoscrc.toByteArray(), 1);
        baos.write(crc, 0, crc.length);
        int ill3 = payload_temp.length - baos.size();
        for (int ir = 0; ir < ill3; ir++) {
            baos.write(0xFF);
        }
        return baos.toByteArray();
    }
    public boolean isPAT(byte[] byte_tmp){
        calc cal=new calc();
        if ((cal.byte2int(byte_tmp,0,8)==0)&&(cal.byte2int(byte_tmp,9,3)==3)&&(cal.byte2int(byte_tmp, 40, 2)==3)){
            return true;
        }else{
            return false;
        }
    }
    public boolean isPMT(byte[] byte_tmp){
        calc cal=new calc();
        if ((cal.byte2int(byte_tmp,9,3)==3)&&(cal.byte2int(byte_tmp, 40, 2)==3)&&(cal.byte2int(byte_tmp,64,3)==3)&&(cal.byte2int(byte_tmp,80,4)==15)){
            return true;
        }else{
            return false;
        }
    }
    private String getCRC32(String s) {
        return getCRC32(String2Byte(s), 1);
    }

    private String getCRC32(byte[] data, int offset) {
        // x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
        int[] g = {1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1};
        int[] shift_reg = new int[32];
        long crc = 0;
        byte crc32[] = new byte[4];

        // Initialize shift register's to '1'
        java.util.Arrays.fill(shift_reg, 1);

        // Calculate nr of data bits, summa of bits
        int nr_bits = (data.length - offset) * 8;

        for (int bit_count = 0, bit_in_byte = 0, data_bit; bit_count < nr_bits; bit_count++) {
            // Fetch bit from bitstream
            data_bit = (data[offset] & 0x80 >>> (bit_in_byte++)) != 0 ? 1 : 0;

            if ((bit_in_byte &= 7) == 0) {
                offset++;
            }

            // Perform the shift and modula 2 addition
            data_bit ^= shift_reg[31];

            for (int i = 31; i > 0; i--) {
                shift_reg[i] = g[i] == 1 ? (shift_reg[i - 1] ^ data_bit) : shift_reg[i - 1];
            }

            shift_reg[0] = data_bit;
        }

        for (int i = 0; i < 32; i++) {
            crc = ((crc << 1) | (shift_reg[31 - i]));
        }

        for (int i = 0; i < 4; i++) {
            crc32[i] = (byte) (0xFF & (crc >>> ((3 - i) * 8)));
        }
        String s = Long2String(crc, 32);
        return s;
    }

    private byte[] getCRC32_byte(byte[] data, int offset) {
        // x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
        int[] g = {1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1};
        int[] shift_reg = new int[32];
        long crc = 0;
        byte crc32[] = new byte[4];

        // Initialize shift register's to '1'
        java.util.Arrays.fill(shift_reg, 1);

        // Calculate nr of data bits, summa of bits
        int nr_bits = (data.length - offset) * 8;

        for (int bit_count = 0, bit_in_byte = 0, data_bit; bit_count < nr_bits; bit_count++) {
            // Fetch bit from bitstream
            data_bit = (data[offset] & 0x80 >>> (bit_in_byte++)) != 0 ? 1 : 0;

            if ((bit_in_byte &= 7) == 0) {
                offset++;
            }

            // Perform the shift and modula 2 addition
            data_bit ^= shift_reg[31];

            for (int i = 31; i > 0; i--) {
                shift_reg[i] = g[i] == 1 ? (shift_reg[i - 1] ^ data_bit) : shift_reg[i - 1];
            }

            shift_reg[0] = data_bit;
        }

        for (int i = 0; i < 32; i++) {
            crc = ((crc << 1) | (shift_reg[31 - i]));
        }

        for (int i = 0; i < 4; i++) {
            crc32[i] = (byte) (0xFF & (crc >>> ((3 - i) * 8)));
        }
        return crc32;
    }

    private String addzero(int num) {
        switch (num) {
            case 0:
                return "";
            case 1:
                return "0";
            case 2:
                return "00";
            case 3:
                return "000";
            case 4:
                return "0000";
            case 5:
                return "00000";
            case 6:
                return "000000";
            case 7:
                return "0000000";
            case 8:
                return "00000000";
            default:
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < num; i++) {
                    sb.append("0");
                }
                return sb.toString();
        }
    }

    private String byte2String2(byte[] b) {
        int bl = b.length;
        bl = bl - bl % 8;
        bl = bl / 8;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bl; i++) {
            long retl = 0;
            for (int j = 0; j < 8; j++) {
                retl = retl << 8;
                int ri = b[i * 8 + j] & 0xFF;
                retl = retl + ri;
            }
            sb.append(Long2String(retl, 64));
        }
        int bl2 = b.length % 8;
        bl2 = (bl2 - bl2 % 4) / 4;
        for (int i = 0; i < bl2; i++) {
            int reti = 0;
            for (int j = 0; j < 4; j++) {
                reti = reti << 8;
                reti = reti + (b[bl * 8 + 4 * i + j] & 0xFF);
            }
            sb.append(Int2String(reti, 32));
        }
        for (int i = 0; i < (b.length % 8) % 4; i++) {
            sb.append(Int2String(b[bl * 8 + bl2 * 4 + i] & 0xFF, 8));
        }
        return sb.toString();
    }

    private String Int2String(int num, int length) {
        String ret = Integer.toBinaryString(num);
        if (ret.length() < length) {
            int it = length - ret.length();
            for (int i = 0; i < it; i++) {
                ret = "0" + ret;
            }
        }
        return ret;
    }

    private String Long2String(long num, int length) {
        String ret = Long.toBinaryString(num);
        if (ret.length() < length) {
            int it = length - ret.length();
            for (int i = 0; i < it; i++) {
                ret = "0" + ret;
            }
        }
        return ret;
    }

    private byte[] String2Byte(String ts) {
        //StringBuffer sb=new StringBuffer(ts);
        int len = ts.length() - ts.length() % 8;
        len = len / 8;
        byte[] ret = new byte[len];
        for (int i = 0; i < len; i++) {
            String tet = ts.substring(i * 8, i * 8 + 8);
            int itt = TSString2Int(tet, 0, 8);
            ret[i] = (byte) itt;
        }
        return ret;
    }

    public ArrayList<PATData> getPAT() {
        return pat_list_all;
    }

    public void setPAT(ArrayList<PATData> pat) {
        pat_list_now = pat;
        pat_list_all = pat;
    }

    public ArrayList<PMTData> getPMT() {
        return pmt_list;
    }

    public void setPMT(ArrayList<PMTData> pmt) {
        pmt_list = pmt;
    }

    public int getPID() {
        return PID;
    }

    public String getPayload(byte[] ts) {
        /**
         * 188バイトのtsから読み出したbyteを与える
         */
        String tsbyte = byte2String2(ts);
        //header = tsbyte.substring(0, 31);
        String ret_payload = "";
        //starter = TSString2Int(tsbyte, 0, 8);
        //transporterror = TSString2Int(tsbyte, 8, 1);
        //payloadstart = TSString2Int(tsbyte, 9, 1);
        //transport_priority = TSString2Int(tsbyte, 10, 1);
        int pid = TSString2Int(tsbyte, 11, 13);
        int af = TSString2Int(tsbyte, 26, 2);
        //continuity_counter = TSString2Int(tsbyte, 28, 4);
        if (pid != 8191) {
            if (af == 1) {
                ret_payload = tsbyte.substring(40);
            } else if (af == 3) {
                int al = TSString2Int(tsbyte, 32, 8);
                if ((al < 184) & ((tsbyte.length() - al * 8) > 48)) {
                    al = al * 8;
                }
                ret_payload = tsbyte.substring(48 + al);
            }
        }
        return ret_payload;
    }

    public byte[] getPayload_byte(byte[] ts) {
        /**
         * 188バイトのtsから読み出したbyteを与える
         */
        calc cal = new calc();
        String tsbyte = byte2String2(ts);
        //header = tsbyte.substring(0, 31);
        byte[] retb = null;
        //starter = TSString2Int(tsbyte, 0, 8);
        //transporterror = TSString2Int(tsbyte, 8, 1);
        //payloadstart = TSString2Int(tsbyte, 9, 1);
        //transport_priority = TSString2Int(tsbyte, 10, 1);
        int pid = cal.byte2int(ts, 11, 13);
        int af = cal.byte2int(ts, 26, 2);
        //continuity_counter = TSString2Int(tsbyte, 28, 4);
        if (pid != 8191) {
            if (af == 1) {
                retb = cal.byte2subbyte(ts, 5, ts.length - 5);
            } else if (af == 3) {
                int al = cal.byte2int(ts, 32, 8);
                if ((al < 184) & ((ts.length * 8 - al * 8) > 48)) {
                    al = al * 8;
                }
                retb = cal.byte2subbyte(ts, 6 + al / 8, ts.length - 6 - al / 8);
            }
        }
        return retb;
    }

    public ArrayList<PMTData> readPMTglobal_byte(byte[] ts, int TABLE_NUM) {
        byte[] payloadt = getPayload_byte(ts);
        return readPMT_byte(payloadt, TABLE_NUM);
    }

    public void showPAT(byte[] ts){
        calc c=new calc();
        showPAT(c.byte2String2(ts));
    }
    public void showPAT(String ts) {
        System.out.println("先頭:" + ts.substring(0, 8));
        System.out.println("" + ts.substring(8, 11));
        System.out.println("PID:" + ts.substring(11, 24));
        System.out.println("" + ts.substring(24, 32));
        System.out.println("Adap_Len:" + ts.substring(32, 40));
        System.out.println("TableID:" + ts.substring(40, 48));
        System.out.println("" + ts.substring(48, 52));
        System.out.println("len : " + ts.substring(52, 64) + "//" + Integer.toString(Integer.parseInt(ts.substring(52, 64), 2)));
        System.out.println("TS ID:" + ts.substring(64, 80));
        System.out.println("11:" + ts.substring(80, 82));
        System.out.println("" + ts.substring(82, 104));
        for (int i = 0; i < 10; i++) {
            System.out.println(Integer.toString(i) + " : BroadNum:" + ts.substring(104 + 32 * i, 120 + 32 * i)+" (0x"+Integer.toHexString(Integer.parseInt(ts.substring(104 + 32 * i, 120 + 32 * i), 2))+") 111:"+ ts.substring(120 + 32 * i, 123 + 32 * i)+" Net/PMT PID :"+ ts.substring(123 + 32 * i, 136 + 32 * i)+" (0x"+Integer.toHexString(Integer.parseInt(ts.substring(123 + 32 * i, 136 + 32 * i), 2))+")");
        }
        System.out.println("Length:" + Integer.toString(ts.length()));
    }
}
