ffmpeg YUV编码成h264

介绍

直接读取本地YUV文件,然后编码成h264,再存盘

流程如下

输出上下文

AVFormatContext* formatCtx = NULL;
	if (avformat_alloc_output_context2(&formatCtx, NULL, NULL, pOutFileName) < 0)
	{
		std::cout << "avformat_alloc_output_context2 failed" << std::endl;
		return;
	}

打开输入

if (avio_open2(&formatCtx->pb, pOutFileName, AVIO_FLAG_READ_WRITE, NULL, NULL) < 0)
	{
		std::cout << "avio_open2 failed" << std::endl;
		return;
	}

创建视频流

AVStream* stream = avformat_new_stream(formatCtx, NULL);
	if (stream == NULL)
	{
		std::cout << "avformat_new_stream failed" << std::endl;
		return;
	}

参数设置

stream->time_base.den = 25;
stream->time_base.num = 1;

AVCodecParameters* codecParams = formatCtx->streams[stream->index]->codecpar;
codecParams->width = nWidth;
codecParams->height = nHeight;
codecParams->codec_type = AVMEDIA_TYPE_VIDEO;

查找编码器

AVCodec* codec = avcodec_find_encoder(outFormat->video_codec);
if (codec == NULL)
{
	std::cout << "avcodec_find_encoder failed" << std::endl;
	return;
}

设置编码器

AVCodecContext* codecCtx = avcodec_alloc_context3(codec);
if (codecCtx == NULL)
{
	std::cout << "avcodec_alloc_context3 failed" << std::endl;
	return;
}
avcodec_parameters_to_context(codecCtx, codecParams);

codecCtx->codec_id = outFormat->video_codec;
codecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
codecCtx->width = nWidth;
codecCtx->height = nHeight;
codecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
codecCtx->time_base.den = 25;
codecCtx->time_base.num = 1;
codecCtx->bit_rate = 400000;
codecCtx->gop_size = 12;

//h264
codecCtx->qmin = 10;
codecCtx->qmax = 51;
codecCtx->qcompress = (float)0.6;

打开编码器

if (avcodec_open2(codecCtx, codec, NULL) < 0)
{
	std::cout << "avcodec_open2 failed" << std::endl;
	return;
}

写入文件头

avformat_write_header(formatCtx, NULL);

循环读取数据

for (int i = 0; i < nFrames; i++)
{
	//读取YUV数据
	fread(pFrameBuffer, 1, (unsigned long)(pix_size + pix_size / 2), wj);
	frame->data[0] = pFrameBuffer;
	frame->data[1] = pFrameBuffer + pix_size;
	frame->data[2] = pFrameBuffer + pix_size + pix_size / 4;
	//写入数据
}

写入数据

packet->stream_index = stream->index;
//时间基转换
av_packet_rescale_ts(packet, codecCtx->time_base, stream->time_base);

//写入
packet->pos = -1;
ret = av_interleaved_write_frame(formatCtx, packet);
if (ret < 0) 
{
	char buf[AV_ERROR_MAX_STRING_SIZE] = { 0 };
	av_make_error_string(buf, AV_ERROR_MAX_STRING_SIZE, ret);
	printf("error is: %s.\n", buf);
}

写入文件尾

av_write_trailer(formatCtx);

示例代码

示例代码在此.

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值