eARCONTROLLER_ERROR ARCONTROLLER_Network_StartVideoStream (ARCONTROLLER_Network_t *networkController)
{
    // -- Start Video stream --
    
    eARCONTROLLER_ERROR error = ARCONTROLLER_OK;
    int locked = 0;
    
    // Check parameters
    if (networkController == NULL)
    {
        error = ARCONTROLLER_ERROR_BAD_PARAMETER;
    }
    // No Else: the checking parameters sets error to ARNETWORK_ERROR_BAD_PARAMETER and stop the processing
    
    if (error == ARCONTROLLER_OK)
    {
        if (ARSAL_Mutex_Lock (&(networkController->mutex)) != 0)
        {
            error = ARCONTROLLER_ERROR_MUTEX;
        }
        else
        {
            locked = 1;
        }
    }
    
    if (error == ARCONTROLLER_OK)
    {
        // Check if the device has video
        if (networkController->hasVideo)
        {
            error = ARCONTROLLER_Stream_Start (networkController->videoController, networkController->networkManager);
        }
        //NO else ; device has not video
    }
    // No else: skipped by an error
    
    if (locked)
    {
        ARSAL_Mutex_Unlock (&(networkController->mutex));
    }
    
    return error;
}
ARCONTROLLER_Network_t *ARCONTROLLER_Network_New (ARDISCOVERY_Device_t *discoveryDevice, ARCONTROLLER_Network_DisconnectionCallback_t disconnectionCallback, ARDISCOVERY_Device_ConnectionJsonCallback_t sendJsonCallback, ARDISCOVERY_Device_ConnectionJsonCallback_t receiveJsonCallback, void *customData, eARCONTROLLER_ERROR *error)
{
    // -- Create a new Network Controller --
    
    ARSAL_PRINT(ARSAL_PRINT_DEBUG, ARCONTROLLER_NETWORK_TAG, "ARCONTROLLER_Network_New ...");
    
    //local declarations
    eARCONTROLLER_ERROR localError = ARCONTROLLER_OK;
    ARCONTROLLER_Network_t *networkController =  NULL;
    eARDISCOVERY_ERROR dicoveryError = ARDISCOVERY_OK;
    
    // Check parameters
    if (discoveryDevice == NULL)
    {
        localError = ARCONTROLLER_ERROR_BAD_PARAMETER;
    }
    // No Else: the checking parameters sets localError to ARNETWORK_ERROR_BAD_PARAMETER and stop the processing
    
    if (localError == ARCONTROLLER_OK)
    {
        // Create the Network Controller
        networkController = malloc (sizeof (ARCONTROLLER_Network_t));
        if (networkController != NULL)
        {
            // Initialize to default values
            networkController->discoveryDevice = NULL;
            networkController->networkALManager = NULL;
            networkController->networkManager = NULL;
            networkController->rxThread = NULL;
            networkController->txThread = NULL;
            networkController->readerThreads = NULL;
            networkController->readerThreadsData = NULL;
            networkController->state = ARCONTROLLER_NETWORK_STATE_RUNNING;
            
            //video part
            networkController->hasVideo = 0;
            networkController->videoController = NULL;
            
            //Connection callback
            networkController->sendJsonCallback = sendJsonCallback;
            networkController->receiveJsonCallback = receiveJsonCallback;
            networkController->disconnectionCallback = disconnectionCallback;
            networkController->callbacksCustomData = customData;
            
            // init networkConfiguration
            networkController->networkConfig.controllerToDeviceNotAckId = -1;
            networkController->networkConfig.controllerToDeviceAckId = -1;
            networkController->networkConfig.controllerToDeviceHightPriority = -1;
            networkController->networkConfig.controllerToDeviceARStreamAck = -1;
            networkController->networkConfig.deviceToControllerNotAckId = -1;
            networkController->networkConfig.deviceToControllerAckId = -1;
            //networkController->networkConfig.deviceToControllerHightPriority = -1;
            networkController->networkConfig.deviceToControllerARStreamData = -1;
            networkController->networkConfig.numberOfControllerToDeviceParam = 0;
            networkController->networkConfig.controllerToDeviceParams = NULL;
            networkController->networkConfig.numberOfDeviceToControllerParam  = 0;
            networkController->networkConfig.deviceToControllerParams = NULL;
            networkController->networkConfig.pingDelayMs =-1;
            networkController->networkConfig.numberOfDeviceToControllerCommandsBufferIds = 0;
            networkController->networkConfig.deviceToControllerCommandsBufferIds = NULL;
            
            /* Create the mutex/condition */
            if ( (localError == ARCONTROLLER_OK) &&
                 (ARSAL_Mutex_Init (&(networkController->mutex)) != 0))
            {
                localError = ARCONTROLLER_ERROR_INIT_MUTEX;
            }
        }
        else
        {
            localError = ARCONTROLLER_ERROR_ALLOC;
        }
    }
    
    if (localError == ARCONTROLLER_OK)
    {
        // Copy the device
        eARDISCOVERY_ERROR dicoveryError = ARDISCOVERY_OK;
        
        networkController->discoveryDevice = ARDISCOVERY_Device_NewByCopy (discoveryDevice, &dicoveryError);
        if (dicoveryError != ARDISCOVERY_OK)
        {
            localError = ARCONTROLLER_ERROR_INIT_DEVICE_COPY;
        }
    }
    
    // Check if it is a wifi device
    if ((localError == ARCONTROLLER_OK) && 
        (ARDISCOVERY_getProductService (networkController->discoveryDevice->productID) == ARDISCOVERY_PRODUCT_NSNETSERVICE))
    {
        // Add callbacks for the connection json part
        dicoveryError = ARDISCOVERY_Device_WifiAddConnectionCallbacks (networkController->discoveryDevice, ARCONTROLLER_Network_OnSendJson, ARCONTROLLER_Network_OnReceiveJson, networkController);
        if (dicoveryError != ARDISCOVERY_OK)
        {
            localError = ARCONTROLLER_ERROR_INIT_DEVICE_JSON_CALLBACK;
        }
    }
    
    if (localError == ARCONTROLLER_OK)
    {
        // Initialize the network Configuration
        eARDISCOVERY_ERROR dicoveryError = ARDISCOVERY_OK;
        dicoveryError = ARDISCOVERY_Device_InitNetworkCongifuration (networkController->discoveryDevice, &(networkController->networkConfig));
        if (dicoveryError != ARDISCOVERY_OK)
        {
            localError = ARCONTROLLER_ERROR_INIT_NETWORK_CONFIG;
        }
    }
    
    if (localError == ARCONTROLLER_OK)
    {
        // Check if the device has video
        if (networkController->networkConfig.deviceToControllerARStreamData != -1)
        {
            networkController->hasVideo = 1;
            networkController->videoController = ARCONTROLLER_Stream_New (&(networkController->networkConfig), &localError);
        }
        //NO else ; device has not video
    }
    // No else: skipped by an error
    
    if (localError == ARCONTROLLER_OK)
    {
        // Create the NetworkAL
        eARDISCOVERY_ERROR dicoveryError = ARDISCOVERY_OK;
        eARNETWORKAL_ERROR netALError = ARNETWORKAL_OK;
        networkController->networkALManager = ARDISCOVERY_Device_NewARNetworkAL (networkController->discoveryDevice, &dicoveryError, &netALError);
        if (dicoveryError != ARDISCOVERY_OK)
        {
            if (netALError != ARNETWORKAL_OK)
            {
                ARSAL_PRINT (ARSAL_PRINT_ERROR, ARCONTROLLER_NETWORK_TAG, "error: %s", ARNETWORKAL_Error_ToString (netALError));
            }
            
            localError = ARCONTROLLER_ERROR_INIT_ARNETWORKAL_MANAGER;
        }
    }
    
    if (localError == ARCONTROLLER_OK)
    {
        // Create the ARNetworkManager.
        eARNETWORK_ERROR netError = ARNETWORK_OK;
        
        networkController->networkManager = ARNETWORK_Manager_New (networkController->networkALManager, networkController->networkConfig.numberOfControllerToDeviceParam, networkController->networkConfig.controllerToDeviceParams, networkController->networkConfig.numberOfDeviceToControllerParam, networkController->networkConfig.deviceToControllerParams, networkController->networkConfig.pingDelayMs, ARCONTROLLER_Network_OnDisconnectNetwork, networkController, &netError);
        if (netError != ARNETWORK_OK)
        {
            localError = ARCONTROLLER_ERROR_INIT_ARNETWORK_MANAGER;
        }
    }

    if (localError == ARCONTROLLER_OK)
    {
        // Create the Network receiver and transmitter Threads
        localError = ARCONTROLLER_Network_CreateNetworkThreads (networkController);
    }
    
    if (localError == ARCONTROLLER_OK)
    {
        // Create the reader Threads
        localError = ARCONTROLLER_Network_CreateReaderThreads (networkController);
    }
    
    if (localError == ARCONTROLLER_OK)
    {
        // Check if the device has video
        if (networkController->hasVideo)
        {
            localError = ARCONTROLLER_Stream_Start (networkController->videoController, networkController->networkManager);
        }
        //NO else ; device has not video
    }
    // No else: skipped by an error
    
    // delete the Network Controller if an error occurred
    if (localError != ARCONTROLLER_OK)
    {
        ARSAL_PRINT (ARSAL_PRINT_ERROR, ARCONTROLLER_NETWORK_TAG, "error: %s", ARCONTROLLER_Error_ToString (localError));
        ARCONTROLLER_Network_Delete (&networkController);
    }
    // No else: skipped by an error 

    // Return the error
    if (error != NULL)
    {
        *error = localError;
    }
    // No else: error is not returned 

    return networkController;
}