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

paw5zx Lv4

简介

本文针对官方例程 中的: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 不同的是,本例中图像获取过程以及停止采集条件的改变都是异步进行的(在回调函数中)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* 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池中取出buffer
g_assert (buffer == arv_stream_pop_buffer(callback_data->stream));
g_assert (buffer != NULL);

//检索10个有效buffer
if (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结构我们在后面的讨论中会给出回答。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

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

1
2
3
4
5
6
7
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是一个函数指针类型,用于在实例化流对象时注册回调函数。

1
2
3
4
5
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 注册回调完成后,会立即开启一个流接收线程,用于数据接收。

1
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参数值执行不同的操作,以实现在流线程的不同时间点完成用户自定义的相关操作。

  • 标题: 开源相机管理库Aravis例程学习(三)——注册回调multiple-acquisition-callback
  • 作者: paw5zx
  • 创建于 : 2024-04-15 09:29:23
  • 更新于 : 2024-09-04 17:18:59
  • 链接: https://paw5zx.github.io/aravis-multiple-acquisition-callback/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
开源相机管理库Aravis例程学习(三)——注册回调multiple-acquisition-callback