Files
ANSCORE/MediaClient/media/video_render_sdl.cpp

245 lines
5.3 KiB
C++
Raw Normal View History

2026-03-28 16:54:11 +11:00
/***************************************************************************************
*
* 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_sdl.h"
#include "lock.h"
extern "C"
{
#include <libavutil/imgutils.h>
}
/***************************************************************************************/
static void * g_sdl_mutex = sys_os_create_mutex();
/***************************************************************************************/
CSDLVideoRender::CSDLVideoRender()
: CVideoRender()
, m_pWindow(NULL)
, m_pRenderer(NULL)
, m_pTexture(NULL)
{
}
CSDLVideoRender::~CSDLVideoRender()
{
unInit();
}
BOOL CSDLVideoRender::init(WId hWnd, int w, int h, int videofmt)
{
CVideoRender::init(hWnd, w, h, videofmt);
CLock lock(g_sdl_mutex);
m_bInited = initTexture();
return m_bInited;
}
void CSDLVideoRender::unInit()
{
CLock lock(g_sdl_mutex);
if (m_pTexture)
{
SDL_DestroyTexture(m_pTexture);
m_pTexture = NULL;
}
if (m_pRenderer)
{
SDL_DestroyRenderer(m_pRenderer);
m_pRenderer = NULL;
}
if (m_pWindow)
{
SDL_DestroyWindow(m_pWindow);
m_pWindow = NULL;
}
m_bInited = FALSE;
}
BOOL CSDLVideoRender::reInit(WId hWnd, int w, int h, int videofmt)
{
BOOL ret;
#ifdef IOS
char title[512] = {'\0'};
if (m_pWindow)
{
const char * p_title = SDL_GetWindowTitle(m_pWindow);
if (p_title)
{
strncpy(title, p_title, sizeof(title)-1);
}
}
#endif
unInit();
ret = init(m_hWnd, w, h, m_nVideoFmt);
#ifdef IOS
if (ret && m_pWindow)
{
SDL_SetWindowTitle(m_pWindow, title);
}
#endif
return ret;
}
BOOL CSDLVideoRender::render(AVFrame * frame, int mode)
{
if (!m_bInited || NULL == frame)
{
return FALSE;
}
return renderTexture(frame, mode);
}
BOOL CSDLVideoRender::initTexture()
{
#ifdef IOS
// On Mac platform, SDL does not support rendering videos on child windows
// and must be presented on a separate top-level window
m_pWindow = SDL_CreateWindow("", 0, 0, 400, 300, SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE);
#else
m_pWindow = SDL_CreateWindowFrom((void *)m_hWnd);
#endif
if (NULL == m_pWindow)
{
return FALSE;
}
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if (NULL == m_pRenderer)
{
return FALSE;
}
m_pTexture = SDL_CreateTexture(m_pRenderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, m_nVideoWidth, m_nVideoHeight);
if (NULL == m_pTexture)
{
return FALSE;
}
SDL_ShowWindow(m_pWindow);
return TRUE;
}
BOOL CSDLVideoRender::renderTexture(AVFrame * frame, int mode)
{
int pitch;
uint8 * ptr;
uint8 * pixels;
AVFrame dstFrame;
if (m_nVideoWidth != frame->width || m_nVideoHeight != frame->height)
{
if (!reInit(m_hWnd, frame->width, frame->height, m_nVideoFmt))
{
return TRUE;
}
m_nVideoWidth = frame->width;
m_nVideoHeight = frame->height;
}
memset(&dstFrame, 0, sizeof(AVFrame));
SDL_LockTexture(m_pTexture, NULL, (void **)&pixels, &pitch);
av_image_fill_arrays(dstFrame.data, dstFrame.linesize, pixels, AV_PIX_FMT_YUV420P, m_nVideoWidth, m_nVideoHeight, 1);
// swap UV plane
ptr = dstFrame.data[1];
dstFrame.data[1] = dstFrame.data[2];
dstFrame.data[2] = ptr;
av_image_copy(dstFrame.data, dstFrame.linesize, (const uint8_t**)frame->data, frame->linesize, AV_PIX_FMT_YUV420P, m_nVideoWidth, m_nVideoHeight);
SDL_UnlockTexture(m_pTexture);
SDL_RenderClear(m_pRenderer);
int w, h;
SDL_Rect rect;
SDL_GetRendererOutputSize(m_pRenderer, &w, &h);
if (mode == RENDER_MODE_KEEP)
{
double dw = w / (double) m_nVideoWidth;
double dh = h / (double) m_nVideoHeight;
double rate = (dw > dh) ? dh : dw;
int rw = (int)(m_nVideoWidth * rate);
int rh = (int)(m_nVideoHeight * rate);
rect.x = (w - rw) / 2;
rect.y = (h - rh) / 2;
rect.w = rw;
rect.h = rh;
}
else
{
rect.x = 0;
rect.y = 0;
rect.w = w;
rect.h = h;
}
SDL_RenderCopy(m_pRenderer, m_pTexture, NULL, &rect);
SDL_RenderPresent(m_pRenderer);
return TRUE;
}
void CSDLVideoRender::setWindowSize(QSize size)
{
reInit(m_hWnd, m_nVideoWidth, m_nVideoHeight, m_nVideoFmt);
}
void CSDLVideoRender::setWindowTitle(const char * title)
{
if (m_pWindow)
{
if (title)
{
SDL_SetWindowTitle(m_pWindow, title);
}
else
{
SDL_SetWindowTitle(m_pWindow, "");
}
}
}