您的位置:首页 > 其它

使用ffmpeg将实时流保存为AVI

2017-08-06 20:03 106 查看

使用ffmpeg将实时流保存为AVI

项目中需要将编码器编码出的H264数据保存为avi格式文件。使用ffmpeg接口进行实现。

ffmpeg一般是直接打开本地视频文件(如avi、mp4等)或者网络视频流(如:rtmp流媒体等),只需要直接将本地视频文件名或者流媒体的URL作为avformat_open_input的参数即可。但是这次的项目中,则需要直接将编码器编码出的H264流保存为avi文件。原本准备参考雷神的《ffmpeg 从内存中读取数据(或将数据输出到内存)》,但是这样对现有的程序结构改动比较大,因此考虑更为直接的方式,跳过avformat_open_input过程:

#include "libavformat/avformat.h"

int main(int argc, char **argv)
{
int ret;
char buf[] = "";
AVOutputFormat *ofmt_ctx = NULL;
AVStream *out_stream = NULL;
AVPacket pkt = { 0 };

av_register_all();
av_log_set_level(AV_LOG_DEBUG);

/* allocate the output media context */
avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename);
if (!ofmt_ctx) {
printf("Could not deduce output format from file extension: using AVI.\n");
avformat_alloc_output_context2(&ofmt_ctx, NULL, "avi", filename);
}
if(!ofmt_ctx) {
goto exit;
}

out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream) {
printf( "Failed allocating output stream\n");
ret = AVERROR_UNKNOWN;
goto exit;
}

AVCodecContext *avctx = out_stream->codec;
avctx->codec_type = AVMEDIA_TYPE_VIDEO;
/*此处,需指定编码后的H264数据的分辨率、帧率及码率*/
avctx->codec_id = AV_CODEC_ID_H264;
avctx->bit_rate = 2000000;
avctx->width = 640;
avctx->height = 480;
avctx->time_base.num = 1;
avctx->time_base.den = 30;

/* print output stream information*/
av_dump_format(ofmt_ctx, 0, filename, 1);

if (!(ofmt->flags & AVFMT_NOFILE))
{
ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE);
if (ret < 0) {
printf( "Could not open output file '%s'\n", filename);
goto exit;
}
printf("Open output file success!\n");
}

//写文件头(Write file header)
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0) {
printf( "write avi file header failed\n");
goto exit;
}
printf("Write avi header success!\n");

while(...) {
av_init_packet(&pkt);

// get a video frame(从编码器获取一帧编码后的H264数据)
...

// determine whether the I frame
if(/* I frame */) { // 判断该H264帧是否为I帧
pkt.flags |= AV_PKT_FLAG_KEY;
} else { /* p frame*/
pkt.flags = 0;
}

pkt.dts = pkt.pts = AV_NOPTS_VALUE;
pkt.size = size; /*帧大小*/

pkt.data = data; /*帧数据*/
if(!pkt.data) {
printf("no data\n");
}

//写入(Write)
ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
if (ret < 0) {
av_strerror(ret, buf, 1024);
}
av_packet_unref(&pkt);
}

av_write_trailer(ofmt_ctx);
exit:
/* close output */
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_close(ofmt_ctx->pb);

avformat_free_context(ofmt_ctx);

return 0
}


上面的代码只贴出了创建ffmpeg输入流、创建并保存数据到AVI文件的部分程序,方式已验证,能正常录制avi并使用VLC等进行播放。若是想保存为MP4文件,则还需另外写入extradata,否则会出现VLC能播放,但其它播放器无法播放,或播放帧率不对的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐