当前位置: 首页 > news >正文

用 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.icon-default.png?t=N7T8https://www.elecard.com/software

相关文章:

用 Wireshark 解码 H.264

H264&#xff0c;你不知道的小技巧-腾讯云开发者社区-腾讯云 这篇文章写的非常好 这里仅做几点补充 init.lua内容&#xff1a; -- Set enable_lua to false to disable Lua support. enable_lua trueif not enable_lua thenreturn end-- If false and Wireshark was start…...

鸿蒙TypeScript学习第10天:【String(字符串)】

1、TypeScript String&#xff08;字符串&#xff09; String 对象用于处理文本&#xff08;字符串&#xff09;。 语法 var txt new String("string"); 或者更简单方式&#xff1a; var txt "string"; 2、String 对象属性 下表列出了 String 对象支…...

【201】Java8读取JSON树形结构并插入到MySQL数据库表中

我写了一个 maven 项目的 Demo&#xff0c;用来演示 JAVA8 如何读取 JSON 文件树形结构&#xff0c;并将这种树形结构保存到 MySQL 中。 json文件 city.json {"name": "山东省","sub": [{"name": "青岛市","sub"…...

AI“复活”:慰藉心灵还是触碰禁忌?一文看懂技术与伦理的较量|TodayAI

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;其应用领域也越来越广泛&#xff0c;不仅仅局限于数据分析、机器人自动化等传统领域&#xff0c;更是延伸到了一些人们曾经认为只存在于科幻小说中的领域。近年来&#xff0c;使用AI技术“复活”逝者的概念&a…...

Jackson @JsonUnwrapped注解扁平化 序列化反序列化数据

参考资料 Jackson 2.x 系列【7】注解大全篇三JsonUnwrapped 以扁平的数据结构序列化/反序列化属性Jackson扁平化处理对象 目录 一. 前期准备1.1 前端1.2 实体类1.3 Controller层 二. 扁平化序列反序列化数据2.1 序列化数据2.2 反序列化数据 三. 前缀后缀处理属性同名四. Map数…...

日期时间相关的类

分界线jdk8 jdk8之前和之后分别提供了一些日期和时间的类&#xff0c;推荐使用jdk8之后的日期和时间类 Date类型 这是一个jdk8之前的类型&#xff0c;其中有很多方法已经过时了&#xff0c;选取了一些没有过时的API //jdk1.8之前的日期 Date Date date new Date(); // 从1970年…...

微信小程序脚本的执行顺序

在小程序中的脚本执行顺序和浏览器中有所不同。 小程序的执行的入口文件是 app.js 。 并且会根据其中 require 的模块顺序决定文件的运行顺序&#xff0c;代码是一个 app.js 示例。 app.js /* a.js console.log(a.js) */ var a require(./a.js) console.log(app.js)/* b.js co…...

zabbix监控警告

监控概述 对服务的管理&#xff0c;不能仅限于可用性。 还需要服务可以安全、稳定、高效地运行。 监控的目的&#xff1a;早发现、早治疗。 被监控的资源类型&#xff1a; 公开数据&#xff1a;对外开放的&#xff0c;不需要认证即可获取的数据 私有数据&#xff1a;对外不…...

YOLOv9架构图分享

YOLOv9是YOLO (You Only Look Once)系列实时目标检测系统的最新迭代。它建立在以前的版本之上&#xff0c;结合了深度学习技术和架构设计的进步&#xff0c;以在目标检测任务中实现卓越的性能。通过将可编程梯度信息(PGI)概念与广义ELAN (GELAN)架构相结合&#xff0c;YOLOv9在…...

全自动封箱机的工作原理:科技与效率的完美结合

随着科技的不断发展&#xff0c;越来越多的自动化设备走进了我们的日常生活和工业生产中。其中&#xff0c;全自动封箱机作为物流包装领域的重要一环&#xff0c;凭借其高效、精准的工作性能&#xff0c;正逐渐成为提升生产效率、降低劳动成本的得力助手。星派就来与大家深入探…...

【管理咨询宝藏48】AA银行信息科技提升分析报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏48】AA银行信息科技提升分析报告 【格式】PPT版本&#xff0c;可编辑 【关键词】战略规划、商业分析、管理咨询 【强烈推荐】这是一套市面上非常…...

循序表实战——基于循序表的通讯录

前言&#xff1a;本篇文章主要是利用顺序表作为底层&#xff0c; 实现一个通讯录。偏向于应用&#xff0c; 对于已经学习过c的友友们可能没有难度了已经。没有学习过c的友友&#xff0c; 如果顺序表不会写&#xff0c; 或者说没有自己实现过&#xff0c; 请移步学习顺序表相关内…...

Java编程规范及最佳实践

文章目录 一、命名规范二、代码风格规范三、注释规范四、推荐的编程实践五、类和接口六、异常处理七、可见性八、并发九、代码复用十、代码组织和模块化十一、Java集合框架十二、输入验证十三、资源管理十四、文档和注释十五、测试和代码质量十六、代码可读性十七、性能优化十八…...

90天玩转Python—07—基础知识篇:Python中运算符详解

90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…...

C语言 位域

C 语言的位域&#xff08;bit-field&#xff09;是一种特殊的结构体成员&#xff0c;允许我们按位对成员进行定义&#xff0c;指定其占用的位数。 如果程序的结构中包含多个开关的变量&#xff0c;即变量值为 TRUE/FALSE&#xff0c;如下&#xff1a; struct {unsigned int w…...

【LeetCode热题100】【技巧】颜色分类

题目链接&#xff1a;75. 颜色分类 - 力扣&#xff08;LeetCode&#xff09; 只需排序三种&#xff0c;可以记录0和1的个数&#xff0c;然后直接原地赋值 class Solution { public:void sortColors(vector<int> &nums) {int zero 0, one 0;for (auto &num: n…...

笔记本电脑win7 Wireless-AC 7265连不上wifi6

1.背景介绍 旧路由器连接人数有限&#xff0c;老旧&#xff0c;信号不稳定更换了新路由器&#xff0c;如 TL-XDR5430易展版用户电脑连不上新的WIFI网络了&#xff0c;比较着急 核心问题&#xff1a;有效解决笔记本连接wifi上网问题&#xff0c;方法不限 2.环境信息 Windows…...

Linux gcc day5粘滞位

粘滞位 背景&#xff1a;一定时在一个公共目录&#xff08;root创建&#xff09;下。进行临时文件的操作 Linux系统中有很多人&#xff0c;我们需要在一个公共目录下&#xff0c;进行临时文件的操作&#xff08;增删查改&#xff09; 创建一个根目录下的dir&#xff08;mytmp…...

单片机按键消抖常用的软硬件方法

一&#xff1a;什么是开关抖动&#xff1f; 当我们按下按钮或拨动开关或微动开关时&#xff0c;两个金属部件会接触以短路电源。但它们不会立即连接&#xff0c;而是金属部件在实际稳定连接之前连接和断开几次。释放按钮时也会发生同样的事情。这会导致误触发或多次触发&#…...

钉钉自建应用-下载excel(h5)

由于不同手机对于文件下载有不同的支持&#xff0c;而且文件路径也不一样&#xff0c;找起来十分的麻烦。所以&#xff0c;最好是找到一个都支持的方法。还好&#xff0c;钉钉官网提供了网盘&#xff0c;我们可把文件保存到钉钉自带的网盘&#xff0c;这样方便查找。 这里需要…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》

近日&#xff0c;嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》&#xff0c;海云安高敏捷信创白盒&#xff08;SCAP&#xff09;成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天&#xff0c;网络安全已成为企业生存与发展的核心基石&#xff0c;为了解…...

算法刷题-回溯

今天给大家分享的还是一道关于dfs回溯的问题&#xff0c;对于这类问题大家还是要多刷和总结&#xff0c;总体难度还是偏大。 对于回溯问题有几个关键点&#xff1a; 1.首先对于这类回溯可以节点可以随机选择的问题&#xff0c;要做mian函数中循环调用dfs&#xff08;i&#x…...