数字电视技术实验(一)——TS流中PAT的读取及分析
程序员文章站
2022-03-23 08:33:24
...
实验目的:
- 输出TS包的包长
- 节目套数及对应节目的PMT PID
(一)实验代码
#include <iostream>
#include <cstdio>
#include <stdio.h>
#include <string>
#include <fstream>
using namespace std;
int package_len=0;
int firstPackagePos = 0;
int ProgramTotalNumber = 0;//节目总数
int Program_count = 0;//用以表示现在存到第几个Program了
struct _Program{
int Program_number;
int PMT_PID;
int PCR_PID;
int Video_PID;
int Audio_PID_1;
int Audio_PID_2;
bool flag;
}Program[16];
/*判断包长究竟是188还是204*/
void FindSyn(unsigned char *pBuffer_408)
{
for(int i=0;i<204;i++)
{
//包长188字节的情况
if (pBuffer_408[i]==0x47 && pBuffer_408[i+188]==0x47)
{
package_len=188;
firstPackagePos=i;
cout<<"packetage length = "<<188<<" & start from "<<i<<endl;
break;
}
//包长204字节的情况
else if (pBuffer_408[i]==71 && pBuffer_408[i+204]==71)
{
package_len=204;
firstPackagePos=i;
cout<<"package length = "<<204<<" & start from "<<i<<endl;
break;
}
}
}
/*判断adaptation_field_control的值,共有00,01,10,11四种可能
adaptation_field_control==00或10,返回0 (没有有效载荷)
adaptation_field_control==01, 返回1 (没有适配域)
adaptation_field_control==11, 返回2 (有适配域)*/
int IsValid(unsigned char* pBuffer_package)
{
unsigned char adaptation_field_control = (pBuffer_package[3] << 2) >> 6;
if ((adaptation_field_control == 0) || (adaptation_field_control == 2))
return 0;
else if (adaptation_field_control == 1)
return 1;
else if (adaptation_field_control == 3)
return 2;
else
return 3;
}
int GetNumber(int offset, unsigned char* pBuffer_package)
{
int section_length = (pBuffer_package[offset + 1] % 16) * 256 + pBuffer_package[offset + 2];
int number = (section_length - 9) / 4;
return number;
}
/*return 0:表示这是PAT的最后一个包
return 1:表示在之后依然会传输PAT包*/
int ReadPAT(unsigned char *pBuffer_package)
{
//计算此时是不是PAT包
int high5 = int(pBuffer_package[1]);
int low8 = int(pBuffer_package[2]);
int PID = (high5 % 32) * 256 + low8;
if (PID == 0)//此时是PAT包了
{
//0:无效载荷;1:01;2:11
int ValidFlag = IsValid(pBuffer_package);
//确定净荷偏移为offset,开始读PAT表
int offset = 0;
unsigned char payload_unit_start_indicator = (pBuffer_package[1] << 1) >> 7;
switch (ValidFlag)
{
case 0:
return 1;
case 1:
offset = 4;
if (payload_unit_start_indicator)
{
//从当前offset位置读取pointer_field字节
int pointer_field = pBuffer_package[4];
offset += pointer_field + 1;
}
break;
case 2:
int adaption_field_length = pBuffer_package[4];
offset = adaption_field_length + 5;
if (payload_unit_start_indicator)
{
//从当前offset位置读取pointer_field字节
int pointer_field = pBuffer_package[4];
offset += pointer_field + 1;
}
break;
}
//进行PAT包的读取
if (pBuffer_package[offset] != 0)//如果table id!=0,读取下一个TS包
return 1;
int number = GetNumber(offset, pBuffer_package);//根据section_length,确定节目总数N
ProgramTotalNumber += number;
int tempPos = offset + 8;
for (int i = 0; i < number; i++)
{
Program[Program_count].Program_number = (pBuffer_package[tempPos] % 256 * 256) + pBuffer_package[tempPos + 1];
Program[Program_count].PMT_PID = ((pBuffer_package[tempPos + 2] % 32) * 256) + pBuffer_package[tempPos + 3];
tempPos += 4;
Program_count++;
}
unsigned char section_number = pBuffer_package[offset + 6];
unsigned char last_section_number = pBuffer_package[offset + 7];
if (section_number != last_section_number)
return 1;
}
else if (PID != 0)
return 1;
return 0;
}
int main()
{
string m_Analyze_OpenFile="2.TS";
ifstream file_analyze("2.ts", ios::binary);
unsigned char* pBuffer_408=new unsigned char[408];
if(!file_analyze)
{
cout<<"Open File Error!!"<<endl;
exit(1);
}
file_analyze.read((char*) pBuffer_408,408);//先将408个值读入文件中(204*2)
//判断sync_byte==0x47
FindSyn(pBuffer_408);//判断包长是188还是204
file_analyze.seekg(firstPackagePos, ios::beg);//回归TS包最开始的数值
delete []pBuffer_408;//前述工作全部完成,结论为包长为188
unsigned char* pBuffer_package=new unsigned char[package_len];//一个包一个包进行读写。
//16套节目
for(int i=0;i<16;i++)
{
Program[i].Program_number=-1;
Program[i].PMT_PID=-1;
Program[i].PCR_PID=-1;
Program[i].Video_PID=-1;
Program[i].Audio_PID_1=-1;
Program[i].Audio_PID_2=-1;
Program[i].flag=false;
}
int m, n;
file_analyze.seekg(0, ios::beg);
m = file_analyze.tellg();
file_analyze.seekg(0, ios::end);
n = file_analyze.tellg();
int len = n - m;
int package_counts=(len-firstPackagePos)/package_len;
cout<<"共有"<<package_counts<<" 个包"<<endl;
file_analyze.seekg(firstPackagePos, ios::beg);
//读TS包,将所有PAT包读出来
for(int j=0;j<package_counts;j++)
{
file_analyze.read((char*)pBuffer_package, package_len);
int continue_flag = ReadPAT(pBuffer_package);
if (continue_flag == 0)
{
break;
}
}
cout << "共有 " << ProgramTotalNumber << " 套节目" << endl;
for (int i = 0; i < ProgramTotalNumber; i++)
{
cout << "节目 " << Program[i].Program_number << " 的 PMT PID为 " << Program[i].PMT_PID << endl;
}
delete []pBuffer_package;
return 0;
}
(二)实验结果
上一篇: H264和音频流打包成TS流 (MPEG2-TS)
下一篇: 如何获取http的码流