您当前的位置: 首页 > 

qianbo_insist

暂无认证

  • 0浏览

    0关注

    399博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

h264编码基础

qianbo_insist 发布时间:2021-06-18 13:09:44 ,浏览量:0

h264编码

    h264编码10年屹立,优秀的东西总是一直在发光,相对于RGB和YUV,将数据成几百倍的压缩。

    初始化包含进来的数据格式,出去的数据格式,一般我们的数据如果为BGR格式,一个像素是有三个字节组成的,那么一副图像比如720P是有多大呢,12807203 = 2764800 字节 ,一秒钟20帧数 ,那就是 2764800*20 = 55,296,000 字节,也就是一秒钟52M字节,一分钟产生的图像数据为 3120M字节,也就是3G 左右,第一步为转码为YUV420P,这个格式为RGB的一半,经过h264 编码压缩,比如压缩为每秒钟比特率为3Mbit,一分钟也就是180Mbit,字节为22M多,也就是3G 和 22M byte的对比。压缩比到了 141:1。

    除了直接用libx264 编码,也可以用ffmpeg,实际上ffmpeg封装了libx264 libx265,甚至像intel Gpu qsv 和 cuda 硬件编码。这里使用软编码作为示例。

ffmpeg的作者之一Bellard 贝拉是一位极其著名优秀的软件工程师,qemu 的作者,同时也出品了quickjs,有兴趣可以看看他写的东西。

1、编码初始化
int Encodeh264::Encoder_Init(AVCodecID codec_id, 
	int in_w, 
	int in_h, 
	int fps, AVPixelFormat src_pix_fmt, 
	int dst_w, 
	int dst_h, AVPixelFormat dst_pix_fmt 
	)
{
	//

	_pCodec = avcodec_find_encoder(codec_id);
	if (!_pCodec)
	{
		printf("Codec not found\n");
		return -1;
	}

	//
	_pCodecCtx = avcodec_alloc_context3(_pCodec);

	if (!_pCodecCtx)
	{
		printf("Could not allocate video codec context\n");
		return -1;
	}
	//编码指定
	_pCodecCtx->bit_rate = 200*1000; //这个需要传进来
	_pCodecCtx->width = in_w;
	_pCodecCtx->height = in_h;
	_pCodecCtx->time_base.num = 1;
	_pCodecCtx->time_base.den = fps;
	_pCodecCtx->framerate.num = fps;
	_pCodecCtx->framerate.den = 1;
	_pCodecCtx->gop_size = fps;
	_pCodecCtx->max_b_frames = 0; //b帧指定为0
	_pCodecCtx->pix_fmt = dst_pix_fmt;
	//线程指定
	_pCodecCtx->thread_count = 2;
	av_opt_set(_pCodecCtx->priv_data, "preset", "ultrafast", 0);
	av_opt_set(_pCodecCtx->priv_data, "tune", "zerolatency", 0);
	av_opt_set(_pCodecCtx->priv_data, "preset", "ultrafast", 0);
	_pCodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

	//
	if (avcodec_open2(_pCodecCtx, _pCodec, NULL) format = src_pix_fmt;
	_AVFrame->width  = in_w;
	_AVFrame->height = in_h;
	int ret = av_frame_get_buffer(_AVFrame, 0);

	if (ret format = dst_pix_fmt;
	_YUVFrame->width = dst_w;
	_YUVFrame->height = dst_h;

	ret = av_frame_get_buffer(_YUVFrame, 0);

	if (ret priv_data, "preset", "ultrafast", 0);
	av_opt_set(_pCodecCtx->priv_data, "tune", "zerolatency", 0);
	av_opt_set(_pCodecCtx->priv_data, "preset", "ultrafast", 0);

这三句话是用来实时编码用的,可以修改,具体看ffmpeg的帮助。如果存文件,可以将编码从ultrafast 改成 slow等在码率不变的情况下更加清晰。图像的编码首先是把BGR24这种图像转成YUV420P,然后将YUV420P压缩成h26x

编码
AVPacket *Encodeh264::Encode_H264(uint8_t *data)
{
	sws_scale(_img_converT_ctx, &data, _AVFrame->linesize, 0, _AVFrame->height, _YUVFrame->data, _YUVFrame->linesize);
	int ret = avcodec_send_frame(_pCodecCtx, _YUVFrame);
	if (ret pts++; /*= v_framenum++;*/
			return pkt;
		}
	}
}
调用
Encodeh264  v_264_obj;
	if (v_264_obj.Encoder_Init(AV_CODEC_ID_H264,
			CANVAS_WIDTH,
			CANVAS_HEIGHT, fps,
			AV_PIX_FMT_BGR24,
			CANVAS_WIDTH,
			CANVAS_HEIGHT, AV_PIX_FMT_YUV420P) != 0)
		{
			std::cout             
关注
打赏
1663161521
查看更多评论
0.0412s