• 在window下使用ffmpeg进行解码


     

    在window下使用ffmpeg进行解码

    分类: ffmpeg 18人阅读 评论(0) 收藏 举报

    ffmpeg的库可下载:搜索ffmpeg sdk 3.2即可得到。

    一、解码显示过程

    我使用的环境是vs2008

    头文件:

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

     #ifdef __cplusplus

    extern "C" {
    #endif
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    #ifdef __cplusplus
    }
    #endif

    1、注册所用编码器或者解码器
        av_register_all();

    2、打开视频文件
        AVFormatContext *pFormatCtx;//AVFormatContext 即format I/O context,比较重要,里面记录了流文件相关信息,基本贯穿整个处理流程

        // Open video file

        if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
           return -1; // Couldn't open file
        dump_format(pFormatCtx, 0,argv[1],  0);//用于调试,可以输出一些相关信息的

    3、获取流的一些信息,比如说解码时需要的height及width
        if(av_find_stream_info(pFormatCtx)<0)
           return -1; // Couldn't find stream information

    4、找到视频流

     AVCodecContext *pCodecCtx;//AVCodecContext即Codec的相关信息
     
     // Find the first video stream
     
     int videoStream=-1;
     
     for(int i=0; i<pFormatCtx->nb_streams; i++)
     {
      
      if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
       
        videoStream=i;
       
        break;
       
      }
      
     }
     if(videoStream==-1)
      
       return -1; // Didn't find a video stream
     
     // Get a pointer to the codec context for the video stream
     
     pCodecCtx=pFormatCtx->streams[videoStream]->codec;
    5、为对应的视频流找到编解码器
        // Find the decoder for the video stream
     
     AVCodec *pCodec;//编解码器信息
     pCodec = NULL;
     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
     
     if(pCodec==NULL) {
      
       fprintf(stderr, "Unsupported codec!\n");
      
       return -1; // Codec not found
      
     }
    6、为对应的流打开所需要的编码器
        // Open codec
     
     if(avcodec_open(pCodecCtx, pCodec)<0)
      
       return -1; // Could not open code
    7、解码
    -----分配一个AVFrame的结构,用于记录原始图像信息
     AVFrame *pFrame;
     pFrame = NULL;
     pFrame = avcodec_alloc_frame();
     
     if(pFrame==NULL)
      
       return -1;
    -----根据图像大小创建一个缓冲区
     uint8_t *buffer;
     
     int numBytes;
     
     // Determine required buffer size and allocate buffer
     
     numBytes=avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width,
      
     pCodecCtx->height);
     
     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
     avpicture_fill((AVPicture *)pFrame, buffer, PIX_FMT_RGB24,
      
     pCodecCtx->width, pCodecCtx->height);//填充AVPicture对应域
    -------解码
     int frameFinished;
     
     AVPacket packet;
     
     i=0;
     
     while(av_read_frame(pFormatCtx, &packet)>=0) {
      
      // Is this a packet from the video stream?
      
      if(packet.stream_index==videoStream) {
       
       // Decode video frame
       
         avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
        
         packet.data, packet.size);
       
       // Did we get a video frame?
       
       if(frameFinished) {


        显示视频。。。。。。
        
     
       }
       
      }
      
      // Free the packet that was allocated by av_read_frame
      
      
      
     }
    -------释放资源
     
     av_free_packet(&packet);
     av_free(buffer);
     
     av_free(pFrame);
     
     // Close the codec
     
     avcodec_close(pCodecCtx);
     
     // Close the video file
     
     av_close_input_file(pFormatCtx);
    -------显示视频
     1)加入SDL动态库
              1)下载SDL开发包SDL-devel-1.2.14-VC6.zip,并解压主要生成include、lib文件,下载地址:http://www.libsdl.org/download-1.2.php
              2)在vc的安装目录Microsoft Visual Studio\VC98\Include下创建一个新文件夹SDL,将1)中解压后的include文件夹中所有文件拷贝到所创建SDL文件夹中
              3)将1)中解压后的lib文件夹中.lib文件以及.dll文件拷贝到所创建的工程目录下
              4)在工程的选项配置为多线程已解决库冲突问题
              5)编译后会发现数据定义有冲突,我解决的办法是把SDL中对应的项注释掉
     2)初始化SDL库

     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) 
     {//SDL init
      
       fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
      
       return -1;
      
     }
     3)设置视频模式
     SDL_Surface *screen;
     
     screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
     
     if(!screen) //create a screen
     {
      
       fprintf(stderr, "SDL: could not set video mode - exiting\n");
       return -2;
     }
     4)创建贴图
     SDL_Overlay *bmp;
     
     bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,
      
     SDL_YV12_OVERLAY, screen);
     
     SDL_LockYUVOverlay(bmp);
     
     AVPicture pict;
     
     pict.data[0] = bmp->pixels[0];
     
     pict.data[1] = bmp->pixels[2];
     
     pict.data[2] = bmp->pixels[1];
     
     pict.linesize[0] = bmp->pitches[0];
     
     pict.linesize[1] = bmp->pitches[2];
     
     pict.linesize[2] = bmp->pitches[1];
     
     SwsContext *ctx;
     ctx = sws_getContext(
      pCodecCtx->width,
      pCodecCtx->height,
      pCodecCtx->pix_fmt,
      pCodecCtx->width,
      pCodecCtx->height,
      PIX_FMT_YUV420P,
      SWS_BICUBIC, NULL, NULL, NULL);
        
     if(ctx == NULL) 
     {
       fprintf(stderr, "Cannot get resampling context\n");
       return -3;
     }
     //sws_scale(  ctx,pFrame->data,pFrame->linesize,0,pCodecCtx->height,pFrame->data,pFrame->linesize);//原文中这句话没有注释,我在测试时发现需要注释掉才能成功
     sws_scale(  ctx,pFrame->data,pFrame->linesize,0,pCodecCtx->height,pict.data,pict.linesize);
     SDL_UnlockYUVOverlay(bmp);
     

     //draw
     
     5)显示图像
     SDL_Rect rect;
     rect.x = 0;   
     rect.y = 0; 
     rect.w = pCodecCtx->width;
     rect.h = pCodecCtx->height;
     SDL_DisplayYUVOverlay(bmp, &rect);
    二、注意
    1、此实例只解码视频
    2、显示图像的时候没有帧率方面的处理,所以播放速度过快,cpu占用率过高,有待完善

    原文地址:http://tianyou8.blog.hexun.com/46861549_d.html

     

    ffmpeg解码视频存为BMP文件

    分类: ffmpeg 5人阅读 评论(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. }   
  • 相关阅读:
    tapestrydomain modelxdocletmaven
    单元测试与GUI
    Bitufo
    纪念
    郁闷的报表问题(2)
    wordpress 列表页脚加广告
    <转>程序员,都去写一写前端代码吧
    <转> 编写超级可读代码的15个最佳实践
    wordpress 如何移除管理后台仪表盘小工具
    php简易页面内调试技巧
  • 原文地址:https://www.cnblogs.com/moonvan/p/2173443.html
Copyright © 2020-2023  润新知