/** * FreeRDP: A Remote Desktop Protocol Implementation * Video Capture Virtual Channel Extension * * Copyright 2026 Armin Novak * Copyright 2026 Thincast Technologies GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #if defined(CHANNEL_RDPECAM) #include #include #include WINPR_ATTR_FORMAT_ARG(5, 6) static inline void rdpecam_PrintWarning(wLog* log, const char* file, const char* fkt, size_t line, WINPR_FORMAT_ARG const char* fmt, ...) { const DWORD level = WLOG_WARN; va_list ap = WINPR_C_ARRAY_INIT; va_start(ap, fmt); if (WLog_IsLevelActive(log, level)) WLog_PrintTextMessageVA(log, level, line, file, fkt, fmt, ap); va_end(ap); } /** @brief check input data is a valid \ref CAM_MSG_ID value * * @param id The message id to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_messageId(id) \ rdpecam_valid_messageId_((id), WLog_Get(TAG), __FILE__, __func__, __LINE__) WINPR_ATTR_NODISCARD static inline bool rdpecam_valid_messageId_(UINT8 id, wLog* log, const char* file, const char* fkt, size_t line) { switch (id) { case CAM_MSG_ID_SuccessResponse: case CAM_MSG_ID_ErrorResponse: case CAM_MSG_ID_SelectVersionRequest: case CAM_MSG_ID_SelectVersionResponse: case CAM_MSG_ID_DeviceAddedNotification: case CAM_MSG_ID_DeviceRemovedNotification: case CAM_MSG_ID_ActivateDeviceRequest: case CAM_MSG_ID_DeactivateDeviceRequest: case CAM_MSG_ID_StreamListRequest: case CAM_MSG_ID_StreamListResponse: case CAM_MSG_ID_MediaTypeListRequest: case CAM_MSG_ID_MediaTypeListResponse: case CAM_MSG_ID_CurrentMediaTypeRequest: case CAM_MSG_ID_CurrentMediaTypeResponse: case CAM_MSG_ID_StartStreamsRequest: case CAM_MSG_ID_StopStreamsRequest: case CAM_MSG_ID_SampleRequest: case CAM_MSG_ID_SampleResponse: case CAM_MSG_ID_SampleErrorResponse: case CAM_MSG_ID_PropertyListRequest: case CAM_MSG_ID_PropertyListResponse: case CAM_MSG_ID_PropertyValueRequest: case CAM_MSG_ID_PropertyValueResponse: case CAM_MSG_ID_SetPropertyValueRequest: return true; default: rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_MSG_ID %" PRIu8, id); return false; } } /** @brief check input data is a valid \ref CAM_ERROR_CODE value * * @param code The code to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_CamErrorCode(code) \ rdpecam_valid_CamErrorCode_((code), WLog_Get(TAG), __FILE__, __func__, __LINE__) WINPR_ATTR_NODISCARD static inline bool rdpecam_valid_CamErrorCode_(UINT32 code, wLog* log, const char* file, const char* fkt, size_t line) { switch (code) { case CAM_ERROR_CODE_UnexpectedError: case CAM_ERROR_CODE_InvalidMessage: case CAM_ERROR_CODE_NotInitialized: case CAM_ERROR_CODE_InvalidRequest: case CAM_ERROR_CODE_InvalidStreamNumber: case CAM_ERROR_CODE_InvalidMediaType: case CAM_ERROR_CODE_OutOfMemory: case CAM_ERROR_CODE_ItemNotFound: case CAM_ERROR_CODE_SetNotFound: case CAM_ERROR_CODE_OperationNotSupported: return true; default: rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_ERROR_CODE %" PRIu32, code); return false; } } /** @brief check input data is a valid \ref CAM_STREAM_FRAME_SOURCE_TYPES value * * @param val The value to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_CamStreamFrameSourceType(val) \ rdpecam_valid_CamStreamFrameSourceType_((val), WLog_Get(TAG), __FILE__, __func__, __LINE__) WINPR_ATTR_NODISCARD static inline bool rdpecam_valid_CamStreamFrameSourceType_(UINT16 val, wLog* log, const char* file, const char* fkt, size_t line) { switch (val) { case CAM_STREAM_FRAME_SOURCE_TYPE_Color: case CAM_STREAM_FRAME_SOURCE_TYPE_Infrared: case CAM_STREAM_FRAME_SOURCE_TYPE_Custom: return true; default: rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_STREAM_FRAME_SOURCE_TYPES %" PRIu16, val); return false; } } /** @brief check input data is a valid \ref CAM_STREAM_CATEGORY value * * @param val The value to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_CamStreamCategory(val) \ rdpecam_valid_CamStreamCategory_((val), WLog_Get(TAG), __FILE__, __func__, __LINE__) WINPR_ATTR_NODISCARD static inline bool rdpecam_valid_CamStreamCategory_(UINT8 val, wLog* log, const char* file, const char* fkt, size_t line) { switch (val) { case CAM_STREAM_CATEGORY_Capture: return true; default: rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_STREAM_CATEGORY %" PRIu8, val); return false; } } /** @brief check input data is a valid \ref CAM_MEDIA_FORMAT value * * @param val The value to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_CamMediaFormat(val) \ rdpecam_valid_CamMediaFormat_((val), WLog_Get(TAG), __FILE__, __func__, __LINE__) WINPR_ATTR_NODISCARD static inline bool rdpecam_valid_CamMediaFormat_(UINT8 val, wLog* log, const char* file, const char* fkt, size_t line) { switch (val) { case CAM_MEDIA_FORMAT_INVALID: case CAM_MEDIA_FORMAT_H264: case CAM_MEDIA_FORMAT_MJPG: case CAM_MEDIA_FORMAT_YUY2: case CAM_MEDIA_FORMAT_NV12: case CAM_MEDIA_FORMAT_I420: case CAM_MEDIA_FORMAT_RGB24: case CAM_MEDIA_FORMAT_RGB32: return true; default: rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_MEDIA_FORMAT %" PRIu8, val); return false; } } /** @brief check input data is a valid \ref CAM_MEDIA_TYPE_DESCRIPTION_FLAGS value * * @param val The value to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_MediaTypeDescriptionFlags(val) \ rdpecam_valid_MediaTypeDescriptionFlags_((val), WLog_Get(TAG), __FILE__, __func__, __LINE__) WINPR_ATTR_NODISCARD static inline bool rdpecam_valid_MediaTypeDescriptionFlags_(UINT8 val, wLog* log, const char* file, const char* fkt, size_t line) { switch (val) { case CAM_MEDIA_TYPE_DESCRIPTION_FLAG_DecodingRequired: case CAM_MEDIA_TYPE_DESCRIPTION_FLAG_BottomUpImage: return true; default: rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_MEDIA_TYPE_DESCRIPTION_FLAGS %" PRIu8, val); return false; } } /** @brief check input data is a valid \ref CAM_PROPERTY_MODE value * * @param val The value to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_CamPropertyMode(val) \ rdpecam_valid_CamPropertyMode_((val), WLog_Get(TAG), __FILE__, __func__, __LINE__) static inline bool rdpecam_valid_CamPropertyMode_(UINT8 val, wLog* log, const char* file, const char* fkt, size_t line) { switch (val) { case CAM_PROPERTY_MODE_Manual: case CAM_PROPERTY_MODE_Auto: return true; default: rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_PROPERTY_MODE %" PRIu8, val); return false; } } /** @brief check input data is a valid \ref CAM_PROPERTY_SET value * * @param val The value to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_CamPropertySet(val) \ rdpecam_valid_CamPropertySet_((val), WLog_Get(TAG), __FILE__, __func__, __LINE__) WINPR_ATTR_NODISCARD static inline bool rdpecam_valid_CamPropertySet_(UINT8 val, wLog* log, const char* file, const char* fkt, size_t line) { switch (val) { case CAM_PROPERTY_SET_CameraControl: case CAM_PROPERTY_SET_VideoProcAmp: return true; default: rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_PROPERTY_SET %" PRIu8, val); return false; } } /** @brief check input data is a valid \ref CAM_PROPERTY_CAPABILITIES value * * @param val The value to check * @param log The logger to use * @param file The file name the function is called from * @param fkt The function calling this function * @param line The line number where the function is called * * @return \b true for success, \b false if invalid * @since version 3.20.1 */ #define rdpecam_valid_CamPropertyCapabilities(val) \ rdpecam_valid_CamPropertyCapabilities_((val), WLog_Get(TAG), __FILE__, __func__, __LINE__) WINPR_ATTR_NODISCARD static inline bool rdpecam_valid_CamPropertyCapabilities_(UINT32 val, wLog* log, const char* file, const char* fkt, size_t line) { if ((val & ~((UINT32)CAM_PROPERTY_CAPABILITY_Manual | CAM_PROPERTY_CAPABILITY_Auto)) != 0) { rdpecam_PrintWarning(log, file, fkt, line, "Invalid CAM_PROPERTY_CAPABILITIES %" PRIu8, val); return false; } return true; } #endif