blob: bd494213b109abed56b43012925db1a367a63531 [file] [log] [blame]
fei.dengf7a0cd32023-08-29 09:36:37 +00001/*
2 * Copyright (C) 2021 Amlogic Corporation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <stdlib.h>
17#include <stdio.h>
18#include <stddef.h>
19#include <sys/time.h>
20#include <stdarg.h>
21#include <sys/file.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <fcntl.h>
25#include <unistd.h>
26#include <limits.h>
27#include <time.h>
28#include <errno.h>
fei.dengf7a0cd32023-08-29 09:36:37 +000029#include "wstclient_socket.h"
30#include "wstclient_plugin.h"
31#include "Logger.h"
fei.dengb9a1a572023-09-13 01:33:57 +000032#include "Utils.h"
fei.dengf7a0cd32023-08-29 09:36:37 +000033
34#define TAG "rlib:wstclient_socket"
35
fei.dengb9a1a572023-09-13 01:33:57 +000036WstClientSocket::WstClientSocket(WstClientPlugin *plugin, int logCategory)
fei.dengf7a0cd32023-08-29 09:36:37 +000037{
fei.dengb9a1a572023-09-13 01:33:57 +000038 mLogCategory = logCategory;
fei.dengf7a0cd32023-08-29 09:36:37 +000039 mPlugin = plugin;
fei.dengb9a1a572023-09-13 01:33:57 +000040 mPoll = new Tls::Poll(true);
fei.dengf7a0cd32023-08-29 09:36:37 +000041}
42
43WstClientSocket::~WstClientSocket()
44{
fei.dengb9a1a572023-09-13 01:33:57 +000045 if (mPoll) {
46 delete mPoll;
47 mPoll = NULL;
48 }
fei.dengf7a0cd32023-08-29 09:36:37 +000049}
50
51bool WstClientSocket::connectToSocket(const char *name)
52{
53 int rc;
54 bool error= true;
55 const char *workingDir;
56 int pathNameLen, addressSize;
57
58 mSocketFd = -1;
59 mName = name;
60
61 workingDir = getenv("XDG_RUNTIME_DIR");
62 if ( !workingDir )
63 {
64 workingDir = "/run";
fei.dengb9a1a572023-09-13 01:33:57 +000065 ERROR(mLogCategory,"wstCreateVideoClientConnection: XDG_RUNTIME_DIR is not set,set default %s",workingDir);
fei.dengf7a0cd32023-08-29 09:36:37 +000066 }
67
fei.dengb9a1a572023-09-13 01:33:57 +000068 INFO(mLogCategory,"XDG_RUNTIME_DIR=%s",workingDir);
fei.dengf7a0cd32023-08-29 09:36:37 +000069
70 pathNameLen = strlen(workingDir)+strlen("/")+strlen(mName) + 1;
71 if ( pathNameLen > (int)sizeof(mAddr.sun_path) )
72 {
fei.dengb9a1a572023-09-13 01:33:57 +000073 ERROR(mLogCategory,"wstCreateVideoClientConnection: name for server unix domain socket is too long: %d versus max %d",
74 pathNameLen, (int)sizeof(mAddr.sun_path) );
fei.dengf7a0cd32023-08-29 09:36:37 +000075 goto exit;
76 }
77
78 mAddr.sun_family = AF_LOCAL;
79 strcpy( mAddr.sun_path, workingDir );
80 strcat( mAddr.sun_path, "/" );
81 strcat( mAddr.sun_path, mName );
82
83 mSocketFd = socket( PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0 );
84 if ( mSocketFd < 0 )
85 {
fei.dengb9a1a572023-09-13 01:33:57 +000086 ERROR(mLogCategory,"wstCreateVideoClientConnection: unable to open socket: errno %d", errno );
fei.dengf7a0cd32023-08-29 09:36:37 +000087 goto exit;
88 }
89
90 addressSize = pathNameLen + offsetof(struct sockaddr_un, sun_path);
91
92 rc = connect(mSocketFd, (struct sockaddr *)&mAddr, addressSize );
93 if ( rc < 0 )
94 {
fei.dengb9a1a572023-09-13 01:33:57 +000095 ERROR(mLogCategory,"wstCreateVideoClientConnection: connect failed for socket: errno %d,path:%s", errno,mAddr.sun_path );
fei.dengf7a0cd32023-08-29 09:36:37 +000096 goto exit;
97 }
98
fei.dengb9a1a572023-09-13 01:33:57 +000099 INFO(mLogCategory,"wstclient socket connected,path:%s",mAddr.sun_path);
fei.dengf7a0cd32023-08-29 09:36:37 +0000100
101 run("wstclientsocket");
102 return true;
103
104exit:
105
106 mAddr.sun_path[0] = '\0';
107 if ( mSocketFd >= 0 )
108 {
109 close( mSocketFd );
110 mSocketFd = -1;
111 }
112 return false;
113}
114
115bool WstClientSocket::disconnectFromSocket()
116{
117 if (isRunning()) {
fei.dengb9a1a572023-09-13 01:33:57 +0000118 INFO(mLogCategory,"try stop socket thread");
119 if (mPoll) {
120 mPoll->setFlushing(true);
121 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000122 requestExitAndWait();
123 }
124
125 if ( mSocketFd >= 0 )
126 {
127 mAddr.sun_path[0]= '\0';
fei.dengb9a1a572023-09-13 01:33:57 +0000128 INFO(mLogCategory,"close socket");
fei.dengf7a0cd32023-08-29 09:36:37 +0000129 close( mSocketFd );
130 mSocketFd = -1;
131 }
132 return true;
133}
134
135void WstClientSocket::sendLayerVideoClientConnection(bool pip)
136{
137 struct msghdr msg;
138 struct iovec iov[1];
139 unsigned char mbody[5];
140 int len;
141 int sentLen;
142
143 msg.msg_name= NULL;
144 msg.msg_namelen= 0;
145 msg.msg_iov= iov;
146 msg.msg_iovlen= 1;
147 msg.msg_control= 0;
148 msg.msg_controllen= 0;
149 msg.msg_flags= 0;
150
151 len= 0;
152 mbody[len++]= 'V';
153 mbody[len++]= 'S';
154 mbody[len++]= 2;
155 mbody[len++]= 'N';
156 mbody[len++]= (pip? 1 : 0);
157
158 iov[0].iov_base= (char*)mbody;
159 iov[0].iov_len= len;
160
161 do
162 {
163 sentLen= sendmsg(mSocketFd, &msg, MSG_NOSIGNAL );
164 }
165 while ( (sentLen < 0) && (errno == EINTR));
166
167 if ( sentLen == len )
168 {
fei.dengb9a1a572023-09-13 01:33:57 +0000169 INFO(mLogCategory,"sent pip %d to video server", pip);
fei.dengf7a0cd32023-08-29 09:36:37 +0000170 }
171}
172
173void WstClientSocket::sendResourceVideoClientConnection(bool pip)
174{
175 struct msghdr msg;
176 struct iovec iov[1];
177 unsigned char mbody[8];
178 int len;
179 int sentLen;
180 int resourceId= (pip? 1 : 0);
181
182 msg.msg_name= NULL;
183 msg.msg_namelen= 0;
184 msg.msg_iov= iov;
185 msg.msg_iovlen= 1;
186 msg.msg_control= 0;
187 msg.msg_controllen= 0;
188 msg.msg_flags= 0;
189
190 len= 0;
191 mbody[len++]= 'V';
192 mbody[len++]= 'S';
193 mbody[len++]= 5;
194 mbody[len++]= 'V';
195 len += putU32( &mbody[len], resourceId );
196
197 iov[0].iov_base= (char*)mbody;
198 iov[0].iov_len= len;
199
200 do
201 {
202 sentLen= sendmsg(mSocketFd, &msg, MSG_NOSIGNAL );
203 }
204 while ( (sentLen < 0) && (errno == EINTR));
205
206 if ( sentLen == len )
207 {
fei.dengb9a1a572023-09-13 01:33:57 +0000208 INFO(mLogCategory,"sent resource id %d (0:primary,1:pip) to video server", resourceId);
fei.dengf7a0cd32023-08-29 09:36:37 +0000209 }
210}
211
212void WstClientSocket::sendFlushVideoClientConnection()
213{
214 struct msghdr msg;
215 struct iovec iov[1];
216 unsigned char mbody[4];
217 int len;
218 int sentLen;
219
220 msg.msg_name = NULL;
221 msg.msg_namelen = 0;
222 msg.msg_iov = iov;
223 msg.msg_iovlen = 1;
224 msg.msg_control = 0;
225 msg.msg_controllen = 0;
226 msg.msg_flags = 0;
227
228 len = 0;
229 mbody[len++] = 'V';
230 mbody[len++] = 'S';
231 mbody[len++] = 1;
232 mbody[len++] = 'S';
233
234 iov[0].iov_base = (char*)mbody;
235 iov[0].iov_len = len;
236
237 do
238 {
239 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
240 }
241 while ( (sentLen < 0) && (errno == EINTR));
242
243 if ( sentLen == len )
244 {
fei.dengb9a1a572023-09-13 01:33:57 +0000245 INFO(mLogCategory,"sent flush to video server");
fei.dengf7a0cd32023-08-29 09:36:37 +0000246 }
247}
248
249void WstClientSocket::sendPauseVideoClientConnection(bool pause)
250{
251 struct msghdr msg;
252 struct iovec iov[1];
253 unsigned char mbody[7];
254 int len;
255 int sentLen;
256
257 msg.msg_name = NULL;
258 msg.msg_namelen = 0;
259 msg.msg_iov = iov;
260 msg.msg_iovlen = 1;
261 msg.msg_control = 0;
262 msg.msg_controllen = 0;
263 msg.msg_flags = 0;
264
265 len= 0;
266 mbody[len++] = 'V';
267 mbody[len++] = 'S';
268 mbody[len++] = 2;
269 mbody[len++] = 'P';
270 mbody[len++] = (pause ? 1 : 0);
271
272 iov[0].iov_base = (char*)mbody;
273 iov[0].iov_len = len;
274
275 do
276 {
277 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
278 }
279 while ( (sentLen < 0) && (errno == EINTR));
280
281 if ( sentLen == len )
282 {
fei.dengb9a1a572023-09-13 01:33:57 +0000283 INFO(mLogCategory,"sent pause %d to video server", pause);
fei.dengf7a0cd32023-08-29 09:36:37 +0000284 }
285}
286
287void WstClientSocket::sendHideVideoClientConnection(bool hide)
288{
289 struct msghdr msg;
290 struct iovec iov[1];
291 unsigned char mbody[7];
292 int len;
293 int sentLen;
294
295 msg.msg_name = NULL;
296 msg.msg_namelen = 0;
297 msg.msg_iov = iov;
298 msg.msg_iovlen = 1;
299 msg.msg_control = 0;
300 msg.msg_controllen = 0;
301 msg.msg_flags = 0;
302
303 len= 0;
304 mbody[len++] = 'V';
305 mbody[len++] = 'S';
306 mbody[len++] = 2;
307 mbody[len++] = 'H';
308 mbody[len++] = (hide ? 1 : 0);
309
310 iov[0].iov_base = (char*)mbody;
311 iov[0].iov_len = len;
312
313 do
314 {
315 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
316 }
317 while ( (sentLen < 0) && (errno == EINTR));
318
319 if ( sentLen == len )
320 {
fei.dengb9a1a572023-09-13 01:33:57 +0000321 INFO(mLogCategory,"sent hide %d to video server", hide);
fei.dengf7a0cd32023-08-29 09:36:37 +0000322 }
323}
324
325void WstClientSocket::sendSessionInfoVideoClientConnection(int sessionId, int syncType )
326{
327 struct msghdr msg;
328 struct iovec iov[1];
329 unsigned char mbody[9];
330 int len;
331 int sentLen;
332
333 msg.msg_name = NULL;
334 msg.msg_namelen = 0;
335 msg.msg_iov = iov;
336 msg.msg_iovlen = 1;
337 msg.msg_control = 0;
338 msg.msg_controllen = 0;
339 msg.msg_flags = 0;
340
341 len= 0;
342 mbody[len++] = 'V';
343 mbody[len++] = 'S';
344 mbody[len++] = 6;
345 mbody[len++] = 'I';
346 mbody[len++] = syncType;
347 len += putU32( &mbody[len], sessionId );
348
349 iov[0].iov_base = (char*)mbody;
350 iov[0].iov_len = len;
351
352 do
353 {
354 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
355 }
356 while ( (sentLen < 0) && (errno == EINTR));
357
358 if ( sentLen == len )
359 {
fei.dengb9a1a572023-09-13 01:33:57 +0000360 INFO(mLogCategory,"sent session info: synctype %d sessionId %d to video server", syncType, sessionId);
fei.dengf7a0cd32023-08-29 09:36:37 +0000361 }
362}
363
364void WstClientSocket::sendFrameAdvanceVideoClientConnection()
365{
366 struct msghdr msg;
367 struct iovec iov[1];
368 unsigned char mbody[4];
369 int len;
370 int sentLen;
371
372 msg.msg_name = NULL;
373 msg.msg_namelen = 0;
374 msg.msg_iov = iov;
375 msg.msg_iovlen = 1;
376 msg.msg_control = 0;
377 msg.msg_controllen = 0;
378 msg.msg_flags = 0;
379
380 len= 0;
381 mbody[len++] = 'V';
382 mbody[len++] = 'S';
383 mbody[len++] = 1;
384 mbody[len++] = 'A';
385
386 iov[0].iov_base = (char*)mbody;
387 iov[0].iov_len = len;
388
389 do
390 {
391 sentLen= sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
392 }
393 while ( (sentLen < 0) && (errno == EINTR));
394
395 if ( sentLen == len )
396 {
fei.dengb9a1a572023-09-13 01:33:57 +0000397 INFO(mLogCategory,"sent frame adavnce to video server");
fei.dengf7a0cd32023-08-29 09:36:37 +0000398 }
399}
400
401void WstClientSocket::sendRectVideoClientConnection(int videoX, int videoY, int videoWidth, int videoHeight )
402{
403 struct msghdr msg;
404 struct iovec iov[1];
405 unsigned char mbody[20];
406 int len;
407 int sentLen;
408 int vx, vy, vw, vh;
409
410 vx = videoX;
411 vy = videoY;
412 vw = videoWidth;
413 vh = videoHeight;
414
415 msg.msg_name = NULL;
416 msg.msg_namelen = 0;
417 msg.msg_iov = iov;
418 msg.msg_iovlen = 1;
419 msg.msg_control = 0;
420 msg.msg_controllen = 0;
421 msg.msg_flags = 0;
422
423 len = 0;
424 mbody[len++] = 'V';
425 mbody[len++] = 'S';
426 mbody[len++] = 17;
427 mbody[len++] = 'W';
428 len += putU32( &mbody[len], vx );
429 len += putU32( &mbody[len], vy );
430 len += putU32( &mbody[len], vw );
431 len += putU32( &mbody[len], vh );
432
433 iov[0].iov_base = (char*)mbody;
434 iov[0].iov_len = len;
435
436 do
437 {
438 sentLen= sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
439 }
440 while ( (sentLen < 0) && (errno == EINTR));
441
442 if ( sentLen == len )
443 {
fei.dengb9a1a572023-09-13 01:33:57 +0000444 INFO(mLogCategory,"sent position to video server,vx:%d,vy:%d,vw:%d,vh:%d",videoX,videoY,videoWidth,videoHeight);
fei.dengf7a0cd32023-08-29 09:36:37 +0000445 }
446}
447
448void WstClientSocket::sendRateVideoClientConnection(int fpsNum, int fpsDenom )
449{
450 struct msghdr msg;
451 struct iovec iov[1];
452 unsigned char mbody[12];
453 int len;
454 int sentLen;
455
456 msg.msg_name = NULL;
457 msg.msg_namelen = 0;
458 msg.msg_iov = iov;
459 msg.msg_iovlen = 1;
460 msg.msg_control = 0;
461 msg.msg_controllen = 0;
462 msg.msg_flags = 0;
463
464 len = 0;
465 mbody[len++] = 'V';
466 mbody[len++] = 'S';
467 mbody[len++] = 9;
468 mbody[len++] = 'R';
469 len += putU32( &mbody[len], fpsNum );
470 len += putU32( &mbody[len], fpsDenom );
471
472 iov[0].iov_base = (char*)mbody;
473 iov[0].iov_len = len;
474
475 do
476 {
477 sentLen= sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
478 }
479 while ( (sentLen < 0) && (errno == EINTR));
480
481 if ( sentLen == len )
482 {
fei.dengb9a1a572023-09-13 01:33:57 +0000483 INFO(mLogCategory,"sent frame rate to video server: %d/%d", fpsNum, fpsDenom);
fei.dengf7a0cd32023-08-29 09:36:37 +0000484 }
485}
486
487bool WstClientSocket::sendFrameVideoClientConnection(WstBufferInfo *wstBufferInfo, WstRect *wstRect)
488{
489 bool result= false;
490 int sentLen;
491
492 struct msghdr msg;
493 struct cmsghdr *cmsg;
494 struct iovec iov[1];
495 unsigned char mbody[4+64];
496 char cmbody[CMSG_SPACE(3*sizeof(int))];
497 int i, len;
498 int *fd;
499 int numFdToSend;
500 int frameFd0 = -1, frameFd1 = -1, frameFd2 = -1;
501 int fdToSend0 = -1, fdToSend1 = -1, fdToSend2 = -1;
502 int offset0, offset1, offset2;
503 int stride0, stride1, stride2;
504 uint32_t pixelFormat;
505 int bufferId = -1;
506 int vx, vy, vw, vh;
507
508 if ( wstBufferInfo )
509 {
510 bufferId = wstBufferInfo->bufferId;
511
512 numFdToSend = 1;
513 offset0 = offset1 = offset2 = 0;
514 stride0 = stride1 = stride2 = wstBufferInfo->frameWidth;
515 if ( wstBufferInfo->planeCount > 1 )
516 {
517 frameFd0 = wstBufferInfo->planeInfo[0].fd;
518 stride0 = wstBufferInfo->planeInfo[0].stride;
519
520 frameFd1 = wstBufferInfo->planeInfo[1].fd;
521 stride1 = wstBufferInfo->planeInfo[1].stride;
522 if ( frameFd1 < 0 )
523 {
524 offset1 = wstBufferInfo->frameWidth*wstBufferInfo->frameHeight;
525 stride1 = stride0;
526 }
527
528 frameFd2 = wstBufferInfo->planeInfo[2].fd;
529 stride2 = wstBufferInfo->planeInfo[2].stride;
530 if ( frameFd2 < 0 )
531 {
532 offset2 = offset1 + (wstBufferInfo->frameWidth*wstBufferInfo->frameHeight)/2;
533 stride2 = stride0;
534 }
535 }
536 else
537 {
538 frameFd0 = wstBufferInfo->planeInfo[0].fd;
539 stride0 = wstBufferInfo->planeInfo[0].stride;
540 offset1 = stride0*wstBufferInfo->frameHeight;
541 stride1 = stride0;
542 offset2 = 0;
543 stride2 = 0;
544 }
545
546 //must change pixelformat to v4l2 support pixel format
547 pixelFormat = wstBufferInfo->pixelFormat;
548
549 fdToSend0 = fcntl( frameFd0, F_DUPFD_CLOEXEC, 0 );
550 if ( fdToSend0 < 0 )
551 {
fei.dengb9a1a572023-09-13 01:33:57 +0000552 ERROR(mLogCategory,"wstSendFrameVideoClientConnection: failed to dup fd0");
fei.dengf7a0cd32023-08-29 09:36:37 +0000553 goto exit;
554 }
555 if ( frameFd1 >= 0 )
556 {
557 fdToSend1 = fcntl( frameFd1, F_DUPFD_CLOEXEC, 0 );
558 if ( fdToSend1 < 0 )
559 {
fei.dengb9a1a572023-09-13 01:33:57 +0000560 ERROR(mLogCategory,"wstSendFrameVideoClientConnection: failed to dup fd1");
fei.dengf7a0cd32023-08-29 09:36:37 +0000561 goto exit;
562 }
563 ++numFdToSend;
564 }
565 if ( frameFd2 >= 0 )
566 {
567 fdToSend2 = fcntl( frameFd2, F_DUPFD_CLOEXEC, 0 );
568 if ( fdToSend2 < 0 )
569 {
fei.dengb9a1a572023-09-13 01:33:57 +0000570 ERROR(mLogCategory,"wstSendFrameVideoClientConnection: failed to dup fd2");
fei.dengf7a0cd32023-08-29 09:36:37 +0000571 goto exit;
572 }
573 ++numFdToSend;
574 }
575
576 vx = wstRect->x;
577 vy = wstRect->y;
578 vw = wstRect->w;
579 vh = wstRect->h;
580
fei.dengb9a1a572023-09-13 01:33:57 +0000581 TRACE(mLogCategory,"send frame:resolution(%dx%d),rect x:%d,y:%d,w:%d,h:%d", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000582 wstBufferInfo->frameWidth,wstBufferInfo->frameHeight, vx, vy, vw, vh);
583
584 i = 0;
585 mbody[i++] = 'V';
586 mbody[i++] = 'S';
587 mbody[i++] = 65;
588 mbody[i++] = 'F';
589 i += putU32( &mbody[i], wstBufferInfo->frameWidth );
590 i += putU32( &mbody[i], wstBufferInfo->frameHeight );
591 i += putU32( &mbody[i], pixelFormat );
592 i += putU32( &mbody[i], vx );
593 i += putU32( &mbody[i], vy );
594 i += putU32( &mbody[i], vw );
595 i += putU32( &mbody[i], vh );
596 i += putU32( &mbody[i], offset0 );
597 i += putU32( &mbody[i], stride0 );
598 i += putU32( &mbody[i], offset1 );
599 i += putU32( &mbody[i], stride1 );
600 i += putU32( &mbody[i], offset2 );
601 i += putU32( &mbody[i], stride2 );
602 i += putU32( &mbody[i], bufferId );
603 i += putS64( &mbody[i], wstBufferInfo->frameTime );
604
605 iov[0].iov_base = (char*)mbody;
606 iov[0].iov_len = i;
607
608 cmsg = (struct cmsghdr*)cmbody;
609 cmsg->cmsg_len = CMSG_LEN(numFdToSend*sizeof(int));
610 cmsg->cmsg_level = SOL_SOCKET;
611 cmsg->cmsg_type = SCM_RIGHTS;
612
613 msg.msg_name = NULL;
614 msg.msg_namelen = 0;
615 msg.msg_iov = iov;
616 msg.msg_iovlen = 1;
617 msg.msg_control = cmsg;
618 msg.msg_controllen = cmsg->cmsg_len;
619 msg.msg_flags = 0;
620
621 fd = (int*)CMSG_DATA(cmsg);
622 fd[0] = fdToSend0;
623 if ( fdToSend1 >= 0 )
624 {
625 fd[1] = fdToSend1;
626 }
627 if ( fdToSend2 >= 0 )
628 {
629 fd[2] = fdToSend2;
630 }
631
fei.dengb9a1a572023-09-13 01:33:57 +0000632 TRACE(mLogCategory,"send frame:bufferid %d, fd (%d, %d, %d [%d, %d, %d]),realtmUs:%lld", bufferId, frameFd0, frameFd1, frameFd2, fdToSend0, fdToSend1, fdToSend2,wstBufferInfo->frameTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000633
634 do
635 {
636 sentLen = sendmsg( mSocketFd, &msg, 0 );
637 } while ( (sentLen < 0) && (errno == EINTR));
638
639 if ( sentLen == iov[0].iov_len )
640 {
641 result = true;
642 }
643 else
644 {
fei.dengb9a1a572023-09-13 01:33:57 +0000645 ERROR(mLogCategory,"out: failed(%s) %d, sentLen(%d)%d, send frame %lld buffer %d ", \
fei.dengf7a0cd32023-08-29 09:36:37 +0000646 strerror(errno), errno, sentLen, iov[0].iov_len, wstBufferInfo->frameTime, bufferId);
647 }
648 }
649
650exit:
651 if ( fdToSend0 >= 0 )
652 {
653 close( fdToSend0 );
654 fdToSend0 = -1;
655 }
656 if ( fdToSend1 >= 0 )
657 {
658 close( fdToSend1 );
659 fdToSend1 = -1;
660 }
661 if ( fdToSend2 >= 0 )
662 {
663 close( fdToSend2 );
664 fdToSend2 = -1;
665 }
666
667 return result;
668}
669
670void WstClientSocket::sendCropFrameSizeClientConnection(int x, int y, int w, int h)
671{
672 struct msghdr msg;
673 struct iovec iov[1];
674 unsigned char mbody[20];
675 int len;
676 int sentLen;
677
678 msg.msg_name = NULL;
679 msg.msg_namelen = 0;
680 msg.msg_iov = iov;
681 msg.msg_iovlen = 1;
682 msg.msg_control = 0;
683 msg.msg_controllen = 0;
684 msg.msg_flags = 0;
685
686 len = 0;
687 mbody[len++] = 'V';
688 mbody[len++] = 'S';
689 mbody[len++] = 17;
690 mbody[len++] = 'C';
691 len += putU32( &mbody[len], x );
692 len += putU32( &mbody[len], y );
693 len += putU32( &mbody[len], w );
694 len += putU32( &mbody[len], h );
695
696 iov[0].iov_base = (char*)mbody;
697 iov[0].iov_len = len;
698
699 do
700 {
701 sentLen= sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
702 }
703 while ( (sentLen < 0) && (errno == EINTR));
704
705 if ( sentLen == len )
706 {
fei.dengb9a1a572023-09-13 01:33:57 +0000707 INFO(mLogCategory,"sent crop frame size to video server,x:%d,y:%d,w:%d,h:%d",x,y,w,h);
fei.dengf7a0cd32023-08-29 09:36:37 +0000708 }
709}
710
711void WstClientSocket::sendKeepLastFrameVideoClientConnection(bool keep)
712{
713 struct msghdr msg;
714 struct iovec iov[1];
715 unsigned char mbody[7];
716 int len;
717 int sentLen;
718
719 msg.msg_name = NULL;
720 msg.msg_namelen = 0;
721 msg.msg_iov = iov;
722 msg.msg_iovlen = 1;
723 msg.msg_control = 0;
724 msg.msg_controllen = 0;
725 msg.msg_flags = 0;
726
727 len= 0;
728 mbody[len++] = 'V';
729 mbody[len++] = 'S';
730 mbody[len++] = 2;
731 mbody[len++] = 'K';
732 mbody[len++] = (keep ? 1 : 0);
733
734 iov[0].iov_base = (char*)mbody;
735 iov[0].iov_len = len;
736
737 do
738 {
739 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
740 }
741 while ( (sentLen < 0) && (errno == EINTR));
742
743 if ( sentLen == len )
744 {
fei.dengb9a1a572023-09-13 01:33:57 +0000745 INFO(mLogCategory,"sent keep last frame %d to video server", keep);
fei.dengf7a0cd32023-08-29 09:36:37 +0000746 }
747}
748
749void WstClientSocket::processMessagesVideoClientConnection()
750{
751 struct msghdr msg;
752 struct iovec iov[1];
753 unsigned char mbody[256];
754 unsigned char *m = mbody;
755 int len;
756
757 iov[0].iov_base = (char*)mbody;
758 iov[0].iov_len = sizeof(mbody);
759
760 msg.msg_name = NULL;
761 msg.msg_namelen = 0;
762 msg.msg_iov = iov;
763 msg.msg_iovlen = 1;
764 msg.msg_control = 0;
765 msg.msg_controllen = 0;
766 msg.msg_flags = 0;
767
768 do
769 {
770 len= recvmsg( mSocketFd, &msg, 0 );
771 }
772 while ( (len < 0) && (errno == EINTR));
773
774 while ( len >= 4 )
775 {
776 if ( (m[0] == 'V') && (m[1] == 'S') )
777 {
778 int mlen, id;
779 mlen= m[2];
780 if ( len >= (mlen+3) )
781 {
782 id= m[3];
783 switch ( id )
784 {
785 case 'R':
786 if ( mlen >= 5)
787 {
788 int rate = getU32( &m[4] );
fei.dengb9a1a572023-09-13 01:33:57 +0000789 DEBUG(mLogCategory,"out: got rate %d from video server", rate);
fei.dengf7a0cd32023-08-29 09:36:37 +0000790 mServerRefreshRate = rate;
791 if ( mPlugin )
792 {
793 WstEvent wstEvent;
794 wstEvent.event = WST_REFRESH_RATE;
795 wstEvent.param = rate;
796 mPlugin->onWstSocketEvent(&wstEvent);
797 }
798 }
799 break;
800 case 'B':
801 if ( mlen >= 5)
802 {
803 int bid= getU32( &m[4] );
fei.dengb9a1a572023-09-13 01:33:57 +0000804 TRACE(mLogCategory,"out: release received for buffer %d", bid);
fei.dengf7a0cd32023-08-29 09:36:37 +0000805 if ( mPlugin )
806 {
807 WstEvent wstEvent;
808 wstEvent.event = WST_BUFFER_RELEASE;
809 wstEvent.param = bid;
810 mPlugin->onWstSocketEvent(&wstEvent);
811 }
812 }
813 break;
814 case 'S':
815 if ( mlen >= 13)
816 {
817 /* set position from frame currently presented by the video server */
818 uint64_t frameTime = getS64( &m[4] );
819 uint32_t numDropped = getU32( &m[12] );
fei.dengb9a1a572023-09-13 01:33:57 +0000820 TRACE(mLogCategory,"out: status received: frameTime %lld numDropped %d", frameTime, numDropped);
fei.dengf7a0cd32023-08-29 09:36:37 +0000821 if ( mPlugin )
822 {
823 WstEvent wstEvent;
824 wstEvent.event = WST_STATUS;
825 wstEvent.param = numDropped;
826 wstEvent.lparam = frameTime;
827 mPlugin->onWstSocketEvent(&wstEvent);
828 }
829 }
830 break;
831 case 'U':
832 if ( mlen >= 9 )
833 {
834 uint64_t frameTime = getS64( &m[4] );
fei.dengb9a1a572023-09-13 01:33:57 +0000835 TRACE(mLogCategory,"out: underflow received: frameTime %lld", frameTime);
fei.dengf7a0cd32023-08-29 09:36:37 +0000836 if ( mPlugin )
837 {
838 WstEvent wstEvent;
839 wstEvent.event = WST_UNDERFLOW;
840 wstEvent.lparam = frameTime;
841 mPlugin->onWstSocketEvent(&wstEvent);
842 }
843 }
844 break;
845 case 'Z':
846 if ( mlen >= 13)
847 {
848 int globalZoomActive= getU32( &m[4] );
849 int allow4kZoom = getU32( &m[8] );
850 int zoomMode= getU32( &m[12] );
fei.dengb9a1a572023-09-13 01:33:57 +0000851 DEBUG(mLogCategory,"out: got zoom-mode %d from video server (globalZoomActive %d allow4kZoom %d)", zoomMode, globalZoomActive, allow4kZoom);
fei.dengf7a0cd32023-08-29 09:36:37 +0000852 if ( mPlugin )
853 {
854 WstEvent wstEvent;
855 wstEvent.event = WST_ZOOM_MODE;
856 wstEvent.param = zoomMode;
857 wstEvent.param1 = globalZoomActive;
858 wstEvent.param2 = allow4kZoom;
859 mPlugin->onWstSocketEvent(&wstEvent);
860 }
861 }
862 break;
863 case 'D':
864 if ( mlen >= 5)
865 {
866 int debugLevel = getU32( &m[4] );
fei.dengb9a1a572023-09-13 01:33:57 +0000867 DEBUG(mLogCategory,"out: got video-debug-level %d from video server", debugLevel);
fei.dengf7a0cd32023-08-29 09:36:37 +0000868 if ( (debugLevel >= 0) && (debugLevel <= 7) )
869 {
870 if ( mPlugin )
871 {
872 WstEvent wstEvent;
873 wstEvent.event = WST_DEBUG_LEVEL;
874 wstEvent.param = debugLevel;
875 mPlugin->onWstSocketEvent(&wstEvent);
876 }
877 }
878 }
879 break;
880 default:
881 break;
882 }
883 m += (mlen+3);
884 len -= (mlen+3);
885 }
886 else
887 {
888 len= 0;
889 }
890 }
891 else
892 {
893 len= 0;
894 }
895 }
896}
897
898void WstClientSocket::readyToRun()
899{
fei.dengb9a1a572023-09-13 01:33:57 +0000900 if (mPoll && mSocketFd > 0) {
901 mPoll->addFd(mSocketFd);
902 mPoll->setFdReadable(mSocketFd, true);
903 }
fei.dengf7a0cd32023-08-29 09:36:37 +0000904}
905
906bool WstClientSocket::threadLoop()
907{
908 int ret;
fei.dengb9a1a572023-09-13 01:33:57 +0000909 ret = mPoll->wait(-1); //wait for ever
fei.dengf7a0cd32023-08-29 09:36:37 +0000910 if (ret < 0) { //poll error
fei.dengb9a1a572023-09-13 01:33:57 +0000911 WARNING(mLogCategory,"poll error");
fei.dengf7a0cd32023-08-29 09:36:37 +0000912 return false;
913 } else if (ret == 0) { //poll time out
914 return true; //run loop
915 }
916 processMessagesVideoClientConnection();
917 return true;
918}