wireshark导出H264裸流

news2024/9/22 1:01:13

导出H264裸流

  • 安装wireshark
  • 下载rtp_h264_extractor.lua脚本
  • 配置lua脚本
  • 重启wireshark
  • 筛选

安装wireshark

下载抓包工具:首先,您需要下载并安装一个网络抓包工具,例如Wireshark(https://www.wireshark.org)或tcpdump(https://www.tcpdump.org)。这些工具可用于捕获网络流量并保存为pcap或pcapng文件。在这里插入代码片

打开抓包工具:打开所选择的抓包工具,并启动网络监控。

下载rtp_h264_extractor.lua脚本

下载rtp_h264_extractor.lua脚本

--[[
 * rtp_h264_extractor.lua
 * wireshark plugin to extract h264 stream from RTP packets
 * 
 * Copyright (C) 2015 Volvet Zhang <volvet2002@gmail.com>
 *
 * rtp_h264_extractor is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * rtp_h264_extractor is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *]]


do
    local MAX_JITTER_SIZE = 50
    local h264_data = Field.new("h264")
    local rtp_seq = Field.new("rtp.seq")
	
    local function extract_h264_from_rtp()
        local function dump_filter(fd)
            local fh = "h264";
            if fd ~= nil and fd ~= "" then
                return string.format("%s and (%s)", fh, fd)
            else    
                return fh
            end
        end

        local h264_tap = Listener.new("ip", dump_filter(get_filter()))
        local text_window = TextWindow.new("h264 extractor")
        local filename = ""
        local seq_payload_table = { }
        local pass = 0
        local packet_count = 0
        local max_packet_count = 0
        local fu_info = nil
		
        local function log(info)
            text_window:append(info)
            text_window:append("\n")
        end
        
        -- get_preference is only available since 3.5.0
        if get_preference then
            filename = get_preference("gui.fileopen.dir") .. "/" .. os.date("video_%Y%m%d-%H%M%S.264")
        else
            filename = "dump.264"
        end
        
        log("Dumping H264 stream to " .. filename)
        local fp = io.open(filename, "wb")
        if fp == nil then 
            log("open dump file fail")
        end
        
        local function seq_compare(left, right)  
            if math.abs(right.key - left.key) < 1000 then  
                return left.key < right.key  
            else 
                return left.key > right.key  
            end  
        end  
        
        local function dump_single_nal(h264_payload)
            fp:write("\00\00\00\01")
            fp:write(h264_payload:tvb()():raw())
            fp:flush()
        end
        
        local function dump_fu_a(fu_info) 
            if  fu_info.complete ==  true then 
                log("dump_fu_a")
                fp:write("\00\00\00\01")
                fp:write(string.char(fu_info.nal_header))
            
                for i, obj in ipairs(fu_info.payloads) do
                    fp:write(obj:tvb()():raw(2))
                end
                fp:flush()
            else
                log("Incomplete NAL from FUs, dropped")
            end
        end
        
        local function handle_fu_a(seq, h264_data)
            fu_indicator = h264_data:get_index(0)
            fu_header = h264_data:get_index(1)
            nal_header = bit.bor(bit.band(fu_indicator, 0xe0), bit.band(fu_header, 0x1f))
            
            if bit.band(fu_header, 0x80) ~= 0 then
                -- fu start flag found
                fu_info = { }
                fu_info.payloads = { }
                fu_info.seq = seq
                fu_info.complete = true
                fu_info.nal_header = nal_header
                
                table.insert(fu_info.payloads, h264_data)
                log("Fu start: seq = "..tostring(seq))
                return
            end
            
            if fu_info == nil then 
                log("Incomplete FU found: No start flag, dropped")
                return
            end
            
            if seq ~= (fu_info.seq + 1)% 65536 then
                log("Incomplete FU found:  fu_info.seq = "..tostring(fu_info.seq)..", input seq = "..tostring(seq))
                fu_info.complete = false;
                return
            end
            
            fu_info.seq = seq
            
            table.insert(fu_info.payloads, h264_data)
            
            if bit.band(fu_header, 0x40) ~= 0 then
                -- fu end flag found
                log("Fu stop: seq = "..tostring(seq))
                dump_fu_a(fu_info)
                fu_info = nil
            end 
            
        end
        
        local function handle_stap_a(h264_data)
            log("start dump stap nals")
            offset = 1		-- skip nal header of STAP-A
            repeat
                size = h264_data:tvb()(offset, 2):uint()
                offset = offset + 2
                local next_nal_type = bit.band(h264_data:get_index(offset), 0x1f)
                log("STAP-A has naltype = "..next_nal_type..", size = "..size)
                fp:write("\00\00\00\01")
                fp:write(h264_data:tvb()():raw(offset, size))
                offset = offset + size
            until offset >= h264_data:tvb():len()
            fp:flush()
            log("finish dump stap nals")
        end
		
        local function on_ordered_h264_payload(seq, h264_data)
            local naltype = bit.band(h264_data:get_index(0), 0x1f)
            if naltype > 0 and naltype < 24 then 
                -- Single NAL unit packet
                if fu_info ~= nil then
                    log("Incomplete FU found: No start flag, dropped")
                    fu_info = nil
                end
                dump_single_nal(h264_data)
                --log("tap.packet: "..", single nal packet dumpped, naltype = "..tostring(naltype)..", len = "..tostring(packet.len))
            elseif naltype == 28 then
                -- FU-A
                handle_fu_a(seq, h264_data)
            elseif naltype == 24 then
                -- STAP-A
                if fu_info ~= nil then
                    log("Incomplete FU found: No start flag, dropped")
                    fu_info = nil
                end
                handle_stap_a(h264_data)
            else
                log("tap.packet: "..", Unsupported nal, naltype = "..tostring(naltype))				
            end 
        end
        
        local function on_jitter_buffer_output()
            table.sort(seq_payload_table, seq_compare)
            
            if #seq_payload_table > 0 then
                log("on_jitter_buffer_output:  seq = "..tostring(seq_payload_table[1].key)..", payload len = "..tostring(seq_payload_table[1].value:len()))
                on_ordered_h264_payload(seq_payload_table[1].key, seq_payload_table[1].value)
                table.remove(seq_payload_table, 1)
            end
        end
        
        local function jitter_buffer_finilize() 
            for i, obj in ipairs(seq_payload_table) do
                log("jitter_buffer_finilize:  seq = "..tostring(obj.key)..", payload len = "..tostring(obj.value:len()))
                on_ordered_h264_payload(obj.key, obj.value)
            end
        end
        
        local function on_h264_rtp_payload(seq, payload)
            --log("on_h264_rtp_payload:  seq = "..tostring(seq.value)..", payload len = "..tostring(payload.len))
            table.insert(seq_payload_table, { key = tonumber(seq.value), value = payload.value })
            
            --log("on_h264_rtp_payload: table size is "..tostring(#seq_payload_table))
            if #seq_payload_table > MAX_JITTER_SIZE then
                on_jitter_buffer_output()
            end
        end
        
        function h264_tap.packet(pinfo, tvb)
            local payloadTable = { h264_data() }
            local seqTable = { rtp_seq() }
            
            if (#payloadTable) < (#seqTable) then 
                log("ERROR: payloadTable size is "..tostring(#payloadTable)..", seqTable size is "..tostring(#seqTable))
                return
            end
            
            if pass == 0 then 
                for i, payload in ipairs(payloadTable) do
                    max_packet_count = max_packet_count + 1
                end
            else 
                packet_count = packet_count + 1
                
                for i, payload in ipairs(payloadTable) do
                    on_h264_rtp_payload(seqTable[1], payload)
                end
                
                if packet_count == max_packet_count then
                    jitter_buffer_finilize()
                end
            end 
        end
		
        function h264_tap.reset()
        end
		
        function h264_tap.draw() 
        end
		
        local function remove() 
            if fp then 
                fp:close()
                fp = nil
            end
            h264_tap:remove()
        end 
		
        log("Start")
		
        text_window:set_atclose(remove)
		
        log("phase 1")
        pass = 0
        retap_packets()
        
        log("phase 2:  max_packet_count = "..tostring(max_packet_count))
        pass = 1
        retap_packets()

        if fp ~= nil then 
           fp:close()
           fp = nil
           log("Video stream written to " .. filename)
        end
        
        log("End")
	end


	register_menu("Extract h264 stream from RTP", extract_h264_from_rtp, MENU_TOOLS_UNSORTED)
end

配置lua脚本

下载上述链接中的文件,将rtp_h264_extractor.lua文件放到wireshark的安装目录下。然后在wireshark安装目录下的init.lua文件末尾添加 dofile(DATA_DIR…”rtp_h264_extractor.lua”)
并且确保disable_lua=false

重启wireshark

在这里插入图片描述

筛选

用wireshark加载选定的视频抓包文件后,点击Extra h264 stream from RTP,即可将rtp中的视频数据(h264编码格式)导出成h264文件.
在这里插入图片描述

请记住,由于网络抓包文件通常包含多个协议和数据包,因此在导出H.264裸流之前,确保仅选择包含H.264数据的数据包,以避免保存不相关的数据。此外,使用网络抓包工具时,请务必遵守适用法律和道德准则,并确保合法使用该工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/799466.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源数据库 | 记一次在麒麟操作系统上适配openGauss进阶之旅

引入 适配 | 认证-Kylin V10 ARM 麒麟操作系统openGauss数据库 开篇 1、数据库架构 百度百科&#xff1a;openGauss 是一款全面友好开放&#xff0c;携手伙伴共同打造的企业级开源关系型数据库。openGauss采用木兰宽松许可证v2发行&#xff0c;提供面向多核架构的极致性能、全…

linux安装nginx遇到的报错

1、Linux如何修改只读文件&#xff08;以设置自动连网为例&#xff09; vim /etc/sysconfig/network-scripts/ifcfg-ens33 然后提示 E45&#xff1a;已设定选项“readonly”&#xff08;请加&#xff01;强制执行&#xff09; 如果需要强制修改&#xff0c;可以使用&#xff0…

关于idea如何成功运行web项目

导入项目 如图 依次选择 file - new - Project from Existing Sources 选择存放的项目目录地址 如图 导入完成 点击ok 如图 依次选择 Create project from existing sources 点击next如图 &#xff0c;此处默认即可 点击 next如图 点击next有该提示 是因为之前导入过…

抖音seo源码开发源代码开发技术分享

一、 抖音SEO源码开发&#xff0c;需要掌握以下技术&#xff1a; 抖音API接口&#xff1a;抖音提供了丰富的API接口&#xff0c;包括用户信息、视频信息、评论信息等。 数据爬取技术&#xff1a;通过抓包分析抖音接口的数据结构&#xff0c;可以使用Python等编程语言编写爬虫程…

Elasticsearch Query DSL

Elasticsearch Query DSL 这里使用的 Elasticsearch 的版本为 7.12.1。 1、基本概念 1.1 文档(Document) ElasticSearch 是面向文档的&#xff0c;文档是所有可搜索数据的最小单位&#xff0c;例如 MySQL 的一条数据记录。 文档会被序列化成为 json 格式&#xff0c;保存在…

B076-项目实战--宠物上下架 展示 领养 收购订单

目录 上下架功能提供后台宠物列表实现 前台展示前台宠物列表和详情展示店铺展示 领养分析前台后端PetControllerPetServiceImpl 订单需求分析可能产生订单的模块订单模块额外功能 订单设计表设计流程设计 集成基础代码收购订单创建订单前端后端 上下架功能提供 后台宠物列表实…

生成虚拟淘宝购买记录截图图片制作

大家都知道&#xff0c;淘宝购买记录截图在某些情况下非常重要&#xff0c;但手动制作却非常繁琐&#xff0c;耗费时间和精力。如果你也遇到了这个问题&#xff0c;那么不妨试试淘宝订单生成器&#xff0c;它能够帮助你轻松生成淘宝购买记录截图&#xff0c;提升工作效率。 虚拟…

Docker 容器高级操作

Docker容器高级操作 Docker容器创建、停止、启动、删除等基础操作上篇已述,然Docker容器被广大开发者青睐,不可能只有如此简单的功能,必有高阶功法。那么接下来 让我们一同走进容器操作的高级篇,领略其高级操作的魅力。 查看容器 docker ps -a | grep tomcat [root@tudou…

【数据结构】实验十:哈夫曼编码

实验十 哈夫曼编码 一、实验目的与要求 1&#xff09;掌握树、森林与二叉树的转换&#xff1b; 2&#xff09;掌握哈夫曼树和哈夫曼编码算法的实现&#xff1b; 二、 实验内容 1. 请编程实现如图所示的树转化为二叉树。 2. 编程实现一个哈夫曼编码系统&#xff0c;系统功能…

PingCAP 陈煜琦:深耕中国市场,构建客户成功生态

在 PingCAP 用户峰会 2023 上&#xff0c;PingCAP 副总裁陈煜琦分享了“激流入海&#xff0c;PingCAP 中国业务发展策略”的演讲&#xff0c;介绍了 PingCAP 在技术层面的发展方向&#xff0c;强调了 PingCAP 服务于中国企业客户的重要性&#xff0c;并介绍了 PingCAP 助力 客户…

Pytest学习教程_基础知识(一)

前言 pytest是一个用于编写和执行Python单元测试的框架。它提供了丰富的功能和灵活性&#xff0c;使得编写和运行测试变得简单而高效。 pytest的一些主要特点和解释如下&#xff1a; 自动发现测试&#xff1a;pytest会自动查找以"test_"开头的文件、类和函数&#x…

TEE GP(Global Platform)功能认证方案

TEE之GP(Global Platform)认证汇总 一、功能认证介绍 二、功能认证测试套和测试工具 1、“测试套件”是指由GlobalPlatform测试文档、测试脚本和/或其他材料组成的套件&#xff0c;基于给定的GlobalPlatform规范和相关配置&#xff0c;由GlobalPlatform发布&#xff0c;目的是…

【C++】类和对象-对象特性

1.构造函数和析构函数 2.函数的分类以及调用 以后采用括号法 int main() { /******************************************///test01();//test02();Person p;/******************************************/system("pause");return 0; }&#xff08;1&#xff09…

行业追踪,2023-07-27

自动复盘 2023-07-27 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

linux系统下(centos7.9)安装Jenkins全流程

一、卸载历史版本 # rpm卸载 rpm -e jenkins# 检查是否卸载成功 rpm -ql jenkins# 彻底删除残留文件 find / -iname jenkins | xargs -n 1000 rm -rf二、环境依赖安装 yum -y install epel-releaseyum -y install daemonize三、安装Jenkins Jenkins官网传送带&#xff1a; …

【bar堆叠图形绘制】

绘制条形图示例 在数据可视化中&#xff0c;条形图是一种常用的图表类型&#xff0c;用于比较不同类别的数据值。Python的matplotlib库为我们提供了方便易用的功能来绘制条形图。 1. 基本条形图 首先&#xff0c;我们展示如何绘制基本的条形图。假设我们有一个包含十个类别的…

【数据结构】实验四:循环链表

实验四 循环链表 一、实验目的与要求 1&#xff09;熟悉循环链表的类型定义和基本操作&#xff1b; 2&#xff09;灵活应用循环链表解决具体应用问题。 二、实验内容 题目一&#xff1a;有n个小孩围成一圈&#xff0c;给他们从1开始依次编号&#xff0c;从编号为1的小孩开…

写给新手的单元测试框架unittest运行的简单问题

当使用unittest框架编写和运行单元测试时&#xff0c;需要遵循以下步骤&#xff1a; 1、导入unittest模块&#xff1a;在代码中首先导入unittest模块。 import unittest 2、创建测试类&#xff1a;创建一个继承自unittest.TestCase的测试类。该类将包含一系列测试方法。 cla…

#P1006. [NOIP2010普及组] 三国游戏

题目描述 小涵很喜欢电脑游戏&#xff0c;这些天他正在玩一个叫做《三国》的游戏。 在游戏中&#xff0c;小涵和计算机各执一方&#xff0c;组建各自的军队进行对战。游戏中共有 NN 位武将&#xff08;NN为偶数且不小于44&#xff09;&#xff0c;任意两个武将之间有一个“默…

什么是低代码开发平台?它可以实现哪些功能?

什么是低代码开发平台&#xff1f; 低代码来源于英文“Low Code&#xff0c;它意指一种快速开发的方式&#xff0c;使用最少的代码、以最快的速度来交付应用程序。通俗的来说&#xff0c;就是所需代码数量低&#xff0c;开发人员门槛低&#xff0c;操作难度低。一般采用简单的…