videoplayer.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. #include "precompile.h"
  2. #include "videoplayer.h"
  3. #define WIN32_LEAN_AND_MEAN
  4. #include <windows.h>
  5. #include <vfw.h>
  6. #include <assert.h>
  7. #define av_always_inline __inline
  8. #define inline __inline
  9. #include <libswscale\swscale.h>
  10. #include "video_common/ffmpeg_api_adapter.h"
  11. #define WM_MSG_INIT (WM_APP+1)
  12. #define WM_MSG_CLEAR (WM_APP+2)
  13. #define WM_MSG_FRAME (WM_APP+3)
  14. #define FRAME_MIN_CACHE_MSEC 125
  15. #define FRAME_MAX_CACHE_MSEC 500
  16. #define FRAME_QUEUE_LEGNTH 50
  17. enum eVideoSizeMode{
  18. eNormalSize,
  19. eDoubleSize,
  20. eZoomOutSize
  21. };
  22. typedef enum eVideoSizeMode eVideoSizeMode;
  23. typedef struct frame_entry
  24. {
  25. video_frame *raw_frame;
  26. videoplayer_free_frame free_frame;
  27. void *free_frame_user_data;
  28. DWORD dwTick;
  29. }frame_entry;
  30. #pragma pack(push,1)
  31. struct winthunk_t
  32. {
  33. DWORD m_mov;
  34. DWORD m_this;
  35. BYTE m_jmp;
  36. DWORD m_relproc;
  37. };
  38. #pragma pack(pop)
  39. struct videoplayer_t
  40. {
  41. struct winthunk_t thunk;
  42. HWND hWndVideo;
  43. int x;
  44. int y;
  45. int cx;
  46. int cy;
  47. int fps_num;
  48. int fps_den;
  49. int width;
  50. int height;
  51. WNDPROC oldWndProc;
  52. int flags;
  53. eVideoSizeMode esizemode; // double size mode
  54. struct SwsContext *double_size_sws_context;
  55. LPVOID double_size_data;
  56. struct SwsContext *zoomout_size_sws_context;
  57. LPVOID zoomout_size_data;
  58. frame_entry current_frame;
  59. CRITICAL_SECTION q_lock;
  60. frame_entry frames[FRAME_QUEUE_LEGNTH];
  61. int q_head;
  62. int q_tail;
  63. int q_caching;
  64. LPVOID black_frame_data;
  65. LPVOID res_frame_data;
  66. struct SwsContext *sws_context;
  67. DWORD dwPlayTimer;
  68. HDRAWDIB hdib;
  69. int min_cache_size;
  70. int max_cache_size;
  71. videoplayer_on_pull on_pull;
  72. videoplayer_free_frame free_frame;
  73. void *user_data;
  74. char name[16];
  75. };
  76. #ifndef SMALL_RECORD_VIDEO_WIDTH
  77. #define SMALL_RECORD_VIDEO_WIDTH 244
  78. #endif
  79. #ifndef SMALL_RECORD_VIDEO_HEIGHT
  80. #define SMALL_RECORD_VIDEO_HEIGHT 138
  81. #endif
  82. // use thunk tech
  83. #define QUEUE_SIZE(head, tail, length) (((tail)+(length)-(head))%(length))
  84. #define QUEUE_INC(x, length) (((x) + 1) % (length))
  85. int nWindowState = 0;
  86. int bMove = 0;
  87. static RECT g_Rect;
  88. int IsHideRemoteWin = 0;
  89. int IsHideLocalWin = 0;
  90. static void Dbg(const char *fmt, ...)
  91. {
  92. int n;
  93. va_list arg;
  94. va_start(arg, fmt);
  95. n = _vscprintf(fmt, arg);
  96. if (n > 0) {
  97. char *buf = (char*)_alloca(n+3);
  98. vsprintf(buf, fmt, arg);
  99. strcat(buf, "\r\n");
  100. OutputDebugStringA(buf);
  101. }
  102. va_end(arg);
  103. }
  104. static __inline int InRectangle(int xPos, int yPos, int x0, int y0, int cx, int cy)
  105. {
  106. return xPos >= x0 && xPos <= x0+cx && yPos >= y0 && yPos <= y0+cy;
  107. }
  108. static __inline void free_frame_entry(videoplayer_t *player, struct frame_entry *entry)
  109. {
  110. if (entry && entry->raw_frame) {
  111. (*entry->free_frame)(player, entry->free_frame_user_data, entry->raw_frame);
  112. }
  113. }
  114. static int init_thunk(struct winthunk_t *thunk, DWORD_PTR proc, videoplayer_t *player)
  115. {
  116. thunk->m_mov = 0x042444C7;
  117. thunk->m_this = (DWORD)player;
  118. thunk->m_jmp = 0xe9;
  119. thunk->m_relproc = (DWORD)((INT_PTR)proc - ((INT_PTR)player+sizeof(struct winthunk_t)));
  120. FlushInstructionCache(GetCurrentProcess(), thunk, sizeof(struct winthunk_t));
  121. return 0;
  122. }
  123. static void display_frame_entry(videoplayer_t *player, video_frame *frame);
  124. static BOOL is_parent_window_of(HWND x, HWND y)
  125. {
  126. HWND t = GetParent(y);
  127. while (t) {
  128. if (t == x)
  129. return TRUE;
  130. t = GetParent(t);
  131. }
  132. return FALSE;
  133. }
  134. static void check_on_top(videoplayer_t *player)
  135. {
  136. RECT rc;
  137. if (GetWindowRect(player->hWndVideo, &rc)) {
  138. HWND hWnd;
  139. POINT t;
  140. t.x = (rc.left + rc.right) >> 1;
  141. t.y = (rc.top + rc.bottom) >> 1;
  142. hWnd = WindowFromPoint(t);
  143. if (hWnd && hWnd != player->hWndVideo) {
  144. //if (!is_parent_window_of(hWnd, player->hWndVideo) && !is_parent_window_of(player->hWndVideo, hWnd)) {
  145. BringWindowToTop(player->hWndVideo);
  146. //MessageBeep(MB_OK);
  147. //}
  148. }
  149. }
  150. }
  151. static void OnMsgFrame(videoplayer_t *player, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  152. {
  153. frame_entry *entry = (frame_entry*)wParam;
  154. display_frame_entry(player, entry->raw_frame);
  155. free_frame_entry(player, &player->current_frame);
  156. player->current_frame.raw_frame = entry->raw_frame;
  157. player->current_frame.free_frame = entry->free_frame;
  158. player->current_frame.free_frame_user_data = entry->free_frame_user_data;
  159. player->current_frame.dwTick = entry->dwTick;
  160. entry->raw_frame = NULL;
  161. free(entry);
  162. }
  163. static void display_frame_entry(videoplayer_t *player, video_frame *frame)
  164. {
  165. if (NULL == player || NULL == frame){
  166. return;
  167. }
  168. if (player->flags & VIDEOPLAYER_FLAG_CHECKTOP) {
  169. check_on_top(player);
  170. }
  171. if (player->hdib) {
  172. HDC hdc;
  173. hdc = GetDC(player->hWndVideo);
  174. if (hdc) {
  175. if (eDoubleSize == player->esizemode) {
  176. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  177. unsigned char *src_data[4] = {frame->data[0], NULL, NULL, NULL};
  178. int src_linesize[4] = {player->width*3, 0, 0, 0};
  179. unsigned char *dst_data[4] = {player->double_size_data, NULL, NULL, NULL};
  180. int dst_linesize[4] = {player->cx*2*3, 0, 0, 0};
  181. bmpheader.biPlanes = 1;
  182. bmpheader.biBitCount = 24;//pr->bpp;
  183. bmpheader.biCompression = BI_RGB;
  184. bmpheader.biHeight = player->cy<<1;
  185. bmpheader.biWidth = player->cx<<1;
  186. sws_scale(player->double_size_sws_context, src_data, src_linesize,
  187. 0, player->height, dst_data, dst_linesize);
  188. DrawDibDraw(player->hdib, hdc, 0, 0, -1, -1, &bmpheader, player->double_size_data, 0, 0, player->cx<<1, player->cy<<1, DDF_SAME_DRAW|DDF_SAME_HDC);
  189. }
  190. else if(eZoomOutSize == player->esizemode){
  191. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  192. unsigned char *src_data[4] = {frame->data[0], NULL, NULL, NULL};
  193. int src_linesize[4] = {player->width*3, 0, 0, 0};
  194. unsigned char *dst_data[4] = {player->zoomout_size_data, NULL, NULL, NULL};
  195. int dst_linesize[4] = {SMALL_RECORD_VIDEO_WIDTH*3, 0, 0, 0};
  196. //{
  197. // static int icount = 0;
  198. // if (icount == 0)
  199. // {
  200. // video_frame frame;
  201. // video_frame_alloc(320, 240, VIDEO_FORMAT_RGB24, &frame);
  202. // video_frame_fill_black(&frame);
  203. // frame.data[0] = src_data[0];
  204. // frame.linesize[0] = src_linesize[0];
  205. // video_frame_save_bmpfile("d:\\src.bmp", &frame);
  206. // icount++;
  207. // }
  208. //}
  209. bmpheader.biPlanes = 1;
  210. bmpheader.biBitCount = 24;//pr->bpp;
  211. bmpheader.biCompression = BI_RGB;
  212. bmpheader.biHeight = SMALL_RECORD_VIDEO_HEIGHT;
  213. bmpheader.biWidth = SMALL_RECORD_VIDEO_WIDTH;
  214. sws_scale(player->zoomout_size_sws_context, src_data, src_linesize,
  215. 0, player->height, dst_data, dst_linesize);
  216. //{
  217. // static int icount = 0;
  218. // if (icount == 0)
  219. // {
  220. // video_frame frame;
  221. // video_frame_alloc(SMALL_RECORD_VIDEO_WIDTH, SMALL_RECORD_VIDEO_HEIGHT, VIDEO_FORMAT_RGB24, &frame);
  222. // video_frame_fill_black(&frame);
  223. // frame.data[0] = /*dst_data[0];*/ (unsigned char*)player->zoomout_size_data;
  224. // frame.linesize[0] = dst_linesize[0];
  225. // video_frame_save_bmpfile("d:\\dest.bmp", &frame);
  226. // icount++;
  227. // }
  228. //}
  229. DrawDibDraw(player->hdib, hdc, 0, 0, -1, -1, &bmpheader, player->zoomout_size_data, 0, 0, SMALL_RECORD_VIDEO_WIDTH, SMALL_RECORD_VIDEO_HEIGHT, DDF_SAME_DRAW|DDF_SAME_HDC);
  230. }
  231. else{
  232. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  233. bmpheader.biPlanes = 1;
  234. bmpheader.biBitCount = 24;//pr->bpp;
  235. bmpheader.biCompression = BI_RGB;
  236. bmpheader.biHeight = player->cy;
  237. bmpheader.biWidth = player->cx;
  238. if (player->sws_context) {
  239. unsigned char *src_data[4] = {frame->data[0], NULL, NULL, NULL};
  240. int src_linesize[4] = {player->width*3, 0, 0, 0};
  241. unsigned char *dst_data[4] = {player->res_frame_data, NULL, NULL, NULL};
  242. int dst_linesize[4] = {player->cx*3, 0, 0, 0};
  243. sws_scale(player->sws_context, src_data, src_linesize,
  244. 0, player->height, dst_data, dst_linesize);
  245. DrawDibDraw(player->hdib, hdc, 0, 0, -1, -1, &bmpheader, player->res_frame_data, 0, 0, player->cx, player->cy, DDF_SAME_DRAW|DDF_SAME_HDC);
  246. } else {
  247. DrawDibDraw(player->hdib, hdc, 0, 0, -1, -1, &bmpheader, frame->data[0], 0, 0, player->cx, player->cy, DDF_SAME_DRAW|DDF_SAME_HDC);
  248. }
  249. }
  250. ReleaseDC(player->hWndVideo, hdc);
  251. }
  252. }
  253. }
  254. static void display_black_frame(videoplayer_t *player)
  255. {
  256. if (player->flags & VIDEOPLAYER_FLAG_CHECKTOP) {
  257. check_on_top(player);
  258. }
  259. if (player->hdib) {
  260. HDC hdc;
  261. hdc = GetDC(player->hWndVideo);
  262. if (hdc) {
  263. if (eDoubleSize == player->esizemode) {
  264. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  265. unsigned char *src_data[4] = {player->black_frame_data, NULL, NULL, NULL};
  266. int src_linesize[4] = {player->cx*3, 0, 0, 0};
  267. unsigned char *dst_data[4] = {player->double_size_data, NULL, NULL, NULL};
  268. int dst_linesize[4] = {player->cx*2*3, 0, 0, 0};
  269. sws_scale(player->double_size_sws_context, src_data, src_linesize,
  270. 0, player->height, dst_data, dst_linesize);
  271. bmpheader.biPlanes = 1;
  272. bmpheader.biBitCount = 24;//pr->bpp;
  273. bmpheader.biCompression = BI_RGB;
  274. bmpheader.biHeight = player->cy<<1;
  275. bmpheader.biWidth = player->cx<<1;
  276. DrawDibDraw(player->hdib, hdc, 0, 0, -1, -1, &bmpheader, player->double_size_data, 0, 0, player->cx<<1, player->cy<<1, DDF_SAME_DRAW|DDF_SAME_HDC);
  277. }
  278. else if(eZoomOutSize == player->esizemode){
  279. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  280. unsigned char *src_data[4] = {player->black_frame_data, NULL, NULL, NULL};
  281. int src_linesize[4] = {player->cx*3, 0, 0, 0};
  282. unsigned char *dst_data[4] = {player->zoomout_size_data, NULL, NULL, NULL};
  283. int dst_linesize[4] = {SMALL_RECORD_VIDEO_WIDTH*3, 0, 0, 0};
  284. sws_scale(player->zoomout_size_sws_context, src_data, src_linesize,
  285. 0, player->height, dst_data, dst_linesize);
  286. bmpheader.biPlanes = 1;
  287. bmpheader.biBitCount = 24;//pr->bpp;
  288. bmpheader.biCompression = BI_RGB;
  289. bmpheader.biHeight = SMALL_RECORD_VIDEO_HEIGHT;
  290. bmpheader.biWidth = SMALL_RECORD_VIDEO_WIDTH;
  291. DrawDibDraw(player->hdib, hdc, 0, 0, -1, -1, &bmpheader, player->zoomout_size_data, 0, 0, SMALL_RECORD_VIDEO_WIDTH, SMALL_RECORD_VIDEO_HEIGHT, DDF_SAME_DRAW|DDF_SAME_HDC);
  292. }
  293. else{
  294. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  295. bmpheader.biPlanes = 1;
  296. bmpheader.biBitCount = 24;//pr->bpp;
  297. bmpheader.biCompression = BI_RGB;
  298. bmpheader.biHeight = player->cy;
  299. bmpheader.biWidth = player->cx;
  300. DrawDibDraw(player->hdib, hdc, 0, 0, -1, -1, &bmpheader, player->black_frame_data, 0, 0, player->cx, player->cy, DDF_SAME_DRAW|DDF_SAME_HDC);
  301. }
  302. ReleaseDC(player->hWndVideo, hdc);
  303. }
  304. }
  305. }
  306. static void OnMsgTimer_PushMode(videoplayer_t *player, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  307. {
  308. DWORD dwNow = GetTickCount();
  309. EnterCriticalSection(&player->q_lock);
  310. //获取窗口显示状态
  311. nWindowState = player->on_pull(player, player->user_data,NULL);
  312. if (player->q_caching) {
  313. OutputDebugStringA("caching\n");
  314. while (player->q_tail != player->q_head) {
  315. frame_entry *entry = &player->frames[player->q_head];
  316. if (dwNow - entry->dwTick > 3000) {
  317. player->q_head = QUEUE_INC(player->q_head, FRAME_QUEUE_LEGNTH);
  318. free_frame_entry(player, entry);
  319. } else {
  320. break;
  321. }
  322. }
  323. } else {
  324. int displayed = 0;
  325. //if (player->q_head == player->q_tail)
  326. while (player->q_tail != player->q_head) {
  327. frame_entry *entry = &player->frames[player->q_head];
  328. player->q_head = QUEUE_INC(player->q_head, FRAME_QUEUE_LEGNTH);
  329. if (dwNow - entry->dwTick > 3000) {
  330. //Dbg("clear frame");
  331. free_frame_entry(player, entry);
  332. } else {
  333. //Dbg("display frame");
  334. display_frame_entry(player, entry->raw_frame);
  335. displayed = TRUE;
  336. free_frame_entry(player, &player->current_frame);
  337. player->current_frame.raw_frame = entry->raw_frame;
  338. player->current_frame.free_frame = entry->free_frame;
  339. player->current_frame.free_frame_user_data = entry->free_frame_user_data;
  340. player->current_frame.dwTick = entry->dwTick;
  341. entry->raw_frame = NULL;
  342. break;
  343. }
  344. }
  345. if (!displayed) {
  346. player->q_caching = TRUE;
  347. Dbg("recaching");
  348. }
  349. }
  350. LeaveCriticalSection(&player->q_lock);
  351. }
  352. static void OnMsgTimer_PullMode(videoplayer_t *player, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  353. {
  354. video_frame *frame = NULL;
  355. nWindowState = player->on_pull(player, player->user_data, &frame);
  356. display_frame_entry(player, frame);
  357. player->free_frame(player, player->user_data, frame);
  358. }
  359. static void OnMsgInit(videoplayer_t *player, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  360. {
  361. HDC hdc;
  362. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  363. bmpheader.biPlanes = 1;
  364. bmpheader.biBitCount = 24;
  365. bmpheader.biCompression = BI_RGB;
  366. bmpheader.biHeight = player->cy;
  367. bmpheader.biWidth = player->cx;
  368. player->hdib = DrawDibOpen();
  369. if (!player->hdib)
  370. return;
  371. hdc = GetDC(hWnd);
  372. if (!DrawDibBegin(player->hdib, hdc, player->cx, player->cy, &bmpheader,
  373. player->cx, player->cy, DDF_SAME_DRAW|DDF_SAME_HDC)) {
  374. DrawDibClose(player->hdib);
  375. player->hdib = NULL;
  376. ReleaseDC(hWnd, hdc);
  377. return;
  378. }
  379. ReleaseDC(hWnd, hdc);
  380. player->q_head = player->q_tail = 0;
  381. player->q_caching = 1;
  382. player->black_frame_data = malloc(player->cx*player->cy*3);
  383. memset(player->black_frame_data, 0, player->cx*player->cy*3);
  384. if (player->cx != player->width || player->cy != player->height) {
  385. player->res_frame_data = malloc(player->cx*player->cy*3);
  386. player->sws_context = sws_getCachedContext(
  387. NULL,
  388. player->width,
  389. player->height,
  390. PIX_FMT_BGR24,
  391. player->cx,
  392. player->cy,
  393. PIX_FMT_BGR24,
  394. SWS_LANCZOS,
  395. NULL,
  396. NULL,
  397. NULL);
  398. }
  399. if (player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE) {
  400. player->double_size_data = malloc(player->cx * player->cy * 4 * 3);
  401. player->double_size_sws_context = sws_getCachedContext(
  402. NULL,
  403. player->width,
  404. player->height,
  405. PIX_FMT_BGR24,
  406. 2 * player->cx,
  407. 2 * player->cy,
  408. PIX_FMT_BGR24,
  409. SWS_LANCZOS,
  410. NULL,
  411. NULL,
  412. NULL);
  413. }
  414. if (player->flags & VIDEOPLAYER_FLAG_ZOOMOUTSIZE) {
  415. player->zoomout_size_data = malloc(SMALL_RECORD_VIDEO_WIDTH*SMALL_RECORD_VIDEO_HEIGHT*3);
  416. player->zoomout_size_sws_context = sws_getCachedContext(
  417. NULL,
  418. player->width,
  419. player->height,
  420. PIX_FMT_BGR24,
  421. SMALL_RECORD_VIDEO_WIDTH,
  422. SMALL_RECORD_VIDEO_HEIGHT,
  423. PIX_FMT_BGR24,
  424. SWS_LANCZOS,
  425. NULL,
  426. NULL,
  427. NULL);
  428. }
  429. if (!(player->flags & VIDEOPLAYER_FLAG_NOTIMER)) {
  430. player->dwPlayTimer = SetTimer(hWnd, 3, 1000*player->fps_den/player->fps_num, NULL);
  431. }
  432. }
  433. static void OnMsgClear(videoplayer_t *player, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  434. {
  435. if (player->dwPlayTimer != 0) {
  436. KillTimer(hWnd, player->dwPlayTimer);
  437. }
  438. display_black_frame(player);
  439. free(player->black_frame_data);
  440. player->black_frame_data = NULL;
  441. while (QUEUE_SIZE(player->q_head, player->q_tail, FRAME_QUEUE_LEGNTH)) {
  442. frame_entry *entry = &player->frames[player->q_head];
  443. player->q_head = QUEUE_INC(player->q_head, FRAME_QUEUE_LEGNTH);
  444. free_frame_entry(player, entry);
  445. }
  446. assert(player->q_head == player->q_tail);
  447. if (player->sws_context) {
  448. free(player->res_frame_data);
  449. player->res_frame_data = NULL;
  450. sws_freeContext(player->sws_context);
  451. player->sws_context = NULL;
  452. }
  453. if (player->double_size_sws_context) {
  454. free(player->double_size_data);
  455. player->double_size_data = NULL;
  456. sws_freeContext(player->double_size_sws_context);
  457. player->double_size_sws_context = NULL;
  458. }
  459. if (player->zoomout_size_sws_context) {
  460. free(player->zoomout_size_data);
  461. player->zoomout_size_data = NULL;
  462. sws_freeContext(player->zoomout_size_sws_context);
  463. player->zoomout_size_sws_context = NULL;
  464. }
  465. free_frame_entry(player, &player->current_frame);
  466. player->q_caching = 0;
  467. }
  468. static LRESULT VideoWndProc(videoplayer_t *player, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  469. {
  470. {
  471. char tmp[128];
  472. sprintf(tmp, "%s, msg=%d, wparam=%d,lparam=%d\n", player->name, msg, wParam, lParam);
  473. OutputDebugStringA(tmp);
  474. }
  475. switch (msg) {
  476. case WM_MSG_FRAME:
  477. OnMsgFrame(player, hWnd, msg, wParam, lParam);
  478. break;
  479. case WM_MSG_INIT:
  480. OnMsgInit(player, hWnd, msg, wParam, lParam);
  481. break;
  482. case WM_MSG_CLEAR:
  483. OnMsgClear(player, hWnd, msg, wParam, lParam);
  484. break;
  485. case WM_TIMER:
  486. //是否隐藏本地视频窗口
  487. if (player->flags & VIDEOPLAYER_FLAG_PULL)
  488. {
  489. if ((nWindowState == 2)||(nWindowState == 4))
  490. {
  491. if (IsHideLocalWin==0)
  492. {
  493. ShowWindow(hWnd,SW_HIDE);
  494. IsHideLocalWin = 1;
  495. }
  496. }
  497. else if((nWindowState == 0)||(nWindowState == 1)||(nWindowState == 3))
  498. {
  499. if (IsHideLocalWin==1)
  500. {
  501. ShowWindow(hWnd,SW_SHOW);
  502. IsHideLocalWin = 0;
  503. }
  504. }
  505. }
  506. //是否隐藏远端视频窗口
  507. if (player->flags & VIDEOPLAYER_FLAG_PUSH)
  508. {
  509. if (nWindowState == 2)
  510. {
  511. if (IsHideRemoteWin==0)
  512. {
  513. ShowWindow(hWnd,SW_HIDE);
  514. IsHideRemoteWin = 1;
  515. }
  516. }
  517. else if((nWindowState == 0)||(nWindowState == 1)||(nWindowState == 3)||(nWindowState == 4))
  518. {
  519. if (IsHideRemoteWin==1)
  520. {
  521. ShowWindow(hWnd,SW_SHOW);
  522. IsHideRemoteWin = 0;
  523. }
  524. }
  525. }
  526. //是否将本地窗口放大显示
  527. if (((nWindowState==1 && player->cx != 960)&&(bMove==0))&&(player->flags & VIDEOPLAYER_FLAG_PULL)&&(player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE)&&(IsHideLocalWin==0))
  528. {
  529. GetWindowRect(hWnd, &g_Rect);
  530. MoveWindow(hWnd, g_Rect.left, g_Rect.top, player->cx<<1, player->cy<<1, TRUE);
  531. player->esizemode = eDoubleSize;
  532. if (player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE)
  533. {
  534. int xPos = LOWORD(lParam);
  535. int yPos = HIWORD(lParam);
  536. HDC hdc = GetDC(hWnd);
  537. if (hdc) {
  538. if (player->hdib) {
  539. if (eDoubleSize == player->esizemode)
  540. {
  541. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  542. bmpheader.biPlanes = 1;
  543. bmpheader.biBitCount = 24;
  544. bmpheader.biCompression = BI_RGB;
  545. bmpheader.biHeight = player->cy<<1;
  546. bmpheader.biWidth = player->cx<<1;
  547. DrawDibBegin(player->hdib, hdc, player->cx<<1, player->cy<<1, &bmpheader, player->cx<<1, player->cy<<1, DDF_SAME_DRAW|DDF_SAME_HDC);
  548. }
  549. else if(eNormalSize == player->esizemode)
  550. {
  551. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  552. bmpheader.biPlanes = 1;
  553. bmpheader.biBitCount = 24;
  554. bmpheader.biCompression = BI_RGB;
  555. bmpheader.biHeight = player->cy;
  556. bmpheader.biWidth = player->cx;
  557. DrawDibBegin(player->hdib, hdc, player->cx, player->cy, &bmpheader, player->cx, player->cy, DDF_SAME_DRAW|DDF_SAME_HDC);
  558. }
  559. }
  560. ReleaseDC(hWnd, hdc);
  561. }
  562. }
  563. bMove = 1;
  564. }
  565. else if ((nWindowState==0)&&bMove&&(player->flags & VIDEOPLAYER_FLAG_PULL)&&(player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE || player->flags & VIDEOPLAYER_FLAG_ZOOMOUTSIZE)&&(IsHideLocalWin==0))
  566. {
  567. MoveWindow(hWnd, g_Rect.left, g_Rect.top, player->cx, player->cy, TRUE);
  568. player->esizemode = eNormalSize;
  569. bMove = 0;
  570. if (player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE||player->flags & VIDEOPLAYER_FLAG_ZOOMOUTSIZE)
  571. {
  572. int xPos = LOWORD(lParam);
  573. int yPos = HIWORD(lParam);
  574. HDC hdc = GetDC(hWnd);
  575. if (hdc) {
  576. if (player->hdib) {
  577. if (eDoubleSize == player->esizemode)
  578. {
  579. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  580. bmpheader.biPlanes = 1;
  581. bmpheader.biBitCount = 24;
  582. bmpheader.biCompression = BI_RGB;
  583. bmpheader.biHeight = player->cy<<1;
  584. bmpheader.biWidth = player->cx<<1;
  585. DrawDibBegin(player->hdib, hdc, player->cx<<1, player->cy<<1, &bmpheader, player->cx<<1, player->cy<<1, DDF_SAME_DRAW|DDF_SAME_HDC);
  586. }
  587. else if(eNormalSize == player->esizemode)
  588. {
  589. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  590. bmpheader.biPlanes = 1;
  591. bmpheader.biBitCount = 24;
  592. bmpheader.biCompression = BI_RGB;
  593. bmpheader.biHeight = player->cy;
  594. bmpheader.biWidth = player->cx;
  595. DrawDibBegin(player->hdib, hdc, player->cx, player->cy, &bmpheader, player->cx, player->cy, DDF_SAME_DRAW|DDF_SAME_HDC);
  596. }
  597. }
  598. ReleaseDC(hWnd, hdc);
  599. }
  600. }
  601. }
  602. if ((nWindowState==5)&&(player->flags&VIDEOPLAYER_FLAG_ZOOMOUTSIZE))
  603. {
  604. //Dbg("zoom out size video echo.");
  605. GetWindowRect(hWnd, &g_Rect);
  606. MoveWindow(hWnd, g_Rect.left, g_Rect.top, SMALL_RECORD_VIDEO_WIDTH, SMALL_RECORD_VIDEO_HEIGHT, TRUE);
  607. player->esizemode = eZoomOutSize;
  608. if (player->flags&VIDEOPLAYER_FLAG_ZOOMOUTSIZE)
  609. {
  610. HDC hdc = GetDC(hWnd);
  611. if (hdc){
  612. if (player->hdib) {
  613. if (eZoomOutSize == player->esizemode)
  614. {
  615. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  616. bmpheader.biPlanes = 1;
  617. bmpheader.biBitCount = 24;
  618. bmpheader.biCompression = BI_RGB;
  619. bmpheader.biHeight = SMALL_RECORD_VIDEO_HEIGHT;
  620. bmpheader.biWidth = SMALL_RECORD_VIDEO_WIDTH;
  621. DrawDibBegin(player->hdib, hdc, SMALL_RECORD_VIDEO_WIDTH, SMALL_RECORD_VIDEO_HEIGHT, &bmpheader, SMALL_RECORD_VIDEO_WIDTH, SMALL_RECORD_VIDEO_HEIGHT, DDF_SAME_DRAW|DDF_SAME_HDC);
  622. }
  623. else if(eNormalSize == player->esizemode)
  624. {
  625. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  626. bmpheader.biPlanes = 1;
  627. bmpheader.biBitCount = 24;
  628. bmpheader.biCompression = BI_RGB;
  629. bmpheader.biHeight = player->cy;
  630. bmpheader.biWidth = player->cx;
  631. DrawDibBegin(player->hdib, hdc, player->cx, player->cy, &bmpheader, player->cx, player->cy, DDF_SAME_DRAW|DDF_SAME_HDC);
  632. }
  633. }
  634. ReleaseDC(hWnd, hdc);
  635. }
  636. }
  637. bMove = 1;
  638. }
  639. if (wParam == player->dwPlayTimer)
  640. {
  641. if (player->flags & VIDEOPLAYER_FLAG_PUSH)
  642. {
  643. OnMsgTimer_PushMode(player, hWnd, msg, wParam, lParam);
  644. }
  645. else if (player->flags & VIDEOPLAYER_FLAG_PULL)
  646. {
  647. OnMsgTimer_PullMode(player, hWnd, msg, wParam, lParam);
  648. }
  649. }
  650. break;
  651. case WM_LBUTTONDOWN:
  652. if((player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE)&&!(player->flags & VIDEOPLAYER_FLAG_PULL))
  653. {
  654. eVideoSizeMode old = player->esizemode;
  655. if (eNormalSize == player->esizemode)
  656. {
  657. player->esizemode = eDoubleSize;
  658. }
  659. if (old != player->esizemode)
  660. {
  661. RECT rc;
  662. GetWindowRect(hWnd, &rc);
  663. if (eDoubleSize == player->esizemode)
  664. {
  665. MoveWindow(hWnd, rc.left, rc.top, player->cx<<1, player->cy<<1, TRUE);
  666. }
  667. else
  668. {
  669. MoveWindow(hWnd, rc.left, rc.top, player->cx, player->cy, TRUE);
  670. }
  671. }
  672. }
  673. else
  674. {
  675. return CallWindowProcA(player->oldWndProc, hWnd, msg, wParam, lParam);
  676. }
  677. break;
  678. case WM_LBUTTONUP:
  679. if ((player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE)&&!(player->flags & VIDEOPLAYER_FLAG_PULL))
  680. {
  681. eVideoSizeMode old = player->esizemode;
  682. if (eDoubleSize == player->esizemode) {
  683. player->esizemode = eNormalSize;
  684. }
  685. if (old != player->esizemode) {
  686. RECT rc;
  687. GetWindowRect(hWnd, &rc);
  688. if (eDoubleSize == player->esizemode)
  689. {
  690. MoveWindow(hWnd, rc.left, rc.top, player->cx<<1, player->cy<<1, TRUE);
  691. }
  692. else
  693. {
  694. MoveWindow(hWnd, rc.left, rc.top, player->cx, player->cy, TRUE);
  695. }
  696. }
  697. } else {
  698. return CallWindowProcA(player->oldWndProc, hWnd, msg, wParam, lParam);
  699. }
  700. break;
  701. case WM_MOUSEMOVE:
  702. if ((player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE)&&!(player->flags & VIDEOPLAYER_FLAG_PULL))
  703. {
  704. eVideoSizeMode old = player->esizemode;
  705. if (eDoubleSize == player->esizemode) {
  706. POINT pt = {LOWORD(lParam), HIWORD(lParam)};
  707. RECT rc;
  708. GetWindowRect(hWnd, &rc);
  709. ClientToScreen(hWnd, &pt);
  710. if (!InRectangle(pt.x, pt.y, rc.left, rc.top, player->cx, player->cy)) { // once out of rectangle, taken as LBUTTONUP
  711. player->esizemode = eNormalSize;
  712. }
  713. }
  714. if (old != player->esizemode) {
  715. RECT rc;
  716. GetWindowRect(hWnd, &rc);
  717. if (eDoubleSize == player->esizemode) {
  718. MoveWindow(hWnd, rc.left, rc.top, player->cx<<1, player->cy<<1, TRUE);
  719. } else {
  720. MoveWindow(hWnd, rc.left, rc.top, player->cx, player->cy, TRUE);
  721. }
  722. }
  723. } else {
  724. return CallWindowProcA(player->oldWndProc, hWnd, msg, wParam, lParam);
  725. }
  726. break;
  727. case WM_SIZE:
  728. if (player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE || player->flags & VIDEOPLAYER_FLAG_ZOOMOUTSIZE)
  729. {
  730. int xPos = LOWORD(lParam);
  731. int yPos = HIWORD(lParam);
  732. HDC hdc = GetDC(hWnd);
  733. if (hdc) {
  734. if (player->hdib) {
  735. if (eDoubleSize == player->esizemode) {
  736. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  737. bmpheader.biPlanes = 1;
  738. bmpheader.biBitCount = 24;
  739. bmpheader.biCompression = BI_RGB;
  740. bmpheader.biHeight = player->cy<<1;
  741. bmpheader.biWidth = player->cx<<1;
  742. DrawDibBegin(player->hdib, hdc, player->cx<<1, player->cy<<1, &bmpheader, player->cx<<1, player->cy<<1, DDF_SAME_DRAW|DDF_SAME_HDC);
  743. }
  744. else if(eZoomOutSize == player->esizemode){
  745. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  746. bmpheader.biPlanes = 1;
  747. bmpheader.biBitCount = 24;
  748. bmpheader.biCompression = BI_RGB;
  749. bmpheader.biHeight = SMALL_RECORD_VIDEO_HEIGHT;
  750. bmpheader.biWidth = SMALL_RECORD_VIDEO_WIDTH;
  751. DrawDibBegin(player->hdib, hdc, SMALL_RECORD_VIDEO_WIDTH, SMALL_RECORD_VIDEO_HEIGHT, &bmpheader, SMALL_RECORD_VIDEO_WIDTH, SMALL_RECORD_VIDEO_HEIGHT, DDF_SAME_DRAW|DDF_SAME_HDC);
  752. }
  753. else{
  754. BITMAPINFOHEADER bmpheader = {sizeof(BITMAPINFOHEADER)};
  755. bmpheader.biPlanes = 1;
  756. bmpheader.biBitCount = 24;
  757. bmpheader.biCompression = BI_RGB;
  758. bmpheader.biHeight = player->cy;
  759. bmpheader.biWidth = player->cx;
  760. DrawDibBegin(player->hdib, hdc, player->cx, player->cy, &bmpheader, player->cx, player->cy, DDF_SAME_DRAW|DDF_SAME_HDC);
  761. }
  762. }
  763. ReleaseDC(hWnd, hdc);
  764. }
  765. } else {
  766. return CallWindowProcA(player->oldWndProc, hWnd, msg, wParam, lParam);
  767. }
  768. break;
  769. case WM_PAINT:
  770. if (player->flags & VIDEOPLAYER_FLAG_DOUBLESIZE || player->flags & VIDEOPLAYER_FLAG_ZOOMOUTSIZE)
  771. {
  772. if (player->current_frame.raw_frame) {
  773. display_frame_entry(player, player->current_frame.raw_frame);
  774. ValidateRect(hWnd, NULL);
  775. return 0;
  776. }
  777. }
  778. else
  779. {
  780. ValidateRect(hWnd, NULL);
  781. return 0;
  782. }
  783. return CallWindowProcA(player->oldWndProc, hWnd, msg, wParam, lParam);
  784. default:
  785. return CallWindowProcA(player->oldWndProc, hWnd, msg, wParam, lParam);
  786. }
  787. return 0;
  788. }
  789. static LRESULT CALLBACK __VideoWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  790. {
  791. videoplayer_t *player = (videoplayer_t*)hWnd;
  792. return VideoWndProc(player, player->hWndVideo, msg, wParam, lParam);
  793. }
  794. static int hook_window(videoplayer_t *player)
  795. {
  796. init_thunk(&player->thunk, (DWORD_PTR)&__VideoWndProc, player);
  797. player->oldWndProc = SetWindowLongA(player->hWndVideo, GWL_WNDPROC, (LONG)&player->thunk);
  798. SendMessageA(player->hWndVideo, WM_MSG_INIT, 0, 0);
  799. return 0;
  800. }
  801. static void unhook_window(videoplayer_t *player)
  802. {
  803. SendMessageA(player->hWndVideo, WM_MSG_CLEAR, 0, 0);
  804. SetWindowLongA(player->hWndVideo, GWL_WNDPROC, (LONG)player->oldWndProc);
  805. }
  806. int videoplayer_create(HWND hWndVideo,
  807. int x, int y, int cx, int cy,
  808. int fps_num,int fps_den,
  809. int width, int height, int flags, const char *name,
  810. videoplayer_on_pull on_pull,
  811. videoplayer_free_frame free_frame,
  812. void *user_data,
  813. videoplayer_t **p_player)
  814. {
  815. videoplayer_t *player = (videoplayer_t*)VirtualAlloc(NULL, sizeof(videoplayer_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  816. if (player) {
  817. memset(player, 0, sizeof(videoplayer_t));
  818. assert(fps_den != 0);
  819. assert(fps_num < FRAME_QUEUE_LEGNTH * fps_den);
  820. player->hWndVideo = hWndVideo;
  821. player->x = x;
  822. player->y = y;
  823. player->cx = cx;
  824. player->cy = cy;
  825. player->fps_den = fps_den;
  826. player->fps_num = fps_num;
  827. player->width = width;
  828. player->height = height;
  829. player->min_cache_size = FRAME_MIN_CACHE_MSEC * fps_num / 1000 * fps_den;
  830. player->max_cache_size = FRAME_MAX_CACHE_MSEC * fps_num / 1000 * fps_den;
  831. player->res_frame_data = player->black_frame_data = NULL;
  832. player->sws_context = NULL;
  833. player->esizemode = eNormalSize;
  834. player->double_size_sws_context = NULL;
  835. player->double_size_data = NULL;
  836. player->zoomout_size_sws_context = NULL;
  837. player->zoomout_size_data = NULL;
  838. player->current_frame.raw_frame = NULL;
  839. player->flags = flags;
  840. player->hdib = NULL;
  841. player->on_pull = on_pull;
  842. player->free_frame = free_frame;
  843. player->user_data = user_data;
  844. strncpy(player->name, name, sizeof(player->name)-1);
  845. player->name[sizeof(player->name)-1] = 0;
  846. InitializeCriticalSection(&player->q_lock);
  847. if (hook_window(player) != 0) {
  848. VirtualFree(player, sizeof(videoplayer_t), MEM_RELEASE);
  849. return -1;
  850. }
  851. *p_player = player;
  852. } else {
  853. return -1;
  854. }
  855. //初始化窗口状态
  856. nWindowState = 0;
  857. bMove = 0;
  858. IsHideRemoteWin = 0;
  859. IsHideLocalWin = 0;
  860. return 0;
  861. }
  862. void videoplayer_destroy(videoplayer_t *player)
  863. {
  864. MSG msg;
  865. while (PeekMessageA(&msg, player->hWndVideo, WM_MSG_FRAME, WM_MSG_FRAME, PM_REMOVE)) {
  866. frame_entry *entry = (frame_entry *)msg.wParam;
  867. free_frame_entry(player, entry);
  868. free(entry);
  869. }
  870. unhook_window(player);
  871. DeleteCriticalSection(&player->q_lock);
  872. VirtualFree(player, 0, MEM_RELEASE|MEM_DECOMMIT);
  873. }
  874. int videoplayer_queue_frame(videoplayer_t *player, video_frame *frame, videoplayer_free_frame free_frame, void *free_frame_user_data)
  875. {
  876. assert(frame->format == VIDEO_FORMAT_RGB24);
  877. if (player && player->hWndVideo && (player->flags&VIDEOPLAYER_FLAG_PUSH)) {
  878. if (player->flags & VIDEOPLAYER_FLAG_NOTIMER) {
  879. frame_entry *entry = (frame_entry*)malloc(sizeof(frame_entry));
  880. entry->free_frame = free_frame;
  881. entry->free_frame_user_data = free_frame_user_data;
  882. entry->raw_frame = frame;
  883. entry->dwTick = GetTickCount();
  884. if (!PostMessageA(player->hWndVideo, WM_MSG_FRAME, (WPARAM)entry, 0))
  885. {
  886. free(entry);
  887. return -1;
  888. }
  889. } else {
  890. EnterCriticalSection(&player->q_lock);
  891. player->frames[player->q_tail].raw_frame = frame;
  892. player->frames[player->q_tail].free_frame = free_frame;
  893. player->frames[player->q_tail].free_frame_user_data = free_frame_user_data;
  894. player->frames[player->q_tail].dwTick = GetTickCount();
  895. player->q_tail = QUEUE_INC(player->q_tail, FRAME_QUEUE_LEGNTH);
  896. if (player->q_caching) {
  897. int qlen = QUEUE_SIZE(player->q_head, player->q_tail, FRAME_QUEUE_LEGNTH);
  898. Dbg("qlen:%d, %d, %d", qlen, player->min_cache_size, player->max_cache_size);
  899. if (qlen >= player->min_cache_size)
  900. player->q_caching = 0;
  901. }
  902. while (QUEUE_SIZE(player->q_head, player->q_tail, FRAME_QUEUE_LEGNTH) > player->max_cache_size) {
  903. int qlen = QUEUE_SIZE(player->q_head, player->q_tail, FRAME_QUEUE_LEGNTH);
  904. Dbg("erase qlen:%d", qlen);
  905. free_frame_entry(player, &player->frames[player->q_head]);
  906. player->q_head = QUEUE_INC(player->q_head, FRAME_QUEUE_LEGNTH);
  907. }
  908. LeaveCriticalSection(&player->q_lock);
  909. }
  910. } else {
  911. return -1;
  912. }
  913. return 0;
  914. }