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.

535 lines
18 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //==========================================================================;
  11. #include "Scaler.h"
  12. #include "capdebug.h"
  13. #include "capmain.h"
  14. #include "defaults.h"
  15. // video information for PAL
  16. VideoInfoStruct NTSCVideoInfo =
  17. {
  18. 730, // Clkx1_HACTIVE = 746
  19. 148, // Clkx1_HDELAY = 140
  20. 44, // Min_Pixels = 44
  21. 240, // Active_lines_per_field = 240
  22. 144, // Min_UncroppedPixels = Min_Pixels + 100
  23. 724, // Max_Pixels = ((Clkx1_HACTIVE < 774) ? Clkx1_HACTIVE - 6 : 768)
  24. 32, // Min_Lines = (Active_lines_per_field / 16 + 1) * 2
  25. 240, // Max_Lines = Active_lines_per_field
  26. 352, // Max_VFilter1_Pixels = ((Clkx1_HACTIVE > 796) ? 384 : (Clkx1_HACTIVE * 14 / 29))
  27. 176, // Max_VFilter2_Pixels = Clkx1_HACTIVE * 8 / 33
  28. 176, // Max_VFilter3_Pixels = Clkx1_HACTIVE * 8 / 33
  29. 240, // Max_VFilter1_Lines = Active_lines_per_field
  30. 120, // Max_VFilter2_Lines = Active_lines_per_field / 2
  31. 96, // Max_VFilter3_Lines = Active_lines_per_field * 2 / 5
  32. };
  33. // video information for PAL
  34. VideoInfoStruct PALVideoInfo =
  35. {
  36. 914, // Clkx1_HACTIVE = 914
  37. 190, // Clkx1_HDELAY = 190
  38. 48, // Min_Pixels = 48
  39. 284, // Active_lines_per_field = 284
  40. 148, // Min_UncroppedPixels = Min_Pixels + 100
  41. 768, // Max_Pixels = ((Clkx1_HACTIVE < 774) ? Clkx1_HACTIVE - 6 : 768)
  42. 36, // Min_Lines = (Active_lines_per_field / 16 + 1) * 2
  43. 284, // Max_Lines = Active_lines_per_field
  44. 384, // Max_VFilter1_Pixels = ((Clkx1_HACTIVE > 796) ? 384 : (Clkx1_HACTIVE * 14 / 29))
  45. 221, // Max_VFilter2_Pixels = Clkx1_HACTIVE * 8 / 33
  46. 221, // Max_VFilter3_Pixels = Clkx1_HACTIVE * 8 / 33
  47. 284, // Max_VFilter1_Lines = Active_lines_per_field
  48. 142, // Max_VFilter2_Lines = Active_lines_per_field / 2
  49. 113, // Max_VFilter3_Lines = Active_lines_per_field * 2 / 5
  50. };
  51. //===========================================================================
  52. // Bt848 Scaler Class Implementation
  53. //===========================================================================
  54. /////////////////////////////////////////////////////////////////////////////
  55. // Constructor
  56. /////////////////////////////////////////////////////////////////////////////
  57. #define REGALIGNMENT 1
  58. #define offset 0
  59. Scaler::Scaler(PDEVICE_PARMS pDeviceParms):
  60. regCROP ((0x03 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  61. fieldVACTIVE_MSB(regCROP, 4, 2, RW) ,
  62. fieldHDELAY_MSB(regCROP, 2, 2, RW) ,
  63. fieldHACTIVE_MSB(regCROP, 0, 2, RW) ,
  64. regVACTIVE_LO ((0x05 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  65. regHDELAY_LO ((0x06 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  66. regHACTIVE_LO ((0x07 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  67. regHSCALE_HI ((0x08 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  68. fieldHSCALE_MSB(regHSCALE_HI, 0, 8, RW) ,
  69. regHSCALE_LO ((0x09 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  70. regSCLOOP ((0x10 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  71. fieldHFILT(regSCLOOP, 3, 2, RW) ,
  72. regVSCALE_HI ((0x13 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  73. fieldVSCALE_MSB(regVSCALE_HI, 0, 5, RW) ,
  74. regVSCALE_LO ((0x14 * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  75. regVActive(regVACTIVE_LO, 8, fieldVACTIVE_MSB, RW),
  76. regVScale(regVSCALE_LO, 8, fieldVSCALE_MSB, RW),
  77. regHDelay(regHDELAY_LO, 8, fieldHDELAY_MSB, RW),
  78. regHActive(regHACTIVE_LO, 8, fieldHACTIVE_MSB, RW),
  79. regHScale(regHSCALE_LO, 8, fieldHSCALE_MSB, RW),
  80. regVTC ((0x1B * REGALIGNMENT) + (offset), RW, pDeviceParms) ,
  81. fieldVBIEN (regVTC, 4, 1, RW),
  82. fieldVBIFMT (regVTC, 3, 1, RW),
  83. fieldVFILT (regVTC, 0, 2, RW),
  84. regReverse_CROP (0x03, RW, pDeviceParms),
  85. fieldVDELAY_MSB(regReverse_CROP, 6, 2, RW),
  86. regVDELAY_LO (0x04, RW, pDeviceParms),
  87. regVDelay(regVDELAY_LO, 8, fieldVDELAY_MSB, RW),
  88. m_videoFormat(VFormat_NTSC), VFilterFlag_(On),
  89. DigitalWin_(0,0,NTSCMaxOutWidth,NTSCMaxOutHeight)
  90. {
  91. m_HActive = 0;
  92. m_pixels = 0;
  93. m_lines = 0;
  94. m_VFilter = 0;
  95. }
  96. /////////////////////////////////////////////////////////////////////////////
  97. // Destructor
  98. /////////////////////////////////////////////////////////////////////////////
  99. Scaler::~Scaler()
  100. {
  101. }
  102. /////////////////////////////////////////////////////////////////////////////
  103. // Method: void Scaler::VideoFormatChanged(VideoFormat format)
  104. // Purpose: Set which video format is using
  105. // Input: Video format -
  106. // Auto format: VFormat_AutoDetect
  107. // NTSC (M): VFormat_NTSC
  108. // PAL (B, D, G, H, I): VFormat_PAL_BDGHI
  109. // PAL (M): VFormat_PAL_M
  110. // PAL(N): VFormat_PAL_N
  111. // SECAM: VFormat_SECAM
  112. // Output: None
  113. // Return: None
  114. /////////////////////////////////////////////////////////////////////////////
  115. void Scaler::VideoFormatChanged(VideoFormat format)
  116. {
  117. m_videoFormat = format;
  118. Scale(DigitalWin_);
  119. }
  120. /////////////////////////////////////////////////////////////////////////////
  121. // Method: void Scaler::Scale(MRect & clientScr)
  122. // Purpose: Perform scaling
  123. // Input: MRect & clientScr - rectangle to scale to
  124. // Output: None
  125. // Return: None
  126. /////////////////////////////////////////////////////////////////////////////
  127. void Scaler::Scale(MRect & clientScr)
  128. {
  129. switch (m_videoFormat)
  130. {
  131. case VFormat_NTSC:
  132. case VFormat_NTSC_J:
  133. case VFormat_PAL_M:
  134. m_ptrVideoIn = &NTSCVideoInfo; // set scaling constants for NTSC
  135. break;
  136. case VFormat_PAL_BDGHI:
  137. case VFormat_PAL_N:
  138. case VFormat_SECAM:
  139. case VFormat_PAL_N_COMB:
  140. m_ptrVideoIn = &PALVideoInfo; // set scaling constants for PAL/SECAM
  141. if ( m_videoFormat == VFormat_PAL_N_COMB )
  142. {
  143. m_ptrVideoIn->Clkx1_HACTIVE = NTSCVideoInfo.Clkx1_HACTIVE; // p. 26 of BT guide
  144. m_ptrVideoIn->Clkx1_HDELAY = NTSCVideoInfo.Clkx1_HDELAY; // empirical
  145. }
  146. break;
  147. }
  148. // the order of functions calling here is important because some
  149. // calculations are based on previous results
  150. SetHActive(clientScr);
  151. SetVActive();
  152. SetVScale(clientScr);
  153. SetVFilter();
  154. SetVDelay();
  155. SetHDelay();
  156. SetHScale();
  157. SetHFilter();
  158. }
  159. /////////////////////////////////////////////////////////////////////////////
  160. // Method: void Scaler::SetHActive(MRect & clientScr)
  161. // Purpose: Set HActive register
  162. // Input: MRect & clientScr - rectangle to scale to
  163. // Output: None
  164. // Return: None
  165. /////////////////////////////////////////////////////////////////////////////
  166. void Scaler::SetHActive(MRect & clientScr)
  167. {
  168. m_HActive = min(m_ptrVideoIn->Max_Pixels,
  169. max((WORD)clientScr.Width(), m_ptrVideoIn->Min_Pixels));
  170. regHActive = m_HActive;
  171. }
  172. /////////////////////////////////////////////////////////////////////////////
  173. // Method: void Scaler::SetHDelay()
  174. // Purpose: Set HDelay register
  175. // Input: None
  176. // Output: None
  177. // Return: None
  178. /////////////////////////////////////////////////////////////////////////////
  179. void Scaler::SetHDelay()
  180. {
  181. // calculations here requires calculation of HActive first!
  182. m_pixels = m_HActive;
  183. if (m_pixels < m_ptrVideoIn->Min_UncroppedPixels)
  184. m_pixels += (WORD) ((m_ptrVideoIn->Min_UncroppedPixels - m_pixels + 9) / 10);
  185. LONG a = (LONG)m_pixels * (LONG)m_ptrVideoIn->Clkx1_HDELAY;
  186. LONG b = (LONG)m_ptrVideoIn->Clkx1_HACTIVE * 2L;
  187. WORD HDelay = (WORD) ((a + (LONG)m_ptrVideoIn->Clkx1_HACTIVE * 2 - 1) / b * 2L);
  188. // now add the cropping region into HDelay register; i.e. skip some pixels
  189. // before we start taking them as real image
  190. HDelay += (WORD)AnalogWin_.left;
  191. // HDelay must be even or else color would be wrong
  192. HDelay &= ~01;
  193. regHDelay = HDelay;
  194. // since we increase HDelay, we should decrease HActive by the same amount
  195. m_HActive -= (WORD)AnalogWin_.left;
  196. regHActive = m_HActive;
  197. }
  198. /////////////////////////////////////////////////////////////////////////////
  199. // Method: void Scaler::SetHScale()
  200. // Purpose: Set HScale register
  201. // Input: None
  202. // Output: None
  203. // Return: None
  204. /////////////////////////////////////////////////////////////////////////////
  205. void Scaler::SetHScale()
  206. {
  207. regHScale = (WORD) ((((LONG)m_ptrVideoIn->Clkx1_HACTIVE * 4096L) /
  208. (LONG)m_pixels) - 4096L);
  209. }
  210. /////////////////////////////////////////////////////////////////////////////
  211. // Method: void Scaler::SetHFilter()
  212. // Purpose: Set HFilt register field
  213. // Input: None
  214. // Output: None
  215. // Return: None
  216. /////////////////////////////////////////////////////////////////////////////
  217. void Scaler::SetHFilter()
  218. {
  219. if (m_videoFormat != VFormat_SECAM)
  220. fieldHFILT = HFilter_AutoFormat;
  221. else // SECAM
  222. if (m_pixels < m_ptrVideoIn->Clkx1_HACTIVE / 7)
  223. fieldHFILT = HFilter_ICON;
  224. else
  225. fieldHFILT = HFilter_QCIF;
  226. }
  227. /////////////////////////////////////////////////////////////////////////////
  228. // Method: void Scaler::SetVScale(MRect & clientScr)
  229. // Purpose: Set VScale register
  230. // Input: MRect & clientScr - rectangle to scale to
  231. // Output: None
  232. // Return: None
  233. /////////////////////////////////////////////////////////////////////////////
  234. void Scaler::SetVScale(MRect & clientScr)
  235. {
  236. m_lines = min(m_ptrVideoIn->Max_Lines,
  237. max((WORD)clientScr.Height(), m_ptrVideoIn->Min_Lines));
  238. WORD LPB_VScale_Factor = (WORD) (1 + (m_lines - 1) / m_ptrVideoIn->Active_lines_per_field);
  239. m_lines = (WORD) ((m_lines + LPB_VScale_Factor - 1) / LPB_VScale_Factor);
  240. LONG a = (LONG)m_ptrVideoIn->Active_lines_per_field * 512L / (LONG)m_lines;
  241. WORD VScale = (WORD) ((0x10000L - a + 512L) & 0x1FFFL);
  242. regVScale = VScale;
  243. }
  244. /////////////////////////////////////////////////////////////////////////////
  245. // Method: void Scaler::SetVDelay()
  246. // Purpose: Set VDelay register
  247. // Input: None
  248. // Output: None
  249. // Return: None
  250. /////////////////////////////////////////////////////////////////////////////
  251. void Scaler::SetVDelay()
  252. {
  253. WORD VDelay, moreDelay;
  254. // increase VDelay will eliminate garbage lines at top of image
  255. switch (m_VFilter)
  256. {
  257. case 3:
  258. moreDelay = 4;
  259. break;
  260. case 2:
  261. moreDelay = 2;
  262. break;
  263. case 1:
  264. case 0:
  265. default:
  266. moreDelay = 0;
  267. break;
  268. }
  269. if ( ( m_videoFormat == VFormat_NTSC ) ||
  270. ( m_videoFormat == VFormat_NTSC_J ) ||
  271. ( m_videoFormat == VFormat_PAL_M ) ||
  272. ( m_videoFormat == VFormat_PAL_N_COMB ) ) // the reason that PAL_N_COMB is here is purely empirical
  273. VDelay = 0x001A + moreDelay; // NTSC
  274. else
  275. VDelay = 0x0026 + moreDelay; // PAL/SECAM
  276. // now add the cropping region into VDelay register; i.e. skip some pixels
  277. // before we start taking them as real image
  278. VDelay += (WORD)(((LONG)m_ptrVideoIn->Max_Lines * (LONG)AnalogWin_.top + m_lines - 1) / (LONG)m_lines * 2);
  279. regVDelay = VDelay;
  280. }
  281. /////////////////////////////////////////////////////////////////////////////
  282. // Method: void Scaler::SetVActive()
  283. // Purpose: Set VActive register
  284. // Input: None
  285. // Output: None
  286. // Return: None
  287. /////////////////////////////////////////////////////////////////////////////
  288. void Scaler::SetVActive()
  289. {
  290. // No calculation needed for VActive register since it based on the UNSCALED image
  291. if ( ( m_videoFormat == VFormat_NTSC ) ||
  292. ( m_videoFormat == VFormat_NTSC_J ) ||
  293. ( m_videoFormat == VFormat_PAL_M ) )
  294. regVActive = 0x1F4;
  295. else
  296. regVActive = 0x238;
  297. }
  298. /////////////////////////////////////////////////////////////////////////////
  299. // Method: void Scaler::SetVBIEN(BOOL)
  300. // Purpose: Set VBIEN register field
  301. // Input: None
  302. // Output: None
  303. // Return: None
  304. /////////////////////////////////////////////////////////////////////////////
  305. void Scaler::SetVBIEN(BOOL enable)
  306. {
  307. if (enable)
  308. {
  309. fieldVBIEN = 1;
  310. }
  311. else
  312. {
  313. fieldVBIEN = 0;
  314. }
  315. }
  316. /////////////////////////////////////////////////////////////////////////////
  317. // Method: BOOL void Scaler::IsVBIEN()
  318. // Purpose: Set VBIEN register field
  319. // Input: None
  320. // Output: None
  321. // Return: None
  322. /////////////////////////////////////////////////////////////////////////////
  323. BOOL Scaler::IsVBIEN()
  324. {
  325. if (fieldVBIEN)
  326. return TRUE;
  327. else
  328. return FALSE;
  329. }
  330. /////////////////////////////////////////////////////////////////////////////
  331. // Method: void Scaler::SetVBIFMT(BOOL)
  332. // Purpose: Set VBIFMT register field
  333. // Input: None
  334. // Output: None
  335. // Return: None
  336. /////////////////////////////////////////////////////////////////////////////
  337. void Scaler::SetVBIFMT(BOOL enable)
  338. {
  339. if (enable)
  340. {
  341. fieldVBIFMT = 1;
  342. }
  343. else
  344. {
  345. fieldVBIFMT = 0;
  346. }
  347. }
  348. /////////////////////////////////////////////////////////////////////////////
  349. // Method: BOOL void Scaler::IsVBIFMT()
  350. // Purpose: Set VBIFMT register field
  351. // Input: None
  352. // Output: None
  353. // Return: None
  354. /////////////////////////////////////////////////////////////////////////////
  355. BOOL Scaler::IsVBIFMT()
  356. {
  357. if (fieldVBIFMT)
  358. return TRUE;
  359. else
  360. return FALSE;
  361. }
  362. /////////////////////////////////////////////////////////////////////////////
  363. // Method: void Scaler::SetVFilter()
  364. // Purpose: Set VFilt register field
  365. // Input: None
  366. // Output: None
  367. // Return: None
  368. /////////////////////////////////////////////////////////////////////////////
  369. void Scaler::SetVFilter()
  370. {
  371. // this is to remove junk lines at the top of video. flag set to off
  372. // when image hight is above CIF
  373. if (VFilterFlag_ == Off) {
  374. fieldVFILT = 0;
  375. m_VFilter = 0;
  376. return;
  377. }
  378. if ((m_HActive <= m_ptrVideoIn->Max_VFilter3_Pixels) &&
  379. (m_lines <= m_ptrVideoIn->Max_VFilter3_Lines))
  380. m_VFilter = 3;
  381. else if ((m_HActive <= m_ptrVideoIn->Max_VFilter2_Pixels) &&
  382. (m_lines <= m_ptrVideoIn->Max_VFilter2_Lines))
  383. m_VFilter = 2;
  384. else if ((m_HActive <= m_ptrVideoIn->Max_VFilter1_Pixels) &&
  385. (m_lines <= m_ptrVideoIn->Max_VFilter1_Lines))
  386. m_VFilter = 1;
  387. else
  388. m_VFilter = 0;
  389. fieldVFILT = m_VFilter;
  390. }
  391. /////////////////////////////////////////////////////////////////////////////
  392. // Method: void Scaler::GetDigitalWin(MRect &DigWin) const
  393. // Purpose: Retreives the size of digital window
  394. // Input: None
  395. // Output: MRect &DigWin - retrieved value
  396. // Return: None
  397. /////////////////////////////////////////////////////////////////////////////
  398. void Scaler::GetDigitalWin(MRect &DigWin) const
  399. {
  400. DigWin = DigitalWin_;
  401. }
  402. /////////////////////////////////////////////////////////////////////////////
  403. // Method: ErrorCode Scaler::SetDigitalWin(const MRect &DigWin)
  404. // Purpose: Sets the size and location of the digital window
  405. // Input: const MRect &DigWin - window size to set to
  406. // Output: None
  407. // Return: Success or Fail if passed rect is bigger then analog window
  408. // Note: This function can affect the scaling, so Scale() is called
  409. /////////////////////////////////////////////////////////////////////////////
  410. ErrorCode Scaler::SetDigitalWin(const MRect &DigWin)
  411. {
  412. // we can not scale up
  413. if ((DigWin.Height() > AnalogWin_.Height()) ||
  414. (DigWin.Width() > AnalogWin_.Width()))
  415. return Fail;
  416. DigitalWin_ = DigWin;
  417. // every invocation of SetDigitalWin potentially changes the scaling
  418. Scale(DigitalWin_);
  419. return Success;
  420. }
  421. /////////////////////////////////////////////////////////////////////////////
  422. // Method: void Scaler::GetAnalogWin(MRect &AWin) const
  423. // Purpose: Retreives the size of analog window
  424. // Input: None
  425. // Output: MRect &DigWin - retrieved value
  426. // Return: None
  427. /////////////////////////////////////////////////////////////////////////////
  428. void Scaler::GetAnalogWin(MRect &AWin) const
  429. {
  430. AWin = AnalogWin_;
  431. }
  432. /////////////////////////////////////////////////////////////////////////////
  433. // Method: ErrorCode Scaler::SetAnalogWin(const MRect &AWin)
  434. // Purpose: Sets the size and location of the analog window
  435. // Input: const MRect &AWin - window size to set to
  436. // Output: None
  437. // Return: Success or Fail if passed rect is bigger then analog window
  438. /////////////////////////////////////////////////////////////////////////////
  439. ErrorCode Scaler::SetAnalogWin(const MRect &AWin)
  440. {
  441. AnalogWin_ = AWin;
  442. return Success;
  443. }
  444. void Scaler::DumpSomeState()
  445. {
  446. UINT vDelay = regVDelay;
  447. UINT vActive = regVActive;
  448. UINT vScale = regVScale;
  449. UINT hDelay = regHDelay;
  450. UINT hActive = regHActive;
  451. UINT hScale = regHScale;
  452. MRect rect;
  453. GetDigitalWin(rect);
  454. DBGINFO(("vDelay = 0x%x\n", vDelay));
  455. DBGINFO(("vActive = 0x%x\n", vActive));
  456. DBGINFO(("vScale = 0x%x\n", vScale));
  457. DBGINFO(("hDelay = 0x%x\n", hDelay));
  458. DBGINFO(("hActive = 0x%x\n", hActive));
  459. DBGINFO(("hScale = 0x%x\n", hScale));
  460. DBGINFO(("top = 0x%x\n", rect.top));
  461. DBGINFO(("left = 0x%x\n", rect.left));
  462. DBGINFO(("right = 0x%x\n", rect.right));
  463. DBGINFO(("bottom = 0x%x\n", rect.bottom));
  464. }