int startAudioStream(void) { int err; callbacks.init(); rtpSocket = bindUdpSocket(); if (rtpSocket == INVALID_SOCKET) { return LastSocketError(); } err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread); if (err != 0) { return err; } err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread); if (err != 0) { return err; } err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread); if (err != 0) { return err; } callbacks.start(); return 0; }
// Start the video stream int startVideoStream(void* rendererContext, int drFlags) { int err; // This must be called before the decoder thread starts submitting // decode units LC_ASSERT(NegotiatedVideoFormat != 0); VideoCallbacks.setup(NegotiatedVideoFormat, StreamConfig.width, StreamConfig.height, StreamConfig.fps, rendererContext, drFlags); rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER); if (rtpSocket == INVALID_SOCKET) { return LastSocketError(); } err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread); if (err != 0) { return err; } if ((VideoCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread); if (err != 0) { return err; } } if (ServerMajorVersion == 3) { // Connect this socket to open port 47998 for our ping thread firstFrameSocket = connectTcpSocket(&RemoteAddr, RemoteAddrLen, FIRST_FRAME_PORT, FIRST_FRAME_TIMEOUT_SEC); if (firstFrameSocket == INVALID_SOCKET) { return LastSocketError(); } } // Start pinging before reading the first frame so GFE knows where // to send UDP data err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread); if (err != 0) { return err; } if (ServerMajorVersion == 3) { // Read the first frame to start the flow of video err = readFirstFrame(); if (err != 0) { return err; } } return 0; }
int startAudioStream(void* audioContext, int arFlags) { int err; POPUS_MULTISTREAM_CONFIGURATION chosenConfig; if (StreamConfig.audioConfiguration == AUDIO_CONFIGURATION_STEREO) { chosenConfig = &opusStereoConfig; } else if (StreamConfig.audioConfiguration == AUDIO_CONFIGURATION_51_SURROUND) { if (HighQualitySurroundEnabled) { chosenConfig = &opus51HighSurroundConfig; } else { chosenConfig = &opus51SurroundConfig; } } else { Limelog("Invalid audio configuration: %d\n", StreamConfig.audioConfiguration); return -1; } err = AudioCallbacks.init(StreamConfig.audioConfiguration, chosenConfig, audioContext, arFlags); if (err != 0) { return err; } rtpSocket = bindUdpSocket(RemoteAddr.ss_family, RTP_RECV_BUFFER); if (rtpSocket == INVALID_SOCKET) { err = LastSocketFail(); AudioCallbacks.cleanup(); return err; } AudioCallbacks.start(); err = PltCreateThread(ReceiveThreadProc, NULL, &receiveThread); if (err != 0) { AudioCallbacks.stop(); closeSocket(rtpSocket); AudioCallbacks.cleanup(); return err; } if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { err = PltCreateThread(DecoderThreadProc, NULL, &decoderThread); if (err != 0) { AudioCallbacks.stop(); PltInterruptThread(&receiveThread); PltJoinThread(&receiveThread); PltCloseThread(&receiveThread); closeSocket(rtpSocket); AudioCallbacks.cleanup(); return err; } } // Don't start pinging (which will cause GFE to start sending us traffic) // until everything else is started. Otherwise we could accumulate a // bunch of audio packets in the socket receive buffer while our audio // backend is starting up and create audio latency. err = PltCreateThread(UdpPingThreadProc, NULL, &udpPingThread); if (err != 0) { AudioCallbacks.stop(); PltInterruptThread(&receiveThread); if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { // Signal threads waiting on the LBQ LbqSignalQueueShutdown(&packetQueue); PltInterruptThread(&decoderThread); } PltJoinThread(&receiveThread); if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { PltJoinThread(&decoderThread); } PltCloseThread(&receiveThread); if ((AudioCallbacks.capabilities & CAPABILITY_DIRECT_SUBMIT) == 0) { PltCloseThread(&decoderThread); } closeSocket(rtpSocket); AudioCallbacks.cleanup(); return err; } return 0; }
UDP_NTWK_READER_ERRORS udpNtwkReaderThreadStart(tThreadId* lpThreadId, UdpNtwkReaderArgs* pArgs, int iNumArgs) { int i; UdpReaderArgs* psArgs; psArgs = malloc(sizeof(UdpReaderArgs)); memset(psArgs,0,sizeof(UdpReaderArgs)); if (psArgs == NULL) return UDP_NTWK_READER_NO_ARGS; memset(lpThreadId,0,sizeof(tThreadId)); for (i=0; i < iNumArgs; i++) { switch (pArgs[i].eArgType) { case UDP_NTWK_READER_STREAM_IP: psArgs->iMcastIp = CAST_POINTER_TO_INT(pArgs[i].pvArgData); break; case UDP_NTWK_READER_STREAM_PORT: psArgs->sMcastPort = CAST_POINTER_TO_SHORT(pArgs[i].pvArgData); break; case UDP_NTWK_READER_NETWORK_INT: psArgs->iMcastIntIp = CAST_POINTER_TO_INT(pArgs[i].pvArgData); break; case UDP_NTWK_READER_RECIEVE_QUEUE_NAME: memset(psArgs->acRecieveQueueName,0,MAX_QUEUE_NAME); strcpy(psArgs->acRecieveQueueName,(char*)(pArgs[i].pvArgData)); break; case UDP_NTWK_READER_OUTGOING_QUEUE_NAME: memset(psArgs->acOutgoingQueueName,0,MAX_QUEUE_NAME); strcpy(psArgs->acOutgoingQueueName,(char*)(pArgs[i].pvArgData)); break; default: DEBUG_PRINT("UdpNtwkReader: Unknown argument type %d\n",pArgs->eArgType); break; } } if (createUdpSocket(&(psArgs->iSocketFd)) != UDPSOCK_NO_ERROR) { DEBUG_PRINT("UdpNtwkReader: Failed to create socket\n"); free(psArgs); return UDP_NTWK_FAILED_INIT; } if (bindUdpSocket(&(psArgs->iSocketFd),psArgs->iMcastIp,psArgs->sMcastPort) != UDPSOCK_NO_ERROR) { DEBUG_PRINT("UdpNtwkReader: Failed to bind socket to multicast Ip and Port\n"); closeUdpSocket(&(psArgs->iSocketFd),0); free(psArgs); return UDP_NTWK_FAILED_INIT; } #if 0 /*this works for root only*/ if (bindUdpSocketToNtwkInt(&(psArgs->iSocketFd), psArgs->iMcastIntIp) != UDPSOCK_NO_ERROR) { DEBUG_PRINT("UdpNtwkReader: Failed to bind socket to physical interface\n"); closeUdpSocket(&(psArgs->iSocketFd),0); free(psArgs); return UDP_NTWK_FAILED_INIT; } #endif if (joinMcastUdpSocket(&(psArgs->iSocketFd),psArgs->iMcastIntIp,psArgs->iMcastIp) != UDPSOCK_NO_ERROR) { DEBUG_PRINT("UdpNtwkReader: Failed to join multicast group\n"); closeUdpSocket(&(psArgs->iSocketFd),0); free(psArgs); return UDP_NTWK_FAILED_INIT; } psArgs->bExitThread = false; if (createPosixThread(&(psArgs->liThreadID),threadFunct,psArgs) != PTHREAD_NO_ERROR) { free(psArgs); closeUdpSocket(&(psArgs->iSocketFd),0); return UDP_NTWK_READER_THREAD_LAUNCH_ERROR; } memcpy(lpThreadId,&(psArgs->liThreadID),sizeof(tThreadId)); return UDP_NTWK_READER_NO_ERROR; }