图灵转世 2023-05-23 16:33 采纳率: 75%
浏览 70
已结题

vlc二次开发播放视频,direct3d 11 output窗口问题

vlc二次开发,mfc窗口,调用libvlc,播放海康rtsp流,出现了两个窗口,一个mfc dialog窗口,一个vlc direct3d 11 output窗口,视频就显示了最初一帧,就停了。请大家解决。
代码如下:

#pragma once
# ifdef __cplusplus
extern "C" {
# endif
void cfgvlc(int winid);
void play();
# ifdef __cplusplus
}
# endif

```c++
typedef int ssize_t;
#include "vlc/vlc.h"
libvlc_instance_t* _vlcinstance;
libvlc_media_player_t* _mp;
libvlc_media_t* _m;
void cfgvlc(int winid)
{
    const char* const vlc_args[] = {
       "--verbose=2", //be much more verbose then normal for debugging purpose
     "--network-caching=100",
    };

    //create a new libvlc instance
    _vlcinstance= libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);  //tricky calculation of the char space used
    // Create a media player playing environement
    _mp = libvlc_media_player_new(_vlcinstance);


    ///* Create a new LibVLC media descriptor */
    _m = libvlc_media_new_location(_vlcinstance, "rtsp://admin:a8628391@192.168.1.64:554/h265/ch1/main/av_stream");
    libvlc_media_player_set_media(_mp, _m);
    ///* Get our media instance to use our window */
    //int windid = (int)GetDlgItem(IDC_STATIC_VLC)->m_hWnd;//ui->frame->winId();
    libvlc_media_player_set_xwindow(_mp, winid);
    ///* Play */
    libvlc_media_player_play(_mp);


    return;
}

void play()
{
    libvlc_media_player_play(_mp);
}





```c++

// MFCvlcDlg.h: 头文件
//

#pragma once

//#include "vlc/vlc.h"
// CMFCvlcDlg 对话框
class CMFCvlcDlg : public CDialogEx
{
// 构造
public:
    CMFCvlcDlg(CWnd* pParent = nullptr);    // 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_MFCVLC_DIALOG };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

public:

// 实现
protected:
    HICON m_hIcon;

    // 生成的消息映射函数
    virtual BOOL OnInitDialog();
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnTimer(UINT_PTR nIDEvent); 
    DECLARE_MESSAGE_MAP()
};



```c++

// MFCvlcDlg.cpp: 实现文件
//
//#include "vlc/vlc.h"
#include "pch.h"
#include "framework.h"
#include "MFCvlc.h"
#include "MFCvlcDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//#undef WIN32_LEAN_AND_MEAN
#include "myvlc.h"
#define TIMERID 8

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
    CAboutDlg();

// 对话框数据
#ifdef AFX_DESIGN_TIME
    enum { IDD = IDD_ABOUTBOX };
#endif

    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
    DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMFCvlcDlg 对话框



CMFCvlcDlg::CMFCvlcDlg(CWnd* pParent /*=nullptr*/)
    : CDialogEx(IDD_MFCVLC_DIALOG, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFCvlcDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMFCvlcDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_WM_TIMER()
END_MESSAGE_MAP()


// CMFCvlcDlg 消息处理程序

BOOL CMFCvlcDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 将“关于...”菜单项添加到系统菜单中。

    // IDM_ABOUTBOX 必须在系统命令范围内。
    ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX < 0xF000);

    CMenu* pSysMenu = GetSystemMenu(FALSE);
    if (pSysMenu != nullptr)
    {
        BOOL bNameValid;
        CString strAboutMenu;
        bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
        ASSERT(bNameValid);
        if (!strAboutMenu.IsEmpty())
        {
            pSysMenu->AppendMenu(MF_SEPARATOR);
            pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }
    }

    // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);            // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标

    // TODO: 在此添加额外的初始化代码
    //libvlc_instance_t* _vlcinstance;
    //libvlc_media_player_t* _mp;
    //libvlc_media_t* _m;

    const char* const vlc_args[] = {
        //   "--verbose=2", //be much more verbose then normal for debugging purpose
     "--network-caching=100",
    };

    //create a new libvlc instance
    ///*_vlcinstance*/ libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);  //tricky calculation of the char space used
    // Create a media player playing environement
    //_mp = (void *)libvlc_media_player_new(_vlcinstance);


    ///* Create a new LibVLC media descriptor */
    //_m = (void*)libvlc_media_new_location(_vlcinstance, "rtsp://admin:a8628391@192.168.1.64:554/h265/ch1/main/av_stream");
    //libvlc_media_player_set_media(_mp, _m);
    ///* Get our media instance to use our window */
    //int windid = (int)GetDlgItem(IDC_STATIC_VLC)->m_hWnd;//ui->frame->winId();
    //libvlc_media_player_set_xwindow(_mp, windid);
    ///* Play */
    //libvlc_media_player_play(_mp);


    cfgvlc((int)GetDlgItem(IDC_STATIC_VLC)->m_hWnd);
    SetTimer(TIMERID, 1, 0);

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CMFCvlcDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CMFCvlcDlg::OnPaint()
{
    if (IsIconic())
    {
        CPaintDC dc(this); // 用于绘制的设备上下文

        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // 使图标在工作区矩形中居中
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // 绘制图标
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialogEx::OnPaint();
    }
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCvlcDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}

void CMFCvlcDlg::OnTimer(UINT_PTR nIDEvent)
{
    play();
}



```

  • 写回答

5条回答 默认 最新

  • @晓码自在 2023-05-23 18:00
    关注

    该回答引用GPT与博主@晓码自在合作编写:

    从代码中可以看出,有以下几个问题:

    1. 创建了两个窗口,一个MFC的dialog窗口,一个libvlc的video输出窗口。这会导致视频显示在libvlc的窗口中,而不是MFC的dialog窗口中。

    解决方法: 在创建libvlc_media_player_t对象后,调用libvlc_media_player_set_hwnd()函数设置其HWND为MFC dialog窗口的句柄,而不是调用libvlc_media_player_set_xwindow()设置X窗口ID。这样可以使视频输出到MFC窗口中。

    1. 视频播放后就停止了,只显示第一帧。

    这可能是由于网络连接或其他原因导致的。可以在Timer事件回调函数中不停地调用libvlc_media_player_play()函数来重播视频,这可以避免视频播放结束后停止的问题。

    1. 两个窗口会重叠显示,视频窗口会覆盖在MFC窗口上面。

    可以调用SetWindowPos()函数设置视频窗口的位置,使其不会覆盖MFC窗口。

    修改后的代码如下:

    cpp
    void CMFCvlcDlg::OnInitDialog()
    {
        // ...
    
        // 创建libvlc实例和media player
        libvlc_instance_t* _vlcinstance = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);  
        libvlc_media_player_t* _mp = libvlc_media_player_new(_vlcinstance);
    
        // 设置media
        libvlc_media_t* _m = libvlc_media_new_location(_vlcinstance, "rtsp://admin:a8628391@192.168.1.64:554/h265/ch1/main/av_stream");
        libvlc_media_player_set_media(_mp, _m);
        
        // 设置HWND而不是X窗口ID
        libvlc_media_player_set_hwnd(_mp, m_hWnd);  
    
        // 播放视频
        libvlc_media_player_play(_mp);
    }
    
    void CMFCvlcDlg::OnTimer(UINT_PTR nIDEvent) 
    {
        // 重复调用播放来避免视频停止
        libvlc_media_player_play(_mp);
    }
    
    void CMFCvlcDlg::OnInitDialog() 
    {
        // ...
       
        // 设置视频窗口位置
        libvlc_video_set_position(_mp, 100, 100, 640, 480); 
    }
    
    

    希望这能帮助解决vlc播放海康rtsp流时遇到的问题。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

问题事件

  • 系统已结题 6月6日
  • 已采纳回答 5月29日
  • 创建了问题 5月23日

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c