2012年3月24日 星期六

貼心的 libgmp

常在 $HOME 裡安裝一些自己需要的 library,剛好看到 libgmp 有個貼心的提醒:



..

..

2012年3月10日 星期六

[ffmpeg] 0.9 版後的新式 interrupt

這次試著更新專案內的 ffmpeg 至最新的 tag 版本 n0.9。發現專案內的『deprecated』比以往更多,但還都是能編譯的狀態。依慣例得確認一下在最新的 source code 裡,那些 deprecated 是真的被移除。於是編了 master branch 上的 code,發現 io interrupt callback 的寫法已經不再相容舊版了。

對於 ffmpeg 文件常跟不上 source code 的狀態,這連 changelog 也沒有記載這件事,我們可以簡單 diff n0.9 與前一版找出改變的部分,能利用一定會用到 io interrupt callback 的 ffmpeg.c 來作 diff:

..

舊式的 io interrupt callback 是一個 global function pointer:
..

新式的 io interrupt callback 使用一個 struct 包起來,設定在各別的 AVFormatContext:
..

要修改的部分雖然不太多,但 callback function 的參數有改,這是得注意的部分 :D

2012年3月7日 星期三

[osx] 發現 ARCHFLAGS 的妙用

試著用 easy_install 安裝 PIL 結果發生問題:

qrtt1$ sudo easy_install -U pil
Searching for pil
Reading http://pypi.python.org/simple/pil/
Reading http://www.pythonware.com/products/pil
Reading http://effbot.org/zone/pil-changes-115.htm
Reading http://effbot.org/downloads/#Imaging
Best match: PIL 1.1.7
Downloading http://effbot.org/media/downloads/PIL-1.1.7.tar.gz
Processing PIL-1.1.7.tar.gz
Running PIL-1.1.7/setup.py -q bdist_egg --dist-dir /var/folders/aQ/aQLNlFLOF28xewK2A7i0X++++TM/-Tmp-/easy_install-eVQU9j/PIL-1.1.7/egg-dist-tmp-L149wy
--- using frameworks at /System/Library/Frameworks
_imaging.c:3017: warning: initialization from incompatible pointer type
_imaging.c:3077: warning: initialization from incompatible pointer type
/usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/as: assembler (/usr/bin/../libexec/as/ppc/as or /usr/bin/../local/libexec/as/ppc/as) for architecture ppc not installed
Installed assemblers are:
/usr/bin/../libexec/as/x86_64/as for architecture x86_64
/usr/bin/../libexec/as/i386/as for architecture i386
/usr/bin/../libexec/as/arm/as for architecture arm
_imaging.c:3017: warning: initialization from incompatible pointer type
_imaging.c:3077: warning: initialization from incompatible pointer type
_imaging.c:3281: fatal error: error writing to -: Broken pipe
compilation terminated.
_imaging.c:3017: warning: initialization from incompatible pointer type
_imaging.c:3077: warning: initialization from incompatible pointer type
lipo: can't open input file: /var/folders/aQ/aQLNlFLOF28xewK2A7i0X++++TM/-Tmp-//ccCj3S35.out (No such file or directory)
error: Setup script exited with error: command 'gcc-4.2' failed with exit status 1

看了一下 log 訊息,發現怎麼多了編譯 arm 版本的動作呢?在網上也找到有人分享了它的解法,重點在於如何讓 easy_install 只編譯我們真正需要用到的 x86_64 與 i386 版本。原來重點在於 ARCHFLAGS 的使用:

sudo ARCHFLAGS="-arch i386 -arch x86_64" easy_install -U pil

感謝 Installing python PIL in MAC OS, having xcode4 提供的解決之道 :D

2012年3月5日 星期一

[ffmpeg] 由 0.8.7 昇級至 0.9 的 linking error on osx

由於舊的 swscale 在轉換 yuv 至 rgb 時,在某些 format 會產生一條綠色的矩形在底部。這個情況已經透過由 AVFrame 內的 data 抓出來,用 swscale 之外的工具驗證過了。但單純地將 yuv 轉成 png 是沒有那個綠色的矩形的。在回報 bug 或是要試著自行修復前,當然得做一點『標準動作』:

  • 確認下一個 stable 版是否也有同樣的問題
  • 確認 repo 上最新的狀態是否也有同樣的問題
目前採用的是 ffmpeg 0.8.7 加上我們自己的 patch,由 git fetch 後,我們能看到還有 0.8.8, 0.8.9 再來就進入了 0.9 版。我選擇了 0.9 版作為我們預計要使用的 stable 版本,利用 cherry-pick 簡單地 patch 需要的檔案後,編譯一切正常。但進入 xcode 編譯 Application 時發生了問題:


Undefined symbols for architecture x86_64:
"_kVDADecoderConfiguration_Height", referenced from:
_ff_vda_create_decoder in libavcodec.a(vda.o)
"_kVDADecoderConfiguration_Width", referenced from:
_ff_vda_create_decoder in libavcodec.a(vda.o)
"_kVDADecoderConfiguration_SourceFormat", referenced from:
_ff_vda_create_decoder in libavcodec.a(vda.o)
"_kVDADecoderConfiguration_avcCData", referenced from:
_ff_vda_create_decoder in libavcodec.a(vda.o)
"_kCVPixelBufferPixelFormatTypeKey", referenced from:
_ff_vda_create_decoder in libavcodec.a(vda.o)
"_kCVPixelBufferIOSurfacePropertiesKey", referenced from:
_ff_vda_create_decoder in libavcodec.a(vda.o)
"_VDADecoderCreate", referenced from:
_ff_vda_create_decoder in libavcodec.a(vda.o)
"_VDADecoderDecode", referenced from:
_ff_vda_decoder_decode in libavcodec.a(vda.o)
"_CVPixelBufferRelease", referenced from:
_ff_vda_release_vda_frame in libavcodec.a(vda.o)
_ff_vda_destroy_decoder in libavcodec.a(vda.o)
"_VDADecoderDestroy", referenced from:
_ff_vda_destroy_decoder in libavcodec.a(vda.o)
"_CVPixelBufferGetPixelFormatType", referenced from:
_vda_decoder_callback in libavcodec.a(vda.o)
"_CVPixelBufferRetain", referenced from:
_vda_decoder_callback in libavcodec.a(vda.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

有某些 symbol 找不到。查了一下 changelog,原來 0.9 版還多了 vda 的加速技能。既然在 ffmpeg 編譯時沒有問題,那應該就是 xcode 的設定需要改變,透過這些 symbol 名稱,找出了我們缺少了二個 framework:
加上這二個 framework 後,我們就能編譯正常並且使用具有 VDA 加速效果的 ffmpeg。

2012年3月4日 星期日

[autotools] 加入額外的 m4 路徑

要試著在 osx 上編譯 irssi,由於我並不是用 macports 安裝 library 的,有些 .m4 檔並不是裝預設的目錄。以 homebrew 來說,它會放在 homebrew 安裝目錄的 share/aclocal。為了要讓 irssi 提供的 autogen.sh 吃到我指定的 .m4 路徑,需要更動 ACLOCAL 變數:

ACLOCAL="aclocal -I. -I$HOME/app/homebrew/share/aclocal" ./autogen.sh

除此之外,再解決一些相依性的問題,我就能編譯自己的 irssi 了 :D

2012年3月2日 星期五

[autotools] configure 指定額外的 library

想試著編 ffmpeg 並且引用 libmp3lame 的功能。但我並沒有將此 library 裝在系統內,所以得另外指定 library 的位置:

CFLAGS="-I/opt/libmp3lame/include" LDFLAGS="-L/opt/libmp3lame/lib" ./configure --enable-libmp3lame --prefix=/opt/ffmpeg_full

主要就是透過 CFLAGS 指定 include path,透過 LDFLAGS 通知 linker 該去哪個目錄找 library

2012年3月1日 星期四

[Android] 偵測 USB 拔除

最近 Player 開始測試播放 USB 上的檔案,播放當然是正常的,只是當使用者未正常地結束播放就拔掉 USB 這件事就不知道怎麼處理了。
好在同事分享了一個方法,能直接透過 Broadcast Receiver 來獲得通知,重點在於要怎麼寫 IntentFilter:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_EJECT);
intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
intentFilter.addAction(Intent.ACTION_MEDIA_REMOVED);
intentFilter.addAction(Intent.ACTION_MEDIA_NOFS);
intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTABLE);
intentFilter.addAction(Intent.ACTION_MEDIA_SHARED);
intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
intentFilter.addDataScheme("file");


對我們的情況來說,最重要的是 Intent.ACTION_MEDIA_EJECT,因為不管怎麼樣,只要 USB 被拔掉了,而 Player 又在播放 local file 的情況我們就需要停下它。