开源相机管理库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,一经查实,立即删除!

相关文章

ActiveMQ 04 Linux下安装

Active MQ 04 Linux下安装 下载 解压 在init.d下建立软连接 ln -s /usr/local/activemq/bin/activemq ./设置开启启动 chkconfig activemq on 服务管理 service activemq start service activemq status service activemq stopNIO配置 默认配置为tcp&#xff0c;使用的…

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…

深入理解ClickHouse 的高性能与高可用原理

架构 ClickHouse 的架构设计旨在提供高性能、高吞吐量的数据存储和查询能力&#xff0c;特别适合处理大规模数据集和实时分析场景。ClickHouse 的架构可以分为几个关键组成部分&#xff0c;它们共同工作以提供高效的数据处理能力和高可用性。 主要组件 1. 存储引擎 ClickHo…

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

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

【ES6】使用记录

Symbol const sym Symbol(Mo_qyue); console.log(sym.description) //Mo_qyue作为属性名Symbol let mySymbol Symbol() let a {} a[mySymbol] hello; console.log(a[mySymbol]) //hellolet b{[mySymbol]:hello} console.log(b[mySymbol]) //hellolet cObject.defineProp…

金蝶云星空与领星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的高分辨率视…

ActiveMQ 06 Request/Response模型实现

Active MQ 06 Request/Response模型实现 QueueRequestor 同步阻塞 TemporaryQueue 异步监听&#xff0c;当消息过多时会创建响应的临时queue JMSCorrelationID 消息属性 异步监听&#xff0c;公用queue 调优总结 Topic加强 可追溯消息 http://activemq.apache.org/re…

自然语言处理(Natural Language Processing, NLP)简介

自然语言处理 (NLP) 是计算机科学的一个分支&#xff0c;更具体地说&#xff0c;是人工智能 (AI) 的分支&#xff0c;旨在让计算机能够以与人类大致相同的方式理解文本和语音。 自然语言处理 (NLP) 将计算语言学&#xff08;基于规则的人类语言建模&#xff09;与统计、机器学…

华为云Stack学习笔记

云服务层-基础设施层-----------------为云服务和华为云stack环境的部署提供基本的硬件支持 1.计算资源&#xff1a;服务器 &#xff08;1&#xff09;国产&#xff1a;兆芯服务器、海光服务器、飞腾服务器、鲲鹏服务器(泰山服务器、黄河服务器、宝德服务器) &#xff08;2&…

JavaWeb--正则表达式

目录 1. 简介 1.1. 语法 1.1.1. 使用RegExp构造函数创建正则表达式 1.1.2. 使用正则表达式字面量语法创建正则表达式 1.1.3. 正则表达式的应用 2. 修饰符 3. 方括号 4. 元字符 5. 量词 6. RegExp对象方法 7. 支持正则的String的方法 8. 正则表达式体验 8.1. 验证 …

【uniapp / vue】中动态添加绑定style 或 class

一、style样式动态设置 1.普通对象动态添加&#xff08;比较常见&#xff09; <template><view><view :style"{color:fontColor}"> </view><view :style"{ paddingTop: num px }"></view><view :style"{bac…

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] 也将被视…

C++11的新特性

C11是由C标准委员会指定的语言规范。相比于C98/03&#xff0c;C11则带来了数量可观的变化&#xff0c;其中包含了约140 个新特性&#xff0c;以及对C03标准中约600个缺陷的修正&#xff0c;C11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全&#xff0c;…

数据结构 -- 数组

本篇文章主要是对数组的实操&#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;因为它允许病理…

【linux】如何写一个launch文件

编写一个ROS&#xff08;Robot Operating System&#xff09;的launch文件是为了方便地启动一组相关的节点&#xff08;nodes&#xff09;、参数服务器&#xff08;parameter server&#xff09;参数、消息发布者/订阅者&#xff08;publishers/subscribers&#xff09;、服务&…

深入浅出 -- 系统架构之Spring、SpringBoot、SpringCloud的区别

首先我们做技术&#xff0c;尤其是java开发人员&#xff0c;应该对Spring、SpringBoot、SpringCloud 三个家伙一点不陌生。 结合发展史Spring出现的最早&#xff0c;后面为了可以让开发人员偷懒&#xff0c;简化配置&#xff0c;就是约定犹于配置或者说大于&#xff0c;进而出…