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

时间:2013-05-14 20:18:48

标签: python ffmpeg h.264 pcap

我在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。

  1. 我想知道是否有办法传递(在单独的文件上?) 时间戳矢量或任何其他信息ffmpeg所以 结果会正确创建吗?
  2. 有没有其他方法可以将数据从PCAP文件中取出并播放或转换然后播放?
  3. 由于所有工作都是在Python中完成的,因此欢迎任何有助于工作的库/模块建议(即使需要一些编码)。
  4. 注意:所有工作都是离线完成的,输出没有限制。它可以是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  
    

    通常,这会将来自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
      一个= FMTP:109   分组模式= 1;轮廓级别-ID = 64000c; sprop-参数集= Z2QADKwkpAeCP6wEQAAAAwBAAAAFI8UKkg ==,aMvMsiw =;
      B = AS:200

    结果:

      

    ffmpeg版本0.10.2版权所有(c)2000-2012 FFmpeg开发人员
      建立于2012年3月20日04:34:50与gcc 4.4.6 20110731(红帽   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   探测大小= 2048并得分= 50 [sdp @ 0x15c0c00]视频编解码器集   to:h264 [NULL @ 0x15c7240] RTP打包模式:1 [NULL @   0x15c7240] RTP配置文件IDC:64配置文件IOP:0级别:c [NULL @   0x15c7240] Extradata设置为0x15c78e0(大小:36)!错误{或,} _识别   分开: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 个答案:

答案 0 :(得分:1)

我非常确定(理所当然)唯一的方法是使用数据包之间的网络时间重播rtp流作为延迟。

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

如果h264流是一个恒定的帧速率,你可以将rtp数据推送到ffmpeg而没有设置输入fps的时间,但我不知道任何h264 rtp流就是这样工作的。您最有可能看到的是视频流在某些部分播放的速度,在其他部分播放的速度较慢。