转 ffmpeg+sdl rstp 播放

基于ffmpeg+SDL2 实现简单rtsp播放器

参考资料:

           编译参考:         http://blog.chinaunix.net/uid-20718335-id-2980793.html

           代码参考:         http://blog.csdn.net/leixiaohua1020/article/details/8652605


实现ffmpeg在window下编译,并基于ffmpeg动态库用测试程序播放本地文件和RTSP视频流

csdn博客插个图片怎么这么麻烦,上篇辛辛苦苦截了那么多图一上传全没了,代码里想变色结果发布了一看全成HTML掺在程序里了,真是无语。。。

1、下载安装MinGW,http://sourceforge.net/projects/mingw/ 下载安装MinGW Installation Manager,选择mingw-develop-toolkit、mingw32-base、mingw32-gcc-g++、mysys-base,然后Apply Changes

2、进入到MinGW安装目录,默认是C:\MInGW,编辑C:\MinGW\msys\1.0\msys.bat,在文件开始加上 call "C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\vcvars32.bat" 根据具体VS路径,保存。

3、下载ffmpeg http://www.ffmpeg.org/releases/ 选择最新版本,当前是ffmpeg-2.2.4.tar.gz

       下载yasm  http://yasm.tortall.net/Download.html(ffmpeg汇编编译器)

       下载mp3lame http://sourceforge.net/projects/lame/files/(支持MP3)

       下载x264 http://www.videolan.org/developers/x264.html(支持264)

       下载SDL2 http://www.libsdl.org/release/SDL2-devel-2.0.3-VC.zip (SDL 多媒体开发库,用来显示,因此直接下载已编译好的)

       另外几个可选项:

       Xxid  http://www.xvid.org/

       faad2 http://www.audiocoding.com/downloads.html

       faac http://www.audiocoding.com/downloads.html

       aacenc http://sourceforge.net/projects/opencore-amr/files/

       amr-nb amr-wb http://www.penguin.cz/~utx/amr

       opencore-amr http://sourceforge.net/projects/opencore-amr/files/

4、解压yasm,将exe放到c:\windows\system32下

       解压ffmpeg,并将上面的第三方包分别解压到ffmpeg文件夹下

       运行mysys.bat

        安装mp3lame

[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. cd lame-3.99.2  
  2. ./configure --disable-shared  
  3. make  
  4. make install  


       安装x264
[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. cd x264-snapshot-20140703-2245  
  2. ./configure --enable-shared  
  3. make   
  4. make install  

       安装其他第三方库同上
       默认安装到C:\MinGW\msys\1.0\local下

       安装ffmpeg

[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. cd ffmpeg-2.2.4  
  2. ./configure --enable-shared --disable-static --enable-ffplay --enable-nonfree --enable-memalign-hack --enable-libmp3lame --enable-gpl --enable-libx264 --enable-version3 --extra-cflags=-IC:/MinGW/msys/1.0/local/include --extra-ldflags=-LC:/MinGW/msys/1.0/local/lib  
  3. make  
  4. make install  
make install时出现错误:
C:\MinGW\bin\strip.exe: unable to rename 'C:/MinGW/msys/1.0/local/bin/avcodec-55
.dll'; reason: File exists

后来发现将360关了就好了


OK,烦人的编译过程已经结束,接下来就可以愉快的写测试demo了

==================================================================================================================================

1、VS2010建立VC++  win32控制台项目

2、在工程目录下建立lib目录和include目录,将已编译好的lib拷打lib下,include拷到include下,dll拷到Debug目录下,sdl2解压编译好的文件拷贝到相应目录

3、工程属性--配置属性--VC++目录--包含目录,添加ffmpeg头文件目录及其他第三方头文件目录

                                             链接器--常规--附加库目录,添加lib目录

                                             链接器--输入--附加依赖项,添加各个lib名

4、在include下新建文本文档 添加#define FFMPEG_VERSION "2.2.4" 并保存为version.h

5、添加ffmpeg-test.cpp

  1. // ffmpeg-test.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5.   
  6. #ifdef __cplusplus  
  7. extern "C" {  
  8. #endif  
  9.   
  10. #include <avcodec.h>  
  11. #include <avdevice.h>  
  12. #include <avformat.h>  
  13. #include <avfilter.h>  
  14. #include <avutil.h>  
  15. #include <swscale.h>  
  16. #include <SDL/SDL.h>  
  17.   
  18. #ifdef __cplusplus  
  19. }  
  20. #endif  
  21.   
  22. int _tmain(int argc, _TCHAR* argv[])  
  23. {  
  24.     AVFormatContext *pFormatCtx;  
  25.     int             i, videoindex;  
  26.     AVCodecContext  *pCodecCtx;  
  27.     AVCodec         *pCodec;  
  28.     char filepath[]="nwn.mp4";  
  29.     //char rtspUrl[] = "rtsp://192.168.11.19/live0.264";  
  30.     //char rtspUrl[] = "rtsp://218.204.223.237:554/live/1/0547424F573B085C/gsfp90ef4k0a6iap.sdp";  
  31.     char rtspUrl[] = "rtsp://211.139.194.251:554/live/2/13E6330A31193128/5iLd2iNl5nQ2s8r8.sdp";  
  32.     av_register_all();//注册组件  
  33.     avformat_network_init();//支持网络流  
  34.     pFormatCtx = avformat_alloc_context();//初始化AVFormatContext  
  35.     if(avformat_open_input(&pFormatCtx,/*filepath*/rtspUrl,NULL,NULL)!=0){//打开文件  
  36.         printf("无法打开文件\n");  
  37.         return -1;  
  38.     }  
  39.     if(av_find_stream_info(pFormatCtx)<0)//查找流信息  
  40.     {  
  41.         printf("Couldn't find stream information.\n");  
  42.         return -1;  
  43.     }  
  44.     videoindex=-1;  
  45.     for(i=0; i<pFormatCtx->nb_streams; i++) //获取视频流ID  
  46.         if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)  
  47.         {  
  48.             videoindex=i;  
  49.             break;  
  50.         }  
  51.     if(videoindex==-1)  
  52.     {  
  53.         printf("Didn't find a video stream.\n");  
  54.         return -1;  
  55.     }  
  56.     pCodecCtx=pFormatCtx->streams[videoindex]->codec;  
  57.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);//查找解码器  
  58.     if(pCodec==NULL)  
  59.     {  
  60.         printf("Codec not found.\n");  
  61.         return -1;  
  62.     }  
  63.     if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)//打开解码器  
  64.     {  
  65.         printf("Could not open codec.\n");  
  66.         return -1;  
  67.     }  
  68.     AVFrame *pFrame,*pFrameYUV;  
  69.     pFrame=avcodec_alloc_frame();//存储解码后AVFrame  
  70.     pFrameYUV=avcodec_alloc_frame();//存储转换后AVFrame(为什么要转换?后文解释)  
  71.     uint8_t *out_buffer;  
  72.     out_buffer=new uint8_t[avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)];//分配AVFrame所需内存  
  73.     avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//填充AVFrame  
  74.   
  75.     //------------SDL初始化--------  
  76.     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {    
  77.         printf( "Could not initialize SDL - %s\n", SDL_GetError());   
  78.         return -1;  
  79.     }   
  80.     SDL_Window *screen = SDL_CreateWindow("RTSP Client Demo",  
  81.                           SDL_WINDOWPOS_UNDEFINED,  
  82.                           SDL_WINDOWPOS_UNDEFINED,  
  83.                           pCodecCtx->width, pCodecCtx->height,  
  84.                           SDL_WINDOW_RESIZABLE/* SDL_WINDOW_HIDDEN*/| SDL_WINDOW_OPENGL);  
  85.     if(!screen) {    
  86.         printf("SDL: could not set video mode - exiting\n");    
  87.         return -1;  
  88.     }  
  89.     SDL_Renderer* sdlRenderer = SDL_CreateRenderer(screen, -1, 0);    
  90.     SDL_Texture* sdlTexture = SDL_CreateTexture(    
  91.         sdlRenderer,    
  92.         SDL_PIXELFORMAT_YV12,    
  93.         SDL_TEXTUREACCESS_STREAMING,    
  94.         pCodecCtx->width,    
  95.         pCodecCtx->height);   
  96.    
  97.     SDL_Rect rect;  
  98.     //-----------------------------  
  99.     int ret, got_picture;  
  100.     static struct SwsContext *img_convert_ctx;  
  101.     int y_size = pCodecCtx->width * pCodecCtx->height;  
  102.   
  103.     SDL_Event event;   
  104.     AVPacket *packet=(AVPacket *)malloc(sizeof(AVPacket));//存储解码前数据包AVPacket  
  105.     av_new_packet(packet, y_size);  
  106.     //输出一下信息-----------------------------  
  107.     printf("文件信息-----------------------------------------\n");  
  108.     av_dump_format(pFormatCtx,0,filepath,0);  
  109.     printf("-------------------------------------------------\n");  
  110.     //------------------------------  
  111.     while(av_read_frame(pFormatCtx, packet)>=0)//循环获取压缩数据包AVPacket  
  112.     {  
  113.         if(packet->stream_index==videoindex)  
  114.         {  
  115.             ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);//解码。输入为AVPacket,输出为AVFrame  
  116.             if(ret < 0)  
  117.             {  
  118.                 printf("解码错误\n");  
  119.                 return -1;  
  120.             }  
  121.             if(got_picture)  
  122.             {  
  123.                 //像素格式转换。pFrame转换为pFrameYUV。  
  124.                 img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);   
  125.                 sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);  
  126.                 sws_freeContext(img_convert_ctx);  
  127.                 //------------SDL显示--------  
  128.                 rect.x = 0;      
  129.                 rect.y = 0;      
  130.                 rect.w = pCodecCtx->width;      
  131.                 rect.h = pCodecCtx->height;      
  132.                   
  133.                 SDL_UpdateTexture( sdlTexture, &rect, pFrameYUV->data[0], pFrameYUV->linesize[0] );    
  134.                 SDL_RenderClear( sdlRenderer );    
  135.                 SDL_RenderCopy( sdlRenderer, sdlTexture, &rect, &rect );    
  136.                 SDL_RenderPresent( sdlRenderer );  
  137.                 //延时40ms  
  138.                 SDL_Delay(20);  
  139.                 //------------SDL-----------  
  140.             }  
  141.         }  
  142.         av_free_packet(packet);  
  143.         SDL_PollEvent(&event);    
  144.         switch( event.type ) {    
  145.             case SDL_QUIT:    
  146.                 SDL_Quit();    
  147.                 exit(0);    
  148.                 break;    
  149.             default:    
  150.                 break;    
  151.         }    
  152.     }  
  153.   
  154.     SDL_DestroyTexture(sdlTexture);   
  155.     delete[] out_buffer;  
  156.     av_free(pFrameYUV);  
  157.     avcodec_close(pCodecCtx);  
  158.     avformat_close_input(&pFormatCtx);  
  159.   
  160.     return 0;  
  161. }  
参考了网上的资料并做了修改,主要是ffmpeg接口和SDL2接口的改变,SDL2改动的接口参照 http://wiki.libsdl.org/MigrationGuide,ffmpeg改动的接口在源码目录下的doc\APIchanges文件
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值