blob: d168c6a6232380ab77d39561392e085eb90a07a3 [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>
29#include <poll.h>
30#include "wstclient_socket.h"
31#include "wstclient_plugin.h"
32#include "Logger.h"
33
34#define TAG "rlib:wstclient_socket"
35
36static int putU32( unsigned char *p, unsigned n )
37{
38 p[0]= (n>>24);
39 p[1]= (n>>16);
40 p[2]= (n>>8);
41 p[3]= (n&0xFF);
42
43 return 4;
44}
45
46static unsigned int getU32( unsigned char *p )
47{
48 unsigned n;
49
50 n= (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|(p[3]);
51
52 return n;
53}
54
55static int64_t getS64( unsigned char *p )
56{
57 int64_t n;
58
59 n= ((((int64_t)(p[0]))<<56) |
60 (((int64_t)(p[1]))<<48) |
61 (((int64_t)(p[2]))<<40) |
62 (((int64_t)(p[3]))<<32) |
63 (((int64_t)(p[4]))<<24) |
64 (((int64_t)(p[5]))<<16) |
65 (((int64_t)(p[6]))<<8) |
66 (p[7]) );
67
68 return n;
69}
70
71static int putS64( unsigned char *p, int64_t n )
72{
73 p[0]= (((uint64_t)n)>>56);
74 p[1]= (((uint64_t)n)>>48);
75 p[2]= (((uint64_t)n)>>40);
76 p[3]= (((uint64_t)n)>>32);
77 p[4]= (((uint64_t)n)>>24);
78 p[5]= (((uint64_t)n)>>16);
79 p[6]= (((uint64_t)n)>>8);
80 p[7]= (((uint64_t)n)&0xFF);
81
82 return 8;
83}
84
85WstClientSocket::WstClientSocket(WstClientPlugin *plugin)
86{
87 mPlugin = plugin;
88}
89
90WstClientSocket::~WstClientSocket()
91{
92}
93
94bool WstClientSocket::connectToSocket(const char *name)
95{
96 int rc;
97 bool error= true;
98 const char *workingDir;
99 int pathNameLen, addressSize;
100
101 mSocketFd = -1;
102 mName = name;
103
104 workingDir = getenv("XDG_RUNTIME_DIR");
105 if ( !workingDir )
106 {
107 workingDir = "/run";
108 ERROR("wstCreateVideoClientConnection: XDG_RUNTIME_DIR is not set,set default %s",workingDir);
109 }
110
111 DEBUG("XDG_RUNTIME_DIR=%s",workingDir);
112
113 pathNameLen = strlen(workingDir)+strlen("/")+strlen(mName) + 1;
114 if ( pathNameLen > (int)sizeof(mAddr.sun_path) )
115 {
116 ERROR("wstCreateVideoClientConnection: name for server unix domain socket is too long: %d versus max %d", \
117 pathNameLen, (int)sizeof(mAddr.sun_path) );
118 goto exit;
119 }
120
121 mAddr.sun_family = AF_LOCAL;
122 strcpy( mAddr.sun_path, workingDir );
123 strcat( mAddr.sun_path, "/" );
124 strcat( mAddr.sun_path, mName );
125
126 mSocketFd = socket( PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0 );
127 if ( mSocketFd < 0 )
128 {
129 ERROR("wstCreateVideoClientConnection: unable to open socket: errno %d", errno );
130 goto exit;
131 }
132
133 addressSize = pathNameLen + offsetof(struct sockaddr_un, sun_path);
134
135 rc = connect(mSocketFd, (struct sockaddr *)&mAddr, addressSize );
136 if ( rc < 0 )
137 {
138 ERROR("wstCreateVideoClientConnection: connect failed for socket: errno %d,path:%s", errno,mAddr.sun_path );
139 goto exit;
140 }
141
142 INFO("wstclient socket connected,path:%s",mAddr.sun_path);
143
144 run("wstclientsocket");
145 return true;
146
147exit:
148
149 mAddr.sun_path[0] = '\0';
150 if ( mSocketFd >= 0 )
151 {
152 close( mSocketFd );
153 mSocketFd = -1;
154 }
155 return false;
156}
157
158bool WstClientSocket::disconnectFromSocket()
159{
160 if (isRunning()) {
161 requestExitAndWait();
162 }
163
164 if ( mSocketFd >= 0 )
165 {
166 mAddr.sun_path[0]= '\0';
167 INFO("close socket");
168 close( mSocketFd );
169 mSocketFd = -1;
170 }
171 return true;
172}
173
174void WstClientSocket::sendLayerVideoClientConnection(bool pip)
175{
176 struct msghdr msg;
177 struct iovec iov[1];
178 unsigned char mbody[5];
179 int len;
180 int sentLen;
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++]= 2;
194 mbody[len++]= 'N';
195 mbody[len++]= (pip? 1 : 0);
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 {
208 INFO("sent pip %d to video server", pip);
209 }
210}
211
212void WstClientSocket::sendResourceVideoClientConnection(bool pip)
213{
214 struct msghdr msg;
215 struct iovec iov[1];
216 unsigned char mbody[8];
217 int len;
218 int sentLen;
219 int resourceId= (pip? 1 : 0);
220
221 msg.msg_name= NULL;
222 msg.msg_namelen= 0;
223 msg.msg_iov= iov;
224 msg.msg_iovlen= 1;
225 msg.msg_control= 0;
226 msg.msg_controllen= 0;
227 msg.msg_flags= 0;
228
229 len= 0;
230 mbody[len++]= 'V';
231 mbody[len++]= 'S';
232 mbody[len++]= 5;
233 mbody[len++]= 'V';
234 len += putU32( &mbody[len], resourceId );
235
236 iov[0].iov_base= (char*)mbody;
237 iov[0].iov_len= len;
238
239 do
240 {
241 sentLen= sendmsg(mSocketFd, &msg, MSG_NOSIGNAL );
242 }
243 while ( (sentLen < 0) && (errno == EINTR));
244
245 if ( sentLen == len )
246 {
247 INFO("sent resource id %d (0:primary,1:pip) to video server", resourceId);
248 }
249}
250
251void WstClientSocket::sendFlushVideoClientConnection()
252{
253 struct msghdr msg;
254 struct iovec iov[1];
255 unsigned char mbody[4];
256 int len;
257 int sentLen;
258
259 msg.msg_name = NULL;
260 msg.msg_namelen = 0;
261 msg.msg_iov = iov;
262 msg.msg_iovlen = 1;
263 msg.msg_control = 0;
264 msg.msg_controllen = 0;
265 msg.msg_flags = 0;
266
267 len = 0;
268 mbody[len++] = 'V';
269 mbody[len++] = 'S';
270 mbody[len++] = 1;
271 mbody[len++] = 'S';
272
273 iov[0].iov_base = (char*)mbody;
274 iov[0].iov_len = len;
275
276 do
277 {
278 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
279 }
280 while ( (sentLen < 0) && (errno == EINTR));
281
282 if ( sentLen == len )
283 {
284 INFO("sent flush to video server");
285 }
286}
287
288void WstClientSocket::sendPauseVideoClientConnection(bool pause)
289{
290 struct msghdr msg;
291 struct iovec iov[1];
292 unsigned char mbody[7];
293 int len;
294 int sentLen;
295
296 msg.msg_name = NULL;
297 msg.msg_namelen = 0;
298 msg.msg_iov = iov;
299 msg.msg_iovlen = 1;
300 msg.msg_control = 0;
301 msg.msg_controllen = 0;
302 msg.msg_flags = 0;
303
304 len= 0;
305 mbody[len++] = 'V';
306 mbody[len++] = 'S';
307 mbody[len++] = 2;
308 mbody[len++] = 'P';
309 mbody[len++] = (pause ? 1 : 0);
310
311 iov[0].iov_base = (char*)mbody;
312 iov[0].iov_len = len;
313
314 do
315 {
316 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
317 }
318 while ( (sentLen < 0) && (errno == EINTR));
319
320 if ( sentLen == len )
321 {
322 INFO("sent pause %d to video server", pause);
323 }
324}
325
326void WstClientSocket::sendHideVideoClientConnection(bool hide)
327{
328 struct msghdr msg;
329 struct iovec iov[1];
330 unsigned char mbody[7];
331 int len;
332 int sentLen;
333
334 msg.msg_name = NULL;
335 msg.msg_namelen = 0;
336 msg.msg_iov = iov;
337 msg.msg_iovlen = 1;
338 msg.msg_control = 0;
339 msg.msg_controllen = 0;
340 msg.msg_flags = 0;
341
342 len= 0;
343 mbody[len++] = 'V';
344 mbody[len++] = 'S';
345 mbody[len++] = 2;
346 mbody[len++] = 'H';
347 mbody[len++] = (hide ? 1 : 0);
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 {
360 INFO("sent hide %d to video server", hide);
361 }
362}
363
364void WstClientSocket::sendSessionInfoVideoClientConnection(int sessionId, int syncType )
365{
366 struct msghdr msg;
367 struct iovec iov[1];
368 unsigned char mbody[9];
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++] = 6;
384 mbody[len++] = 'I';
385 mbody[len++] = syncType;
386 len += putU32( &mbody[len], sessionId );
387
388 iov[0].iov_base = (char*)mbody;
389 iov[0].iov_len = len;
390
391 do
392 {
393 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
394 }
395 while ( (sentLen < 0) && (errno == EINTR));
396
397 if ( sentLen == len )
398 {
399 INFO("sent session info: synctype %d sessionId %d to video server", syncType, sessionId);
400 }
401}
402
403void WstClientSocket::sendFrameAdvanceVideoClientConnection()
404{
405 struct msghdr msg;
406 struct iovec iov[1];
407 unsigned char mbody[4];
408 int len;
409 int sentLen;
410
411 msg.msg_name = NULL;
412 msg.msg_namelen = 0;
413 msg.msg_iov = iov;
414 msg.msg_iovlen = 1;
415 msg.msg_control = 0;
416 msg.msg_controllen = 0;
417 msg.msg_flags = 0;
418
419 len= 0;
420 mbody[len++] = 'V';
421 mbody[len++] = 'S';
422 mbody[len++] = 1;
423 mbody[len++] = 'A';
424
425 iov[0].iov_base = (char*)mbody;
426 iov[0].iov_len = len;
427
428 do
429 {
430 sentLen= sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
431 }
432 while ( (sentLen < 0) && (errno == EINTR));
433
434 if ( sentLen == len )
435 {
436 INFO("sent frame adavnce to video server");
437 }
438}
439
440void WstClientSocket::sendRectVideoClientConnection(int videoX, int videoY, int videoWidth, int videoHeight )
441{
442 struct msghdr msg;
443 struct iovec iov[1];
444 unsigned char mbody[20];
445 int len;
446 int sentLen;
447 int vx, vy, vw, vh;
448
449 vx = videoX;
450 vy = videoY;
451 vw = videoWidth;
452 vh = videoHeight;
453
454 msg.msg_name = NULL;
455 msg.msg_namelen = 0;
456 msg.msg_iov = iov;
457 msg.msg_iovlen = 1;
458 msg.msg_control = 0;
459 msg.msg_controllen = 0;
460 msg.msg_flags = 0;
461
462 len = 0;
463 mbody[len++] = 'V';
464 mbody[len++] = 'S';
465 mbody[len++] = 17;
466 mbody[len++] = 'W';
467 len += putU32( &mbody[len], vx );
468 len += putU32( &mbody[len], vy );
469 len += putU32( &mbody[len], vw );
470 len += putU32( &mbody[len], vh );
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 {
483 INFO("sent position to video server,vx:%d,vy:%d,vw:%d,vh:%d",videoX,videoY,videoWidth,videoHeight);
484 }
485}
486
487void WstClientSocket::sendRateVideoClientConnection(int fpsNum, int fpsDenom )
488{
489 struct msghdr msg;
490 struct iovec iov[1];
491 unsigned char mbody[12];
492 int len;
493 int sentLen;
494
495 msg.msg_name = NULL;
496 msg.msg_namelen = 0;
497 msg.msg_iov = iov;
498 msg.msg_iovlen = 1;
499 msg.msg_control = 0;
500 msg.msg_controllen = 0;
501 msg.msg_flags = 0;
502
503 len = 0;
504 mbody[len++] = 'V';
505 mbody[len++] = 'S';
506 mbody[len++] = 9;
507 mbody[len++] = 'R';
508 len += putU32( &mbody[len], fpsNum );
509 len += putU32( &mbody[len], fpsDenom );
510
511 iov[0].iov_base = (char*)mbody;
512 iov[0].iov_len = len;
513
514 do
515 {
516 sentLen= sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
517 }
518 while ( (sentLen < 0) && (errno == EINTR));
519
520 if ( sentLen == len )
521 {
522 INFO("sent frame rate to video server: %d/%d", fpsNum, fpsDenom);
523 }
524}
525
526bool WstClientSocket::sendFrameVideoClientConnection(WstBufferInfo *wstBufferInfo, WstRect *wstRect)
527{
528 bool result= false;
529 int sentLen;
530
531 struct msghdr msg;
532 struct cmsghdr *cmsg;
533 struct iovec iov[1];
534 unsigned char mbody[4+64];
535 char cmbody[CMSG_SPACE(3*sizeof(int))];
536 int i, len;
537 int *fd;
538 int numFdToSend;
539 int frameFd0 = -1, frameFd1 = -1, frameFd2 = -1;
540 int fdToSend0 = -1, fdToSend1 = -1, fdToSend2 = -1;
541 int offset0, offset1, offset2;
542 int stride0, stride1, stride2;
543 uint32_t pixelFormat;
544 int bufferId = -1;
545 int vx, vy, vw, vh;
546
547 if ( wstBufferInfo )
548 {
549 bufferId = wstBufferInfo->bufferId;
550
551 numFdToSend = 1;
552 offset0 = offset1 = offset2 = 0;
553 stride0 = stride1 = stride2 = wstBufferInfo->frameWidth;
554 if ( wstBufferInfo->planeCount > 1 )
555 {
556 frameFd0 = wstBufferInfo->planeInfo[0].fd;
557 stride0 = wstBufferInfo->planeInfo[0].stride;
558
559 frameFd1 = wstBufferInfo->planeInfo[1].fd;
560 stride1 = wstBufferInfo->planeInfo[1].stride;
561 if ( frameFd1 < 0 )
562 {
563 offset1 = wstBufferInfo->frameWidth*wstBufferInfo->frameHeight;
564 stride1 = stride0;
565 }
566
567 frameFd2 = wstBufferInfo->planeInfo[2].fd;
568 stride2 = wstBufferInfo->planeInfo[2].stride;
569 if ( frameFd2 < 0 )
570 {
571 offset2 = offset1 + (wstBufferInfo->frameWidth*wstBufferInfo->frameHeight)/2;
572 stride2 = stride0;
573 }
574 }
575 else
576 {
577 frameFd0 = wstBufferInfo->planeInfo[0].fd;
578 stride0 = wstBufferInfo->planeInfo[0].stride;
579 offset1 = stride0*wstBufferInfo->frameHeight;
580 stride1 = stride0;
581 offset2 = 0;
582 stride2 = 0;
583 }
584
585 //must change pixelformat to v4l2 support pixel format
586 pixelFormat = wstBufferInfo->pixelFormat;
587
588 fdToSend0 = fcntl( frameFd0, F_DUPFD_CLOEXEC, 0 );
589 if ( fdToSend0 < 0 )
590 {
591 ERROR("wstSendFrameVideoClientConnection: failed to dup fd0");
592 goto exit;
593 }
594 if ( frameFd1 >= 0 )
595 {
596 fdToSend1 = fcntl( frameFd1, F_DUPFD_CLOEXEC, 0 );
597 if ( fdToSend1 < 0 )
598 {
599 ERROR("wstSendFrameVideoClientConnection: failed to dup fd1");
600 goto exit;
601 }
602 ++numFdToSend;
603 }
604 if ( frameFd2 >= 0 )
605 {
606 fdToSend2 = fcntl( frameFd2, F_DUPFD_CLOEXEC, 0 );
607 if ( fdToSend2 < 0 )
608 {
609 ERROR("wstSendFrameVideoClientConnection: failed to dup fd2");
610 goto exit;
611 }
612 ++numFdToSend;
613 }
614
615 vx = wstRect->x;
616 vy = wstRect->y;
617 vw = wstRect->w;
618 vh = wstRect->h;
619
620 TRACE("send frame:resolution(%dx%d),rect x:%d,y:%d,w:%d,h:%d", \
621 wstBufferInfo->frameWidth,wstBufferInfo->frameHeight, vx, vy, vw, vh);
622
623 i = 0;
624 mbody[i++] = 'V';
625 mbody[i++] = 'S';
626 mbody[i++] = 65;
627 mbody[i++] = 'F';
628 i += putU32( &mbody[i], wstBufferInfo->frameWidth );
629 i += putU32( &mbody[i], wstBufferInfo->frameHeight );
630 i += putU32( &mbody[i], pixelFormat );
631 i += putU32( &mbody[i], vx );
632 i += putU32( &mbody[i], vy );
633 i += putU32( &mbody[i], vw );
634 i += putU32( &mbody[i], vh );
635 i += putU32( &mbody[i], offset0 );
636 i += putU32( &mbody[i], stride0 );
637 i += putU32( &mbody[i], offset1 );
638 i += putU32( &mbody[i], stride1 );
639 i += putU32( &mbody[i], offset2 );
640 i += putU32( &mbody[i], stride2 );
641 i += putU32( &mbody[i], bufferId );
642 i += putS64( &mbody[i], wstBufferInfo->frameTime );
643
644 iov[0].iov_base = (char*)mbody;
645 iov[0].iov_len = i;
646
647 cmsg = (struct cmsghdr*)cmbody;
648 cmsg->cmsg_len = CMSG_LEN(numFdToSend*sizeof(int));
649 cmsg->cmsg_level = SOL_SOCKET;
650 cmsg->cmsg_type = SCM_RIGHTS;
651
652 msg.msg_name = NULL;
653 msg.msg_namelen = 0;
654 msg.msg_iov = iov;
655 msg.msg_iovlen = 1;
656 msg.msg_control = cmsg;
657 msg.msg_controllen = cmsg->cmsg_len;
658 msg.msg_flags = 0;
659
660 fd = (int*)CMSG_DATA(cmsg);
661 fd[0] = fdToSend0;
662 if ( fdToSend1 >= 0 )
663 {
664 fd[1] = fdToSend1;
665 }
666 if ( fdToSend2 >= 0 )
667 {
668 fd[2] = fdToSend2;
669 }
670
671 TRACE("send frame:bufferid %d, fd (%d, %d, %d [%d, %d, %d]),realtmUs:%lld", bufferId, frameFd0, frameFd1, frameFd2, fdToSend0, fdToSend1, fdToSend2,wstBufferInfo->frameTime);
672
673 do
674 {
675 sentLen = sendmsg( mSocketFd, &msg, 0 );
676 } while ( (sentLen < 0) && (errno == EINTR));
677
678 if ( sentLen == iov[0].iov_len )
679 {
680 result = true;
681 }
682 else
683 {
684 ERROR("out: failed(%s) %d, sentLen(%d)%d, send frame %lld buffer %d ", \
685 strerror(errno), errno, sentLen, iov[0].iov_len, wstBufferInfo->frameTime, bufferId);
686 }
687 }
688
689exit:
690 if ( fdToSend0 >= 0 )
691 {
692 close( fdToSend0 );
693 fdToSend0 = -1;
694 }
695 if ( fdToSend1 >= 0 )
696 {
697 close( fdToSend1 );
698 fdToSend1 = -1;
699 }
700 if ( fdToSend2 >= 0 )
701 {
702 close( fdToSend2 );
703 fdToSend2 = -1;
704 }
705
706 return result;
707}
708
709void WstClientSocket::sendCropFrameSizeClientConnection(int x, int y, int w, int h)
710{
711 struct msghdr msg;
712 struct iovec iov[1];
713 unsigned char mbody[20];
714 int len;
715 int sentLen;
716
717 msg.msg_name = NULL;
718 msg.msg_namelen = 0;
719 msg.msg_iov = iov;
720 msg.msg_iovlen = 1;
721 msg.msg_control = 0;
722 msg.msg_controllen = 0;
723 msg.msg_flags = 0;
724
725 len = 0;
726 mbody[len++] = 'V';
727 mbody[len++] = 'S';
728 mbody[len++] = 17;
729 mbody[len++] = 'C';
730 len += putU32( &mbody[len], x );
731 len += putU32( &mbody[len], y );
732 len += putU32( &mbody[len], w );
733 len += putU32( &mbody[len], h );
734
735 iov[0].iov_base = (char*)mbody;
736 iov[0].iov_len = len;
737
738 do
739 {
740 sentLen= sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
741 }
742 while ( (sentLen < 0) && (errno == EINTR));
743
744 if ( sentLen == len )
745 {
746 INFO("sent crop frame size to video server,x:%d,y:%d,w:%d,h:%d",x,y,w,h);
747 }
748}
749
750void WstClientSocket::sendKeepLastFrameVideoClientConnection(bool keep)
751{
752 struct msghdr msg;
753 struct iovec iov[1];
754 unsigned char mbody[7];
755 int len;
756 int sentLen;
757
758 msg.msg_name = NULL;
759 msg.msg_namelen = 0;
760 msg.msg_iov = iov;
761 msg.msg_iovlen = 1;
762 msg.msg_control = 0;
763 msg.msg_controllen = 0;
764 msg.msg_flags = 0;
765
766 len= 0;
767 mbody[len++] = 'V';
768 mbody[len++] = 'S';
769 mbody[len++] = 2;
770 mbody[len++] = 'K';
771 mbody[len++] = (keep ? 1 : 0);
772
773 iov[0].iov_base = (char*)mbody;
774 iov[0].iov_len = len;
775
776 do
777 {
778 sentLen = sendmsg( mSocketFd, &msg, MSG_NOSIGNAL );
779 }
780 while ( (sentLen < 0) && (errno == EINTR));
781
782 if ( sentLen == len )
783 {
784 INFO("sent keep last frame %d to video server", keep);
785 }
786}
787
788void WstClientSocket::processMessagesVideoClientConnection()
789{
790 struct msghdr msg;
791 struct iovec iov[1];
792 unsigned char mbody[256];
793 unsigned char *m = mbody;
794 int len;
795
796 iov[0].iov_base = (char*)mbody;
797 iov[0].iov_len = sizeof(mbody);
798
799 msg.msg_name = NULL;
800 msg.msg_namelen = 0;
801 msg.msg_iov = iov;
802 msg.msg_iovlen = 1;
803 msg.msg_control = 0;
804 msg.msg_controllen = 0;
805 msg.msg_flags = 0;
806
807 do
808 {
809 len= recvmsg( mSocketFd, &msg, 0 );
810 }
811 while ( (len < 0) && (errno == EINTR));
812
813 while ( len >= 4 )
814 {
815 if ( (m[0] == 'V') && (m[1] == 'S') )
816 {
817 int mlen, id;
818 mlen= m[2];
819 if ( len >= (mlen+3) )
820 {
821 id= m[3];
822 switch ( id )
823 {
824 case 'R':
825 if ( mlen >= 5)
826 {
827 int rate = getU32( &m[4] );
828 DEBUG("out: got rate %d from video server", rate);
829 mServerRefreshRate = rate;
830 if ( mPlugin )
831 {
832 WstEvent wstEvent;
833 wstEvent.event = WST_REFRESH_RATE;
834 wstEvent.param = rate;
835 mPlugin->onWstSocketEvent(&wstEvent);
836 }
837 }
838 break;
839 case 'B':
840 if ( mlen >= 5)
841 {
842 int bid= getU32( &m[4] );
843 TRACE("out: release received for buffer %d", bid);
844 if ( mPlugin )
845 {
846 WstEvent wstEvent;
847 wstEvent.event = WST_BUFFER_RELEASE;
848 wstEvent.param = bid;
849 mPlugin->onWstSocketEvent(&wstEvent);
850 }
851 }
852 break;
853 case 'S':
854 if ( mlen >= 13)
855 {
856 /* set position from frame currently presented by the video server */
857 uint64_t frameTime = getS64( &m[4] );
858 uint32_t numDropped = getU32( &m[12] );
859 TRACE("out: status received: frameTime %lld numDropped %d", frameTime, numDropped);
860 if ( mPlugin )
861 {
862 WstEvent wstEvent;
863 wstEvent.event = WST_STATUS;
864 wstEvent.param = numDropped;
865 wstEvent.lparam = frameTime;
866 mPlugin->onWstSocketEvent(&wstEvent);
867 }
868 }
869 break;
870 case 'U':
871 if ( mlen >= 9 )
872 {
873 uint64_t frameTime = getS64( &m[4] );
874 TRACE("out: underflow received: frameTime %lld", frameTime);
875 if ( mPlugin )
876 {
877 WstEvent wstEvent;
878 wstEvent.event = WST_UNDERFLOW;
879 wstEvent.lparam = frameTime;
880 mPlugin->onWstSocketEvent(&wstEvent);
881 }
882 }
883 break;
884 case 'Z':
885 if ( mlen >= 13)
886 {
887 int globalZoomActive= getU32( &m[4] );
888 int allow4kZoom = getU32( &m[8] );
889 int zoomMode= getU32( &m[12] );
890 DEBUG("out: got zoom-mode %d from video server (globalZoomActive %d allow4kZoom %d)", zoomMode, globalZoomActive, allow4kZoom);
891 if ( mPlugin )
892 {
893 WstEvent wstEvent;
894 wstEvent.event = WST_ZOOM_MODE;
895 wstEvent.param = zoomMode;
896 wstEvent.param1 = globalZoomActive;
897 wstEvent.param2 = allow4kZoom;
898 mPlugin->onWstSocketEvent(&wstEvent);
899 }
900 }
901 break;
902 case 'D':
903 if ( mlen >= 5)
904 {
905 int debugLevel = getU32( &m[4] );
906 DEBUG("out: got video-debug-level %d from video server", debugLevel);
907 if ( (debugLevel >= 0) && (debugLevel <= 7) )
908 {
909 if ( mPlugin )
910 {
911 WstEvent wstEvent;
912 wstEvent.event = WST_DEBUG_LEVEL;
913 wstEvent.param = debugLevel;
914 mPlugin->onWstSocketEvent(&wstEvent);
915 }
916 }
917 }
918 break;
919 default:
920 break;
921 }
922 m += (mlen+3);
923 len -= (mlen+3);
924 }
925 else
926 {
927 len= 0;
928 }
929 }
930 else
931 {
932 len= 0;
933 }
934 }
935}
936
937void WstClientSocket::readyToRun()
938{
939}
940
941bool WstClientSocket::threadLoop()
942{
943 int ret;
944 struct pollfd fds;
945
946 fds.fd = mSocketFd;
947 fds.events = POLLERR | POLLNVAL | POLLHUP |POLLIN | POLLPRI | POLLRDNORM;
948 fds.revents = 0;
949
950 ret = poll(&fds, 1, 500);
951 if (ret < 0) { //poll error
952 WARNING("poll error");
953 return false;
954 } else if (ret == 0) { //poll time out
955 return true; //run loop
956 }
957 processMessagesVideoClientConnection();
958 return true;
959}