20 #include <QApplication>
22 #include <QDesktopWidget>
25 #pragma GCC diagnostic push
26 #pragma GCC diagnostic ignored "-Wold-style-cast"
27 #include <libavdevice/avdevice.h>
28 #include <libavformat/avformat.h>
29 #pragma GCC diagnostic pop
37 #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
90 AVFormatContext* fctx =
nullptr;
93 std::string devString;
99 if (
devName.startsWith(
"x11grab#")) {
101 format = idesktopFormat;
102 }
else if (
devName.startsWith(
"gdigrab#")) {
104 format = idesktopFormat;
109 devString =
devName.toStdString();
110 if (avformat_open_input(&fctx, devString.c_str(), format, options) < 0) {
115 #if FF_API_PROBESIZE_32
116 aduration = fctx->max_analyze_duration2 = 0;
118 aduration = fctx->max_analyze_duration = 0;
121 if (avformat_find_stream_info(fctx,
nullptr) < 0) {
122 avformat_close_input(&fctx);
126 #if FF_API_PROBESIZE_32
127 fctx->max_analyze_duration2 = aduration;
129 fctx->max_analyze_duration = aduration;
158 qDebug() <<
"Tried to open the null device";
163 if (mode.
FPS > 0.0f) {
166 qWarning() <<
"VideoMode could be invalid!";
169 const std::string videoSize = QStringLiteral(
"%1x%2").arg(mode.
width).arg(mode.
height).toStdString();
170 const std::string framerate = QString{}.setNum(FPS).toStdString();
172 AVDictionary* options =
nullptr;
176 else if (
devName.startsWith(
"x11grab#")) {
179 screen.setWidth(mode.
width);
180 screen.setHeight(mode.
height);
182 QScreen* defaultScreen = QApplication::primaryScreen();
183 qreal pixRatio = defaultScreen->devicePixelRatio();
185 screen = defaultScreen->size();
188 screen.setWidth((screen.width() * pixRatio) - 2);
189 screen.setHeight((screen.height() * pixRatio) - 2);
191 const std::string screenVideoSize = QStringLiteral(
"%1x%2").arg(screen.width()).arg(screen.height()).toStdString();
192 av_dict_set(&options,
"video_size", screenVideoSize.c_str(), 0);
193 devName += QString(
"+%1,%2").arg(QString().setNum(mode.
x), QString().setNum(mode.
y));
195 av_dict_set(&options,
"framerate", framerate.c_str(), 0);
196 }
else if (iformat->name == QString(
"video4linux2,v4l2") && mode) {
197 av_dict_set(&options,
"video_size", videoSize.c_str(), 0);
198 av_dict_set(&options,
"framerate", framerate.c_str(), 0);
201 if (pixelFormatStr !=
"unknown" && pixelFormatStr !=
"invalid") {
202 const char* pixel_format = pixelFormatStr.c_str();
203 av_dict_set(&options,
"pixel_format", pixel_format, 0);
208 else if (
devName.startsWith(
"gdigrab#")) {
210 const std::string offsetX = QString().setNum(mode.
x).toStdString();
211 const std::string offsetY = QString().setNum(mode.
y).toStdString();
212 av_dict_set(&options,
"framerate", framerate.c_str(), 0);
213 av_dict_set(&options,
"offset_x", offsetX.c_str(), 0);
214 av_dict_set(&options,
"offset_y", offsetY.c_str(), 0);
215 av_dict_set(&options,
"video_size", videoSize.c_str(), 0);
216 }
else if (iformat->name == QString(
"dshow") && mode) {
217 av_dict_set(&options,
"video_size", videoSize.c_str(), 0);
218 av_dict_set(&options,
"framerate", framerate.c_str(), 0);
222 else if (iformat->name == QString(
"avfoundation")) {
224 av_dict_set(&options,
"video_size", videoSize.c_str(), 0);
225 av_dict_set(&options,
"framerate", framerate.c_str(), 0);
227 av_dict_set(&options,
"framerate", framerate.c_str(), 0);
228 av_dict_set_int(&options,
"capture_cursor", 1, 0);
229 av_dict_set_int(&options,
"capture_mouse_clicks", 1, 0);
234 qWarning().nospace() <<
"No known options for " << iformat->name <<
", using defaults.";
240 av_dict_free(&options);
268 avformat_close_input(&
context);
280 QVector<QPair<QString, QString>> devices;
287 if (!(s = avformat_alloc_context()))
290 if (!iformat->priv_class || !AV_IS_INPUT_DEVICE(iformat->priv_class->category)) {
291 avformat_free_context(s);
295 s->iformat = iformat;
296 if (s->iformat->priv_data_size > 0) {
297 s->priv_data = av_mallocz(s->iformat->priv_data_size);
299 avformat_free_context(s);
302 if (s->iformat->priv_class) {
303 *
static_cast<const AVClass**
>(s->priv_data) = s->iformat->priv_class;
304 av_opt_set_defaults(s->priv_data);
307 s->priv_data =
nullptr;
311 AVDeviceInfoList* devlist =
nullptr;
312 AVDictionary* tmp =
nullptr;
313 av_dict_copy(&tmp,
nullptr, 0);
314 if (av_opt_set_dict2(s, &tmp, AV_OPT_SEARCH_CHILDREN) < 0) {
316 avformat_free_context(s);
319 avdevice_list_devices(s, &devlist);
321 avformat_free_context(s);
323 qWarning() <<
"avdevice_list_devices failed";
328 devices.resize(devlist->nb_devices);
329 for (
int i = 0; i < devlist->nb_devices; ++i) {
330 AVDeviceInfo* dev = devlist->devices[i];
331 devices[i].first = dev->device_name;
332 devices[i].second = dev->device_description;
334 avdevice_free_list_devices(&devlist);
345 QVector<QPair<QString, QString>> devices;
347 devices.append({
"none", QObject::tr(
"None",
"No camera device set")});
355 else if (iformat->name == QString(
"dshow"))
359 else if (iformat->name == QString(
"video4linux2,v4l2"))
363 else if (iformat->name == QString(
"avfoundation"))
369 if (idesktopFormat) {
370 if (idesktopFormat->name == QString(
"x11grab")) {
371 QString dev =
"x11grab#";
372 QByteArray display = qgetenv(
"DISPLAY");
374 if (display.isNull())
377 dev += display.constData();
379 devices.push_back(QPair<QString, QString>{
380 dev, QObject::tr(
"Desktop",
"Desktop as a camera input for screen sharing")});
382 if (idesktopFormat->name == QString(
"gdigrab"))
383 devices.push_back(QPair<QString, QString>{
385 QObject::tr(
"Desktop",
"Desktop as a camera input for screen sharing")});
404 for (
const QPair<QString, QString>& device : devlist)
405 if (defaultdev == device.first)
408 if (devlist.isEmpty())
411 return devlist[0].first;
421 return devName.startsWith(
"x11grab") ||
devName.startsWith(
"gdigrab");
431 QVector<VideoMode> result;
433 std::for_each(screens.begin(), screens.end(), [&result](QScreen* s) {
434 QRect rect = s->geometry();
435 QPoint p = rect.topLeft();
436 qreal pixRatio = s->devicePixelRatio();
438 VideoMode mode(rect.width() * pixRatio, rect.height() * pixRatio, p.x() * pixRatio,
440 result.push_back(mode);
460 else if (iformat->name == QString(
"dshow"))
464 else if (iformat->name == QString(
"video4linux2,v4l2"))
468 else if (iformat->name == QString(
"avfoundation"))
472 qWarning() <<
"Video mode listing not implemented for input " << iformat->name;
487 return QString(
"unknown");
517 avdevice_register_all();
521 idesktopFormat = av_find_input_format(
"x11grab");
524 idesktopFormat = av_find_input_format(
"gdigrab");
529 if ((iformat = av_find_input_format(
"v4l2")))
534 if ((iformat = av_find_input_format(
"dshow")))
536 if ((iformat = av_find_input_format(
"vfwcap")))
541 if ((iformat = av_find_input_format(
"avfoundation")))
543 if ((iformat = av_find_input_format(
"qtkit")))
547 qWarning() <<
"No valid input format found";