Merge remote-tracking branch 'remotes/RedstoneRemote/master'

This commit is contained in:
Sch 2023-11-01 16:09:21 +08:00
commit bb79be6d54
8 changed files with 126 additions and 27 deletions

View File

@ -2,8 +2,6 @@
#include "CutMainWidgetInterface.h" #include "CutMainWidgetInterface.h"
#include "Cut5/Utils/FFMPEGUtils.h" #include "Cut5/Utils/FFMPEGUtils.h"
#include "Utils/SchCounter.h"
#include "Utils/SchUtilsLib.h"
bool FVideoThread::Init() bool FVideoThread::Init()
{ {
@ -26,9 +24,6 @@ uint32 FVideoThread::Run()
{ {
if (CurrentSeekingFrame != -1) if (CurrentSeekingFrame != -1)
{ {
TSharedPtr<FSchTime> SchTime = SchUtilsLib::CreateTimeCounter();
int32 VideoFPS = NewPropertyData.VideoCodecContext->time_base.den; int32 VideoFPS = NewPropertyData.VideoCodecContext->time_base.den;
if (VideoFPS < FGlobalData::GlobalFPS) if (VideoFPS < FGlobalData::GlobalFPS)
{ {
@ -48,7 +43,6 @@ uint32 FVideoThread::Run()
if (CurrentSeekingFrame - LastSeekFrame > 1 || CurrentSeekingFrame - LastSeekFrame < 0 || LastSeekFrame == -1) if (CurrentSeekingFrame - LastSeekFrame > 1 || CurrentSeekingFrame - LastSeekFrame < 0 || LastSeekFrame == -1)
{ {
av_seek_frame(NewPropertyData.Context, NewPropertyData.VideoStream, Timestamp, AVSEEK_FLAG_BACKWARD); av_seek_frame(NewPropertyData.Context, NewPropertyData.VideoStream, Timestamp, AVSEEK_FLAG_BACKWARD);
SchUtilsLib::PrintImmediately(TEXT("Seeked"));
} }
@ -68,17 +62,14 @@ uint32 FVideoThread::Run()
AllocatedFrame = LastFrame; AllocatedFrame = LastFrame;
bNeedReadFrame = false; bNeedReadFrame = false;
} }
} }
SchTime->PrintCurrentTime(TEXT("点1"));
const TSharedPtr<FSchCounter> SchCounter = SchUtilsLib::CreateCounter();
bool IsFailed = false; bool IsFailed = false;
if (bNeedReadFrame) if (bNeedReadFrame)
{ {
while (av_read_frame(NewPropertyData.Context, Packet) >= 0) while (av_read_frame(NewPropertyData.Context, Packet) >= 0)
{ {
SchCounter->AddCount(1);
if (Packet->stream_index == NewPropertyData.VideoStream) if (Packet->stream_index == NewPropertyData.VideoStream)
{ {
int32 Response = avcodec_send_packet(NewPropertyData.VideoCodecContext, Packet); int32 Response = avcodec_send_packet(NewPropertyData.VideoCodecContext, Packet);
@ -106,14 +97,12 @@ uint32 FVideoThread::Run()
} }
} }
av_packet_unref(Packet); av_packet_unref(Packet);
SchCounter->PrintCount("AV_READ_FRAME", true);
if (IsFailed == true) if (IsFailed == true)
{ {
CurrentSeekingFrame = -1; CurrentSeekingFrame = -1;
continue;; continue;;
} }
SchTime->PrintCurrentTime(TEXT("点2"));
uint8* RawData = nullptr; uint8* RawData = nullptr;
@ -209,13 +198,10 @@ uint32 FVideoThread::Run()
sws_freeContext(SwsCtx); sws_freeContext(SwsCtx);
} }
SchTime->PrintCurrentTime(TEXT("点3"));
int32 X = AllocatedFrame->width; int32 X = AllocatedFrame->width;
int32 Y = AllocatedFrame->height; int32 Y = AllocatedFrame->height;
const float NewTime = 1 / ((FDateTime::Now().GetMillisecond() * 0.001f) - LastTime);
GEngine->AddOnScreenDebugMessage(0, 0.1f, FColor::Red, FString::SanitizeFloat(NewTime));
LastTime = FDateTime::Now().GetMillisecond() * 0.001f;
AsyncTask(ENamedThreads::GameThread, [this, X, Y, RawData, AllocatedFrame]() AsyncTask(ENamedThreads::GameThread, [this, X, Y, RawData, AllocatedFrame]()
{ {
if (ClipData.ClipType == ETrackType::VideoTrack) if (ClipData.ClipType == ETrackType::VideoTrack)
@ -236,8 +222,6 @@ uint32 FVideoThread::Run()
FMemory::Memcpy(ColorArray.GetData(), RawData, FGlobalData::LightArrayX * FGlobalData::LightArrayY * 4); FMemory::Memcpy(ColorArray.GetData(), RawData, FGlobalData::LightArrayX * FGlobalData::LightArrayY * 4);
MainInterface->OnUpdateLightBar(ColorArray); MainInterface->OnUpdateLightBar(ColorArray);
} }
}); });
// }); // });
@ -250,7 +234,7 @@ uint32 FVideoThread::Run()
} }
else else
{ {
FPlatformProcess::Sleep(0.01f); FPlatformProcess::Sleep(0.1f);
} }
} }
return 0; return 0;

View File

@ -20,6 +20,4 @@ public:
std::atomic<int32> LastSeekFrame = -1; std::atomic<int32> LastSeekFrame = -1;
AVFrame* LastFrame = nullptr; AVFrame* LastFrame = nullptr;
bool IsStop = false; bool IsStop = false;
float LastTime = 0.0f;
}; };

View File

@ -32,10 +32,8 @@ uint32 FVideoThumbnailThread::Run()
{ {
if (i < BrushCount && ClipData->ResourcePropertyDataPtr && ClipData->ResourcePropertyDataPtr->Context && ClipData->ResourcePropertyDataPtr->VideoStream != -1) if (i < BrushCount && ClipData->ResourcePropertyDataPtr && ClipData->ResourcePropertyDataPtr->Context && ClipData->ResourcePropertyDataPtr->VideoStream != -1)
{ {
const int32 CurrentFrame = BrushCount - (BrushCount - i);
const int32 CurrentInterval = BrushCount - (BrushCount - i); const int64 Timestamp = av_rescale_q(CurrentFrame / FGlobalData::GlobalFPS * AV_TIME_BASE, AVRational{1, AV_TIME_BASE}, Info.Context->streams[Info.VideoStream]->time_base);
const int32 CurrentFrame = (Info.Context->duration / AV_TIME_BASE * Info.VideoCodecContext->time_base.den) / BrushCount * CurrentInterval;
const int64 Timestamp = av_rescale_q(CurrentFrame * AV_TIME_BASE, AVRational{1, AV_TIME_BASE}, Info.Context->streams[Info.VideoStream]->time_base);
av_seek_frame(Info.Context, Info.VideoStream, Timestamp, AVSEEK_FLAG_BACKWARD); av_seek_frame(Info.Context, Info.VideoStream, Timestamp, AVSEEK_FLAG_BACKWARD);
AVPacket Packet; AVPacket Packet;
av_init_packet(&Packet); av_init_packet(&Packet);

View File

@ -1,5 +1,6 @@
#include "FFMPEGUtils.h" #include "FFMPEGUtils.h"
#include "FFMPEGUtils.h" #include "FFMPEGUtils.h"
#include "FFMPEGUtils.h"
@ -7,6 +8,8 @@
#include "ImageUtils.h" #include "ImageUtils.h"
#include "Utils.h" #include "Utils.h"
#include "Cut5/FFT/kiss_fft.h" #include "Cut5/FFT/kiss_fft.h"
#include "Cut5/Interface/CutMainWidgetInterface.h"
#include "Cut5/Widgets/SCutMainWindow.h"
#include "Engine/Canvas.h" #include "Engine/Canvas.h"
#include "Engine/TextureRenderTarget2D.h" #include "Engine/TextureRenderTarget2D.h"
#include "Kismet/KismetRenderingLibrary.h" #include "Kismet/KismetRenderingLibrary.h"
@ -661,6 +664,79 @@ TArray<FSlateBrush> FFFMPEGUtils::GetAudioBrush(FClipData* ClipData)
return {}; return {};
} }
void FFFMPEGUtils::GenerateProjectorEvent(const FClipData* ClipData)
{
// Get Projector Track Data
SCutTimeline* Timeline = FGlobalData::MainWidgetInterface->GetSelf()->GetCutTimeline();
FTrackData* ProjectorTrackData = Timeline->GetTrackDataByType(ETrackType::ProjectorTrack);
if (ClipData->ClipType == ETrackType::VideoTrack
&& ClipData->ResourcePropertyDataPtr)
{
FTimelinePropertyData Info;
LoadContextPure(ToFullPath(ClipData->MoviePath), &Info);
if (Info.Context == nullptr)
return;
while (1)
{
AVPacket* Packet = av_packet_alloc();
AVFrame* Frame = av_frame_alloc();
if (av_read_frame(Info.Context, Packet) < 0)
{
if (av_read_frame(Info.Context, Packet) < 0)
{
break;
}
}
if (int32 Response = avcodec_send_packet(Info.VideoCodecContext, Packet) < 0)
{
check(false);
};
if (int32 Response = avcodec_receive_frame(Info.VideoCodecContext, Frame) >= 0)
{
if (Frame->width == 0 || Frame->height == 0)
continue;
SwsContext* SwsConvert =
sws_getContext(Frame->width, Frame->height, Info.VideoCodecContext->pix_fmt,
128, 72, AV_PIX_FMT_RGBA, SWS_BICUBIC, nullptr, nullptr, nullptr);
uint8* RawData = new uint8[128 * 72 * 4];
uint8* Dest[4] = {RawData, nullptr, nullptr, nullptr};
constexpr int32 DestStride[4] = {128 * 4, 0, 0, 0};
sws_scale(SwsConvert, Frame->data, Frame->linesize, 0, Frame->height, Dest, DestStride);
sws_freeContext(SwsConvert);
float RawDataFloat = RawData[0];
int32 GrayCount = 0;
for (int32 i = 0; i < 128 * 72; i++)
{
float Gray = RawData[i * 4 + 0] * 0.299 + RawData[i * 4 + 1] * 0.587 + RawData[i * 4 + 2] * 0.114;
}
av_packet_free(&Packet);
av_frame_free(&Frame);
continue;
}
av_packet_free(&Packet);
av_frame_free(&Frame);
break;
}
}
}
TArray<TArray<FColor>> FFFMPEGUtils::GetVideoFrameLightArray(FString VideoPath, int32 X, int32 Y) TArray<TArray<FColor>> FFFMPEGUtils::GetVideoFrameLightArray(FString VideoPath, int32 X, int32 Y)
{ {
@ -704,4 +780,4 @@ TArray<TArray<FColor>> FFFMPEGUtils::GetVideoFrameLightArray(FString VideoPath,
} }
} }
return Colors; return Colors;
} }

View File

@ -24,4 +24,6 @@ struct FFFMPEGUtils
static TArray<FSlateBrush> GetMovieBrush(struct FClipData* ClipData, bool Regenerate = false); static TArray<FSlateBrush> GetMovieBrush(struct FClipData* ClipData, bool Regenerate = false);
static TArray<FSlateBrush> GetAudioBrush(struct FClipData* ClipData); static TArray<FSlateBrush> GetAudioBrush(struct FClipData* ClipData);
static void GenerateProjectorEvent(const FClipData* ClipData);
}; };

View File

@ -36,8 +36,8 @@ public:
inline static FString ExportPath = ""; inline static FString ExportPath = "";
inline static bool Export_OnlyXML = false; inline static bool Export_OnlyXML = false;
inline static TArray<FString> ExportErrorString; inline static TArray<FString> ExportErrorString;
inline static class ICutMainWidgetInterface* MainWidgetInterface = nullptr;
inline static TArray<FColor> Colors = inline static TArray<FColor> Colors =
{ {

View File

@ -47,6 +47,9 @@ BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SCutMainWindow::Construct(const FArguments& InArgs) void SCutMainWindow::Construct(const FArguments& InArgs)
{ {
FGlobalData::MainWidgetInterface = this;
SAssignNew(CutTimeline, SCutTimeline).MainWidgetInterface(this); SAssignNew(CutTimeline, SCutTimeline).MainWidgetInterface(this);
SAssignNew(StatePanel, SStatePanel); SAssignNew(StatePanel, SStatePanel);
SAssignNew(CustomPanel, SCustomPanel); SAssignNew(CustomPanel, SCustomPanel);

View File

@ -1,5 +1,6 @@
#include "ClipProxy.h" #include "ClipProxy.h"
#include "Cut5/Utils/FFMPEGUtils.h"
#include "Cut5/Utils/Utils.h" #include "Cut5/Utils/Utils.h"
#include "Cut5/Widgets/SCutMainWindow.h" #include "Cut5/Widgets/SCutMainWindow.h"
#include "Cut5/Widgets/SCutTimeline.h" #include "Cut5/Widgets/SCutTimeline.h"
@ -653,6 +654,43 @@ TSharedPtr<SWidget> FClipProxy::GetPropertiesWidget()
] ]
]; ];
} }
if (ClipData->ClipType == ETrackType::VideoTrack)
{
VerticalBox->AddSlot()
.SizeParam(FStretch(1.0))
[
SNew(SSpacer)
];
VerticalBox->AddSlot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Bottom)
.Padding(0, 0, 0, 24)
[
SNew(SBox).HeightOverride(40).WidthOverride(144)
[
SNew(SOverlay)
+ SOverlay::Slot()
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
[
SNew(SButton)
.OnClicked_Lambda([this]()
{
FFFMPEGUtils::GenerateProjectorEvent(ClipData);
return FReply::Handled();
})
]
+ SOverlay::Slot()
[
SNew(STextBlock)
.Visibility(EVisibility::HitTestInvisible)
.Text(FText::FromString((TEXT("生成投影仪事件"))))
.Font(NormalText.Font)
.Justification(ETextJustify::Center)
]
]
];
}