• ffmpeg解码视频存为BMP文件


    分类: ffmpeg2011-07-28 12:13 8人阅读 评论(0) 收藏 举报
    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. }   
  • 相关阅读:
    linux挂载windows共享文件夹
    Cython
    python并行编程
    数据库学习----MySQL 存储引擎
    数据库学习----MySQL 日志
    数据库学习----从文件l数据到数据库
    Golang 学习 ---- 编译打包
    数字转换成千字符
    el-select选择框宽度与输入框相同
    git常用命令总结
  • 原文地址:https://www.cnblogs.com/moonvan/p/2173467.html
Copyright © 2020-2023  润新知