From 3f0df00dcef29ad1196cdcbb59553e59886d6b8f Mon Sep 17 00:00:00 2001 From: Sch <3516520171@qq.com> Date: Mon, 30 Oct 2023 16:35:50 +0800 Subject: [PATCH] Add Auto Projector Generator --- Cut5.sln | 78 ++++++++--- Source/Cut5/Interface/VideoInterface.cpp | 2 +- Source/Cut5/Utils/FFMPEGUtils.cpp | 121 +++++++++++++++--- Source/Cut5/Utils/Utils.cpp | 22 ++++ Source/Cut5/Utils/Utils.h | 7 + .../DragDropOperator/DragDropOperator.cpp | 48 +++---- 6 files changed, 215 insertions(+), 63 deletions(-) diff --git a/Cut5.sln b/Cut5.sln index 6b74737..8e4f79f 100644 --- a/Cut5.sln +++ b/Cut5.sln @@ -7,49 +7,85 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine", "Engine", "{233774 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Games", "Games", "{DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE5", "Intermediate\ProjectFiles\UE5.vcxproj", "{6EE39883-7339-3FB6-AD82-931FB137D37F}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cut5", "Intermediate\ProjectFiles\Cut5.vcxproj", "{B95E7D0E-DB45-3765-9058-E00EBBC4B157}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Cut5", "Intermediate\ProjectFiles\Cut5.vcxproj", "{AF5A253A-0F37-38CE-8998-45CA936C112B}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UE5", "Intermediate\ProjectFiles\UE5.vcxproj", "{C48D0E9D-C862-3EA3-96A7-752EE9D06362}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Visualizers", "Visualizers", "{1CCEC849-CC72-4C59-8C36-2F7C38706D4C}" ProjectSection(SolutionItems) = preProject - D:\UE\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis = D:\UE\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis + ..\..\Software\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis = ..\..\Software\UE_5.2\Engine\Extras\VisualStudioDebugging\Unreal.natvis EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + DebugGame Editor|Android = DebugGame Editor|Android + DebugGame Editor|IOS = DebugGame Editor|IOS DebugGame Editor|Win64 = DebugGame Editor|Win64 + DebugGame|Android = DebugGame|Android + DebugGame|IOS = DebugGame|IOS DebugGame|Win64 = DebugGame|Win64 + Development Editor|Android = Development Editor|Android + Development Editor|IOS = Development Editor|IOS Development Editor|Win64 = Development Editor|Win64 + Development|Android = Development|Android + Development|IOS = Development|IOS Development|Win64 = Development|Win64 + Shipping|Android = Shipping|Android + Shipping|IOS = Shipping|IOS Shipping|Win64 = Shipping|Win64 EndGlobalSection # UnrealVS Section GlobalSection(ddbf523f-7eb6-4887-bd51-85a714ff87eb) = preSolution - AvailablePlatforms=Win64 + AvailablePlatforms=Win64;IOS;Android EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6EE39883-7339-3FB6-AD82-931FB137D37F}.DebugGame Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {6EE39883-7339-3FB6-AD82-931FB137D37F}.DebugGame|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {6EE39883-7339-3FB6-AD82-931FB137D37F}.Development Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {6EE39883-7339-3FB6-AD82-931FB137D37F}.Development|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {6EE39883-7339-3FB6-AD82-931FB137D37F}.Shipping|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame Editor|Win64.ActiveCfg = DebugGame_Editor|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame Editor|Win64.Build.0 = DebugGame_Editor|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame|Win64.ActiveCfg = DebugGame|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.DebugGame|Win64.Build.0 = DebugGame|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Development Editor|Win64.ActiveCfg = Development_Editor|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Development Editor|Win64.Build.0 = Development_Editor|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Development|Win64.ActiveCfg = Development|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Development|Win64.Build.0 = Development|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Shipping|Win64.ActiveCfg = Shipping|x64 - {AF5A253A-0F37-38CE-8998-45CA936C112B}.Shipping|Win64.Build.0 = Shipping|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Android.ActiveCfg = Invalid|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|IOS.ActiveCfg = Invalid|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Win64.ActiveCfg = DebugGame_Editor|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame Editor|Win64.Build.0 = DebugGame_Editor|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Android.ActiveCfg = Android_DebugGame|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Android.Build.0 = Android_DebugGame|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|IOS.ActiveCfg = IOS_DebugGame|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|IOS.Build.0 = IOS_DebugGame|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Win64.ActiveCfg = DebugGame|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.DebugGame|Win64.Build.0 = DebugGame|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Android.ActiveCfg = Invalid|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|IOS.ActiveCfg = Invalid|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Win64.ActiveCfg = Development_Editor|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development Editor|Win64.Build.0 = Development_Editor|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Android.ActiveCfg = Android_Development|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Android.Build.0 = Android_Development|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|IOS.ActiveCfg = IOS_Development|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|IOS.Build.0 = IOS_Development|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Win64.ActiveCfg = Development|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Development|Win64.Build.0 = Development|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Android.ActiveCfg = Android_Shipping|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Android.Build.0 = Android_Shipping|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|IOS.ActiveCfg = IOS_Shipping|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|IOS.Build.0 = IOS_Shipping|Win64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Win64.ActiveCfg = Shipping|x64 + {B95E7D0E-DB45-3765-9058-E00EBBC4B157}.Shipping|Win64.Build.0 = Shipping|x64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame Editor|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame Editor|IOS.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame|IOS.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.DebugGame|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development Editor|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development Editor|IOS.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development Editor|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development|IOS.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Development|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Shipping|Android.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Shipping|IOS.ActiveCfg = BuiltWithUnrealBuildTool|Win64 + {C48D0E9D-C862-3EA3-96A7-752EE9D06362}.Shipping|Win64.ActiveCfg = BuiltWithUnrealBuildTool|Win64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {6EE39883-7339-3FB6-AD82-931FB137D37F} = {233774A8-CC9D-3FA9-86D1-90573E92B704} - {AF5A253A-0F37-38CE-8998-45CA936C112B} = {DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6} + {C48D0E9D-C862-3EA3-96A7-752EE9D06362} = {233774A8-CC9D-3FA9-86D1-90573E92B704} + {B95E7D0E-DB45-3765-9058-E00EBBC4B157} = {DE1F8B53-6C02-3C13-9101-A7C8D96F3FF6} EndGlobalSection EndGlobal diff --git a/Source/Cut5/Interface/VideoInterface.cpp b/Source/Cut5/Interface/VideoInterface.cpp index 7680ad0..7fd0cdf 100644 --- a/Source/Cut5/Interface/VideoInterface.cpp +++ b/Source/Cut5/Interface/VideoInterface.cpp @@ -234,7 +234,7 @@ uint32 FVideoThread::Run() } else { - FPlatformProcess::Sleep(0.1f); + FPlatformProcess::Sleep(0.01f); } } return 0; diff --git a/Source/Cut5/Utils/FFMPEGUtils.cpp b/Source/Cut5/Utils/FFMPEGUtils.cpp index 80c3a29..e695b56 100644 --- a/Source/Cut5/Utils/FFMPEGUtils.cpp +++ b/Source/Cut5/Utils/FFMPEGUtils.cpp @@ -670,6 +670,20 @@ void FFFMPEGUtils::GenerateProjectorEvent(const FClipData* ClipData) SCutTimeline* Timeline = FGlobalData::MainWidgetInterface->GetSelf()->GetCutTimeline(); FTrackData* ProjectorTrackData = Timeline->GetTrackDataByType(ETrackType::ProjectorTrack); + + + for (int32 i = ProjectorTrackData->ClipData.Num() - 1; i > 0; i--) + { + if (ProjectorTrackData->ClipData[i].ClipStartFrame >= ClipData->ClipStartFrame + || ProjectorTrackData->ClipData[i].ClipEndFrame <= ClipData->ClipEndFrame) + { + ProjectorTrackData->ClipData.RemoveAt(i); + } + } + + + struct ProjectorClipInfo{ int32 Frame; bool bStart; }; + TArray ClipInfos; if (ClipData->ClipType == ETrackType::VideoTrack && ClipData->ResourcePropertyDataPtr) { @@ -679,11 +693,13 @@ void FFFMPEGUtils::GenerateProjectorEvent(const FClipData* ClipData) return; - + AVPacket* Packet = av_packet_alloc(); + AVFrame* Frame = av_frame_alloc(); + while (1) { - AVPacket* Packet = av_packet_alloc(); - AVFrame* Frame = av_frame_alloc(); + int32 Response = -1; + if (av_read_frame(Info.Context, Packet) < 0) { @@ -693,18 +709,21 @@ void FFFMPEGUtils::GenerateProjectorEvent(const FClipData* ClipData) } } - if (int32 Response = avcodec_send_packet(Info.VideoCodecContext, Packet) < 0) + if ((Response = avcodec_send_packet(Info.VideoCodecContext, Packet)) < 0) { - check(false); + }; - if (int32 Response = avcodec_receive_frame(Info.VideoCodecContext, Frame) >= 0) + if ((Response = avcodec_receive_frame(Info.VideoCodecContext, Frame)) >= 0) { if (Frame->width == 0 || Frame->height == 0) continue; + + double RealTime = Frame->pts * av_q2d(Info.Context->streams[Info.VideoStream]->time_base); + int32 CurrentFrame = RealTime * FGlobalData::GlobalFPS; SwsContext* SwsConvert = sws_getContext(Frame->width, Frame->height, Info.VideoCodecContext->pix_fmt, - 128, 72, AV_PIX_FMT_RGBA, SWS_BICUBIC, nullptr, nullptr, nullptr); + 128, 72, AV_PIX_FMT_RGBA, SWS_BILINEAR, nullptr, nullptr, nullptr); uint8* RawData = new uint8[128 * 72 * 4]; uint8* Dest[4] = {RawData, nullptr, nullptr, nullptr}; @@ -713,28 +732,96 @@ void FFFMPEGUtils::GenerateProjectorEvent(const FClipData* ClipData) 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; + uint8 Gray = RawData[i * 4] * 0.299 + RawData[i * 4 + 1] * 0.587 + RawData[i * 4 + 2] * 0.114; + if (Gray < 10) + { + GrayCount++; + } + } + float AvgGray = GrayCount / (128 * 72.0f); + if (AvgGray > 0.988) + { + ClipInfos.Add({CurrentFrame, true}); + } + else + { + ClipInfos.Add({CurrentFrame, false}); } - - - av_packet_free(&Packet); - av_frame_free(&Frame); continue; } - - + if (Response == AVERROR(EAGAIN)) + { + continue; + } av_packet_free(&Packet); av_frame_free(&Frame); break; } + const int32 MaxFrame = av_rescale_q(Info.Context->streams[Info.VideoStream]->duration, Info.Context->streams[Info.VideoStream]->time_base, AVRational{1, AV_TIME_BASE}) / AV_TIME_BASE * FGlobalData::GlobalFPS; + + + if (ClipInfos.Num() == 0) + { + return; + } + int32 StartFrame = 0; + int32 CurrentClipIndex = 0; + bool CurrentProjectorStart = ClipInfos[0].bStart; + for (int32 i = 0; i < ClipInfos.Num(); i++) + { + if (i + 1 >= ClipInfos.Num()) + { + CurrentProjectorStart = !ClipInfos[CurrentClipIndex].bStart; + + FClipData NewClipData; + NewClipData.ClipGuid = FGuid::NewGuid(); + NewClipData.BindTrackGuid = ProjectorTrackData->DeviceTrack.Guid; + NewClipData.ClipType = ETrackType::ProjectorTrack; + NewClipData.PresetType = CurrentProjectorStart ? EPresetType::EnableProjector : EPresetType::DisableProjector; + + NewClipData.ClipStartFrame = StartFrame + ClipData->ClipStartFrame; + NewClipData.ClipEndFrame = ClipData->ClipEndFrame; + ProjectorTrackData->ClipData.Add(NewClipData); + + break; + } + + if (StartFrame == 0) + { + StartFrame = ClipInfos[i].Frame; + CurrentClipIndex = i; + } + if (CurrentProjectorStart == ClipInfos[i].bStart) + { + continue; + } + else + { + CurrentProjectorStart = !CurrentProjectorStart; + + FClipData NewClipData; + NewClipData.ClipGuid = FGuid::NewGuid(); + NewClipData.BindTrackGuid = ProjectorTrackData->DeviceTrack.Guid; + NewClipData.ClipType = ETrackType::ProjectorTrack; + NewClipData.PresetType = CurrentProjectorStart ? EPresetType::EnableProjector : EPresetType::DisableProjector; + + NewClipData.ClipStartFrame = StartFrame + ClipData->ClipStartFrame; + NewClipData.ClipEndFrame = ClipInfos[i].Frame + ClipData->ClipStartFrame; + ProjectorTrackData->ClipData.Add(NewClipData); + + StartFrame = 0; + continue;; + } + } + Timeline->RenderGroup(); } - + + + } diff --git a/Source/Cut5/Utils/Utils.cpp b/Source/Cut5/Utils/Utils.cpp index 0946c63..a09fc75 100644 --- a/Source/Cut5/Utils/Utils.cpp +++ b/Source/Cut5/Utils/Utils.cpp @@ -4,6 +4,7 @@ #include "FFMPEGUtils.h" #include "FFMPEGUtils.h" #include "Cut5/Widgets/DefineGlobal.h" +#include "Cut5/Widgets/MicroWidgets/SProcessing.h" #include "Kismet/KismetStringLibrary.h" extern "C" { @@ -1029,6 +1030,27 @@ void FUtils::AddTips(TSharedPtr Widget) GEngine->GameViewport->AddViewportWidgetContent(Widget.ToSharedRef()); } +void FUtils::StartProcessing(const FString& Name, float MaxPercent) +{ + SAssignNew(ProcessingWidget, SProcessing).MaxPercent(MaxPercent); +} + +void FUtils::UpdateProcessing(float Percent) +{ + if (ProcessingWidget.IsValid()) + { + StaticCastSharedPtr(ProcessingWidget)->CurrentPercent = Percent; + } +} + +void FUtils::EndProcessing() +{ + if (ProcessingWidget.IsValid()) + { + GEngine->GameViewport->RemoveViewportWidgetContent(ProcessingWidget.ToSharedRef()); + } +} + FSaveModifier::FSaveModifier(const FString& FullSavedPath) { diff --git a/Source/Cut5/Utils/Utils.h b/Source/Cut5/Utils/Utils.h index 4eaecf1..09bcd1f 100644 --- a/Source/Cut5/Utils/Utils.h +++ b/Source/Cut5/Utils/Utils.h @@ -96,6 +96,13 @@ public: static void AddTips(TSharedPtr Widget); + + + static void StartProcessing(const FString& Name, float MaxPercent); + static void UpdateProcessing(float Percent); + static void EndProcessing(); + + inline static TSharedPtr ProcessingWidget; }; template diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp index dac1baa..77f7865 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp @@ -122,30 +122,30 @@ void DragDropOperator::CloseCursorDecorator() void DragDropOperator::OnUpdateVideoTrack(const FClipData& VideoClipData) { - SCutTimeline* Timeline = SavedMainInterface->GetCutTimeline(); - FTrackData* ProjectorTrack = Timeline->GetTrackDataByType(ETrackType::ProjectorTrack); - - if (true) - { - ProjectorTrack->ClipData.Empty(); - FClipData NewClipData; - NewClipData.ClipStartFrame = VideoClipData.ClipStartFrame; - NewClipData.ClipEndFrame = VideoClipData.ClipEndFrame; - NewClipData.ClipGuid = FGuid::NewGuid(); - NewClipData.ClipType = ETrackType::ProjectorTrack; - NewClipData.PresetType = EPresetType::EnableProjector; - NewClipData.BindTrackGuid = ProjectorTrack->DeviceTrack.Guid; - - FPresetsCustomData CustomPresetData; - CustomPresetData.PresetCustomType = FPresetsCustomData::EPresetCustomType::None; - - NewClipData.PresetsCustomData = CustomPresetData; - - - - ProjectorTrack->ClipData.Add(NewClipData); - Timeline->RenderGroup(); - } + // SCutTimeline* Timeline = SavedMainInterface->GetCutTimeline(); + // FTrackData* ProjectorTrack = Timeline->GetTrackDataByType(ETrackType::ProjectorTrack); + // + // if (true) + // { + // ProjectorTrack->ClipData.Empty(); + // FClipData NewClipData; + // NewClipData.ClipStartFrame = VideoClipData.ClipStartFrame; + // NewClipData.ClipEndFrame = VideoClipData.ClipEndFrame; + // NewClipData.ClipGuid = FGuid::NewGuid(); + // NewClipData.ClipType = ETrackType::ProjectorTrack; + // NewClipData.PresetType = EPresetType::EnableProjector; + // NewClipData.BindTrackGuid = ProjectorTrack->DeviceTrack.Guid; + // + // FPresetsCustomData CustomPresetData; + // CustomPresetData.PresetCustomType = FPresetsCustomData::EPresetCustomType::None; + // + // NewClipData.PresetsCustomData = CustomPresetData; + // + // + // + // ProjectorTrack->ClipData.Add(NewClipData); + // Timeline->RenderGroup(); + // } } void DragDropOperator::OnUpdateProjectorTrack(const FClipData& ProjectorClipData)