From 1dd4f4f285765e40d0fbb50d1dc665d405abb3b2 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Tue, 9 May 2023 11:49:26 +0200 Subject: [PATCH] Fix crash when loading some chats with video. Detect video availability when building the thumbnail in order to avoid playing all the file while waiting of a frame. Fix image type detection from Mime (appimage was detected as an image and Qt considered compressed file as a readable image) --- .../components/chat-room/ChatRoomModel.cpp | 4 +-- .../components/other/images/ImageModel.cpp | 36 ++++++++++++++++--- linphone-app/src/utils/Utils.cpp | 14 ++++---- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index b3f154a27..9722d93a2 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -984,7 +984,7 @@ void ChatRoomModel::initEntries(){ if( e->mType == ChatRoomModel::EntryType::MessageEntry){ connect(e.objectCast().get(), &ChatMessageModel::remove, this, &ChatRoomModel::removeEntry); auto model = e.objectCast().get(); - qDebug() << "Adding" << model->getReceivedTimestamp().toString("yyyy/MM/dd hh:mm:ss.zzz") << model->getTimestamp().toString("yyyy/MM/dd hh:mm:ss.zzz") << model->getChatMessage()->getUtf8Text().c_str(); + qDebug() << "Adding" << model->getReceivedTimestamp().toString("yyyy/MM/dd hh:mm:ss.zzz") << model->getTimestamp().toString("yyyy/MM/dd hh:mm:ss.zzz") << QString(model->getChatMessage()->getUtf8Text().c_str()).left(5); } mList.push_back(e); } @@ -1149,7 +1149,7 @@ QSharedPointer ChatRoomModel::insertMessageAtEnd (const std::s if(mIsInitialized && !exists(message)){ model = ChatMessageModel::create(message); if(model){ - qDebug() << "Adding at end" << model->getReceivedTimestamp().toString("hh:mm:ss.zzz") << model->getTimestamp().toString("hh:mm:ss.zzz") << message->getUtf8Text().c_str(); + qDebug() << "Adding at end" << model->getReceivedTimestamp().toString("hh:mm:ss.zzz") << model->getTimestamp().toString("hh:mm:ss.zzz") << QString(message->getUtf8Text().c_str()).left(5); connect(model.get(), &ChatMessageModel::remove, this, &ChatRoomModel::removeEntry); setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); add(model); diff --git a/linphone-app/src/components/other/images/ImageModel.cpp b/linphone-app/src/components/other/images/ImageModel.cpp index e17eae237..730aa3a23 100644 --- a/linphone-app/src/components/other/images/ImageModel.cpp +++ b/linphone-app/src/components/other/images/ImageModel.cpp @@ -160,19 +160,45 @@ QImage ImageModel::createThumbnail(const QString& path){ originalImage = QImage(path, format); else if(Utils::isVideo(path)){ QObject context; + int mediaStep = 0; QMediaPlayer player(&context); - player.setMedia(QUrl::fromLocalFile(path)); - player.setPosition(player.duration() / 2); VideoFrameGrabber grabber(&context); - player.setVideoOutput(&grabber); +// Media connections + QObject::connect(&player, QOverload::of(&QMediaPlayer::error), &context, [&context, &mediaStep, path](QMediaPlayer::Error error) mutable{ + mediaStep = -1; + }); + QObject::connect(&player, &QMediaPlayer::mediaStatusChanged, &context, [&context, &player, &mediaStep](QMediaPlayer::MediaStatus status) mutable{ + switch(status){ + case QMediaPlayer::LoadedMedia : if(mediaStep == 0){ + if( player.isVideoAvailable() ) + mediaStep = 1; + else + mediaStep = -1; + } + break; + case QMediaPlayer::UnknownMediaStatus: + case QMediaPlayer::InvalidMedia: + case QMediaPlayer::EndOfMedia: + mediaStep = -1; + break; + default:{} + } + }); QObject::connect(&grabber, &VideoFrameGrabber::frameAvailable, &context, [&context,&originalImage, &player](QImage frame) mutable{ originalImage = frame.copy(); player.stop(); }, Qt::DirectConnection); - player.play(); +// Processing + player.setVideoOutput(&grabber); + player.setMedia(QUrl::fromLocalFile(path)); do{ qApp->processEvents(); - }while(player.state() != QMediaPlayer::State::StoppedState); + if(mediaStep == 1){ + mediaStep = 2; + player.setPosition(player.duration() / 2); + player.play(); + } + }while(mediaStep >= 0 ); } } if (!originalImage.isNull()){ diff --git a/linphone-app/src/utils/Utils.cpp b/linphone-app/src/utils/Utils.cpp index 7b31e2845..574f8acff 100644 --- a/linphone-app/src/utils/Utils.cpp +++ b/linphone-app/src/utils/Utils.cpp @@ -624,25 +624,27 @@ bool Utils::isMe(const std::shared_ptr& address){ bool Utils::isAnimatedImage(const QString& path){ if(path.isEmpty()) return false; QFileInfo info(path); - if( !info.exists()) + if( !info.exists() || !QMimeDatabase().mimeTypeForFile(info).name().contains("image/")) return false; QImageReader reader(path); - return reader.supportsAnimation() && reader.imageCount() > 1; + return reader.canRead() && reader.supportsAnimation() && reader.imageCount() > 1; } bool Utils::isImage(const QString& path){ if(path.isEmpty()) return false; QFileInfo info(path); if( !info.exists()){ - return QMimeDatabase().mimeTypeForFile(info, QMimeDatabase::MatchExtension).name().contains("image"); - } + return QMimeDatabase().mimeTypeForFile(info, QMimeDatabase::MatchExtension).name().contains("image/"); + }else if(!QMimeDatabase().mimeTypeForFile(info).name().contains("image/")) + return false; QImageReader reader(path); - return reader.imageCount() == 1; + qWarning() << reader.imageCount(); + return reader.canRead() && reader.imageCount() == 1; } bool Utils::isVideo(const QString& path){ if(path.isEmpty()) return false; - return QMimeDatabase().mimeTypeForFile(path).name().contains("video"); + return QMimeDatabase().mimeTypeForFile(path).name().contains("video/"); } bool Utils::isPdf(const QString& path){