C# 我有一个包含RTP数据包的日志文件:现在怎么办?
我有一个日志文件,其中包含来自黑盒设备的RTP数据包。我还有一个相应的SDP文件(RTSP descripe)。我需要把这个文件转换成某种可播放的视频文件。我可以将这两个文件传递给FFMpeg或VLC或其他文件,并将其多路复用到可播放的文件中吗 作为替代方案,我可以循环代码中的各个数据包,并对每个数据包进行处理。但是,似乎已有用于解析此数据的库。而且它似乎手工做这件事需要一个大项目。是否有某种视频文件格式是SDP和RTP的原始混合?谢谢你抽出时间 FFmpeg或VLC是否有办法打开SDP文件,然后通过STDIN获取输入数据包 我通常使用C#,但如果必要的话我可以使用C 更新1:这是我的非工作代码。我正在尝试用ffplay获得一些输出,但是我还没有任何运气。它给了我无效的数据错误。据我所知,它确实正确地检查了所有数据。我的输出几乎和我的输入一样大(大约4MB)C# 我有一个包含RTP数据包的日志文件:现在怎么办?,c#,ffmpeg,vlc,libvlc,sharpffmpeg,C#,Ffmpeg,Vlc,Libvlc,Sharpffmpeg,我有一个日志文件,其中包含来自黑盒设备的RTP数据包。我还有一个相应的SDP文件(RTSP descripe)。我需要把这个文件转换成某种可播放的视频文件。我可以将这两个文件传递给FFMpeg或VLC或其他文件,并将其多路复用到可播放的文件中吗 作为替代方案,我可以循环代码中的各个数据包,并对每个数据包进行处理。但是,似乎已有用于解析此数据的库。而且它似乎手工做这件事需要一个大项目。是否有某种视频文件格式是SDP和RTP的原始混合?谢谢你抽出时间 FFmpeg或VLC是否有办法打开SDP文件,然
公共类RtpPacket2
{
公共字节版本pxcc;
公共字节MPT;
公共ushort序列;//长度?
公共uint时间戳;
公共uint Ssrc;
公共int版本{get{return VersionPXCC>>6;}
公共布尔填充{get{return(VersionPXCC&32)>0;}
公共bool扩展{get{return(VersionPXCC&16)>0;}
public int CsrcCount{get{return VersionPXCC&0xf;}}//ItemCount
公共布尔标记{get{return(MPT&0x80)>0;}
public int PayloadType{get{return MPT&0x7f;}}//PacketType
}
静态void Main(字符串[]参数)
{
如果(参数长度!=2)
{
Console.WriteLine(“用法:”);
返回;
}
var inputFile=args[0];
var outputFile=args[1];
如果(File.Exists(outputFile))File.Delete(outputFile);
//来自SDP:fmtp 96配置文件级别id=4D0014;打包模式=0
var sps=Convert.FromBase64String(“zolahiluffge0iaaa4qaak/IAQ==”;//位转换器.ToString(sps)“67-42-C0-1E-88-8B-50-58-1E-D0-80-00-03-84-00-00-AF-C8-01”字符串
var pps=Convert.FromBase64String(“aM44gA=”);//BitConverter.ToString(pps)“68-CE-38-80”字符串
var sep=新字节[]{00,00,01};
var数据包=新的RtpPacket2();
bool firstFrame=true;
使用(var input=File.OpenRead(inputFile))
使用(变量读取器=新二进制读取器(输入))
使用(var output=File.OpenWrite(outputFile))
{
//输出.写入(头,0,头.长度);
输出写入(sep,0,sep.Length);
输出.写入(sps,0,sps.长度);
输出写入(sep,0,sep.Length);
输出.写入(pps,0,pps.长度);
输出写入(sep,0,sep.Length);
while(input.Position0 | | packet.Extension)抛出新的NotImplementedException();
var header0=reader.ReadByte();
var header1=reader.ReadByte();
var fragmentType=header0&0x1F;//对于视频来说应该是28
如果(fragmentType!=28)//28用于视频?
{
输入。位置+=尺寸-14;
继续;
}
var nalUnit=header0&~0x1F;
var nalType=header1&0x1F;
var start=(header1&0x80)>0;
var end=(表头1和0x40)>0;
如果(第一帧)
{
输出写入(sep,0,sep.Length);
output.WriteByte((字节)(nalUnit | fragmentType));
firstFrame=false;
}
对于(int i=0;i
不要在包级别做任何事情,因为您可能会陷入编码流如何打包的细节中
浏览上面的链接。SDP/RTP/RTSP流媒体是非常复杂的协议,当您试图将它们直接连接到希望只打开本地媒体文件的播放器时,这些协议通常不起作用
如果您正在处理流,并且希望从流中保存文件,那么您可能希望在任何大型媒体项目(ffmpeg、vlc、live555、openrtsp)中搜索“文件链接”,因为这些项目已经有开源文件链接实现(C、C++)
例如,在live555中,所有编解码器在./live/liveMedia目录中都有文件链接实现
如果您有来自SDP源的流,则可以使用该曲目使用的编解码器的文件链接来处理每个曲目(音频、视频)。然后,您可以将这些曲目多路复用到播放器或独立播放这些曲目
不要在包级别做任何事情,因为您可能会陷入编码流如何打包的细节中
浏览上面的链接。SDP/RTP/RTSP流媒体是非常复杂的协议,当您试图将它们直接连接到播放器时,它们通常不起作用
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;
}
}
}