private static unsafe IntPtr MarshalSubsampleArray(EncryptedPacket packet) { var subsamplePointer = IntPtr.Zero; if (packet.Subsamples != null) { var subsamples = packet.Subsamples.Select(o => new MSD_SUBSAMPLE_INFO { uBytesOfClearData = o.ClearData, uBytesOfEncryptedData = o.EncData }).ToArray(); var totalSize = Marshal.SizeOf(typeof(MSD_SUBSAMPLE_INFO)) * subsamples.Length; var array = Marshal.AllocHGlobal(totalSize); var pointer = (MSD_SUBSAMPLE_INFO *)array.ToPointer(); for (var i = 0; i < subsamples.Length; i++) { pointer[i] = subsamples[i]; } subsamplePointer = (IntPtr)pointer; } var subData = new MSD_FMP4_DATA { uSubSampleCount = (uint)(packet.Subsamples?.Length ?? 0), pSubSampleInfo = subsamplePointer }; var subdataPointer = Marshal.AllocHGlobal(Marshal.SizeOf(subData)); Marshal.StructureToPtr(subData, subdataPointer, false); return(subdataPointer); }
private unsafe eCDMReturnType CreateParamsAndDecryptData(EncryptedPacket packet, byte *data, int dataLen, ref HandleSize[] pHandleArray, CancellationToken token) { fixed(byte *iv = packet.Iv, kId = packet.KeyId) { var subdataPointer = MarshalSubsampleArray(packet); var subsampleInfoPointer = ((MSD_FMP4_DATA *)subdataPointer.ToPointer())->pSubSampleInfo; try { var param = new sMsdCipherParam { algorithm = eMsdCipherAlgorithm.MSD_AES128_CTR, format = eMsdMediaFormat.MSD_FORMAT_FMP4, pdata = data, udatalen = (uint)dataLen, piv = iv, uivlen = (uint)packet.Iv.Length, pkid = kId, ukidlen = (uint)packet.KeyId.Length, psubdata = subdataPointer }; return(DecryptData(new[] { param }, ref pHandleArray, packet.StreamType, token)); } finally { if (subsampleInfoPointer != IntPtr.Zero) { Marshal.FreeHGlobal(subsampleInfoPointer); } Marshal.FreeHGlobal(subdataPointer); } } }
private Packet DecryptPacketOnIemeThread(EncryptedPacket packet, CancellationToken token) { // Do padding only for Widevine with keys shorter then 16 bytes // Shorter keys need to be zero padded, not PCKS#7 if (DrmType == EmeUtils.DrmType.Widevine && packet.Iv.Length < 16) { packet.Iv = PadIv(packet.Iv); } var pHandleArray = new HandleSize[1]; var ret = CreateParamsAndDecryptData(packet, ref pHandleArray, token); if (ret == eCDMReturnType.E_SUCCESS) { return(new DecryptedEMEPacket(thread) { Dts = packet.Dts, Pts = packet.Pts, StreamType = packet.StreamType, IsKeyFrame = packet.IsKeyFrame, Duration = packet.Duration, HandleSize = pHandleArray[0] }); } Logger.Error($"Decryption failed: {packet.StreamType} - {ret}"); throw new DrmException($"Decryption failed: {packet.StreamType} - {ret}"); }
private unsafe eCDMReturnType CreateParamsAndDecryptData(EncryptedPacket packet, ref HandleSize[] pHandleArray, CancellationToken token) { switch (packet.Storage) { case IManagedDataStorage managedStorage: fixed(byte *data = managedStorage.Data) return(CreateParamsAndDecryptData(packet, data, managedStorage.Data.Length, ref pHandleArray, token)); case INativeDataStorage nativeStorage: return(CreateParamsAndDecryptData(packet, nativeStorage.Data, nativeStorage.Length, ref pHandleArray, token)); default: throw new DrmException($"Unsupported packet storage: {packet.Storage?.GetType()}"); } }
public async Task <Packet> DecryptPacket(EncryptedPacket packet, CancellationToken token) { ThrowIfDisposed(); return(await thread.Factory.Run(() => DecryptPacketOnIemeThread(packet, token))); }