An attempt at getting image data back
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* media_device_acquire.cpp- Test acquire/release of a MediaDevice
|
||||
*/
|
||||
|
||||
#include "media_device_test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
|
||||
class MediaDeviceAcquire : public MediaDeviceTest
|
||||
{
|
||||
int run()
|
||||
{
|
||||
if (!media_->acquire())
|
||||
return TestFail;
|
||||
|
||||
if (media_->acquire())
|
||||
return TestFail;
|
||||
|
||||
media_->release();
|
||||
|
||||
if (!media_->acquire())
|
||||
return TestFail;
|
||||
|
||||
media_->release();
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_REGISTER(MediaDeviceAcquire)
|
||||
@@ -0,0 +1,222 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* Tests link handling on VIMC media device
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "media_device_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 MediaDeviceTest
|
||||
{
|
||||
int init()
|
||||
{
|
||||
int ret = MediaDeviceTest::init();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!media_->acquire()) {
|
||||
cerr << "Unable to acquire media device "
|
||||
<< media_->deviceNode() << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
|
||||
int run()
|
||||
{
|
||||
/*
|
||||
* First of all disable all links in the media graph to
|
||||
* ensure we start from a known state.
|
||||
*/
|
||||
if (media_->disableLinks()) {
|
||||
cerr << "Failed to disable all links in the media graph";
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if link can be consistently retrieved through the
|
||||
* different functions the media device offers.
|
||||
*/
|
||||
string linkName("'Debayer A':[1] -> 'Scaler':[0]'");
|
||||
MediaLink *link = media_->link("Debayer A", 1, "Scaler", 0);
|
||||
if (!link) {
|
||||
cerr << "Unable to find link: " << linkName
|
||||
<< " using lookup by name" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
MediaEntity *source = media_->getEntityByName("Debayer A");
|
||||
if (!source) {
|
||||
cerr << "Unable to find entity: 'Debayer A'" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
MediaEntity *sink = media_->getEntityByName("Scaler");
|
||||
if (!sink) {
|
||||
cerr << "Unable to find entity: 'Scaler'" << endl;
|
||||
return TestFail;
|
||||
}
|
||||
|
||||
MediaLink *link2 = media_->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 = media_->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 = media_->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 = media_->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 = media_->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 (media_->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()
|
||||
{
|
||||
media_->release();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_REGISTER(MediaDeviceLinkTest)
|
||||
@@ -0,0 +1,150 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2018-2019, Google Inc.
|
||||
*
|
||||
* Print out media devices
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libcamera/internal/media_device.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* MediaDevicePrintTest takes all media devices found in the system and print
|
||||
* them out to verify correctness.
|
||||
*
|
||||
* If no accessible media device is found, the test is skipped.
|
||||
*/
|
||||
class MediaDevicePrintTest : public Test
|
||||
{
|
||||
protected:
|
||||
int init() { return 0; }
|
||||
int run();
|
||||
void cleanup() {}
|
||||
|
||||
private:
|
||||
int testMediaDevice(string deviceNode);
|
||||
|
||||
void printMediaGraph(const MediaDevice &media, ostream &os);
|
||||
void printLinkFlags(const MediaLink *link, ostream &os);
|
||||
void printNode(const MediaPad *pad, ostream &os);
|
||||
};
|
||||
|
||||
void MediaDevicePrintTest::printNode(const MediaPad *pad, ostream &os)
|
||||
{
|
||||
const MediaEntity *entity = pad->entity();
|
||||
|
||||
os << "\"" << entity->name() << "\"["
|
||||
<< pad->index() << "]";
|
||||
}
|
||||
|
||||
void MediaDevicePrintTest::printLinkFlags(const MediaLink *link, ostream &os)
|
||||
{
|
||||
unsigned int flags = link->flags();
|
||||
|
||||
os << " [";
|
||||
if (flags) {
|
||||
os << (flags & MEDIA_LNK_FL_ENABLED ? "ENABLED," : "")
|
||||
<< (flags & MEDIA_LNK_FL_IMMUTABLE ? "IMMUTABLE" : "");
|
||||
}
|
||||
os << "]\n";
|
||||
}
|
||||
|
||||
/*
|
||||
* For each entity in the media graph, printout links directed to its sinks
|
||||
* and source pads.
|
||||
*/
|
||||
void MediaDevicePrintTest::printMediaGraph(const MediaDevice &media, ostream &os)
|
||||
{
|
||||
os << "\n" << media.driver() << " - " << media.deviceNode() << "\n\n";
|
||||
|
||||
for (auto const &entity : media.entities()) {
|
||||
os << "\"" << entity->name() << "\"\n";
|
||||
|
||||
for (auto const &sink : entity->pads()) {
|
||||
if (!(sink->flags() & MEDIA_PAD_FL_SINK))
|
||||
continue;
|
||||
|
||||
os << " [" << sink->index() << "]" << ": Sink\n";
|
||||
for (auto const &link : sink->links()) {
|
||||
os << "\t";
|
||||
printNode(sink, os);
|
||||
os << " <- ";
|
||||
printNode(link->source(), os);
|
||||
printLinkFlags(link, os);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
for (auto const &source : entity->pads()) {
|
||||
if (!(source->flags() & MEDIA_PAD_FL_SOURCE))
|
||||
continue;
|
||||
|
||||
os << " [" << source->index() << "]" << ": Source\n";
|
||||
for (auto const &link : source->links()) {
|
||||
os << "\t";
|
||||
printNode(source, os);
|
||||
os << " -> ";
|
||||
printNode(link->sink(), os);
|
||||
printLinkFlags(link, os);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
os.flush();
|
||||
}
|
||||
|
||||
/* Test a single media device. */
|
||||
int MediaDevicePrintTest::testMediaDevice(const string deviceNode)
|
||||
{
|
||||
MediaDevice dev(deviceNode);
|
||||
int ret;
|
||||
|
||||
ret = dev.populate();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Print out the media graph. */
|
||||
printMediaGraph(dev, cerr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Run tests on all media devices. */
|
||||
#define MAX_MEDIA_DEV 256
|
||||
int MediaDevicePrintTest::run()
|
||||
{
|
||||
const string deviceNode("/dev/media");
|
||||
unsigned int i;
|
||||
int ret = 77; /* skip test exit code */
|
||||
|
||||
/*
|
||||
* Run the test sequence on all media device found in the
|
||||
* system, if any.
|
||||
*/
|
||||
for (i = 0; i < MAX_MEDIA_DEV; i++) {
|
||||
string mediadev = deviceNode + to_string(i);
|
||||
struct stat pstat = {};
|
||||
|
||||
if (stat(mediadev.c_str(), &pstat))
|
||||
continue;
|
||||
|
||||
ret = testMediaDevice(mediadev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TEST_REGISTER(MediaDevicePrintTest)
|
||||
36
spider-cam/libcamera/test/media_device/media_device_test.cpp
Normal file
36
spider-cam/libcamera/test/media_device/media_device_test.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* libcamera media device test base class
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "media_device_test.h"
|
||||
|
||||
using namespace libcamera;
|
||||
using namespace std;
|
||||
|
||||
int MediaDeviceTest::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");
|
||||
media_ = enumerator_->search(dm);
|
||||
if (!media_) {
|
||||
cerr << "No VIMC media device found: skip test" << endl;
|
||||
return TestSkip;
|
||||
}
|
||||
|
||||
return TestPass;
|
||||
}
|
||||
30
spider-cam/libcamera/test/media_device/media_device_test.h
Normal file
30
spider-cam/libcamera/test/media_device/media_device_test.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019, Google Inc.
|
||||
*
|
||||
* libcamera media device test base class
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "libcamera/internal/device_enumerator.h"
|
||||
#include "libcamera/internal/media_device.h"
|
||||
|
||||
#include "test.h"
|
||||
|
||||
class MediaDeviceTest : public Test
|
||||
{
|
||||
public:
|
||||
MediaDeviceTest()
|
||||
: media_(nullptr), enumerator_(nullptr) {}
|
||||
|
||||
protected:
|
||||
int init();
|
||||
|
||||
std::shared_ptr<libcamera::MediaDevice> media_;
|
||||
|
||||
private:
|
||||
std::unique_ptr<libcamera::DeviceEnumerator> enumerator_;
|
||||
};
|
||||
24
spider-cam/libcamera/test/media_device/meson.build
Normal file
24
spider-cam/libcamera/test/media_device/meson.build
Normal file
@@ -0,0 +1,24 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
lib_mdev_test_sources = files([
|
||||
'media_device_test.cpp',
|
||||
])
|
||||
|
||||
media_device_tests = [
|
||||
{'name': 'media_device_acquire', 'sources': ['media_device_acquire.cpp']},
|
||||
{'name': 'media_device_print_test', 'sources': ['media_device_print_test.cpp']},
|
||||
{'name': 'media_device_link_test', 'sources': ['media_device_link_test.cpp']},
|
||||
]
|
||||
|
||||
lib_mdev_test = static_library('lib_mdev_test', lib_mdev_test_sources,
|
||||
dependencies : libcamera_private,
|
||||
include_directories : test_includes_internal)
|
||||
|
||||
foreach test : media_device_tests
|
||||
exe = executable(test['name'], test['sources'],
|
||||
dependencies : libcamera_private,
|
||||
link_with : [test_libraries, lib_mdev_test],
|
||||
include_directories : test_includes_internal)
|
||||
|
||||
test(test['name'], exe, suite : 'media_device', is_parallel : false)
|
||||
endforeach
|
||||
Reference in New Issue
Block a user