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;   
BITMAPFILEHEADERFAR *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;   
BITMAPINFOHEADERFAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;   
   
#endif   
    //YUV_BMP_CreateBmpHead(head,m_hDecoder->width,m_hDecoder->height);

//BYTE head[sizeof(BITMAPFILEHEADER) +sizeof(BITMAPINFOHEADER)];
// ZeroMemory(head,sizeof(head));
//保存BMP文件的函数  
void SaveAsBMP (AVFrame *pFrameRGBint widthint heightint indexint 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 (&bmpheadersizeof(bmpheader), 1fp);   
    fwrite (&bmpinfosizeof(bmpinfo), 1fp);   
    fwrite (pFrameRGB->data[0], width*height*bpp/81fp);   
       
    fclose(fp);   
}   
   
//主函数  
int main (void)   
{   
    unsigned int i = 0videoStream = -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(&pFormatCtxfilenameNULL0NULL) != 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=0i<pFormatCtx->nb_streamsi++ )   
    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(pCodecCtxpCodec)<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_BGR24pCodecCtx->widthpCodecCtx->height);   
    buf = (uint8_t*)av_malloc(PictureSize);   
       
    if ( buf == NULL )   
    {   
        printf"av malloc failed!\n");   
        exit(1);   
    }   
    avpicture_fill ( (AVPicture *)pFrameRGBbufPIX_FMT_BGR24pCodecCtx->widthpCodecCtx->height);   
       
//设置图像转换上下文  
    pSwsCtx = sws_getContext (pCodecCtx->width,   
             pCodecCtx->height,   
             pCodecCtx->pix_fmt,   
             pCodecCtx->width,   
             pCodecCtx->height,   
             PIX_FMT_BGR24,   
             SWS_BICUBIC,   
             NULLNULLNULL);   
    i = 0;   
    while(av_read_frame(pFormatCtx, &packet) >= 0)   
    {   
    if(packet.stream_index==videoStream)   
    {   
       avcodec_decode_video(pCodecCtxpFrame, &frameFinished,  
     packet.datapacket.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 (pSwsCtxpFrame->datapFrame->linesize0pCodecCtx->heightpFrameRGB->datapFrameRGB->linesize);   
     SaveAsBMP (pFrameRGBpCodecCtx->widthpCodecCtx->heighti++, 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、付费专栏及课程。

余额充值