videowidget.cpp 6.57 KB
Newer Older
1
/***************************************************************************
2
 * Copyright (C) 2015-2016 by Savoir-faire Linux                                *
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com>*
 *                                                                         *
 * This program is free software; you can redistribute it and/or modify    *
 * it under the terms of the GNU General Public License as published by    *
 * the Free Software Foundation; either version 3 of the License, or       *
 * (at your option) any later version.                                     *
 *                                                                         *
 * This program is distributed in the hope that it will be useful,         *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 * GNU General Public License for more details.                            *
 *                                                                         *
 * You should have received a copy of the GNU General Public License       *
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
 **************************************************************************/

#include "videowidget.h"

21
VideoWidget::VideoWidget(QWidget* parent) :
22 23 24
    QWidget(parent)
  , previewRenderer_(nullptr)
  , renderer_(nullptr)
25
  , isPreviewDisplayed_(true)
26
  , fullPreview_(false)
27
{
Edric Milaret's avatar
Edric Milaret committed
28
    connect(&Video::PreviewManager::instance(),
29
            SIGNAL(previewStarted(Video::Renderer*)),
Edric Milaret's avatar
Edric Milaret committed
30
            this, SLOT(previewStarted(Video::Renderer*)));
Edric Milaret's avatar
Edric Milaret committed
31 32 33 34 35

    QPalette pal(palette());
    pal.setColor(QPalette::Background, Qt::black);
    this->setAutoFillBackground(true);
    this->setPalette(pal);
36 37 38 39 40 41
}

VideoWidget::~VideoWidget()
{}

void
42
VideoWidget::previewStarted(Video::Renderer* renderer) {
Éloi Bail's avatar
Éloi Bail committed
43 44 45
    //Enforce that only one videowidget we'll be used at the same time
    if (not isVisible())
        return;
46 47
    if (previewRenderer_ == renderer)
        return;
48 49 50 51 52
    previewRenderer_ = renderer;
    connect(previewRenderer_, SIGNAL(frameUpdated()),
            this, SLOT(frameFromPreview()));
    connect(previewRenderer_, SIGNAL(stopped()),
            this, SLOT(previewStopped()));
53 54 55
}

void
Edric Milaret's avatar
Edric Milaret committed
56 57
VideoWidget::previewStopped() {
    disconnect(previewRenderer_, SIGNAL(frameUpdated()),
58
               this, SLOT(frameFromPreview()));
Edric Milaret's avatar
Edric Milaret committed
59
    disconnect(previewRenderer_, SIGNAL(stopped()),
60
               this, SLOT(previewStopped()));
61
    previewRenderer_ = nullptr;
62
    repaint();
63 64 65 66
}

void
VideoWidget::frameFromPreview() {
Éloi Bail's avatar
Éloi Bail committed
67
    if (previewRenderer_ && previewRenderer_->isRendering()) {
68 69 70 71 72
        {
            QMutexLocker lock(&mutex_);
            auto tmp  = previewRenderer_->currentFrame();
            if (tmp.storage.size())
                currentPreviewFrame_ = tmp;
Éloi Bail's avatar
Éloi Bail committed
73
        }
74
        update();
75 76 77 78
    }
}

void
79
VideoWidget::paintEvent(QPaintEvent* evt) {
80 81
    Q_UNUSED(evt)
    QPainter painter(this);
82 83 84 85

    if (renderer_) {
        {
            QMutexLocker lock(&mutex_);
86 87
            if (currentDistantFrame_.storage.size() != 0
                && currentDistantFrame_.storage.size() ==
Edric Milaret's avatar
Edric Milaret committed
88
                    (unsigned int)(renderer_->size().height()*renderer_->size().width()*4)) {
89 90 91 92 93 94 95 96 97 98 99 100 101
                frameDistant_ = std::move(currentDistantFrame_.storage);
                distantImage_.reset(new QImage((uchar*)frameDistant_.data(),
                                               renderer_->size().width(),
                                               renderer_->size().height(),
                                               QImage::Format_ARGB32_Premultiplied));
            }
        }
        if (distantImage_) {
            auto scaledDistant = distantImage_->scaled(size(), Qt::KeepAspectRatio);
            auto xDiff = (width() - scaledDistant.width()) / 2;
            auto yDiff = (height() - scaledDistant.height()) /2;
            painter.drawImage(QRect(xDiff,yDiff,scaledDistant.width(),scaledDistant.height()), scaledDistant);
        }
Edric Milaret's avatar
Edric Milaret committed
102
    }
103
    if (previewRenderer_ && isPreviewDisplayed_) {
104 105
        {
            QMutexLocker lock(&mutex_);
106 107
            if (currentPreviewFrame_.storage.size() != 0
                 && currentPreviewFrame_.storage.size() ==
Edric Milaret's avatar
Edric Milaret committed
108
                    (unsigned int)(previewRenderer_->size().height()*previewRenderer_->size().width()*4)) {
109 110 111 112 113 114 115 116 117
                framePreview_ = std::move(currentPreviewFrame_.storage);
                previewImage_.reset(new QImage((uchar*)framePreview_.data(),
                                               previewRenderer_->size().width(),
                                               previewRenderer_->size().height(),
                                               QImage::Format_ARGB32_Premultiplied));

            }
        }
        if (previewImage_) {
118 119
            auto previewHeight = fullPreview_ ? height() : height()/4;
            auto previewWidth = fullPreview_  ? width() : width()/4;
120 121 122
            auto scaledPreview = previewImage_->scaled(previewWidth, previewHeight, Qt::KeepAspectRatio);
            auto xDiff = (previewWidth - scaledPreview.width()) / 2;
            auto yDiff = (previewHeight - scaledPreview.height()) / 2;
123 124
            auto yPos = fullPreview_ ? yDiff : height() - previewHeight - previewMargin_;
            auto xPos = fullPreview_ ? xDiff : width() - scaledPreview.width() - previewMargin_;
125 126 127
            painter.drawImage(QRect(xPos,yPos,scaledPreview.width(),scaledPreview.height()),
                              scaledPreview);
        }
128 129 130 131 132
    }
    painter.end();
}

void
133 134
VideoWidget::setDistantRenderer(Video::Renderer* renderer) {
    if (not renderer)
Éloi Bail's avatar
Éloi Bail committed
135
        return;
136 137 138 139 140 141
    if (renderer_ != renderer) {
        renderingStopped();
        renderer_ = renderer;
        connect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant()));
        connect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped()));
    }
142 143 144 145
}

void
VideoWidget::frameFromDistant() {
Éloi Bail's avatar
Éloi Bail committed
146
    if (renderer_ && renderer_->isRendering()) {
147 148 149 150 151
        {
            QMutexLocker lock(&mutex_);
            auto tmp  = renderer_->currentFrame();
            if (tmp.storage.size())
                currentDistantFrame_ = tmp;
Éloi Bail's avatar
Éloi Bail committed
152
        }
153
        update();
154 155 156 157 158
    }
}

void
VideoWidget::renderingStopped() {
159 160
    if (not renderer_)
        return;
Edric Milaret's avatar
Edric Milaret committed
161 162
    disconnect(renderer_, SIGNAL(frameUpdated()), this, SLOT(frameFromDistant()));
    disconnect(renderer_, SIGNAL(stopped()),this, SLOT(renderingStopped()));
163
    renderer_ = nullptr;
164
    repaint();
165
}
166 167 168 169 170

void
VideoWidget::setPreviewDisplay(bool display) {
    isPreviewDisplayed_ = display;
}
171 172 173 174 175

void
VideoWidget::setIsFullPreview(bool full) {
    fullPreview_ = full;
}