int ARSTREAM2_H264_NaluFifoPushFreeItem(ARSTREAM2_H264_NaluFifo_t *fifo, ARSTREAM2_H264_NaluFifoItem_t *item)
{
    if ((!fifo) || (!item))
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return -1;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    if (fifo->free)
    {
        fifo->free->prev = item;
        item->next = fifo->free;
    }
    else
    {
        item->next = NULL;
    }
    fifo->free = item;
    item->prev = NULL;

    ARSAL_Mutex_Unlock(&(fifo->mutex));

    return 0;
}
eARNETWORK_ERROR ARNETWORK_RingBuffer_PopFrontWithSize(ARNETWORK_RingBuffer_t *ringBuffer, uint8_t *dataPop, int dataSize)
{
    /* -- Pop the oldest data -- */

    /* local declarations */
    uint8_t *buffer = NULL;
    eARNETWORK_ERROR error = ARNETWORK_OK;

    ARSAL_Mutex_Lock(&(ringBuffer->mutex));

    if (!ARNETWORK_RingBuffer_IsEmptyUnlocked(ringBuffer))
    {
        if(dataPop != NULL)
        {
            /* get the address of the front data */
            buffer = ringBuffer->dataBuffer + (ringBuffer->indexOutput % (ringBuffer->numberOfCell * ringBuffer->cellSize));
            memcpy(dataPop, buffer, dataSize);
        }
        /* No else: the data popped is not returned  */
        (ringBuffer->indexOutput) += ringBuffer->cellSize;
        ARNETWORK_RingBuffer_NormalizeIndexes(ringBuffer);
    }
    else
    {
        error = ARNETWORK_ERROR_BUFFER_EMPTY;
    }

    ARSAL_Mutex_Unlock(&(ringBuffer->mutex));

    return error;
}
예제 #3
0
float ARSTREAM_Reader_GetEstimatedEfficiency (ARSTREAM_Reader_t *reader)
{
    if (reader == NULL)
    {
        return -1.0f;
    }
    float retVal = 1.0f;
    uint32_t totalPackets = 0;
    uint32_t usefulPackets = 0;
    int i;
    ARSAL_Mutex_Lock (&(reader->ackPacketMutex));
    for (i = 0; i < ARSTREAM_READER_EFFICIENCY_AVERAGE_NB_FRAMES; i++)
    {
        totalPackets += reader->efficiency_nbTotal [i];
        usefulPackets += reader->efficiency_nbUseful [i];
    }
    ARSAL_Mutex_Unlock (&(reader->ackPacketMutex));
    if (totalPackets == 0)
    {
        retVal = 0.0f; // We didn't receive anything yet ... not really efficient
    }
    else if (usefulPackets > totalPackets)
    {
        retVal = 1.0f; // If this happens, it means that we have a big problem
        ARSAL_PRINT (ARSAL_PRINT_ERROR, ARSTREAM_READER_TAG, "Computed efficiency is greater that 1.0 ...");
    }
    else
    {
        retVal = (1.f * usefulPackets) / (1.f * totalPackets);
    }
    return retVal;
}
int ARSTREAM2_H264_AuFifoAddQueue(ARSTREAM2_H264_AuFifo_t *fifo, ARSTREAM2_H264_AuFifoQueue_t *queue)
{
    if ((!fifo) || (!queue))
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return -1;
    }

    int mutexRet = ARSAL_Mutex_Init(&(queue->mutex));
    if (mutexRet != 0)
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Mutex creation failed (%d)", mutexRet);
        return -1;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    queue->count = 0;
    queue->head = NULL;
    queue->tail = NULL;
    queue->prev = NULL;
    queue->next = fifo->queue;
    if (queue->next)
    {
        queue->next->prev = queue;
    }

    fifo->queue = queue;
    fifo->queueCount++;

    ARSAL_Mutex_Unlock(&(fifo->mutex));

    return 0;
}
int ARSTREAM2_H264_AuFifoPushFreeItem(ARSTREAM2_H264_AuFifo_t *fifo, ARSTREAM2_H264_AuFifoItem_t *item)
{
    if ((!fifo) || (!item))
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return -1;
    }

    int ret = ARSTREAM2_H264_AuNaluFifoFlush(&item->au);
    if (ret != 0)
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "ARSTREAM2_H264_AuNaluFifoFlush() failed (%d)", ret);
        return -1;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    if (fifo->itemFree)
    {
        fifo->itemFree->prev = item;
        item->next = fifo->itemFree;
    }
    else
    {
        item->next = NULL;
    }
    fifo->itemFree = item;
    item->prev = NULL;

    ARSAL_Mutex_Unlock(&(fifo->mutex));

    return 0;
}
eARNETWORK_ERROR ARNETWORK_RingBuffer_Front(ARNETWORK_RingBuffer_t *ringBuffer, uint8_t *frontData)
{
    /* -- Return a pointer on the front data -- */

    /* local declarations */
    eARNETWORK_ERROR error = ARNETWORK_OK;
    uint8_t *buffer = NULL;

    ARSAL_Mutex_Lock(&(ringBuffer->mutex));

    /* get the address of the front data */
    buffer = ringBuffer->dataBuffer + (ringBuffer->indexOutput % (ringBuffer->numberOfCell * ringBuffer->cellSize));

    if( !ARNETWORK_RingBuffer_IsEmptyUnlocked(ringBuffer) )
    {
        memcpy(frontData, buffer, ringBuffer->cellSize);
    }
    else
    {
        error = ARNETWORK_ERROR_BUFFER_EMPTY;
    }

    ARSAL_Mutex_Unlock(&(ringBuffer->mutex));

    return error;
}
ARSTREAM2_H264_AuFifoItem_t* ARSTREAM2_H264_AuFifoPopFreeItem(ARSTREAM2_H264_AuFifo_t *fifo)
{
    if (!fifo)
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return NULL;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    if (fifo->itemFree)
    {
        ARSTREAM2_H264_AuFifoItem_t* cur = fifo->itemFree;
        fifo->itemFree = cur->next;
        if (cur->next) cur->next->prev = NULL;
        cur->prev = NULL;
        cur->next = NULL;
        ARSAL_Mutex_Unlock(&(fifo->mutex));
        return cur;
    }
    else
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "AU FIFO is full");
        ARSAL_Mutex_Unlock(&(fifo->mutex));
        return NULL;
    }
}
void ARNETWORK_RingBuffer_DataPrint(ARNETWORK_RingBuffer_t *ringBuffer)
{
    /* -- Print the contents of the ring buffer -- */

    /* local declarations */
    uint8_t *byteIterator = NULL;
    unsigned int cellIndex = 0;
    unsigned int byteIndex = 0;

    ARSAL_Mutex_Lock(&(ringBuffer->mutex));

    /* for all cell of the ringBuffer */
    for (cellIndex = ringBuffer->indexOutput ; cellIndex < ringBuffer->indexInput ; cellIndex += ringBuffer->cellSize )
    {
        byteIterator = ringBuffer->dataBuffer + (cellIndex % (ringBuffer->numberOfCell * ringBuffer->cellSize) );

        ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG,"    - 0x: ");

        /* for all byte of the cell */
        for(byteIndex = 0 ; byteIndex < ringBuffer->cellSize ; ++byteIndex)
        {
            ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG,"%2x | ",*((uint8_t*)byteIterator));
            ++byteIterator;
        }
        ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG,"\n");
    }

    ARSAL_Mutex_Unlock(&(ringBuffer->mutex));
}
int ARSTREAM2_H264_AuFifoEnqueueItem(ARSTREAM2_H264_AuFifoQueue_t *queue, ARSTREAM2_H264_AuFifoItem_t *item)
{
    if ((!queue) || (!item))
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return -1;
    }

    ARSAL_Mutex_Lock(&(queue->mutex));

    item->next = NULL;
    if (queue->tail)
    {
        queue->tail->next = item;
        item->prev = queue->tail;
    }
    else
    {
        item->prev = NULL;
    }
    queue->tail = item;
    if (!queue->head)
    {
        queue->head = item;
    }
    queue->count++;

    ARSAL_Mutex_Unlock(&(queue->mutex));

    return 0;
}
ARSTREAM2_H264_AuFifoBuffer_t* ARSTREAM2_H264_AuFifoGetBuffer(ARSTREAM2_H264_AuFifo_t *fifo)
{
    if (!fifo)
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return NULL;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    if (fifo->bufferFree)
    {
        ARSTREAM2_H264_AuFifoBuffer_t* cur = fifo->bufferFree;
        fifo->bufferFree = cur->next;
        if (cur->next) cur->next->prev = NULL;
        cur->prev = NULL;
        cur->next = NULL;
        cur->refCount = 1;
        ARSAL_Mutex_Unlock(&(fifo->mutex));
        return cur;
    }
    else
    {
        ARSAL_Mutex_Unlock(&(fifo->mutex));
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "No free buffer in pool");
        return NULL;
    }
}
예제 #11
0
void* ARSTREAM_Reader_RunAckThread (void *ARSTREAM_Reader_t_Param)
{
    ARSTREAM_NetworkHeaders_AckPacket_t sendPacket = {0};
    ARSTREAM_Reader_t *reader = (ARSTREAM_Reader_t *)ARSTREAM_Reader_t_Param;
    memset(&sendPacket, 0, sizeof(sendPacket));

    ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Ack sender thread running");
    reader->ackThreadStarted = 1;

    while (reader->threadsShouldStop == 0)
    {
        int isPeriodicAck = 0;
        ARSAL_Mutex_Lock (&(reader->ackSendMutex));
        if (reader->maxAckInterval <= 0)
        {
            ARSAL_Cond_Wait (&(reader->ackSendCond), &(reader->ackSendMutex));
        }
        else
        {
            int retval = ARSAL_Cond_Timedwait (&(reader->ackSendCond), &(reader->ackSendMutex), reader->maxAckInterval);
            if (retval == -1 && errno == ETIMEDOUT)
            {
                isPeriodicAck = 1;
            }
        }
        ARSAL_Mutex_Unlock (&(reader->ackSendMutex));

        /* Only send an ACK if the maxAckInterval value allows it. */
        if ((reader->maxAckInterval > 0) ||
            ((reader->maxAckInterval == 0) && (isPeriodicAck == 0)))
        {
            ARSAL_Mutex_Lock (&(reader->ackPacketMutex));
            sendPacket.frameNumber = htods  (reader->ackPacket.frameNumber);
            sendPacket.highPacketsAck = htodll (reader->ackPacket.highPacketsAck);
            sendPacket.lowPacketsAck  = htodll (reader->ackPacket.lowPacketsAck);
            ARSAL_Mutex_Unlock (&(reader->ackPacketMutex));
            ARNETWORK_Manager_SendData (reader->manager, reader->ackBufferID, (uint8_t *)&sendPacket, sizeof (sendPacket), NULL, ARSTREAM_Reader_NetworkCallback, 1);
        }
    }

    ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Ack sender thread ended");
    reader->ackThreadStarted = 0;
    return (void *)0;
}
void ARNETWORK_Sender_GotPingAck (ARNETWORK_Sender_t *senderPtr, struct timespec *startTime, struct timespec *endTime)
{
    ARSAL_Mutex_Lock (&(senderPtr->pingMutex));
    if ((senderPtr->isPingRunning == 1) &&
        (ARSAL_Time_TimespecEquals (startTime, &(senderPtr->pingStartTime))))
    {
        senderPtr->lastPingValue = ARSAL_Time_ComputeTimespecMsTimeDiff (startTime, endTime);
        senderPtr->isPingRunning = 0;
    }
    ARSAL_Mutex_Unlock (&(senderPtr->pingMutex));
}
int ARNETWORK_RingBuffer_GetFreeCellNumber(ARNETWORK_RingBuffer_t *ringBuffer)
{
    int numberOfFreeCell = -1;
    
    ARSAL_Mutex_Lock(&(ringBuffer->mutex));
    
    numberOfFreeCell = ringBuffer->numberOfCell - ( (ringBuffer->indexInput - ringBuffer->indexOutput) / ringBuffer->cellSize );
    
    ARSAL_Mutex_Unlock(&(ringBuffer->mutex));
    
    return numberOfFreeCell;
}
int ARNETWORK_RingBuffer_IsEmpty(ARNETWORK_RingBuffer_t *ringBuffer)
{
    int isEmpty = 0;
    
    ARSAL_Mutex_Lock(&(ringBuffer->mutex));
    
    isEmpty = (ringBuffer->indexInput == ringBuffer->indexOutput) ? 1 : 0;
    
    ARSAL_Mutex_Unlock(&(ringBuffer->mutex));
    
    return isEmpty;
}
예제 #15
0
void ARSTREAM_Reader_StopReader (ARSTREAM_Reader_t *reader)
{
    if (reader != NULL)
    {
        reader->threadsShouldStop = 1;
        /* Force unblock the ACK thread to allow it to shutdown quickly.
         * This is necessary if maxAckInterval is set to -1, 0 or a large value.
         * If maxAckInterval >= 0, an ACK packet will be sent as a side-effect. */
        if (reader->ackThreadStarted == 1)
        {
            ARSAL_Mutex_Lock (&(reader->ackSendMutex));
            ARSAL_Cond_Signal (&(reader->ackSendCond));
            ARSAL_Mutex_Unlock (&(reader->ackSendMutex));
        }
    }
}
int ARSTREAM2_H264_AuFifoBufferAddRef(ARSTREAM2_H264_AuFifo_t *fifo, ARSTREAM2_H264_AuFifoBuffer_t *buffer)
{
    if (!buffer)
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return -1;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    buffer->refCount++;

    ARSAL_Mutex_Unlock(&(fifo->mutex));

    return 0;
}
예제 #17
0
int ARSAL_Sem_Getvalue(ARSAL_Sem_t *sem, int *value)
{
    int result = -1;

    if (NULL == sem || NULL == *sem || NULL == value)
    {
        errno = EINVAL;
        return result;
    }
    /* No else. */

#if __SAL_USE_POSIX_SEM

    result = sem_getvalue((sem_t *)*sem, value);

#else

    /*
     * Custom getvalue algo:
     * Lock mutex
     * Read counter to *value
     * Unlock mutex
     */

    ARSAL_Sem_CustomImpl_t *psem = (ARSAL_Sem_CustomImpl_t *)*sem;
    int unlockRes = 0;
    result = ARSAL_Mutex_Lock (&(psem->lock));
    ARSAL_SEM_ERRNO_TRANSFORM (result);

    if (0 == result)
    {
        *value = psem->count;
    }
    /* No else. */

    unlockRes = ARSAL_Mutex_Unlock (&(psem->lock));
    if (0 != unlockRes)
    {
        result = -1;
        errno = unlockRes;
    }
    /* No else. */

#endif

    return result;
}
eARCONTROLLER_ERROR ARCONTROLLER_Network_Resume (ARCONTROLLER_Network_t *networkController)
{
    // -- Resumes the Network Controller --
    
    eARCONTROLLER_ERROR error = ARCONTROLLER_OK;
    
    // 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;
        }
    }
    
    if (error == ARCONTROLLER_OK)
    {
        switch (networkController->state)
        {
            case ARCONTROLLER_NETWORK_STATE_PAUSE:
                networkController->state = ARCONTROLLER_NETWORK_STATE_RUNNING;
                break;
                
            case ARCONTROLLER_NETWORK_STATE_RUNNING:
                ARSAL_PRINT(ARSAL_PRINT_WARNING, ARCONTROLLER_NETWORK_TAG, "Nothing to do ; Network controller state : %d ", networkController->state);
                break;
                
            case ARCONTROLLER_NETWORK_STATE_STOPPED:
                error = ARCONTROLLER_ERROR_STATE;
                break;
            
            default:
                ARSAL_PRINT(ARSAL_PRINT_ERROR, ARCONTROLLER_NETWORK_TAG, "State : %d not known", networkController->state);
                break;
        }
        
        ARSAL_Mutex_Unlock (&(networkController->mutex));
    }
    
    return error;
}
eARCONTROLLER_ERROR ARCONTROLLER_Network_SetVideoReceiveCallback (ARCONTROLLER_Network_t *networkController, ARCONTROLLER_Stream_DecoderConfigCallback_t decoderConfigCallback, ARCONTROLLER_Stream_DidReceiveFrameCallback_t receiveFrameCallback, ARCONTROLLER_Stream_TimeoutFrameCallback_t timeoutFrameCallback, void *customData)
{
    // -- Set Video Receive Callback --
    
    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)
    {
        if (networkController->videoController != NULL)
        {
            error = ARCONTROLLER_Stream_SetReceiveFrameCallback (networkController->videoController, decoderConfigCallback, receiveFrameCallback, timeoutFrameCallback, customData);
        }
        else
        {
            error = ARCONTROLLER_ERROR_NO_VIDEO;
        }
    }
        
    if (locked)
    {
        ARSAL_Mutex_Unlock (&(networkController->mutex));
    }
    
    return error;
}
void ARNETWORK_RingBuffer_Print(ARNETWORK_RingBuffer_t *ringBuffer)
{
    /* -- Print the state of the ring buffer -- */

    ARSAL_Mutex_Lock(&(ringBuffer->mutex));

    ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG," pointer dataBuffer :%p \n",ringBuffer->dataBuffer);
    ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG," numberOfCell :%d \n",ringBuffer->numberOfCell);
    ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG," cellSize :%d \n",ringBuffer->cellSize);
    ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG," indexOutput :%d \n",ringBuffer->indexOutput);
    ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG," indexInput :%d \n",ringBuffer->indexInput);
    ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG," overwriting :%d \n",ringBuffer->isOverwriting);
    ARSAL_PRINT(ARSAL_PRINT_WARNING, ARNETWORK_RINGBUFFER_TAG," data : \n");

    ARSAL_Mutex_Unlock(&(ringBuffer->mutex));

    ARNETWORK_RingBuffer_DataPrint(ringBuffer);
}
int ARNETWORK_Sender_GetPing (ARNETWORK_Sender_t *senderPtr)
{
    int retVal = -1;
    ARSAL_Mutex_Lock (&(senderPtr->pingMutex));
    if (senderPtr->isPingRunning == 1)
    {
        struct timespec now;
        ARSAL_Time_GetTime(&now);
        retVal = ARSAL_Time_ComputeTimespecMsTimeDiff (&(senderPtr->pingStartTime), &now);
    }
    if ((senderPtr->lastPingValue > retVal) ||
        (senderPtr->lastPingValue == -1))
    {
        retVal = senderPtr->lastPingValue;
    }
    ARSAL_Mutex_Unlock (&(senderPtr->pingMutex));
    return retVal;
}
eARCONTROLLER_ERROR ARCONTROLLER_Network_SetVideoStreamMP4Compliant (ARCONTROLLER_Network_t *networkController, int isMP4Compliant)
{
    // -- Set video stream compliant with the mp4 format --
    
    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 ARCONTROLLER_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_SetMP4Compliant (networkController->videoController, isMP4Compliant);
        }
        //NO else ; device has not video
    }
    // No else: skipped by an error
    
    if (locked)
    {
        ARSAL_Mutex_Unlock (&(networkController->mutex));
    }
    
    return error;
}
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;
}
eARNETWORK_ERROR ARNETWORK_RingBuffer_PushBackWithSize(ARNETWORK_RingBuffer_t *ringBuffer, const uint8_t *newData, int dataSize, uint8_t **dataCopy)
{
    /* -- Add the new data at the back of the ring buffer with specification of the data size -- */

    /* local declarations */
    int error = ARNETWORK_OK;
    uint8_t* buffer = NULL;

    ARSAL_Mutex_Lock(&(ringBuffer->mutex));

    /* check if the has enough free cell or the buffer is overwriting */
    if ((ARNETWORK_RingBuffer_GetFreeCellNumberUnlocked(ringBuffer)) || (ringBuffer->isOverwriting))
    {
        if (!ARNETWORK_RingBuffer_GetFreeCellNumberUnlocked(ringBuffer))
        {
            (ringBuffer->indexOutput) += ringBuffer->cellSize;
        }
        /* No else: the ringBuffer is not full */

        buffer = ringBuffer->dataBuffer + ( ringBuffer->indexInput % (ringBuffer->numberOfCell * ringBuffer->cellSize) );

        memcpy(buffer, newData, dataSize);

        /* return the pointer on the data copy in the ring buffer */
        if(dataCopy != NULL)
        {
            *dataCopy = buffer;
        }
        /* No else: data are not returned */

        ringBuffer->indexInput += ringBuffer->cellSize;
        ARNETWORK_RingBuffer_NormalizeIndexes(ringBuffer);
    }
    else
    {
        error = ARNETWORK_ERROR_BUFFER_SIZE;
    }

    ARSAL_Mutex_Unlock(&(ringBuffer->mutex));

    return error;
}
ARSTREAM2_H264_AuFifoItem_t* ARSTREAM2_H264_AuFifoDequeueItem(ARSTREAM2_H264_AuFifoQueue_t *queue)
{
    ARSTREAM2_H264_AuFifoItem_t* cur;

    if (!queue)
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return NULL;
    }

    ARSAL_Mutex_Lock(&(queue->mutex));

    if ((!queue->head) || (!queue->count))
    {
        ARSAL_Mutex_Unlock(&(queue->mutex));
        //ARSAL_PRINT(ARSAL_PRINT_VERBOSE, ARSTREAM2_H264_TAG, "FIFO is empty");
        return NULL;
    }

    cur = queue->head;
    if (cur->next)
    {
        cur->next->prev = NULL;
        queue->head = cur->next;
        queue->count--;
    }
    else
    {
        queue->head = NULL;
        queue->count = 0;
        queue->tail = NULL;
    }
    cur->prev = NULL;
    cur->next = NULL;

    ARSAL_Mutex_Unlock(&(queue->mutex));

    return cur;
}
ARSTREAM2_H264_NaluFifoItem_t* ARSTREAM2_H264_NaluFifoDequeueItem(ARSTREAM2_H264_NaluFifo_t *fifo)
{
    ARSTREAM2_H264_NaluFifoItem_t* cur;

    if (!fifo)
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return NULL;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    if ((!fifo->head) || (!fifo->count))
    {
        ARSAL_Mutex_Unlock(&(fifo->mutex));
        //ARSAL_PRINT(ARSAL_PRINT_VERBOSE, ARSTREAM2_H264_TAG, "NALU FIFO is empty");
        return NULL;
    }

    cur = fifo->head;
    if (cur->next)
    {
        cur->next->prev = NULL;
        fifo->head = cur->next;
        fifo->count--;
    }
    else
    {
        fifo->head = NULL;
        fifo->count = 0;
        fifo->tail = NULL;
    }
    cur->prev = NULL;
    cur->next = NULL;

    ARSAL_Mutex_Unlock(&(fifo->mutex));

    return cur;
}
int ARSTREAM2_H264_NaluFifoEnqueueItem(ARSTREAM2_H264_NaluFifo_t *fifo, ARSTREAM2_H264_NaluFifoItem_t *item)
{
    if ((!fifo) || (!item))
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return -1;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    if (fifo->count >= fifo->size)
    {
        ARSAL_Mutex_Unlock(&(fifo->mutex));
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "NALU FIFO is full");
        return -2;
    }

    item->next = NULL;
    if (fifo->tail)
    {
        fifo->tail->next = item;
        item->prev = fifo->tail;
    }
    else
    {
        item->prev = NULL;
    }
    fifo->tail = item;
    if (!fifo->head)
    {
        fifo->head = item;
    }
    fifo->count++;

    ARSAL_Mutex_Unlock(&(fifo->mutex));

    return 0;
}
int ARSTREAM2_H264_AuFifoUnrefBuffer(ARSTREAM2_H264_AuFifo_t *fifo, ARSTREAM2_H264_AuFifoBuffer_t *buffer)
{
    if ((!fifo) || (!buffer))
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return -1;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    if (buffer->refCount != 0)
    {
        buffer->refCount--;
    }
    else
    {
        ARSAL_PRINT(ARSAL_PRINT_WARNING, ARSTREAM2_H264_TAG, "FIXME! Ref count is already null, this should not happen!");
    }

    if (buffer->refCount == 0)
    {
        if (fifo->bufferFree)
        {
            fifo->bufferFree->prev = buffer;
            buffer->next = fifo->bufferFree;
        }
        else
        {
            buffer->next = NULL;
        }
        fifo->bufferFree = buffer;
        buffer->prev = NULL;
    }

    ARSAL_Mutex_Unlock(&(fifo->mutex));

    return 0;
}
int ARSTREAM2_H264_AuFifoRemoveQueue(ARSTREAM2_H264_AuFifo_t *fifo, ARSTREAM2_H264_AuFifoQueue_t *queue)
{
    if ((!fifo) || (!queue))
    {
        ARSAL_PRINT(ARSAL_PRINT_ERROR, ARSTREAM2_H264_TAG, "Invalid pointer");
        return -1;
    }

    ARSAL_Mutex_Lock(&(fifo->mutex));

    if (queue->prev)
    {
        queue->prev->next = queue->next;
    }
    if (queue->next)
    {
        queue->next->prev = queue->prev;
    }
    if ((!queue->prev) && (!queue->next))
    {
        fifo->queue = NULL;
    }
    fifo->queueCount--;

    queue->prev = NULL;
    queue->next = NULL;
    queue->count = 0;
    queue->head = NULL;
    queue->tail = NULL;

    ARSAL_Mutex_Unlock(&(fifo->mutex));

    ARSAL_Mutex_Destroy(&(queue->mutex));

    return 0;
}
예제 #30
0
void* ARSTREAM_Reader_RunDataThread (void *ARSTREAM_Reader_t_Param)
{
    uint8_t *recvData = NULL;
    int recvSize;
    uint16_t previousFNum = UINT16_MAX;
    int skipCurrentFrame = 0;
    int packetWasAlreadyAck = 0;
    ARSTREAM_Reader_t *reader = (ARSTREAM_Reader_t *)ARSTREAM_Reader_t_Param;
    ARSTREAM_NetworkHeaders_DataHeader_t *header = NULL;
    int recvDataLen = reader->maxFragmentSize + sizeof (ARSTREAM_NetworkHeaders_DataHeader_t);

    /* Parameters check */
    if (reader == NULL)
    {
        ARSAL_PRINT (ARSAL_PRINT_ERROR, ARSTREAM_READER_TAG, "Error while starting %s, bad parameters", __FUNCTION__);
        return (void *)0;
    }

    /* Alloc and check */
    recvData = malloc (recvDataLen);
    if (recvData == NULL)
    {
        ARSAL_PRINT (ARSAL_PRINT_ERROR, ARSTREAM_READER_TAG, "Error while starting %s, can not alloc memory", __FUNCTION__);
        return (void *)0;
    }
    header = (ARSTREAM_NetworkHeaders_DataHeader_t *)recvData;

    ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Stream reader thread running");
    reader->dataThreadStarted = 1;

    while (reader->threadsShouldStop == 0)
    {
        eARNETWORK_ERROR err = ARNETWORK_Manager_ReadDataWithTimeout (reader->manager, reader->dataBufferID, recvData, recvDataLen, &recvSize, ARSTREAM_READER_DATAREAD_TIMEOUT_MS);
        if (ARNETWORK_OK != err)
        {
            if (ARNETWORK_ERROR_BUFFER_EMPTY != err)
            {
                ARSAL_PRINT (ARSAL_PRINT_ERROR, ARSTREAM_READER_TAG, "Error while reading stream data: %s", ARNETWORK_Error_ToString (err));
            }
        }
        else
        {
            int cpIndex, cpSize, endIndex;
            ARSAL_Mutex_Lock (&(reader->ackPacketMutex));
            if (header->frameNumber != reader->ackPacket.frameNumber)
            {
                reader->efficiency_index ++;
                reader->efficiency_index %= ARSTREAM_READER_EFFICIENCY_AVERAGE_NB_FRAMES;
                reader->efficiency_nbTotal [reader->efficiency_index] = 0;
                reader->efficiency_nbUseful [reader->efficiency_index] = 0;
                skipCurrentFrame = 0;
                reader->currentFrameSize = 0;
                reader->ackPacket.frameNumber = header->frameNumber;
#ifdef DEBUG
                uint32_t nackPackets = ARSTREAM_NetworkHeaders_AckPacketCountNotSet (&(reader->ackPacket), header->fragmentsPerFrame);
                if (nackPackets != 0)
                {
                    ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Dropping a frame (missing %d fragments)", nackPackets);
                }
#endif
                ARSTREAM_NetworkHeaders_AckPacketResetUpTo (&(reader->ackPacket), header->fragmentsPerFrame);
            }
            packetWasAlreadyAck = ARSTREAM_NetworkHeaders_AckPacketFlagIsSet (&(reader->ackPacket), header->fragmentNumber);
            ARSTREAM_NetworkHeaders_AckPacketSetFlag (&(reader->ackPacket), header->fragmentNumber);

            reader->efficiency_nbTotal [reader->efficiency_index] ++;
            if (packetWasAlreadyAck == 0)
            {
                reader->efficiency_nbUseful [reader->efficiency_index] ++;
            }

            ARSAL_Mutex_Unlock (&(reader->ackPacketMutex));

            ARSAL_Mutex_Lock (&(reader->ackSendMutex));
            ARSAL_Cond_Signal (&(reader->ackSendCond));
            ARSAL_Mutex_Unlock (&(reader->ackSendMutex));


            cpIndex = reader->maxFragmentSize * header->fragmentNumber;
            cpSize = recvSize - sizeof (ARSTREAM_NetworkHeaders_DataHeader_t);
            endIndex = cpIndex + cpSize;
            while ((endIndex > reader->currentFrameBufferSize) &&
                   (skipCurrentFrame == 0) &&
                   (packetWasAlreadyAck == 0))
            {
                uint32_t nextFrameBufferSize = reader->maxFragmentSize * header->fragmentsPerFrame;
                uint32_t dummy;
                uint8_t *nextFrameBuffer = reader->callback (ARSTREAM_READER_CAUSE_FRAME_TOO_SMALL, reader->currentFrameBuffer, reader->currentFrameSize, 0, 0, &nextFrameBufferSize, reader->custom);
                if (nextFrameBufferSize >= reader->currentFrameSize && nextFrameBufferSize > 0)
                {
                    memcpy (nextFrameBuffer, reader->currentFrameBuffer, reader->currentFrameSize);
                }
                else
                {
                    skipCurrentFrame = 1;
                }
                //TODO: Add "SKIP_FRAME"
                reader->callback (ARSTREAM_READER_CAUSE_COPY_COMPLETE, reader->currentFrameBuffer, reader->currentFrameSize, 0, skipCurrentFrame, &dummy, reader->custom);
                reader->currentFrameBuffer = nextFrameBuffer;
                reader->currentFrameBufferSize = nextFrameBufferSize;
            }

            if (skipCurrentFrame == 0)
            {
                if (packetWasAlreadyAck == 0)
                {
                    memcpy (&(reader->currentFrameBuffer)[cpIndex], &recvData[sizeof (ARSTREAM_NetworkHeaders_DataHeader_t)], recvSize - sizeof (ARSTREAM_NetworkHeaders_DataHeader_t));
                }

                if (endIndex > reader->currentFrameSize)
                {
                    reader->currentFrameSize = endIndex;
                }

                ARSAL_Mutex_Lock (&(reader->ackPacketMutex));
                if (ARSTREAM_NetworkHeaders_AckPacketAllFlagsSet (&(reader->ackPacket), header->fragmentsPerFrame))
                {
                    if (header->frameNumber != previousFNum)
                    {
                        int nbMissedFrame = 0;
                        int isFlushFrame = ((header->frameFlags & ARSTREAM_NETWORK_HEADERS_FLAG_FLUSH_FRAME) != 0) ? 1 : 0;
                        ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Ack all in frame %d (isFlush : %d)", header->frameNumber, isFlushFrame);
                        if (header->frameNumber != previousFNum + 1)
                        {
                            nbMissedFrame = header->frameNumber - previousFNum - 1;
                            ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Missed %d frames !", nbMissedFrame);
                        }
                        previousFNum = header->frameNumber;
                        skipCurrentFrame = 1;
                        reader->currentFrameBuffer = reader->callback (ARSTREAM_READER_CAUSE_FRAME_COMPLETE, reader->currentFrameBuffer, reader->currentFrameSize, nbMissedFrame, isFlushFrame, &(reader->currentFrameBufferSize), reader->custom);
                    }
                }
                ARSAL_Mutex_Unlock (&(reader->ackPacketMutex));
            }
        }
    }

    free (recvData);

    reader->callback (ARSTREAM_READER_CAUSE_CANCEL, reader->currentFrameBuffer, reader->currentFrameSize, 0, 0, &(reader->currentFrameBufferSize), reader->custom);

    ARSAL_PRINT (ARSAL_PRINT_DEBUG, ARSTREAM_READER_TAG, "Stream reader thread ended");
    reader->dataThreadStarted = 0;
    return (void *)0;
}