您的位置:首页 > 产品设计 > 产品经理

利用ffmpeg截取视频图像并保存为ppm和jpg图片格式

2014-11-12 09:25 1306 查看
转换为JPEG格式的图片需要利用到libjpeg的库。这个库直接网上下载就行了。下载下来的是源代码形式的。需要自己进行编译下。最简单的编译方式为:

1.去libjpeg下载源码,解压

2.使用vs2010的命令提示工具,切换到解压目录

3.执行nmake -f makefile.vc setup-v10命令

4.会在目录中生成jpeg.sln,直接用vs2010打开编译即可

5.将生成的lib文件导入到你的目录下,即可使用libjpeg库

直接贴出代码:()

/*
*author tongli
*mail:2074929378@qq.com
*/
void saveFrame(***Frame* pFrame, int width, int height, int iFrame)
{
	FILE *pFile;
	char szFilename[32];
	int y;

	sprintf(szFilename, "frame%d.ppm", iFrame);
	pFile = fopen(szFilename, "wb");
	if (pFile == NULL)
		return;

	fprintf(pFile, "P6\n%d %d\n255\n", width, height);

	for (y = 0; y < height; y++)
		fwrite(pFrame->data[0] + y*pFrame->linesize[0], 1, width * 3, pFile);

	fclose(pFile);
}
int main()
{
	***FormatContext *pFormatCtx;
	int i, videoIndex;
	***CodecContext *pCodecCtx = NULL;
	***Codec *pCodec = NULL;
	
	***Packet packet;
	int frameFinished;
	int numBytes;
	uint8_t *buffer;

	//char* filename = "nihao.avi";
	char* filename = "cuc_ieschool.flv";
	pFormatCtx = avformat_alloc_context();
	av_register_all();
	if (avformat_open_input(&pFormatCtx, filename, NULL, 0) != 0)//打开输入流,本质上是filename这个字符串来获取输入流的格式等信息。
		return -1;
	if (avformat_find_stream_info(pFormatCtx, NULL) < 0)//获取输入流的信息。
		return -1;
	av_dump_format(pFormatCtx, 0, filename, 0);//输出码流的基本信息到标准错误

	videoIndex = -1;
	for (i = 0; i < pFormatCtx->nb_streams; ++i){//找到流索引
		if (pFormatCtx->streams[i]->codec->codec_type == ***MEDIA_TYPE_VIDEO){
			videoIndex = i;
			break;
		}
	}
	if (videoIndex == -1)
	{
		fprintf(stderr, "unsupport codec\n");
		return -1;
	}
	pCodecCtx = pFormatCtx->streams[videoIndex]->codec;
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
		return -1;

	***Frame *pFrameRGB, *pFrame;
	pFrame = av_frame_alloc();
	pFrameRGB = av_frame_alloc();
	if (pFrame == NULL)
		return -1;

	numBytes = avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
	buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));

	avpicture_fill((***Picture*)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
	
	i = 0;
	struct SwsContext* img_convert_ctx;
	img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
		pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);

	while (av_read_frame(pFormatCtx, &packet) >= 0){//读包
		if (packet.stream_index == videoIndex){
			avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
			
			if (frameFinished)//够一帧的话就进行转码
			{
				sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, 
					pFrameRGB->data, pFrameRGB->linesize);

				if (++i <= 100)
					saveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);//保存图片
			}
		}
		av_free_packet(&packet);
	}

	av_free(buffer);
	av_free(pFrameRGB);
	av_free(pFrame);
	avcodec_close(pCodecCtx);
	return 0;
}


生成jpeg图片saveframe函数这么写:

/*
*author tongli
*mail:<span style="font-family: Arial, Helvetica, sans-serif;">2074929378@qq.com</span>
*/

void saveFrame(***Frame* pFrame, int width, int height, int iFrame)
{
	char fname[128] = { 0 };
	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	JSAMPROW row_pointer[1];
	int row_stride;
	uint8_t *buffer;
	FILE *fp;

	buffer = pFrame->data[0];
	sprintf(fname, "%s%d.jpg", "frame", iFrame);

	fp = fopen(fname, "wb");

	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, fp);
	
	cinfo.image_width = width;
	cinfo.image_height = height;
	cinfo.input_components = 3;
	cinfo.in_color_space = JCS_RGB;

	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];
		(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}

	jpeg_finish_compress(&cinfo);
	fclose(fp);
	jpeg_destroy_compress(&cinfo);
	return;
}


源代码下载地址:将视频帧转换为ppm图片格式 将视频帧转换为jpg图片格式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐