Skip to content
Snippets Groups Projects
Commit b0d7461e authored by Sébastien Blin's avatar Sébastien Blin
Browse files

videoprovider: fix captureVideoFrame

The photoboothview was bugguy and didn't take photo all the time.
Homogeneize captureVideoFrame with other methods.

GitLab: #727
Change-Id: I742e51e161c17ffc324e911341c5a4a701037f90
parent 820ef309
No related branches found
No related tags found
No related merge requests found
......@@ -294,7 +294,7 @@ Popup {
imageColor: UtilsAdapter.luma(JamiTheme.backgroundColor) ? "white" : JamiTheme.buttonTintedBlue
onClicked: {
root.photo = videoProvider.captureVideoFrame(localVideo.videoSink)
root.photo = videoProvider.captureVideoFrame(VideoDevices.getDefaultDevice())
updateState(RecordBox.States.REC_SUCCESS)
}
}
......
......@@ -67,31 +67,41 @@ VideoProvider::unregisterSink(QVideoSink* obj)
}
}
QString
VideoProvider::captureVideoFrame(QVideoSink* obj)
QVideoFrame*
VideoProvider::frame(const QString& id)
{
QImage img;
QVideoFrame currentFrame = obj->videoFrame();
FrameObject* frameObj {nullptr};
QMutexLocker lk(&framesObjsMutex_);
for (auto& frameObjIt : qAsConst(framesObjects_)) {
auto& subs = frameObjIt.second->subscribers;
auto it = subs.constFind(obj);
if (it != subs.cend()) {
frameObj = frameObjIt.second.get();
}
// framesObjsMutex_ MUST be locked
auto it = framesObjects_.find(id);
if (it == framesObjects_.end()) {
return {};
}
if (frameObj) {
QMutexLocker lk(&frameObj->mutex);
if (it->second->subscribers.empty()) {
return {};
}
QMutexLocker lk(&it->second->mutex);
auto videoFrame = it->second->videoFrame.get();
if (!mapVideoFrame(videoFrame)) {
qWarning() << "QVideoFrame can't be mapped" << id;
return {};
}
return videoFrame;
}
QString
VideoProvider::captureVideoFrame(const QString& id)
{
QMutexLocker framesLk(&framesObjsMutex_);
if (auto* videoFrame = frame(id)) {
auto imageFormat = QVideoFrameFormat::imageFormatFromPixelFormat(
QVideoFrameFormat::Format_RGBA8888);
img = QImage(currentFrame.bits(0),
currentFrame.width(),
currentFrame.height(),
currentFrame.bytesPerLine(0),
imageFormat);
}
return Utils::byteArrayToBase64String(Utils::QImageToByteArray(img));
auto img = QImage(videoFrame->bits(0),
videoFrame->width(),
videoFrame->height(),
videoFrame->bytesPerLine(0),
imageFormat);
return Utils::byteArrayToBase64String(Utils::QImageToByteArray(img));
}
return {};
}
void
......@@ -127,30 +137,19 @@ void
VideoProvider::onFrameBufferRequested(const QString& id, AVFrame* avframe)
{
QMutexLocker framesLk(&framesObjsMutex_);
auto it = framesObjects_.find(id);
if (it == framesObjects_.end()) {
return;
}
if (it->second->subscribers.empty()) {
return;
}
QMutexLocker lk(&it->second->mutex);
auto videoFrame = it->second->videoFrame.get();
if (!mapVideoFrame(videoFrame)) {
qWarning() << "QVideoFrame can't be mapped" << id;
return;
if (auto* videoFrame = frame(id)) {
// The ownership of avframe structure remains the subscriber(jamid), and
// the videoFrame instance is owned by the VideoProvider(client). The
// avframe structure contains only a description of the QVideoFrame
// underlying buffer.
// TODO: ideally, the colorspace format should likely come from jamid and
// be the decoded format.
avframe->format = AV_PIX_FMT_RGBA;
avframe->width = videoFrame->width();
avframe->height = videoFrame->height();
avframe->data[0] = (uint8_t*) videoFrame->bits(0);
avframe->linesize[0] = videoFrame->bytesPerLine(0);
}
// The ownership of avframe structure remains the subscriber(jamid), and
// the videoFrame instance is owned by the VideoProvider(client). The
// avframe structure contains only a description of the QVideoFrame
// underlying buffer.
// TODO: ideally, the colorspace format should likely come from jamid and
// be the decoded format.
avframe->format = AV_PIX_FMT_RGBA;
avframe->width = videoFrame->width();
avframe->height = videoFrame->height();
avframe->data[0] = (uint8_t*) videoFrame->bits(0);
avframe->linesize[0] = videoFrame->bytesPerLine(0);
}
void
......@@ -230,7 +229,7 @@ VideoProvider::copyUnaligned(QVideoFrame* dst, const video::Frame& src)
// The provided source must be valid.
assert(src.ptr != nullptr and src.size > 0);
// The source buffer must be greater or equal to the min required
// buffer size. The SHM buffer might be slightly larger than the
// buffer size. The SHM buffer might be slightly larger than the
// required size due to the 16-byte alignment.
if (dst->width() * dst->height() * BYTES_PER_PIXEL > src.size) {
qCritical() << "The size of frame buffer " << src.size << " is smaller than expected "
......
......@@ -45,13 +45,14 @@ public:
Q_INVOKABLE void registerSink(const QString& id, QVideoSink* obj);
Q_INVOKABLE void unregisterSink(QVideoSink* obj);
Q_INVOKABLE QString captureVideoFrame(QVideoSink* obj);
Q_INVOKABLE QString captureVideoFrame(const QString& id);
private Q_SLOTS:
void onRendererStarted(const QString& id);
void onFrameBufferRequested(const QString& id, AVFrame* avframe);
void onFrameUpdated(const QString& id);
void onRendererStopped(const QString& id);
QVideoFrame* frame(const QString& id);
private:
void copyUnaligned(QVideoFrame* dst, const video::Frame& src);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment