获取MP4视频关键帧图像,并保存为JPEG格式文件

方法:
1.利用ffmpeg对MP4文件进行解码,将原始数据格式转换成AV_PIX_FMT_RGB24格式;
对视频解压缩后的数据进行像素格式转换需要用到sws_scale()函数,其详细使用方法可参考FFmpeg源代码简单分析:libswscale的sws_scale()
由三个函数完成其转换工作:
sws_getContext():初始化一个SwsContext。
sws_scale():处理图像数据。
sws_freeContext():释放一个SwsContext。
示例:

			if(pFrame->key_frame==1)
			{
					if (img_convert_ctx == NULL)
					{
						width = ifmt->streams[video_index]->codecpar->width;
						height = ifmt->streams[video_index]->codecpar->height;
						img_convert_ctx = sws_getContext(width, height, video_codec_ctx->pix_fmt,
							width, height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
						if (img_convert_ctx == NULL)
						{
							ret = INITIALIZE_CONVERSION_ERROR;
							break;
						}
					}
					sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0,
						ifmt->streams[video_index]->codecpar->height, pFrameRGB->data, pFrameRGB->linesize);
					ret = SaveAsJpeg(pFrameRGB, ifmt->streams[video_index]->codecpar->width, ifmt->streams[video_index]->codecpar->height, picture_name);
					av_packet_unref(&packet);
					break;
			}

这部分主要是对视频的第一个关键帧的原始视频数据转换成AV_PIX_FMT_RGB24像素格式。然后将转换后的视频关键帧数据通过SaveAsJpeg()函数进行编码,生成最终的JPEG格式。

2.利用libjpeg对转换过后的视频数据编码成JPEG格式;
为了方便将原始视频数据编码为JPEG格式的文件,有多种方式可以选择,可以通过ffmpeg内部的编码器进行编码,也可以选择其它的编码库,这里选择利用libjpeg库进行编码,主要是考虑到调用方便。其使用方法如下:

int SaveAsJpeg(AVFrame *pFrameRGB, int width, int height,const char* fname)
{
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	JSAMPROW row_pointer[1];
	int row_stride;
	uint8_t *buffer;
	FILE *fp = NULL;

	buffer = pFrameRGB->data[0];
	int size = sizeof(buffer);
	cinfo.err = jpeg_std_error(&jerr);  //绑定错误处理结构对象
	jpeg_create_compress(&cinfo);   //初始化cinfo结构,注意这里是编码而不是解码
	int ret=NO_VALUE;
	ret=fopen_s(&fp,fname, "wb");  
	if (ret!=0)
		return -1;
		
	jpeg_stdio_dest(&cinfo, fp); //指定压缩目标数据源
	cinfo.image_width = width;//图像宽度
	cinfo.image_height = height;//图像高度
	cinfo.input_components = 3;     //彩色图
	cinfo.in_color_space = JCS_RGB;//JCS_RGB表示彩色图像,JCS_GRAYSCALE表示灰度图

	jpeg_set_defaults(&cinfo);
	jpeg_set_quality(&cinfo, 80, true); //图像质量
	jpeg_start_compress(&cinfo, TRUE);//开始编码
	row_stride = width * 3;
	while (cinfo.next_scanline < height)
	{
		row_pointer[0] = &buffer[cinfo.next_scanline * row_stride];//分配一行数据空间
		jpeg_write_scanlines(&cinfo, row_pointer, 1);//写入一行jpg图像数据到row_pointer中
	}
	jpeg_finish_compress(&cinfo);//完成编码
	fclose(fp);
	jpeg_destroy_compress(&cinfo);//释放资源
	return 0;
}

如果需要原始工程文件,请前往下载:将MP4关键帧数据保存成JPEG格式原始工程

你可能感兴趣的:(音视频)