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

How to convert H264 RTP stream from PCAP to a playable video file

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

  • 我想知道是否可以通过(在单独的文件上?)
    时间戳向量或ffmpeg的任何其他信息,因此
    结果将被正确创建?
  • 还有其他方法可以将数据从PCAP文件中取出并播放或转换然后播放吗?
  • 由于所有工作都是在Python中完成的,因此也欢迎任何对库/模块有帮助的建议(即使需要一些编码)。
  • 注意:所有工作都脱机完成,对输出没有限制。它可以是cbr / vbr,任何可播放的容器和转码。我唯一的"局限性"是:它都应在Linux上运行…

    谢谢
    ?

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

    下面的代码无法成功执行以上操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    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文件传递到以下命令:

    1
    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=No Name
    c=IN IP4 ::1
    t=0 0
    a=tool:libavformat 53.32.100
    m=video 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 version 0.10.2 Copyright (c) 2000-2012 the FFmpeg developers
    built on Mar 20 2012 04:34:50 with gcc 4.4.6 20110731 (Red Hat
    4.4.6-3) configuration: --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] Format sdp
    probed with size=2048 and score=50 [sdp @ 0x15c0c00] video codec set
    to: h264 [NULL @ 0x15c7240] RTP Packetization Mode: 1 [NULL @
    0x15c7240] RTP Profile IDC: 64 Profile IOP: 0 Level: c [NULL @
    0x15c7240] Extradata set to 0x15c78e0 (size: 36)!err{or,}_recognition
    separate: 1; 1 [h264 @ 0x15c7240] err{or,}_recognition combined: 1;
    10001 [sdp @ 0x15c0c00] decoding for stream 0 failed [sdp @
    0x15c0c00] Could not find codec parameters (Video: h264) [sdp @
    0x15c0c00] Estimating duration from bitrate, this may be inaccurate
    109c.sdp: could not find codec parameters Traceback (most recent
    call last): File"./ffpipe.py", line 26, in
    ffmpeg_proc.stdin.write(data[42:]) IOError: [Errno 32] Broken pipe

    (原谅上面的内容,编辑器继续抱怨未缩进的代码行?)

    我已经在这个问题上工作了好几天...任何帮助/建议/提示将不胜感激。


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

    问题是可变帧速率,因为h264周围没有容器可以告诉它在此帧与最后一个帧之间经过的时间X,所以它不知道如何对所有时间进行计时。

    如果h264流是恒定的帧速率,则您可以在不设置输入fps的时间的情况下将rtp数据推送到ffmpeg,但是我不知道有任何这样的h264 rtp流。 您最有可能看到的是视频流播放方式,某些部分快,而另一些慢。