MPEG2/TS 获取Video PID

本文介绍了如何从MPEG2/TS流的PMT表中获取Video PID,提供了GetPmtPid函数的实现链接,并展示了Little endian结构定义,包括MpegPmtStream_t和MpegPmtHeader_t结构体,用于解析PID和流信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

GetPmtPid函数的实现见:http://blog.youkuaiyun.com/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;

 

ushort GetVideoPid(const char* filename)
{
#define TSPACKET_SIZE     188 
#define CRC_SIZE          4
	ushort pid, pmtpid, videopid = 0;
	uchar buf[TSPACKET_SIZE];
	uchar* p = buf;
	MpegPmtHeader_t* header;
	MpegPmtStream_t* stream;
	FILE*  fp;
	int pos = 0;
	ushort section_len;
	
	pmtpid = GetPmtPid(filename);
	if (pmtpid == 0) {
		fprintf(stderr, "Unable to get PMT PID!\n");
		return 0;
	}

	fp = fopen(filename, "rb");
	if (fp == NULL) {
		fprintf(stderr, "Failed to open the file %s: %s\n", filename, strerror(errno));
		return 0;
	}


	while (fread(buf, 1, TSPACKET_SIZE, fp) == TSPACKET_SIZE) {
		if (buf[0] != MPEG_TS_SYNC_BYTE) { // @MPEG_TS_SYNC_BYTE = 0x47
			fprintf(stderr, "No sync byte!\n");
			break;
		}

		p = buf;
		pid = MAKE_PID((p+1));
		if( pid != pmtpid ) {
			// Not a  PMT packet
			continue;
		}

		// payload_unit_start_indicator 必须为1
		if (!(buf[1] >> 6 & 0x01)) {
			fprintf(stderr, "No payload_unit_start_indicator!\n");
			continue;
		}

		// Skip the TS header
		p += MPEG_TS_HEADER_SIZE; //@MPEG_TS_HEADER_SIZE = 4

		// Adaptation field exist or not
		if ((buf[3] >> 4 & 0x03) & 0x2) {
			fprintf(stderr, "Adaptation field exist\n");
			p += 1 + p[0];  // p[0]是Adaptation field长度, 1为长度域
		}

		// p[0] 为 Point field长度, 1为Point field
		p += 1 + p[0];

		// Now p 指向 PMT表头
        header = (MpegPmtHeader_t*)p;
		pos +=  sizeof(MpegPmtHeader_t); 
		pos += MAKE_WORD(header->program_info_length_high, header->program_info_length_low);;

		// Parse stream table
		section_len = MAKE_WORD(header->section_length_high, header->section_length_low);
		while (pos < (section_len + 2) - CRC_SIZE) {
			stream = (MpegPmtStream_t*)(p + pos);
			// @MPEG_TS_STREAM_TYPE_VIDEO_2 = 0x02
			if (stream->stream_type == MPEG_TS_STREAM_TYPE_VIDEO_2) {
				videopid = MAKE_WORD(stream->elementary_PID_high, stream->elementary_PID_low);
				break;
			}
			// @MPEG_PMT_STREAM_HEADER_SIZE = 5
			pos +=  MPEG_PMT_STREAM_HEADER_SIZE 
			    + MAKE_WORD(stream->ES_info_length_high, stream->ES_info_length_low);
		}
	}

	fclose(fp);
	return videopid;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值