From 41272ce08e45e7fe306d35487f182eb511585b01 Mon Sep 17 00:00:00 2001 From: Jan Grewe Date: Tue, 12 Mar 2024 07:40:23 +0100 Subject: [PATCH] intermediate state, more todos, writer not working in dual cam setting --- dualcamwrapper.cpp | 4 +- notes.md | 2 +- pylonrecorder.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++--- pylonrecorder.h | 3 +- writer.cpp | 5 +- writer.h | 7 ++- 6 files changed, 137 insertions(+), 17 deletions(-) diff --git a/dualcamwrapper.cpp b/dualcamwrapper.cpp index 11abcee..2713e8b 100644 --- a/dualcamwrapper.cpp +++ b/dualcamwrapper.cpp @@ -215,11 +215,12 @@ bool DualcamWrapper::openCameras(std::string &message) { qDebug() << "opening cameras"; bool valid = true; Pylon::CTlFactory& tlFactory = Pylon::CTlFactory::GetInstance(); - // Pylon::CInstantCameraArray cameras(2); cameras.Initialize(2); try { cameras[0].Attach( tlFactory.CreateDevice( layout.devices[0].c_str() ) ); + cameras[0].Open(); cameras[1].Attach( tlFactory.CreateDevice( layout.devices[1].c_str() ) ); + cameras[1].Open(); valid = cameras[0].IsOpen(); valid = valid & cameras[1].IsOpen(); message = "Successfully opened camera!"; @@ -231,7 +232,6 @@ bool DualcamWrapper::openCameras(std::string &message) { } resetCamera(0); resetCamera(1); - return valid; } diff --git a/notes.md b/notes.md index f6d2daf..d554e37 100644 --- a/notes.md +++ b/notes.md @@ -6,7 +6,7 @@ Recorder for up to two Basler cameras. * implement grabbing from 2 joined cameras * set the region of interest -* save properly +* !!! dual cam writer!!! chgeck file opening! ## FIXMEs diff --git a/pylonrecorder.cpp b/pylonrecorder.cpp index 9cd6541..a03dea8 100644 --- a/pylonrecorder.cpp +++ b/pylonrecorder.cpp @@ -657,6 +657,7 @@ void PylonRecorder::connectCamera() { updateActions(); } if (layout.mode == CameraMode::dual && layout.devices.size() == 2) { + std::cerr << "Dual MODE" << std::endl; qDebug() << "dual camera mode"; std::string message; qDebug() << "creating dual cam wrapper"; @@ -719,7 +720,7 @@ VideoSpecs PylonRecorder::getVideoSpecs(const ImageSettings &settings) { void PylonRecorder::startSinglecamRecording() { - qDebug() << "start recording!"; + qDebug() << "start single-camera recording!"; std::string filename = createFilename(".mp4"); fileLabel->setText(QString::fromStdString(filename)); qDebug() << "storing to file " << filename.c_str(); @@ -763,8 +764,8 @@ void PylonRecorder::startSinglecamRecording() { delete writer0; writer0 = nullptr; } - writer0 = new Writer(buffer0); - connect(writer0, &Writer::writingDone, this, &PylonRecorder::writerDone); + writer0 = new Writer(buffer0, 0); + connect(writer0, SLOT(writingDone( int)), this, SLOT(writerDone( int ))); writer0->setVideoSpecs(specs); QSettings s; @@ -774,6 +775,7 @@ void PylonRecorder::startSinglecamRecording() { buffer0->clear(); if (!dryRunCheckBox->isChecked()) { writer0->start(); + iswriting[0] = true; writing = true; } dryRun = dryRunCheckBox->isChecked(); @@ -784,7 +786,99 @@ void PylonRecorder::startSinglecamRecording() { void PylonRecorder::startDualcamRecording() { + qDebug() << "start dual-camera recording!"; + std::string filenamea = createFilename("a", ".mp4"); + std::string filenameb = createFilename("b", ".mp4"); + fileLabel->setText(QString::fromStdString(filenamea + " & " + filenameb)); + qDebug() << "storing to files " << filenamea.c_str() << ", " << filenameb.c_str(); + ImageSettings settings = dualcam->getImageSettings(0); + qDebug() << "got image settings"; + + VideoSpecs specsa = getVideoSpecs(settings); + specsa.filename = filenamea; + specsa.format = VideoFormat::mp4; + + VideoSpecs specsb = getVideoSpecs(settings); + specsb.filename = filenameb; + specsb.format = VideoFormat::mp4; + qDebug() << "got video specifications"; + + if (buffer0 != nullptr) { + buffer0->clear(); + delete buffer0; + buffer0 = nullptr; + } + if (buffer1 != nullptr) { + buffer1->clear(); + delete buffer1; + buffer1 = nullptr; + } + + qDebug() << "setting image buffer to size " << buffersizeSpinner->value(); + buffer0 = new ImageBuffer(defaultBufferSize); + if (buffersizeSpinner->value() != static_cast(buffer0->capacity())) { + buffer0->resize(static_cast(buffersizeSpinner->value())); + loadBar->setRange(0, buffersizeSpinner->value()); + } + buffer1 = new ImageBuffer(defaultBufferSize); + if (buffersizeSpinner->value() != static_cast(buffer1->capacity())) { + buffer1->resize(static_cast(buffersizeSpinner->value())); + } + + qDebug() << "setting up grabber"; + if (dualcamgrabber != nullptr) { + delete dualcamgrabber; + dualcamgrabber = nullptr; + } + dualcamgrabber = new DualcamGrabber(dualcam, buffer0, buffer1, defaultFrameRate); + if (framerateSpinner->value() != dualcamgrabber->currentFramerate()) + dualcamgrabber->setFrameRate(framerateSpinner->value()); + if (exposureSpinner->value() != int(dualcamgrabber->currentExposureTime())) + dualcamgrabber->setExposureTime(static_cast(exposureSpinner->value())); + if (gainSpinner->value() != int(dualcamgrabber->currentGain())) + dualcamgrabber->setGain(static_cast(gainSpinner->value())); + + qDebug() << "setting up writers"; + if (writer0 != nullptr) { + delete writer0; + writer0 = nullptr; + } + writer0 = new Writer(buffer0, 0); + connect(writer0, SIGNAL(writingDone(int)), this, SLOT(writerDone( int ))); + writer0->setVideoSpecs(specsa); + + if (writer1 != nullptr) { + delete writer1; + writer1 = nullptr; + } + writer1 = new Writer(buffer1, 1); + connect(writer1, SIGNAL(writingDone(int)), this, SLOT(writerDone( int ))); + writer1->setVideoSpecs(specsb); + + qDebug() << "push metadata to writer"; + QSettings s; + this->mdata.read(s); + writer0->setProjectMetadata(mdata); + + buffer0->clear(); + if (!dryRunCheckBox->isChecked()) { + writer0->start(); + writing = true; + iswriting[0] = true; + } + + buffer1->clear(); + if (!dryRunCheckBox->isChecked()) { + writer1->start(); + writing = true; + iswriting[1] = true; + } + + dryRun = dryRunCheckBox->isChecked(); + dualcamgrabber->start(); + grabbing = true; + stopRequest = false; } @@ -815,30 +909,52 @@ void PylonRecorder::stopRecording() { qDebug() << "StopRecording: stop writer!"; if (writer0 != nullptr) writer0->requestStop(); + if (writer1 != nullptr) + writer1->requestStop(); + grabbing = false; stopRequest = true; grab_stop_action->setEnabled(false); qDebug() << "StopRecording: clear buffer!"; if(buffer0 != nullptr) { buffer0->clear(); - writerDone(); + // writerDone( 0 ); // Needed? or even dangerous? + } + qDebug() << "StopRecording: clear buffer!"; + if(buffer1 != nullptr) { + buffer1->clear(); + // writerDone( 1 ); } } qDebug() << "StopRecording done!"; } -void PylonRecorder::writerDone() { - std::cerr << "writer is Done!!!" << std::endl; +void PylonRecorder::writerDone(int cam) { + std::cerr << "writer " << cam << "is Done!!!" << std::endl; + iswriting[cam] = false; + if (iswriting[0] + iswriting[1] > 0) { + qDebug() << "waiting for the other writer to finish"; + return; + } pressureTimer->stop(); pressureBar->reset(); loadBar->reset(); labelTimer->stop(); writingLabel->setStyleSheet(inactiveLabelStyle); grabbingLabel->setStyleSheet(inactiveLabelStyle); - singlecamgrabber->wait(10000); - writer0->wait(10000); + if (layout.mode == CameraMode::single) { + singlecamgrabber->wait(10000); + } else { + dualcamgrabber->wait(10000); + } + if (writer0 != nullptr) + writer0->wait(10000); + if (writer1 != nullptr) + writer1->wait(10000); writing = false; + iswriting[0] = false; + iswriting[1] = false; updateActions(); qInfo() << "writer is Done!"; } @@ -916,6 +1032,7 @@ void PylonRecorder::grabStillFromPylon() { } else { statusBar()->showMessage(tr("Camera is not open! Connect to camera first!")); } + //FIXME does not work for single camera mode! qDebug() << "grabbing still image done!"; } diff --git a/pylonrecorder.h b/pylonrecorder.h index a77f401..79afb42 100644 --- a/pylonrecorder.h +++ b/pylonrecorder.h @@ -66,7 +66,7 @@ private slots: void displaySingleFrame(); void displayBufferPressure(); void displayActivity(); - void writerDone(); + void writerDone(int cam); void selectStorageLocation(); void cameraConfigurationAccepted(); void cameraConfigurationAborted(); @@ -111,6 +111,7 @@ private: Writer *writer0, *writer1; CameraLayout layout; bool grabbing, stopRequest, writing, labelSwitch, dryRun, cameraOpened, camsconfigured; + bool iswriting[2] = {0, 0}; QPalette progressPalette; QString activeLabelStyleHigh = "QLabel { font-size: 10pt;font-family: Arial; color : red; }"; QString activeLabelStyleLow = "QLabel { font-size: 10pt;font-family: Arial; color : cmyk(0, 255, 255, 0, 50); }"; diff --git a/writer.cpp b/writer.cpp index 116205f..fe89a7d 100644 --- a/writer.cpp +++ b/writer.cpp @@ -11,6 +11,7 @@ void Writer::setVideoSpecs(VideoSpecs specs) { } void Writer::setProjectMetadata(ProjectMetadata mdata) { + qDebug() << "received metadata"; metadata = mdata; metadata_valid = true; } @@ -35,7 +36,7 @@ void Writer::run() { // Releases all pylon resources. // PylonTerminate(); // Return with error code 1. - emit writingDone(); + emit writingDone(this->cam_number); return; } Pylon::CVideoWriter videoWriter; @@ -137,5 +138,5 @@ void Writer::run() { } else { std::cerr << "Got no video specifications, not writing!" << std::endl; } - emit writingDone(); + emit writingDone(cam_number); } diff --git a/writer.h b/writer.h index 5765f68..3c0f220 100644 --- a/writer.h +++ b/writer.h @@ -27,8 +27,8 @@ class Writer : public QThread { Q_OBJECT public: - explicit Writer(ImageBuffer*buffer, QObject *parent = nullptr) : - QThread(parent), buffer(buffer) {} + explicit Writer(ImageBuffer*buffer, int number, QObject *parent = nullptr) : + QThread(parent), buffer(buffer), cam_number(number) {} void setVideoSpecs(VideoSpecs specs); void setProjectMetadata(ProjectMetadata mdata); @@ -37,9 +37,10 @@ public: signals: void terminated(); - void writingDone(); + void writingDone(int cam); private: + int cam_number; ImageBuffer *buffer; VideoSpecs videoSpecs; ProjectMetadata metadata;