#include #include #include #include #include #include namespace smo { namespace stim_buff { namespace lcamera_buff { namespace { std::string normalizeFourccToken(std::string token) { for (char& character : token) { character = static_cast( std::toupper(static_cast(character))); } return token; } bool fourccInSet( const std::string& fourcc, const std::unordered_set& candidates) { return candidates.find(fourcc) != candidates.end(); } const std::unordered_set& yuv420FourccSet() { static const std::unordered_set fourccs = { "YU12", "YV12", "YUV420", "YVU420", "NV12", "NV21", }; return fourccs; } const std::unordered_set& yuv422FourccSet() { static const std::unordered_set fourccs = { "YUYV", "YVYU", "UYVY", "VYUY", "YUV422", "YVU422", "NV16", "NV61", "YU16", "YV16", }; return fourccs; } const std::unordered_set& yuv444FourccSet() { static const std::unordered_set fourccs = { "YUV444", "YVU444", }; return fourccs; } unsigned chromaPlaneWidth(unsigned frameWidth, YuvChromaSubsampling subsampling) { switch (subsampling) { case YuvChromaSubsampling::Yuv420: case YuvChromaSubsampling::Yuv422: return (frameWidth + 1u) / 2u; case YuvChromaSubsampling::Yuv444: return frameWidth; } throw std::logic_error( "lcameraBuff: unhandled YuvChromaSubsampling in chromaPlaneWidth"); } unsigned chromaPlaneHeight(unsigned frameHeight, YuvChromaSubsampling subsampling) { switch (subsampling) { case YuvChromaSubsampling::Yuv420: return (frameHeight + 1u) / 2u; case YuvChromaSubsampling::Yuv422: case YuvChromaSubsampling::Yuv444: return frameHeight; } throw std::logic_error( "lcameraBuff: unhandled YuvChromaSubsampling in chromaPlaneHeight"); } } // namespace YuvChromaSubsampling classifyYuvChromaSubsampling( const lcamera_dev::LcameraDevConfiguredCameraMode& configuredMode) { const std::string fourcc = normalizeFourccToken(configuredMode.pixelFormatName); if (fourccInSet(fourcc, yuv420FourccSet())) { return YuvChromaSubsampling::Yuv420; } if (fourccInSet(fourcc, yuv422FourccSet())) { return YuvChromaSubsampling::Yuv422; } if (fourccInSet(fourcc, yuv444FourccSet())) { return YuvChromaSubsampling::Yuv444; } throw std::runtime_error( "lcameraBuff: unsupported YUV pixel format for chroma geometry: " + configuredMode.pixelFormatName); } size_t computeDeinterleavedChannelByteSize( YuvChannelKind channel, unsigned width, unsigned height, YuvChromaSubsampling subsampling) { switch (channel) { case YuvChannelKind::Y: return static_cast(width) * static_cast(height); case YuvChannelKind::U: case YuvChannelKind::V: { const unsigned chromaWidth = chromaPlaneWidth(width, subsampling); const unsigned chromaHeight = chromaPlaneHeight(height, subsampling); return static_cast(chromaWidth) * static_cast(chromaHeight); } } throw std::logic_error( "lcameraBuff: unhandled YuvChannelKind in computeDeinterleavedChannelByteSize"); } } // namespace lcamera_buff } // namespace stim_buff } // namespace smo