20#include <winpr/assert.h>
21#include <winpr/cast.h>
22#include <winpr/interlocked.h>
23#include <winpr/sysinfo.h>
26#include "rdpecam-utils.h"
28#define TAG CHANNELS_TAG("rdpecam-device.client")
44 const CAM_MEDIA_FORMAT available[] = { CAM_MEDIA_FORMAT_H264, CAM_MEDIA_FORMAT_MJPG,
45 CAM_MEDIA_FORMAT_YUY2, CAM_MEDIA_FORMAT_NV12,
46 CAM_MEDIA_FORMAT_I420, CAM_MEDIA_FORMAT_RGB24,
47 CAM_MEDIA_FORMAT_RGB32 };
50 formats[ARRAYSIZE(available) * ARRAYSIZE(available)];
51 static size_t count = 0;
52 static BOOL initialized = FALSE;
56 for (
size_t dst = 0; dst < ARRAYSIZE(available); dst++)
58 const CAM_MEDIA_FORMAT dstFormat = available[dst];
60 for (
size_t src = 0; src < ARRAYSIZE(available); src++)
62 const CAM_MEDIA_FORMAT srcFormat = available[src];
63 if (freerdp_video_conversion_supported(ecamToVideoFormat(srcFormat),
64 ecamToVideoFormat(dstFormat)))
80static CAM_MEDIA_TYPE_DESCRIPTION_FLAGS ecam_media_type_flags(CAM_MEDIA_FORMAT format)
82 if ((format == CAM_MEDIA_FORMAT_H264) || (format == CAM_MEDIA_FORMAT_MJPG))
83 return CAM_MEDIA_TYPE_DESCRIPTION_FLAG_DecodingRequired;
84 return AM_MEDIA_TYPE_DESCRIPTION_FLAG_Invalid;
89 WINPR_ASSERT(mediaType);
91 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, mediaType->Format));
92 Stream_Write_UINT32(s, mediaType->Width);
93 Stream_Write_UINT32(s, mediaType->Height);
94 Stream_Write_UINT32(s, mediaType->FrameRateNumerator);
95 Stream_Write_UINT32(s, mediaType->FrameRateDenominator);
96 Stream_Write_UINT32(s, mediaType->PixelAspectRatioNumerator);
97 Stream_Write_UINT32(s, mediaType->PixelAspectRatioDenominator);
98 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, mediaType->Flags));
103 WINPR_ASSERT(mediaType);
105 const uint8_t format = Stream_Get_UINT8(s);
106 if (!rdpecam_valid_CamMediaFormat(format))
109 mediaType->Format = WINPR_ASSERTING_INT_CAST(CAM_MEDIA_FORMAT, format);
110 mediaType->Width = Stream_Get_UINT32(s);
111 mediaType->Height = Stream_Get_UINT32(s);
112 mediaType->FrameRateNumerator = Stream_Get_UINT32(s);
113 mediaType->FrameRateDenominator = Stream_Get_UINT32(s);
114 mediaType->PixelAspectRatioNumerator = Stream_Get_UINT32(s);
115 mediaType->PixelAspectRatioDenominator = Stream_Get_UINT32(s);
117 if (mediaType->FrameRateNumerator == 0)
119 if (mediaType->FrameRateDenominator == 0)
121 if (mediaType->PixelAspectRatioNumerator == 0)
123 if (mediaType->PixelAspectRatioDenominator == 0)
126 const uint8_t flags = Stream_Get_UINT8(s);
127 if (!rdpecam_valid_MediaTypeDescriptionFlags(flags))
129 mediaType->Flags = WINPR_ASSERTING_INT_CAST(CAM_MEDIA_TYPE_DESCRIPTION_FLAGS, flags);
135 WINPR_ASSERT(mediaType);
137 WLog_DBG(TAG,
"Format: %u, width: %u, height: %u, fps: %u, flags: %u", mediaType->Format,
138 mediaType->Width, mediaType->Height, mediaType->FrameRateNumerator, mediaType->Flags);
152 CAM_MSG_ID msg = CAM_MSG_ID_SampleResponse;
154 Stream_ResetPosition(stream->sampleRespBuffer);
155 if (!Stream_EnsureRemainingCapacity(stream->sampleRespBuffer, 3))
158 Stream_Write_UINT8(stream->sampleRespBuffer,
159 WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
160 Stream_Write_UINT8(stream->sampleRespBuffer, WINPR_ASSERTING_INT_CAST(uint8_t, msg));
161 Stream_Write_UINT8(stream->sampleRespBuffer, WINPR_ASSERTING_INT_CAST(uint8_t, streamIndex));
163 return stream->sampleRespBuffer;
166static BOOL mediaSupportDrops(CAM_MEDIA_FORMAT format)
170 case CAM_MEDIA_FORMAT_H264:
177static UINT ecam_dev_send_sample_error_response(
CameraDevice* dev,
179 size_t streamIndex, CAM_ERROR_CODE errorCode)
183 wStream* s = Stream_New(
nullptr, CAM_HEADER_SIZE + 5);
185 return ERROR_NOT_ENOUGH_MEMORY;
187 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
188 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, CAM_MSG_ID_SampleErrorResponse));
189 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, streamIndex));
190 Stream_Write_UINT32(s, (UINT32)errorCode);
192 return ecam_channel_write(dev->ecam, hchannel, CAM_MSG_ID_SampleErrorResponse, s, TRUE);
198 WINPR_ASSERT(stream);
200 if (stream->samplesRequested <= 0)
202 WLog_VRB(TAG,
"Frame delayed: No sample requested");
203 return CHANNEL_RC_OK;
206 if (!stream->haveSample)
208 WLog_VRB(TAG,
"Frame response delayed: No sample available");
209 return CHANNEL_RC_OK;
212 wStream* output = ecam_dev_prepare_sample_response(dev, streamIndex);
214 return CHANNEL_RC_OK;
216 const BYTE* encodedSample = Stream_Buffer(stream->pendingSample);
217 const size_t encodedSize = Stream_Length(stream->pendingSample);
218 if (!ecam_encoder_compress(stream, encodedSample, encodedSize, output))
220 WLog_DBG(TAG,
"Frame dropped: error in ecam_encoder_compress");
221 stream->haveSample = FALSE;
222 return CHANNEL_RC_OK;
225 if (!stream->streaming)
227 WLog_DBG(TAG,
"Frame delayed/dropped: stream stopped");
228 return CHANNEL_RC_OK;
231 stream->samplesRequested--;
232 stream->haveSample = FALSE;
235 return ecam_channel_write(dev->ecam, stream->hSampleReqChannel, CAM_MSG_ID_SampleResponse,
239static UINT ecam_dev_sample_captured_callback(
CameraDevice* dev,
size_t streamIndex,
240 const BYTE* sample,
size_t size)
244 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
245 return ERROR_INVALID_INDEX;
249 if (!stream->streaming)
251 WLog_DBG(TAG,
"Frame drop: stream not running");
252 return CHANNEL_RC_OK;
255 EnterCriticalSection(&stream->lock);
256 UINT ret = CHANNEL_RC_NO_MEMORY;
257 if (dev->ihal->RequestDrivenCapture && (stream->samplesRequested <= 0))
262 const UINT64 idle = GetTickCount64() - stream->lastSampleRequestTime;
263 if (idle >= ECAM_CAPTURE_IDLE_TIMEOUT_MS)
265 WLog_DBG(TAG,
"No sample requested for %" PRIu64
" ms, releasing capture device", idle);
266 stream->captureRunning = FALSE;
267 ret = ECAM_SAMPLE_CAPTURE_DRAINED;
277 if (stream->haveSample && !mediaSupportDrops(stream->formats.inputFormat))
286 DWORD waitDelay = (1000 * stream->currMediaType.FrameRateDenominator) /
287 stream->currMediaType.FrameRateNumerator;
293 while (stream->haveSample && stream->streaming)
295 LeaveCriticalSection(&stream->lock);
297 SleepEx(waitDelay, TRUE);
299 EnterCriticalSection(&stream->lock);
302 if (!stream->streaming)
304 WLog_DBG(TAG,
"Frame drop: stream not running");
310 Stream_ResetPosition(stream->pendingSample);
311 if (!Stream_EnsureRemainingCapacity(stream->pendingSample, size))
314 Stream_Write(stream->pendingSample, sample, size);
315 Stream_SealLength(stream->pendingSample);
316 stream->haveSample = TRUE;
318 ret = ecam_dev_send_pending(dev, streamIndex, stream);
321 LeaveCriticalSection(&stream->lock);
325static void ecam_dev_stop_stream(
CameraDevice* dev,
size_t streamIndex)
329 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
334 if (stream->streaming)
336 stream->streaming = FALSE;
337 stream->captureRunning = FALSE;
338 dev->ihal->StopStream(dev->ihal, dev->deviceId, 0);
340 DeleteCriticalSection(&stream->lock);
343 Stream_Free(stream->sampleRespBuffer, TRUE);
344 stream->sampleRespBuffer =
nullptr;
346 Stream_Free(stream->pendingSample, TRUE);
347 stream->pendingSample =
nullptr;
349 ecam_encoder_context_free(stream);
357static UINT ecam_dev_process_stop_streams_request(
CameraDevice* dev,
363 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
364 ecam_dev_stop_stream(dev, i);
366 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
370static BOOL media_type_valid(
CameraDevice* dev, UINT8 streamIndex,
377 size_t nMediaTypes = ARRAYSIZE(supported);
379 size_t nSupportedFormats = 0;
382 dev->ihal->GetMediaTypeDescriptions(dev->ihal, dev->deviceId, streamIndex, supportedFormats,
383 nSupportedFormats, supported, &nMediaTypes);
387 for (
size_t x = 0; x < nMediaTypes; x++)
390 cur.Format = supportedFormats[formatIndex].outputFormat;
392 cur.Flags = ecam_media_type_flags(cur.Format);
404static UINT ecam_dev_process_start_streams_request(
CameraDevice* dev,
407 BYTE streamIndex = 0;
412 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1 + 26))
413 return ERROR_INVALID_DATA;
415 Stream_Read_UINT8(s, streamIndex);
417 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
419 WLog_ERR(TAG,
"Incorrect streamIndex %" PRIu8, streamIndex);
420 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
421 return ERROR_INVALID_INDEX;
424 if (!ecam_dev_read_media_type(s, &mediaType))
426 WLog_ERR(TAG,
"Unable to read MEDIA_TYPE_DESCRIPTION");
427 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidMessage);
428 return ERROR_INVALID_DATA;
431 ecam_dev_print_media_type(&mediaType);
432 if (!media_type_valid(dev, streamIndex, &mediaType))
434 WLog_ERR(TAG,
"Unannounced MEDIA_TYPE_DESCRIPTION");
435 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidMessage);
436 return ERROR_INVALID_DATA;
441 if (stream->streaming)
443 WLog_ERR(TAG,
"Streaming already in progress, device %s, streamIndex %u", dev->deviceId,
445 return CAM_ERROR_CODE_UnexpectedError;
451 stream->currMediaType = mediaType;
453 if (!ecam_encoder_context_init(stream))
455 WLog_ERR(TAG,
"stream_ecam_encoder_init failed");
456 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_UnexpectedError);
457 return ERROR_INVALID_DATA;
460 stream->sampleRespBuffer = Stream_New(
nullptr, ECAM_SAMPLE_RESPONSE_BUFFER_SIZE);
461 if (!stream->sampleRespBuffer)
463 WLog_ERR(TAG,
"Stream_New failed");
464 ecam_dev_stop_stream(dev, streamIndex);
465 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
466 return ERROR_INVALID_DATA;
470 mediaType.Format = streamInputFormat(stream);
472 stream->samplesRequested = 0;
473 stream->lastSampleRequestTime = GetTickCount64();
474 stream->haveSample = FALSE;
476 if (!InitializeCriticalSectionEx(&stream->lock, 0, 0))
478 WLog_ERR(TAG,
"InitializeCriticalSectionEx failed");
479 ecam_dev_stop_stream(dev, streamIndex);
480 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
481 return ERROR_INVALID_DATA;
484 stream->pendingSample = Stream_New(
nullptr, 4ull * mediaType.Width * mediaType.Height);
485 if (!stream->pendingSample)
487 WLog_ERR(TAG,
"pending stream failed");
488 ecam_dev_stop_stream(dev, streamIndex);
489 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
490 return ERROR_INVALID_DATA;
493 stream->captureRunning = TRUE;
494 const CAM_ERROR_CODE error = dev->ihal->StartStream(dev->ihal, dev, streamIndex, &mediaType,
495 ecam_dev_sample_captured_callback);
498 stream->captureRunning = FALSE;
499 WLog_ERR(TAG,
"StartStream failure");
500 ecam_dev_stop_stream(dev, streamIndex);
501 ecam_channel_send_error_response(dev->ecam, hchannel, error);
502 return ERROR_INVALID_DATA;
505 stream->streaming = TRUE;
506 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
514static UINT ecam_dev_process_property_list_request(
CameraDevice* dev,
521 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_PropertyListResponse);
529static UINT ecam_dev_send_current_media_type_response(
CameraDevice* dev,
533 CAM_MSG_ID msg = CAM_MSG_ID_CurrentMediaTypeResponse;
540 WLog_ERR(TAG,
"Stream_New failed");
541 return ERROR_NOT_ENOUGH_MEMORY;
544 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
545 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, msg));
547 ecam_dev_write_media_type(s, mediaType);
549 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
560 BYTE streamIndex = 0;
564 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
565 return ERROR_INVALID_DATA;
567 Stream_Read_UINT8(s, streamIndex);
569 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
571 WLog_ERR(TAG,
"Incorrect streamIndex %u", streamIndex);
572 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
573 return ERROR_INVALID_INDEX;
577 BOOL startCapture = FALSE;
580 EnterCriticalSection(&stream->lock);
583 if (stream->hSampleReqChannel != hchannel)
584 stream->hSampleReqChannel = hchannel;
586 stream->samplesRequested++;
587 stream->lastSampleRequestTime = GetTickCount64();
588 const UINT ret = ecam_dev_send_pending(dev, streamIndex, stream);
589 if (dev->ihal->RequestDrivenCapture && (ret == CHANNEL_RC_OK) && !stream->captureRunning)
591 stream->captureRunning = TRUE;
592 mediaType = stream->currMediaType;
593 mediaType.Format = streamInputFormat(stream);
597 LeaveCriticalSection(&stream->lock);
601 WLog_DBG(TAG,
"Sample requested, restarting capture device");
602 const CAM_ERROR_CODE error = dev->ihal->StartStream(dev->ihal, dev, streamIndex, &mediaType,
603 ecam_dev_sample_captured_callback);
606 WLog_ERR(TAG,
"StartStream failure");
607 EnterCriticalSection(&stream->lock);
608 stream->captureRunning = FALSE;
609 if (stream->samplesRequested > 0)
610 stream->samplesRequested--;
611 LeaveCriticalSection(&stream->lock);
612 ecam_dev_send_sample_error_response(dev, hchannel, streamIndex, error);
613 return ERROR_INVALID_DATA;
625static UINT ecam_dev_process_current_media_type_request(
CameraDevice* dev,
629 BYTE streamIndex = 0;
633 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
634 return ERROR_INVALID_DATA;
636 Stream_Read_UINT8(s, streamIndex);
638 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
640 WLog_ERR(TAG,
"Incorrect streamIndex %u", streamIndex);
641 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
642 return ERROR_INVALID_INDEX;
647 if (stream->currMediaType.Format == 0)
649 WLog_ERR(TAG,
"Current media type unknown for streamIndex %u", streamIndex);
650 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_NotInitialized);
651 return ERROR_DEVICE_REINITIALIZATION_NEEDED;
654 return ecam_dev_send_current_media_type_response(dev, hchannel, &stream->currMediaType);
662static UINT ecam_dev_send_media_type_list_response(
CameraDevice* dev,
667 CAM_MSG_ID msg = CAM_MSG_ID_MediaTypeListResponse;
671 wStream* s = Stream_New(
nullptr, CAM_HEADER_SIZE + ECAM_MAX_MEDIA_TYPE_DESCRIPTORS *
675 WLog_ERR(TAG,
"Stream_New failed");
676 return ERROR_NOT_ENOUGH_MEMORY;
679 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
680 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, msg));
682 for (
size_t i = 0; i < nMediaTypes; i++, mediaTypes++)
684 ecam_dev_write_media_type(s, mediaTypes);
687 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
695static UINT ecam_dev_process_media_type_list_request(
CameraDevice* dev,
698 UINT error = CHANNEL_RC_OK;
699 BYTE streamIndex = 0;
701 size_t nMediaTypes = ECAM_MAX_MEDIA_TYPE_DESCRIPTORS;
705 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
706 return ERROR_INVALID_DATA;
708 Stream_Read_UINT8(s, streamIndex);
710 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
712 WLog_ERR(TAG,
"Incorrect streamIndex %u", streamIndex);
713 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
714 return ERROR_INVALID_INDEX;
722 WLog_ERR(TAG,
"calloc failed");
723 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
724 return CHANNEL_RC_NO_MEMORY;
727 size_t nSupportedFormats = 0;
731 dev->ihal->GetMediaTypeDescriptions(dev->ihal, dev->deviceId, streamIndex, supportedFormats,
732 nSupportedFormats, mediaTypes, &nMediaTypes);
733 if (formatIndex == -1 || nMediaTypes == 0)
735 WLog_ERR(TAG,
"Camera doesn't support any compatible video formats");
736 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_ItemNotFound);
737 error = ERROR_DEVICE_FEATURE_NOT_SUPPORTED;
741 stream->formats = supportedFormats[formatIndex];
744 for (
size_t i = 0; i < nMediaTypes; i++)
746 mediaTypes[i].Format = streamOutputFormat(stream);
748 mediaTypes[i].Flags = ecam_media_type_flags(mediaTypes[i].Format);
751 if (stream->currMediaType.Format == 0)
754 stream->currMediaType = mediaTypes[0];
757 error = ecam_dev_send_media_type_list_response(dev, hchannel, mediaTypes, nMediaTypes);
769static UINT ecam_dev_send_stream_list_response(
CameraDevice* dev,
772 CAM_MSG_ID msg = CAM_MSG_ID_StreamListResponse;
779 WLog_ERR(TAG,
"Stream_New failed");
780 return ERROR_NOT_ENOUGH_MEMORY;
783 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
784 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, msg));
787 Stream_Write_UINT16(s, CAM_STREAM_FRAME_SOURCE_TYPE_Color);
788 Stream_Write_UINT8(s, CAM_STREAM_CATEGORY_Capture);
789 Stream_Write_UINT8(s, TRUE );
790 Stream_Write_UINT8(s, FALSE );
792 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
800static UINT ecam_dev_process_stream_list_request(
CameraDevice* dev,
804 return ecam_dev_send_stream_list_response(dev, hchannel);
812static UINT ecam_dev_process_activate_device_request(
CameraDevice* dev,
817 CAM_ERROR_CODE errorCode = CAM_ERROR_CODE_None;
819 if (dev->ihal->Activate(dev->ihal, dev->deviceId, &errorCode))
820 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
822 return ecam_channel_send_error_response(dev->ecam, hchannel, errorCode);
830static UINT ecam_dev_process_deactivate_device_request(
CameraDevice* dev,
837 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
838 ecam_dev_stop_stream(dev, i);
840 CAM_ERROR_CODE errorCode = CAM_ERROR_CODE_None;
841 if (dev->ihal->Deactivate(dev->ihal, dev->deviceId, &errorCode))
842 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
844 return ecam_channel_send_error_response(dev->ecam, hchannel, errorCode);
852static UINT ecam_dev_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
wStream* data)
854 UINT error = CHANNEL_RC_OK;
859 if (!hchannel || !data)
860 return ERROR_INVALID_PARAMETER;
865 return ERROR_INTERNAL_ERROR;
867 if (!Stream_CheckAndLogRequiredLength(TAG, data, CAM_HEADER_SIZE))
868 return ERROR_NO_DATA;
870 Stream_Read_UINT8(data, version);
871 Stream_Read_UINT8(data, messageId);
872 WLog_DBG(TAG,
"ChannelId=%" PRIu32
", MessageId=0x%02" PRIx8
", Version=%d",
873 hchannel->channel_mgr->GetChannelId(hchannel->channel), messageId, version);
877 case CAM_MSG_ID_ActivateDeviceRequest:
878 error = ecam_dev_process_activate_device_request(dev, hchannel, data);
881 case CAM_MSG_ID_DeactivateDeviceRequest:
882 error = ecam_dev_process_deactivate_device_request(dev, hchannel, data);
885 case CAM_MSG_ID_StreamListRequest:
886 error = ecam_dev_process_stream_list_request(dev, hchannel, data);
889 case CAM_MSG_ID_MediaTypeListRequest:
890 error = ecam_dev_process_media_type_list_request(dev, hchannel, data);
893 case CAM_MSG_ID_CurrentMediaTypeRequest:
894 error = ecam_dev_process_current_media_type_request(dev, hchannel, data);
897 case CAM_MSG_ID_PropertyListRequest:
898 error = ecam_dev_process_property_list_request(dev, hchannel, data);
901 case CAM_MSG_ID_StartStreamsRequest:
902 error = ecam_dev_process_start_streams_request(dev, hchannel, data);
905 case CAM_MSG_ID_StopStreamsRequest:
906 error = ecam_dev_process_stop_streams_request(dev, hchannel, data);
909 case CAM_MSG_ID_SampleRequest:
910 error = ecam_dev_process_sample_request(dev, hchannel, data);
914 WLog_WARN(TAG,
"unknown MessageId=0x%02" PRIx8
"", messageId);
915 error = ERROR_INVALID_DATA;
916 ecam_channel_send_error_response(dev->ecam, hchannel,
917 CAM_ERROR_CODE_OperationNotSupported);
929static UINT ecam_dev_on_open(WINPR_ATTR_UNUSED IWTSVirtualChannelCallback* pChannelCallback)
931 WLog_DBG(TAG,
"entered");
932 return CHANNEL_RC_OK;
940static UINT ecam_dev_on_close(IWTSVirtualChannelCallback* pChannelCallback)
943 WINPR_ASSERT(hchannel);
948 WLog_DBG(TAG,
"entered");
950 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
951 ecam_dev_stop_stream(dev, i);
954 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
955 if (dev->streams[i].hSampleReqChannel == hchannel)
956 dev->streams[i].hSampleReqChannel =
nullptr;
959 return CHANNEL_RC_OK;
967static UINT ecam_dev_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
968 IWTSVirtualChannel* pChannel,
969 WINPR_ATTR_UNUSED BYTE* Data,
970 WINPR_ATTR_UNUSED BOOL* pbAccept,
971 IWTSVirtualChannelCallback** ppCallback)
975 if (!hlistener || !hlistener->plugin)
976 return ERROR_INTERNAL_ERROR;
978 WLog_DBG(TAG,
"entered");
984 WLog_ERR(TAG,
"calloc failed");
985 return CHANNEL_RC_NO_MEMORY;
988 hchannel->iface.OnDataReceived = ecam_dev_on_data_received;
989 hchannel->iface.OnOpen = ecam_dev_on_open;
990 hchannel->iface.OnClose = ecam_dev_on_close;
991 hchannel->plugin = hlistener->plugin;
992 hchannel->channel_mgr = hlistener->channel_mgr;
993 hchannel->channel = pChannel;
994 *ppCallback = (IWTSVirtualChannelCallback*)hchannel;
995 return CHANNEL_RC_OK;
1004 WINPR_ATTR_UNUSED
const char* deviceName)
1007 WINPR_ASSERT(ecam->hlistener);
1009 IWTSVirtualChannelManager* pChannelMgr = ecam->hlistener->channel_mgr;
1010 WINPR_ASSERT(pChannelMgr);
1012 WLog_DBG(TAG,
"entered for %s", deviceId);
1018 WLog_ERR(TAG,
"calloc failed");
1023 dev->ihal = ecam->ihal;
1024 strncpy(dev->deviceId, deviceId,
sizeof(dev->deviceId) - 1);
1027 if (!dev->hlistener)
1030 WLog_ERR(TAG,
"calloc failed");
1034 dev->hlistener->iface.OnNewChannelConnection = ecam_dev_on_new_channel_connection;
1035 dev->hlistener->plugin = (IWTSPlugin*)dev;
1036 dev->hlistener->channel_mgr = pChannelMgr;
1037 if (CHANNEL_RC_OK != pChannelMgr->CreateListener(pChannelMgr, deviceId, 0,
1038 &dev->hlistener->iface, &dev->listener))
1040 free(dev->hlistener);
1042 WLog_ERR(TAG,
"CreateListener failed");
1060 WLog_DBG(TAG,
"entered for %s", dev->deviceId);
1064 IWTSVirtualChannelManager* mgr = dev->hlistener->channel_mgr;
1066 IFCALL(mgr->DestroyListener, mgr, dev->listener);
1069 free(dev->hlistener);
1071 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
1072 ecam_dev_stop_stream(dev, i);