创建一个MediaPlayer的材质,转换成画刷,,然后给SImage,在Tick更新画面,就是这样,下面是具体代码,
#pragma once
#include "CoreMinimal.h"
#include "UObject/WeakObjectPtr.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/SCompoundWidget.h"
class UAudioComponent;
class UMaterial;
class UMaterialExpressionTextureSample;
class UMediaPlayer;
class UMediaSoundWave;
class UMediaTexture;
struct FSlateBrush;
enum class EMediaEvent;
/**
*
*/
class USERINTERFACE_API SVideoPlay : public SCompoundWidget
{
public:
DECLARE_DELEGATE(FCloseVieoPlay)
SLATE_BEGIN_ARGS(SVideoPlay)
{}
SLATE_EVENT(FCloseVieoPlay,OnCloseVideoPlay)
SLATE_ARGUMENT(FString, VideoURL)
SLATE_END_ARGS()
SVideoPlay();
~SVideoPlay();
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
/** The material that wraps the video texture for display in an SImage. */
UMaterial* Material;
/** The Slate brush that renders the material. */
TSharedPtr<FSlateBrush> MaterialBrush;
/** The media player whose video texture is shown in this widget. */
UMediaPlayer* MediaPlayer;
UMediaTexture* DefaultTexture;
TWeakObjectPtr<UMediaTexture> CurrentTexture;
/** The video texture sampler in the wrapper material. */
UMaterialExpressionTextureSample* TextureSampler;
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
void UpdateMaterial();
FString VideoURL;
FReply CloseVideoPlay();
FCloseVieoPlay OnCloseVideoPlay;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "UserInterface.h"
#include "SVideoPlay.h"
#include "Styling/SlateBrush.h"
#include "Widgets/Images/SImage.h"
#include "IMediaOutput.h"
#include "IMediaPlayer.h"
#include "Materials/Material.h"
#include "Materials/MaterialExpressionTextureSample.h"
#include "MediaPlayer.h"
#include "MediaTexture.h"
#include "Engine.h"
#include "SlateOptMacros.h"
SVideoPlay::SVideoPlay() :
CurrentTexture(nullptr)
, DefaultTexture(nullptr)
, Material(nullptr)
, MediaPlayer(nullptr)
{
//DefaultSoundWave = NewObject<UMediaSoundWave>(GetTransientPackage(), NAME_None, RF_Transient | RF_Public);
//if (DefaultSoundWave != nullptr)
//{
// DefaultSoundWave->AddToRoot();
// AudioComponent = FAudioDevice::CreateComponent(DefaultSoundWave);
// if (AudioComponent != nullptr)
// {
// AudioComponent->SetVolumeMultiplier(1.0f);
// AudioComponent->SetPitchMultiplier(1.0f);
// AudioComponent->bAllowSpatialization = false;
// AudioComponent->bIsUISound = true;
// AudioComponent->bAutoDestroy = false;
// AudioComponent->AddToRoot();
// }
//}
}
SVideoPlay::~SVideoPlay()
{
if (MediaPlayer != nullptr)
{
MediaPlayer->OnMediaEvent().RemoveAll(this);
// remove default sinks from native player
//FMediaPlayerBase& Player = MediaPlayer->GetBasePlayer();
/*if (MediaPlayer->GetSoundWave() == nullptr)
{
Player.SetAudioSink(nullptr);
}*/
/*if (MediaPlayer->GetVideoTexture() == nullptr)
{
Player.SetVideoSink(nullptr);
}*/
}
// release default sinks
/*if (AudioComponent != nullptr)
{
AudioComponent->Stop();
AudioComponent->RemoveFromRoot();
}*/
if (Material != nullptr)
{
Material->RemoveFromRoot();
}
/*if (DefaultSoundWave != nullptr)
{
DefaultSoundWave->RemoveFromRoot();
}*/
if (DefaultTexture != nullptr)
{
DefaultTexture->RemoveFromRoot();
}
}
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SVideoPlay::Construct(const FArguments& InArgs)
{
OnCloseVideoPlay = InArgs._OnCloseVideoPlay;
VideoURL = InArgs._VideoURL;
MediaPlayer = LoadObject<UMediaPlayer>(NULL, TEXT("/Game/Common/Video/MediaPlayer.MediaPlayer"), NULL, LOAD_None, NULL);
Material = NewObject<UMaterial>(GetTransientPackage(), NAME_None, RF_Transient | RF_Public);
if (Material != nullptr)
{
TextureSampler = NewObject<UMaterialExpressionTextureSample>(Material);
{
TextureSampler->SamplerType = SAMPLERTYPE_Color;
}
FExpressionOutput& Output = TextureSampler->GetOutputs()[0];
FExpressionInput& Input = Material->EmissiveColor;
{
Input.Expression = TextureSampler;
Input.Mask = Output.Mask;
Input.MaskR = Output.MaskR;
Input.MaskG = Output.MaskG;
Input.MaskB = Output.MaskB;
Input.MaskA = Output.MaskA;
}
Material->Expressions.Add(TextureSampler);
Material->MaterialDomain = EMaterialDomain::MD_UI;
Material->AddToRoot();
}
create Slate brush
MaterialBrush = MakeShareable(new FSlateBrush());
{
MaterialBrush->SetResourceObject(Material);
}
UpdateMaterial();
ChildSlot
[
SNew(SBox)
.WidthOverride(1000)
.HeightOverride(1000)
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.ButtonStyle(FPanelStyle::Get(), "Button_alpha")
.OnClicked(this, &SVideoPlay::CloseVideoPlay)
.HAlign(HAlign_Right)
.VAlign(VAlign_Center)
.Content()
[
SNew(SImage)
.Image(FPanelStyle::GetBrush("scheme_close"))
]
]
+SVerticalBox::Slot()
[
SNew(SImage)
.Image(MaterialBrush.Get())
]
]
];
//bool IsPlay = MediaPlayer->OpenUrl(TEXT("http://127.0.0.1:8080/Marionette_RL.mp4"));
bool IsPlay = MediaPlayer->OpenUrl(VideoURL);
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SVideoPlay::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
UpdateMaterial();
//UpdateSoundWave();
}
void SVideoPlay::UpdateMaterial()
{
UMediaTexture* Texture = MediaPlayer->GetVideoTexture();
//if (Texture == nullptr)
//{
// // create default texture if needed
// if (DefaultTexture == nullptr)
// {
// DefaultTexture = NewObject<UMediaTexture>(GetTransientPackage(), NAME_None, RF_Transient | RF_Public);
// if (DefaultTexture != nullptr)
// {
// DefaultTexture->UpdateResource();
// DefaultTexture->AddToRoot();
// }
// }
// // set default texture as output sink
// if (DefaultTexture != nullptr)
// {
// MediaPlayer->GetBasePlayer().SetVideoSink(DefaultTexture);
// }
// Texture = DefaultTexture;
//}
// assign new texture to material
if (Texture != CurrentTexture)
{
TextureSampler->Texture = Texture;
Material->PostEditChange();
CurrentTexture = Texture;
}
// resize current texture
if (CurrentTexture != nullptr)
{
MaterialBrush->ImageSize.X = CurrentTexture->GetSurfaceWidth();
MaterialBrush->ImageSize.Y = CurrentTexture->GetSurfaceHeight();
}
else
{
MaterialBrush->ImageSize = FVector2D::ZeroVector;
}
}
FReply SVideoPlay::CloseVideoPlay()
{
if (OnCloseVideoPlay.IsBound())
{
OnCloseVideoPlay.Execute();
}
//OnCloseVideoPlay.ExecuteIfBound();
return FReply::Handled();
}
音频部分注释掉了,如果需要,自己完善吧。