Ensure preview scaling is not lost when a monitor is stopped (like when switching monitors)

Related to #649
parent 1b4d376f
......@@ -342,7 +342,7 @@ static void uploadTextures(QOpenGLContext *context, const SharedFrame &frame, GL
{
int width = frame.get_image_width();
int height = frame.get_image_height();
const uint8_t *image = frame.get_image();
const uint8_t *image = frame.get_image(mlt_image_yuv420p);
QOpenGLFunctions *f = context->functions();
// The planes of pixel data may not be a multiple of the default 4 bytes.
......@@ -420,7 +420,7 @@ bool GLWidget::acquireSharedFrameTextures()
// C & D
m_contextSharedAccess.lock();
if (m_sharedFrame.is_valid()) {
m_texture[0] = *((const GLuint *)m_sharedFrame.get_image());
m_texture[0] = *((const GLuint *)m_sharedFrame.get_image(mlt_image_glsl_texture));
}
}
......@@ -656,9 +656,7 @@ void GLWidget::requestSeek(int position)
if (!qFuzzyIsNull(m_producer->get_speed())) {
m_consumer->purge();
}
if (m_consumer->is_stopped()) {
m_consumer->start();
}
restartConsumer();
m_consumer->set("refresh", 1);
}
......@@ -679,9 +677,7 @@ void GLWidget::refresh()
{
m_refreshTimer.stop();
QMutexLocker locker(&m_mltMutex);
if (m_consumer->is_stopped()) {
m_consumer->start();
}
restartConsumer();
m_consumer->set("refresh", 1);
}
......@@ -1488,10 +1484,6 @@ FrameRenderer::~FrameRenderer()
void FrameRenderer::showFrame(Mlt::Frame frame)
{
int width = 0;
int height = 0;
mlt_image_format format = mlt_image_yuv420p;
frame.get_image(format, width, height);
// Save this frame for future use and to keep a reference to the GL Texture.
m_displayFrame = SharedFrame(frame);
......@@ -1519,12 +1511,6 @@ void FrameRenderer::showFrame(Mlt::Frame frame)
void FrameRenderer::showGLFrame(Mlt::Frame frame)
{
if ((m_context != nullptr) && m_context->isValid()) {
int width = 0;
int height = 0;
frame.set("movit.convert.use_texture", 1);
mlt_image_format format = mlt_image_glsl_texture;
frame.get_image(format, width, height);
m_context->makeCurrent(m_surface);
pipelineSyncToFrame(frame);
......@@ -1543,12 +1529,8 @@ void FrameRenderer::showGLFrame(Mlt::Frame frame)
void FrameRenderer::showGLNoSyncFrame(Mlt::Frame frame)
{
if ((m_context != nullptr) && m_context->isValid()) {
int width = 0;
int height = 0;
frame.set("movit.convert.use_texture", 1);
mlt_image_format format = mlt_image_glsl_texture;
frame.get_image(format, width, height);
m_context->makeCurrent(m_surface);
m_context->functions()->glFinish();
......@@ -1655,9 +1637,7 @@ bool GLWidget::playZone(bool loop)
m_consumer->purge();
m_producer->set("out", m_proxy->zoneOut());
m_producer->set_speed(1.0);
if (m_consumer->is_stopped()) {
m_consumer->start();
}
restartConsumer();
m_consumer->set("scrub_audio", 0);
m_consumer->set("refresh", 1);
m_isZoneMode = true;
......@@ -1665,6 +1645,23 @@ bool GLWidget::playZone(bool loop)
return true;
}
bool GLWidget::restartConsumer()
{
int result = 0;
if (m_consumer->is_stopped()) {
// When restarting the consumer, we need to restore the preview scaling
int cWidth = m_consumer->get_int("width");
int cHeigth = m_consumer->get_int("height");
result = m_consumer->start();
if (cWidth > 0) {
m_consumer->set("width", cWidth);
m_consumer->set("height", cHeigth);
}
}
return result != -1;
}
bool GLWidget::loopClip(QPoint inOut)
{
if (!m_producer || inOut.y() <= inOut.x()) {
......@@ -1677,9 +1674,7 @@ bool GLWidget::loopClip(QPoint inOut)
m_consumer->purge();
m_producer->set("out", inOut.y());
m_producer->set_speed(1.0);
if (m_consumer->is_stopped()) {
m_consumer->start();
}
restartConsumer();
m_consumer->set("scrub_audio", 0);
m_consumer->set("refresh", 1);
m_isZoneMode = false;
......@@ -1722,7 +1717,7 @@ void GLWidget::startConsumer()
if (m_consumer == nullptr) {
return;
}
if (m_consumer->is_stopped() && m_consumer->start() == -1) {
if (!restartConsumer()) {
// ARGH CONSUMER BROKEN!!!!
KMessageBox::error(
qApp->activeWindow(),
......
......@@ -242,6 +242,8 @@ private:
QOpenGLFramebufferObject *m_fbo;
void refreshSceneLayout();
void resetZoneMode();
/** @brief Restart consumer, keeping preview scaling settings */
bool restartConsumer();
/* OpenGL context management. Interfaces to MLT according to the configured render pipeline.
*/
......
......@@ -16,6 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sharedframe.h"
#include <mutex>
void destroyFrame(void* p)
{
delete static_cast<Mlt::Frame*>(p);
}
class FrameData : public QSharedData
{
......@@ -31,6 +37,7 @@ public:
~FrameData() = default;
Mlt::Frame f;
std::mutex m;
private:
Q_DISABLE_COPY(FrameData)
......@@ -164,12 +171,54 @@ int SharedFrame::get_image_height() const
return d->f.get_int("height");
}
const uint8_t *SharedFrame::get_image() const
const uint8_t *SharedFrame::get_image(mlt_image_format format) const
{
mlt_image_format format = get_image_format();
mlt_image_format native_format = get_image_format();
int width = get_image_width();
int height = get_image_height();
return (uint8_t *)d->f.get_image(format, width, height, 0);
uint8_t* image = nullptr;
if (format == mlt_image_none) {
format = native_format;
}
if (format == native_format) {
// Native format is requested. Return frame image.
image = (uint8_t*)d->f.get_image(format, width, height, 0);
} else {
// Non-native format is requested. Return a cached converted image.
const char* formatName = mlt_image_format_name( format );
// Convert to non-const so that the cache can be accessed/modified while
// under lock.
FrameData* nonConstData = const_cast<FrameData*>(d.data());
nonConstData->m.lock();
Mlt::Frame* cacheFrame = static_cast<Mlt::Frame*>(nonConstData->f.get_data(formatName));
if (cacheFrame == nullptr) {
// A cached image does not exist, create one.
// Make a non-deep clone of the frame (including convert function)
mlt_frame cloneFrame = mlt_frame_clone(nonConstData->f.get_frame(), 0);
cloneFrame->convert_image = nonConstData->f.get_frame()->convert_image;
// Create a new cache frame
cacheFrame = new Mlt::Frame(cloneFrame);
// Release the reference on the clone
// (now it is owned by the cache frame)
mlt_frame_close( cloneFrame );
// Save the cache frame as a property under the name of the image
// format for later use.
nonConstData->f.set(formatName, static_cast<void*>(cacheFrame), 0, destroyFrame);
// Break a circular reference
cacheFrame->clear("_cloned_frame");
}
// Get the image from the cache frame.
// This will cause a conversion if it was just created.
image = (uint8_t*)cacheFrame->get_image(format, width, height, 0);
nonConstData->m.unlock();
}
return image;
}
mlt_audio_format SharedFrame::get_audio_format() const
......
......@@ -63,7 +63,7 @@ public:
mlt_image_format get_image_format() const;
int get_image_width() const;
int get_image_height() const;
const uint8_t *get_image() const;
const uint8_t *get_image(mlt_image_format format) const;
mlt_audio_format get_audio_format() const;
int get_audio_channels() const;
int get_audio_frequency() const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment