20 #include <winpr/assert.h>
24 #define TAG CHANNELS_TAG("rdpecam-device.client")
31 #if defined(WITH_INPUT_FORMAT_H264)
32 { CAM_MEDIA_FORMAT_H264, CAM_MEDIA_FORMAT_H264 },
34 #if defined(WITH_INPUT_FORMAT_MJPG)
35 { CAM_MEDIA_FORMAT_MJPG, CAM_MEDIA_FORMAT_H264 },
37 { CAM_MEDIA_FORMAT_I420, CAM_MEDIA_FORMAT_H264 },
38 { CAM_MEDIA_FORMAT_YUY2, CAM_MEDIA_FORMAT_H264 },
39 { CAM_MEDIA_FORMAT_NV12, CAM_MEDIA_FORMAT_H264 },
40 { CAM_MEDIA_FORMAT_RGB24, CAM_MEDIA_FORMAT_H264 },
41 { CAM_MEDIA_FORMAT_RGB32, CAM_MEDIA_FORMAT_H264 },
43 static const size_t nSupportedFormats = ARRAYSIZE(supportedFormats);
47 WINPR_ASSERT(mediaType);
49 Stream_Write_UINT8(s, mediaType->Format);
50 Stream_Write_UINT32(s, mediaType->Width);
51 Stream_Write_UINT32(s, mediaType->Height);
52 Stream_Write_UINT32(s, mediaType->FrameRateNumerator);
53 Stream_Write_UINT32(s, mediaType->FrameRateDenominator);
54 Stream_Write_UINT32(s, mediaType->PixelAspectRatioNumerator);
55 Stream_Write_UINT32(s, mediaType->PixelAspectRatioDenominator);
56 Stream_Write_UINT8(s, mediaType->Flags);
61 WINPR_ASSERT(mediaType);
63 Stream_Read_UINT8(s, mediaType->Format);
64 Stream_Read_UINT32(s, mediaType->Width);
65 Stream_Read_UINT32(s, mediaType->Height);
66 Stream_Read_UINT32(s, mediaType->FrameRateNumerator);
67 Stream_Read_UINT32(s, mediaType->FrameRateDenominator);
68 Stream_Read_UINT32(s, mediaType->PixelAspectRatioNumerator);
69 Stream_Read_UINT32(s, mediaType->PixelAspectRatioDenominator);
70 Stream_Read_UINT8(s, mediaType->Flags);
76 WINPR_ASSERT(mediaType);
78 WLog_DBG(TAG,
"Format: %d, width: %d, height: %d, fps: %d, flags: %d", mediaType->Format,
79 mediaType->Width, mediaType->Height, mediaType->FrameRateNumerator, mediaType->Flags);
87 static UINT ecam_dev_send_sample_response(
CameraDevice* dev,
size_t streamIndex,
const BYTE* sample,
93 CAM_MSG_ID msg = CAM_MSG_ID_SampleResponse;
95 Stream_SetPosition(stream->sampleRespBuffer, 0);
97 Stream_Write_UINT8(stream->sampleRespBuffer, dev->ecam->version);
98 Stream_Write_UINT8(stream->sampleRespBuffer, msg);
99 Stream_Write_UINT8(stream->sampleRespBuffer, streamIndex);
101 Stream_Write(stream->sampleRespBuffer, sample, size);
104 return ecam_channel_write(dev->ecam, stream->hSampleReqChannel, msg, stream->sampleRespBuffer,
113 static UINT ecam_dev_sample_captured_callback(
CameraDevice* dev,
int streamIndex,
114 const BYTE* sample,
size_t size)
116 BYTE* encodedSample = NULL;
117 size_t encodedSize = 0;
121 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
122 return ERROR_INVALID_INDEX;
126 if (!stream->streaming)
127 return CHANNEL_RC_OK;
129 if (streamInputFormat(stream) != streamOutputFormat(stream))
131 if (!ecam_encoder_compress(stream, sample, size, &encodedSample, &encodedSize))
133 WLog_DBG(TAG,
"Frame drop or error in ecam_encoder_compress");
134 return CHANNEL_RC_OK;
137 if (!stream->streaming)
138 return CHANNEL_RC_OK;
142 encodedSample = WINPR_CAST_CONST_PTR_AWAY(sample, BYTE*);
146 if (stream->nSampleCredits == 0)
148 WLog_DBG(TAG,
"Skip sample: no credits left");
149 return CHANNEL_RC_OK;
151 stream->nSampleCredits--;
153 return ecam_dev_send_sample_response(dev, streamIndex, encodedSample, encodedSize);
156 static void ecam_dev_stop_stream(
CameraDevice* dev,
size_t streamIndex)
160 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
165 if (stream->streaming)
167 stream->streaming = FALSE;
168 dev->ihal->StopStream(dev->ihal, dev->deviceId, 0);
171 if (stream->sampleRespBuffer)
173 Stream_Free(stream->sampleRespBuffer, TRUE);
174 stream->sampleRespBuffer = NULL;
177 ecam_encoder_context_free(stream);
185 static UINT ecam_dev_process_stop_streams_request(
CameraDevice* dev,
191 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
192 ecam_dev_stop_stream(dev, i);
194 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
202 static UINT ecam_dev_process_start_streams_request(
CameraDevice* dev,
205 BYTE streamIndex = 0;
210 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1 + 26))
211 return ERROR_INVALID_DATA;
213 Stream_Read_UINT8(s, streamIndex);
215 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
217 WLog_ERR(TAG,
"Incorrect streamIndex %" PRIuz, streamIndex);
218 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
219 return ERROR_INVALID_INDEX;
222 if (!ecam_dev_read_media_type(s, &mediaType))
224 WLog_ERR(TAG,
"Unable to read MEDIA_TYPE_DESCRIPTION");
225 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidMessage);
226 return ERROR_INVALID_DATA;
229 ecam_dev_print_media_type(&mediaType);
233 if (stream->streaming)
235 WLog_ERR(TAG,
"Streaming already in progress, device %s, streamIndex %d", dev->deviceId,
237 return CAM_ERROR_CODE_UnexpectedError;
243 stream->currMediaType = mediaType;
246 if (streamInputFormat(stream) != streamOutputFormat(stream) &&
247 !ecam_encoder_context_init(stream))
249 WLog_ERR(TAG,
"stream_ecam_encoder_init failed");
250 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_UnexpectedError);
251 return ERROR_INVALID_DATA;
254 stream->sampleRespBuffer = Stream_New(NULL, ECAM_SAMPLE_RESPONSE_BUFFER_SIZE);
255 if (!stream->sampleRespBuffer)
257 WLog_ERR(TAG,
"Stream_New failed");
258 ecam_dev_stop_stream(dev, streamIndex);
259 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
260 return ERROR_INVALID_DATA;
264 mediaType.Format = streamInputFormat(stream);
266 stream->nSampleCredits = 0;
268 UINT error = dev->ihal->StartStream(dev->ihal, dev, streamIndex, &mediaType,
269 ecam_dev_sample_captured_callback);
272 WLog_ERR(TAG,
"StartStream failure");
273 ecam_dev_stop_stream(dev, streamIndex);
274 ecam_channel_send_error_response(dev->ecam, hchannel, error);
275 return ERROR_INVALID_DATA;
278 stream->streaming = TRUE;
279 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
287 static UINT ecam_dev_process_property_list_request(
CameraDevice* dev,
293 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_PropertyListResponse);
301 static UINT ecam_dev_send_current_media_type_response(
CameraDevice* dev,
305 CAM_MSG_ID msg = CAM_MSG_ID_CurrentMediaTypeResponse;
312 WLog_ERR(TAG,
"Stream_New failed");
313 return ERROR_NOT_ENOUGH_MEMORY;
316 Stream_Write_UINT8(s, dev->ecam->version);
317 Stream_Write_UINT8(s, msg);
319 ecam_dev_write_media_type(s, mediaType);
321 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
332 BYTE streamIndex = 0;
336 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
337 return ERROR_INVALID_DATA;
339 Stream_Read_UINT8(s, streamIndex);
341 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
343 WLog_ERR(TAG,
"Incorrect streamIndex %d", streamIndex);
344 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
345 return ERROR_INVALID_INDEX;
351 if (stream->hSampleReqChannel != hchannel)
352 stream->hSampleReqChannel = hchannel;
355 stream->nSampleCredits = ECAM_MAX_SAMPLE_CREDITS;
357 return CHANNEL_RC_OK;
365 static UINT ecam_dev_process_current_media_type_request(
CameraDevice* dev,
369 BYTE streamIndex = 0;
373 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
374 return ERROR_INVALID_DATA;
376 Stream_Read_UINT8(s, streamIndex);
378 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
380 WLog_ERR(TAG,
"Incorrect streamIndex %d", streamIndex);
381 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
382 return ERROR_INVALID_INDEX;
387 if (stream->currMediaType.Format == 0)
389 WLog_ERR(TAG,
"Current media type unknown for streamIndex %d", streamIndex);
390 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_NotInitialized);
391 return ERROR_DEVICE_REINITIALIZATION_NEEDED;
394 return ecam_dev_send_current_media_type_response(dev, hchannel, &stream->currMediaType);
402 static UINT ecam_dev_send_media_type_list_response(
CameraDevice* dev,
407 CAM_MSG_ID msg = CAM_MSG_ID_MediaTypeListResponse;
411 wStream* s = Stream_New(NULL, CAM_HEADER_SIZE + ECAM_MAX_MEDIA_TYPE_DESCRIPTORS *
415 WLog_ERR(TAG,
"Stream_New failed");
416 return ERROR_NOT_ENOUGH_MEMORY;
419 Stream_Write_UINT8(s, dev->ecam->version);
420 Stream_Write_UINT8(s, msg);
422 for (
size_t i = 0; i < nMediaTypes; i++, mediaTypes++)
424 ecam_dev_write_media_type(s, mediaTypes);
427 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
435 static UINT ecam_dev_process_media_type_list_request(
CameraDevice* dev,
438 UINT error = CHANNEL_RC_OK;
439 BYTE streamIndex = 0;
441 size_t nMediaTypes = ECAM_MAX_MEDIA_TYPE_DESCRIPTORS;
445 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
446 return ERROR_INVALID_DATA;
448 Stream_Read_UINT8(s, streamIndex);
450 if (streamIndex >= ECAM_DEVICE_MAX_STREAMS)
452 WLog_ERR(TAG,
"Incorrect streamIndex %d", streamIndex);
453 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_InvalidStreamNumber);
454 return ERROR_INVALID_INDEX;
462 WLog_ERR(TAG,
"calloc failed");
463 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_OutOfMemory);
464 return CHANNEL_RC_NO_MEMORY;
468 dev->ihal->GetMediaTypeDescriptions(dev->ihal, dev->deviceId, streamIndex, supportedFormats,
469 nSupportedFormats, mediaTypes, &nMediaTypes);
470 if (formatIndex == -1 || nMediaTypes == 0)
472 WLog_ERR(TAG,
"Camera doesn't support any compatible video formats");
473 ecam_channel_send_error_response(dev->ecam, hchannel, CAM_ERROR_CODE_ItemNotFound);
474 error = ERROR_DEVICE_FEATURE_NOT_SUPPORTED;
478 stream->formats = supportedFormats[formatIndex];
481 for (
size_t i = 0; i < nMediaTypes; i++)
483 mediaTypes[i].Format = streamOutputFormat(stream);
484 mediaTypes[i].Flags = CAM_MEDIA_TYPE_DESCRIPTION_FLAG_DecodingRequired;
487 if (stream->currMediaType.Format == 0)
490 stream->currMediaType = mediaTypes[0];
493 error = ecam_dev_send_media_type_list_response(dev, hchannel, mediaTypes, nMediaTypes);
505 static UINT ecam_dev_send_stream_list_response(
CameraDevice* dev,
508 CAM_MSG_ID msg = CAM_MSG_ID_StreamListResponse;
515 WLog_ERR(TAG,
"Stream_New failed");
516 return ERROR_NOT_ENOUGH_MEMORY;
519 Stream_Write_UINT8(s, dev->ecam->version);
520 Stream_Write_UINT8(s, msg);
523 Stream_Write_UINT16(s, CAM_STREAM_FRAME_SOURCE_TYPE_Color);
524 Stream_Write_UINT8(s, CAM_STREAM_CATEGORY_Capture);
525 Stream_Write_UINT8(s, TRUE );
526 Stream_Write_UINT8(s, FALSE );
528 return ecam_channel_write(dev->ecam, hchannel, msg, s, TRUE);
536 static UINT ecam_dev_process_stream_list_request(
CameraDevice* dev,
539 return ecam_dev_send_stream_list_response(dev, hchannel);
547 static UINT ecam_dev_process_activate_device_request(
CameraDevice* dev,
553 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
561 static UINT ecam_dev_process_deactivate_device_request(
CameraDevice* dev,
568 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
569 ecam_dev_stop_stream(dev, i);
571 return ecam_channel_send_generic_msg(dev->ecam, hchannel, CAM_MSG_ID_SuccessResponse);
579 static UINT ecam_dev_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
wStream* data)
581 UINT error = CHANNEL_RC_OK;
586 if (!hchannel || !data)
587 return ERROR_INVALID_PARAMETER;
592 return ERROR_INTERNAL_ERROR;
594 if (!Stream_CheckAndLogRequiredCapacity(TAG, data, CAM_HEADER_SIZE))
595 return ERROR_NO_DATA;
597 Stream_Read_UINT8(data, version);
598 Stream_Read_UINT8(data, messageId);
599 WLog_DBG(TAG,
"ChannelId=%d, MessageId=0x%02" PRIx8
", Version=%d",
600 hchannel->channel_mgr->GetChannelId(hchannel->channel), messageId, version);
604 case CAM_MSG_ID_ActivateDeviceRequest:
605 error = ecam_dev_process_activate_device_request(dev, hchannel, data);
608 case CAM_MSG_ID_DeactivateDeviceRequest:
609 error = ecam_dev_process_deactivate_device_request(dev, hchannel, data);
612 case CAM_MSG_ID_StreamListRequest:
613 error = ecam_dev_process_stream_list_request(dev, hchannel, data);
616 case CAM_MSG_ID_MediaTypeListRequest:
617 error = ecam_dev_process_media_type_list_request(dev, hchannel, data);
620 case CAM_MSG_ID_CurrentMediaTypeRequest:
621 error = ecam_dev_process_current_media_type_request(dev, hchannel, data);
624 case CAM_MSG_ID_PropertyListRequest:
625 error = ecam_dev_process_property_list_request(dev, hchannel, data);
628 case CAM_MSG_ID_StartStreamsRequest:
629 error = ecam_dev_process_start_streams_request(dev, hchannel, data);
632 case CAM_MSG_ID_StopStreamsRequest:
633 error = ecam_dev_process_stop_streams_request(dev, hchannel, data);
636 case CAM_MSG_ID_SampleRequest:
637 error = ecam_dev_process_sample_request(dev, hchannel, data);
641 WLog_WARN(TAG,
"unknown MessageId=0x%02" PRIx8
"", messageId);
642 error = ERROR_INVALID_DATA;
643 ecam_channel_send_error_response(dev->ecam, hchannel,
644 CAM_ERROR_CODE_OperationNotSupported);
656 static UINT ecam_dev_on_open(IWTSVirtualChannelCallback* pChannelCallback)
659 WINPR_ASSERT(hchannel);
664 WLog_DBG(TAG,
"entered");
665 return CHANNEL_RC_OK;
673 static UINT ecam_dev_on_close(IWTSVirtualChannelCallback* pChannelCallback)
676 WINPR_ASSERT(hchannel);
681 WLog_DBG(TAG,
"entered");
684 for (
size_t i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
685 if (dev->streams[i].hSampleReqChannel == hchannel)
686 dev->streams[i].hSampleReqChannel = NULL;
689 return CHANNEL_RC_OK;
697 static UINT ecam_dev_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
698 IWTSVirtualChannel* pChannel, BYTE* Data,
700 IWTSVirtualChannelCallback** ppCallback)
704 if (!hlistener || !hlistener->plugin)
705 return ERROR_INTERNAL_ERROR;
707 WLog_DBG(TAG,
"entered");
713 WLog_ERR(TAG,
"calloc failed");
714 return CHANNEL_RC_NO_MEMORY;
717 hchannel->iface.OnDataReceived = ecam_dev_on_data_received;
718 hchannel->iface.OnOpen = ecam_dev_on_open;
719 hchannel->iface.OnClose = ecam_dev_on_close;
720 hchannel->plugin = hlistener->plugin;
721 hchannel->channel_mgr = hlistener->channel_mgr;
722 hchannel->channel = pChannel;
723 *ppCallback = (IWTSVirtualChannelCallback*)hchannel;
724 return CHANNEL_RC_OK;
735 WINPR_ASSERT(ecam->hlistener);
737 IWTSVirtualChannelManager* pChannelMgr = ecam->hlistener->channel_mgr;
738 WINPR_ASSERT(pChannelMgr);
740 WLog_DBG(TAG,
"entered for %s", deviceId);
746 WLog_ERR(TAG,
"calloc failed");
751 dev->ihal = ecam->ihal;
752 strncpy(dev->deviceId, deviceId,
sizeof(dev->deviceId) - 1);
758 WLog_ERR(TAG,
"calloc failed");
762 dev->hlistener->iface.OnNewChannelConnection = ecam_dev_on_new_channel_connection;
763 dev->hlistener->plugin = (IWTSPlugin*)dev;
764 dev->hlistener->channel_mgr = pChannelMgr;
765 if (CHANNEL_RC_OK != pChannelMgr->CreateListener(pChannelMgr, deviceId, 0,
766 &dev->hlistener->iface, &dev->listener))
768 free(dev->hlistener);
770 WLog_ERR(TAG,
"CreateListener failed");
788 WLog_DBG(TAG,
"entered for %s", dev->deviceId);
792 IWTSVirtualChannelManager* mgr = dev->hlistener->channel_mgr;
794 IFCALL(mgr->DestroyListener, mgr, dev->listener);
797 free(dev->hlistener);
799 for (
int i = 0; i < ECAM_DEVICE_MAX_STREAMS; i++)
800 ecam_dev_stop_stream(dev, i);