2013年2月25日 星期一

libmms 在 iOS 下的使用方式

以下紀錄將 libmms 移植到 iPad 的實驗過程。



1. 下載 libmms
直接從官方網頁 http://sourceforge.net/projects/libmms/ 下載程式碼進行編譯,會無法正常編譯為 iOS 對應的 library。
編譯的命令如下: ./build.sh make
其中 build.sh 的內容如下: export CC=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc export CFLAGS="-arch i386" export LD=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk export AS=/usr/local/bin/gas-preprocessor.pl export LDFLAGS="-L/Users/albert/Work/pkg-config-0.28/glib":$LDFLAGS ./configure \ --prefix=/Users/albert/Work/libmms-0.6.2/compiled/i386
錯誤訊息如下: localhost:libmms-0.6.2 albert$ make make all-recursive Making all in src make all-am /bin/sh ../libtool --tag=CC --mode=link /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc -arch i386 -version-info 0:2:0 -no-undefined -export-dynamic -L/Users/albert/Work/pkg-config-0.28/glib: -o libmms.la -rpath /Users/albert/Work/libmms-0.6.2/compiled/i386/lib mms.lo mmsh.lo mmsx.lo uri.lo -L/opt/local/lib -lglib-2.0 -lintl libtool: link: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc -dynamiclib -o .libs/libmms.0.dylib .libs/mms.o .libs/mmsh.o .libs/mmsx.o .libs/uri.o -L/Users/albert/Work/pkg-config-0.28/glib: -L/opt/local/lib /opt/local/lib/libglib-2.0.dylib -lresolv /opt/local/lib/libintl.dylib /opt/local/lib/libiconv.dylib -lc -arch i386 -install_name /Users/albert/Work/libmms-0.6.2/compiled/i386/lib/libmms.0.dylib -compatibility_version 1 -current_version 1.2 ld: warning: directory not found for option '-L/Users/albert/Work/pkg-config-0.28/glib:' ld: warning: ignoring file /opt/local/lib/libglib-2.0.dylib, file was built for unsupported file format ( 0xcf 0xfa 0xed 0xfe 0x 7 0x 0 0x 0 0x 1 0x 3 0x 0 0x 0 0x 0 0x 6 0x 0 0x 0 0x 0 ) which is not the architecture being linked (i386): /opt/local/lib/libglib-2.0.dylib ld: warning: ignoring file /opt/local/lib/libintl.dylib, file was built for unsupported file format ( 0xcf 0xfa 0xed 0xfe 0x 7 0x 0 0x 0 0x 1 0x 3 0x 0 0x 0 0x 0 0x 6 0x 0 0x 0 0x 0 ) which is not the architecture being linked (i386): /opt/local/lib/libintl.dylib ld: warning: ignoring file /opt/local/lib/libiconv.dylib, file was built for unsupported file format ( 0xcf 0xfa 0xed 0xfe 0x 7 0x 0 0x 0 0x 1 0x 3 0x 0 0x 0 0x 0 0x 6 0x 0 0x 0 0x 0 ) which is not the architecture being linked (i386): /opt/local/lib/libiconv.dylib Undefined symbols for architecture i386: "_g_free", referenced from: _split_user_passwd in uri.o _gnet_uri_new in uri.o _gnet_uri_delete in uri.o _field_escape in uri.o _gnet_uri_set_scheme in uri.o _gnet_uri_set_userinfo in uri.o _gnet_uri_set_hostname in uri.o ... "_g_malloc", referenced from: _field_escape in uri.o "_g_malloc0_n", referenced from: _gnet_uri_new in uri.o _gnet_uri_new_fields in uri.o _gnet_uri_new_fields_all in uri.o _gnet_uri_clone in uri.o "_g_return_if_fail_warning", referenced from: _gnet_uri_new in uri.o _gnet_uri_clone in uri.o _gnet_uri_equal in uri.o _gnet_uri_hash in uri.o _gnet_uri_escape in uri.o _gnet_uri_unescape in uri.o _gnet_uri_get_string in uri.o ... "_g_str_hash", referenced from: _gnet_uri_hash in uri.o "_g_strdup", referenced from: _split_user_passwd in uri.o _gnet_uri_new in uri.o _gnet_uri_new_fields in uri.o _gnet_uri_new_fields_all in uri.o _gnet_uri_clone in uri.o _gnet_uri_set_scheme in uri.o _gnet_uri_set_userinfo in uri.o ... "_g_string_append", referenced from: _gnet_uri_get_string in uri.o "_g_string_append_printf", referenced from: _gnet_uri_get_string in uri.o "_g_string_free", referenced from: _gnet_uri_get_string in uri.o "_g_string_insert_c", referenced from: _g_string_append_c_inline in uri.o "_g_string_sized_new", referenced from: _gnet_uri_get_string in uri.o "_g_strndup", referenced from: _gnet_uri_new in uri.o "_libiconv", referenced from: _string_utf16 in mms.o "_libiconv_close", referenced from: _mms_connect in mms.o "_libiconv_open", referenced from: _mms_connect in mms.o ld: symbol(s) not found for architecture i386 collect2: ld returned 1 exit status make[3]: *** [libmms.la] Error 1 make[2]: *** [all] Error 2 make[1]: *** [all-recursive] Error 1 make: *** [all] Error 2


2. 編譯成 library
使用更改過後的libmms,直接使用 xCode 打開,則可以正確編譯。 
git clone git://github.com/aporat/xcode-libmms.git。 
編譯後的library位於 
/Users/albert/Library/Developer/Xcode/DerivedData/MMS-afkkckenpbbhexgcbgmgvvysynsy/Build/Products/Release-iphoneos

3. 比較 libmms 與 xcode-libmms 的差異處
主要在於 URI的使用方式。
 xcode-libmms 不會 #include uri.h,也不使用 GURI,透過新增四個參數 host, uri, query, pport利用這些參數取代原本 GURI的功能。

4. 使用 libmms
使用 xCode 開啟 xcode-libmms project。更改iOS Deployment Target,接著便可以編譯成iOS Device使用的library。
新增一個 project for iOS device,命名為 testMMS。 在 project中新增下列指令,編譯後會發現以下錯誤 
Undefined symbols for architecture armv7: "_iconv", referenced from: _string_utf16 in libMMS.a(mms.o) "_iconv_open", referenced from: _mms_connect in libMMS.a(mms.o) "_iconv_close", referenced from: _mms_connect in libMMS.a(mms.o) "_Status_GetNewStatusByKey", referenced from: _mms_connect in libMMS.a(mms.o) _mmsh_connect in libMMS.a(mmsh.o) _mmsh_connect_int in libMMS.a(mmsh.o) "_Status_SetNewStatusByKey", referenced from: _mms_connect in libMMS.a(mms.o) _mmsh_connect in libMMS.a(mmsh.o) _mmsh_connect_int in libMMS.a(mmsh.o) ld: symbol(s) not found for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)

解決方式: 
Step1. 在 xcode 專案中選擇要編譯的target,選擇 Build Phases 中的 Link Library With Libraries,新增 libiconv

Step2. _Status_SetNewStatusByKey 與 _Status_GetNewStatusByKey 是不需要的,因此直接在 xcode-libmms 中移除對應的程式,在重新編譯libmms即可。
執行下列程式,應該可以看到已經正確建立連線。 
mms_t *vpMMS; vpMMS=connect(NULL, NULL,"mms://bcr.media.hinet.net/RA000008","bcr.media.hinet.net","RA000008","",1755,64*1024);

註:實驗發現 ffmpeg 可以透過 mmsh 或 mmst 直接連結 mms 對應的音樂串流,因此後續實作網路電台時便沒有再使用 libmms 的函數。

參考資料:
1. http://sourceforge.net/projects/libmms/
2. http://www.wunderradio.com/code.html
3. http://biancheng.dnbcw.info/c/257462.html
4. http://fryfishtw.pixnet.net/blog/post/24293699-台灣網路廣播電台清單
5. http://stackoverflow.com/questions/7464851/libiconv-not-linking-to-ios-project