如何将 H264 RTP 流从 PCAP 转换为可播放的视频文件

Posted

技术标签:

【中文标题】如何将 H264 RTP 流从 PCAP 转换为可播放的视频文件【英文标题】:How to convert H264 RTP stream from PCAP to a playable video file 【发布时间】:2013-05-09 06:15:54 【问题描述】:

我在 PCAP 文件中捕获了 H264 流,并尝试从数据中创建媒体文件。容器并不重要(avi、mp4、mkv、...)。 当我使用videosnarf或rtpbreak(结合python代码在每个数据包之前添加00 00 00 01)然后使用ffmpeg时,只有当输入帧速率恒定(或接近恒定)时结果才可以。但是,当输入为 vfr 时,结果播放速度过快(在极少数情况下播放速度过慢)。 例如:

videosnarf -i capture.pcap –c ffmpeg -i H264-media-1.264 output.avi

在对该问题进行了一些调查后,我现在相信由于videosnarf(和rtpbreak)正在从数据包中删除RTP标头,因此时间戳丢失并且ffmpeg将输入数据称为cbr。

    我想知道是否有办法通过(在单独的文件上?) ffmpeg 的时间戳向量或任何其他信息,因此 结果将被正确创建? 有没有其他方法可以将数据从 PCAP 文件中取出并播放或转换后再播放? 由于所有工作都是在 Python 中完成的,因此也欢迎任何可以帮助完成工作的库/模块建议(即使需要一些编码)。

注意:所有工作都是离线完成的,输出没有限制。它可以是 cbr/vbr,任何可播放的容器和转码。我唯一的“限制”:它应该都在 linux 上运行……

谢谢 是的

一些附加信息: 由于没有为 FFMPEG 提供时间戳数据,我决定尝试一种不同的方法:跳过 videonarf 并使用 Python 代码将数据包直接通过管道传输到 ffmpeg(使用“-f -i -”选项),但随后它拒绝接受除非我提供 SDP 文件... 如何提供 SDP 文件?它是一个额外的输入文件吗? ("-i config.sdp")

下面的代码是一次不成功的尝试:

import time  
import sys  
import shutil  
import subprocess  
import os  
import dpkt  

if len(sys.argv) < 2:  
    print "argument required!"  
    print "txpcap <pcap file>"  
    sys.exit(2)  
pcap_full_path = sys.argv[1]  

ffmp_cmd = ['ffmpeg','-loglevel','debug','-y','-i','109c.sdp','-f','rtp','-i','-','-na','-vcodec','copy','p.mp4']  

ffmpeg_proc = subprocess.Popen(ffmp_cmd,stdout = subprocess.PIPE,stdin = subprocess.PIPE)  

with open(pcap_full_path, "rb") as pcap_file:  
    pcapReader = dpkt.pcap.Reader(pcap_file)  
    for ts, data in pcapReader:  
        if len(data) < 49:  
            continue  
        ffmpeg_proc.stdin.write(data[42:])

sout, err = ffmpeg_proc.communicate()  
print "stdout ---------------------------------------"  
print sout  
print "stderr ---------------------------------------"  
print err  

一般来说,这会将数据包从 PCAP 文件传送到以下命令:

ffmpeg -loglevel debug -y -i 109c.sdp -f rtp -i - -na -vcodec copy p.mp4

SDP 文件:[RTP 包括动态负载类型#109,H264]

v=0 o=- 0 0 IN IP4 ::1 s=没有名字 c=IN IP4 ::1 t=0 0 a=工具:libavformat 53.32.100 m=视频 0 RTP/AVP 109 a=rtpmap:109 H264/90000 a=fmtp:109 打包模式=1;profile-level-id=64000c;sprop-parameter-sets=Z2QADKwkpAeCP6wEQAAAAwBAAAAFI8UKkg==,aMvMsiw=; b=AS:200

结果:

ffmpeg 版本 0.10.2 版权所有 (c) 2000-2012 FFmpeg 开发者 使用 gcc 4.4.6 20110731(红帽)于 2012 年 3 月 20 日 04:34:50 构建 4.4.6-3) 配置: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 --mandir=/usr/share/man --enable-shared --enable-runtime -cpudetect --enable-gpl --enable-version3 --enable-postproc --enable-avfilter --enable-pthreads --enable-x11grab --enable-vdpau --disable-avisynth --enable-frei0r --enable -libopencv --enable-libdc1394 --enable-libdirac --enable-libgsm --enable-libmp3lame --enable-libnut --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable- librtmp --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid --extra-cflags='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC' --disable-stripping libavutil 51. 35.100 / 51 . 35.100 libavcodec 53. 61.100 / 53. 61.100 libavformat 53. 32.100 / 53. 32.100 libavdevice 53. 4.100 / 53. 4.100 libavfilter 2. 61.100 / 2. 61.100 libswscale 2. 1.100 / 2. 1.100 libswresample 0. 6.100 / 0. 6.100 libpostproc 52. 0.100 / 52. 0.100 [sdp @ 0x15c0c00] 格式 sdp 使用 size=2048 和 score=50 [sdp @ 0x15c0c00] 视频编解码器集进行探测 to:h264 [NULL @ 0x15c7240] RTP 打包模式:1 [NULL @ 0x15c7240] RTP 配置文件 IDC:64 配置文件 IOP:0 级别:c [NULL @ 0x15c7240] Extradata 设置为 0x15c78e0 (size: 36)!error,_recognition 分开:1; 1 [h264 @ 0x15c7240] error,_recognition 组合:1; 10001 [sdp @ 0x15c0c00] 流 0 解码失败 [sdp @ 0x15c0c00] 找不到编解码器参数(视频:h264)[sdp @ 0x15c0c00] 从比特率估计持续时间,这可能不准确 109c.sdp:找不到编解码器参数 Traceback(最近 最后调用):文件“./ffpipe.py”,第 26 行,在 ffmpeg_proc.stdin.write(data[42:]) IOError: [Errno 32] Broken pipe

(请原谅上面的大量内容,编辑一直在抱怨代码没有缩进好吗??)

我正在处理这个问题好几天...任何帮助/建议/提示将不胜感激。

【问题讨论】:

运气好吗?寻找相同的 寻找同样的东西 如果你会写c/c++,你可以修改videosnarf将h264数据传递给libavformat。但是,如果您从未使用过 libavformat,则需要时间来适应它,但您可以从 ffmpeg 邮件列表中获取有关如何操作的帮助。 问题以一种“肮脏”的方式解决了...: @yoosha 如果您找到了解决方案,请发布并接受它作为答案。这有助于其他用户知道此问题已解决。 【参考方案1】:

我很确定(明智地)唯一的方法是使用数据包之间的网络时间作为延迟来重播 rtp 流。

问题在于可变帧速率,因为 h264 周围没有容器可以告诉它在这一帧和最后一帧之间经过了 X 时间,它不知道如何计时。

如果 h264 流是恒定帧速率,您可能能够将 rtp 数据推送到 ffmpeg,而无需设置输入 fps 的时间,但我不知道有任何类似的 h264 rtp 流。您最有可能看到的是视频流播放方式在某些部分快而在其他部分慢。

【讨论】:

以上是关于如何将 H264 RTP 流从 PCAP 转换为可播放的视频文件的主要内容,如果未能解决你的问题,请参考以下文章

转:关于H264通过RTP传输的打包方式

将图像编码为 h264 和 rtp 输出:没有 sprop-parameter-sets 的 SDP 文件无法播放

《音视频:wireshark抓rtp包,提取出H264裸流数据》

H264 NALU 使用PS封装 RTP发送

在 ffplay 中获得绿屏:使用 Live555 通过 RTP 流将桌面(DirectX 表面)流式传输为 H264 视频

VLC播放RTP封装的h264,PS,TS流的SDP写法