开源相机管理库Aravis例程学习(三)——注册回调multiple-acquisition-callback

开源相机管理库Aravis例程学习(三)——回调multiple-acquisition-callback

  • 简介
  • 例程代码
  • arv_camera_create_stream
  • ArvStreamCallbackType
  • ArvStreamCallback

简介

本文针对官方例程中的:02-multiple-acquisition-callback做简单的讲解。

aravis版本:0.8.31
操作系统:ubuntu-20.04
gcc版本:9.4.0

例程代码

这段代码使用Aravis的API,控制相机连续采集,并异步地在回调函数中获取10个有效图像,主要操作步骤如下:

  • 连接相机
  • 设置采集模式为连续采集
  • 创建流对象(同时注册回调),并向流对象的buffer池中添加buffer
  • 开始采集
  • 获取10张有效图像后停止采集
  • 释放资源

与连续采集multiple-acquisition-main-thread不同的是,本例中图像获取过程以及停止采集条件的改变都是异步进行的(在回调函数中)。

/* SPDX-License-Identifier:Unlicense *//* Aravis header */
#include <arv.h>
/* Standard headers */
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include "LogManager.h"//用于回调函数中传递和储存流的状态和计数器
typedef struct {ArvStream *stream;int counter;gboolean done;
} ArvStreamCallbackData;//回调函数
//根据不同的回调类型处理视频流事件
static void stream_callback (void *user_data, ArvStreamCallbackType type, ArvBuffer *buffer)
{ArvStreamCallbackData *callback_data = (ArvStreamCallbackData *) user_data;/* 回调函数内尽量不做非必要的耗时操作 */switch (type) {case ARV_STREAM_CALLBACK_TYPE_INIT:PAW_INFO("ARV_STREAM_CALLBACK_TYPE_INIT");break;case ARV_STREAM_CALLBACK_TYPE_START_BUFFER:PAW_INFO("ARV_STREAM_CALLBACK_TYPE_START_BUFFER");break;case ARV_STREAM_CALLBACK_TYPE_BUFFER_DONE:PAW_INFO("ARV_STREAM_CALLBACK_TYPE_BUFFER_DONE");//从buffer池中取出bufferg_assert (buffer == arv_stream_pop_buffer(callback_data->stream));g_assert (buffer != NULL);//检索10个有效bufferif (callback_data->counter < 10) {if (arv_buffer_get_status(buffer) == ARV_BUFFER_STATUS_SUCCESS)PAW_INFO("Acquired"<<arv_buffer_get_image_width(buffer)<<"x"<<arv_buffer_get_image_height(buffer)<< " buffer");arv_stream_push_buffer(callback_data->stream, buffer);callback_data->counter++;} else {callback_data->done = TRUE;}break;case ARV_STREAM_CALLBACK_TYPE_EXIT:PAW_INFO("ARV_STREAM_CALLBACK_TYPE_EXIT");/* Stream thread ended */break;}
}/** Connect to the first available camera, then acquire 10 buffers.*/
int main (int argc, char **argv)
{CLogManager& p_log_instance = CLogManager::GetInstance();ArvCamera *camera;GError *error = NULL;//连接相机camera = arv_camera_new ("192.168.6.63", &error);if (ARV_IS_CAMERA (camera)) {ArvStreamCallbackData callback_data;printf ("Found camera '%s'\n", arv_camera_get_model_name (camera, NULL));//设置相机采集模式为连续采集arv_camera_set_acquisition_mode (camera, ARV_ACQUISITION_MODE_CONTINUOUS, &error);//初始化回调数据callback_data.counter = 0;callback_data.done = FALSE;callback_data.stream = NULL;if (error == NULL) {//创建流对象,注册回调PAW_INFO("create stream");callback_data.stream = arv_camera_create_stream (camera, stream_callback, &callback_data, &error);PAW_INFO("create stream end");}if (ARV_IS_STREAM (callback_data.stream)) {int i;size_t payload;/* Retrieve the payload size for buffer creation *///从相机对象中获取图像负载大小(每个图像的字节大小)payload = arv_camera_get_payload (camera, &error);PAW_INFO("payload:" << payload);if (error == NULL) {/* Insert some buffers in the stream buffer pool *///双缓冲for (i = 0; i < 2; i++)arv_stream_push_buffer (callback_data.stream, arv_buffer_new (payload, NULL));}if (error == NULL)/* Start the acquisition */arv_camera_start_acquisition (camera, &error);if (error == NULL) {while (!callback_data.done) {usleep (1000);}}if (error == NULL)/* Stop the acquisition */arv_camera_stop_acquisition (camera, &error);/* Destroy the stream object */g_clear_object (&callback_data.stream);}/* Destroy the camera instance */PAW_INFO("destroy stream");g_clear_object (&camera);PAW_INFO("destroy stream end");}if (error != NULL) {/* En error happened, display the correspdonding message */printf ("Error: %s\n", error->message);return EXIT_FAILURE;}return EXIT_SUCCESS;
}

注:PAW_INFO是我自定义的用于打印日志的宏

运行结果:
在这里插入图片描述

其中<>之间的是线程号。

arv_camera_create_stream

在连续采集multiple-acquisition-main-thread中我们简单介绍了arv_camera_create_stream函数,在那个例子中callbackuser_data都被设置为NULL,表示不注册回调。而在本例中callback注册了一个我们自定义的函数stream_callback。至于stream_callback中为什么为switch结构我们在后面的讨论中会给出回答。

static void stream_callback (void *user_data, ArvStreamCallbackType type, ArvBuffer *buffer)
{ArvStreamCallbackData *callback_data = (ArvStreamCallbackData *) user_data;switch (type) {case ARV_STREAM_CALLBACK_TYPE_INIT:...break;case ARV_STREAM_CALLBACK_TYPE_START_BUFFER:...break;case ARV_STREAM_CALLBACK_TYPE_BUFFER_DONE:...break;case ARV_STREAM_CALLBACK_TYPE_EXIT:...break;}
}

ArvStreamCallbackType

简介:一个枚举类,描述了流回调函数被调用的时间点。

typedef enum {ARV_STREAM_CALLBACK_TYPE_INIT,ARV_STREAM_CALLBACK_TYPE_EXIT,ARV_STREAM_CALLBACK_TYPE_START_BUFFER,ARV_STREAM_CALLBACK_TYPE_BUFFER_DONE
} ArvStreamCallbackType;

ArvStreamCallback

简介:ArvStreamCallback是一个函数指针类型,用于在实例化流对象时注册回调函数。

typedef void(* ArvStreamCallback) (void* user_data,ArvStreamCallbackType type,ArvBuffer* buffer
)

它在四种情况下会被调用:
①流接收线程的初始化时(只会被调用一次,对应type为ARV_STREAM_CALLBACK_TYPE_INIT
②流接收线程的终止时(只会被调用一次,对应type为ARV_STREAM_CALLBACK_TYPE_EXIT
③每一个buffer从缓冲队列被开始取出时(对应type为ARV_STREAM_CALLBACK_TYPE_START_BUFFER
④每一个buffer从缓冲队列中取出完毕时(无论成功与否,对应type为ARV_STREAM_CALLBACK_TYPE_BUFFER_DONE

现在回答关于stream_callback中的switch结构的问题:

在调用arv_camera_create_stream 注册回调完成后,会立即开启一个流接收线程,用于数据接收。

arv_camera_create_stream (camera, stream_callback, &callback_data, &error);

在这个流线程初始化时,会调用stream_callback并向type传入ARV_STREAM_CALLBACK_TYPE_INIT。然后是在开启采集之后,会对每一帧满足上述情况③和情况④的图像,再调用stream_callback,并分别向type传入ARV_STREAM_CALLBACK_TYPE_START_BUFFERARV_STREAM_CALLBACK_TYPE_BUFFER_DONE。最后在线程退出时最后调用一次stream_callback,并向type传入ARV_STREAM_CALLBACK_TYPE_EXIT

回调函数中使用switch结构是为了根据不同的type参数值执行不同的操作,以实现在流线程的不同时间点完成用户自定义的相关操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/818932.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言 | Leetcode C语言题解之第30题串联所有单词的子串

题目&#xff1a; 题解&#xff1a; typedef struct {char key[32];int val;UT_hash_handle hh; } HashItem;int* findSubstring(char * s, char ** words, int wordsSize, int* returnSize){ int m wordsSize, n strlen(words[0]), ls strlen(s);int *res (int *)mall…

【opencv】示例-videocapture_starter.cpp 从视频文件、图像序列或连接到计算机的摄像头中捕获帧...

/** * file videocapture_starter.cpp * brief 一个使用OpenCV的VideoCapture与捕获设备&#xff0c;视频文件或图像序列的入门示例 * 就像CV_PI一样简单&#xff0c;对吧&#xff1f; * * 创建于: 2010年11月23日 * 作者: Ethan Rublee * * 修改于: 2013年4月17日 * …

金蝶云星空与领星ERP对接集成分布式调入单查询打通添加/编辑本地产品

金蝶云星空与领星ERP对接集成分布式调入单查询打通添加/编辑本地产品 接通系统&#xff1a;金蝶云星空 金蝶K/3Cloud结合当今先进管理理论和数十万家国内客户最佳应用实践&#xff0c;面向事业部制、多地点、多工厂等运营协同与管控型企业及集团公司&#xff0c;提供一个通用的…

Unity 扩展自定义编辑器窗口

在Assets文件夹路径下任意位置创建Editor文件夹&#xff0c;将扩展编辑器的代码放在Editor文件夹下 生成编辑器窗口 代码中首先引用命名空间 using UnityEditor; 然后将创建的类继承自EditorWindow public class MenuEditor : EditorWindow 然后通过扩展编辑器菜单功能调用…

51-40 Align your Latents,基于LDM的高分辨率视频生成

由于数据工程、仿真测试工程&#xff0c;咱们不得不进入AIGC图片视频生成领域。兜兜转转&#xff0c;这一篇与智驾场景特别密切。23年4月&#xff0c;英伟达Nvidia联合几所大学发布了带文本条件融合、时空注意力的Video Latent Diffusion Models。提出一种基于LDM的高分辨率视…

MySQL8.0.36-社区版:通用语法(2)

语法格式规范 sql语句可以以单号或者多行为书写&#xff0c;以分号结尾 可以使用空格或者缩进来增加可读性 mysql的sql语句不区分大小写&#xff0c;但是推荐大写关键字 注释分为单号注释和多行 单号注释&#xff1a;--内容 或者 # 内容 多行注释/* 注释内容 */ sql语句的…

面试算法-175-将有序数组转换为二叉搜索树

题目 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,-3,null,9] 也将被视…

数据结构 -- 数组

本篇文章主要是对数组的实操&#xff0c;所以对数组的概念不在赘述&#xff0c;了解更多数组相关可参照链接 Java数组的概念及使用-CSDN博客 1、DynamicArray类 package com.hh.algorithm.array;import java.util.Arrays; import java.util.Iterator; import java.util.functi…

记录--病理切片图像处理

简介 数字病理切片&#xff0c;也称为全幻灯片成像&#xff08;Whole Slide Imaging&#xff0c;WSI&#xff09;或数字切片扫描&#xff0c;是将传统的玻片病理切片通过高分辨率扫描仪转换为数字图像的技术。这种技术对病理学领域具有革命性的意义&#xff0c;因为它允许病理…

每日OJ题_BFS解决最短路③_力扣127. 单词接龙

目录 ③力扣127. 单词接龙 解析代码 ③力扣127. 单词接龙 127. 单词接龙 难度 困难 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk&#xff1a; 每一对相邻的单词只差一个字母。…

互联网元搜索引擎SearXNG

最近有个很火的项目叫 FreeAskInternet&#xff0c;其工作原理是&#xff1a; 第一步、用户提出问题第二步、用 SearXNG&#xff08;本地运行&#xff09;在多个搜索引擎上进行搜索第三步、将搜索结果传入 LLM 生成答案 所有进程都在本地运行&#xff0c;适用于需要快速获取信…

Python数据分析与应用 |第4章 使用pandas进行数据预处理 (实训)

表1-1healthcare-dataset-stroke.xlsx 部分中风患者的基础信息和体检数据 编号性别高血压是否结婚工作类型居住类型体重指数吸烟史中风9046男否是私人城市36.6以前吸烟是51676女否是私营企业农村N/A从不吸烟是31112男否是私人农村32.5从不吸烟是60182女否是私人城市34.4抽烟是…

【LAMMPS学习】八、基础知识(3.2)使用chunks计算系统属性

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

蓝桥杯 — —灵能传输

灵能传输 友情链接&#xff1a;灵能传输 题目&#xff1a; 输入样例&#xff1a; 3 3 5 -2 3 4 0 0 0 0 3 1 2 3输出样例&#xff1a; 3 0 3思路&#xff1a; 题目大意&#xff1a;给出一个数组&#xff0c;每次选择数组中的一个数&#xff08;要求不能是第一个数与最后一个…

大数据几种任务调度工具

文章目录 一、DolphinScheduler概述和部署1、DolphinScheduler简介1.1 概述1.2 核心架构 2、DolphinScheduler部署模式2.1 概述2.2 单机模式2.3 伪集群模式2.4 集群模式 3、DolphinScheduler集群模式部署3.1 集群规划与准备3.2 下载与配置部署脚本3.3 初始化数据库3.4 一键部署…

maven引入外部jar包

将jar包放入文件夹lib包中 pom文件 <dependency><groupId>com.jyx</groupId><artifactId>Spring-xxl</artifactId><version>1.0-SNAPSHOT</version><scope>system</scope><systemPath>${project.basedir}/lib/Spr…

电商技术揭秘二十四:无人仓储与自动化技术

相关系列文章 电商技术揭秘一&#xff1a;电商架构设计与核心技术 电商技术揭秘二&#xff1a;电商平台推荐系统的实现与优化 电商技术揭秘三&#xff1a;电商平台的支付与结算系统 电商技术揭秘四&#xff1a;电商平台的物流管理系统 电商技术揭秘五&#xff1a;电商平台…

华媒舍:7种方式,打造出旅游媒体套餐

现如今&#xff0c;伴随着旅游业发展与繁荣&#xff0c;更多旅游业发展从业人员越来越重视产品营销品牌基本建设&#xff0c;希望可以将自己的度假旅游产品和服务营销推广给更多的潜在用户。而建立一个优秀的旅游业发展媒体套餐内容品牌是吸引目标客户的重要步骤。下面我们就详…

Golang | Leetcode Golang题解之第30题串联所有单词的子串

题目&#xff1a; 题解&#xff1a; func findSubstring(s string, words []string) (ans []int) {ls, m, n : len(s), len(words), len(words[0])for i : 0; i < n && im*n < ls; i {differ : map[string]int{}for j : 0; j < m; j {differ[s[ij*n:i(j1)*n]…

把握零碎时间,开启长期副业兼职之旅!在家也能轻松赚钱!

转眼间&#xff0c;2024年已悄然走过三分之一。这一年&#xff0c;外界环境似乎并不那么友好&#xff0c;但对我而言&#xff0c;我的月收入仍然相对稳定。我找到的副业让我每月能赚到3000元以上&#xff0c;这让我深感庆幸。 现实中&#xff0c;只依赖主业工资的日子确实艰辛…