2 * jTsSplitter - java based mpeg2ts splitter.
3 * Copyright (C) 2009-2010 Yukikaze
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import jtssplitter.data.PATData;
10 import jtssplitter.data.PMTData;
11 import jtssplitter.data.Descriptor;
12 import jtssplitter.data.EITData;
13 import java.io.ByteArrayOutputStream;
19 public class Mpeg2TSPacket {
23 public String payload;
24 public String adaptation;
25 public byte[] header_byte;
26 public byte[] payload_byte;
27 public byte[] adaptation_byte;
28 public byte[] bPAT_payload = null;
29 //private ArrayList<TsDate> date=new ArrayList<TsDate>();
30 //date.add(new TsDate("Starter"))
32 private int starter;//0-7
33 private int transporterror;//本TSパケットの誤りを示す 1bit 8
34 private int payloadstart;//セクションの先頭バイトが入っているかどうか1bit 9
35 private int transport_priority;//1bit 10
36 private int PID = -1;//tsパケットの種類 13bit 11-23
37 private int transport_scrambled;//2bit 00is " not scrambled" 24-25
38 private int adaptation_field;//2bit 26-27 01:adaptation fieldなしでおk 10は絶対いる 11はペイロードはアダプテーションに続く00は予約
39 private int continuity_counter;//連続性(PIDごとの通し番号) 4bit 28-31
40 //ここからアダプテーションフィールド(最後まで)
41 private int adaptation_length;//8bit 32-39
42 private int discontinuity;//1bit
43 private int random_access;//1bit ランダムアクセスの開始場所となる
44 private int ES_priority;//1bit プライオリティ
45 private int five_flag;//5bit
46 private ArrayList<PATData> pat_list_now = new ArrayList<PATData>();//[0]:番組番号 [1]:PMT PID
47 private ArrayList<PATData> pat_list_all = new ArrayList<PATData>();
48 private ArrayList<PMTData> pmt_list = new ArrayList<PMTData>();//[0]番組番号 [1]テーブルID
49 private int pointer_field;//8bit adaptation fieldの次?
50 private String payload_s;
54 private int staffing_byte;//
56 public Mpeg2TSPacket() {
59 public int getPIDFirst_byte(byte[] ts) {
60 calc cal = new calc();
61 byte[] b = new byte[2];
64 return cal.byte2int(b, 3, 13);
65 //return cal.byte2int(ts,11,13);
68 public void readTS_byte(byte[] ts) {
70 * 188バイトのtsから読み出したbyteを与える
72 calc cal = new calc();
73 String tsbyte = byte2String2(ts);
74 boolean begin_payload_unit = cal.byte2int(ts, 9, 1) == 1;
75 //header = tsbyte.substring(0, 31);
76 payload = tsbyte.substring(32);
77 //starter = TSString2Int(tsbyte, 0, 8);
78 //transporterror = TSString2Int(tsbyte, 8, 1);
79 //payloadstart = TSString2Int(tsbyte, 9, 1);
80 //transport_priority = TSString2Int(tsbyte, 10, 1);
81 //PID = TSString2Int(tsbyte, 11, 13);
82 PID = cal.byte2int(ts, 11, 13);
83 adaptation_field = cal.byte2int(ts, 26, 2);
84 //continuity_counter = TSString2Int(tsbyte, 28, 4);
87 if (adaptation_field == 1) {
88 if (begin_payload_unit) {
89 pointer_field = cal.byte2int(ts, 32, 8);
90 if ((ts.length - 5 - pointer_field) < (5 + pointer_field)) {
93 payload_byte = cal.byte2subbyte(ts, 5 + pointer_field, ts.length - 5 - pointer_field);
96 payload_byte = cal.byte2subbyte(ts, 4, ts.length - 4);
98 } else if (adaptation_field == 3) {
99 adaptation_length = cal.byte2int(ts, 32, 8);
100 if ((adaptation_length < 184) & ((ts.length * 8 - adaptation_length * 8) > 48)) {
101 adaptation_length = adaptation_length * 8;
103 adaptation_byte = cal.byte2subbyte(ts, 4, 1 + adaptation_length / 8);
104 if (begin_payload_unit) {
105 pointer_field = cal.byte2int(ts, 40 + adaptation_length, 8);
106 if ((ts.length - 6 - (adaptation_length / 8) - pointer_field) < (6 + (adaptation_length / 8) + pointer_field)) {
109 payload_byte = cal.byte2subbyte(ts, 6 + (adaptation_length / 8) + pointer_field, ts.length - 6 - (adaptation_length / 8) - pointer_field);
112 payload_byte = cal.byte2subbyte(ts, 5 + adaptation_length / 8, ts.length - 5 - adaptation_length / 8);
118 if (payload_byte != null) {
119 if ((PID == 0) && (begin_payload_unit)) {
120 //cal.showPAT(tsbyte);
121 if (isPAT(payload_byte)){
122 pat_list_now = readPAT_byte(payload_byte);
123 if (pat_list_now.size()>3){
124 pat_list_all=pat_list_now;
126 //pat_list_all.addAll(pat_list_now);
129 for (int i = 0; i < pat_list_now.size(); i++) {
130 if ((PID == pat_list_now.get(i).PID) && (PID != 0)) {
131 pmt_list.addAll(readPMT_byte(payload_byte, pat_list_now.get(i).Program_TABLE));
138 private ArrayList<PATData> readPAT_byte(byte[] payload_temp) {
140 * payloadの文字列を入力して[intテーブル,int PID]のArrayListを返す。
144 calc cal = new calc();
145 ArrayList program_number = new ArrayList();
146 tableid = cal.byte2int(payload_temp, 0, 8);
147 sectionlength = cal.byte2int(payload_temp, 12, 12);//-40-32;
148 int patnum = sectionlength * 8 - 72;
149 patnum = patnum / 32;
150 for (int i = 0; i < patnum; i++) {
151 if (payload_temp.length * 8 > 64 + 32 * i + 96) {
152 if (cal.byte2int(payload_temp, 64 + 32 * i + 16, 3) == 7) {
153 PATData patd = new PATData();
154 patd.Program_TABLE = cal.byte2int(payload_temp, 64 + 32 * i, 16);
155 patd.PID = cal.byte2int(payload_temp, 32 * i + 64 + 19, 13);
156 program_number.add(patd);
160 return program_number;
162 private ArrayList<PMTData> readPMT_byte(byte[] payload_temp, int PAT_TABLE) {
163 ArrayList<PMTData> pmt_t = new ArrayList<PMTData>();
164 calc cal = new calc();
165 int tableid = cal.byte2int(payload_temp, 0, 8);
166 int section_length = cal.byte2int(payload_temp, 12, 12);
167 int pcr_pid = cal.byte2int(payload_temp, 67, 13);
168 int program_info_length = cal.byte2int(payload_temp, 84, 12);
170 int cur_point = 96 + program_info_length * 8;
171 if ((cur_point > section_length * 8 - 1) || (cur_point > payload_temp.length * 8 - 11)) {
174 while (end != true) {
175 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) {
176 int pmt_stream_type = cal.byte2int(payload_temp, cur_point, 8);
177 int elementary_PID = cal.byte2int(payload_temp, cur_point + 11, 13);
178 //System.out.println(Integer.toString(cur_point)+" : "+Integer.toString(section_length*8));
179 int es_length = cal.byte2int(payload_temp, cur_point + 28, 12);
180 /*if (pmt_stream_type==0x02){
181 Descriptor des=new Descriptor();
182 Object a=des.getDescriptors(payload_temp.substring(cur_point + 40,cur_point + 40+es_length*8));
183 }else if(pmt_stream_type==0x0f){
184 Descriptor des=new Descriptor();
185 Object a=des.getDescriptors(payload_temp.substring(cur_point + 40,cur_point + 40+es_length*8));
189 PMTData pmtd = new PMTData();
190 if ((pmt_stream_type == 0x02) || (pmt_stream_type == 0x0f)||(pmt_stream_type == 0x06)) {
191 pmtd.Stream_Type = pmt_stream_type;
192 pmtd.Program_Table = PAT_TABLE;
193 pmtd.Elementary_PID = elementary_PID;
194 pmtd.PCR_PID = pcr_pid;
197 cur_point = cur_point + 40 + es_length * 8;
198 //System.out.println(Integer.toString(cur_point)+" : "+Integer.toString(section_length*8));
199 if ((cur_point > section_length * 8 - 1) || (cur_point > payload_temp.length * 8 - 11)) {
202 if (payload_temp.length * 8 < cur_point + 40){
212 public ArrayList<EITData> readEIT(byte[] ts) {
213 String payload_temp = getPayload(ts);
214 int tableid = TSString2Int(payload_temp, 0, 8);
215 int section_length = TSString2Int(payload_temp, 12, 12);
216 int program_number = TSString2Int(payload_temp, 24, 16);
217 boolean current_next_indicator = (TSString2Int(payload_temp, 47, 1) == 1);
218 int section_number = TSString2Int(payload_temp, 48, 8);
220 ArrayList<EITData> ret = new ArrayList<EITData>();
221 while (curpoint < 24 + section_length * 8 - 32) {
222 EITData eitd = new EITData();
223 eitd.current_newt_indicator = current_next_indicator;
224 eitd.event_id = TSString2Int(payload_temp, curpoint, 16);
225 eitd.program_number = program_number;
226 eitd.section_number = section_number;
227 int des_len = TSString2Int(payload_temp, curpoint + 84, 12);
228 Descriptor des = new Descriptor();
229 eitd.descriptors = des.getDescriptors(payload_temp.substring(curpoint + 96, curpoint + 84 + des_len * 8));
231 curpoint = curpoint + 84 + des_len * 8;
236 private int TSString2Int(String s, int begin, int length) {
237 String st = s.substring(begin, begin + length);
238 int i = Integer.parseInt(st, 2);
242 public byte[] splitPAT_byte(byte[] ts, int p_table) {
245 * p_tableで指定された番組テーブルのみを取り出すPATを作る。
247 byte[] tbb = new byte[ts.length - 4];
248 System.arraycopy(ts, 4, tbb, 0, tbb.length);
249 if (bPAT_payload != null) {
250 if (Arrays.equals(tbb, bPAT_payload)) {
251 byte[] retb = new byte[188];
252 System.arraycopy(ts, 0, retb, 0, 4);
253 System.arraycopy(bPAT_payload, 0, retb, 4, 184);
257 calc cal = new calc();
258 header_byte = cal.byte2subbyte(ts, 0, 4);
259 byte[] pointer_byte = cal.byte2subbyte(ts, 4, 1);
260 payload_byte = cal.byte2subbyte(ts, 4, ts.length - 4);
261 starter = cal.byte2int(ts, 0, 8);
262 boolean begin_payload_unit = cal.byte2int(ts, 9, 1) == 1;
263 transporterror = cal.byte2int(ts, 8, 1);
264 payloadstart = cal.byte2int(ts, 9, 1);
265 transport_priority = cal.byte2int(ts, 10, 1);
266 PID = cal.byte2int(ts, 11, 13);
267 adaptation_field = cal.byte2int(ts, 26, 2);
268 continuity_counter = cal.byte2int(ts, 28, 4);
269 if (adaptation_field == 1) {
270 if (begin_payload_unit) {
271 pointer_field = cal.byte2int(ts, 32, 8);
272 if ((ts.length - 5 - pointer_field) < (5 + pointer_field)) {
275 payload_byte = cal.byte2subbyte(ts, 5 + pointer_field, ts.length - 5 - pointer_field);
278 payload_byte = cal.byte2subbyte(ts, 4, ts.length - 4);
280 } else if (adaptation_field == 3) {
281 adaptation_length = cal.byte2int(ts, 32, 8);
282 if ((adaptation_length < 184) & ((ts.length * 8 - adaptation_length * 8) > 48)) {
283 adaptation_length = adaptation_length * 8;
285 adaptation_byte = cal.byte2subbyte(ts, 4, 1 + adaptation_length / 8);
286 if (begin_payload_unit) {
287 pointer_field = cal.byte2int(ts, 40 + adaptation_length, 8);
288 if ((ts.length - 6 - (adaptation_length / 8) - pointer_field) < (6 + (adaptation_length / 8) + pointer_field)) {
291 payload_byte = cal.byte2subbyte(ts, 6 + (adaptation_length / 8) + pointer_field, ts.length - 6 - (adaptation_length / 8) - pointer_field);
294 payload_byte = cal.byte2subbyte(ts, 5 + adaptation_length / 8, ts.length - 5 - adaptation_length / 8);
299 if ((PID == 0) && (begin_payload_unit) && (payload_byte != null)) {
300 byte[] new_pointer=new byte[1];
302 if (isPAT(payload_byte)){
303 payload_byte = makePAT_byte(new_pointer, payload_byte, p_table);
304 if (payload_byte.length>0){
305 bPAT_payload = payload_byte;
309 if ((payload_byte != null)&& (begin_payload_unit)) {
310 ByteArrayOutputStream baos = new ByteArrayOutputStream(ts.length);
311 baos.write(header_byte, 0, header_byte.length);
312 baos.write(pointer_byte, 0, pointer_byte.length);
313 baos.write(payload_byte, 0, payload_byte.length);
314 for (int ir = 0; ir < 188-baos.size(); ir++) {
317 return baos.toByteArray();
323 private byte[] makePAT_byte(byte[] pointer_field, byte[] payload_temp, int Table) {
324 ByteArrayOutputStream baos = new ByteArrayOutputStream(payload_temp.length);
326 calc cal = new calc();
327 sectionlength = cal.byte2int(payload_temp, 12, 12); //-40-32;
328 int patnum = sectionlength * 8 - 72;
329 baos.write(payload_temp, 0, 1);
330 int new_section_length = (2 * 32 + 32 + 40) / 8;
331 baos.write(cal.joinByte((byte) cal.byte2int(payload_temp, 8, 4), (byte) (new_section_length & 0xF00), 4));
332 baos.write((byte) (new_section_length & 0xFF));
333 baos.write(payload_temp, 3, 5);
334 patnum = patnum / 32;
336 for (int i = 0; i < patnum; i++) {
337 int[] pat = new int[2];
338 pat[0] = cal.byte2int(payload_temp, 64 + 32 * i, 16);
339 pat[1] = cal.byte2int(payload_temp, 32 * i + 64 + 19, 13);
341 baos.write(payload_temp, 8 + 4 * i, 4);
343 } else if (pat[0] == Table) {
344 baos.write(payload_temp, 8 + 4 * i, 4);
349 ByteArrayOutputStream baoscrc = new ByteArrayOutputStream(nowt + 1);
350 baoscrc.write(pointer_field[0]);
351 baoscrc.write(baos.toByteArray(), 0, baos.size());
352 byte[] crc = cal.getCRC32_byte(baoscrc.toByteArray(), 1);
353 //byte[] crc = getCRC32_byte(baoscrc.toByteArray(), 1);
354 baos.write(crc, 0, crc.length);
355 int ill3 = payload_temp.length - baos.size();
356 for (int ir = 0; ir < ill3; ir++) {
359 return baos.toByteArray();
361 public boolean isPAT(byte[] byte_tmp){
363 if ((cal.byte2int(byte_tmp,0,8)==0)&&(cal.byte2int(byte_tmp,9,3)==3)&&(cal.byte2int(byte_tmp, 40, 2)==3)){
369 public boolean isPMT(byte[] byte_tmp){
371 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)){
377 private String getCRC32(String s) {
378 return getCRC32(String2Byte(s), 1);
381 private String getCRC32(byte[] data, int offset) {
382 // 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
383 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};
384 int[] shift_reg = new int[32];
386 byte crc32[] = new byte[4];
388 // Initialize shift register's to '1'
389 java.util.Arrays.fill(shift_reg, 1);
391 // Calculate nr of data bits, summa of bits
392 int nr_bits = (data.length - offset) * 8;
394 for (int bit_count = 0, bit_in_byte = 0, data_bit; bit_count < nr_bits; bit_count++) {
395 // Fetch bit from bitstream
396 data_bit = (data[offset] & 0x80 >>> (bit_in_byte++)) != 0 ? 1 : 0;
398 if ((bit_in_byte &= 7) == 0) {
402 // Perform the shift and modula 2 addition
403 data_bit ^= shift_reg[31];
405 for (int i = 31; i > 0; i--) {
406 shift_reg[i] = g[i] == 1 ? (shift_reg[i - 1] ^ data_bit) : shift_reg[i - 1];
409 shift_reg[0] = data_bit;
412 for (int i = 0; i < 32; i++) {
413 crc = ((crc << 1) | (shift_reg[31 - i]));
416 for (int i = 0; i < 4; i++) {
417 crc32[i] = (byte) (0xFF & (crc >>> ((3 - i) * 8)));
419 String s = Long2String(crc, 32);
423 private byte[] getCRC32_byte(byte[] data, int offset) {
424 // 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
425 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};
426 int[] shift_reg = new int[32];
428 byte crc32[] = new byte[4];
430 // Initialize shift register's to '1'
431 java.util.Arrays.fill(shift_reg, 1);
433 // Calculate nr of data bits, summa of bits
434 int nr_bits = (data.length - offset) * 8;
436 for (int bit_count = 0, bit_in_byte = 0, data_bit; bit_count < nr_bits; bit_count++) {
437 // Fetch bit from bitstream
438 data_bit = (data[offset] & 0x80 >>> (bit_in_byte++)) != 0 ? 1 : 0;
440 if ((bit_in_byte &= 7) == 0) {
444 // Perform the shift and modula 2 addition
445 data_bit ^= shift_reg[31];
447 for (int i = 31; i > 0; i--) {
448 shift_reg[i] = g[i] == 1 ? (shift_reg[i - 1] ^ data_bit) : shift_reg[i - 1];
451 shift_reg[0] = data_bit;
454 for (int i = 0; i < 32; i++) {
455 crc = ((crc << 1) | (shift_reg[31 - i]));
458 for (int i = 0; i < 4; i++) {
459 crc32[i] = (byte) (0xFF & (crc >>> ((3 - i) * 8)));
464 private String addzero(int num) {
485 StringBuffer sb = new StringBuffer();
486 for (int i = 0; i < num; i++) {
489 return sb.toString();
493 private String byte2String2(byte[] b) {
497 StringBuffer sb = new StringBuffer();
498 for (int i = 0; i < bl; i++) {
500 for (int j = 0; j < 8; j++) {
502 int ri = b[i * 8 + j] & 0xFF;
505 sb.append(Long2String(retl, 64));
507 int bl2 = b.length % 8;
508 bl2 = (bl2 - bl2 % 4) / 4;
509 for (int i = 0; i < bl2; i++) {
511 for (int j = 0; j < 4; j++) {
513 reti = reti + (b[bl * 8 + 4 * i + j] & 0xFF);
515 sb.append(Int2String(reti, 32));
517 for (int i = 0; i < (b.length % 8) % 4; i++) {
518 sb.append(Int2String(b[bl * 8 + bl2 * 4 + i] & 0xFF, 8));
520 return sb.toString();
523 private String Int2String(int num, int length) {
524 String ret = Integer.toBinaryString(num);
525 if (ret.length() < length) {
526 int it = length - ret.length();
527 for (int i = 0; i < it; i++) {
534 private String Long2String(long num, int length) {
535 String ret = Long.toBinaryString(num);
536 if (ret.length() < length) {
537 int it = length - ret.length();
538 for (int i = 0; i < it; i++) {
545 private byte[] String2Byte(String ts) {
546 //StringBuffer sb=new StringBuffer(ts);
547 int len = ts.length() - ts.length() % 8;
549 byte[] ret = new byte[len];
550 for (int i = 0; i < len; i++) {
551 String tet = ts.substring(i * 8, i * 8 + 8);
552 int itt = TSString2Int(tet, 0, 8);
558 public ArrayList<PATData> getPAT() {
562 public void setPAT(ArrayList pat) {
567 public ArrayList<PMTData> getPMT() {
571 public void setPMT(ArrayList pmt) {
575 public int getPID() {
579 public String getPayload(byte[] ts) {
581 * 188バイトのtsから読み出したbyteを与える
583 String tsbyte = byte2String2(ts);
584 //header = tsbyte.substring(0, 31);
585 String ret_payload = "";
586 //starter = TSString2Int(tsbyte, 0, 8);
587 //transporterror = TSString2Int(tsbyte, 8, 1);
588 //payloadstart = TSString2Int(tsbyte, 9, 1);
589 //transport_priority = TSString2Int(tsbyte, 10, 1);
590 int pid = TSString2Int(tsbyte, 11, 13);
591 int af = TSString2Int(tsbyte, 26, 2);
592 //continuity_counter = TSString2Int(tsbyte, 28, 4);
595 ret_payload = tsbyte.substring(40);
596 } else if (af == 3) {
597 int al = TSString2Int(tsbyte, 32, 8);
598 if ((al < 184) & ((tsbyte.length() - al * 8) > 48)) {
601 ret_payload = tsbyte.substring(48 + al);
607 public byte[] getPayload_byte(byte[] ts) {
609 * 188バイトのtsから読み出したbyteを与える
611 calc cal = new calc();
612 String tsbyte = byte2String2(ts);
613 //header = tsbyte.substring(0, 31);
615 //starter = TSString2Int(tsbyte, 0, 8);
616 //transporterror = TSString2Int(tsbyte, 8, 1);
617 //payloadstart = TSString2Int(tsbyte, 9, 1);
618 //transport_priority = TSString2Int(tsbyte, 10, 1);
619 int pid = cal.byte2int(ts, 11, 13);
620 int af = cal.byte2int(ts, 26, 2);
621 //continuity_counter = TSString2Int(tsbyte, 28, 4);
624 retb = cal.byte2subbyte(ts, 5, ts.length - 5);
625 } else if (af == 3) {
626 int al = cal.byte2int(ts, 32, 8);
627 if ((al < 184) & ((ts.length * 8 - al * 8) > 48)) {
630 retb = cal.byte2subbyte(ts, 6 + al / 8, ts.length - 6 - al / 8);
636 public ArrayList<PMTData> readPMTglobal_byte(byte[] ts, int TABLE_NUM) {
637 byte[] payloadt = getPayload_byte(ts);
638 return readPMT_byte(payloadt, TABLE_NUM);
641 public void showPAT(String ts) {
642 System.out.println("先頭:" + ts.substring(0, 8));
643 System.out.println("" + ts.substring(8, 11));
644 System.out.println("PID:" + ts.substring(11, 24));
645 System.out.println("" + ts.substring(24, 32));
646 System.out.println("Adap_Len:" + ts.substring(32, 40));
647 System.out.println("TableID:" + ts.substring(40, 48));
648 System.out.println("" + ts.substring(48, 52));
649 System.out.println("len : " + ts.substring(52, 64) + "//" + Integer.toString(Integer.parseInt(ts.substring(52, 64), 2)));
650 System.out.println("TS ID:" + ts.substring(64, 80));
651 System.out.println("11:" + ts.substring(80, 82));
652 System.out.println("" + ts.substring(82, 104));
653 for (int i = 0; i < 10; i++) {
654 System.out.println(Integer.toString(i) + " : " + ts.substring(104 + 32 * i, 136 + 32 * i));
656 System.out.println("Length:" + Integer.toString(ts.length()));