/*****************************************************************************
* dvbpsi_PushPacket 数字电视中TS包解码函数注解
*****************************************************************************
* Injection of a TS packet into a PSI decoder.
*****************************************************************************/
void dvbpsi_PushPacket(dvbpsi_handle h_dvbpsi, uint8_t* p_data)
{
uint8_t i_expected_counter; /* 存储下一个数据包的连续计数器数字 */
dvbpsi_psi_section_t* p_section; /* 当前段指针 */
uint8_t* p_payload_pos; /* 当前位置指针 */
uint8_t* p_new_pos = NULL; /* Beginning of the new section,updated to NULL when the new section is handled */
int i_available; /* 包中可用字节数 */
/* TS start code */
if(p_data[0] != 0x47) //同步字节(sync byte:1B),应为0x47
{
DVBPSI_ERROR("PSI decoder", "not a TS packet");
return;
}
/* 连续检查 */
i_expected_counter = (h_dvbpsi->i_continuity_counter + 1) & 0xf; /*连续计数器累加1*/
h_dvbpsi->i_continuity_counter = p_data[3] & 0xf; //TS头部最后4比特为连续计数器
if(i_expected_counter != h_dvbpsi->i_continuity_counter) /*判断是否是连续传送的包*/
{
DVBPSI_ERROR_ARG("PSI decoder",
"TS discontinuity (received %d, expected %d)",
h_dvbpsi->i_continuity_counter, i_expected_counter);
h_dvbpsi->b_discontinuity = 1; //将不连续标志置1
if(h_dvbpsi->p_current_section) //删除当前段
{
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section); //释放空间
h_dvbpsi->p_current_section = NULL;
}
}
/* 判断是否有有效负载,没有就返回*/
if(!(p_data[3] & 0x10)) //第28bit标识有无调整段
{
return;
}
/* 跳过自适应长度区 */
if(p_data[3] & 0x20) //第27bit标识有无自适应区(adaption field)
p_payload_pos = p_data + 5 + p_data[4]; //5为包头4字节及1字节的自适应长度 p_data[4]自适应区长度
else
p_payload_pos = p_data + 4;
/* Unit start -> skip the pointer_field and a new section begins */
if(p_data[1] & 0x40) //即"payload unit start indicator"bit位 有效荷载单元起始批示符位,值为1表示存在确定的起始信息
{
p_new_pos = p_payload_pos + *p_payload_pos + 1; //指向包数据起始位置
p_payload_pos += 1; //跳过长度指示的1个字节
}
p_section = h_dvbpsi->p_current_section;
/* If the psi decoder needs a begginning of section and a new section
begins in the packet then initialize the dvbpsi_psi_section_t structure */
if(p_section == NULL)
{
if(p_new_pos)
{
/* 为结构分配内存空间 */
h_dvbpsi->p_current_section
= p_section
= dvbpsi_NewPSISection(h_dvbpsi->i_section_max_size);
/* 更新当前位置指针 */
p_payload_pos = p_new_pos;
/* 有指针指向新段 */
p_new_pos = NULL;
/* Just need the header to know how long is the section */
h_dvbpsi->i_need = 3; //在前3个字节中包含了表ID、section syntax indicator和长度批示,能确定是那种表,有多长
h_dvbpsi->b_complete_header = 0;
}
else
{
/* No new section => return */
return;
}
}
/* Remaining bytes in the payload */
i_available = 188 + p_data - p_payload_pos; //有效载荷长度
while(i_available > 0)
{
if(i_available >= h_dvbpsi->i_need)
{
/* 有足够的字节存储头部或整个段的信息 */
memcpy(p_section->p_payload_end, p_payload_pos, h_dvbpsi->i_need);
p_payload_pos += h_dvbpsi->i_need;
p_section->p_payload_end += h_dvbpsi->i_need;
i_available -= h_dvbpsi->i_need;
if(!h_dvbpsi->b_complete_header)
{
/* Header is complete */
h_dvbpsi->b_complete_header = 1;
/* Compute p_section->i_length and update h_dvbpsi->i_need */
//不懂?????????
h_dvbpsi->i_need = p_section->i_length = ((uint16_t)(p_section->p_data[1] & 0xf)) << 8 | p_section->p_data[2]; //从第12个比特位到第24个比特位为长度批示段
/* 检查段是否超过最大长度 */
if(h_dvbpsi->i_need > h_dvbpsi->i_section_max_size - 3) //包头3个字节
{
DVBPSI_ERROR("PSI decoder", "PSI section too long");
dvbpsi_DeletePSISections(p_section);
h_dvbpsi->p_current_section = NULL;
/* 如果还有新段没有分析,则继续*/
if(p_new_pos)
{
h_dvbpsi->p_current_section
= p_section
= dvbpsi_NewPSISection(h_dvbpsi->i_section_max_size);
p_payload_pos = p_new_pos;
p_new_pos = NULL;
h_dvbpsi->i_need = 3;
h_dvbpsi->b_complete_header = 0;
i_available = 188 + p_data - p_payload_pos;
}
else
{
i_available = 0;
}
}
}
else
{
/* PSI section is complete */
p_section->b_syntax_indicator = p_section->p_data[1] & 0x80; //读段语法标志 位
p_section->b_private_indicator = p_section->p_data[1] & 0x40; //固定的'0',这是为了防止和ISO13818Video流格式中的控制字冲突而设置的
/* 如果存在CRC校验数据,则更新p_payload_end指针 */
if(p_section->b_syntax_indicator)
p_section->p_payload_end -= 4;
if(dvbpsi_ValidPSISection(p_section)) /*调用函数对数据进行CRC校验*/
{
/* 数据无误 */
p_section->i_table_id = p_section->p_data[0]; //从第一个字节读取表ID,0x00为PAT,0x02为PMT
if(p_section->b_syntax_indicator)
{
p_section->i_extension = (p_section->p_data[3] << 8)
| p_section->p_data[4]; //16bits的当前流ID,DVB内唯一.(事实上很多都是自定义的TS ID)
p_section->i_version = (p_section->p_data[5] & 0x3e) >> 1; //43到47的5bits为版本号码,标注当前节目的版本.这是个非常有用的参数,当检测到这个字段改变时,说明TS流中的节目已经变化了,程序必须重新搜索节目
p_section->b_current_next = p_section->p_data[5] & 0x1; //第48比特位,当前还是未来使用标志符,一般情况下为'0'
p_section->i_number = p_section->p_data[6]; //当前段号码
p_section->i_last_number = p_section->p_data[7]; //最后段号码(section_number和last_section_number的功能是当PAT内容>184字节时,PAT表会分成多个段(sections),解复用程序必须在全部接收完成后再进行PAT的分析)从for()开始,就是描述了当前流中的频道数目(N),每一个频道对应的PMT PID是什么.解复用程序需要和上图类似的循环来接收所有的频道号码和对应的PMT PID,并把这些信息在缓冲区中保存起来.在后部的处理中需要使用到PMT PID.
p_section->p_payload_start = p_section->p_data + 8; //前面已分析了8个字节,指向新的开始
}
else
{
p_section->p_payload_start = p_section->p_data + 3;
}
h_dvbpsi->pf_callback(h_dvbpsi, p_section);
h_dvbpsi->p_current_section = NULL;
}
else
{
/* PSI section isn't valid => trash it */
dvbpsi_DeletePSISections(p_section);
h_dvbpsi->p_current_section = NULL;
}
/* If there is a new section not being handled then go forward
in the packet */
if(p_new_pos)
{
h_dvbpsi->p_current_section
= p_section
= dvbpsi_NewPSISection(h_dvbpsi->i_section_max_size);
p_payload_pos = p_new_pos;
p_new_pos = NULL;
h_dvbpsi->i_need = 3;
h_dvbpsi->b_complete_header = 0;
i_available = 188 + p_data - p_payload_pos;
}
else
{
i_available = 0;
}
}
}
else
{
/* There aren't enough bytes in this packet to complete the
header/section */
memcpy(p_section->p_payload_end, p_payload_pos, i_available);
p_section->p_payload_end += i_available;
h_dvbpsi->i_need -= i_available;
i_available = 0;
}
}
}
数字电视中TS包解码函数
最新推荐文章于 2019-08-04 11:54:59 发布