DataFrameHandle Kvs_streamAddDataFrame()

in src/source/stream/stream.c [191:317]


DataFrameHandle Kvs_streamAddDataFrame(StreamHandle xStreamHandle, DataFrameIn_t *pxDataFrameIn)
{
    int xRes = KVS_ERRNO_NONE;
    Stream_t *pxStream = xStreamHandle;
    DataFrame_t *pxDataFrame = NULL;
    size_t uMkvHdrLen = 0;
    DataFrame_t *pxDataFrameCurrent = NULL;
    PDLIST_ENTRY pxListHead = NULL;
    PDLIST_ENTRY pxListItem = NULL;
    bool bListAdded = false;
    bool bNeedCorrectDeltaTimestamp = false;
    bool bCorrectDeltaTimestampStarted = false;
    uint64_t uClusterTimestamp = 0;
    uint16_t uDeltaTimestampMs = 0;

    if (pxStream == NULL || pxDataFrameIn == NULL)
    {
        LogError("Invalid argument");
        xRes = KVS_ERRNO_FAIL;
    }
    else if ((uMkvHdrLen = Mkv_getClusterHdrLen(pxDataFrameIn->xClusterType)) == 0 || (pxDataFrame = (DataFrame_t *)kvsMalloc(sizeof(DataFrame_t) + uMkvHdrLen)) == NULL)
    {
        LogError("Failed to create data frame");
        xRes = KVS_ERRNO_FAIL;
    }
    else if (Lock(pxStream->xLock) != LOCK_OK)
    {
        LogError("Failed to Lock");
        xRes = KVS_ERRNO_FAIL;
    }
    else
    {
        memset(pxDataFrame, 0, sizeof(DataFrame_t));
        memcpy(pxDataFrame, pxDataFrameIn, sizeof(DataFrameIn_t));
        DList_InitializeListHead(&(pxDataFrame->xClusterEntry));
        DList_InitializeListHead(&(pxDataFrame->xDataFrameEntry));
        pxDataFrame->uMkvHdrLen = uMkvHdrLen;
        pxDataFrame->pMkvHdr = (char *)pxDataFrame + sizeof(DataFrame_t);
        uClusterTimestamp = pxStream->uEarliestClusterTimestamp;

        pxListHead = &(pxStream->xDataFramePending);
        pxListItem = pxListHead->Flink;
        while (pxListItem != pxListHead)
        {
            pxDataFrameCurrent = containingRecord(pxListItem, DataFrame_t, xDataFrameEntry);
            if (pxDataFrame->xDataFrameIn.uTimestampMs < pxDataFrameCurrent->xDataFrameIn.uTimestampMs ||
                ((pxDataFrame->xDataFrameIn.uTimestampMs == pxDataFrameCurrent->xDataFrameIn.uTimestampMs) && (pxDataFrame->xDataFrameIn.xTrackType == TRACK_VIDEO)))
            {
                DList_InsertTailList(pxListItem, &(pxDataFrame->xDataFrameEntry));
                uDeltaTimestampMs = (uint16_t)(pxDataFrame->xDataFrameIn.uTimestampMs - uClusterTimestamp);
                if (pxDataFrame->xDataFrameIn.xClusterType == MKV_CLUSTER)
                {
                    uDeltaTimestampMs = 0;

                    /* If we insert a cluster head, then the following frames's delta timestamp needs updates. */
                    bNeedCorrectDeltaTimestamp = true;
                }
                bListAdded = true;
                break;
            }
            if (pxDataFrameCurrent->xDataFrameIn.xClusterType == MKV_CLUSTER)
            {
                uClusterTimestamp = pxDataFrameCurrent->xDataFrameIn.uTimestampMs;
            }
            pxListItem = pxListItem->Flink;
        }
        if (!bListAdded)
        {
            uDeltaTimestampMs = (uint16_t)(pxDataFrame->xDataFrameIn.uTimestampMs - uClusterTimestamp);
            DList_InsertTailList(&(pxStream->xDataFramePending), &(pxDataFrame->xDataFrameEntry));
            bListAdded = true;
        }

        Mkv_initializeClusterHdr(
            (uint8_t *)(pxDataFrame->pMkvHdr),
            pxDataFrame->uMkvHdrLen,
            pxDataFrameIn->xClusterType,
            pxDataFrameIn->uDataLen,
            pxDataFrameIn->xTrackType,
            pxDataFrameIn->bIsKeyFrame,
            pxDataFrameIn->uTimestampMs,
            uDeltaTimestampMs);

        if (bNeedCorrectDeltaTimestamp)
        {
            bCorrectDeltaTimestampStarted = false;
            pxListHead = &(pxStream->xDataFramePending);
            pxListItem = pxListHead->Flink;
            while (pxListItem != pxListHead)
            {
                pxDataFrameCurrent = containingRecord(pxListItem, DataFrame_t, xDataFrameEntry);
                if (pxDataFrameCurrent->xDataFrameIn.xClusterType == MKV_CLUSTER)
                {
                    uClusterTimestamp = pxDataFrameCurrent->xDataFrameIn.uTimestampMs;
                    bCorrectDeltaTimestampStarted = true;
                }
                if (bCorrectDeltaTimestampStarted)
                {
                    uDeltaTimestampMs = (uint16_t)(pxDataFrameCurrent->xDataFrameIn.uTimestampMs - uClusterTimestamp);
                    Mkv_initializeClusterHdr(
                        (uint8_t *)(pxDataFrameCurrent->pMkvHdr),
                        pxDataFrameCurrent->uMkvHdrLen,
                        pxDataFrameCurrent->xDataFrameIn.xClusterType,
                        pxDataFrameCurrent->xDataFrameIn.uDataLen,
                        pxDataFrameCurrent->xDataFrameIn.xTrackType,
                        pxDataFrameCurrent->xDataFrameIn.bIsKeyFrame,
                        pxDataFrameCurrent->xDataFrameIn.uTimestampMs,
                        uDeltaTimestampMs);
                }
                pxListItem = pxListItem->Flink;
            }
        }

        Unlock(pxStream->xLock);
    }

    if (xRes != KVS_ERRNO_NONE)
    {
        if (pxDataFrame != NULL)
        {
            kvsFree(pxDataFrame);
            pxDataFrame = NULL;
        }
    }

    return pxDataFrame;
}