?
?
Qt
與
ffmpeg
與
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的錯誤,不知道該怎么解決,在網上沒查到有用的信息 !以后用的時候再解決這個問題,反正現在也可以編譯了。
(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(); ?
191.
??
}?
就可以看到圖像了,哈哈。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

