我十分期望能得到以下问题的帮助:
我有一款带摄像头的小工具,生成 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.
packet.pts = packet.dts = AV_NOPTS_VALUE
来避免这个错误。但是我现在意识到这可能仍然不足,因为你正在处理 raw H264 数据包。你的流中是否有所有头文件或只有 VOP ... 即 ... 你的所有帧是否都以 0x000001b6 开始?你能否发布一下你用于初始化视频流的代码? - bob2