📄 rfccrypto.cpp
字号:
const char *part4kil = "key-indicator-length"; const char *part4ivl = "IV-length"; // add 1 for null char int pathlen = strlen(part1)+strlen(part2a)+strlen(part3)+strlen(part4se) + 1; char *path; path = (char *)malloc(pathlen); // get selective encryption setting from the file (iSFM atom) snprintf(path, pathlen, "%s%s%s%s", part1, isAudio ? part2a : part2v, part3, part4se); uint64_t temp; MP4GetTrackIntegerProperty(mp4File, mediaTrackId, path, &temp); *useSelectiveEnc = temp; // get the key indicator length from the file (iSFM atom) snprintf(path, pathlen, "%s%s%s%s", part1, isAudio ? part2a : part2v, part3, part4kil); MP4GetTrackIntegerProperty(mp4File, mediaTrackId, path, &temp); *KIlen = temp; // get the IV length from the file (iSFM atom) snprintf(path, pathlen, "%s%s%s%s", part1, isAudio ? part2a : part2v, part3, part4ivl); MP4GetTrackIntegerProperty(mp4File, mediaTrackId, path, &temp); *IVlen = temp; free(path); return true;}// gets the AU hdr length, and the AU sample header data informationstatic bool MP4AV_ProcessIsmaCrypHdrs(MP4FileHandle mp4File, MP4TrackId mediaTrackId, u_int8_t samplesThisHint, MP4SampleId* pSampleIds, u_int8_t useSelectiveEnc, u_int8_t KIlen, u_int8_t IVlen, u_int8_t *deltaIVLen, u_int16_t *iCrypAUHdrLen, ismaCrypSampleHdrDataInfo_t **iCrypSampleHdrData, mp4av_ismacrypParams *icPp){ int numEncAUs = 0; u_int8_t i = 0; u_int8_t kIPerAU = false; /**/ kIPerAU = icPp->key_ind_perau; *deltaIVLen = icPp->delta_iv_len; *iCrypAUHdrLen = 0; u_int32_t maxSampleSize = MP4GetTrackMaxSampleSize(mp4File, mediaTrackId); u_int8_t * pSampleBuffer = (u_int8_t *) malloc ((maxSampleSize + IVlen + KIlen + 1) * sizeof(u_int8_t)); if (pSampleBuffer == NULL) return false; for (i = 0; i < samplesThisHint; i++) { bool sampleIsEncrypted = false; if (useSelectiveEnc) { // add the 8 bits to signal if sample is encrypted // (always present for selencryption) *iCrypAUHdrLen += 8; (*iCrypSampleHdrData)[i].hasEncField = 1; // need to figure out if sample is encrypted u_int32_t sampleSize = maxSampleSize; bool rc = MP4ReadSample(mp4File, mediaTrackId, pSampleIds[i], &pSampleBuffer, &sampleSize); if (!rc) { free(pSampleBuffer); return false; } // check the 1st bit, if 1, then is encrypted, else is not if (pSampleBuffer[0] & 0x01) { sampleIsEncrypted = true; (*iCrypSampleHdrData)[i].isEncrypted = 1; } else { sampleIsEncrypted = false; (*iCrypSampleHdrData)[i].isEncrypted = 0; } if (pSampleBuffer != NULL) { free(pSampleBuffer); } } else { sampleIsEncrypted = true; (*iCrypSampleHdrData)[i].isEncrypted = 1; (*iCrypSampleHdrData)[i].hasEncField = 0; } if (sampleIsEncrypted) { if ((IVlen > 0) && (numEncAUs == 0)) { // first AU of pkt *iCrypAUHdrLen += 8 * IVlen; (*iCrypSampleHdrData)[i].hasIVField = 1; } else if ((IVlen > 0) && (numEncAUs > 0) && (*deltaIVLen > 0)) { // IsmaCrypDeltaIVLength is non-zero *iCrypAUHdrLen += 8 * (*deltaIVLen); (*iCrypSampleHdrData)[i].hasIVField = 1; // is delta iv field } else { (*iCrypSampleHdrData)[i].hasIVField = 0; } // the hdr has the key indicator if this is the first encrypted AU // of the packet or if IsmaCrypKeyIndicatorPerAU is not zero if ((KIlen > 0) && (numEncAUs == 0 || kIPerAU)) { *iCrypAUHdrLen += 8 * KIlen; (*iCrypSampleHdrData)[i].hasKIField = 1; } else { (*iCrypSampleHdrData)[i].hasKIField = 0; } numEncAUs++; } } return true;}// Note: this is based on MP4AV_RfcIsmaConcatenatorstatic bool MP4AV_RfcCryptoConcatenator( MP4FileHandle mp4File, MP4TrackId mediaTrackId, MP4TrackId hintTrackId, u_int8_t samplesThisHint, MP4SampleId* pSampleIds, MP4Duration hintDuration, u_int16_t maxPayloadSize, mp4av_ismacrypParams *icPp, bool isInterleaved){ // handle degenerate case if (samplesThisHint == 0) { return true; } u_int8_t auPayloadHdrSize = 0; // LATER would be more efficient if this were a parameter u_int8_t mpeg4AudioType = MP4GetTrackAudioMpeg4Type(mp4File, mediaTrackId); if (mpeg4AudioType == MP4_MPEG4_CELP_AUDIO_TYPE) { auPayloadHdrSize = 1; } else { auPayloadHdrSize = 2; } // construct the new hint MP4AddRtpHint(mp4File, hintTrackId); MP4AddRtpPacket(mp4File, hintTrackId, true); u_int8_t payloadHeader[2]; u_int16_t numHdrBits = samplesThisHint * auPayloadHdrSize * 8; ismaCrypSampleHdrDataInfo_t *iCrypSampleHdrInfo = (ismaCrypSampleHdrDataInfo_t *) malloc (samplesThisHint * sizeof(ismaCrypSampleHdrDataInfo_t)); if (iCrypSampleHdrInfo == NULL) return false; memset(iCrypSampleHdrInfo, 0, samplesThisHint * sizeof(ismaCrypSampleHdrDataInfo_t)); u_int16_t ismaCrypAUHdrLen = 0; 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, true) == false) { return false; } bool rc = MP4AV_ProcessIsmaCrypHdrs(mp4File, mediaTrackId, samplesThisHint, pSampleIds, useSelectiveEnc, KIlen, IVlen, &deltaIVlen, &ismaCrypAUHdrLen, &iCrypSampleHdrInfo, icPp); if (rc == false) { return false; } // add the AU header length AU header numHdrBits += ismaCrypAUHdrLen; payloadHeader[0] = numHdrBits >> 8; payloadHeader[1] = numHdrBits & 0xFF; MP4AddRtpImmediateData(mp4File, hintTrackId, (u_int8_t*)&payloadHeader, sizeof(payloadHeader)); u_int8_t i; // add the AU headers u_int32_t prevIV = 0; u_int32_t prevSize = 0; /* u_int32_t maxSampleSize = MP4GetTrackMaxSampleSize(mp4File, mediaTrackId); u_int8_t * pSampleBuffer = (u_int8_t *) malloc ((maxSampleSize + IVlen + KIlen + 1) * sizeof(u_int8_t)); if (pSampleBuffer == NULL) return false; */ for (i = 0; i < samplesThisHint; i++) { MP4SampleId sampleId = pSampleIds[i]; u_int32_t maxSampleSize = MP4GetTrackMaxSampleSize(mp4File, mediaTrackId); u_int32_t curIV = 0; // add the ismacryp AU header for the sample // first read the sample data into pSampleBuffer u_int32_t sampleSize = maxSampleSize; u_int8_t * pSampleBuffer = (u_int8_t *) malloc ((maxSampleSize + IVlen + KIlen + 1) * sizeof(u_int8_t)); if (pSampleBuffer == NULL) return false; bool rc = MP4ReadSample(mp4File, mediaTrackId, pSampleIds[i], &pSampleBuffer, &sampleSize); if (!rc) { return false; } u_int8_t * pCurPosSampleBuffer = pSampleBuffer; // add the selective encryption header field if needed if (iCrypSampleHdrInfo[i].hasEncField == 1) { // if selective encryption // add the 8 bits to signal if the sample is encrypted // sample_is_encrypted bit + 7 reserved bits MP4AddRtpImmediateData(mp4File, hintTrackId, pCurPosSampleBuffer, 1); pCurPosSampleBuffer += 1; } // add the IV/delta IV header field if needed if (iCrypSampleHdrInfo[i].hasIVField == 1) { // get the value of the current IV u_int32_t tmpIV = 0; memcpy(&tmpIV, pCurPosSampleBuffer, IVlen); // convert back to host byte order curIV = ntohl(tmpIV); // add the IV - from the ismacryp sample header data if (i == 0) { // first AU MP4AddRtpImmediateData(mp4File, hintTrackId, pCurPosSampleBuffer, IVlen); } else if ((i > 0) && isInterleaved) { // subsequent AU and interleaving u_int8_t ivdeltalen = sizeof(int8_t) * deltaIVlen; // compute the delta IV if (deltaIVlen == 1) { int8_t ivDelta = curIV - prevIV - prevSize; MP4AddRtpImmediateData(mp4File, hintTrackId, (u_int8_t*)&ivDelta, ivdeltalen); } else if (deltaIVlen == 2) { u_int16_t ivDelta = htons(curIV - prevIV - prevSize); MP4AddRtpImmediateData(mp4File, hintTrackId, (u_int8_t*)&ivDelta, ivdeltalen); } else if (deltaIVlen > 2) { // should not happen with current ismacryp spec return false; } } } // there is always an IV field in the ismacryp sample header // if IVlen > 0 so move the data pointer pCurPosSampleBuffer += IVlen; // add the key indicator field if needed if (iCrypSampleHdrInfo[i].hasKIField == 1) { // add the key indicator - from the ismacryp sample header data MP4AddRtpImmediateData(mp4File, hintTrackId, pCurPosSampleBuffer, KIlen); } // there is always a key indicator field in the ismacryp sample header // if KIlen > 0 so move the data pointer pCurPosSampleBuffer += KIlen; if (pSampleBuffer != NULL) { free(pSampleBuffer); } // remove size of ismaCryp sample header from the sample size u_int32_t ismaCrypSampleHdrSize = MP4AV_GetIsmaCrypSampleHdrSize ( iCrypSampleHdrInfo[i], IVlen, KIlen); sampleSize = MP4GetSampleSize(mp4File, mediaTrackId, sampleId) - ismaCrypSampleHdrSize; if (auPayloadHdrSize == 1) { // AU payload header is 6 bits of size // follow by 2 bits of the difference between sampleId's - 1 payloadHeader[0] = sampleSize << 2; } else { // auPayloadHdrSize == 2 // AU payload header is 13 bits of size // follow by 3 bits of the difference between sampleId's - 1 payloadHeader[0] = sampleSize >> 5; payloadHeader[1] = (sampleSize & 0x1F) << 3; } if (i > 0) { payloadHeader[auPayloadHdrSize - 1] |= ((sampleId - pSampleIds[i-1]) - 1); }#if 0 printf("sample %u size %u %02x %02x prev sample %d\n", sampleId, sampleSize, payloadHeader[0], payloadHeader[1], pSampleIds[i-1]);#endif MP4AddRtpImmediateData(mp4File, hintTrackId, (u_int8_t*)&payloadHeader, auPayloadHdrSize); prevIV = curIV; prevSize = sampleSize; } // then the samples for (i = 0; i < samplesThisHint; i++) { MP4SampleId sampleId = pSampleIds[i]; // figure out the size of the ismacryp sample header u_int32_t iCrypSampleHdrSize = MP4AV_GetIsmaCrypSampleHdrSize (iCrypSampleHdrInfo[i], IVlen, KIlen); // remove it from the sample size to get the real size of the data u_int32_t sampleSize = MP4GetSampleSize(mp4File, mediaTrackId, sampleId) - iCrypSampleHdrSize; // use the offset parameter to point to the beginning of the data // and skip the ismacryp sample header MP4AddRtpSampleData(mp4File, hintTrackId, sampleId, iCrypSampleHdrSize, sampleSize); } // write the hint MP4WriteRtpHint(mp4File, hintTrackId, hintDuration); if (iCrypSampleHdrInfo != NULL) { free(iCrypSampleHdrInfo); } return true;}// Add the RTP packet with a sample fragmentstatic bool MP4AV_RfcCryptoFragmenter( MP4FileHandle mp4File, MP4TrackId mediaTrackId, MP4TrackId hintTrackId, MP4SampleId sampleId, u_int32_t sampleSize, MP4Duration sampleDuration, u_int16_t maxPayloadSize, mp4av_ismacrypParams *icPp){ MP4AddRtpHint(mp4File, hintTrackId); MP4AddRtpPacket(mp4File, hintTrackId, false); // ismacryp u_int16_t numHdrBits = 0; 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; 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, true) == false) { return false; } bool rc = MP4AV_ProcessIsmaCrypHdrs(mp4File, mediaTrackId, 1, &sampleId, useSelectiveEnc, KIlen, IVlen, &deltaIVlen, &ismaCrypAUHdrLen, &iCrypSampleHdrInfo, icPp); if (rc == false) { return false; } // Note: CELP is never fragmented // so we assume the two byte AAC-hbr payload header numHdrBits = 16 + ismaCrypAUHdrLen; // 2 bytes for AAC AU hdr // add size of AU headers u_int8_t payloadHeaderSize[2]; payloadHeaderSize[0] = numHdrBits >> 8; payloadHeaderSize[1] = numHdrBits & 0xFF; MP4AddRtpImmediateData(mp4File, hintTrackId, (u_int8_t*)&payloadHeaderSize, sizeof(payloadHeaderSize)); // add ismacryp AU headers if (ismaCrypAUHdrLen > 0) { u_int32_t tmpSampleSize = sampleSize; 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) { 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; // add AAC AU header u_int8_t payloadHeader[2]; payloadHeader[0] = sampleSize >> 5; payloadHeader[1] = (sampleSize & 0x1F) << 3; MP4AddRtpImmediateData(mp4File, hintTrackId, (u_int8_t*)&payloadHeader, sizeof(payloadHeader)); // start after the ismaCrypSampleHdr u_int16_t sampleOffset = ismaCrypSampleHdrSize; u_int16_t fragLength = maxPayloadSize - 4; do { MP4AddRtpSampleData(mp4File, hintTrackId, sampleId, sampleOffset, fragLength); sampleOffset += fragLength; if (sampleSize - sampleOffset > maxPayloadSize) { fragLength = maxPayloadSize; MP4AddRtpPacket(mp4File, hintTrackId, false); } else { fragLength = sampleSize - sampleOffset; if (fragLength) { MP4AddRtpPacket(mp4File, hintTrackId, true); } } } while (sampleOffset < sampleSize); MP4WriteRtpHint(mp4File, hintTrackId, sampleDuration); return true;}// based on MP4AV_RfcIsmaHinter, with ismacryp SDP addedextern "C" bool MP4AV_RfcCryptoAudioHinter( MP4FileHandle mp4File, MP4TrackId mediaTrackId, mp4av_ismacrypParams *icPp, bool interleave,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -