从mpeg ts文件中提取I帧(1):将ts包拼装为section或pes包

2023-11-15

写在前面的话:
        不觉中已经在数码工作了十年有余,十年的青春、十年的汗水,如今即将离开,个中滋味难以言表!
以后可能不会在广电行业工作了,就用这个小程序,为自己十年的广电工作画上一个句号吧。
依旧是:版权没有 盗版不纠 欢迎转载。

本程序的功能:提取ts文件的视频I帧并显示输出,同时可以将I帧保存为yuv bmp格式的文件。
基本思路:
1、探测文件中ts包的长度 188?192?204?
2、将ts包拼装为section,解析pat section。
3、依据pat,解析所有的pmt section。
4、依据pmt,分析video pid是否合法。
5、将ts包拼装为pes,依据video pid获取video pes。
6、解析video pes,获取I帧。
7、使用ffmpeg解码I帧为 yuv bmp格式。
8、使用opencv显示yuv。

开发环境:
ubuntu-14.04-64位
gcc-4.8.4 
ffmpeg-3.0.0 
opencv-3.4.0
SlickEdit Pro 2016 感兴趣的可以参考:https://blog.csdn.net/maxzero/article/details/78728098

本章主要讲解如何将ts包拼装为section或pes包。依据的标准为ITU-T H.222.0建议书。

一、mpeg ts包的语法结构

1、ts包的长度有3种
     * 欧洲标准是 188B
     * 日本标准是 192B
     * 第三种是     204B 是在188B的基础上,加上16B的FEC(前向纠错).

2、相关字段解析
     * sync_byte  ts包的起始值,固定为0x47。
     * payload_unit_start_indicator 
       当传输流包有效载荷包含 PES 数据时: 
      1-指示此传输流包承载PES包的首字节。0-指示此传输流包不承载PES包的首字节。 
      当传输流包有效载荷包含 PSI 数据时: 
      1-指示此传输流包承载PSI分段的首字节,并存在pointer_field字段。
      0-指示此传输流包不承载PSI分段的首字节,不存在pointer_field字段。
    *data_byte 有效负载
    *pid 指示包有效载荷中存储的数据类型。
    *continuity_counter 连续性计数器。相同pid的ts包continuity_counter在0-15之间循环。可以用来判断是否丢包。

二、ts包拼装为section pes流程


为了图的简洁并未画出完整的ts header。已pat(pid=0)为例:
1、首先找到pid=0,payload_unit_start_indicator=1的ts包,该包为pat section的起始包,并记录continuity_counter的值n。
2、下一个包就应该是 pid=0,payload_unit_start_indicator=0 continuity_counter=n+1。
3、以此类推,当找到pid=0,payload_unit_start_indicator=1时,搜索结束。
4、去掉ts header将这些有效负载依次拼装起来就是完整的pat section。

说明:
1、对于section数据,我们拿到第一个ts包后,可以通过分析section头部的section_length字段获取section的总长度,
      并依据这个长度来接收剩余的section数据。
2、对于pes数据,其长度是可变的,只能依据上图描述的方法进行接收。

三、ts包的解析
重点注意:有效负载为0的情况和pointer_field字段即可。

int mpeg_tsp_packet_parse(transport_packet_t *ptspkt, uint8_t *data, uint32_t size, uint32_t type)
{
    uint8_t *ptr = data;

    if (NULL==ptr || NULL==ptspkt || size<MPEGTS_PACKET_SIZE) {
        print_err("ptspkt=%p data=%p size=%d\n", ptspkt, data, size);
        return -1;
    }

    ptspkt->sync_byte                    = ((ptr[0]));
    ptspkt->transport_error_indicator    = ((ptr[1]>>7));
    ptspkt->payload_unit_start_indicator = ((ptr[1]<<1) >> 7);
    ptspkt->transport_priority           = ((ptr[1]<<2) >> 7);
    ptspkt->pid                          = ((ptr[1]&0x1f)<<8) | ptr[2];
    ptspkt->transport_scrambling_control = ((ptr[3]&0xc0) >> 6);
    ptspkt->adaption_field_control       = ((ptr[3]&0x30) >> 4);
    ptspkt->continuity_counter           = ((ptr[3]&0x0f));

    if (0x47 != ptspkt->sync_byte) {
        print_err("sync_byte=0x%x\n", ptspkt->sync_byte);
        return -1;
    }
    if (1 == ptspkt->transport_error_indicator) {
        print_err("pid=0x%04x transport_error_indicator=0x%x\n", ptspkt->pid, ptspkt->transport_error_indicator);
        return -1;
    }

    ptr += 4;
    ptspkt->playload_offset += 4;
    
    /*处理adaption_field字段*/
    if (ptspkt->adaption_field_control==0x02 || ptspkt->adaption_field_control==0x00) {
        ptspkt->adaptation_field_length = ptr[0];
        ptspkt->playload_offset = 0;
        /*
        print_dbg("pid=0x%04x adaptation_field. no playload.\n", ptspkt->pid);*/
        return 0;
    }
    
    if (ptspkt->adaption_field_control == 0x03) {
        ptspkt->adaptation_field_length = ptr[0];
        ptr += (ptspkt->adaptation_field_length + 1);
        ptspkt->playload_offset += (ptspkt->adaptation_field_length + 1);
    }
    
    /*承载PSI/SI数据时才有pointer_field*/
    if (ptspkt->payload_unit_start_indicator==1 && MPEGTS_PACKET_TYPE_PSI==type) { 
        ptspkt->pointer_field = ptr[0];
        ptr += 1;
        ptspkt->playload_offset += 1;
    }

    return 0;
}

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

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

从mpeg ts文件中提取I帧(1):将ts包拼装为section或pes包 的相关文章

随机推荐

  • ES6 Iterator

    不同数据集合怎么用统一的方式读取 可以用for of循环了 转载于 https www cnblogs com moneyss p 10641507 html
  • 双向链表,单向链表//循环

    head h ifndef HEAD H define HEAD H include
  • 将Oracle zip安装文件转换成Linux可用的iso镜像

    在Oracle官网下载得到的zip安装文件 要在VMware虚拟机上挂载iso安装Oracle 所以想将zip文件转化为iso 除了使用UltraISO软件外 这里尝试使用Linux mkisofs命令生成ISO 9660文件 mkisof
  • IOS 网络初探(一) - NSURLConnection

    在IOS中 除了最基本的socket外 苹果提供了NSURLConnection类来实现网络通信 请求服务器数据 GET方式 请求服务器数据分成异步和同步两种方式 先来看看异步 非阻塞 NSURL url NSURL URLWithStri
  • LPDDR4 JEDEC标准测试实例解析--写操作

    在LPDDR4的JEDEC标准中 写操作相关的时序参数要求基本都是围绕DQS信号 如下图所示 图中的单位 tCK 指的是时钟信号的工作周期 tCK的测试方法如下图所示 Write preamble and postamble设置 这一步对于
  • 3.1 Git 分支 - 分支简介

    3 1 Git 分支 分支简介 版本说明 版本 作者 日期 备注 0 1 loon 2019 3 23 初稿 目录 文章目录 3 1 Git 分支 分支简介 版本说明 目录 1 分支简介 Figure 9 首次提交对象及其树结构 Figur
  • Pycharm

    运行该程序 窗口底部会出现终端面板 Terminal pane 显示你的代码输出结果 使用Pycharm在运行过程中 查看每个变量的操作 show variables pytharm能不能像MATLAB一样显示中间变量的值呢 答案是可以的
  • Vue3.0 组合式 API 分析与实践

    本文带大家深入理解组合式 API 的设计详情 同时加入我们的实践经验总结 01 背景 Vue3 x 版本的出现带来了许多令人眼前一亮的新特性 其中组合式 API Composition API 一组附加的 基于功能的 API 被作为一种新的
  • 51单片机学习之-中断

    中断 在51单片机中共5个中断源 分别为 总的来说分为内部中断与外部中断 先说内部中断 也就是上图的两种定时器中断 T0 T1 它们的使用与4个寄存器有关 现在来介绍四种寄存器 中断允许寄存器 中断优先级寄存器 定时器工作方式寄存器 定时器
  • 151. 反转字符串中的单词

    1 题目地址 151 反转字符串中的单词 2 题目描述 给你一个字符串 s 请你反转字符串中 单词 的顺序 单词 是由非空格字符组成的字符串 s 中使用至少一个空格将字符串中的 单词 分隔开 返回 单词 顺序颠倒且 单词 之间用单个空格连接
  • vba与python的优缺点_对比VBA学Python操作Excel

    关于先学VBA还是先Python 或者作为办公族选什么 这些问题 我已经写了专题 就不再啰嗦 建议先阅读 讨论 学习VBA还是Python 但是大家一直还是被Python吸引 所以小编就说一期Python操作Excel吧 大部分教编程的 对
  • tensorflow 混合精度训练相关报错

    如题 在混合精度开发的时候遇到的报错 先列环境 V100服务器 ubuntu16 04 tensorflow 1 14 0 cuda10 0 python3 6 报错一 ValueError opt must be an instance
  • MySQL进阶语句

    目录 常用查询 order by按关键字排序 升序排序 降序排序 结合where进行条件过滤再排序 多字段排序 and or判断 and or 且与或的使用 嵌套 多条件使用 distinct 查询不重复记录 GROUP BY对结果进行分组
  • 经济,jiaxi

  • moviepy音视频开发:音频合成类CompositeAudioClip介绍

    前往老猿Python博文目录 CompositeAudioClip是AudioClip的直接子类 用于将几个音频剪辑合成为一个音频剪辑 CompositeAudioClip类只有一个构造方法 在构造方法内定义了一个内嵌函数make fram
  • 蓝屏错误代码分析和解决方法

    文字代码 可能的原因 可尝试的解决方法 0x00000001 APC INDEX MISMATCH 驱动出现问题 或安装了错误 不兼容的驱动 更新 重新安装相应设备官网的驱动 0x00000005 INVALID PROCESS ATTAC
  • VSCode的Pettier插件原理和设置

    最近写了一个 Prettier 插件 可以达到这样的效果 同事每次保存代码的时候 import 语句的顺序都会随机变 但是他去 prettier 配置文件里还啥也发现不了 于是就会一脸懵逼 那么这个同事发现了会打你的 prettier 插件
  • 在生信中利用Chat GPT/GPT4

    论文链接Ten Quick Tips for Harnessing the Power of ChatGPT GPT 4 in Computational Biology Papers With Code 之前在paper with cod
  • JAVA-JDK8的特性之Lambda表达式

    1 Lambda表达式 2 函数式接口 3 方法引用 4 Stream流 5 日期时间类 1 Lambda表达式 1 1 Lambda的由来 package demo01 public class Test01 public static
  • 从mpeg ts文件中提取I帧(1):将ts包拼装为section或pes包

    写在前面的话 不觉中已经在数码工作了十年有余 十年的青春 十年的汗水 如今即将离开 个中滋味难以言表 以后可能不会在广电行业工作了 就用这个小程序 为自己十年的广电工作画上一个句号吧 依旧是 版权没有 盗版不纠 欢迎转载 本程序的功能 提取