1# 数字版权保护(C/C++) 2 3## 功能介绍 4 5开发者可以调用DRM Kit的C/C++接口实现DRM证书管理、DRM许可证管理、DRM节目授权、DRM节目解密等数字版权保护功能。 6 7DRM Kit提供MediaKeySystem实现DRM证书管理、DRM许可证管理功能,并管理MediaKeySession实例;MediaKeySession实现DRM节目授权,并可支持Media Kit或AVCodec Kit实现DRM节目解密以实现DRM节目播放。 8 9## 开发步骤 10 11详细的API说明请参考[DRM API](../../reference/apis-drm-kit/capi-drm.md)。 12 131. 导入DRM Kit接口。 14 15 ```c++ 16 #include "multimedia/drm_framework/native_drm_common.h" 17 #include "multimedia/drm_framework/native_drm_err.h" 18 #include "multimedia/drm_framework/native_mediakeysession.h" 19 #include "multimedia/drm_framework/native_mediakeysystem.h" 20 ``` 21 222. 在CMake脚本中链接动态库。 23 24 ```txt 25 target_link_libraries(PUBLIC libnative_drm.so) 26 ``` 27 283. 获取设备支持的DRM解决方案名称和唯一标识的列表。 29 30 ```c++ 31 uint32_t count = 3; // count是当前设备实际支持的DRM插件的个数,用户根据实际情况设置。 32 DRM_MediaKeySystemDescription descriptions[3]; 33 memset(descriptions, 0, sizeof(descriptions)); 34 Drm_ErrCode ret = OH_MediaKeySystem_GetMediaKeySystems(descriptions, &count); 35 if (ret != DRM_ERR_OK) { 36 printf("OH_MediaKeySystem_GetMediaKeySystems failed."); 37 } 38 ``` 39 404. (可选)查询设备是否支持对应DRM解决方案名称、媒体类型、安全保护级别的DRM解决方案。 41 42 ```c++ 43 bool isSupported = OH_MediaKeySystem_IsSupported3("com.clearplay.drm", "video/mp4", CONTENT_PROTECTION_LEVEL_SW_CRYPTO); 44 if (isSupported != true) { 45 printf("The device does not support the content protection level."); 46 } 47 ``` 48 495. 创建MediaKeySystem实例。 50 51 ```c++ 52 MediaKeySystem *mediaKeySystem = nullptr; 53 ret = OH_MediaKeySystem_Create("com.clearplay.drm", &mediaKeySystem); 54 if (ret != DRM_ERR_OK || mediaKeySystem == nullptr) { 55 printf("OH_MediaKeySystem_Create failed."); 56 } 57 ``` 58 596. (可选)设置MediaKeySystem事件监听回调。 60 61 ```c++ 62 static Drm_ErrCode SystemCallBackWithObj(MediaKeySystem *mediaKeySystem, DRM_EventType eventType, 63 uint8_t *info, int32_t infoLen, char *extra) 64 { 65 printf("SystemCallBackWithObj enter"); 66 if (eventType == EVENT_PROVISION_REQUIRED) { 67 // 设备DRM证书请求和处理。 68 } 69 return DRM_ERR_OK; 70 } 71 72 ret = OH_MediaKeySystem_SetCallback(mediaKeySystem, SystemCallBackWithObj); 73 if (ret != DRM_ERR_OK) { 74 printf("OH_MediaKeySystem_SetCallback failed."); 75 } 76 ``` 77 787. (可选)获取设备DRM证书状态。 79 80 ```c++ 81 DRM_CertificateStatus certStatus = CERT_STATUS_INVALID; 82 // 检查设备DRM证书状态。 83 ret = OH_MediaKeySystem_GetCertificateStatus(mediaKeySystem, &certStatus); 84 if (ret == DRM_ERR_OK && certStatus != CERT_STATUS_PROVISIONED) { 85 // 设备DRM证书请求和处理。 86 } 87 ``` 88 898. (可选)生成设备DRM证书请求与处理设备DRM证书响应。 90 91 ```c++ 92 #define MAX_DRM_PROVISION_BUF_SIZE 24576 // 24576: (2 * 12 * 1024) 93 unsigned char request[MAX_DRM_PROVISION_BUF_SIZE] = { 0x00 }; // 设备DRM证书request最大长度为MAX_DRM_PROVISION_BUF_SIZE,按实际大小申请。 94 int32_t requestLen = MAX_DRM_PROVISION_BUF_SIZE; 95 // DRM服务URL的最大长度为2048。 96 char defaultUrl[2048] = { 0x00 }; 97 int32_t defaultUrlLen = 2048; 98 ret = OH_MediaKeySystem_GenerateKeySystemRequest(mediaKeySystem, request, &requestLen, defaultUrl, 99 defaultUrlLen); 100 if (ret != DRM_ERR_OK) { 101 printf("OH_MediaKeySystem_GenerateKeySystemRequest failed."); 102 } 103 /* 104 应用通过网络请求,将设备DRM证书请求信息传到DRM服务获取设备DRM证书请求响应keySystemResponse, 105 再将设备DRM证书请求响应设置到设备上,请根据实际的数据和长度传入。 106 */ 107 unsigned char keySystemResponse[MAX_DRM_PROVISION_BUF_SIZE] = {0x00}; 108 ret = OH_MediaKeySystem_ProcessKeySystemResponse(mediaKeySystem, keySystemResponse, sizeof(keySystemResponse)); 109 if (ret != DRM_ERR_OK) { 110 printf("OH_MediaKeySystem_ProcessKeySystemResponse failed."); 111 } 112 ``` 113 1149. (可选)获取设备支持的最大内容保护级别。 115 116 ```c++ 117 DRM_ContentProtectionLevel maxContentProtectionLevel = CONTENT_PROTECTION_LEVEL_UNKNOWN; 118 ret = OH_MediaKeySystem_GetMaxContentProtectionLevel(mediaKeySystem, &maxContentProtectionLevel); 119 if (ret != DRM_ERR_OK) { 120 printf("OH_MediaKeySystem_GetMaxContentProtectionLevel failed."); 121 } 122 ``` 123 12410. 创建MediaKeySession实例。 125 126 ```c++ 127 MediaKeySession *mediaKeySession = nullptr; 128 DRM_ContentProtectionLevel contentProtectionLevel = CONTENT_PROTECTION_LEVEL_SW_CRYPTO; // 依据设备支持的内容保护级别设置。 129 ret = OH_MediaKeySystem_CreateMediaKeySession(mediaKeySystem, &contentProtectionLevel, &mediaKeySession); 130 if (ret != DRM_ERR_OK || mediaKeySession == nullptr) { 131 printf("OH_MediaKeySystem_CreateMediaKeySession failed."); 132 } 133 ``` 134 13511. (可选)设置MediaKeySession事件监听回调。 136 137 ```c++ 138 static Drm_ErrCode SessionEventCallBackWithObj(MediaKeySession *mediaKeySession, DRM_EventType eventType, uint8_t *info, int32_t infoLen, char *extra) 139 { 140 if (eventType == EVENT_KEY_REQUIRED) { 141 // 媒体密钥请求与处理。 142 } 143 return DRM_ERR_OK; 144 } 145 146 static Drm_ErrCode SessionKeyChangeCallBackWithObj(MediaKeySession *mediaKeySession, DRM_KeysInfo *keysInfo, bool hasNewGoodKeys) 147 { 148 return DRM_ERR_OK; 149 } 150 151 OH_MediaKeySession_Callback sessionCallback = { SessionEventCallBackWithObj, SessionKeyChangeCallBackWithObj }; 152 ret = OH_MediaKeySession_SetCallback(mediaKeySession, &sessionCallback); 153 if (ret != DRM_ERR_OK) { 154 printf("OH_MediaKeySession_SetCallback failed."); 155 } 156 ``` 157 15812. (可选)查询是否需要安全解码。 159 160 ```c++ 161 bool requireSecureDecoder; 162 ret = OH_MediaKeySession_RequireSecureDecoderModule(mediaKeySession, "video/avc", &requireSecureDecoder); 163 if (ret != DRM_ERR_OK) { 164 printf("OH_MediaKeySession_RequireSecureDecoderModule failed."); 165 } 166 ``` 167 16813. 生成媒体密钥请求与处理媒体密钥响应,以请求许可证完成DRM节目授权。 169 170 ```c++ 171 #define MAX_DRM_MEDIA_KEY_RESPONSE_BUF_SIZE 24576 // 24576: (2 * 12 * 1024) 172 DRM_MediaKeyRequest mediaKeyRequest; 173 DRM_MediaKeyRequestInfo info; 174 // initData对应码流中的pssh数据,请按实际数据填入。 175 unsigned char initData[512] = {0x00}; 176 memset(&info, 0, sizeof(DRM_MediaKeyRequestInfo)); 177 info.initDataLen = sizeof(initData); 178 info.type = MEDIA_KEY_TYPE_ONLINE; // MEDIA_KEY_TYPE_ONLINE: 在线媒体密钥请求类型; MEDIA_KEY_TYPE_OFFLINE: 离线媒体密钥请求类型。 179 memcpy(info.mimeType, (char *)"video/mp4", sizeof("video/mp4")); 180 memcpy(info.initData, initData, sizeof(initData)); 181 memcpy(info.optionName[0], (char *)"optionalDataName", sizeof("optionalDataName")); 182 memcpy(info.optionData[0], (char *)"optionalDataValue", sizeof("optionalDataValue")); 183 info.optionsCount = 1; 184 ret = OH_MediaKeySession_GenerateMediaKeyRequest(mediaKeySession, &info, &mediaKeyRequest); 185 if (ret != DRM_ERR_OK) { 186 printf("OH_MediaKeySession_GenerateMediaKeyRequest failed."); 187 } 188 /* 189 应用通过网络请求DRM服务,获取媒体密钥响应mediaKeyResponse,将响应传到OH_MediaKeySession_ProcessMediaKeyResponse, 190 若是离线媒体密钥响应处理,则返回离线媒体密钥标识mediaKeyId,请根据实际的数据和长度传入。 191 */ 192 unsigned char mediaKeyId[128] = {0x00}; 193 int32_t mediaKeyIdLen = 128; 194 // 媒体密钥响应长度最大为MAX_DRM_MEDIA_KEY_RESPONSE_BUF_SIZE,请按实际数据输入。 195 unsigned char mediaKeyResponse[MAX_DRM_MEDIA_KEY_RESPONSE_BUF_SIZE] = {0x00}; 196 int32_t mediaKeyResponseLen = MAX_DRM_MEDIA_KEY_RESPONSE_BUF_SIZE; 197 ret = OH_MediaKeySession_ProcessMediaKeyResponse(mediaKeySession, mediaKeyResponse, 198 mediaKeyResponseLen, mediaKeyId, &mediaKeyIdLen); 199 if (ret != DRM_ERR_OK) { 200 printf("OH_MediaKeySession_ProcessMediaKeyResponse failed."); 201 } 202 ``` 203 20414. (可选)恢复离线媒体密钥。 205 206 ```c++ 207 // 将指定媒体密钥标识的媒体密钥加载到当前会话。 208 ret = OH_MediaKeySession_RestoreOfflineMediaKeys(mediaKeySession, mediaKeyId, mediaKeyIdLen); 209 if (ret != DRM_ERR_OK) { 210 printf("OH_MediaKeySession_RestoreOfflineMediaKeys failed."); 211 } 212 ``` 213 21415. (可选)检查媒体密钥状态。 215 216 ```c++ 217 DRM_MediaKeyStatus mediaKeyStatus; 218 ret = OH_MediaKeySession_CheckMediaKeyStatus(mediaKeySession, &mediaKeyStatus); 219 if (ret != DRM_ERR_OK) { 220 printf("OH_MediaKeySession_CheckMediaKeyStatus failed."); 221 } 222 ``` 223 22416. (可选)获取离线媒体密钥标识列表、获取离线媒体密钥状态与清除离线媒体密钥。 225 226 ```c++ 227 DRM_OfflineMediakeyIdArray offlineMediaKeyIds; 228 ret = OH_MediaKeySystem_GetOfflineMediaKeyIds(mediaKeySystem, &offlineMediaKeyIds); 229 if (ret != DRM_ERR_OK) { 230 printf("OH_MediaKeySystem_GetOfflineMediaKeyIds failed."); 231 } 232 DRM_OfflineMediaKeyStatus OfflineMediaKeyStatus = OFFLINE_MEDIA_KEY_STATUS_UNKNOWN; 233 ret = OH_MediaKeySystem_GetOfflineMediaKeyStatus(mediaKeySystem, offlineMediaKeyIds.ids[0], offlineMediaKeyIds.idsLen[0], &OfflineMediaKeyStatus); 234 if (ret != DRM_ERR_OK) { 235 printf("OH_MediaKeySystem_GetOfflineMediaKeyStatus failed."); 236 } 237 ret = OH_MediaKeySystem_ClearOfflineMediaKeys(mediaKeySystem, offlineMediaKeyIds.ids[0], offlineMediaKeyIds.idsLen[0]); 238 if (ret != DRM_ERR_OK) { 239 printf("OH_MediaKeySystem_ClearOfflineMediaKeys failed."); 240 } 241 ``` 242 24317. 销毁MediaKeySession实例。 244 245 ```c++ 246 ret = OH_MediaKeySession_Destroy(mediaKeySession); 247 if (ret != DRM_ERR_OK) { 248 printf("OH_MediaKeySession_Destroy failed."); 249 } 250 ``` 251 25218. 销毁MediaKeySystem实例。 253 254 ```c++ 255 ret = OH_MediaKeySystem_Destroy(mediaKeySystem); 256 if (ret != DRM_ERR_OK) { 257 printf("OH_MediaKeySystem_Destroy failed."); 258 } 259 ```