📄 mp4drm.cpp
字号:
free(ipmpData); return true; }private: BlowfishEncryptor* encryptor; std::string contentID; std::string rightsHost;};/*! \brief Protect sample using given encryptor. \param srcFile input, source file handle. \param srcTrackId input, source file track identifier. \param srcSampleId input, source sample identifier. \param encryptor input, DRM encryptor. \param dstFile input, destination file handle. \param dstTrackId input, destination file track identifier. \param dstSampleDuration input, destination sample duration. \param logger input-output, message logger. \returns Boolean indicating success or failure.*/bool MP4EncryptSample(MP4FileHandle srcFile, MP4TrackId srcTrackId, MP4SampleId srcSampleId, IMPEG4SinfDRMEncryptor* encryptor, MP4FileHandle dstFile, MP4TrackId dstTrackId, MP4Duration dstSampleDuration, DRMLogger& logger) { bool rc; u_int8_t* pBytes = NULL; u_int32_t numBytes = 0; u_int8_t* encSampleData = NULL; u_int32_t encSampleLength = 0; MP4Duration sampleDuration; MP4Duration renderingOffset; bool isSyncSample; // Note: we leave it up to the caller to ensure that the // source and destination tracks are compatible. // i.e. copying audio samples into a video track // is unlikely to do anything useful rc = MP4ReadSample(srcFile, srcTrackId, srcSampleId, &pBytes, &numBytes, NULL, &sampleDuration, &renderingOffset, &isSyncSample); if (!rc) { return false; } if (dstFile == MP4_INVALID_FILE_HANDLE) { dstFile = srcFile; } if (dstTrackId == MP4_INVALID_TRACK_ID) { dstTrackId = srcTrackId; } if (dstSampleDuration != MP4_INVALID_DURATION) { sampleDuration = dstSampleDuration; } if (encryptor->EncryptSample((ByteT*)pBytes, numBytes, (ByteT**)&encSampleData, &encSampleLength, logger) == false) { fprintf(stderr, "Can't encrypt the sample and add its header %u\n", srcSampleId); free(pBytes); return false; } rc = MP4WriteSample(dstFile, dstTrackId, encSampleData, encSampleLength, sampleDuration, renderingOffset, isSyncSample); free(pBytes); if (encSampleData != NULL) { free(encSampleData); } return rc;}/*! \brief Protect track using given encryptor. Read all the samples from the track and protect them using given encryptor. When it's done, add DRM information to IMP4SinfAtom. \param srcFile input, source file handle. \param srcTrackId input, source file track identifier. \param encryptor input, DRM encryptor. \param dstFile input, destination file handle. \param dstTrackId input, destination file track identifier. \param applyEdits input, apply edits flag. \param logger input-output, message logger. \returns If failed MP4_INVALID_TRACK_ID, otherwise != MP4_INVALID_TRACK_ID.*/MP4TrackId MP4EncryptTrack(MP4FileHandle srcFile, MP4TrackId srcTrackId, IMPEG4SinfDRMEncryptor* encryptor, MP4FileHandle dstFile, MP4TrackId dstTrackId, bool applyEdits, DRMLogger& logger) { bool copySamples = true; // LATER allow false => reference samples bool viaEdits = applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId); MP4SampleId sampleId = 0; MP4SampleId numSamples = MP4GetTrackNumberOfSamples(srcFile, srcTrackId); MP4Timestamp when = 0; MP4Duration editsDuration = MP4GetTrackEditTotalDuration(srcFile, srcTrackId); while (true) { MP4Duration sampleDuration = MP4_INVALID_DURATION; if (viaEdits) { sampleId = MP4GetSampleIdFromEditTime(srcFile, srcTrackId, when, NULL, &sampleDuration); // in theory, this shouldn't happen if (sampleId == MP4_INVALID_SAMPLE_ID) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } when += sampleDuration; if (when >= editsDuration) { break; } } else { sampleId++; if (sampleId > numSamples) { break; } } bool rc = false; if (copySamples) { // encrypt and copy rc = MP4EncryptSample(srcFile, srcTrackId, sampleId, encryptor, dstFile, dstTrackId, sampleDuration, logger); } else { // not sure what these are - encrypt? rc = MP4ReferenceSample(srcFile, srcTrackId, sampleId, dstFile, dstTrackId, sampleDuration); } if (!rc) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } } MP4Track* track; MP4Atom* atom; MP4Atom* pStsdAtom; MP4Atom* sEntry; MP4Atom* sinf; track = ((MP4File*)srcFile)->GetTrack(srcTrackId); atom = track->GetTrakAtom(); pStsdAtom = atom->FindAtom("trak.mdia.minf.stbl.stsd"); if (pStsdAtom == 0) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } sEntry = pStsdAtom->GetChildAtom(0); if (sEntry == 0) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } std::string otypes = sEntry->GetType(); if (otypes.size() != 4) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } u_int32_t otype = ((otypes[0] << 24) | (otypes[1] << 16) | (otypes[2] << 8) | otypes[3]); track = ((MP4File*)dstFile)->GetTrack(dstTrackId); atom = track->GetTrakAtom(); pStsdAtom = atom->FindAtom("trak.mdia.minf.stbl.stsd"); if (pStsdAtom == 0) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } sEntry = pStsdAtom->GetChildAtom(0); if (sEntry == 0) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } sinf = sEntry->FindChildAtom("sinf"); if (sinf == 0) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } if (encryptor->Finish(otype, sinf, logger) == false) { MP4DeleteTrack(dstFile, dstTrackId); return MP4_INVALID_TRACK_ID; } return dstTrackId;}/*! \brief Global handler for DRM protection.*/class DRMEncHandler {public: DRMEncHandler(): doc(0), xmlDoc(0) { XMLFactory::Initialize(); PublicCryptoFactory::Initialize(); ThreadSyncFactory::Initialize(); } ~DRMEncHandler() { if (doc != 0) { delete doc; doc = 0; } XMLFactory::Terminate(); PublicCryptoFactory::Terminate(); ThreadSyncFactory::Terminate(); } IMPEG4SinfDRMEncryptor* GetEncryptor(const std::string& drmMethod, const std::string& encMethod, const std::string& xmlFileName, const std::vector<std::string>& sensitive, const std::vector<std::string>& node, const std::string& fName, MP4TrackId srcTrackId, DRMLogger& logger) { if (drmMethod == "") { fprintf(stderr, "GetEncryptor: Missing drm method!\n"); return 0; } if (encMethod == "") { fprintf(stderr, "GetEncryptor: Missing encryption method!\n"); return 0; } if (fName == "") { fprintf(stderr, "GetEncryptor: Missing input mp4 file!\n"); return 0; } if (xmlDoc == 0) { xmlDoc = GetXML(xmlFileName, sensitive, node); } ContentInfoManager* infoManager = 0; IDRMEncManager* drmManager = 0; IMPEG4SinfDRMEncryptor* encryptor = 0; try { infoManager = ContentInfoManagerFactory::GetContentInfoManager( OPENIPMPDOIINFOMANAGER, xmlDoc, logger); if (infoManager == 0) { fprintf(stderr, "GetEncryptor: Error creating content info manager!\n"); return 0; } char tID[11]; itoa(srcTrackId, tID, 10); std::string title = fName + ".track" + std::string(tID); DRMPlugin::IXMLElement* elem = xmlDoc->GetChildElement("ContentTitle"); if (elem == 0) { delete infoManager; fprintf(stderr, "GetEncryptor: Error in XML document!\n"); return 0; } if (elem->SetStrValue(title) == false) { delete infoManager; fprintf(stderr, "GetEncryptor: Error in XML document!\n"); return 0; } std::string info; if (infoManager->GetContentInfo(xmlDoc, info, logger) == false) { delete infoManager; fprintf(stderr, "GetEncryptor: Content info manager error!\n"); return 0; } delete infoManager; infoManager = 0; if (drmMethod == "openipmp") { drmManager = OpenIPMPDRMEncManagerFactory::GetOpenIPMPDRMEncManager(xmlDoc, logger); if (drmManager == 0) { fprintf(stderr, "GetEncryptor: Error creating DRM manager!\n"); return 0; } if (encMethod == "ctr") { encryptor = new AES128CTROpenIPMPMPEG4SinfDRMEncryptor(drmManager, info, xmlDoc, logger); } else if (encMethod == "bfs") { encryptor = new BlowfishOpenIPMPMPEG4SinfDRMEncryptor(drmManager, info, xmlDoc, logger); } else { delete drmManager; fprintf(stderr, "GetEncryptor: Wrong encryption method!\n"); return 0; } } else if (drmMethod == "oma") { drmManager = OMADRMEncManagerFactory::GetOMADRMEncManager(xmlDoc, logger); if (drmManager == 0) { fprintf(stderr, "GetEncryptor: Error creating DRM manager!\n"); return 0; } if (encMethod == "ctr") { encryptor = new AES128CTROMAMPEG4SinfDRMEncryptor(drmManager, info, xmlDoc, logger); } else if (encMethod == "cbc") { encryptor = new AES128CBCOMAMPEG4SinfDRMEncryptor(drmManager, info, xmlDoc, logger); } else { delete drmManager; fprintf(stderr, "GetEncryptor: Wrong encryption method!\n"); return 0; } } else if (drmMethod == "isma") { drmManager = ISMADRMEncManagerFactory::GetISMADRMEncManager(xmlDoc, logger); if (drmManager == 0) { fprintf(stderr, "GetEncryptor: Error creating DRM manager!\n"); return 0; } if (encMethod == "icm") { encryptor = new AES128ICMISMAMPEG4SinfDRMEncryptor(drmManager, info, xmlDoc, logger); } else { delete drmManager; fprintf(stderr, "GetEncryptor: Wrong encryption method!\n"); return 0; } } else { fprintf(stderr, "GetEncryptor: Wrong DRM method!\n"); return 0; } // When and where to add license? drmManager->AddLicense(info, xmlDoc, logger); delete drmManager; drmManager = 0; } catch (...) { if (infoManager != 0) delete infoManager; if (drmManager != 0) delete drmManager; if (encryptor != 0) delete encryptor; fprintf(stderr, "GetEncryptor: Unknown error!\n"); return 0; } return encryptor; } DRMPlugin::IXMLElement* GetXML(const std::string& xmlFileName, const std::vector<std::string>& sensitive, const std::vector<std::string>& node) { if (xmlFileName != "") { if ((doc = XMLFactory::DecodeDocumentFromFile(xmlFileName)) == 0) { fprintf(stderr, "%s: Invalid XML configuration file!\n", ProgName); return 0; } if ((xmlDoc = doc->GetRootElement()) == 0) { delete doc; doc = 0; xmlDoc = 0; return 0; } for (unsigned int count = 0; count < sensitive.size(); count++) { char* slash = strchr(sensitive[count].begin(), '/'); if (slash == NULL) { delete doc; doc = 0; xmlDoc = 0; return 0; } std::string path = std::string(sensitive[count].begin(), slash); std::string value = std::string(++slash, sensitive[count].end()); DRMPlugin::IXMLElement* elem = xmlDoc->GetChildElement(path); if (elem == 0) { delete doc; doc = 0; xmlDoc = 0; return 0; } if (elem->SetStrValue(value) == false) { delete doc; doc = 0; xmlDoc = 0; return 0; } } for (count = 0; count < node.size()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -