UE4 c++ Mediaplayer取消自动播放,运行时首帧为黑屏的问题
0,前言
工作需要使用C++制作一个ue4的视频插件,其中一个功能是能够选择 运行时是否自动播放 视频的功能。
在实现时遇见了一个问题,取消自动播放之后,运行时首帧是没有取到的,在场景里面看是黑色的。就这个问题我想到了使用了一个线程去监控纹理渲染,渲染到第一帧,就暂停,这样的效果看起来就是取消自动播放时,视频插件在场景中显示视频的第一帧。插件的代码不方便贴出来,我这里只贴线程监控的代码。
大部分都是使用蓝图和UE自带的mediaplayer实现视频播放的方案,直接使用UE的mediaplayer,他在给plane附加纹理的时候,会自动生成一个当前视频帧的材质,所以看不到黑帧。但是其实在打开ue第一次运行的时候,还没有读取视频,视频帧的材质也是黑帧。
中间尝试了在mediaplayer中添加回调,在MediaOpened事件中调用play(),然后调用seek()函数,在SeekCompleted事件中调用pause()函数,来做到播放第一帧的效果,但是play()函数只是设置rate为1,渲染第一帧的工作是别的线程实现的,这也就导致,在SeekCompleted事件中调用pause()函数时,另一个线程还没有渲染第一帧,从而运行时还是显示黑帧。
1,原理
查看了mediaplayer的源码,大概捋了一下它的流程,下面是流程图,分了两个线程,一个向队列里面送buffer,一个从队列里面取buffer之后送去渲染:
这只是其中一部分和mediaplayer有关的线程,中间还有很多流程。但我们只需要了解到这个线程是怎么运行的就能够解决目前的问题。
大家可以去贴出来的函数里面打个断点跟一下下流程,大概了解一下就行。
主要看一下第二天取buffer的线程,也就是红框中的流程,有下面的代码:
while (SampleQueue->Dequeue(Sample));if (!Sample.IsValid()){// Player is active (do not clear), but we have no new data// -> we do not need to trigger anything on the renderthreadreturn;}UpdateSampleInfo(Sample);RenderParams.TextureSample = Sample;RenderParams.Rate = CurrentPlayerPtr->GetRate();RenderParams.Time = Sample->GetTime();其中最后一行代码 Sample->GetTime(); 这个GetTime()是纹理中player的时间,我猜是记录播放时长,我们利用这个来实现监控纹理。
原理就是获取视频的帧率,从而获取每帧播放的时长,启动一个线程,监控纹理的player的播放时长,在大于每帧播放时间的时候就暂停掉,从而实现第一帧暂停的效果。
2,实现
多线程的时候代码参考(照抄)了这位博主的:
UE4 C++ 子线程的创建及使用_ue4 启动线程_北极熊的奋斗史的博客-CSDN博客
头文件:
class RNGThread : public FRunnable
{
public://ConstructorRNGThread(int Count = 50000, int minNumber = 0, int maxNumber = 1000, int chunkCount = 20);//Destructor~RNGThread();// 杀死线程,该线程将不能再使用,想再开启的话,需要重新创建//Use this method to kill the thread!!void EnsureCompletion();// 暂停线程//Pause the thread void PauseThread();// 继续线程//Continue/UnPause the threadvoid ContinueThread();// 当前线程是否处于暂停状态bool IsThreadPaused();bool setMediaPlayer(UMediaPlayer* MediaPlayer);bool setVideoComponent(UPXVideoComponent* PXVideoComponent);protected://FRunnable interface.virtual bool Init();virtual uint32 Run();virtual void Stop();private://Thread to run the worker FRunnable onFRunnableThread* Thread;UMediaPlayer* MediaPlayer = nullptr;UPXVideoComponent* PXVideoComponent = nullptr;FCriticalSection m_mutex; // 线程锁FEvent* m_semaphore; // 信号量int m_chunkCount;int m_amount;int m_MinInt;int m_MaxInt;//As the name states those members are Thread safeFThreadSafeBool m_Kill; // bool 类型的变量,线程安全FThreadSafeBool m_Pause;};
源文件:
RNGThread::RNGThread(int Count, int minNumber, int maxNumber, int chunkCount)
{m_Kill = false;m_Pause = false;//Initialize FEvent (as a cross platform (Confirmed Mac/Windows))m_semaphore = FGenericPlatformProcess::GetSynchEventFromPool(false); // 信号量m_MinInt = minNumber;m_MaxInt = maxNumber;m_chunkCount = chunkCount;// 启动线程Thread = FRunnableThread::Create(this, TEXT("RNGThread"), 0, TPri_BelowNormal);
}RNGThread::~RNGThread()
{if (m_semaphore){//Cleanup the FEventFGenericPlatformProcess::ReturnSynchEventToPool(m_semaphore);m_semaphore = nullptr;}if (Thread){//Cleanup the worker threaddelete Thread;Thread = nullptr;}
}bool RNGThread::Init()
{//Init the Data return true;
}/***************************************************************************************/
/*注意:不要在线程中做 spawning / modifying / deleting UObjects / AActors 等等之类的事 */
/***************************************************************************************/uint32 RNGThread::Run()
{// 等待一下初始化//Initial wait before startingFPlatformProcess::Sleep(0.03);// 判断是否停止了线程while (!m_Kill){// 判断当前是否处于暂停状态if (m_Pause){//使用信号量使线程处于睡眠状态,直到被唤醒m_semaphore->Wait();if (m_Kill){return 0;}}else{if(MediaPlayer != nullptr){float framerate = MediaPlayer->GetVideoTrackFrameRate(0,0);FTimespan FrameTime = FTimespan::FromSeconds(1 / (FMath::IsNearlyZero(framerate) ? -1 : framerate));if (MediaPlayer->GetTime() <= FrameTime){while ((MediaPlayer->GetTime() <= FrameTime) && !m_Pause);MediaPlayer->Pause();break;}}}FPlatformProcess::Sleep(0.01);}return 0;
}void RNGThread::PauseThread()
{m_Pause = true;
}void RNGThread::ContinueThread()
{m_Pause = false;// 启动线程if (m_semaphore){//Here is a FEvent signal "Trigger()" -> it will wake up the thread.m_semaphore->Trigger();}
}void RNGThread::Stop()
{// 设置停止的标志m_Kill = true; //Thread kill condition "while (!m_Kill){...}"m_Pause = false;// 触发一下线程,让其在下一次判断中退出if (m_semaphore){//We shall signal "Trigger" the FEvent (in case the Thread is sleeping it shall wake up!!)m_semaphore->Trigger();}
}//Use this method to kill the thread!!
void RNGThread::EnsureCompletion()
{// 停止线程Stop();// 等待线程运行结束if (Thread){Thread->WaitForCompletion();}if (this->MediaPlayer != nullptr){MediaPlayer = nullptr;}if (this->PXVideoComponent != nullptr){this->PXVideoComponent->UnregisterComponent();this->PXVideoComponent->DestroyComponent();this->PXVideoComponent = nullptr;}
}bool RNGThread::IsThreadPaused()
{return (bool)m_Pause;
}bool RNGThread::setMediaPlayer(UMediaPlayer* pMediaPlayer)
{this->MediaPlayer = pMediaPlayer;return true;
}
bool RNGThread::setVideoComponent(UPXVideoComponent* pPXVideoComponent)
{ this->PXVideoComponent = pPXVideoComponent;return true;
}
使用方法:
启动线程:
RNGThread * pThread = new RNGThread();
pThread->setMediaPlayer(MediaPlayer);关闭线程:
if (pThread != nullptr)
{pThread->EnsureCompletion();delete pThread;pThread = nullptr;
}
相关文章:
UE4 c++ Mediaplayer取消自动播放,运行时首帧为黑屏的问题
0,前言 工作需要使用C制作一个ue4的视频插件,其中一个功能是能够选择 运行时是否自动播放 视频的功能。 在实现时遇见了一个问题,取消自动播放之后,运行时首帧是没有取到的,在场景里面看是黑色的。就这个问题我想到了使…...
C语言-基础了解-17-C结构体
C结构体一、c结构体C 数组允许定义可存储相同类型数据项的变量,结构是 C 编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。结构体中的数据成员可以是基本数据类型(如 int、float、char 等),也可…...
Python爬虫实践:优志愿 院校列表
https://www.youzy.cn/tzy/search/colleges/collegeList获取目标网址等信息打开开发人员工具(F12),拿到调用接口的地址,以及接口请求参数等信息,如下curl https://uwf7de983aad7a717eb.youzy.cn/youzy.dms.basiclib.ap…...
Java框架学习 | MySQL和Maven笔记
1.MySQL提问式思考 为什么要有数据库?MySQL的优劣势?Java的优劣势? JavaMySQL开源具有大量的社区成员和丰富的资源免费/具有大量的社区成员和丰富的资源可扩展性多态、继承和接口等分区、复制和集群等方式扩展数据库的容量和性能安全性有许…...
C++入门教程||C++ 变量作用域||C++ 常量
C 变量作用域 作用域是程序的一个区域,一般来说有三个地方可以声明变量: 在函数或一个代码块内部声明的变量,称为局部变量。在函数参数的定义中声明的变量,称为形式参数。在所有函数外部声明的变量,称为全局变量。 我…...
想找工作,这一篇15w字数+的文章帮你解决
文章目录前言一 专业技能1. 熟悉GoLang语言1.1 Slice1.2 Map1.3 Channel1.4 Goroutine1.5 GMP调度1.6 垃圾回收机制1.7 其他知识点2. 掌握Web框架Gin和微服务框架Micro2.1 Gin框架2.2 Micro框架2.3 Viper2.4 Swagger2.5 Zap2.6 JWT3. 熟悉使用 MySQL 数据库3.1 索引3.2 事务3.3…...
Mac brew搭建php整套开发环境
Homebrew完整版,安装时间较长/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"精简版/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" speednginxBrew sear…...
111 e
全部 答对 答错 单选题 4.一个项目已经执行了两个多月,出乎意料的是,项目经理收到一封来自高级管理层的电子邮件,指出项目发起人正在请求变更项目开工会议的日期,项目经理未能执行哪项活动? A为项目管理计划制定基准…...
Cookie和Session
1. Cookie饼干 1.1 什么是Cookie? Cookie翻译过来就是饼干的意思Cookie是服务器通知客户端保存键值对的一种技术客户端有了Cookie后,每次请求都发送给服务器每个Cookie的大小不能超过4kb 1.2 如何创建Cookie BaseServlet 程序 package com.gdhd;impo…...
git上传下载
拉取: 先在电脑中创建一个文件夹用来存放要从码云上拉下来的项目并且用Git打开输入 git remote add origin + (想要下拉的项目的地址http/ssh)第一次拉取代码,输入码云的用户名(自己设置的个人地址名)和码云的账号密码 git pull origin master 拉取完成OK 上传: 进行 G…...
如何使用码匠连接 Oracle
目录 在码匠中集成 Oracle 在码匠中使用 Oracle 关于码匠 Oracle 是一种关系型数据库,可用于存储和管理大量结构化数据。Oracle 数据源支持多种操作系统,包括 Windows、Linux 和 Unix 等,同时也提供了各种工具和服务,例如 Orac…...
【Git】git常用命令集合
目录最常用的git命令git拉取代码git本地如何合并分支上传文件识别大小写开发分支(dev)上的代码达到上线的标准后,要合并到master分支当master代码改动了,需要更新开发分支(dev)上的代码git本地版本回退与远…...
基于 WebSocket、Spring Boot 教你实现“QQ聊天功能”的底层简易demo
目录 前言 一、分析 1.1、qq聊天功能分析 1.2、WebSocket介绍 1.2.1、什么是消息推送呢? 1.2.2、原理解析 1.2.3、报文格式 二、简易demo 2.1、后端实现 2.1.1、引入依赖 2.1.2、继承TextWebSocketHandler 2.1.3、实现 WebSocketConfigurer 接口 2.2、…...
13. 郭老师爱合并果子
1 题目描述 郭老师爱合并果子成绩20开启时间2021年10月8日 星期五 18:00折扣0.8折扣时间2021年10月26日 星期二 00:00允许迟交否关闭时间2021年12月1日 星期三 00:00 郭老师家有个果园,每年到了秋收的时候都会收获很多不同种类的果子。他决定把所有的果子合成一堆&…...
Method breakpoints may dramatically slow down debugging 解决方案
项目无法启动了 简单介绍一下事情的过程:昨天在进行代码调试的时候,代码部分处理完成之后,启动debug模式的热部署准备测试一下逻辑,结果左下角提示我热部署失败,需要重新启动Tomcat才能再次调试,所以只得重…...
ABAP ALV和OOALV设置单元格颜色,编辑
首先给大家分享一篇博客: REUSE_ALV_GRID_DISPLAY_LVC-可编辑单元格 文章目录单元格编辑单元格/行-颜色效果展示**需求:**我是想实现某个单元格可根据数据来判断是否是可以进行编辑的或要添加一个什么样的颜色. 我们需要用到下面的三个结构 ALV 控制: 单元格的类型表:LVC_T_ST…...
Java知识复习(十三)数据库和SQL
1、主键和外键 主键也叫主码。主键用于唯一标识一个元组,不能有重复,不允许为空。一个表只能有一个主键。外键也叫外码。外键用来和其他表建立联系用,外键是另一表的主键,外键是可以有重复的,可以是空值。一个表可以有…...
JVM虚拟机种类
1,Sun Classic VM: 1.现在此款虚拟机已经淘汰了,是历史上第一款商用的虚拟机。2.只能使用纯解释器的方式来执行Java代码。3.服役于 JDK 1.0、1.1、1.2;在 1.3、1.4 作为 HotSpot VM 的备选 VM;之后退出历史舞台;2,Sun Exact VM 1.…...
Linux操作系统学习(线程基础)
文章目录线程的基础概念线程控制内核LWP和线程ID的关系线程的基础概念 一般教材对线程描述是:是在进程内部运行的一个分支(执行流),属于进程的一部分,粒度要比进程更加细和轻量化 一个进程中是可能存在多个线程…...
YOLOv5源码逐行超详细注释与解读(1)——项目目录结构解析
前言 前面简单介绍了YOLOv5的网络结构和创新点(直通车:【YOLO系列】YOLOv5超详细解读(网络详解)) 在接下来我们会进入到YOLOv5更深一步的学习,首先从源码解读开始。 因为我是纯小白,刚开始下…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
