7#include <QtCore/QDateTime>
8#include <QtCore/QLoggingCategory>
9#include <QtCore/QtMath>
20 bool canCaptureImageInVideoMode,
21 bool canCaptureVideoInImageMode,
23 bool hasTrackingPoint,
24 bool hasTrackingRectangle)
28 uint32_t configuredFlags = 0;
29 if (captureVideo) configuredFlags |= CAMERA_CAP_FLAGS_CAPTURE_VIDEO;
30 if (captureImage) configuredFlags |= CAMERA_CAP_FLAGS_CAPTURE_IMAGE;
31 if (hasModes) configuredFlags |= CAMERA_CAP_FLAGS_HAS_MODES;
32 if (hasVideoStream) configuredFlags |= CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM;
33 if (canCaptureImageInVideoMode) configuredFlags |= CAMERA_CAP_FLAGS_CAN_CAPTURE_IMAGE_IN_VIDEO_MODE;
34 if (canCaptureVideoInImageMode) configuredFlags |= CAMERA_CAP_FLAGS_CAN_CAPTURE_VIDEO_IN_IMAGE_MODE;
35 if (hasBasicZoom) configuredFlags |= CAMERA_CAP_FLAGS_HAS_BASIC_ZOOM;
36 if (hasTrackingPoint) configuredFlags |= CAMERA_CAP_FLAGS_HAS_TRACKING_POINT;
37 if (hasTrackingRectangle) configuredFlags |= CAMERA_CAP_FLAGS_HAS_TRACKING_RECTANGLE;
40 _cameras[0].compId = MAV_COMP_ID_CAMERA;
41 _cameras[0].capFlags = configuredFlags;
42 _cameras[0].cameraMode = CAMERA_MODE_IMAGE;
43 if ((configuredFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM) && (configuredFlags & CAMERA_CAP_FLAGS_HAS_MODES)) {
44 _cameras[0].cameraMode = CAMERA_MODE_VIDEO;
48 _cameras[1].compId = MAV_COMP_ID_CAMERA2;
49 _cameras[1].capFlags = CAMERA_CAP_FLAGS_CAPTURE_IMAGE;
50 _cameras[1].cameraMode = CAMERA_MODE_IMAGE;
55 for (uint8_t i = 0; i < kNumCameras; i++) {
56 if (_cameras[i].compId == compId) {
63const char *MockLinkCamera::_imageCaptureStatusToString(uint8_t status)
70 default:
return "Unknown";
76 for (uint8_t i = 0; i < kNumCameras; i++) {
78 (void) mavlink_msg_heartbeat_pack_chan(
84 MAV_AUTOPILOT_INVALID,
96 QMutexLocker locker(&_camerasMutex);
97 const qint64 now = QDateTime::currentMSecsSinceEpoch();
99 for (uint8_t i = 0; i < kNumCameras; i++) {
108 qCDebug(MockLinkCameraLog) <<
"Camera" << cam->
compId <<
"single-shot complete, total:" << cam->
imagesCaptured;
109 _sendCameraImageCaptured(cam->
compId);
114 const qint64 intervalMs =
static_cast<qint64
>(cam->
image_interval * 1000.0f);
119 qCDebug(MockLinkCameraLog) <<
"Camera" << cam->
compId <<
"interval capture, total:" << cam->
imagesCaptured;
120 _sendCameraImageCaptured(cam->
compId);
125 qCDebug(MockLinkCameraLog) <<
"Camera" << cam->
compId <<
"interval capture complete";
137 const double elapsed =
static_cast<double>(now - cam->
trackingStartMs) / 1000.0;
138 const float driftX = 0.05f *
static_cast<float>(qSin(elapsed * 0.7));
139 const float driftY = 0.05f *
static_cast<float>(qSin(elapsed * 1.1));
147 const float cx = std::clamp(cam->
trackAnchorX + driftX, halfW, 1.0f - halfW);
148 const float cy = std::clamp(cam->
trackAnchorY + driftY, halfH, 1.0f - halfH);
155 _sendCameraTrackingImageStatus(cam->
compId);
164 if (msg.msgid != MAVLINK_MSG_ID_COMMAND_LONG) {
169 mavlink_msg_command_long_decode(&msg, &request);
172 if (request.target_component < MAV_COMP_ID_CAMERA || request.target_component > MAV_COMP_ID_CAMERA6) {
176 const uint8_t targetCompId = request.target_component;
178 if (request.command == MAV_CMD_REQUEST_MESSAGE) {
179 return _handleRequestMessage(request, targetCompId);
182 return _handleCameraCommand(request, targetCompId);
190 QMutexLocker locker(&_camerasMutex);
191 CameraState *cam = _findCamera(targetCompId);
196 switch (request.command) {
197 case MAV_CMD_REQUEST_CAMERA_INFORMATION:
198 _sendCameraInformation(targetCompId);
199 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
202 case MAV_CMD_REQUEST_CAMERA_SETTINGS:
203 _sendCameraSettings(targetCompId);
204 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
207 case MAV_CMD_REQUEST_STORAGE_INFORMATION:
208 _sendStorageInformation(targetCompId);
209 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
212 case MAV_CMD_REQUEST_CAMERA_CAPTURE_STATUS:
213 _sendCameraCaptureStatus(targetCompId);
214 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
217 case MAV_CMD_REQUEST_VIDEO_STREAM_INFORMATION:
218 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM) {
219 const uint8_t streamId =
static_cast<uint8_t
>(request.param1);
222 for (uint8_t s = 1; s <= kNumStreams; s++) {
223 _sendVideoStreamInformation(targetCompId, s);
226 _sendVideoStreamInformation(targetCompId, streamId);
228 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
230 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
234 case MAV_CMD_REQUEST_VIDEO_STREAM_STATUS:
235 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM) {
236 const uint8_t streamId =
static_cast<uint8_t
>(request.param1);
238 for (uint8_t s = 1; s <= kNumStreams; s++) {
239 _sendVideoStreamStatus(targetCompId, s);
242 _sendVideoStreamStatus(targetCompId, streamId);
244 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
246 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
250 case MAV_CMD_SET_CAMERA_MODE:
251 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_MODES) {
252 const uint8_t requestedMode =
static_cast<uint8_t
>(request.param2);
254 if ((requestedMode != CAMERA_MODE_IMAGE) && (requestedMode != CAMERA_MODE_VIDEO)) {
255 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
259 const bool supportsImageMode =
260 (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_IMAGE) ||
261 (cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM);
262 const bool supportsVideoMode =
263 (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_VIDEO) ||
264 (cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM);
266 if ((requestedMode == CAMERA_MODE_IMAGE && !supportsImageMode) ||
267 (requestedMode == CAMERA_MODE_VIDEO && !supportsVideoMode)) {
268 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
272 cam->cameraMode = requestedMode;
273 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"mode set to" << cam->cameraMode;
274 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
276 _sendCameraSettings(targetCompId);
278 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
282 case MAV_CMD_IMAGE_START_CAPTURE:
283 if (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_IMAGE) {
284 if ((cam->capFlags & CAMERA_CAP_FLAGS_HAS_MODES) &&
285 (cam->cameraMode == CAMERA_MODE_VIDEO) &&
286 !(cam->capFlags & CAMERA_CAP_FLAGS_CAN_CAPTURE_IMAGE_IN_VIDEO_MODE)) {
287 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
291 const float interval = request.param2;
292 const int count =
static_cast<int>(request.param3);
297 cam->image_interval = interval;
298 cam->intervalRemaining = count;
299 cam->intervalLastCaptureMs = 0;
300 cam->singleShotStartMs = 0;
304 cam->image_interval = 0.0f;
305 cam->singleShotStartMs = QDateTime::currentMSecsSinceEpoch();
308 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"image capture started"
309 <<
"interval:" << interval <<
"count:" << count;
310 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
312 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
316 case MAV_CMD_IMAGE_STOP_CAPTURE:
317 if (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_IMAGE) {
319 cam->image_interval = 0.0f;
320 cam->intervalRemaining = 0;
321 cam->singleShotStartMs = 0;
322 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"image capture stopped";
323 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
325 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
329 case MAV_CMD_VIDEO_START_CAPTURE:
330 if (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_VIDEO) {
331 if ((cam->capFlags & CAMERA_CAP_FLAGS_HAS_MODES) &&
332 (cam->cameraMode == CAMERA_MODE_IMAGE) &&
333 !(cam->capFlags & CAMERA_CAP_FLAGS_CAN_CAPTURE_VIDEO_IN_IMAGE_MODE)) {
334 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
338 cam->recording =
true;
339 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"video recording started";
340 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
342 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
346 case MAV_CMD_VIDEO_STOP_CAPTURE:
347 if (cam->capFlags & CAMERA_CAP_FLAGS_CAPTURE_VIDEO) {
348 cam->recording =
false;
349 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"video recording stopped";
350 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
352 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
356 case MAV_CMD_STORAGE_FORMAT:
357 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"storage formatted";
358 cam->imagesCaptured = 0;
360 cam->image_interval = 0.0f;
361 cam->intervalRemaining = 0;
362 cam->singleShotStartMs = 0;
363 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
364 _sendStorageInformation(targetCompId);
367 case MAV_CMD_SET_CAMERA_ZOOM:
368 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_BASIC_ZOOM) {
371 switch (
static_cast<int>(request.param1)) {
372 case ZOOM_TYPE_RANGE:
373 cam->zoomLevel = request.param2;
374 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"zoom set to" << cam->zoomLevel;
377 cam->zoomLevel = std::clamp(cam->zoomLevel + (request.param2 * kZoomStepPercent), kZoomMinPercent, kZoomMaxPercent);
378 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"zoom stepped to" << cam->zoomLevel;
385 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
387 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
391 case MAV_CMD_SET_CAMERA_FOCUS:
392 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
395 case MAV_CMD_RESET_CAMERA_SETTINGS:
396 cam->cameraMode = CAMERA_MODE_IMAGE;
397 cam->zoomLevel = 1.0f;
398 cam->focusLevel = 0.0f;
400 cam->image_interval = 0.0f;
401 cam->intervalRemaining = 0;
402 cam->singleShotStartMs = 0;
403 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"settings reset";
404 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
405 _sendCameraSettings(targetCompId);
408 case MAV_CMD_CAMERA_TRACK_POINT:
409 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_TRACKING_POINT) {
410 cam->trackingMode = CAMERA_TRACKING_MODE_POINT;
411 cam->trackPointX = request.param1;
412 cam->trackPointY = request.param2;
413 cam->trackRadius = request.param3;
414 cam->trackAnchorX = request.param1;
415 cam->trackAnchorY = request.param2;
416 cam->trackingStartMs = QDateTime::currentMSecsSinceEpoch();
417 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"tracking point"
418 << cam->trackPointX << cam->trackPointY <<
"radius" << cam->trackRadius;
419 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
421 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
425 case MAV_CMD_CAMERA_TRACK_RECTANGLE:
426 if (cam->capFlags & CAMERA_CAP_FLAGS_HAS_TRACKING_RECTANGLE) {
427 cam->trackingMode = CAMERA_TRACKING_MODE_RECTANGLE;
428 cam->trackRecTopX = request.param1;
429 cam->trackRecTopY = request.param2;
430 cam->trackRecBottomX = request.param3;
431 cam->trackRecBottomY = request.param4;
432 cam->trackAnchorX = (request.param1 + request.param3) / 2.0f;
433 cam->trackAnchorY = (request.param2 + request.param4) / 2.0f;
434 cam->trackingStartMs = QDateTime::currentMSecsSinceEpoch();
435 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"tracking rectangle"
436 << cam->trackRecTopX << cam->trackRecTopY
437 <<
"->" << cam->trackRecBottomX << cam->trackRecBottomY;
438 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
440 _sendCommandAck(targetCompId, request.command, MAV_RESULT_DENIED);
444 case MAV_CMD_CAMERA_STOP_TRACKING:
445 cam->trackingMode = CAMERA_TRACKING_MODE_NONE;
446 cam->trackingStatusIntervalUs = -1;
447 cam->trackingStatusLastSentMs = 0;
448 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId <<
"tracking stopped";
449 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
452 case MAV_CMD_SET_MESSAGE_INTERVAL:
454 const int msgId =
static_cast<int>(request.param1);
455 if (msgId == MAVLINK_MSG_ID_CAMERA_TRACKING_IMAGE_STATUS) {
456 cam->trackingStatusIntervalUs =
static_cast<qint64
>(request.param2);
457 cam->trackingStatusLastSentMs = 0;
458 qCDebug(MockLinkCameraLog) <<
"Camera" << targetCompId
459 <<
"tracking status interval" << cam->trackingStatusIntervalUs <<
"us";
460 _sendCommandAck(targetCompId, request.command, MAV_RESULT_ACCEPTED);
463 _sendCommandAck(targetCompId, request.command, MAV_RESULT_UNSUPPORTED);
476 const CameraState *cam = _findCamera(targetCompId);
481 const int msgId =
static_cast<int>(request.param1);
484 case MAVLINK_MSG_ID_CAMERA_INFORMATION:
485 _sendCameraInformation(targetCompId);
486 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
489 case MAVLINK_MSG_ID_CAMERA_SETTINGS:
490 _sendCameraSettings(targetCompId);
491 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
494 case MAVLINK_MSG_ID_STORAGE_INFORMATION:
495 _sendStorageInformation(targetCompId);
496 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
499 case MAVLINK_MSG_ID_CAMERA_CAPTURE_STATUS:
500 _sendCameraCaptureStatus(targetCompId);
501 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
504 case MAVLINK_MSG_ID_VIDEO_STREAM_INFORMATION:
506 if (!(cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM)) {
507 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_DENIED, msgId);
510 const uint8_t streamId =
static_cast<uint8_t
>(request.param2);
512 for (uint8_t s = 1; s <= kNumStreams; s++) {
513 _sendVideoStreamInformation(targetCompId, s);
516 _sendVideoStreamInformation(targetCompId, streamId);
518 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
522 case MAVLINK_MSG_ID_VIDEO_STREAM_STATUS:
524 if (!(cam->capFlags & CAMERA_CAP_FLAGS_HAS_VIDEO_STREAM)) {
525 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_DENIED, msgId);
528 const uint8_t streamId =
static_cast<uint8_t
>(request.param2);
530 for (uint8_t s = 1; s <= kNumStreams; s++) {
531 _sendVideoStreamStatus(targetCompId, s);
534 _sendVideoStreamStatus(targetCompId, streamId);
536 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_ACCEPTED, msgId);
544 _sendCommandAck(targetCompId, MAV_CMD_REQUEST_MESSAGE, MAV_RESULT_DENIED, msgId);
549void MockLinkCamera::_sendCameraInformation(uint8_t compId)
551 const CameraState *cam = _findCamera(compId);
556 const int cameraIndex = compId - MAV_COMP_ID_CAMERA;
558 const uint8_t vendorName[32] =
"MockLink";
559 const char cameraDefinitionUri[MAVLINK_MSG_CAMERA_INFORMATION_FIELD_CAM_DEFINITION_URI_LEN] = {};
560 const QString model = QStringLiteral(
"MockCam %1").arg(cameraIndex + 1);
561 QByteArray modelBA = model.toLocal8Bit();
562 modelBA.resize(MAVLINK_MSG_CAMERA_INFORMATION_FIELD_MODEL_NAME_LEN);
565 (void) mavlink_msg_camera_information_pack_chan(
572 reinterpret_cast<const uint8_t *
>(modelBA.constData()),
587 qCDebug(MockLinkCameraLog) <<
"Sent CAMERA_INFORMATION for compId:" << compId <<
"model:" << model;
590void MockLinkCamera::_sendCameraSettings(uint8_t compId)
592 const CameraState *cam = _findCamera(compId);
598 (void) mavlink_msg_camera_settings_pack_chan(
610 qCDebug(MockLinkCameraLog) <<
"Sent CAMERA_SETTINGS for compId:" << compId
611 <<
"mode:" << cam->cameraMode
612 <<
"zoom:" << cam->zoomLevel
613 <<
"focus:" << cam->focusLevel;
616void MockLinkCamera::_sendStorageInformation(uint8_t compId)
618 const char storageName[MAVLINK_MSG_STORAGE_INFORMATION_FIELD_NAME_LEN] = {};
621 (void) mavlink_msg_storage_information_pack_chan(
629 STORAGE_STATUS_READY,
630 static_cast<float>(kStorageTotalMiB),
631 static_cast<float>(kStorageTotalMiB - kStorageFreeMiB),
632 static_cast<float>(kStorageFreeMiB),
640 qCDebug(MockLinkCameraLog) <<
"Sent STORAGE_INFORMATION for compId:" << compId;
643void MockLinkCamera::_sendCameraCaptureStatus(uint8_t compId)
645 const CameraState *cam = _findCamera(compId);
651 (void) mavlink_msg_camera_capture_status_pack_chan(
658 cam->recording ? 1 : 0,
661 static_cast<float>(kStorageFreeMiB),
666 qCDebug(MockLinkCameraLog) <<
"Sent CAMERA_CAPTURE_STATUS for compId:" << compId
667 <<
"status:" << _imageCaptureStatusToString(cam->image_status)
668 <<
"interval:" << cam->image_interval
669 <<
"recording:" << cam->recording
670 <<
"images:" << cam->imagesCaptured;
673void MockLinkCamera::_sendCameraImageCaptured(uint8_t compId)
675 const CameraState *cam = _findCamera(compId);
682 const int32_t lat =
static_cast<int32_t
>(_mockLink->
vehicleLatitude() * 1e7);
683 const int32_t lon =
static_cast<int32_t
>(_mockLink->
vehicleLongitude() * 1e7);
685 const float q[4] = {1.0f, 0.0f, 0.0f, 0.0f};
686 const char fileUrl[MAVLINK_MSG_CAMERA_IMAGE_CAPTURED_FIELD_FILE_URL_LEN] = {};
689 (void) mavlink_msg_camera_image_captured_pack_chan(
696 (compId - MAV_COMP_ID_CAMERA) + 1,
707 qCDebug(MockLinkCameraLog) <<
"Sent CAMERA_IMAGE_CAPTURED for compId:" << compId
708 <<
"index:" << cam->imagesCaptured;
711void MockLinkCamera::_sendVideoStreamInformation(uint8_t compId, uint8_t streamId)
713 const int cameraIndex = compId - MAV_COMP_ID_CAMERA;
714 const QString name = QStringLiteral(
"Stream %1-%2").arg(cameraIndex + 1).arg(streamId);
715 QByteArray nameBA = name.toLocal8Bit();
716 nameBA.resize(MAVLINK_MSG_VIDEO_STREAM_INFORMATION_FIELD_NAME_LEN);
721 uint8_t streamType = VIDEO_STREAM_TYPE_RTPUDP;
722 uint8_t encoding = VIDEO_STREAM_ENCODING_H264;
723 QString uri = QStringLiteral(
"udp://127.0.0.1:5600");
724 uint16_t flags = VIDEO_STREAM_STATUS_FLAGS_RUNNING;
729 switch (servedType) {
731 streamType = VIDEO_STREAM_TYPE_RTPUDP;
732 encoding = VIDEO_STREAM_ENCODING_H264;
736 streamType = VIDEO_STREAM_TYPE_RTPUDP;
737 encoding = VIDEO_STREAM_ENCODING_H265;
741 streamType = VIDEO_STREAM_TYPE_RTSP;
742 encoding = VIDEO_STREAM_ENCODING_H264;
746 streamType = VIDEO_STREAM_TYPE_MPEG_TS;
747 encoding = VIDEO_STREAM_ENCODING_H264;
751 streamType = VIDEO_STREAM_TYPE_TCP_MPEG;
752 encoding = VIDEO_STREAM_ENCODING_H264;
756#ifdef QGC_GST_STREAMING
769 QByteArray uriBA = uri.toLocal8Bit();
770 uriBA.resize(MAVLINK_MSG_VIDEO_STREAM_INFORMATION_FIELD_URI_LEN);
773 (void) mavlink_msg_video_stream_information_pack_chan(
794 qCDebug(MockLinkCameraLog) <<
"Sent VIDEO_STREAM_INFORMATION for compId:" << compId <<
"stream:" << streamId
795 <<
"type:" << streamType <<
"uri:" << uri;
798void MockLinkCamera::_sendVideoStreamStatus(uint8_t compId, uint8_t streamId)
803 uint16_t flags = VIDEO_STREAM_STATUS_FLAGS_RUNNING;
804#ifdef QGC_GST_STREAMING
815 (void) mavlink_msg_video_stream_status_pack_chan(
831 qCDebug(MockLinkCameraLog) <<
"Sent VIDEO_STREAM_STATUS for compId:" << compId <<
"stream:" << streamId;
834void MockLinkCamera::_sendCameraTrackingImageStatus(uint8_t compId)
836 const CameraState *cam = _findCamera(compId);
837 if (!cam || cam->trackingMode == CAMERA_TRACKING_MODE_NONE) {
842 (void) mavlink_msg_camera_tracking_image_status_pack_chan(
847 CAMERA_TRACKING_STATUS_FLAGS_ACTIVE,
849 CAMERA_TRACKING_TARGET_DATA_EMBEDDED,
855 cam->trackRecBottomX,
856 cam->trackRecBottomY,
861void MockLinkCamera::_sendCommandAck(uint8_t compId, uint16_t command, uint8_t result,
int requestedMsgId)
864 (void) mavlink_msg_command_ack_pack_chan(
878 QString logMsg = QStringLiteral(
"Sent COMMAND_ACK for compId: %1 command: %2 result: %3")
879 .arg(compId).arg(commandName).arg(result);
881 if (command == MAV_CMD_REQUEST_MESSAGE && requestedMsgId >= 0) {
882 const mavlink_message_info_t* info = mavlink_get_message_info_by_id(
static_cast<uint32_t
>(requestedMsgId));
883 QString msgName = info ? info->name : QString::number(requestedMsgId);
884 logMsg += QStringLiteral(
" requestedMsg: %1").arg(msgName);
887 qCDebug(MockLinkCameraLog) << logMsg;
struct __mavlink_message mavlink_message_t
#define QGC_LOGGING_CATEGORY(name, categoryStr)
struct __mavlink_command_long_t mavlink_command_long_t
static MissionCommandTree * instance()
QString rawName(MAV_CMD command) const
Returns the raw name for the specified command.
@ VideoStreamRtpUdpH265
RTP/UDP H.265 -> udp265://.
@ VideoStreamNone
No stream served.
@ VideoStreamRtpUdpH264
RTP/UDP H.264 -> udp://.
@ VideoStreamRtspH264
RTSP H.264 -> rtsp://.
@ VideoStreamMpegTsTcp
MPEG-TS over TCP -> tcp://.
@ VideoStreamMpegTsUdp
MPEG-TS over UDP -> mpegts://.
Simulates MAVLink Camera Protocol v2 components for MockLink.
void sendCameraHeartbeats()
Send heartbeats for all simulated camera components (call from 1Hz tasks)
bool handleMavlinkMessage(const mavlink_message_t &msg)
void run10HzTasks()
Update camera states (call from 10Hz tasks)
@ ImageCaptureInProgress
Single image capture in progress.
@ ImageCaptureInterval
Interval capture enabled.
@ ImageCaptureIntervalCapture
Interval capture with capture in progress.
@ ImageCaptureIdle
No capture in progress.
void servedVideoStream(MockConfiguration::VideoStreamType &type, QString &uri) const
double vehicleAltitudeAMSL() const
uint8_t outgoingMavlinkChannel() const
Vehicle-side channel used to encode outgoing (mock vehicle -> QGC) messages. Signing state lives here...
void respondWithMavlinkMessage(const mavlink_message_t &msg)
Sends the specified mavlink message to QGC.
double vehicleLatitude() const
MockConfiguration::VideoStreamType requestedVideoStreamType() const
Video stream type the configuration requested (immutable after construction).
double vehicleLongitude() const
GPSCommandSequence::Command command(QByteArrayView body, GPSTextMatcher reply, std::chrono::milliseconds timeout)
body labelled by its text, framed as a sentence, and completed by reply within timeout.
Per-camera simulated state.
int intervalRemaining
Images left in interval capture (0 = unlimited)
qint64 trackingStatusLastSentMs
Timestamp of last tracking status message.
float trackAnchorX
Original center X of tracked target.
qint64 intervalLastCaptureMs
Timestamp of last interval capture.
float image_interval
Interval between image captures (seconds)
qint64 singleShotStartMs
Timestamp when single-shot capture started (0 = not active)
qint64 trackingStatusIntervalUs
Interval for CAMERA_TRACKING_IMAGE_STATUS (-1 = disabled)
qint64 trackingStartMs
Timestamp when tracking was started (for drift animation)
uint8_t trackingMode
CAMERA_TRACKING_MODE enum.
float trackAnchorY
Original center Y of tracked target.
uint8_t image_status
ImageCaptureStatus enum.