左右声道,视频截图,进度条设计
This commit is contained in:
parent
be067f98cc
commit
1be1ffc4cd
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <portaudio.h>
|
#include <portaudio.h>
|
||||||
|
|
||||||
|
#include "Cut5/Widgets/DefineGlobal.h"
|
||||||
|
|
||||||
FCriticalSection Mutex;
|
FCriticalSection Mutex;
|
||||||
|
|
||||||
FSoundThread::FSoundThread(int32 OutputChannel, int32 SampleRate) : FRunnable()
|
FSoundThread::FSoundThread(int32 OutputChannel, int32 SampleRate) : FRunnable()
|
||||||
@ -33,7 +35,7 @@ uint32 FSoundThread::Run()
|
|||||||
{
|
{
|
||||||
TArray<uint8, TInlineAllocator<11760>> ResultData;
|
TArray<uint8, TInlineAllocator<11760>> ResultData;
|
||||||
const int32 FrameLength = Audio.Num();
|
const int32 FrameLength = Audio.Num();
|
||||||
for (int32 i = SeekedFrame * (SampleRate / 27) * 4 * 2; i < (SeekedFrame + 1) * (SampleRate / 27) * 4 * 2 && i < FrameLength; ++i)
|
for (int32 i = SeekedFrame * (SampleRate / 26) * 4 * 2; i < (SeekedFrame + 1) * (SampleRate / 26) * 4 * 2 && i < FrameLength; ++i)
|
||||||
{
|
{
|
||||||
ResultData.Add(Audio[i]);
|
ResultData.Add(Audio[i]);
|
||||||
}
|
}
|
||||||
@ -46,14 +48,55 @@ uint32 FSoundThread::Run()
|
|||||||
|
|
||||||
void FSoundThread::Stop()
|
void FSoundThread::Stop()
|
||||||
{
|
{
|
||||||
|
bStoped = true;
|
||||||
FRunnable::Stop();
|
FRunnable::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool FSoundThread::CopyAudio(const uint8* Data, int32 Size)
|
bool FSoundThread::CopyAudio(const uint8* Data, int32 Size, ESoundSolveType SolveType)
|
||||||
{
|
{
|
||||||
Audio = TArray<uint8>(Data, Size);
|
Audio = TArray<uint8>(Data, Size);
|
||||||
|
switch (SolveType)
|
||||||
|
{
|
||||||
|
case ESoundSolveType::None:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ESoundSolveType::OnlyLeft:
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Size / 4; i++)
|
||||||
|
{
|
||||||
|
if (i % 2 == 1)
|
||||||
|
{
|
||||||
|
Audio[i * 4] = 0;
|
||||||
|
Audio[i * 4 + 1] = 0;
|
||||||
|
Audio[i * 4 + 2] = 0;
|
||||||
|
Audio[i * 4 + 3] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ESoundSolveType::OnlyRight:
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < Size / 4; i++)
|
||||||
|
{
|
||||||
|
if (i % 2 == 0)
|
||||||
|
{
|
||||||
|
Audio[i * 4] = 0;
|
||||||
|
Audio[i * 4 + 1] = 0;
|
||||||
|
Audio[i * 4 + 2] = 0;
|
||||||
|
Audio[i * 4 + 3] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Cut5/Widgets/DefineGlobal.h"
|
||||||
|
|
||||||
extern "C"{
|
extern "C"{
|
||||||
#include <portaudio.h>
|
#include <portaudio.h>
|
||||||
}
|
}
|
||||||
@ -20,7 +22,7 @@ public:
|
|||||||
|
|
||||||
bool bStoped = false;
|
bool bStoped = false;
|
||||||
|
|
||||||
bool CopyAudio(const uint8* Data, int32 Size);
|
bool CopyAudio(const uint8* Data, int32 Size, ESoundSolveType SolveType);
|
||||||
bool SeekFrame(int32 SeekFrameLoc);
|
bool SeekFrame(int32 SeekFrameLoc);
|
||||||
int32 SeekedFrame = 0;
|
int32 SeekedFrame = 0;
|
||||||
TArray<uint8> Audio;
|
TArray<uint8> Audio;
|
||||||
|
@ -237,18 +237,36 @@ bool FFFMPEGUtils::ExportImage(UTexture2D* Texture2D, const FString& Path)
|
|||||||
return FFileHelper::SaveArrayToFile(ImgData, *Path);
|
return FFileHelper::SaveArrayToFile(ImgData, *Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
TArray<FSlateBrush> FFFMPEGUtils::GetMovieBrush(FClipData* ClipData)
|
TArray<FSlateBrush> FFFMPEGUtils::GetMovieBrush(FClipData* ClipData, bool Regenerate)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
TArray<FSlateBrush> Result;
|
||||||
|
ClipData->MovieBrushes.Empty();
|
||||||
|
if (ClipData->MovieBrushesPath.Num() > 0 && !Regenerate)
|
||||||
|
{
|
||||||
|
for (int32 i = 0; i < ClipData->MovieBrushesPath.Num(); i++)
|
||||||
|
{
|
||||||
|
FSlateDynamicImageBrush Brush = FSlateDynamicImageBrush(*ClipData->MovieBrushesPath[i], FVector2f(0, 0));
|
||||||
|
Result.Add(Brush);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int32 i = 0; i < ClipData->MovieBrushes.Num(); i++)
|
for (int32 i = 0; i < ClipData->MovieBrushes.Num(); i++)
|
||||||
{
|
{
|
||||||
ClipData->MovieBrushes[i].SetResourceObject(nullptr);
|
ClipData->MovieBrushes[i].SetResourceObject(nullptr);
|
||||||
}
|
}
|
||||||
ClipData->MovieBrushes.Empty();
|
|
||||||
|
ClipData->MovieBrushesPath.Empty();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TArray<FSlateBrush> Result;
|
|
||||||
if (ClipData->ResourcePropertyDataPtr)
|
if (ClipData->ResourcePropertyDataPtr)
|
||||||
{
|
{
|
||||||
const float ClipLength = (ClipData->VideoEndFrame - ClipData->VideoStartFrame) * FGlobalData::DefaultTimeTickSpace;
|
const float ClipLength = (ClipData->VideoEndFrame - ClipData->VideoStartFrame) * FGlobalData::DefaultTimeTickSpace;
|
||||||
@ -286,36 +304,40 @@ TArray<FSlateBrush> FFFMPEGUtils::GetMovieBrush(FClipData* ClipData)
|
|||||||
{
|
{
|
||||||
struct SwsContext* swsCtx = sws_getContext(
|
struct SwsContext* swsCtx = sws_getContext(
|
||||||
Frame->width, Frame->height, VideoCodecContext->pix_fmt,
|
Frame->width, Frame->height, VideoCodecContext->pix_fmt,
|
||||||
Frame->width, Frame->height, AV_PIX_FMT_BGRA,
|
Frame->width / 10, Frame->height / 10, AV_PIX_FMT_BGRA,
|
||||||
SWS_BILINEAR, NULL, NULL, NULL
|
SWS_BILINEAR, NULL, NULL, NULL
|
||||||
);
|
);
|
||||||
if (!swsCtx)
|
if (!swsCtx)
|
||||||
{
|
{
|
||||||
UE_LOG(LogTemp, Error, TEXT("Error creating swsContext"));
|
UE_LOG(LogTemp, Error, TEXT("Error creating swsContext"));
|
||||||
}
|
}
|
||||||
uint8* RawData = new uint8[Frame->width * Frame->height * 4];
|
uint8* RawData = new uint8[(Frame->width / 10) * (Frame->height / 10) * 4];
|
||||||
uint8* dest[4] = {RawData, 0, 0, 0};
|
uint8* dest[4] = {RawData, 0, 0, 0};
|
||||||
int32 dest_linesize[4] = {Frame->width * 4, 0, 0, 0};
|
int32 dest_linesize[4] = {(Frame->width / 10) * 4, 0, 0, 0};
|
||||||
sws_scale(swsCtx, Frame->data, Frame->linesize, 0, Frame->height, dest, dest_linesize);
|
sws_scale(swsCtx, Frame->data, Frame->linesize, 0, Frame->height, dest, dest_linesize);
|
||||||
sws_freeContext(swsCtx);
|
sws_freeContext(swsCtx);
|
||||||
|
|
||||||
|
|
||||||
UTexture2D* Texture = UTexture2D::CreateTransient(Frame->width, Frame->height, PF_B8G8R8A8);
|
UTexture2D* Texture = UTexture2D::CreateTransient(Frame->width / 10, Frame->height / 10, PF_B8G8R8A8);
|
||||||
if (Texture)
|
if (Texture)
|
||||||
{
|
{
|
||||||
void* MipData = Texture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
|
void* MipData = Texture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
|
||||||
FMemory::Memcpy(MipData, RawData, Frame->width * Frame->height * 4);
|
FMemory::Memcpy(MipData, RawData, (Frame->width / 10) * (Frame->height / 10) * 4);
|
||||||
Texture->GetPlatformData()->Mips[0].BulkData.Unlock();
|
Texture->GetPlatformData()->Mips[0].BulkData.Unlock();
|
||||||
Texture->UpdateResource();
|
Texture->UpdateResource();
|
||||||
|
|
||||||
// FGuid Guid = FGuid::NewGuid();
|
FGuid Guid = FGuid::NewGuid();
|
||||||
// ExportImage(Texture, *FPaths::Combine(FUtils::GetTempPath() / Guid.ToString() + ".png"));
|
ExportImage(Texture, *FPaths::Combine(FUtils::GetTempPath() / ClipData->ClipGuid.ToString() / Guid.ToString() + ".png"));
|
||||||
|
ClipData->MovieBrushesPath.Add(FPaths::Combine(FUtils::GetTempPath() / ClipData->ClipGuid.ToString() / Guid.ToString() + ".png"));
|
||||||
|
|
||||||
|
|
||||||
FSlateBrush NewBrush;
|
FSlateBrush NewBrush;
|
||||||
NewBrush.SetResourceObject(Texture);
|
NewBrush.SetResourceObject(Texture);
|
||||||
Result.Add(NewBrush);
|
Result.Add(NewBrush);
|
||||||
delete RawData;
|
delete RawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,6 @@ struct FFFMPEGUtils
|
|||||||
static FString ConvertMediaGoPto1(const FString& Path);
|
static FString ConvertMediaGoPto1(const FString& Path);
|
||||||
static bool ExportImage(UTexture2D* Texture2D, const FString& Path);
|
static bool ExportImage(UTexture2D* Texture2D, const FString& Path);
|
||||||
|
|
||||||
static TArray<FSlateBrush> GetMovieBrush(struct FClipData* ClipData);
|
static TArray<FSlateBrush> GetMovieBrush(struct FClipData* ClipData, bool Regenerate = false);
|
||||||
static TArray<FSlateBrush> GetAudioBrush(struct FClipData* ClipData);
|
static TArray<FSlateBrush> GetAudioBrush(struct FClipData* ClipData);
|
||||||
};
|
};
|
||||||
|
@ -270,11 +270,9 @@ TArray<FEncodeVideoInfo> FUtils::ExportPsaf(FTrackData TrackData, const FString&
|
|||||||
FString TempPath = TempClipData.ResourcePropertyDataPtr->MoviePath;
|
FString TempPath = TempClipData.ResourcePropertyDataPtr->MoviePath;
|
||||||
frames.Empty();
|
frames.Empty();
|
||||||
|
|
||||||
|
|
||||||
VideoCapture capture;
|
VideoCapture capture;
|
||||||
bool ret = capture.open(TCHAR_TO_UTF8(*TempPath));
|
bool ret = capture.open(TCHAR_TO_UTF8(*TempPath));
|
||||||
|
|
||||||
UE_LOG(LogTemp, Log, TEXT("cv numThreads -> %s"), *FString::FromInt(getNumThreads()));
|
|
||||||
|
|
||||||
//setNumThreads(2);
|
//setNumThreads(2);
|
||||||
|
|
||||||
@ -309,7 +307,9 @@ TArray<FEncodeVideoInfo> FUtils::ExportPsaf(FTrackData TrackData, const FString&
|
|||||||
|
|
||||||
Size old_size = frameSize;
|
Size old_size = frameSize;
|
||||||
|
|
||||||
|
capture.set(CAP_PROP_POS_FRAMES, TempClipData.ClipStartFrame);
|
||||||
int32 frameCount = capture.get(CV_CAP_PROP_FRAME_COUNT);
|
int32 frameCount = capture.get(CV_CAP_PROP_FRAME_COUNT);
|
||||||
|
frameCount -= ClipData[i].ClipStartFrame;
|
||||||
UE_LOG(LogTemp, Log, TEXT("frameCount: %s"), *FString::FromInt(frameCount));
|
UE_LOG(LogTemp, Log, TEXT("frameCount: %s"), *FString::FromInt(frameCount));
|
||||||
|
|
||||||
char p[128] = "pasf";
|
char p[128] = "pasf";
|
||||||
|
@ -297,6 +297,7 @@ struct CUT5_API FClipData
|
|||||||
Ar << ClipData.PresetType;
|
Ar << ClipData.PresetType;
|
||||||
Ar << ClipData.bCanDrag;
|
Ar << ClipData.bCanDrag;
|
||||||
Ar << ClipData.PresetsCustomData;
|
Ar << ClipData.PresetsCustomData;
|
||||||
|
Ar << ClipData.MovieBrushesPath;
|
||||||
return Ar;
|
return Ar;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -323,6 +324,8 @@ struct CUT5_API FClipData
|
|||||||
int32 GetClipRelativeEndFrame() const { return ClipEndFrame - ClipStartFrame; }
|
int32 GetClipRelativeEndFrame() const { return ClipEndFrame - ClipStartFrame; }
|
||||||
FPresetsCustomData PresetsCustomData;
|
FPresetsCustomData PresetsCustomData;
|
||||||
TArray<FSlateBrush> MovieBrushes;
|
TArray<FSlateBrush> MovieBrushes;
|
||||||
|
TArray<FString> MovieBrushesPath;
|
||||||
|
|
||||||
int32 MovieBrushNum;
|
int32 MovieBrushNum;
|
||||||
|
|
||||||
TArray<FSlateBrush> AudioBrushes;
|
TArray<FSlateBrush> AudioBrushes;
|
||||||
@ -908,3 +911,10 @@ enum class ESelectMode
|
|||||||
SelectMode = 0,
|
SelectMode = 0,
|
||||||
CutMode = 1,
|
CutMode = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ESoundSolveType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
OnlyLeft,
|
||||||
|
OnlyRight,
|
||||||
|
};
|
@ -6,6 +6,7 @@
|
|||||||
#include "SlateOptMacros.h"
|
#include "SlateOptMacros.h"
|
||||||
#include "STimelineTick.h"
|
#include "STimelineTick.h"
|
||||||
#include "STrackBody.h"
|
#include "STrackBody.h"
|
||||||
|
#include "Cut5/Utils/FFMPEGUtils.h"
|
||||||
#include "Cut5/Utils/Utils.h"
|
#include "Cut5/Utils/Utils.h"
|
||||||
#include "DragDropOperator/DragDropOperator.h"
|
#include "DragDropOperator/DragDropOperator.h"
|
||||||
#include "MicroWidgets/SClickEditableText.h"
|
#include "MicroWidgets/SClickEditableText.h"
|
||||||
@ -667,6 +668,7 @@ bool SCutTimeline::LoadTimeline(const FString& LoadPath, FTimelineInfo& Info)
|
|||||||
{
|
{
|
||||||
if (StaticCastSharedPtr<STrackHead>(TrackGroupInstances[l].Head)->TrackData.DeviceTrack.Guid == DeviceTrackGroups[j].DeviceTracks[k].Guid)
|
if (StaticCastSharedPtr<STrackHead>(TrackGroupInstances[l].Head)->TrackData.DeviceTrack.Guid == DeviceTrackGroups[j].DeviceTracks[k].Guid)
|
||||||
{
|
{
|
||||||
|
AllClips[i].MovieBrushes = FFFMPEGUtils::GetMovieBrush(&AllClips[i], false);
|
||||||
StaticCastSharedPtr<STrackHead>(TrackGroupInstances[l].Head)->TrackData.ClipData.Add(AllClips[i]);
|
StaticCastSharedPtr<STrackHead>(TrackGroupInstances[l].Head)->TrackData.ClipData.Add(AllClips[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
43
Source/Cut5/Widgets/SProgressPanel.cpp
Normal file
43
Source/Cut5/Widgets/SProgressPanel.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "SProgressPanel.h"
|
||||||
|
|
||||||
|
#include "SlateOptMacros.h"
|
||||||
|
#include "Widgets/Layout/SBackgroundBlur.h"
|
||||||
|
#include "Widgets/Layout/SConstraintCanvas.h"
|
||||||
|
#include "Widgets/Notifications/SProgressBar.h"
|
||||||
|
|
||||||
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
||||||
|
|
||||||
|
void SProgressPanel::Construct(const FArguments& InArgs)
|
||||||
|
{
|
||||||
|
CurrentProgress = InArgs._Limit.X;
|
||||||
|
TotalProgress = InArgs._Limit.Y;
|
||||||
|
ChildSlot
|
||||||
|
[
|
||||||
|
SNew(SConstraintCanvas)
|
||||||
|
+ SConstraintCanvas::Slot()
|
||||||
|
[
|
||||||
|
SNew(SBackgroundBlur)
|
||||||
|
.BlurStrength(100.0)
|
||||||
|
]
|
||||||
|
+ SConstraintCanvas::Slot()
|
||||||
|
[
|
||||||
|
SNew(SOverlay)
|
||||||
|
+ SOverlay::Slot()
|
||||||
|
[
|
||||||
|
SNew(SBox).WidthOverride(1000).HeightOverride(80)
|
||||||
|
[
|
||||||
|
SAssignNew(Progress, SProgressBar)
|
||||||
|
.Percent_Lambda([this]() {return CurrentProgress / TotalProgress; })
|
||||||
|
]
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
32
Source/Cut5/Widgets/SProgressPanel.h
Normal file
32
Source/Cut5/Widgets/SProgressPanel.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Widgets/SCompoundWidget.h"
|
||||||
|
#include "Widgets/Notifications/SProgressBar.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class CUT5_API SProgressPanel : public SCompoundWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SLATE_BEGIN_ARGS(SProgressPanel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
SLATE_ARGUMENT(FVector2D, Limit)
|
||||||
|
SLATE_END_ARGS()
|
||||||
|
|
||||||
|
/** Constructs this widget with InArgs */
|
||||||
|
void Construct(const FArguments& InArgs);
|
||||||
|
|
||||||
|
TSharedPtr<SProgressBar> Progress;
|
||||||
|
|
||||||
|
float CurrentProgress;
|
||||||
|
float TotalProgress;
|
||||||
|
|
||||||
|
void AddPercent(const float Percent) { CurrentProgress += Percent; }
|
||||||
|
void SetPercent(const float Percent) { CurrentProgress = Percent; }
|
||||||
|
float GetPercent() const { return CurrentProgress / TotalProgress; }
|
||||||
|
};
|
@ -303,7 +303,7 @@ void STimelineClip::Seek(int32 Frame)
|
|||||||
sws_freeContext(swsCtx);
|
sws_freeContext(swsCtx);
|
||||||
|
|
||||||
MainWidgetInterface->OnUpdateVideo(FGuid::NewGuid(), AllocatedFrame->width, AllocatedFrame->height, RawData);
|
MainWidgetInterface->OnUpdateVideo(FGuid::NewGuid(), AllocatedFrame->width, AllocatedFrame->height, RawData);
|
||||||
|
DoSound(ESoundSolveType::None, Frame);
|
||||||
av_frame_free(&AllocatedFrame);
|
av_frame_free(&AllocatedFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -517,20 +517,13 @@ void STimelineClip::Seek(int32 Frame)
|
|||||||
break;
|
break;
|
||||||
case ETrackType::AudioTrack:
|
case ETrackType::AudioTrack:
|
||||||
{
|
{
|
||||||
if (SoundThread == nullptr)
|
DoSound(ESoundSolveType::OnlyLeft, Frame);
|
||||||
{
|
break;
|
||||||
SoundThread = new FSoundThread(2, ClipData->ResourcePropertyDataPtr->AudioSample);
|
|
||||||
FRunnableThread* Thread = FRunnableThread::Create(SoundThread, TEXT("SoundThread"));
|
|
||||||
SoundThread->CopyAudio(ClipData->ResourcePropertyDataPtr->AudioData.GetData(), ClipData->ResourcePropertyDataPtr->AudioData.Num());
|
|
||||||
}
|
}
|
||||||
|
case ETrackType::AudioTrackR:
|
||||||
|
|
||||||
const int32 Offset = Frame - ClipData->ClipStartFrame;
|
|
||||||
const int32 SeekMovieFrame = ClipData->VideoStartFrame + Offset;
|
|
||||||
if (SoundThread)
|
|
||||||
{
|
{
|
||||||
SoundThread->SeekFrame(SeekMovieFrame);
|
DoSound(ESoundSolveType::OnlyRight, Frame);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -820,6 +813,22 @@ FReply STimelineClip::OnDragOver(const FGeometry& MyGeometry, const FDragDropEve
|
|||||||
return SCompoundWidget::OnDragOver(MyGeometry, DragDropEvent);
|
return SCompoundWidget::OnDragOver(MyGeometry, DragDropEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void STimelineClip::DoSound(ESoundSolveType SolveType, int32 InFrame)
|
||||||
|
{
|
||||||
|
if (SoundThread == nullptr)
|
||||||
|
{
|
||||||
|
SoundThread = new FSoundThread(2, ClipData->ResourcePropertyDataPtr->AudioSample);
|
||||||
|
FRunnableThread* Thread = FRunnableThread::Create(SoundThread, TEXT("SoundThread"));
|
||||||
|
SoundThread->CopyAudio(ClipData->ResourcePropertyDataPtr->AudioData.GetData(), ClipData->ResourcePropertyDataPtr->AudioData.Num(), SolveType);
|
||||||
|
}
|
||||||
|
const int32 Offset = InFrame - ClipData->ClipStartFrame;
|
||||||
|
const int32 SeekMovieFrame = ClipData->VideoStartFrame + Offset;
|
||||||
|
if (SoundThread)
|
||||||
|
{
|
||||||
|
SoundThread->SeekFrame(SeekMovieFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void STimelineClip::OnDragEnter(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
|
void STimelineClip::OnDragEnter(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
|
||||||
{
|
{
|
||||||
bIsDragOver = true;
|
bIsDragOver = true;
|
||||||
|
@ -59,6 +59,8 @@ public:
|
|||||||
TSharedPtr<FUICommandList> CommandList;
|
TSharedPtr<FUICommandList> CommandList;
|
||||||
FSoundThread* SoundThread;
|
FSoundThread* SoundThread;
|
||||||
|
|
||||||
|
void DoSound(ESoundSolveType SolveType, int32 InFrame);
|
||||||
|
|
||||||
virtual void OnDragEnter(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
|
virtual void OnDragEnter(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent) override;
|
||||||
virtual void OnDragLeave(const FDragDropEvent& DragDropEvent) override;
|
virtual void OnDragLeave(const FDragDropEvent& DragDropEvent) override;
|
||||||
bool bIsDragOver = false;
|
bool bIsDragOver = false;
|
||||||
|
@ -67,6 +67,15 @@ void STrackBody::CallRender()
|
|||||||
{
|
{
|
||||||
Overlay->ClearChildren();
|
Overlay->ClearChildren();
|
||||||
|
|
||||||
|
for (TSharedPtr<STimelineClip> Clip : SlateClips)
|
||||||
|
{
|
||||||
|
if (Clip->SoundThread)
|
||||||
|
{
|
||||||
|
Clip->SoundThread->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
SlateClips.Empty();
|
SlateClips.Empty();
|
||||||
for (FClipData& TempClipData : TrackHead->TrackData.ClipData)
|
for (FClipData& TempClipData : TrackHead->TrackData.ClipData)
|
||||||
{
|
{
|
||||||
@ -178,8 +187,8 @@ void STrackBody::BreakClip(const FGuid& Guid)
|
|||||||
|
|
||||||
if (TrackHead->TrackData.ClipData[i].ClipType == ETrackType::VideoTrack)
|
if (TrackHead->TrackData.ClipData[i].ClipType == ETrackType::VideoTrack)
|
||||||
{
|
{
|
||||||
TrackHead->TrackData.ClipData[i].MovieBrushes = FFFMPEGUtils::GetMovieBrush(&TrackHead->TrackData.ClipData[i]);
|
TrackHead->TrackData.ClipData[i].MovieBrushes = FFFMPEGUtils::GetMovieBrush(&TrackHead->TrackData.ClipData[i], true);
|
||||||
TrackHead->TrackData.ClipData[Index].MovieBrushes = FFFMPEGUtils::GetMovieBrush(&NewClipData);
|
TrackHead->TrackData.ClipData[Index].MovieBrushes = FFFMPEGUtils::GetMovieBrush(&NewClipData, true);
|
||||||
}
|
}
|
||||||
else if (TrackHead->TrackData.ClipData[i].ClipType == ETrackType::AudioTrack || TrackHead->TrackData.ClipData[i].ClipType == ETrackType::AudioTrack)
|
else if (TrackHead->TrackData.ClipData[i].ClipType == ETrackType::AudioTrack || TrackHead->TrackData.ClipData[i].ClipType == ETrackType::AudioTrack)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user