yoo*_*sha 13 python ffmpeg pcap h.264
我在PCAP文件中捕获了H264流,并尝试从数据创建媒体文件.容器并不重要(avi,mp4,mkv,...).
当我使用videosnarf或rtpbreak(结合在每个数据包之前添加00 00 00 01的python代码)然后ffmpeg时,仅当输入帧速率恒定(或接近常量)时结果才可以.但是,当输入为vfr时,结果播放得太快(并且在相同的罕见情况下太慢).
例如:
videosnarf -i captured.pcap -c
ffmpeg -i H264-media-1.264 output.avi
在对该问题进行一些调查后,我现在相信,由于videosnarf(和rtpbreak)正在从数据包中删除RTP标头,因此时间戳丢失,ffmpeg将输入数据称为cbr.
注意:所有工作都是离线完成的,输出没有限制.它可以是cbr/vbr,任何可播放的容器和转码.我唯一的"限制":它应该全部运行在Linux上...
谢谢你
一些额外的信息:
由于没有为FFMPEG提供时间戳数据,我决定尝试不同的方法:跳过videosnarf并使用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
Run Code Online (Sandbox Code Playgroud)
通常,这会将来自PCAP文件的数据包传输到以下命令:
ffmpeg -loglevel debug -y -i 109c.sdp -f rtp -i - -na -vcodec copy p.mp4
Run Code Online (Sandbox Code Playgroud)
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 packetization-mode = 1; profile-level-id = 64000c; sprop-parameter-sets = Z2QADKwkpAeCP6wEQAAAAwBAAAAFI8UKkg ==,aMvMsiw =;
B = AS:200
结果:
ffmpeg版本0.10.2版权所有(c)2000-2012 FFmpeg开发人员
建立于2012年3月20日04:34:50与gcc 4.4.6 20110731(Red Hat 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/5 3. 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,大小= 2048,得分= 50 [sdp @ 0x15c0c00]视频编解码器设置为:h264 [NULL @ 0x15c7240] RTP打包模式:1 [NULL @ 0x15c7240] RTP配置文件IDC:64配置文件IOP :0级:c [NULL @ 0x15c7240] Extradata设置为0x15c78e0(大小:36)!err {或,} _识别单独:1; 1 [h264 @ 0x15c7240]错误{或,} _识别合并: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]管道损坏
(原谅上面的质量,编辑继续抱怨没有缩进的代码好吗??)
我正在研究这个问题好几天...任何帮助/建议/提示将不胜感激.
小智 1
我非常确定(理智地)唯一的方法是使用数据包之间的网络时间作为延迟来重播 rtp 流。
问题是可变帧速率,因为 h264 周围没有容器来告诉它此帧和最后一帧之间经过的 X 时间,它不知道如何对所有内容进行计时。
如果 h264 流是恒定的帧速率,您也许可以将 rtp 数据推送到 ffmpeg,而无需设置输入 fps 的时序,但我不知道有任何 h264 rtp 流可以这样工作。您最有可能看到的是视频流播放方式在某些部分快而在其他部分慢。