水煮苹果的做法煮多久:DVBPSI中PAT PMT 编码函数注解 - 放下的窝棚 - CSDN博客
来源:百度文库 编辑:中财网 时间:2024/04/29 18:04:20
DVBPSI中PAT PMT 编码函数注解收藏
和段师兄一起学习dvbpsi的笔记
主要是PAT、PMT的编码函数的注释
/*****************************************************************************
* dvbpsi_GenPATSections
*****************************************************************************
* 用传入的p_pat信息构建PAT,i_max_pps参数用于限制每个pat里携带节目信息的数量(最多253个)
*****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat,
int i_max_pps)
{
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); /*保存返回值*/
dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_pat_program_t* p_program = p_pat->p_first_program; /*传入的不同节目PMT所使用的PID号的结构链*/
int i_count = 0; /*存储已经写入的节目数*/
/* 一个PAT表最多能携带253个节目信息 */
if((i_max_pps <= 0) || (i_max_pps > 253))
i_max_pps = 253;
p_current->i_table_id = 0; /*标志本表格的类型,PAT应该是0x00*/
p_current->b_syntax_indicator = 1; /*段语法标志*/
p_current->b_private_indicator = 0;
p_current->i_length = 9; /* header + CRC_32 */
p_current->i_extension = p_pat->i_ts_id; /*16bits的当前流ID,DVB内唯一.(事实上很多都是自定义的TS ID)*/
p_current->i_version = p_pat->i_version; /*5bits版本号码,标注当前节目的版本.这是个非常有用的参数,当检测到这个字段改变时,说明TS流中的节目已经变化了,程序必须重新搜索节目*/
p_current->b_current_next = p_pat->b_current_next; /*当前还是未来使用标志符,一般情况下为'0'*/
p_current->i_number = 0; /*当前段号码*/
p_current->p_payload_end += 8; /* 跳过8字节的表头信息*/
p_current->p_payload_start = p_current->p_payload_end; /*未写入数据时,开始和结束在同一位置*/
/* 向PAT中填入节目信息 */
while(p_program != NULL)
{
/* 如果一个PAT表保存不完,则需新建一个PAT表*/
if(++i_count > i_max_pps)
{
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
i_count = 1; /*下面将在新段写入第一个节目信息*/
p_current->i_table_id = 0;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 9; /* header + CRC_32 */
p_current->i_extension = p_pat->i_ts_id;
p_current->i_version = p_pat->i_version;
p_current->b_current_next = p_pat->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 8; /* 跳过头,指向节目信息开始*/
p_current->p_payload_start = p_current->p_payload_end;
}
/* p_payload_end 指向节目信息开始处,从这里开始填充数据*/
p_current->p_payload_end[0] = p_program->i_number >> 8; /*填入16bits的节目号*/
p_current->p_payload_end[1] = p_program->i_number;
p_current->p_payload_end[2] = (p_program->i_pid >> 8) | 0xe0; /*0xe0=11100000 保留的三位置1,填入PMT的PID的高5位*/
p_current->p_payload_end[3] = p_program->i_pid; /*PID的低8位*/
/* 每个PMT占4字节,所以按4字节递增*/
p_current->p_payload_end += 4;
p_current->i_length += 4;
p_program = p_program->p_next;
}
/* 将所有PAT表中的最后段号码设置成最后一个PAT的号码*/
p_prev = p_result;
while(p_prev != NULL)
{
p_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev); /*调用dvbpsi_BuildPSISection构建PSI包*/
p_prev = p_prev->p_next;
}
return p_result;
}
/*****************************************************************************
* dvbpsi_GenPMTSections
*****************************************************************************
* 用传入的p_pmt信息构建PMT
*****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_pmt_t* p_pmt)
{
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); /*分配空间,用来存放最后结果*/
dvbpsi_psi_section_t* p_current = p_result;
dvbpsi_psi_section_t* p_prev;
dvbpsi_descriptor_t* p_descriptor = p_pmt->p_first_descriptor;
dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es;
uint16_t i_info_length; /*存储段或描述符长度*/
p_current->i_table_id = 0x02; /*表ID为0x02表示此表为PMT*/
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0; /*私有标志:0 不是私有数据*/
p_current->i_length = 13; /* 表头 + 4bytes CRC_32校验数据,从program_number开始,到CRC_32(包含)的字节总数 */
p_current->i_extension = p_pmt->i_program_number; /*16bits的频道号码,表示当前的PMT关联到的频道*/
p_current->i_version =p_pmt->i_version; /*版本号码,如果PMT内容有更新,则version_number会递增1通知解复用程序需要重新接收节目信息,否则version_number是固定不变的.*/
p_current->b_current_next = p_pmt->b_current_next;
p_current->i_number = 0; /*当前未来标志符,一般是0*/
p_current->p_payload_end += 12; /* 指向频道描述符开始 */
p_current->p_payload_start = p_current->p_data + 8; /*跳过表头,指向数据开始*/
/* 填入PCR信息*/
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; /*68~81bit的13bit位存储PCR信息,先填入高5位数据*/
p_current->p_data[9] = p_pmt->i_pcr_pid;
/* PMT descriptors */
while(p_descriptor != NULL)
{
/* 判断是否需要新的PMT表*/
/* 已写入的数据长度 + 描述符长度 + 2 > 1024 - CRC_32_length ,2字节用于存储描述符长度*/
if( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length > 1018)
{
/* 节目信息长度,就是紧接着的若干个描述符的总长度*/
i_info_length = (p_current->p_payload_end - p_current->p_data) - 12; /*减去表头的12个字节*/
p_current->p_data[10] = (i_info_length >> 8) | 0xf0; /*将长度写入到77~88bit的14bit中,先写入高4位*/
p_current->p_data[11] = i_info_length;
/*一个PMT存储不完,构建新的PMT继续存储*/
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 13; /* header + CRC_32 */
p_current->i_extension = p_pmt->i_program_number;
p_current->i_version = p_pmt->i_version;
p_current->b_current_next = p_pmt->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 12; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8;
/* PCR_PID */
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0;
p_current->p_data[9] = p_pmt->i_pcr_pid;
}
/* p_payload_end 已经指向描述符开始处 */
p_current->p_payload_end[0] = p_descriptor->i_tag; /*设置描述符标志*/
p_current->p_payload_end[1] = p_descriptor->i_length; /*设置描述符长度*/
memcpy(p_current->p_payload_end + 2, /*将描述符数据填充入p_data中*/
p_descriptor->p_data,
p_descriptor->i_length);
/* 每个描述符只用2个字节来存储标志和长度,所以以2递增*/
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
/* 写入描述符总长度信息*/
i_info_length = (p_current->p_payload_end - p_current->p_data) - 12;
p_current->p_data[10] = (i_info_length >> 8) | 0xf0;
p_current->p_data[11] = i_info_length;
/* PMT ESs */
while(p_es != NULL)
{
uint8_t* p_es_start = p_current->p_payload_end;
uint16_t i_es_length = 5;
/* 测试当前PMT表能否存储所有描述符 */
p_descriptor = p_es->p_first_descriptor;
while( (p_descriptor != NULL)
&& ((p_es_start - p_current->p_data) + i_es_length <= 1020)) /*1020=1024-4 留出4字节的CRC校验数据空间*/
{
i_es_length += p_descriptor->i_length + 2; /*2是指存储描述符标志和长度把占用的2字节*/
p_descriptor = p_descriptor->p_next;
}
/* 如果描述符链末空,当前表不是空表,则创建新表*/
if( (p_descriptor != NULL) /*链未空,仍有描述符未被存储*/
&& (p_es_start - p_current->p_data != 12) /*当前表不是空表*/
&& (i_es_length <= 1008)) /*1008=1024-12-4 ,12字节的表头和4字节的CRC数据,我觉得该判断会始终为真???*/
{
/* 将剩余的描述符存入新表中 */
DVBPSI_DEBUG("PMT generator",
"create a new section to carry more ES descriptors");
p_prev = p_current;
p_current = dvbpsi_NewPSISection(1024);
p_prev->p_next = p_current;
p_current->i_table_id = 0x02;
p_current->b_syntax_indicator = 1;
p_current->b_private_indicator = 0;
p_current->i_length = 13; /* header + CRC_32 */
p_current->i_extension = p_pmt->i_program_number;
p_current->i_version = p_pmt->i_version;
p_current->b_current_next = p_pmt->b_current_next;
p_current->i_number = p_prev->i_number + 1;
p_current->p_payload_end += 12; /* just after the header */
p_current->p_payload_start = p_current->p_data + 8;
/* PCR_PID */
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0;
p_current->p_data[9] = p_pmt->i_pcr_pid;
/* program_info_length */
i_info_length = 0; /*只携带ES描述符,所以节目信息长度设置为0*/
p_current->p_data[10] = 0xf0; /*保留的4位置1*/
p_current->p_data[11] = 0x00;
p_es_start = p_current->p_payload_end;
}
/* p_es_start 已经指向ES数据开始处,写入ES相关信息 */
p_es_start[0] = p_es->i_type;
p_es_start[1] = (p_es->i_pid >> 8) | 0xe0; /*用14bit位存储ES PID,先写入高4位*/
p_es_start[2] = p_es->i_pid;
/* 占用了5个字节 */
p_current->p_payload_end += 5;
p_current->i_length += 5;
/* ES descriptors */
p_descriptor = p_es->p_first_descriptor;
while( (p_descriptor != NULL)
&& ( (p_current->p_payload_end - p_current->p_data)
+ p_descriptor->i_length <= 1018)) /*ES描述符不为空及空间足够,已用空间+4字节CRC+2字节(tag和length)<1018*/
{
/* p_payload_end is where the descriptor begins */
p_current->p_payload_end[0] = p_descriptor->i_tag;
p_current->p_payload_end[1] = p_descriptor->i_length;
memcpy(p_current->p_payload_end + 2,
p_descriptor->p_data,
p_descriptor->i_length);
/* 向后移动 descriptor_length + 2 */
p_current->p_payload_end += p_descriptor->i_length + 2;
p_current->i_length += p_descriptor->i_length + 2;
p_descriptor = p_descriptor->p_next;
}
if(p_descriptor != NULL)
DVBPSI_ERROR("PMT generator", "unable to carry all the ES descriptors");
/* ES_info_length */
i_es_length = p_current->p_payload_end - p_es_start - 5;
p_es_start[3] = (i_es_length >> 8) | 0xf0; /*写入ES描述符的总长度*/
p_es_start[4] = i_es_length;
p_es = p_es->p_next;
}
/* Finalization */
p_prev = p_result;
while(p_prev != NULL)
{
p_prev->i_last_number = p_current->i_number;
dvbpsi_BuildPSISection(p_prev);
p_prev = p_prev->p_next;
}
return p_result;
}