解析PMT
解析完成PAT之后,就得到了program的信息了,如果program中存放了PMT的信息,那么就把program中PMT的PID记录下来,根据PID查找对应的TS包,找到之后就可以从该TS包中解析出PMT了
从TS包中读取PMT
// 从TS包中读取PMT
friend PMT& operator<<(PMT& pmt, Packet& packet)
{
const char* payload;
// 从TS包中读取负载
packet.getPayload(payload);
// 强制转换为PMT
pmt = *reinterpret_cast<const PMT*> (payload);
// 判断table的id是否等于0x02,如果是,那么表示真的是PMT
if (pmt.table_id == TABLE_ID_PMT)
{
pmt.good = true;
}
return pmt;
}
从PMT中解析stream的信息
stream的定义
class Stream
{
public:
friend class PMT;
// stream的类型
enum StreamType
{
MPEG_1_VIDEO = 0x01, // MPEG1的视频
MPEG_2_VIDEO = 0x02, // MPEG2的视频
MPEG_1_AUDIO = 0x03, // MPEG1的音频
MPEG_2_AUDIO = 0x04, // MPEG2的音频
};
inline StreamType getStreamType() const
{
return static_cast<StreamType> (stream_type);
}
inline uint16_t getElementaryPid() const
{
return (elementary_pid1 << 8) | elementary_pid2;
}
private:
uint8_t stream_type; // stream的类型
uint8_t elementary_pid1 :5; // PID
uint8_t reserved1 :3;
uint8_t elementary_pid2;
uint8_t es_info_length1 :2; // ES 描述符长度
uint8_t reserved2 :6;
uint8_t es_info_length2;
// FIXME no ES descriptor
};
读取stream的信息
stream中就存放了音视频数据的信息,例如类型和状态这些音视频数据的TS包等
// 返回stream
std::vector<PMT::Stream> getStreams() const
{
std::vector<PMT::Stream> streams;
// 在PMT头部与crc之间存放了stream的信息
for (const uint8_t* off = data; off < data + getSectionLength()
- sizeof(CRC32) - (data - §ion_length2); off
+= sizeof(Stream))
{
// 强制转换
Stream stream = *reinterpret_cast<const Stream*> (off);
off += (stream.es_info_length1 << 8) | stream.es_info_length2;
streams.push_back(stream);
}
return streams;
}