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

2023-11-07

本系列的第一篇文章讲解了如何把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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • Linux文件I/O编程

    文章目录 一 文件描述符 二 打开文件 三 创建文件 四 关闭文件 五 读取文件 六 向文件写入数据 七 设定文件偏移量 八 获取文件状态 九 创建和删除目录项 十 文件锁定 十一 建立文件和内存映射 十二 mmap 和 共享内存对比 I
  • React中CodeMirror插件的使用及封装

    目录 一 CodeMirror是什么 二 React中CodeMirror的基本使用介绍 一 引入CodeMirror 1 安装CodeMirror插件 2 引入 CodeMirror 插件 二 引入文件配置 三 关键属性解读 1 valu
  • hive 表中常用的 增加/修改/替换列操作

    1 语法 更新列 ALTER TABLE table name CHANGE COLUMN col old name col new name column type COMMENT col comment FIRST AFTER colu
  • C++ 仿函数(二)

    在上一篇里我们讲了仿函数是什么 以及一元谓词 二元谓词的概念 C 仿函数 一 小梁今天敲代码了吗的博客 CSDN博客 这篇是讲 内建函数对象 主要包括 算术仿函数 关系仿函数 逻辑仿函数 目录 一 算术仿函数 示例 二 关系仿函数 示例 举
  • windows 开机启动脚本(亲测可用)

    1 打开计划任务 2 创建任务 3 添加一个启动触发器 4 添加一个脚本操作 5 点击确认 输入登录管理员密码即可 重启试试吧
  • 部署 Exsi 7.0.3

    文章目录 1 下载介质 2 u盘引导安装启动盘 3 硬件连接 4 安装 EXSI 7 0 3 1 下载介质 下载 VMware VMvisor Installer 7 0U3l 21424296 x86 64 iso 安装 EXSI 7 0
  • vue H5页面跳转微信小程序以及生成二维码跳转小程序

    研究了两种H5跳转小程序的方法 同时携带参数 1 手机浏览器打开H5页面 点击按钮拉起微信小程序 2 H5页面上生成小程序二维码 手机微信扫码跳转目标小程序 为了开发方便 以上两种均借助了微信小程序云函数来实现 事前准备 在vue工程的in
  • Oracle数据库的导入&导出

    1 权限配置及导入导出 1 1 配置导入导出目录及设置相应权限 SQL gt select from dba directories dir where dir DIRECTORY NAME in DUMPDIR DATA PUMP DIR
  • 百万youtube高清视频数据集采集

    HD VILA 100M是什么 HD VILA 100M是一个大规模 高分辨率 多样化的视频语言数据集 有助于多模态表示学习 数据统计 该数据集共包含330万个视频 视频质量较高 均衡分布在15个类别中 下载 Download 您可以通过此
  • 详解34家银行对公账号编码规则及其编码分析

    1 工商银行 账号位数19位 地区代码4位 13为安徽 网点号4位 账户性质应用号2位 09基本户 19一般户 29专户 39临时户 账号顺序号7位 校验码2位 编码分析攻略 中国工商银行对公账户共19位 其中1 4位为地区代码 详见代码表
  • 树莓派教程 - 1.0 树莓派GPIO库wiringPi 点亮LED

    Git例程源码仓库 https github com ZhiliangMa raspberry git 电脑需要提前安装的工具 SSH 串口 终端神器 MobaXterm 官网下载链接 https mobaxterm mobatek net
  • java.sql.sQLException: No suitable driver found for jdbc:mysql

    用Maven构建父工程后 再搭建DAO模块 执行测试类测试StudentDao java查询数据库功能报错 定位到相应的类中 发现是数据库连接问题 之前我也遇到类似的问题 解决方案为 jdbc url jdbc mysql localhos
  • YOLO系列目标检测算法-Scaled-YOLOv4

    YOLO系列目标检测算法目录 文章链接 YOLO系列目标检测算法总结对比 文章链接 YOLOv1 文章链接 YOLOv2 文章链接 YOLOv3 文章链接 YOLOv4 文章链接 Scaled YOLOv4 文章链接 YOLOv5 文章链接
  • 主业工资5000,靠“爬虫技术”月入20000:会赚钱的人,从不靠拼命

    因为我们主行业的一个内卷以及薪资问题 现在已经有很多人都在从事一个副业 副业往往比主业更自由 轻松 甚至有的副业工资比他的一个主业工资还高 现在 只要你会python的爬虫技术 网上接单副业的项目更是多的供过于求 现在业界对Python爬虫
  • Python和OpenCV 提取图像特定目标区域-图像分割【原创】

    在OpenCV中 一般转换图像格式为HSV格式 默认格式为BGR 再进行指定颜色的提取 直接使用RGB提取颜色不推荐 HSV格式的介绍 HSV 为色相 饱和度 明度 1 将一副图像从rgb颜色空间转换到hsv颜色空间 hsv cv2 cvt
  • <Visual Studio 2019安装及环境配置教程>

    目录 1 Visual Studio 2019下载安装 1 1 进入官网 1 2 选择所需Visual Studio 2019安装包 1 3 Visual Studio 2019 版本说明 1 4 点击下载 安装 1 5 登录账户 1 6
  • 2022年华中杯数学建模挑战赛B题量化投资问题求解全过程文档及程序

    2022年华中杯数学建模 B题 量化投资问题 原题再现 量化投资是指通过数量化方式及计算机程序化发出买卖指令 以获取稳定收益为目的的交易方式 投资者通过数据分析探索市场运行规律 并预测市场走势 从而进行决策交易 随着大数据技术的发展 量化投
  • windows11安装wsl

    wsl2 简单点说 就是可以在Windows上用Linux 并且支持docker 管理员身份打开powerShell win x 输入下面命令 wsl install dism exe online enable feature featu
  • 算法(C++)金币阵列问题

    题目描述 有m n m 100 n 100 个金币在桌面上排成一个m 行n 列的金币阵列 每一枚金币或正面朝上或背面朝上 用数字表示金币状态 0 表示金币正面朝上 1 表示背面朝上 金币阵列游戏的规则是 1 每次可将任一行金币翻过来放在原来
  • 从mpeg ts文件中提取I帧(3):pes包的解析

    本系列的第一篇文章讲解了如何把ts包拼装为pes包 本章主要讲解如何解析pes包 一 pes包的格式如下图所示 二 相关字段解析 packet start code prefix 标识包起始端的包起始码 固定值为 0000 0000 000