본문 바로가기

Programming/JAVA

TS packet Reader - realize JAVA ( Postedy by H2K )




TS(Transport Stream) Packet

방송 사업자가 전송하는 stream은 TS packet으로 구성된다.


이러한 TS packet은 다음과 같은 구조로 구현되어 있다.
 

TS Packet의 중요한 Filed는 다음과 같다

  - PID : Packet 구분자로 오디오/비디오와 같은 스트림에 대해서 고유한 PID가 할 당 되므로, ES 스트림을 구분하
           는데 사용한다. 같은 프로그램의 같은 ES는 PID를 가지게 된다.

  - Sync_byte : sync_byte는 패킷의 시작점을 나타내는 0x47로 고정되어 있으며, 이 sync_byte를 이용해서 
                 스트림에서 개별 Packet을 구분해 낸다.

  - Payload_unit_start_indicator :  현재 Packet에 들어있는 데이터가 어떤 특정 논리 데이터 묶음의 시작을 
                 알려주기 위해 사용. 즉, 같은 PID를 가진 연속된 Packet 스트림에서 Payload unit start
                 indicator가 ‘1’인 Packet부터 다음 ‘1’인 Packet까지의 Packet들이 담고 있는 데이터를 묶으
                 면 하나의 논리 데이터 묶음이 된다. 여기서 논리 데이터는 주로 PES나 MPEG2 Private  
                 Section 같이 상위 프로토콜에서 규정하고 있는 데이터 구조체이다.

  - Adaptation Field : 이 영역은 두 종류 이상의 논리 데이터의 수신 동기화를 위한 시간 정보를 담고 있다. 예를
                 들어, 영상과 음성은 각각의 PID를 가진 Packet 스트림으로 전송이 되고 있기 때문에, 동기를 위한 
                 시간 정보를 보내주지 않으면 영상과 음성을 맞출 수가 없기 때문에 꼭 필요하다.


각 TS packet은 가지고 있는 PID에 의하여 하느의 stream으로 묶인다. 이렇듯 PID에 따라서 TS packet을 분석한다면 방송사들의 stream을 구별할 수 있게 된다.




간단한 PID추출 프로그램을 JAVA를 이용하여 구현해보았다.

PID를 추출하여 각각의 TS packet이 가지고 있는 PID에 따라 stream을 구별해 보았다.

/* PID packet Analyze Module */

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;


public class TSReader {	
	
        /* create PID table */
        static HashMap  table_PID = new HashMap ();	
		
        public static void main(String args[]) throws IOException{
		
                String fileName = "out.mpg";

                File file_TS = new File(fileName);
		
                DataInputStream dInStream = new DataInputStream(new FileInputStream(file_TS));
        
                this.TSPacketReader(dInStream);

                this.PrintPIDTable();  		
   	
                dInStream.close();
    		
        }
	
        /* this method is read the TS packet */
        public void TSPacketReader(DataInputStream dInStream) throws IOException{

                int pid =0;		

                /* size of TSpacket */
                byte[] packet = new byte[188];
        
                while (dInStream.read(packet) != -1) {
    			
                        /* find the start point of packet */	
                        if(packet[0] == 0x47){

                                /* find the PID (masking) */
                                pid = (packet[1] & 31) << 8;
                                pid = (packet[2] & 0xff) | pid;
    				
                                Integer cnt = null;

                                /*mapping the PID cnt*/
                                if((cnt = table_PID.get(pid)) == null){    					
                                        table_PID.put(pid, 1);
                                }else {
                                        table_PID.put(pid, cnt+1);
                                }
                        }
                }
        }

        /* this method is print the PID table */
        public void PrintPIDTable(){
                Set set = table_PID.keySet();
                Iterator keys = set.iterator();
    	
                while(keys.hasNext()){
                        int pIdName = (Integer) keys.next();
                        System.out.println("0x" + Integer.toHexString(pIdName) + " : " + 
                                                        table_PID.get(pIdName));
                }
        }
}