欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

FFmpeg学习:04.利用FFmpeg将rgb转为yuv

最编程 2024-08-15 15:27:30
...

rgb格式,yuv格式:网上官方和博客的解释真的令人头大,其实简单讲这俩格式就是视频帧的格式,本质上也就是一张图片。

准备工作

利用FFmpeg将bmp图片转为rgb32和yuv420,yuv444

ffmpeg -i Screen0.bmp -video_size 1920x1080 -pix_fmt yuv444p Screen0-yuv444p.yuv

ffmpeg -i Screen0.bmp -video_size 1920x1080 -pix_fmt yuv420p Screen0-yuv420p.yuv

ffmpeg -i Screen0.bmp -video_size 1920x1080 -pix_fmt rgb24 Screen0-rgb32.rgb

发现rgb,yuv都无法双击打开,咱们还是需要使用ffmpeg打开这两种文件。

ffplay -f rawvideo -pixel_format yuv420p -video_size 1920x1080 Screen0-yuv420p.yuv

ffplay -f rawvideo -pixel_format rgb32 -video_size 1920x1080 Screen0-rgb32.rgb

编码

网上大部分的转换都是使用libyuv库进行转换:www.jianshu.com/p/4e9708713…

我这里使用FFmpeg直接进行转换。

**强调!!!!转换格式前,一定要明确你自己的数据是什么格式的!!!! **

//准确来讲这个是rgb32到yuv420p的转换。如果你的rgb数据只有一帧,那么把循环拆了就行
void SaveRgb2YuvComplete()
{
	int width = 1920;
	int height = 1080;

	FILE* fpinRGB = fopen("ScreenRGBComplete.rgb", "rb");
	if (!fpinRGB) return;

	FILE* fpoutYUV = fopen("ScreenYUVComplete.yuv", "wb");
	if (!fpoutYUV) return;

	av_register_all();

	//所有牵扯到格式转换的格式的参数一定要注意!
	SwsContext *swsCtx = sws_getContext(
		width, height, AV_PIX_FMT_RGB32,
		width, height, AV_PIX_FMT_YUV420P,
		SWS_BICUBIC,
		NULL, NULL, NULL
	);

	AVFrame *yuvFrame = av_frame_alloc();
	yuvFrame->format = AV_PIX_FMT_YUV420P;
	yuvFrame->width = width;
	yuvFrame->height = height;
	av_frame_get_buffer(yuvFrame, 4*8);
    //这里的4*8由源格式 AV_PIX_FMT_RGB24 决定,R,G,B,A 各有 1 个字节,总共就是 4*8 位

	unsigned char *rgbBuf = new unsigned char[width * height * 4];

	while (true)
	{
		int len = fread(rgbBuf, width*height * 4, 1, fpinRGB);
		if (len <= 0) break;

		AVFrame *rgbFrame = av_frame_alloc();
		avpicture_fill((AVPicture *)rgbFrame, rgbBuf, AV_PIX_FMT_BGR32, width, height);

		int outSliceH = sws_scale(swsCtx, rgbFrame->data, rgbFrame->linesize, 0, height,
			yuvFrame->data, yuvFrame->linesize);
		if (outSliceH <= 0) return;

		fwrite(yuvFrame->data[0], width * height, 1, fpoutYUV);
		fwrite(yuvFrame->data[1], width * height / 4, 1, fpoutYUV);
		fwrite(yuvFrame->data[2], width * height / 4, 1, fpoutYUV);
	}
	
	fclose(fpinRGB);
	fclose(fpoutYUV);
	av_frame_free(&yuvFrame);
	sws_freeContext(swsCtx);
}

代码参考链接:www.cnblogs.com/linuxAndMcu…