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;
}
Beispiel #4
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;
}