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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* media_device_link_test.cpp - Tests link handling on VIMC media device
*/
#include <iostream>
#include <memory>
#include "device_enumerator.h"
#include "media_device.h"
#include "test.h"
using namespace libcamera;
using namespace std;
/*
* This link test requires a vimc device in order to exercise the
* MediaObject link handling API on a graph with a predetermined topology.
*
* vimc is a Media Controller kernel driver that creates virtual devices.
* From a userspace point of view they appear as normal media controller
* devices, but are not backed by any particular piece of hardware. They can
* thus be used for testing purpose without depending on a particular hardware
* platform.
*
* If no vimc device is found (most likely because the vimc driver is not
* loaded) the test is skipped.
*/
class MediaDeviceLinkTest : public Test
{
int init()
{
enumerator = unique_ptr<DeviceEnumerator>(DeviceEnumerator::create());
if (!enumerator) {
cerr << "Failed to create device enumerator" << endl;
return TestFail;
}
if (enumerator->enumerate()) {
cerr << "Failed to enumerate media devices" << endl;
return TestFail;
}
DeviceMatch dm("vimc");
dev_ = enumerator->search(dm);
if (!dev_) {
cerr << "No VIMC media device found: skip test" << endl;
return TestSkip;
}
if (!dev_->acquire()) {
cerr << "Unable to acquire media device "
<< dev_->deviceNode() << endl;
return TestSkip;
}
return 0;
}
int run()
{
/*
* First of all disable all links in the media graph to
* ensure we start from a known state.
*/
if (dev_->disableLinks()) {
cerr << "Failed to disable all links in the media graph";
return TestFail;
}
/*
* Test if link can be consistently retrieved through the
* different methods the media device offers.
*/
string linkName("'Debayer A':[1] -> 'Scaler':[0]'");
MediaLink *link = dev_->link("Debayer A", 1, "Scaler", 0);
if (!link) {
cerr << "Unable to find link: " << linkName
<< " using lookup by name" << endl;
return TestFail;
}
MediaEntity *source = dev_->getEntityByName("Debayer A");
if (!source) {
cerr << "Unable to find entity: 'Debayer A'" << endl;
return TestFail;
}
MediaEntity *sink = dev_->getEntityByName("Scaler");
if (!sink) {
cerr << "Unable to find entity: 'Scaler'" << endl;
return TestFail;
}
MediaLink *link2 = dev_->link(source, 1, sink, 0);
if (!link2) {
cerr << "Unable to find link: " << linkName
<< " using lookup by entity" << endl;
return TestFail;
}
if (link != link2) {
cerr << "Link lookup by name and by entity don't match"
<< endl;
return TestFail;
}
link2 = dev_->link(source->getPadByIndex(1),
sink->getPadByIndex(0));
if (!link2) {
cerr << "Unable to find link: " << linkName
<< " using lookup by pad" << endl;
return TestFail;
}
if (link != link2) {
cerr << "Link lookup by name and by pad don't match"
<< endl;
return TestFail;
}
/* After reset the link shall not be enabled. */
if (link->flags() & MEDIA_LNK_FL_ENABLED) {
cerr << "Link " << linkName
<< " should not be enabled after a device reset"
<< endl;
return TestFail;
}
/* Enable the link and test if enabling was successful. */
if (link->setEnabled(true)) {
cerr << "Failed to enable link: " << linkName
<< endl;
return TestFail;
}
if (!(link->flags() & MEDIA_LNK_FL_ENABLED)) {
cerr << "Link " << linkName
<< " was enabled but it is reported as disabled"
<< endl;
return TestFail;
}
/* Disable the link and test if disabling was successful. */
if (link->setEnabled(false)) {
cerr << "Failed to disable link: " << linkName
<< endl;
return TestFail;
}
if (link->flags() & MEDIA_LNK_FL_ENABLED) {
cerr << "Link " << linkName
<< " was disabled but it is reported as enabled"
<< endl;
return TestFail;
}
/* Try to get a non existing link. */
linkName = "'Sensor A':[1] -> 'Scaler':[0]";
link = dev_->link("Sensor A", 1, "Scaler", 0);
if (link) {
cerr << "Link lookup for " << linkName
<< " succeeded but link does not exist"
<< endl;
return TestFail;
}
/* Now get an immutable link and try to disable it. */
linkName = "'Sensor A':[0] -> 'Raw Capture 0':[0]";
link = dev_->link("Sensor A", 0, "Raw Capture 0", 0);
if (!link) {
cerr << "Unable to find link: " << linkName
<< " using lookup by name" << endl;
return TestFail;
}
if (!(link->flags() & MEDIA_LNK_FL_IMMUTABLE)) {
cerr << "Link " << linkName
<< " should be 'IMMUTABLE'" << endl;
return TestFail;
}
/* Disabling an immutable link shall fail. */
if (!link->setEnabled(false)) {
cerr << "Disabling immutable link " << linkName
<< " succeeded but should have failed" << endl;
return TestFail;
}
/*
* Enable an disabled link, and verify it is disabled again
* after disabling all links in the media graph.
*/
linkName = "'Debayer B':[1] -> 'Scaler':[0]'";
link = dev_->link("Debayer B", 1, "Scaler", 0);
if (!link) {
cerr << "Unable to find link: " << linkName
<< " using lookup by name" << endl;
return TestFail;
}
if (link->setEnabled(true)) {
cerr << "Failed to enable link: " << linkName
<< endl;
return TestFail;
}
if (!(link->flags() & MEDIA_LNK_FL_ENABLED)) {
cerr << "Link " << linkName
<< " was enabled but it is reported as disabled"
<< endl;
return TestFail;
}
if (dev_->disableLinks()) {
cerr << "Failed to disable all links in the media graph";
return TestFail;
}
if (link->flags() & MEDIA_LNK_FL_ENABLED) {
cerr << "All links in the media graph have been disabled"
<< " but link " << linkName
<< " is still reported as enabled" << endl;
return TestFail;
}
return 0;
}
void cleanup()
{
dev_->release();
}
private:
unique_ptr<DeviceEnumerator> enumerator;
shared_ptr<MediaDevice> dev_;
};
TEST_REGISTER(MediaDeviceLinkTest);
|