255 lines
6.0 KiB
C++
255 lines
6.0 KiB
C++
/***************************************************************************************
|
|
*
|
|
* 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;
|
|
}
|
|
|
|
|
|
|