CVB++ 14.0
Movie2/QtMovie2

This example requires Qt5 >= 5.9 setup for building.

You may build it with Ubuntu 18.04's default Qt5 after installing:

1
2
3
4
5
6
7#ifdef _MSC_VER
8#pragma warning ( push, 1)
9#pragma warning ( disable : 4702)
10#endif
11
12#include <QApplication>
13#include <QIcon>
14
15#include "main_widget.hpp"
16
17
18
19#ifdef _MSC_VER
20#pragma warning ( pop)
21#endif
22
23int main(int argc, char* argv[])
24{
25 QApplication application(argc, argv);
26 MainWidget mainWidget;
27 mainWidget.setWindowIcon(QIcon(":/qttutorial.png"));
28 mainWidget.show();
29 application.exec();
30}
1#pragma once
2
3#include <QWidget>
4#include <QCheckBox>
5
6
7#include <cvb/movie2/recorder.hpp>
8#include <cvb/ui/image_view.hpp>
9#include <cvb/async/single_stream_handler.hpp>
10
11// The main widget
12class MainWidget : public QWidget
13{
14 Q_OBJECT
15
16public:
17 explicit MainWidget();
18 virtual ~MainWidget() {}
19
20private:
21 void Load(const QString& driver);
22
23protected:
25
26private:
27
28 Cvb::UI::ImageView* imageView_ = nullptr;
30
31 QLineEdit* movieFile_ = nullptr;
32 QCheckBox* grabCheckBox_ = nullptr;
33
34 // The custom stream handler to handle image processing while grabbing
35 class CustomStreamHandler :
37 {
38 public:
39 static std::unique_ptr<CustomStreamHandler> Create(const Cvb::StreamPtr& stream, MainWidget& mainWidget)
40 {
41 return std::unique_ptr<CustomStreamHandler>(new CustomStreamHandler(stream, mainWidget));
42 }
43
44 ~CustomStreamHandler()
45 {
46 TryFinish();
47 }
48
49 private:
50 CustomStreamHandler(const Cvb::StreamPtr& stream, MainWidget& mainWidget)
52 , mainWidget_(mainWidget)
53 {}
54
55 void HandleAsyncStream(const Cvb::StreamPtr & stream) override
56 {
57 auto waitResult = stream->WaitFor(std::chrono::milliseconds(10000));
58 if (waitResult.Status != Cvb::WaitStatus::Ok)
59 return;
60
61 // Write the image to the recorder file
62 if (mainWidget_.recorder_)
63 mainWidget_.recorder_->Write(*waitResult.Image);
64 }
65
66 MainWidget& mainWidget_;
67
68 };
69
71
72};
73
74
Handler object for a single stream.
Definition: decl_single_stream_handler.hpp:34
Settings for initializing a direct show engine recorder.
Definition: recording_settings.hpp:94
View to display an image.
Definition: decl_image_view.hpp:75
@ Ok
Everything is fine, a new image arrived.
1
4//
5#include "main_widget.hpp"
6
7#include <QDir>
8#include <QFileDialog>
9#include <QGridLayout>
10#include <QLabel>
11#include <QLineEdit>
12#include <QPushButton>
13#include <QMessageBox>
14#include <QComboBox>
15
16
17#include <cvb/image.hpp>
18#include <cvb/device_factory.hpp>
19#include <cvb/device.hpp>
20#include <cvb/driver/driver.hpp>
21#include <cvb/driver/stream.hpp>
22#include <cvb/size_2d.hpp>
23
24
25#include <cvb/movie2/recorder.hpp>
26#include <cvb/movie2/recording_settings.hpp>
27
28
29MainWidget::MainWidget()
30 : QWidget()
31{
32 auto layout = new QGridLayout;
33 auto fileName = QDir::homePath() + QDir::separator() + "Documents" + QDir::separator() + "Movie2ExampleVideo.avi";
34 movieFile_ = new QLineEdit(fileName);
35 auto btnFileSelect = new QPushButton("Record to...");
36
37 QObject::connect(btnFileSelect, &QPushButton::clicked, [=]() {
38 auto file = QFileDialog::getSaveFileName(this, "Record Video", fileName, "Video Files (*.avi)");
39 if (file.isEmpty())
40 file = fileName;
41 movieFile_->setText(file);
42 });
43
44 imageView_ = new Cvb::UI::ImageView;
46 imageView_->SetRenderEngine(Cvb::UI::RenderEngine::Raster);
47 imageView_->resize(800, 600);
48
49
50 QPushButton* openImgBtn = new QPushButton("Open Image");
51 QObject::connect(openImgBtn, &QPushButton::clicked, [=]()
52 {
53 auto driver = QFileDialog::getOpenFileName(this, "Load Image"
54 , Cvb::UI::CvbToQt(Cvb::InstallPath() + CVB_LIT("tutorial"))
55 , "CVB Emulator Image Lists (*.emu);;CVB Drivers (*.vin);;Images (*.bmp *.png *.tif *.tiff *.jpg)");
56
57 Load(driver);
58 });
59
60 grabCheckBox_ = new QCheckBox("Grab");
61 QObject::connect(grabCheckBox_, &QCheckBox::stateChanged, [=](int state)
62 {
63 if (state == Qt::CheckState::Checked)
64 {
65 // Start streaming
66 streamHandler_->Run();
67 assert(streamHandler_->IsActive());
68 }
69 else
70 {
71 // Disable possible blocking of the UI if necessary
72 bool wait = imageView_->IsWaitForRepaintEnabled();
73 if (wait)
74 imageView_->SetWaitForRepaintEnabled(!wait);
75 // Stop streaming
76 streamHandler_->Finish();
77 // Reset the previous state
78 imageView_->SetWaitForRepaintEnabled(wait);
79 assert(!streamHandler_->IsActive());
80 }
81 });
82
83 auto recordCheckBox = new QCheckBox("Record");
84 QObject::connect(recordCheckBox, &QPushButton::clicked, [=]()
85 {
86 if (!recorder_)
87 {
88 // Start recording, Write to avi file is in HandleAsyncStream
89 recorder_ = Cvb::Movie2::Recorder::Create(Cvb::UI::QtToCvb(movieFile_->text()), imageView_->Image()->Size(),
91 }
92 else
93 {
94 // Stop recording (necessary to close the recording file correctly)
95 recorder_.reset();
96 }
97 });
98
99 // Show recording codecs of direct show engine
100 auto codecComboBox = new QComboBox();
101 auto codecs = settings_.AvailableCodecs();
102 for(const auto & codec : codecs)
103 codecComboBox->addItem(Cvb::UI::CvbToQt(codec));
104 codecComboBox->setCurrentText(Cvb::UI::CvbToQt(settings_.Codec()));
105
106 layout->addWidget(btnFileSelect, 0, 0);
107 layout->addWidget(movieFile_, 0, 1);
108 layout->addWidget(openImgBtn, 0, 2);
109 layout->addWidget(grabCheckBox_, 0, 3);
110 layout->addWidget(recordCheckBox, 1, 2, 1, 2);
111 layout->addWidget(codecComboBox, 2, 2, 1, -1);
112 layout->addWidget(imageView_, 1, 0, 3, 2);
113
114 Load(Cvb::UI::CvbToQt(Cvb::InstallPath() + CVB_LIT("tutorial/ClassicSwitch.emu")));
115
116 setLayout(layout);
117}
118
119// Load an image or driver
120void MainWidget::Load(const QString& driver)
121{
122 QString fileName = driver;
123 if (fileName.isEmpty())
124 return;
125
126 if (fileName.contains(".emu", Qt::CaseInsensitive))
127 fileName = fileName.replace("/", "\\"); // necessary for emu files
128
129 try
130 {
131 // Either load an image or device (vin or emu)
132 if (fileName.contains(".bmp", Qt::CaseInsensitive) || fileName.contains(".png", Qt::CaseInsensitive) || fileName.contains(".tif", Qt::CaseInsensitive) || fileName.contains(".jpg", Qt::CaseInsensitive))
133 {
135 imageView_->Refresh(image);
136 // Disable the grab check box for images
137 grabCheckBox_->setEnabled(false);
138 }
139 else
140 {
141 auto device = Cvb::DeviceFactory::Open(Cvb::UI::QtToCvb(fileName), Cvb::AcquisitionStack::Vin);
142 // Connect the device with the ImageView
143 imageView_->Refresh(device->DeviceImage(), Cvb::UI::AutoRefresh::On);
144 // Create a stream handler
145 streamHandler_ = CustomStreamHandler::Create(device->Stream(), *this);
146 // Enable the grab check box for devices
147 grabCheckBox_->setEnabled(true);
148 }
149 }
150 catch (const std::exception& error)
151 {
152 QMessageBox::critical(this, "Error", QString(error.what()));
153 }
154}
static std::shared_ptr< T > Open(const String &provider, AcquisitionStack acquisitionStack=AcquisitionStack::PreferVin)
Opens a device with the given provider with its default board and port (if applicable).
Definition: decl_device_factory.hpp:50
static std::unique_ptr< Image > Load(const String &fileName)
Loads an image with the given file name.
Definition: detail_image.hpp:32
static std::unique_ptr< Recorder > Create(const String &path, Size2D< int > size, RecorderPixelFormat pixelFormat, const RecordingSettings &settings)
Creates a recorder object writing video streams with the given pixel format and recording engine.
Definition: recorder.hpp:96
void SetUploadMode(Cvb::UI::UploadMode uploadMode)
Set the current upload mode.
Definition: decl_image_view.hpp:354
@ Mono
Recorder writes single-plane monochrome data.
Cvb::String QtToCvb(const QString text) noexcept
Convenience converter for strings.
Definition: ui.hpp:239
QString CvbToQt(const Cvb::String &text) noexcept
Convenience converter for strings.
Definition: ui.hpp:254
void clicked(bool checked)
void stateChanged(int state)
QString homePath()
QChar separator()
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString & replace(int position, int n, QChar after)