ffmpeg解码视频存为BMP文件

  1. #include <windows.h>  
  2.  #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <string.h>  
  5. #pragma once    
  6.   
  7.  #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. #include <libavcodec/avcodec.h>  
  11. #include <libavformat/avformat.h>  
  12. #include <libswscale/swscale.h>  
  13.   
  14.   
  15. #ifdef __cplusplus  
  16. }  
  17. #endif  
  18.   
  19. //定义BMP文件头  
  20.  #ifndef _WINGDI_   
  21. #define _WINGDI_  
  22. typedef struct tagBITMAPFILEHEADER {   
  23.         WORD    bfType;   
  24.         DWORD   bfSize;   
  25.         WORD    bfReserved1;   
  26.         WORD    bfReserved2;   
  27.         DWORD   bfOffBits;   
  28. } BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;   
  29.    
  30. typedef struct tagBITMAPINFOHEADER{   
  31.         DWORD      biSize;   
  32.         LONG       biWidth;   
  33.         LONG       biHeight;   
  34.         WORD       biPlanes;   
  35.         WORD       biBitCount;   
  36.         DWORD      biCompression;   
  37.         DWORD      biSizeImage;   
  38.         LONG       biXPelsPerMeter;   
  39.         LONG       biYPelsPerMeter;   
  40.         DWORD      biClrUsed;   
  41.         DWORD      biClrImportant;   
  42. } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;   
  43.    
  44. #endif   
  45.    
  46. //保存BMP文件的函数  
  47. void SaveAsBMP (AVFrame *pFrameRGB, int width, int height, int index, int bpp)   
  48. {   
  49.     char buf[5] = {0};   
  50.     BITMAPFILEHEADER bmpheader;   
  51.     BITMAPINFOHEADER bmpinfo;   
  52.     FILE *fp;   
  53.        
  54.     char *filename = new char[255];  
  55.        //文件存放路径,根据自己的修改  
  56.     sprintf_s(filename,255,"%s%d.bmp","D:/My Documents/Visual Studio 2008/Projects/WriteVideo/Debug/test",index);  
  57.     if ( (fp=fopen(filename,"wb+")) == NULL )   
  58.     {   
  59.        printf ("open file failed!\n");   
  60.        return;   
  61.     }   
  62.    
  63.     bmpheader.bfType = 0x4d42;   
  64.     bmpheader.bfReserved1 = 0;   
  65.     bmpheader.bfReserved2 = 0;   
  66.     bmpheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);   
  67.     bmpheader.bfSize = bmpheader.bfOffBits + width*height*bpp/8;   
  68.        
  69.     bmpinfo.biSize = sizeof(BITMAPINFOHEADER);   
  70.     bmpinfo.biWidth = width;   
  71.     bmpinfo.biHeight = height;   
  72.     bmpinfo.biPlanes = 1;   
  73.     bmpinfo.biBitCount = bpp;   
  74.     bmpinfo.biCompression = BI_RGB;   
  75.     bmpinfo.biSizeImage = (width*bpp+31)/32*4*height;   
  76.     bmpinfo.biXPelsPerMeter = 100;   
  77.     bmpinfo.biYPelsPerMeter = 100;   
  78.     bmpinfo.biClrUsed = 0;   
  79.     bmpinfo.biClrImportant = 0;   
  80.        
  81.     fwrite (&bmpheader, sizeof(bmpheader), 1, fp);   
  82.     fwrite (&bmpinfo, sizeof(bmpinfo), 1, fp);   
  83.     fwrite (pFrameRGB->data[0], width*height*bpp/8, 1, fp);   
  84.        
  85.     fclose(fp);   
  86. }   
  87.    
  88. //主函数  
  89. int main (void)   
  90. {   
  91.     unsigned int i = 0, videoStream = -1;   
  92.     AVCodecContext *pCodecCtx;   
  93.     AVFormatContext *pFormatCtx;   
  94.     AVCodec *pCodec;   
  95.     AVFrame *pFrame, *pFrameRGB;   
  96.     struct SwsContext *pSwsCtx;   
  97.     const char *filename = "D:/My Documents/Visual Studio 2008/Projects/WriteVideo/Debug/DELTA.MPG";   
  98.     AVPacket packet;   
  99.     int frameFinished;   
  100.     int PictureSize;   
  101.     uint8_t *buf;   
  102.      //注册编解码器  
  103.     av_register_all();   
  104.      //打开视频文件  
  105.     if ( av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL) != 0 )   
  106.     {   
  107.         printf ("av open input file failed!\n");   
  108.         exit (1);   
  109.     }   
  110.      //获取流信息  
  111.     if ( av_find_stream_info(pFormatCtx) < 0 )   
  112.     {   
  113.         printf ("av find stream info failed!\n");   
  114.         exit (1);   
  115.     }   
  116.      //获取视频流  
  117.     for ( i=0; i<pFormatCtx->nb_streams; i++ )   
  118.     if ( pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO )   
  119.     {   
  120.        videoStream = i;   
  121.        break;   
  122.     }   
  123.        
  124.     if (videoStream == -1)   
  125.     {   
  126.         printf ("find video stream failed!\n");   
  127.         exit (1);   
  128.     }   
  129.        
  130.     pCodecCtx = pFormatCtx->streams[videoStream]->codec;   
  131.        
  132.     pCodec = avcodec_find_decoder (pCodecCtx->codec_id);   
  133.        
  134.     if (pCodec == NULL)   
  135.     {   
  136.         printf ("avcode find decoder failed!\n");   
  137.         exit (1);   
  138.     }   
  139.      //打开解码器  
  140.     if ( avcodec_open(pCodecCtx, pCodec)<0 )   
  141.     {   
  142.         printf ("avcode open failed!\n");   
  143.         exit (1);   
  144.     }   
  145.        
  146.    //为每帧图像分配内存  
  147.     pFrame = avcodec_alloc_frame();   
  148.     pFrameRGB = avcodec_alloc_frame();   
  149.        
  150.     if ( (pFrame==NULL)||(pFrameRGB==NULL) )   
  151.     {   
  152.         printf("avcodec alloc frame failed!\n");   
  153.         exit (1);   
  154.     }   
  155.        
  156.     PictureSize = avpicture_get_size (PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);   
  157.     buf = (uint8_t*)av_malloc(PictureSize);   
  158.        
  159.     if ( buf == NULL )   
  160.     {   
  161.         printf( "av malloc failed!\n");   
  162.         exit(1);   
  163.     }   
  164.     avpicture_fill ( (AVPicture *)pFrameRGB, buf, PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);   
  165.        
  166. //设置图像转换上下文  
  167.     pSwsCtx = sws_getContext (pCodecCtx->width,   
  168.              pCodecCtx->height,   
  169.              pCodecCtx->pix_fmt,   
  170.              pCodecCtx->width,   
  171.              pCodecCtx->height,   
  172.              PIX_FMT_BGR24,   
  173.              SWS_BICUBIC,   
  174.              NULL, NULL, NULL);   
  175.     i = 0;   
  176.     while(av_read_frame(pFormatCtx, &packet) >= 0)   
  177.     {   
  178.     if(packet.stream_index==videoStream)   
  179.     {   
  180.        avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,  
  181.      packet.data, packet.size);   
  182.          
  183.        if(frameFinished)   
  184.        {      
  185.             //反转图像 ,否则生成的图像是上下调到的  
  186.             pFrame->data[0] += pFrame->linesize[0] * (pCodecCtx->height - 1);   
  187.             pFrame->linesize[0] *= -1;   
  188.             pFrame->data[1] += pFrame->linesize[1] * (pCodecCtx->height / 2 - 1);   
  189.             pFrame->linesize[1] *= -1;   
  190.             pFrame->data[2] += pFrame->linesize[2] * (pCodecCtx->height / 2 - 1);   
  191.             pFrame->linesize[2] *= -1;   
  192.      //转换图像格式,将解压出来的YUV420P的图像转换为BRG24的图像  
  193.             sws_scale (pSwsCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);   
  194.      SaveAsBMP (pFrameRGB, pCodecCtx->width, pCodecCtx->height, i++, 24);   
  195.        }       
  196.     }   
  197.     av_free_packet(&packet);   
  198.     }   
  199.        
  200.     sws_freeContext (pSwsCtx);   
  201.     av_free (pFrame);   
  202.     av_free (pFrameRGB);   
  203.     avcodec_close (pCodecCtx);   
  204.     av_close_input_file (pFormatCtx);   
  205.        
  206.     return 0;   
  207. }   
#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; 
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值