详解 Qt与 ffmpeg 与 SDl 教程

移动开发
本文介绍的是Qt与 ffmpeg 与 SDl 教程,我们在这里需要做的是根据 qmake 所运行的平台来使用相应的作用域来进行处理。

Qtffmpeg SDl 教程是本文要介绍的内容,从多个角度介绍本文,运用了qmake,先来看内容。

1.  注释

从“ #” 开始,到这一行结束。

2.  指定源文件

  1. SOURCES = *.cpp  

对于多源文件,可用空格分开,如: SOURCES = 1.cpp 2.cpp3.cpp

或者每一个文件可以被列在一个分开的行里面,通过反斜线另起一行,就像这样 :

  1. SOURCES = hello.cpp   
  2.      main.cpp  

一个更冗长的方法是单独地列出每一个文件,就像这样:

 

  1. SOURCES+= hello.cpp   
  2. SOURCES +=main.cpp  

这种方法中使用“ +=” 比“ =” 更安全,因为它只是向已有的列表中添加新的文件,而不是替换整个列表。

3.  指定头文件

HEADERS = hello.h 或者 HEADERS += hello.h

列出源文件的任何一个方法对头文件也都适用。

4.  配置信息

CONFIG 用来告诉 qmake 关于应用程序的配置信息。

  1. CONFIG+= qt warn_on release  

在这里使用“ +=” ,是因为我们添加我们的配置选项到任何一个已经存在中。这样做比使用“ =” 那样替换已经指定的所有选项是更安全的。

A> qt 部分告诉 qmake 这个应用程序是使用 Qt 来连编的。这也就是说 qmake 在连接和为编译添加所需的包含路径的时候会考虑到 Qt 库的。

B> warn_on 部分告诉 qmake 要把编译器设置为输出警告信息的。

C> release 部分告诉 qmake 应用程序必须被连编为一个发布的应用程序。在开发过程中,程序员也可以使用 debug 来替换 release

5.  指定目标文件名

  1. TARGET = filename  

如果不设置该项目,目标名会被自动设置为跟项目文件一样的名称

6.  添加界面文件 (ui)

  1. INTERFACES = filename.ui  

7.  平台相关性处理

我们在这里需要做的是根据 qmake 所运行的平台来使用相应的作用域来进行处理。为 Windows 平台添加的依赖平台的文件的简单的作用域看起来就像这样:

  1. win32 {   
  2. SOURCES += hello_win.cpp   
  3. }  

所以如果 qmake 运行在 Windows 上的时候,它就会把 hello_win.cpp 添加到源文件列表中。如果 qmake 运行在其它平台上的时候,它会很简单地把这部分忽略。

8.  如果一个文件不存在,停止 qmake

如果某一个文件不存在的 时候,你也许不想生成一个 Makefile 。我们可以通过使用 exists() 函数来检查一个文件是否存在。我们可以通过使用 error() 函数把正在运 行的 qmake 停下来。这和作用域的工作方式一样。只要很简单地用这个函数来替换作用域条件。对 main.cpp 文件的检查就像这样:

  1. !exists( main.cpp ) {   
  2.   error( "No main.cpp file found")   
  3. }  

“!” 用来否定这个测试,比如,如果文件存在, exists( main.cpp) 是真,如果文件不存在, !exists( main.cpp ) 是真。

9.  检查多于一个的条件

假设你使用 Windows 并且当你在命令 行运行你的应用程序的时候你想能够看到 qDebug() 语句。除非你在连编你的程序的时候使用 console 设置,你不会看到输出。我们可以很容易地把 console 添加到 CONFIG 行中,这样在 Windows 下, Makefile 就会有这个设置。但是如果告诉你我们只是想在当我们的应用程序运行在 Windows 下并且当 debug 已经在 CONFIG 行中的时候,添加 console 。这需要两个嵌套的作用域;只要生成一个作用域,然后在它里面再生成 另一个。把设置放在最里面的作用域里,就像这样:

  1. win32 {   
  2.   debug {   
  3.      CONFIG += console   
  4.   }   
  5. }  

嵌套的作用域可以使用冒号连接起来,像这样:

  1. win32:debug {   
  2. CONFIG += console   
  3. }  

10.  摸板

模板变量告诉 qmake 为这个应用程序生成哪种 makefile 。下面是可供使用的选择:

A> app - 建立一个应用程序的 makefile 。这是默认值,所以如果模板没有被指定,这个将被使用。

B> lib - 建立一个库的 makefile 。

C> vcapp - 建立一个应用程序的 VisualStudio 项目文件。

D> vclib - 建立一个库的 VisualStudio 项目文件。

E> subdirs - 这是一个特殊的模板,它可以创建一个能够进入特定目录并且为一个项目文件生成 makefile 并且为它调用 make 的 makefile 。

11、生成 Makefile

当你已经创建好你的项目文件,生成 Makefile 就很容易了,你所要做的就是先到你所生成的项目文件那里然后输入:

Makefile 可以像这样由“ .pro” 文件生成:

  1. qmake -oMakefile hello.pro  

对于 VisualStudio 的用户, qmake 也可以生成“ .dsp” 文件,例如:

  1. qmake -tvcapp -o hello.dsp hello.pro  

参考文档:详解 QT 中.pro文件的写法 

Qmake 不仅仅只用于QT其他地方也用到了,根据模板的值可以生成app,lib,vclib等待makefile文件

(2)声明其他的库

如果你需要在工程中使用其他的库 , 需要在工程文件里面指定

让 qmake 找到库的路径和相应需要连接的库 , 可以在 LIBS 变量里面添加 . 库的路径要给出 , 或者常见的 unix 样式的符号来指定库和库的路径

例如下面的展示了如何使用指定的库

  1. LIBS += -L/usr/local/lib -lmath  

可以用类似的方法来指定头文件的路径 , 不过是使用 INCLUDEPATH 变量 , 如下面可能添加好几个头文件的路径

  1. INCLUDEPATH = c:/msdev/include d:/stl/include  

不过我的习惯是下面这样的 , 比较清晰还有 , 最好 windows 的路径不要有空格 , 中文也不要有 , 斜杠也推荐用 / 而不是 windows 的 \ 因为跟分行符号 \ 相同了 / 可以在 unix 和 windows 用 , 但是 \ 貌似到了 unix 或 linux 就不行了 , 所以用 / 是通用的

  1. INCLUDEPATH = c:/msdev/include \   
  2.                             d:/stl/include  

见别人是这样添加到

在 .pro文件中添加LIBS += -lavformat  -lavcodec -lavutil lz -lavutil -lm `sdl-config --cflags --libs`

(3)因为ffmpeg是c程序,所以在编译的时候需要在头文件中加入

  1. extern "C" {  
  2. #include <ffmpeg/avcodec.h> 
  3. #include <ffmpeg/avformat.h> 
  4. }  

注:这里的C是大写。我之前好久没动手编程,这也查了蛮久,打击自信心啊!!!!

解释如下:

1、extern 是 C/C++ 语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器 其声明的函数和变量可以在本模块或其它模块中使用;

2、与 extern 对应的关键字是 static ,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被 extern “C” 修饰;

3、被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和连接的;

4、C编译器和c++编译器对函数的翻译不一样,如:int  root(int a,int b);c对应的是_root,c++对应的是_root_int_int,因为c不支持重载而c++支持,因此需要识别函数的参数。

(4)直接运行可执行文件出现缺少minwm10.dll错误提示,将D:\Qt\2009.05\mingw\bin;D:\Qt\2009.05\qt\bin添加到环境变量就可以了。

(5)因为现在比较熟悉opencv,就用opencv+qt尝试qt连接库

  1. INCLUDEPATH +=   C:\OpenCV\cv\include \  
  2.   C:\OpenCV\cvaux\include \  
  3.   C:\OpenCV\cxcore\include \  
  4.   C:\OpenCV\otherlibs\highgui  
  5. LIBS +=   C:\OpenCV\lib\cv.lib \  
  6.   C:\OpenCV\lib\cvaux.lib \  
  7.   C:\OpenCV\lib\cxcore.lib \  
  8.   C:\OpenCV\lib\highgui.lib \  

程序可以编译运行,但是出现could not initialize ole的错误,不知道该怎么解决,在网上没查到有用的信息 !以后用的时候再解决这个问题,反正现在也可以编译了。

#p#

(6)接着用同样的方法改下.pro文件,添加头文件和库文件

  1. INCLUDEPATH +=   
  2.  
  3.                D:\Qt\2009.05\ffmpeg\include\libavcodec \  
  4.                D:\Qt\2009.05\ffmpeg\include\libavdevice \  
  5.                D:\Qt\2009.05\ffmpeg\include\libavfilter \  
  6.                D:\Qt\2009.05\ffmpeg\include\libavformat \  
  7.                D:\Qt\2009.05\ffmpeg\include\libavutil \  
  8.                D:\Qt\2009.05\ffmpeg\include\libswscale \  
  9.                D:\Qt\2009.05\ffmpeg\include \  
  10. LIBS +=   
  11.  
  12. D:\Qt\2009.05\ffmpeg\lib\avcodec.lib \  
  13. D:\Qt\2009.05\ffmpeg\lib\avdevice.lib \  
  14. D:\Qt\2009.05\ffmpeg\lib\avfilter.lib \  
  15. D:\Qt\2009.05\ffmpeg\lib\avformat.lib \  
  16. D:\Qt\2009.05\ffmpeg\lib\avutil.lib \  
  17. D:\Qt\2009.05\ffmpeg\lib\swscale.lib \  

(7)添加Sdl库

同理在文件中添加

  1. D:\Qt\2009.05\SDL\include \   
  2. D:\Qt\2009.05\SDL\lib\SDL.lib \  
  3. D:\Qt\2009.05\SDL\lib\SDLmain.lib \  

并加入头文件

  1. #include <SDL.h> 
  2. #include <SDL_thread.h>  

编译会出现一个错误

  1. undefined reference to `qMain(int, char**)'  

这是因为sdl中的 SDL _main.h已经定义了main,加上#undef main就可以解决了

(8)在av_register_all();时遇到 exited with code -1073741515错误

这是因为ffmpeg没有配置好,出现这个错误的原因是没有找到dll,dll一般是放在C:\WINDOWS\system32目录下的,我把他ffmpeg的库,复制到该目录下就ok了 ×— —×

(9)将tutorial02.c的代码改改,如下:

  1. #include <QtGui/QApplication> 
  2. #include "mainwindow.h"  
  3. #include <stdio.h> 
  4. #include <QLabel> 
  5. #include <QWidget>   
  6.  
  7. extern "C"{  
  8. #include <avcodec.h> 
  9. #include <avformat.h> 
  10. #include <swscale.h> 
  11. #include <SDL.h> 
  12. #include <SDL_thread.h> 
  13. }   
  14.  
  15. #ifdef __MINGW32__  
  16. #undef main /* Prevents SDL from overriding main() */  
  17. #endif   
  18.  
  19. int main(int argc, char *argv[])  
  20. {   
  21.      QApplication a(argc, argv);   
  22.  
  23.      AVFormatContext *pFormatCtx;  
  24.      int             i, videoStream;  
  25.      AVCodecContext  *pCodecCtx;  
  26.      AVCodec         *pCodec;  
  27.      AVFrame         *pFrame;  
  28.      AVPacket        packet;  
  29.      int             frameFinished;  
  30.      float           aspect_ratio;  
  31.      static struct   SwsContext *img_convert_ctx;  
  32.      static int sws_flags = SWS_BICUBIC;   
  33.  
  34.      SDL_Overlay     *bmp;  
  35.      SDL_Surface     *screen;  
  36.      SDL_Rect        rect;  
  37.      SDL_Event       event;   
  38.  
  39.      MainWindow w;  
  40.      QLabel *frame_pre;  
  41.      frame_pre = new QLabel;  
  42.      QWidget *widget_player;  
  43.      widget_player = new QWidget();  
  44.      widget_player->setAttribute(Qt::WA_PaintOnScreen);  
  45.      widget_player->setAttribute(Qt::WA_NoSystemBackground);  
  46.      widget_player->show();  
  47.      w.show();  
  48.      frame_pre->show();   
  49.  
  50.      av_register_all();   
  51.  
  52.     /*set sdl env*/  
  53.     char variable[64];  
  54.     #ifdef Q_OS_WIN  
  55.     sprintf(variable, "SDL_WINDOWID=0x%lx", widget_player->winId());  
  56.     #else  
  57.     sprintf(variable, "SDL_WINDOWID=0x%lx", this->winId());  
  58.     #endif  
  59.     putenv(variable);   
  60.  
  61.     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {  
  62.         fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());  
  63.         exit(1);  
  64.       }   
  65.  
  66.     // Open video file  
  67.     if(av_open_input_file(&pFormatCtx, "D:\\Flyhigh.wmv", NULL, 0, NULL)!=0)  
  68.       return -1; // Couldn't open file   
  69.  
  70.     // Retrieve stream information  
  71.     if(av_find_stream_info(pFormatCtx)<0)  
  72.        return -1; // Couldn't find stream information   
  73.  
  74.     // Dump information about file onto standard error  
  75.     dump_format(pFormatCtx, 0, "D:\\Flyhigh.wmv", 0);   
  76.  
  77.     // Find the first video stream  
  78.     videoStream=-1;  
  79.     for(i=0; i<pFormatCtx->nb_streams; i++)  
  80.         if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {  
  81.           videoStream=i;  
  82.           break;  
  83.         }  
  84.     if(videoStream==-1)  
  85.          return -1; // Didn't find a video stream   
  86.  
  87.     // Get a pointer to the codec context for the video stream  
  88.     pCodecCtx=pFormatCtx->streams[videoStream]->codec;   
  89.  
  90.     // Find the decoder for the video stream  
  91.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
  92.       if(pCodec==NULL) {  
  93.         fprintf(stderr, "Unsupported codec!\n");  
  94.         return -1; // Codec not found  
  95.       }   
  96.  
  97.     // Open codec  
  98.     if(avcodec_open(pCodecCtx, pCodec)<0)  
  99.       return -1; // Could not open codec   
  100.  
  101.     // Allocate video frame  
  102.     pFrame=avcodec_alloc_frame();   
  103.  
  104.     // Make a screen to put our video  
  105.     #ifndef __DARWIN__  
  106.             screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);  
  107.     #else  
  108.             screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 24, 0);  
  109.     #endif  
  110.     if(!screen) {  
  111.         fprintf(stderr, "SDL: could not set video mode - exiting\n");  
  112.         exit(1);  
  113.       }   
  114.  
  115.     // Allocate a place to put our YUV image on that screen  
  116.     bmp = SDL_CreateYUVOverlay(pCodecCtx->width,  
  117.                                        pCodecCtx->height,  
  118.                                        SDL_YV12_OVERLAY,  
  119.                                        screen);   
  120.  
  121.     // Read frames and save first five frames to disk  
  122.     i=0;   
  123.  
  124.     while(av_read_frame(pFormatCtx, &packet)>=0) {  
  125.     // Is this a packet from the video stream?  
  126.     if(packet.stream_index==videoStream) {  
  127.     // Decode video frame  
  128.     avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,  
  129.                                    packet.data, packet.size);  
  130.     // Did we get a video frame?  
  131.     if(frameFinished) {  
  132.                       SDL_LockYUVOverlay(bmp);  
  133.                       AVPicture *pict;  
  134.                       pict = new AVPicture;  
  135.                       pict->data[0] = bmp->pixels[0];  
  136.                       pict->data[1] = bmp->pixels[2];  
  137.                       pict->data[2] = bmp->pixels[1];   
  138.  
  139.                       pict->linesize[0] = bmp->pitches[0];  
  140.                       pict->linesize[1] = bmp->pitches[2];  
  141.                       pict->linesize[2] = bmp->pitches[1];   
  142.  
  143.                       // Convert the image into YUV format that SDL uses  
  144.                       if (pCodecCtx->pix_fmt == PIX_FMT_YUV420P) {  
  145.                       /* as we only generate a YUV420P picture, we must convert it  
  146.                         to the codec pixel format if needed */  
  147.                       img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,  
  148.                                                               pCodecCtx->pix_fmt,  
  149.                                                                pCodecCtx->width, pCodecCtx->height,  
  150.                                                                PIX_FMT_YUV420P,  
  151.                                                                sws_flags, NULL, NULL, NULL);  
  152.                           if (img_convert_ctx == NULL) {  
  153.                                fprintf(stderr, "Cannot initialize the conversion context\n");  
  154.                                exit(1);  
  155.                                }  
  156.                           sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,  
  157.                                            0, pCodecCtx->height, pict->data, pict->linesize);  
  158.                         }  
  159. //                    img_convert(&pict, PIX_FMT_YUV420P,  
  160. //                                (AVPicture *)pFrame, pCodecCtx->pix_fmt,  
  161. //                                pCodecCtx->width, pCodecCtx->height);  
  162.                       SDL_UnlockYUVOverlay(bmp);  
  163.                       rect.x = 0;  
  164.                       rect.y = 0;  
  165.                       rect.w = pCodecCtx->width;  
  166.                       rect.h = pCodecCtx->height;  
  167.                       SDL_DisplayYUVOverlay(bmp, &rect);  
  168.                     }  
  169.           }   
  170.                   // Free the packet that was allocated by av_read_frame  
  171.                   av_free_packet(&packet);  
  172.                   SDL_PollEvent(&event);  
  173.                   switch(event.type) {  
  174.                   case SDL_QUIT:  
  175.                     SDL_Quit();  
  176.                     exit(0);  
  177.                     break;  
  178.                     default:  
  179.                     break;  
  180.                   }   
  181.      }  
  182.      // Free the YUV frame  
  183.      av_free(pFrame);   
  184.  
  185.      // Close the codec  
  186.      avcodec_close(pCodecCtx);   
  187.  
  188.      // Close the video file  
  189.      av_close_input_file(pFormatCtx);  
  190.      return a.exec();  

就可以看到图像了,哈哈。

小结:关于Qtffmpeg SDl 教程的内容介绍完了,希望本文对你有帮助。更多内容请参考编辑推荐。

责任编辑:zhaolei 来源: CSDN博客
相关推荐

2011-06-24 09:13:30

QT SDL

2011-06-24 10:05:51

QT 对象 父对象

2011-07-04 15:48:57

Qt 桌面

2011-06-21 17:23:40

QT 编译

2009-06-23 11:44:31

业务应用信息安全SDL

2011-06-24 10:54:34

Qt Mysql

2011-07-01 12:52:50

Ubuntu Qt wxWidgets

2011-09-07 16:28:46

QT WidgetQWidget

2011-06-20 11:14:09

Qt QxtGlobalS 热键

2011-06-13 09:33:04

2011-06-30 15:25:05

QT QPF TTF

2011-06-24 17:05:07

QT QT 4.7.3 windows

2011-09-01 16:01:25

Qt插件

2011-07-01 16:04:45

Qt Python

2011-06-14 14:41:14

Python Qt

2011-09-01 15:10:22

Qt数据库SQL

2011-07-04 17:26:00

Qt SQLite

2011-09-01 15:51:53

Qt插件VS 2010

2011-06-22 13:27:04

QT QMap

2020-12-30 11:07:43

开发安全SDLDevSecOps
点赞
收藏

51CTO技术栈公众号