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.

383 lines
13 KiB

  1. // $Header: G:/SwDev/WDM/Video/bt848/rcs/Scaler.cpp 1.3 1998/04/29 22:43:40 tomz Exp $
  2. #include "Scaler.h"
  3. #include "S_constr.h"
  4. // video information for PAL
  5. VideoInfoStruct NTSCVideoInfo =
  6. {
  7. 730, // Clkx1_HACTIVE = 746
  8. 148, // Clkx1_HDELAY = 140
  9. 44, // Min_Pixels = 44
  10. 240, // Active_lines_per_field = 240
  11. 144, // Min_UncroppedPixels = Min_Pixels + 100
  12. 724, // Max_Pixels = ((Clkx1_HACTIVE < 774) ? Clkx1_HACTIVE - 6 : 768)
  13. 32, // Min_Lines = (Active_lines_per_field / 16 + 1) * 2
  14. 240, // Max_Lines = Active_lines_per_field
  15. 352, // Max_VFilter1_Pixels = ((Clkx1_HACTIVE > 796) ? 384 : (Clkx1_HACTIVE * 14 / 29))
  16. 176, // Max_VFilter2_Pixels = Clkx1_HACTIVE * 8 / 33
  17. 176, // Max_VFilter3_Pixels = Clkx1_HACTIVE * 8 / 33
  18. 240, // Max_VFilter1_Lines = Active_lines_per_field
  19. 120, // Max_VFilter2_Lines = Active_lines_per_field / 2
  20. 96, // Max_VFilter3_Lines = Active_lines_per_field * 2 / 5
  21. };
  22. // video information for PAL
  23. VideoInfoStruct PALVideoInfo =
  24. {
  25. 914, // Clkx1_HACTIVE = 914
  26. 190, // Clkx1_HDELAY = 190
  27. 48, // Min_Pixels = 48
  28. 284, // Active_lines_per_field = 284
  29. 148, // Min_UncroppedPixels = Min_Pixels + 100
  30. 768, // Max_Pixels = ((Clkx1_HACTIVE < 774) ? Clkx1_HACTIVE - 6 : 768)
  31. 36, // Min_Lines = (Active_lines_per_field / 16 + 1) * 2
  32. 284, // Max_Lines = Active_lines_per_field
  33. 384, // Max_VFilter1_Pixels = ((Clkx1_HACTIVE > 796) ? 384 : (Clkx1_HACTIVE * 14 / 29))
  34. 221, // Max_VFilter2_Pixels = Clkx1_HACTIVE * 8 / 33
  35. 221, // Max_VFilter3_Pixels = Clkx1_HACTIVE * 8 / 33
  36. 284, // Max_VFilter1_Lines = Active_lines_per_field
  37. 142, // Max_VFilter2_Lines = Active_lines_per_field / 2
  38. 113, // Max_VFilter3_Lines = Active_lines_per_field * 2 / 5
  39. };
  40. //===========================================================================
  41. // Bt848 Scaler Class Implementation
  42. //===========================================================================
  43. /////////////////////////////////////////////////////////////////////////////
  44. // Constructor
  45. /////////////////////////////////////////////////////////////////////////////
  46. Scaler::Scaler( VidField field ):
  47. CONSTRUCT_SCALER_REGISTERS( ( ( field == VF_Even ) ? 0 : 0x80 ) ),
  48. // Since VDelay in hardware is reversed; i.e. odd reg is really even field
  49. // and vice versa, construct the opposite here
  50. regReverse_CROP ( (0x03 * 4) + ( ( field == VF_Even ) ? 0x80 : 0 ), RW ),
  51. fieldVDELAY_MSB( regReverse_CROP, 6, 2, RW),
  52. regVDELAY_LO ( (0x04 * 4) + ( ( field == VF_Even ) ? 0x80 : 0 ), RW ),
  53. regVDelay( regVDELAY_LO, 8, fieldVDELAY_MSB, RW ),
  54. m_videoFormat( VFormat_NTSC ), VFilterFlag_( On ),
  55. m_ptrVideoIn( &NTSCVideoInfo )
  56. {
  57. m_HActive = 0;
  58. m_pixels = 0;
  59. m_lines = 0;
  60. m_VFilter = 0;
  61. // this seems to be the minimum needed for reliable CC capture
  62. regVDelay = 0x1A;
  63. }
  64. /////////////////////////////////////////////////////////////////////////////
  65. // Destructor
  66. /////////////////////////////////////////////////////////////////////////////
  67. Scaler::~Scaler()
  68. {
  69. }
  70. /////////////////////////////////////////////////////////////////////////////
  71. // Method: void Scaler::VideoFormatChanged( VideoFormat format )
  72. // Purpose: Set which video format is using
  73. // Input: Video format -
  74. // Auto format: VFormat_AutoDetect
  75. // NTSC (M): VFormat_NTSC
  76. // PAL (B, D, G, H, I): VFormat_PAL_BDGHI
  77. // PAL (M): VFormat_PAL_M
  78. // PAL(N): VFormat_PAL_N
  79. // SECAM: VFormat_SECAM
  80. // Output: None
  81. // Return: None
  82. /////////////////////////////////////////////////////////////////////////////
  83. void Scaler::VideoFormatChanged( VideoFormat format )
  84. {
  85. m_videoFormat = format;
  86. }
  87. /////////////////////////////////////////////////////////////////////////////
  88. // Method: void Scaler::Scale( MRect & clientScr )
  89. // Purpose: Perform scaling
  90. // Input: MRect & clientScr - rectangle to scale to
  91. // Output: None
  92. // Return: None
  93. /////////////////////////////////////////////////////////////////////////////
  94. void Scaler::Scale( MRect & clientScr )
  95. {
  96. if ( m_videoFormat == VFormat_NTSC )
  97. m_ptrVideoIn = &NTSCVideoInfo; // set scaling constants for NTSC
  98. else
  99. m_ptrVideoIn = &PALVideoInfo; // set scaling constants for PAL/SECAM
  100. // the order of functions calling here is important because some
  101. // calculations are based on previous results
  102. SetHActive( clientScr );
  103. SetVActive();
  104. SetVScale( clientScr );
  105. SetVFilter();
  106. SetVDelay();
  107. SetHDelay();
  108. SetHScale();
  109. SetHFilter();
  110. }
  111. /////////////////////////////////////////////////////////////////////////////
  112. // Method: void Scaler::SetHActive( MRect & clientScr )
  113. // Purpose: Set HActive register
  114. // Input: MRect & clientScr - rectangle to scale to
  115. // Output: None
  116. // Return: None
  117. /////////////////////////////////////////////////////////////////////////////
  118. void Scaler::SetHActive( MRect & clientScr )
  119. {
  120. m_HActive = min( m_ptrVideoIn->Max_Pixels,
  121. max( (WORD)clientScr.Width(), m_ptrVideoIn->Min_Pixels ) );
  122. regHActive = m_HActive;
  123. }
  124. /////////////////////////////////////////////////////////////////////////////
  125. // Method: void Scaler::SetHDelay( void )
  126. // Purpose: Set HDelay register
  127. // Input: None
  128. // Output: None
  129. // Return: None
  130. /////////////////////////////////////////////////////////////////////////////
  131. void Scaler::SetHDelay( void )
  132. {
  133. // calculations here requires calculation of HActive first!
  134. m_pixels = m_HActive;
  135. if ( m_pixels < m_ptrVideoIn->Min_UncroppedPixels )
  136. m_pixels += (WORD) ( ( m_ptrVideoIn->Min_UncroppedPixels - m_pixels + 9 ) / 10 );
  137. LONG a = (LONG)m_pixels * (LONG)m_ptrVideoIn->Clkx1_HDELAY;
  138. LONG b = (LONG)m_ptrVideoIn->Clkx1_HACTIVE * 2L;
  139. WORD HDelay = (WORD) ( ( a + (LONG)m_ptrVideoIn->Clkx1_HACTIVE * 2 - 1) / b * 2L );
  140. // now add the cropping region into HDelay register; i.e. skip some pixels
  141. // before we start taking them as real image
  142. HDelay += (WORD)AnalogWin_.left;
  143. // HDelay must be even or else color would be wrong
  144. HDelay &= ~01;
  145. regHDelay = HDelay;
  146. // since we increase HDelay, we should decrease HActive by the same amount
  147. m_HActive -= (WORD)AnalogWin_.left;
  148. regHActive = m_HActive;
  149. }
  150. /////////////////////////////////////////////////////////////////////////////
  151. // Method: void Scaler::SetHScale( void )
  152. // Purpose: Set HScale register
  153. // Input: None
  154. // Output: None
  155. // Return: None
  156. /////////////////////////////////////////////////////////////////////////////
  157. void Scaler::SetHScale( void )
  158. {
  159. regHScale = (WORD) ( ( ( (LONG)m_ptrVideoIn->Clkx1_HACTIVE * 4096L ) /
  160. (LONG)m_pixels ) - 4096L );
  161. }
  162. /////////////////////////////////////////////////////////////////////////////
  163. // Method: void Scaler::SetHFilter( void )
  164. // Purpose: Set HFilt register field
  165. // Input: None
  166. // Output: None
  167. // Return: None
  168. /////////////////////////////////////////////////////////////////////////////
  169. void Scaler::SetHFilter( void )
  170. {
  171. if ( m_videoFormat != VFormat_SECAM )
  172. fieldHFILT = HFilter_AutoFormat;
  173. else // SECAM
  174. if ( m_pixels < m_ptrVideoIn->Clkx1_HACTIVE / 7 )
  175. fieldHFILT = HFilter_ICON;
  176. else
  177. fieldHFILT = HFilter_QCIF;
  178. }
  179. /////////////////////////////////////////////////////////////////////////////
  180. // Method: void Scaler::SetVScale( MRect & clientScr )
  181. // Purpose: Set VScale register
  182. // Input: MRect & clientScr - rectangle to scale to
  183. // Output: None
  184. // Return: None
  185. /////////////////////////////////////////////////////////////////////////////
  186. void Scaler::SetVScale( MRect & clientScr )
  187. {
  188. m_lines = min( m_ptrVideoIn->Max_Lines,
  189. max( (WORD)clientScr.Height(), m_ptrVideoIn->Min_Lines ) );
  190. WORD LPB_VScale_Factor = (WORD) ( 1 + ( m_lines - 1 ) / m_ptrVideoIn->Active_lines_per_field );
  191. m_lines = (WORD) ( ( m_lines + LPB_VScale_Factor - 1 ) / LPB_VScale_Factor );
  192. LONG a = (LONG)m_ptrVideoIn->Active_lines_per_field * 512L / (LONG)m_lines;
  193. WORD VScale = (WORD) ( ( 0x10000L - a + 512L ) & 0x1FFFL );
  194. regVScale = VScale;
  195. }
  196. /////////////////////////////////////////////////////////////////////////////
  197. // Method: void Scaler::SetVDelay( void )
  198. // Purpose: Set VDelay register
  199. // Input: None
  200. // Output: None
  201. // Return: None
  202. /////////////////////////////////////////////////////////////////////////////
  203. void Scaler::SetVDelay( void )
  204. {
  205. WORD VDelay, moreDelay;
  206. // increase VDelay will eliminate garbage lines at top of image
  207. switch ( m_VFilter )
  208. {
  209. case 3:
  210. moreDelay = 4;
  211. break;
  212. case 2:
  213. moreDelay = 2;
  214. break;
  215. case 1:
  216. case 0:
  217. default:
  218. moreDelay = 0;
  219. break;
  220. }
  221. if ( m_videoFormat == VFormat_NTSC )
  222. VDelay = 0x001A + moreDelay; // NTSC
  223. else
  224. VDelay = 0x0026 + moreDelay; // PAL/SECAM
  225. // now add the cropping region into VDelay register; i.e. skip some pixels
  226. // before we start taking them as real image
  227. VDelay += (WORD)( ( (LONG)m_ptrVideoIn->Max_Lines * (LONG)AnalogWin_.top + m_lines - 1 ) / (LONG)m_lines * 2 );
  228. regVDelay = VDelay;
  229. }
  230. /////////////////////////////////////////////////////////////////////////////
  231. // Method: void Scaler::SetVActive( void )
  232. // Purpose: Set VActive register
  233. // Input: None
  234. // Output: None
  235. // Return: None
  236. /////////////////////////////////////////////////////////////////////////////
  237. void Scaler::SetVActive( void )
  238. {
  239. // No calculation needed for VActive register since it based on the UNSCALED image
  240. if ( m_videoFormat == VFormat_NTSC )
  241. regVActive = 0x1F4;
  242. else
  243. regVActive = 0x238;
  244. }
  245. /////////////////////////////////////////////////////////////////////////////
  246. // Method: void Scaler::SetVFilter( void )
  247. // Purpose: Set VFilt register field
  248. // Input: None
  249. // Output: None
  250. // Return: None
  251. /////////////////////////////////////////////////////////////////////////////
  252. void Scaler::SetVFilter( void )
  253. {
  254. // this is to remove junk lines at the top of video. flag set to off
  255. // when image hight is above CIF
  256. if ( VFilterFlag_ == Off ) {
  257. fieldVFILT = 0;
  258. m_VFilter = 0;
  259. return;
  260. }
  261. if ( ( m_HActive <= m_ptrVideoIn->Max_VFilter3_Pixels ) &&
  262. ( m_lines <= m_ptrVideoIn->Max_VFilter3_Lines ) )
  263. m_VFilter = 3;
  264. else if ( ( m_HActive <= m_ptrVideoIn->Max_VFilter2_Pixels ) &&
  265. ( m_lines <= m_ptrVideoIn->Max_VFilter2_Lines ) )
  266. m_VFilter = 2;
  267. else if ( ( m_HActive <= m_ptrVideoIn->Max_VFilter1_Pixels ) &&
  268. ( m_lines <= m_ptrVideoIn->Max_VFilter1_Lines ) )
  269. m_VFilter = 1;
  270. else
  271. m_VFilter = 0;
  272. fieldVFILT = m_VFilter;
  273. }
  274. /////////////////////////////////////////////////////////////////////////////
  275. // Method: void Scaler::GetDigitalWin( MRect &DigWin ) const
  276. // Purpose: Retreives the size of digital window
  277. // Input: None
  278. // Output: MRect &DigWin - retrieved value
  279. // Return: None
  280. /////////////////////////////////////////////////////////////////////////////
  281. void Scaler::GetDigitalWin( MRect &DigWin ) const
  282. {
  283. DigWin = DigitalWin_;
  284. }
  285. /////////////////////////////////////////////////////////////////////////////
  286. // Method: ErrorCode Scaler::SetDigitalWin( const MRect &DigWin )
  287. // Purpose: Sets the size and location of the digital window
  288. // Input: const MRect &DigWin - window size to set to
  289. // Output: None
  290. // Return: Success or Fail if passed rect is bigger then analog window
  291. // Note: This function can affect the scaling, so Scale() is called
  292. /////////////////////////////////////////////////////////////////////////////
  293. ErrorCode Scaler::SetDigitalWin( const MRect &DigWin )
  294. {
  295. // we can not scale up
  296. if ( ( DigWin.Height() > AnalogWin_.Height() ) ||
  297. ( DigWin.Width() > AnalogWin_.Width() ) )
  298. return Fail;
  299. DigitalWin_ = DigWin;
  300. // every invocation of SetDigitalWin potentially changes the scaling
  301. Scale( DigitalWin_ );
  302. return Success;
  303. }
  304. /////////////////////////////////////////////////////////////////////////////
  305. // Method: void Scaler::GetAnalogWin( MRect &AWin ) const
  306. // Purpose: Retreives the size of analog window
  307. // Input: None
  308. // Output: MRect &DigWin - retrieved value
  309. // Return: None
  310. /////////////////////////////////////////////////////////////////////////////
  311. void Scaler::GetAnalogWin( MRect &AWin ) const
  312. {
  313. AWin = AnalogWin_;
  314. }
  315. /////////////////////////////////////////////////////////////////////////////
  316. // Method: ErrorCode Scaler::SetAnalogWin( const MRect &AWin )
  317. // Purpose: Sets the size and location of the analog window
  318. // Input: const MRect &AWin - window size to set to
  319. // Output: None
  320. // Return: Success or Fail if passed rect is bigger then analog window
  321. /////////////////////////////////////////////////////////////////////////////
  322. ErrorCode Scaler::SetAnalogWin( const MRect &AWin )
  323. {
  324. AnalogWin_ = AWin;
  325. return Success;
  326. }