2013年12月30日 星期一

Raspicam Code Review

*** This Note is the Code Review of Raspicam Video ***
RASPIVID_STATE

PORT_USERDATA : 



MMAL_COMPONENT_T
MMAL_CONNECTION_T
MMAL_POOL_T In void main() :

Initialization Section
  • RASPIVID_STATE  state // is data storage vessel ,資料都從這裡存取
  • MMAL_STATUS_T 
  • MMAL_PORT_T
    • camera_video_port (動態)
    • camera_still_port    (靜態)
    • preview_input_port
    • encoder 
      • encoder_input_port
      • encoder_output_port
signal(SIGINT, singnal_hanlder)
default_status( &state );
  • h = state.height
  • w = state.width
Initiailize window and OpenCV stuff

dstImage = cvCreateImage( cvSize(w,h), IPL_DEPTH_8U, 3) // 3 Channels
  • py, pu, pv        : py 大小 w*h, pu, pv 大小只有 w/2 * h/2 
  • pu_big, pv_big : big u, v 將上面的長寬統一,變為 w * h
由於編碼格式的關係 (planar format - I420),所以所以u, v長度較短,在組合成影像時必須經過內插。

  • 以YUV 4:2:0的方式記錄。 
  • YUV4:2:0並不是說只有U(即Cb), V(即Cr)一定為0,而是指U:V互相援引,時見時隱,也就是說對於每一個行,只有一個U或者V份量,如果一行是4:2:0的話,下一行就是4:0:2,再下一行是4:2:0...以此類推。 

為節省頻寬起見,大多數YUV格式平均使用的每像素位數都少於24位元。
主要的抽樣(subsample)格式有YCbCr 4:2:0、YCbCr 4:2:2、YCbCr 4:1:1和YCbCr 4:4:4。

YUV的表示法稱為A:B:C表示法:
  • 4:4:4表示完全取樣。
  • 4:2:2表示2:1的水平取樣,沒有垂直下採樣。
  • 4:2:0表示2:1的水平取樣,2:1的垂直下採樣。
  • 4:1:1表示4:1的水平取樣,沒有垂直下採樣。
Create Camera

create_camera_component( &state );
重要的  function ,裡面包括了mmal的初始化以及 video_buffer 的 callback function.

raspipreview_create( &state.preview_parameters ) ;

  • if not success : destroy_camera_component( &state )

PORT_USERDATA callback_data

camera_video_port
state.camera_component -> output[MMAL_CAMERA_VIDEO_PORT]; 

callback_data.pstate = &state

VCOS_STATUS_T vcos_status; // what is VCOS?
vcos_status = vcos_semaphore_create( &callback_data.complete_semaphore..);
vcos_assert(...);

這裡將來自camera 的 data pointer 指派給 user 讓 callback function 可以使用
camera_video_port -> userdata = 
(struct MMAL_PORT_USERDATA_T*) & callback_data;

 接下來的事情比較看不懂了,分別是

  • 初始化 timer
  • 開始抓取
  • 將所有的 buffer 送到 video port
  • wait until need to stop
  • disable all connections
  • destroy_encoder_components 
  • cvReleaseImage(IplImages)
之後仔細閱讀在詳述,現在應該把焦點放到 callback function 以及如何加速


In MMAL_COMPONENT_T *crate_camera_component( *state) : 

MMAL_ES_FORMAT_T *format
MMAL_COMPONENT_T *camera;
MMAL_PORT_T *video_port, *still_port, *preview_port; 

function 的流程為 :

  • Create camera component 
    • mmal_create_component(DEFAULT_CAMREA, &camera)
  • Set up camera configuration
    • 可以注意這種config設定的寫法
    • stills_yuv422 = 0; 暗示靜態有另一種編碼?
    • num_preview_video_frame = 3; (preview_video的意思待確定)

  • Set the encode format on the video port
    • format = video_port -> format;
  • Plug the callback to the video port
    • mmal_port_enable(video_port, video_buffer_callback); 
    • then ensure there is enough buffers to avoid dropping frames

  • Set the encode format on the still port 
    • Is still port necessary for video?
  • Create pool of message on video port
    • What is pool ?
  • Enable component

It seems that MMAL is the boardcom wrapper over OpenMAX. (Ref:Stack overflow

MMAL API runs over OpenMAX = Media Acceleration (中文/英文)
程式碼可以在Pi提供的userland中找到。
OpenMAX 的 簡介,他包含三層
  • DL (Development Layer) 
    • OpenMAX AL是多媒體應用程式(如Media Player)和平台媒體框架之間的介面。它允許公司開發應用程序方便地移植到不同平台的應用程序(客戶),並支持OpenMAX AL API。 
  • IL (Integration Layer) 
    • OpenMAX IL API透過C語言致力於打造可移植的媒體組件的陣列的平台。 
    • 這些組件可以是來源(source)、匯出(sink)、編解碼器(codec)、過濾器(filter)、分離器(splitter)、混頻器(mixers),或任何其他資料操作。
  • AL (Application Layer)
    • AL功能包括 視頻播放和錄製
    • 音頻播放和錄製
    • 圖像捕捉(攝像機)並顯示
    • 攝影控制
    • 廣播和RDS
    • 基本MIDI播放
    • 元數據(Metadata)的提取和插入

In video_buffer_callback(MMAL_PORT_T *port,                        MMAL_BUFFER_HEADER_T *buffer) : 

PORT_USERDATA *pData = (PORT_USERDATA*) port -> userdata; 

防止錯誤
...  if (pData) 
...  if (buffer -> length)

mmal_buffer_header_mem_lock( buffer ); 

不是很了解Memory lock再做什麼,但常常看到,似乎是重要的技巧。(待查

OpenCV  here
w = pData-> pstate->width;
h = pData-> pstate->height;
h4 = h >> 2;  // h= h/4 

接下來透過讀取YUV,得到影像,分成兩種情況 (determined by graymode in RASPIVID_STATE)

  • 如果要得到Color map,YUV三者接需要
  • 如果只要用到gray image ,計算Y值即可

mmal_buffer_header_mem_unlock( buffer ); 

There are two algorithm that we want implement on my Pi.

  • Template Matching
  • Optical flow 
為了實踐這兩種演算法我想用ARM提供的NEON SIMD來加速。

在Github上找到了neon的(浮點)加速測試範例 :vfp-test
浮點運算也很重要,因為optical flow將會用到)
但是可以看得出來,Pi 會產生錯誤訊息 :failed to run and generated an Illegal instruction exception.



Reference : 
補充知識 :

YUV format (Luminance, Chrominance, Chroma)
  • 緊縮格式(packed formats):將Y、U、V值儲存成Macro Pixels陣列,和RGB的存放方式類似。 
  • 平面格式(planar formats):將Y、U、V的三個份量分別存放在不同的矩陣中,Raspicam用的是這種方式。每Y份量,U份量和V份量都是以獨立的平面組織的,也就是說所有的U份量必須在Y分量後面,而V份量在所有的U份量後面,此一格式適用於採樣(subsample)。









沒有留言:

張貼留言