An attempt at getting image data back

This commit is contained in:
2024-07-14 00:27:33 +02:00
parent e026bc93f7
commit 6452d2e774
1314 changed files with 218350 additions and 38 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View 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;
}

View 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_;
};

View 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