我真的很感谢您对以下问题的帮助:
我有一个带摄像头的小工具,产生H264压缩视频帧,这些帧被发送到我的应用程序。这些帧不是在容器中,只是原始数据。
我想使用ffmpeg和libav函数创建一个视频文件,以后可以使用。
如果我解码的帧,然后编码,一切工作正常,我得到一个有效的视频文件。(解码/编码步骤是通常的libav命令,没有什么花哨在这里,我把他们从万能的互联网,他们是坚如磐石)...然而,我浪费了很多时间解码和编码,所以我想跳过这一步,直接把帧在输出流。现在,问题来了。
下面是我为生成编码而编写的代码:
AVFrame* picture;
avpicture_fill((AVPicture*) picture, (uint8_t*)frameData,
codecContext->pix_fmt, codecContext->width,
codecContext->height);
int outSize = avcodec_encode_video(codecContext, videoOutBuf,
sizeof(videoOutBuf), picture);
if (outSize > 0)
{
AVPacket packet;
av_init_packet(&packet);
packet.pts = av_rescale_q(codecContext->coded_frame->pts,
codecContext->time_base, videoStream->time_base);
if (codecContext->coded_frame->key_frame)
{
packet.flags |= PKT_FLAG_KEY;
}
packet.stream_index = videoStream->index;
packet.data = videoOutBuf;
packet.size = outSize;
av_interleaved_write_frame(context, &packet);
put_flush_packet(context->pb);
}
其中变量如下所示:frameData
是来自相机的解码帧数据,其在先前步骤中被解码,并且videoOutBuf
是用于保持数据的普通uint8_t缓冲器
我已经修改了应用程序,以便不解码帧,但简单地通过数据,如:
AVPacket packet;
av_init_packet(&packet);
packet.stream_index = videoStream->index;
packet.data = (uint8_t*)frameData;
packet.size = currentFrameSize;
av_interleaved_write_frame(context, &packet);
put_flush_packet(context->pb);
其中frameData
是原始H264帧,currentFrameSize
是原始H264帧的大小,即我从每个帧的小工具中获得的字节数。
突然应用程序不能正常工作了,生成的视频无法播放。这很明显,因为我没有为数据包设置正确的PTS。我做了以下操作(我很绝望,你可以从这个方法中看到:)
packet.pts = timestamps[timestamp_counter ++];
其中timestamps
实际上是由上述工作代码生成的PTS列表,并写入文件(是的,您正确阅读了它,我记录了10分钟会话的所有PTS,并希望使用它们)。
应用程序仍然无法工作。
现在,我在这里没有任何线索做什么,所以这里的问题:
我想使用libav函数创建一个“mpegts”视频流,在流中插入已经编码的视频帧,并创建一个视频文件。我该怎么做?
谢了,F。
2条答案
按热度按时间avwztpqn1#
我相信如果你设置了以下内容,你会看到视频回放。
你应该根据h264包的头设置packet.flags。你可以尝试this fellow stack overflowian's建议直接从流中提取。
如果你也添加音频,那么pts/dts会更重要。我建议你学习this tutorial
编辑
我抽出时间从我的测试应用中提取出适合我的内容。出于某种原因,dts/pts值为0时适合我,但0或AV_NOPTS_VALUE以外的值不适合我。我想知道我们是否有不同版本的ffmpeg。我有来自git://www.example.com的最新git.videolan.org/ffmpeg.git。
快速测试.cpp
zbsbpyhn2#
您可以创建一个进程从控制台调用ffmpeg。
处理文件(如000001.jpg、000002.jpg、000003.jpg等)的命令行示例
视频压缩编码器
ffmpeg文档中的其他示例