|
|
|
@ -5,12 +5,14 @@ |
|
|
|
|
|
|
|
|
|
#include "InputBar.h" |
|
|
|
|
|
|
|
|
|
#include <QVideoSink> |
|
|
|
|
#include <QBuffer> |
|
|
|
|
#include <QClipboard> |
|
|
|
|
#include <QDropEvent> |
|
|
|
|
#include <QFileDialog> |
|
|
|
|
#include <QGuiApplication> |
|
|
|
|
#include <QInputMethod> |
|
|
|
|
#include <QVideoFrame> |
|
|
|
|
#include <QMediaMetaData> |
|
|
|
|
#include <QMediaPlayer> |
|
|
|
|
#include <QMimeData> |
|
|
|
@ -52,55 +54,6 @@ MediaUpload::thumbnailDataUrl() const |
|
|
|
|
return QString("data:image/png;base64,") + base64; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
InputVideoSurface::present(const QVideoFrame &frame) |
|
|
|
|
{ |
|
|
|
|
QImage::Format format = QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat()); |
|
|
|
|
|
|
|
|
|
if (format == QImage::Format_Invalid) { |
|
|
|
|
emit newImage({}); |
|
|
|
|
return false; |
|
|
|
|
} else { |
|
|
|
|
QVideoFrame frametodraw(frame); |
|
|
|
|
|
|
|
|
|
if (!frametodraw.map(QAbstractVideoBuffer::ReadOnly)) { |
|
|
|
|
emit newImage({}); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// this is a shallow operation. it just refer the frame buffer
|
|
|
|
|
QImage image(qAsConst(frametodraw).bits(), |
|
|
|
|
frametodraw.width(), |
|
|
|
|
frametodraw.height(), |
|
|
|
|
frametodraw.bytesPerLine(), |
|
|
|
|
format); |
|
|
|
|
image.detach(); |
|
|
|
|
|
|
|
|
|
frametodraw.unmap(); |
|
|
|
|
|
|
|
|
|
emit newImage(std::move(image)); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QList<QVideoFrame::PixelFormat> |
|
|
|
|
InputVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const |
|
|
|
|
{ |
|
|
|
|
if (type == QAbstractVideoBuffer::NoHandle) { |
|
|
|
|
return { |
|
|
|
|
QVideoFrame::Format_ARGB32, |
|
|
|
|
QVideoFrame::Format_ARGB32_Premultiplied, |
|
|
|
|
QVideoFrame::Format_RGB24, |
|
|
|
|
QVideoFrame::Format_BGR24, |
|
|
|
|
QVideoFrame::Format_RGB32, |
|
|
|
|
QVideoFrame::Format_RGB565, |
|
|
|
|
QVideoFrame::Format_RGB555, |
|
|
|
|
}; |
|
|
|
|
} else { |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
InputBar::paste(bool fromMouse) |
|
|
|
|
{ |
|
|
|
@ -371,7 +324,7 @@ InputBar::message(const QString &msg, MarkdownOverride useMarkdown, bool rainbow |
|
|
|
|
|
|
|
|
|
QString body; |
|
|
|
|
bool firstLine = true; |
|
|
|
|
auto lines = related.quoted_body.splitRef(u'\n'); |
|
|
|
|
auto lines = QStringView(related.quoted_body).split(u'\n'); |
|
|
|
|
for (auto line : qAsConst(lines)) { |
|
|
|
|
if (firstLine) { |
|
|
|
|
firstLine = false; |
|
|
|
@ -799,21 +752,22 @@ MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_, |
|
|
|
|
blurhash_ = |
|
|
|
|
QString::fromStdString(blurhash::encode(data_.data(), img.width(), img.height(), 4, 3)); |
|
|
|
|
} else if (mimeClass_ == u"video" || mimeClass_ == u"audio") { |
|
|
|
|
auto mediaPlayer = new QMediaPlayer( |
|
|
|
|
this, |
|
|
|
|
mimeClass_ == u"video" ? QFlags{QMediaPlayer::VideoSurface} : QMediaPlayer::Flags{}); |
|
|
|
|
mediaPlayer->setMuted(true); |
|
|
|
|
auto mediaPlayer = new QMediaPlayer(this); |
|
|
|
|
|
|
|
|
|
mediaPlayer->setAudioOutput(nullptr); |
|
|
|
|
|
|
|
|
|
if (mimeClass_ == u"video") { |
|
|
|
|
auto newSurface = new InputVideoSurface(this); |
|
|
|
|
auto newSurface = new QVideoSink(this); |
|
|
|
|
connect( |
|
|
|
|
newSurface, &InputVideoSurface::newImage, this, [this, mediaPlayer](QImage img) { |
|
|
|
|
newSurface, &QVideoSink::videoFrameChanged, this, [this, mediaPlayer](const QVideoFrame& frame) { |
|
|
|
|
QImage img = frame.toImage(); |
|
|
|
|
|
|
|
|
|
if (img.size().isEmpty()) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
mediaPlayer->stop(); |
|
|
|
|
|
|
|
|
|
auto orientation = mediaPlayer->metaData(QMediaMetaData::Orientation).toInt(); |
|
|
|
|
auto orientation = mediaPlayer->metaData().value(QMediaMetaData::Orientation).toInt(); |
|
|
|
|
if (orientation == 90 || orientation == 270 || orientation == 180) { |
|
|
|
|
img = |
|
|
|
|
img.transformed(QTransform().rotate(orientation), Qt::SmoothTransformation); |
|
|
|
@ -844,11 +798,11 @@ MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
connect(mediaPlayer, |
|
|
|
|
qOverload<QMediaPlayer::Error>(&QMediaPlayer::error), |
|
|
|
|
&QMediaPlayer::error, |
|
|
|
|
this, |
|
|
|
|
[mediaPlayer](QMediaPlayer::Error error) { |
|
|
|
|
[mediaPlayer]() { |
|
|
|
|
nhlog::ui()->debug("Media player error {} and errorStr {}", |
|
|
|
|
error, |
|
|
|
|
mediaPlayer->error(), |
|
|
|
|
mediaPlayer->errorString().toStdString()); |
|
|
|
|
}); |
|
|
|
|
connect(mediaPlayer, |
|
|
|
@ -858,18 +812,18 @@ MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_, |
|
|
|
|
"Media player status {} and error {}", status, mediaPlayer->error()); |
|
|
|
|
}); |
|
|
|
|
connect(mediaPlayer, |
|
|
|
|
qOverload<const QString &, const QVariant &>(&QMediaPlayer::metaDataChanged), |
|
|
|
|
[this, mediaPlayer](QString t, QVariant) { |
|
|
|
|
nhlog::ui()->debug("Got metadata {}", t.toStdString()); |
|
|
|
|
&QMediaPlayer::metaDataChanged, |
|
|
|
|
[this, mediaPlayer]() { |
|
|
|
|
nhlog::ui()->debug("Got metadata"); |
|
|
|
|
|
|
|
|
|
if (mediaPlayer->duration() > 0) |
|
|
|
|
this->duration_ = mediaPlayer->duration(); |
|
|
|
|
|
|
|
|
|
auto dimensions = mediaPlayer->metaData(QMediaMetaData::Resolution).toSize(); |
|
|
|
|
auto dimensions = mediaPlayer->metaData().value(QMediaMetaData::Resolution).toSize(); |
|
|
|
|
if (!dimensions.isEmpty()) { |
|
|
|
|
dimensions_ = dimensions; |
|
|
|
|
auto orientation = |
|
|
|
|
mediaPlayer->metaData(QMediaMetaData::Orientation).toInt(); |
|
|
|
|
mediaPlayer->metaData().value(QMediaMetaData::Orientation).toInt(); |
|
|
|
|
if (orientation == 90 || orientation == 270) { |
|
|
|
|
dimensions_.transpose(); |
|
|
|
|
} |
|
|
|
@ -886,8 +840,8 @@ MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_, |
|
|
|
|
|
|
|
|
|
auto originalFile = qobject_cast<QFile *>(source.get()); |
|
|
|
|
|
|
|
|
|
mediaPlayer->setMedia( |
|
|
|
|
QMediaContent(originalFile ? originalFile->fileName() : originalFilename_), source.get()); |
|
|
|
|
mediaPlayer->setSourceDevice( |
|
|
|
|
source.get(), QUrl(originalFile ? originalFile->fileName() : originalFilename_) ); |
|
|
|
|
|
|
|
|
|
mediaPlayer->play(); |
|
|
|
|
} |
|
|
|
|