20#include <winpr/assert.h>
21#include <winpr/cast.h>
22#include <winpr/interlocked.h>
25#include "rdpecam-utils.h"
27#define TAG CHANNELS_TAG("rdpecam-device.client")
43 const CAM_MEDIA_FORMAT available[] = { CAM_MEDIA_FORMAT_H264, CAM_MEDIA_FORMAT_MJPG,
44 CAM_MEDIA_FORMAT_YUY2, CAM_MEDIA_FORMAT_NV12,
45 CAM_MEDIA_FORMAT_I420, CAM_MEDIA_FORMAT_RGB24,
46 CAM_MEDIA_FORMAT_RGB32 };
49 formats[ARRAYSIZE(available) * ARRAYSIZE(available)];
50 static size_t count = 0;
51 static BOOL initialized = FALSE;
55 for (
size_t dst = 0; dst < ARRAYSIZE(available); dst++)
57 const CAM_MEDIA_FORMAT dstFormat = available[dst];
59 for (
size_t src = 0; src < ARRAYSIZE(available); src++)
61 const CAM_MEDIA_FORMAT srcFormat = available[src];
62 if (freerdp_video_conversion_supported(ecamToVideoFormat(srcFormat),
63 ecamToVideoFormat(dstFormat)))
78 WINPR_ASSERT(mediaType);
80 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, mediaType->Format));
81 Stream_Write_UINT32(s, mediaType->Width);
82 Stream_Write_UINT32(s, mediaType->Height);
83 Stream_Write_UINT32(s, mediaType->FrameRateNumerator);
84 Stream_Write_UINT32(s, mediaType->FrameRateDenominator);
85 Stream_Write_UINT32(s, mediaType->PixelAspectRatioNumerator);
86 Stream_Write_UINT32(s, mediaType->PixelAspectRatioDenominator);
87 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, mediaType->Flags));
92 WINPR_ASSERT(mediaType);
94 const uint8_t format = Stream_Get_UINT8(s);
95 if (!rdpecam_valid_CamMediaFormat(format))
98 mediaType->Format = WINPR_ASSERTING_INT_CAST(CAM_MEDIA_FORMAT, format);
99 mediaType->Width = Stream_Get_UINT32(s);
100 mediaType->Height = Stream_Get_UINT32(s);
101 mediaType->FrameRateNumerator = Stream_Get_UINT32(s);
102 mediaType->FrameRateDenominator = Stream_Get_UINT32(s);
103 mediaType->PixelAspectRatioNumerator = Stream_Get_UINT32(s);
104 mediaType->PixelAspectRatioDenominator = Stream_Get_UINT32(s);
106 if (mediaType->FrameRateNumerator == 0)
108 if (mediaType->FrameRateDenominator == 0)
110 if (mediaType->PixelAspectRatioNumerator == 0)
112 if (mediaType->PixelAspectRatioDenominator == 0)
115 const uint8_t flags = Stream_Get_UINT8(s);
116 if (!rdpecam_valid_MediaTypeDescriptionFlags(flags))
118 mediaType->Flags = WINPR_ASSERTING_INT_CAST(CAM_MEDIA_TYPE_DESCRIPTION_FLAGS, flags);
124 WINPR_ASSERT(mediaType);
126 WLog_DBG(TAG,
"Format: %u, width: %u, height: %u, fps: %u, flags: %u", mediaType->Format,
127 mediaType->Width, mediaType->Height, mediaType->FrameRateNumerator, mediaType->Flags);
141 CAM_MSG_ID msg = CAM_MSG_ID_SampleResponse;
143 Stream_ResetPosition(stream->sampleRespBuffer);
144 if (!Stream_EnsureRemainingCapacity(stream->sampleRespBuffer, 3))
147 Stream_Write_UINT8(stream->sampleRespBuffer,
148 WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
149 Stream_Write_UINT8(stream->sampleRespBuffer, WINPR_ASSERTING_INT_CAST(uint8_t, msg));
150 Stream_Write_UINT8(stream->sampleRespBuffer, WINPR_ASSERTING_INT_CAST(uint8_t, streamIndex));
152 return stream->sampleRespBuffer;
155static BOOL mediaSupportDrops(CAM_MEDIA_FORMAT format)
159 case CAM_MEDIA_FORMAT_H264:
166static UINT ecam_dev_send_sample_error_response(
CameraDevice* dev,
168 size_t streamIndex, CAM_ERROR_CODE errorCode)
172 wStream* s = Stream_New(
nullptr, CAM_HEADER_SIZE + 5);
174 return ERROR_NOT_ENOUGH_MEMORY;
176 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
177 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, CAM_MSG_ID_SampleErrorResponse));
178 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, streamIndex));
179 Stream_Write_UINT32(s, (UINT32)errorCode);
181 return ecam_channel_write(dev->ecam, hchannel, CAM_MSG_ID_SampleErrorResponse, s, TRUE);
187 WINPR_ASSERT(stream);
189 if (stream->samplesRequested <= 0)
191 WLog_VRB(TAG,
"Frame delayed: No sample requested");
192 return CHANNEL_RC_OK;
195 if (!stream->haveSample)
197 WLog_VRB(TAG,
"Frame response delayed: No sample available");
198 return CHANNEL_RC_OK;
201 wStream* output = ecam_dev_prepare_sample_response(dev, streamIndex);
203 return CHANNEL_RC_OK;
205 const BYTE* encodedSample = Stream_Buffer(stream->pendingSample);
206 const size_t encodedSize = Stream_Length(stream->pendingSample);
207 if (!ecam_encoder_compress(stream, encodedSample, encodedSize, output))
209 WLog_DBG(TAG,
"Frame dropped: error in ecam_encoder_compress");
210 stream->haveSample = FALSE;
211 return CHANNEL_RC_OK;
214 if (!stream->streaming)
216 WLog_DBG(TAG,
"Frame delayed/dropped: stream stopped");
217 return CHANNEL_RC_OK;
220 stream->samplesRequested--;
221 stream->haveSample = FALSE;
224 return ecam_channel_write(dev->ecam, stream->hSampleReqChannel, CAM_MSG_ID_SampleResponse,
228static UINT ecam_dev_sample_captured_callback(
CameraDevice* dev,
size_t streamIndex,
229 const BYTE* sample,
size_t size)
233 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
234 return ERROR_INVALID_INDEX;
238 if (!stream->streaming)
240 WLog_DBG(TAG,
"Frame drop: stream not running");
241 return CHANNEL_RC_OK;
244 EnterCriticalSection(&stream->lock);
245 UINT ret = CHANNEL_RC_NO_MEMORY;
246 if (dev->ihal->RequestDrivenCapture && (stream->samplesRequested <= 0))
248 WLog_DBG(TAG,
"No sample requested, releasing capture device");
249 stream->captureRunning = FALSE;
250 ret = ECAM_SAMPLE_CAPTURE_DRAINED;
259 if (stream->haveSample && !mediaSupportDrops(stream->formats.inputFormat))
268 DWORD waitDelay = (1000 * stream->currMediaType.FrameRateDenominator) /
269 stream->currMediaType.FrameRateNumerator;
275 while (stream->haveSample && stream->streaming)
277 LeaveCriticalSection(&stream->lock);
279 SleepEx(waitDelay, TRUE);
281 EnterCriticalSection(&stream->lock);
284 if (!stream->streaming)
286 WLog_DBG(TAG,
"Frame drop: stream not running");
292 Stream_ResetPosition(stream->pendingSample);
293 if (!Stream_EnsureRemainingCapacity(stream->pendingSample, size))
296 Stream_Write(stream->pendingSample, sample, size);
297 Stream_SealLength(stream->pendingSample);
298 stream->haveSample = TRUE;
300 ret = ecam_dev_send_pending(dev, streamIndex, stream);
303 LeaveCriticalSection(&stream->lock);
307static void ecam_dev_stop_stream(
CameraDevice* dev,
size_t streamIndex)
311 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
316 if (stream->streaming)
318 stream->streaming = FALSE;
319 stream->captureRunning = FALSE;
320 dev->ihal->StopStream(dev->ihal, dev->deviceId, 0);
322 DeleteCriticalSection(&stream->lock);
325 Stream_Free(stream->sampleRespBuffer, TRUE);
326 stream->sampleRespBuffer =
nullptr;
328 Stream_Free(stream->pendingSample, TRUE);
329 stream->pendingSample =
nullptr;
331 ecam_encoder_context_free(stream);
339static UINT ecam_dev_process_stop_streams_request(
CameraDevice* dev,
345 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
346 ecam_dev_stop_stream(dev, i);
348 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
352static BOOL media_type_valid(
CameraDevice* dev, UINT8 streamIndex,
359 size_t nMediaTypes = ARRAYSIZE(supported);
361 size_t nSupportedFormats = 0;
364 dev->ihal->GetMediaTypeDescriptions(dev->ihal, dev->deviceId, streamIndex, supportedFormats,
365 nSupportedFormats, supported, &nMediaTypes);
369 for (
size_t x = 0; x < nMediaTypes; x++)
383static UINT ecam_dev_process_start_streams_request(
CameraDevice* dev,
386 BYTE streamIndex = 0;
391 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1 + 26))
392 return ERROR_INVALID_DATA;
394 Stream_Read_UINT8(s, streamIndex);
396 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
398 WLog_ERR(TAG,
"Incorrect streamIndex %" PRIu8, streamIndex);
399 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
400 return ERROR_INVALID_INDEX;
403 if (!ecam_dev_read_media_type(s, &mediaType))
405 WLog_ERR(TAG,
"Unable to read MEDIA_TYPE_DESCRIPTION");
406 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidMessage);
407 return ERROR_INVALID_DATA;
410 ecam_dev_print_media_type(&mediaType);
411 if (!media_type_valid(dev, streamIndex, &mediaType))
413 WLog_ERR(TAG,
"Unannounced MEDIA_TYPE_DESCRIPTION");
414 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidMessage);
415 return ERROR_INVALID_DATA;
420 if (stream->streaming)
422 WLog_ERR(TAG,
"Streaming already in progress, device %s, streamIndex %u", dev->deviceId,
424 return CAM_ERROR_CODE_UnexpectedError;
430 stream->currMediaType = mediaType;
432 if (!ecam_encoder_context_init(stream))
434 WLog_ERR(TAG,
"stream_ecam_encoder_init failed");
435 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_UnexpectedError);
436 return ERROR_INVALID_DATA;
439 stream->sampleRespBuffer = Stream_New(
nullptr, ECAM_SAMPLE_RESPONSE_BUFFER_SIZE);
440 if (!stream->sampleRespBuffer)
442 WLog_ERR(TAG,
"Stream_New failed");
443 ecam_dev_stop_stream(dev, streamIndex);
444 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
445 return ERROR_INVALID_DATA;
449 mediaType.Format = streamInputFormat(stream);
451 stream->samplesRequested = 0;
452 stream->haveSample = FALSE;
454 if (!InitializeCriticalSectionEx(&stream->lock, 0, 0))
456 WLog_ERR(TAG,
"InitializeCriticalSectionEx failed");
457 ecam_dev_stop_stream(dev, streamIndex);
458 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
459 return ERROR_INVALID_DATA;
462 stream->pendingSample = Stream_New(
nullptr, 4ull * mediaType.Width * mediaType.Height);
463 if (!stream->pendingSample)
465 WLog_ERR(TAG,
"pending stream failed");
466 ecam_dev_stop_stream(dev, streamIndex);
467 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
468 return ERROR_INVALID_DATA;
471 stream->captureRunning = TRUE;
472 const CAM_ERROR_CODE error = dev->ihal->StartStream(dev->ihal, dev, streamIndex, &mediaType,
473 ecam_dev_sample_captured_callback);
476 stream->captureRunning = FALSE;
477 WLog_ERR(TAG,
"StartStream failure");
478 ecam_dev_stop_stream(dev, streamIndex);
479 ecam_channel_send_error_response(dev->ecam, hchannel, error);
480 return ERROR_INVALID_DATA;
483 stream->streaming = TRUE;
484 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
492static UINT ecam_dev_process_property_list_request(
CameraDevice* dev,
499 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_PropertyListResponse);
507static UINT ecam_dev_send_current_media_type_response(
CameraDevice* dev,
511 CAM_MSG_ID msg = CAM_MSG_ID_CurrentMediaTypeResponse;
518 WLog_ERR(TAG,
"Stream_New failed");
519 return ERROR_NOT_ENOUGH_MEMORY;
522 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
523 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, msg));
525 ecam_dev_write_media_type(s, mediaType);
527 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
538 BYTE streamIndex = 0;
542 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
543 return ERROR_INVALID_DATA;
545 Stream_Read_UINT8(s, streamIndex);
547 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
549 WLog_ERR(TAG,
"Incorrect streamIndex %u", streamIndex);
550 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
551 return ERROR_INVALID_INDEX;
555 BOOL startCapture = FALSE;
558 EnterCriticalSection(&stream->lock);
561 if (stream->hSampleReqChannel != hchannel)
562 stream->hSampleReqChannel = hchannel;
564 stream->samplesRequested++;
565 const UINT ret = ecam_dev_send_pending(dev, streamIndex, stream);
566 if (dev->ihal->RequestDrivenCapture && (ret == CHANNEL_RC_OK) && !stream->captureRunning)
568 stream->captureRunning = TRUE;
569 mediaType = stream->currMediaType;
570 mediaType.Format = streamInputFormat(stream);
574 LeaveCriticalSection(&stream->lock);
578 WLog_DBG(TAG,
"Sample requested, restarting capture device");
579 const CAM_ERROR_CODE error = dev->ihal->StartStream(dev->ihal, dev, streamIndex, &mediaType,
580 ecam_dev_sample_captured_callback);
583 WLog_ERR(TAG,
"StartStream failure");
584 EnterCriticalSection(&stream->lock);
585 stream->captureRunning = FALSE;
586 if (stream->samplesRequested > 0)
587 stream->samplesRequested--;
588 LeaveCriticalSection(&stream->lock);
589 ecam_dev_send_sample_error_response(dev, hchannel, streamIndex, error);
590 return ERROR_INVALID_DATA;
602static UINT ecam_dev_process_current_media_type_request(
CameraDevice* dev,
606 BYTE streamIndex = 0;
610 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
611 return ERROR_INVALID_DATA;
613 Stream_Read_UINT8(s, streamIndex);
615 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
617 WLog_ERR(TAG,
"Incorrect streamIndex %u", streamIndex);
618 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
619 return ERROR_INVALID_INDEX;
624 if (stream->currMediaType.Format == 0)
626 WLog_ERR(TAG,
"Current media type unknown for streamIndex %u", streamIndex);
627 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_NotInitialized);
628 return ERROR_DEVICE_REINITIALIZATION_NEEDED;
631 return ecam_dev_send_current_media_type_response(dev, hchannel, &stream->currMediaType);
639static UINT ecam_dev_send_media_type_list_response(
CameraDevice* dev,
644 CAM_MSG_ID msg = CAM_MSG_ID_MediaTypeListResponse;
648 wStream* s = Stream_New(
nullptr, CAM_HEADER_SIZE + ECAM_MAX_MEDIA_TYPE_DESCRIPTORS *
652 WLog_ERR(TAG,
"Stream_New failed");
653 return ERROR_NOT_ENOUGH_MEMORY;
656 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
657 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, msg));
659 for (
size_t i = 0; i < nMediaTypes; i++, mediaTypes++)
661 ecam_dev_write_media_type(s, mediaTypes);
664 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
672static UINT ecam_dev_process_media_type_list_request(
CameraDevice* dev,
675 UINT error = CHANNEL_RC_OK;
676 BYTE streamIndex = 0;
678 size_t nMediaTypes = ECAM_MAX_MEDIA_TYPE_DESCRIPTORS;
682 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
683 return ERROR_INVALID_DATA;
685 Stream_Read_UINT8(s, streamIndex);
687 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
689 WLog_ERR(TAG,
"Incorrect streamIndex %u", streamIndex);
690 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
691 return ERROR_INVALID_INDEX;
699 WLog_ERR(TAG,
"calloc failed");
700 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
701 return CHANNEL_RC_NO_MEMORY;
704 size_t nSupportedFormats = 0;
708 dev->ihal->GetMediaTypeDescriptions(dev->ihal, dev->deviceId, streamIndex, supportedFormats,
709 nSupportedFormats, mediaTypes, &nMediaTypes);
710 if (formatIndex == -1 || nMediaTypes == 0)
712 WLog_ERR(TAG,
"Camera doesn't support any compatible video formats");
713 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_ItemNotFound);
714 error = ERROR_DEVICE_FEATURE_NOT_SUPPORTED;
718 stream->formats = supportedFormats[formatIndex];
721 for (
size_t i = 0; i < nMediaTypes; i++)
723 mediaTypes[i].Format = streamOutputFormat(stream);
724 mediaTypes[i].Flags = CAM_MEDIA_TYPE_DESCRIPTION_FLAG_DecodingRequired;
727 if (stream->currMediaType.Format == 0)
730 stream->currMediaType = mediaTypes[0];
733 error = ecam_dev_send_media_type_list_response(dev, hchannel, mediaTypes, nMediaTypes);
745static UINT ecam_dev_send_stream_list_response(
CameraDevice* dev,
748 CAM_MSG_ID msg = CAM_MSG_ID_StreamListResponse;
755 WLog_ERR(TAG,
"Stream_New failed");
756 return ERROR_NOT_ENOUGH_MEMORY;
759 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, dev->ecam->version));
760 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, msg));
763 Stream_Write_UINT16(s, CAM_STREAM_FRAME_SOURCE_TYPE_Color);
764 Stream_Write_UINT8(s, CAM_STREAM_CATEGORY_Capture);
765 Stream_Write_UINT8(s, TRUE );
766 Stream_Write_UINT8(s, FALSE );
768 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
776static UINT ecam_dev_process_stream_list_request(
CameraDevice* dev,
780 return ecam_dev_send_stream_list_response(dev, hchannel);
788static UINT ecam_dev_process_activate_device_request(
CameraDevice* dev,
793 CAM_ERROR_CODE errorCode = CAM_ERROR_CODE_None;
795 if (dev->ihal->Activate(dev->ihal, dev->deviceId, &errorCode))
796 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
798 return ecam_channel_send_error_response(dev->ecam, hchannel, errorCode);
806static UINT ecam_dev_process_deactivate_device_request(
CameraDevice* dev,
813 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
814 ecam_dev_stop_stream(dev, i);
816 CAM_ERROR_CODE errorCode = CAM_ERROR_CODE_None;
817 if (dev->ihal->Deactivate(dev->ihal, dev->deviceId, &errorCode))
818 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
820 return ecam_channel_send_error_response(dev->ecam, hchannel, errorCode);
828static UINT ecam_dev_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
wStream* data)
830 UINT error = CHANNEL_RC_OK;
835 if (!hchannel || !data)
836 return ERROR_INVALID_PARAMETER;
841 return ERROR_INTERNAL_ERROR;
843 if (!Stream_CheckAndLogRequiredLength(TAG, data, CAM_HEADER_SIZE))
844 return ERROR_NO_DATA;
846 Stream_Read_UINT8(data, version);
847 Stream_Read_UINT8(data, messageId);
848 WLog_DBG(TAG,
"ChannelId=%" PRIu32
", MessageId=0x%02" PRIx8
", Version=%d",
849 hchannel->channel_mgr->GetChannelId(hchannel->channel), messageId, version);
853 case CAM_MSG_ID_ActivateDeviceRequest:
854 error = ecam_dev_process_activate_device_request(dev, hchannel, data);
857 case CAM_MSG_ID_DeactivateDeviceRequest:
858 error = ecam_dev_process_deactivate_device_request(dev, hchannel, data);
861 case CAM_MSG_ID_StreamListRequest:
862 error = ecam_dev_process_stream_list_request(dev, hchannel, data);
865 case CAM_MSG_ID_MediaTypeListRequest:
866 error = ecam_dev_process_media_type_list_request(dev, hchannel, data);
869 case CAM_MSG_ID_CurrentMediaTypeRequest:
870 error = ecam_dev_process_current_media_type_request(dev, hchannel, data);
873 case CAM_MSG_ID_PropertyListRequest:
874 error = ecam_dev_process_property_list_request(dev, hchannel, data);
877 case CAM_MSG_ID_StartStreamsRequest:
878 error = ecam_dev_process_start_streams_request(dev, hchannel, data);
881 case CAM_MSG_ID_StopStreamsRequest:
882 error = ecam_dev_process_stop_streams_request(dev, hchannel, data);
885 case CAM_MSG_ID_SampleRequest:
886 error = ecam_dev_process_sample_request(dev, hchannel, data);
890 WLog_WARN(TAG,
"unknown MessageId=0x%02" PRIx8
"", messageId);
891 error = ERROR_INVALID_DATA;
892 ecam_channel_send_error_response(dev->ecam, hchannel,
893 CAM_ERROR_CODE_OperationNotSupported);
905static UINT ecam_dev_on_open(WINPR_ATTR_UNUSED IWTSVirtualChannelCallback* pChannelCallback)
907 WLog_DBG(TAG,
"entered");
908 return CHANNEL_RC_OK;
916static UINT ecam_dev_on_close(IWTSVirtualChannelCallback* pChannelCallback)
919 WINPR_ASSERT(hchannel);
924 WLog_DBG(TAG,
"entered");
926 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
927 ecam_dev_stop_stream(dev, i);
930 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
931 if (dev->streams[i].hSampleReqChannel == hchannel)
932 dev->streams[i].hSampleReqChannel =
nullptr;
935 return CHANNEL_RC_OK;
943static UINT ecam_dev_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
944 IWTSVirtualChannel* pChannel,
945 WINPR_ATTR_UNUSED BYTE* Data,
946 WINPR_ATTR_UNUSED BOOL* pbAccept,
947 IWTSVirtualChannelCallback** ppCallback)
951 if (!hlistener || !hlistener->plugin)
952 return ERROR_INTERNAL_ERROR;
954 WLog_DBG(TAG,
"entered");
960 WLog_ERR(TAG,
"calloc failed");
961 return CHANNEL_RC_NO_MEMORY;
964 hchannel->iface.OnDataReceived = ecam_dev_on_data_received;
965 hchannel->iface.OnOpen = ecam_dev_on_open;
966 hchannel->iface.OnClose = ecam_dev_on_close;
967 hchannel->plugin = hlistener->plugin;
968 hchannel->channel_mgr = hlistener->channel_mgr;
969 hchannel->channel = pChannel;
970 *ppCallback = (IWTSVirtualChannelCallback*)hchannel;
971 return CHANNEL_RC_OK;
980 WINPR_ATTR_UNUSED
const char* deviceName)
983 WINPR_ASSERT(ecam->hlistener);
985 IWTSVirtualChannelManager* pChannelMgr = ecam->hlistener->channel_mgr;
986 WINPR_ASSERT(pChannelMgr);
988 WLog_DBG(TAG,
"entered for %s", deviceId);
994 WLog_ERR(TAG,
"calloc failed");
999 dev->ihal = ecam->ihal;
1000 strncpy(dev->deviceId, deviceId,
sizeof(dev->deviceId) - 1);
1003 if (!dev->hlistener)
1006 WLog_ERR(TAG,
"calloc failed");
1010 dev->hlistener->iface.OnNewChannelConnection = ecam_dev_on_new_channel_connection;
1011 dev->hlistener->plugin = (IWTSPlugin*)dev;
1012 dev->hlistener->channel_mgr = pChannelMgr;
1013 if (CHANNEL_RC_OK != pChannelMgr->CreateListener(pChannelMgr, deviceId, 0,
1014 &dev->hlistener->iface, &dev->listener))
1016 free(dev->hlistener);
1018 WLog_ERR(TAG,
"CreateListener failed");
1036 WLog_DBG(TAG,
"entered for %s", dev->deviceId);
1040 IWTSVirtualChannelManager* mgr = dev->hlistener->channel_mgr;
1042 IFCALL(mgr->DestroyListener, mgr, dev->listener);
1045 free(dev->hlistener);
1047 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
1048 ecam_dev_stop_stream(dev, i);