Skip to content

Commit 8706c35

Browse files
committed
display write flush popup
1 parent 0b00e11 commit 8706c35

File tree

4 files changed

+155
-63
lines changed

4 files changed

+155
-63
lines changed

MLDX12VideoCapture/MLAviWriter.cpp

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ void MLAviWriter::WriteFccHeader(const char *fccS, int bytes) {
133133
}
134134

135135

136-
bool MLAviWriter::Init(std::wstring path, int width, int height, int fps, ImageFormat imgFmt) {
136+
bool MLAviWriter::Start(std::wstring path, int width, int height, int fps, ImageFormat imgFmt) {
137137
assert(mFp == nullptr);
138138

139139
mWidth = width;
@@ -207,22 +207,16 @@ void MLAviWriter::AddImage(const uint32_t * img, int bytes) {
207207
SetEvent(m_readyEvent);
208208
}
209209

210-
void MLAviWriter::Term(void) {
211-
assert(mFp != nullptr);
212-
213-
StopThread();
214-
215-
FinishList(mLastMoviIdx);
216-
FinishRiff(mLastRiffIdx);
217-
218-
_fseeki64(mFp, mAviMainHeaderPos, SEEK_SET);
219-
WriteAviMainHeader();
210+
void MLAviWriter::StopBlocking(void) {
211+
if (mFp == nullptr) {
212+
return;
213+
}
220214

221-
_fseeki64(mFp, mAviStreamHeaderPos, SEEK_SET);
222-
WriteAviStreamHeader();
215+
StopThreadBlock();
216+
}
223217

224-
fclose(mFp);
225-
mFp = nullptr;
218+
void MLAviWriter::StopAsync(void) {
219+
StopThreadAsync();
226220
}
227221

228222
int MLAviWriter::RecQueueSize(void) {
@@ -414,18 +408,42 @@ void MLAviWriter::StartThread(void)
414408
m_thread = CreateThread(nullptr, 0, AviWriterEntry, this, 0, nullptr);
415409
}
416410

417-
void MLAviWriter::StopThread(void) {
411+
void MLAviWriter::StopThreadBlock(void) {
418412
if (m_thread == nullptr) {
419413
return;
420414
}
421415

422-
mState = AVIS_Init;
423-
424416
assert(m_shutdownEvent != nullptr);
425417
SetEvent(m_shutdownEvent);
426418
WaitForSingleObject(m_thread, INFINITE);
427419
CloseHandle(m_thread);
428420
m_thread = nullptr;
421+
mState = AVIS_Init;
422+
}
423+
424+
void MLAviWriter::StopThreadAsync(void) {
425+
if (m_thread == nullptr) {
426+
return;
427+
}
428+
429+
mState = AVIS_WaitThreadEnd;
430+
431+
assert(m_shutdownEvent != nullptr);
432+
SetEvent(m_shutdownEvent);
433+
}
434+
435+
bool MLAviWriter::PollThreadEnd(void) {
436+
if (m_thread == nullptr) {
437+
return true;
438+
}
439+
440+
if (mState == AVIS_Init) {
441+
CloseHandle(m_thread);
442+
m_thread = nullptr;
443+
return true;
444+
}
445+
446+
return false;
429447
}
430448

431449

@@ -456,7 +474,21 @@ MLAviWriter::ThreadMain(void) {
456474
WriteAll();
457475
}
458476

477+
FinishList(mLastMoviIdx);
478+
FinishRiff(mLastRiffIdx);
479+
480+
_fseeki64(mFp, mAviMainHeaderPos, SEEK_SET);
481+
WriteAviMainHeader();
482+
483+
_fseeki64(mFp, mAviStreamHeaderPos, SEEK_SET);
484+
WriteAviStreamHeader();
485+
486+
fclose(mFp);
487+
mFp = nullptr;
488+
459489
CoUninitialize();
490+
491+
mState = AVIS_Init;
460492
return rv;
461493
}
462494

MLDX12VideoCapture/MLAviWriter.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,19 @@ class MLAviWriter {
1717
IF_YUV422v210,
1818
};
1919

20-
bool Init(std::wstring path, int width, int height, int fps, ImageFormat imgFmt);
20+
bool Start(std::wstring path, int width, int height, int fps, ImageFormat imgFmt);
2121

2222
void AddImage(const uint32_t * img, int bytes);
2323

24-
void Term(void);
24+
// send thread to flush remaining data and end.
25+
// StopAsync() then call PallThreadEnd() every frame until PollThreadEnd() returns true
26+
void StopAsync(void);
27+
28+
// returns true when writing thread ends
29+
bool PollThreadEnd(void);
30+
31+
// blocking termination
32+
void StopBlocking(void);
2533

2634
bool IsOpen(void) const { return mFp != nullptr; }
2735

@@ -37,6 +45,7 @@ class MLAviWriter {
3745
enum AVIState {
3846
AVIS_Init,
3947
AVIS_Writing,
48+
AVIS_WaitThreadEnd,
4049
};
4150

4251
AVIState mState;
@@ -100,7 +109,9 @@ class MLAviWriter {
100109
void WriteAll(void);
101110
void WriteOne(ImageItem& ii);
102111
void StartThread(void);
103-
void StopThread(void);
112+
void StopThreadBlock(void);
113+
114+
void StopThreadAsync(void);
104115

105116
};
106117

MLDX12VideoCapture/MLDX12App.cpp

Lines changed: 87 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,25 @@ MLDX12App::ImGuiCommands(void)
709709
{
710710
ImGui::Begin("Settings");
711711

712-
ImGui::Text("Average redraw frames per second : %.1f", ImGui::GetIO().Framerate);
712+
if (ImGui::BeginPopupModal("ErrorPopup", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
713+
ImGui::Text(m_msg);
714+
if (ImGui::Button("OK", ImVec2(120, 0))) {
715+
ImGui::CloseCurrentPopup();
716+
m_msg[0] = 0;
717+
}
718+
ImGui::EndPopup();
719+
}
713720

721+
if (ImGui::BeginPopupModal("WriteFlushPopup", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
722+
ImGui::Text(m_msg);
723+
724+
if (m_state != S_WaitRecordEnd) {
725+
ImGui::CloseCurrentPopup();
726+
}
727+
ImGui::EndPopup();
728+
}
729+
730+
ImGui::Text("Average redraw frames per second : %.1f", ImGui::GetIO().Framerate);
714731
ImGui::Text("ALT+Enter to toggle fullscreen.");
715732

716733
static int selectedDeviceIdx = 0;
@@ -733,78 +750,95 @@ MLDX12App::ImGuiCommands(void)
733750
m_videoCapture.SetCallback(this);
734751
bool brv = m_videoCapture.StartCapture(0);
735752
if (brv) {
736-
m_state = S_Capturing;
753+
m_state = S_Previewing;
754+
}
755+
}
756+
break;
757+
case S_WaitRecordEnd:
758+
{
759+
sprintf_s(m_msg, "Now Writing AVI...\nRemaining %d frames.", m_aviWriter.RecQueueSize());
760+
m_mutex.lock();
761+
bool bEnd = m_aviWriter.PollThreadEnd();
762+
m_mutex.unlock();
763+
if (bEnd) {
764+
m_state = S_Previewing;
737765
}
738766
}
739767
break;
740768
case S_Recording:
741-
case S_Capturing:
769+
case S_Previewing:
742770
{
743771
int queueSize = 0;
772+
m_mutex.lock();
773+
if (!m_capturedImages.empty()) {
774+
queueSize = (int)m_capturedImages.size();
775+
auto & front = m_capturedImages.front();
776+
ImGui::Text(front.imgFormat.c_str());
777+
} else {
778+
ImGui::Text("");
779+
}
780+
m_mutex.unlock();
744781

745-
if (m_state == S_Capturing) {
746-
ImGui::Text("Now Capturing...");
747-
BMDTimeScale ts = m_videoCapture.FrameRateTS();
748-
BMDTimeValue tv = m_videoCapture.FrameRateTV();
749-
ImGui::Text("Frame rate : %llu %llu", (uint64_t)ts, (uint64_t)tv);
782+
BMDTimeScale ts = m_videoCapture.FrameRateTS();
783+
BMDTimeValue tv = m_videoCapture.FrameRateTV();
784+
ImGui::Text("Frame rate : %.1f", (double)ts / tv);
750785

786+
ImGui::Separator();
787+
788+
if (m_state == S_Previewing) {
789+
ImGui::Text("Now Previewing...");
751790
BMDPixelFormat pixFmt = m_videoCapture.PixelFormat();
752791
if (bmdFormat10BitYUV == pixFmt) {
753792
ImGui::InputText("Record filename", m_writePath, sizeof m_writePath - 1);
754-
ImGui::Text(m_msg);
755-
if (ImGui::Button("Record")) {
793+
if (ImGui::Button("Record", ImVec2(256, 64))) {
756794
wchar_t path[512];
757795
memset(path, 0, sizeof path);
758796
MultiByteToWideChar(CP_UTF8, 0, m_writePath, sizeof m_writePath, path, 511);
759797

760-
bool bRv = m_aviWriter.Init(path, m_videoCapture.Width(),
798+
bool bRv = m_aviWriter.Start(path, m_videoCapture.Width(),
761799
m_videoCapture.Height(), (int)(ts / 1000),
762800
MLAviWriter::IF_YUV422v210);
763801
if (bRv) {
764802
m_state = S_Recording;
765803
m_msg[0] = 0;
766804
} else {
767-
sprintf_s(m_msg, "File open error : %s", m_writePath);
805+
sprintf_s(m_msg, "Record Failed.\nFile open error : %s", m_writePath);
806+
ImGui::OpenPopup("ErrorPopup");
768807
}
769808
}
770809
}
771-
}
772810

773-
m_mutex.lock();
774-
if (!m_capturedImages.empty()) {
775-
queueSize = (int)m_capturedImages.size();
776-
auto & front = m_capturedImages.front();
777-
ImGui::Text(front.imgFormat.c_str());
778-
} else {
779-
ImGui::Text("");
780-
}
781-
m_mutex.unlock();
782-
783-
ImGui::Text("Draw Queue size : %d", queueSize);
784-
ImGui::Text("Frame skip count : %lld", m_frameSkipCount);
785-
786-
if (m_state == S_Recording) {
787-
ImGui::Text("Now Recording...");
788-
ImGui::Text("Rec Queue size : %d", m_aviWriter.RecQueueSize());
789-
if (ImGui::Button("Stop Recording")) {
790-
m_state = S_Capturing;
791-
792-
m_mutex.lock();
793-
m_aviWriter.Term();
794-
m_mutex.unlock();
795-
}
796-
} else {
797811
if (ImGui::Button("Stop Capture")) {
798-
812+
799813
m_videoCapture.StopCapture();
800814
m_videoCapture.Term();
801-
815+
802816
m_videoCaptureDeviceList.Term();
803817
m_videoCaptureDeviceList.Init();
804818

805819
m_state = S_Init;
806820
}
821+
} else if (m_state == S_Recording) {
822+
ImGui::Text("Now Recording...");
823+
ImGui::Text("Record filename : %s", m_writePath);
824+
if (ImGui::Button("Stop Recording", ImVec2(256, 64))) {
825+
m_state = S_WaitRecordEnd;
826+
827+
m_mutex.lock();
828+
m_aviWriter.StopAsync();
829+
m_mutex.unlock();
830+
831+
ImGui::OpenPopup("WriteFlushPopup");
832+
}
833+
834+
ImGui::Text("Rec Queue size : %d", m_aviWriter.RecQueueSize());
835+
}
836+
837+
ImGui::Text("Draw Queue size : %d", queueSize);
838+
if (ImGui::Button("Clear Draw Queue")) {
839+
ClearDrawQueue();
807840
}
841+
ImGui::Text("Frame Draw skip count : %lld", m_frameSkipCount);
808842

809843
ImGui::BeginGroup();
810844
if (ImGui::RadioButton("Center Crosshair", m_crosshairType == CH_CenterCrosshair)) {
@@ -815,7 +849,7 @@ MLDX12App::ImGuiCommands(void)
815849
m_crosshairType = CH_4Crosshairs;
816850
}
817851
ImGui::SameLine();
818-
if (ImGui::RadioButton("None", m_crosshairType == CH_None)) {
852+
if (ImGui::RadioButton("CHNone", m_crosshairType == CH_None)) {
819853
m_crosshairType = CH_None;
820854
}
821855
ImGui::EndGroup();
@@ -831,7 +865,7 @@ MLDX12App::ImGuiCommands(void)
831865
m_gridType = GR_6x6;
832866
}
833867
ImGui::SameLine();
834-
if (ImGui::RadioButton("None", m_gridType == GR_None)) {
868+
if (ImGui::RadioButton("GRNone", m_gridType == GR_None)) {
835869
m_gridType = GR_None;
836870
}
837871
ImGui::EndGroup();
@@ -982,6 +1016,18 @@ MLDX12App::MLVideoCaptureCallback_VideoInputFrameArrived(IDeckLinkVideoInputFram
9821016
m_mutex.unlock();
9831017
}
9841018

1019+
void MLDX12App::ClearDrawQueue(void)
1020+
{
1021+
m_mutex.lock();
1022+
for (auto ite = m_capturedImages.begin(); ite != m_capturedImages.end(); ++ite) {
1023+
CapturedImage &ci = *ite;
1024+
delete [] ci.data;
1025+
ci.data = nullptr;
1026+
}
1027+
m_capturedImages.clear();
1028+
m_mutex.unlock();
1029+
}
1030+
9851031
void
9861032
MLDX12App::UpdateVideoTexture(void) {
9871033
m_mutex.lock();

MLDX12VideoCapture/MLDX12App.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ class MLDX12App : public MLDX12, IMLVideoCaptureCallback {
4545

4646
enum State {
4747
S_Init,
48-
S_Capturing,
48+
S_Previewing,
4949
S_Recording,
50+
S_WaitRecordEnd,
5051
};
5152

5253
struct Vertex
@@ -152,6 +153,8 @@ class MLDX12App : public MLDX12, IMLVideoCaptureCallback {
152153
void LoadSizeDependentResources(void);
153154
void UpdateViewAndScissor(void);
154155

156+
void ClearDrawQueue(void);
157+
155158
void CreateVideoTexture(int texIdx, int w, int h, DXGI_FORMAT fmt, int pixelBytes, uint8_t *data);
156159
void UpdateVideoTexture(void);
157160

0 commit comments

Comments
 (0)