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;
}