Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

568 lines
16 KiB

  1. // Copyright (c) 1999 Microsoft Corporation. All rights reserved.
  2. //
  3. // Declaration of CParams.
  4. //
  5. #include "dmerror.h"
  6. #include "param.h"
  7. #include "math.h"
  8. #include "validate.h"
  9. #include "debug.h"
  10. #pragma warning(disable:4296)
  11. CCurveList::~CCurveList()
  12. {
  13. while(this->GetHead())
  14. {
  15. delete this->RemoveHead();
  16. }
  17. }
  18. CParamsManager::CParamsManager()
  19. {
  20. m_fDirty = FALSE;
  21. m_cTimeFormats = 0;
  22. m_pguidTimeFormats = NULL;
  23. m_guidCurrentTimeFormat = GUID_NULL;
  24. m_cParams = 0;
  25. m_pCurveLists = NULL;
  26. m_pParamInfos = NULL;
  27. m_dwActiveBits = 0;
  28. InitializeCriticalSection(&m_ParamsCriticalSection);
  29. }
  30. CParamsManager::~CParamsManager()
  31. {
  32. delete[] m_pguidTimeFormats;
  33. delete[] m_pCurveLists;
  34. delete[] m_pParamInfos;
  35. DeleteCriticalSection(&m_ParamsCriticalSection);
  36. }
  37. HRESULT CParamsManager::InitParams(DWORD cTimeFormats, const GUID *pguidTimeFormats, DWORD dwFormatIndex, MP_TIMEDATA mptdTimeData, DWORD cParams, ParamInfo *pParamInfo)
  38. {
  39. //check that the index is in a valid range
  40. if (0 > dwFormatIndex || dwFormatIndex >= cTimeFormats || cParams > sizeof(DWORD) * 8)
  41. return E_INVALIDARG;
  42. m_pCurveLists = new CCurveList[cParams];
  43. if (!m_pCurveLists)
  44. return E_OUTOFMEMORY;
  45. // save the time formats
  46. m_pguidTimeFormats = new GUID[cTimeFormats];
  47. if (!m_pguidTimeFormats)
  48. return E_OUTOFMEMORY;
  49. for (DWORD dwIndex = 0; dwIndex < cTimeFormats; dwIndex++)
  50. {
  51. memcpy(&m_pguidTimeFormats[dwIndex], &pguidTimeFormats[dwIndex], sizeof(*pguidTimeFormats));
  52. }
  53. // save the count of formats
  54. m_cTimeFormats = cTimeFormats;
  55. // save the current time format
  56. m_guidCurrentTimeFormat = m_pguidTimeFormats[dwFormatIndex];
  57. // save the TimeData
  58. m_mptdCurrentTimeData = mptdTimeData;
  59. // save the parameter info
  60. m_pParamInfos
  61. = new ParamInfo[cParams];
  62. if (!m_pParamInfos)
  63. return E_OUTOFMEMORY;
  64. for (dwIndex = 0; dwIndex < cParams; dwIndex++)
  65. {
  66. if (pParamInfo[dwIndex].dwIndex < cParams)
  67. {
  68. memcpy(&m_pParamInfos[pParamInfo[dwIndex].dwIndex],&pParamInfo[dwIndex],sizeof(ParamInfo));
  69. }
  70. }
  71. m_cParams = cParams;
  72. return S_OK;
  73. }
  74. HRESULT CParamsManager::GetParamCount(DWORD *pdwParams)
  75. {
  76. if (pdwParams == NULL)
  77. return E_POINTER;
  78. *pdwParams = m_cParams;
  79. return S_OK;
  80. }
  81. HRESULT CParamsManager::GetParamInfo(DWORD dwParamIndex,MP_PARAMINFO *pInfo)
  82. {
  83. if (!pInfo)
  84. {
  85. return E_POINTER;
  86. }
  87. if (dwParamIndex < m_cParams)
  88. {
  89. *pInfo = m_pParamInfos[dwParamIndex].MParamInfo;
  90. return S_OK;
  91. }
  92. else
  93. {
  94. return E_INVALIDARG;
  95. }
  96. }
  97. HRESULT CParamsManager::GetParamText(DWORD dwParamIndex,WCHAR **ppwchText)
  98. {
  99. if (!ppwchText)
  100. {
  101. return E_POINTER;
  102. }
  103. if (dwParamIndex < m_cParams)
  104. {
  105. // write string of format: "Label\0Unit\0Enums1\0Enum2\0...EnumN\0\0"
  106. ParamInfo &pinfo = m_pParamInfos[dwParamIndex];
  107. int iUnit = wcslen(pinfo.MParamInfo.szLabel) + 1; // begin writing unit text here
  108. int iEnums = iUnit + wcslen(pinfo.MParamInfo.szUnitText) + 1; // begin writing enum text here
  109. int iEnd = iEnums + wcslen(pinfo.pwchText) + 1; // write the final (second) null terminator here
  110. WCHAR *pwsz = static_cast<WCHAR *>(CoTaskMemAlloc((iEnd + 1) * sizeof(WCHAR)));
  111. if (!pwsz)
  112. return E_OUTOFMEMORY;
  113. // StringCchPrintfW will write into various points of the string, neatly terminating each with a null
  114. StringCchPrintfW(pwsz,iEnd+1,L"%ls%lc%ls%lc%s%lc",pinfo.MParamInfo.szLabel,L'\0', pinfo.MParamInfo.szUnitText,L'\0', pinfo.pwchText,L'\0');
  115. // The text field was defined with commas to separate the enum values.
  116. // Replace them with NULL characters now.
  117. for (WCHAR *pwch = pwsz + iEnums; *pwch; ++pwch)
  118. {
  119. if (*pwch == L',')
  120. *pwch = L'\0';
  121. }
  122. pwsz[iEnd] = L'\0';
  123. *ppwchText = pwsz;
  124. return S_OK;
  125. }
  126. else
  127. {
  128. return E_INVALIDARG;
  129. }
  130. }
  131. HRESULT CParamsManager::GetNumTimeFormats(DWORD *pdwNumTimeFormats)
  132. {
  133. if (!pdwNumTimeFormats)
  134. {
  135. return E_POINTER;
  136. }
  137. *pdwNumTimeFormats = m_cTimeFormats;
  138. return S_OK;
  139. }
  140. HRESULT CParamsManager::GetSupportedTimeFormat(DWORD dwFormatIndex,GUID *pguidTimeFormat)
  141. {
  142. if (!pguidTimeFormat)
  143. {
  144. return E_POINTER;
  145. }
  146. if (dwFormatIndex >= m_cTimeFormats)
  147. {
  148. return E_INVALIDARG;
  149. }
  150. *pguidTimeFormat = m_pguidTimeFormats[dwFormatIndex];
  151. return S_OK;
  152. }
  153. HRESULT CParamsManager::GetCurrentTimeFormat( GUID *pguidTimeFormat,MP_TIMEDATA *pTimeData)
  154. {
  155. HRESULT hr=S_OK;
  156. // Parameter Validation
  157. if ((pguidTimeFormat == NULL) || (pTimeData == NULL))
  158. {
  159. hr = E_POINTER;
  160. Trace(1,"ERROR: pGuidTimeFormat or pTimeData is NULL\n");
  161. }
  162. // Return the values
  163. if (SUCCEEDED(hr))
  164. {
  165. *pguidTimeFormat = m_guidCurrentTimeFormat;
  166. *pTimeData = m_mptdCurrentTimeData;
  167. }
  168. return hr;
  169. }
  170. HRESULT CParamsManager::CopyParamsFromSource( CParamsManager * pSource)
  171. {
  172. HRESULT hr = S_OK;
  173. DWORD dwIndex;
  174. for (dwIndex = 0; dwIndex < m_cParams; dwIndex++)
  175. {
  176. if (pSource->m_guidCurrentTimeFormat == m_pguidTimeFormats[dwIndex])
  177. {
  178. break;
  179. }
  180. }
  181. hr = InitParams(pSource->m_cTimeFormats, pSource->m_pguidTimeFormats, dwIndex, pSource->m_mptdCurrentTimeData, pSource->m_cParams,pSource->m_pParamInfos);
  182. if (SUCCEEDED(hr))
  183. {
  184. for (dwIndex = 0; dwIndex < m_cParams; dwIndex++)
  185. {
  186. CCurveItem *pCurve = pSource->m_pCurveLists[dwIndex].GetHead();
  187. for (;pCurve;pCurve = pCurve->GetNext())
  188. {
  189. CCurveItem *pNew = new CCurveItem;
  190. if (!pNew)
  191. {
  192. return E_OUTOFMEMORY;
  193. }
  194. pNew->m_Envelope = pCurve->m_Envelope;
  195. m_pCurveLists[dwIndex].AddTail(pNew);
  196. }
  197. }
  198. }
  199. return hr;
  200. }
  201. void
  202. CParamsManager ::UpdateActiveParams(REFERENCE_TIME rtTime, UpdateCallback &rThis)
  203. {
  204. if (!m_dwActiveBits)
  205. return; // nothing to recalc
  206. DWORD dwBit = 1;
  207. for (DWORD dwIndex = 0; dwIndex < m_cParams; dwIndex++, dwBit = dwBit << 1)
  208. {
  209. if (m_dwActiveBits & dwBit)
  210. {
  211. float fVal = 0;
  212. HRESULT hr = GetParamFloat(dwIndex, rtTime, &fVal);
  213. rThis.SetParamUpdate(dwIndex, fVal);
  214. if (hr == S_FALSE)
  215. m_dwActiveBits &= ~dwBit; // we're beyond the last curve, don't need to recalc next time
  216. TraceI(6, "DMO value: time %I64d, param #%d, current value %hf\n", rtTime, dwIndex, fVal);
  217. }
  218. }
  219. }
  220. inline float ValRange(float valToClip, float valMin, float valMax)
  221. {
  222. return valToClip < valMin
  223. ? valMin
  224. : (valToClip > valMax ? valMax : valToClip);
  225. }
  226. HRESULT CParamsManager::GetParamFloat(DWORD dwParamIndex,REFERENCE_TIME rtTime,float *pval)
  227. {
  228. HRESULT hr = S_OK;
  229. if (dwParamIndex >= m_cParams)
  230. return E_INVALIDARG;
  231. EnterCriticalSection(&m_ParamsCriticalSection);
  232. CCurveList *pList = &m_pCurveLists[dwParamIndex];
  233. ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  234. // if no points, then neutral value
  235. CCurveItem *pCurveHead = pList->GetHead();
  236. if (!pCurveHead)
  237. {
  238. *pval = pInfo->MParamInfo.mpdNeutralValue;
  239. LeaveCriticalSection(&m_ParamsCriticalSection);
  240. return S_FALSE;
  241. }
  242. // Find the curve during or before the requested time
  243. // If the time is during a curve, we will use that.
  244. // If not, we need the end value of the previous curve.
  245. // Our list keeps these in backwards order, so we are scanning from the
  246. // highest point in time backwards.
  247. for (CCurveItem *pCurve = pCurveHead; pCurve && pCurve->m_Envelope.rtStart > rtTime;pCurve = pCurve->GetNext());
  248. // If there is no pCurve, there was no curve prior to or during rtTime. Give up.
  249. if (!pCurve)
  250. {
  251. *pval = pInfo->MParamInfo.mpdNeutralValue;
  252. LeaveCriticalSection(&m_ParamsCriticalSection);
  253. return S_OK;
  254. }
  255. // Now, if pCurve ends before the requested time,
  256. // return the final value of pCurve, since that will hold until the start of the next curve.
  257. if (pCurve->m_Envelope.rtEnd < rtTime)
  258. {
  259. *pval = pCurve->m_Envelope.valEnd;
  260. LeaveCriticalSection(&m_ParamsCriticalSection);
  261. if (pCurve == pCurveHead)
  262. return S_FALSE; // past last curve
  263. else
  264. return S_OK; // there are more curves ahead
  265. }
  266. // If we get this far, the curve must bound rtTime.
  267. if (pCurve->m_Envelope.iCurve & MP_CURVE_JUMP)
  268. {
  269. *pval = pCurve->m_Envelope.valEnd;
  270. LeaveCriticalSection(&m_ParamsCriticalSection);
  271. return S_OK;
  272. }
  273. REFERENCE_TIME rtTimeChange = pCurve->m_Envelope.rtEnd - pCurve->m_Envelope.rtStart;
  274. REFERENCE_TIME rtTimeIntermediate = rtTime - pCurve->m_Envelope.rtStart;
  275. float fltScalingX = static_cast<float>(rtTimeIntermediate) / rtTimeChange; // horizontal distance along curve between 0 and 1
  276. float fltScalingY; // height of curve at that point between 0 and 1 based on curve function
  277. switch (pCurve->m_Envelope.iCurve)
  278. {
  279. case MP_CURVE_SQUARE:
  280. fltScalingY = fltScalingX * fltScalingX;
  281. break;
  282. case MP_CURVE_INVSQUARE:
  283. fltScalingY = (float) sqrt(fltScalingX);
  284. break;
  285. case MP_CURVE_SINE:
  286. // �� Maybe we should have a lookup table here?
  287. fltScalingY = (float) (sin(fltScalingX * 3.1415926535 - (3.1415926535/2)) + 1) / 2;
  288. break;
  289. case MP_CURVE_LINEAR:
  290. default:
  291. fltScalingY = fltScalingX;
  292. }
  293. // Find out if we need to pull the start point from the previous curve,
  294. // the default neutral value, or the current curve.
  295. float fStartVal = pCurve->m_Envelope.valStart;
  296. if (pCurve->m_Envelope.flags & MPF_ENVLP_BEGIN_NEUTRALVAL)
  297. {
  298. fStartVal = pInfo->MParamInfo.mpdNeutralValue;
  299. }
  300. // Currentval, if it exists, will override neutralval.
  301. if (pCurve->m_Envelope.flags & MPF_ENVLP_BEGIN_CURRENTVAL)
  302. {
  303. // Take advantage of the fact that these are inserted in backwards order.
  304. // Scan for the previous curve that ends before this time.
  305. CCurveItem *pPrevious = pCurve->GetNext();
  306. for (;pPrevious && pPrevious->m_Envelope.rtEnd > rtTime;pPrevious = pPrevious->GetNext());
  307. if (pPrevious)
  308. {
  309. fStartVal = pPrevious->m_Envelope.valEnd;
  310. }
  311. }
  312. // Apply that scaling to the range of the actual points
  313. *pval = (pCurve->m_Envelope.valEnd - fStartVal) * fltScalingY + fStartVal;
  314. LeaveCriticalSection(&m_ParamsCriticalSection);
  315. return hr;
  316. }
  317. HRESULT CParamsManager::GetParamInt(DWORD dwParamIndex,REFERENCE_TIME rt,long *pval)
  318. {
  319. HRESULT hr = E_POINTER;
  320. if (pval)
  321. {
  322. float fVal;
  323. hr = GetParamFloat(dwParamIndex,rt,&fVal);
  324. if (SUCCEEDED(hr))
  325. {
  326. *pval = (long) (fVal + 1/2); // Round.
  327. }
  328. }
  329. else
  330. {
  331. Trace(1,"ERROR: pval is NULL\n");
  332. }
  333. return hr;
  334. }
  335. //////////////////////////////////////////////////////////////////////
  336. // IMediaParams
  337. HRESULT CParamsManager::GetParam(DWORD dwParamIndex,MP_DATA *pValue)
  338. {
  339. V_INAME(CParams::GetParam);
  340. V_PTR_WRITE(pValue, MP_DATA);
  341. if (dwParamIndex >= m_cParams)
  342. return E_INVALIDARG;
  343. EnterCriticalSection(&m_ParamsCriticalSection);
  344. CCurveList *pList = &m_pCurveLists[dwParamIndex];
  345. ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  346. // if no points, then neutral value
  347. CCurveItem *pCurve = pList->GetHead();
  348. if (pCurve)
  349. {
  350. *pValue = pCurve->m_Envelope.valEnd;
  351. }
  352. else
  353. {
  354. *pValue = pInfo->MParamInfo.mpdNeutralValue;
  355. }
  356. LeaveCriticalSection(&m_ParamsCriticalSection);
  357. return S_OK;
  358. }
  359. HRESULT CParamsManager::SetParam(DWORD dwParamIndex,MP_DATA value)
  360. {
  361. V_INAME(CParams::SetParam);
  362. if (dwParamIndex >= m_cParams)
  363. return E_INVALIDARG;
  364. EnterCriticalSection(&m_ParamsCriticalSection);
  365. m_fDirty = TRUE;
  366. CCurveList *pList = &m_pCurveLists[dwParamIndex];
  367. ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  368. // If we've already got a list, just force the most recent curve item to this value.
  369. // Otherwise, create a node and add it.
  370. CCurveItem *pCurve = pList->GetHead();
  371. if (!pCurve)
  372. {
  373. pCurve = new CCurveItem;
  374. if (pCurve)
  375. {
  376. pCurve->m_Envelope.rtStart = 0x8000000000000000; // Max negative.
  377. pCurve->m_Envelope.rtEnd = 0x7FFFFFFFFFFFFFFF; // Max positive.
  378. pCurve->m_Envelope.flags = 0;
  379. pList->AddHead(pCurve);
  380. }
  381. else
  382. {
  383. LeaveCriticalSection(&m_ParamsCriticalSection);
  384. return E_OUTOFMEMORY;
  385. }
  386. }
  387. pCurve->m_Envelope.valStart = value;
  388. pCurve->m_Envelope.valEnd = value;
  389. pCurve->m_Envelope.iCurve = MP_CURVE_JUMP;
  390. LeaveCriticalSection(&m_ParamsCriticalSection);
  391. return S_OK;
  392. }
  393. HRESULT CParamsManager::AddEnvelope(
  394. DWORD dwParamIndex,
  395. DWORD cPoints,
  396. MP_ENVELOPE_SEGMENT *ppEnvelope)
  397. {
  398. V_INAME(CParams::AddEnvelope);
  399. V_PTR_READ(ppEnvelope, *ppEnvelope);
  400. if (dwParamIndex >= m_cParams)
  401. return E_INVALIDARG;
  402. if (!m_pParamInfos)
  403. return DMUS_E_NOT_INIT;
  404. HRESULT hr = S_OK;
  405. EnterCriticalSection(&m_ParamsCriticalSection);
  406. m_fDirty = TRUE;
  407. CCurveList *pList = &m_pCurveLists[dwParamIndex];
  408. ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  409. DWORD dwCount;
  410. for (dwCount = 0; dwCount < cPoints; dwCount++)
  411. {
  412. CCurveItem *pCurve = new CCurveItem;
  413. if (!pCurve)
  414. {
  415. hr = E_OUTOFMEMORY;
  416. Trace(1,"ERROR: Out of memory\n");
  417. break;
  418. }
  419. pCurve->m_Envelope = ppEnvelope[dwCount];
  420. pCurve->m_Envelope.valEnd = ValRange(pCurve->m_Envelope.valEnd,
  421. pInfo->MParamInfo.mpdMinValue, pInfo->MParamInfo.mpdMaxValue);
  422. pCurve->m_Envelope.valStart = ValRange(pCurve->m_Envelope.valStart,
  423. pInfo->MParamInfo.mpdMinValue, pInfo->MParamInfo.mpdMaxValue);
  424. pList->AddHead(pCurve);
  425. m_dwActiveBits |= 1 << dwParamIndex; // next call to UpdateActiveParams will ensure the parameter's value is recalculated
  426. TraceI(6, "DMO envelope: time %I64d-%I64d, param #%d, value %hf-%hf\n",
  427. pCurve->m_Envelope.rtStart, pCurve->m_Envelope.rtEnd,
  428. dwParamIndex, pCurve->m_Envelope.valStart, pCurve->m_Envelope.valEnd);
  429. }
  430. LeaveCriticalSection(&m_ParamsCriticalSection);
  431. return hr;
  432. }
  433. HRESULT CParamsManager::FlushEnvelope(
  434. DWORD dwParamIndex,
  435. REFERENCE_TIME refTimeStart,
  436. REFERENCE_TIME refTimeEnd)
  437. {
  438. if (dwParamIndex >= m_cParams)
  439. return E_INVALIDARG;
  440. if (!m_pParamInfos)
  441. return DMUS_E_NOT_INIT;
  442. if (refTimeStart >= refTimeEnd)
  443. return E_INVALIDARG;
  444. EnterCriticalSection(&m_ParamsCriticalSection);
  445. m_fDirty = TRUE;
  446. CCurveList *pList = &m_pCurveLists[dwParamIndex];
  447. ParamInfo *pInfo = &m_pParamInfos[dwParamIndex];
  448. CCurveList TempList;
  449. CCurveItem *pCurve;
  450. while (pCurve = pList->RemoveHead())
  451. {
  452. if ((pCurve->m_Envelope.rtStart >= refTimeStart) &&
  453. (pCurve->m_Envelope.rtEnd <= refTimeEnd))
  454. {
  455. delete pCurve;
  456. }
  457. else
  458. {
  459. TempList.AddHead(pCurve);
  460. }
  461. }
  462. while (pCurve = TempList.RemoveHead())
  463. {
  464. pList->AddHead(pCurve);
  465. }
  466. LeaveCriticalSection(&m_ParamsCriticalSection);
  467. return S_OK;
  468. }
  469. HRESULT CParamsManager::SetTimeFormat(
  470. GUID guidTimeFormat,
  471. MP_TIMEDATA mpTimeData)
  472. {
  473. for (DWORD dwIndex = 0; dwIndex < m_cTimeFormats; dwIndex++)
  474. {
  475. if (guidTimeFormat == m_pguidTimeFormats[dwIndex])
  476. {
  477. m_guidCurrentTimeFormat = m_pguidTimeFormats[dwIndex];
  478. return S_OK;
  479. }
  480. }
  481. return E_INVALIDARG;
  482. }