123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- #include "precompile.h"
- #include "videoview.h"
- #include <vfw.h>
- #define MAX_VIEW_ENTRY 8
- #define BUFFER_COUNT 4
- #define CMB_VIDEOVIEW _T("cmb_videoview")
- #define WM_VIDEO (WM_APP+0x03)
- struct videoview {
- HWND hwnd;
- int own;
- WNDPROC lpfnOrigin;/* use when hwnd != NULL, for subclass window */
- char *buf[BUFFER_COUNT]; /* backgournd buffer */
- volatile LONG buf_use[BUFFER_COUNT];
- int buf_size;
- int offset_x;
- int offset_y;
- int height;
- int width;
- HDRAWDIB hDrawDib;
- /* use when own == TRUE */
- HANDLE hevtnotify; /* set when user call videoview_create with hwnd == null */
- HANDLE uithread;
- };
- static struct {
- HWND hwnd;
- struct videoview *pvv;
- } _map[MAX_VIEW_ENTRY] = {0};
- static LRESULT CALLBACK SubclassWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- int i;
- struct videoview *pvv = NULL;
- for (i = 0; i < MAX_VIEW_ENTRY; ++i) {
- if (_map[i].hwnd == hWnd) {
- pvv = _map[i].pvv;
- break;
- }
- }
- if (i == MAX_VIEW_ENTRY) {
- /* bug */
- return DefWindowProc(hWnd, msg, wParam, lParam);
- }
- if (msg == WM_VIDEO) {
- int idx = (int)wParam;
- if (idx >= 0 && idx < BUFFER_COUNT && pvv->hDrawDib) {
- HDC hdc = GetDC(hWnd);
- BITMAPINFOHEADER bmiHeader = {sizeof(BITMAPINFOHEADER)};
- bmiHeader.biBitCount = 24;
- bmiHeader.biWidth = pvv->width;
- bmiHeader.biHeight = pvv->height;
- bmiHeader.biPlanes = 1;
- bmiHeader.biCompression = BI_RGB;
- DrawDibDraw(pvv->hDrawDib, hdc, pvv->offset_x, pvv->offset_y, -1, -1,
- &bmiHeader, pvv->buf[idx], 0, 0, pvv->width, pvv->height, DDF_SAME_DRAW);
- InterlockedExchange(&pvv->buf_use[idx], 0);/* clear use flag */
- ReleaseDC(hWnd, hdc);
- } else if (idx == -1) { /* create drawdib */
- if (pvv->hDrawDib == NULL) {
- if ((pvv->hDrawDib = DrawDibOpen()) != NULL) {
- HDC hdc = GetDC(hWnd);
- BITMAPINFOHEADER bmiHeader = {sizeof(BITMAPINFOHEADER)};
- bmiHeader.biBitCount = 24;
- bmiHeader.biWidth = pvv->width;
- bmiHeader.biHeight = pvv->height;
- bmiHeader.biPlanes = 1;
- bmiHeader.biCompression = BI_RGB;
- if (DrawDibBegin(pvv->hDrawDib, hdc, -1, -1, &bmiHeader, pvv->width,
- pvv->height, 0) == FALSE) {
- DrawDibClose(pvv->hDrawDib);
- pvv->hDrawDib = NULL;
- } else {
- UINT u = DrawDibRealize(pvv->hDrawDib, hdc, 0);
- pvv->hDrawDib;
- }
- ReleaseDC(hWnd, hdc);
- }
- }
- return (LRESULT)pvv->hDrawDib;
- } else if (idx == -2) { /* destroy drawdib */
- if (pvv->hDrawDib) {
- DrawDibEnd(pvv->hDrawDib);
- DrawDibClose(pvv->hDrawDib);
- pvv->hDrawDib = NULL;
- }
- } else if (idx == -3) { /* destroy window */
- DestroyWindow(hWnd);
- PostQuitMessage(0);
- }
- return 0;
- }
- if (pvv->own) {
- if (msg == WM_CLOSE)
- return 0;
- }
- if (pvv->lpfnOrigin)
- return (*pvv->lpfnOrigin)(hWnd, msg, wParam, lParam);
- return DefWindowProc(hWnd, msg, wParam, lParam);
- }
- static BOOL InitDrawDib(videoview_t vv)
- {
- if (vv && vv->hwnd)
- return (BOOL)SendMessage(vv->hwnd, WM_VIDEO, (WPARAM)-1, 0); /* -1 for init */
- return -1;
- }
- static void DeinitDrawDib(videoview_t vv)
- {
- SendMessage(vv->hwnd, WM_VIDEO, (WPARAM)-2, 0); /* -2 for destroy */
- }
- static unsigned __stdcall VideoViewUIThreadProc(void *param)
- {
- MSG msg;
- WNDCLASS wc;
- struct videoview * pvv = (struct videoview*)param;
- int width, height;
- CoInitialize(NULL);
- /* register class */
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wc.hInstance = NULL;
- wc.style = CS_HREDRAW|CS_VREDRAW|CS_NOCLOSE;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = CMB_VIDEOVIEW;
- wc.lpfnWndProc = &SubclassWndProc;
- RegisterClass(&wc);
- /* create window */
- height = pvv->height + 2*GetSystemMetrics(SM_CYBORDER) +
- 2*GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CYCAPTION);
- width = pvv->width + 2*GetSystemMetrics(SM_CXBORDER) + 2*GetSystemMetrics(SM_CXEDGE);
- pvv->hwnd = CreateWindow(CMB_VIDEOVIEW, _T("cmb video view"),
- WS_MINIMIZE|WS_CAPTION|WS_POPUPWINDOW|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
- width, height, NULL, NULL, NULL, NULL);
- /* notify caller's thread, ui thread window is ready */
- SetEvent(pvv->hevtnotify);
- while (GetMessage(&msg, 0, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- CoUninitialize();
- _endthreadex(0);
- return 0;
- }
- int videoview_create(videoview_t *pvv, HWND hWnd, int off_x, int off_y, int pic_width, int pic_height)
- {
- int i;
- struct videoview *p;
- if (!pvv)
- return -1;
- for (i = 0; i < MAX_VIEW_ENTRY; ++i)
- if (_map[i].hwnd == NULL)
- break;
- if (i == MAX_VIEW_ENTRY)
- return -1;
- p = (struct videoview*)malloc(sizeof(struct videoview));
- if (p == NULL)
- return -1;
- ZeroMemory(p, sizeof(struct videoview));
- p->height = pic_height;
- p->width = pic_width;
- p->buf_size = pic_width * pic_height * 3;
- p->offset_x = off_x;
- p->offset_y = off_y;
- p->buf[0] = malloc(BUFFER_COUNT*p->buf_size);
- if (p->buf[0] == NULL) {
- free(p);
- return -1;
- }
- for (i = 1; i < BUFFER_COUNT; ++i)
- p->buf[i] = p->buf[0] + i*p->buf_size;
- if (hWnd) {
- if (!IsWindow(hWnd)) {
- free(p->buf[0]);
- free(p);
- return -1;
- }
- p->own = FALSE;
- p->hwnd = hWnd;
- p->lpfnOrigin = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)SubclassWndProc);
- _map[i].hwnd = p->hwnd;
- *pvv = _map[i].pvv = p;
- if (!InitDrawDib(p)) {
- SetWindowLong(hWnd, GWL_WNDPROC, (LONG)p->lpfnOrigin);
- free(p->buf[0]);
- free(p);
- _map[i].hwnd = NULL;
- _map[i].pvv = NULL;
- return -1;
- }
- } else {
- p->own = TRUE;
- p->hevtnotify = CreateEvent(NULL, FALSE, FALSE, NULL);
- p->uithread = (HANDLE)_beginthreadex(0, 0, &VideoViewUIThreadProc, p, 0, NULL);
- WaitForSingleObject(p->hevtnotify, INFINITE);
- _map[i].hwnd = p->hwnd;
- *pvv = _map[i].pvv = p;
- if (!InitDrawDib(p)) {
- PostMessage(p->hwnd, WM_CLOSE, 0, 0);
- WaitForSingleObject(p->uithread, INFINITE);
- CloseHandle(p->uithread);
- CloseHandle(p->hevtnotify);
- free(p->buf[0]);
- free(p);
- _map[i].hwnd = NULL;
- _map[i].pvv = NULL;
- return -1;
- }
- }
- return 0;
- }
- void videoview_destroy(videoview_t vv)
- {
- if (!vv || !vv->hwnd)
- return;
-
- if (vv->hDrawDib)
- DeinitDrawDib(vv);
- if (vv->own) {
- int i;
- for (i = 0; i < MAX_VIEW_ENTRY; ++i)
- if (_map[i].pvv == vv)
- break;
- if (i == MAX_VIEW_ENTRY)
- return;
- PostMessage(vv->hwnd, WM_VIDEO, (WPARAM)-3, 0);
- WaitForSingleObject(vv->uithread, INFINITE);
- CloseHandle(vv->uithread);
- CloseHandle(vv->hevtnotify);
- _map[i].hwnd = NULL;
- _map[i].pvv = NULL;
- } else {
- if (vv->lpfnOrigin)
- SetWindowLong(vv->hwnd, GWL_WNDPROC, (LONG)vv->lpfnOrigin);
- }
- free(vv->buf[0]);
- free(vv);
- }
- int videoview_put(videoview_t vv, void *buf, int len, unsigned int ts_rtp/*for later usage*/)
- {
- int i;
- if (!vv || !vv->hwnd || !buf || len != vv->buf_size)
- return -1;
- for (i = 0; i < BUFFER_COUNT; ++i) {
- if (vv->buf_use[i] == 0) { /* first try */
- if (InterlockedCompareExchange(&vv->buf_use[i], 1, 0) == 0) { /* second try, ok */
- memcpy(vv->buf[i], buf, len);
- PostMessage(vv->hwnd, WM_VIDEO, (WPARAM)i, (LPARAM)ts_rtp);
- return 0;
- }
- }
- }
- return -1; /* not enough slot */
- }
|