我有一个日志文件,其中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;
}
}
}
答案 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或类似的文件格式。