当你自我炫耀时,便会受到谄媚者的青睐

发掘积累过程的快感

首页 » BIBLE模型 » GoLang » Golang通过pcap文件解析TS流,还原TS视频

Golang通过pcap文件解析TS流,还原TS视频


最近在做抓包录像方面的案例,通过 tcpdump 抓包后再分析包文件,解析出包中的视频等文件信息。先做最简单的部分,针对组播流的抓包录像分析。

TS 识别

TS 包由 4B 的包头(header)、可变长度的调整头和净荷(payload)组成;
包头结构定义如下:

struct ts_header{
        char     syn_byte:8;                        // 包头同步字节,0x47
        char     transport_error_indicator:1;       //传送数据包差错指示器
        char    payload_unit_start_indicator:1;     //有效净荷单元开始指示器
        char    transport_priority:1;               //传送优先级
        int        PID:13;                          //包 ID
        char    transport_scrambling_control:2;     //传送加扰控制
        char    adaptation_field_control:2;         //调整字段控制
        char    continuity_conunter:4;              //连续计数器 0-15
    }
  • syn_byte:值为 0x47,是 MPEG-2TS 的传送包标识符;
  • transport_error_indicator:值为 1 时,表示相关的传送包中至少有一个不可纠正的错误位,只有错误位纠正后,该位才能置 0;
  • payload_unit_start_indicator:表示 TS 包的有效净荷带有 PES 或 PSI 数据的情况;当 TS 包的有效净荷带有 PES 包数据时,payload_unit_start_indicator 为 1,表示 TS 包的有效净荷以 PES 包的第一个字节开始;为 0,表示 TS 包的开始不是 PES 包;当 TS 包带有 PSI 数据时,payload_unit_start_indicator 为 1,表示 TS 包带有 PSI 部分的第一个字节,即第一个字节带有指针 pointer_field,为 0 表示 TS 包不带有一个 PSI 部分的第一个字节,即在有效净荷中没有指针 pointer_field;对于空包的包,play_unit_start_indicator 应该置为 0;(这一点尤为重要,在组建自己的 section 时经常会用到这个)
  • transport_priority:置 1 表示相关的包比其他具有相同 PID 但 transport_priority 为 0 的包有更高的优先级;
  • PID:表示存储于传送包的有效净荷中数据的类型。
  • transport_scrambling_control:指示 TS 包有效净荷的加扰方式,如果首部包括调整字段,则不应该被加扰,对于空包,值要置“00”;
  • adaptation_field_control:传送流包首部是否跟随有调整字段和/或有效净荷。
  • continuity_conunter:随着具有相同 PID TS 包的增加而增加,当达到最大时,又恢复为 0,如果调整字段控制值 adaptation_field_control 为“00”或“10”,则该连续计数器不增加;在 TS 中,当复用的包可能被作为两个连续的具有相同 PID 的 TS 包传送出去时,则复用的传送包与原传送包具有相同的 continuity_counter,而 adaptation_field_control 字段值应为“01”或者”10”。在复用的包中,除了节目参考时钟 PCR 有效字段的值被重新编码外,原包中每个字节将被复制。

利用 syn_byte 位来识别 TS 流,连个 47 之间的间隔是 188,并且连续超过 3 个(降低干扰造成的误判),那么这条流就是 TS,可以字节将原始二进制文件写入到一个空白的 ts 文件中。

识别代码

// 判断 连续 三个 71 中间间隔是否 187
func isTs(p *[]byte) bool{
    var (
        num int // 包含连续 71 的个数
    )
    for index,value :=range *p{
        if value!=71 {
            continue
        }
        lastindex:=index
        for {
            ni:=lastindex+188
            if (len(*p)-1)=3 {
                return true
            }
            lastindex=ni
        }
    }
    return false
}

上面代码中用 71 的原因,47 转成十进制就是 71,识别到是 ts 流后,就可以将当前包的 Payload 保存在文件中,最终生成一个 TS 文件,这样就完成了对 TS 流的抓包文件进行视频还原。

互联网信息太多太杂,各互联网公司不断推送娱乐花边新闻,SNS,微博不断转移我们的注意力。但是,我们的时间和精力却是有限的。这里是互联网浩瀚的海洋中的一座宁静与美丽的小岛,供开发者歇息与静心潜心修炼。 “Bible”是圣经,有权威的书,我们的本意就是为开发者提供真正有用的的资料。 我的电子邮件 1217179982@qq.com,您在开发过程中遇到任何问题,欢迎与我联系。
Copyright © 2024. All rights reserved. 本站由 Helay 纯手工打造. 蜀ICP备15017444号