用 Mingw64 編譯 mp4v2

很早之前我在使用 cygwin 的時候發現他不方便, 想要拿 open source 的專案來用,  編譯出來的環境還要再開 cygwin 才能跑, 十分不便利, 而當時 mingw 也還沒有很成熟.

但是最近我因為工作需求又開始再重新去 study 這部份的知識. 一用之下發現 MinGW64 + MSYS2 簡直是超強, 我都以為我在 Linux 底下開發. MSYS2 內建類似 ArchLinux 的套件系統 Pacman, 可以輕易的就產補足所缺的 Library. 就算是沒有, 還可以下載 source code 自行安裝到 MSYS2 底下. 




不過有一點需要注意的是, MinGW 編譯出來的 DLL檔沒辦法在 Visual Studio 下使用. 只能用 gcc 或是 clang 下使用. 如果是純 C 的 Library, 其實是還好, google 一下就有 solution 了. 但是 Visual studio compiler 跟 gcc 在實作 c++ 底層記憶體管理的方式不同造成他們不相容, 不過 Visual studio 專用的 library/DLL 在 gcc 下運作是完全沒問題的. 關於如何設定 MinGW, 網上都有很詳細的說明文件, 在此就不再詳述, 大致上就是下載 MSYS2 以及 MinGW 並在第一次設定 MSYS2 環境的時候指定 MinGW 的路徑即可.

現在大部分的影音檔都有一定的格式, 例如: mp4, m4a, mkv, 這個檔案格式的概念就是相當於一個容器, 你可以在裡面採用不同的影音壓縮格式, 但是外面包的都是同一種檔案格式. MP4 檔案格式有點複雜, 我是建議大家可以上網 google 了解一下.

因為工作上的需求需要解 M4A(Apple AAC) 檔案格式, 所以我就去找了一下, 畢竟重複發明輪子是一件很蠢的事情. 而且 MP4 檔案格式有點複雜, 要實作太花時間. 目前我是採用 mp4v2 這個 solution. 他可以解析 mp4 檔案並告訴我們影音檔的壓縮格式, 取得每一段資料相對應的時間以及實際資料. 甚至於他可以解析 iTunes 產生的歌曲資訊, 例如像作者, 專輯, 音樂類型等等.
要用 MinGW 編譯 mp4v2 需要花費點功夫. 首先先安裝 svn

pacman -S subversion

下載 mp4v2 的原始碼:

svn checkout http://mp4v2.googlecode.com/svn/trunk/ mp4v2-read-only

千萬不要用官網上打包好的穩定版, 問題很多.

接下來就是重點了. mp4v2 目前還是只有支援舊版的 MinGW, 所以需要做 patch. 以下是 patch 的內容, 可以存成 .patch 檔做 patch. 假設我存成 mingw.patch

diff --git a/GNUmakefile.am b/GNUmakefile.am
index 947e6e3..d2026ae 100644
--- a/GNUmakefile.am
+++ b/GNUmakefile.am
@@ -150,7 +150,6 @@ libmp4v2_la_SOURCES += \
     libplatform/platform.h               \
     libplatform/platform_base.h          \
     libplatform/platform_posix.h         \
-    libplatform/platform_win32.h         \
     libplatform/process/process.h        \
     libplatform/prog/option.cpp          \
     libplatform/prog/option.h            \
@@ -170,6 +169,7 @@ if ADD_PLATFORM_POSIX
 endif
 if ADD_PLATFORM_WIN32
     libmp4v2_la_SOURCES += \
+ libplatform/platform_win32.cpp       \
         libplatform/io/File_win32.cpp          \
         libplatform/io/FileSystem_win32.cpp    \
         libplatform/number/random_win32.cpp    \
diff --git a/configure.ac b/configure.ac
index 83e9dce..7ec65a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,7 @@ AC_ARG_ENABLE([mingw_mt],
 ###############################################################################
 
 AC_PROG_CXX
+AC_LIBTOOL_WIN32_DLL
 AC_PROG_LIBTOOL
 
 AC_CHECK_PROG([FOUND_HELP2MAN],[help2man],[yes],[no])
@@ -100,7 +101,6 @@ case ${host} in
     ;;
 *-*-mingw*)
     # do not support shared
-    enable_shared=no
     X_PLATFORM=win32
     X_MINGW_LIBS="$X_MINGW_LIBS"
     X_CXX_W="$X_CXX_W -Wno-format"
@@ -207,6 +207,9 @@ case ${host} in
     *-*-cygwin*)
         X_libmp4v2_la_LDFLAGS='-no-undefined'
         ;;
+    *-*-mingw*)
+        X_libmp4v2_la_LDFLAGS='-no-undefined'
+        ;;
     *)
         X_libmp4v2_la_LDFLAGS=
         ;;
diff --git a/include/mp4v2/platform.h b/include/mp4v2/platform.h
index d400edf..4c693e2 100644
--- a/include/mp4v2/platform.h
+++ b/include/mp4v2/platform.h
@@ -26,7 +26,7 @@
     #endif
 #endif
 
-#if defined( _WIN32 ) || defined( __MINGW32__ )
+#if defined( _WIN32 ) && !defined( __MINGW32__ )
 #   if defined( MP4V2_EXPORTS )
 #       define MP4V2_EXPORT __declspec(dllexport)
 #   elif defined( MP4V2_USE_DLL_IMPORT ) || !defined( MP4V2_USE_STATIC_LIB )

然後切換到 mp4v2 的目錄底下做 patch

cd mp4v2-read-only
patch 1 < mingw.patch

接下來就是用 autotools 編譯了, 預設路徑是 ~/mp4v2, 如果有缺指令的可以用 pacman -S -l | grep [package_name] 去看看檔案在哪, 並用 pacman -S [package_name] 去安裝.

cd ~/mp4v2-read-only
automake --add-missing
autoreconf --install
./configure --prefix=`echo ~`/mp4v2
make
make install
之後就是去安裝路徑撈已經編譯好的 library, 編譯好的dll檔案是 ~/mp4v2/bin/libmp4v2-2.dll, lib 檔則是 ~/mp4v2/lib/libmp4v2.dll.a. 在 Windows實際對應的路徑是 [where_you_install_msys2]/home/[username]/mp4v2. [where_you_install_msys2] 是 msys2的安裝路徑, [username] 是 Windows 使用者帳號名稱.

我的習慣是都會把 libmp4v2.dll.a 改名成 libmp4v2.a 再使用. 記得開發的時候要把 include path 加進 ~/mp4v2/include. 然後編譯的時候再用 -L"path" -lmp4v2 做連結, 記得要把 .dll 放在跟編譯好的執行檔同一目錄才不會有 runtime error.

留言

熱門文章