Loading services/camera/virtualcamera/VirtualCameraDevice.cc +5 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,11 @@ ndk::ScopedAStatus VirtualCameraDevice::isStreamCombinationSupported( bool VirtualCameraDevice::isStreamCombinationSupported( const StreamConfiguration& streamConfiguration) const { if (streamConfiguration.streams.empty()) { ALOGE("%s: Querying empty configuration", __func__); return false; } for (const Stream& stream : streamConfiguration.streams) { ALOGV("%s: Configuration queried: %s", __func__, stream.toString().c_str()); Loading services/camera/virtualcamera/VirtualCameraSession.cc +11 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define LOG_TAG "VirtualCameraSession" #include "VirtualCameraSession.h" #include <algorithm> #include <atomic> #include <chrono> #include <cstddef> Loading Loading @@ -150,6 +151,13 @@ HalStream getHalStream(const Stream& stream) { return halStream; } Stream getHighestResolutionStream(const std::vector<Stream>& streams) { return *(std::max_element(streams.begin(), streams.end(), [](const Stream& a, const Stream& b) { return a.width * a.height < b.width * b.height; })); } } // namespace VirtualCameraSession::VirtualCameraSession( Loading Loading @@ -233,8 +241,9 @@ ndk::ScopedAStatus VirtualCameraSession::configureStreams( } } inputWidth = streams[0].width; inputHeight = streams[0].height; Stream maxResStream = getHighestResolutionStream(streams); inputWidth = maxResStream.width; inputHeight = maxResStream.height; if (mRenderThread == nullptr) { // If there's no client callback, start camera in test mode. const bool testMode = mVirtualCameraClientCallback == nullptr; Loading services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc +50 −26 Original line number Diff line number Diff line Loading @@ -37,10 +37,13 @@ namespace companion { namespace virtualcamera { namespace { constexpr int kWidth = 640; constexpr int kHeight = 480; constexpr int kVgaWidth = 640; constexpr int kVgaHeight = 480; constexpr int kSvgaWidth = 800; constexpr int kSvgaHeight = 600; constexpr int kMaxFps = 30; constexpr int kStreamId = 0; constexpr int kSecondStreamId = 1; constexpr int kCameraId = 42; using ::aidl::android::companion::virtualcamera::BnVirtualCameraCallback; Loading Loading @@ -109,10 +112,16 @@ class VirtualCameraSessionTest : public ::testing::Test { mMockVirtualCameraClientCallback = ndk::SharedRefBase::make<MockVirtualCameraCallback>(); mVirtualCameraDevice = ndk::SharedRefBase::make<VirtualCameraDevice>( kCameraId, VirtualCameraConfiguration{ kCameraId, VirtualCameraConfiguration{ .supportedStreamConfigs = {SupportedStreamConfiguration{ .width = kWidth, .height = kHeight, .width = kVgaWidth, .height = kVgaHeight, .pixelFormat = Format::YUV_420_888, .maxFps = kMaxFps}, SupportedStreamConfiguration{ .width = kSvgaWidth, .height = kSvgaHeight, .pixelFormat = Format::YUV_420_888, .maxFps = kMaxFps}}, .virtualCameraCallback = nullptr, Loading Loading @@ -154,18 +163,22 @@ TEST_F(VirtualCameraSessionTest, ConfigureTriggersClientConfigureCallback) { PixelFormat format = PixelFormat::YCBCR_420_888; StreamConfiguration streamConfiguration; streamConfiguration.streams = { createStream(kStreamId, kWidth, kHeight, format)}; createStream(kStreamId, kVgaWidth, kVgaHeight, format), createStream(kSecondStreamId, kSvgaWidth, kSvgaHeight, format)}; std::vector<HalStream> halStreams; EXPECT_CALL( *mMockVirtualCameraClientCallback, onStreamConfigured(kStreamId, _, kWidth, kHeight, Format::YUV_420_888)); // Expect highest resolution to be picked for the client input. EXPECT_CALL(*mMockVirtualCameraClientCallback, onStreamConfigured(kStreamId, _, kSvgaWidth, kSvgaHeight, Format::YUV_420_888)); ASSERT_TRUE( mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams) .isOk()); EXPECT_THAT(halStreams, SizeIs(streamConfiguration.streams.size())); EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0)); EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(kStreamId, kSecondStreamId)); } TEST_F(VirtualCameraSessionTest, SecondConfigureDropsUnreferencedStreams) { Loading @@ -173,18 +186,18 @@ TEST_F(VirtualCameraSessionTest, SecondConfigureDropsUnreferencedStreams) { StreamConfiguration streamConfiguration; std::vector<HalStream> halStreams; streamConfiguration.streams = {createStream(0, kWidth, kHeight, format), createStream(1, kWidth, kHeight, format), createStream(2, kWidth, kHeight, format)}; streamConfiguration.streams = {createStream(0, kVgaWidth, kVgaHeight, format), createStream(1, kVgaWidth, kVgaHeight, format), createStream(2, kVgaWidth, kVgaHeight, format)}; ASSERT_TRUE( mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams) .isOk()); EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0, 1, 2)); streamConfiguration.streams = {createStream(0, kWidth, kHeight, format), createStream(2, kWidth, kHeight, format), createStream(3, kWidth, kHeight, format)}; streamConfiguration.streams = {createStream(0, kVgaWidth, kVgaHeight, format), createStream(2, kVgaWidth, kVgaHeight, format), createStream(3, kVgaWidth, kVgaHeight, format)}; ASSERT_TRUE( mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams) .isOk()); Loading @@ -209,8 +222,8 @@ TEST_F(VirtualCameraSessionTest, FlushBeforeConfigure) { TEST_F(VirtualCameraSessionTest, onProcessCaptureRequestTriggersClientCallback) { StreamConfiguration streamConfiguration; streamConfiguration.streams = { createStream(kStreamId, kWidth, kHeight, PixelFormat::YCBCR_420_888)}; streamConfiguration.streams = {createStream(kStreamId, kVgaWidth, kVgaHeight, PixelFormat::YCBCR_420_888)}; std::vector<CaptureRequest> requests(1); requests[0].frameNumber = 42; requests[0].settings = *( Loading @@ -234,8 +247,8 @@ TEST_F(VirtualCameraSessionTest, onProcessCaptureRequestTriggersClientCallback) TEST_F(VirtualCameraSessionTest, configureAfterCameraRelease) { StreamConfiguration streamConfiguration; streamConfiguration.streams = { createStream(kStreamId, kWidth, kHeight, PixelFormat::YCBCR_420_888)}; streamConfiguration.streams = {createStream(kStreamId, kVgaWidth, kVgaHeight, PixelFormat::YCBCR_420_888)}; std::vector<HalStream> halStreams; // Release virtual camera. Loading @@ -248,6 +261,17 @@ TEST_F(VirtualCameraSessionTest, configureAfterCameraRelease) { Eq(static_cast<int32_t>(Status::CAMERA_DISCONNECTED))); } TEST_F(VirtualCameraSessionTest, ConfigureWithEmptyStreams) { StreamConfiguration streamConfiguration; std::vector<HalStream> halStreams; // Expect configuration attempt returns CAMERA_DISCONNECTED service specific code. EXPECT_THAT( mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams) .getServiceSpecificError(), Eq(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT))); } } // namespace } // namespace virtualcamera } // namespace companion Loading Loading
services/camera/virtualcamera/VirtualCameraDevice.cc +5 −0 Original line number Diff line number Diff line Loading @@ -283,6 +283,11 @@ ndk::ScopedAStatus VirtualCameraDevice::isStreamCombinationSupported( bool VirtualCameraDevice::isStreamCombinationSupported( const StreamConfiguration& streamConfiguration) const { if (streamConfiguration.streams.empty()) { ALOGE("%s: Querying empty configuration", __func__); return false; } for (const Stream& stream : streamConfiguration.streams) { ALOGV("%s: Configuration queried: %s", __func__, stream.toString().c_str()); Loading
services/camera/virtualcamera/VirtualCameraSession.cc +11 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #define LOG_TAG "VirtualCameraSession" #include "VirtualCameraSession.h" #include <algorithm> #include <atomic> #include <chrono> #include <cstddef> Loading Loading @@ -150,6 +151,13 @@ HalStream getHalStream(const Stream& stream) { return halStream; } Stream getHighestResolutionStream(const std::vector<Stream>& streams) { return *(std::max_element(streams.begin(), streams.end(), [](const Stream& a, const Stream& b) { return a.width * a.height < b.width * b.height; })); } } // namespace VirtualCameraSession::VirtualCameraSession( Loading Loading @@ -233,8 +241,9 @@ ndk::ScopedAStatus VirtualCameraSession::configureStreams( } } inputWidth = streams[0].width; inputHeight = streams[0].height; Stream maxResStream = getHighestResolutionStream(streams); inputWidth = maxResStream.width; inputHeight = maxResStream.height; if (mRenderThread == nullptr) { // If there's no client callback, start camera in test mode. const bool testMode = mVirtualCameraClientCallback == nullptr; Loading
services/camera/virtualcamera/tests/VirtualCameraSessionTest.cc +50 −26 Original line number Diff line number Diff line Loading @@ -37,10 +37,13 @@ namespace companion { namespace virtualcamera { namespace { constexpr int kWidth = 640; constexpr int kHeight = 480; constexpr int kVgaWidth = 640; constexpr int kVgaHeight = 480; constexpr int kSvgaWidth = 800; constexpr int kSvgaHeight = 600; constexpr int kMaxFps = 30; constexpr int kStreamId = 0; constexpr int kSecondStreamId = 1; constexpr int kCameraId = 42; using ::aidl::android::companion::virtualcamera::BnVirtualCameraCallback; Loading Loading @@ -109,10 +112,16 @@ class VirtualCameraSessionTest : public ::testing::Test { mMockVirtualCameraClientCallback = ndk::SharedRefBase::make<MockVirtualCameraCallback>(); mVirtualCameraDevice = ndk::SharedRefBase::make<VirtualCameraDevice>( kCameraId, VirtualCameraConfiguration{ kCameraId, VirtualCameraConfiguration{ .supportedStreamConfigs = {SupportedStreamConfiguration{ .width = kWidth, .height = kHeight, .width = kVgaWidth, .height = kVgaHeight, .pixelFormat = Format::YUV_420_888, .maxFps = kMaxFps}, SupportedStreamConfiguration{ .width = kSvgaWidth, .height = kSvgaHeight, .pixelFormat = Format::YUV_420_888, .maxFps = kMaxFps}}, .virtualCameraCallback = nullptr, Loading Loading @@ -154,18 +163,22 @@ TEST_F(VirtualCameraSessionTest, ConfigureTriggersClientConfigureCallback) { PixelFormat format = PixelFormat::YCBCR_420_888; StreamConfiguration streamConfiguration; streamConfiguration.streams = { createStream(kStreamId, kWidth, kHeight, format)}; createStream(kStreamId, kVgaWidth, kVgaHeight, format), createStream(kSecondStreamId, kSvgaWidth, kSvgaHeight, format)}; std::vector<HalStream> halStreams; EXPECT_CALL( *mMockVirtualCameraClientCallback, onStreamConfigured(kStreamId, _, kWidth, kHeight, Format::YUV_420_888)); // Expect highest resolution to be picked for the client input. EXPECT_CALL(*mMockVirtualCameraClientCallback, onStreamConfigured(kStreamId, _, kSvgaWidth, kSvgaHeight, Format::YUV_420_888)); ASSERT_TRUE( mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams) .isOk()); EXPECT_THAT(halStreams, SizeIs(streamConfiguration.streams.size())); EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0)); EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(kStreamId, kSecondStreamId)); } TEST_F(VirtualCameraSessionTest, SecondConfigureDropsUnreferencedStreams) { Loading @@ -173,18 +186,18 @@ TEST_F(VirtualCameraSessionTest, SecondConfigureDropsUnreferencedStreams) { StreamConfiguration streamConfiguration; std::vector<HalStream> halStreams; streamConfiguration.streams = {createStream(0, kWidth, kHeight, format), createStream(1, kWidth, kHeight, format), createStream(2, kWidth, kHeight, format)}; streamConfiguration.streams = {createStream(0, kVgaWidth, kVgaHeight, format), createStream(1, kVgaWidth, kVgaHeight, format), createStream(2, kVgaWidth, kVgaHeight, format)}; ASSERT_TRUE( mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams) .isOk()); EXPECT_THAT(mVirtualCameraSession->getStreamIds(), ElementsAre(0, 1, 2)); streamConfiguration.streams = {createStream(0, kWidth, kHeight, format), createStream(2, kWidth, kHeight, format), createStream(3, kWidth, kHeight, format)}; streamConfiguration.streams = {createStream(0, kVgaWidth, kVgaHeight, format), createStream(2, kVgaWidth, kVgaHeight, format), createStream(3, kVgaWidth, kVgaHeight, format)}; ASSERT_TRUE( mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams) .isOk()); Loading @@ -209,8 +222,8 @@ TEST_F(VirtualCameraSessionTest, FlushBeforeConfigure) { TEST_F(VirtualCameraSessionTest, onProcessCaptureRequestTriggersClientCallback) { StreamConfiguration streamConfiguration; streamConfiguration.streams = { createStream(kStreamId, kWidth, kHeight, PixelFormat::YCBCR_420_888)}; streamConfiguration.streams = {createStream(kStreamId, kVgaWidth, kVgaHeight, PixelFormat::YCBCR_420_888)}; std::vector<CaptureRequest> requests(1); requests[0].frameNumber = 42; requests[0].settings = *( Loading @@ -234,8 +247,8 @@ TEST_F(VirtualCameraSessionTest, onProcessCaptureRequestTriggersClientCallback) TEST_F(VirtualCameraSessionTest, configureAfterCameraRelease) { StreamConfiguration streamConfiguration; streamConfiguration.streams = { createStream(kStreamId, kWidth, kHeight, PixelFormat::YCBCR_420_888)}; streamConfiguration.streams = {createStream(kStreamId, kVgaWidth, kVgaHeight, PixelFormat::YCBCR_420_888)}; std::vector<HalStream> halStreams; // Release virtual camera. Loading @@ -248,6 +261,17 @@ TEST_F(VirtualCameraSessionTest, configureAfterCameraRelease) { Eq(static_cast<int32_t>(Status::CAMERA_DISCONNECTED))); } TEST_F(VirtualCameraSessionTest, ConfigureWithEmptyStreams) { StreamConfiguration streamConfiguration; std::vector<HalStream> halStreams; // Expect configuration attempt returns CAMERA_DISCONNECTED service specific code. EXPECT_THAT( mVirtualCameraSession->configureStreams(streamConfiguration, &halStreams) .getServiceSpecificError(), Eq(static_cast<int32_t>(Status::ILLEGAL_ARGUMENT))); } } // namespace } // namespace virtualcamera } // namespace companion Loading