wireshark抓rtp包,提取出H265裸流数
调试rtsp收发流时,经常会需要抓包以确认是网络问题还是程序问题还是其它问题。通过tcpdump或者wireshark抓到的包通常是rtp流,保存为.pcap格式文件后中,可通过wireshark进行解析,得出h264裸流,并保存为文件。
1.wireshark配置
从gitee上可以直接下载的
WiresharkPlugin: The H265 H264 PS PCM AMR SILK plugin for Wireshark Lua (gitee.com)
1.1 下载rtp_h365_extractor.lua
-- Dump RTP h.265 payload to raw h.265 file (*.265)
-- According to RFC7798 to dissector H265 payload of RTP to NALU, and write it
-- to from<sourceIp_sourcePort>to<dstIp_dstPort>.265 file.
-- By now, we support Single NAL Unit Packets, Aggregation Packets (APs)
-- and Fragmentation Units (FUs) format RTP payload for H.265.
-- You can access this feature by menu "Tools"
-- Reference from Huang Qiangxiong (qiangxiong.huang@gmail.com)
-- Author: Yang Xing (hongch_911@126.com)
------------------------------------------------------------------------------------------------
dolocal version_str = string.match(_VERSION, "%d+[.]%d*")local version_num = version_str and tonumber(version_str) or 5.1local bit = (version_num >= 5.2) and require("bit32") or require("bit")function string.starts(String,Start)return string.sub(String,1,string.len(Start))==Startendfunction string.ends(String,End)return End=='' or string.sub(String,-string.len(End))==Endendfunction get_temp_path()local tmp = nilif tmp == nil or tmp == '' thentmp = os.getenv('HOME')if tmp == nil or tmp == '' thentmp = os.getenv('USERPROFILE')if tmp == nil or tmp == '' thentmp = persconffile_path('temp')elsetmp = tmp .. "/wireshark_temp"endelsetmp = tmp .. "/wireshark_temp"endendreturn tmpendfunction get_ffmpeg_path()local tmp = nilif tmp == nil or tmp == '' thentmp = os.getenv('FFMPEG')if tmp == nil or tmp == '' thentmp = ""elseif not string.ends(tmp, "/bin/") thentmp = tmp .. "/bin/"endendendreturn tmpend-- for geting h265 data (the field's value is type of ByteArray)local f_h265 = Field.new("h265") local f_rtp = Field.new("rtp") local f_rtp_seq = Field.new("rtp.seq")local f_rtp_timestamp = Field.new("rtp.timestamp")local filter_string = nil-- menu action. When you click "Tools->Export H265 to file" will run this functionlocal function export_h265_to_file()-- window for showing informationlocal tw = TextWindow.new("Export H265 to File Info Win")local pgtw;-- add message to information windowfunction twappend(str)tw:append(str)tw:append("\n")endlocal ffmpeg_path = get_ffmpeg_path()-- temp pathlocal temp_path = get_temp_path()-- running first time for counting and finding sps+pps, second time for real savinglocal first_run = true local writed_nalu_begin = false-- variable for storing rtp stream and dumping parameterslocal stream_infos = nil-- trigered by all h265 packatslocal list_filter = ''if filter_string == nil or filter_string == '' thenlist_filter = "h265"elseif string.find(filter_string,"h265")~=nil thenlist_filter = filter_stringelselist_filter = "h265 && "..filter_stringendtwappend("Listener filter: " .. list_filter .. "\n")local my_h265_tap = Listener.new("frame", list_filter)-- get rtp stream info by src and dst addressfunction get_stream_info(pinfo)local key = "from_" .. tostring(pinfo.src) .. "_" .. tostring(pinfo.src_port) .. "_to_" .. tostring(pinfo.dst) .. "_" .. tostring(pinfo.dst_port)key = key:gsub(":", ".")local stream_info = stream_infos[key]if not stream_info then -- if not exists, create onestream_info = { }stream_info.filename = key.. ".265"-- stream_info.filepath = stream_info.filename-- stream_info.file,msg = io.open(stream_info.filename, "wb")if not Dir.exists(temp_path) thenDir.make(temp_path)endstream_info.filepath = temp_path.."/"..stream_info.filenamestream_info.file,msg = io.open(temp_path.."/"..stream_info.filename, "wb")if msg thentwappend("io.open "..stream_info.filepath..", error "..msg)end-- twappend("Output file path:" .. stream_info.filepath)stream_info.counter = 0 -- counting h265 total NALUsstream_info.counter2 = 0 -- for second time runningstream_infos[key] = stream_infotwappend("Ready to export H.265 data (RTP from " .. tostring(pinfo.src) .. ":" .. tostring(pinfo.src_port) .. " to " .. tostring(pinfo.dst) .. ":" .. tostring(pinfo.dst_port) .. " write to file:[" .. stream_info.filename .. "] ...")endreturn stream_infoend-- write a NALU or part of NALU to file.local function write_to_file(stream_info, str_bytes, begin_with_nalu_hdr, end_of_nalu)if first_run thenstream_info.counter = stream_info.counter + 1if begin_with_nalu_hdr then-- save VPS SPS PPSlocal nalu_type = bit.rshift(bit.band(str_bytes:byte(0,1), 0x7e),1)if not stream_info.vps and nalu_type == 32 thenstream_info.vps = str_byteselseif not stream_info.sps and nalu_type == 33 thenstream_info.sps = str_byteselseif not stream_info.pps and nalu_type == 34 thenstream_info.pps = str_bytesendendelse -- second time runningif not writed_nalu_begin thenif begin_with_nalu_hdr thenwrited_nalu_begin = trueelsereturnendendif stream_info.counter2 == 0 thenlocal nalu_type = bit.rshift(bit.band(str_bytes:byte(0,1), 0x7e),1)if nalu_type ~= 32 then-- write VPS SPS and PPS to file header firstif stream_info.vps thenstream_info.file:write("\x00\x00\x00\x01")stream_info.file:write(stream_info.vps)elsetwappend("Not found VPS for [" .. stream_info.filename .. "], it might not be played!")endif stream_info.sps thenstream_info.file:write("\x00\x00\x00\x01")stream_info.file:write(stream_info.sps)elsetwappend("Not found SPS for [" .. stream_info.filename .. "], it might not be played!")endif stream_info.pps thenstream_info.file:write("\x00\x00\x00\x01")stream_info.file:write(stream_info.pps)elsetwappend("Not found PPS for [" .. stream_info.filename .. "], it might not be played!")endendendif begin_with_nalu_hdr then-- *.265 raw file format seams that every nalu start with 0x00000001stream_info.file:write("\x00\x00\x00\x01")endstream_info.file:write(str_bytes)stream_info.counter2 = stream_info.counter2 + 1-- update progress window's progress barif stream_info.counter > 0 and stream_info.counter2 < stream_info.counter thenpgtw:update(stream_info.counter2 / stream_info.counter)endendend-- read RFC3984 about single nalu/ap/fu H265 payload format of rtp-- single NALU: one rtp payload contains only NALUlocal function process_single_nalu(stream_info, h265)write_to_file(stream_info, h265:tvb():raw(), true, true)end-- APs: one rtp payload contains more than one NALUslocal function process_ap(stream_info, h265)local h265tvb = h265:tvb()local offset = 2repeatlocal size = h265tvb(offset,2):uint()write_to_file(stream_info, h265tvb:raw(offset+2, size), true, true)offset = offset + 2 + sizeuntil offset >= h265tvb:len()end-- FUs: one rtp payload contains only one part of a NALU (might be begin, middle and end part of a NALU)local function process_fu(stream_info, h265)local h265tvb = h265:tvb()local start_of_nalu = (h265tvb:range(2, 1):bitfield(0,1) ~= 0)local end_of_nalu = (h265tvb:range(2, 1):bitfield(1,1) ~= 0)if start_of_nalu then-- start bit is set then save nalu header and bodylocal nalu_hdr_0 = bit.bor(bit.band(h265:get_index(0), 0x81), bit.lshift(bit.band(h265:get_index(2),0x3F), 1))local nalu_hdr_1 = h265:get_index(1)write_to_file(stream_info, string.char(nalu_hdr_0, nalu_hdr_1) .. h265tvb:raw(3), start_of_nalu, end_of_nalu)else-- start bit not set, just write part of nalu bodywrite_to_file(stream_info, h265tvb:raw(3), start_of_nalu, end_of_nalu)endend-- call this function if a packet contains h265 payloadfunction my_h265_tap.packet(pinfo,tvb)if stream_infos == nil then-- not triggered by button event, so do nothing.returnendlocal h265s = { f_h265() } -- using table because one packet may contains more than one RTPfor i,h265_f in ipairs(h265s) doif h265_f.len < 5 thenreturnendlocal h265 = h265_f.range:bytes() local hdr_type = h265_f.range(0,1):bitfield(1,6)local stream_info = get_stream_info(pinfo)if hdr_type > 0 and hdr_type < 48 then-- Single NALUprocess_single_nalu(stream_info, h265)elseif hdr_type == 48 then-- APsprocess_ap(stream_info, h265)elseif hdr_type == 49 then-- FUsprocess_fu(stream_info, h265)elsetwappend("Error: No.=" .. tostring(pinfo.number) .. " unknown type=" .. hdr_type .. " ; we only know 1-47(Single NALU),48(APs),49(FUs)!")endendend-- close all open fileslocal function close_all_files()twappend("")local index = 0;if stream_infos thenlocal no_streams = truefor id,stream in pairs(stream_infos) doif stream and stream.file thenstream.file:flush()stream.file:close()stream.file = nilindex = index + 1twappend(index .. ": [" .. stream.filename .. "] generated OK!")local anony_fuc = function ()twappend("ffplay -x 640 -y 640 -autoexit "..stream.filename)--copy_to_clipboard("ffplay -x 640 -y 640 -autoexit "..stream.filepath)os.execute(ffmpeg_path.."ffplay -x 640 -y 640 -autoexit "..stream.filepath)endtw:add_button("Play "..index, anony_fuc)no_streams = falseendendif no_streams thentwappend("Not found any H.265 over RTP streams!")elsetw:add_button("Browser", function () browser_open_data_file(temp_path) end)endendendfunction my_h265_tap.reset()-- do nothing nowendtw:set_atclose(function ()my_h265_tap:remove()if Dir.exists(temp_path) thenDir.remove_all(temp_path)endend)local function export_h265()pgtw = ProgDlg.new("Export H265 to File Process", "Dumping H265 data to file...")first_run = truestream_infos = {}-- first time it runs for counting h.265 packets and finding SPS and PPSretap_packets()first_run = false-- second time it runs for saving h265 data to target file.retap_packets()close_all_files()-- close progress windowpgtw:close()stream_infos = nilendtw:add_button("Export All", function ()export_h265()end)tw:add_button("Set Filter", function ()tw:close()dialog_menu()end)endlocal function dialog_func(str)filter_string = strexport_h265_to_file()endfunction dialog_menu()new_dialog("Filter Dialog",dialog_func,"Filter")endlocal function dialog_default()filter_string = get_filter()export_h265_to_file()end-- Find this feature in menu "Tools"register_menu("Video/Export H265", dialog_default, MENU_TOOLS_UNSORTED)
end
1.2 rtp_h365_extractor.lua放在 Wireshark 安装目录中
1.3 修改init.lua配置文件
2. 流分析
2.1. 解码为RTP数据包
使用wireshark抓包工具抓取码流包(如下图),基于UDP传输。
选中其中一个数据包(包要选择正确,可根据protocol的类型选择),右键选择解码为(如下图)。
新增解码规则,选择解码为RTP流(如下图)。
解码后,可看到数据包解码成了RTP包(如下图)。
导出h265视频流
2.2. vlc播放视频流
相关文章:

wireshark抓rtp包,提取出H265裸流数
调试rtsp收发流时,经常会需要抓包以确认是网络问题还是程序问题还是其它问题。通过tcpdump或者wireshark抓到的包通常是rtp流,保存为.pcap格式文件后中,可通过wireshark进行解析,得出h264裸流,并保存为文件。 1.wires…...

Excel往Word复制表格时删除空格
1.背景 在编写文档,经常需要从Excel往Word里复制表格 但是复制过去的表格前面会出现空格(缩进) 再WPS中试了很多方法,终于摆脱了挨个删除的困扰 2. WPS排版中删除 选择表格菜单栏-选在【开始】-【排版】选择【更多段落处理】-【段…...

客户机操作系统已禁用 CPU。请关闭或重置虚拟机(解决)
解决: 关闭虚拟机进入设置点击处理器给虚拟化引擎两个勾上确认后重新即可...

UnityShaderLab —— 简单的流光shader
原理: 就是在原先的模型表面叠加一层可以流动的图片, 算法代码: float2 tex; tex float2(i.uv.x - _Time.x * _Speed,i.uv.y); fixed4 col0 tex2D(_Tex, tex)* _Strenth; fixed4 col1 tex2D(_MainTex, i.uv); return col0 col1; 这里…...

代理IP在保护跨境商家网络安全中的重要作用
在当前全球化的背景下,跨境电商成为一种重要的商业模式,越来越多的商家涌入国际市场,商家们通过互联网平台将商品远销国外,但网络安全风险随之而来。跨境商家因为需要处理大量的在线交易和产品数据,如果未能对这些敏感…...

2核4G服务器支持多少用户同时在线访问?卡不卡?
腾讯云轻量2核4G5M带宽服务器支持多少人在线访问?5M带宽下载速度峰值可达640KB/秒,阿腾云以搭建网站为例,假设优化后平均大小为60KB,则5M带宽可支撑10个用户同时在1秒内打开网站,从CPU内存的角度,网站程序效…...

[Error]在Swift项目Build Settings的Preprocessor Macros中定义的宏无效的问题
问题 如图,在Build Settings -> Preprocessor Macros中添加了ISADEMO1。但在代码中判断无效,还是会输出“isn’t ADemo” #if ISADEMOprint("is ADemo") #elseprint("isnt ADemo") #endif解决 如图,要让Preproces…...

网格管理安全巡检系统—助企业全面安全检查
通过应用安全巡检管理系统,企业能更好地管理控制安全风险,保障员工生命安全和财产安全,避免出现各种危险隐患,帮助企业快速提高生产发展实力。 一、凡尔码搭建安全巡检系统的功能 1.巡检计划:帮助用户制定巡检计划,包括…...
【Java】replace替换方法
String 替换方法 replace() 方法用于将目标字符串中的指定字符(串)替换成新的字符(串)replaceFirst() 方法用于将目标字符串中匹配某正则表达式的第一个子字符串替换成新的字符串replaceAll() 方法用于将目标字符串中匹配某正则表…...
CentOS yum update
详情内容 CentOS yum update升级命令详解,包括yum check-update,yum update,yum install等升级安装命令详细使用方法。 1.列出所有可更新的软件清单 命令: yum check-update 2.安装所有更新软件 命令: yum updat…...
/etc/profile与~/.bash_profile的区别
/etc/profile和~/.bash_profile都是用于存储用户的配置文件的,但它们的作用范围和加载顺序有所不同。 /etc/profile是系统级的配置文件,它应用于所有用户。当用户登录时,系统会首先加载/etc/profile。这个文件存储了系统范围的环境变量、系统…...

vue+element实现电商商城礼品代发网,商品、订单管理
一、项目效果图 1.首页 2.登录 版本2: 3.注册 4.找回密码 5.立即下单 6.商品详情 7.个人中心-工作台 8.个人中心-订单列表 9.订单中心-包裹列表 10.个人中心-工单管理 11.我的钱包 12.实名认证 13.升级vip 14.个人中心-推广赚钱 二、关键源码 1.路由配置 impor…...

Python接口自动化-requests模块之post请求
一、源码解析 def post(url, dataNone, jsonNone, **kwargs):r"""Sends a POST request.:param url: URL for the new :class:Request object.:param data: (optional) Dictionary, list of tuples, bytes, or file-likeobject to send in the body of the :cl…...
DDoS检测防御实现方案
流量采集模式 通过分光器将流量直接镜像到攻击检测器,收包采用DPDK库。 当前整机流量、源IP信息、连接数 、连接内容(五元组等)的信息汇聚 当发生告警时采样原始数据包, 采用固定采样算法 基于检测对象的TCP syn ack psh ack established的个数、流量…...

ArcGIS: 第二届全国大学生GIS技能大赛(广西师范学院)详解-下午题
目录 01 题目 02 思路和实操 2.1 流域提取-思路 2.2 流域提取-实操 2.2.1 获取DEM 编辑 2.2.2 水文分析-提取流域基于单出水口 2.3 河网分级-思路 2.4 河网分级-实操 2.4.1 提取河道网络 2.4.2 河网分级 编辑 2.5 子流域提取和处理-思路 2.6 子流域提取和处理-实…...

vue七牛云视频直传
完成后样式: 下面的代码是我自己项目里面用到的,一些判断看自己情况去掉,用的是element-ui组件 安装 uuid 库。你可以使用 npm 或 yarn 来完成安装。在终端中执行以下命令: npm install uuidhtml部分 <el-upload class&quo…...

云原生Kubernetes:K8S集群版本升级(v1.20.15 - v1.22.14)
目录 一、理论 1.K8S集群升级 2.集群概况 3.升级集群(v1.21.14) 4.验证集群(v1.21.14) 5.升级集群(v1.22.14) 6.验证集群 (v1.22.14) 二、实验 1.升级集群(v1.21.14) 2.验…...

VUE树结构实现
实现效果: 数据库表结构如下: 要求:需要有parentId,id。parentId就是父记录的id 表数据要求:一定不要让一条记录的parentid和id相同 前端代码: 注意:el-table标签里面需要加上属性,才可以有下拉箭头的样式 <el-table v-loading="listLoading" :data...

Node.js 正在逐渐被淘汰!Bun 1.0 正在改变 JavaScript 的游戏规则
在深入讨论之前,我们需要解释什么是 JavaScript 运行时以及为什么我们应该关心其速度。 想象一下,你用 JavaScript 写了一个故事,需要有人大声读出来。JavaScript 运行时就像是那个友好的叙述者,为你的故事赋予生命!它…...

[Machine Learning][Part 5]监督学习——逻辑回归
之前文章中提到监督学习的应用可分为两类:线性回归和逻辑回归。和线性回归不同,逻辑回归输出只有0和1。对于一个逻辑回归任务,可以先使用线性回归来预测y。然而我们希望逻辑回归预测模型输出的是0和1,为了达到这个目的,…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...