将 RTP 视频流(H264 编解码器)写入 mp4 文件
我想将从 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数据包的最终标头信息,因为我可以使用标准rtp标头打开录制的h263视频(但视频质量非常糟糕) 。
i want to store a H264 video that is recorded from a rtp (live)stream to a file.
i've tried this with a simple java program, but vlc player cannot open the file.
here is my code:
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();
}
the file will be created, but it's not possible to open it.
are there any header informations i've to cut of or add to the byte array to get a correct video file?
UPDATE:
ok, the problem seems to be the nal header information of the h264 rtp packet, because i can open a recorded h263 video with a standard rtp header (but the quality of the video is really bad).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Rtp 的数据包中包含不属于 h264 流一部分的标头,并且具有将一个 nal 单元(本质上是单个 h264“数据包”)拆分为多个数据包或将多个 nal 单元合并到一个数据包中的机制,这两种方式添加不能成为最终产品一部分的元数据。
此外,RTP 流可能不包含播放视频所需的一些元数据,尤其是通过 rtsp 协商时。如果是这种情况,您必须从 SDP 的 sprop-parameter-sets 中提取一些 NAL 单元。
您可以在此处找到有关所有这些工作原理的文档: https://www.rfc-editor .org/rfc/rfc6184。这实际上并不像听起来那么难。
当 h264 写入文件时,每个 nal 单元前面必须有 3 个 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 是一个很棒的程序,在损坏的视频文件上运行它可以提供一些有关问题所在的见解。
Rtp has headers in their packets that aren't part of the h264 stream, as well as has mechanics for splitting one nal unit (essentially a single h264 "packet") over multiple packets or merging multiple nal units into one packet, both of which add metadata that can't be a part of the final product.
Additionally, the RTP stream may not contain some of the metadata necessary to play the video, especially if its negotiated over rtsp. If that's the case you'll have to pull some NAL units out of the sprop-parameter-sets in the SDP.
You can find the documentation on how all of that works here: https://www.rfc-editor.org/rfc/rfc6184. It's really not as hard as it sounds.
When h264 is written to a file, each nal unit must be preceded by three 0 bytes and then a 1 byte. You can find more details on that here: https://www.itu.int/rec/T-REC-H.264-201906-I/en
VLC has to be talked into playing raw h264 files. You can google that and find easy steps to do so, its not related to the code so I won't copy them here.
If you want the file as a mp4, your best using a library to do this. If you want to do it all yourself, heaven help you, but you can find the spec here: https://web.archive.org/web/20180921052457/http://l.web.umkc.edu:80/lizhu/teaching/2016sp.video-communication/ref/mp4.pdf. The https://github.com/sannies/mp4parser library is java and may do that but, has some issues. Ffmpeg is a wonderful program to do this, and I've had luck running it as a subprocess to Java and feeding its standard in and reading from its standard out.
As a side note, ffprobe is a great program, running it on a broken video file can provide some insight on what's wrong with it.
您必须从 RTP 数据包中解压视频数据
You have to unpack the video data from RTP packets