STATUS mkvgenAdaptCodecPrivateData()

in src/mkvgen/src/MkvGenerator.c [1662:1765]


STATUS mkvgenAdaptCodecPrivateData(PStreamMkvGenerator pMkvGenerator, MKV_TRACK_INFO_TYPE trackType, PCHAR codecId, UINT32 cpdSize, PBYTE cpd,
                                   PUINT32 pCpdSize, PBYTE* ppCpd, PTrackCustomData pData)
{
    ENTERS();
    STATUS retStatus = STATUS_SUCCESS;
    UINT32 adaptedCodecPrivateDataSize;
    PBYTE pCpd = NULL;

    // Initialize to existing size
    adaptedCodecPrivateDataSize = cpdSize;

    // Early return on empty cpd
    CHK(adaptedCodecPrivateDataSize != 0, retStatus);

    // Check if the CPD needs to be adapted
    if (trackType == MKV_TRACK_INFO_TYPE_VIDEO && pMkvGenerator->adaptCpdNals) {
        if ((pMkvGenerator->contentType & MKV_CONTENT_TYPE_H264) != MKV_CONTENT_TYPE_NONE) {
            CHK_STATUS(adaptH264CpdNalsFromAnnexBToAvcc(cpd, cpdSize, NULL, &adaptedCodecPrivateDataSize));
        } else if ((pMkvGenerator->contentType & MKV_CONTENT_TYPE_H265) != MKV_CONTENT_TYPE_NONE) {
            CHK_STATUS(adaptH265CpdNalsFromAnnexBToHvcc(cpd, cpdSize, NULL, &adaptedCodecPrivateDataSize));
        }
    }

    // Adapt/copy the CPD
    pCpd = (PBYTE) MEMALLOC(adaptedCodecPrivateDataSize);
    CHK(pCpd != NULL, STATUS_NOT_ENOUGH_MEMORY);

    if (trackType == MKV_TRACK_INFO_TYPE_VIDEO && pMkvGenerator->adaptCpdNals) {
        if ((pMkvGenerator->contentType & MKV_CONTENT_TYPE_H264) != MKV_CONTENT_TYPE_NONE) {
            CHK_STATUS(adaptH264CpdNalsFromAnnexBToAvcc(cpd, cpdSize, pCpd, &adaptedCodecPrivateDataSize));
        } else if ((pMkvGenerator->contentType & MKV_CONTENT_TYPE_H265) != MKV_CONTENT_TYPE_NONE) {
            CHK_STATUS(adaptH265CpdNalsFromAnnexBToHvcc(cpd, cpdSize, pCpd, &adaptedCodecPrivateDataSize));
        }
    } else {
        MEMCPY(pCpd, cpd, adaptedCodecPrivateDataSize);
    }

    // Check whether we need to generate a video config element for
    // H264, H265 or M-JJPG content type if the CPD is present
    switch (trackType) {
        case MKV_TRACK_INFO_TYPE_UNKOWN:
            break;

        case MKV_TRACK_INFO_TYPE_VIDEO:
            // Check and process the H264 then H265 and later M-JPG content type
            if ((pMkvGenerator->contentType & MKV_CONTENT_TYPE_H264) != MKV_CONTENT_TYPE_NONE) {
                // Important: The assumption here is that if this is not in AvCC format and it's in Annex-B or RAW then
                // the first NALu is the SPS. We will not skip over possible SEI or AUD NALus
                retStatus = getVideoWidthAndHeightFromH264Sps(pCpd, adaptedCodecPrivateDataSize, &pData->trackVideoConfig.videoWidth,
                                                              &pData->trackVideoConfig.videoHeight);

            } else if ((pMkvGenerator->contentType & MKV_CONTENT_TYPE_H265) != MKV_CONTENT_TYPE_NONE) {
                // Important: The assumption here is that if this is not in HvCC format and it's in Annex-B or RAW then
                // the first NALu is the SPS. We will not skip over possible SEI or AUD NALus
                retStatus = getVideoWidthAndHeightFromH265Sps(pCpd, adaptedCodecPrivateDataSize, &pData->trackVideoConfig.videoWidth,
                                                              &pData->trackVideoConfig.videoHeight);

            } else if (((pMkvGenerator->contentType & MKV_CONTENT_TYPE_X_MKV_VIDEO) != MKV_CONTENT_TYPE_NONE) &&
                       (0 == STRCMP(codecId, MKV_FOURCC_CODEC_ID))) {
                // For M-JPG we have content type as video/x-matroska and the codec
                // type set as V_MS/VFW/FOURCC
                retStatus = getVideoWidthAndHeightFromBih(pCpd, adaptedCodecPrivateDataSize, &pData->trackVideoConfig.videoWidth,
                                                          &pData->trackVideoConfig.videoHeight);
            }

            if (STATUS_FAILED(retStatus)) {
                // This might not be yet fatal so warn and reset the status
                DLOGW("Failed extracting video configuration from SPS with %08x.", retStatus);
                MEMSET(&pData->trackVideoConfig, 0x00, SIZEOF(TrackVideoConfig));
                retStatus = STATUS_SUCCESS;
            }

            break;

        case MKV_TRACK_INFO_TYPE_AUDIO:
            // zero out the fields
            MEMSET(&pData->trackAudioConfig, 0x00, SIZEOF(TrackCustomData));

            if ((pMkvGenerator->contentType & MKV_CONTENT_TYPE_AAC) != MKV_CONTENT_TYPE_NONE) {
                retStatus = getSamplingFreqAndChannelFromAacCpd(pCpd, adaptedCodecPrivateDataSize, &pData->trackAudioConfig.samplingFrequency,
                                                                &pData->trackAudioConfig.channelConfig);
            } else if ((pMkvGenerator->contentType & (MKV_CONTENT_TYPE_ALAW | MKV_CONTENT_TYPE_MULAW)) != MKV_CONTENT_TYPE_NONE) {
                retStatus = getAudioConfigFromAmsAcmCpd(pCpd, adaptedCodecPrivateDataSize, &pData->trackAudioConfig.samplingFrequency,
                                                        &pData->trackAudioConfig.channelConfig, &pData->trackAudioConfig.bitDepth);
            }

            if (STATUS_FAILED(retStatus)) {
                // This might not be yet fatal so warn and reset the status
                DLOGW("Failed extracting audio configuration from codec private data with %08x.", retStatus);
                MEMSET(&pData->trackAudioConfig, 0x00, SIZEOF(TrackAudioConfig));
                retStatus = STATUS_SUCCESS;
            }

            break;
    }

CleanUp:

    *ppCpd = pCpd;
    *pCpdSize = adaptedCodecPrivateDataSize;

    LEAVES();
    return retStatus;
}