MPEG2/TS 获取Video PID

从PMT表中获取Video PID的函数代码

 

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

#define MAKE_PID(p) (((p[0]<<8) + p[1]) & 0x1fff)
#define MAKE_WORD(h, l) (((h) << 8) | (l))

 

Little endian 的结构定义

typedef struct {
  unsigned stream_type  :8;

  unsigned elementary_PID_high :5;
  unsigned    :3;

  unsigned elementary_PID_low :8;

  unsigned ES_info_length_high :4;
  unsigned    :4;

  unsigned ES_info_length_low :8;
}MpegPmtStream_t;

 

typedef struct {
  unsigned table_id   :8;

  unsigned section_length_high  :4;
  unsigned     :2;
  unsigned    :1;
  unsigned section_syntax_indicator :1;
  
  unsigned section_length_low  :8;
  
  unsigned program_number_high  :8;

  unsigned program_number_low  :8;

  unsigned current_next_indicator :1;
  unsigned version_number  :5;
  unsigned     :2;

  unsigned section_number  :8;

  unsigned last_section_number  :8;
  
  unsigned PCR_PID_high   :5;
  unsigned    :3;

  unsigned PCR_PID_low   :8;
  
  unsigned program_info_length_high :4;
  unsigned    :4;
  
  unsigned program_info_length_low :8;
}MpegPmtHeader_t;

 

[html]  view plain  copy
  1. ushort GetVideoPid(const char* filename)  
  2. {  
  3. #define TSPACKET_SIZE     188   
  4. #define CRC_SIZE          4  
  5.     ushort pid, pmtpid, videopid = 0;  
  6.     uchar buf[TSPACKET_SIZE];  
  7.     uchar* p = buf;  
  8.     MpegPmtHeader_t* header;  
  9.     MpegPmtStream_t* stream;  
  10.     FILE*  fp;  
  11.     int pos = 0;  
  12.     ushort section_len;  
  13.       
  14.     pmtpid = GetPmtPid(filename);  
  15.     if (pmtpid == 0) {  
  16.         fprintf(stderr, "Unable to get PMT PID!\n");  
  17.         return 0;  
  18.     }  
  19.   
  20.     fp = fopen(filename, "rb");  
  21.     if (fp == NULL) {  
  22.         fprintf(stderr, "Failed to open the file %s: %s\n", filename, strerror(errno));  
  23.         return 0;  
  24.     }  
  25.   
  26.   
  27.     while (fread(buf, 1, TSPACKET_SIZE, fp) == TSPACKET_SIZE) {  
  28.         if (buf[0] != MPEG_TS_SYNC_BYTE) { // @MPEG_TS_SYNC_BYTE = 0x47  
  29.             fprintf(stderr, "No sync byte!\n");  
  30.             break;  
  31.         }  
  32.   
  33.         p = buf;  
  34.         pid = MAKE_PID((p+1));  
  35.         if( pid != pmtpid ) {  
  36.             // Not a  PMT packet  
  37.             continue;  
  38.         }  
  39.   
  40.         // payload_unit_start_indicator 必须为1  
  41.         if (!(buf[1] >> 6 & 0x01)) {  
  42.             fprintf(stderr, "No payload_unit_start_indicator!\n");  
  43.             continue;  
  44.         }  
  45.   
  46.         // Skip the TS header  
  47.         p += MPEG_TS_HEADER_SIZE; //@MPEG_TS_HEADER_SIZE = 4  
  48.   
  49.         // Adaptation field exist or not  
  50.         if ((buf[3] >> 4 & 0x03) & 0x2) {  
  51.             fprintf(stderr, "Adaptation field exist\n");  
  52.             p += 1 + p[0];  // p[0]是Adaptation field长度, 1为长度域  
  53.         }  
  54.   
  55.         // p[0] 为 Point field长度, 1为Point field  
  56.         p += 1 + p[0];  
  57.   
  58.         // Now p 指向 PMT表头  
  59.         header = (MpegPmtHeader_t*)p;  
  60.         pos +=  sizeof(MpegPmtHeader_t);   
  61.         pos += MAKE_WORD(header->program_info_length_high, header->program_info_length_low);;  
  62.   
  63.         // Parse stream table  
  64.         section_len = MAKE_WORD(header->section_length_high, header->section_length_low);  
  65.         while (pos < (section_len + 2) - CRC_SIZE) {  
  66.             stream = (MpegPmtStream_t*)(p + pos);  
  67.             // @MPEG_TS_STREAM_TYPE_VIDEO_2 = 0x02  
  68.             if (stream->stream_type == MPEG_TS_STREAM_TYPE_VIDEO_2) {  
  69.                 videopid = MAKE_WORD(stream->elementary_PID_high, stream->elementary_PID_low);  
  70.                 break;  
  71.             }  
  72.             // @MPEG_PMT_STREAM_HEADER_SIZE = 5  
  73.             pos +=  MPEG_PMT_STREAM_HEADER_SIZE   
  74.                 + MAKE_WORD(stream->ES_info_length_high, stream->ES_info_length_low);  
  75.         }  
  76.     }  
  77.   
  78.     fclose(fp);  
  79.     return videopid;  
  80. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值