Files
ANSCORE/MediaClient/media/video_render_gdi.cpp

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;
}