1,前言:
根據INSTALL.WIN32的描述,作者推薦大家在gnu/linux系統上,使用mingw32跨平台編譯win32版本的vlc.exe(以及附屬産品)
Building VLC from the source code
=================================
If you want to build VLC from sources, you can do it in several ways:
- On GNU/Linux, using the mingw32 cross-compiler.
This method is preferred over all the others.
- natively on Windows, using MSYS+MINGW (www.mingw.org)
(MSYS is a minimal build environment to compile Unixish projects under
windoze. It provides all the common Unix tools like sh, gmake...)
Please note that the gettext utilities are not included in the default
MSYS/MINGW packages so you won't be able to build VLC with i18n support.
UNSUPPORTED METHODS
-------------------
- natively on Windows, using cygwin (www.cygwin.com) with or without the
POSIX emulation layer. This is the preferred way to compile vlc if you want
to do it on Windows.
Read http://wiki.videolan.org/Win32CompileCygwinNew to have a complete HOWTO
- natively on Windows, using Microsoft Visual Studio. This will not work.
本文安裝的os環境是win7,試試看吧,可能也很多問題吧。
另外,mingw/minsys沒有再帶gettext工具,可能無法編譯多語言支援,(TODO: 給minsys裝上gettext工具)
mingw-get.exe install mingw32-gettext
2,下載下傳安裝mingw和minsys
http://nchc.dl.sourceforge.net/project/mingw/Installer/mingw-get-inst/mingw-get-inst-20120426/mingw-get-inst-20120426.exe
選擇以下元件:
C Compiler,
C++ Compiler,
MSYS basic system,
MinGW developer toolkit
打開MSYS終端
D:\MinGW\msys\1.0\msys.bat
3,下載下傳vlc的源代碼
http://download.videolan.org/pub/videolan/vlc/1.0.2/
tar xvjpf vlc-1.0.2.tar.bz2 -C /h
解壓到一個位置,本文的位置在/h,一個記憶體盤
4,下載下傳預編譯的第三方contrib庫依賴
http://download.videolan.org/pub/videolan/vlc/1.0.2/contribs-1.0.2-gcc-4.2.1-sjlj-runtime-3.15.2-only.tar.bz2
---- or ------
http://people.videolan.org/~jb/Contribs/contrib-20111017-win32-bin-gcc-4.4.4-runtime-3.17-only.tar.bz2
5,檢查pkg-config工具
http://jaist.dl.sourceforge.net/project/pkgconfiglite/0.28-1/pkg-config-lite-0.28-1_bin-win32.zip
解壓,複制lib和share檔案夾到/usr更目錄,覆寫
6,配置
如果,出現libavcodec找不到的錯誤,試試吧vlc整個目錄删除,重新解壓再configure。
PATH=/usr/win32/bin:$PATH \
PKG_CONFIG_PATH="/usr/win32/lib/pkgconfig" \
CPPFLAGS="-I/usr/win32/include -I/usr/win32/include/ebml" \
CXXFLAGS="-fpermissive" \
LDFLAGS="-L/usr/win32/lib" \
./configure \
--with-contrib=/usr/win32 \
--enable-nls \
--enable-sdl \
--enable-faad \
--enable-flac \
--enable-theora \
--enable-live555 \
--enable-caca \
--enable-goom \
--enable-fb \
--enable-twolame \
--enable-dvdread \
--enable-debug \
--disable-cddax \
--disable-vcdx \
--disable-fluidsynth \
--disable-mkv \
--disable-taglib \
--prefix=`pwd`/dest
7, 編譯
$ PATH=/usr/win32/bin:$PATH make -j
如果make -j 失敗,試試make
8, FAQ
.
1) 未定義WSA_QOS_EUNKNOWNPSOBJ
/*****************************************************************************
* winsock.c: POSIX replacements for Winsock
*****************************************************************************
* Copyright © 2006-2008 Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <errno.h>
#include <vlc_network.h>
#ifndef WSA_QOS_EUNKNOWNPSOBJ
#define WSA_QOS_EUNKNOWNPSOBJ 11024L
#endif
typedef struct
{
int code;
const char *msg;
} wsaerrmsg_t;
2) moc 不能執行
/usr/win32/bin 倆面有3個檔案 moc.exe rcc.exe uic.exe 另外還有3個不帶.exe的檔案,minsys會無法區分,建議把不帶.exe的三個檔案删掉,或者重命名成.elf的,
3) input_slider.cpp構造中調用構造
vlc-1.0.2\modules\gui\qt4\util\input_slider.cpp 構造函數調用構造函數,使用-fpermissive修改.
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive will
allow some nonconforming code to compile.
4) vtable-thunks檢查
dnl Check for fvtable-thunks support for mingw32
if test "${SYS}" = "mingw32" -a "${CXX}" != ""
then
AC_LANG_PUSH(C++)
AC_CACHE_CHECK([if \$CXX accepts -fvtable-thunks],
[ac_cv_cxx_fvtable_thunks],
[CXXFLAGS="${CXXFLAGS_save} -Wall -Werror -fvtable-thunks"
AC_TRY_COMPILE([],,ac_cv_cxx_fvtable_thunks=yes,
ac_cv_cxx_fvtable_thunks=no)])
if test "${ac_cv_cxx_fvtable_thunks}" = "yes"; then
CXXFLAGS_mingw32_special="-fvtable-thunks"
fi
CXXFLAGS_save="${CXXFLAGS_save} ${CXXFLAGS_mingw32_special}"; CXXFLAGS="${CXXFLAGS_save}"
AC_LANG_POP(C++)
fi
5) win7上用msys環境執行bootstrap失敗,很可能是autotool工具的版本問題,或者configure.ac的寫作不規範,改了幾處的quote,但是含有AS_IF等找不到的情況,有待研究。
6) linux上倒是可以很順利的bootstrap來生成Makfile.am等工作,但是linux native編譯可能存在的問題:
./configure --with-contrib=/usr/win32 --enable-nls --enable-sdl --disable-faad --enable-flac --enable-theora --enable-live555 --enable-caca --enable-goom --enable-fb --disable-twolame --disable-dvdread --enable-debug --disable-cddax --disable-vcdx --disable-fluidsynth --disable-mkv --disable-taglib --disable-glx --disable-qte --disable-skins2 --disable-fribidi --prefix=/root/harrywu/temp/vlc-1.0.2/dest
6.1) modules/codec/png.c 找不到 png_infopp_NULL
手動添加定義 #define png_infopp_NULL (png_infopp) NULL
6.2)modules/codec/x264.c
x264.c:995: error: ‘x264_param_t’ has no member named ‘b_bframe_pyramid’
https://trac.macports.org/ticket/24230
發現在x264.h的213行,有這個定義
typedef struct x264_param_t
{
// ...
int i_bframe_pyramid; /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */
// ...
修改 modules/codec/x264.c : 995
b_bframe_pyramid -> i_bframe_pyramid;
6.3) 還是x264.c報錯,x264_nal_encode找不到,
/* x264_nal_encode:
* encode a nal into a buffer, setting the size.
* if b_annexeb then a long synch work is added
* XXX: it currently doesn't check for overflow */
int x264_nal_encode( void *, int *, int b_annexeb, x264_nal_t *nal );
在x264.c頭部,聲明一下這個函數, libx263.a裡面應該有這個函數吧。
OK, linux 本地也編譯過了,但是沒有qt4界面,應該可以作為轉碼伺服器使用吧。
9,打包
目标位址下/bin/vlc.exe是不能直接運作的,需要打包
在打包之前,確定MSYS已經安裝了zip工具
mingw-get.exe install msys-zip
make package-win32-zip
可以在目前目錄下生成一個vlc-{version}.zip, 解壓這個zip,運作裡面的vlc.exe可以播放。
不過依然有個小問題,不能直接打開vlc的gui界面,有待調查,可以以 vlc.exe your_video_file_name.avi 播放檔案,提示vlc -I qt

2013.3.20
進展一:如果實在migw的指令行下執行./vlc.exe可以打開gui界面,但是直接在win7裡面輕按兩下就不行,可能是依賴某個msys的環境變量導緻的。
進展二:如果在msys裡面執行,用windbg檢視,vlc加載了
ModLoad: 6e940000 6e964000 d:\MinGW\bin\libgcc_s_dw2-1.dll
ModLoad: 6fc40000 6fd36000 d:\MinGW\bin\libstdc++-6.dll
以及
ModLoad: 031e0000 03a5c000 c:\vlc-1.0.2\plugins\libqt4_plugin.dll
可能是qt4子產品依賴于libgcc_s_dw2-1.dll & libstdc++-6.dll,
如果在mingw打開,可以通過/bin(d:\mingw\bin)找到這2個dll。
如果在win7直接打開,這2個dll的路徑未知。
是以,把這2個dll複制到vlc的安裝目錄下,就可以打開GUI界面了。
進展三:調查libqt4_plugin.dll是否依賴libgcc_s_dw2-1.dll & libstdc++-6.dll?
10, 調試
1,被調試程式的Ctrl_C處理
./debugbreak.exe pid_of_vlc_exe
2,符号表設定
複制生成的所有.dll.dbg檔案到dll所在的目前目錄(.; ./plugins),或者,通過以下指令指定符号表位置,如果build-id和crc校驗成功,mingw的gdb會自動加載這些符号表。
set debug-file-directory H:/symbols-1.0.2
3,源檔案目錄設定
gdb --pid pid_of_vlc_exe --directory source_dir
Breakpoint 1, vlc_entry__main (p_module=0x6237e8) at libvlc-module.c:1510
1510 vlc_module_begin ()
(gdb) bt
#0 vlc_entry__main (p_module=0x6237e8) at libvlc-module.c:1510
#1 0x6a5b90aa in AllocateBuiltinModule (p_this=0x622c6c,
pf_entry=0x6a544db8 <vlc_entry__main>) at modules/modules.c:1352
#2 0x6a5b7391 in __module_InitBank (p_this=0x622c6c) at modules/modules.c:140
#3 0x6a541663 in libvlc_InternalInit (p_libvlc=0x622c6c, i_argc=1,
ppsz_argv=0x28fda0) at libvlc.c:330
#4 0x6a3014ef in libvlc_new (argc=0, argv=0x28fe24, p_e=0x28fe5c)
at control/core.c:129
#5 0x004015b9 in [email protected] (hInstance=0x400000, hPrevInstance=0x0,
lpCmdLine=0x4b3bf5 "", nCmdShow=10) at winvlc.c:163
#6 0x00402356 in main (argc=4974184, argv=0x4be5f8, __p__environ=0)
at ../mingw/main.c:73
(gdb)
可以看到調用鍊vlc.exe -> libvlc -> libvlccore
libvlccore使用裝載一個builtin子產品main。
vlc_entry__main是main子產品的入口。
libvlc_InternalInit()
是一個很長的函數,主要是加載了modules的清單,隻是周遊所有plugins目錄,加載子產品,擷取子產品的描述資訊(cap,score,callback等),最後得到一個module的清單。
後面__module_need()隻要從裡面搜尋就可以了。
播放子產品(vout)打開時候的棧
Breakpoint 1, OpenVideo (p_this=0x5cc101c) at direct3d.c:161
161 vout_thread_t * p_vout = (vout_thread_t *)p_this;
(gdb) bt
#0 OpenVideo (p_this=0x5cc101c) at direct3d.c:161
#1 0x6d7813e6 in OpenVideoVista (obj=0x5cc101c) at direct3d.c:111
#2 0x6a5b7e7f in __module_need (p_this=0x5cc101c,
psz_capability=0x6a61b956 "video output", psz_name=0x5e033d0 "",
b_strict=false) at modules/modules.c:581
#3 0x6a5908bc in __vout_Create (p_parent=0x5ca3c5c, p_fmt=0x5cdf77c)
at video_output/video_output.c:490
#4 0x6a58fff2 in __vout_Request (p_this=0x5ca3c5c, p_vout=0x0,
p_fmt=0x5cdf77c) at video_output/video_output.c:286
#5 0x6a58639b in RequestVout (p_resource=0x5c521e0, p_vout=0x0,
p_fmt=0x5cdf77c, b_recycle=true) at input/resource.c:240
#6 0x6a586b08 in input_resource_RequestVout (p_resource=0x5c521e0,
p_vout=0x0, p_fmt=0x5cdf77c, b_recycle=true) at input/resource.c:454
#7 0x6a56e7aa in vout_new_buffer (p_dec=0x5cdf5c4) at input/decoder.c:2328
#8 0x6a569e74 in decoder_NewPicture (p_decoder=0x5cdf5c4)
at input/decoder.c:185
#9 0x66742c57 in GetNewPicture (p_dec=0x5cdf5c4) at libmpeg2.c:655
#10 0x66743303 in DpbNewPicture (p_dec=0x5cdf5c4) at libmpeg2.c:827
#11 0x66742014 in DecodeBlock (p_dec=0x5cdf5c4, pp_block=0x9dffe44)
at libmpeg2.c:271
#12 0x6a56cc36 in DecoderDecodeVideo (p_dec=0x5cdf5c4, p_block=0x5be6358)
at input/decoder.c:1458
#13 0x6a56d6c4 in DecoderProcessVideo (p_dec=0x5cdf5c4, p_block=0x5be6358,
b_flush=false) at input/decoder.c:1821
#14 0x6a56dc40 in DecoderProcess (p_dec=0x5cdf5c4, p_block=0x5be6358)
at input/decoder.c:1993
#15 0x6a56b5c3 in DecoderThread (p_this=0x5cdf5c4) at input/decoder.c:887
#16 0x6a5bfb2c in thread_entry (data=0x5cb03b0) at misc/threads.c:1093
#17 0x6a5bf7d5 in vlc_entry (data=0x5b8a970) at misc/threads.c:741
#18 0x766f1287 in msvcrt!_itow_s () from C:\Windows\syswow64\msvcrt.dll
#19 0x766f1328 in msvcrt!_endthreadex () from C:\Windows\syswow64\msvcrt.dll
#20 0x74ee33aa in KERNEL32!BaseCleanupAppcompatCacheSupport ()
from C:\Windows\syswow64\kernel32.dll
#21 0x09dfffd4 in ?? ()
#22 0x774e9ef2 in ntdll!RtlpNtSetValueKey ()
from C:\Windows\system32\ntdll.dll
#23 0x05cb3818 in ?? ()
#24 0x774e9ec5 in ntdll!RtlpNtSetValueKey ()
from C:\Windows\system32\ntdll.dll
#25 0x766f12e5 in msvcrt!_endthreadex () from C:\Windows\syswow64\msvcrt.dll
#26 0x00000000 in ?? ()
(gdb)
可以看出decoder子產品要輸出的時候,發現沒有vout結構,于是在input/resource.c : 2328 處請求建立vout:
input_resource_RequestVout(...)
從這裡可以得到一個簡單的方法檢視子產品的加載過程,break 一下某個子產品的入口回調,等斷點命中,檢視堆棧。
另外:vlc裡面,每一個module的使用者都有一個相應的結構體描述:
decoder module -> decoder_t
e.g.: decoder_t裡面的解碼回調函數來自decoder module裡面的靜态函數。
video output module-> vout_thread_t
e.g.: vout_thread_t裡面的顯示函數來自video output module裡面的靜态函數。
在libvlc-module.c中:
// Pretend we are a builtin module
#define MODULE_NAME main
#define MODULE_PATH main
#define __BUILTIN__
然後才包含<vlc_plugin.h>,而且這個檔案的編譯沒有加__PLUGIN__編譯,是以這個子產品的入口是vlc_entry__main。
否則,就和其他外置子產品類似了,使用這樣的子產品入口 vlc_entry__1_0_0e
# define MODULE_SYMBOL 1_0_0e
=====================================================================================
11,截圖:
參考:
vlc官方子產品編寫指南: http://wiki.videolan.org/Documentation:Hacker%27s_Guide/How_To_Write_a_Module
vlc官方filter指南: http://wiki.videolan.org/Hacker_Guide/Video_Filters
vlc編譯和結構分析
http://blog.csdn.net/szu030606/article/details/7210758
簡單的子產品編寫讨論
http://forum.videolan.org/viewtopic.php?f=32&t=57085