let them have their little white house please

seen from France
seen from Malaysia
seen from France
seen from France
seen from Türkiye
seen from Türkiye
seen from Türkiye

seen from T1
seen from Türkiye
seen from France
seen from United Kingdom

seen from France
seen from Türkiye
seen from United States

seen from India
seen from Malaysia
seen from China

seen from Malaysia

seen from Australia

seen from Malaysia
let them have their little white house please
i spent a couple of nights awake texting with a friend and ba-da-bum, man is transfem now
♛ OUT OF WORLDS
another got blog is following me. i -- where did you come from?
Raspberry Pi: VideoCore #2, MMAL
ตอนที่แล้วได้กล่าวถึง มาตรฐานเปิดต่างๆที่ผู้ผลิต VideoCore ได้เตรียมไว้ให้ คราวนี้มาดู API อีกชุดที่ไม่ได้เป็นมาตรฐานเปิดบ้าง
MMAL (Multi-Media Abstraction Layer)
MMAL เป็นชุด API หรือ frameworks อีกชุดหนึ่งทีผู้ผลิต VideoCore ได้เตรียมไว้ให้ โดยภาพรวมๆแล้วก็จะคลายๆกับ OpenMAX IL ที่เคยพูดถึงในครั้งที่แล้ว แต่ถูกออกแบบมาเฉพาะให้ใช้งานได้ง่ายขึ้น โดยใช้กับ VideoCore โดยเฉพาะ
รายละเอียดเอกสารการใช้งานต่างๆเกี่ยวกับ MMAL ในขณะที่ผมเขียนอยู่นี้ หาได้น้อยมาก จะมีเพียงเอกสารที่อยู่ใน Comment และแกะจากการทำงานของตัวอย่าง Code เท่านั้น ซึ่งผมก็หวังเอาไว้ว่าทางผู้ผลิตคงจะทำเอกสารคู่มือออกมาให้มากขึ้นกว่านี้
การใช้งานการทำงานต่างๆของ MMAL นั้นคล้ายกับ OpenMAX IL มาก นั้นคือมีลักษาณะที่เป็น Component, Port, Connection และ Tunnel เหมือนๆกัน เหตุที่ผมยกเอา MMAL มาอธิบายให้ดูก็เพราะตัวอย่าง Code สำหรับถ่ายภาพนิ่งภาพวิดีโอด้วยกล้องของ Raspberry Pi (raspicam) นั้นเขียนโดยใช้ MMAL ไม่ใช่ OpenMAX IL ทำให้การศึกษา Code เพื่อทำความเข้าใจและนำไปเขียนโปรแกรมติดต่อกับกล้องด้วย MMAL ใน Raspberry Pi นั้นจะง่ายๆกว่า เพราะสามารถนำเอา Code หลายๆส่วน หรือวิธีการ Set ค่าต่างๆ ลำดับขั้นตอนการทำงาน จากตัวอย่าง Code ใน raspicam ไปใช้ได้มาก
Coding
เพื่อความง่ายในการทำความเข้าใจและทดลองเขียนโปรแกรม ผมได้ถอดเอา code จาก raspicam ใน userland ออกมาเขียนใหม่ และโดยลด code ให้น้อยที่สุดเท่าที่จะยังพอทำงานได้ แล้วได้ใส่ไว้ใน github ที่
https://github.com/tasanakorn/rpi-mmal-demo
ท่านที่สนใจสามารถที่จะ
$ git clone https://github.com/tasanakorn/rpi-mmal-demo.git $ cd rpi-mmal-demo $ mkdir build $ cmake .. $ make
โดยมีเงื่อนไขนิดหนึ่งคือ code ชุดนี้ผมยังไช้ include และ library จาก userland อยู่ ทำให้ต้องมี userland https://github.com/raspberrypi/userland อยู่ด้วย โดยให้วางไว้ที่ /home/pi/src/raspberrypi/userland (หรือจะวางที่อื่น แล้วแก้ CMakeLists.txt ก็ได้)
How it works
อย่างที่บอกครับ หลักการทำงานของ MMAL นั้นคล้ายกับ OpenMAX IL มาก ตัวอย่าง code ผมก็จะเขียนแบบเดียวกับครั้งที่แล้ว
include <stdio.h>
#include <stdlib.h> #include "bcm_host.h" #include "interface/vcos/vcos.h" #include "interface/mmal/mmal.h" #include "interface/mmal/util/mmal_default_components.h" #include "interface/mmal/util/mmal_connection.h" #define MMAL_CAMERA_PREVIEW_PORT 0 #define MMAL_CAMERA_VIDEO_PORT 1 #define MMAL_CAMERA_CAPTURE_PORT 2 int main(int argc, char** argv) { MMAL_COMPONENT_T *camera = 0; MMAL_COMPONENT_T *preview = 0; MMAL_ES_FORMAT_T *format; MMAL_STATUS_T status; MMAL_PORT_T *camera_preview_port = NULL, *camera_video_port = NULL, *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; MMAL_CONNECTION_T *camera_preview_connection = 0; printf("Running...\n"); bcm_host_init(); status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { printf("Error: create camera %x\n", status); return -1; } camera_preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; { MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { { MMAL_PARAMETER_CAMERA_CONFIG, sizeof (cam_config)}, .max_stills_w = 1280, .max_stills_h = 720, .stills_yuv422 = 0, .one_shot_stills = 1, .max_preview_video_w = 1280, .max_preview_video_h = 720, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; mmal_port_parameter_set(camera->control, &cam_config.hdr); } format = camera_preview_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = 1280; format->es->video.height = 720; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = 1280; format->es->video.crop.height = 720; status = mmal_port_format_commit(camera_preview_port); if (status != MMAL_SUCCESS) { printf("Error: camera viewfinder format couldn't be set\n"); return -1; } status = mmal_component_enable(camera); status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &preview); if (status != MMAL_SUCCESS) { printf("Error: unable to create preview (%u)\n", status); return -1; } preview_input_port = preview->input[0]; { MMAL_DISPLAYREGION_T param; param.hdr.id = MMAL_PARAMETER_DISPLAYREGION; param.hdr.size = sizeof (MMAL_DISPLAYREGION_T); param.set = MMAL_DISPLAY_SET_LAYER; param.layer = 0; param.set |= MMAL_DISPLAY_SET_FULLSCREEN; param.fullscreen = 1; status = mmal_port_parameter_set(preview_input_port, ¶m.hdr); if (status != MMAL_SUCCESS && status != MMAL_ENOSYS) { printf("Error: unable to set preview port parameters (%u)\n", status); return -1; } } status = mmal_connection_create(&camera_preview_connection, camera_preview_port, preview_input_port, MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if (status != MMAL_SUCCESS) { printf("Error: unable to create connection (%u)\n", status); return -1; } status = mmal_connection_enable(camera_preview_connection); if (status != MMAL_SUCCESS) { printf("Error: unable to enable connection (%u)\n", status); return -1; } while (1); return 0; }
นั้นคือสร้าง component ที่เป็น camera และ video_render กำหนดค่า parameters ต่างๆ แล้วทำ tunnel port เข้าด้วยกัน ซึ่งผลการรันโปรแกรม ก็จะออกมา คล้ายๆ กับในตอนที่แล้ว (เพิ่มการปรับ Resolution ให้เป็นภาพ wide screen เข้ามา)
เมื่อเราเขาใจหลักการ การทำงานของเขียน MMAL และการทำงาน raspicam แล้ว เราก็จะประยุคดัดแปรงหรือเขียนโปรแกรมติดต่อกับกล้องหรือ component ต่างๆ ใน MMAL ได้