2

ブラックボックスデバイスからのRTPパケットを含むログファイルがあります。対応するSDPファイル(RTSP DESCRIBE)もあります。このファイルをある種の再生可能なビデオファイルに変換する必要があります。これらの2つのファイルを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;
            }
        }
    }
4

2 に答える 2

0

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

エンコードされたストリームがどのようにパケット化されるかの詳細に行き詰まる可能性があるため、パケットレベルで何もしないでください。

上記のリンクをご覧ください。SDP / RTP / RTSPストリーミングはかなり複雑なプロトコルであり、ローカルメディアファイルを開くことだけを期待しているプレーヤーに直接接続しようとすると、通常は機能しません。

ストリームを処理していて、ストリームからファイルを保存したい場合は、ビッグメディアプロジェクト(ffmpeg、vlc、live555、openrtsp)のいずれかで「filesinks」をグーグルで検索することをお勧めします。これらのプロジェクトにはすでにオープンソースのfileSink実装があります(C 、C ++)。

たとえば、live555では、すべてのコーデックの./live/liveMediaディレクトリにfileSinkの実装があります。

SDPソースからのストリームがある場合は、そのトラックで使用されるコーデックのfileSinkを使用して、各トラック(オーディオ、ビデオ)を処理できます。次に、それらのトラックをプレーヤーに多重化するか、トラックを個別に再生できます。

于 2012-04-12T02:54:27.560 に答える
0

vlcでSDPファイルを開き、小さなアプリを作成してRTPパケットをネットワークに再度再生し、VLCが受信できるようにします。それらを127.0.0.1とSDPファイルと一致するポート番号で再生するようにしてください。

VLCは、いくつかのパケットを受信するまで待機し、VLCを使用して、MP4または同様のファイル形式にトランスコードせずにメディアを保存します。

于 2012-05-09T04:44:40.813 に答える