方法:
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格式原始工程