diff --git a/Source/Cut5/Utils/FFMPEGUtils.cpp b/Source/Cut5/Utils/FFMPEGUtils.cpp index 30e1841..f5a68b7 100644 --- a/Source/Cut5/Utils/FFMPEGUtils.cpp +++ b/Source/Cut5/Utils/FFMPEGUtils.cpp @@ -1,6 +1,8 @@ #include "FFMPEGUtils.h" #include "FFMPEGUtils.h" + + #include "CanvasTypes.h" #include "ImageUtils.h" #include "Utils.h" @@ -126,10 +128,13 @@ FString FFFMPEGUtils::LoadMedia(const FString& Path, FTimelinePropertyData* Prop AVFrame* Frame = av_frame_alloc(); const AVSampleFormat SampleFormat = *AudioCodecContext->codec->sample_fmts; + av_seek_frame(FormatContext, AudioStream, 0, AVSEEK_FLAG_BACKWARD); while (true) { - if (av_read_frame(FormatContext, &Packet) < 0) + int32 Response = av_read_frame(FormatContext, &Packet); + if (Response < 0) { + av_usleep(1000); if (av_read_frame(FormatContext, &Packet) < 0) { break; diff --git a/Source/Cut5/Utils/FFMPEGUtils.h b/Source/Cut5/Utils/FFMPEGUtils.h index 1e63850..f2ca883 100644 --- a/Source/Cut5/Utils/FFMPEGUtils.h +++ b/Source/Cut5/Utils/FFMPEGUtils.h @@ -6,6 +6,7 @@ extern "C"{ #include #include +#include } struct FFFMPEGUtils { diff --git a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp index 5288eda..52ac12a 100644 --- a/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp +++ b/Source/Cut5/Widgets/DragDropOperator/DragDropOperator.cpp @@ -784,6 +784,8 @@ void DragDropOperator::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& if ((ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::LightArrayTrack) || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::LightBarTrack) || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::PlayerTrack) + || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::AudioTrack) + || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::AudioTrackR) || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::AudioTrack && TrackHead->TrackData.TrackType == ETrackType::AudioTrackR) || (ClipDragOperation.TimelinePropertyData->Type == ETrackType::VideoTrack && TrackHead->TrackData.TrackType == ETrackType::AtomSphereLightTrack)) { diff --git a/Source/Cut5/Widgets/SCutMainWindow.cpp b/Source/Cut5/Widgets/SCutMainWindow.cpp index fc78bca..5548abc 100644 --- a/Source/Cut5/Widgets/SCutMainWindow.cpp +++ b/Source/Cut5/Widgets/SCutMainWindow.cpp @@ -364,7 +364,7 @@ void SCutMainWindow::Construct(const FArguments& InArgs) SNew(SImage).Image(FUtils::GetBrushFromImage(FUtils::GetResourcesPath(TEXT("MouseCursor.png")), {48, 48})) ]; GEngine->GameViewport->AddSoftwareCursorFromSlateWidget(EMouseCursor::Type::Default, NewWidget.ToSharedRef()); - + @@ -561,6 +561,13 @@ void SCutMainWindow::Construct(const FArguments& InArgs) OnUpdateProjector(0, true); DragDropOperator::GetDragDropOperator()->SavedMainInterface = this; + + + FCoreDelegates::OnPreExit.AddLambda([this]() + { + CloseAllThreads(); + CutTimeline->TickCursorTimeThread->Stop(); + }); } @@ -962,7 +969,7 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) if (ExportPath.IsEmpty()) return; - FGlobalData::ExportPath = ExportPath / FGlobalData::CurrentProjectName; + FGlobalData::ExportPath = ExportPath / FGlobalData::CurrentProjectName + TEXT("_XML"); FPlatformFileManager::Get().GetPlatformFile().DeleteDirectoryRecursively(*FGlobalData::ExportPath); @@ -1190,7 +1197,7 @@ void SCutMainWindow::ExportProject(const FString& ExportPath) GetSpecialEffectList(RootElement); - FString XMLExportPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(ExportPath, FGlobalData::CurrentProjectName, TEXT("Process.xml"))); + FString XMLExportPath = FPaths::ConvertRelativePathToFull(FPaths::Combine(ExportPath, FGlobalData::CurrentProjectName + TEXT("_XML"), TEXT("Process.xml"))); TArray Data; FFileHelper::SaveArrayToFile(Data, *XMLExportPath); //GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, XMLExportPath); @@ -1791,7 +1798,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoElement(tinyxml2::XMLElement* Pare { tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent"); VolumeEvent->InsertNewChildElement("TimeCode")->InsertNewText("0"); - VolumeEvent->InsertNewChildElement("Value")->InsertNewText("0"); + VolumeEvent->InsertNewChildElement("Value")->InsertNewText("100"); } } @@ -1927,7 +1934,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundElement(tinyxml2::XMLElement* Pare { tinyxml2::XMLElement* VolumeEvent = VolumeEventList->InsertNewChildElement("VolumeEvent"); VolumeEvent->InsertNewChildElement("TimeCode")->InsertNewText("0"); - VolumeEvent->InsertNewChildElement("Value")->InsertNewText("0"); + VolumeEvent->InsertNewChildElement("Value")->InsertNewText("100"); } } @@ -1974,17 +1981,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetVideoListElement(tinyxml2::XMLElement* { if (StaticCastSharedPtr(CutTimeline->TrackGroupInstances[i].Head)->TrackData.TrackType == ETrackType::VideoTrack) { - FString Filename; - for (FCurtainGroup& CurtainGroup : CurtainPanel->Groups) - { - for (const FCurtain& Curtain : CurtainGroup.Curtains) - { - if (Curtain.bIsActive) - { - Filename = Curtain.CurtainName; - } - } - } + FString Filename = + GetCurrentSelectFileName(); FString NewExportFilePath = FGlobalData::ExportPath / "Video" / Filename; // GEngine->AddOnScreenDebugMessage(-1, 10.0F, FColor::White, NewExportFilePath); TArray EncodeVideoInfos = @@ -2044,6 +2042,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement* const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / ClipData.VirtualCurtainName; FEncodeVideoInfo EncodeVideoInfo; EncodeVideoInfo.EncodedVideoName = VirtualFileName; + EncodeVideoInfo.ClipData = ClipData; GetSoundElement(AudioList, EncodeVideoInfo); } } @@ -2057,6 +2056,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetSoundListElement(tinyxml2::XMLElement* const FString VirtualFileName = FGlobalData::ExportPath / "Sound" / ClipData.VirtualCurtainName; FEncodeVideoInfo EncodeVideoInfo; EncodeVideoInfo.EncodedVideoName = VirtualFileName; + EncodeVideoInfo.ClipData = ClipData; GetSoundElement(AudioList, EncodeVideoInfo); } } @@ -2088,6 +2088,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetProcessA(tinyxml2::XMLElement* Parent, ProcessA->SetAttribute("Name", TCHAR_TO_UTF8(*CurtainGroup->GroupName)); for (int32 i = 0; i < CurtainGroup->Curtains.Num(); i++) { + DeselectAll(); CurtainPanel->DeSelectedAll(); CurtainGroup->Curtains[i].bIsActive = true; OpenTimeline(CurtainGroup->Curtains[i].TimelineInfo.CurrentOpenFullPath, true, true); @@ -2105,6 +2106,12 @@ tinyxml2::XMLElement* SCutMainWindow::GetProcessB(tinyxml2::XMLElement* Parent, tinyxml2::XMLElement* ProcessB = Parent->InsertNewChildElement("ProcessB"); ProcessB->SetAttribute("Name", TCHAR_TO_UTF8(*Curtain->CurtainName)); ProcessB->InsertNewChildElement("ID")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(Curtain->Step))); + + + + + + ProcessB->InsertNewChildElement("AutoNext")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(0))); ProcessB->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::FromInt(-1))); @@ -2174,6 +2181,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffectList(tinyxml2::XMLElement* { if (!EffectCardsPanel->EffectCardGroups[i].bIsDedicated) { + DeselectAll(); + EffectCardsPanel->EffectCardGroups[i].bIsActive = true; OpenTimeline(FUtils::GroupFullPath(EffectCardsPanel->EffectCardGroups[i].Guid.ToString()), true, true); CurrentSelectedPropertiesInterfaceGuid = EffectCardsPanel->EffectCardGroups[i].Guid; GetSpecialEffectGroup(SpecialEffectsList, &EffectCardsPanel->EffectCardGroups[i]); @@ -2182,6 +2191,8 @@ tinyxml2::XMLElement* SCutMainWindow::GetSpecialEffectList(tinyxml2::XMLElement* } for (int32 j = 0; j < EffectCardsPanel->EffectCardGroups[i].Cards.Num(); j++) { + DeselectAll(); + EffectCardsPanel->EffectCardGroups[i].Cards[j].bIsActive = true; OpenTimeline(FUtils::SingleCardFullPath(EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid.ToString()), true, true); CurrentSelectedPropertiesInterfaceGuid = EffectCardsPanel->EffectCardGroups[i].Cards[j].Guid; GetSpecialEffect(SpecialEffectsList, &EffectCardsPanel->EffectCardGroups[i].Cards[j]); @@ -2286,7 +2297,7 @@ tinyxml2::XMLElement* SCutMainWindow::GetBreatheLight(tinyxml2::XMLElement* Pare Parent->InsertNewChildElement("InitialColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(ClipData.PresetsCustomData.Colors[0].ToFColor(false))))); Parent->InsertNewChildElement("EndColor")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::Color2Hex3(FLinearColor::Black.ToFColor(false))))); float PerLength = (ClipData.PresetsCustomData.Time / ClipData.PresetsCustomData.Times); - Parent->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), int32(PerLength * 1000)))); + Parent->InsertNewChildElement("TimeLength")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), int32(ClipData.PresetsCustomData.Time * 1000)))); Parent->InsertNewChildElement("TimeCode")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%ls"), *FUtils::GetMsFromString(FGlobalData::GetTimeData(ClipData.ClipStartFrame))))); Parent->InsertNewChildElement("Cycle")->InsertNewText(TCHAR_TO_UTF8(*FString::Printf(TEXT("%d"), static_cast(PerLength * 1000)))); return nullptr; diff --git a/Source/Cut5/Widgets/STimelineClip.cpp b/Source/Cut5/Widgets/STimelineClip.cpp index f3f8a65..569fa45 100644 --- a/Source/Cut5/Widgets/STimelineClip.cpp +++ b/Source/Cut5/Widgets/STimelineClip.cpp @@ -498,6 +498,9 @@ void STimelineClip::UpdatePosition(int32 StartFrame) } ClipData->ClipStartFrame = StartFrame; + + ClipData->PresetsCustomData.Time = (ClipData->ClipEndFrame - ClipData->ClipStartFrame) / FGlobalData::GlobalFPS; + } void STimelineClip::UpdateLength(int32 EndFrame) @@ -529,6 +532,8 @@ void STimelineClip::UpdateLength(int32 EndFrame) } } } + + ClipData->PresetsCustomData.Time = (ClipData->ClipEndFrame - ClipData->ClipStartFrame) / FGlobalData::GlobalFPS; } void STimelineClip::UpdateMove(int32 X, int32 DragOffset) @@ -879,6 +884,14 @@ void STimelineClip::Tick(const FGeometry& AllottedGeometry, const double InCurre if (Frame) { + if (Frame->width == 0 || Frame->height == 0) + { + TArray Brushes; + Brushes.Init(FSlateBrush(), ClipData->MovieBrushNum - ClipData->MovieBrushes.Num()); + ClipData->MovieBrushes.Append(Brushes); + return; + } + struct SwsContext* swsCtx = sws_getContext( Frame->width, Frame->height, VideoCodecContext->pix_fmt, Frame->width / 10, Frame->height / 10, AV_PIX_FMT_BGRA,