DeCSSInputPin.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:9k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include <atlbase.h>
  23. #include <streams.h>
  24. #include <dvdmedia.h>
  25. #include <ks.h>
  26. #include <ksmedia.h>
  27. #include "DeCSSInputPin.h"
  28. #include "..DSUtilDSUtil.h"
  29. #include "CSSauth.h"
  30. #include "CSSscramble.h"
  31. #include <initguid.h>
  32. #include "....includemoreuuids.h"
  33. //
  34. // CDeCSSInputPin
  35. //
  36. CDeCSSInputPin::CDeCSSInputPin(TCHAR* pObjectName, CTransformFilter* pFilter, HRESULT* phr, LPWSTR pName)
  37. : CTransformInputPin(pObjectName, pFilter, phr, pName)
  38. {
  39. m_varient = -1;
  40. memset(m_Challenge, 0, sizeof(m_Challenge));
  41. memset(m_KeyCheck, 0, sizeof(m_KeyCheck));
  42. memset(m_DiscKey, 0, sizeof(m_DiscKey));
  43. memset(m_TitleKey, 0, sizeof(m_TitleKey));
  44. }
  45. STDMETHODIMP CDeCSSInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
  46. {
  47.     CheckPointer(ppv, E_POINTER);
  48. return
  49. QI(IKsPropertySet)
  50.  __super::NonDelegatingQueryInterface(riid, ppv);
  51. }
  52. // IMemInputPin
  53. STDMETHODIMP CDeCSSInputPin::Receive(IMediaSample* pSample)
  54. {
  55. long len = pSample->GetActualDataLength();
  56. BYTE* p = NULL;
  57. if(SUCCEEDED(pSample->GetPointer(&p)) && len > 0)
  58. {
  59. BYTE* base = p;
  60. if(m_mt.majortype == MEDIATYPE_DVD_ENCRYPTED_PACK && len == 2048 && (p[0x14]&0x30))
  61. {
  62. CSSdescramble(p, m_TitleKey);
  63. p[0x14] &= ~0x30;
  64. if(CComQIPtr<IMediaSample2> pMS2 = pSample)
  65. {
  66. AM_SAMPLE2_PROPERTIES props;
  67. memset(&props, 0, sizeof(props));
  68. if(SUCCEEDED(pMS2->GetProperties(sizeof(props), (BYTE*)&props))
  69. && (props.dwTypeSpecificFlags & AM_UseNewCSSKey))
  70. {
  71. props.dwTypeSpecificFlags &= ~AM_UseNewCSSKey;
  72. pMS2->SetProperties(sizeof(props), (BYTE*)&props);
  73. }
  74. }
  75. }
  76. }
  77. HRESULT hr = Transform(pSample);
  78. return hr == S_OK ? __super::Receive(pSample) :
  79. hr == S_FALSE ? S_OK : hr;
  80. }
  81. void CDeCSSInputPin::StripPacket(BYTE*& p, long& len)
  82. {
  83. GUID majortype = m_mt.majortype;
  84. if(majortype == MEDIATYPE_MPEG2_PACK || majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
  85. if(len > 0 && *(DWORD*)p == 0xba010000) // MEDIATYPE_*_PACK
  86. {
  87. len -= 14; p += 14;
  88. if(int stuffing = (p[-1]&7)) {len -= stuffing; p += stuffing;}
  89. majortype = MEDIATYPE_MPEG2_PES;
  90. }
  91. if(majortype == MEDIATYPE_MPEG2_PES)
  92. if(len > 0 && *(DWORD*)p == 0xbb010000)
  93. {
  94. len -= 4; p += 4;
  95. int hdrlen = ((p[0]<<8)|p[1]) + 2;
  96. len -= hdrlen; p += hdrlen;
  97. }
  98. if(majortype == MEDIATYPE_MPEG2_PES)
  99. if(len > 0 
  100. && ((*(DWORD*)p&0xf0ffffff) == 0xe0010000 
  101. || (*(DWORD*)p&0xe0ffffff) == 0xc0010000
  102. || (*(DWORD*)p&0xbdffffff) == 0xbd010000)) // PES
  103. {
  104. bool ps1 = (*(DWORD*)p&0xbdffffff) == 0xbd010000;
  105. len -= 4; p += 4;
  106. int expected = ((p[0]<<8)|p[1]);
  107. len -= 2; p += 2;
  108. BYTE* p0 = p;
  109. for(int i = 0; i < 16 && *p == 0xff; i++, len--, p++);
  110. if((*p&0xc0) == 0x80) // mpeg2
  111. {
  112. len -= 2; p += 2;
  113. len -= *p+1; p += *p+1;
  114. }
  115. else // mpeg1
  116. {
  117. if((*p&0xc0) == 0x40) 
  118. {
  119. len -= 2; p += 2;
  120. }
  121. if((*p&0x30) == 0x30 || (*p&0x30) == 0x20)
  122. {
  123. bool pts = !!(*p&0x20), dts = !!(*p&0x10);
  124. if(pts) len -= 5; p += 5;
  125. if(dts) {ASSERT((*p&0xf0) == 0x10); len -= 5; p += 5;}
  126. }
  127. else
  128. {
  129. len--; p++;
  130. }
  131. }
  132. if(ps1)
  133. {
  134. len--; p++;
  135. if(m_mt.subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO) {len -= 6; p += 6;}
  136. else if(m_mt.subtype == MEDIASUBTYPE_DOLBY_AC3 || m_mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3 
  137. || m_mt.subtype == MEDIASUBTYPE_DTS || m_mt.subtype == MEDIASUBTYPE_WAVE_DTS) {len -= 3; p += 3;}
  138. }
  139. if(expected > 0)
  140. {
  141. expected -= (p - p0);
  142. len = min(expected, len);
  143. }
  144. }
  145. if(len < 0) {ASSERT(0); len = 0;}
  146. }
  147. // IKsPropertySet
  148. STDMETHODIMP CDeCSSInputPin::Set(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength)
  149. {
  150. if(PropSet != AM_KSPROPSETID_CopyProt)
  151. return E_NOTIMPL;
  152. switch(Id)
  153. {
  154. case AM_PROPERTY_COPY_MACROVISION:
  155. break;
  156. case AM_PROPERTY_DVDCOPY_CHLG_KEY: // 3. auth: receive drive nonce word, also store and encrypt the buskey made up of the two nonce words
  157. {
  158. AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
  159. for(int i = 0; i < 10; i++)
  160. m_Challenge[i] = pChlgKey->ChlgKey[9-i];
  161. CSSkey2(m_varient, m_Challenge, &m_Key[5]);
  162. CSSbuskey(m_varient, m_Key, m_KeyCheck);
  163. }
  164. break;
  165. case AM_PROPERTY_DVDCOPY_DISC_KEY: // 5. receive the disckey
  166. {
  167. AM_DVDCOPY_DISCKEY* pDiscKey = (AM_DVDCOPY_DISCKEY*)pPropertyData; // pDiscKey->DiscKey holds the disckey encrypted with itself and the 408 disckeys encrypted with the playerkeys
  168. bool fSuccess = false;
  169. for(int j = 0; j < g_nPlayerKeys; j++)
  170. {
  171. for(int k = 1; k < 409; k++)
  172. {
  173. BYTE DiscKey[6];
  174. for(int i = 0; i < 5; i++)
  175. DiscKey[i] = pDiscKey->DiscKey[k*5+i] ^ m_KeyCheck[4-i];
  176. DiscKey[5] = 0;
  177. CSSdisckey(DiscKey, g_PlayerKeys[j]);
  178. BYTE Hash[6];
  179. for(int i = 0; i < 5; i++)
  180. Hash[i] = pDiscKey->DiscKey[i] ^ m_KeyCheck[4-i];
  181. Hash[5] = 0;
  182. CSSdisckey(Hash, DiscKey);
  183. if(!memcmp(Hash, DiscKey, 6))
  184. {
  185. memcpy(m_DiscKey, DiscKey, 6);
  186. j = g_nPlayerKeys;
  187. fSuccess = true;
  188. break;
  189. }
  190. }
  191. }
  192. if(!fSuccess)
  193. return E_FAIL;
  194. }
  195. break;
  196. case AM_PROPERTY_DVDCOPY_DVD_KEY1: // 2. auth: receive our drive-encrypted nonce word and decrypt it for verification
  197. {
  198. AM_DVDCOPY_BUSKEY* pKey1 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
  199. for(int i = 0; i < 5; i++)
  200. m_Key[i] =  pKey1->BusKey[4-i];
  201. m_varient = -1;
  202. for(int i = 31; i >= 0; i--)
  203. {
  204. CSSkey1(i, m_Challenge, m_KeyCheck);
  205. if(memcmp(m_KeyCheck, &m_Key[0], 5) == 0)
  206. m_varient = i;
  207. }
  208. }
  209. break;
  210. case AM_PROPERTY_DVDCOPY_REGION:
  211. break;
  212. case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
  213. break;
  214. case AM_PROPERTY_DVDCOPY_TITLE_KEY: // 6. receive the title key and decrypt it with the disc key
  215. {
  216. AM_DVDCOPY_TITLEKEY* pTitleKey = (AM_DVDCOPY_TITLEKEY*)pPropertyData;
  217. for(int i = 0; i < 5; i++)
  218. m_TitleKey[i] = pTitleKey->TitleKey[i] ^ m_KeyCheck[4-i];
  219. m_TitleKey[5] = 0;
  220. CSStitlekey(m_TitleKey, m_DiscKey);
  221. }
  222. break;
  223. default:
  224. return E_PROP_ID_UNSUPPORTED;
  225. }
  226. return S_OK;
  227. }
  228. STDMETHODIMP CDeCSSInputPin::Get(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength, ULONG* pBytesReturned)
  229. {
  230. if(PropSet != AM_KSPROPSETID_CopyProt)
  231. return E_NOTIMPL;
  232. switch(Id)
  233. {
  234. case AM_PROPERTY_DVDCOPY_CHLG_KEY: // 1. auth: send our nonce word
  235. {
  236. AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
  237. for(int i = 0; i < 10; i++)
  238. pChlgKey->ChlgKey[i] = 9 - (m_Challenge[i] = i);
  239. *pBytesReturned = sizeof(AM_DVDCOPY_CHLGKEY);
  240. }
  241. break;
  242. case AM_PROPERTY_DVDCOPY_DEC_KEY2: // 4. auth: send back the encrypted drive nonce word to finish the authentication
  243. {
  244. AM_DVDCOPY_BUSKEY* pKey2 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
  245. for(int i = 0; i < 5; i++)
  246. pKey2->BusKey[4-i] = m_Key[5+i];
  247. *pBytesReturned = sizeof(AM_DVDCOPY_BUSKEY);
  248. }
  249. break;
  250. case AM_PROPERTY_DVDCOPY_REGION:
  251. {
  252. DVD_REGION* pRegion = (DVD_REGION*)pPropertyData;
  253. pRegion->RegionData = 0;
  254. pRegion->SystemRegion = 0;
  255. *pBytesReturned = sizeof(DVD_REGION);
  256. }
  257. break;
  258. case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
  259. {
  260. AM_DVDCOPY_SET_COPY_STATE* pState = (AM_DVDCOPY_SET_COPY_STATE*)pPropertyData;
  261. pState->DVDCopyState = AM_DVDCOPYSTATE_AUTHENTICATION_REQUIRED;
  262. *pBytesReturned = sizeof(AM_DVDCOPY_SET_COPY_STATE);
  263. }
  264. break;
  265. default:
  266. return E_PROP_ID_UNSUPPORTED;
  267. }
  268. return S_OK;
  269. }
  270. STDMETHODIMP CDeCSSInputPin::QuerySupported(REFGUID PropSet, ULONG Id, ULONG* pTypeSupport)
  271. {
  272. if(PropSet != AM_KSPROPSETID_CopyProt)
  273. return E_NOTIMPL;
  274. switch(Id)
  275. {
  276. case AM_PROPERTY_COPY_MACROVISION:
  277. *pTypeSupport = KSPROPERTY_SUPPORT_SET;
  278. break;
  279. case AM_PROPERTY_DVDCOPY_CHLG_KEY:
  280. *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
  281. break;
  282. case AM_PROPERTY_DVDCOPY_DEC_KEY2:
  283. *pTypeSupport = KSPROPERTY_SUPPORT_GET;
  284. break;
  285. case AM_PROPERTY_DVDCOPY_DISC_KEY:
  286. *pTypeSupport = KSPROPERTY_SUPPORT_SET;
  287. break;
  288. case AM_PROPERTY_DVDCOPY_DVD_KEY1:
  289. *pTypeSupport = KSPROPERTY_SUPPORT_SET;
  290. break;
  291. case AM_PROPERTY_DVDCOPY_REGION:
  292. *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
  293. break;
  294. case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
  295. *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
  296. break;
  297. case AM_PROPERTY_DVDCOPY_TITLE_KEY:
  298. *pTypeSupport = KSPROPERTY_SUPPORT_SET;
  299. break;
  300. default:
  301. return E_PROP_ID_UNSUPPORTED;
  302. }
  303. return S_OK;
  304. }