📄 rfccrypto.cpp
字号:
u_int16_t maxPayloadSize, char* PayloadMIMEType){ // gather information, and check for validity u_int32_t numSamples = MP4GetTrackNumberOfSamples(mp4File, mediaTrackId); if (numSamples == 0) { return false; } u_int32_t timeScale = MP4GetTrackTimeScale(mp4File, mediaTrackId); if (timeScale == 0) { return false; } u_int8_t audioType = MP4GetTrackEsdsObjectTypeId(mp4File, mediaTrackId); if (audioType != MP4_MPEG4_AUDIO_TYPE && !MP4_IS_AAC_AUDIO_TYPE(audioType)) { return false; } u_int8_t mpeg4AudioType = MP4GetTrackAudioMpeg4Type(mp4File, mediaTrackId); if (audioType == MP4_MPEG4_AUDIO_TYPE) { // check that track contains either MPEG-4 AAC or CELP if (!MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg4AudioType) && mpeg4AudioType != MP4_MPEG4_CELP_AUDIO_TYPE) { return false; } } MP4Duration sampleDuration = MP4AV_GetAudioSampleDuration(mp4File, mediaTrackId); if (sampleDuration == MP4_INVALID_DURATION) { return false; } /* get the ES configuration */ u_int8_t* pConfig = NULL; u_int32_t configSize; uint8_t channels; MP4GetTrackESConfiguration(mp4File, mediaTrackId, &pConfig, &configSize); if (!pConfig) { return false; } channels = MP4AV_AacConfigGetChannels(pConfig); /* convert ES Config into ASCII form */ char* sConfig = MP4BinaryToBase16(pConfig, configSize); free(pConfig); if (!sConfig) { return false; } // now add the hint track MP4TrackId hintTrackId = MP4AddHintTrack(mp4File, mediaTrackId); if (hintTrackId == MP4_INVALID_TRACK_ID) { free(sConfig); return false; } u_int8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD; char buffer[10]; if (channels != 1) { snprintf(buffer, sizeof(buffer), "%u", channels); } MP4SetHintTrackRtpPayload(mp4File, hintTrackId, (const char*)PayloadMIMEType, &payloadNumber, 0, channels != 1 ? buffer : NULL); // moved this interleave check to here. u_int32_t samplesPerPacket = 0; if (interleave) { u_int32_t maxSampleSize = MP4GetTrackMaxSampleSize(mp4File, mediaTrackId); // compute how many maximum size samples would fit in a packet samplesPerPacket = (maxPayloadSize - 2) / (maxSampleSize + 2); // can't interleave if this number is 0 or 1 if (samplesPerPacket < 2) { interleave = false; // Since interleave is now false, reset delta IV length // for the session to zero or headers will be wrong...AWV // This needs to be done before the SDP is created. ...AWV icPp->delta_iv_len = 0; } else // set the delta IV length parameter to 2 // per the ismacryp specification (setting to 1 is too small) icPp->delta_iv_len = 2; } // compute the ISMACryp configuration parameters mjb ISMACrypConfigTable_t ismac_table; u_int16_t i; memset(&ismac_table, 0, sizeof(ISMACrypConfigTable_t)); if(!InitISMACrypConfigTable(&ismac_table, icPp)){ free(sConfig); return false; } char* sISMACrypConfig = NULL; if (!MP4AV_RfcCryptoPolicyOk(&ismac_table)) { free(sConfig); for(i = 0; i < ismac_table.settings[ISMACRYP_KEY_COUNT];i++) { free(ismac_table.keys[i]); free(ismac_table.salts[i]); } return false; } if (!MP4AV_RfcCryptoConfigure(&ismac_table, &sISMACrypConfig)) { free(sConfig); return false; } int sdpBufLen = strlen(sConfig) + strlen(sISMACrypConfig) + ISMACRYP_SDP_ADDITIONAL_CONFIG_MAX_LEN; char* sdpBuf = (char*)malloc(sdpBufLen); if (!sdpBuf) { free(sConfig); free(sISMACrypConfig); return false; } MP4Duration maxLatency; bool OneByteHeader = false; if (mpeg4AudioType == MP4_MPEG4_CELP_AUDIO_TYPE) { snprintf(sdpBuf, sdpBufLen, "a=fmtp:%u " "streamtype=5; profile-level-id=15; mode=CELP-vbr; " "config=%s; SizeLength=6; IndexLength=2; " "IndexDeltaLength=2; Profile=0;" "%s" "\015\012", payloadNumber, sConfig, sISMACrypConfig); // 200 ms max latency for ISMA profile 1 maxLatency = timeScale / 5; OneByteHeader = true; } else { // AAC snprintf(sdpBuf, sdpBufLen, "a=fmtp:%u " "streamtype=5; profile-level-id=15; mode=AAC-hbr; " "config=%s; SizeLength=13; IndexLength=3; " "IndexDeltaLength=3; Profile=1;" "%s " //mjb "\015\012", payloadNumber, sConfig, sISMACrypConfig); // 500 ms max latency for ISMA profile 1 maxLatency = timeScale / 2; } /* add this to the track's sdp */ MP4AppendHintTrackSdp(mp4File, hintTrackId, sdpBuf); free(sConfig); free(sdpBuf); free(sISMACrypConfig); //mjb for(i = 0; i < ismac_table.settings[ISMACRYP_KEY_COUNT];i++) { free(ismac_table.keys[i]); free(ismac_table.salts[i]); } // this is where the interleave check was....AWV bool rc; if (interleave) { u_int32_t samplesPerGroup = maxLatency / sampleDuration; u_int32_t stride; stride = samplesPerGroup / samplesPerPacket; if (OneByteHeader && stride > 3) stride = 3; if (!OneByteHeader && stride > 7) stride = 7;#if 0 printf("max latency %llu sampleDuration %llu spg %u spp %u strid %u\n", maxLatency, sampleDuration, samplesPerGroup, samplesPerPacket, stride);#endif rc = MP4AV_CryptoAudioInterleaveHinter( mp4File, mediaTrackId, hintTrackId, sampleDuration, stride, // stride samplesPerPacket, // bundle maxPayloadSize, icPp); } else { rc = MP4AV_CryptoAudioConsecutiveHinter( mp4File, mediaTrackId, hintTrackId, sampleDuration, 2, // perPacketHeaderSize 2, // perSampleHeaderSize maxLatency / sampleDuration, // maxSamplesPerPacket maxPayloadSize, MP4GetSampleSize, icPp); } if (!rc) { MP4DeleteTrack(mp4File, hintTrackId); return false; } return true;}// based on MP4AV_Rfc3016Hinterextern "C" bool MP4AV_RfcCryptoVideoHinter( MP4FileHandle mp4File, MP4TrackId mediaTrackId, mp4av_ismacrypParams *icPp, u_int16_t maxPayloadSize, char* PayloadMIMEType){ u_int32_t numSamples = MP4GetTrackNumberOfSamples(mp4File, mediaTrackId); u_int32_t maxSampleSize = MP4GetTrackMaxSampleSize(mp4File, mediaTrackId); if (numSamples == 0 || maxSampleSize == 0) { return false; } MP4TrackId hintTrackId = MP4AddHintTrack(mp4File, mediaTrackId); if (hintTrackId == MP4_INVALID_TRACK_ID) { return false; } u_int8_t payloadNumber = MP4_SET_DYNAMIC_PAYLOAD; MP4SetHintTrackRtpPayload(mp4File, hintTrackId, (const char*) PayloadMIMEType, &payloadNumber, 0); /* get the mpeg4 video configuration */ u_int8_t* pConfig; u_int32_t configSize; u_int8_t systemsProfileLevel = 0xFE; MP4GetTrackESConfiguration(mp4File, mediaTrackId, &pConfig, &configSize); if (pConfig) { // compute the ISMACryp configuration parameters mjb ISMACrypConfigTable_t ismac_table; u_int16_t i; memset(&ismac_table, 0, sizeof(ISMACrypConfigTable_t)); if(!InitISMACrypConfigTable(&ismac_table, icPp)){ return false; } char* sISMACrypConfig = NULL; if (!MP4AV_RfcCryptoPolicyOk(&ismac_table)) { for(i = 0; i < ismac_table.settings[ISMACRYP_KEY_COUNT];i++){ free(ismac_table.keys[i]); free(ismac_table.salts[i]); } return false; } if (!MP4AV_RfcCryptoConfigure(&ismac_table, &sISMACrypConfig)) return false; // attempt to get a valid profile-level static u_int8_t voshStartCode[4] = { 0x00, 0x00, 0x01, MP4AV_MPEG4_VOSH_START }; if (configSize >= 5 && !memcmp(pConfig, voshStartCode, 4)) { systemsProfileLevel = pConfig[4]; } if (systemsProfileLevel == 0xFE) { u_int8_t iodProfileLevel = MP4GetVideoProfileLevel(mp4File); if (iodProfileLevel > 0 && iodProfileLevel < 0xFE) { systemsProfileLevel = iodProfileLevel; } else { systemsProfileLevel = 1; } } /* convert it into ASCII form */ char* sConfig = MP4BinaryToBase16(pConfig, configSize); if (sConfig == NULL) { MP4DeleteTrack(mp4File, hintTrackId); free(sISMACrypConfig); for(i = 0; i < ismac_table.settings[ISMACRYP_KEY_COUNT];i++) { free(ismac_table.keys[i]); free(ismac_table.salts[i]); } return false; } int sdpBufLen = strlen(sConfig) + strlen(sISMACrypConfig) + ISMACRYP_SDP_ADDITIONAL_CONFIG_MAX_LEN; char* sdpBuf = (char*)malloc(sdpBufLen); if (sdpBuf == NULL) { free(sISMACrypConfig); free(sConfig); return false; } snprintf(sdpBuf, sdpBufLen, "a=fmtp:%u profile-level-id=%u; mode=mpeg4-video; " "config=%s; %s; \015\012", payloadNumber, systemsProfileLevel, sConfig, sISMACrypConfig); /* add this to the track's sdp */ MP4AppendHintTrackSdp(mp4File, hintTrackId, sdpBuf); free(sConfig); free(sdpBuf); free(sISMACrypConfig); for(i = 0; i < ismac_table.settings[ISMACRYP_KEY_COUNT];i++) { free(ismac_table.keys[i]); free(ismac_table.salts[i]); } } u_int8_t* pSampleBuffer = (u_int8_t*)malloc(maxSampleSize); if (pSampleBuffer == NULL) { MP4DeleteTrack(mp4File, hintTrackId); return false; } u_int8_t useSelectiveEnc = 0; u_int8_t KIlen = 0; u_int8_t IVlen = 0; u_int8_t deltaIVlen = 0; if (MP4AV_GetiSFMSettings(mp4File, mediaTrackId, &useSelectiveEnc, &KIlen, &IVlen, false) == false) { return false; } for (MP4SampleId sampleId = 1; sampleId <= numSamples; sampleId++) { u_int32_t sampleSize = maxSampleSize; // +IVlen +KIlen +1 MP4Timestamp startTime; MP4Duration duration; MP4Duration renderingOffset; bool isSyncSample; bool rc = MP4ReadSample(mp4File, mediaTrackId, sampleId, &pSampleBuffer, &sampleSize, &startTime, &duration, &renderingOffset, &isSyncSample); if (!rc) { MP4DeleteTrack(mp4File, hintTrackId); return false; } bool isBFrame = (MP4AV_Mpeg4GetVopType(pSampleBuffer, sampleSize) == VOP_TYPE_B); MP4AddRtpVideoHint(mp4File, hintTrackId, isBFrame, renderingOffset); // comment from bill: may need to remove or put it in the header ?? if (sampleId == 1) { MP4AddRtpESConfigurationPacket(mp4File, hintTrackId); } u_int32_t offset = 0; u_int32_t remaining = sampleSize; // TBD should scan for resync markers (if enabled in ES config) // and packetize on those boundaries while (remaining) { bool isLastPacket = false; u_int32_t length; // need to add ismacryp AU header length if (remaining <= maxPayloadSize) { length = remaining; isLastPacket = true; } else { length = maxPayloadSize; } MP4AddRtpPacket(mp4File, hintTrackId, isLastPacket); ismaCrypSampleHdrDataInfo_t *iCrypSampleHdrInfo = (ismaCrypSampleHdrDataInfo_t *) malloc (sizeof(ismaCrypSampleHdrDataInfo_t)); if (iCrypSampleHdrInfo == NULL) return false; memset(iCrypSampleHdrInfo, 0, sizeof(ismaCrypSampleHdrDataInfo_t)); u_int16_t ismaCrypAUHdrLen = 0; bool rc = MP4AV_ProcessIsmaCrypHdrs(mp4File, mediaTrackId, 1, &sampleId, useSelectiveEnc, KIlen, IVlen, &deltaIVlen, &ismaCrypAUHdrLen, &iCrypSampleHdrInfo, icPp); if (rc == false) { // handle error return false; } if (ismaCrypAUHdrLen > 0) { // add AU hdr length u_int8_t payloadHeader[2]; payloadHeader[0] = ismaCrypAUHdrLen >> 8; payloadHeader[1] = ismaCrypAUHdrLen & 0xFF; MP4AddRtpImmediateData(mp4File, hintTrackId, (u_int8_t*)&payloadHeader, sizeof(payloadHeader)); // add ismacryp AU headers u_int32_t tmpSampleSize = maxSampleSize; u_int8_t * pSampleBuffer = (u_int8_t *) malloc ((tmpSampleSize + IVlen + KIlen + 1) * sizeof(u_int8_t)); if (pSampleBuffer == NULL) return false; u_int8_t * pCurSampleBuf = pSampleBuffer; bool rc2 = MP4ReadSample(mp4File, mediaTrackId, sampleId, &pSampleBuffer, &tmpSampleSize); if (rc2 == false) { // handle error return false; } if (iCrypSampleHdrInfo[0].hasEncField == 1) { MP4AddRtpImmediateData(mp4File, hintTrackId, pCurSampleBuf, 1); pCurSampleBuf += 1; } if (iCrypSampleHdrInfo[0].hasIVField == 1) { MP4AddRtpImmediateData(mp4File, hintTrackId, pCurSampleBuf, IVlen); } pCurSampleBuf += IVlen; if (iCrypSampleHdrInfo[0].hasKIField == 1) { MP4AddRtpImmediateData(mp4File, hintTrackId, pCurSampleBuf, KIlen); } pCurSampleBuf += KIlen; if (pSampleBuffer != NULL) { free(pSampleBuffer); } // remove size of ismaCryp sample header from the sample size u_int32_t ismaCrypSampleHdrSize = MP4AV_GetIsmaCrypSampleHdrSize (iCrypSampleHdrInfo[0], IVlen, KIlen); sampleSize -= ismaCrypSampleHdrSize; } MP4AddRtpSampleData(mp4File, hintTrackId, sampleId, offset, length); offset += length; remaining -= length; } MP4WriteRtpHint(mp4File, hintTrackId, duration, isSyncSample); } return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -