首页 > 代码库 > ffmpeg+sdl教程----------编写一个简单的播放器1

ffmpeg+sdl教程----------编写一个简单的播放器1

来源:http://blog.csdn.net/mu399/article/details/5813561

最近在研究ffmpeg,由于详细介绍ffmpeg的文档资料很少,有人就说了学习ffmpeg的最好办法就是看一些可以正常工作的代码,当你看懂 了ffmpeg.c和ffplay.c两个文件就算入门了,但是这两个文件相当恐怖啊,一个4300行,一个3200行,初学者难免看着难免头晕吃力,可 以先从简单的开始,比如output-example.c和api-example.c,然后再去网上找点稍微复杂点的例子来看

   我觉得这个(http://dranger.com/ffmpeg/tutorial01.html)教程很好,由浅入深,而最终代码也不过一千行多一点,非常适合像我这样的初学者,决定整理一下这个教程,方便以后查看

   首先是编译环境的搭建,先下载两个压缩包FFmpeg-full-SDK-3.2.rar和SDL-devel-1.2.14-VC8.zip,再下载一 个工程压缩包output_example_me(这个压缩包可以通过关键字“ffmpeg output-example”找到)。

   第一步,编译output_example_me中的工程

    解压output_example_me中的工程,我用的是vc2005编译的这个工程,也可用vc6.0来编译,如果编译成功了,运行程序会生成一个自 定义文件名的视频音频文件,这个文件通过简单的算法生成了规则变换的图像和声音(图像是几个有渐变色的斜放色条像左移动,声音很难听),至此ffmpeg 的环境就算搭建好了,可以成功编译http://dranger.com/ffmpeg/tutorial01.html的第一个例子了,要成功编译后面的例子需要SDL的支持。

    第二步,为工程导入SDL库,具体步骤可以通过搜索“vc SDL使用”找到相关教程,如果导入不成功可以为工程添加依赖项:

工程-->选项-->链接器-->输入-->附加依赖项:SDL.lib SDLmain.lib avcodec.lib avdevice.lib avfilter.lib avformat.lib avutil.lib swscale.lib

    例1的程序功能是把一个视频文件的前5帧导出为ppm格式的文件,ppm格式的文件可以通过ACDSee等软件打开

    下面是例1的完整代码:

[cpp] view plaincopy
  1. // tutorial01.c  
  2. // Code based on a tutorial by Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de)  
  3. // Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1  
  4.   
  5. // A small sample program that shows how to use libavformat and libavcodec to  
  6. // read video from a file.  
  7. //  
  8. // Use  
  9. //  
  10. // gcc -o tutorial01 tutorial01.c -lavformat -lavcodec -lz  
  11. //  
  12. // to build (assuming libavformat and libavcodec are correctly installed  
  13. // your system).  
  14. //  
  15. // Run using  
  16. //  
  17. // tutorial01 myvideofile.mpg  
  18. //  
  19. // to write the first five frames from "myvideofile.mpg" to disk in PPM  
  20. // format.  
  21.   
  22. #include "libavformat/avformat.h"  
  23. #include "libswscale/swscale.h"  
  24.   
  25. #include <stdio.h>  
  26. #include <math.h>  
  27.   
  28. void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)  
  29. {  
  30.     FILE *pFile;  
  31.     char szFilename[32];  
  32.     int  y;  
  33.   
  34.     // Open file  
  35.     sprintf(szFilename, "frame%d.ppm", iFrame);  
  36.     pFile=fopen(szFilename, "wb");  
  37.     if(pFile==NULL)  
  38.         return;  
  39.   
  40.     // Write header  
  41.     fprintf(pFile, "P6/n%d %d/n255/n", width, height);  
  42.   
  43.     // Write pixel data  
  44.     for(y=0; y<height; y++)  
  45.         fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);  
  46.   
  47.     // Close file  
  48.     fclose(pFile);  
  49. }  
  50.   
  51. int main(int argc, char *argv[])  
  52. {  
  53.     AVFormatContext *pFormatCtx;  
  54.     int             i, videoStream;  
  55.     AVCodecContext  *pCodecCtx;  
  56.     AVCodec         *pCodec;  
  57.     AVFrame         *pFrame;  
  58.     AVFrame         *pFrameRGB;  
  59.     AVPacket        packet;  
  60.     int             frameFinished;  
  61.     int             numBytes;  
  62.     uint8_t         *buffer;  
  63.   
  64.     if(argc < 2)  
  65.     {  
  66.         printf("Please provide a movie file/n");  
  67.         return -1;  
  68.     }  
  69.     // Register all formats and codecs  
  70.     av_register_all();  
  71.   
  72.     // Open video file  
  73.     if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)  
  74.         return -1; // Couldn‘t open file  
  75.   
  76.     // Retrieve stream information  
  77.     if(av_find_stream_info(pFormatCtx)<0)  
  78.         return -1; // Couldn‘t find stream information  
  79.   
  80.     // Dump information about file onto standard error  
  81.     dump_format(pFormatCtx, 0, argv[1], 0);  
  82.   
  83.     // Find the first video stream  
  84.     videoStream=-1;  
  85.     for(i=0; i<pFormatCtx->nb_streams; i++)  
  86.         if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)  
  87.         {  
  88.             videoStream=i;  
  89.             break;  
  90.         }  
  91.     if(videoStream==-1)  
  92.         return -1; // Didn‘t find a video stream  
  93.   
  94.     // Get a pointer to the codec context for the video stream  
  95.     pCodecCtx=pFormatCtx->streams[videoStream]->codec;  
  96.   
  97.     // Find the decoder for the video stream  
  98.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
  99.     if(pCodec==NULL)  
  100.     {  
  101.         fprintf(stderr, "Unsupported codec!/n");  
  102.         return -1; // Codec not found  
  103.     }  
  104.     // Open codec  
  105.     if(avcodec_open(pCodecCtx, pCodec)<0)  
  106.         return -1; // Could not open codec  
  107.   
  108.     // Allocate video frame  
  109.     pFrame=avcodec_alloc_frame();  
  110.   
  111.     // Allocate an AVFrame structure  
  112.     pFrameRGB=avcodec_alloc_frame();  
  113.     if(pFrameRGB==NULL)  
  114.         return -1;  
  115.   
  116.     // Determine required buffer size and allocate buffer  
  117.     numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,  
  118.                                 pCodecCtx->height);  
  119.     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));  
  120.   
  121.     // Assign appropriate parts of buffer to image planes in pFrameRGB  
  122.     // Note that pFrameRGB is an AVFrame, but AVFrame is a superset  
  123.     // of AVPicture  
  124.     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,  
  125.                    pCodecCtx->width, pCodecCtx->height);  
  126.   
  127.     static struct SwsContext *img_convert_ctx;  
  128.     if (img_convert_ctx == NULL)  
  129.     {  
  130.         img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,  
  131.                                          pCodecCtx->pix_fmt,  
  132.                                          pCodecCtx->width, pCodecCtx->height,  
  133.                                          PIX_FMT_RGB24,  
  134.                                          SWS_BICUBIC, NULL, NULL, NULL);  
  135.         if (img_convert_ctx == NULL)  
  136.         {  
  137.             fprintf(stderr, "Cannot initialize the conversion context/n");  
  138.             return 0;  
  139.         }  
  140.     }  
  141.     // Read frames and save first five frames to disk  
  142.     i=0;  
  143.     while(av_read_frame(pFormatCtx, &packet)>=0)  
  144.     {  
  145.         // Is this a packet from the video stream?  
  146.         if(packet.stream_index==videoStream)  
  147.         {  
  148.             // Decode video frame  
  149.             avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,  
  150.                                  packet.data, packet.size);  
  151.   
  152.             // Did we get a video frame?  
  153.             if(frameFinished)  
  154.             {  
  155.                 // Convert the image from its native format to RGB  
  156.                 sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,  
  157.                           0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);  
  158.                 // Save the frame to disk  
  159.                 if(++i<=5)  
  160.                     SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height,i);  
  161.             }  
  162.         }  
  163.   
  164.         // Free the packet that was allocated by av_read_frame  
  165.         av_free_packet(&packet);  
  166.     }  
  167.   
  168.     // Free the RGB image  
  169.     av_free(buffer);  
  170.     av_free(pFrameRGB);  
  171.   
  172.     // Free the YUV frame  
  173.     av_free(pFrame);  
  174.   
  175.     // Close the codec  
  176.     avcodec_close(pCodecCtx);  
  177.   
  178.     // Close the video file  
  179.     av_close_input_file(pFormatCtx);  
  180.   
  181.     return 0;  
  182. }  

output-example.c在linux下编译的参数为

gcc -g -o exa output-example.c -lavformat -lswscale `sdl-config --cflags --libs`

ffmpeg+sdl教程----------编写一个简单的播放器1