lcameraDev: honor opt-planar when selecting YUV capture format.
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>
This commit is contained in:
@@ -52,23 +52,19 @@ TEST(CameraModeRequestTest, UnsupportedColourSpaceThrows)
|
||||
std::runtime_error);
|
||||
}
|
||||
|
||||
TEST(CameraModeRequestTest, FullPlanarOptionalRejectedAtConfigureApi)
|
||||
TEST(CameraModeRequestTest, CameraModeRequestsEqualComparesOptionalPlanarFlag)
|
||||
{
|
||||
LcameraDevCameraModeRequest request;
|
||||
request.width = 640;
|
||||
request.height = 480;
|
||||
request.fullPlanarIsOptional = true;
|
||||
LcameraDevCameraModeRequest left;
|
||||
left.width = 640;
|
||||
left.height = 480;
|
||||
left.colourSpace = LcameraDevColourSpace::Yuv;
|
||||
left.fullPlanarIsOptional = false;
|
||||
|
||||
try {
|
||||
rejectFullPlanarOptionalAtConfigureApi(request);
|
||||
FAIL() << "Expected runtime_error";
|
||||
}
|
||||
catch (const std::runtime_error& exception)
|
||||
{
|
||||
sscl::tests::expectExceptionMessageContains(
|
||||
exception,
|
||||
"not honored yet");
|
||||
}
|
||||
LcameraDevCameraModeRequest right = left;
|
||||
EXPECT_TRUE(cameraModeRequestsEqual(left, right));
|
||||
|
||||
right.fullPlanarIsOptional = true;
|
||||
EXPECT_FALSE(cameraModeRequestsEqual(left, right));
|
||||
}
|
||||
|
||||
TEST(CameraModeRequestTest, CameraModeRequestsEqualComparesAllFields)
|
||||
|
||||
@@ -537,5 +537,99 @@ TEST_F(LcameraDevConfigureHilTest, ConflictingReconfigureThrows)
|
||||
}
|
||||
}
|
||||
|
||||
void configureProfileWithOptPlanarExpectingYuyv(
|
||||
const test_fixtures::BakedCameraProfile *profile,
|
||||
const LcameraDevCameraModeRequest& request,
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread)
|
||||
{
|
||||
lcamera_dev::LcameraDevGetOrCreateResult createResult;
|
||||
|
||||
sscl::tests::runNonViralNurseryOnComponentThread(
|
||||
componentThread,
|
||||
[profile, &createResult](
|
||||
sscl::co::NonViralTaskNursery::Slot::Lease& lease)
|
||||
{
|
||||
return getOrCreateCInd(
|
||||
lease.getExceptionStorage(),
|
||||
lease.getCallerLambda(),
|
||||
profile->exampleSelector,
|
||||
createResult);
|
||||
});
|
||||
|
||||
EXPECT_TRUE(createResult.deviceSession != nullptr)
|
||||
<< profile->profileTag;
|
||||
|
||||
LcameraDevConfiguredCameraMode configuredMode;
|
||||
LcameraDevCameraModeRequest optPlanarRequest = request;
|
||||
optPlanarRequest.fullPlanarIsOptional = true;
|
||||
|
||||
runNonViralNurseryRethrowingOnComponentThread(
|
||||
componentThread,
|
||||
[&createResult, &optPlanarRequest, &configuredMode](
|
||||
sscl::co::NonViralTaskNursery::Slot::Lease& lease)
|
||||
{
|
||||
return configureCInd(
|
||||
lease.getExceptionStorage(),
|
||||
lease.getCallerLambda(),
|
||||
createResult.deviceSession,
|
||||
optPlanarRequest,
|
||||
configuredMode);
|
||||
});
|
||||
|
||||
EXPECT_FALSE(configuredMode.isFullyPlanar) << profile->profileTag;
|
||||
EXPECT_EQ(configuredMode.planeCount, 1u) << profile->profileTag;
|
||||
EXPECT_EQ(configuredMode.pixelFormatName, "YUYV") << profile->profileTag;
|
||||
EXPECT_GE(configuredMode.width, 1u) << profile->profileTag;
|
||||
EXPECT_GE(configuredMode.height, 1u) << profile->profileTag;
|
||||
|
||||
sscl::tests::runNonViralNurseryOnComponentThread(
|
||||
componentThread,
|
||||
[&createResult](sscl::co::NonViralTaskNursery::Slot::Lease& lease)
|
||||
{
|
||||
return releaseCInd(
|
||||
lease.getExceptionStorage(),
|
||||
lease.getCallerLambda(),
|
||||
createResult.deviceSession);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(LcameraDevConfigureHilTest, ConfigureUsbHdmiYuvWithOptPlanarSelectsYuyv)
|
||||
{
|
||||
const test_fixtures::BakedCameraProfile *profile =
|
||||
findProfile("usb_hdmi_camera");
|
||||
if (!profile) {
|
||||
GTEST_SKIP() << "usb_hdmi_camera profile not available";
|
||||
}
|
||||
|
||||
runLcameraDevMainAndNurseryTask(
|
||||
[this, profile](
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread)
|
||||
{
|
||||
configureProfileWithOptPlanarExpectingYuyv(
|
||||
profile,
|
||||
configureRequest,
|
||||
componentThread);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_F(LcameraDevConfigureHilTest, ConfigureIntegratedWebcamYuvWithOptPlanarSelectsYuyv)
|
||||
{
|
||||
const test_fixtures::BakedCameraProfile *profile =
|
||||
findProfile("integrated_webcam");
|
||||
if (!profile) {
|
||||
GTEST_SKIP() << "integrated_webcam profile not available";
|
||||
}
|
||||
|
||||
runLcameraDevMainAndNurseryTask(
|
||||
[this, profile](
|
||||
const std::shared_ptr<sscl::ComponentThread>& componentThread)
|
||||
{
|
||||
configureProfileWithOptPlanarExpectingYuyv(
|
||||
profile,
|
||||
configureRequest,
|
||||
componentThread);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace lcamera_dev
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
namespace lcamera_dev {
|
||||
namespace {
|
||||
|
||||
using libcamera::formats::MJPEG;
|
||||
using libcamera::formats::NV12;
|
||||
using libcamera::formats::YUYV;
|
||||
using libcamera::formats::YUV420;
|
||||
@@ -67,5 +68,18 @@ TEST(PlanarYuvFormatPolicyTest, IsFullyPlanarYuvRecognizesYuv420)
|
||||
EXPECT_FALSE(isFullyPlanarYuv(NV12));
|
||||
}
|
||||
|
||||
TEST(PlanarYuvFormatPolicyTest, FullyPlanarOptionalPicksYuyvOverMjpeg)
|
||||
{
|
||||
const std::vector<libcamera::PixelFormat> candidates = {MJPEG, YUYV};
|
||||
|
||||
const std::optional<libcamera::PixelFormat> selected =
|
||||
selectYuvCaptureFormat(candidates, true);
|
||||
|
||||
EXPECT_TRUE(selected.has_value());
|
||||
EXPECT_EQ(*selected, YUYV);
|
||||
EXPECT_FALSE(isFullyPlanarYuv(*selected));
|
||||
EXPECT_EQ(yuvCapturePlaneCount(*selected), 1u);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace lcamera_dev
|
||||
|
||||
Reference in New Issue
Block a user