ffmpeg解码视频存为BMP文件

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

 #ifdef __cplusplus
extern "C" {
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>


#ifdef __cplusplus
}
#endif

//定义BMP文件头
 #ifndef _WINGDI_ 
#define _WINGDI_
typedef struct tagBITMAPFILEHEADER { 
        WORD    bfType; 
        DWORD   bfSize; 
        WORD    bfReserved1; 
        WORD    bfReserved2; 
        DWORD   bfOffBits; 
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER; 
 
typedef struct tagBITMAPINFOHEADER{ 
        DWORD      biSize; 
        LONG       biWidth; 
        LONG       biHeight; 
        WORD       biPlanes; 
        WORD       biBitCount; 
        DWORD      biCompression; 
        DWORD      biSizeImage; 
        LONG       biXPelsPerMeter; 
        LONG       biYPelsPerMeter; 
        DWORD      biClrUsed; 
        DWORD      biClrImportant; 
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER; 
 
#endif 
 
//保存BMP文件的函数
void SaveAsBMP (AVFrame *pFrameRGB, int width, int height, int index, int bpp) 
{ 
	char buf[5] = {0}; 
	BITMAPFILEHEADER bmpheader; 
	BITMAPINFOHEADER bmpinfo; 
	FILE *fp; 
	 
	char *filename = new char[255];
       //文件存放路径,根据自己的修改
	sprintf_s(filename,255,"%s%d.bmp","D:/My Documents/Visual Studio 2008/Projects/WriteVideo/Debug/test",index);
	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; 
	AVCodec *pCodec; 
	AVFrame *pFrame, *pFrameRGB; 
	struct SwsContext *pSwsCtx; 
	const char *filename = "D:/My Documents/Visual Studio 2008/Projects/WriteVideo/Debug/DELTA.MPG"; 
	AVPacket packet; 
	int frameFinished; 
	int PictureSize; 
	uint8_t *buf; 
	 //注册编解码器
	av_register_all(); 
	 //打开视频文件
	if ( av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL) != 0 ) 
	{ 
		printf ("av open input file failed!\n"); 
		exit (1); 
	} 
	 //获取流信息
	if ( av_find_stream_info(pFormatCtx) < 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 == CODEC_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_open(pCodecCtx, pCodec)<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_video(pCodecCtx, pFrame, &frameFinished,
	 packet.data, packet.size); 
	   
	   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; 
	 //转换图像格式,将解压出来的YUV420P的图像转换为BRG24的图像
			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); 
	} 
	 
	sws_freeContext (pSwsCtx); 
	av_free (pFrame); 
	av_free (pFrameRGB); 
	avcodec_close (pCodecCtx); 
	av_close_input_file (pFormatCtx); 
	 
	return 0; 
} 


你可能感兴趣的:(Stream,struct,File,null,input,FP)