从mpeg ts文件中提取I帧(3):pes包的解析

本系列的第一篇文章讲解了如何把ts包拼装为pes包,本章主要讲解如何解析pes包。
一、pes包的格式如下图所示:

二、相关字段解析
packet_start_code_prefix         标识包起始端的包起始码。固定值为  0000 0000 0000 0000 0000 0001 (0x000001)
stream_id                                  指示基本流的类型
PES_packet_length                  指示 PES 包中跟随该字段最后字节的字节数。
PES_scrambling_control          指示 PES 包有效载荷的加扰方式。
PTS (presentation time stamp) 显示时间戳
DTS (decoding time stamp)      解码时间戳


三、pes解析代码

int mpeg_pes_packet_parse(pes_packet_t *ppespkt, uint8_t *data, uint32_t size, uint32_t type)
{
    uint8_t *ptr = data;

    if (NULL==ptr || NULL==ppespkt) {
        print_err("phdrts=%p data=%p\n", ptr, ppespkt);
        return -1;
    }

    if (MPEG_STREAM_TYPE_VIDEO == type) {
        if (!MPEG_STREAM_IS_VIDEO(ptr[3])) {
            print_err("pes stream_id=0x%x is not video\n", ptr[3]);
            return -1;
        }
    }
    else if (MPEG_STREAM_TYPE_AUDIO == type) {
        if (!MPEG_STREAM_IS_AUDIO(ptr[3])) {
            print_err("pes stream_id=0x%x is not audio\n", ptr[3]);
            return -1;
        }
    }
    else { /*暂不支持其他类型*/
        print_err("pes type=%d\n", type);
        return -1;
    }

    ppespkt->packet_start_code_prefix  = ((ptr[0] << 16) | (ptr[1] << 8) | (ptr[2]));
    ppespkt->stream_id                 = ((ptr[3]));
    
    ppespkt->packet_length             = ((ptr[4]<< 8) | (ptr[5]));
    ppespkt->reserved_0                = ((ptr[6]&0xc0) >> 6);
    ppespkt->scrambling_control        = ((ptr[6]&0x30) >> 4);

    ppespkt->priority                  = ((ptr[6]&0x08) >> 3); /* 1 bslbf*/
    ppespkt->data_alignment_indicator  = ((ptr[6]&0x04) >> 2); /* 1 bslbf*/
    ppespkt->copyright                 = ((ptr[6]&0x02) >> 1); /* 1 bslbf*/
    ppespkt->original_or_copy          = ((ptr[6]&0x01));      /* 1 bslbf*/

    ppespkt->pts_dts_flags             = ((ptr[7]&0xc0) >> 6); /* 2 bslbf*/
    ppespkt->escr_flag                 = ((ptr[7]&0x20) >> 5); /* 1 bslbf*/
    ppespkt->es_rate_flag              = ((ptr[7]&0x10) >> 4); /* 1 bslbf*/

    ppespkt->dsm_trick_mode_flag       = ((ptr[7]&0x08) >> 3); /* 1 bslbf*/
    ppespkt->additional_copy_info_flag = ((ptr[7]&0x04) >> 2); /* 1 bslbf*/
    ppespkt->crc_flag                  = ((ptr[7]&0x02) >> 1); /* 1 bslbf*/
    ppespkt->extension_flag            = ((ptr[7]&0x01));      /* 1 bslbf*/

    ppespkt->header_data_length        = ((ptr[8]));           /* 8 uimsbf*/

    ptr += 9;
    ppespkt->playload_offset = ppespkt->header_data_length + 9;
    switch (ppespkt->pts_dts_flags) {
    case 2:
        ppespkt->pts = ((uint64_t)((ptr[0]&0x0e)>>1)<<30) | ((((ptr[1]<<8)|(ptr[2]&0xfe))>>1)<<15) | (((ptr[3]<<8)|(ptr[4]&0xfe))>>1);
        ppespkt->dts = NOPTS_VALUE;
        
        break;
    case 3:
        ppespkt->pts = ((uint64_t)((ptr[0]&0x0e)>>1)<<30) | ((((ptr[1]<<8)|(ptr[2]&0xfe))>>1)<<15) | (((ptr[3]<<8)|(ptr[4]&0xfe))>>1);
        ptr += 5;
        ppespkt->dts = ((uint64_t)((ptr[0]&0x0e)>>1)<<30) | ((((ptr[1]<<8)|(ptr[2]&0xfe))>>1)<<15) | (((ptr[3]<<8)|(ptr[4]&0xfe))>>1);
        ptr += 5;
        
        break;
    default:
        ppespkt->pts = NOPTS_VALUE;
        ppespkt->dts = NOPTS_VALUE;
    }

    return 0;
}

四、关于pts和dts
这里的pts、dts都是以90kHz为基准,转换为毫秒的算法:
pts * 1000 / 90000
pts和dts都是一个由27MHz脉冲触发计数器生成,再经300分频器分频成90kHz脉冲送入一个33位计数器生成90kHz基值是时间戳。这就是pts、dts位33位并以90khz为基准的原因。

五、pes解析运行结果
 

|+++++++++++++++++++++++++++++++++++++++++++++|
 sizeof(pes_packet_t)     = 32  
 packet_start_code_prefix = 0x1 
 stream_id                = 0xea 
 packet_length            = 0x0 
 reserved_0               = 0x2 
 scrambling_control       = 0x0 
 priority                 = 0x1 
 data_alignment_indicator = 0x1 
 copyright                = 0x0 
 original_or_copy         = 0x0 
 pts_dts_flags            = 0x3 
 escr_flag                = 0x0 
 es_rate_flag             = 0x0 
 dsm_trick_mode_flag      = 0x0 
 additional_copy_info_flag= 0x0 
 crc_flag                 = 0x0 
 extension_flag           = 0x0 
 header_data_length       = 0xa 
 playload_offset          = 0x13 
 reserved_1               = 0x0 
 pts                      = 0x121e7b6d6(4863801046)(15:00:42 233)
 dts                      = 0x121e78ca6(4863790246)(15:00:42 113)
|+++++++++++++++++++++++++++++++++++++++++++++|

mpeg2标准:https://download.csdn.net/download/maxzero/10402761
完整的代码:https://download.csdn.net/download/maxzero/10572383

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值