少尉

嗯。

 

在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. }   

posted on 2011-09-11 00:09  moonvan  阅读(1967)  评论(0编辑  收藏  举报

导航