static int prvCreateAudioTrackEntry()

in src/source/mkv/mkv_generator.c [434:536]


static int prvCreateAudioTrackEntry(AudioTrackInfo_t *pAudioTrackInfo, uint8_t **ppBuf, uint32_t *pBufLen)
{
    int xRes = KVS_ERRNO_NONE;
    uint32_t uHeaderLen = 0;
    uint8_t *pHeader = NULL;
    uint8_t *pIdx = NULL;
    uint32_t uAudioHeaderLen = 0;
    bool bHasCodecPrivateData = false;
    bool bHasBitsPerSampleField = false;
    double audioFrequency = 0.0;

    if (pAudioTrackInfo == NULL || ppBuf == NULL || pBufLen == NULL)
    {
        LogError("Invalid argument");
        xRes = KVS_ERRNO_FAIL;
    }
    else
    {
        if (pAudioTrackInfo->pCodecPrivate != NULL && pAudioTrackInfo->uCodecPrivateLen != 0)
        {
            bHasCodecPrivateData = true;
        }

        if (pAudioTrackInfo->uBitsPerSample > 0)
        {
            bHasBitsPerSampleField = true;
        }

        /* Calculate header length */
        uHeaderLen = gSegmentTrackEntryHeaderSize;
        uHeaderLen += gSegmentTrackEntryCodecHeaderSize + strlen(pAudioTrackInfo->pCodecName);
        uHeaderLen += gSegmentTrackEntryAudioHeaderSize;
        if (bHasBitsPerSampleField)
        {
            uHeaderLen += gSegmentTrackEntryAudioHeaderBitsPerSampleSize;
        }
        if (bHasCodecPrivateData)
        {
            uHeaderLen += gSegmentTrackEntryCodecPrivateHeaderSize;
            uHeaderLen += pAudioTrackInfo->uCodecPrivateLen;
        }

        if ((pHeader = (uint8_t *)kvsMalloc(uHeaderLen)) == NULL)
        {
            LogError("OOM: audio track entry header");
            xRes = KVS_ERRNO_FAIL;
        }
        else
        {
            pIdx = pHeader;

            memcpy(pIdx, gSegmentTrackEntryHeader, gSegmentTrackEntryHeaderSize);
            *(pIdx + MKV_SEGMENT_TRACK_ENTRY_TRACK_NUMBER_OFFSET) = (uint8_t)TRACK_AUDIO;
            PUT_UNALIGNED_8_byte_BE(pIdx + MKV_SEGMENT_TRACK_ENTRY_TRACK_UID_OFFSET, TRACK_AUDIO);
            *(pIdx + MKV_SEGMENT_TRACK_ENTRY_TRACK_TYPE_OFFSET) = (uint8_t)TRACK_AUDIO;
            snprintf((char *)(pIdx + MKV_SEGMENT_TRACK_ENTRY_TRACK_NAME_OFFSET), TRACK_NAME_MAX_LEN, "%s", pAudioTrackInfo->pTrackName);
            pIdx += gSegmentTrackEntryHeaderSize;

            memcpy(pIdx, gSegmentTrackEntryCodecHeader, gSegmentTrackEntryCodecHeaderSize);
            PUT_UNALIGNED_2_byte_BE(pIdx + MKV_SEGMENT_TRACK_ENTRY_CODEC_LEN_OFFSET, MKV_LENGTH_INDICATOR_2_BYTE | strlen(pAudioTrackInfo->pCodecName));
            pIdx += gSegmentTrackEntryCodecHeaderSize;

            memcpy(pIdx, pAudioTrackInfo->pCodecName, strlen(pAudioTrackInfo->pCodecName));
            pIdx += strlen(pAudioTrackInfo->pCodecName);

            memcpy(pIdx, gSegmentTrackEntryAudioHeader, gSegmentTrackEntryAudioHeaderSize);
            audioFrequency = (double)pAudioTrackInfo->uFrequency;
            PUT_UNALIGNED_8_byte_BE(pIdx + MKV_SEGMENT_TRACK_ENTRY_AUDIO_FREQUENCY_OFFSET, *((uint64_t *)(&audioFrequency)));
            *(pIdx + MKV_SEGMENT_TRACK_ENTRY_AUDIO_CHANNEL_NUMBER_OFFSET) = pAudioTrackInfo->uChannelNumber;
            if (bHasBitsPerSampleField)
            {
                /* Adjust the length field of Audio header. */
                uAudioHeaderLen = gSegmentTrackEntryAudioHeaderSize + gSegmentTrackEntryAudioHeaderBitsPerSampleSize - MKV_SEGMENT_TRACK_ENTRY_AUDIO_HEADER_SIZE;
                PUT_UNALIGNED_4_byte_BE(pIdx + MKV_SEGMENT_TRACK_ENTRY_AUDIO_LEN_OFFSET, MKV_LENGTH_INDICATOR_4_BYTE | uAudioHeaderLen);
            }
            pIdx += gSegmentTrackEntryAudioHeaderSize;

            if (bHasBitsPerSampleField)
            {
                memcpy(pIdx, gSegmentTrackEntryAudioHeaderBitsPerSample, gSegmentTrackEntryAudioHeaderBitsPerSampleSize);
                *(pIdx + MKV_SEGMENT_TRACK_ENTRY_AUDIO_BPS_OFFSET) = pAudioTrackInfo->uBitsPerSample;
                pIdx += gSegmentTrackEntryAudioHeaderBitsPerSampleSize;
            }

            if (bHasCodecPrivateData)
            {
                memcpy(pIdx, gSegmentTrackEntryCodecPrivateHeader, gSegmentTrackEntryCodecPrivateHeaderSize);
                PUT_UNALIGNED_4_byte_BE(pIdx + MKV_SEGMENT_TRACK_ENTRY_CODEC_PRIVATE_LEN_OFFSET, MKV_LENGTH_INDICATOR_4_BYTE | pAudioTrackInfo->uCodecPrivateLen);
                pIdx += gSegmentTrackEntryCodecPrivateHeaderSize;

                memcpy(pIdx, pAudioTrackInfo->pCodecPrivate, pAudioTrackInfo->uCodecPrivateLen);
                pIdx += pAudioTrackInfo->uCodecPrivateLen;
            }

            PUT_UNALIGNED_4_byte_BE(pHeader + MKV_SEGMENT_TRACK_ENTRY_LEN_OFFSET, MKV_LENGTH_INDICATOR_4_BYTE | (uHeaderLen - MKV_SEGMENT_TRACK_ENTRY_HEADER_SIZE));

            *ppBuf = pHeader;
            *pBufLen = uHeaderLen;
        }
    }

    return xRes;
}