in src/source/mkv/mkv_generator.c [540:645]
int Mkv_initializeHeaders(MkvHeader_t *pMkvHeader, VideoTrackInfo_t *pVideoTrackInfo, AudioTrackInfo_t *pAudioTrackInfo)
{
int xRes = KVS_ERRNO_NONE;
;
uint8_t *pIdx = NULL;
uint32_t uHeaderLen = 0;
uint8_t pSegmentUuid[UUID_LEN] = {0};
uint32_t uSegmentTracksLen = 0;
uint8_t *pSegmentVideo = NULL;
uint32_t uSegmentVideoLen = 0;
bool bHasAudioTrack = false;
uint8_t *pSegmentAudio = NULL;
uint32_t uSegmentAudioLen = 0;
size_t i = 0;
if (pMkvHeader == NULL || pVideoTrackInfo == NULL)
{
LogError("Invalid argument");
xRes = KVS_ERRNO_FAIL;
}
else
{
memset(pMkvHeader, 0, sizeof(MkvHeader_t));
for (i = 0; i < UUID_LEN; i++)
{
pSegmentUuid[i] = getRandomNumber();
}
bHasAudioTrack = (pAudioTrackInfo != NULL) ? true : false;
if (prvCreateVideoTrackEntry(pVideoTrackInfo, &pSegmentVideo, &uSegmentVideoLen) != KVS_ERRNO_NONE ||
(bHasAudioTrack && prvCreateAudioTrackEntry(pAudioTrackInfo, &pSegmentAudio, &uSegmentAudioLen) != KVS_ERRNO_NONE))
{
LogError("Failed to create track entries");
xRes = KVS_ERRNO_FAIL;
}
else
{
/* Calculate size of EBML and Segment header. */
uHeaderLen = gEbmlHeaderSize;
uHeaderLen += gSegmentHeaderSize;
uHeaderLen += gSegmentInfoHeaderSize;
uHeaderLen += gSegmentTrackHeaderSize;
uHeaderLen += uSegmentVideoLen;
uHeaderLen += (bHasAudioTrack) ? uSegmentAudioLen : 0;
/* Allocate memory for EBML and Segment header. */
if ((pMkvHeader->pHeader = (uint8_t *)kvsMalloc(uHeaderLen)) == NULL)
{
LogError("OOM: MKV Header");
xRes = KVS_ERRNO_FAIL;
}
else
{
pIdx = pMkvHeader->pHeader;
memcpy(pIdx, gEbmlHeader, gEbmlHeaderSize);
pIdx += gEbmlHeaderSize;
memcpy(pIdx, gSegmentHeader, gSegmentHeaderSize);
pIdx += gSegmentHeaderSize;
memcpy(pIdx, gSegmentInfoHeader, gSegmentInfoHeaderSize);
memcpy(pIdx + MKV_SEGMENT_INFO_UID_OFFSET, pSegmentUuid, UUID_LEN);
snprintf((char *)(pIdx + MKV_SEGMENT_INFO_TITLE_OFFSET), SEGMENT_TITLE_MAX_LEN, "%s", SEGMENT_TITLE);
snprintf((char *)(pIdx + MKV_SEGMENT_INFO_MUXING_APP_OFFSET), MUXING_APP_MAX_LEN, "%s", MUXING_APP);
snprintf((char *)(pIdx + MKV_SEGMENT_INFO_WRITING_APP_OFFSET), WRITING_APP_MAX_LEN, "%s", WRITING_APP);
pIdx += gSegmentInfoHeaderSize;
memcpy(pIdx, gSegmentTrackHeader, gSegmentTrackHeaderSize);
uSegmentTracksLen = uSegmentVideoLen;
uSegmentTracksLen += (bHasAudioTrack) ? uSegmentAudioLen : 0;
PUT_UNALIGNED_4_byte_BE(pIdx + MKV_SEGMENT_TRACK_LENGTH_OFFSET, MKV_LENGTH_INDICATOR_4_BYTE | uSegmentTracksLen);
pIdx += gSegmentTrackHeaderSize;
memcpy(pIdx, pSegmentVideo, uSegmentVideoLen);
pIdx += uSegmentVideoLen;
if (bHasAudioTrack)
{
memcpy(pIdx, pSegmentAudio, uSegmentAudioLen);
pIdx += uSegmentAudioLen;
}
pMkvHeader->uHeaderLen = uHeaderLen;
}
}
}
if (pSegmentVideo != NULL)
{
kvsFree(pSegmentVideo);
}
if (pSegmentAudio != NULL)
{
kvsFree(pSegmentAudio);
}
return xRes;
}