2009年9月22日 星期二

在netbeans中使用opencv的 library

最近想來用opencv來寫一些cv的東西
一開始就是先灌opencv到ubuntu中
就直接用ubuntu的套件管理灌啦
選的是libcv-dev就可以了
他會自動灌libcv1, libhighgui1, libcvaux1,libcvauz-dev, libhighgui-dev...等的
這樣其實就可以用了 真方便
我為了看document來安裝了opencv-doc (不過證明其實可以不用 有更好用的)
那好用的document在哪裡勒
http://opencv.willowgarage.com/documentation/index.html
這個是在opencv的wiki上面的document 好用的地方是在可以搜尋

接下來是內容是要設定如何在netbeans中如何設定才能夠方便的使用
其實我有看了網路上的一篇教學
http://rorasa.wordpress.com/2009/08/19/opencv-with-netbeans-ide/
但是這篇有很多步驟我都沒做就可以用了

我從第三步開始做的  是要用code assistance的
但是第三步其實不用做 我沒又設定就可以用了 我猜有可能是因為ubuntu設定在default的位置

第四步要設定compile的include path用的
project properties中的Build的C++ Compiler中的Include Directories
我設定成/usr/include/opencv

接下來是第5步 要設定link用的library的路徑
我的設定方法很爛 直接加在additional options上面(應該有更好寫法)
project preperties中的Build中的Linker中的additional options
加上以下這四個就可以了
-lm -lcv -lhighgui -lcvaux
這樣就完成了 就可以在ubuntu底下的netbeans中用opencv了

2009年9月20日 星期日

用python分析ffmpeg的log

今天想將之前跑h.264產生的log來作一些處理來得到我想要的資訊
想當然的 我一開始會需要去看document 因為我從來就不會去記得function的名稱
結果今天我發現python的網站怪怪的 連不太上
我就想ubuntu裡面應該有python的document
就發現是要安裝一個套件python2.6-doc才可以
安裝好之後 就會發現/usr/share/doc裡面多一個python2.6-doc這個資料夾
裡面的html資料夾 就是平常會在網站上看到的文件
也可以從/usr/share/doc/python2.6/html/是一樣的地方(這裡才是真正的地方 剛剛那裡是symbolic link)

這樣我就可以開始parse我之前跑出來的log擋了
我主要用的東西是regular expression相關的module
這裡比較重要的是可以先做出一個regular expression的object
然後在用re的object來做match會產生match object
在match的object中會有很多相關的資訊可以利用
大致上就是這些

還有就是python現在已經沒有atoi()的function 用int()就可以完全取代了

h264 in ffmpeg deblocking filter survey

之前我已經確定說ffmpeg是以一個一個macroblock的形式去作inverse transform,prediction及deblocking filter
雖然說這跟standard寫得順序似乎有點出入
standard中寫是順序是要decode完一個完整frame的時候  才會一口氣做完deblocking filter
這裡就浮現了一個問題 就是每個macroblock都有可能會作intra prediction的動作(好 standard中寫只有I跟SI picture)
那在decode現在的macroblock會需要附近已經decode出來的macroblcok
那這些macroblock究竟是已經做完deblock filter還是還沒有做的勒
我看了standard發現這些時還沒有進行deblocking filter的macroblock 
這時候就會發現ffmpeg的h.264的code一定有在這個地方動手腳  可能是將還沒deblocking的macroblock不知道存在哪裡
不然要怎麼reference 不過這裡我之後再看

接下來我在看standrad中luma在boundary filtering strength小於4的時候的function
基本上做的事是跟h264_loop_filter_luma_c一樣 但是裡面的判斷式 跟standard中寫得並沒有完全一樣
我想一定是因為ffmpeg為了加速改寫了一大堆的東西  不過還好的是ffmpeg中的變數名稱還認得出來
不過看的話可能要在花點時間
還有就是小記一下h264_loop_filter_luma_c是一次處理16條6個byte的內容

另外我有沿者filter_mb來開始看code
發現其實要看的code其實沒有很多 有很多部份是跟mbaff 就查一下這是什麼吧
這好像是有field的時候才會需要的東西 去除掉這些東西的話
其實要看的code就沒這麼多了

2009年9月19日 星期六

virtualbox 3.0.6的小bug

其實我不知道這是不是這一版才有的bug
就是我現在想將網路設定成bridge adapter
我就使用virtualbox中的第一張網路卡設定成Bridged adapter
結果居然是偶爾才可以用  我本來以為是我們dhcp server的問題
結果看了很久才發現是virtualbox虛擬網卡的問題
我用預設的網路卡PCnet-FAST III(我之前在3.0.0就發現有問題)
這張網卡就是偶爾才連的上
結果我就換另一張網卡 Intel PRO/1000 MT Desktop 就一切正常了

所以我想以後virtualbox網路有問題的時候
可以先換換虛擬網卡 說不定問題就解決了

2009年9月18日 星期五

h.264在ffmpeg中 deblocking fileter的實做

我之前花了點時間看了h.264目前可以拿到的standard
我就仔細的看了deblocking filter實做部份的內容
應該是在8.7的部份  大致上跟我在wiki上面的deblocking filter paper是一樣的
但在這裡我看到驚人的東西
standard上面定義的deblocking filter執行時間 跟我自己在ffmpeg中不一樣
我在standard中看到的是在decode完一個frame後才對整張frame的一個一個macroblock作deblocking fileter
但是在ffmpeg中好像不是這樣
我看到的是他是在decode一個一個macroblock的時候 順便作deblock filter
我又仔細的看了一遍 並且用debugger設了一堆的breakpoint來確定執行的順序
沒錯真的一個一個macroblock這樣做

但是我有去看jm(h.264的reference software)了
發現的作法是跟standard寫得一模一樣  但是如果是這樣的話 就會比較好加速
不過這裡我就又不懂了 如果這樣做的話那麼在intra prediction的時候的macroblock 不就是沒有經過deblocking的macroblock
這樣不會是錯的嗎
不然我會因為在傳資料上花非常多時間

2009年9月17日 星期四

使用virtualbox的serial port

我現在想在virtualbox的guest中使用host的serial port
我的guest是window xp
而我的host是ubuntu 9.04
然後其實我的guest上面沒有serial port
我是利用usb to serial的線來產生出一個serial port的
virtualbox 3.0.6
以上就是我的環境

其實virtualbox中原本就有提供這樣的功能
所以只需要一些簡單的設定就可以用了
首先因為是usb to serial的轉接線 所以在ubuntu上面的serial port是在/dev/ttyUSB0(接很多條有可能是/dev/ttyUSB1之類的)
接下來是guest window xp的設定 所有的設定都是在序列埠的部份
首先要將啟用序列埠勾起來
在port number上面選COM1 其實也可以選其他項不過我沒試過 後面兩欄不用理他
在port Mode的部份選擇主端裝置
建立管線的部份不用選
最後是port/File Path就輸入/dev/ttyUSB0
這樣在guest window xp的配置就設好了
但是這樣還是不能動的
因為window xp還沒有偵測到COM1所以說還需要在windows上面裝上序列埠的driver才行

這樣就可以讓guest window xp看到一個序列埠

serial terminial的挑選

我原本是一直在用linux上面的minicom
會用這個的原因純粹是因為這是我在linux找到唯一可以接受serial input/output的software
其實我覺得也沒有做比較好  就是將就將就用

而且我一直覺得連線到板子上並且用minicom上面打指令很麻煩
會打的指令就是那些 u-boot上面又沒有histroy 也不能用上一個指令
我原本有找到一個方法就是寫u-boot的script
就是將要在u-boot上面要打得command打在一個檔案中
然後將這個檔案用u-boot提供的mkimage作成u-boot的script檔
再將這個檔用tftp傳到板子上 並用autoscr來執行傳到位置
但是這樣有個缺點就是還是要在minicom中打最少兩行的指令就是傳檔跟執行script
雖然說真的變少了 但是還是打了不少重複的東西

之前去某個training course的時候發現有一種在windows上面的terminal工具
這個工具是teraterm pro 這是個比超級終端機強大的的東西
他有提供一種東西叫做macro 是ttl 就是Tera Term Language
這就是host端上面寫script然後透過serial terminial傳到板子上
這樣就可以很容易的執行一大堆的指令

不過我覺得minicom上面一定有相同的功能
找了很久就找到了很相似的功能這個東西就叫做runscript
我就想太好了這樣也可以在linux上面寫terminal專用的script
不過我在仔細看 發現這兩樣似乎不是一樣的東西
runscript是只能在minicom一開始的時候執行 而不是在任何時間都可以執行
所以說並不是說非常好

後來就只好投向teraterm pro的懷抱了
我就開始研究簡單的ttl了
我現在會用的只有sendln跟wait
sendln就是丟一行指令
而wait就是等待某個字串出現
我現在是
sendln
wait
sendln
wait
這樣來寫 才能正常執行(要怎麼使用很簡單 就去看看TeraTerm附的doc就可以了)
目前我還不知道為什麼要用wait 有時間在繼續看
所以說我以後應該會是用TeraTerm當作我連serial的terminial

2009年9月8日 星期二

h.264 in ffmpeg -- deblocking

先繼續往deblocking 的部份看
因為我時再不知道這個deblocking 到底在做什麼
沒辦法 我這時只能靠google了 google了一陣子 我在wiki中的deblocking filter找到有用的pdf檔
in-loop deblocking filter for H.264/AVC video
這篇paper的內容並不是要告訴別人什麼是deblocking filter
他是要說明deblocking filter真的能有效的消除blocking  artifacts
不過同時他也很仔細的介紹了deblocking filter 是怎麼做的(這比spec中寫的好多了)

這裡稍微介紹一下paper好了 
一開始就說明以前的其他video standard都將deblocking filter放到optional或是沒設計
但是h.264卻是將他放到standard中一定要做的部份
還有介紹in-loop filter跟post filter的差別
in-loop filter就是h.264中的deblocking filter 是在一個個macroblock上面做的
post filter是都做完整個frame的時候 再對整張圖做的處理

接下來是用圖解的方式來說明說 怎麼對macroblock做處理
就是先在luma的的部份 再來由左到右一條條vertical(4條)做 然後再來由上到下一條條horizontal(4條)做
做完luma再來換chrominance 跟剛剛一樣但是這裡只有各兩條

基本上是這樣 再來是細節的部份這裡會分成三個部份 filter strength, filter decision, filter implementation
第一個是說這個filter的強度 分成0到4五種 0就是不用做 1到3是一種level 4是一種(這是我的理解 我沒看過spec)
第二個是決定說這個要不要做 剛剛0是一定不用做  這是是會用別的方法來決定還有哪些是不用做的
第三個就是實做的部份 這裡就是列了一堆的條件式 蠻複雜的

小記一下 deblocking filter是一個一個macroblock丟進去做

2009年9月6日 星期日

/dev/null的小研究


不知道為什麼我現在用的ramdisk上面會沒有/dev/null
所以我就開始看看網路上關於/dev/null的說明
基本上在wiki上面就有很好的說明了

簡單的來說/dev/null就是一個黑洞 什麼丟進去 什麼就會不見
這是一個好東西
知道之後現在就是要想辦法說在ramdisk上面 做出/dev/null

我有看到說打一下的指令就可以了
mknod -m 0666 /dev/null c 1 3
說明一下這個指令(主要是看man的)
這裡的-m是設定這個device的權限
然後/dev/null是這個node的名稱
c是指這是一個怎樣的device
1是major number
3是minor number
這裡要注意的就是以上的major number跟minor number是linux kernel中定義的
像在freebsd就不是這樣的

那究竟現在的我用的l4linux可不可以這樣打就能用了
我就去trace l4linux的source code去找/dev/null的實做(其實我是用google找的)
找到了(linux top)/drivers/char/mem.c 的null_fops就是/dev/null的實做
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
static const struct {
 unsigned int  minor;
 char   *name;
 umode_t   mode;
 const struct file_operations *fops;
} devlist[] = { /* list of minor devices */
 {1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
#ifdef CONFIG_DEVKMEM
 {2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
#endif
 {3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
#ifdef CONFIG_DEVPORT
 {4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
#endif
 {5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
 {7, "full",    S_IRUGO | S_IWUGO,           &full_fops},
 {8, "random",  S_IRUGO | S_IWUSR,           &random_fops},
 {9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops},
 {11,"kmsg",    S_IRUGO | S_IWUSR,           &kmsg_fops},
#ifdef CONFIG_CRASH_DUMP
 {12,"oldmem",    S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
#endif
};
987
988
if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
  printk("unable to get major %d for memory devs\n", MEM_MAJOR);
不過這裡重要的是要找到他用的major number跟minor number
這個時候 就看到了devlist這個variable
這裡定義了null的minor number是3
接下來找major number
這時看到一個macro 就是MEM_MAJOR他的宣告是在(linux top)/include/linux/major.h中
1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#ifndef _LINUX_MAJOR_H
#define _LINUX_MAJOR_H

/*
 * This file has definitions for major device numbers.
 * For the device number assignments, see Documentation/devices.txt.
 */

#define UNNAMED_MAJOR  0
#define MEM_MAJOR  1
#define RAMDISK_MAJOR  1
#define FLOPPY_MAJOR  2
然後在這裡MEM_MAJOR是1
這樣我確定l4linux裡面有實做/dev/null

所以就很放心的用上面的command 建立node 然後用echo測試
echo "hello" > /dev/null 看到/dev/null的size沒有變 很好成功了

在板子上播影片

我本來是將h.264轉mpeg 1 video的ffmpeg放在板子上 驗證他是不是正確
但是我現在我需要得到他的workload
我原本以為說其實mpeg 1 video的encode 應該是不會花多少時間
但是好像不是這樣的 我加上mpeg1 video的話fps就變成4到5之間
不過如果只有h.264 decoder的話 那們他的fps就會是9左右
可是這樣一樣沒有很好 因為還沒跑完就因為使用的memory量過大 就當機了
我本來以為只要導到/dev/null就會沒但是居然沒有耶 我的天阿

我目前有三條路可以走
第一條就是找找看有沒有辦法在ramdisk上面 做出一個/dev/null來 這樣就可以直接用H.264 decoder
第二條就是在找找看ffmpeg有沒有可以直接將decoder的資訊丟掉的辦法
第三條路就是繼續用h.264轉mpeg1 video的converter

2009年9月3日 星期四

python 比較不同資料夾的部份內容


最近再看學長的code 我發現有點小問題  就是他的reposiroty最早的版本不是他一開始沒改的版本
喔  不 所以說我只好手動來找是哪些檔改過了  我當然知道diff是我最好的朋友
不過我不知道要怎麼比整個資料夾 我感覺bash script一定可以最這件事  但是現在離我上次寫bash script有點久耶
雖然書在旁邊  完全不沒有想去翻他的慾望  難道我真的要一個一個手動打diff比嗎
其實也可以啦 反正大不了一百多個  那我就不用寫這篇了....

想想python好像蠻強大的  用用看吧
以下就是簡單的python code
1
2
3
4
5
6
7
8
9
#! /usr/bin/python
import os
import re
fileName = os.listdir("~/kernel_new/");
firDir = "~/kernel_new/"
secDir = "~/kernel/"
for oneName in fileName:
        if re.match(".*cpp", oneName):
                reslut = os.system("diff -c " + firDir + oneName + " " + secDir + oneName); 
主要用到的就是os跟re這兩個module 簡單介紹一下
os就是一些平常在bash可以打得一些command 其實就是一些system programming會出現的東西
re就是reguler expression的縮寫  這就是正規表示法 就是有*,?,.,[]等等的符號的東西  他是用來更方便描述string特性
程式一開始先用os.listdir()取得新的資料夾裡面有什麼
再來設定兩個資料夾是哪兩個資料夾(這裡好像有點重複到)
接者將一個個檔名抓出來比較看看結尾是不是cpp 是的話再用os.system去call diff來作比較
這樣簡單的一個檔案就可以比較整個資料夾的某些檔案

在這裡我曾經犯了一個錯誤  就是我忘了reguler expression是什麼了  跟bash的wildcard混在一起了
我還以為可以打*cpp就得到所有cpp結尾的檔案 當然是不行的 因為在*前面一定要接是什麼東西要重複
還又就是re.match()是只要string前面match就可以了  不需要全部的string

2009年9月1日 星期二

ffmpeg benchmark

今天突然想要看看H.264的某一段code花的時間
我就熊熊想到ffmpeg好像本來就有benchmark的功能
就想說用他裡面就有的benchmark來測一定很棒
結果就看一下code 原來只有ffmpeg.c中的main()有用到
他只是用來測av_encode這個function所花的時間 不會吧
我本來以為benchmark很強大

好吧 看來我要測地方的時間 就只需要將ffmpeg的benchmark相關的code複製過去就好了
因為其實ffmpeg benchmark相關的code也不複雜
既然這樣就來看看ffmpeg的benchmark是怎麼做的 我這邊只看linux是怎麼做 至於windows是怎麼做的就再說啦

其實他只實做了一個function -- getutime()
顧名思義他就是要取得micro second(百萬分之一秒)
這裡的話會根據不同的平台會call不同的function
在linux的話 他會用sys/resource.h的getrusage
他會用這個的目的是要得到user time而不是要wall-clock time
在這裡我覺得很合理 因為這是codec大部分的時間都會在user mode底下執行 很少在system mode底下執行

看了看感覺getrusage好像很強大 ffmpeg居然用他來benchmark
就上網查了一下 發現這個function也不是完美的 在hyperthread的processor好像會不準  不過我沒試過

我另外看到這篇不錯的東西 寫得很好
Benchmarking misconceptions, microtime() vs. getrusage()
雖然說最後的code是php 但是其實概念是一樣的

profiling tool的使用

我用的是valgrind中附的callgrind
另外觀看結果是用kcachegrind(這是一個KDE上面的application)
為什麼我不用gnome上面的application 原因很簡單  就是我找不到在gnome裡面對應的程式
不然我都用gnome的桌布怎麼會用KDE的application
好所以說我只要用的就是callgrind跟kcachegrind(如果是gnome桌布的話 灌的時後 會灌一堆KDE的套件)
這兩個套件都很好灌  都是直接打名字在synaptic裡面 就會找到了(callgrind是要打valgrind)

接下來就是用法了 因為callgrind是valgrind中的其中一個工具 所以說用callgrind 只是用valgrind的其中一個工具

valgrind --tool=callgrind [option] program_name
以上就是指令的打法
後面program_name(包括program_name以及他後面會接的一大堆有關這個program的選項) 這些就是原本我們執行這個程式後面會接的選項
中間的option是callgrind他自己特殊的選項 這裡我沒有特別去看
我用的時候都是用default就好了
我稍微看了一下 這裡的選項有一些功能像我們不一定要在程式開始的時候就profiling
可以執行到中間的時候在進行profiling 可能這是一個interactive的程式之類的
這時後會用到另一個指令是callgrind_control (我沒用過)

當打完以上的指令(就是valgrind那行) 然後等程式執行完(會比正常執行時間久 久很多)
會出現一個檔(如果沒有自己指定其他檔名的話) callgrind.out.[執行時候的pid]
(當然也有可能出現兩個檔以上 看你用幾個thread來執行程式)
這時候就可以用kcachegrind來看結果  相信我直接看檔什麼也看不懂的
kcachegrind是GUI的  很容易  看一看就會知道結果(比callgrind_annotate好看多了)