MFC音视频播放器-支持电子放大等功能

前言

本播放器在VS2019下开发,使用ffmpeg+D3D实现视频播放渲染功能。同时本播放器支持录像功能、截图功能、音视频播放功能、码流信息显示、电子放大功能等。D3D的渲染同时支持surface和texture两种方式,电子放大功能是在D3D Texture方式下进行实现。以下为该功能的一些核心代码,具体可以通过本文末的链接进行工程源码下载。

一、播放器电子放大功能操作

步骤一:播放RTSP 视频流后,点击开启电子放大功能按钮,如下图:
步骤二:点击按钮后,视频上会出现电子放大的变倍信息,本功能支持鼠标滚轮进行图形放大与缩小,也支持鼠标拖动视频进行显示,如下图:
步骤三:鼠标滚轮操作电子放大的放大缩小功能,如下图:
步骤四:按住鼠标左键后,可以拖动视频进行显示,如下图:
步骤五:点击关闭电子放大按钮后,恢复正常显示:

二、电子放大相关源码

CVideoPlayer鼠标事件:

复制代码
void CVideoPlayer::OnLButtonDown(UINT nFlags, CPoint point)
{
    myprint("OnLButtonDown");
    SetFocus();

    if (m_bDigitalZoom) // Digital Zoom
    {
        m_D3DRender.SetStartPt(point);
        m_bLBtnDown = true;
    }

    CStatic::OnLButtonDown(nFlags, point);
}


void CVideoPlayer::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_bLBtnDown = false;
    ReleaseCapture();
}


BOOL CVideoPlayer::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{    
    myprint("OnMouseWheel");
    CRect rcClient;
    GetClientRect(&rcClient);
    CPoint ptTemp = pt;
    ::ScreenToClient(m_hWnd, &ptTemp);
    if (!PtInRect(&rcClient, ptTemp))
        return FALSE;
    m_ptWheel = pt;
    ::ScreenToClient(m_hWnd, &m_ptWheel);

    if (m_bDigitalZoom)
    {
        zDelta /= WHEEL_DELTA;

        myprint("OnMouseWheel zDelta:%d", zDelta);
        if (zDelta > 0)
        {
            for (short i = 0; i < zDelta; i++)
                m_D3DRender.ZoomOut();
        }
        else
        {
            for (short i = 0; i > zDelta; i--)
                m_D3DRender.ZoomIn();
        }
        return TRUE;
    }
    return FALSE;
}

void CVideoPlayer::OnMouseMove(UINT nFlags, CPoint point)
{
    if (m_bPlaying == false)
        return;

    SetFocus();

    if (m_bLBtnDown && m_bDigitalZoom)
    {
        CRect rc;
        GetClientRect(&rc);
        m_D3DRender.MoveToPtStart(point, rc);
    }
    
    CStatic::OnMouseMove(nFlags, point);
}

CD3DRender处理:

复制代码
//zoom
void CD3DRender::ZoomIn()
{
    m_Radius += m_RadiusFirst / DEFAULT_ZOOM_TIMES;
    myprint("ZoomIn m_RadiusFirst:%lf m_Radius:%lf\n", m_RadiusFirst, m_Radius);

    if (m_Radius >= DEFAULT_ZOOM_TIMES)
    {
        m_Radius = DEFAULT_ZOOM_TIMES;
    }

    D3DXVECTOR3 position(-x_curCam, y_curCam, sinf(m_Angle) * m_Radius);
    D3DXVECTOR3 target(-x_curCam, y_curCam, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    D3DXMATRIX V;
    D3DXMatrixLookAtLH(&V, &position, &target, &up);

    m_pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);
}

void CD3DRender::ZoomOut()
{
    m_Radius -= m_RadiusFirst / DEFAULT_ZOOM_TIMES;
    myprint("ZoomOut m_RadiusFirst:%lf m_Radius:%lf\n", m_RadiusFirst, m_Radius);

    if (m_Radius <= 1.1f)
    {
        m_Radius = 1.1f;
    }

    D3DXVECTOR3 position(-x_curCam, y_curCam, sinf(m_Angle) * m_Radius);
    D3DXVECTOR3 target(-x_curCam, y_curCam, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    D3DXMATRIX V;
    D3DXMatrixLookAtLH(&V, &position, &target, &up);

    m_pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);
}

void CD3DRender::ResetZoom()
{
    x_Cam = x_curCam = 0;
    y_Cam = y_curCam = 0;

    m_Radius = m_RadiusFirst;
    m_Angle = m_AngleFirst;

    D3DXVECTOR3 position(cosf(m_Angle) * m_Radius, 0.0f, sinf(m_Angle) * m_Radius);
    D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    D3DXMATRIX V;
    D3DXMatrixLookAtLH(&V, &position, &target, &up);

    m_pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);
}

HRESULT CD3DRender::AppendZoomTextInfo(TCHAR* sText, CRect rcText) 
{
    my_mutex_lock(m_pDrawMutex);

    memset(&m_DigZoomInfo, 0, sizeof(StreamInfo_t));

    _sntprintf_s(m_DigZoomInfo.sText, sizeof(m_DigZoomInfo.sText), sizeof(m_DigZoomInfo.sText) - 1, "%s", sText);
    m_DigZoomInfo.rcText.top = rcText.top;
    m_DigZoomInfo.rcText.left = rcText.left;
    m_DigZoomInfo.rcText.right = rcText.right;
    m_DigZoomInfo.rcText.bottom = rcText.bottom;

    my_mutex_unlock(m_pDrawMutex);
    return 0;
}

HRESULT CD3DRender::ClearZoomTextInfo()
{
    my_mutex_lock(m_pDrawMutex);

    memset(&m_DigZoomInfo, 0, sizeof(StreamInfo_t));

    my_mutex_unlock(m_pDrawMutex);
    return 0;
}

void CD3DRender::D3DDrawZoomText()
{
    my_mutex_lock(m_pDrawMutex);

    m_pD3DFont->DrawText(NULL, m_DigZoomInfo.sText, -1, &m_DigZoomInfo.rcText, DT_LEFT/*DT_CENTER | DT_VCENTER*/, D3DCOLOR_XRGB(220, 20, 60));

    my_mutex_unlock(m_pDrawMutex);
}

void CD3DRender::SetStartPt(::CPoint pt)
{
    pt_start = pt;
    x_Cam = x_curCam;
    y_Cam = y_curCam;
}


void CD3DRender::MoveToPtStart(::CPoint pt, CRect rc)
{
    float x = x_Cam + 40.0f * ((float)m_Radius / 20.0f) * (float)(pt.x - pt_start.x) / (float)(rc.right - rc.left);
    float y = y_Cam + 40.0f * ((float)m_Radius / 20.0f) * (float)(pt.y - pt_start.y) / (float)(rc.bottom - rc.top);
    x_curCam = x;
    y_curCam = y;

    myprint("position( %f, %f, %f)  x_Cam = %f, y_Cam = %f\n", x, y, sinf(m_Angle) * m_Radius, x_Cam, y_Cam);
    myprint("rc(%d, %d, %d, %d)", rc.left, rc.top, rc.right, rc.bottom);
    D3DXVECTOR3 position(-x, y, sinf(m_Angle) * m_Radius);
    D3DXVECTOR3 target(-x, y, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    D3DXMATRIX V;
    D3DXMatrixLookAtLH(&V, &position, &target, &up);

    m_pDirect3DDevice->SetTransform(D3DTS_VIEW, &V);
}

三、相关下载

链接1: 可执行exe下载

链接2: 播放器工程源码下载

相关推荐
嶔某4 分钟前
网络:应用层
linux·服务器·网络·c++
linux kernel1 小时前
第十一讲:模板进阶以及反向迭代器
c++
青牛科技-Allen2 小时前
GC8871刷式直流电机驱动器深度解析:3.6A驱动与内置电流检测技术
单片机·嵌入式硬件·音视频·音响·电动工具·散热风扇·电脑散热风扇
小徐不徐说4 小时前
每日一算:华为-批萨分配问题
数据结构·c++·算法·leetcode·华为·动态规划·后端开发
姜暮儿6 小时前
C++ 性能优化
开发语言·c++
铭哥的编程日记7 小时前
《从C风格到C++风格:内存管理的进化之路》
开发语言·c++
程序员编程指南8 小时前
Qt 与 SQLite 嵌入式数据库开发
c语言·数据库·c++·qt
屁股割了还要学11 小时前
【C语言进阶】柔性数组
c语言·开发语言·数据结构·c++·学习·算法·柔性数组
oioihoii11 小时前
C++实战案例:从static成员到线程安全的单例模式
java·c++·单例模式
Tracy97312 小时前
HF83311_VB1/HF83311Q_VB1:高性能USB HiFi音频解码器固件技术解析
音视频·xmos 模组·xmos 模组固件