1. 程式人生 > >使用ffmpeg將BMP圖片編碼為x264視訊檔案,將H264視訊儲存為BMP圖片,yuv視訊檔案儲存為圖片的程式碼

使用ffmpeg將BMP圖片編碼為x264視訊檔案,將H264視訊儲存為BMP圖片,yuv視訊檔案儲存為圖片的程式碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#ifdef  __cplusplus
extern "C" {
#endif

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>

void SaveAsBMP (AVFrame *pFrameRGB, int width, int height, int index, int bpp)
{
	char buf[5] = {0};
	BITMAPFILEHEADER bmpheader;
	BITMAPINFOHEADER bmpinfo;
	FILE *fp;

	char filename[20] = "";
	_itoa (index, buf, 10);
	strcat (filename, buf);
	strcat (filename, ".bmp");

	if ( (fp = fopen(filename,"wb+")) == NULL )
	{
		printf ("open file failed!\n");
		return;
	}

	bmpheader.bfType = 0x4d42;
	bmpheader.bfReserved1 = 0;
	bmpheader.bfReserved2 = 0;
	bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	bmpheader.bfSize = bmpheader.bfOffBits + width*height*bpp/8;

	bmpinfo.biSize = sizeof(BITMAPINFOHEADER);
	bmpinfo.biWidth = width;
	bmpinfo.biHeight = height;
	bmpinfo.biPlanes = 1;
	bmpinfo.biBitCount = bpp;
	bmpinfo.biCompression = BI_RGB;
	bmpinfo.biSizeImage = (width*bpp+31)/32*4*height;
	bmpinfo.biXPelsPerMeter = 100;
	bmpinfo.biYPelsPerMeter = 100;
	bmpinfo.biClrUsed = 0;
	bmpinfo.biClrImportant = 0;

	fwrite (&bmpheader, sizeof(bmpheader), 1, fp);
	fwrite (&bmpinfo, sizeof(bmpinfo), 1, fp);
	fwrite (pFrameRGB->data[0], width*height*bpp/8, 1, fp);

	fclose(fp);
}


int main (void)
{
	unsigned int i = 0, videoStream = -1;
	AVCodecContext *pCodecCtx;
	AVFormatContext *pFormatCtx = NULL;
	AVCodec *pCodec;
	AVFrame *pFrame, *pFrameRGB;
	struct SwsContext *pSwsCtx;
	const char *filename = "myData.h264";
	AVPacket packet;
	int frameFinished;
	int PictureSize;
	uint8_t *buf;

	av_register_all();

	if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0 ){
		printf ("av open input file failed!\n");
		exit (1);
	}

	if ( avformat_find_stream_info(pFormatCtx,NULL) < 0 ){
		printf ("av find stream info failed!\n");
		exit (1);
	}

	for ( i=0; i<pFormatCtx->nb_streams; i++ ){
		if ( pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ){
			videoStream = i;
			break;
		}
	}

	if (videoStream == -1){
		printf ("find video stream failed!\n");
		exit (1);
	}

	pCodecCtx = pFormatCtx->streams[videoStream]->codec;

	pCodec = avcodec_find_decoder (pCodecCtx->codec_id);
	if (pCodec == NULL){
		printf ("avcode find decoder failed!\n");
		exit (1);
	}




	if ( avcodec_open2(pCodecCtx, pCodec,NULL)<0 ){
		printf ("avcode open failed!\n");
		exit (1);
	}

	pFrame = avcodec_alloc_frame();
	pFrameRGB = avcodec_alloc_frame();

	if ( (pFrame == NULL)||(pFrameRGB == NULL) ){
		printf("avcodec alloc frame failed!\n");
		exit (1);
	}

	PictureSize = avpicture_get_size (PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);

	buf = (uint8_t *)av_malloc(PictureSize);

	if ( buf == NULL ){
		printf( "av malloc failed!\n");
		exit(1);
	}

	avpicture_fill ( (AVPicture *)pFrameRGB, buf, PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);

	pSwsCtx = sws_getContext (pCodecCtx->width,
			pCodecCtx->height,
			pCodecCtx->pix_fmt,
			pCodecCtx->width,
			pCodecCtx->height,
			PIX_FMT_BGR24,
			SWS_BICUBIC,
			NULL, NULL, NULL);

		i = 0;

	while(av_read_frame(pFormatCtx, &packet) >= 0){
		if(packet.stream_index == videoStream){
			avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

			if(frameFinished){ 
					//反轉影象
				pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height - 1);
				pFrame->linesize[0] *= -1;
				pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height / 2 - 1);
				pFrame->linesize[1] *= -1;
				pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height / 2 - 1);
				pFrame->linesize[2] *= -1;

				sws_scale (pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

				SaveAsBMP (pFrameRGB, pCodecCtx->width, pCodecCtx->height, i++, 24);
			} 
		}
		av_free_packet(&packet);
	}

	while(1){  
		packet.data = NULL;  
		packet.size = 0;  
		avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

		if(frameFinished){ 
			//反轉影象
			pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height - 1);
			pFrame->linesize[0] *= -1;
			pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height / 2 - 1);
			pFrame->linesize[1] *= -1;
			pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height / 2 - 1);
			pFrame->linesize[2] *= -1;

			sws_scale (pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

			SaveAsBMP (pFrameRGB, pCodecCtx->width, pCodecCtx->height, i++, 24);
		}else{
			break;
		}

		av_free_packet(&packet);  
	}  

	sws_freeContext (pSwsCtx);
	av_free (pFrame);
	av_free (pFrameRGB);
	avcodec_close (pCodecCtx);
	avformat_close_input (&pFormatCtx);

	return 0;
}

#ifdef  __cplusplus
}
#endif