我想将从 rtp(实时)流录制的 H264 视频存储到文件中。 我已经用一个简单的java程序尝试过这个,但是vlc播放器无法打开该文件。
这是我的代码:
try
{
socket = new DatagramSocket(port);
fos = new FileOutputStream(filePath + outputFileName);
do
{
DatagramPacket in = new DatagramPacket(inData, inData.length);
socket.receive(in);
byte[] bytes = in.getData();
if (curPos < buffer.length)
{
for (int i = 0; i < bytes.length; i++)
{
buffer[curPos] = bytes[i];
curPos++;
if (curPos >= buffer.length)
{
receivePackets = false;
break;
}
}
}
else
{
receivePackets = false;
}
Thread.sleep(SOCKET_TIMEOUT);
}
while (receivePackets);
fos.write(buffer, 0, buffer.length);
if (fos != null)
{
fos.close();
}
if (socket != null)
{
socket.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
文件将被创建,但无法打开它。 我是否需要删除或添加任何标题信息到字节数组才能获得正确的视频文件?
更新:
好吧,问题似乎是h264 rtp数据包的最终 header 信息,因为我可以打开带有标准rtp header 的录制的h263视频(但视频质量非常糟糕)。
最佳答案
Rtp 的数据包中包含不属于 h264 流一部分的 header ,并且具有将一个 nal 单元(本质上是单个 h264“数据包”)拆分为多个数据包或将多个 nal 单元合并为一个数据包的机制,两者都添加了不能成为最终产品一部分的元数据。
此外,RTP 流可能不包含播放视频所需的一些元数据,尤其是通过 rtsp 协商时。如果是这种情况,您必须从 SDP 的 sprop-parameter-sets 中提取一些 NAL 单元。
您可以在此处找到有关所有这些工作原理的文档:https://www.rfc-editor.org/rfc/rfc6184 。这实际上并不像听起来那么难。
当 h264 写入文件时,每个 nal 单元前面必须有三个 0 字节,然后是一个 1 字节。您可以在这里找到更多详细信息:https://www.itu.int/rec/T-REC-H.264-201906-I/en
必须让 VLC 播放原始 h264 文件。您可以在谷歌上搜索并找到简单的步骤,它与代码无关,所以我不会在此处复制它们。
如果您希望文件为 mp4,最好使用库来执行此操作。如果你想自己做这一切,上帝会帮助你,但你可以在这里找到规范:https://web.archive.org/web/20180921052457/http://l.web.umkc.edu:80/lizhu/teaching/2016sp.video-communication/ref/mp4.pdf 。 https://github.com/sannies/mp4parser库是java的,可以做到这一点,但是有一些问题。 Ffmpeg 是一个很棒的程序,可以做到这一点,我很幸运将它作为 Java 的子进程运行,并输入其标准并从其标准输出中读取。
顺便说一句,ffprobe 是一个很棒的程序,在损坏的视频文件上运行它可以提供一些有关问题所在的见解。
关于java - 将 RTP 视频流(H264 编解码器)写入 mp4 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7255467/