COverlayController.cpp
上传用户:hhs829
上传日期:2022-06-17
资源大小:586k
文件大小:12k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. //
  2. // COverlayController.cpp
  3. //
  4. #include <streams.h>
  5. #include "COverlayController.h"
  6. #include "CPixelRGB32.h"
  7. #include "CPixelRGB24.h"
  8. #include "CPixelRGB565.h"
  9. #include "CPixelRGB555.h"
  10. #include "CPixelRGB8.h"
  11. #include "CAutoFont.h"
  12. //////////////////////////////////////////////////////////////////////////////
  13. COverlayController::COverlayController()
  14. {
  15. mPixelConverter   = 0;
  16. mCanDoOverlay     = FALSE;
  17. mIsOverlayByCover = TRUE;
  18. mOverlayCounter   = 0;
  19. mDoubleStartTime  = 0;
  20. mDoubleEndTime    = -1;
  21. mOverlayStartTime = 0;
  22. mOverlayEndTime   = -1; // Means to the end
  23. mTitle            = new char[1];
  24. *mTitle           = '';
  25. mTitleDIBBits     = 0;
  26. mColorRed         = 0;
  27. mColorGreen       = 128;
  28. mColorBlue        = 0;
  29. memset(&mTitleSize, 0, sizeof(SIZE));
  30. memset(&mStartPos, 0, sizeof(POINT));
  31. memset(&mTitleFont, 0, sizeof(LOGFONT));
  32. mIsFontChanged   = FALSE;
  33. mInputColorSpace = FT_NONE;
  34. mImageWidth      = 0;
  35. mImageHeight     = 0;
  36. mImageWidthInBytes = 0;
  37. mImageBitCount     = 0;
  38. mIsBottomUpImage   = TRUE;
  39. mDIBWidthInBytes   = 0;
  40. mInputFrameRate    = 25;
  41. }
  42. COverlayController::~COverlayController()
  43. {
  44. ReleasePixelConverter();
  45. ReleaseTitleBuffer();
  46. ReleaseTitleDIB();
  47. }
  48. void COverlayController::ReleasePixelConverter(void)
  49. {
  50. if (mPixelConverter)
  51. {
  52. delete mPixelConverter;
  53. mPixelConverter = 0;
  54. }
  55. }
  56. void COverlayController::ReleaseTitleBuffer(void)
  57. {
  58. if (mTitle)
  59. {
  60. delete[] mTitle;
  61. mTitle = 0;
  62. }
  63. }
  64. void COverlayController::ReleaseTitleDIB(void)
  65. {
  66. if (mTitleDIBBits)
  67. {
  68. delete[] mTitleDIBBits;
  69. mTitleDIBBits = 0;
  70. }
  71. }
  72. // In order to create the pixel convertor used by overlay working properly,
  73. // this method must be invoke
  74. void COverlayController::SetInputColorSpace(RGB_FORMAT inColorSpace)
  75. {
  76. if (mInputColorSpace != inColorSpace)
  77. {
  78. ReleasePixelConverter();
  79. mInputColorSpace = inColorSpace;
  80. SideEffectColorSpaceChanged();
  81. }
  82. }
  83. BOOL COverlayController::CreateTitleDIBBits(void)
  84. {
  85. HDC hdc = CreateCompatibleDC(NULL);
  86. if (hdc)
  87. {
  88. HBITMAP hbm = ActualCreateTitleDIB(hdc);
  89. DeleteDC(hdc);
  90. if (hbm)
  91. {
  92. DeleteObject(hbm);
  93. return TRUE;
  94. }
  95. }
  96. return FALSE;
  97. }
  98. HBITMAP COverlayController::ActualCreateTitleDIB(HDC inDC)
  99. {
  100. // DIB info we used to create title pixel-mapping.
  101. // The system default color policy is: 
  102. // Initial Whole Black, while output area White-background and Black-text.
  103. struct {
  104. BITMAPINFOHEADER bmiHeader;
  105. DWORD rgbEntries[2];
  106. } bmi =
  107. {
  108. {
  109. sizeof(BITMAPINFOHEADER),
  110. 0,
  111. 0,
  112. 1,
  113. 1,
  114. BI_RGB,
  115. 0,
  116. 0,
  117. 0
  118. },
  119. {
  120. 0x00000000,
  121. 0xFFFFFFFF
  122. }
  123. };
  124. // We change the system default color policy.
  125. // That is, we use Black-background and White-text.
  126. // We do so especially for rotation font using.
  127. // SetBkColor(hdc, RGB(0, 0, 0));
  128. // SetTextColor(hdc, RGB(255, 255, 255));
  129. // Set tile font here, so we can get the exact size of the title
  130. CAutoFont  autoFont;
  131. if (mIsFontChanged)
  132. {
  133. // autoFont.CreateFont("Arial");  // Testing
  134. autoFont.CreateFont(mTitleFont);
  135. autoFont.SelectToDC(inDC);
  136. }
  137. GetTextExtentPoint32(inDC, mTitle, lstrlen(mTitle), &mTitleSize);
  138. // Overridable to change title DIB size
  139. if (!ValidateTitleDIBSize())
  140. {
  141. return NULL;
  142. }
  143. // Set proper DIB size here! Important!
  144. bmi.bmiHeader.biHeight = mTitleSize.cy;
  145. bmi.bmiHeader.biWidth  = mTitleSize.cx;
  146. HBITMAP hbm = CreateDIBitmap(inDC, &bmi.bmiHeader, 0, NULL, NULL, 0);
  147. BOOL   pass = (hbm != NULL);
  148. // Draw title after selecting DIB into the DC
  149. if (pass)
  150. {
  151. HGDIOBJ hobj = SelectObject(inDC, hbm);
  152. pass = ExtTextOut(inDC, 0, 0, ETO_OPAQUE | ETO_CLIPPED, NULL, 
  153. mTitle, lstrlen(mTitle), NULL);
  154. SelectObject(inDC, hobj);
  155. }
  156. // Get the title-drew DIB bits
  157. if (pass)
  158. {
  159. ReleaseTitleDIB();
  160. // Attention: To get bitmap data from the DIB object,
  161. // the scan line must be a multiple of 4 (DWORD)!
  162. // If the actual bitmap data is not exactly fit for DWORD,
  163. // The rest of DWORD bits will be filled automatically.
  164. // So we should expand to bytes and round up to a multiple of 4.
  165. mDIBWidthInBytes = ((mTitleSize.cx + 31) >> 3) & ~3;
  166. mTitleDIBBits    = new BYTE[mDIBWidthInBytes * mTitleSize.cy];
  167. memset(mTitleDIBBits, 0, mDIBWidthInBytes * mTitleSize.cy);
  168. LONG lLines = GetDIBits(inDC, hbm, 0, mTitleSize.cy, (PVOID)mTitleDIBBits, 
  169. (BITMAPINFO *)&bmi, DIB_RGB_COLORS);
  170. pass = (lLines != 0);
  171. }
  172. if (!pass && hbm)
  173. {
  174. DeleteObject(hbm);
  175. hbm = NULL;
  176. }
  177. return hbm;
  178. }
  179. BOOL COverlayController::ValidateTitleDIBSize(void)
  180. {
  181. return TRUE;
  182. }
  183. void COverlayController::SideEffectColorSpaceChanged(void)
  184. {
  185. switch (mInputColorSpace)
  186. {
  187. case FT_RGB8:
  188. mPixelConverter = new CPixelRGB8();
  189. mPixelConverter->SetPixelSize(1);
  190. break;
  191. case FT_RGB555:
  192. mPixelConverter = new CPixelRGB555();
  193. mPixelConverter->SetPixelSize(2);
  194. break;
  195. case FT_RGB565:
  196. mPixelConverter = new CPixelRGB565();
  197. mPixelConverter->SetPixelSize(2);
  198. break;
  199. case FT_RGB24:
  200. mPixelConverter = new CPixelRGB24();
  201. mPixelConverter->SetPixelSize(3);
  202. break;
  203. case FT_RGB32:
  204. mPixelConverter = new CPixelRGB32();
  205. mPixelConverter->SetPixelSize(4);
  206. break;
  207. }
  208. // Set the title color to the pixel converter
  209. if (mPixelConverter)
  210. {
  211. mPixelConverter->SetTargetColor(mColorRed, mColorGreen, mColorBlue);
  212. }
  213. }
  214. // Commonly we don't support rotation font
  215. // Subclass can override this to support it
  216. void COverlayController::SideEffectFontChanged(void)
  217. {
  218. mTitleFont.lfEscapement  = 0;
  219. mTitleFont.lfOrientation = 0;
  220. }
  221. void COverlayController::SetInputVideoInfo(const VIDEOINFOHEADER * inInfoHeader)
  222. {
  223. ASSERT(inInfoHeader);
  224. mImageWidth    = inInfoHeader->bmiHeader.biWidth;
  225. mImageHeight   = (DWORD)(abs(inInfoHeader->bmiHeader.biHeight));
  226. mImageBitCount = inInfoHeader->bmiHeader.biBitCount;
  227. if (inInfoHeader->AvgTimePerFrame > 0)
  228. {
  229. mInputFrameRate = 1.0 * UNITS / inInfoHeader->AvgTimePerFrame;
  230. SideEffectProgressChanged();
  231. }
  232. // biWidth is the stride in pixels for 'normal formats'
  233. // Expand to bytes and round up to a multiple of 4
  234. if (mImageBitCount != 0 && 0 == (7 & mImageBitCount)) 
  235. {
  236. mImageWidthInBytes = (mImageWidth * (mImageBitCount / 8) + 3) & ~3;
  237. }
  238. else 
  239. {
  240. mImageWidthInBytes = mImageWidth;
  241. }
  242. mIsBottomUpImage = mImageHeight > 0 ? TRUE : FALSE;
  243. }
  244. void COverlayController::SetEstimatedFrameRate(double inFrameRate)
  245. {
  246. mInputFrameRate = inFrameRate;
  247. SideEffectProgressChanged();
  248. }
  249. void COverlayController::SetOverlayStyle(BOOL inUsingCover)
  250. {
  251. mIsOverlayByCover = inUsingCover;
  252. }
  253. void COverlayController::GetOverlayStyle(BOOL * outUsingCover)
  254. {
  255. *outUsingCover = mIsOverlayByCover;
  256. }
  257. void COverlayController::SetTitle(const char * inTitle, int inLength)
  258. {
  259. ReleaseTitleBuffer();
  260. mTitle = new char[inLength + 1];
  261. if (inTitle && mTitle)
  262. {
  263. strcpy(mTitle, inTitle);
  264. }
  265. }
  266. void COverlayController::SetTitleColor(BYTE inR, BYTE inG, BYTE inB)
  267. {
  268. mColorRed   = inR;
  269. mColorGreen = inG;
  270. mColorBlue  = inB;
  271. // Set the title color to the pixel converter
  272. if (mPixelConverter)
  273. {
  274. mPixelConverter->SetTargetColor(mColorRed, mColorGreen, mColorBlue);
  275. }
  276. }
  277. void COverlayController::SetTitleStartPosition(POINT inStartPos)
  278. {
  279. mStartPos.x = inStartPos.x;
  280. mStartPos.y = inStartPos.y;
  281. }
  282. void COverlayController::SetTitleFont(LOGFONT inFont)
  283. {
  284. mTitleFont     = inFont;
  285. mIsFontChanged = TRUE;
  286. // Do title font validation
  287. SideEffectFontChanged();   
  288. }
  289. void COverlayController::SetTitleDuration(double inStart, double inEnd)
  290. {
  291. mDoubleStartTime  = inStart;
  292. mDoubleEndTime    = inEnd;
  293. SideEffectProgressChanged();
  294. }
  295. void COverlayController::SideEffectProgressChanged(void)
  296. {
  297. mOverlayStartTime = long(mInputFrameRate * mDoubleStartTime);
  298. mOverlayEndTime   = -1;
  299. if (mDoubleEndTime > 0)
  300. {
  301. mOverlayEndTime = long(mInputFrameRate * mDoubleEndTime);
  302. }
  303. }
  304. // Commonly, invoker should get the title length first by passing NULL to outBuffer
  305. int COverlayController::GetTitle(char * outBuffer)
  306. {
  307. int titleLength = 0;
  308. if (mTitle)
  309. {
  310. titleLength = strlen(mTitle) + 1;
  311. if (outBuffer)
  312. {
  313. strcpy(outBuffer, mTitle);
  314. }
  315. }
  316. return titleLength;
  317. }
  318. void COverlayController::GetTitleColor(BYTE * outR, BYTE * outG, BYTE * outB)
  319. {
  320. *outR = mColorRed;
  321. *outG = mColorGreen;
  322. *outB = mColorBlue;
  323. }
  324. void COverlayController::GetTitleStartPosition(POINT * outStartPos)
  325. {
  326. outStartPos->x = mStartPos.x;
  327. outStartPos->y = mStartPos.y;
  328. }
  329. void COverlayController::GetTitleFont(LOGFONT * outFont)
  330. {
  331. *outFont = mTitleFont;
  332. }
  333. void COverlayController::GetTitleDuration(double * outStart, double * outEnd)
  334. {
  335. *outStart = mDoubleStartTime;
  336. *outEnd   = mDoubleEndTime;
  337. }
  338. // This method must be invoked before all actual title overlay work.
  339. // We can create title DIB map here!
  340. BOOL COverlayController::StartTitleOverlay(void)
  341. {
  342. mCanDoOverlay = (mPixelConverter != 0);
  343. if (mCanDoOverlay)
  344. {
  345. mCanDoOverlay = CreateTitleDIBBits();
  346. }
  347. return mCanDoOverlay;
  348. }
  349. BOOL COverlayController::StopTitleOverlay(void)
  350. {
  351. mCanDoOverlay   = FALSE;
  352. mOverlayCounter = 0;
  353. return TRUE;
  354. }
  355. BOOL COverlayController::DoTitleOverlay(PBYTE inImage)
  356. {
  357. if (!mCanDoOverlay)
  358. {
  359. return FALSE;
  360. }
  361. BOOL pass = BeforeActualOverlay();
  362. if (pass)
  363. {
  364. pass = ActualOverlay(inImage);
  365. }
  366. if (pass)
  367. {
  368. pass = AfterActualOverlay();
  369. }
  370. return pass;
  371. }
  372. // Do title duration checking here!
  373. // Subclass can override this method to ignore tile duration feature
  374. BOOL COverlayController::BeforeActualOverlay(void)
  375. {
  376. // Only keep the title duration here
  377. if (mOverlayCounter >= mOverlayStartTime)
  378. {
  379. if (mOverlayEndTime == -1 || mOverlayCounter <= mOverlayEndTime)
  380. {
  381. return TRUE;
  382. }
  383. }
  384. // If not reach the start time, count any way!
  385. mOverlayCounter++;
  386. return FALSE;
  387. }
  388. BOOL COverlayController::AfterActualOverlay(void)
  389. {
  390. mOverlayCounter++;
  391. return TRUE;
  392. }
  393. BOOL COverlayController::ActualOverlay(PBYTE inImage)
  394. {
  395. // Now copy the data from the DIB section (which is usually bottom-up)
  396. // but first check if it's too big
  397. if (mImageWidth > mStartPos.x && mImageHeight > mStartPos.y && 
  398. mTitleSize.cx > 0 && mTitleSize.cy > 0) 
  399. {
  400. long actualOverlayWidth  = min((mImageWidth - mStartPos.x), mTitleSize.cx);
  401. long actualOverlayHeight = min((mImageHeight - mStartPos.y), mTitleSize.cy);
  402. // Image may be bottom-up, may be top-down.
  403. // Anyway retrieve the pointer which point to the top line
  404. PBYTE   pTopLine      = NULL;
  405. long    strideInBytes = 0;
  406. if (mIsBottomUpImage)
  407. {
  408. strideInBytes = -mImageWidthInBytes;
  409.     pTopLine      = inImage + mImageWidthInBytes * (mImageHeight - 1);
  410. }
  411. else
  412. {
  413. strideInBytes = mImageWidthInBytes;
  414. pTopLine      = inImage;
  415. }
  416. PBYTE  pStartPos = pTopLine + mStartPos.y * strideInBytes + mStartPos.x * mImageBitCount / 8;
  417. for (DWORD dwY = 0; dwY < (DWORD)actualOverlayHeight; dwY++) 
  418. {
  419. PBYTE pbTitle  = mTitleDIBBits + mDIBWidthInBytes * ((DWORD)mTitleSize.cy - dwY - 1);
  420. for (DWORD dwX = 0; dwX < (DWORD)actualOverlayWidth; dwX++) 
  421. {
  422. // dwX & 7, value from 0 - 7
  423. // 0x80 >> (dwX & 7), value from 10000000 to 00000001
  424. // dwX >> 3, value add one every eight
  425. // If the source bit is 0, the background. If 1, draw the text.
  426. if ( !((0x80 >> (dwX & 7)) & pbTitle[dwX >> 3]) ) 
  427. {
  428. PBYTE pbPixel = mPixelConverter->NextNPixel(pStartPos, dwX);
  429. if (mIsOverlayByCover)
  430. {
  431. mPixelConverter->ConvertByCover(pbPixel);
  432. }
  433. else
  434. {
  435. mPixelConverter->ConvertByReverse(pbPixel);
  436. }
  437. }
  438. }
  439. pStartPos += strideInBytes;
  440. }
  441. return TRUE;
  442. }
  443. return FALSE;
  444. }