欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TS码流解析-3-解析PAT表

程序员文章站 2022-03-05 12:13:17
...

任务三

解析PAT表,并且获取码流里面跟节目相关的PID

相关知识

我们首先来查看下PAT表的结构,如下图所示
TS码流解析-3-解析PAT表

在这个结构里面,我们需要关注的是program_number以及program_map_PID。
我们获取到PAT的表之后,对其中的section进行解析,把我们需要的信息取出来,然后存入数据结构,这个任务就算完成了。

解析过程

1 流程图

TS码流解析-3-解析PAT表

2 数据结构定义

typedef struct pat_info
{
    unsigned int program_number      :16;
    unsigned int reserved            :3;
    unsigned int program_number_pid  :13;
    struct pat_info *next;
}PAT_INFO;

3 代码

static PAT_INFO *insert_pat_info_to_link(PAT_INFO *pat_info_link_head, PAT_INFO additive_node)
{
    PAT_INFO *new_pat_info_node = NULL;
    new_pat_info_node = (PAT_INFO*)malloc(sizeof(PAT_INFO));
    
    if (NULL == new_pat_info_node)
    {
        log("malloc error!\n");
        return pat_info_link_head;
    }

    
    new_pat_info_node->program_number = additive_node.program_number;
    new_pat_info_node->program_number_pid = additive_node.program_number_pid;
    new_pat_info_node->reserved = additive_node.reserved;
    // head insert
    new_pat_info_node->next = pat_info_link_head;
    
    return new_pat_info_node;
}

PAT_INFO *create_pat_info_link(FILE *ts_file, unsigned int package_length, int first_sync_position)
{
    SECTION *pat_table = NULL;
    SECTION *current_handle_section = NULL;
    int current_read_position = 0;
    int end_read_position = 0;
    PAT_INFO swap_pat_node = {0};
    PAT_INFO *pat_info_link_head = NULL;

    if ((NULL==ts_file) || (first_sync_position<0) || (0==package_length))
    {
        log("function parse_pmt parameter error");
        return pat_info_link_head;
    }

    pat_table = create_section_link(ts_file, package_length, first_sync_position, PAT_TABLE_ID, PAT_PID, eit_check);
    if (NULL == pat_table)
    {
        log("get PAT table error!\n");
        return pat_info_link_head;
    }

    current_handle_section = pat_table;
    while (current_handle_section != NULL)
    {
        current_read_position = SECTION_HEAD_LENGTH;
        end_read_position = current_handle_section->section_length - SECTION_CRC_LENGTH;

        while (current_read_position < end_read_position)
        {
            swap_pat_node.program_number = (current_handle_section->section_buffer[current_read_position] << 8) | 
                current_handle_section->section_buffer[current_read_position + 1];
            swap_pat_node.program_number_pid = (current_handle_section->section_buffer[current_read_position + 2] & 0x1f) << 8 | 
                current_handle_section->section_buffer[current_read_position + 3];
            current_read_position += PROGRAM_INFO_LENGTH;

            if (NETWORK_PID == swap_pat_node.program_number)
            {
                continue;
            }
            pat_info_link_head = insert_pat_info_to_link(pat_info_link_head, swap_pat_node);
        }
        current_handle_section = current_handle_section->next;
    }
    log("-----------------------------------PAT-----------------------------------\n");

    show_pat_info(pat_info_link_head);
    destroy_section_link(pat_table);
    pat_table = NULL;

    return pat_info_link_head;
}

相对来说,解析PAT表的难度不大,需要注意的是读取字节的位置一定要准确,是读取当前位置呢,还是读取下一个位置一定要清楚,不然整个读取过程都会乱套的。