diff --git a/src/avatarmanipulation.cpp b/src/avatarmanipulation.cpp index 3ad61cca64c683c4eed69e0d2bc99adf6fca2e89..f3d343201340c8a301d0bf69b81c8a7ffc4e7608 100644 --- a/src/avatarmanipulation.cpp +++ b/src/avatarmanipulation.cpp @@ -118,7 +118,7 @@ avatar_manipulation_dispose(GObject *object) /* make sure we stop the preview and the video widget */ if (priv->video_started_by_avatar_manipulation) - priv->avModel_->stopPreview(priv->avModel_->getDefaultDevice()); + priv->avModel_->stopPreview("camera://" + priv->avModel_->getDefaultDevice()); if (priv->video_widget) { gtk_container_remove(GTK_CONTAINER(priv->frame_video), priv->video_widget); priv->video_widget = NULL; @@ -264,7 +264,7 @@ set_state(AvatarManipulation *self, AvatarManipulationState state) /* make sure video widget and camera is not running */ if (priv->video_started_by_avatar_manipulation) { - priv->avModel_->stopPreview(priv->avModel_->getDefaultDevice()); + priv->avModel_->stopPreview("camera://" + priv->avModel_->getDefaultDevice()); QObject::disconnect(priv->local_renderer_connection); } if (priv->video_widget) { @@ -288,8 +288,7 @@ set_state(AvatarManipulation *self, AvatarManipulationState state) // local renderer, but set as "remote" so that it takes up the whole screen const lrc::api::video::Renderer* prenderer = nullptr; try { - prenderer = &priv->avModel_->getRenderer( - lrc::api::video::PREVIEW_RENDERER_ID); + prenderer = &priv->avModel_->getRenderer("camera://" + priv->avModel_->getDefaultDevice()); } catch (const std::out_of_range& e) {} priv->video_started_by_avatar_manipulation = @@ -305,7 +304,7 @@ set_state(AvatarManipulation *self, AvatarManipulationState state) &*priv->avModel_, &lrc::api::AVModel::rendererStarted, [=](const QString& id) { - if (id != lrc::api::video::PREVIEW_RENDERER_ID) + if (id.indexOf( priv->avModel_->getDefaultDevice()) == -1) return; try { const auto* prenderer = @@ -318,7 +317,7 @@ set_state(AvatarManipulation *self, AvatarManipulationState state) g_warning("Cannot start preview"); } }); - priv->avModel_->startPreview(priv->avModel_->getDefaultDevice()); + priv->avModel_->startPreview("camera://" + priv->avModel_->getDefaultDevice()); } /* available actions: take snapshot, return*/ @@ -331,7 +330,7 @@ set_state(AvatarManipulation *self, AvatarManipulationState state) { /* make sure video widget and camera is not running */ if (priv->video_started_by_avatar_manipulation) - priv->avModel_->stopPreview(priv->avModel_->getDefaultDevice()); + priv->avModel_->stopPreview("camera://" + priv->avModel_->getDefaultDevice()); if (priv->video_widget) { gtk_container_remove(GTK_CONTAINER(priv->frame_video), priv->video_widget); priv->video_widget = NULL; diff --git a/src/chatview.cpp b/src/chatview.cpp index ed1268360d7ad3dfb51ce1bdb728ef1f12b2e045..558f056b3b83c141301ff1d080330b79944ca780 100644 --- a/src/chatview.cpp +++ b/src/chatview.cpp @@ -436,7 +436,7 @@ on_record_closed(GtkPopover*, ChatView *self) priv->cpp->current_action_ = RecordAction::RECORD; if (priv->timer_duration) g_source_remove(priv->timer_duration); if (priv->is_video_record) { - priv->cpp->avModel_->stopPreview(priv->cpp->avModel_->getDefaultDevice()); + priv->cpp->avModel_->stopPreview("camera://" + priv->cpp->avModel_->getDefaultDevice()); QObject::disconnect(priv->local_renderer_connection); } priv->duration = 0; @@ -484,7 +484,7 @@ chat_view_show_recorder(ChatView *self, int pt_x, int pt_y, bool is_video_record priv->is_video_record = is_video_record; if (is_video_record) - priv->cpp->avModel_->startPreview(priv->cpp->avModel_->getDefaultDevice()); + priv->cpp->avModel_->startPreview("camera://" + priv->cpp->avModel_->getDefaultDevice()); std::string css = is_video_record ? ".record-button { background: rgba(0, 0, 0, 0.2); border-radius: 50%; border: 0; transition: all 0.3s ease; } \ .record-button:hover { background: rgba(0, 0, 0, 0.2); border-radius: 50%; border: 0; transition: all 0.3s ease; } \ .label_time { color: white; }" @@ -1287,7 +1287,7 @@ on_main_action_clicked(ChatView *self) } gtk_widget_destroy(priv->record_popover); priv->cpp->current_action_ = RecordAction::RECORD; - priv->cpp->avModel_->stopPreview(priv->cpp->avModel_->getDefaultDevice()); + priv->cpp->avModel_->stopPreview("camera://" + priv->cpp->avModel_->getDefaultDevice()); QObject::disconnect(priv->local_renderer_connection); break; } @@ -1305,7 +1305,7 @@ init_video_widget(ChatView* self) const lrc::api::video::Renderer* prenderer = nullptr; try { prenderer = &priv->cpp->avModel_->getRenderer( - lrc::api::video::PREVIEW_RENDERER_ID); + "camera://" + priv->cpp->avModel_->getDefaultDevice()); } catch (const std::out_of_range& e) {} priv->video_started_by_settings = @@ -1322,7 +1322,7 @@ init_video_widget(ChatView* self) &*priv->cpp->avModel_, &lrc::api::AVModel::rendererStarted, [=](const QString& id) { - if (id != lrc::api::video::PREVIEW_RENDERER_ID + if (id.indexOf(priv->cpp->avModel_->getDefaultDevice()) == -1 || !priv->readyToRecord_) return; try { diff --git a/src/currentcallview.cpp b/src/currentcallview.cpp index 48a2feff5d34a5beef72e32c75b1ca00c9d10428..6e6c3d1f8844f016ebfcdcf3b300fa360831ba9b 100644 --- a/src/currentcallview.cpp +++ b/src/currentcallview.cpp @@ -1436,7 +1436,7 @@ CppImpl::setCallInfo() // local renderer const lrc::api::video::Renderer* previewRenderer = &avModel_->getRenderer( - lrc::api::video::PREVIEW_RENDERER_ID); + "camera://" + avModel_->getDefaultDevice()); if (previewRenderer->isRendering()) { video_widget_add_new_renderer(VIDEO_WIDGET(widgets->video_widget), avModel_, previewRenderer, VIDEO_RENDERER_LOCAL); @@ -1478,11 +1478,11 @@ CppImpl::setCallInfo() &*avModel_, &lrc::api::AVModel::rendererStarted, [=](const QString& id) { - if (id == lrc::api::video::PREVIEW_RENDERER_ID) { + if (id.indexOf("://") != -1) { try { // local renderer const lrc::api::video::Renderer* previewRenderer = - &avModel_->getRenderer(lrc::api::video::PREVIEW_RENDERER_ID); + &avModel_->getRenderer(id); if (previewRenderer->isRendering()) { video_widget_add_new_renderer(VIDEO_WIDGET(widgets->video_widget), avModel_, previewRenderer, VIDEO_RENDERER_LOCAL); diff --git a/src/mediasettingsview.cpp b/src/mediasettingsview.cpp index 2ce842f0aa4daea4bd7c706e0f1fa5cd8fbf902e..01251f599408383c831ced1ce635ab5d1568e4c0 100644 --- a/src/mediasettingsview.cpp +++ b/src/mediasettingsview.cpp @@ -390,7 +390,7 @@ CppImpl::drawVideoDevices() gtk_widget_hide(widgets->video_resolution_row); gtk_widget_hide(widgets->video_framerate_row); if (widgets->video_widget) - avModel_->stopPreview(avModel_->getDefaultDevice()); + avModel_->stopPreview("camera://" + avModel_->getDefaultDevice()); return; } if (gtk_widget_get_visible(widgets->no_camera_row)) { @@ -445,7 +445,7 @@ media_settings_view_dispose(GObject *object) /* make sure to stop the preview if this view is getting destroyed */ if (priv->video_started_by_settings) { - priv->cpp->avModel_->stopPreview(priv->cpp->avModel_->getDefaultDevice()); + priv->cpp->avModel_->stopPreview("camera://" + priv->cpp->avModel_->getDefaultDevice()); priv->video_started_by_settings = FALSE; } @@ -852,7 +852,7 @@ media_settings_view_show_preview(MediaSettingsView *self, gboolean show_preview) &*priv->cpp->avModel_, &lrc::api::AVModel::rendererStarted, [=](const QString& id) { - if (id != lrc::api::video::PREVIEW_RENDERER_ID) + if (id.indexOf(priv->cpp->avModel_->getDefaultDevice()) == -1) return; const auto* prenderer = &priv->cpp->avModel_->getRenderer(id); video_widget_add_new_renderer( @@ -869,7 +869,7 @@ media_settings_view_show_preview(MediaSettingsView *self, gboolean show_preview) const lrc::api::video::Renderer* prenderer = nullptr; try { prenderer = &priv->cpp->avModel_->getRenderer( - lrc::api::video::PREVIEW_RENDERER_ID); + "camera://" + priv->cpp->avModel_->getDefaultDevice()); } catch (const std::out_of_range& e) { } if (prenderer){ @@ -879,13 +879,13 @@ media_settings_view_show_preview(MediaSettingsView *self, gboolean show_preview) prenderer, VIDEO_RENDERER_REMOTE); } else - priv->cpp->avModel_->startPreview(priv->cpp->avModel_->getDefaultDevice()); + priv->cpp->avModel_->startPreview("camera://" + priv->cpp->avModel_->getDefaultDevice()); priv->cpp->avModel_->startAudioDevice(); priv->cpp->avModel_->setAudioMeterState(true); } else { if (priv->video_started_by_settings) { - priv->cpp->avModel_->stopPreview(priv->cpp->avModel_->getDefaultDevice()); + priv->cpp->avModel_->stopPreview("camera://" + priv->cpp->avModel_->getDefaultDevice()); QObject::disconnect(priv->local_renderer_connection); QObject::disconnect(priv->device_event_connection); priv->video_started_by_settings = FALSE; diff --git a/src/video/video_widget.cpp b/src/video/video_widget.cpp index 09e8900597d563a519927db1cc0f000c616810ec..d52308ca410914d0618b1c458de8b5447bc74ff7 100644 --- a/src/video/video_widget.cpp +++ b/src/video/video_widget.cpp @@ -141,6 +141,8 @@ public: VideoWidget* self = nullptr; // The GTK widget itself AccountInfoPointer const *accountInfo = nullptr; QString callId {}; + + std::vector<uint8_t> buffer; }; } @@ -990,7 +992,7 @@ free_pixels(guchar *pixels, gpointer) } static void -clutter_render_image(VideoWidgetRenderer* wg_renderer) +clutter_render_image(VideoWidgetRenderer* wg_renderer, VideoWidgetPrivate* priv) { auto actor = wg_renderer->actor; g_return_if_fail(CLUTTER_IS_ACTOR(actor)); @@ -1055,10 +1057,27 @@ clutter_render_image(VideoWidgetRenderer* wg_renderer) auto v_renderer = wg_renderer->v_renderer; if (!v_renderer) return; - auto frame_data = v_renderer->currentFrame().ptr; - if (!frame_data) - return; + auto frame = v_renderer->currentFrame(); + + auto size = 0; + unsigned int width = v_renderer->size().width(); + unsigned int height = v_renderer->size().height(); + if (v_renderer->useDirectRenderer()) { + size = frame.storage.size(); + } else { + size = frame.size; + } + if (size != 0 && size == width * height * 4) { + if (v_renderer->useDirectRenderer()) { + priv->cpp->buffer = std::move(frame.storage); + } else { + priv->cpp->buffer.resize(size); + std::move(frame.ptr, frame.ptr + size, priv->cpp->buffer.begin()); + } + } else { + return; + } image_new = clutter_image_new(); g_return_if_fail(image_new); @@ -1069,7 +1088,7 @@ clutter_render_image(VideoWidgetRenderer* wg_renderer) GError *error = nullptr; clutter_image_set_data( CLUTTER_IMAGE(image_new), - frame_data, + priv->cpp->buffer.data(), COGL_PIXEL_FORMAT_BGRA_8888, res.width(), res.height(), @@ -1090,9 +1109,9 @@ clutter_render_image(VideoWidgetRenderer* wg_renderer) /* conversion from BGRA to RGB */ for(int i = 0, j = 0 ; i < res.width() * res.height() * 4 ; i += 4, j += 3 ) { - pixbuf_frame_data[j + 0] = frame_data[i + 2]; - pixbuf_frame_data[j + 1] = frame_data[i + 1]; - pixbuf_frame_data[j + 2] = frame_data[i + 0]; + pixbuf_frame_data[j + 0] = priv->cpp->buffer[i + 2]; + pixbuf_frame_data[j + 1] = priv->cpp->buffer[i + 1]; + pixbuf_frame_data[j + 2] = priv->cpp->buffer[i + 0]; } if (wg_renderer->snapshot) { @@ -1129,9 +1148,9 @@ check_frame_queue(VideoWidget *self) return TRUE; /* display renderer's frames */ - if (priv->show_preview) - clutter_render_image(priv->local); - clutter_render_image(priv->remote); + if (priv->show_preview && priv->local) + clutter_render_image(priv->local, priv); + clutter_render_image(priv->remote, priv); // HACK: https://gitlab.gnome.org/GNOME/clutter-gtk/-/issues/11 // Because the CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT change the ratio of the widget inside the actor @@ -1194,6 +1213,7 @@ free_video_widget_renderer(VideoWidgetRenderer *renderer) { QObject::disconnect(renderer->render_stop); QObject::disconnect(renderer->render_start); + renderer_stop(renderer); if (renderer->snapshot) g_object_unref(renderer->snapshot); g_free(renderer);