ffmpeg解码视频存为BMP文件

来源:互联网 发布:如何利用网络寻找客户 编辑:程序博客网 时间:2024/06/05 05:13
#include <windows.h> #include <stdio.h>#include <stdlib.h>#include <string.h>#pragma once   #ifdef __cplusplusextern "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; } 


原创粉丝点击