Merge remote-tracking branch 'remotes/RedstoneRemote/master'
This commit is contained in:
commit
bb79be6d54
@ -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;
|
||||||
|
@ -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;
|
|
||||||
};
|
};
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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 =
|
||||||
{
|
{
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user