【AWTK使用经验】如何播放视频或摄像头画面

描述

AWTK是基于C语言开发的跨平台GUI框架。《AWTK使用经验》系列文章将介绍开发AWTK过程中一些常见问题与解决方案,例如:如何加载外部资源?如何设计自定义进度条?这些都会在系列文章进行解答。

 

假设目前想在 ZTP800示教器 的AWTK程序中实现播放视频或者播放摄像头画面的效果,可以借助AWTK的mutable_image控件或usb_camera控件来显示画面。下图则是ZTP800示教器使用usb_camera控件Demo显示摄像头画面的效果图:
视频图 1 ZTP800示教器显示摄像头画面效果图 

usb_camera控件和mutable_image控件的对比

关于文章开头提到的两个控件对比如下:

1. mutable_image控件

mutable_image控件可以显示视频画面,也可以显示摄像头等外接设备画面。适用性比较广泛,但使用起来相对繁琐一些。它本身是不负责解析视频或摄像头设备画面数据的,用户可以通过第三方库解析并获取画面原始RGB数据,将数据拷贝到mutable_image控件特定回调函数里面即可显示画面。

2. usb_camera控件

usb_camera控件本质上是对mutable_image控件的封装,专门用于显示摄像头画面。在控件内部实现了获取并解析摄像头画面数据的代码,用户只需调用特定的API即可显示摄像头画面,而不用手动拷贝原始RGB数据。与mutable_image相比没那么广,但是使用起来相对方便。

 

使用usb_camera控件显示摄像头画面

使用usb_camera控件显示摄像头画面的流程比较简单:在AWStudio插件列表可以安装该插件,之后在自己的AWTK应用放置一个usb_camera控件和一个按钮控件,设置usb_camera控件的摄像头设备、大小等属性,并且给该按钮注册点击事件用于打开摄像头。视频图 2 使用usb_camera控件页面布局示例

 按钮点击事件回调函数可以参考以下代码示例:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

static ret_t on_button_click(void* ctx, event_t* e) {  ret_t ret = RET_OK;  widget_t* win = WIDGET(ctx);  widget_t* camera = widget_lookup(win, "usb_camera", TRUE);
 if(usb_camera_is_open(camera) && usb_camera_is_play(camera)) {    usb_camera_stop(camera);    usb_camera_close(camera);  } else {    ret = usb_camera_open(camera);    if (ret != RET_OK) {      dialog_toast("open camera fail", 3000);      return ret;    }    return usb_camera_play(camera);  }  return RET_OK;}


 

使用mutable_image控件显示视频或摄像头画面

mutable_image控件主要提供了 mutable_image_set_prepare_image 函数注册一个回调函数,该回调函数在每次绘制之前被调用,用于准备下一帧要显示的图片。
由于mutable_image控件本身不带有获取视频或摄像头画面的功能,因此获取画面数据的操作可以借助第三方库(如:OpenCV)来实现。mutable_image为了以最高性能绘制,会采取和当前LCD相同的位图数据格式(调用 lcd_get_desired_bitmap_format 获取)因此为了兼容不同LCD格式,可以在回调函数中写好不同格式的拷贝像素逻辑。

下面则是利用OpenCV接口获取摄像头数据并显示到mutable_image控件的部分代码示例:

 

static cv::Mat cv_image;static cv::VideoCapture cv_capture;
/* mutable_image_set_prepare_image回调函数 */ret_t mutable_image_prepare_image(void* ctx, bitmap_t* image) { uint8_t* image_buff = NULL; uint32_t bpp = bitmap_get_bpp(image); widget_t* widget = WIDGET(ctx); bitmap_format_t format = (bitmap_format_t)image->format; cv_capture >> cv_image; image_buff = bitmap_lock_buffer_for_write(image); for (int h = 0; h < image->h; ++h) { uint8_t* p_buff = image_buff + image->w * h * bpp; for (int w = 0; w < image->w; ++w) { /* 调用OpenCV接口获取摄像头当前帧的原始RGB数据 */ cv::Vec3b val = cv_image.at(h, w); if (format == BITMAP_FMT_RGB888 || format == BITMAP_FMT_RGBA8888) { /* RGB888或 RGBA8888示例, 由于该示例上面cv::at数据的格式为BGR,需要进行转换, 具体是否需要转换根据实际格式而决定 */ uint8_t blue = val[0]; uint8_t green = val[1]; uint8_t red = val[2]; p_buff[0] = red; p_buff[1] = green; p_buff[2] = blue; if (format == BITMAP_FMT_RGBA8888) { p_buff[3] = 255; } p_buff += bpp;
} else if (format == BITMAP_FMT_BGR888 || format == BITMAP_FMT_BGRA8888) { ... } else if (format == BITMAP_FMT_BGR565) { } else if (format == BITMAP_FMT_RGB565) { ... } } }
return bitmap_unlock_buffer(image);}
ret_t camera_open(widget_t* win) { widget_t* mutable_image = widget_child(win, "mutable_image");
cv_capture.open(0); mutable_image_set_prepare_image(mutable_image,mutable_image_prepare_image, mutable_image); return RET_OK;}

上面代码通过设置mutable_image控件的回调函数,在回调函数里面使用OpenCV的API获取到摄像头原始RGB数据,最后将数据写到mutable_image控件画面缓冲区上。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分