7a47f2bd49
Pass fullPlanarIsOptional through session configure so optional planar mode can succeed with packed YUYV; extend unit and configure HIL coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
146 lines
4.1 KiB
C++
146 lines
4.1 KiB
C++
#include <boostAsioLinkageFix.h>
|
|
|
|
#include <cameraModeRequest.h>
|
|
#include <planarYuvFormatPolicy.h>
|
|
#include <sessionModeConfigure.h>
|
|
#include <libcamera/camera.h>
|
|
#include <libcamera/stream.h>
|
|
#include <stdexcept>
|
|
#include <utility>
|
|
|
|
namespace lcamera_dev {
|
|
|
|
namespace {
|
|
|
|
LcameraDevConfiguredCameraMode buildConfiguredModeFromStreamConfig(
|
|
const LcameraDevCameraModeRequest& request,
|
|
const libcamera::StreamConfiguration& streamConfig)
|
|
{
|
|
LcameraDevConfiguredCameraMode configuredMode;
|
|
configuredMode.width = streamConfig.size.width;
|
|
configuredMode.height = streamConfig.size.height;
|
|
configuredMode.colourSpace = request.colourSpace;
|
|
configuredMode.pixelFormatName = streamConfig.pixelFormat.toString();
|
|
configuredMode.isFullyPlanar =
|
|
isFullyPlanarYuv(streamConfig.pixelFormat);
|
|
configuredMode.planeCount =
|
|
yuvCapturePlaneCount(streamConfig.pixelFormat);
|
|
return configuredMode;
|
|
}
|
|
|
|
std::unique_ptr<libcamera::CameraConfiguration> generateCaptureConfiguration(
|
|
const std::shared_ptr<libcamera::Camera>& camera)
|
|
{
|
|
std::unique_ptr<libcamera::CameraConfiguration> config =
|
|
camera->generateConfiguration(
|
|
{libcamera::StreamRole::VideoRecording});
|
|
|
|
if (!config || config->empty())
|
|
{
|
|
config = camera->generateConfiguration(
|
|
{libcamera::StreamRole::Viewfinder});
|
|
}
|
|
|
|
if (!config || config->empty())
|
|
{
|
|
throw std::runtime_error(
|
|
"lcameraDev: camera does not support VideoRecording or "
|
|
"Viewfinder stream roles");
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
void validateConfigurationStatus(
|
|
libcamera::CameraConfiguration::Status status,
|
|
const std::string& cameraId)
|
|
{
|
|
if (status == libcamera::CameraConfiguration::Valid
|
|
|| status == libcamera::CameraConfiguration::Adjusted)
|
|
{
|
|
return;
|
|
}
|
|
|
|
throw std::runtime_error(
|
|
"lcameraDev: libcamera configuration invalid for camera "
|
|
+ cameraId);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
ConfigureSessionModeStatus applyModeRequestToSessionState(
|
|
CameraSessionResources& resources,
|
|
const LcameraDevCameraModeRequest& request,
|
|
const LcameraDevConfiguredCameraMode& resolvedMode,
|
|
std::shared_ptr<libcamera::CameraConfiguration> heldConfiguration)
|
|
{
|
|
if (resources.configuredMode.has_value())
|
|
{
|
|
if (cameraModeRequestsEqual(resources.configuredRequest, request)) {
|
|
return ConfigureSessionModeStatus::NoOpAlreadyConfigured;
|
|
}
|
|
|
|
throw std::runtime_error(
|
|
"lcameraDev: conflicting camera mode request on configured "
|
|
"session");
|
|
}
|
|
|
|
resources.configuredRequest = request;
|
|
resources.configuredMode = resolvedMode;
|
|
resources.heldConfiguration = heldConfiguration;
|
|
++resources.libcameraConfigureCallCount;
|
|
return ConfigureSessionModeStatus::Configured;
|
|
}
|
|
|
|
LcameraDevConfiguredCameraMode configureLibcameraSessionMode(
|
|
const std::shared_ptr<libcamera::Camera>& camera,
|
|
const LcameraDevCameraModeRequest& request,
|
|
std::shared_ptr<libcamera::CameraConfiguration>& heldConfiguration)
|
|
{
|
|
if (!camera)
|
|
{
|
|
throw std::runtime_error(
|
|
"lcameraDev: configureSessionModeCReq camera is null");
|
|
}
|
|
|
|
std::unique_ptr<libcamera::CameraConfiguration> config =
|
|
generateCaptureConfiguration(camera);
|
|
|
|
libcamera::StreamConfiguration& streamConfig = config->at(0);
|
|
streamConfig.size = libcamera::Size(request.width, request.height);
|
|
|
|
const std::vector<libcamera::PixelFormat> pixelFormatCandidates =
|
|
streamConfig.formats().pixelformats();
|
|
const std::optional<libcamera::PixelFormat> selectedPixelFormat =
|
|
selectYuvCaptureFormat(
|
|
pixelFormatCandidates,
|
|
request.fullPlanarIsOptional);
|
|
|
|
if (!selectedPixelFormat.has_value())
|
|
{
|
|
throw std::runtime_error(
|
|
"lcameraDev: failed to select YUV capture format");
|
|
}
|
|
|
|
streamConfig.pixelFormat = *selectedPixelFormat;
|
|
|
|
const libcamera::CameraConfiguration::Status validateStatus =
|
|
config->validate();
|
|
validateConfigurationStatus(validateStatus, camera->id());
|
|
|
|
const int configureRc = camera->configure(config.get());
|
|
if (configureRc != 0)
|
|
{
|
|
throw std::runtime_error(
|
|
"lcameraDev: libcamera configure failed for camera "
|
|
+ camera->id());
|
|
}
|
|
|
|
const LcameraDevConfiguredCameraMode configuredMode =
|
|
buildConfiguredModeFromStreamConfig(request, streamConfig);
|
|
heldConfiguration = std::move(config);
|
|
return configuredMode;
|
|
}
|
|
|
|
} // namespace lcamera_dev
|