我有一个带RTP包的日志文件:现在是什么?

时间:2012-04-09 19:48:43

标签: c# ffmpeg vlc libvlc sharpffmpeg

我有一个日志文件,其中RTP数据包来自黑匣子设备。我也有相应的SDP文件(RTSP DESCRIBE)。我需要将此文件转换为某种可播放的视频文件。我可以将这两个文件传递给FFMpeg或VLC或其他文件,并将数据复制到可播放的内容中吗?

作为一个替代计划,我可以在代码中循环遍历各个数据包,并对每个数据包执行某些操作。但是,似乎存在用于解析此数据的现有库。它似乎是手工完成它会要求一个大项目。是否有某种视频文件格式是SDP和RTP的相当原始组合?谢谢你的时间。

有没有办法让FFmpeg或VLC打开SDP文件,然后通过STDIN获取输入数据包?

我通常使用C#,但如果需要,我可以使用C.

更新1:这是我的非工作代码。我正在尝试使用ffplay获得某种输出,但我还没有运气。它给了我无效的数据错误。据我所知,它确实正确地覆盖了所有数据。我的输出几乎与我的输入一样大(大约4MB)。

    public class RtpPacket2
    {
        public byte VersionPXCC;
        public byte MPT;
        public ushort Sequence; // length?
        public uint Timestamp;
        public uint Ssrc;
        public int Version { get { return VersionPXCC >> 6; } }
        public bool Padding { get { return (VersionPXCC & 32) > 0; } }
        public bool Extension { get { return (VersionPXCC & 16) > 0; } }
        public int CsrcCount { get { return VersionPXCC & 0xf; } } // ItemCount
        public bool Marker { get { return (MPT & 0x80) > 0; } }
        public int PayloadType { get { return MPT & 0x7f; } } // PacketType
    }


    static void Main(string[] args)
    {
        if (args.Length != 2)
        {
            Console.WriteLine("Usage: <input RTP file> <output 3GP file>");
            return;
        }
        var inputFile = args[0];
        var outputFile = args[1];
        if(File.Exists(outputFile)) File.Delete(outputFile);

        // FROM the SDP : fmtp 96 profile-level-id=4D0014;packetization-mode=0
        var sps = Convert.FromBase64String("Z0LAHoiLUFge0IAAA4QAAK/IAQ=="); //      BitConverter.ToString(sps)  "67-42-C0-1E-88-8B-50-58-1E-D0-80-00-03-84-00-00-AF-C8-01"  string
        var pps = Convert.FromBase64String("aM44gA=="); //      BitConverter.ToString(pps)  "68-CE-38-80"   string
        var sep = new byte[] { 00, 00, 01 };

        var packet = new RtpPacket2();
        bool firstFrame = true;
        using (var input = File.OpenRead(inputFile))
        using (var reader = new BinaryReader(input))
        using (var output = File.OpenWrite(outputFile))
        {
            //output.Write(header, 0, header.Length);
            output.Write(sep, 0, sep.Length);
            output.Write(sps, 0, sps.Length);
            output.Write(sep, 0, sep.Length);
            output.Write(pps, 0, pps.Length);
            output.Write(sep, 0, sep.Length);
            while (input.Position < input.Length)
            {
                var size = reader.ReadInt16();
                packet.VersionPXCC = reader.ReadByte();
                packet.MPT = reader.ReadByte();
                packet.Sequence = reader.ReadUInt16();
                packet.Timestamp = reader.ReadUInt32();
                packet.Ssrc = reader.ReadUInt32();
                if (packet.PayloadType == 96)
                {
                    if (packet.CsrcCount > 0 || packet.Extension) throw new NotImplementedException();

                    var header0 = reader.ReadByte();
                    var header1 = reader.ReadByte();

                    var fragmentType = header0 & 0x1F; // should be 28 for video
                    if(fragmentType != 28) // 28 for video?
                    {
                        input.Position += size - 14;
                        continue;
                    }
                    var nalUnit = header0 & ~0x1F;
                    var nalType = header1 & 0x1F;
                    var start = (header1 & 0x80) > 0;
                    var end = (header1 & 0x40) > 0;

                    if(firstFrame)
                    {
                        output.Write(sep, 0, sep.Length);
                        output.WriteByte((byte)(nalUnit | fragmentType));
                        firstFrame = false;
                    }

                    for (int i = 0; i < size - 14; i++)
                        output.WriteByte(reader.ReadByte());
                    if (packet.Marker)
                        firstFrame = true;
                }
                else input.Position += size - 12;
            }
        }
    }

2 个答案:

答案 0 :(得分:0)

http://www.bogotobogo.com/VideoStreaming/videostreaming_etc.php

远离在数据包级别执行任何操作,因为您可能会陷入编码流打包方式的详细信息中。

通过以上链接查看。 SDP / RTP / RTSP流是非常复杂的协议,当您尝试将它们直接连接到期望仅打开本地媒体文件的播放器时,这些协议通常不起作用。

如果您正在处理流并且想要从流中保存文件,则可能需要使用任何大型媒体项目(ffmpeg,vlc,live555,openrtsp)来搜索'filesinks',因为这些项目已经有开源文件信息实现(C,C ++)。

例如,在live555中,所有编解码器都在./live/liveMedia目录中具有fileSink实现。

如果您有来自SDP源的流,则可以使用fileSink处理每个轨道(音频,视频),以获取该轨道使用的编解码器。然后你可以将这些曲目复制到播放器或独立播放曲目。

答案 1 :(得分:0)

在vlc中打开SDP文件,然后编写一个小应用程序,再次将RTP数据包重新播放到网络,以便VLC可以接收它们。 确保将它们播放到127.0.0.1以及与SDP文件匹配的端口号。

VLC会等到收到一些数据包,然后使用VLC保存媒体,而不转码为MP4或类似的文件格式。