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 
23 int 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
12 class MainWidget : public QWidget
13 {
14  Q_OBJECT
15 
16 public:
17  explicit MainWidget();
18  virtual ~MainWidget() {}
19 
20 private:
21  void Load(const QString& driver);
22 
23 protected:
24  Cvb::Movie2::RecorderPtr recorder_;
25 
26 private:
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)
51  : Cvb::SingleStreamHandler(stream)
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 
STL class.
Everything is fine, a new image arrived.
Settings for initializing a direct show engine recorder.
Definition: recording_settings.hpp:93
Handler object for a single stream.
Definition: decl_single_stream_handler.hpp:32
STL class.
View to display an image.
Definition: decl_image_view.hpp:70
1 //
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 
29 MainWidget::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
120 void 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 }
Cvb::String QtToCvb(const QString text) noexcept
Convenience converter for strings.
Definition: ui.hpp:239
void SetUploadMode(Cvb::UI::UploadMode uploadMode)
Set the current upload mode.
Definition: decl_image_view.hpp:354
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
QString homePath()
QChar separator()
bool isEmpty() const const
void clicked(bool checked)
QString CvbToQt(const Cvb::String &text) noexcept
Convenience converter for strings.
Definition: ui.hpp:254
STL class.
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString & replace(int position, int n, QChar after)
Recorder writes single-plane monochrome data.
void stateChanged(int state)
View to display an image.
Definition: decl_image_view.hpp:70
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)
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
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)