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 ) ;
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;
接下來的事情比較看不懂了,分別是
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( &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)
程式碼可以在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)
mmal_buffer_header_mem_unlock( buffer );
There are two algorithm that we want implement on my Pi.
... 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來加速。
(浮點運算也很重要,因為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)。
沒有留言:
張貼留言