在 c# 中将 Rtsp 数据包转换为位图



你好,我在 c# https://github.com/ngraziano/SharpRTSP 中实现了 SharpRtsp 我正在接收 rtsp 数据包,它具有 h264 格式它在 H264Payload 类中有以下方法

private List<byte[]> Process_H264_RTP_Frame(List<byte[]> rtp_payloads)
{
Console.WriteLine("RTP Data comprised of " + rtp_payloads.Count + " rtp packets");
List<byte[]> nal_units = new List<byte[]>(); // Stores the NAL units for a Video Frame. May be more than one NAL unit in a video frame.
for (int payload_index = 0; payload_index < rtp_payloads.Count; payload_index++)
{
// Examine the first rtp_payload and the first byte (the NAL header)
int nal_header_f_bit = (rtp_payloads[payload_index][0] >> 7) & 0x01;
int nal_header_nri = (rtp_payloads[payload_index][0] >> 5) & 0x03;
int nal_header_type = (rtp_payloads[payload_index][0] >> 0) & 0x1F;
// If the Nal Header Type is in the range 1..23 this is a normal NAL (not fragmented)
// So write the NAL to the file
if (nal_header_type >= 1 && nal_header_type <= 23)
{
Console.WriteLine("Normal NAL");
norm++;
nal_units.Add(rtp_payloads[payload_index]);
}
// There are 4 types of Aggregation Packet (split over RTP payloads)
else if (nal_header_type == 24)
{
Console.WriteLine("Agg STAP-A");
stap_a++;
// RTP packet contains multiple NALs, each with a 16 bit header
//   Read 16 byte size
//   Read NAL
try
{
int ptr = 1; // start after the nal_header_type which was '24'
// if we have at least 2 more bytes (the 16 bit size) then consume more data
while (ptr + 2 < (rtp_payloads[payload_index].Length - 1))
{
int size = (rtp_payloads[payload_index][ptr] << 8) + (rtp_payloads[payload_index][ptr + 1] << 0);
ptr = ptr + 2;
byte[] nal = new byte[size];
System.Array.Copy(rtp_payloads[payload_index], ptr, nal, 0, size); // copy the NAL
nal_units.Add(nal); // Add to list of NALs for this RTP frame. Start Codes like 00 00 00 01 get added later
ptr = ptr + size;
}
}
catch
{
// do nothing
}
}
else if (nal_header_type == 25)
{
Console.WriteLine("Agg STAP-B not supported");
stap_b++;
}
else if (nal_header_type == 26)
{
Console.WriteLine("Agg MTAP16 not supported");
mtap16++;
}
else if (nal_header_type == 27)
{
Console.WriteLine("Agg MTAP24 not supported");
mtap24++;
}
else if (nal_header_type == 28)
{
Console.WriteLine("Frag FU-A");
fu_a++;
// Parse Fragmentation Unit Header
int fu_header_s = (rtp_payloads[payload_index][1] >> 7) & 0x01;  // start marker
int fu_header_e = (rtp_payloads[payload_index][1] >> 6) & 0x01;  // end marker
int fu_header_r = (rtp_payloads[payload_index][1] >> 5) & 0x01;  // reserved. should be 0
int fu_header_type = (rtp_payloads[payload_index][1] >> 0) & 0x1F; // Original NAL unit header
Console.WriteLine("Frag FU-A s=" + fu_header_s + "e=" + fu_header_e);
// Check Start and End flags
if (fu_header_s == 1 && fu_header_e == 0)
{
// Start of Fragment.
// Initiise the fragmented_nal byte array
// Build the NAL header with the original F and NRI flags but use the the Type field from the fu_header_type
byte reconstructed_nal_type = (byte)((nal_header_f_bit << 7) + (nal_header_nri << 5) + fu_header_type);
// Empty the stream
fragmented_nal.SetLength(0);
// Add reconstructed_nal_type byte to the memory stream
fragmented_nal.WriteByte(reconstructed_nal_type);
// copy the rest of the RTP payload to the memory stream
fragmented_nal.Write(rtp_payloads[payload_index], 2, rtp_payloads[payload_index].Length - 2);
}
if (fu_header_s == 0 && fu_header_e == 0)
{
// Middle part of Fragment
// Append this payload to the fragmented_nal
// Data starts after the NAL Unit Type byte and the FU Header byte
fragmented_nal.Write(rtp_payloads[payload_index], 2, rtp_payloads[payload_index].Length - 2);
}
if (fu_header_s == 0 && fu_header_e == 1)
{
// End part of Fragment
// Append this payload to the fragmented_nal
// Data starts after the NAL Unit Type byte and the FU Header byte
fragmented_nal.Write(rtp_payloads[payload_index], 2, rtp_payloads[payload_index].Length - 2);
// Add the NAL to the array of NAL units
nal_units.Add(fragmented_nal.ToArray());
}
}
else if (nal_header_type == 29)
{
Console.WriteLine("Frag FU-B not supported");
fu_b++;
}
else
{
Console.WriteLine("Unknown NAL header " + nal_header_type + " not supported");
}
}
// Output some statistics
Console.WriteLine("Norm=" + norm + " ST-A=" + stap_a + " ST-B=" + stap_b + " M16=" + mtap16 + " M24=" + mtap24 + " FU-A=" + fu_a + " FU-B=" + fu_b);
// Output all the NALs that form one RTP Frame (one frame of video)
return nal_units;
}

}

我已经尝试并完成了阅读,但我还没有找到任何将 H264 帧转换为位图的方法,我只想让它另存为位图,任何人都可以帮助我将这些数据转换为位图吗?

该函数的末尾以 H264 格式返回数据

// Output all the NALs that form one RTP Frame (one frame of video)
return nal_units;

要获取位图,您需要将 H264 数据传递到视频解压缩器中。如果您不熟悉数字视频,请考虑.ZIP或.RAR或.7Z文件。 如果没有正确的软件将压缩数据转换回可用格式,您将无法读取这些文件的内容。 这同样适用于视频。H264 是一种压缩数据格式。 您需要使用 H264 解压缩编解码器将nal_units授予位图(或另一种称为 YUV 的视频格式(。

有些人使用ffmpeg进行这种解压缩。其他人将H264数据传递到操作系统API(如Mac上的VideoToolbox或Android上的MediaCodec或Windows支持的任何内容(。

但是您需要这些额外的步骤。

最新更新