Fix preview deadlock + preview on call connection + 1-1 call

This commit is contained in:
Julien Wadel 2024-04-04 10:29:04 +02:00
parent 2f6a4828cb
commit 41359252c9
5 changed files with 29 additions and 249 deletions

View file

@ -99,6 +99,8 @@ QQuickFramebufferObject::Renderer *CameraGui::createRenderer(bool resetWindowId)
lInfo() << "[Camera] (" << qmlName << ") " << (resetWindowId ? "Resetting" : "Setting")
<< " Camera to ParticipantDeviceModel";
if (resetWindowId) {
renderer = (QQuickFramebufferObject::Renderer *)device->getNativeVideoWindowId();
if (renderer) device->setNativeVideoWindowId(NULL);
} else {
renderer = (QQuickFramebufferObject::Renderer *)device->createNativeVideoWindowId();
if (renderer) device->setNativeVideoWindowId(renderer);

View file

@ -66,15 +66,19 @@ QQuickFramebufferObject::Renderer *PreviewManager::subscribe(const CameraGui *ca
} else {
lDebug() << log().arg("Resubscribing") << itCandidate->first->getQmlName();
}
App::postModelBlock(
[&renderer, isFirst = (itCandidate == mCandidates.begin()), name = itCandidate->first->getQmlName()]() {
renderer =
(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId();
if (isFirst) {
lDebug() << "[PreviewManager] " << name << " Set Native Preview Id";
CoreModel::getInstance()->getCore()->setNativePreviewWindowId(renderer);
}
});
App::postModelBlock([&renderer, isFirst = (itCandidate == mCandidates.begin()),
name = itCandidate->first->getQmlName()]() {
renderer =
(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId();
if (!renderer) { // TODO debug
renderer =
(QQuickFramebufferObject::Renderer *)CoreModel::getInstance()->getCore()->createNativePreviewWindowId();
}
if (isFirst) {
lDebug() << "[PreviewManager] " << name << " Set Native Preview Id";
CoreModel::getInstance()->getCore()->setNativePreviewWindowId(renderer);
}
});
itCandidate->second = renderer;
mCounterMutex.unlock();
return renderer;
@ -114,9 +118,9 @@ void PreviewManager::unsubscribe(QObject *sender) {
}
void PreviewManager::activate() {
App::postModelSync([]() { CoreModel::getInstance()->getCore()->enableVideoPreview(true); });
App::postModelBlock([]() { CoreModel::getInstance()->getCore()->enableVideoPreview(true); });
}
void PreviewManager::deactivate() {
App::postModelSync([]() { CoreModel::getInstance()->getCore()->enableVideoPreview(false); });
App::postModelBlock([]() { CoreModel::getInstance()->getCore()->enableVideoPreview(false); });
}

View file

@ -26,8 +26,9 @@ Window {
console.log("CALL", call)
// if conference, the main item is only
// displayed when state is connected
if (!conferenceInfo)
if (call && middleItemStackView.currentItem != inCallItem) middleItemStackView.replace(inCallItem)
if (call && middleItemStackView.currentItem != inCallItem
&& (!conferenceInfo || conference) )
middleItemStackView.replace(inCallItem)
}
property var callObj

View file

@ -28,7 +28,7 @@ Item {
: null
property string peerAddress:peerAddressObj ? peerAddressObj.value : ""
property var identityAddress: account ? UtilsCpp.getDisplayName(account.core.identityAddress) : null
property bool cameraEnabled: previewEnabled
property bool cameraEnabled: previewEnabled || participantDevice && participantDevice.core.videoEnabled
property string qmlName
Rectangle {
@ -79,7 +79,8 @@ Item {
Timer{
id: resetTimer
interval: 1
onTriggered: {cameraLoader.reset=true; cameraLoader.reset=false;}
triggeredOnStart: true
onTriggered: {cameraLoader.reset = !cameraLoader.reset}
}
active: mainItem.visible && mainItem.cameraEnabled && !mainItem.reset
onActiveChanged: console.log("("+mainItem.qmlName+") Camera active " + active)
@ -100,12 +101,12 @@ Item {
participantDevice: mainItem.participantDevice
isPreview: mainItem.previewEnabled
onRequestNewRenderer: {
console.log("Request new renderer")
console.log("Request new renderer for " +mainItem.qmlName)
resetTimer.restart()
}
layer.enabled: true
}
ShaderEffect {
id: roundEffect
property variant src: cameraItem

View file

@ -31,7 +31,6 @@ Item{
Sticker {
id: activeSpeakerSticker
//call: mainItem.call
Layout.fillWidth: true
Layout.fillHeight: true
call: mainItem.call
@ -47,6 +46,7 @@ Item{
onTriggered: waitingTime.seconds += 1
}
ColumnLayout {
id: waitingConnection
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 30 * DefaultStyle.dp
@ -90,15 +90,13 @@ Item{
Sticker {
visible: mainItem.callState != LinphoneEnums.CallState.End && mainItem.callState != LinphoneEnums.CallState.Released
&& modelData.core.address != activeSpeakerSticker.address
onVisibleChanged: console.log(modelData.core.address)
height: visible ? 180 * DefaultStyle.dp : 0
width: 300 * DefaultStyle.dp
qmlName: 'M_'+index
qmlName: 'S_'+index
participantDevice: modelData
cameraEnabled: mainItem.call.core.cameraEnabled
Component.onCompleted: console.log(modelData.core.address)
previewEnabled: index == 0
Component.onCompleted: console.log(qmlName + " is " +modelData.core.address)
}
}
}
@ -106,7 +104,7 @@ Item{
id: preview
qmlName: 'P'
previewEnabled: true
visible: mainItem.call && allDevices.count <= 2
visible: mainItem.call && allDevices.count <= 2 && !waitingConnection.visible
onVisibleChanged: console.log(visible + " : " +allDevices.count)
height: 180 * DefaultStyle.dp
width: 300 * DefaultStyle.dp
@ -143,230 +141,4 @@ Item{
}
}
}
/*
Sticker {
id: preview
visible: mainItem.callState != LinphoneEnums.CallState.End
&& mainItem.callState != LinphoneEnums.CallState.Released
height: 180 * DefaultStyle.dp
width: 300 * DefaultStyle.dp
anchors.right: mainItem.right
anchors.bottom: mainItem.bottom
anchors.rightMargin: 10 * DefaultStyle.dp
anchors.bottomMargin: 10 * DefaultStyle.dp
AccountProxy{
id: accounts
}
account: accounts.defaultAccount
previewEnabled: mainItem.call.core.cameraEnabled
MovableMouseArea {
id: previewMouseArea
anchors.fill: parent
// visible: mainItem.participantCount <= 2
movableArea: mainItem
margin: 10 * DefaultStyle.dp
function resetPosition(){
preview.anchors.right = mainItem.right
preview.anchors.bottom = mainItem.bottom
preview.anchors.rightMargin = previewMouseArea.margin
preview.anchors.bottomMargin = previewMouseArea.margin
}
onVisibleChanged: if(!visible){
resetPosition()
}
drag.target: preview
onDraggingChanged: if(dragging) {
preview.anchors.right = undefined
preview.anchors.bottom = undefined
}
onRequestResetPosition: resetPosition()
}
}
property int previousWidth
Component.onCompleted: {
previousWidth = width
}
onWidthChanged: {
if (width < previousWidth) {
previewMouseArea.updatePosition(0, 0)
} else {
previewMouseArea.updatePosition(width - previousWidth, 0)
}
previousWidth = width
}*/
/*
Item {
id: mainItem
property CallModel callModel
property bool isRightReducedLayout: false
property bool isLeftReducedLayout: false
property bool cameraEnabled: true
property bool isConference: callModel && callModel.isConference
property bool isConferenceReady: isConference && callModel.conferenceModel && callModel.conferenceModel.isReady
property int participantCount: isConference ? allDevices.count + 1 : 2 // +me. allDevices==0 if !conference
property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel {
id: allDevices
callModel: mainItem.callModel
showMe: false
onConferenceCreated: cameraView.resetCamera()
}
Sticker{
id: cameraView
anchors.fill: parent
anchors.leftMargin: isRightReducedLayout || isLeftReducedLayout? 30 : 140
anchors.rightMargin: isRightReducedLayout ? 10 : 140
cameraQmlName: 'AS'
callModel: mainItem.callModel
currentDevice: isPreview
? allDevices.me
: mainItem.isConference
? allDevices.activeSpeaker
: null
deactivateCamera: !mainItem.cameraEnabled || (isPreview && callModel.pausedByUser)
? true
: mainItem.isConference
? (callModel && (callModel.pausedByUser || callModel.status === CallModel.CallStatusPaused) )
|| (!(callModel && callModel.cameraEnabled) && mainItem.participantCount == 1)
|| (currentDevice && !currentDevice.videoEnabled)// && mainItem.participantCount == 2)
|| !mainItem.isConferenceReady
: (callModel && (callModel.pausedByUser || callModel.status === CallModel.CallStatusPaused || !callModel.videoEnabled) )
|| currentDevice && !currentDevice.videoEnabled
isPreview: !preview.visible && mainItem.participantCount == 1
onIsPreviewChanged: {cameraView.resetCamera() }
isCameraFromDevice: isPreview
isPaused: isPreview && callModel.pausedByUser
? false
: mainItem.isConference
? //callModel && callModel.pausedByUser && mainItem.participantCount != 2 ||
(currentDevice && currentDevice.isPaused)
: callModel && !callModel.pausedByUser && (callModel.status === CallModel.CallStatusPaused)
quickTransition: true
showCloseButton: false
showActiveSpeakerOverlay: false // This is an active speaker. We don't need to show the indicator.
showCustomButton: false
avatarStickerBackgroundColor: isPreview ? IncallStyle.container.avatar.stickerPreviewBackgroundColor.color : IncallStyle.container.avatar.stickerBackgroundColor.color
avatarBackgroundColor: IncallStyle.container.avatar.backgroundColor.color
}
Item{// Need an item to not override Sticker internal states. States are needed for changing anchors.
id: preview
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 30
anchors.bottomMargin: 15
height: visible ? miniViews.cellHeight : 0
width: 16 * height / 9
visible: mainItem.isConferenceReady && allDevices.count >= 1
|| (!mainItem.isConference && mainItem.callModel && mainItem.callModel.cameraEnabled)// use videoEnabled if we want to show the preview sticker
Loader{
anchors.fill: parent
anchors.margins: 3
sourceComponent:
Sticker{
id: previewSticker
cameraQmlName: 'AS_Preview'
deactivateCamera: !mainItem.cameraEnabled || !mainItem.callModel || callModel.pausedByUser || !mainItem.callModel.cameraEnabled
currentDevice: allDevices.me
isPreview: true
callModel: mainItem.callModel
isCameraFromDevice: true
showCloseButton: false
showCustomButton: false
showAvatarBorder: true
avatarStickerBackgroundColor: IncallStyle.container.avatar.stickerPreviewBackgroundColor.color
avatarBackgroundColor: IncallStyle.container.avatar.backgroundColor.color
}
active: parent.visible
}
MovableMouseArea{
id: dragger
anchors.fill: parent
visible: mainItem.participantCount <= 2
function resetPosition(){
preview.anchors.right = mainItem.right
preview.anchors.bottom = mainItem.bottom
}
onVisibleChanged: if(!visible){
resetPosition()
}
drag.target: preview
onDraggingChanged: if(dragging){
preview.anchors.right = undefined
preview.anchors.bottom = undefined
}
onRequestResetPosition: resetPosition()
}
}
Item{
id: miniViewArea
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: preview.top
anchors.rightMargin: 30
anchors.topMargin: 15
anchors.bottomMargin: 0
//---------------
width: 16 * miniViews.cellHeight / 9
visible: mainItem.isConferenceReady || !mainItem.isConference
property int heightLeft: parent.height - preview.height
onHeightLeftChanged: {Qt.callLater(miniViewArea.forceRefresh)}
function forceRefresh(){// Force a content refresh via margins. Qt is buggy when managing sizes in ListView.
++miniViewArea.anchors.topMargin
--miniViewArea.anchors.topMargin
}
ScrollableListView{
id: miniViews
property int cellHeight: 150
anchors.fill: parent
model : mainItem.isConference && mainItem.participantDevices.count > 1 ? mainItem.participantDevices : []
spacing: 0
verticalLayoutDirection: ListView.BottomToTop
fitCacheToContent: false
property int oldCount : 0// Count changed can be called without a change... (bug?). Use oldCount to avoid it.
onCountChanged: {if(oldCount != count){ oldCount = count ; Qt.callLater(miniViewArea.forceRefresh)}}
Component.onCompleted: {Qt.callLater(miniViewArea.forceRefresh)}
delegate:Item{
height: visible ? miniViews.cellHeight + 15 : 0
width: visible ? miniViews.width : 0
visible: cameraView.currentDevice != modelData
clip:false
Sticker{
id: miniView
anchors.fill: parent
anchors.topMargin: 3
anchors.leftMargin: 3
anchors.rightMargin: 3
anchors.bottomMargin: 18
cameraQmlName: 'S_'+index
deactivateCamera: (!mainItem.isConferenceReady || !mainItem.isConference)
&& (index <0 || !mainItem.cameraEnabled || (!modelData.videoEnabled) || (callModel && callModel.pausedByUser) )
currentDevice: modelData.isPreview ? null : modelData
callModel: modelData.isPreview ? null : mainItem.callModel
isCameraFromDevice: mainItem.isConference
isPaused: currentDevice && currentDevice.isPaused
showCloseButton: false
showCustomButton: false
showAvatarBorder: true
avatarStickerBackgroundColor: IncallStyle.container.avatar.stickerBackgroundColor.color
avatarBackgroundColor: IncallStyle.container.avatar.backgroundColor.color
}
}
}
}
}
*/