fix no video shown
This commit is contained in:
@@ -22,6 +22,7 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QOpenGLExtraFunctions>
|
#include <QOpenGLExtraFunctions>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
|
|
||||||
@@ -834,28 +835,65 @@ void OpenGLRenderer::ClearDestinationInternal(double r, double g, double b,
|
|||||||
|
|
||||||
GLuint OpenGLRenderer::CompileShader(GLenum type, const QString &code)
|
GLuint OpenGLRenderer::CompileShader(GLenum type, const QString &code)
|
||||||
{
|
{
|
||||||
static const QString shader_preamble =
|
const bool is_gles = context_ && context_->isOpenGLES();
|
||||||
|
const int major = context_ ? context_->format().majorVersion() : 0;
|
||||||
|
const int minor = context_ ? context_->format().minorVersion() : 0;
|
||||||
|
const bool is_gles2 = is_gles && (major < 3);
|
||||||
|
const QString gles_preamble = is_gles2
|
||||||
|
? QStringLiteral("#version 100\n\n"
|
||||||
|
"precision highp float;\n\n"
|
||||||
|
"#define frag_color gl_FragColor\n")
|
||||||
|
: QStringLiteral("#version 300 es\n\n"
|
||||||
|
"precision highp float;\n\n");
|
||||||
|
const QString desktop_preamble =
|
||||||
// Use appropriate GL 3.2 shader header
|
// Use appropriate GL 3.2 shader header
|
||||||
QStringLiteral("#version 150\n\n"
|
QStringLiteral("#version 150\n\n"
|
||||||
"precision highp float;\n\n");
|
"precision highp float;\n\n");
|
||||||
|
const QString shader_preamble = is_gles ? gles_preamble : desktop_preamble;
|
||||||
|
|
||||||
QString complete_code;
|
QString base_code = code;
|
||||||
|
if (base_code.isEmpty()) {
|
||||||
if (!code.startsWith(QStringLiteral("#version"))) {
|
|
||||||
complete_code = shader_preamble;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (code.isEmpty()) {
|
|
||||||
// Use default code
|
// Use default code
|
||||||
if (type == GL_FRAGMENT_SHADER) {
|
if (type == GL_FRAGMENT_SHADER) {
|
||||||
complete_code.append(FileFunctions::ReadFileAsString(
|
base_code = FileFunctions::ReadFileAsString(
|
||||||
QStringLiteral(":/shaders/default.frag")));
|
QStringLiteral(":/shaders/default.frag"));
|
||||||
} else if (type == GL_VERTEX_SHADER) {
|
} else if (type == GL_VERTEX_SHADER) {
|
||||||
complete_code.append(FileFunctions::ReadFileAsString(
|
base_code = FileFunctions::ReadFileAsString(
|
||||||
QStringLiteral(":/shaders/default.vert")));
|
QStringLiteral(":/shaders/default.vert"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString complete_code;
|
||||||
|
if (base_code.startsWith(QStringLiteral("#version"))) {
|
||||||
|
if (is_gles || !desktop_preamble.startsWith(QStringLiteral("#version"))) {
|
||||||
|
int newline = base_code.indexOf('\n');
|
||||||
|
if (newline >= 0) {
|
||||||
|
complete_code = shader_preamble + base_code.mid(newline + 1);
|
||||||
|
} else {
|
||||||
|
complete_code = shader_preamble;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
complete_code = base_code;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
complete_code.append(code);
|
complete_code = shader_preamble + base_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_gles2) {
|
||||||
|
if (type == GL_VERTEX_SHADER) {
|
||||||
|
complete_code.replace(QRegularExpression(QStringLiteral("\\bin\\b")),
|
||||||
|
QStringLiteral("attribute"));
|
||||||
|
complete_code.replace(QRegularExpression(QStringLiteral("\\bout\\b")),
|
||||||
|
QStringLiteral("varying"));
|
||||||
|
} else if (type == GL_FRAGMENT_SHADER) {
|
||||||
|
complete_code.replace(QRegularExpression(QStringLiteral("\\bin\\b")),
|
||||||
|
QStringLiteral("varying"));
|
||||||
|
complete_code.replace(QRegularExpression(
|
||||||
|
QStringLiteral("\\bout\\s+vec4\\s+frag_color\\s*;")),
|
||||||
|
QStringLiteral("// frag_color output"));
|
||||||
|
complete_code.replace(QRegularExpression(QStringLiteral("\\btexture\\b")),
|
||||||
|
QStringLiteral("texture2D"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray code_utf8 = complete_code.toUtf8();
|
QByteArray code_utf8 = complete_code.toUtf8();
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ void TimeBasedWidget::SetScaleAndCenterOnPlayhead(const double &scale)
|
|||||||
|
|
||||||
ViewerOutput *TimeBasedWidget::GetConnectedNode() const
|
ViewerOutput *TimeBasedWidget::GetConnectedNode() const
|
||||||
{
|
{
|
||||||
return viewer_node_;
|
return viewer_node_.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
||||||
@@ -89,10 +89,17 @@ void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set viewer node
|
// Set viewer node
|
||||||
ViewerOutput *old = viewer_node_;
|
ViewerOutput *old = viewer_node_.data();
|
||||||
viewer_node_ = node;
|
viewer_node_ = node;
|
||||||
Current::getInstance().setCurrentVideoParams(viewer_node_->GetVideoParams());
|
if (viewer_node_) {
|
||||||
Current::getInstance().setCurrentAudioParams(viewer_node_->GetAudioParams());
|
Current::getInstance().setCurrentVideoParams(
|
||||||
|
viewer_node_->GetVideoParams());
|
||||||
|
Current::getInstance().setCurrentAudioParams(
|
||||||
|
viewer_node_->GetAudioParams());
|
||||||
|
} else {
|
||||||
|
Current::getInstance().setCurrentVideoParams(VideoParams());
|
||||||
|
Current::getInstance().setCurrentAudioParams(AudioParams());
|
||||||
|
}
|
||||||
if (old) {
|
if (old) {
|
||||||
// Call potential derivative functions for disconnecting the viewer node
|
// Call potential derivative functions for disconnecting the viewer node
|
||||||
DisconnectNodeEvent(old);
|
DisconnectNodeEvent(old);
|
||||||
@@ -121,17 +128,17 @@ void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
|||||||
|
|
||||||
// Call derivatives
|
// Call derivatives
|
||||||
for (TimeBasedView *view : timeline_views_) {
|
for (TimeBasedView *view : timeline_views_) {
|
||||||
view->SetViewerNode(viewer_node_);
|
view->SetViewerNode(viewer_node_.data());
|
||||||
}
|
}
|
||||||
ConnectedNodeChangeEvent(viewer_node_);
|
ConnectedNodeChangeEvent(viewer_node_.data());
|
||||||
|
|
||||||
if (viewer_node_) {
|
if (viewer_node_) {
|
||||||
// Connect length changed signal
|
// Connect length changed signal
|
||||||
connect(viewer_node_, &ViewerOutput::LengthChanged, this,
|
connect(viewer_node_.data(), &ViewerOutput::LengthChanged, this,
|
||||||
&TimeBasedWidget::UpdateMaximumScroll);
|
&TimeBasedWidget::UpdateMaximumScroll);
|
||||||
connect(viewer_node_, &ViewerOutput::RemovedFromGraph, this,
|
connect(viewer_node_.data(), &ViewerOutput::RemovedFromGraph, this,
|
||||||
&TimeBasedWidget::ConnectedNodeRemovedFromGraph);
|
&TimeBasedWidget::ConnectedNodeRemovedFromGraph);
|
||||||
connect(viewer_node_, &ViewerOutput::PlayheadChanged, this,
|
connect(viewer_node_.data(), &ViewerOutput::PlayheadChanged, this,
|
||||||
&TimeBasedWidget::PlayheadTimeChanged);
|
&TimeBasedWidget::PlayheadTimeChanged);
|
||||||
|
|
||||||
// Connect ruler and scrollbar to timeline points
|
// Connect ruler and scrollbar to timeline points
|
||||||
@@ -141,14 +148,14 @@ void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
|||||||
// If we're setting the timebase, set it automatically based on the video and audio parameters
|
// If we're setting the timebase, set it automatically based on the video and audio parameters
|
||||||
if (auto_set_timebase_) {
|
if (auto_set_timebase_) {
|
||||||
AutoUpdateTimebase();
|
AutoUpdateTimebase();
|
||||||
connect(viewer_node_, &ViewerOutput::FrameRateChanged, this,
|
connect(viewer_node_.data(), &ViewerOutput::FrameRateChanged, this,
|
||||||
&TimeBasedWidget::AutoUpdateTimebase);
|
&TimeBasedWidget::AutoUpdateTimebase);
|
||||||
connect(viewer_node_, &ViewerOutput::SampleRateChanged, this,
|
connect(viewer_node_.data(), &ViewerOutput::SampleRateChanged, this,
|
||||||
&TimeBasedWidget::AutoUpdateTimebase);
|
&TimeBasedWidget::AutoUpdateTimebase);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call derivatives
|
// Call derivatives
|
||||||
ConnectNodeEvent(viewer_node_);
|
ConnectNodeEvent(viewer_node_.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateMaximumScroll();
|
UpdateMaximumScroll();
|
||||||
@@ -271,6 +278,10 @@ void TimeBasedWidget::SendCatchUpScrollEvent()
|
|||||||
|
|
||||||
void TimeBasedWidget::AutoUpdateTimebase()
|
void TimeBasedWidget::AutoUpdateTimebase()
|
||||||
{
|
{
|
||||||
|
if (!viewer_node_) {
|
||||||
|
SetTimebase(rational());
|
||||||
|
return;
|
||||||
|
}
|
||||||
rational video_tb =
|
rational video_tb =
|
||||||
viewer_node_->GetVideoParams().frame_rate_as_time_base();
|
viewer_node_->GetVideoParams().frame_rate_as_time_base();
|
||||||
|
|
||||||
@@ -448,7 +459,7 @@ void TimeBasedWidget::ZoomOut()
|
|||||||
void TimeBasedWidget::GoToPrevCut()
|
void TimeBasedWidget::GoToPrevCut()
|
||||||
{
|
{
|
||||||
// Cuts are only possible in sequences
|
// Cuts are only possible in sequences
|
||||||
Sequence *sequence = dynamic_cast<Sequence *>(viewer_node_);
|
Sequence *sequence = dynamic_cast<Sequence *>(viewer_node_.data());
|
||||||
|
|
||||||
if (!sequence) {
|
if (!sequence) {
|
||||||
return;
|
return;
|
||||||
@@ -480,7 +491,7 @@ void TimeBasedWidget::GoToPrevCut()
|
|||||||
void TimeBasedWidget::GoToNextCut()
|
void TimeBasedWidget::GoToNextCut()
|
||||||
{
|
{
|
||||||
// Cuts are only possible in sequences
|
// Cuts are only possible in sequences
|
||||||
Sequence *sequence = dynamic_cast<Sequence *>(viewer_node_);
|
Sequence *sequence = dynamic_cast<Sequence *>(viewer_node_.data());
|
||||||
|
|
||||||
if (!sequence) {
|
if (!sequence) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#ifndef TIMEBASEDWIDGET_H
|
#ifndef TIMEBASEDWIDGET_H
|
||||||
#define TIMEBASEDWIDGET_H
|
#define TIMEBASEDWIDGET_H
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "node/output/viewer/viewer.h"
|
#include "node/output/viewer/viewer.h"
|
||||||
@@ -239,7 +240,7 @@ private:
|
|||||||
|
|
||||||
bool UserIsDraggingPlayhead() const;
|
bool UserIsDraggingPlayhead() const;
|
||||||
|
|
||||||
ViewerOutput *viewer_node_;
|
QPointer<ViewerOutput> viewer_node_;
|
||||||
|
|
||||||
TimeRuler *ruler_;
|
TimeRuler *ruler_;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ add_executable(olive-gtest
|
|||||||
task_taskmanager_test.cpp
|
task_taskmanager_test.cpp
|
||||||
module_smoke_test.cpp
|
module_smoke_test.cpp
|
||||||
shader_resources_test.cpp
|
shader_resources_test.cpp
|
||||||
|
timebased_widget_test.cpp
|
||||||
timeline_coordinate_test.cpp
|
timeline_coordinate_test.cpp
|
||||||
timeline_workarea_test.cpp
|
timeline_workarea_test.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "widget/timebased/timebasedwidget.h"
|
||||||
|
#include "node/output/viewer/viewer.h"
|
||||||
|
|
||||||
|
TEST(TimeBasedWidget, ConnectViewerNodeNullSafe)
|
||||||
|
{
|
||||||
|
olive::TimeBasedWidget widget(false, false);
|
||||||
|
widget.ConnectViewerNode(nullptr);
|
||||||
|
EXPECT_EQ(widget.GetConnectedNode(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TimeBasedWidget, ConnectedNodeClearsOnDelete)
|
||||||
|
{
|
||||||
|
olive::TimeBasedWidget widget(false, false);
|
||||||
|
auto *viewer = new olive::ViewerOutput();
|
||||||
|
widget.ConnectViewerNode(viewer);
|
||||||
|
EXPECT_EQ(widget.GetConnectedNode(), viewer);
|
||||||
|
delete viewer;
|
||||||
|
EXPECT_EQ(widget.GetConnectedNode(), nullptr);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user