现在的位置: 首页 > 综合 > 正文

利用FFmpeg将视频文件生成bmp图像帧(解决反转问题)

2018年03月16日 ⁄ 综合 ⁄ 共 4449字 ⁄ 字号 评论关闭

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

#include "avformat.h"
#include "avcodec.h"
#include "swscale.h"

#pragma comment (lib, "avcodec.lib")
#pragma comment (lib, "avformat.lib")
#pragma comment (lib, "avutil.lib")
#pragma comment (lib, "swscale.lib")

#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

 

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] = "R://test";
 _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;
 AVCodec *pCodec;
 AVFrame *pFrame, *pFrameRGB;
 struct SwsContext *pSwsCtx;
 const char *filename = "test.avi";
 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 = 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]) =  pCodecCtx->width * (pCodecCtx->height-1);
    //pFrame ->linesize[0] = -(pCodecCtx->height);
    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);
 }

 sws_freeContext (pSwsCtx);
 av_free (pFrame);
 av_free (pFrameRGB);
 avcodec_close (pCodecCtx);
 av_close_input_file (pFormatCtx);

 return 0;
}

抱歉!评论已关闭.