用Wireshark解码H.264
H264,你不知道的小技巧-腾讯云开发者社区-腾讯云
这篇文章写的非常好
这里仅做几点补充
init.lua内容:
-- Set enable_lua to false to disable Lua support.
enable_lua = trueif not enable_lua thenreturn
end-- If false and Wireshark was started as (setuid) root, then the user
-- will not be able to execute custom Lua scripts from the personal
-- configuration directory, the -Xlua_script command line option or
-- the Lua Evaluate menu option in the GUI.
-- Note: Not checked on Windows. running_superuser is always false.
--run_user_scripts_when_superuser = truedofile(DATA_DIR.."rtp_h264_extractor.lua")
init.lua放到了这个目录:
C:\Program Files\Wireshark\plugins
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*]]dolocal MAX_JITTER_SIZE = 50local 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 ~= "" thenreturn string.format("%s and (%s)", fh, fd)elsereturn fhendendlocal h264_tap = Listener.new("ip", dump_filter(get_filter()))local text_window = TextWindow.new("h264 extractor")local filename = ""local seq_payload_table = { }local pass = 0local packet_count = 0local max_packet_count = 0local fu_info = nillocal pre_seq = 0;local function log(info)text_window:append(info)text_window:append("\n")end-- get_preference is only available since 3.5.0if get_preference thenfilename = get_preference("gui.fileopen.dir") .. "/" .. os.date("video_%Y%m%d-%H%M%S.264")elsefilename = "dump.264"endlog("Dumping H264 stream to " .. filename)local fp = io.open(filename, "wb")if fp == nil thenlog("open dump file fail")endlocal function seq_compare(left, right)if math.abs(right.key - left.key) < 1000 thenreturn left.key < right.keyelsereturn left.key > right.keyendendlocal function dump_single_nal(h264_payload)fp:write("\00\00\00\01")fp:write(h264_payload:tvb()():raw())fp:flush()endlocal function dump_fu_a(fu_info)if fu_info.complete == true thenlog("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) dofp:write(obj:tvb()():raw(2))endfp:flush()elselog("Incomplete NAL from FUs, dropped")endendlocal 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 foundfu_info = { }fu_info.payloads = { }fu_info.seq = seqfu_info.complete = truefu_info.nal_header = nal_headertable.insert(fu_info.payloads, h264_data)log("Fu start: seq = "..tostring(seq))returnendif fu_info == nil thenlog("Incomplete FU found: No start flag, dropped")returnendif seq ~= (fu_info.seq + 1)% 65536 thenlog("Incomplete FU found: fu_info.seq = "..tostring(fu_info.seq)..", input seq = "..tostring(seq))fu_info.complete = false;returnendfu_info.seq = seqtable.insert(fu_info.payloads, h264_data)if bit.band(fu_header, 0x40) ~= 0 then-- fu end flag foundlog("Fu stop: seq = "..tostring(seq))dump_fu_a(fu_info)fu_info = nilendendlocal function handle_stap_a(h264_data)log("start dump stap nals")offset = 1 -- skip nal header of STAP-Arepeatsize = h264_data:tvb()(offset, 2):uint()offset = offset + 2local 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 + sizeuntil offset >= h264_data:tvb():len()fp:flush()log("finish dump stap nals")endlocal 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 packetif fu_info ~= nil thenlog("Incomplete FU found: No start flag, dropped")fu_info = nilenddump_single_nal(h264_data)--log("tap.packet: "..", single nal packet dumpped, naltype = "..tostring(naltype)..", len = "..tostring(packet.len))elseif naltype == 28 then-- FU-Ahandle_fu_a(seq, h264_data)elseif naltype == 24 then-- STAP-Aif fu_info ~= nil thenlog("Incomplete FU found: No start flag, dropped")fu_info = nilendhandle_stap_a(h264_data)elselog("tap.packet: "..", Unsupported nal, naltype = "..tostring(naltype))endendlocal function on_jitter_buffer_output()table.sort(seq_payload_table, seq_compare)if #seq_payload_table > 0 thenlog("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)endendlocal function jitter_buffer_finilize()for i, obj in ipairs(seq_payload_table) dolog("jitter_buffer_finilize: seq = "..tostring(obj.key)..", payload len = "..tostring(obj.value:len()))on_ordered_h264_payload(obj.key, obj.value)endendlocal function on_h264_rtp_payload(seq, payload)local cur_seq = seq.value--log("on_h264_rtp_payload: seq = "..tostring(seq.value)..", payload len = "..tostring(payload.len)..",pre_seq = "..pre_seq..",cur_seq = "..cur_seq..",packet_count = "..packet_count)if packet_count == 0 thenpre_seq = cur_seqelseif cur_seq == pre_seq thenpacket_count = packet_count + 1--log("on_h264_rtp_payload, duplicate seq = "..tostring(seq.value)..",packet_count = "..packet_count)returnelsepre_seq = cur_seqendendpacket_count = packet_count + 1table.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 thenon_jitter_buffer_output()endendfunction h264_tap.packet(pinfo, tvb)local payloadTable = { h264_data() }local seqTable = { rtp_seq() }if (#payloadTable) < (#seqTable) thenlog("ERROR: payloadTable size is "..tostring(#payloadTable)..", seqTable size is "..tostring(#seqTable))returnendif pass == 0 thenfor i, payload in ipairs(payloadTable) domax_packet_count = max_packet_count + 1endelsefor i, payload in ipairs(payloadTable) doon_h264_rtp_payload(seqTable[1], payload)endif packet_count == max_packet_count thenjitter_buffer_finilize()endendendfunction h264_tap.reset()endfunction h264_tap.draw()endlocal function remove()if fp thenfp:close()fp = nilendh264_tap:remove()endlog("Start")text_window:set_atclose(remove)log("phase 1")pass = 0retap_packets()log("phase 2: max_packet_count = "..tostring(max_packet_count))pass = 1retap_packets()if fp ~= nil thenfp:close()fp = nillog("Video stream written to " .. filename)endlog("End")endregister_menu("Extract h264 stream from RTP", extract_h264_from_rtp, MENU_TOOLS_UNSORTED)
end
该文件放到了这里:
C:\Program Files\Wireshark
此外,Elecard StreamEye Tools可以到这里下载:
Download video analysis and monitoring applications| Elecard: Video Compression GuruDownload Elecard products for video analysis and monitoring, encoding and decoding video of various formats.
https://www.elecard.com/software
相关文章:
用Wireshark解码H.264
H264,你不知道的小技巧-腾讯云开发者社区-腾讯云 这篇文章写的非常好 这里仅做几点补充 init.lua内容: -- Set enable_lua to false to disable Lua support. enable_lua trueif not enable_lua thenreturn end-- If false and Wireshark was start…...
Flink中几个关键问题总结
硬核!八张图搞懂 Flink 端到端精准一次处理语义 Exactly-once(深入原理,建议收藏) Flink可靠性的基石-checkpoint机制详细解析 硬核!一文学完Flink流计算常用算子(Flink算子大全)...
华为配置ARP安全综合功能实验
华为配置ARP安全综合功能实验 组网图形 图1 配置ARP安全功能组网图 ARP安全简介配置注意事项组网需求配置思路操作步骤配置文件 ARP安全简介 ARP(Address Resolution Protocol)安全是针对ARP攻击的一种安全特性,它通过一系列对ARP表项学…...
new mars3d.layer.XyzLayer({的rectangle瓦片数据的矩形区域范围说明
new mars3d.layer.XyzLayer({的rectangle瓦片数据的矩形区域范围说明 2.这个xyz图层的矩形区域范围rectangle从图层文件中无法获取,但是看图层文件可以知道这个是12-21级的数据。 3.一般这个图层数据文件服务会有提供相应的rectangle范围,在服务的xml文…...
数据分析之Tebleau可视化:折线图、饼图、环形图
1.折线图的绘制 方法一: 拖入订单日期和销售金额,自动生成一个折线图 方法二: 选中订单日期和销售金额(摁住ctrl可以选择多个纬度) 点击右边的智能推荐,选择折线图 2.双线图的绘制、双轴的设置 方法一&…...
【Frida】【Android】 07_爬虫之网络通信库HttpURLConnection
🛫 系列文章导航 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446【Frida】【Android】03_RPC https://bl…...
算法2.6基数排序
基数排序 属于分配式排序,又称桶子法,通过键值的各个位上的值,将要排序的元素分配至某些桶中,达到排序的作用. 基数排序属于稳定性排序,是效率高的稳定性排序法 是桶排序的扩展,将整数按照位数进行切割,再按各个位数进行比较 是用空间换时间的经典算法 在使用8kw个数据进行…...
redis -List
一,List(列表) 1,所应用场景 list实际上是一个链表,before Node after , left, right 都可以插入值如果key不存在,则创建新的链表如果key存在,新增内容如果移除了所有值,空链表,也代表不存在在…...
ARMv8-A架构下的外部debug模型(external debug)简介
Armv8-A external debug Armv8-A debug模型一,外部调试 External debug 简介二,Debug state2.1 Debug state的进入与退出 三,DAP,Debug Access Port3.1 EDSCR, External Debug Status and Control Register调试状态标识࿰…...
DevOps入门
DevOps入门 1. 基础概念和原则 了解DevOps的定义、历史和主要目标 DevOps是一种将软件开发(Dev)与信息技术运维(Ops)结合起来的文化、运动或实践,旨在缩短系统开发生命周期,同时提供高质量的持续交付。DevOps的历史可以追溯到敏捷软件开发的兴起,它强调了开发和运维团队之…...
Docker搭建私有镜像仓库
1.Docker镜像仓库 搭建镜像仓库可以基于Docker官方提供的DockerRegistry来实现。 官网地址:https://hub.docker.com/_/registry 1.1.简化版镜像仓库 Docker官方的Docker Registry是一个基础版本的Docker镜像仓库,具备仓库管理的完整功能,…...
流行的API架构学习
几种流行的API架构风格图 SOAP(Simple Object Access Protocol) 优点:SOAP 是一种基于 XML 的通信协议,具有良好的跨平台和跨语言支持。它提供了丰富的安全性和事务管理功能,并支持复杂的消息交换模式。 缺点…...
问题解决:Fatal Python error: initfsencoding: unable to load the file system codec
问题: "D:\...Climb_C_site\venv\Scripts\python.exe" "D:\...\Small_Case\change_suffix.py" Fatal Python error: initfsencoding: unable to load the file system codec ModuleNotFoundError: No module named encodingsCurrent thread 0x…...
WPF —— TreeView树形控件
1 TreeView简介 TreeView 表示一个控件,该控件在树结构(其中的项可以展开和折叠)中显示分层数据。 TreeView 是一个 ItemsControl,这意味着它可以包含任何类型的对象的集合 (,例如字符串、图像或面板) 。 2 Tree Vie…...
2024.2.20力扣每日一题——从前序和中序遍历序列构建二叉树
2024.2.20 题目来源我的题解方法一 递归方法二 迭代 题目来源 力扣每日一题;题序:105 我的题解 方法一 递归 前序特点:[ 根节点, [左子树的前序遍历结果], [右子树的前序遍历结果] ]中序特点:[ [左子树的中序遍历结果], 根节点…...
c++ 小游戏(2种)
目录 介绍 游戏1 游戏2 介绍 因为DEV C的编译环境较小,所以大部分的游戏代码都无法在此上运行,我收集了一部分摸鱼小游戏的源码,在此呈现,如果有能在DEV C上运行的我会先作声明: 游戏1 扫雷 #include<stdio.…...
电阻详解:定义、公式、影响因素及电阻器类型解析
电阻定义 电阻是指当电流通过导体时,导体对电流流动所呈现的阻碍作用的物理量。它是电路元件的一个基本参数,用于量化导体阻止电荷定向移动的能力。#电阻#的大小决定了通过导体的电流与两端电压之间的关系,遵循欧姆定律,即在恒定…...
LabVIEW动车组谐波分析与检测系统
LabVIEW动车组谐波分析与检测系统 随着中国高速铁路网络的快速发展,动车组数量和运行速度的不断提升,其产生的谐波问题对电网产生了不小的影响。基于图形化编程语言LabVIEW,开发了一套动车组谐波分析与检测系统,旨在实时监控与分…...
H5移动端 Vue3 + vue-virtual-scroller 实现长列表性能优化
文章目录 安装 vue-virtual-scroller引入📢注意事项使用基础使用上拉加载下拉刷新 移动端在渲染长列表时 大量dom节点的渲染和重绘重排会导致页面卡顿、滚动不流畅、设备耗电加快、影响移动设备电池寿命等性能问题 这里分享使用【虚拟滚动】方案进行长列表优化&…...
第20章-IP路由原理
目录 1. 概述 2. 路由表 3. 查表规则 4. 路由来源类型 5. 路由优先级 6. 路由的度量值 7. 路由器写表规则 1. 概述 1. 定义 路由器:异构网络互联机制; 路由:指导路由器如何进行数据发送的路径信息; 路由表:目的地址、下一跳、出接口等; 2. IP连通的条件 沿途的每…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
