/*************************************************************************************** * * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. * * By downloading, copying, installing or using the software you agree to this license. * If you do not agree to this license, do not download, install, * copy or use the software. * * Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved. * * Redistribution and use in binary forms, with or without modification, are permitted. * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific * language governing permissions and limitations under the License. * ****************************************************************************************/ #include "sys_inc.h" #include "video_render_gdi.h" /***************************************************************************************/ #pragma comment(lib, "vfw32") /***************************************************************************************/ CGDIVideoRender::CGDIVideoRender() : CVideoRender() , m_hDC(NULL) , m_hCompatDC(NULL) , m_hCompatBitmap(NULL) , m_hDib(NULL) , m_bReinit(FALSE) { memset(&m_bmpHdr, 0, sizeof(m_bmpHdr)); memset(&m_dstRect, 0, sizeof(RECT)); } CGDIVideoRender::~CGDIVideoRender() { unInit(); } BOOL CGDIVideoRender::init(WId wid, int w, int h, int videofmt) { HWND hWnd = (HWND)wid; m_hDC = ::GetDC(hWnd); if (NULL == m_hDC) { return FALSE; } m_hCompatDC = ::CreateCompatibleDC(m_hDC); if (NULL == m_hCompatDC) { log_print(HT_LOG_ERR, "%s, CreateCompatibleDC failed\r\n", __FUNCTION__); return FALSE; } ::SetStretchBltMode(m_hDC, HALFTONE); ::SetStretchBltMode(m_hCompatDC, HALFTONE); RECT rect; ::GetClientRect(hWnd, &rect); m_hCompatBitmap = ::CreateCompatibleBitmap(m_hDC, rect.right - rect.left, rect.bottom - rect.top); if (NULL == m_hCompatBitmap) { log_print(HT_LOG_ERR, "%s, CreateCompatibleBitmap failed\r\n", __FUNCTION__); return FALSE; } ::SelectObject(m_hCompatDC, m_hCompatBitmap); memset(&m_bmpHdr, 0, sizeof(BITMAPINFOHEADER)); m_bmpHdr.biSize = 40; m_bmpHdr.biWidth = w; m_bmpHdr.biHeight = h; m_bmpHdr.biBitCount = 24; m_bmpHdr.biPlanes = 1; m_bmpHdr.biSizeImage = w * h * m_bmpHdr.biBitCount / 8; m_hDib = ::DrawDibOpen(); if (NULL == m_hDib) { log_print(HT_LOG_ERR, "%s, DrawDibOpen failed\r\n", __FUNCTION__); return FALSE; } int rectw = rect.right - rect.left; int recth = rect.bottom - rect.top; double dw = rectw / (double) w; double dh = recth / (double) h; double rate = (dw > dh)? dh : dw; int rw = (int)(w * rate); int rh = (int)(h * rate); m_dstRect.left = (rectw - rw) / 2; m_dstRect.top = (recth - rh) / 2; m_dstRect.right = m_dstRect.left + rw; m_dstRect.bottom = m_dstRect.top + rh; CVideoRender::init(wid, w, h, videofmt); m_bInited = ::DrawDibBegin(m_hDib, m_hCompatDC, rw, rh, &m_bmpHdr, w, h, 0); return m_bInited; } void CGDIVideoRender::unInit() { if (m_hCompatDC) { ::DeleteDC(m_hCompatDC); m_hCompatDC = NULL; } if (m_hDC) { ::ReleaseDC((HWND)m_hWnd, m_hDC); m_hDC = NULL; } if (m_hCompatBitmap) { ::DeleteObject(m_hCompatBitmap); m_hCompatBitmap = NULL; } if (m_hDib) { ::DrawDibEnd(m_hDib); ::DrawDibClose(m_hDib); m_hDib = NULL; } m_bInited = FALSE; } BOOL CGDIVideoRender::render(AVFrame * frame, int mode) { if (NULL == frame) { return FALSE; } if (m_bReinit) { unInit(); if (init(m_hWnd, frame->width, frame->height, m_nVideoFmt)) { m_bReinit = FALSE; } } if (!m_bInited) { return FALSE; } BOOL ret = FALSE; RECT rect; GetClientRect((HWND)m_hWnd, &rect); RECT targetRect; RECT sourceRect; sourceRect.left = 0; sourceRect.top = 0; sourceRect.right = frame->width; sourceRect.bottom = frame->height; if (mode == RENDER_MODE_KEEP) { int rectw = rect.right - rect.left; int recth = rect.bottom - rect.top; double dw = rectw / (double) frame->width; double dh = recth / (double) frame->height; double rate = (dw > dh) ? dh : dw; int rw = (int)(frame->width * rate); int rh = (int)(frame->height * rate); targetRect.left = (rectw - rw) / 2; targetRect.top = (recth - rh) / 2; targetRect.right = targetRect.left + rw; targetRect.bottom = targetRect.top + rh; } else { targetRect = rect; } if (memcmp(&m_dstRect, &targetRect, sizeof(RECT)) != 0) { m_bReinit = TRUE; memcpy(&m_dstRect, &targetRect, sizeof(RECT)); } if (m_nVideoWidth != frame->width || m_nVideoHeight != frame->height) { m_bReinit = TRUE; } if (m_bReinit) { unInit(); if (!init(m_hWnd, frame->width, frame->height, m_nVideoFmt)) { log_print(HT_LOG_ERR, "%s, init failed\r\n", __FUNCTION__); return FALSE; } m_bReinit = FALSE; } ::FillRect(m_hCompatDC, &rect, (HBRUSH) ::GetStockObject(BLACK_BRUSH)); if (RENDER_MODE_KEEP == mode) { ret = ::DrawDibDraw(m_hDib, m_hCompatDC, targetRect.left, targetRect.top, targetRect.right - targetRect.left, targetRect.bottom - targetRect.top, &m_bmpHdr, frame->data[0], sourceRect.left, sourceRect.top, sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, DDF_BACKGROUNDPAL); } else { ret = ::DrawDibDraw(m_hDib, m_hCompatDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, &m_bmpHdr, frame->data[0], sourceRect.left, sourceRect.top, sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, DDF_BACKGROUNDPAL); } if (ret) { ret = ::BitBlt(m_hDC, 0, 0, rect.right - rect.left, rect.bottom - rect.top , m_hCompatDC, 0, 0, SRCCOPY); } return ret; }