從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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章