MPEG2/TS获取PCR PID方法

来源:互联网 发布:魔兽世界mac国服下载 编辑:程序博客网 时间:2024/05/18 03:30

一个简单的从指定MPEG2/TS文件中获取PCR PID的函数,

PMT的头结构中有PCR PID,我们首先得到PMT PID,然后分析PMT包,就可以得到PCR PID了。

GetPmtPid函数的实现见:http://blog.csdn.net/myaccella/article/details/6982596

MAKE_PID:

#define MAKE_PID(p) (((p[0]<<8) + p[1]) & 0x1fff)

 

[html] view plain copy
  1. ushort GetPcrPid(const char* filename)  
  2. {  
  3. #define TSPACKET_SIZE     188   
  4.     ushort pid, pmtpid, pcrpid = 0;  
  5.     uchar buf[TSPACKET_SIZE];  
  6.     uchar* p = buf;  
  7.     FILE*  fp;  
  8.       
  9.     pmtpid = GetPmtPid(filename);  
  10.     if (pmtpid == 0) {  
  11.         fprintf(stderr, "Unable to get PMT PID!\n");  
  12.         return 0;  
  13.     }  
  14.   
  15.     fp = fopen(filename, "rb");  
  16.     if (fp == NULL) {  
  17.         fprintf(stderr, "Failed to open the file %s: %s\n", filename, strerror(errno));  
  18.         return 0;  
  19.     }  
  20.   
  21.   
  22.     while (fread(buf, 1, TSPACKET_SIZE, fp) == TSPACKET_SIZE) {  
  23.         if (buf[0] != MPEG_TS_SYNC_BYTE) { // @MPEG_TS_SYNC_BYTE = 0x47  
  24.             fprintf(stderr, "No sync byte!\n");  
  25.             break;  
  26.         }  
  27.   
  28.         p = buf;  
  29.         pid = MAKE_PID((p+1));  
  30.         if( pid != pmtpid ) {  
  31.             // Not a  PMT packet  
  32.             continue;  
  33.         }  
  34.   
  35.         // payload_unit_start_indicator 必须为1  
  36.         if (!(buf[1] >> 6 & 0x01)) {  
  37.             fprintf(stderr, "No payload_unit_start_indicator!\n");  
  38.             continue;  
  39.         }  
  40.   
  41.         // Skip the TS header  
  42.         p += MPEG_TS_HEADER_SIZE; //@MPEG_TS_HEADER_SIZE = 4  
  43.   
  44.         // Adaptation field exist or not  
  45.         if ((buf[3] >> 4 & 0x03) & 0x2) {  
  46.             fprintf(stderr, "Adaptation field exist\n");  
  47.             p += 1 + p[0];  // p[0]是Adaptation field长度, 1为长度域  
  48.         }  
  49.   
  50.         // p[0] 为 Point field长度, 1为Point field  
  51.         p += 1 + p[0];  
  52.   
  53.         // 8 为PCR PID在PMT表头中的偏移  
  54.         p += 8;  
  55.   
  56.         // 取到的PCR PID如果是0x1fff, 则需要继续取  
  57.         pcrpid = MAKE_PID(p);  
  58.         if (pcrpid == 0x1fff) {  
  59.             pcrpid = 0;  
  60.             continue;  
  61.         }  
  62.           
  63.         break;  
  64.     }  
  65.          fclose(fp);  
  66.     return pcrpid;  
  67. }