style: reformat C/C++ sources and headers with clang-format
Run clang-format over all project C/C++ source and header files (.c, .cpp, .cc, .h, .hpp, .hh, .m, .mm) under app/ and tests/. Non-source files (svg, qm, qrc, etc.) were not touched.
This commit is contained in:
@@ -11,7 +11,8 @@ extern "C" {
|
|||||||
#include <libavutil/channel_layout.h>
|
#include <libavutil/channel_layout.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
olive::core::AudioParams MakeStereoParams()
|
olive::core::AudioParams MakeStereoParams()
|
||||||
{
|
{
|
||||||
|
|||||||
+579
-572
File diff suppressed because it is too large
Load Diff
@@ -13,8 +13,8 @@ TEST(AudioSynchronizer, PlacesCandidateBySourceStartTime)
|
|||||||
candidate.has_source_start_time = true;
|
candidate.has_source_start_time = true;
|
||||||
|
|
||||||
const olive::AudioSynchronizer::Placement placement =
|
const olive::AudioSynchronizer::Placement placement =
|
||||||
olive::AudioSynchronizer::PlaceBySourceTime(
|
olive::AudioSynchronizer::PlaceBySourceTime(reference, candidate,
|
||||||
reference, candidate, olive::core::rational(10));
|
olive::core::rational(10));
|
||||||
|
|
||||||
ASSERT_TRUE(placement.valid);
|
ASSERT_TRUE(placement.valid);
|
||||||
EXPECT_EQ(placement.timeline_in, olive::core::rational(22));
|
EXPECT_EQ(placement.timeline_in, olive::core::rational(22));
|
||||||
@@ -33,8 +33,8 @@ TEST(AudioSynchronizer, AccountsForMediaInWhenPlacingBySourceTime)
|
|||||||
candidate.has_source_start_time = true;
|
candidate.has_source_start_time = true;
|
||||||
|
|
||||||
const olive::AudioSynchronizer::Placement placement =
|
const olive::AudioSynchronizer::Placement placement =
|
||||||
olive::AudioSynchronizer::PlaceBySourceTime(
|
olive::AudioSynchronizer::PlaceBySourceTime(reference, candidate,
|
||||||
reference, candidate, olive::core::rational(20));
|
olive::core::rational(20));
|
||||||
|
|
||||||
ASSERT_TRUE(placement.valid);
|
ASSERT_TRUE(placement.valid);
|
||||||
EXPECT_EQ(placement.timeline_in, olive::core::rational(23));
|
EXPECT_EQ(placement.timeline_in, olive::core::rational(23));
|
||||||
@@ -49,8 +49,8 @@ TEST(AudioSynchronizer, RejectsMissingSourceStartTime)
|
|||||||
olive::AudioSynchronizer::SourceClip candidate;
|
olive::AudioSynchronizer::SourceClip candidate;
|
||||||
|
|
||||||
const olive::AudioSynchronizer::Placement placement =
|
const olive::AudioSynchronizer::Placement placement =
|
||||||
olive::AudioSynchronizer::PlaceBySourceTime(
|
olive::AudioSynchronizer::PlaceBySourceTime(reference, candidate,
|
||||||
reference, candidate, olive::core::rational(10));
|
olive::core::rational(10));
|
||||||
|
|
||||||
EXPECT_FALSE(placement.valid);
|
EXPECT_FALSE(placement.valid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ extern "C" {
|
|||||||
#include <libavutil/channel_layout.h>
|
#include <libavutil/channel_layout.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
olive::core::AudioParams MakeMonoParams()
|
olive::core::AudioParams MakeMonoParams()
|
||||||
{
|
{
|
||||||
@@ -46,13 +47,11 @@ TEST(AudioWaveformSync, ExtractsRmsEnvelope)
|
|||||||
|
|
||||||
TEST(AudioWaveformSync, EstimatesCandidateLag)
|
TEST(AudioWaveformSync, EstimatesCandidateLag)
|
||||||
{
|
{
|
||||||
const QVector<float> reference_values = {
|
const QVector<float> reference_values = { 0.0f, 0.0f, 0.8f, 0.8f, 0.1f,
|
||||||
0.0f, 0.0f, 0.8f, 0.8f, 0.1f, 0.1f, 0.6f, 0.6f, 0.0f, 0.0f
|
0.1f, 0.6f, 0.6f, 0.0f, 0.0f };
|
||||||
};
|
const QVector<float> candidate_values = { 0.0f, 0.0f, 0.0f, 0.0f,
|
||||||
const QVector<float> candidate_values = {
|
0.8f, 0.8f, 0.1f, 0.1f,
|
||||||
0.0f, 0.0f, 0.0f, 0.0f, 0.8f, 0.8f, 0.1f,
|
0.6f, 0.6f, 0.0f, 0.0f };
|
||||||
0.1f, 0.6f, 0.6f, 0.0f, 0.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
const olive::AudioWaveformSync::OffsetResult result =
|
const olive::AudioWaveformSync::OffsetResult result =
|
||||||
olive::AudioWaveformSync::EstimateOffset(
|
olive::AudioWaveformSync::EstimateOffset(
|
||||||
@@ -65,13 +64,11 @@ TEST(AudioWaveformSync, EstimatesCandidateLag)
|
|||||||
|
|
||||||
TEST(AudioWaveformSync, EstimatesCandidateLead)
|
TEST(AudioWaveformSync, EstimatesCandidateLead)
|
||||||
{
|
{
|
||||||
const QVector<float> reference_values = {
|
const QVector<float> reference_values = { 0.0f, 0.0f, 0.0f, 0.0f,
|
||||||
0.0f, 0.0f, 0.0f, 0.0f, 0.9f, 0.9f, 0.3f,
|
0.9f, 0.9f, 0.3f, 0.3f,
|
||||||
0.3f, 0.7f, 0.7f, 0.0f, 0.0f
|
0.7f, 0.7f, 0.0f, 0.0f };
|
||||||
};
|
const QVector<float> candidate_values = { 0.9f, 0.9f, 0.3f, 0.3f,
|
||||||
const QVector<float> candidate_values = {
|
0.7f, 0.7f, 0.0f, 0.0f };
|
||||||
0.9f, 0.9f, 0.3f, 0.3f, 0.7f, 0.7f, 0.0f, 0.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
const olive::AudioWaveformSync::OffsetResult result =
|
const olive::AudioWaveformSync::OffsetResult result =
|
||||||
olive::AudioWaveformSync::EstimateOffset(
|
olive::AudioWaveformSync::EstimateOffset(
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ TEST(CodecDecoder, RetrieveVideoFrameFromDemoMp4)
|
|||||||
.filePath(QStringLiteral("tests/demo.mp4"));
|
.filePath(QStringLiteral("tests/demo.mp4"));
|
||||||
ASSERT_TRUE(QFileInfo::exists(path));
|
ASSERT_TRUE(QFileInfo::exists(path));
|
||||||
|
|
||||||
olive::DecoderPtr decoder = olive::Decoder::CreateFromID(QStringLiteral("ffmpeg"));
|
olive::DecoderPtr decoder =
|
||||||
|
olive::Decoder::CreateFromID(QStringLiteral("ffmpeg"));
|
||||||
ASSERT_TRUE(decoder);
|
ASSERT_TRUE(decoder);
|
||||||
|
|
||||||
ASSERT_TRUE(decoder->Open(olive::Decoder::CodecStream(path, 0, nullptr)));
|
ASSERT_TRUE(decoder->Open(olive::Decoder::CodecStream(path, 0, nullptr)));
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
#include "codec/encoder.h"
|
#include "codec/encoder.h"
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
class TestEncoder final : public olive::Encoder {
|
class TestEncoder final : public olive::Encoder {
|
||||||
public:
|
public:
|
||||||
explicit TestEncoder(const olive::EncodingParams ¶ms)
|
explicit TestEncoder(const olive::EncodingParams ¶ms)
|
||||||
@@ -57,8 +58,8 @@ TEST(CodecEncoder, ImageSequenceFilenames)
|
|||||||
QStringLiteral("frame_[####].png")),
|
QStringLiteral("frame_[####].png")),
|
||||||
QStringLiteral("frame.png"));
|
QStringLiteral("frame.png"));
|
||||||
|
|
||||||
const QString filename = encoder.GetFilenameForFrame(
|
const QString filename =
|
||||||
olive::core::rational(1, 24));
|
encoder.GetFilenameForFrame(olive::core::rational(1, 24));
|
||||||
EXPECT_EQ(filename, QStringLiteral("frame_0001.png"));
|
EXPECT_EQ(filename, QStringLiteral("frame_0001.png"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,21 +67,18 @@ TEST(CodecEncoder, MatrixGeneration)
|
|||||||
{
|
{
|
||||||
using Method = olive::EncodingParams::VideoScalingMethod;
|
using Method = olive::EncodingParams::VideoScalingMethod;
|
||||||
|
|
||||||
QMatrix4x4 stretch =
|
QMatrix4x4 stretch = olive::EncodingParams::GenerateMatrix(
|
||||||
olive::EncodingParams::GenerateMatrix(Method::kStretch, 1920, 1080,
|
Method::kStretch, 1920, 1080, 1280, 720);
|
||||||
1280, 720);
|
|
||||||
EXPECT_TRUE(qFuzzyCompare(stretch(0, 0), 1.0f));
|
EXPECT_TRUE(qFuzzyCompare(stretch(0, 0), 1.0f));
|
||||||
EXPECT_TRUE(qFuzzyCompare(stretch(1, 1), 1.0f));
|
EXPECT_TRUE(qFuzzyCompare(stretch(1, 1), 1.0f));
|
||||||
|
|
||||||
QMatrix4x4 fit =
|
QMatrix4x4 fit = olive::EncodingParams::GenerateMatrix(Method::kFit, 1920,
|
||||||
olive::EncodingParams::GenerateMatrix(Method::kFit, 1920, 1080,
|
1080, 1024, 1024);
|
||||||
1024, 1024);
|
|
||||||
EXPECT_TRUE(qFuzzyCompare(fit(0, 0), 1.0f));
|
EXPECT_TRUE(qFuzzyCompare(fit(0, 0), 1.0f));
|
||||||
EXPECT_FALSE(qFuzzyCompare(fit(1, 1), 1.0f));
|
EXPECT_FALSE(qFuzzyCompare(fit(1, 1), 1.0f));
|
||||||
|
|
||||||
QMatrix4x4 crop =
|
QMatrix4x4 crop = olive::EncodingParams::GenerateMatrix(Method::kCrop, 1920,
|
||||||
olive::EncodingParams::GenerateMatrix(Method::kCrop, 1920, 1080,
|
1080, 1024, 1024);
|
||||||
1024, 1024);
|
|
||||||
EXPECT_FALSE(qFuzzyCompare(crop(0, 0), 1.0f));
|
EXPECT_FALSE(qFuzzyCompare(crop(0, 0), 1.0f));
|
||||||
EXPECT_TRUE(qFuzzyCompare(crop(1, 1), 1.0f));
|
EXPECT_TRUE(qFuzzyCompare(crop(1, 1), 1.0f));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ TEST(CodecExportFormat, NamesAndExtensions)
|
|||||||
QStringLiteral("mxf"));
|
QStringLiteral("mxf"));
|
||||||
EXPECT_EQ(ExportFormat::GetName(ExportFormat::kFormatCount),
|
EXPECT_EQ(ExportFormat::GetName(ExportFormat::kFormatCount),
|
||||||
QStringLiteral("Unknown"));
|
QStringLiteral("Unknown"));
|
||||||
EXPECT_TRUE(ExportFormat::GetExtension(ExportFormat::kFormatCount).isEmpty());
|
EXPECT_TRUE(
|
||||||
|
ExportFormat::GetExtension(ExportFormat::kFormatCount).isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CodecExportFormat, AllFormatsHaveNames)
|
TEST(CodecExportFormat, AllFormatsHaveNames)
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ TEST(CodecFrame, AllocateMatchesLineSize)
|
|||||||
TEST(CodecFrame, DestroyDeallocatesData)
|
TEST(CodecFrame, DestroyDeallocatesData)
|
||||||
{
|
{
|
||||||
olive::FramePtr frame = olive::Frame::Create();
|
olive::FramePtr frame = olive::Frame::Create();
|
||||||
frame->set_video_params(olive::VideoParams(
|
frame->set_video_params(
|
||||||
8, 8, olive::core::PixelFormat::U8,
|
olive::VideoParams(8, 8, olive::core::PixelFormat::U8,
|
||||||
olive::VideoParams::kRGBAChannelCount));
|
olive::VideoParams::kRGBAChannelCount));
|
||||||
frame->allocate();
|
frame->allocate();
|
||||||
EXPECT_TRUE(frame->is_allocated());
|
EXPECT_TRUE(frame->is_allocated());
|
||||||
|
|
||||||
@@ -55,7 +55,6 @@ TEST(CodecFrame, DestroyDeallocatesData)
|
|||||||
EXPECT_EQ(frame->data(), nullptr);
|
EXPECT_EQ(frame->data(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(CodecFrame, AllocateInvalidParamsFails)
|
TEST(CodecFrame, AllocateInvalidParamsFails)
|
||||||
{
|
{
|
||||||
olive::Frame frame;
|
olive::Frame frame;
|
||||||
@@ -157,13 +156,15 @@ TEST(CodecFrame, InterlaceFrames)
|
|||||||
TEST(CodecFrame, InterlaceIncompatibleReturnsNull)
|
TEST(CodecFrame, InterlaceIncompatibleReturnsNull)
|
||||||
{
|
{
|
||||||
olive::FramePtr top = olive::Frame::Create();
|
olive::FramePtr top = olive::Frame::Create();
|
||||||
top->set_video_params(olive::VideoParams(
|
top->set_video_params(
|
||||||
4, 4, olive::core::PixelFormat::U8, olive::VideoParams::kRGBAChannelCount));
|
olive::VideoParams(4, 4, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount));
|
||||||
top->allocate();
|
top->allocate();
|
||||||
|
|
||||||
olive::FramePtr bottom = olive::Frame::Create();
|
olive::FramePtr bottom = olive::Frame::Create();
|
||||||
bottom->set_video_params(olive::VideoParams(
|
bottom->set_video_params(
|
||||||
8, 8, olive::core::PixelFormat::U8, olive::VideoParams::kRGBAChannelCount));
|
olive::VideoParams(8, 8, olive::core::PixelFormat::U8,
|
||||||
|
olive::VideoParams::kRGBAChannelCount));
|
||||||
bottom->allocate();
|
bottom->allocate();
|
||||||
|
|
||||||
EXPECT_EQ(olive::Frame::Interlace(top, bottom), nullptr);
|
EXPECT_EQ(olive::Frame::Interlace(top, bottom), nullptr);
|
||||||
@@ -177,8 +178,7 @@ TEST(CodecFrame, ConvertU8ToU16)
|
|||||||
frame->set_video_params(params);
|
frame->set_video_params(params);
|
||||||
frame->allocate();
|
frame->allocate();
|
||||||
|
|
||||||
olive::FramePtr converted =
|
olive::FramePtr converted = frame->convert(olive::core::PixelFormat::U16);
|
||||||
frame->convert(olive::core::PixelFormat::U16);
|
|
||||||
ASSERT_NE(converted, nullptr);
|
ASSERT_NE(converted, nullptr);
|
||||||
EXPECT_EQ(converted->format(), olive::core::PixelFormat::U16);
|
EXPECT_EQ(converted->format(), olive::core::PixelFormat::U16);
|
||||||
EXPECT_EQ(converted->width(), 4);
|
EXPECT_EQ(converted->width(), 4);
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
namespace OCIO = OCIO_NAMESPACE;
|
namespace OCIO = OCIO_NAMESPACE;
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
bool IsOakSupportedLutExtension(QString suffix)
|
bool IsOakSupportedLutExtension(QString suffix)
|
||||||
{
|
{
|
||||||
@@ -31,19 +32,19 @@ bool IsOakSupportedLutExtension(QString suffix)
|
|||||||
|
|
||||||
QString WriteTestCube(QTemporaryDir *dir)
|
QString WriteTestCube(QTemporaryDir *dir)
|
||||||
{
|
{
|
||||||
const QString path = QDir(dir->path()).filePath(QStringLiteral("invert.cube"));
|
const QString path =
|
||||||
|
QDir(dir->path()).filePath(QStringLiteral("invert.cube"));
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray data =
|
const QByteArray data = "TITLE \"Oak test invert\"\n"
|
||||||
"TITLE \"Oak test invert\"\n"
|
"LUT_1D_SIZE 2\n"
|
||||||
"LUT_1D_SIZE 2\n"
|
"DOMAIN_MIN 0.0 0.0 0.0\n"
|
||||||
"DOMAIN_MIN 0.0 0.0 0.0\n"
|
"DOMAIN_MAX 1.0 1.0 1.0\n"
|
||||||
"DOMAIN_MAX 1.0 1.0 1.0\n"
|
"1.0 1.0 1.0\n"
|
||||||
"1.0 1.0 1.0\n"
|
"0.0 0.0 0.0\n";
|
||||||
"0.0 0.0 0.0\n";
|
|
||||||
file.write(data);
|
file.write(data);
|
||||||
file.close();
|
file.close();
|
||||||
return path;
|
return path;
|
||||||
@@ -87,9 +88,10 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void ProcessColorTransform(olive::TexturePtr destination,
|
virtual void
|
||||||
const olive::Node *node,
|
ProcessColorTransform(olive::TexturePtr destination,
|
||||||
const olive::ColorTransformJob *job) override
|
const olive::Node *node,
|
||||||
|
const olive::ColorTransformJob *job) override
|
||||||
{
|
{
|
||||||
Q_UNUSED(destination)
|
Q_UNUSED(destination)
|
||||||
Q_UNUSED(node)
|
Q_UNUSED(node)
|
||||||
@@ -110,11 +112,12 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
QString WriteTestCubeLut(QTemporaryDir *dir, const char *title,
|
QString WriteTestCubeLut(QTemporaryDir *dir, const char *title, float low,
|
||||||
float low, float high)
|
float high)
|
||||||
{
|
{
|
||||||
const QString path = QDir(dir->path()).filePath(
|
const QString path =
|
||||||
QStringLiteral("%1.cube").arg(QString::fromUtf8(title)));
|
QDir(dir->path())
|
||||||
|
.filePath(QStringLiteral("%1.cube").arg(QString::fromUtf8(title)));
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
return QString();
|
return QString();
|
||||||
@@ -147,14 +150,13 @@ QString WriteAsymmetricCube(QTemporaryDir *dir)
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QByteArray data =
|
const QByteArray data = "TITLE \"Oak test asymmetric\"\n"
|
||||||
"TITLE \"Oak test asymmetric\"\n"
|
"LUT_1D_SIZE 3\n"
|
||||||
"LUT_1D_SIZE 3\n"
|
"DOMAIN_MIN 0.0 0.0 0.0\n"
|
||||||
"DOMAIN_MIN 0.0 0.0 0.0\n"
|
"DOMAIN_MAX 1.0 1.0 1.0\n"
|
||||||
"DOMAIN_MAX 1.0 1.0 1.0\n"
|
"0.00 0.00 0.00\n"
|
||||||
"0.00 0.00 0.00\n"
|
"0.75 0.75 0.75\n"
|
||||||
"0.75 0.75 0.75\n"
|
"1.00 1.00 1.00\n";
|
||||||
"1.00 1.00 1.00\n";
|
|
||||||
file.write(data);
|
file.write(data);
|
||||||
file.close();
|
file.close();
|
||||||
return path;
|
return path;
|
||||||
@@ -231,7 +233,8 @@ TEST(ColorLut, CubeFileTransformConvertsColor)
|
|||||||
olive::ColorProcessor::Create(config->getProcessor(transform));
|
olive::ColorProcessor::Create(config->getProcessor(transform));
|
||||||
ASSERT_TRUE(processor);
|
ASSERT_TRUE(processor);
|
||||||
|
|
||||||
const olive::Color out = processor->ConvertColor(olive::Color(0.25f, 0.50f, 0.75f, 1.0f));
|
const olive::Color out =
|
||||||
|
processor->ConvertColor(olive::Color(0.25f, 0.50f, 0.75f, 1.0f));
|
||||||
EXPECT_NEAR(out.red(), 0.75f, 0.02f);
|
EXPECT_NEAR(out.red(), 0.75f, 0.02f);
|
||||||
EXPECT_NEAR(out.green(), 0.50f, 0.02f);
|
EXPECT_NEAR(out.green(), 0.50f, 0.02f);
|
||||||
EXPECT_NEAR(out.blue(), 0.25f, 0.02f);
|
EXPECT_NEAR(out.blue(), 0.25f, 0.02f);
|
||||||
@@ -240,9 +243,8 @@ TEST(ColorLut, CubeFileTransformConvertsColor)
|
|||||||
|
|
||||||
TEST(ColorV04, FactoryCreatesColorNodes)
|
TEST(ColorV04, FactoryCreatesColorNodes)
|
||||||
{
|
{
|
||||||
std::unique_ptr<olive::Node> lut(
|
std::unique_ptr<olive::Node> lut(olive::NodeFactory::CreateFromFactoryIndex(
|
||||||
olive::NodeFactory::CreateFromFactoryIndex(
|
olive::NodeFactory::kOCIOLut));
|
||||||
olive::NodeFactory::kOCIOLut));
|
|
||||||
ASSERT_NE(lut, nullptr);
|
ASSERT_NE(lut, nullptr);
|
||||||
EXPECT_EQ(lut->id(), QStringLiteral("org.olivevideoeditor.Olive.ociolut"));
|
EXPECT_EQ(lut->id(), QStringLiteral("org.olivevideoeditor.Olive.ociolut"));
|
||||||
|
|
||||||
@@ -260,8 +262,8 @@ TEST(ColorV04, FactoryCreatesColorNodes)
|
|||||||
olive::ThreeWayColorNode::kHighlightsColorInput));
|
olive::ThreeWayColorNode::kHighlightsColorInput));
|
||||||
|
|
||||||
const olive::Color neutral =
|
const olive::Color neutral =
|
||||||
three_way->GetStandardValue(
|
three_way
|
||||||
olive::ThreeWayColorNode::kMidtonesColorInput)
|
->GetStandardValue(olive::ThreeWayColorNode::kMidtonesColorInput)
|
||||||
.value<olive::Color>();
|
.value<olive::Color>();
|
||||||
EXPECT_FLOAT_EQ(neutral.red(), 0.5f);
|
EXPECT_FLOAT_EQ(neutral.red(), 0.5f);
|
||||||
EXPECT_FLOAT_EQ(neutral.green(), 0.5f);
|
EXPECT_FLOAT_EQ(neutral.green(), 0.5f);
|
||||||
@@ -306,9 +308,8 @@ TEST(ColorLutNode, ForwardDirectionInvertsPixels)
|
|||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
PixelColorTransformTraverser traverser;
|
PixelColorTransformTraverser traverser;
|
||||||
traverser.SetCacheVideoParams(params);
|
traverser.SetCacheVideoParams(params);
|
||||||
@@ -354,9 +355,8 @@ TEST(ColorLutNode, InverseDirectionReversesForwardTransform)
|
|||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
PixelColorTransformTraverser traverser;
|
PixelColorTransformTraverser traverser;
|
||||||
traverser.SetCacheVideoParams(params);
|
traverser.SetCacheVideoParams(params);
|
||||||
@@ -402,9 +402,8 @@ TEST(ColorLutNode, SwitchingDirectionUpdatesProcessorAndPixels)
|
|||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
// First render: forward direction.
|
// First render: forward direction.
|
||||||
PixelColorTransformTraverser forward_traverser;
|
PixelColorTransformTraverser forward_traverser;
|
||||||
@@ -471,9 +470,8 @@ TEST(ColorLutNode, EmptyFilePathLeavesProcessorNull)
|
|||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
PixelColorTransformTraverser traverser;
|
PixelColorTransformTraverser traverser;
|
||||||
traverser.SetCacheVideoParams(params);
|
traverser.SetCacheVideoParams(params);
|
||||||
@@ -503,14 +501,13 @@ TEST(ColorLutNode, MissingFilePathLeavesProcessorNull)
|
|||||||
auto *lut = new olive::OCIOLutNode();
|
auto *lut = new olive::OCIOLutNode();
|
||||||
lut->setParent(&project);
|
lut->setParent(&project);
|
||||||
lut->SetStandardValue(olive::OCIOLutNode::kFileInput,
|
lut->SetStandardValue(olive::OCIOLutNode::kFileInput,
|
||||||
QStringLiteral("/nonexistent/path/lut.cube"));
|
QStringLiteral("/nonexistent/path/lut.cube"));
|
||||||
|
|
||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
PixelColorTransformTraverser traverser;
|
PixelColorTransformTraverser traverser;
|
||||||
traverser.SetCacheVideoParams(params);
|
traverser.SetCacheVideoParams(params);
|
||||||
@@ -538,14 +535,13 @@ TEST(ColorLutNode, UnsupportedExtensionLeavesProcessorNull)
|
|||||||
auto *lut = new olive::OCIOLutNode();
|
auto *lut = new olive::OCIOLutNode();
|
||||||
lut->setParent(&project);
|
lut->setParent(&project);
|
||||||
lut->SetStandardValue(olive::OCIOLutNode::kFileInput,
|
lut->SetStandardValue(olive::OCIOLutNode::kFileInput,
|
||||||
QStringLiteral("/tmp/lut.txt"));
|
QStringLiteral("/tmp/lut.txt"));
|
||||||
|
|
||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
PixelColorTransformTraverser traverser;
|
PixelColorTransformTraverser traverser;
|
||||||
traverser.SetCacheVideoParams(params);
|
traverser.SetCacheVideoParams(params);
|
||||||
@@ -579,14 +575,13 @@ TEST(ColorLutNode, DirectionStringValuesAreAccepted)
|
|||||||
lut->setParent(&project);
|
lut->setParent(&project);
|
||||||
lut->SetStandardValue(olive::OCIOLutNode::kFileInput, path);
|
lut->SetStandardValue(olive::OCIOLutNode::kFileInput, path);
|
||||||
lut->SetStandardValue(olive::OCIOLutNode::kDirectionInput,
|
lut->SetStandardValue(olive::OCIOLutNode::kDirectionInput,
|
||||||
QStringLiteral("forward"));
|
QStringLiteral("forward"));
|
||||||
|
|
||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
PixelColorTransformTraverser traverser;
|
PixelColorTransformTraverser traverser;
|
||||||
traverser.SetCacheVideoParams(params);
|
traverser.SetCacheVideoParams(params);
|
||||||
@@ -626,14 +621,13 @@ TEST(ColorLutNode, DirectionStringInverseIsAccepted)
|
|||||||
lut->setParent(&project);
|
lut->setParent(&project);
|
||||||
lut->SetStandardValue(olive::OCIOLutNode::kFileInput, path);
|
lut->SetStandardValue(olive::OCIOLutNode::kFileInput, path);
|
||||||
lut->SetStandardValue(olive::OCIOLutNode::kDirectionInput,
|
lut->SetStandardValue(olive::OCIOLutNode::kDirectionInput,
|
||||||
QStringLiteral("inverse"));
|
QStringLiteral("inverse"));
|
||||||
|
|
||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
PixelColorTransformTraverser traverser;
|
PixelColorTransformTraverser traverser;
|
||||||
traverser.SetCacheVideoParams(params);
|
traverser.SetCacheVideoParams(params);
|
||||||
@@ -676,9 +670,8 @@ TEST(ColorLutNode, ReusingSameFileDoesNotCrash)
|
|||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
// Render twice; the second render should reuse the cached processor.
|
// Render twice; the second render should reuse the cached processor.
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
@@ -708,10 +701,8 @@ TEST(ColorLutNode, SwitchingBackToOriginalFileRestoresOriginalPixels)
|
|||||||
QTemporaryDir dir;
|
QTemporaryDir dir;
|
||||||
ASSERT_TRUE(dir.isValid());
|
ASSERT_TRUE(dir.isValid());
|
||||||
|
|
||||||
const QString invert_path = WriteTestCubeLut(
|
const QString invert_path = WriteTestCubeLut(&dir, "invert", 0.0f, 1.0f);
|
||||||
&dir, "invert", 0.0f, 1.0f);
|
const QString boost_path = WriteTestCubeLut(&dir, "boost", 0.5f, 1.0f);
|
||||||
const QString boost_path = WriteTestCubeLut(
|
|
||||||
&dir, "boost", 0.5f, 1.0f);
|
|
||||||
ASSERT_FALSE(invert_path.isEmpty());
|
ASSERT_FALSE(invert_path.isEmpty());
|
||||||
ASSERT_FALSE(boost_path.isEmpty());
|
ASSERT_FALSE(boost_path.isEmpty());
|
||||||
|
|
||||||
@@ -728,9 +719,8 @@ TEST(ColorLutNode, SwitchingBackToOriginalFileRestoresOriginalPixels)
|
|||||||
olive::Node::ConnectEdge(
|
olive::Node::ConnectEdge(
|
||||||
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
solid, olive::NodeInput(lut, olive::OCIOLutNode::kTextureInput));
|
||||||
|
|
||||||
const olive::VideoParams params(
|
const olive::VideoParams params(16, 16, olive::core::PixelFormat::F32,
|
||||||
16, 16, olive::core::PixelFormat::F32,
|
olive::VideoParams::kRGBAChannelCount);
|
||||||
olive::VideoParams::kRGBAChannelCount);
|
|
||||||
|
|
||||||
auto render = [&]() {
|
auto render = [&]() {
|
||||||
PixelColorTransformTraverser traverser;
|
PixelColorTransformTraverser traverser;
|
||||||
|
|||||||
@@ -4,80 +4,80 @@
|
|||||||
|
|
||||||
TEST(CommonCommandLineParser, OptionWithoutArgument)
|
TEST(CommonCommandLineParser, OptionWithoutArgument)
|
||||||
{
|
{
|
||||||
CommandLineParser parser;
|
CommandLineParser parser;
|
||||||
const CommandLineParser::Option *opt = parser.AddOption(
|
const CommandLineParser::Option *opt =
|
||||||
{QStringLiteral("help"), QStringLiteral("h")},
|
parser.AddOption({ QStringLiteral("help"), QStringLiteral("h") },
|
||||||
QStringLiteral("Show help"), false);
|
QStringLiteral("Show help"), false);
|
||||||
|
|
||||||
parser.Process({QStringLiteral("app"), QStringLiteral("-help")});
|
parser.Process({ QStringLiteral("app"), QStringLiteral("-help") });
|
||||||
|
|
||||||
EXPECT_TRUE(opt->IsSet());
|
EXPECT_TRUE(opt->IsSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonCommandLineParser, ShortOption)
|
TEST(CommonCommandLineParser, ShortOption)
|
||||||
{
|
{
|
||||||
CommandLineParser parser;
|
CommandLineParser parser;
|
||||||
const CommandLineParser::Option *opt = parser.AddOption(
|
const CommandLineParser::Option *opt =
|
||||||
{QStringLiteral("help"), QStringLiteral("h")},
|
parser.AddOption({ QStringLiteral("help"), QStringLiteral("h") },
|
||||||
QStringLiteral("Show help"), false);
|
QStringLiteral("Show help"), false);
|
||||||
|
|
||||||
parser.Process({QStringLiteral("app"), QStringLiteral("-h")});
|
parser.Process({ QStringLiteral("app"), QStringLiteral("-h") });
|
||||||
|
|
||||||
EXPECT_TRUE(opt->IsSet());
|
EXPECT_TRUE(opt->IsSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonCommandLineParser, OptionWithArgument)
|
TEST(CommonCommandLineParser, OptionWithArgument)
|
||||||
{
|
{
|
||||||
CommandLineParser parser;
|
CommandLineParser parser;
|
||||||
const CommandLineParser::Option *opt = parser.AddOption(
|
const CommandLineParser::Option *opt = parser.AddOption(
|
||||||
{QStringLiteral("project")}, QStringLiteral("Project file"), true,
|
{ QStringLiteral("project") }, QStringLiteral("Project file"), true,
|
||||||
QStringLiteral("file"));
|
QStringLiteral("file"));
|
||||||
|
|
||||||
parser.Process({QStringLiteral("app"), QStringLiteral("-project"),
|
parser.Process({ QStringLiteral("app"), QStringLiteral("-project"),
|
||||||
QStringLiteral("test.ove")});
|
QStringLiteral("test.ove") });
|
||||||
|
|
||||||
EXPECT_TRUE(opt->IsSet());
|
EXPECT_TRUE(opt->IsSet());
|
||||||
EXPECT_EQ(opt->GetSetting(), QStringLiteral("test.ove"));
|
EXPECT_EQ(opt->GetSetting(), QStringLiteral("test.ove"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonCommandLineParser, PositionalArgument)
|
TEST(CommonCommandLineParser, PositionalArgument)
|
||||||
{
|
{
|
||||||
CommandLineParser parser;
|
CommandLineParser parser;
|
||||||
const CommandLineParser::PositionalArgument *arg =
|
const CommandLineParser::PositionalArgument *arg =
|
||||||
parser.AddPositionalArgument(QStringLiteral("filename"),
|
parser.AddPositionalArgument(QStringLiteral("filename"),
|
||||||
QStringLiteral("Project file"), true);
|
QStringLiteral("Project file"), true);
|
||||||
|
|
||||||
parser.Process({QStringLiteral("app"), QStringLiteral("test.ove")});
|
parser.Process({ QStringLiteral("app"), QStringLiteral("test.ove") });
|
||||||
|
|
||||||
EXPECT_EQ(arg->GetSetting(), QStringLiteral("test.ove"));
|
EXPECT_EQ(arg->GetSetting(), QStringLiteral("test.ove"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonCommandLineParser, UnknownOptionWarning)
|
TEST(CommonCommandLineParser, UnknownOptionWarning)
|
||||||
{
|
{
|
||||||
CommandLineParser parser;
|
CommandLineParser parser;
|
||||||
parser.AddOption({QStringLiteral("known")}, QStringLiteral("Known"));
|
parser.AddOption({ QStringLiteral("known") }, QStringLiteral("Known"));
|
||||||
|
|
||||||
// Should not crash; unknown option is logged
|
// Should not crash; unknown option is logged
|
||||||
parser.Process({QStringLiteral("app"), QStringLiteral("-unknown")});
|
parser.Process({ QStringLiteral("app"), QStringLiteral("-unknown") });
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonCommandLineParser, UnknownPositionalWarning)
|
TEST(CommonCommandLineParser, UnknownPositionalWarning)
|
||||||
{
|
{
|
||||||
CommandLineParser parser;
|
CommandLineParser parser;
|
||||||
|
|
||||||
// Should not crash; unknown positional is logged
|
// Should not crash; unknown positional is logged
|
||||||
parser.Process({QStringLiteral("app"), QStringLiteral("extra")});
|
parser.Process({ QStringLiteral("app"), QStringLiteral("extra") });
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonCommandLineParser, HiddenOptionExcludedFromHelp)
|
TEST(CommonCommandLineParser, HiddenOptionExcludedFromHelp)
|
||||||
{
|
{
|
||||||
CommandLineParser parser;
|
CommandLineParser parser;
|
||||||
parser.AddOption({QStringLiteral("visible")}, QStringLiteral("Visible"));
|
parser.AddOption({ QStringLiteral("visible") }, QStringLiteral("Visible"));
|
||||||
parser.AddOption({QStringLiteral("hidden")}, QStringLiteral("Hidden"),
|
parser.AddOption({ QStringLiteral("hidden") }, QStringLiteral("Hidden"),
|
||||||
false, QString(), true);
|
false, QString(), true);
|
||||||
parser.AddPositionalArgument(QStringLiteral("file"),
|
parser.AddPositionalArgument(QStringLiteral("file"),
|
||||||
QStringLiteral("Input file"));
|
QStringLiteral("Input file"));
|
||||||
|
|
||||||
// Should not crash; hidden option should be skipped during help output
|
// Should not crash; hidden option should be skipped during help output
|
||||||
parser.PrintHelp("/usr/bin/app");
|
parser.PrintHelp("/usr/bin/app");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ TEST(CommonCurrent, SetAndGetVideoParams)
|
|||||||
params.set_height(1080);
|
params.set_height(1080);
|
||||||
Current::getInstance().setCurrentVideoParams(params);
|
Current::getInstance().setCurrentVideoParams(params);
|
||||||
|
|
||||||
const olive::VideoParams &stored = Current::getInstance().currentVideoParams();
|
const olive::VideoParams &stored =
|
||||||
|
Current::getInstance().currentVideoParams();
|
||||||
EXPECT_EQ(stored.width(), 1920);
|
EXPECT_EQ(stored.width(), 1920);
|
||||||
EXPECT_EQ(stored.height(), 1080);
|
EXPECT_EQ(stored.height(), 1080);
|
||||||
}
|
}
|
||||||
@@ -22,6 +23,7 @@ TEST(CommonCurrent, SetAndGetAudioParams)
|
|||||||
params.set_sample_rate(48000);
|
params.set_sample_rate(48000);
|
||||||
Current::getInstance().setCurrentAudioParams(params);
|
Current::getInstance().setCurrentAudioParams(params);
|
||||||
|
|
||||||
const olive::AudioParams &stored = Current::getInstance().currentAudioParams();
|
const olive::AudioParams &stored =
|
||||||
|
Current::getInstance().currentAudioParams();
|
||||||
EXPECT_EQ(stored.sample_rate(), 48000);
|
EXPECT_EQ(stored.sample_rate(), 48000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
TEST(CommonDebug, DebugHandlerFormatsAllLevels)
|
TEST(CommonDebug, DebugHandlerFormatsAllLevels)
|
||||||
{
|
{
|
||||||
// Install handler and restore after test
|
// Install handler and restore after test
|
||||||
QtMessageHandler old = qInstallMessageHandler(olive::DebugHandler);
|
QtMessageHandler old = qInstallMessageHandler(olive::DebugHandler);
|
||||||
|
|
||||||
qDebug() << "debug message";
|
qDebug() << "debug message";
|
||||||
qInfo() << "info message";
|
qInfo() << "info message";
|
||||||
qWarning() << "warning message";
|
qWarning() << "warning message";
|
||||||
qCritical() << "critical message";
|
qCritical() << "critical message";
|
||||||
|
|
||||||
qInstallMessageHandler(old);
|
qInstallMessageHandler(old);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,49 +4,49 @@
|
|||||||
|
|
||||||
TEST(CommonDecibel, FromLinearZeroReturnsMinimum)
|
TEST(CommonDecibel, FromLinearZeroReturnsMinimum)
|
||||||
{
|
{
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(0.0), olive::Decibel::MINIMUM);
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(0.0), olive::Decibel::MINIMUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDecibel, FromLinearOneReturnsZero)
|
TEST(CommonDecibel, FromLinearOneReturnsZero)
|
||||||
{
|
{
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(1.0), 0.0);
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(1.0), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDecibel, FromLinearTenReturnsTwenty)
|
TEST(CommonDecibel, FromLinearTenReturnsTwenty)
|
||||||
{
|
{
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(10.0), 20.0);
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLinear(10.0), 20.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDecibel, ToLinearZeroReturnsOne)
|
TEST(CommonDecibel, ToLinearZeroReturnsOne)
|
||||||
{
|
{
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(0.0), 1.0);
|
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(0.0), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDecibel, ToLinearMinimumReturnsZero)
|
TEST(CommonDecibel, ToLinearMinimumReturnsZero)
|
||||||
{
|
{
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(olive::Decibel::MINIMUM), 0.0);
|
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(olive::Decibel::MINIMUM), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDecibel, ToLinearTwentyReturnsTen)
|
TEST(CommonDecibel, ToLinearTwentyReturnsTen)
|
||||||
{
|
{
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(20.0), 10.0);
|
EXPECT_DOUBLE_EQ(olive::Decibel::toLinear(20.0), 10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDecibel, FromLogarithmicAtEdges)
|
TEST(CommonDecibel, FromLogarithmicAtEdges)
|
||||||
{
|
{
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::fromLogarithmic(0.0),
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLogarithmic(0.0),
|
||||||
olive::Decibel::MINIMUM);
|
olive::Decibel::MINIMUM);
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::fromLogarithmic(1.0), 0.0);
|
EXPECT_DOUBLE_EQ(olive::Decibel::fromLogarithmic(1.0), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDecibel, ToLogarithmicAtEdges)
|
TEST(CommonDecibel, ToLogarithmicAtEdges)
|
||||||
{
|
{
|
||||||
EXPECT_DOUBLE_EQ(olive::Decibel::toLogarithmic(0.0), 1.0);
|
EXPECT_DOUBLE_EQ(olive::Decibel::toLogarithmic(0.0), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDecibel, LinearLogarithmicRoundTrip)
|
TEST(CommonDecibel, LinearLogarithmicRoundTrip)
|
||||||
{
|
{
|
||||||
EXPECT_NEAR(olive::Decibel::LogarithmicToLinear(
|
EXPECT_NEAR(olive::Decibel::LogarithmicToLinear(
|
||||||
olive::Decibel::LinearToLogarithmic(0.5)),
|
olive::Decibel::LinearToLogarithmic(0.5)),
|
||||||
0.5, 1e-6);
|
0.5, 1e-6);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,20 +4,20 @@
|
|||||||
|
|
||||||
TEST(CommonDigit, SingleDigit)
|
TEST(CommonDigit, SingleDigit)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(olive::GetDigitCount(0), 1);
|
EXPECT_EQ(olive::GetDigitCount(0), 1);
|
||||||
EXPECT_EQ(olive::GetDigitCount(5), 1);
|
EXPECT_EQ(olive::GetDigitCount(5), 1);
|
||||||
EXPECT_EQ(olive::GetDigitCount(-5), 1);
|
EXPECT_EQ(olive::GetDigitCount(-5), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDigit, MultipleDigits)
|
TEST(CommonDigit, MultipleDigits)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(olive::GetDigitCount(10), 2);
|
EXPECT_EQ(olive::GetDigitCount(10), 2);
|
||||||
EXPECT_EQ(olive::GetDigitCount(999), 3);
|
EXPECT_EQ(olive::GetDigitCount(999), 3);
|
||||||
EXPECT_EQ(olive::GetDigitCount(1000), 4);
|
EXPECT_EQ(olive::GetDigitCount(1000), 4);
|
||||||
EXPECT_EQ(olive::GetDigitCount(-12345), 5);
|
EXPECT_EQ(olive::GetDigitCount(-12345), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonDigit, LargeValue)
|
TEST(CommonDigit, LargeValue)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(olive::GetDigitCount(123456789012345LL), 15);
|
EXPECT_EQ(olive::GetDigitCount(123456789012345LL), 15);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,144 +6,149 @@ using namespace olive;
|
|||||||
|
|
||||||
TEST(CommonFFmpegUtils, GetNativeSampleFormatMapsCorrectly)
|
TEST(CommonFFmpegUtils, GetNativeSampleFormatMapsCorrectly)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_U8),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_U8),
|
||||||
SampleFormat::U8);
|
SampleFormat::U8);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S16),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S16),
|
||||||
SampleFormat::S16);
|
SampleFormat::S16);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S32),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S32),
|
||||||
SampleFormat::S32);
|
SampleFormat::S32);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S64),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S64),
|
||||||
SampleFormat::S64);
|
SampleFormat::S64);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_FLT),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_FLT),
|
||||||
SampleFormat::F32);
|
SampleFormat::F32);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_DBL),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_DBL),
|
||||||
SampleFormat::F64);
|
SampleFormat::F64);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_U8P),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_U8P),
|
||||||
SampleFormat::U8P);
|
SampleFormat::U8P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S16P),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S16P),
|
||||||
SampleFormat::S16P);
|
SampleFormat::S16P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S32P),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S32P),
|
||||||
SampleFormat::S32P);
|
SampleFormat::S32P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S64P),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_S64P),
|
||||||
SampleFormat::S64P);
|
SampleFormat::S64P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_FLTP),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_FLTP),
|
||||||
SampleFormat::F32P);
|
SampleFormat::F32P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_DBLP),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_DBLP),
|
||||||
SampleFormat::F64P);
|
SampleFormat::F64P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_NONE),
|
EXPECT_EQ(FFmpegUtils::GetNativeSampleFormat(AV_SAMPLE_FMT_NONE),
|
||||||
SampleFormat::INVALID);
|
SampleFormat::INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonFFmpegUtils, GetFFmpegSampleFormatMapsCorrectly)
|
TEST(CommonFFmpegUtils, GetFFmpegSampleFormatMapsCorrectly)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::U8),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::U8),
|
||||||
AV_SAMPLE_FMT_U8);
|
AV_SAMPLE_FMT_U8);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S16),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S16),
|
||||||
AV_SAMPLE_FMT_S16);
|
AV_SAMPLE_FMT_S16);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S32),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S32),
|
||||||
AV_SAMPLE_FMT_S32);
|
AV_SAMPLE_FMT_S32);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S64),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S64),
|
||||||
AV_SAMPLE_FMT_S64);
|
AV_SAMPLE_FMT_S64);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F32),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F32),
|
||||||
AV_SAMPLE_FMT_FLT);
|
AV_SAMPLE_FMT_FLT);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F64),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F64),
|
||||||
AV_SAMPLE_FMT_DBL);
|
AV_SAMPLE_FMT_DBL);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::U8P),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::U8P),
|
||||||
AV_SAMPLE_FMT_U8P);
|
AV_SAMPLE_FMT_U8P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S16P),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S16P),
|
||||||
AV_SAMPLE_FMT_S16P);
|
AV_SAMPLE_FMT_S16P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S32P),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S32P),
|
||||||
AV_SAMPLE_FMT_S32P);
|
AV_SAMPLE_FMT_S32P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S64P),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::S64P),
|
||||||
AV_SAMPLE_FMT_S64P);
|
AV_SAMPLE_FMT_S64P);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F32P),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F32P),
|
||||||
AV_SAMPLE_FMT_FLTP);
|
AV_SAMPLE_FMT_FLTP);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F64P),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::F64P),
|
||||||
AV_SAMPLE_FMT_DBLP);
|
AV_SAMPLE_FMT_DBLP);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::INVALID),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegSampleFormat(SampleFormat::INVALID),
|
||||||
AV_SAMPLE_FMT_NONE);
|
AV_SAMPLE_FMT_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonFFmpegUtils, GetSwsColorspaceFromAVColorSpace)
|
TEST(CommonFFmpegUtils, GetSwsColorspaceFromAVColorSpace)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT709),
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT709),
|
||||||
SWS_CS_ITU709);
|
SWS_CS_ITU709);
|
||||||
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_FCC),
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_FCC),
|
||||||
SWS_CS_FCC);
|
SWS_CS_FCC);
|
||||||
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT470BG),
|
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT470BG),
|
||||||
SWS_CS_ITU624);
|
SWS_CS_ITU624);
|
||||||
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_SMPTE170M),
|
EXPECT_EQ(
|
||||||
SWS_CS_SMPTE170M);
|
FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_SMPTE170M),
|
||||||
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_SMPTE240M),
|
SWS_CS_SMPTE170M);
|
||||||
SWS_CS_SMPTE240M);
|
EXPECT_EQ(
|
||||||
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT2020_NCL),
|
FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_SMPTE240M),
|
||||||
SWS_CS_BT2020);
|
SWS_CS_SMPTE240M);
|
||||||
EXPECT_EQ(FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_UNSPECIFIED),
|
EXPECT_EQ(
|
||||||
SWS_CS_DEFAULT);
|
FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_BT2020_NCL),
|
||||||
|
SWS_CS_BT2020);
|
||||||
|
EXPECT_EQ(
|
||||||
|
FFmpegUtils::GetSwsColorspaceFromAVColorSpace(AVCOL_SPC_UNSPECIFIED),
|
||||||
|
SWS_CS_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonFFmpegUtils, ConvertJPEGSpaceToRegularSpace)
|
TEST(CommonFFmpegUtils, ConvertJPEGSpaceToRegularSpace)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ420P),
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ420P),
|
||||||
AV_PIX_FMT_YUV420P);
|
AV_PIX_FMT_YUV420P);
|
||||||
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ422P),
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ422P),
|
||||||
AV_PIX_FMT_YUV422P);
|
AV_PIX_FMT_YUV422P);
|
||||||
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ444P),
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ444P),
|
||||||
AV_PIX_FMT_YUV444P);
|
AV_PIX_FMT_YUV444P);
|
||||||
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ440P),
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ440P),
|
||||||
AV_PIX_FMT_YUV440P);
|
AV_PIX_FMT_YUV440P);
|
||||||
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ411P),
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUVJ411P),
|
||||||
AV_PIX_FMT_YUV411P);
|
AV_PIX_FMT_YUV411P);
|
||||||
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUV420P),
|
EXPECT_EQ(FFmpegUtils::ConvertJPEGSpaceToRegularSpace(AV_PIX_FMT_YUV420P),
|
||||||
AV_PIX_FMT_YUV420P);
|
AV_PIX_FMT_YUV420P);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonFFmpegUtils, GetCompatiblePixelFormatNative)
|
TEST(CommonFFmpegUtils, GetCompatiblePixelFormatNative)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U8),
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U8),
|
||||||
PixelFormat::U8);
|
PixelFormat::U8);
|
||||||
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U10),
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U10),
|
||||||
PixelFormat::U8);
|
PixelFormat::U8);
|
||||||
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U16),
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::U16),
|
||||||
PixelFormat::U16);
|
PixelFormat::U16);
|
||||||
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::F16),
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::F16),
|
||||||
PixelFormat::U16);
|
PixelFormat::U16);
|
||||||
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::F32),
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::F32),
|
||||||
PixelFormat::U16);
|
PixelFormat::U16);
|
||||||
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::INVALID),
|
EXPECT_EQ(FFmpegUtils::GetCompatiblePixelFormat(PixelFormat::INVALID),
|
||||||
PixelFormat::INVALID);
|
PixelFormat::INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonFFmpegUtils, GetFFmpegPixelFormat)
|
TEST(CommonFFmpegUtils, GetFFmpegPixelFormat)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U8,
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U8,
|
||||||
VideoParams::kRGBChannelCount),
|
VideoParams::kRGBChannelCount),
|
||||||
AV_PIX_FMT_RGB24);
|
AV_PIX_FMT_RGB24);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U16,
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U16,
|
||||||
VideoParams::kRGBChannelCount),
|
VideoParams::kRGBChannelCount),
|
||||||
AV_PIX_FMT_RGB48);
|
AV_PIX_FMT_RGB48);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::F32,
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::F32,
|
||||||
VideoParams::kRGBChannelCount),
|
VideoParams::kRGBChannelCount),
|
||||||
AV_PIX_FMT_RGBF32);
|
AV_PIX_FMT_RGBF32);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U8,
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U8,
|
||||||
VideoParams::kRGBAChannelCount),
|
VideoParams::kRGBAChannelCount),
|
||||||
AV_PIX_FMT_RGBA);
|
AV_PIX_FMT_RGBA);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U16,
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::U16,
|
||||||
VideoParams::kRGBAChannelCount),
|
VideoParams::kRGBAChannelCount),
|
||||||
AV_PIX_FMT_RGBA64);
|
AV_PIX_FMT_RGBA64);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::F32,
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::F32,
|
||||||
VideoParams::kRGBAChannelCount),
|
VideoParams::kRGBAChannelCount),
|
||||||
AV_PIX_FMT_RGBAF32);
|
AV_PIX_FMT_RGBAF32);
|
||||||
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::INVALID, 0),
|
EXPECT_EQ(FFmpegUtils::GetFFmpegPixelFormat(PixelFormat::INVALID, 0),
|
||||||
AV_PIX_FMT_NONE);
|
AV_PIX_FMT_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonFFmpegUtils, GetCompatiblePixelFormatAV)
|
TEST(CommonFFmpegUtils, GetCompatiblePixelFormatAV)
|
||||||
{
|
{
|
||||||
AVPixelFormat fmt = FFmpegUtils::GetCompatiblePixelFormat(AV_PIX_FMT_YUV420P);
|
AVPixelFormat fmt =
|
||||||
EXPECT_NE(fmt, AV_PIX_FMT_NONE);
|
FFmpegUtils::GetCompatiblePixelFormat(AV_PIX_FMT_YUV420P);
|
||||||
|
EXPECT_NE(fmt, AV_PIX_FMT_NONE);
|
||||||
|
|
||||||
fmt = FFmpegUtils::GetCompatiblePixelFormat(AV_PIX_FMT_YUV420P,
|
fmt = FFmpegUtils::GetCompatiblePixelFormat(AV_PIX_FMT_YUV420P,
|
||||||
PixelFormat::U8);
|
PixelFormat::U8);
|
||||||
EXPECT_EQ(fmt, AV_PIX_FMT_RGBA);
|
EXPECT_EQ(fmt, AV_PIX_FMT_RGBA);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ TEST(CommonFileFunctions, EnsureFilenameExtension)
|
|||||||
EXPECT_EQ(olive::FileFunctions::EnsureFilenameExtension(
|
EXPECT_EQ(olive::FileFunctions::EnsureFilenameExtension(
|
||||||
QStringLiteral("PROJECT"), QStringLiteral("ove")),
|
QStringLiteral("PROJECT"), QStringLiteral("ove")),
|
||||||
QStringLiteral("PROJECT.ove"));
|
QStringLiteral("PROJECT.ove"));
|
||||||
EXPECT_TRUE(olive::FileFunctions::EnsureFilenameExtension(QString(), QStringLiteral("ove")).isEmpty());
|
EXPECT_TRUE(olive::FileFunctions::EnsureFilenameExtension(
|
||||||
|
QString(), QStringLiteral("ove"))
|
||||||
|
.isEmpty());
|
||||||
EXPECT_EQ(olive::FileFunctions::EnsureFilenameExtension(
|
EXPECT_EQ(olive::FileFunctions::EnsureFilenameExtension(
|
||||||
QStringLiteral("project"), QString()),
|
QStringLiteral("project"), QString()),
|
||||||
QStringLiteral("project"));
|
QStringLiteral("project"));
|
||||||
@@ -46,7 +48,8 @@ TEST(CommonFileFunctions, DirectoryIsValid)
|
|||||||
QTemporaryDir dir;
|
QTemporaryDir dir;
|
||||||
ASSERT_TRUE(dir.isValid());
|
ASSERT_TRUE(dir.isValid());
|
||||||
|
|
||||||
EXPECT_TRUE(olive::FileFunctions::DirectoryIsValid(QDir(dir.path()), false));
|
EXPECT_TRUE(
|
||||||
|
olive::FileFunctions::DirectoryIsValid(QDir(dir.path()), false));
|
||||||
|
|
||||||
QDir nonexistent(dir.filePath(QStringLiteral("subdir/nested")));
|
QDir nonexistent(dir.filePath(QStringLiteral("subdir/nested")));
|
||||||
EXPECT_TRUE(olive::FileFunctions::DirectoryIsValid(nonexistent, true));
|
EXPECT_TRUE(olive::FileFunctions::DirectoryIsValid(nonexistent, true));
|
||||||
@@ -133,7 +136,8 @@ TEST(CommonFileFunctions, ReadFileAsString)
|
|||||||
EXPECT_EQ(olive::FileFunctions::ReadFileAsString(f.fileName()),
|
EXPECT_EQ(olive::FileFunctions::ReadFileAsString(f.fileName()),
|
||||||
QStringLiteral("hello world"));
|
QStringLiteral("hello world"));
|
||||||
EXPECT_TRUE(olive::FileFunctions::ReadFileAsString(
|
EXPECT_TRUE(olive::FileFunctions::ReadFileAsString(
|
||||||
QStringLiteral("/nonexistent/path")).isEmpty());
|
QStringLiteral("/nonexistent/path"))
|
||||||
|
.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonFileFunctions, GetUniqueFileIdentifier)
|
TEST(CommonFileFunctions, GetUniqueFileIdentifier)
|
||||||
@@ -148,10 +152,10 @@ TEST(CommonFileFunctions, GetUniqueFileIdentifier)
|
|||||||
EXPECT_EQ(id1, id2);
|
EXPECT_EQ(id1, id2);
|
||||||
|
|
||||||
EXPECT_TRUE(olive::FileFunctions::GetUniqueFileIdentifier(
|
EXPECT_TRUE(olive::FileFunctions::GetUniqueFileIdentifier(
|
||||||
QStringLiteral("/nonexistent")).isEmpty());
|
QStringLiteral("/nonexistent"))
|
||||||
|
.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(CommonFileFunctions, GetConfigurationLocation)
|
TEST(CommonFileFunctions, GetConfigurationLocation)
|
||||||
{
|
{
|
||||||
QString loc = olive::FileFunctions::GetConfigurationLocation();
|
QString loc = olive::FileFunctions::GetConfigurationLocation();
|
||||||
@@ -176,7 +180,8 @@ TEST(CommonFileFunctions, DirectoryIsValidExisting)
|
|||||||
{
|
{
|
||||||
QTemporaryDir dir;
|
QTemporaryDir dir;
|
||||||
ASSERT_TRUE(dir.isValid());
|
ASSERT_TRUE(dir.isValid());
|
||||||
EXPECT_TRUE(olive::FileFunctions::DirectoryIsValid(QDir(dir.path()), false));
|
EXPECT_TRUE(
|
||||||
|
olive::FileFunctions::DirectoryIsValid(QDir(dir.path()), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonFileFunctions, CopyDirectoryWithOverwrite)
|
TEST(CommonFileFunctions, CopyDirectoryWithOverwrite)
|
||||||
@@ -212,5 +217,5 @@ TEST(CommonFileFunctions, CopyDirectorySourceMissing)
|
|||||||
|
|
||||||
// Should not crash even if source doesn't exist
|
// Should not crash even if source doesn't exist
|
||||||
olive::FileFunctions::CopyDirectory(QStringLiteral("/nonexistent/path"),
|
olive::FileFunctions::CopyDirectory(QStringLiteral("/nonexistent/path"),
|
||||||
dst.path(), false);
|
dst.path(), false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,39 +4,39 @@
|
|||||||
|
|
||||||
TEST(CommonJobTime, ConstructorAcquiresValue)
|
TEST(CommonJobTime, ConstructorAcquiresValue)
|
||||||
{
|
{
|
||||||
olive::JobTime a;
|
olive::JobTime a;
|
||||||
olive::JobTime b;
|
olive::JobTime b;
|
||||||
|
|
||||||
EXPECT_NE(a.value(), b.value());
|
EXPECT_NE(a.value(), b.value());
|
||||||
EXPECT_LT(a.value(), b.value());
|
EXPECT_LT(a.value(), b.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonJobTime, AcquireUpdatesValue)
|
TEST(CommonJobTime, AcquireUpdatesValue)
|
||||||
{
|
{
|
||||||
olive::JobTime a;
|
olive::JobTime a;
|
||||||
uint64_t first = a.value();
|
uint64_t first = a.value();
|
||||||
a.Acquire();
|
a.Acquire();
|
||||||
uint64_t second = a.value();
|
uint64_t second = a.value();
|
||||||
|
|
||||||
EXPECT_GT(second, first);
|
EXPECT_GT(second, first);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonJobTime, ComparisonOperators)
|
TEST(CommonJobTime, ComparisonOperators)
|
||||||
{
|
{
|
||||||
olive::JobTime a;
|
olive::JobTime a;
|
||||||
olive::JobTime b;
|
olive::JobTime b;
|
||||||
|
|
||||||
EXPECT_LT(a, b);
|
EXPECT_LT(a, b);
|
||||||
EXPECT_GT(b, a);
|
EXPECT_GT(b, a);
|
||||||
EXPECT_LE(a, a);
|
EXPECT_LE(a, a);
|
||||||
EXPECT_GE(b, b);
|
EXPECT_GE(b, b);
|
||||||
EXPECT_EQ(a, a);
|
EXPECT_EQ(a, a);
|
||||||
EXPECT_NE(a, b);
|
EXPECT_NE(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CommonJobTime, DebugStream)
|
TEST(CommonJobTime, DebugStream)
|
||||||
{
|
{
|
||||||
olive::JobTime a;
|
olive::JobTime a;
|
||||||
QDebug debug(QtDebugMsg);
|
QDebug debug(QtDebugMsg);
|
||||||
debug << a;
|
debug << a;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ TEST(CommonQtUtils, FlipControlAndShiftModifiers)
|
|||||||
// (Qt::ControlModifier & Qt::ShiftModifier is always zero), so the function
|
// (Qt::ControlModifier & Qt::ShiftModifier is always zero), so the function
|
||||||
// always swaps Control and Shift. This test documents current behavior.
|
// always swaps Control and Shift. This test documents current behavior.
|
||||||
Qt::KeyboardModifiers both = Qt::ControlModifier | Qt::ShiftModifier;
|
Qt::KeyboardModifiers both = Qt::ControlModifier | Qt::ShiftModifier;
|
||||||
Qt::KeyboardModifiers flipped = olive::QtUtils::FlipControlAndShiftModifiers(both);
|
Qt::KeyboardModifiers flipped =
|
||||||
|
olive::QtUtils::FlipControlAndShiftModifiers(both);
|
||||||
EXPECT_TRUE(flipped & Qt::ControlModifier);
|
EXPECT_TRUE(flipped & Qt::ControlModifier);
|
||||||
EXPECT_FALSE(flipped & Qt::ShiftModifier);
|
EXPECT_FALSE(flipped & Qt::ShiftModifier);
|
||||||
|
|
||||||
@@ -112,11 +113,10 @@ TEST(CommonQtUtils, ToQColor)
|
|||||||
EXPECT_NEAR(qc.alphaF(), 0.4, 0.001);
|
EXPECT_NEAR(qc.alphaF(), 0.4, 0.001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(CommonQtUtils, GetFormattedDateTime)
|
TEST(CommonQtUtils, GetFormattedDateTime)
|
||||||
{
|
{
|
||||||
QDateTime dt = QDateTime::fromString(QStringLiteral("2025-01-15T10:30:00"),
|
QDateTime dt = QDateTime::fromString(QStringLiteral("2025-01-15T10:30:00"),
|
||||||
Qt::ISODate);
|
Qt::ISODate);
|
||||||
QString s = olive::QtUtils::GetFormattedDateTime(dt);
|
QString s = olive::QtUtils::GetFormattedDateTime(dt);
|
||||||
EXPECT_FALSE(s.isEmpty());
|
EXPECT_FALSE(s.isEmpty());
|
||||||
}
|
}
|
||||||
@@ -132,8 +132,8 @@ TEST(CommonQtUtils, WordWrapString)
|
|||||||
EXPECT_GE(wrapped.size(), 1u);
|
EXPECT_GE(wrapped.size(), 1u);
|
||||||
|
|
||||||
// Should preserve manual newlines
|
// Should preserve manual newlines
|
||||||
wrapped = olive::QtUtils::WordWrapString(
|
wrapped = olive::QtUtils::WordWrapString(QStringLiteral("line1\nline2"), fm,
|
||||||
QStringLiteral("line1\nline2"), fm, 1000);
|
1000);
|
||||||
EXPECT_EQ(wrapped.size(), 2);
|
EXPECT_EQ(wrapped.size(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ TEST(CommonXmlUtils, ReadNextStartElementSkipsUnknown)
|
|||||||
EXPECT_EQ(reader.name().toString(), QStringLiteral("known"));
|
EXPECT_EQ(reader.name().toString(), QStringLiteral("known"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(CommonXmlUtils, ReadNextStartElementWithCancel)
|
TEST(CommonXmlUtils, ReadNextStartElementWithCancel)
|
||||||
{
|
{
|
||||||
QByteArray xml = "<root><child/></root>";
|
QByteArray xml = "<root><child/></root>";
|
||||||
|
|||||||
+12
-12
@@ -46,18 +46,18 @@ TEST(Config, GraphicsBackendStringConversion)
|
|||||||
olive::RenderManager::kVulkan);
|
olive::RenderManager::kVulkan);
|
||||||
EXPECT_EQ(olive::RenderManager::BackendFromString(QStringLiteral("dummy")),
|
EXPECT_EQ(olive::RenderManager::BackendFromString(QStringLiteral("dummy")),
|
||||||
olive::RenderManager::kDummy);
|
olive::RenderManager::kDummy);
|
||||||
EXPECT_EQ(olive::RenderManager::BackendFromString(
|
EXPECT_EQ(
|
||||||
QStringLiteral("multiprocess")),
|
olive::RenderManager::BackendFromString(QStringLiteral("multiprocess")),
|
||||||
olive::RenderManager::kMultiProcess);
|
olive::RenderManager::kMultiProcess);
|
||||||
EXPECT_EQ(olive::RenderManager::BackendToString(
|
EXPECT_EQ(
|
||||||
olive::RenderManager::kOpenGL),
|
olive::RenderManager::BackendToString(olive::RenderManager::kOpenGL),
|
||||||
QStringLiteral("opengl"));
|
QStringLiteral("opengl"));
|
||||||
EXPECT_EQ(olive::RenderManager::BackendToString(
|
EXPECT_EQ(
|
||||||
olive::RenderManager::kVulkan),
|
olive::RenderManager::BackendToString(olive::RenderManager::kVulkan),
|
||||||
QStringLiteral("vulkan"));
|
QStringLiteral("vulkan"));
|
||||||
EXPECT_EQ(olive::RenderManager::BackendToString(
|
EXPECT_EQ(
|
||||||
olive::RenderManager::kDummy),
|
olive::RenderManager::BackendToString(olive::RenderManager::kDummy),
|
||||||
QStringLiteral("dummy"));
|
QStringLiteral("dummy"));
|
||||||
EXPECT_EQ(olive::RenderManager::BackendToString(
|
EXPECT_EQ(olive::RenderManager::BackendToString(
|
||||||
olive::RenderManager::kMultiProcess),
|
olive::RenderManager::kMultiProcess),
|
||||||
QStringLiteral("multiprocess"));
|
QStringLiteral("multiprocess"));
|
||||||
|
|||||||
@@ -6,115 +6,115 @@ using namespace olive::core;
|
|||||||
|
|
||||||
TEST(CoreBezier, DefaultConstruction)
|
TEST(CoreBezier, DefaultConstruction)
|
||||||
{
|
{
|
||||||
Bezier b;
|
Bezier b;
|
||||||
EXPECT_DOUBLE_EQ(b.x(), 0.0);
|
EXPECT_DOUBLE_EQ(b.x(), 0.0);
|
||||||
EXPECT_DOUBLE_EQ(b.y(), 0.0);
|
EXPECT_DOUBLE_EQ(b.y(), 0.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp1_x(), 0.0);
|
EXPECT_DOUBLE_EQ(b.cp1_x(), 0.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp1_y(), 0.0);
|
EXPECT_DOUBLE_EQ(b.cp1_y(), 0.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp2_x(), 0.0);
|
EXPECT_DOUBLE_EQ(b.cp2_x(), 0.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp2_y(), 0.0);
|
EXPECT_DOUBLE_EQ(b.cp2_y(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, ValueConstruction)
|
TEST(CoreBezier, ValueConstruction)
|
||||||
{
|
{
|
||||||
Bezier b(1.0, 2.0);
|
Bezier b(1.0, 2.0);
|
||||||
EXPECT_DOUBLE_EQ(b.x(), 1.0);
|
EXPECT_DOUBLE_EQ(b.x(), 1.0);
|
||||||
EXPECT_DOUBLE_EQ(b.y(), 2.0);
|
EXPECT_DOUBLE_EQ(b.y(), 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, FullConstruction)
|
TEST(CoreBezier, FullConstruction)
|
||||||
{
|
{
|
||||||
Bezier b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
|
Bezier b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
|
||||||
EXPECT_DOUBLE_EQ(b.x(), 1.0);
|
EXPECT_DOUBLE_EQ(b.x(), 1.0);
|
||||||
EXPECT_DOUBLE_EQ(b.y(), 2.0);
|
EXPECT_DOUBLE_EQ(b.y(), 2.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp1_x(), 3.0);
|
EXPECT_DOUBLE_EQ(b.cp1_x(), 3.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp1_y(), 4.0);
|
EXPECT_DOUBLE_EQ(b.cp1_y(), 4.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp2_x(), 5.0);
|
EXPECT_DOUBLE_EQ(b.cp2_x(), 5.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp2_y(), 6.0);
|
EXPECT_DOUBLE_EQ(b.cp2_y(), 6.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, Setters)
|
TEST(CoreBezier, Setters)
|
||||||
{
|
{
|
||||||
Bezier b;
|
Bezier b;
|
||||||
b.set_x(10.0);
|
b.set_x(10.0);
|
||||||
b.set_y(20.0);
|
b.set_y(20.0);
|
||||||
b.set_cp1_x(30.0);
|
b.set_cp1_x(30.0);
|
||||||
b.set_cp1_y(40.0);
|
b.set_cp1_y(40.0);
|
||||||
b.set_cp2_x(50.0);
|
b.set_cp2_x(50.0);
|
||||||
b.set_cp2_y(60.0);
|
b.set_cp2_y(60.0);
|
||||||
|
|
||||||
EXPECT_DOUBLE_EQ(b.x(), 10.0);
|
EXPECT_DOUBLE_EQ(b.x(), 10.0);
|
||||||
EXPECT_DOUBLE_EQ(b.y(), 20.0);
|
EXPECT_DOUBLE_EQ(b.y(), 20.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp1_x(), 30.0);
|
EXPECT_DOUBLE_EQ(b.cp1_x(), 30.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp1_y(), 40.0);
|
EXPECT_DOUBLE_EQ(b.cp1_y(), 40.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp2_x(), 50.0);
|
EXPECT_DOUBLE_EQ(b.cp2_x(), 50.0);
|
||||||
EXPECT_DOUBLE_EQ(b.cp2_y(), 60.0);
|
EXPECT_DOUBLE_EQ(b.cp2_y(), 60.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, QuadraticXtoT)
|
TEST(CoreBezier, QuadraticXtoT)
|
||||||
{
|
{
|
||||||
double t = Bezier::QuadraticXtoT(0.5, 0.0, 0.5, 1.0);
|
double t = Bezier::QuadraticXtoT(0.5, 0.0, 0.5, 1.0);
|
||||||
EXPECT_NEAR(t, 0.5, 0.00001);
|
EXPECT_NEAR(t, 0.5, 0.00001);
|
||||||
|
|
||||||
t = Bezier::QuadraticXtoT(0.0, 0.0, 0.5, 1.0);
|
t = Bezier::QuadraticXtoT(0.0, 0.0, 0.5, 1.0);
|
||||||
EXPECT_NEAR(t, 0.0, 0.00001);
|
EXPECT_NEAR(t, 0.0, 0.00001);
|
||||||
|
|
||||||
t = Bezier::QuadraticXtoT(1.0, 0.0, 0.5, 1.0);
|
t = Bezier::QuadraticXtoT(1.0, 0.0, 0.5, 1.0);
|
||||||
EXPECT_NEAR(t, 1.0, 0.00001);
|
EXPECT_NEAR(t, 1.0, 0.00001);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, QuadraticTtoY)
|
TEST(CoreBezier, QuadraticTtoY)
|
||||||
{
|
{
|
||||||
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 0.0), 0.0, 0.00001);
|
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 0.0), 0.0, 0.00001);
|
||||||
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 0.5), 0.5, 0.00001);
|
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 0.5), 0.5, 0.00001);
|
||||||
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 1.0), 1.0, 0.00001);
|
EXPECT_NEAR(Bezier::QuadraticTtoY(0.0, 0.5, 1.0, 1.0), 1.0, 0.00001);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, QuadraticXtoY)
|
TEST(CoreBezier, QuadraticXtoY)
|
||||||
{
|
{
|
||||||
Imath::V2d a(0.0, 0.0);
|
Imath::V2d a(0.0, 0.0);
|
||||||
Imath::V2d b(0.5, 0.5);
|
Imath::V2d b(0.5, 0.5);
|
||||||
Imath::V2d c(1.0, 1.0);
|
Imath::V2d c(1.0, 1.0);
|
||||||
|
|
||||||
EXPECT_NEAR(Bezier::QuadraticXtoY(0.5, a, b, c), 0.5, 0.00001);
|
EXPECT_NEAR(Bezier::QuadraticXtoY(0.5, a, b, c), 0.5, 0.00001);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, CubicXtoT)
|
TEST(CoreBezier, CubicXtoT)
|
||||||
{
|
{
|
||||||
double t = Bezier::CubicXtoT(0.5, 0.0, 0.33, 0.66, 1.0);
|
double t = Bezier::CubicXtoT(0.5, 0.0, 0.33, 0.66, 1.0);
|
||||||
EXPECT_NEAR(t, 0.5, 0.01);
|
EXPECT_NEAR(t, 0.5, 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, CubicTtoY)
|
TEST(CoreBezier, CubicTtoY)
|
||||||
{
|
{
|
||||||
EXPECT_NEAR(Bezier::CubicTtoY(0.0, 0.33, 0.66, 1.0, 0.0), 0.0, 0.00001);
|
EXPECT_NEAR(Bezier::CubicTtoY(0.0, 0.33, 0.66, 1.0, 0.0), 0.0, 0.00001);
|
||||||
EXPECT_NEAR(Bezier::CubicTtoY(0.0, 0.33, 0.66, 1.0, 1.0), 1.0, 0.00001);
|
EXPECT_NEAR(Bezier::CubicTtoY(0.0, 0.33, 0.66, 1.0, 1.0), 1.0, 0.00001);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, CubicXtoY)
|
TEST(CoreBezier, CubicXtoY)
|
||||||
{
|
{
|
||||||
Imath::V2d a(0.0, 0.0);
|
Imath::V2d a(0.0, 0.0);
|
||||||
Imath::V2d b(0.33, 0.0);
|
Imath::V2d b(0.33, 0.0);
|
||||||
Imath::V2d c(0.66, 1.0);
|
Imath::V2d c(0.66, 1.0);
|
||||||
Imath::V2d d(1.0, 1.0);
|
Imath::V2d d(1.0, 1.0);
|
||||||
|
|
||||||
double y = Bezier::CubicXtoY(0.5, a, b, c, d);
|
double y = Bezier::CubicXtoY(0.5, a, b, c, d);
|
||||||
EXPECT_GE(y, 0.0);
|
EXPECT_GE(y, 0.0);
|
||||||
EXPECT_LE(y, 1.0);
|
EXPECT_LE(y, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreBezier, VectorConverters)
|
TEST(CoreBezier, VectorConverters)
|
||||||
{
|
{
|
||||||
Bezier b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
|
Bezier b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
|
||||||
Imath::V2d v = b.to_vec();
|
Imath::V2d v = b.to_vec();
|
||||||
EXPECT_DOUBLE_EQ(v.x, 1.0);
|
EXPECT_DOUBLE_EQ(v.x, 1.0);
|
||||||
EXPECT_DOUBLE_EQ(v.y, 2.0);
|
EXPECT_DOUBLE_EQ(v.y, 2.0);
|
||||||
|
|
||||||
Imath::V2d cp1 = b.control_point_1_to_vec();
|
Imath::V2d cp1 = b.control_point_1_to_vec();
|
||||||
EXPECT_DOUBLE_EQ(cp1.x, 3.0);
|
EXPECT_DOUBLE_EQ(cp1.x, 3.0);
|
||||||
EXPECT_DOUBLE_EQ(cp1.y, 4.0);
|
EXPECT_DOUBLE_EQ(cp1.y, 4.0);
|
||||||
|
|
||||||
Imath::V2d cp2 = b.control_point_2_to_vec();
|
Imath::V2d cp2 = b.control_point_2_to_vec();
|
||||||
EXPECT_DOUBLE_EQ(cp2.x, 5.0);
|
EXPECT_DOUBLE_EQ(cp2.x, 5.0);
|
||||||
EXPECT_DOUBLE_EQ(cp2.y, 6.0);
|
EXPECT_DOUBLE_EQ(cp2.y, 6.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,164 +6,164 @@ using namespace olive::core;
|
|||||||
|
|
||||||
TEST(CoreColor, DefaultConstruction)
|
TEST(CoreColor, DefaultConstruction)
|
||||||
{
|
{
|
||||||
Color c;
|
Color c;
|
||||||
EXPECT_FLOAT_EQ(c.red(), 0.0f);
|
EXPECT_FLOAT_EQ(c.red(), 0.0f);
|
||||||
EXPECT_FLOAT_EQ(c.green(), 0.0f);
|
EXPECT_FLOAT_EQ(c.green(), 0.0f);
|
||||||
EXPECT_FLOAT_EQ(c.blue(), 0.0f);
|
EXPECT_FLOAT_EQ(c.blue(), 0.0f);
|
||||||
EXPECT_FLOAT_EQ(c.alpha(), 0.0f);
|
EXPECT_FLOAT_EQ(c.alpha(), 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, ValueConstruction)
|
TEST(CoreColor, ValueConstruction)
|
||||||
{
|
{
|
||||||
Color c(0.1f, 0.2f, 0.3f, 0.4f);
|
Color c(0.1f, 0.2f, 0.3f, 0.4f);
|
||||||
EXPECT_FLOAT_EQ(c.red(), 0.1f);
|
EXPECT_FLOAT_EQ(c.red(), 0.1f);
|
||||||
EXPECT_FLOAT_EQ(c.green(), 0.2f);
|
EXPECT_FLOAT_EQ(c.green(), 0.2f);
|
||||||
EXPECT_FLOAT_EQ(c.blue(), 0.3f);
|
EXPECT_FLOAT_EQ(c.blue(), 0.3f);
|
||||||
EXPECT_FLOAT_EQ(c.alpha(), 0.4f);
|
EXPECT_FLOAT_EQ(c.alpha(), 0.4f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, SettersAndDataAccess)
|
TEST(CoreColor, SettersAndDataAccess)
|
||||||
{
|
{
|
||||||
Color c;
|
Color c;
|
||||||
c.set_red(0.5f);
|
c.set_red(0.5f);
|
||||||
c.set_green(0.6f);
|
c.set_green(0.6f);
|
||||||
c.set_blue(0.7f);
|
c.set_blue(0.7f);
|
||||||
c.set_alpha(0.8f);
|
c.set_alpha(0.8f);
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(c.data()[0], 0.5f);
|
EXPECT_FLOAT_EQ(c.data()[0], 0.5f);
|
||||||
EXPECT_FLOAT_EQ(c.data()[1], 0.6f);
|
EXPECT_FLOAT_EQ(c.data()[1], 0.6f);
|
||||||
EXPECT_FLOAT_EQ(c.data()[2], 0.7f);
|
EXPECT_FLOAT_EQ(c.data()[2], 0.7f);
|
||||||
EXPECT_FLOAT_EQ(c.data()[3], 0.8f);
|
EXPECT_FLOAT_EQ(c.data()[3], 0.8f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, FromHsvRed)
|
TEST(CoreColor, FromHsvRed)
|
||||||
{
|
{
|
||||||
Color c = Color::fromHsv(0.0f, 1.0f, 1.0f);
|
Color c = Color::fromHsv(0.0f, 1.0f, 1.0f);
|
||||||
EXPECT_NEAR(c.red(), 1.0f, 0.001f);
|
EXPECT_NEAR(c.red(), 1.0f, 0.001f);
|
||||||
EXPECT_NEAR(c.green(), 0.0f, 0.001f);
|
EXPECT_NEAR(c.green(), 0.0f, 0.001f);
|
||||||
EXPECT_NEAR(c.blue(), 0.0f, 0.001f);
|
EXPECT_NEAR(c.blue(), 0.0f, 0.001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, FromHsvGreen)
|
TEST(CoreColor, FromHsvGreen)
|
||||||
{
|
{
|
||||||
Color c = Color::fromHsv(120.0f, 1.0f, 1.0f);
|
Color c = Color::fromHsv(120.0f, 1.0f, 1.0f);
|
||||||
EXPECT_NEAR(c.red(), 0.0f, 0.001f);
|
EXPECT_NEAR(c.red(), 0.0f, 0.001f);
|
||||||
EXPECT_NEAR(c.green(), 1.0f, 0.001f);
|
EXPECT_NEAR(c.green(), 1.0f, 0.001f);
|
||||||
EXPECT_NEAR(c.blue(), 0.0f, 0.001f);
|
EXPECT_NEAR(c.blue(), 0.0f, 0.001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, FromHsvBlue)
|
TEST(CoreColor, FromHsvBlue)
|
||||||
{
|
{
|
||||||
Color c = Color::fromHsv(240.0f, 1.0f, 1.0f);
|
Color c = Color::fromHsv(240.0f, 1.0f, 1.0f);
|
||||||
EXPECT_NEAR(c.red(), 0.0f, 0.001f);
|
EXPECT_NEAR(c.red(), 0.0f, 0.001f);
|
||||||
EXPECT_NEAR(c.green(), 0.0f, 0.001f);
|
EXPECT_NEAR(c.green(), 0.0f, 0.001f);
|
||||||
EXPECT_NEAR(c.blue(), 1.0f, 0.001f);
|
EXPECT_NEAR(c.blue(), 1.0f, 0.001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, HsvRoundTrip)
|
TEST(CoreColor, HsvRoundTrip)
|
||||||
{
|
{
|
||||||
Color original(0.8f, 0.4f, 0.2f);
|
Color original(0.8f, 0.4f, 0.2f);
|
||||||
float h, s, v;
|
float h, s, v;
|
||||||
original.toHsv(&h, &s, &v);
|
original.toHsv(&h, &s, &v);
|
||||||
|
|
||||||
EXPECT_NEAR(original.hsv_hue(), h, 0.001f);
|
EXPECT_NEAR(original.hsv_hue(), h, 0.001f);
|
||||||
EXPECT_NEAR(original.hsv_saturation(), s, 0.001f);
|
EXPECT_NEAR(original.hsv_saturation(), s, 0.001f);
|
||||||
EXPECT_NEAR(original.value(), v, 0.001f);
|
EXPECT_NEAR(original.value(), v, 0.001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, HslRoundTrip)
|
TEST(CoreColor, HslRoundTrip)
|
||||||
{
|
{
|
||||||
Color original(0.2f, 0.5f, 0.8f);
|
Color original(0.2f, 0.5f, 0.8f);
|
||||||
float h, s, l;
|
float h, s, l;
|
||||||
original.toHsl(&h, &s, &l);
|
original.toHsl(&h, &s, &l);
|
||||||
|
|
||||||
EXPECT_NEAR(original.hsl_hue(), h, 0.001f);
|
EXPECT_NEAR(original.hsl_hue(), h, 0.001f);
|
||||||
EXPECT_NEAR(original.hsl_saturation(), s, 0.001f);
|
EXPECT_NEAR(original.hsl_saturation(), s, 0.001f);
|
||||||
EXPECT_NEAR(original.lightness(), l, 0.001f);
|
EXPECT_NEAR(original.lightness(), l, 0.001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, ArithmeticOperators)
|
TEST(CoreColor, ArithmeticOperators)
|
||||||
{
|
{
|
||||||
Color a(1.0f, 2.0f, 3.0f, 4.0f);
|
Color a(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
Color b(0.5f, 0.5f, 0.5f, 0.5f);
|
Color b(0.5f, 0.5f, 0.5f, 0.5f);
|
||||||
|
|
||||||
Color sum = a + b;
|
Color sum = a + b;
|
||||||
EXPECT_FLOAT_EQ(sum.red(), 1.5f);
|
EXPECT_FLOAT_EQ(sum.red(), 1.5f);
|
||||||
|
|
||||||
Color diff = a - b;
|
Color diff = a - b;
|
||||||
EXPECT_FLOAT_EQ(diff.red(), 0.5f);
|
EXPECT_FLOAT_EQ(diff.red(), 0.5f);
|
||||||
|
|
||||||
Color scaled = a * 2.0f;
|
Color scaled = a * 2.0f;
|
||||||
EXPECT_FLOAT_EQ(scaled.red(), 2.0f);
|
EXPECT_FLOAT_EQ(scaled.red(), 2.0f);
|
||||||
|
|
||||||
Color divided = a / 2.0f;
|
Color divided = a / 2.0f;
|
||||||
EXPECT_FLOAT_EQ(divided.red(), 0.5f);
|
EXPECT_FLOAT_EQ(divided.red(), 0.5f);
|
||||||
|
|
||||||
Color added_scalar = a + 1.0f;
|
Color added_scalar = a + 1.0f;
|
||||||
EXPECT_FLOAT_EQ(added_scalar.red(), 2.0f);
|
EXPECT_FLOAT_EQ(added_scalar.red(), 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, CompoundAssignment)
|
TEST(CoreColor, CompoundAssignment)
|
||||||
{
|
{
|
||||||
Color c(1.0f, 2.0f, 3.0f, 4.0f);
|
Color c(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
c += Color(0.5f, 0.5f, 0.5f, 0.5f);
|
c += Color(0.5f, 0.5f, 0.5f, 0.5f);
|
||||||
EXPECT_FLOAT_EQ(c.red(), 1.5f);
|
EXPECT_FLOAT_EQ(c.red(), 1.5f);
|
||||||
|
|
||||||
c *= 2.0f;
|
c *= 2.0f;
|
||||||
EXPECT_FLOAT_EQ(c.red(), 3.0f);
|
EXPECT_FLOAT_EQ(c.red(), 3.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, GetRoughLuminance)
|
TEST(CoreColor, GetRoughLuminance)
|
||||||
{
|
{
|
||||||
Color white(1.0f, 1.0f, 1.0f);
|
Color white(1.0f, 1.0f, 1.0f);
|
||||||
EXPECT_FLOAT_EQ(white.GetRoughLuminance(), 1.0f);
|
EXPECT_FLOAT_EQ(white.GetRoughLuminance(), 1.0f);
|
||||||
|
|
||||||
Color black(0.0f, 0.0f, 0.0f);
|
Color black(0.0f, 0.0f, 0.0f);
|
||||||
EXPECT_FLOAT_EQ(black.GetRoughLuminance(), 0.0f);
|
EXPECT_FLOAT_EQ(black.GetRoughLuminance(), 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, ToDataAndFromDataU8)
|
TEST(CoreColor, ToDataAndFromDataU8)
|
||||||
{
|
{
|
||||||
Color c(1.0f, 0.5f, 0.0f, 1.0f);
|
Color c(1.0f, 0.5f, 0.0f, 1.0f);
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
c.toData(reinterpret_cast<char *>(data), PixelFormat::U8, 4);
|
c.toData(reinterpret_cast<char *>(data), PixelFormat::U8, 4);
|
||||||
|
|
||||||
EXPECT_EQ(data[0], 255u);
|
EXPECT_EQ(data[0], 255u);
|
||||||
EXPECT_EQ(data[1], 127u);
|
EXPECT_EQ(data[1], 127u);
|
||||||
EXPECT_EQ(data[2], 0u);
|
EXPECT_EQ(data[2], 0u);
|
||||||
EXPECT_EQ(data[3], 255u);
|
EXPECT_EQ(data[3], 255u);
|
||||||
|
|
||||||
Color restored = Color::fromData(reinterpret_cast<const char *>(data),
|
Color restored = Color::fromData(reinterpret_cast<const char *>(data),
|
||||||
PixelFormat::U8, 4);
|
PixelFormat::U8, 4);
|
||||||
EXPECT_NEAR(restored.red(), 1.0f, 0.01f);
|
EXPECT_NEAR(restored.red(), 1.0f, 0.01f);
|
||||||
EXPECT_NEAR(restored.green(), 0.5f, 0.01f);
|
EXPECT_NEAR(restored.green(), 0.5f, 0.01f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, ToDataAndFromDataF32)
|
TEST(CoreColor, ToDataAndFromDataF32)
|
||||||
{
|
{
|
||||||
Color c(0.25f, 0.5f, 0.75f, 1.0f);
|
Color c(0.25f, 0.5f, 0.75f, 1.0f);
|
||||||
float data[4];
|
float data[4];
|
||||||
c.toData(reinterpret_cast<char *>(data), PixelFormat::F32, 4);
|
c.toData(reinterpret_cast<char *>(data), PixelFormat::F32, 4);
|
||||||
|
|
||||||
EXPECT_FLOAT_EQ(data[0], 0.25f);
|
EXPECT_FLOAT_EQ(data[0], 0.25f);
|
||||||
EXPECT_FLOAT_EQ(data[1], 0.5f);
|
EXPECT_FLOAT_EQ(data[1], 0.5f);
|
||||||
EXPECT_FLOAT_EQ(data[2], 0.75f);
|
EXPECT_FLOAT_EQ(data[2], 0.75f);
|
||||||
EXPECT_FLOAT_EQ(data[3], 1.0f);
|
EXPECT_FLOAT_EQ(data[3], 1.0f);
|
||||||
|
|
||||||
Color restored = Color::fromData(reinterpret_cast<const char *>(data),
|
Color restored = Color::fromData(reinterpret_cast<const char *>(data),
|
||||||
PixelFormat::F32, 4);
|
PixelFormat::F32, 4);
|
||||||
EXPECT_FLOAT_EQ(restored.red(), 0.25f);
|
EXPECT_FLOAT_EQ(restored.red(), 0.25f);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreColor, ToDataAndFromDataU10)
|
TEST(CoreColor, ToDataAndFromDataU10)
|
||||||
{
|
{
|
||||||
Color c(1.0f, 0.5f, 0.0f, 1.0f);
|
Color c(1.0f, 0.5f, 0.0f, 1.0f);
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
c.toData(reinterpret_cast<char *>(&data), PixelFormat::U10, 4);
|
c.toData(reinterpret_cast<char *>(&data), PixelFormat::U10, 4);
|
||||||
|
|
||||||
Color restored = Color::fromData(reinterpret_cast<const char *>(&data),
|
Color restored = Color::fromData(reinterpret_cast<const char *>(&data),
|
||||||
PixelFormat::U10, 4);
|
PixelFormat::U10, 4);
|
||||||
EXPECT_NEAR(restored.red(), 1.0f, 0.001f);
|
EXPECT_NEAR(restored.red(), 1.0f, 0.001f);
|
||||||
EXPECT_NEAR(restored.green(), 0.5f, 0.001f);
|
EXPECT_NEAR(restored.green(), 0.5f, 0.001f);
|
||||||
EXPECT_NEAR(restored.blue(), 0.0f, 0.001f);
|
EXPECT_NEAR(restored.blue(), 0.0f, 0.001f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ TEST(CoreSampleBuffer, Set)
|
|||||||
{
|
{
|
||||||
AudioParams params = MakeParams();
|
AudioParams params = MakeParams();
|
||||||
SampleBuffer b(params, 4);
|
SampleBuffer b(params, 4);
|
||||||
float data[2] = {0.3f, 0.4f};
|
float data[2] = { 0.3f, 0.4f };
|
||||||
b.set(0, data, 1, 2);
|
b.set(0, data, 1, 2);
|
||||||
EXPECT_FLOAT_EQ(b.data(0)[1], 0.3f);
|
EXPECT_FLOAT_EQ(b.data(0)[1], 0.3f);
|
||||||
EXPECT_FLOAT_EQ(b.data(0)[2], 0.4f);
|
EXPECT_FLOAT_EQ(b.data(0)[2], 0.4f);
|
||||||
|
|||||||
@@ -8,58 +8,59 @@ using namespace olive::core;
|
|||||||
|
|
||||||
TEST(CoreStringUtils, Split)
|
TEST(CoreStringUtils, Split)
|
||||||
{
|
{
|
||||||
auto result = StringUtils::split("a,b,c", ',');
|
auto result = StringUtils::split("a,b,c", ',');
|
||||||
ASSERT_EQ(result.size(), 3u);
|
ASSERT_EQ(result.size(), 3u);
|
||||||
EXPECT_EQ(result[0], "a");
|
EXPECT_EQ(result[0], "a");
|
||||||
EXPECT_EQ(result[1], "b");
|
EXPECT_EQ(result[1], "b");
|
||||||
EXPECT_EQ(result[2], "c");
|
EXPECT_EQ(result[2], "c");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreStringUtils, SplitRegex)
|
TEST(CoreStringUtils, SplitRegex)
|
||||||
{
|
{
|
||||||
auto result = StringUtils::split_regex("one:two;three", std::regex("(:)|(;)| "));
|
auto result =
|
||||||
ASSERT_EQ(result.size(), 3u);
|
StringUtils::split_regex("one:two;three", std::regex("(:)|(;)| "));
|
||||||
EXPECT_EQ(result[0], "one");
|
ASSERT_EQ(result.size(), 3u);
|
||||||
EXPECT_EQ(result[1], "two");
|
EXPECT_EQ(result[0], "one");
|
||||||
EXPECT_EQ(result[2], "three");
|
EXPECT_EQ(result[1], "two");
|
||||||
|
EXPECT_EQ(result[2], "three");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreStringUtils, ToInt)
|
TEST(CoreStringUtils, ToInt)
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
EXPECT_EQ(StringUtils::to_int("42", &ok), 42);
|
EXPECT_EQ(StringUtils::to_int("42", &ok), 42);
|
||||||
EXPECT_TRUE(ok);
|
EXPECT_TRUE(ok);
|
||||||
|
|
||||||
EXPECT_EQ(StringUtils::to_int("-7", 10, &ok), -7);
|
EXPECT_EQ(StringUtils::to_int("-7", 10, &ok), -7);
|
||||||
EXPECT_TRUE(ok);
|
EXPECT_TRUE(ok);
|
||||||
|
|
||||||
EXPECT_EQ(StringUtils::to_int("ff", 16, &ok), 255);
|
EXPECT_EQ(StringUtils::to_int("ff", 16, &ok), 255);
|
||||||
EXPECT_TRUE(ok);
|
EXPECT_TRUE(ok);
|
||||||
|
|
||||||
EXPECT_EQ(StringUtils::to_int("abc", &ok), 0);
|
EXPECT_EQ(StringUtils::to_int("abc", &ok), 0);
|
||||||
EXPECT_FALSE(ok);
|
EXPECT_FALSE(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreStringUtils, ToStringLeftpad)
|
TEST(CoreStringUtils, ToStringLeftpad)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(StringUtils::to_string_leftpad(5, 3), "005");
|
EXPECT_EQ(StringUtils::to_string_leftpad(5, 3), "005");
|
||||||
EXPECT_EQ(StringUtils::to_string_leftpad(123, 2), "123");
|
EXPECT_EQ(StringUtils::to_string_leftpad(123, 2), "123");
|
||||||
EXPECT_EQ(StringUtils::to_string_leftpad(7, 4, '*'), "***7");
|
EXPECT_EQ(StringUtils::to_string_leftpad(7, 4, '*'), "***7");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreStringUtils, Format)
|
TEST(CoreStringUtils, Format)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(StringUtils::format("Hello %s %d", "world", 42),
|
EXPECT_EQ(StringUtils::format("Hello %s %d", "world", 42),
|
||||||
"Hello world 42");
|
"Hello world 42");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreStringUtils, Trim)
|
TEST(CoreStringUtils, Trim)
|
||||||
{
|
{
|
||||||
std::string s = " hello world ";
|
std::string s = " hello world ";
|
||||||
StringUtils::trim(s);
|
StringUtils::trim(s);
|
||||||
EXPECT_EQ(s, "hello world");
|
EXPECT_EQ(s, "hello world");
|
||||||
|
|
||||||
EXPECT_EQ(StringUtils::trimmed("\t\nvalue\t\n"), "value");
|
EXPECT_EQ(StringUtils::trimmed("\t\nvalue\t\n"), "value");
|
||||||
EXPECT_EQ(StringUtils::ltrimmed(" left"), "left");
|
EXPECT_EQ(StringUtils::ltrimmed(" left"), "left");
|
||||||
EXPECT_EQ(StringUtils::rtrimmed("right "), "right");
|
EXPECT_EQ(StringUtils::rtrimmed("right "), "right");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,110 +6,111 @@ using namespace olive::core;
|
|||||||
|
|
||||||
TEST(CoreTimecode, TimeToTimecodeSeconds)
|
TEST(CoreTimecode, TimeToTimecodeSeconds)
|
||||||
{
|
{
|
||||||
rational time(5, 1);
|
rational time(5, 1);
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
std::string tc = Timecode::time_to_timecode(time, tb, Timecode::kTimecodeSeconds);
|
std::string tc =
|
||||||
EXPECT_EQ(tc, "00:00:05.000");
|
Timecode::time_to_timecode(time, tb, Timecode::kTimecodeSeconds);
|
||||||
|
EXPECT_EQ(tc, "00:00:05.000");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimeToTimecodeNonDropFrame)
|
TEST(CoreTimecode, TimeToTimecodeNonDropFrame)
|
||||||
{
|
{
|
||||||
rational time(2, 1);
|
rational time(2, 1);
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
std::string tc =
|
std::string tc =
|
||||||
Timecode::time_to_timecode(time, tb, Timecode::kTimecodeNonDropFrame);
|
Timecode::time_to_timecode(time, tb, Timecode::kTimecodeNonDropFrame);
|
||||||
EXPECT_EQ(tc, "00:00:02:00");
|
EXPECT_EQ(tc, "00:00:02:00");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimeToTimecodePlusSign)
|
TEST(CoreTimecode, TimeToTimecodePlusSign)
|
||||||
{
|
{
|
||||||
rational time(1, 1);
|
rational time(1, 1);
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
std::string tc = Timecode::time_to_timecode(time, tb,
|
std::string tc =
|
||||||
Timecode::kTimecodeSeconds, true);
|
Timecode::time_to_timecode(time, tb, Timecode::kTimecodeSeconds, true);
|
||||||
EXPECT_EQ(tc.substr(0, 1), "+");
|
EXPECT_EQ(tc.substr(0, 1), "+");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimeToTimecodeInvalidTimebase)
|
TEST(CoreTimecode, TimeToTimecodeInvalidTimebase)
|
||||||
{
|
{
|
||||||
rational time(1, 1);
|
rational time(1, 1);
|
||||||
EXPECT_EQ(Timecode::time_to_timecode(time, rational(), Timecode::kFrames),
|
EXPECT_EQ(Timecode::time_to_timecode(time, rational(), Timecode::kFrames),
|
||||||
"INVALID TIMEBASE");
|
"INVALID TIMEBASE");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimecodeToTimeSeconds)
|
TEST(CoreTimecode, TimecodeToTimeSeconds)
|
||||||
{
|
{
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
rational t = Timecode::timecode_to_time("00:00:05.500", tb,
|
rational t = Timecode::timecode_to_time("00:00:05.500", tb,
|
||||||
Timecode::kTimecodeSeconds, &ok);
|
Timecode::kTimecodeSeconds, &ok);
|
||||||
EXPECT_TRUE(ok);
|
EXPECT_TRUE(ok);
|
||||||
EXPECT_EQ(t, rational(11, 2));
|
EXPECT_EQ(t, rational(11, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimecodeToTimeNonDropFrame)
|
TEST(CoreTimecode, TimecodeToTimeNonDropFrame)
|
||||||
{
|
{
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
rational t = Timecode::timecode_to_time("00:00:02:03", tb,
|
rational t = Timecode::timecode_to_time(
|
||||||
Timecode::kTimecodeNonDropFrame, &ok);
|
"00:00:02:03", tb, Timecode::kTimecodeNonDropFrame, &ok);
|
||||||
EXPECT_TRUE(ok);
|
EXPECT_TRUE(ok);
|
||||||
EXPECT_EQ(t, rational(53, 25));
|
EXPECT_EQ(t, rational(53, 25));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimecodeToTimeInvalid)
|
TEST(CoreTimecode, TimecodeToTimeInvalid)
|
||||||
{
|
{
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
Timecode::timecode_to_time("not a timecode", tb,
|
Timecode::timecode_to_time("not a timecode", tb, Timecode::kTimecodeSeconds,
|
||||||
Timecode::kTimecodeSeconds, &ok);
|
&ok);
|
||||||
EXPECT_FALSE(ok);
|
EXPECT_FALSE(ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimeToString)
|
TEST(CoreTimecode, TimeToString)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(Timecode::time_to_string(3661000), "01:01:01");
|
EXPECT_EQ(Timecode::time_to_string(3661000), "01:01:01");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, SnapTimeToTimebase)
|
TEST(CoreTimecode, SnapTimeToTimebase)
|
||||||
{
|
{
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
rational snapped = Timecode::snap_time_to_timebase(rational(1, 10), tb);
|
rational snapped = Timecode::snap_time_to_timebase(rational(1, 10), tb);
|
||||||
// 0.1s @ 25fps rounds to frame 3 (0.12s)
|
// 0.1s @ 25fps rounds to frame 3 (0.12s)
|
||||||
EXPECT_EQ(snapped, rational(3, 25));
|
EXPECT_EQ(snapped, rational(3, 25));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimeToTimestamp)
|
TEST(CoreTimecode, TimeToTimestamp)
|
||||||
{
|
{
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
EXPECT_EQ(Timecode::time_to_timestamp(rational(2, 1), tb), 50);
|
EXPECT_EQ(Timecode::time_to_timestamp(rational(2, 1), tb), 50);
|
||||||
EXPECT_EQ(Timecode::time_to_timestamp(0.08, tb, Timecode::kFloor), 2);
|
EXPECT_EQ(Timecode::time_to_timestamp(0.08, tb, Timecode::kFloor), 2);
|
||||||
EXPECT_EQ(Timecode::time_to_timestamp(0.08, tb, Timecode::kCeil), 2);
|
EXPECT_EQ(Timecode::time_to_timestamp(0.08, tb, Timecode::kCeil), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimestampToTime)
|
TEST(CoreTimecode, TimestampToTime)
|
||||||
{
|
{
|
||||||
rational tb(1, 25);
|
rational tb(1, 25);
|
||||||
EXPECT_EQ(Timecode::timestamp_to_time(50, tb), rational(2, 1));
|
EXPECT_EQ(Timecode::timestamp_to_time(50, tb), rational(2, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, RescaleTimestamp)
|
TEST(CoreTimecode, RescaleTimestamp)
|
||||||
{
|
{
|
||||||
rational src(1, 25);
|
rational src(1, 25);
|
||||||
rational dst(1, 30);
|
rational dst(1, 30);
|
||||||
EXPECT_EQ(Timecode::rescale_timestamp(50, src, dst), 60);
|
EXPECT_EQ(Timecode::rescale_timestamp(50, src, dst), 60);
|
||||||
EXPECT_EQ(Timecode::rescale_timestamp(50, src, src), 50);
|
EXPECT_EQ(Timecode::rescale_timestamp(50, src, src), 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, RescaleTimestampCeil)
|
TEST(CoreTimecode, RescaleTimestampCeil)
|
||||||
{
|
{
|
||||||
rational src(1, 25);
|
rational src(1, 25);
|
||||||
rational dst(1, 30);
|
rational dst(1, 30);
|
||||||
EXPECT_EQ(Timecode::rescale_timestamp_ceil(1, src, dst), 2);
|
EXPECT_EQ(Timecode::rescale_timestamp_ceil(1, src, dst), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimecode, TimebaseIsDropFrame)
|
TEST(CoreTimecode, TimebaseIsDropFrame)
|
||||||
{
|
{
|
||||||
EXPECT_FALSE(Timecode::timebase_is_drop_frame(rational(1, 25)));
|
EXPECT_FALSE(Timecode::timebase_is_drop_frame(rational(1, 25)));
|
||||||
EXPECT_TRUE(Timecode::timebase_is_drop_frame(rational(1001, 30000)));
|
EXPECT_TRUE(Timecode::timebase_is_drop_frame(rational(1001, 30000)));
|
||||||
}
|
}
|
||||||
|
|||||||
+102
-101
@@ -6,179 +6,180 @@ using namespace olive::core;
|
|||||||
|
|
||||||
TEST(CoreTimeRange, ConstructAndAccess)
|
TEST(CoreTimeRange, ConstructAndAccess)
|
||||||
{
|
{
|
||||||
TimeRange r(rational(1), rational(5));
|
TimeRange r(rational(1), rational(5));
|
||||||
EXPECT_EQ(r.in(), rational(1));
|
EXPECT_EQ(r.in(), rational(1));
|
||||||
EXPECT_EQ(r.out(), rational(5));
|
EXPECT_EQ(r.out(), rational(5));
|
||||||
EXPECT_EQ(r.length(), rational(4));
|
EXPECT_EQ(r.length(), rational(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRange, NormalizationSwapsReversedBounds)
|
TEST(CoreTimeRange, NormalizationSwapsReversedBounds)
|
||||||
{
|
{
|
||||||
TimeRange r(rational(5), rational(1));
|
TimeRange r(rational(5), rational(1));
|
||||||
EXPECT_EQ(r.in(), rational(1));
|
EXPECT_EQ(r.in(), rational(1));
|
||||||
EXPECT_EQ(r.out(), rational(5));
|
EXPECT_EQ(r.out(), rational(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRange, SettersNormalize)
|
TEST(CoreTimeRange, SettersNormalize)
|
||||||
{
|
{
|
||||||
TimeRange r(rational(0), rational(10));
|
TimeRange r(rational(0), rational(10));
|
||||||
r.set_in(rational(15));
|
r.set_in(rational(15));
|
||||||
EXPECT_EQ(r.in(), rational(10));
|
EXPECT_EQ(r.in(), rational(10));
|
||||||
EXPECT_EQ(r.out(), rational(15));
|
EXPECT_EQ(r.out(), rational(15));
|
||||||
|
|
||||||
r.set_out(rational(2));
|
r.set_out(rational(2));
|
||||||
EXPECT_EQ(r.in(), rational(2));
|
EXPECT_EQ(r.in(), rational(2));
|
||||||
EXPECT_EQ(r.out(), rational(10));
|
EXPECT_EQ(r.out(), rational(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRange, ContainsRational)
|
TEST(CoreTimeRange, ContainsRational)
|
||||||
{
|
{
|
||||||
TimeRange r(rational(0), rational(10));
|
TimeRange r(rational(0), rational(10));
|
||||||
EXPECT_TRUE(r.Contains(rational(5)));
|
EXPECT_TRUE(r.Contains(rational(5)));
|
||||||
EXPECT_FALSE(r.Contains(rational(10)));
|
EXPECT_FALSE(r.Contains(rational(10)));
|
||||||
EXPECT_FALSE(r.Contains(rational(-1)));
|
EXPECT_FALSE(r.Contains(rational(-1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRange, ContainsRange)
|
TEST(CoreTimeRange, ContainsRange)
|
||||||
{
|
{
|
||||||
TimeRange outer(rational(0), rational(10));
|
TimeRange outer(rational(0), rational(10));
|
||||||
TimeRange inner(rational(2), rational(8));
|
TimeRange inner(rational(2), rational(8));
|
||||||
TimeRange partial(rational(5), rational(15));
|
TimeRange partial(rational(5), rational(15));
|
||||||
|
|
||||||
EXPECT_TRUE(outer.Contains(inner));
|
EXPECT_TRUE(outer.Contains(inner));
|
||||||
EXPECT_FALSE(outer.Contains(partial));
|
EXPECT_FALSE(outer.Contains(partial));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRange, OverlapsWith)
|
TEST(CoreTimeRange, OverlapsWith)
|
||||||
{
|
{
|
||||||
TimeRange a(rational(0), rational(10));
|
TimeRange a(rational(0), rational(10));
|
||||||
TimeRange b(rational(5), rational(15));
|
TimeRange b(rational(5), rational(15));
|
||||||
TimeRange c(rational(10), rational(20));
|
TimeRange c(rational(10), rational(20));
|
||||||
|
|
||||||
EXPECT_TRUE(a.OverlapsWith(b));
|
EXPECT_TRUE(a.OverlapsWith(b));
|
||||||
// By default bounds are inclusive, so [0,10] and [10,20] touch and overlap
|
// By default bounds are inclusive, so [0,10] and [10,20] touch and overlap
|
||||||
EXPECT_TRUE(a.OverlapsWith(c));
|
EXPECT_TRUE(a.OverlapsWith(c));
|
||||||
EXPECT_FALSE(a.OverlapsWith(c, false, false));
|
EXPECT_FALSE(a.OverlapsWith(c, false, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRange, CombineAndIntersect)
|
TEST(CoreTimeRange, CombineAndIntersect)
|
||||||
{
|
{
|
||||||
TimeRange a(rational(0), rational(10));
|
TimeRange a(rational(0), rational(10));
|
||||||
TimeRange b(rational(5), rational(15));
|
TimeRange b(rational(5), rational(15));
|
||||||
|
|
||||||
TimeRange combined = a.Combined(b);
|
TimeRange combined = a.Combined(b);
|
||||||
EXPECT_EQ(combined.in(), rational(0));
|
EXPECT_EQ(combined.in(), rational(0));
|
||||||
EXPECT_EQ(combined.out(), rational(15));
|
EXPECT_EQ(combined.out(), rational(15));
|
||||||
|
|
||||||
TimeRange intersect = a.Intersected(b);
|
TimeRange intersect = a.Intersected(b);
|
||||||
EXPECT_EQ(intersect.in(), rational(5));
|
EXPECT_EQ(intersect.in(), rational(5));
|
||||||
EXPECT_EQ(intersect.out(), rational(10));
|
EXPECT_EQ(intersect.out(), rational(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRange, Arithmetic)
|
TEST(CoreTimeRange, Arithmetic)
|
||||||
{
|
{
|
||||||
TimeRange r(rational(0), rational(10));
|
TimeRange r(rational(0), rational(10));
|
||||||
TimeRange shifted = r + rational(5);
|
TimeRange shifted = r + rational(5);
|
||||||
EXPECT_EQ(shifted.in(), rational(5));
|
EXPECT_EQ(shifted.in(), rational(5));
|
||||||
EXPECT_EQ(shifted.out(), rational(15));
|
EXPECT_EQ(shifted.out(), rational(15));
|
||||||
|
|
||||||
shifted -= rational(3);
|
shifted -= rational(3);
|
||||||
EXPECT_EQ(shifted.in(), rational(2));
|
EXPECT_EQ(shifted.in(), rational(2));
|
||||||
EXPECT_EQ(shifted.out(), rational(12));
|
EXPECT_EQ(shifted.out(), rational(12));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRange, Split)
|
TEST(CoreTimeRange, Split)
|
||||||
{
|
{
|
||||||
TimeRange r(rational(0), rational(10));
|
TimeRange r(rational(0), rational(10));
|
||||||
auto pieces = r.Split(3);
|
auto pieces = r.Split(3);
|
||||||
ASSERT_EQ(pieces.size(), 4u);
|
ASSERT_EQ(pieces.size(), 4u);
|
||||||
EXPECT_EQ(pieces.front().in(), rational(0));
|
EXPECT_EQ(pieces.front().in(), rational(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRangeList, InsertMergesOverlapping)
|
TEST(CoreTimeRangeList, InsertMergesOverlapping)
|
||||||
{
|
{
|
||||||
TimeRangeList list;
|
TimeRangeList list;
|
||||||
list.insert(TimeRange(rational(0), rational(5)));
|
list.insert(TimeRange(rational(0), rational(5)));
|
||||||
list.insert(TimeRange(rational(3), rational(8)));
|
list.insert(TimeRange(rational(3), rational(8)));
|
||||||
list.insert(TimeRange(rational(10), rational(12)));
|
list.insert(TimeRange(rational(10), rational(12)));
|
||||||
|
|
||||||
EXPECT_EQ(list.size(), 2);
|
EXPECT_EQ(list.size(), 2);
|
||||||
EXPECT_EQ(list.first().in(), rational(0));
|
EXPECT_EQ(list.first().in(), rational(0));
|
||||||
EXPECT_EQ(list.first().out(), rational(8));
|
EXPECT_EQ(list.first().out(), rational(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRangeList, RemoveSplitsRange)
|
TEST(CoreTimeRangeList, RemoveSplitsRange)
|
||||||
{
|
{
|
||||||
TimeRangeList list;
|
TimeRangeList list;
|
||||||
list.insert(TimeRange(rational(0), rational(10)));
|
list.insert(TimeRange(rational(0), rational(10)));
|
||||||
list.remove(TimeRange(rational(3), rational(7)));
|
list.remove(TimeRange(rational(3), rational(7)));
|
||||||
|
|
||||||
EXPECT_EQ(list.size(), 2);
|
EXPECT_EQ(list.size(), 2);
|
||||||
EXPECT_EQ(list.first().out(), rational(3));
|
EXPECT_EQ(list.first().out(), rational(3));
|
||||||
EXPECT_EQ(list.last().in(), rational(7));
|
EXPECT_EQ(list.last().in(), rational(7));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRangeList, Shift)
|
TEST(CoreTimeRangeList, Shift)
|
||||||
{
|
{
|
||||||
TimeRangeList list;
|
TimeRangeList list;
|
||||||
list.insert(TimeRange(rational(0), rational(5)));
|
list.insert(TimeRange(rational(0), rational(5)));
|
||||||
list.shift(rational(10));
|
list.shift(rational(10));
|
||||||
|
|
||||||
EXPECT_EQ(list.first().in(), rational(10));
|
EXPECT_EQ(list.first().in(), rational(10));
|
||||||
EXPECT_EQ(list.first().out(), rational(15));
|
EXPECT_EQ(list.first().out(), rational(15));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRangeList, TrimInAndOut)
|
TEST(CoreTimeRangeList, TrimInAndOut)
|
||||||
{
|
{
|
||||||
TimeRangeList list;
|
TimeRangeList list;
|
||||||
list.insert(TimeRange(rational(10), rational(20)));
|
list.insert(TimeRange(rational(10), rational(20)));
|
||||||
list.trim_in(rational(5));
|
list.trim_in(rational(5));
|
||||||
EXPECT_EQ(list.first().in(), rational(15));
|
EXPECT_EQ(list.first().in(), rational(15));
|
||||||
EXPECT_EQ(list.first().out(), rational(20));
|
EXPECT_EQ(list.first().out(), rational(20));
|
||||||
|
|
||||||
list.trim_out(rational(-5));
|
list.trim_out(rational(-5));
|
||||||
// set_out(out + diff) = 20 + (-5) = 15
|
// set_out(out + diff) = 20 + (-5) = 15
|
||||||
EXPECT_EQ(list.first().out(), rational(15));
|
EXPECT_EQ(list.first().out(), rational(15));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRangeList, Intersects)
|
TEST(CoreTimeRangeList, Intersects)
|
||||||
{
|
{
|
||||||
TimeRangeList list;
|
TimeRangeList list;
|
||||||
list.insert(TimeRange(rational(0), rational(10)));
|
list.insert(TimeRange(rational(0), rational(10)));
|
||||||
list.insert(TimeRange(rational(20), rational(30)));
|
list.insert(TimeRange(rational(20), rational(30)));
|
||||||
|
|
||||||
TimeRangeList result = list.Intersects(TimeRange(rational(5), rational(25)));
|
TimeRangeList result =
|
||||||
EXPECT_EQ(result.size(), 2);
|
list.Intersects(TimeRange(rational(5), rational(25)));
|
||||||
EXPECT_EQ(result.first().in(), rational(5));
|
EXPECT_EQ(result.size(), 2);
|
||||||
EXPECT_EQ(result.first().out(), rational(10));
|
EXPECT_EQ(result.first().in(), rational(5));
|
||||||
|
EXPECT_EQ(result.first().out(), rational(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRangeListFrameIterator, IteratesFrames)
|
TEST(CoreTimeRangeListFrameIterator, IteratesFrames)
|
||||||
{
|
{
|
||||||
TimeRangeList list;
|
TimeRangeList list;
|
||||||
// 5 seconds at 25fps = 125 frames
|
// 5 seconds at 25fps = 125 frames
|
||||||
list.insert(TimeRange(rational(0), rational(5)));
|
list.insert(TimeRange(rational(0), rational(5)));
|
||||||
TimeRangeListFrameIterator it(list, rational(1, 25));
|
TimeRangeListFrameIterator it(list, rational(1, 25));
|
||||||
|
|
||||||
rational out;
|
rational out;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while (it.GetNext(&out)) {
|
while (it.GetNext(&out)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(count, 125);
|
EXPECT_EQ(count, 125);
|
||||||
EXPECT_EQ(it.size(), 125);
|
EXPECT_EQ(it.size(), 125);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(CoreTimeRangeListFrameIterator, HasNext)
|
TEST(CoreTimeRangeListFrameIterator, HasNext)
|
||||||
{
|
{
|
||||||
TimeRangeList list;
|
TimeRangeList list;
|
||||||
list.insert(TimeRange(rational(0), rational(1)));
|
list.insert(TimeRange(rational(0), rational(1)));
|
||||||
TimeRangeListFrameIterator it(list, rational(1, 25));
|
TimeRangeListFrameIterator it(list, rational(1, 25));
|
||||||
|
|
||||||
EXPECT_TRUE(it.HasNext());
|
EXPECT_TRUE(it.HasNext());
|
||||||
rational out;
|
rational out;
|
||||||
while (it.GetNext(&out)) {
|
while (it.GetNext(&out)) {
|
||||||
}
|
}
|
||||||
EXPECT_FALSE(it.HasNext());
|
EXPECT_FALSE(it.HasNext());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ TEST(DynamicRenderBackend, LoadsExperimentalOpenGLBackend)
|
|||||||
#else
|
#else
|
||||||
olive::DynamicRenderer renderer(QStringLiteral("opengl"));
|
olive::DynamicRenderer renderer(QStringLiteral("opengl"));
|
||||||
if (!renderer.Load()) {
|
if (!renderer.Load()) {
|
||||||
GTEST_SKIP() << "opengl backend library could not be loaded in this environment";
|
GTEST_SKIP()
|
||||||
|
<< "opengl backend library could not be loaded in this environment";
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(renderer.OpenGLContext(), nullptr);
|
EXPECT_EQ(renderer.OpenGLContext(), nullptr);
|
||||||
@@ -48,11 +49,13 @@ TEST(DynamicRenderBackend, OpenGLBackendFollowsAdapterToRenderThread)
|
|||||||
#else
|
#else
|
||||||
olive::DynamicRenderer renderer(QStringLiteral("opengl"));
|
olive::DynamicRenderer renderer(QStringLiteral("opengl"));
|
||||||
if (!renderer.Load()) {
|
if (!renderer.Load()) {
|
||||||
GTEST_SKIP() << "opengl backend library could not be loaded in this environment";
|
GTEST_SKIP()
|
||||||
|
<< "opengl backend library could not be loaded in this environment";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!renderer.Init()) {
|
if (!renderer.Init()) {
|
||||||
GTEST_SKIP() << "OpenGL backend could not be initialized on this system";
|
GTEST_SKIP()
|
||||||
|
<< "OpenGL backend could not be initialized on this system";
|
||||||
}
|
}
|
||||||
|
|
||||||
QThread render_thread;
|
QThread render_thread;
|
||||||
@@ -71,9 +74,9 @@ TEST(DynamicRenderBackend, OpenGLBackendFollowsAdapterToRenderThread)
|
|||||||
&renderer,
|
&renderer,
|
||||||
[&]() {
|
[&]() {
|
||||||
renderer.PostInit();
|
renderer.PostInit();
|
||||||
texture = renderer.CreateTexture(olive::VideoParams(
|
texture = renderer.CreateTexture(
|
||||||
64, 64, olive::PixelFormat::U8,
|
olive::VideoParams(64, 64, olive::PixelFormat::U8,
|
||||||
olive::VideoParams::kRGBAChannelCount));
|
olive::VideoParams::kRGBAChannelCount));
|
||||||
},
|
},
|
||||||
Qt::BlockingQueuedConnection);
|
Qt::BlockingQueuedConnection);
|
||||||
|
|
||||||
@@ -94,7 +97,8 @@ TEST(DynamicRenderBackend, LoadsExperimentalVulkanBackendWhenAvailable)
|
|||||||
#else
|
#else
|
||||||
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
||||||
if (!renderer.Load()) {
|
if (!renderer.Load()) {
|
||||||
GTEST_SKIP() << "vulkan backend library could not be loaded in this environment";
|
GTEST_SKIP()
|
||||||
|
<< "vulkan backend library could not be loaded in this environment";
|
||||||
}
|
}
|
||||||
|
|
||||||
OakRenderBackendInfo info = {};
|
OakRenderBackendInfo info = {};
|
||||||
@@ -121,13 +125,15 @@ TEST(DynamicRenderBackend, FallsBackWhenExperimentalVulkanUnavailable)
|
|||||||
#else
|
#else
|
||||||
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
||||||
if (!renderer.Load()) {
|
if (!renderer.Load()) {
|
||||||
GTEST_SKIP() << "vulkan backend library could not be loaded in this environment";
|
GTEST_SKIP()
|
||||||
|
<< "vulkan backend library could not be loaded in this environment";
|
||||||
}
|
}
|
||||||
|
|
||||||
OakRenderBackendInfo info = {};
|
OakRenderBackendInfo info = {};
|
||||||
ASSERT_TRUE(renderer.GetBackendInfo(&info));
|
ASSERT_TRUE(renderer.GetBackendInfo(&info));
|
||||||
if (info.kind == OAK_RENDER_BACKEND_VULKAN) {
|
if (info.kind == OAK_RENDER_BACKEND_VULKAN) {
|
||||||
GTEST_SKIP() << "Vulkan backend is available on this system; skip fallback test";
|
GTEST_SKIP()
|
||||||
|
<< "Vulkan backend is available on this system; skip fallback test";
|
||||||
}
|
}
|
||||||
EXPECT_EQ(renderer.backend_name(), QStringLiteral("opengl"));
|
EXPECT_EQ(renderer.backend_name(), QStringLiteral("opengl"));
|
||||||
EXPECT_EQ(renderer.OpenGLContext(), nullptr);
|
EXPECT_EQ(renderer.OpenGLContext(), nullptr);
|
||||||
@@ -145,7 +151,8 @@ TEST(DynamicRenderBackend, VulkanUploadBlitDownload)
|
|||||||
#else
|
#else
|
||||||
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
||||||
if (!renderer.Load()) {
|
if (!renderer.Load()) {
|
||||||
GTEST_SKIP() << "vulkan backend library could not be loaded in this environment";
|
GTEST_SKIP()
|
||||||
|
<< "vulkan backend library could not be loaded in this environment";
|
||||||
}
|
}
|
||||||
|
|
||||||
OakRenderBackendInfo info = {};
|
OakRenderBackendInfo info = {};
|
||||||
@@ -168,8 +175,8 @@ TEST(DynamicRenderBackend, VulkanUploadBlitDownload)
|
|||||||
QByteArray src_data(kSize * kSize * 4, 0);
|
QByteArray src_data(kSize * kSize * 4, 0);
|
||||||
for (int i = 0; i < kSize * kSize; ++i) {
|
for (int i = 0; i < kSize * kSize; ++i) {
|
||||||
src_data[i * 4 + 0] = static_cast<char>(255); // R
|
src_data[i * 4 + 0] = static_cast<char>(255); // R
|
||||||
src_data[i * 4 + 1] = static_cast<char>(0); // G
|
src_data[i * 4 + 1] = static_cast<char>(0); // G
|
||||||
src_data[i * 4 + 2] = static_cast<char>(0); // B
|
src_data[i * 4 + 2] = static_cast<char>(0); // B
|
||||||
src_data[i * 4 + 3] = static_cast<char>(255); // A
|
src_data[i * 4 + 3] = static_cast<char>(255); // A
|
||||||
}
|
}
|
||||||
src->Upload(src_data.data(), kSize);
|
src->Upload(src_data.data(), kSize);
|
||||||
@@ -178,23 +185,24 @@ TEST(DynamicRenderBackend, VulkanUploadBlitDownload)
|
|||||||
ASSERT_NE(dst, nullptr);
|
ASSERT_NE(dst, nullptr);
|
||||||
ASSERT_FALSE(dst->IsDummy());
|
ASSERT_FALSE(dst->IsDummy());
|
||||||
|
|
||||||
const QString vert = QStringLiteral(
|
const QString vert =
|
||||||
"uniform mat4 ove_mvpmat;\n"
|
QStringLiteral("uniform mat4 ove_mvpmat;\n"
|
||||||
"in vec4 a_position;\n"
|
"in vec4 a_position;\n"
|
||||||
"in vec2 a_texcoord;\n"
|
"in vec2 a_texcoord;\n"
|
||||||
"out vec2 ove_texcoord;\n"
|
"out vec2 ove_texcoord;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" gl_Position = ove_mvpmat * a_position;\n"
|
" gl_Position = ove_mvpmat * a_position;\n"
|
||||||
" ove_texcoord = a_texcoord;\n"
|
" ove_texcoord = a_texcoord;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
const QString frag = QStringLiteral(
|
const QString frag =
|
||||||
"uniform sampler2D ove_maintex;\n"
|
QStringLiteral("uniform sampler2D ove_maintex;\n"
|
||||||
"in vec2 ove_texcoord;\n"
|
"in vec2 ove_texcoord;\n"
|
||||||
"out vec4 frag_color;\n"
|
"out vec4 frag_color;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" frag_color = texture(ove_maintex, ove_texcoord);\n"
|
" frag_color = texture(ove_maintex, ove_texcoord);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
QVariant shader = renderer.CreateNativeShader(olive::ShaderCode(frag, vert));
|
QVariant shader =
|
||||||
|
renderer.CreateNativeShader(olive::ShaderCode(frag, vert));
|
||||||
ASSERT_FALSE(shader.isNull());
|
ASSERT_FALSE(shader.isNull());
|
||||||
|
|
||||||
olive::ShaderJob job;
|
olive::ShaderJob job;
|
||||||
@@ -226,7 +234,8 @@ TEST(DynamicRenderBackend, VulkanNullDestinationBlitDoesNotCrash)
|
|||||||
#else
|
#else
|
||||||
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
||||||
if (!renderer.Load()) {
|
if (!renderer.Load()) {
|
||||||
GTEST_SKIP() << "vulkan backend library could not be loaded in this environment";
|
GTEST_SKIP()
|
||||||
|
<< "vulkan backend library could not be loaded in this environment";
|
||||||
}
|
}
|
||||||
|
|
||||||
OakRenderBackendInfo info = {};
|
OakRenderBackendInfo info = {};
|
||||||
@@ -253,23 +262,24 @@ TEST(DynamicRenderBackend, VulkanNullDestinationBlitDoesNotCrash)
|
|||||||
}
|
}
|
||||||
src->Upload(src_data.data(), kSize);
|
src->Upload(src_data.data(), kSize);
|
||||||
|
|
||||||
const QString vert = QStringLiteral(
|
const QString vert =
|
||||||
"uniform mat4 ove_mvpmat;\n"
|
QStringLiteral("uniform mat4 ove_mvpmat;\n"
|
||||||
"in vec4 a_position;\n"
|
"in vec4 a_position;\n"
|
||||||
"in vec2 a_texcoord;\n"
|
"in vec2 a_texcoord;\n"
|
||||||
"out vec2 ove_texcoord;\n"
|
"out vec2 ove_texcoord;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" gl_Position = ove_mvpmat * a_position;\n"
|
" gl_Position = ove_mvpmat * a_position;\n"
|
||||||
" ove_texcoord = a_texcoord;\n"
|
" ove_texcoord = a_texcoord;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
const QString frag = QStringLiteral(
|
const QString frag =
|
||||||
"uniform sampler2D ove_maintex;\n"
|
QStringLiteral("uniform sampler2D ove_maintex;\n"
|
||||||
"in vec2 ove_texcoord;\n"
|
"in vec2 ove_texcoord;\n"
|
||||||
"out vec4 frag_color;\n"
|
"out vec4 frag_color;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" frag_color = texture(ove_maintex, ove_texcoord);\n"
|
" frag_color = texture(ove_maintex, ove_texcoord);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
QVariant shader = renderer.CreateNativeShader(olive::ShaderCode(frag, vert));
|
QVariant shader =
|
||||||
|
renderer.CreateNativeShader(olive::ShaderCode(frag, vert));
|
||||||
ASSERT_FALSE(shader.isNull());
|
ASSERT_FALSE(shader.isNull());
|
||||||
|
|
||||||
olive::ShaderJob job;
|
olive::ShaderJob job;
|
||||||
@@ -294,7 +304,8 @@ TEST(DynamicRenderBackend, VulkanIterativeBlitPingPong)
|
|||||||
#else
|
#else
|
||||||
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
||||||
if (!renderer.Load()) {
|
if (!renderer.Load()) {
|
||||||
GTEST_SKIP() << "vulkan backend library could not be loaded in this environment";
|
GTEST_SKIP()
|
||||||
|
<< "vulkan backend library could not be loaded in this environment";
|
||||||
}
|
}
|
||||||
|
|
||||||
OakRenderBackendInfo info = {};
|
OakRenderBackendInfo info = {};
|
||||||
@@ -327,24 +338,25 @@ TEST(DynamicRenderBackend, VulkanIterativeBlitPingPong)
|
|||||||
ASSERT_FALSE(dst->IsDummy());
|
ASSERT_FALSE(dst->IsDummy());
|
||||||
|
|
||||||
// Shader that samples the iterative input and scales RGB by 0.5 each pass.
|
// Shader that samples the iterative input and scales RGB by 0.5 each pass.
|
||||||
const QString vert = QStringLiteral(
|
const QString vert =
|
||||||
"uniform mat4 ove_mvpmat;\n"
|
QStringLiteral("uniform mat4 ove_mvpmat;\n"
|
||||||
"in vec4 a_position;\n"
|
"in vec4 a_position;\n"
|
||||||
"in vec2 a_texcoord;\n"
|
"in vec2 a_texcoord;\n"
|
||||||
"out vec2 ove_texcoord;\n"
|
"out vec2 ove_texcoord;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" gl_Position = ove_mvpmat * a_position;\n"
|
" gl_Position = ove_mvpmat * a_position;\n"
|
||||||
" ove_texcoord = a_texcoord;\n"
|
" ove_texcoord = a_texcoord;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
const QString frag = QStringLiteral(
|
const QString frag =
|
||||||
"uniform sampler2D ove_maintex;\n"
|
QStringLiteral("uniform sampler2D ove_maintex;\n"
|
||||||
"in vec2 ove_texcoord;\n"
|
"in vec2 ove_texcoord;\n"
|
||||||
"out vec4 frag_color;\n"
|
"out vec4 frag_color;\n"
|
||||||
"void main() {\n"
|
"void main() {\n"
|
||||||
" vec4 c = texture(ove_maintex, ove_texcoord);\n"
|
" vec4 c = texture(ove_maintex, ove_texcoord);\n"
|
||||||
" frag_color = vec4(c.rgb * 0.5, c.a);\n"
|
" frag_color = vec4(c.rgb * 0.5, c.a);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
QVariant shader = renderer.CreateNativeShader(olive::ShaderCode(frag, vert));
|
QVariant shader =
|
||||||
|
renderer.CreateNativeShader(olive::ShaderCode(frag, vert));
|
||||||
ASSERT_FALSE(shader.isNull());
|
ASSERT_FALSE(shader.isNull());
|
||||||
|
|
||||||
olive::ShaderJob job;
|
olive::ShaderJob job;
|
||||||
@@ -378,7 +390,8 @@ TEST(DynamicRenderBackend, VulkanUploadDownloadThreeChannel)
|
|||||||
#else
|
#else
|
||||||
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
olive::DynamicRenderer renderer(QStringLiteral("vulkan"));
|
||||||
if (!renderer.Load()) {
|
if (!renderer.Load()) {
|
||||||
GTEST_SKIP() << "vulkan backend library could not be loaded in this environment";
|
GTEST_SKIP()
|
||||||
|
<< "vulkan backend library could not be loaded in this environment";
|
||||||
}
|
}
|
||||||
|
|
||||||
OakRenderBackendInfo info = {};
|
OakRenderBackendInfo info = {};
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ using namespace olive;
|
|||||||
|
|
||||||
TEST(FFmpegDecoderHW, H264_422_10bit_CPUFrame_IsNotBlack)
|
TEST(FFmpegDecoderHW, H264_422_10bit_CPUFrame_IsNotBlack)
|
||||||
{
|
{
|
||||||
const QString path = QStringLiteral("/home/mikesolar/Videos/dual_system_video.MOV");
|
const QString path =
|
||||||
|
QStringLiteral("/home/mikesolar/Videos/dual_system_video.MOV");
|
||||||
|
|
||||||
if (!QFileInfo::exists(path)) {
|
if (!QFileInfo::exists(path)) {
|
||||||
GTEST_SKIP() << "Test footage not available: " << path.toStdString();
|
GTEST_SKIP() << "Test footage not available: " << path.toStdString();
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
Q_INIT_RESOURCE(ocioconf);
|
Q_INIT_RESOURCE(ocioconf);
|
||||||
if (qEnvironmentVariableIsEmpty("OCIO")) {
|
if (qEnvironmentVariableIsEmpty("OCIO")) {
|
||||||
qputenv("OCIO", QFile::encodeName(
|
qputenv("OCIO",
|
||||||
QDir(QStringLiteral(OAK_TEST_SOURCE_DIR))
|
QFile::encodeName(QDir(QStringLiteral(OAK_TEST_SOURCE_DIR))
|
||||||
.filePath(QStringLiteral(
|
.filePath(QStringLiteral(
|
||||||
"app/render/ocioconf/config.ocio"))));
|
"app/render/ocioconf/config.ocio"))));
|
||||||
}
|
}
|
||||||
if (qEnvironmentVariableIsEmpty("QT_QPA_PLATFORM")) {
|
if (qEnvironmentVariableIsEmpty("QT_QPA_PLATFORM")) {
|
||||||
qputenv("QT_QPA_PLATFORM", "offscreen");
|
qputenv("QT_QPA_PLATFORM", "offscreen");
|
||||||
|
|||||||
@@ -5,24 +5,39 @@
|
|||||||
|
|
||||||
TEST(ModuleSmoke, ToolAddableObjectNames)
|
TEST(ModuleSmoke, ToolAddableObjectNames)
|
||||||
{
|
{
|
||||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableEmpty).isEmpty());
|
EXPECT_FALSE(
|
||||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableBars).isEmpty());
|
olive::Tool::GetAddableObjectName(olive::Tool::kAddableEmpty).isEmpty());
|
||||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableShape).isEmpty());
|
EXPECT_FALSE(
|
||||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableSolid).isEmpty());
|
olive::Tool::GetAddableObjectName(olive::Tool::kAddableBars).isEmpty());
|
||||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableTitle).isEmpty());
|
EXPECT_FALSE(
|
||||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableTone).isEmpty());
|
olive::Tool::GetAddableObjectName(olive::Tool::kAddableShape).isEmpty());
|
||||||
EXPECT_FALSE(olive::Tool::GetAddableObjectName(olive::Tool::kAddableSubtitle).isEmpty());
|
EXPECT_FALSE(
|
||||||
|
olive::Tool::GetAddableObjectName(olive::Tool::kAddableSolid).isEmpty());
|
||||||
|
EXPECT_FALSE(
|
||||||
|
olive::Tool::GetAddableObjectName(olive::Tool::kAddableTitle).isEmpty());
|
||||||
|
EXPECT_FALSE(
|
||||||
|
olive::Tool::GetAddableObjectName(olive::Tool::kAddableTone).isEmpty());
|
||||||
|
EXPECT_FALSE(
|
||||||
|
olive::Tool::GetAddableObjectName(olive::Tool::kAddableSubtitle)
|
||||||
|
.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ModuleSmoke, ToolAddableObjectIds)
|
TEST(ModuleSmoke, ToolAddableObjectIds)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableEmpty), QStringLiteral("empty"));
|
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableEmpty),
|
||||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableBars), QStringLiteral("bars"));
|
QStringLiteral("empty"));
|
||||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableShape), QStringLiteral("shape"));
|
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableBars),
|
||||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableSolid), QStringLiteral("solid"));
|
QStringLiteral("bars"));
|
||||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableTitle), QStringLiteral("title"));
|
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableShape),
|
||||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableTone), QStringLiteral("tone"));
|
QStringLiteral("shape"));
|
||||||
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableSubtitle), QStringLiteral("subtitle"));
|
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableSolid),
|
||||||
|
QStringLiteral("solid"));
|
||||||
|
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableTitle),
|
||||||
|
QStringLiteral("title"));
|
||||||
|
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableTone),
|
||||||
|
QStringLiteral("tone"));
|
||||||
|
EXPECT_EQ(olive::Tool::GetAddableObjectID(olive::Tool::kAddableSubtitle),
|
||||||
|
QStringLiteral("subtitle"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ModuleSmoke, HumanStringsSampleRate)
|
TEST(ModuleSmoke, HumanStringsSampleRate)
|
||||||
@@ -33,12 +48,16 @@ TEST(ModuleSmoke, HumanStringsSampleRate)
|
|||||||
|
|
||||||
TEST(ModuleSmoke, HumanStringsChannelLayout)
|
TEST(ModuleSmoke, HumanStringsChannelLayout)
|
||||||
{
|
{
|
||||||
EXPECT_FALSE(olive::HumanStrings::ChannelLayoutToString(AV_CH_LAYOUT_MONO).isEmpty());
|
EXPECT_FALSE(
|
||||||
EXPECT_FALSE(olive::HumanStrings::ChannelLayoutToString(AV_CH_LAYOUT_STEREO).isEmpty());
|
olive::HumanStrings::ChannelLayoutToString(AV_CH_LAYOUT_MONO).isEmpty());
|
||||||
|
EXPECT_FALSE(olive::HumanStrings::ChannelLayoutToString(AV_CH_LAYOUT_STEREO)
|
||||||
|
.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ModuleSmoke, HumanStringsFormat)
|
TEST(ModuleSmoke, HumanStringsFormat)
|
||||||
{
|
{
|
||||||
EXPECT_FALSE(olive::HumanStrings::FormatToString(olive::SampleFormat::U8).isEmpty());
|
EXPECT_FALSE(
|
||||||
EXPECT_FALSE(olive::HumanStrings::FormatToString(olive::SampleFormat::F32).isEmpty());
|
olive::HumanStrings::FormatToString(olive::SampleFormat::U8).isEmpty());
|
||||||
|
EXPECT_FALSE(
|
||||||
|
olive::HumanStrings::FormatToString(olive::SampleFormat::F32).isEmpty());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ TEST(NodeGlobals, ConstructedWithParams)
|
|||||||
audio_params.set_sample_rate(48000);
|
audio_params.set_sample_rate(48000);
|
||||||
audio_params.set_channel_layout(AV_CH_LAYOUT_STEREO);
|
audio_params.set_channel_layout(AV_CH_LAYOUT_STEREO);
|
||||||
|
|
||||||
olive::TimeRange time(olive::core::rational(1, 24), olive::core::rational(2, 24));
|
olive::TimeRange time(olive::core::rational(1, 24),
|
||||||
olive::NodeGlobals globals(video_params, audio_params, time, olive::LoopMode::kLoopModeLoop);
|
olive::core::rational(2, 24));
|
||||||
|
olive::NodeGlobals globals(video_params, audio_params, time,
|
||||||
|
olive::LoopMode::kLoopModeLoop);
|
||||||
|
|
||||||
EXPECT_EQ(globals.vparams().width(), 1920);
|
EXPECT_EQ(globals.vparams().width(), 1920);
|
||||||
EXPECT_EQ(globals.vparams().height(), 1080);
|
EXPECT_EQ(globals.vparams().height(), 1080);
|
||||||
|
|||||||
@@ -47,8 +47,9 @@ TEST(NodeProject, SettingsRoundTrip)
|
|||||||
{
|
{
|
||||||
olive::Project project;
|
olive::Project project;
|
||||||
|
|
||||||
project.SetSetting(olive::Project::kCacheLocationSettingKey,
|
project.SetSetting(
|
||||||
QString::number(olive::Project::kCacheStoreAlongsideProject));
|
olive::Project::kCacheLocationSettingKey,
|
||||||
|
QString::number(olive::Project::kCacheStoreAlongsideProject));
|
||||||
EXPECT_EQ(project.GetCacheLocationSetting(),
|
EXPECT_EQ(project.GetCacheLocationSetting(),
|
||||||
olive::Project::kCacheStoreAlongsideProject);
|
olive::Project::kCacheStoreAlongsideProject);
|
||||||
|
|
||||||
@@ -62,7 +63,8 @@ TEST(NodeProject, SettingsRoundTrip)
|
|||||||
EXPECT_EQ(project.GetDefaultInputColorSpace(), QStringLiteral("ACEScg"));
|
EXPECT_EQ(project.GetDefaultInputColorSpace(), QStringLiteral("ACEScg"));
|
||||||
|
|
||||||
project.SetColorReferenceSpace(QStringLiteral("ACES - ACEScg"));
|
project.SetColorReferenceSpace(QStringLiteral("ACES - ACEScg"));
|
||||||
EXPECT_EQ(project.GetColorReferenceSpace(), QStringLiteral("ACES - ACEScg"));
|
EXPECT_EQ(project.GetColorReferenceSpace(),
|
||||||
|
QStringLiteral("ACES - ACEScg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(NodeProject, InitializeCreatesRoot)
|
TEST(NodeProject, InitializeCreatesRoot)
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
#include "node/value.h"
|
#include "node/value.h"
|
||||||
#include "render/diskmanager.h"
|
#include "render/diskmanager.h"
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
class TestNode final : public olive::Node {
|
class TestNode final : public olive::Node {
|
||||||
public:
|
public:
|
||||||
TestNode()
|
TestNode()
|
||||||
@@ -55,7 +56,8 @@ public:
|
|||||||
|
|
||||||
TEST(NodeSerialization, SaveAndLoadInput)
|
TEST(NodeSerialization, SaveAndLoadInput)
|
||||||
{
|
{
|
||||||
const bool created_disk_manager = (olive::DiskManager::instance() == nullptr);
|
const bool created_disk_manager =
|
||||||
|
(olive::DiskManager::instance() == nullptr);
|
||||||
if (created_disk_manager) {
|
if (created_disk_manager) {
|
||||||
olive::DiskManager::CreateInstance();
|
olive::DiskManager::CreateInstance();
|
||||||
}
|
}
|
||||||
@@ -87,7 +89,9 @@ TEST(NodeSerialization, SaveAndLoadInput)
|
|||||||
EXPECT_EQ(loaded.GetLabel(), QStringLiteral("MyNode"));
|
EXPECT_EQ(loaded.GetLabel(), QStringLiteral("MyNode"));
|
||||||
EXPECT_EQ(loaded.GetOverrideColor(), 2);
|
EXPECT_EQ(loaded.GetOverrideColor(), 2);
|
||||||
EXPECT_DOUBLE_EQ(loaded.GetSplitStandardValue(QStringLiteral("Value"), -1)
|
EXPECT_DOUBLE_EQ(loaded.GetSplitStandardValue(QStringLiteral("Value"), -1)
|
||||||
.first().toDouble(), 3.5);
|
.first()
|
||||||
|
.toDouble(),
|
||||||
|
3.5);
|
||||||
|
|
||||||
if (created_disk_manager) {
|
if (created_disk_manager) {
|
||||||
olive::DiskManager::DestroyInstance();
|
olive::DiskManager::DestroyInstance();
|
||||||
|
|||||||
@@ -11,27 +11,27 @@ TEST(NodeValue, VectorRoundTrip)
|
|||||||
QVector2D v2(1.5f, -2.0f);
|
QVector2D v2(1.5f, -2.0f);
|
||||||
QString encoded = olive::NodeValue::ValueToString(
|
QString encoded = olive::NodeValue::ValueToString(
|
||||||
olive::NodeValue::kVec2, QVariant::fromValue(v2), false);
|
olive::NodeValue::kVec2, QVariant::fromValue(v2), false);
|
||||||
QVariant decoded = olive::NodeValue::StringToValue(
|
QVariant decoded = olive::NodeValue::StringToValue(olive::NodeValue::kVec2,
|
||||||
olive::NodeValue::kVec2, encoded, false);
|
encoded, false);
|
||||||
QVector2D v2_out = decoded.value<QVector2D>();
|
QVector2D v2_out = decoded.value<QVector2D>();
|
||||||
EXPECT_FLOAT_EQ(v2_out.x(), v2.x());
|
EXPECT_FLOAT_EQ(v2_out.x(), v2.x());
|
||||||
EXPECT_FLOAT_EQ(v2_out.y(), v2.y());
|
EXPECT_FLOAT_EQ(v2_out.y(), v2.y());
|
||||||
|
|
||||||
QVector3D v3(1.0f, 2.0f, 3.0f);
|
QVector3D v3(1.0f, 2.0f, 3.0f);
|
||||||
encoded = olive::NodeValue::ValueToString(
|
encoded = olive::NodeValue::ValueToString(olive::NodeValue::kVec3,
|
||||||
olive::NodeValue::kVec3, QVariant::fromValue(v3), false);
|
QVariant::fromValue(v3), false);
|
||||||
decoded = olive::NodeValue::StringToValue(
|
decoded = olive::NodeValue::StringToValue(olive::NodeValue::kVec3, encoded,
|
||||||
olive::NodeValue::kVec3, encoded, false);
|
false);
|
||||||
QVector3D v3_out = decoded.value<QVector3D>();
|
QVector3D v3_out = decoded.value<QVector3D>();
|
||||||
EXPECT_FLOAT_EQ(v3_out.x(), v3.x());
|
EXPECT_FLOAT_EQ(v3_out.x(), v3.x());
|
||||||
EXPECT_FLOAT_EQ(v3_out.y(), v3.y());
|
EXPECT_FLOAT_EQ(v3_out.y(), v3.y());
|
||||||
EXPECT_FLOAT_EQ(v3_out.z(), v3.z());
|
EXPECT_FLOAT_EQ(v3_out.z(), v3.z());
|
||||||
|
|
||||||
QVector4D v4(1.0f, 2.0f, 3.0f, 4.0f);
|
QVector4D v4(1.0f, 2.0f, 3.0f, 4.0f);
|
||||||
encoded = olive::NodeValue::ValueToString(
|
encoded = olive::NodeValue::ValueToString(olive::NodeValue::kVec4,
|
||||||
olive::NodeValue::kVec4, QVariant::fromValue(v4), false);
|
QVariant::fromValue(v4), false);
|
||||||
decoded = olive::NodeValue::StringToValue(
|
decoded = olive::NodeValue::StringToValue(olive::NodeValue::kVec4, encoded,
|
||||||
olive::NodeValue::kVec4, encoded, false);
|
false);
|
||||||
QVector4D v4_out = decoded.value<QVector4D>();
|
QVector4D v4_out = decoded.value<QVector4D>();
|
||||||
EXPECT_FLOAT_EQ(v4_out.x(), v4.x());
|
EXPECT_FLOAT_EQ(v4_out.x(), v4.x());
|
||||||
EXPECT_FLOAT_EQ(v4_out.y(), v4.y());
|
EXPECT_FLOAT_EQ(v4_out.y(), v4.y());
|
||||||
@@ -42,8 +42,8 @@ TEST(NodeValue, VectorRoundTrip)
|
|||||||
TEST(NodeValue, BinaryRoundTrip)
|
TEST(NodeValue, BinaryRoundTrip)
|
||||||
{
|
{
|
||||||
QByteArray data("OliveTest");
|
QByteArray data("OliveTest");
|
||||||
QString encoded = olive::NodeValue::ValueToString(
|
QString encoded =
|
||||||
olive::NodeValue::kBinary, data, false);
|
olive::NodeValue::ValueToString(olive::NodeValue::kBinary, data, false);
|
||||||
QVariant decoded = olive::NodeValue::StringToValue(
|
QVariant decoded = olive::NodeValue::StringToValue(
|
||||||
olive::NodeValue::kBinary, encoded, false);
|
olive::NodeValue::kBinary, encoded, false);
|
||||||
EXPECT_EQ(decoded.toByteArray(), data);
|
EXPECT_EQ(decoded.toByteArray(), data);
|
||||||
@@ -51,9 +51,12 @@ TEST(NodeValue, BinaryRoundTrip)
|
|||||||
|
|
||||||
TEST(NodeValue, TypeClassification)
|
TEST(NodeValue, TypeClassification)
|
||||||
{
|
{
|
||||||
EXPECT_TRUE(olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kFloat));
|
EXPECT_TRUE(
|
||||||
EXPECT_TRUE(olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kColor));
|
olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kFloat));
|
||||||
EXPECT_FALSE(olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kInt));
|
EXPECT_TRUE(
|
||||||
|
olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kColor));
|
||||||
|
EXPECT_FALSE(
|
||||||
|
olive::NodeValue::type_can_be_interpolated(olive::NodeValue::kInt));
|
||||||
|
|
||||||
EXPECT_TRUE(olive::NodeValue::type_is_numeric(olive::NodeValue::kInt));
|
EXPECT_TRUE(olive::NodeValue::type_is_numeric(olive::NodeValue::kInt));
|
||||||
EXPECT_TRUE(olive::NodeValue::type_is_numeric(olive::NodeValue::kFloat));
|
EXPECT_TRUE(olive::NodeValue::type_is_numeric(olive::NodeValue::kFloat));
|
||||||
@@ -70,7 +73,8 @@ TEST(NodeValue, TypeClassification)
|
|||||||
|
|
||||||
TEST(NodeValue, DataTypeNameRoundTrip)
|
TEST(NodeValue, DataTypeNameRoundTrip)
|
||||||
{
|
{
|
||||||
for (int i = olive::NodeValue::kNone; i < olive::NodeValue::kDataTypeCount; ++i) {
|
for (int i = olive::NodeValue::kNone; i < olive::NodeValue::kDataTypeCount;
|
||||||
|
++i) {
|
||||||
auto type = static_cast<olive::NodeValue::Type>(i);
|
auto type = static_cast<olive::NodeValue::Type>(i);
|
||||||
QString name = olive::NodeValue::GetDataTypeName(type);
|
QString name = olive::NodeValue::GetDataTypeName(type);
|
||||||
if (name.isEmpty()) {
|
if (name.isEmpty()) {
|
||||||
@@ -109,8 +113,10 @@ TEST(NodeValueTable, PushAndGet)
|
|||||||
TEST(NodeValueTable, TakeRemovesValue)
|
TEST(NodeValueTable, TakeRemovesValue)
|
||||||
{
|
{
|
||||||
olive::NodeValueTable table;
|
olive::NodeValueTable table;
|
||||||
table.Push(olive::NodeValue(olive::NodeValue::kInt, static_cast<int64_t>(1)));
|
table.Push(
|
||||||
table.Push(olive::NodeValue(olive::NodeValue::kInt, static_cast<int64_t>(2)));
|
olive::NodeValue(olive::NodeValue::kInt, static_cast<int64_t>(1)));
|
||||||
|
table.Push(
|
||||||
|
olive::NodeValue(olive::NodeValue::kInt, static_cast<int64_t>(2)));
|
||||||
|
|
||||||
olive::NodeValue taken = table.Take(olive::NodeValue::kInt);
|
olive::NodeValue taken = table.Take(olive::NodeValue::kInt);
|
||||||
EXPECT_EQ(taken.toInt(), 2);
|
EXPECT_EQ(taken.toInt(), 2);
|
||||||
@@ -120,7 +126,8 @@ TEST(NodeValueTable, TakeRemovesValue)
|
|||||||
TEST(NodeValueTable, ClearEmptiesTable)
|
TEST(NodeValueTable, ClearEmptiesTable)
|
||||||
{
|
{
|
||||||
olive::NodeValueTable table;
|
olive::NodeValueTable table;
|
||||||
table.Push(olive::NodeValue(olive::NodeValue::kText, QStringLiteral("hello")));
|
table.Push(
|
||||||
|
olive::NodeValue(olive::NodeValue::kText, QStringLiteral("hello")));
|
||||||
table.Clear();
|
table.Clear();
|
||||||
EXPECT_TRUE(table.isEmpty());
|
EXPECT_TRUE(table.isEmpty());
|
||||||
EXPECT_EQ(table.Count(), 0);
|
EXPECT_EQ(table.Count(), 0);
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ TEST(OpenGLRenderer, DownloadFromTextureWithoutCurrentContext)
|
|||||||
|
|
||||||
QOpenGLContext context;
|
QOpenGLContext context;
|
||||||
if (!context.create()) {
|
if (!context.create()) {
|
||||||
GTEST_SKIP() << "Skipping OpenGL test because no context can be created";
|
GTEST_SKIP()
|
||||||
|
<< "Skipping OpenGL test because no context can be created";
|
||||||
}
|
}
|
||||||
ASSERT_EQ(QOpenGLContext::currentContext(), nullptr);
|
ASSERT_EQ(QOpenGLContext::currentContext(), nullptr);
|
||||||
|
|
||||||
@@ -26,8 +27,8 @@ TEST(OpenGLRenderer, DownloadFromTextureWithoutCurrentContext)
|
|||||||
olive::VideoParams::kInterlaceNone, 1);
|
olive::VideoParams::kInterlaceNone, 1);
|
||||||
|
|
||||||
unsigned char buffer[4 * 4 * 4] = {};
|
unsigned char buffer[4 * 4 * 4] = {};
|
||||||
renderer.DownloadFromTexture(QVariant::fromValue<GLuint>(0), params,
|
renderer.DownloadFromTexture(QVariant::fromValue<GLuint>(0), params, buffer,
|
||||||
buffer, 4 * 4);
|
4 * 4);
|
||||||
|
|
||||||
EXPECT_EQ(QOpenGLContext::currentContext(), nullptr);
|
EXPECT_EQ(QOpenGLContext::currentContext(), nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,219 +20,236 @@ using namespace olive;
|
|||||||
using namespace olive::core;
|
using namespace olive::core;
|
||||||
|
|
||||||
// Test helper to create AVFrame with specific format
|
// Test helper to create AVFrame with specific format
|
||||||
static AVFramePtr CreateTestFrame(int width, int height, AVPixelFormat fmt, uint32_t fill_color = 0xFF804020) {
|
static AVFramePtr CreateTestFrame(int width, int height, AVPixelFormat fmt,
|
||||||
AVFramePtr frame = CreateAVFramePtr();
|
uint32_t fill_color = 0xFF804020)
|
||||||
frame->width = width;
|
{
|
||||||
frame->height = height;
|
AVFramePtr frame = CreateAVFramePtr();
|
||||||
frame->format = fmt;
|
frame->width = width;
|
||||||
|
frame->height = height;
|
||||||
if (av_frame_get_buffer(frame.get(), 0) < 0) {
|
frame->format = fmt;
|
||||||
return nullptr;
|
|
||||||
}
|
if (av_frame_get_buffer(frame.get(), 0) < 0) {
|
||||||
|
return nullptr;
|
||||||
if (av_frame_make_writable(frame.get()) < 0) {
|
}
|
||||||
return nullptr;
|
|
||||||
}
|
if (av_frame_make_writable(frame.get()) < 0) {
|
||||||
|
return nullptr;
|
||||||
// Fill with test pattern
|
}
|
||||||
uint8_t r = (fill_color >> 24) & 0xFF;
|
|
||||||
uint8_t g = (fill_color >> 16) & 0xFF;
|
// Fill with test pattern
|
||||||
uint8_t b = (fill_color >> 8) & 0xFF;
|
uint8_t r = (fill_color >> 24) & 0xFF;
|
||||||
uint8_t a = fill_color & 0xFF;
|
uint8_t g = (fill_color >> 16) & 0xFF;
|
||||||
|
uint8_t b = (fill_color >> 8) & 0xFF;
|
||||||
if (fmt == AV_PIX_FMT_RGBA) {
|
uint8_t a = fill_color & 0xFF;
|
||||||
for (int y = 0; y < height; ++y) {
|
|
||||||
uint8_t *row = frame->data[0] + y * frame->linesize[0];
|
if (fmt == AV_PIX_FMT_RGBA) {
|
||||||
for (int x = 0; x < width; ++x) {
|
for (int y = 0; y < height; ++y) {
|
||||||
row[x * 4 + 0] = r;
|
uint8_t *row = frame->data[0] + y * frame->linesize[0];
|
||||||
row[x * 4 + 1] = g;
|
for (int x = 0; x < width; ++x) {
|
||||||
row[x * 4 + 2] = b;
|
row[x * 4 + 0] = r;
|
||||||
row[x * 4 + 3] = a;
|
row[x * 4 + 1] = g;
|
||||||
}
|
row[x * 4 + 2] = b;
|
||||||
}
|
row[x * 4 + 3] = a;
|
||||||
} else if (fmt == AV_PIX_FMT_RGBA64) {
|
}
|
||||||
uint16_t r16 = (r << 8) | r;
|
}
|
||||||
uint16_t g16 = (g << 8) | g;
|
} else if (fmt == AV_PIX_FMT_RGBA64) {
|
||||||
uint16_t b16 = (b << 8) | b;
|
uint16_t r16 = (r << 8) | r;
|
||||||
uint16_t a16 = (a << 8) | a;
|
uint16_t g16 = (g << 8) | g;
|
||||||
for (int y = 0; y < height; ++y) {
|
uint16_t b16 = (b << 8) | b;
|
||||||
uint16_t *row = reinterpret_cast<uint16_t*>(frame->data[0] + y * frame->linesize[0]);
|
uint16_t a16 = (a << 8) | a;
|
||||||
for (int x = 0; x < width; ++x) {
|
for (int y = 0; y < height; ++y) {
|
||||||
row[x * 4 + 0] = r16;
|
uint16_t *row = reinterpret_cast<uint16_t *>(
|
||||||
row[x * 4 + 1] = g16;
|
frame->data[0] + y * frame->linesize[0]);
|
||||||
row[x * 4 + 2] = b16;
|
for (int x = 0; x < width; ++x) {
|
||||||
row[x * 4 + 3] = a16;
|
row[x * 4 + 0] = r16;
|
||||||
}
|
row[x * 4 + 1] = g16;
|
||||||
}
|
row[x * 4 + 2] = b16;
|
||||||
}
|
row[x * 4 + 3] = a16;
|
||||||
|
}
|
||||||
return frame;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test U8 to U16 conversion
|
// Test U8 to U16 conversion
|
||||||
TEST(FormatConversion, U8ToU16) {
|
TEST(FormatConversion, U8ToU16)
|
||||||
const int width = 10;
|
{
|
||||||
const int height = 10;
|
const int width = 10;
|
||||||
const uint32_t test_color = 0xFF804020; // ARGB: A=255, R=128, G=64, B=32
|
const int height = 10;
|
||||||
|
const uint32_t test_color = 0xFF804020; // ARGB: A=255, R=128, G=64, B=32
|
||||||
// Create U8 frame
|
|
||||||
AVFramePtr u8_frame = CreateTestFrame(width, height, AV_PIX_FMT_RGBA, test_color);
|
// Create U8 frame
|
||||||
ASSERT_NE(u8_frame, nullptr);
|
AVFramePtr u8_frame =
|
||||||
|
CreateTestFrame(width, height, AV_PIX_FMT_RGBA, test_color);
|
||||||
// Verify U8 values
|
ASSERT_NE(u8_frame, nullptr);
|
||||||
uint8_t *first_pixel_u8 = u8_frame->data[0];
|
|
||||||
EXPECT_EQ(first_pixel_u8[0], 0xFF); // R
|
// Verify U8 values
|
||||||
EXPECT_EQ(first_pixel_u8[1], 0x80); // G
|
uint8_t *first_pixel_u8 = u8_frame->data[0];
|
||||||
EXPECT_EQ(first_pixel_u8[2], 0x40); // B
|
EXPECT_EQ(first_pixel_u8[0], 0xFF); // R
|
||||||
EXPECT_EQ(first_pixel_u8[3], 0x20); // A
|
EXPECT_EQ(first_pixel_u8[1], 0x80); // G
|
||||||
|
EXPECT_EQ(first_pixel_u8[2], 0x40); // B
|
||||||
// Create U16 frame
|
EXPECT_EQ(first_pixel_u8[3], 0x20); // A
|
||||||
AVFramePtr u16_frame = CreateTestFrame(width, height, AV_PIX_FMT_RGBA64, test_color);
|
|
||||||
ASSERT_NE(u16_frame, nullptr);
|
// Create U16 frame
|
||||||
|
AVFramePtr u16_frame =
|
||||||
// Verify U16 values (should be U8 value repeated: 0xFF -> 0xFFFF, 0x80 -> 0x8080)
|
CreateTestFrame(width, height, AV_PIX_FMT_RGBA64, test_color);
|
||||||
uint16_t *first_pixel_u16 = reinterpret_cast<uint16_t*>(u16_frame->data[0]);
|
ASSERT_NE(u16_frame, nullptr);
|
||||||
EXPECT_EQ(first_pixel_u16[0], 0xFFFF); // R
|
|
||||||
EXPECT_EQ(first_pixel_u16[1], 0x8080); // G
|
// Verify U16 values (should be U8 value repeated: 0xFF -> 0xFFFF, 0x80 -> 0x8080)
|
||||||
EXPECT_EQ(first_pixel_u16[2], 0x4040); // B
|
uint16_t *first_pixel_u16 =
|
||||||
EXPECT_EQ(first_pixel_u16[3], 0x2020); // A
|
reinterpret_cast<uint16_t *>(u16_frame->data[0]);
|
||||||
|
EXPECT_EQ(first_pixel_u16[0], 0xFFFF); // R
|
||||||
|
EXPECT_EQ(first_pixel_u16[1], 0x8080); // G
|
||||||
|
EXPECT_EQ(first_pixel_u16[2], 0x4040); // B
|
||||||
|
EXPECT_EQ(first_pixel_u16[3], 0x2020); // A
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test FFmpeg sws_scale for U16 to U8 conversion
|
// Test FFmpeg sws_scale for U16 to U8 conversion
|
||||||
TEST(FormatConversion, FFmpegU16ToU8) {
|
TEST(FormatConversion, FFmpegU16ToU8)
|
||||||
const int width = 10;
|
{
|
||||||
const int height = 10;
|
const int width = 10;
|
||||||
const uint32_t test_color = 0xFF804020;
|
const int height = 10;
|
||||||
|
const uint32_t test_color = 0xFF804020;
|
||||||
// Create U16 frame
|
|
||||||
AVFramePtr u16_frame = CreateTestFrame(width, height, AV_PIX_FMT_RGBA64, test_color);
|
// Create U16 frame
|
||||||
ASSERT_NE(u16_frame, nullptr);
|
AVFramePtr u16_frame =
|
||||||
|
CreateTestFrame(width, height, AV_PIX_FMT_RGBA64, test_color);
|
||||||
// Create destination U8 frame
|
ASSERT_NE(u16_frame, nullptr);
|
||||||
AVFramePtr u8_frame = CreateTestFrame(width, height, AV_PIX_FMT_RGBA, 0);
|
|
||||||
ASSERT_NE(u8_frame, nullptr);
|
// Create destination U8 frame
|
||||||
|
AVFramePtr u8_frame = CreateTestFrame(width, height, AV_PIX_FMT_RGBA, 0);
|
||||||
// Use sws_scale to convert
|
ASSERT_NE(u8_frame, nullptr);
|
||||||
SwsContext *sws_ctx = sws_getContext(
|
|
||||||
width, height, AV_PIX_FMT_RGBA64,
|
// Use sws_scale to convert
|
||||||
width, height, AV_PIX_FMT_RGBA,
|
SwsContext *sws_ctx = sws_getContext(width, height, AV_PIX_FMT_RGBA64,
|
||||||
SWS_POINT, nullptr, nullptr, nullptr);
|
width, height, AV_PIX_FMT_RGBA,
|
||||||
ASSERT_NE(sws_ctx, nullptr);
|
SWS_POINT, nullptr, nullptr, nullptr);
|
||||||
|
ASSERT_NE(sws_ctx, nullptr);
|
||||||
sws_scale(sws_ctx, u16_frame->data, u16_frame->linesize, 0, height,
|
|
||||||
u8_frame->data, u8_frame->linesize);
|
sws_scale(sws_ctx, u16_frame->data, u16_frame->linesize, 0, height,
|
||||||
sws_freeContext(sws_ctx);
|
u8_frame->data, u8_frame->linesize);
|
||||||
|
sws_freeContext(sws_ctx);
|
||||||
// Verify conversion (U16 0xFFFF -> U8 0xFF, 0x8080 -> ~0x80, etc.)
|
|
||||||
// Note: FFmpeg sws_scale has rounding offset, so values may be off by 1
|
// Verify conversion (U16 0xFFFF -> U8 0xFF, 0x8080 -> ~0x80, etc.)
|
||||||
uint8_t *first_pixel = u8_frame->data[0];
|
// Note: FFmpeg sws_scale has rounding offset, so values may be off by 1
|
||||||
EXPECT_NEAR(first_pixel[0], 0xFF, 1); // R (255 vs 255)
|
uint8_t *first_pixel = u8_frame->data[0];
|
||||||
EXPECT_NEAR(first_pixel[1], 0x80, 1); // G (128 vs 129)
|
EXPECT_NEAR(first_pixel[0], 0xFF, 1); // R (255 vs 255)
|
||||||
EXPECT_NEAR(first_pixel[2], 0x40, 1); // B (64 vs 64)
|
EXPECT_NEAR(first_pixel[1], 0x80, 1); // G (128 vs 129)
|
||||||
EXPECT_NEAR(first_pixel[3], 0x20, 1); // A (32 vs 32)
|
EXPECT_NEAR(first_pixel[2], 0x40, 1); // B (64 vs 64)
|
||||||
|
EXPECT_NEAR(first_pixel[3], 0x20, 1); // A (32 vs 32)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test VideoParams to AVPixelFormat mapping
|
// Test VideoParams to AVPixelFormat mapping
|
||||||
TEST(FormatConversion, VideoParamsToAVFormat) {
|
TEST(FormatConversion, VideoParamsToAVFormat)
|
||||||
// U8 RGBA
|
{
|
||||||
VideoParams u8_rgba(320, 240, PixelFormat::U8, 4);
|
// U8 RGBA
|
||||||
AVPixelFormat fmt_u8_rgba = FFmpegUtils::GetFFmpegPixelFormat(u8_rgba.format(), u8_rgba.channel_count());
|
VideoParams u8_rgba(320, 240, PixelFormat::U8, 4);
|
||||||
EXPECT_EQ(fmt_u8_rgba, AV_PIX_FMT_RGBA);
|
AVPixelFormat fmt_u8_rgba = FFmpegUtils::GetFFmpegPixelFormat(
|
||||||
|
u8_rgba.format(), u8_rgba.channel_count());
|
||||||
// U16 RGBA
|
EXPECT_EQ(fmt_u8_rgba, AV_PIX_FMT_RGBA);
|
||||||
VideoParams u16_rgba(320, 240, PixelFormat::U16, 4);
|
|
||||||
AVPixelFormat fmt_u16_rgba = FFmpegUtils::GetFFmpegPixelFormat(u16_rgba.format(), u16_rgba.channel_count());
|
// U16 RGBA
|
||||||
EXPECT_EQ(fmt_u16_rgba, AV_PIX_FMT_RGBA64);
|
VideoParams u16_rgba(320, 240, PixelFormat::U16, 4);
|
||||||
|
AVPixelFormat fmt_u16_rgba = FFmpegUtils::GetFFmpegPixelFormat(
|
||||||
// U8 RGB
|
u16_rgba.format(), u16_rgba.channel_count());
|
||||||
VideoParams u8_rgb(320, 240, PixelFormat::U8, 3);
|
EXPECT_EQ(fmt_u16_rgba, AV_PIX_FMT_RGBA64);
|
||||||
AVPixelFormat fmt_u8_rgb = FFmpegUtils::GetFFmpegPixelFormat(u8_rgb.format(), u8_rgb.channel_count());
|
|
||||||
EXPECT_EQ(fmt_u8_rgb, AV_PIX_FMT_RGB24);
|
// U8 RGB
|
||||||
|
VideoParams u8_rgb(320, 240, PixelFormat::U8, 3);
|
||||||
// U16 RGB
|
AVPixelFormat fmt_u8_rgb = FFmpegUtils::GetFFmpegPixelFormat(
|
||||||
VideoParams u16_rgb(320, 240, PixelFormat::U16, 3);
|
u8_rgb.format(), u8_rgb.channel_count());
|
||||||
AVPixelFormat fmt_u16_rgb = FFmpegUtils::GetFFmpegPixelFormat(u16_rgb.format(), u16_rgb.channel_count());
|
EXPECT_EQ(fmt_u8_rgb, AV_PIX_FMT_RGB24);
|
||||||
EXPECT_EQ(fmt_u16_rgb, AV_PIX_FMT_RGB48);
|
|
||||||
|
// U16 RGB
|
||||||
|
VideoParams u16_rgb(320, 240, PixelFormat::U16, 3);
|
||||||
|
AVPixelFormat fmt_u16_rgb = FFmpegUtils::GetFFmpegPixelFormat(
|
||||||
|
u16_rgb.format(), u16_rgb.channel_count());
|
||||||
|
EXPECT_EQ(fmt_u16_rgb, AV_PIX_FMT_RGB48);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test row bytes calculation
|
// Test row bytes calculation
|
||||||
TEST(FormatConversion, RowBytes) {
|
TEST(FormatConversion, RowBytes)
|
||||||
const int width = 320;
|
{
|
||||||
|
const int width = 320;
|
||||||
// U8 RGBA: 4 bytes per pixel
|
|
||||||
EXPECT_EQ(width * 4, 1280);
|
// U8 RGBA: 4 bytes per pixel
|
||||||
|
EXPECT_EQ(width * 4, 1280);
|
||||||
// U16 RGBA: 8 bytes per pixel
|
|
||||||
EXPECT_EQ(width * 8, 2560);
|
// U16 RGBA: 8 bytes per pixel
|
||||||
|
EXPECT_EQ(width * 8, 2560);
|
||||||
// U8 RGB: 3 bytes per pixel
|
|
||||||
EXPECT_EQ(width * 3, 960);
|
// U8 RGB: 3 bytes per pixel
|
||||||
|
EXPECT_EQ(width * 3, 960);
|
||||||
// U16 RGB: 6 bytes per pixel
|
|
||||||
EXPECT_EQ(width * 6, 1920);
|
// U16 RGB: 6 bytes per pixel
|
||||||
|
EXPECT_EQ(width * 6, 1920);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that linesize may differ from width * bpp due to alignment
|
// Test that linesize may differ from width * bpp due to alignment
|
||||||
TEST(FormatConversion, LinesizeAlignment) {
|
TEST(FormatConversion, LinesizeAlignment)
|
||||||
const int width = 10;
|
{
|
||||||
const int height = 10;
|
const int width = 10;
|
||||||
|
const int height = 10;
|
||||||
AVFramePtr frame = CreateAVFramePtr();
|
|
||||||
frame->width = width;
|
AVFramePtr frame = CreateAVFramePtr();
|
||||||
frame->height = height;
|
frame->width = width;
|
||||||
frame->format = AV_PIX_FMT_RGBA;
|
frame->height = height;
|
||||||
|
frame->format = AV_PIX_FMT_RGBA;
|
||||||
ASSERT_EQ(av_frame_get_buffer(frame.get(), 0), 0);
|
|
||||||
|
ASSERT_EQ(av_frame_get_buffer(frame.get(), 0), 0);
|
||||||
// linesize[0] should be at least width * 4
|
|
||||||
EXPECT_GE(frame->linesize[0], width * 4);
|
// linesize[0] should be at least width * 4
|
||||||
|
EXPECT_GE(frame->linesize[0], width * 4);
|
||||||
// linesize may be larger due to alignment (typically 32-byte aligned)
|
|
||||||
qDebug() << "Width:" << width << "Expected bytes:" << width * 4
|
// linesize may be larger due to alignment (typically 32-byte aligned)
|
||||||
<< "Actual linesize:" << frame->linesize[0];
|
qDebug() << "Width:" << width << "Expected bytes:" << width * 4
|
||||||
|
<< "Actual linesize:" << frame->linesize[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test loading actual image file
|
// Test loading actual image file
|
||||||
TEST(FormatConversion, LoadImageFile) {
|
TEST(FormatConversion, LoadImageFile)
|
||||||
// Load the test image
|
{
|
||||||
QString img_path = QStringLiteral("%1/../tests/img.png").arg(QDir::currentPath());
|
// Load the test image
|
||||||
|
QString img_path =
|
||||||
AVFramePtr frame = CreateAVFramePtr();
|
QStringLiteral("%1/../tests/img.png").arg(QDir::currentPath());
|
||||||
// Just create a simple test frame instead of loading an image
|
|
||||||
frame->width = 1920;
|
AVFramePtr frame = CreateAVFramePtr();
|
||||||
frame->height = 1080;
|
// Just create a simple test frame instead of loading an image
|
||||||
frame->format = AV_PIX_FMT_RGBA;
|
frame->width = 1920;
|
||||||
if (av_frame_get_buffer(frame.get(), 0) < 0) {
|
frame->height = 1080;
|
||||||
return;
|
frame->format = AV_PIX_FMT_RGBA;
|
||||||
}
|
if (av_frame_get_buffer(frame.get(), 0) < 0) {
|
||||||
// Fill with orange color (sunrise sky)
|
return;
|
||||||
for (int y = 0; y < frame->height; ++y) {
|
}
|
||||||
uint8_t *row = frame->data[0] + y * frame->linesize[0];
|
// Fill with orange color (sunrise sky)
|
||||||
uint8_t r = 255;
|
for (int y = 0; y < frame->height; ++y) {
|
||||||
uint8_t g = 128 + (y * 127) / frame->height; // Gradient from 128 to 255
|
uint8_t *row = frame->data[0] + y * frame->linesize[0];
|
||||||
uint8_t b = 64;
|
uint8_t r = 255;
|
||||||
uint8_t a = 255;
|
uint8_t g = 128 + (y * 127) / frame->height; // Gradient from 128 to 255
|
||||||
for (int x = 0; x < frame->width; ++x) {
|
uint8_t b = 64;
|
||||||
row[x * 4 + 0] = r;
|
uint8_t a = 255;
|
||||||
row[x * 4 + 1] = g;
|
for (int x = 0; x < frame->width; ++x) {
|
||||||
row[x * 4 + 2] = b;
|
row[x * 4 + 0] = r;
|
||||||
row[x * 4 + 3] = a;
|
row[x * 4 + 1] = g;
|
||||||
}
|
row[x * 4 + 2] = b;
|
||||||
}
|
row[x * 4 + 3] = a;
|
||||||
ASSERT_NE(frame->data[0], nullptr) << "Failed to create test frame";
|
}
|
||||||
|
}
|
||||||
EXPECT_EQ(frame->width, 1920);
|
ASSERT_NE(frame->data[0], nullptr) << "Failed to create test frame";
|
||||||
EXPECT_EQ(frame->height, 1080);
|
|
||||||
|
EXPECT_EQ(frame->width, 1920);
|
||||||
// Check first pixel (top-left corner of the sunrise image)
|
EXPECT_EQ(frame->height, 1080);
|
||||||
// Based on the image, it should have some orange/pink color in the sky area
|
|
||||||
uint8_t *first_pixel = frame->data[0];
|
// Check first pixel (top-left corner of the sunrise image)
|
||||||
qDebug() << "First pixel RGBA:" << first_pixel[0] << first_pixel[1]
|
// Based on the image, it should have some orange/pink color in the sky area
|
||||||
<< first_pixel[2] << first_pixel[3];
|
uint8_t *first_pixel = frame->data[0];
|
||||||
|
qDebug() << "First pixel RGBA:" << first_pixel[0] << first_pixel[1]
|
||||||
// The image is RGB, so we expect 3 channels
|
<< first_pixel[2] << first_pixel[3];
|
||||||
// First pixel should be non-black (sky area)
|
|
||||||
EXPECT_GT(first_pixel[0] + first_pixel[1] + first_pixel[2], 0);
|
// The image is RGB, so we expect 3 channels
|
||||||
|
// First pixel should be non-black (sky area)
|
||||||
|
EXPECT_GT(first_pixel[0] + first_pixel[1] + first_pixel[2], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests are registered with gtest, no main needed
|
// Tests are registered with gtest, no main needed
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ extern "C" {
|
|||||||
#include "render/texture.h"
|
#include "render/texture.h"
|
||||||
#include "render/videoparams.h"
|
#include "render/videoparams.h"
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
olive::TexturePtr CreateSolidTexture(const olive::VideoParams ¶ms)
|
olive::TexturePtr CreateSolidTexture(const olive::VideoParams ¶ms)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,22 +27,26 @@ extern "C" {
|
|||||||
#include "render/texture.h"
|
#include "render/texture.h"
|
||||||
#include "render/videoparams.h"
|
#include "render/videoparams.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive
|
||||||
namespace plugin {
|
{
|
||||||
namespace test {
|
namespace plugin
|
||||||
|
{
|
||||||
|
namespace test
|
||||||
|
{
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
// Helper to create a test texture with solid color
|
// Helper to create a test texture with solid color
|
||||||
// For U8: fill_value is 0-255
|
// For U8: fill_value is 0-255
|
||||||
// For U16: fill_value is 0-65535
|
// For U16: fill_value is 0-65535
|
||||||
// For Float: fill_value is 0.0-1.0 mapped to bytes
|
// For Float: fill_value is 0.0-1.0 mapped to bytes
|
||||||
template<typename T>
|
template <typename T>
|
||||||
TexturePtr CreateSolidTextureT(const VideoParams ¶ms, T fill_value)
|
TexturePtr CreateSolidTextureT(const VideoParams ¶ms, T fill_value)
|
||||||
{
|
{
|
||||||
AVFramePtr frame = CreateAVFramePtr();
|
AVFramePtr frame = CreateAVFramePtr();
|
||||||
frame->format = FFmpegUtils::GetFFmpegPixelFormat(
|
frame->format = FFmpegUtils::GetFFmpegPixelFormat(params.format(),
|
||||||
params.format(), params.channel_count());
|
params.channel_count());
|
||||||
frame->width = params.width();
|
frame->width = params.width();
|
||||||
frame->height = params.height();
|
frame->height = params.height();
|
||||||
if (frame->format == AV_PIX_FMT_NONE) {
|
if (frame->format == AV_PIX_FMT_NONE) {
|
||||||
@@ -57,7 +61,7 @@ TexturePtr CreateSolidTextureT(const VideoParams ¶ms, T fill_value)
|
|||||||
|
|
||||||
const int linesize = frame->linesize[0];
|
const int linesize = frame->linesize[0];
|
||||||
for (int y = 0; y < frame->height; ++y) {
|
for (int y = 0; y < frame->height; ++y) {
|
||||||
T *row = reinterpret_cast<T*>(frame->data[0] + y * linesize);
|
T *row = reinterpret_cast<T *>(frame->data[0] + y * linesize);
|
||||||
for (int x = 0; x < frame->width * params.channel_count(); ++x) {
|
for (int x = 0; x < frame->width * params.channel_count(); ++x) {
|
||||||
row[x] = fill_value;
|
row[x] = fill_value;
|
||||||
}
|
}
|
||||||
@@ -68,17 +72,21 @@ TexturePtr CreateSolidTextureT(const VideoParams ¶ms, T fill_value)
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturePtr CreateSolidTexture(const VideoParams ¶ms, uint32_t fill_value = 0x7f)
|
TexturePtr CreateSolidTexture(const VideoParams ¶ms,
|
||||||
|
uint32_t fill_value = 0x7f)
|
||||||
{
|
{
|
||||||
// Choose type based on pixel format
|
// Choose type based on pixel format
|
||||||
switch (params.format()) {
|
switch (params.format()) {
|
||||||
case core::PixelFormat::U8:
|
case core::PixelFormat::U8:
|
||||||
return CreateSolidTextureT<uint8_t>(params, static_cast<uint8_t>(fill_value));
|
return CreateSolidTextureT<uint8_t>(params,
|
||||||
|
static_cast<uint8_t>(fill_value));
|
||||||
case core::PixelFormat::U16:
|
case core::PixelFormat::U16:
|
||||||
return CreateSolidTextureT<uint16_t>(params, static_cast<uint16_t>(fill_value));
|
return CreateSolidTextureT<uint16_t>(params,
|
||||||
|
static_cast<uint16_t>(fill_value));
|
||||||
case core::PixelFormat::F16:
|
case core::PixelFormat::F16:
|
||||||
case core::PixelFormat::F32:
|
case core::PixelFormat::F32:
|
||||||
return CreateSolidTextureT<float>(params, static_cast<float>(fill_value) / 255.0f);
|
return CreateSolidTextureT<float>(
|
||||||
|
params, static_cast<float>(fill_value) / 255.0f);
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -87,12 +95,12 @@ TexturePtr CreateSolidTexture(const VideoParams ¶ms, uint32_t fill_value = 0
|
|||||||
// Helper to create a gradient texture
|
// Helper to create a gradient texture
|
||||||
// For U8: gradient is 0-255 per byte
|
// For U8: gradient is 0-255 per byte
|
||||||
// For Float: gradient is 0.0-1.0 per component
|
// For Float: gradient is 0.0-1.0 per component
|
||||||
template<typename T>
|
template <typename T>
|
||||||
TexturePtr CreateGradientTextureT(const VideoParams ¶ms, float scale)
|
TexturePtr CreateGradientTextureT(const VideoParams ¶ms, float scale)
|
||||||
{
|
{
|
||||||
AVFramePtr frame = CreateAVFramePtr();
|
AVFramePtr frame = CreateAVFramePtr();
|
||||||
frame->format = FFmpegUtils::GetFFmpegPixelFormat(
|
frame->format = FFmpegUtils::GetFFmpegPixelFormat(params.format(),
|
||||||
params.format(), params.channel_count());
|
params.channel_count());
|
||||||
frame->width = params.width();
|
frame->width = params.width();
|
||||||
frame->height = params.height();
|
frame->height = params.height();
|
||||||
if (frame->format == AV_PIX_FMT_NONE) {
|
if (frame->format == AV_PIX_FMT_NONE) {
|
||||||
@@ -107,7 +115,7 @@ TexturePtr CreateGradientTextureT(const VideoParams ¶ms, float scale)
|
|||||||
|
|
||||||
const int linesize = frame->linesize[0];
|
const int linesize = frame->linesize[0];
|
||||||
for (int y = 0; y < frame->height; ++y) {
|
for (int y = 0; y < frame->height; ++y) {
|
||||||
T *row = reinterpret_cast<T*>(frame->data[0] + y * linesize);
|
T *row = reinterpret_cast<T *>(frame->data[0] + y * linesize);
|
||||||
T value = static_cast<T>((y * scale) / frame->height);
|
T value = static_cast<T>((y * scale) / frame->height);
|
||||||
for (int x = 0; x < frame->width * params.channel_count(); ++x) {
|
for (int x = 0; x < frame->width * params.channel_count(); ++x) {
|
||||||
row[x] = value;
|
row[x] = value;
|
||||||
@@ -135,17 +143,16 @@ TexturePtr CreateGradientTexture(const VideoParams ¶ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to find and render a plugin
|
// Helper function to find and render a plugin
|
||||||
bool RenderPlugin(const std::string &plugin_id,
|
bool RenderPlugin(const std::string &plugin_id, const VideoParams ¶ms,
|
||||||
const VideoParams ¶ms,
|
const NodeValueRow &inputs, bool verbose = false)
|
||||||
const NodeValueRow &inputs,
|
|
||||||
bool verbose = false)
|
|
||||||
{
|
{
|
||||||
auto *cache = OFX::Host::PluginCache::getPluginCache();
|
auto *cache = OFX::Host::PluginCache::getPluginCache();
|
||||||
if (!cache) {
|
if (!cache) {
|
||||||
if (verbose) std::cerr << "Plugin cache not available" << std::endl;
|
if (verbose)
|
||||||
|
std::cerr << "Plugin cache not available" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
OFX::Host::Plugin *found = nullptr;
|
OFX::Host::Plugin *found = nullptr;
|
||||||
for (auto *plug : cache->getPlugins()) {
|
for (auto *plug : cache->getPlugins()) {
|
||||||
if (plug && plug->getIdentifier() == plugin_id) {
|
if (plug && plug->getIdentifier() == plugin_id) {
|
||||||
@@ -153,66 +160,72 @@ bool RenderPlugin(const std::string &plugin_id,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
if (verbose) std::cerr << "Plugin not found: " << plugin_id << std::endl;
|
if (verbose)
|
||||||
|
std::cerr << "Plugin not found: " << plugin_id << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *image_effect = dynamic_cast<OFX::Host::ImageEffect::ImageEffectPlugin *>(found);
|
auto *image_effect =
|
||||||
|
dynamic_cast<OFX::Host::ImageEffect::ImageEffectPlugin *>(found);
|
||||||
if (!image_effect) {
|
if (!image_effect) {
|
||||||
if (verbose) std::cerr << "Not an image effect plugin" << std::endl;
|
if (verbose)
|
||||||
|
std::cerr << "Not an image effect plugin" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &contexts = image_effect->getContexts();
|
const auto &contexts = image_effect->getContexts();
|
||||||
std::string context = kOfxImageEffectContextFilter;
|
std::string context = kOfxImageEffectContextFilter;
|
||||||
if (!contexts.empty() &&
|
if (!contexts.empty() &&
|
||||||
contexts.find(kOfxImageEffectContextFilter) == contexts.end()) {
|
contexts.find(kOfxImageEffectContextFilter) == contexts.end()) {
|
||||||
context = *contexts.begin();
|
context = *contexts.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
OFX::Host::ImageEffect::Instance *instance =
|
OFX::Host::ImageEffect::Instance *instance =
|
||||||
image_effect->createInstance(context, nullptr);
|
image_effect->createInstance(context, nullptr);
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
if (verbose) std::cerr << "Failed to create instance" << std::endl;
|
if (verbose)
|
||||||
|
std::cerr << "Failed to create instance" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *olive_instance = dynamic_cast<OlivePluginInstance *>(instance);
|
auto *olive_instance = dynamic_cast<OlivePluginInstance *>(instance);
|
||||||
if (!olive_instance) {
|
if (!olive_instance) {
|
||||||
if (verbose) std::cerr << "Not an OlivePluginInstance" << std::endl;
|
if (verbose)
|
||||||
|
std::cerr << "Not an OlivePluginInstance" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
olive_instance->setVideoParam(params);
|
olive_instance->setVideoParam(params);
|
||||||
|
|
||||||
PluginJob job(instance, nullptr, inputs);
|
PluginJob job(instance, nullptr, inputs);
|
||||||
TexturePtr output = std::make_shared<Texture>(params);
|
TexturePtr output = std::make_shared<Texture>(params);
|
||||||
|
|
||||||
PluginRenderer renderer(nullptr);
|
PluginRenderer renderer(nullptr);
|
||||||
renderer.RenderPlugin(nullptr, job, output, params, true, false);
|
renderer.RenderPlugin(nullptr, job, output, params, true, false);
|
||||||
|
|
||||||
bool has_frame = output->frame() != nullptr;
|
bool has_frame = output->frame() != nullptr;
|
||||||
if (!has_frame && verbose) {
|
if (!has_frame && verbose) {
|
||||||
std::cerr << "Render produced no output frame" << std::endl;
|
std::cerr << "Render produced no output frame" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return has_frame;
|
return has_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip check function
|
// Skip check function
|
||||||
bool ShouldSkipTest() {
|
bool ShouldSkipTest()
|
||||||
|
{
|
||||||
const char *itest = std::getenv("OAK_OFX_ITEST");
|
const char *itest = std::getenv("OAK_OFX_ITEST");
|
||||||
if (!itest || std::string(itest) != "1") {
|
if (!itest || std::string(itest) != "1") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *path = std::getenv("OAK_OFX_PLUGIN_PATH");
|
const char *path = std::getenv("OAK_OFX_PLUGIN_PATH");
|
||||||
if (!path || std::string(path).empty()) {
|
if (!path || std::string(path).empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool plugins_loaded = false;
|
static bool plugins_loaded = false;
|
||||||
if (!plugins_loaded) {
|
if (!plugins_loaded) {
|
||||||
QString raw = QString::fromUtf8(path);
|
QString raw = QString::fromUtf8(path);
|
||||||
@@ -223,7 +236,7 @@ bool ShouldSkipTest() {
|
|||||||
}
|
}
|
||||||
plugins_loaded = true;
|
plugins_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,16 +251,16 @@ TEST(PluginMisc, MirrorHorizontal)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mirror plugin typically works with 8-bit
|
// Mirror plugin typically works with 8-bit
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateGradientTexture(params);
|
TexturePtr input = CreateGradientTexture(params);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.Mirror", params, row, true);
|
bool result = RenderPlugin("net.sf.openfx.Mirror", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Mirror plugin should produce output";
|
EXPECT_TRUE(result) << "Mirror plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -261,16 +274,17 @@ TEST(PluginMisc, TransformTranslate)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.TransformPlugin", params, row, true);
|
bool result =
|
||||||
|
RenderPlugin("net.sf.openfx.TransformPlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Transform plugin should produce output";
|
EXPECT_TRUE(result) << "Transform plugin should produce output";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,16 +297,17 @@ TEST(PluginMisc, ColorCorrect)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.ColorCorrectPlugin", params, row, true);
|
bool result =
|
||||||
|
RenderPlugin("net.sf.openfx.ColorCorrectPlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "ColorCorrect plugin should produce output";
|
EXPECT_TRUE(result) << "ColorCorrect plugin should produce output";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,16 +316,17 @@ TEST(PluginMisc, Saturation)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.SaturationPlugin", params, row, true);
|
bool result =
|
||||||
|
RenderPlugin("net.sf.openfx.SaturationPlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Saturation plugin should produce output";
|
EXPECT_TRUE(result) << "Saturation plugin should produce output";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,15 +339,15 @@ TEST(PluginMisc, GaussianBlur)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
// Use CImgBlur from the available plugin list
|
// Use CImgBlur from the available plugin list
|
||||||
bool result = RenderPlugin("net.sf.cimg.CImgBlur", params, row, true);
|
bool result = RenderPlugin("net.sf.cimg.CImgBlur", params, row, true);
|
||||||
EXPECT_TRUE(result) << "GaussianBlur plugin should produce output";
|
EXPECT_TRUE(result) << "GaussianBlur plugin should produce output";
|
||||||
@@ -346,15 +362,15 @@ TEST(PluginMisc, Crop)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.CropPlugin", params, row, true);
|
bool result = RenderPlugin("net.sf.openfx.CropPlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Crop plugin should produce output";
|
EXPECT_TRUE(result) << "Crop plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -364,15 +380,15 @@ TEST(PluginMisc, Grade)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.GradePlugin", params, row, true);
|
bool result = RenderPlugin("net.sf.openfx.GradePlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Grade plugin should produce output";
|
EXPECT_TRUE(result) << "Grade plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -386,16 +402,17 @@ TEST(PluginMisc, NonExistentPlugin)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.NonExistentPlugin", params, row, true);
|
bool result =
|
||||||
|
RenderPlugin("net.sf.openfx.NonExistentPlugin", params, row, true);
|
||||||
EXPECT_FALSE(result) << "Non-existent plugin should fail gracefully";
|
EXPECT_FALSE(result) << "Non-existent plugin should fail gracefully";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,15 +425,15 @@ TEST(PluginMisc, CImgSharpen)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.cimg.CImgSharpen", params, row, true);
|
bool result = RenderPlugin("net.sf.cimg.CImgSharpen", params, row, true);
|
||||||
EXPECT_TRUE(result) << "CImgSharpen plugin should produce output";
|
EXPECT_TRUE(result) << "CImgSharpen plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -426,15 +443,15 @@ TEST(PluginMisc, CImgDenoise)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.cimg.CImgDenoise", params, row, true);
|
bool result = RenderPlugin("net.sf.cimg.CImgDenoise", params, row, true);
|
||||||
EXPECT_TRUE(result) << "CImgDenoise plugin should produce output";
|
EXPECT_TRUE(result) << "CImgDenoise plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -444,15 +461,15 @@ TEST(PluginMisc, CImgBilateral)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.cimg.CImgBilateral", params, row, true);
|
bool result = RenderPlugin("net.sf.cimg.CImgBilateral", params, row, true);
|
||||||
EXPECT_TRUE(result) << "CImgBilateral plugin should produce output";
|
EXPECT_TRUE(result) << "CImgBilateral plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -466,17 +483,16 @@ TEST(PluginMisc, MergeOver)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
row.insert(QStringLiteral("Bg"),
|
row.insert(QStringLiteral("Bg"), NodeValue(NodeValue::kTexture, input));
|
||||||
NodeValue(NodeValue::kTexture, input));
|
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.MergePlugin", params, row, true);
|
bool result = RenderPlugin("net.sf.openfx.MergePlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Merge plugin should produce output";
|
EXPECT_TRUE(result) << "Merge plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -490,15 +506,15 @@ TEST(PluginMisc, Keyer)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.KeyerPlugin", params, row, true);
|
bool result = RenderPlugin("net.sf.openfx.KeyerPlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Keyer plugin should produce output";
|
EXPECT_TRUE(result) << "Keyer plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -512,16 +528,17 @@ TEST(PluginMisc, CornerPin)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.CornerPinPlugin", params, row, true);
|
bool result =
|
||||||
|
RenderPlugin("net.sf.openfx.CornerPinPlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "CornerPin plugin should produce output";
|
EXPECT_TRUE(result) << "CornerPin plugin should produce output";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,16 +547,17 @@ TEST(PluginMisc, LensDistortion)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.LensDistortion", params, row, true);
|
bool result =
|
||||||
|
RenderPlugin("net.sf.openfx.LensDistortion", params, row, true);
|
||||||
EXPECT_TRUE(result) << "LensDistortion plugin should produce output";
|
EXPECT_TRUE(result) << "LensDistortion plugin should produce output";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,15 +570,15 @@ TEST(PluginMisc, Invert)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.Invert", params, row, true);
|
bool result = RenderPlugin("net.sf.openfx.Invert", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Invert plugin should produce output";
|
EXPECT_TRUE(result) << "Invert plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -570,15 +588,15 @@ TEST(PluginMisc, Gamma)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr input = CreateSolidTexture(params, 0x80);
|
TexturePtr input = CreateSolidTexture(params, 0x80);
|
||||||
ASSERT_NE(input, nullptr);
|
ASSERT_NE(input, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, input));
|
NodeValue(NodeValue::kTexture, input));
|
||||||
|
|
||||||
bool result = RenderPlugin("net.sf.openfx.GammaPlugin", params, row, true);
|
bool result = RenderPlugin("net.sf.openfx.GammaPlugin", params, row, true);
|
||||||
EXPECT_TRUE(result) << "Gamma plugin should produce output";
|
EXPECT_TRUE(result) << "Gamma plugin should produce output";
|
||||||
}
|
}
|
||||||
@@ -592,12 +610,12 @@ TEST(PluginMisc, ListAvailablePlugins)
|
|||||||
if (ShouldSkipTest()) {
|
if (ShouldSkipTest()) {
|
||||||
GTEST_SKIP() << "OFX integration test not enabled";
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *cache = OFX::Host::PluginCache::getPluginCache();
|
auto *cache = OFX::Host::PluginCache::getPluginCache();
|
||||||
if (!cache) {
|
if (!cache) {
|
||||||
GTEST_SKIP() << "Plugin cache not available";
|
GTEST_SKIP() << "Plugin cache not available";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "\nAvailable OFX plugins:\n";
|
std::cout << "\nAvailable OFX plugins:\n";
|
||||||
for (auto *plug : cache->getPlugins()) {
|
for (auto *plug : cache->getPlugins()) {
|
||||||
if (plug) {
|
if (plug) {
|
||||||
@@ -605,29 +623,31 @@ TEST(PluginMisc, ListAvailablePlugins)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
SUCCEED();
|
SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(PluginMisc, CImgBilateralGuided_MultiInput)
|
TEST(PluginMisc, CImgBilateralGuided_MultiInput)
|
||||||
{
|
{
|
||||||
if (ShouldSkipTest()) GTEST_SKIP() << "OFX integration test not enabled";
|
if (ShouldSkipTest())
|
||||||
|
GTEST_SKIP() << "OFX integration test not enabled";
|
||||||
// CImgBilateralGuided is a multi-input plugin (Source + Guide).
|
// CImgBilateralGuided is a multi-input plugin (Source + Guide).
|
||||||
// This test verifies that connecting both inputs does not trigger
|
// This test verifies that connecting both inputs does not trigger
|
||||||
// the frame-rate mismatch exception in setupClipPreferencesArgs.
|
// the frame-rate mismatch exception in setupClipPreferencesArgs.
|
||||||
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
VideoParams params(320, 240, core::PixelFormat::F32, 4);
|
||||||
TexturePtr source = CreateSolidTexture(params, 0x80);
|
TexturePtr source = CreateSolidTexture(params, 0x80);
|
||||||
TexturePtr guide = CreateSolidTexture(params, 0x40);
|
TexturePtr guide = CreateSolidTexture(params, 0x40);
|
||||||
ASSERT_NE(source, nullptr);
|
ASSERT_NE(source, nullptr);
|
||||||
ASSERT_NE(guide, nullptr);
|
ASSERT_NE(guide, nullptr);
|
||||||
|
|
||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
row.insert(QString::fromStdString(kOfxImageEffectSimpleSourceClipName),
|
||||||
NodeValue(NodeValue::kTexture, source));
|
NodeValue(NodeValue::kTexture, source));
|
||||||
row.insert(QStringLiteral("Guide"),
|
row.insert(QStringLiteral("Guide"), NodeValue(NodeValue::kTexture, guide));
|
||||||
NodeValue(NodeValue::kTexture, guide));
|
bool result =
|
||||||
bool result = RenderPlugin("net.sf.cimg.CImgBilateralGuided", params, row, true);
|
RenderPlugin("net.sf.cimg.CImgBilateralGuided", params, row, true);
|
||||||
EXPECT_TRUE(result) << "CImgBilateralGuided plugin should produce output with both Source and Guide connected";
|
EXPECT_TRUE(result)
|
||||||
|
<< "CImgBilateralGuided plugin should produce output with both Source and Guide connected";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
#include "render/texture.h"
|
#include "render/texture.h"
|
||||||
#include "render/videoparams.h"
|
#include "render/videoparams.h"
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
class PluginJobTraverser : public olive::NodeTraverser {
|
class PluginJobTraverser : public olive::NodeTraverser {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -8,9 +8,8 @@ TEST(PluginRendererReadback, BytesToPixels)
|
|||||||
olive::core::rational(1, 1),
|
olive::core::rational(1, 1),
|
||||||
olive::VideoParams::kInterlaceNone, 1);
|
olive::VideoParams::kInterlaceNone, 1);
|
||||||
|
|
||||||
const int bytes_per_pixel =
|
const int bytes_per_pixel = olive::VideoParams::GetBytesPerPixel(
|
||||||
olive::VideoParams::GetBytesPerPixel(params.format(),
|
params.format(), params.channel_count());
|
||||||
params.channel_count());
|
|
||||||
ASSERT_EQ(bytes_per_pixel, 4);
|
ASSERT_EQ(bytes_per_pixel, 4);
|
||||||
|
|
||||||
EXPECT_EQ(olive::plugin::detail::BytesToPixels(64, params), 16);
|
EXPECT_EQ(olive::plugin::detail::BytesToPixels(64, params), 16);
|
||||||
|
|||||||
+485
-461
File diff suppressed because it is too large
Load Diff
@@ -4,10 +4,10 @@
|
|||||||
#include "ofxhClip.h"
|
#include "ofxhClip.h"
|
||||||
#include "pluginSupport/OliveClip.h"
|
#include "pluginSupport/OliveClip.h"
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
olive::VideoParams MakeParams(int width, int height,
|
olive::VideoParams MakeParams(int width, int height,
|
||||||
olive::core::PixelFormat format,
|
olive::core::PixelFormat format, int channels,
|
||||||
int channels,
|
|
||||||
bool premultiplied)
|
bool premultiplied)
|
||||||
{
|
{
|
||||||
olive::VideoParams params;
|
olive::VideoParams params;
|
||||||
@@ -64,16 +64,14 @@ TEST(PluginSupportClip, GetImageClampsBoundsAndCachesOutput)
|
|||||||
olive::plugin::OliveClipInstance clip(nullptr, desc, params);
|
olive::plugin::OliveClipInstance clip(nullptr, desc, params);
|
||||||
|
|
||||||
OfxRectD optional_bounds = { -10.0, -10.0, 200.0, 200.0 };
|
OfxRectD optional_bounds = { -10.0, -10.0, 200.0, 200.0 };
|
||||||
OFX::Host::ImageEffect::Image *image =
|
OFX::Host::ImageEffect::Image *image = clip.getImage(0.0, &optional_bounds);
|
||||||
clip.getImage(0.0, &optional_bounds);
|
|
||||||
ASSERT_NE(image, nullptr);
|
ASSERT_NE(image, nullptr);
|
||||||
|
|
||||||
auto *olive_image = static_cast<olive::plugin::Image *>(image);
|
auto *olive_image = static_cast<olive::plugin::Image *>(image);
|
||||||
EXPECT_EQ(olive_image->width(), 100);
|
EXPECT_EQ(olive_image->width(), 100);
|
||||||
EXPECT_EQ(olive_image->height(), 80);
|
EXPECT_EQ(olive_image->height(), 80);
|
||||||
|
|
||||||
OFX::Host::ImageEffect::Image *image_again =
|
OFX::Host::ImageEffect::Image *image_again = clip.getImage(0.0, nullptr);
|
||||||
clip.getImage(0.0, nullptr);
|
|
||||||
EXPECT_EQ(image, image_again);
|
EXPECT_EQ(image, image_again);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
#include "pluginSupport/OliveClip.h"
|
#include "pluginSupport/OliveClip.h"
|
||||||
#include "pluginSupport/image.h"
|
#include "pluginSupport/image.h"
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
olive::VideoParams MakeParams(int width, int height,
|
olive::VideoParams MakeParams(int width, int height,
|
||||||
olive::core::PixelFormat format,
|
olive::core::PixelFormat format, int channels,
|
||||||
int channels,
|
|
||||||
bool premultiplied)
|
bool premultiplied)
|
||||||
{
|
{
|
||||||
olive::VideoParams params;
|
olive::VideoParams params;
|
||||||
@@ -106,14 +106,14 @@ TEST(PluginSupportImage, AllocateSetsOfxProperties)
|
|||||||
EXPECT_NE(image.data(), nullptr);
|
EXPECT_NE(image.data(), nullptr);
|
||||||
EXPECT_EQ(image.row_bytes(), 8 * 4 * 2);
|
EXPECT_EQ(image.row_bytes(), 8 * 4 * 2);
|
||||||
|
|
||||||
int bounds_props[4] = {0};
|
int bounds_props[4] = { 0 };
|
||||||
image.getIntPropertyN(kOfxImagePropBounds, bounds_props, 4);
|
image.getIntPropertyN(kOfxImagePropBounds, bounds_props, 4);
|
||||||
EXPECT_EQ(bounds_props[0], bounds.x1);
|
EXPECT_EQ(bounds_props[0], bounds.x1);
|
||||||
EXPECT_EQ(bounds_props[1], bounds.y1);
|
EXPECT_EQ(bounds_props[1], bounds.y1);
|
||||||
EXPECT_EQ(bounds_props[2], bounds.x2);
|
EXPECT_EQ(bounds_props[2], bounds.x2);
|
||||||
EXPECT_EQ(bounds_props[3], bounds.y2);
|
EXPECT_EQ(bounds_props[3], bounds.y2);
|
||||||
|
|
||||||
int rod_props[4] = {0};
|
int rod_props[4] = { 0 };
|
||||||
image.getIntPropertyN(kOfxImagePropRegionOfDefinition, rod_props, 4);
|
image.getIntPropertyN(kOfxImagePropRegionOfDefinition, rod_props, 4);
|
||||||
EXPECT_EQ(rod_props[0], rod.x1);
|
EXPECT_EQ(rod_props[0], rod.x1);
|
||||||
EXPECT_EQ(rod_props[1], rod.y1);
|
EXPECT_EQ(rod_props[1], rod.y1);
|
||||||
|
|||||||
@@ -4,7 +4,5 @@
|
|||||||
|
|
||||||
TEST(PluginSupport, LoadPluginsEmptyPath)
|
TEST(PluginSupport, LoadPluginsEmptyPath)
|
||||||
{
|
{
|
||||||
EXPECT_NO_THROW({
|
EXPECT_NO_THROW({ olive::plugin::loadPlugins(QString()); });
|
||||||
olive::plugin::loadPlugins(QString());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,16 +45,16 @@ TEST(PreferencesBehaviorTab, BehaviorPrefTrProvidesTranslations)
|
|||||||
{
|
{
|
||||||
QStringList keys;
|
QStringList keys;
|
||||||
keys << QStringLiteral("Enable hover focus")
|
keys << QStringLiteral("Enable hover focus")
|
||||||
<< QStringLiteral("Select also selects all children in the graph")
|
<< QStringLiteral("Select also selects all children in the graph")
|
||||||
<< QStringLiteral("Double-clicking a node opens its properties")
|
<< QStringLiteral("Double-clicking a node opens its properties")
|
||||||
<< QStringLiteral("Auto-Seek to Beginning of Sequence")
|
<< QStringLiteral("Auto-Seek to Beginning of Sequence")
|
||||||
<< QStringLiteral("Scroll wheel zooms instead of scrolling")
|
<< QStringLiteral("Scroll wheel zooms instead of scrolling")
|
||||||
<< QStringLiteral("Enable audio scrubbing");
|
<< QStringLiteral("Enable audio scrubbing");
|
||||||
|
|
||||||
foreach (const QString &key, keys) {
|
foreach (const QString &key, keys) {
|
||||||
EXPECT_FALSE(
|
EXPECT_FALSE(
|
||||||
PreferencesBehaviorTab::BehaviorPrefTr(
|
PreferencesBehaviorTab::BehaviorPrefTr(key.toUtf8().constData())
|
||||||
key.toUtf8().constData()).isEmpty())
|
.isEmpty())
|
||||||
<< key.toStdString();
|
<< key.toStdString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,8 +76,8 @@ TEST(PreferencesGeneralTab, ContainsHoverFocusOption)
|
|||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
foreach (QCheckBox *box, boxes) {
|
foreach (QCheckBox *box, boxes) {
|
||||||
if (box->text() == PreferencesBehaviorTab::BehaviorPrefTr(
|
if (box->text() ==
|
||||||
"Enable hover focus")) {
|
PreferencesBehaviorTab::BehaviorPrefTr("Enable hover focus")) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ TEST(PreferencesAudioTab, AudioScrubbingCheckboxUsesBehaviorTranslation)
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
foreach (QCheckBox *box, boxes) {
|
foreach (QCheckBox *box, boxes) {
|
||||||
if (box->text() == PreferencesBehaviorTab::BehaviorPrefTr(
|
if (box->text() == PreferencesBehaviorTab::BehaviorPrefTr(
|
||||||
"Enable audio scrubbing")) {
|
"Enable audio scrubbing")) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ TEST_F(PreviewAutoCacherTest, ClearSingleFrameRendersDoesNotCrashWhenEmpty)
|
|||||||
cacher.ClearSingleFrameRenders();
|
cacher.ClearSingleFrameRenders();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PreviewAutoCacherTest, ClearSingleFrameRendersThatArentRunningDoesNotCrashWhenEmpty)
|
TEST_F(PreviewAutoCacherTest,
|
||||||
|
ClearSingleFrameRendersThatArentRunningDoesNotCrashWhenEmpty)
|
||||||
{
|
{
|
||||||
PreviewAutoCacher cacher;
|
PreviewAutoCacher cacher;
|
||||||
cacher.ClearSingleFrameRendersThatArentRunning();
|
cacher.ClearSingleFrameRendersThatArentRunning();
|
||||||
|
|||||||
@@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
TEST(ProjectSerializer, SaveLoadProjectRoundTrip)
|
TEST(ProjectSerializer, SaveLoadProjectRoundTrip)
|
||||||
{
|
{
|
||||||
const bool created_disk_manager = (olive::DiskManager::instance() == nullptr);
|
const bool created_disk_manager =
|
||||||
|
(olive::DiskManager::instance() == nullptr);
|
||||||
if (created_disk_manager) {
|
if (created_disk_manager) {
|
||||||
olive::DiskManager::CreateInstance();
|
olive::DiskManager::CreateInstance();
|
||||||
}
|
}
|
||||||
@@ -45,15 +46,15 @@ TEST(ProjectSerializer, SaveLoadProjectRoundTrip)
|
|||||||
QBuffer read_buffer(&xml);
|
QBuffer read_buffer(&xml);
|
||||||
read_buffer.open(QIODevice::ReadOnly);
|
read_buffer.open(QIODevice::ReadOnly);
|
||||||
QXmlStreamReader reader(&read_buffer);
|
QXmlStreamReader reader(&read_buffer);
|
||||||
olive::ProjectSerializer::Result result =
|
olive::ProjectSerializer::Result result = olive::ProjectSerializer::Load(
|
||||||
olive::ProjectSerializer::Load(&loaded_project, &reader,
|
&loaded_project, &reader, olive::ProjectSerializer::kProject);
|
||||||
olive::ProjectSerializer::kProject);
|
|
||||||
EXPECT_EQ(result.code(), olive::ProjectSerializer::kSuccess);
|
EXPECT_EQ(result.code(), olive::ProjectSerializer::kSuccess);
|
||||||
EXPECT_FALSE(loaded_project.nodes().isEmpty());
|
EXPECT_FALSE(loaded_project.nodes().isEmpty());
|
||||||
ASSERT_TRUE(result.GetLoadData().node_ptrs.contains(
|
ASSERT_TRUE(result.GetLoadData().node_ptrs.contains(
|
||||||
reinterpret_cast<quintptr>(node)));
|
reinterpret_cast<quintptr>(node)));
|
||||||
EXPECT_TRUE(loaded_project.nodes().contains(
|
EXPECT_TRUE(
|
||||||
result.GetLoadData().node_ptrs.value(reinterpret_cast<quintptr>(node))));
|
loaded_project.nodes().contains(result.GetLoadData().node_ptrs.value(
|
||||||
|
reinterpret_cast<quintptr>(node))));
|
||||||
|
|
||||||
olive::ProjectSerializer::Destroy();
|
olive::ProjectSerializer::Destroy();
|
||||||
if (created_disk_manager) {
|
if (created_disk_manager) {
|
||||||
|
|||||||
@@ -18,14 +18,14 @@ TEST(ProxyManager, BuildsStableProxyFilename)
|
|||||||
params.version = 1;
|
params.version = 1;
|
||||||
|
|
||||||
const QString first = olive::ProxyManager::GetProxyFilename(
|
const QString first = olive::ProxyManager::GetProxyFilename(
|
||||||
QStringLiteral("/tmp/oak-cache"),
|
QStringLiteral("/tmp/oak-cache"), QStringLiteral("/media/source.mov"),
|
||||||
QStringLiteral("/media/source.mov"), 0, params);
|
0, params);
|
||||||
const QString second = olive::ProxyManager::GetProxyFilename(
|
const QString second = olive::ProxyManager::GetProxyFilename(
|
||||||
QStringLiteral("/tmp/oak-cache"),
|
QStringLiteral("/tmp/oak-cache"), QStringLiteral("/media/source.mov"),
|
||||||
QStringLiteral("/media/source.mov"), 0, params);
|
0, params);
|
||||||
const QString other_stream = olive::ProxyManager::GetProxyFilename(
|
const QString other_stream = olive::ProxyManager::GetProxyFilename(
|
||||||
QStringLiteral("/tmp/oak-cache"),
|
QStringLiteral("/tmp/oak-cache"), QStringLiteral("/media/source.mov"),
|
||||||
QStringLiteral("/media/source.mov"), 1, params);
|
1, params);
|
||||||
|
|
||||||
EXPECT_EQ(first, second);
|
EXPECT_EQ(first, second);
|
||||||
EXPECT_NE(first, other_stream);
|
EXPECT_NE(first, other_stream);
|
||||||
@@ -48,11 +48,11 @@ TEST(ProxyManager, ProxyFilenameIncludesPresetParameters)
|
|||||||
mov_540p.extension = QStringLiteral("mov");
|
mov_540p.extension = QStringLiteral("mov");
|
||||||
|
|
||||||
const QString first = olive::ProxyManager::GetProxyFilename(
|
const QString first = olive::ProxyManager::GetProxyFilename(
|
||||||
QStringLiteral("/tmp/oak-cache"),
|
QStringLiteral("/tmp/oak-cache"), QStringLiteral("/media/source.mov"),
|
||||||
QStringLiteral("/media/source.mov"), 0, mp4_720p);
|
0, mp4_720p);
|
||||||
const QString second = olive::ProxyManager::GetProxyFilename(
|
const QString second = olive::ProxyManager::GetProxyFilename(
|
||||||
QStringLiteral("/tmp/oak-cache"),
|
QStringLiteral("/tmp/oak-cache"), QStringLiteral("/media/source.mov"),
|
||||||
QStringLiteral("/media/source.mov"), 0, mov_540p);
|
0, mov_540p);
|
||||||
|
|
||||||
EXPECT_NE(first, second);
|
EXPECT_NE(first, second);
|
||||||
EXPECT_TRUE(first.contains(QStringLiteral(".1280x720.v1.")));
|
EXPECT_TRUE(first.contains(QStringLiteral(".1280x720.v1.")));
|
||||||
@@ -117,21 +117,21 @@ TEST(ProxyManager, ConvertsProxyStateToAndFromStrings)
|
|||||||
olive::ProxyManager::kProxyFailed),
|
olive::ProxyManager::kProxyFailed),
|
||||||
QStringLiteral("failed"));
|
QStringLiteral("failed"));
|
||||||
|
|
||||||
EXPECT_EQ(olive::ProxyManager::ProxyStateFromString(
|
EXPECT_EQ(
|
||||||
QStringLiteral("missing")),
|
olive::ProxyManager::ProxyStateFromString(QStringLiteral("missing")),
|
||||||
olive::ProxyManager::kProxyMissing);
|
olive::ProxyManager::kProxyMissing);
|
||||||
EXPECT_EQ(olive::ProxyManager::ProxyStateFromString(
|
EXPECT_EQ(
|
||||||
QStringLiteral("generating")),
|
olive::ProxyManager::ProxyStateFromString(QStringLiteral("generating")),
|
||||||
olive::ProxyManager::kProxyGenerating);
|
olive::ProxyManager::kProxyGenerating);
|
||||||
EXPECT_EQ(olive::ProxyManager::ProxyStateFromString(
|
EXPECT_EQ(
|
||||||
QStringLiteral("ready")),
|
olive::ProxyManager::ProxyStateFromString(QStringLiteral("ready")),
|
||||||
olive::ProxyManager::kProxyReady);
|
olive::ProxyManager::kProxyReady);
|
||||||
EXPECT_EQ(olive::ProxyManager::ProxyStateFromString(
|
EXPECT_EQ(
|
||||||
QStringLiteral("failed")),
|
olive::ProxyManager::ProxyStateFromString(QStringLiteral("failed")),
|
||||||
olive::ProxyManager::kProxyFailed);
|
olive::ProxyManager::kProxyFailed);
|
||||||
EXPECT_EQ(olive::ProxyManager::ProxyStateFromString(
|
EXPECT_EQ(
|
||||||
QStringLiteral("unknown")),
|
olive::ProxyManager::ProxyStateFromString(QStringLiteral("unknown")),
|
||||||
olive::ProxyManager::kProxyMissing);
|
olive::ProxyManager::kProxyMissing);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ProxyManager, FootagePersistsProxyMetadata)
|
TEST(ProxyManager, FootagePersistsProxyMetadata)
|
||||||
@@ -225,10 +225,10 @@ TEST(ProxyManager, EmitsProxyFinishedState)
|
|||||||
received_state = state;
|
received_state = state;
|
||||||
});
|
});
|
||||||
|
|
||||||
emit olive::ProxyManager::instance()->ProxyFinished(
|
emit olive::ProxyManager::instance()
|
||||||
QStringLiteral("/media/source.mov"), 0,
|
-> ProxyFinished(QStringLiteral("/media/source.mov"), 0,
|
||||||
QStringLiteral("/cache/proxy/example.mp4"),
|
QStringLiteral("/cache/proxy/example.mp4"),
|
||||||
olive::ProxyManager::kProxyFailed);
|
olive::ProxyManager::kProxyFailed);
|
||||||
|
|
||||||
EXPECT_TRUE(received);
|
EXPECT_TRUE(received);
|
||||||
EXPECT_EQ(received_source, QStringLiteral("/media/source.mov"));
|
EXPECT_EQ(received_source, QStringLiteral("/media/source.mov"));
|
||||||
@@ -241,10 +241,8 @@ TEST(ProxyManager, EmitsProxyFinishedState)
|
|||||||
|
|
||||||
TEST(ProxyManager, WorkingProxyFilenamePrependsExtension)
|
TEST(ProxyManager, WorkingProxyFilenamePrependsExtension)
|
||||||
{
|
{
|
||||||
const QString proxy =
|
const QString proxy = QStringLiteral("/cache/proxy/example.mp4");
|
||||||
QStringLiteral("/cache/proxy/example.mp4");
|
const QString working = olive::ProxyManager::GetWorkingProxyFilename(proxy);
|
||||||
const QString working =
|
|
||||||
olive::ProxyManager::GetWorkingProxyFilename(proxy);
|
|
||||||
|
|
||||||
EXPECT_EQ(working, QStringLiteral("/cache/proxy/example.mp4.working.mp4"));
|
EXPECT_EQ(working, QStringLiteral("/cache/proxy/example.mp4.working.mp4"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ TEST(RenderAudioParams, ValidityAndEquality)
|
|||||||
olive::core::AudioParams invalid;
|
olive::core::AudioParams invalid;
|
||||||
EXPECT_FALSE(invalid.is_valid());
|
EXPECT_FALSE(invalid.is_valid());
|
||||||
|
|
||||||
olive::core::AudioParams params(
|
olive::core::AudioParams params(48000, AV_CH_LAYOUT_STEREO,
|
||||||
48000, AV_CH_LAYOUT_STEREO, olive::core::SampleFormat::S16);
|
olive::core::SampleFormat::S16);
|
||||||
EXPECT_TRUE(params.is_valid());
|
EXPECT_TRUE(params.is_valid());
|
||||||
|
|
||||||
olive::core::AudioParams other(
|
olive::core::AudioParams other(48000, AV_CH_LAYOUT_STEREO,
|
||||||
48000, AV_CH_LAYOUT_STEREO, olive::core::SampleFormat::S16);
|
olive::core::SampleFormat::S16);
|
||||||
EXPECT_TRUE(params == other);
|
EXPECT_TRUE(params == other);
|
||||||
|
|
||||||
other.set_sample_rate(44100);
|
other.set_sample_rate(44100);
|
||||||
@@ -21,8 +21,8 @@ TEST(RenderAudioParams, ValidityAndEquality)
|
|||||||
|
|
||||||
TEST(RenderAudioParams, TimeAndSampleConversions)
|
TEST(RenderAudioParams, TimeAndSampleConversions)
|
||||||
{
|
{
|
||||||
olive::core::AudioParams params(
|
olive::core::AudioParams params(48000, AV_CH_LAYOUT_STEREO,
|
||||||
48000, AV_CH_LAYOUT_STEREO, olive::core::SampleFormat::S16);
|
olive::core::SampleFormat::S16);
|
||||||
|
|
||||||
EXPECT_EQ(params.channel_count(), 2);
|
EXPECT_EQ(params.channel_count(), 2);
|
||||||
EXPECT_EQ(params.bytes_per_sample_per_channel(), 2);
|
EXPECT_EQ(params.bytes_per_sample_per_channel(), 2);
|
||||||
@@ -43,34 +43,34 @@ TEST(RenderAudioParams, TimeAndSampleConversions)
|
|||||||
|
|
||||||
TEST(RenderAudioParams, ChannelLayoutCount)
|
TEST(RenderAudioParams, ChannelLayoutCount)
|
||||||
{
|
{
|
||||||
olive::core::AudioParams mono(
|
olive::core::AudioParams mono(48000, AV_CH_LAYOUT_MONO,
|
||||||
48000, AV_CH_LAYOUT_MONO, olive::core::SampleFormat::F32);
|
olive::core::SampleFormat::F32);
|
||||||
EXPECT_EQ(mono.channel_count(), 1);
|
EXPECT_EQ(mono.channel_count(), 1);
|
||||||
|
|
||||||
olive::core::AudioParams surround(
|
olive::core::AudioParams surround(48000, AV_CH_LAYOUT_5POINT1,
|
||||||
48000, AV_CH_LAYOUT_5POINT1, olive::core::SampleFormat::F32);
|
olive::core::SampleFormat::F32);
|
||||||
EXPECT_EQ(surround.channel_count(), 6);
|
EXPECT_EQ(surround.channel_count(), 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RenderAudioParams, SampleFormatSizes)
|
TEST(RenderAudioParams, SampleFormatSizes)
|
||||||
{
|
{
|
||||||
olive::core::AudioParams u8(
|
olive::core::AudioParams u8(48000, AV_CH_LAYOUT_MONO,
|
||||||
48000, AV_CH_LAYOUT_MONO, olive::core::SampleFormat::U8);
|
olive::core::SampleFormat::U8);
|
||||||
EXPECT_EQ(u8.bytes_per_sample_per_channel(), 1);
|
EXPECT_EQ(u8.bytes_per_sample_per_channel(), 1);
|
||||||
|
|
||||||
olive::core::AudioParams f32(
|
olive::core::AudioParams f32(48000, AV_CH_LAYOUT_MONO,
|
||||||
48000, AV_CH_LAYOUT_MONO, olive::core::SampleFormat::F32);
|
olive::core::SampleFormat::F32);
|
||||||
EXPECT_EQ(f32.bytes_per_sample_per_channel(), 4);
|
EXPECT_EQ(f32.bytes_per_sample_per_channel(), 4);
|
||||||
|
|
||||||
olive::core::AudioParams f64(
|
olive::core::AudioParams f64(48000, AV_CH_LAYOUT_MONO,
|
||||||
48000, AV_CH_LAYOUT_MONO, olive::core::SampleFormat::F64);
|
olive::core::SampleFormat::F64);
|
||||||
EXPECT_EQ(f64.bytes_per_sample_per_channel(), 8);
|
EXPECT_EQ(f64.bytes_per_sample_per_channel(), 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RenderAudioParams, CopyAndAssignment)
|
TEST(RenderAudioParams, CopyAndAssignment)
|
||||||
{
|
{
|
||||||
olive::core::AudioParams params(
|
olive::core::AudioParams params(96000, AV_CH_LAYOUT_STEREO,
|
||||||
96000, AV_CH_LAYOUT_STEREO, olive::core::SampleFormat::F32);
|
olive::core::SampleFormat::F32);
|
||||||
|
|
||||||
olive::core::AudioParams copy(params);
|
olive::core::AudioParams copy(params);
|
||||||
EXPECT_EQ(copy.sample_rate(), 96000);
|
EXPECT_EQ(copy.sample_rate(), 96000);
|
||||||
@@ -85,8 +85,8 @@ TEST(RenderAudioParams, CopyAndAssignment)
|
|||||||
|
|
||||||
TEST(RenderAudioParams, SettersModifyState)
|
TEST(RenderAudioParams, SettersModifyState)
|
||||||
{
|
{
|
||||||
olive::core::AudioParams params(
|
olive::core::AudioParams params(44100, AV_CH_LAYOUT_MONO,
|
||||||
44100, AV_CH_LAYOUT_MONO, olive::core::SampleFormat::S16);
|
olive::core::SampleFormat::S16);
|
||||||
EXPECT_TRUE(params.is_valid());
|
EXPECT_TRUE(params.is_valid());
|
||||||
|
|
||||||
params.set_sample_rate(48000);
|
params.set_sample_rate(48000);
|
||||||
|
|||||||
@@ -40,13 +40,13 @@ TEST(SpscRingBuffer, BasicPushPopAndCapacity)
|
|||||||
EXPECT_TRUE(ring->IsEmptyApprox());
|
EXPECT_TRUE(ring->IsEmptyApprox());
|
||||||
|
|
||||||
uint32_t v = 0;
|
uint32_t v = 0;
|
||||||
EXPECT_FALSE(ring->Pop(&v)); // empty
|
EXPECT_FALSE(ring->Pop(&v)); // empty
|
||||||
|
|
||||||
// Capacity 4 holds at most 3 entries (one slot reserved to disambiguate full/empty).
|
// Capacity 4 holds at most 3 entries (one slot reserved to disambiguate full/empty).
|
||||||
EXPECT_TRUE(ring->Push(10));
|
EXPECT_TRUE(ring->Push(10));
|
||||||
EXPECT_TRUE(ring->Push(20));
|
EXPECT_TRUE(ring->Push(20));
|
||||||
EXPECT_TRUE(ring->Push(30));
|
EXPECT_TRUE(ring->Push(30));
|
||||||
EXPECT_FALSE(ring->Push(40)); // full
|
EXPECT_FALSE(ring->Push(40)); // full
|
||||||
|
|
||||||
EXPECT_TRUE(ring->Pop(&v));
|
EXPECT_TRUE(ring->Pop(&v));
|
||||||
EXPECT_EQ(v, 10u);
|
EXPECT_EQ(v, 10u);
|
||||||
@@ -54,7 +54,7 @@ TEST(SpscRingBuffer, BasicPushPopAndCapacity)
|
|||||||
EXPECT_EQ(v, 20u);
|
EXPECT_EQ(v, 20u);
|
||||||
EXPECT_TRUE(ring->Pop(&v));
|
EXPECT_TRUE(ring->Pop(&v));
|
||||||
EXPECT_EQ(v, 30u);
|
EXPECT_EQ(v, 30u);
|
||||||
EXPECT_FALSE(ring->Pop(&v)); // empty again
|
EXPECT_FALSE(ring->Pop(&v)); // empty again
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(SpscRingBuffer, WrapAround)
|
TEST(SpscRingBuffer, WrapAround)
|
||||||
@@ -75,17 +75,18 @@ TEST(SpscRingBuffer, WrapAround)
|
|||||||
TEST(SpscRingBuffer, ConcurrentProducerConsumer)
|
TEST(SpscRingBuffer, ConcurrentProducerConsumer)
|
||||||
{
|
{
|
||||||
constexpr uint32_t kCapacity = 1024;
|
constexpr uint32_t kCapacity = 1024;
|
||||||
constexpr uint32_t kCount = 2'000'000; // values 0..kCount-1 streamed through the ring
|
constexpr uint32_t kCount =
|
||||||
|
2'000'000; // values 0..kCount-1 streamed through the ring
|
||||||
|
|
||||||
std::vector<uint8_t> mem(SpscRingBuffer::BytesNeeded(kCapacity));
|
std::vector<uint8_t> mem(SpscRingBuffer::BytesNeeded(kCapacity));
|
||||||
SpscRingBuffer *ring = SpscRingBuffer::Create(mem.data(), kCapacity);
|
SpscRingBuffer *ring = SpscRingBuffer::Create(mem.data(), kCapacity);
|
||||||
|
|
||||||
std::atomic<bool> order_ok{true};
|
std::atomic<bool> order_ok{ true };
|
||||||
|
|
||||||
std::thread producer([&] {
|
std::thread producer([&] {
|
||||||
for (uint32_t i = 0; i < kCount; i++) {
|
for (uint32_t i = 0; i < kCount; i++) {
|
||||||
while (!ring->Push(i)) {
|
while (!ring->Push(i)) {
|
||||||
std::this_thread::yield(); // buffer full, spin until consumer drains
|
std::this_thread::yield(); // buffer full, spin until consumer drains
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -124,7 +125,8 @@ TEST(FrameSlotPool, SingleThreadedHandoff)
|
|||||||
constexpr size_t kSlotBytes = 256;
|
constexpr size_t kSlotBytes = 256;
|
||||||
|
|
||||||
std::vector<uint8_t> mem(FrameSlotPool::BytesNeeded(kSlots, kSlotBytes));
|
std::vector<uint8_t> mem(FrameSlotPool::BytesNeeded(kSlots, kSlotBytes));
|
||||||
FrameSlotPool filler = FrameSlotPool::Create(mem.data(), kSlots, kSlotBytes);
|
FrameSlotPool filler =
|
||||||
|
FrameSlotPool::Create(mem.data(), kSlots, kSlotBytes);
|
||||||
FrameSlotPool drainer = FrameSlotPool::Attach(mem.data());
|
FrameSlotPool drainer = FrameSlotPool::Attach(mem.data());
|
||||||
|
|
||||||
ASSERT_TRUE(filler.IsValid());
|
ASSERT_TRUE(filler.IsValid());
|
||||||
@@ -156,7 +158,8 @@ TEST(FrameSlotPool, SingleThreadedHandoff)
|
|||||||
EXPECT_EQ(got_meta->id, 4242);
|
EXPECT_EQ(got_meta->id, 4242);
|
||||||
EXPECT_EQ(got_meta->width, 16);
|
EXPECT_EQ(got_meta->width, 16);
|
||||||
|
|
||||||
const auto *got_data = static_cast<const uint8_t *>(drainer.SlotData(got_idx));
|
const auto *got_data =
|
||||||
|
static_cast<const uint8_t *>(drainer.SlotData(got_idx));
|
||||||
for (size_t i = 0; i < kSlotBytes; i++) {
|
for (size_t i = 0; i < kSlotBytes; i++) {
|
||||||
ASSERT_EQ(got_data[i], uint8_t(i & 0xFF));
|
ASSERT_EQ(got_data[i], uint8_t(i & 0xFF));
|
||||||
}
|
}
|
||||||
@@ -180,7 +183,7 @@ TEST(FrameSlotPool, ExhaustionAndRefill)
|
|||||||
held.push_back(a);
|
held.push_back(a);
|
||||||
}
|
}
|
||||||
uint32_t overflow = 0;
|
uint32_t overflow = 0;
|
||||||
EXPECT_FALSE(pool.Acquire(&overflow)); // pool exhausted
|
EXPECT_FALSE(pool.Acquire(&overflow)); // pool exhausted
|
||||||
|
|
||||||
// Publishing then consuming + releasing returns the slots to the free pool.
|
// Publishing then consuming + releasing returns the slots to the free pool.
|
||||||
for (uint32_t idx : held) {
|
for (uint32_t idx : held) {
|
||||||
@@ -192,7 +195,7 @@ TEST(FrameSlotPool, ExhaustionAndRefill)
|
|||||||
ASSERT_TRUE(pool.Release(c));
|
ASSERT_TRUE(pool.Release(c));
|
||||||
}
|
}
|
||||||
uint32_t again = 0;
|
uint32_t again = 0;
|
||||||
EXPECT_TRUE(pool.Acquire(&again)); // free again
|
EXPECT_TRUE(pool.Acquire(&again)); // free again
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(FrameSlotPool, ConcurrentFillDrainIntegrity)
|
TEST(FrameSlotPool, ConcurrentFillDrainIntegrity)
|
||||||
@@ -202,10 +205,11 @@ TEST(FrameSlotPool, ConcurrentFillDrainIntegrity)
|
|||||||
constexpr int64_t kFrames = 200'000;
|
constexpr int64_t kFrames = 200'000;
|
||||||
|
|
||||||
std::vector<uint8_t> mem(FrameSlotPool::BytesNeeded(kSlots, kSlotBytes));
|
std::vector<uint8_t> mem(FrameSlotPool::BytesNeeded(kSlots, kSlotBytes));
|
||||||
FrameSlotPool filler = FrameSlotPool::Create(mem.data(), kSlots, kSlotBytes);
|
FrameSlotPool filler =
|
||||||
|
FrameSlotPool::Create(mem.data(), kSlots, kSlotBytes);
|
||||||
FrameSlotPool drainer = FrameSlotPool::Attach(mem.data());
|
FrameSlotPool drainer = FrameSlotPool::Attach(mem.data());
|
||||||
|
|
||||||
std::atomic<bool> integrity_ok{true};
|
std::atomic<bool> integrity_ok{ true };
|
||||||
|
|
||||||
// Filler: for each frame id, acquire a slot, stamp the id into meta and a pattern into the data,
|
// Filler: for each frame id, acquire a slot, stamp the id into meta and a pattern into the data,
|
||||||
// publish. Spins when no slot is free (this is the natural backpressure path).
|
// publish. Spins when no slot is free (this is the natural backpressure path).
|
||||||
@@ -220,7 +224,7 @@ TEST(FrameSlotPool, ConcurrentFillDrainIntegrity)
|
|||||||
const uint8_t pat = uint8_t(id & 0xFF);
|
const uint8_t pat = uint8_t(id & 0xFF);
|
||||||
memset(d, pat, kSlotBytes);
|
memset(d, pat, kSlotBytes);
|
||||||
while (!filler.Publish(idx)) {
|
while (!filler.Publish(idx)) {
|
||||||
std::this_thread::yield(); // ready ring transiently full
|
std::this_thread::yield(); // ready ring transiently full
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -292,7 +296,7 @@ TEST(IpcMessage, TypedRoundTrip)
|
|||||||
rf.channel_count = 4;
|
rf.channel_count = 4;
|
||||||
rf.mode = 1;
|
rf.mode = 1;
|
||||||
rf.input_slot = 2;
|
rf.input_slot = 2;
|
||||||
rf.input_slots = {2, 3};
|
rf.input_slots = { 2, 3 };
|
||||||
ASSERT_TRUE(WriteMessage(&dev, rf.ToJson()));
|
ASSERT_TRUE(WriteMessage(&dev, rf.ToJson()));
|
||||||
|
|
||||||
FrameReadyMsg fr;
|
FrameReadyMsg fr;
|
||||||
@@ -349,7 +353,8 @@ TEST(IpcMessage, PartialFrameByteByByte)
|
|||||||
CancelMsg c;
|
CancelMsg c;
|
||||||
c.ticket_id = 7;
|
c.ticket_id = 7;
|
||||||
const QByteArray full =
|
const QByteArray full =
|
||||||
QByteArray(QJsonDocument(c.ToJson()).toJson(QJsonDocument::Compact)) + '\n';
|
QByteArray(QJsonDocument(c.ToJson()).toJson(QJsonDocument::Compact)) +
|
||||||
|
'\n';
|
||||||
|
|
||||||
// Feed the bytes one at a time; ReadMessage must return false until the terminating '\n'.
|
// Feed the bytes one at a time; ReadMessage must return false until the terminating '\n'.
|
||||||
QByteArray reader;
|
QByteArray reader;
|
||||||
@@ -357,9 +362,9 @@ TEST(IpcMessage, PartialFrameByteByByte)
|
|||||||
bool ok = false;
|
bool ok = false;
|
||||||
for (int i = 0; i < full.size() - 1; i++) {
|
for (int i = 0; i < full.size() - 1; i++) {
|
||||||
reader.append(full.at(i));
|
reader.append(full.at(i));
|
||||||
ASSERT_FALSE(ReadMessage(&reader, &obj, &ok)); // no complete line yet
|
ASSERT_FALSE(ReadMessage(&reader, &obj, &ok)); // no complete line yet
|
||||||
}
|
}
|
||||||
reader.append(full.at(full.size() - 1)); // the trailing newline
|
reader.append(full.at(full.size() - 1)); // the trailing newline
|
||||||
ASSERT_TRUE(ReadMessage(&reader, &obj, &ok));
|
ASSERT_TRUE(ReadMessage(&reader, &obj, &ok));
|
||||||
ASSERT_TRUE(ok);
|
ASSERT_TRUE(ok);
|
||||||
|
|
||||||
|
|||||||
@@ -15,29 +15,27 @@ TEST(RenderVideoParams, BytesPerChannelAndPixel)
|
|||||||
EXPECT_EQ(olive::VideoParams::GetBytesPerChannel(
|
EXPECT_EQ(olive::VideoParams::GetBytesPerChannel(
|
||||||
olive::core::PixelFormat::INVALID),
|
olive::core::PixelFormat::INVALID),
|
||||||
0);
|
0);
|
||||||
EXPECT_EQ(olive::VideoParams::GetBytesPerChannel(
|
EXPECT_EQ(
|
||||||
olive::core::PixelFormat::U8),
|
olive::VideoParams::GetBytesPerChannel(olive::core::PixelFormat::U8),
|
||||||
1);
|
1);
|
||||||
EXPECT_EQ(olive::VideoParams::GetBytesPerChannel(
|
EXPECT_EQ(
|
||||||
olive::core::PixelFormat::U16),
|
olive::VideoParams::GetBytesPerChannel(olive::core::PixelFormat::U16),
|
||||||
2);
|
2);
|
||||||
EXPECT_EQ(olive::VideoParams::GetBytesPerChannel(
|
EXPECT_EQ(
|
||||||
olive::core::PixelFormat::F16),
|
olive::VideoParams::GetBytesPerChannel(olive::core::PixelFormat::F16),
|
||||||
2);
|
2);
|
||||||
EXPECT_EQ(olive::VideoParams::GetBytesPerChannel(
|
EXPECT_EQ(
|
||||||
olive::core::PixelFormat::F32),
|
olive::VideoParams::GetBytesPerChannel(olive::core::PixelFormat::F32),
|
||||||
4);
|
4);
|
||||||
EXPECT_EQ(olive::VideoParams::GetBytesPerPixel(
|
EXPECT_EQ(olive::VideoParams::GetBytesPerPixel(olive::core::PixelFormat::U8,
|
||||||
olive::core::PixelFormat::U8, 4),
|
4),
|
||||||
4);
|
4);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(RenderVideoParams, DividerAndFormatNames)
|
TEST(RenderVideoParams, DividerAndFormatNames)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(olive::VideoParams::GetNameForDivider(1),
|
EXPECT_EQ(olive::VideoParams::GetNameForDivider(1), QStringLiteral("Full"));
|
||||||
QStringLiteral("Full"));
|
EXPECT_EQ(olive::VideoParams::GetNameForDivider(3), QStringLiteral("1/3"));
|
||||||
EXPECT_EQ(olive::VideoParams::GetNameForDivider(3),
|
|
||||||
QStringLiteral("1/3"));
|
|
||||||
|
|
||||||
const QString unknown =
|
const QString unknown =
|
||||||
olive::VideoParams::GetFormatName(olive::core::PixelFormat::INVALID);
|
olive::VideoParams::GetFormatName(olive::core::PixelFormat::INVALID);
|
||||||
@@ -47,11 +45,11 @@ TEST(RenderVideoParams, DividerAndFormatNames)
|
|||||||
TEST(RenderVideoParams, ScalingAndDividerForTarget)
|
TEST(RenderVideoParams, ScalingAndDividerForTarget)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(olive::VideoParams::GetScaledDimension(100, 3), 33);
|
EXPECT_EQ(olive::VideoParams::GetScaledDimension(100, 3), 33);
|
||||||
EXPECT_EQ(olive::VideoParams::GetDividerForTargetResolution(
|
EXPECT_EQ(olive::VideoParams::GetDividerForTargetResolution(1920, 1080, 960,
|
||||||
1920, 1080, 960, 540),
|
540),
|
||||||
2);
|
2);
|
||||||
EXPECT_EQ(olive::VideoParams::GetDividerForTargetResolution(
|
EXPECT_EQ(olive::VideoParams::GetDividerForTargetResolution(1920, 1080, 480,
|
||||||
1920, 1080, 480, 270),
|
270),
|
||||||
4);
|
4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,8 +189,7 @@ TEST(RenderVideoParams, SaveLoadRoundTripExtended)
|
|||||||
EXPECT_FLOAT_EQ(loaded.x(), 1.5f);
|
EXPECT_FLOAT_EQ(loaded.x(), 1.5f);
|
||||||
EXPECT_FLOAT_EQ(loaded.y(), -2.25f);
|
EXPECT_FLOAT_EQ(loaded.y(), -2.25f);
|
||||||
EXPECT_EQ(loaded.stream_index(), 7);
|
EXPECT_EQ(loaded.stream_index(), 7);
|
||||||
EXPECT_EQ(loaded.video_type(),
|
EXPECT_EQ(loaded.video_type(), olive::VideoParams::kVideoTypeImageSequence);
|
||||||
olive::VideoParams::kVideoTypeImageSequence);
|
|
||||||
EXPECT_EQ(loaded.frame_rate(), olive::core::rational(30000, 1001));
|
EXPECT_EQ(loaded.frame_rate(), olive::core::rational(30000, 1001));
|
||||||
EXPECT_EQ(loaded.start_time(), 123);
|
EXPECT_EQ(loaded.start_time(), 123);
|
||||||
EXPECT_EQ(loaded.duration(), 456);
|
EXPECT_EQ(loaded.duration(), 456);
|
||||||
|
|||||||
@@ -49,7 +49,8 @@
|
|||||||
using namespace olive;
|
using namespace olive;
|
||||||
using namespace olive::core;
|
using namespace olive::core;
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
#ifdef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
#ifdef OAK_ENABLE_DYNAMIC_RENDER_BACKEND
|
||||||
bool IsRenderBackendAvailable(const QString &backend)
|
bool IsRenderBackendAvailable(const QString &backend)
|
||||||
@@ -96,8 +97,8 @@ QString WorkerBinaryPath()
|
|||||||
// The test binary lives in cmake-build-debug/tests/gtest; the worker is in
|
// The test binary lives in cmake-build-debug/tests/gtest; the worker is in
|
||||||
// cmake-build-debug/app.
|
// cmake-build-debug/app.
|
||||||
QDir dir(QCoreApplication::applicationDirPath());
|
QDir dir(QCoreApplication::applicationDirPath());
|
||||||
dir.cdUp(); // tests/gtest -> tests
|
dir.cdUp(); // tests/gtest -> tests
|
||||||
dir.cdUp(); // tests -> build dir
|
dir.cdUp(); // tests -> build dir
|
||||||
dir.cd(QStringLiteral("app"));
|
dir.cd(QStringLiteral("app"));
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return dir.filePath(QStringLiteral("oak-render-worker.exe"));
|
return dir.filePath(QStringLiteral("oak-render-worker.exe"));
|
||||||
@@ -140,8 +141,10 @@ void SaveFrameAsPng(const void *data, int width, int height,
|
|||||||
for (int x = 0; x < width; ++x) {
|
for (int x = 0; x < width; ++x) {
|
||||||
for (int c = 0; c < 4; ++c) {
|
for (int c = 0; c < 4; ++c) {
|
||||||
float v = src[(y * width + x) * 4 + c];
|
float v = src[(y * width + x) * 4 + c];
|
||||||
if (v < 0.0f) v = 0.0f;
|
if (v < 0.0f)
|
||||||
if (v > 1.0f) v = 1.0f;
|
v = 0.0f;
|
||||||
|
if (v > 1.0f)
|
||||||
|
v = 1.0f;
|
||||||
dst[(x * 4) + c] = static_cast<uchar>(v * 255.0f);
|
dst[(x * 4) + c] = static_cast<uchar>(v * 255.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +156,7 @@ void SaveFrameAsPng(const void *data, int width, int height,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class RenderWorkerFootageTest : public ::testing::Test {
|
class RenderWorkerFootageTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
@@ -210,8 +213,8 @@ protected:
|
|||||||
temp_dir_.filePath(QStringLiteral("worker_graph.ove")));
|
temp_dir_.filePath(QStringLiteral("worker_graph.ove")));
|
||||||
|
|
||||||
ProjectSerializer::Result r = ProjectSerializer::Save(
|
ProjectSerializer::Result r = ProjectSerializer::Save(
|
||||||
ProjectSerializer::SaveData(ProjectSerializer::kProject, project_.get(),
|
ProjectSerializer::SaveData(ProjectSerializer::kProject,
|
||||||
project_file_),
|
project_.get(), project_file_),
|
||||||
false);
|
false);
|
||||||
ASSERT_EQ(r.code(), ProjectSerializer::kSuccess)
|
ASSERT_EQ(r.code(), ProjectSerializer::kSuccess)
|
||||||
<< "Failed to save project file: " << r.GetDetails().toStdString();
|
<< "Failed to save project file: " << r.GetDetails().toStdString();
|
||||||
@@ -222,7 +225,8 @@ protected:
|
|||||||
{
|
{
|
||||||
// ---- decode a frame so we know the dimensions and slot sizes ----
|
// ---- decode a frame so we know the dimensions and slot sizes ----
|
||||||
DecoderPtr decoder = Decoder::CreateFromID(QStringLiteral("ffmpeg"));
|
DecoderPtr decoder = Decoder::CreateFromID(QStringLiteral("ffmpeg"));
|
||||||
if (!decoder || !decoder->Open(Decoder::CodecStream(demo_path_, 0, nullptr))) {
|
if (!decoder ||
|
||||||
|
!decoder->Open(Decoder::CodecStream(demo_path_, 0, nullptr))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Decoder::RetrieveVideoParams retrieve;
|
Decoder::RetrieveVideoParams retrieve;
|
||||||
@@ -251,10 +255,10 @@ protected:
|
|||||||
output_shm_key_ = ipc::SharedMemoryRegion::MakeKey(owner_pid, 0);
|
output_shm_key_ = ipc::SharedMemoryRegion::MakeKey(owner_pid, 0);
|
||||||
input_shm_key_ = ipc::SharedMemoryRegion::MakeKey(owner_pid, 1);
|
input_shm_key_ = ipc::SharedMemoryRegion::MakeKey(owner_pid, 1);
|
||||||
|
|
||||||
const size_t output_bytes = ipc::FrameSlotPool::BytesNeeded(
|
const size_t output_bytes =
|
||||||
kOutputSlots, output_data_bytes_);
|
ipc::FrameSlotPool::BytesNeeded(kOutputSlots, output_data_bytes_);
|
||||||
const size_t input_bytes = ipc::FrameSlotPool::BytesNeeded(
|
const size_t input_bytes =
|
||||||
kInputSlots, input_data_bytes_);
|
ipc::FrameSlotPool::BytesNeeded(kInputSlots, input_data_bytes_);
|
||||||
|
|
||||||
if (!output_region_.Open(output_shm_key_, output_bytes,
|
if (!output_region_.Open(output_shm_key_, output_bytes,
|
||||||
ipc::SharedMemoryRegion::kCreate)) {
|
ipc::SharedMemoryRegion::kCreate)) {
|
||||||
@@ -278,7 +282,8 @@ protected:
|
|||||||
|
|
||||||
// ---- spawn worker ----
|
// ---- spawn worker ----
|
||||||
worker_.setProcessChannelMode(QProcess::SeparateChannels);
|
worker_.setProcessChannelMode(QProcess::SeparateChannels);
|
||||||
worker_.start(worker_path_, QStringList{QStringLiteral("--backend"), backend});
|
worker_.start(worker_path_,
|
||||||
|
QStringList{ QStringLiteral("--backend"), backend });
|
||||||
if (!worker_.waitForStarted(kTimeoutMs)) {
|
if (!worker_.waitForStarted(kTimeoutMs)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -333,8 +338,8 @@ protected:
|
|||||||
if (!input_pool_->Acquire(&input_slot)) {
|
if (!input_pool_->Acquire(&input_slot)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::memcpy(input_pool_->SlotData(input_slot), decoded_frame_->const_data(),
|
std::memcpy(input_pool_->SlotData(input_slot),
|
||||||
input_data_bytes_);
|
decoded_frame_->const_data(), input_data_bytes_);
|
||||||
ipc::FrameSlotMeta *meta = input_pool_->Meta(input_slot);
|
ipc::FrameSlotMeta *meta = input_pool_->Meta(input_slot);
|
||||||
meta->id = 0;
|
meta->id = 0;
|
||||||
meta->time_num = 0;
|
meta->time_num = 0;
|
||||||
@@ -345,9 +350,10 @@ protected:
|
|||||||
meta->channel_count = decoded_frame_->channel_count();
|
meta->channel_count = decoded_frame_->channel_count();
|
||||||
meta->linesize = input_stride_;
|
meta->linesize = input_stride_;
|
||||||
meta->data_size = int32_t(input_data_bytes_);
|
meta->data_size = int32_t(input_data_bytes_);
|
||||||
std::strncpy(meta->colorspace,
|
std::strncpy(
|
||||||
decoded_frame_->video_params().colorspace().toUtf8().constData(),
|
meta->colorspace,
|
||||||
sizeof(meta->colorspace) - 1);
|
decoded_frame_->video_params().colorspace().toUtf8().constData(),
|
||||||
|
sizeof(meta->colorspace) - 1);
|
||||||
meta->colorspace[sizeof(meta->colorspace) - 1] = '\0';
|
meta->colorspace[sizeof(meta->colorspace) - 1] = '\0';
|
||||||
input_pool_->Publish(input_slot);
|
input_pool_->Publish(input_slot);
|
||||||
|
|
||||||
@@ -363,7 +369,8 @@ protected:
|
|||||||
req.mode = int(RenderMode::kOnline);
|
req.mode = int(RenderMode::kOnline);
|
||||||
req.input_slot = 0;
|
req.input_slot = 0;
|
||||||
if (!ipc::WriteMessage(&worker_, req.ToJson())) {
|
if (!ipc::WriteMessage(&worker_, req.ToJson())) {
|
||||||
std::cerr << "RenderFrameAndWait: failed to write request" << std::endl;
|
std::cerr << "RenderFrameAndWait: failed to write request"
|
||||||
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,8 +385,9 @@ protected:
|
|||||||
std::cerr << "RenderFrameAndWait: unexpected message type "
|
std::cerr << "RenderFrameAndWait: unexpected message type "
|
||||||
<< ready[QStringLiteral("type")].toString().toStdString()
|
<< ready[QStringLiteral("type")].toString().toStdString()
|
||||||
<< " body="
|
<< " body="
|
||||||
<< QJsonDocument(ready).toJson(QJsonDocument::Compact)
|
<< QJsonDocument(ready)
|
||||||
.toStdString()
|
.toJson(QJsonDocument::Compact)
|
||||||
|
.toStdString()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -407,8 +415,9 @@ protected:
|
|||||||
if (worker_.state() == QProcess::NotRunning) {
|
if (worker_.state() == QProcess::NotRunning) {
|
||||||
std::cerr << "WaitForMessage: worker exited with code "
|
std::cerr << "WaitForMessage: worker exited with code "
|
||||||
<< worker_.exitCode() << std::endl;
|
<< worker_.exitCode() << std::endl;
|
||||||
std::cerr << "Worker stdout buffer: "
|
std::cerr
|
||||||
<< read_buffer_.toStdString() << std::endl;
|
<< "Worker stdout buffer: " << read_buffer_.toStdString()
|
||||||
|
<< std::endl;
|
||||||
QByteArray err = worker_.readAllStandardError();
|
QByteArray err = worker_.readAllStandardError();
|
||||||
if (!err.isEmpty()) {
|
if (!err.isEmpty()) {
|
||||||
std::cerr << "Worker stderr:\n"
|
std::cerr << "Worker stderr:\n"
|
||||||
@@ -417,8 +426,9 @@ protected:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cerr << "WaitForMessage: timeout, buffer="
|
std::cerr
|
||||||
<< read_buffer_.toStdString() << std::endl;
|
<< "WaitForMessage: timeout, buffer=" << read_buffer_.toStdString()
|
||||||
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,19 +483,21 @@ TEST_F(RenderWorkerFootageTest, VulkanFootageIsNotBlack)
|
|||||||
ASSERT_EQ(int(consumed_slot), output_slot);
|
ASSERT_EQ(int(consumed_slot), output_slot);
|
||||||
|
|
||||||
const void *output_data = output_pool_->SlotData(consumed_slot);
|
const void *output_data = output_pool_->SlotData(consumed_slot);
|
||||||
const double brightness = SampleBrightnessF32(
|
const double brightness =
|
||||||
output_data, output_width_, output_height_,
|
SampleBrightnessF32(output_data, output_width_, output_height_,
|
||||||
output_width_ * 4 * int(sizeof(float)));
|
output_width_ * 4 * int(sizeof(float)));
|
||||||
|
|
||||||
EXPECT_GT(brightness, 0.01)
|
EXPECT_GT(brightness, 0.01)
|
||||||
<< "Worker output frame is black (brightness=" << brightness << ")";
|
<< "Worker output frame is black (brightness=" << brightness << ")";
|
||||||
|
|
||||||
SaveFrameAsPng(output_data, output_width_, output_height_,
|
SaveFrameAsPng(
|
||||||
temp_dir_.filePath(QStringLiteral("worker_output_vulkan.png")));
|
output_data, output_width_, output_height_,
|
||||||
|
temp_dir_.filePath(QStringLiteral("worker_output_vulkan.png")));
|
||||||
QFile::remove(QStringLiteral("/tmp/worker_output_vulkan.png"));
|
QFile::remove(QStringLiteral("/tmp/worker_output_vulkan.png"));
|
||||||
QFile::copy(temp_dir_.filePath(QStringLiteral("worker_output_vulkan.png")),
|
QFile::copy(temp_dir_.filePath(QStringLiteral("worker_output_vulkan.png")),
|
||||||
QStringLiteral("/tmp/worker_output_vulkan.png"));
|
QStringLiteral("/tmp/worker_output_vulkan.png"));
|
||||||
std::cerr << "Vulkan output copied to /tmp/worker_output_vulkan.png" << std::endl;
|
std::cerr << "Vulkan output copied to /tmp/worker_output_vulkan.png"
|
||||||
|
<< std::endl;
|
||||||
output_pool_->Release(consumed_slot);
|
output_pool_->Release(consumed_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,19 +519,20 @@ TEST_F(RenderWorkerFootageTest, OpenGLFootageIsNotBlack)
|
|||||||
ASSERT_EQ(int(consumed_slot), output_slot);
|
ASSERT_EQ(int(consumed_slot), output_slot);
|
||||||
|
|
||||||
const void *output_data = output_pool_->SlotData(consumed_slot);
|
const void *output_data = output_pool_->SlotData(consumed_slot);
|
||||||
const double brightness = SampleBrightnessF32(
|
const double brightness =
|
||||||
output_data, output_width_, output_height_,
|
SampleBrightnessF32(output_data, output_width_, output_height_,
|
||||||
output_width_ * 4 * int(sizeof(float)));
|
output_width_ * 4 * int(sizeof(float)));
|
||||||
|
|
||||||
EXPECT_GT(brightness, 0.01)
|
EXPECT_GT(brightness, 0.01)
|
||||||
<< "Worker output frame is black (brightness=" << brightness << ")";
|
<< "Worker output frame is black (brightness=" << brightness << ")";
|
||||||
|
|
||||||
SaveFrameAsPng(output_data, output_width_, output_height_,
|
SaveFrameAsPng(
|
||||||
temp_dir_.filePath(QStringLiteral("worker_output_opengl.png")));
|
output_data, output_width_, output_height_,
|
||||||
|
temp_dir_.filePath(QStringLiteral("worker_output_opengl.png")));
|
||||||
QFile::remove(QStringLiteral("/tmp/worker_output_opengl.png"));
|
QFile::remove(QStringLiteral("/tmp/worker_output_opengl.png"));
|
||||||
QFile::copy(temp_dir_.filePath(QStringLiteral("worker_output_opengl.png")),
|
QFile::copy(temp_dir_.filePath(QStringLiteral("worker_output_opengl.png")),
|
||||||
QStringLiteral("/tmp/worker_output_opengl.png"));
|
QStringLiteral("/tmp/worker_output_opengl.png"));
|
||||||
std::cerr << "OpenGL output copied to /tmp/worker_output_opengl.png" << std::endl;
|
std::cerr << "OpenGL output copied to /tmp/worker_output_opengl.png"
|
||||||
|
<< std::endl;
|
||||||
output_pool_->Release(consumed_slot);
|
output_pool_->Release(consumed_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ TEST(Shaders, ResourcesAvailable)
|
|||||||
|
|
||||||
for (const QString &path : shader_paths) {
|
for (const QString &path : shader_paths) {
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
ASSERT_TRUE(file.exists()) << "Missing shader resource: "
|
ASSERT_TRUE(file.exists())
|
||||||
<< path.toStdString();
|
<< "Missing shader resource: " << path.toStdString();
|
||||||
ASSERT_TRUE(file.open(QIODevice::ReadOnly))
|
ASSERT_TRUE(file.open(QIODevice::ReadOnly))
|
||||||
<< "Failed to open shader resource: " << path.toStdString();
|
<< "Failed to open shader resource: " << path.toStdString();
|
||||||
const QByteArray contents = file.readAll();
|
const QByteArray contents = file.readAll();
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
#include "task/taskmanager.h"
|
#include "task/taskmanager.h"
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
class DummyTask final : public olive::Task {
|
class DummyTask final : public olive::Task {
|
||||||
public:
|
public:
|
||||||
explicit DummyTask(bool *ran)
|
explicit DummyTask(bool *ran)
|
||||||
@@ -74,9 +75,8 @@ TEST(TaskManager, AddAndRunTask)
|
|||||||
DummyTask *task = new DummyTask(&ran);
|
DummyTask *task = new DummyTask(&ran);
|
||||||
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
QObject::connect(task, &olive::Task::Finished, &loop, [&loop](olive::Task *, bool) {
|
QObject::connect(task, &olive::Task::Finished, &loop,
|
||||||
loop.quit();
|
[&loop](olive::Task *, bool) { loop.quit(); });
|
||||||
});
|
|
||||||
|
|
||||||
mgr->AddTask(task);
|
mgr->AddTask(task);
|
||||||
|
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ TEST(TimecodeMetadata, ParsesDropFrameTimecode)
|
|||||||
TEST(TimecodeMetadata, ParsesBwfTimeReference)
|
TEST(TimecodeMetadata, ParsesBwfTimeReference)
|
||||||
{
|
{
|
||||||
const olive::TimecodeMetadata::SourceTime parsed =
|
const olive::TimecodeMetadata::SourceTime parsed =
|
||||||
olive::TimecodeMetadata::FromBwfTimeReference(
|
olive::TimecodeMetadata::FromBwfTimeReference(QStringLiteral("96000"),
|
||||||
QStringLiteral("96000"), 48000);
|
48000);
|
||||||
|
|
||||||
ASSERT_TRUE(parsed.valid);
|
ASSERT_TRUE(parsed.valid);
|
||||||
EXPECT_EQ(parsed.source, QStringLiteral("bwf_time_reference"));
|
EXPECT_EQ(parsed.source, QStringLiteral("bwf_time_reference"));
|
||||||
@@ -63,20 +63,20 @@ TEST(TimecodeMetadata, RejectsInvalidMetadata)
|
|||||||
EXPECT_FALSE(olive::TimecodeMetadata::FromBwfTimeReference(
|
EXPECT_FALSE(olive::TimecodeMetadata::FromBwfTimeReference(
|
||||||
QStringLiteral("not-a-number"), 48000)
|
QStringLiteral("not-a-number"), 48000)
|
||||||
.valid);
|
.valid);
|
||||||
EXPECT_FALSE(olive::TimecodeMetadata::FromBwfTimeReference(
|
EXPECT_FALSE(
|
||||||
QStringLiteral("123"), 0)
|
olive::TimecodeMetadata::FromBwfTimeReference(QStringLiteral("123"), 0)
|
||||||
.valid);
|
.valid);
|
||||||
EXPECT_FALSE(olive::TimecodeMetadata::FromTimecodeString(
|
EXPECT_FALSE(
|
||||||
QStringLiteral("not-a-timecode"),
|
olive::TimecodeMetadata::FromTimecodeString(
|
||||||
olive::core::rational(1, 24))
|
QStringLiteral("not-a-timecode"), olive::core::rational(1, 24))
|
||||||
.valid);
|
.valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TimecodeMetadata, FromBwfTimeReferenceZeroSampleRateIsInvalid)
|
TEST(TimecodeMetadata, FromBwfTimeReferenceZeroSampleRateIsInvalid)
|
||||||
{
|
{
|
||||||
EXPECT_FALSE(olive::TimecodeMetadata::FromBwfTimeReference(
|
EXPECT_FALSE(
|
||||||
QStringLiteral("0"), 0)
|
olive::TimecodeMetadata::FromBwfTimeReference(QStringLiteral("0"), 0)
|
||||||
.valid);
|
.valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TimecodeMetadata, FootageDescriptionWithoutSourceStartTime)
|
TEST(TimecodeMetadata, FootageDescriptionWithoutSourceStartTime)
|
||||||
@@ -113,8 +113,7 @@ TEST(TimecodeMetadata, FootagePersistsSourceStartTime)
|
|||||||
writer.writeStartElement(QStringLiteral("custom"));
|
writer.writeStartElement(QStringLiteral("custom"));
|
||||||
writer.writeTextElement(QStringLiteral("timestamp"), QStringLiteral("0"));
|
writer.writeTextElement(QStringLiteral("timestamp"), QStringLiteral("0"));
|
||||||
writer.writeStartElement(QStringLiteral("sourcestarttime"));
|
writer.writeStartElement(QStringLiteral("sourcestarttime"));
|
||||||
writer.writeAttribute(QStringLiteral("source"),
|
writer.writeAttribute(QStringLiteral("source"), QStringLiteral("timecode"));
|
||||||
QStringLiteral("timecode"));
|
|
||||||
writer.writeCharacters(QStringLiteral("3600/1"));
|
writer.writeCharacters(QStringLiteral("3600/1"));
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
writer.writeEndElement();
|
writer.writeEndElement();
|
||||||
|
|||||||
@@ -52,13 +52,17 @@ TEST(TimelineCoordinate, CopyAndAssignment)
|
|||||||
TEST(TimelineCoordinate, Equality)
|
TEST(TimelineCoordinate, Equality)
|
||||||
{
|
{
|
||||||
olive::TimelineCoordinate a(olive::core::rational(5, 1),
|
olive::TimelineCoordinate a(olive::core::rational(5, 1),
|
||||||
olive::Track::Reference(olive::Track::kVideo, 1));
|
olive::Track::Reference(olive::Track::kVideo,
|
||||||
|
1));
|
||||||
olive::TimelineCoordinate b(olive::core::rational(5, 1),
|
olive::TimelineCoordinate b(olive::core::rational(5, 1),
|
||||||
olive::Track::Reference(olive::Track::kVideo, 1));
|
olive::Track::Reference(olive::Track::kVideo,
|
||||||
|
1));
|
||||||
olive::TimelineCoordinate c(olive::core::rational(6, 1),
|
olive::TimelineCoordinate c(olive::core::rational(6, 1),
|
||||||
olive::Track::Reference(olive::Track::kVideo, 1));
|
olive::Track::Reference(olive::Track::kVideo,
|
||||||
|
1));
|
||||||
olive::TimelineCoordinate d(olive::core::rational(5, 1),
|
olive::TimelineCoordinate d(olive::core::rational(5, 1),
|
||||||
olive::Track::Reference(olive::Track::kAudio, 1));
|
olive::Track::Reference(olive::Track::kAudio,
|
||||||
|
1));
|
||||||
|
|
||||||
EXPECT_EQ(a.GetFrame(), b.GetFrame());
|
EXPECT_EQ(a.GetFrame(), b.GetFrame());
|
||||||
EXPECT_EQ(a.GetTrack(), b.GetTrack());
|
EXPECT_EQ(a.GetTrack(), b.GetTrack());
|
||||||
|
|||||||
@@ -51,20 +51,17 @@ TEST(TimelineMarkerList, OrderAndLookup)
|
|||||||
1,
|
1,
|
||||||
olive::core::TimeRange(olive::core::rational(10, 1),
|
olive::core::TimeRange(olive::core::rational(10, 1),
|
||||||
olive::core::rational(10, 1)),
|
olive::core::rational(10, 1)),
|
||||||
QStringLiteral("A"),
|
QStringLiteral("A"), &list);
|
||||||
&list);
|
|
||||||
olive::TimelineMarker marker_b(
|
olive::TimelineMarker marker_b(
|
||||||
2,
|
2,
|
||||||
olive::core::TimeRange(olive::core::rational(5, 1),
|
olive::core::TimeRange(olive::core::rational(5, 1),
|
||||||
olive::core::rational(5, 1)),
|
olive::core::rational(5, 1)),
|
||||||
QStringLiteral("B"),
|
QStringLiteral("B"), &list);
|
||||||
&list);
|
|
||||||
olive::TimelineMarker marker_c(
|
olive::TimelineMarker marker_c(
|
||||||
3,
|
3,
|
||||||
olive::core::TimeRange(olive::core::rational(20, 1),
|
olive::core::TimeRange(olive::core::rational(20, 1),
|
||||||
olive::core::rational(20, 1)),
|
olive::core::rational(20, 1)),
|
||||||
QStringLiteral("C"),
|
QStringLiteral("C"), &list);
|
||||||
&list);
|
|
||||||
|
|
||||||
ASSERT_EQ(list.size(), 3);
|
ASSERT_EQ(list.size(), 3);
|
||||||
auto it = list.cbegin();
|
auto it = list.cbegin();
|
||||||
@@ -85,7 +82,8 @@ TEST(TimelineMarkerList, GetMarkerAtTimeReturnsNullWhenEmpty)
|
|||||||
{
|
{
|
||||||
olive::TimelineMarkerList list;
|
olive::TimelineMarkerList list;
|
||||||
EXPECT_EQ(list.GetMarkerAtTime(olive::core::rational(10, 1)), nullptr);
|
EXPECT_EQ(list.GetMarkerAtTime(olive::core::rational(10, 1)), nullptr);
|
||||||
EXPECT_EQ(list.GetClosestMarkerToTime(olive::core::rational(10, 1)), nullptr);
|
EXPECT_EQ(list.GetClosestMarkerToTime(olive::core::rational(10, 1)),
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TimelineMarkerList, SaveLoadWithUnknownElements)
|
TEST(TimelineMarkerList, SaveLoadWithUnknownElements)
|
||||||
@@ -95,8 +93,7 @@ TEST(TimelineMarkerList, SaveLoadWithUnknownElements)
|
|||||||
4,
|
4,
|
||||||
olive::core::TimeRange(olive::core::rational(12, 1),
|
olive::core::TimeRange(olive::core::rational(12, 1),
|
||||||
olive::core::rational(15, 1)),
|
olive::core::rational(15, 1)),
|
||||||
QStringLiteral("Span"),
|
QStringLiteral("Span"), &list);
|
||||||
&list);
|
|
||||||
|
|
||||||
QByteArray xml;
|
QByteArray xml;
|
||||||
QBuffer buffer(&xml);
|
QBuffer buffer(&xml);
|
||||||
@@ -130,8 +127,7 @@ TEST(TimelineMarkerCommands, AddRemoveAndChange)
|
|||||||
&list,
|
&list,
|
||||||
olive::core::TimeRange(olive::core::rational(1, 1),
|
olive::core::TimeRange(olive::core::rational(1, 1),
|
||||||
olive::core::rational(2, 1)),
|
olive::core::rational(2, 1)),
|
||||||
QStringLiteral("One"),
|
QStringLiteral("One"), 1);
|
||||||
1);
|
|
||||||
add.redo_now();
|
add.redo_now();
|
||||||
ASSERT_EQ(list.size(), 1);
|
ASSERT_EQ(list.size(), 1);
|
||||||
auto *marker = list.front();
|
auto *marker = list.front();
|
||||||
@@ -159,14 +155,12 @@ TEST(TimelineMarkerCommands, AddRemoveAndChange)
|
|||||||
2,
|
2,
|
||||||
olive::core::TimeRange(olive::core::rational(5, 1),
|
olive::core::TimeRange(olive::core::rational(5, 1),
|
||||||
olive::core::rational(5, 1)),
|
olive::core::rational(5, 1)),
|
||||||
QStringLiteral("Two"),
|
QStringLiteral("Two"), &list);
|
||||||
&list);
|
|
||||||
EXPECT_EQ(list.front()->time().in(), olive::core::rational(1, 1));
|
EXPECT_EQ(list.front()->time().in(), olive::core::rational(1, 1));
|
||||||
|
|
||||||
olive::MarkerChangeTimeCommand move(
|
olive::MarkerChangeTimeCommand move(
|
||||||
marker,
|
marker, olive::core::TimeRange(olive::core::rational(0, 1),
|
||||||
olive::core::TimeRange(olive::core::rational(0, 1),
|
olive::core::rational(0, 1)));
|
||||||
olive::core::rational(0, 1)));
|
|
||||||
move.redo_now();
|
move.redo_now();
|
||||||
EXPECT_EQ(list.front(), marker);
|
EXPECT_EQ(list.front(), marker);
|
||||||
move.undo_now();
|
move.undo_now();
|
||||||
@@ -180,8 +174,7 @@ TEST(TimelineMarkerCommands, AddCommandUndo)
|
|||||||
&list,
|
&list,
|
||||||
olive::core::TimeRange(olive::core::rational(5, 1),
|
olive::core::TimeRange(olive::core::rational(5, 1),
|
||||||
olive::core::rational(5, 1)),
|
olive::core::rational(5, 1)),
|
||||||
QStringLiteral("UndoMe"),
|
QStringLiteral("UndoMe"), 2);
|
||||||
2);
|
|
||||||
add.redo_now();
|
add.redo_now();
|
||||||
EXPECT_EQ(list.size(), 1);
|
EXPECT_EQ(list.size(), 1);
|
||||||
add.undo_now();
|
add.undo_now();
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ extern "C" {
|
|||||||
using namespace olive;
|
using namespace olive;
|
||||||
using namespace olive::core;
|
using namespace olive::core;
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
AudioParams MakeMonoParams(int sample_rate)
|
AudioParams MakeMonoParams(int sample_rate)
|
||||||
{
|
{
|
||||||
@@ -55,17 +56,16 @@ void WritePartialWaveform(AudioWaveformCache *cache, int sample_rate)
|
|||||||
waveform.OverwriteSamples(buf, sample_rate, rational(1));
|
waveform.OverwriteSamples(buf, sample_rate, rational(1));
|
||||||
|
|
||||||
// Tell the cache that only the middle second is valid in a 3-second clip.
|
// Tell the cache that only the middle second is valid in a 3-second clip.
|
||||||
cache->WriteWaveform(TimeRange(1, 2),
|
cache->WriteWaveform(TimeRange(1, 2), TimeRangeList({ TimeRange(1, 2) }),
|
||||||
TimeRangeList({ TimeRange(1, 2) }),
|
|
||||||
&waveform);
|
&waveform);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST(TimelineWaveformSync, ExtractEnvelopeUsesOnlyValidatedRanges)
|
TEST(TimelineWaveformSync, ExtractEnvelopeUsesOnlyValidatedRanges)
|
||||||
{
|
{
|
||||||
constexpr int kSampleRate = 48000;
|
constexpr int kSampleRate = 48000;
|
||||||
constexpr size_t kWindowSamples = kSampleRate / 20; // 50 ms windows
|
constexpr size_t kWindowSamples = kSampleRate / 20; // 50 ms windows
|
||||||
|
|
||||||
AudioWaveformCache cache;
|
AudioWaveformCache cache;
|
||||||
WritePartialWaveform(&cache, kSampleRate);
|
WritePartialWaveform(&cache, kSampleRate);
|
||||||
@@ -76,8 +76,8 @@ TEST(TimelineWaveformSync, ExtractEnvelopeUsesOnlyValidatedRanges)
|
|||||||
clip.sample_rate = kSampleRate;
|
clip.sample_rate = kSampleRate;
|
||||||
|
|
||||||
const QVector<double> envelope =
|
const QVector<double> envelope =
|
||||||
TimelineWaveformSync::ExtractWaveformCacheEnvelope(
|
TimelineWaveformSync::ExtractWaveformCacheEnvelope(clip, kSampleRate,
|
||||||
clip, kSampleRate, kWindowSamples);
|
kWindowSamples);
|
||||||
|
|
||||||
// 3 seconds at 20 windows per second == 60 windows.
|
// 3 seconds at 20 windows per second == 60 windows.
|
||||||
EXPECT_EQ(envelope.size(), 60);
|
EXPECT_EQ(envelope.size(), 60);
|
||||||
@@ -134,8 +134,7 @@ TEST(TimelineWaveformSync, EmptyCacheIsNotReady)
|
|||||||
clip.set_length_and_media_out(rational(3));
|
clip.set_length_and_media_out(rational(3));
|
||||||
clip.set_media_in(rational(0));
|
clip.set_media_in(rational(0));
|
||||||
|
|
||||||
Node::ConnectEdge(
|
Node::ConnectEdge(&footage, NodeInput(&clip, ClipBlock::kBufferIn));
|
||||||
&footage, NodeInput(&clip, ClipBlock::kBufferIn));
|
|
||||||
|
|
||||||
WaveformSyncClip out;
|
WaveformSyncClip out;
|
||||||
EXPECT_FALSE(TimelineWaveformSync::GetWaveformSyncClip(&clip, &out));
|
EXPECT_FALSE(TimelineWaveformSync::GetWaveformSyncClip(&clip, &out));
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ TEST(TimelineWorkArea, SaveLoadRoundTrip)
|
|||||||
olive::TimelineWorkArea workarea;
|
olive::TimelineWorkArea workarea;
|
||||||
workarea.set_enabled(true);
|
workarea.set_enabled(true);
|
||||||
workarea.set_range(olive::core::TimeRange(olive::core::rational(2, 1),
|
workarea.set_range(olive::core::TimeRange(olive::core::rational(2, 1),
|
||||||
olive::core::rational(6, 1)));
|
olive::core::rational(6, 1)));
|
||||||
|
|
||||||
QByteArray xml;
|
QByteArray xml;
|
||||||
QBuffer buffer(&xml);
|
QBuffer buffer(&xml);
|
||||||
@@ -51,7 +51,7 @@ TEST(TimelineWorkArea, SaveLoadRoundTrip)
|
|||||||
EXPECT_TRUE(loaded.enabled());
|
EXPECT_TRUE(loaded.enabled());
|
||||||
EXPECT_EQ(loaded.range(),
|
EXPECT_EQ(loaded.range(),
|
||||||
olive::core::TimeRange(olive::core::rational(2, 1),
|
olive::core::TimeRange(olive::core::rational(2, 1),
|
||||||
olive::core::rational(6, 1)));
|
olive::core::rational(6, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TimelineWorkArea, DisabledWorkAreaRoundTrip)
|
TEST(TimelineWorkArea, DisabledWorkAreaRoundTrip)
|
||||||
@@ -59,7 +59,7 @@ TEST(TimelineWorkArea, DisabledWorkAreaRoundTrip)
|
|||||||
olive::TimelineWorkArea workarea;
|
olive::TimelineWorkArea workarea;
|
||||||
workarea.set_enabled(false);
|
workarea.set_enabled(false);
|
||||||
workarea.set_range(olive::core::TimeRange(olive::core::rational(0, 1),
|
workarea.set_range(olive::core::TimeRange(olive::core::rational(0, 1),
|
||||||
olive::core::rational(10, 1)));
|
olive::core::rational(10, 1)));
|
||||||
|
|
||||||
QByteArray xml;
|
QByteArray xml;
|
||||||
QBuffer buffer(&xml);
|
QBuffer buffer(&xml);
|
||||||
@@ -82,14 +82,14 @@ TEST(TimelineWorkArea, DisabledWorkAreaRoundTrip)
|
|||||||
EXPECT_FALSE(loaded.enabled());
|
EXPECT_FALSE(loaded.enabled());
|
||||||
EXPECT_EQ(loaded.range(),
|
EXPECT_EQ(loaded.range(),
|
||||||
olive::core::TimeRange(olive::core::rational(0, 1),
|
olive::core::TimeRange(olive::core::rational(0, 1),
|
||||||
olive::core::rational(10, 1)));
|
olive::core::rational(10, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(TimelineWorkArea, SetRangeUpdatesInOut)
|
TEST(TimelineWorkArea, SetRangeUpdatesInOut)
|
||||||
{
|
{
|
||||||
olive::TimelineWorkArea workarea;
|
olive::TimelineWorkArea workarea;
|
||||||
workarea.set_range(olive::core::TimeRange(olive::core::rational(3, 1),
|
workarea.set_range(olive::core::TimeRange(olive::core::rational(3, 1),
|
||||||
olive::core::rational(8, 1)));
|
olive::core::rational(8, 1)));
|
||||||
|
|
||||||
EXPECT_EQ(workarea.in(), olive::core::rational(3, 1));
|
EXPECT_EQ(workarea.in(), olive::core::rational(3, 1));
|
||||||
EXPECT_EQ(workarea.out(), olive::core::rational(8, 1));
|
EXPECT_EQ(workarea.out(), olive::core::rational(8, 1));
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
#include "undo/undostack.h"
|
#include "undo/undostack.h"
|
||||||
#include "undo/undocommand.h"
|
#include "undo/undocommand.h"
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
class TestCommand final : public olive::UndoCommand {
|
class TestCommand final : public olive::UndoCommand {
|
||||||
public:
|
public:
|
||||||
explicit TestCommand(int *value)
|
explicit TestCommand(int *value)
|
||||||
|
|||||||
+374
-368
@@ -25,9 +25,12 @@
|
|||||||
using namespace olive;
|
using namespace olive;
|
||||||
using namespace olive::core;
|
using namespace olive::core;
|
||||||
|
|
||||||
namespace olive {
|
namespace olive
|
||||||
namespace viewer {
|
{
|
||||||
namespace test {
|
namespace viewer
|
||||||
|
{
|
||||||
|
namespace test
|
||||||
|
{
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Smoke Test: ViewerPlaybackTimer
|
// Smoke Test: ViewerPlaybackTimer
|
||||||
@@ -35,92 +38,92 @@ namespace test {
|
|||||||
|
|
||||||
TEST(ViewerSmokeTimer, DefaultConstruction)
|
TEST(ViewerSmokeTimer, DefaultConstruction)
|
||||||
{
|
{
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
// Timer should be in a valid but not-started state
|
// Timer should be in a valid but not-started state
|
||||||
// After Start() is called, it should return valid timestamps
|
// After Start() is called, it should return valid timestamps
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeTimer, BasicTiming)
|
TEST(ViewerSmokeTimer, BasicTiming)
|
||||||
{
|
{
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
|
|
||||||
// Start at timestamp 0, 1x speed, 24fps (timebase = 1/24)
|
// Start at timestamp 0, 1x speed, 24fps (timebase = 1/24)
|
||||||
timer.Start(0, 1, 1.0 / 24.0);
|
timer.Start(0, 1, 1.0 / 24.0);
|
||||||
|
|
||||||
// Immediately get timestamp (should be close to 0)
|
// Immediately get timestamp (should be close to 0)
|
||||||
int64_t ts = timer.GetTimestampNow();
|
int64_t ts = timer.GetTimestampNow();
|
||||||
EXPECT_GE(ts, 0);
|
EXPECT_GE(ts, 0);
|
||||||
|
|
||||||
// Wait a bit and check timestamp has increased
|
// Wait a bit and check timestamp has increased
|
||||||
QThread::msleep(50); // 50ms
|
QThread::msleep(50); // 50ms
|
||||||
int64_t ts2 = timer.GetTimestampNow();
|
int64_t ts2 = timer.GetTimestampNow();
|
||||||
|
|
||||||
// At 24fps, 50ms should be approximately 1 frame (or slightly more)
|
// At 24fps, 50ms should be approximately 1 frame (or slightly more)
|
||||||
// Allow for some timing variance
|
// Allow for some timing variance
|
||||||
EXPECT_GE(ts2, ts);
|
EXPECT_GE(ts2, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeTimer, PlaybackSpeedForward)
|
TEST(ViewerSmokeTimer, PlaybackSpeedForward)
|
||||||
{
|
{
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
|
|
||||||
// Start at timestamp 100, 2x speed, 30fps
|
// Start at timestamp 100, 2x speed, 30fps
|
||||||
timer.Start(100, 2, 1.0 / 30.0);
|
timer.Start(100, 2, 1.0 / 30.0);
|
||||||
|
|
||||||
int64_t ts1 = timer.GetTimestampNow();
|
int64_t ts1 = timer.GetTimestampNow();
|
||||||
QThread::msleep(50);
|
QThread::msleep(50);
|
||||||
int64_t ts2 = timer.GetTimestampNow();
|
int64_t ts2 = timer.GetTimestampNow();
|
||||||
|
|
||||||
// At 2x speed, time should advance twice as fast
|
// At 2x speed, time should advance twice as fast
|
||||||
EXPECT_GT(ts2, ts1);
|
EXPECT_GT(ts2, ts1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeTimer, PlaybackSpeedReverse)
|
TEST(ViewerSmokeTimer, PlaybackSpeedReverse)
|
||||||
{
|
{
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
|
|
||||||
// Start at timestamp 1000, -1x speed (reverse), 24fps
|
// Start at timestamp 1000, -1x speed (reverse), 24fps
|
||||||
timer.Start(1000, -1, 1.0 / 24.0);
|
timer.Start(1000, -1, 1.0 / 24.0);
|
||||||
|
|
||||||
int64_t ts1 = timer.GetTimestampNow();
|
int64_t ts1 = timer.GetTimestampNow();
|
||||||
QThread::msleep(50);
|
QThread::msleep(50);
|
||||||
int64_t ts2 = timer.GetTimestampNow();
|
int64_t ts2 = timer.GetTimestampNow();
|
||||||
|
|
||||||
// In reverse, timestamp should decrease
|
// In reverse, timestamp should decrease
|
||||||
EXPECT_LT(ts2, ts1);
|
EXPECT_LT(ts2, ts1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeTimer, DifferentTimebases)
|
TEST(ViewerSmokeTimer, DifferentTimebases)
|
||||||
{
|
{
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
|
|
||||||
// Test with 24fps
|
// Test with 24fps
|
||||||
timer.Start(0, 1, 1.0 / 24.0);
|
timer.Start(0, 1, 1.0 / 24.0);
|
||||||
QThread::msleep(100);
|
QThread::msleep(100);
|
||||||
int64_t ts24 = timer.GetTimestampNow();
|
int64_t ts24 = timer.GetTimestampNow();
|
||||||
|
|
||||||
// Test with 60fps
|
// Test with 60fps
|
||||||
timer.Start(0, 1, 1.0 / 60.0);
|
timer.Start(0, 1, 1.0 / 60.0);
|
||||||
QThread::msleep(100);
|
QThread::msleep(100);
|
||||||
int64_t ts60 = timer.GetTimestampNow();
|
int64_t ts60 = timer.GetTimestampNow();
|
||||||
|
|
||||||
// At same real time, 60fps should have more frames than 24fps
|
// At same real time, 60fps should have more frames than 24fps
|
||||||
EXPECT_GT(ts60, ts24);
|
EXPECT_GT(ts60, ts24);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeTimer, ZeroSpeed)
|
TEST(ViewerSmokeTimer, ZeroSpeed)
|
||||||
{
|
{
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
|
|
||||||
// Start with 0 speed (paused)
|
// Start with 0 speed (paused)
|
||||||
timer.Start(500, 0, 1.0 / 24.0);
|
timer.Start(500, 0, 1.0 / 24.0);
|
||||||
|
|
||||||
int64_t ts1 = timer.GetTimestampNow();
|
int64_t ts1 = timer.GetTimestampNow();
|
||||||
QThread::msleep(50);
|
QThread::msleep(50);
|
||||||
int64_t ts2 = timer.GetTimestampNow();
|
int64_t ts2 = timer.GetTimestampNow();
|
||||||
|
|
||||||
// With 0 speed, timestamp should not change
|
// With 0 speed, timestamp should not change
|
||||||
EXPECT_EQ(ts1, ts2);
|
EXPECT_EQ(ts1, ts2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -129,121 +132,121 @@ TEST(ViewerSmokeTimer, ZeroSpeed)
|
|||||||
|
|
||||||
TEST(ViewerSmokeQueue, DefaultConstruction)
|
TEST(ViewerSmokeQueue, DefaultConstruction)
|
||||||
{
|
{
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
EXPECT_TRUE(queue.empty());
|
EXPECT_TRUE(queue.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeQueue, AppendForwardPlayback)
|
TEST(ViewerSmokeQueue, AppendForwardPlayback)
|
||||||
{
|
{
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
|
|
||||||
// Append frames for forward playback
|
// Append frames for forward playback
|
||||||
ViewerPlaybackFrame frame1{rational(0), QVariant()};
|
ViewerPlaybackFrame frame1{ rational(0), QVariant() };
|
||||||
ViewerPlaybackFrame frame2{rational(1, 24), QVariant()};
|
ViewerPlaybackFrame frame2{ rational(1, 24), QVariant() };
|
||||||
ViewerPlaybackFrame frame3{rational(2, 24), QVariant()};
|
ViewerPlaybackFrame frame3{ rational(2, 24), QVariant() };
|
||||||
|
|
||||||
queue.AppendTimewise(frame1, 1); // speed = 1 (forward)
|
queue.AppendTimewise(frame1, 1); // speed = 1 (forward)
|
||||||
queue.AppendTimewise(frame2, 1);
|
queue.AppendTimewise(frame2, 1);
|
||||||
queue.AppendTimewise(frame3, 1);
|
queue.AppendTimewise(frame3, 1);
|
||||||
|
|
||||||
EXPECT_EQ(queue.size(), 3);
|
EXPECT_EQ(queue.size(), 3);
|
||||||
|
|
||||||
// Verify order (should be chronological for forward playback)
|
// Verify order (should be chronological for forward playback)
|
||||||
auto it = queue.begin();
|
auto it = queue.begin();
|
||||||
EXPECT_EQ(it->timestamp, rational(0));
|
EXPECT_EQ(it->timestamp, rational(0));
|
||||||
++it;
|
++it;
|
||||||
EXPECT_EQ(it->timestamp, rational(1, 24));
|
EXPECT_EQ(it->timestamp, rational(1, 24));
|
||||||
++it;
|
++it;
|
||||||
EXPECT_EQ(it->timestamp, rational(2, 24));
|
EXPECT_EQ(it->timestamp, rational(2, 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeQueue, AppendReversePlayback)
|
TEST(ViewerSmokeQueue, AppendReversePlayback)
|
||||||
{
|
{
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
|
|
||||||
// Append frames for reverse playback
|
// Append frames for reverse playback
|
||||||
ViewerPlaybackFrame frame1{rational(2, 24), QVariant()};
|
ViewerPlaybackFrame frame1{ rational(2, 24), QVariant() };
|
||||||
ViewerPlaybackFrame frame2{rational(1, 24), QVariant()};
|
ViewerPlaybackFrame frame2{ rational(1, 24), QVariant() };
|
||||||
ViewerPlaybackFrame frame3{rational(0), QVariant()};
|
ViewerPlaybackFrame frame3{ rational(0), QVariant() };
|
||||||
|
|
||||||
queue.AppendTimewise(frame1, -1); // speed = -1 (reverse)
|
queue.AppendTimewise(frame1, -1); // speed = -1 (reverse)
|
||||||
queue.AppendTimewise(frame2, -1);
|
queue.AppendTimewise(frame2, -1);
|
||||||
queue.AppendTimewise(frame3, -1);
|
queue.AppendTimewise(frame3, -1);
|
||||||
|
|
||||||
EXPECT_EQ(queue.size(), 3);
|
EXPECT_EQ(queue.size(), 3);
|
||||||
|
|
||||||
// Verify order (should be reverse chronological for reverse playback)
|
// Verify order (should be reverse chronological for reverse playback)
|
||||||
auto it = queue.begin();
|
auto it = queue.begin();
|
||||||
EXPECT_EQ(it->timestamp, rational(2, 24));
|
EXPECT_EQ(it->timestamp, rational(2, 24));
|
||||||
++it;
|
++it;
|
||||||
EXPECT_EQ(it->timestamp, rational(1, 24));
|
EXPECT_EQ(it->timestamp, rational(1, 24));
|
||||||
++it;
|
++it;
|
||||||
EXPECT_EQ(it->timestamp, rational(0));
|
EXPECT_EQ(it->timestamp, rational(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeQueue, InsertOutOfOrder)
|
TEST(ViewerSmokeQueue, InsertOutOfOrder)
|
||||||
{
|
{
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
|
|
||||||
// Insert frames out of order for forward playback
|
// Insert frames out of order for forward playback
|
||||||
ViewerPlaybackFrame frame1{rational(0), QVariant()};
|
ViewerPlaybackFrame frame1{ rational(0), QVariant() };
|
||||||
ViewerPlaybackFrame frame2{rational(2, 24), QVariant()};
|
ViewerPlaybackFrame frame2{ rational(2, 24), QVariant() };
|
||||||
ViewerPlaybackFrame frame3{rational(1, 24), QVariant()}; // Middle frame
|
ViewerPlaybackFrame frame3{ rational(1, 24), QVariant() }; // Middle frame
|
||||||
|
|
||||||
queue.AppendTimewise(frame1, 1);
|
queue.AppendTimewise(frame1, 1);
|
||||||
queue.AppendTimewise(frame2, 1);
|
queue.AppendTimewise(frame2, 1);
|
||||||
queue.AppendTimewise(frame3, 1); // Should insert in middle
|
queue.AppendTimewise(frame3, 1); // Should insert in middle
|
||||||
|
|
||||||
EXPECT_EQ(queue.size(), 3);
|
EXPECT_EQ(queue.size(), 3);
|
||||||
|
|
||||||
// Verify correct order
|
// Verify correct order
|
||||||
auto it = queue.begin();
|
auto it = queue.begin();
|
||||||
EXPECT_EQ(it->timestamp, rational(0));
|
EXPECT_EQ(it->timestamp, rational(0));
|
||||||
++it;
|
++it;
|
||||||
EXPECT_EQ(it->timestamp, rational(1, 24));
|
EXPECT_EQ(it->timestamp, rational(1, 24));
|
||||||
++it;
|
++it;
|
||||||
EXPECT_EQ(it->timestamp, rational(2, 24));
|
EXPECT_EQ(it->timestamp, rational(2, 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeQueue, PurgeBefore)
|
TEST(ViewerSmokeQueue, PurgeBefore)
|
||||||
{
|
{
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
|
|
||||||
// Add some frames
|
// Add some frames
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
ViewerPlaybackFrame frame{rational(i, 24), QVariant()};
|
ViewerPlaybackFrame frame{ rational(i, 24), QVariant() };
|
||||||
queue.AppendTimewise(frame, 1);
|
queue.AppendTimewise(frame, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(queue.size(), 10);
|
EXPECT_EQ(queue.size(), 10);
|
||||||
|
|
||||||
// Purge frames before 5/24
|
// Purge frames before 5/24
|
||||||
queue.PurgeBefore(rational(5, 24), 1);
|
queue.PurgeBefore(rational(5, 24), 1);
|
||||||
|
|
||||||
// Should have 5 frames remaining (5, 6, 7, 8, 9)
|
// Should have 5 frames remaining (5, 6, 7, 8, 9)
|
||||||
EXPECT_EQ(queue.size(), 5);
|
EXPECT_EQ(queue.size(), 5);
|
||||||
EXPECT_EQ(queue.front().timestamp, rational(5, 24));
|
EXPECT_EQ(queue.front().timestamp, rational(5, 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeQueue, PurgeBeforeReverse)
|
TEST(ViewerSmokeQueue, PurgeBeforeReverse)
|
||||||
{
|
{
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
|
|
||||||
// Add frames for reverse playback (newest first)
|
// Add frames for reverse playback (newest first)
|
||||||
for (int i = 9; i >= 0; i--) {
|
for (int i = 9; i >= 0; i--) {
|
||||||
ViewerPlaybackFrame frame{rational(i, 24), QVariant()};
|
ViewerPlaybackFrame frame{ rational(i, 24), QVariant() };
|
||||||
queue.AppendTimewise(frame, -1);
|
queue.AppendTimewise(frame, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(queue.size(), 10);
|
EXPECT_EQ(queue.size(), 10);
|
||||||
|
|
||||||
// In reverse playback, front() is the largest timestamp (9/24)
|
// In reverse playback, front() is the largest timestamp (9/24)
|
||||||
// PurgeBefore with negative speed removes frames where front > time
|
// PurgeBefore with negative speed removes frames where front > time
|
||||||
queue.PurgeBefore(rational(5, 24), -1);
|
queue.PurgeBefore(rational(5, 24), -1);
|
||||||
|
|
||||||
// Should have frames 0-5 remaining (those <= 5/24)
|
// Should have frames 0-5 remaining (those <= 5/24)
|
||||||
EXPECT_EQ(queue.size(), 6);
|
EXPECT_EQ(queue.size(), 6);
|
||||||
EXPECT_EQ(queue.front().timestamp, rational(5, 24));
|
EXPECT_EQ(queue.front().timestamp, rational(5, 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -252,57 +255,57 @@ TEST(ViewerSmokeQueue, PurgeBeforeReverse)
|
|||||||
|
|
||||||
TEST(ViewerSmokeSafeMargin, DefaultConstruction)
|
TEST(ViewerSmokeSafeMargin, DefaultConstruction)
|
||||||
{
|
{
|
||||||
ViewerSafeMarginInfo info;
|
ViewerSafeMarginInfo info;
|
||||||
EXPECT_FALSE(info.is_enabled());
|
EXPECT_FALSE(info.is_enabled());
|
||||||
EXPECT_FALSE(info.custom_ratio());
|
EXPECT_FALSE(info.custom_ratio());
|
||||||
EXPECT_DOUBLE_EQ(info.ratio(), 0.0);
|
EXPECT_DOUBLE_EQ(info.ratio(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeSafeMargin, EnabledConstruction)
|
TEST(ViewerSmokeSafeMargin, EnabledConstruction)
|
||||||
{
|
{
|
||||||
ViewerSafeMarginInfo info(true);
|
ViewerSafeMarginInfo info(true);
|
||||||
EXPECT_TRUE(info.is_enabled());
|
EXPECT_TRUE(info.is_enabled());
|
||||||
EXPECT_FALSE(info.custom_ratio());
|
EXPECT_FALSE(info.custom_ratio());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeSafeMargin, CustomRatioConstruction)
|
TEST(ViewerSmokeSafeMargin, CustomRatioConstruction)
|
||||||
{
|
{
|
||||||
ViewerSafeMarginInfo info(true, 0.9);
|
ViewerSafeMarginInfo info(true, 0.9);
|
||||||
EXPECT_TRUE(info.is_enabled());
|
EXPECT_TRUE(info.is_enabled());
|
||||||
EXPECT_TRUE(info.custom_ratio());
|
EXPECT_TRUE(info.custom_ratio());
|
||||||
EXPECT_DOUBLE_EQ(info.ratio(), 0.9);
|
EXPECT_DOUBLE_EQ(info.ratio(), 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeSafeMargin, EqualityOperators)
|
TEST(ViewerSmokeSafeMargin, EqualityOperators)
|
||||||
{
|
{
|
||||||
ViewerSafeMarginInfo info1(true, 0.9);
|
ViewerSafeMarginInfo info1(true, 0.9);
|
||||||
ViewerSafeMarginInfo info2(true, 0.9);
|
ViewerSafeMarginInfo info2(true, 0.9);
|
||||||
ViewerSafeMarginInfo info3(false, 0.9);
|
ViewerSafeMarginInfo info3(false, 0.9);
|
||||||
ViewerSafeMarginInfo info4(true, 0.8);
|
ViewerSafeMarginInfo info4(true, 0.8);
|
||||||
|
|
||||||
EXPECT_TRUE(info1 == info2);
|
EXPECT_TRUE(info1 == info2);
|
||||||
EXPECT_FALSE(info1 != info2);
|
EXPECT_FALSE(info1 != info2);
|
||||||
|
|
||||||
EXPECT_FALSE(info1 == info3); // Different enabled state
|
EXPECT_FALSE(info1 == info3); // Different enabled state
|
||||||
EXPECT_FALSE(info1 == info4); // Different ratio
|
EXPECT_FALSE(info1 == info4); // Different ratio
|
||||||
EXPECT_TRUE(info1 != info3);
|
EXPECT_TRUE(info1 != info3);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeSafeMargin, ZeroRatio)
|
TEST(ViewerSmokeSafeMargin, ZeroRatio)
|
||||||
{
|
{
|
||||||
ViewerSafeMarginInfo info(true, 0.0);
|
ViewerSafeMarginInfo info(true, 0.0);
|
||||||
EXPECT_TRUE(info.is_enabled());
|
EXPECT_TRUE(info.is_enabled());
|
||||||
EXPECT_FALSE(info.custom_ratio()); // 0 ratio means no custom ratio
|
EXPECT_FALSE(info.custom_ratio()); // 0 ratio means no custom ratio
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeSafeMargin, CopyConstruction)
|
TEST(ViewerSmokeSafeMargin, CopyConstruction)
|
||||||
{
|
{
|
||||||
ViewerSafeMarginInfo original(true, 0.85);
|
ViewerSafeMarginInfo original(true, 0.85);
|
||||||
ViewerSafeMarginInfo copy(original);
|
ViewerSafeMarginInfo copy(original);
|
||||||
|
|
||||||
EXPECT_EQ(copy.is_enabled(), original.is_enabled());
|
EXPECT_EQ(copy.is_enabled(), original.is_enabled());
|
||||||
EXPECT_EQ(copy.custom_ratio(), original.custom_ratio());
|
EXPECT_EQ(copy.custom_ratio(), original.custom_ratio());
|
||||||
EXPECT_DOUBLE_EQ(copy.ratio(), original.ratio());
|
EXPECT_DOUBLE_EQ(copy.ratio(), original.ratio());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -311,30 +314,30 @@ TEST(ViewerSmokeSafeMargin, CopyConstruction)
|
|||||||
|
|
||||||
TEST(ViewerSmokeAudioCache, DefaultConstruction)
|
TEST(ViewerSmokeAudioCache, DefaultConstruction)
|
||||||
{
|
{
|
||||||
AudioPlaybackCache cache;
|
AudioPlaybackCache cache;
|
||||||
// Should construct without crashing
|
// Should construct without crashing
|
||||||
SUCCEED();
|
SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeAudioCache, ParameterSetters)
|
TEST(ViewerSmokeAudioCache, ParameterSetters)
|
||||||
{
|
{
|
||||||
AudioPlaybackCache cache;
|
AudioPlaybackCache cache;
|
||||||
|
|
||||||
AudioParams params(48000, AV_CH_LAYOUT_STEREO, SampleFormat::F32P);
|
AudioParams params(48000, AV_CH_LAYOUT_STEREO, SampleFormat::F32P);
|
||||||
cache.SetParameters(params);
|
cache.SetParameters(params);
|
||||||
|
|
||||||
// Parameters should be retrievable
|
// Parameters should be retrievable
|
||||||
AudioParams retrieved = cache.GetParameters();
|
AudioParams retrieved = cache.GetParameters();
|
||||||
EXPECT_EQ(retrieved.sample_rate(), params.sample_rate());
|
EXPECT_EQ(retrieved.sample_rate(), params.sample_rate());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeAudioCache, ValidateWithRange)
|
TEST(ViewerSmokeAudioCache, ValidateWithRange)
|
||||||
{
|
{
|
||||||
AudioPlaybackCache cache;
|
AudioPlaybackCache cache;
|
||||||
|
|
||||||
// Initially no validated ranges
|
// Initially no validated ranges
|
||||||
TimeRangeList validated = cache.GetValidatedRanges();
|
TimeRangeList validated = cache.GetValidatedRanges();
|
||||||
EXPECT_TRUE(validated.isEmpty());
|
EXPECT_TRUE(validated.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -346,32 +349,32 @@ TEST(ViewerSmokeAudioCache, ValidateWithRange)
|
|||||||
|
|
||||||
TEST(ViewerSmokeAutoCacher, DISABLED_Construction)
|
TEST(ViewerSmokeAutoCacher, DISABLED_Construction)
|
||||||
{
|
{
|
||||||
// PreviewAutoCacher requires full GUI environment
|
// PreviewAutoCacher requires full GUI environment
|
||||||
SUCCEED();
|
SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeAutoCacher, DISABLED_SetPlayhead)
|
TEST(ViewerSmokeAutoCacher, DISABLED_SetPlayhead)
|
||||||
{
|
{
|
||||||
// PreviewAutoCacher requires full GUI environment
|
// PreviewAutoCacher requires full GUI environment
|
||||||
SUCCEED();
|
SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeAutoCacher, DISABLED_PauseControls)
|
TEST(ViewerSmokeAutoCacher, DISABLED_PauseControls)
|
||||||
{
|
{
|
||||||
// PreviewAutoCacher requires full GUI environment
|
// PreviewAutoCacher requires full GUI environment
|
||||||
SUCCEED();
|
SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeAutoCacher, DISABLED_SetIgnoreCacheRequests)
|
TEST(ViewerSmokeAutoCacher, DISABLED_SetIgnoreCacheRequests)
|
||||||
{
|
{
|
||||||
// PreviewAutoCacher requires full GUI environment
|
// PreviewAutoCacher requires full GUI environment
|
||||||
SUCCEED();
|
SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeAutoCacher, DISABLED_SetDisplayColorProcessor)
|
TEST(ViewerSmokeAutoCacher, DISABLED_SetDisplayColorProcessor)
|
||||||
{
|
{
|
||||||
// PreviewAutoCacher requires full GUI environment
|
// PreviewAutoCacher requires full GUI environment
|
||||||
SUCCEED();
|
SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -380,73 +383,73 @@ TEST(ViewerSmokeAutoCacher, DISABLED_SetDisplayColorProcessor)
|
|||||||
|
|
||||||
TEST(ViewerSmokeRational, DefaultConstruction)
|
TEST(ViewerSmokeRational, DefaultConstruction)
|
||||||
{
|
{
|
||||||
rational r;
|
rational r;
|
||||||
EXPECT_EQ(r.numerator(), 0);
|
EXPECT_EQ(r.numerator(), 0);
|
||||||
EXPECT_EQ(r.denominator(), 1);
|
EXPECT_EQ(r.denominator(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeRational, ValueConstruction)
|
TEST(ViewerSmokeRational, ValueConstruction)
|
||||||
{
|
{
|
||||||
rational r(24, 1);
|
rational r(24, 1);
|
||||||
EXPECT_EQ(r.numerator(), 24);
|
EXPECT_EQ(r.numerator(), 24);
|
||||||
EXPECT_EQ(r.denominator(), 1);
|
EXPECT_EQ(r.denominator(), 1);
|
||||||
|
|
||||||
rational r2(1, 24);
|
rational r2(1, 24);
|
||||||
EXPECT_EQ(r2.numerator(), 1);
|
EXPECT_EQ(r2.numerator(), 1);
|
||||||
EXPECT_EQ(r2.denominator(), 24);
|
EXPECT_EQ(r2.denominator(), 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeRational, ToDouble)
|
TEST(ViewerSmokeRational, ToDouble)
|
||||||
{
|
{
|
||||||
rational r(1, 2);
|
rational r(1, 2);
|
||||||
EXPECT_DOUBLE_EQ(r.toDouble(), 0.5);
|
EXPECT_DOUBLE_EQ(r.toDouble(), 0.5);
|
||||||
|
|
||||||
rational r2(3, 4);
|
rational r2(3, 4);
|
||||||
EXPECT_DOUBLE_EQ(r2.toDouble(), 0.75);
|
EXPECT_DOUBLE_EQ(r2.toDouble(), 0.75);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeRational, Arithmetic)
|
TEST(ViewerSmokeRational, Arithmetic)
|
||||||
{
|
{
|
||||||
rational r1(1, 2);
|
rational r1(1, 2);
|
||||||
rational r2(1, 4);
|
rational r2(1, 4);
|
||||||
|
|
||||||
rational sum = r1 + r2;
|
rational sum = r1 + r2;
|
||||||
EXPECT_EQ(sum.numerator(), 3);
|
EXPECT_EQ(sum.numerator(), 3);
|
||||||
EXPECT_EQ(sum.denominator(), 4);
|
EXPECT_EQ(sum.denominator(), 4);
|
||||||
|
|
||||||
rational diff = r1 - r2;
|
rational diff = r1 - r2;
|
||||||
EXPECT_EQ(diff.numerator(), 1);
|
EXPECT_EQ(diff.numerator(), 1);
|
||||||
EXPECT_EQ(diff.denominator(), 4);
|
EXPECT_EQ(diff.denominator(), 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeRational, Comparison)
|
TEST(ViewerSmokeRational, Comparison)
|
||||||
{
|
{
|
||||||
rational r1(1, 2);
|
rational r1(1, 2);
|
||||||
rational r2(2, 4);
|
rational r2(2, 4);
|
||||||
rational r3(3, 4);
|
rational r3(3, 4);
|
||||||
|
|
||||||
EXPECT_TRUE(r1 == r2); // Equivalent fractions
|
EXPECT_TRUE(r1 == r2); // Equivalent fractions
|
||||||
EXPECT_FALSE(r1 == r3);
|
EXPECT_FALSE(r1 == r3);
|
||||||
EXPECT_TRUE(r1 < r3);
|
EXPECT_TRUE(r1 < r3);
|
||||||
EXPECT_TRUE(r3 > r1);
|
EXPECT_TRUE(r3 > r1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeRational, NullCheck)
|
TEST(ViewerSmokeRational, NullCheck)
|
||||||
{
|
{
|
||||||
rational r;
|
rational r;
|
||||||
EXPECT_TRUE(r.isNull()); // 0/1 is considered null
|
EXPECT_TRUE(r.isNull()); // 0/1 is considered null
|
||||||
|
|
||||||
rational r2(1, 2);
|
rational r2(1, 2);
|
||||||
EXPECT_FALSE(r2.isNull());
|
EXPECT_FALSE(r2.isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeRational, Flipped)
|
TEST(ViewerSmokeRational, Flipped)
|
||||||
{
|
{
|
||||||
rational r(24, 1);
|
rational r(24, 1);
|
||||||
rational flipped = r.flipped();
|
rational flipped = r.flipped();
|
||||||
|
|
||||||
EXPECT_EQ(flipped.numerator(), 1);
|
EXPECT_EQ(flipped.numerator(), 1);
|
||||||
EXPECT_EQ(flipped.denominator(), 24);
|
EXPECT_EQ(flipped.denominator(), 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -455,58 +458,61 @@ TEST(ViewerSmokeRational, Flipped)
|
|||||||
|
|
||||||
TEST(ViewerSmokeThread, ConcurrentTimerAccess)
|
TEST(ViewerSmokeThread, ConcurrentTimerAccess)
|
||||||
{
|
{
|
||||||
const int num_threads = 4;
|
const int num_threads = 4;
|
||||||
const int num_iterations = 100;
|
const int num_iterations = 100;
|
||||||
|
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
timer.Start(0, 1, 1.0 / 30.0);
|
timer.Start(0, 1, 1.0 / 30.0);
|
||||||
|
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
std::atomic<int> success_count{0};
|
std::atomic<int> success_count{ 0 };
|
||||||
|
|
||||||
for (int t = 0; t < num_threads; ++t) {
|
for (int t = 0; t < num_threads; ++t) {
|
||||||
threads.emplace_back([&timer, &success_count, num_iterations]() {
|
threads.emplace_back([&timer, &success_count, num_iterations]() {
|
||||||
for (int i = 0; i < num_iterations; ++i) {
|
for (int i = 0; i < num_iterations; ++i) {
|
||||||
int64_t ts = timer.GetTimestampNow();
|
int64_t ts = timer.GetTimestampNow();
|
||||||
if (ts >= 0) {
|
if (ts >= 0) {
|
||||||
success_count++;
|
success_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &t : threads) {
|
for (auto &t : threads) {
|
||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(success_count.load(), num_threads * num_iterations);
|
EXPECT_EQ(success_count.load(), num_threads * num_iterations);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeThread, ConcurrentQueueAccess)
|
TEST(ViewerSmokeThread, ConcurrentQueueAccess)
|
||||||
{
|
{
|
||||||
const int num_threads = 4;
|
const int num_threads = 4;
|
||||||
const int num_frames_per_thread = 25;
|
const int num_frames_per_thread = 25;
|
||||||
|
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
std::vector<std::thread> threads;
|
std::vector<std::thread> threads;
|
||||||
std::atomic<int> append_count{0};
|
std::atomic<int> append_count{ 0 };
|
||||||
|
|
||||||
for (int t = 0; t < num_threads; ++t) {
|
for (int t = 0; t < num_threads; ++t) {
|
||||||
threads.emplace_back([&queue, &append_count, t, num_frames_per_thread]() {
|
threads.emplace_back(
|
||||||
for (int i = 0; i < num_frames_per_thread; ++i) {
|
[&queue, &append_count, t, num_frames_per_thread]() {
|
||||||
ViewerPlaybackFrame frame{rational(t * num_frames_per_thread + i, 24), QVariant()};
|
for (int i = 0; i < num_frames_per_thread; ++i) {
|
||||||
queue.AppendTimewise(frame, 1);
|
ViewerPlaybackFrame frame{
|
||||||
append_count++;
|
rational(t * num_frames_per_thread + i, 24), QVariant()
|
||||||
}
|
};
|
||||||
});
|
queue.AppendTimewise(frame, 1);
|
||||||
}
|
append_count++;
|
||||||
|
}
|
||||||
for (auto &t : threads) {
|
});
|
||||||
t.join();
|
}
|
||||||
}
|
|
||||||
|
for (auto &t : threads) {
|
||||||
EXPECT_EQ(append_count.load(), num_threads * num_frames_per_thread);
|
t.join();
|
||||||
EXPECT_EQ(queue.size(), num_threads * num_frames_per_thread);
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(append_count.load(), num_threads * num_frames_per_thread);
|
||||||
|
EXPECT_EQ(queue.size(), num_threads * num_frames_per_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -515,70 +521,70 @@ TEST(ViewerSmokeThread, ConcurrentQueueAccess)
|
|||||||
|
|
||||||
TEST(ViewerSmokeIntegration, PlaybackSequenceSimulation)
|
TEST(ViewerSmokeIntegration, PlaybackSequenceSimulation)
|
||||||
{
|
{
|
||||||
// Simulate a basic playback sequence
|
// Simulate a basic playback sequence
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
|
|
||||||
// Start playback at frame 0, 24fps
|
// Start playback at frame 0, 24fps
|
||||||
timer.Start(0, 1, 1.0 / 24.0);
|
timer.Start(0, 1, 1.0 / 24.0);
|
||||||
|
|
||||||
// Queue some frames
|
// Queue some frames
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
ViewerPlaybackFrame frame{rational(i, 24), QVariant(i)};
|
ViewerPlaybackFrame frame{ rational(i, 24), QVariant(i) };
|
||||||
queue.AppendTimewise(frame, 1);
|
queue.AppendTimewise(frame, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current timestamp
|
// Get current timestamp
|
||||||
int64_t current_ts = timer.GetTimestampNow();
|
int64_t current_ts = timer.GetTimestampNow();
|
||||||
|
|
||||||
// Find frame closest to current time
|
// Find frame closest to current time
|
||||||
rational current_time(current_ts, 1);
|
rational current_time(current_ts, 1);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (const auto &frame : queue) {
|
for (const auto &frame : queue) {
|
||||||
if (frame.timestamp >= current_time) {
|
if (frame.timestamp >= current_time) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should have frames available
|
// Should have frames available
|
||||||
EXPECT_FALSE(queue.empty());
|
EXPECT_FALSE(queue.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeIntegration, SafeMarginWithDifferentAspectRatios)
|
TEST(ViewerSmokeIntegration, SafeMarginWithDifferentAspectRatios)
|
||||||
{
|
{
|
||||||
// Test safe margins for different aspect ratios
|
// Test safe margins for different aspect ratios
|
||||||
std::vector<double> ratios = {0.9, 0.85, 0.8, 0.7};
|
std::vector<double> ratios = { 0.9, 0.85, 0.8, 0.7 };
|
||||||
|
|
||||||
for (double ratio : ratios) {
|
for (double ratio : ratios) {
|
||||||
ViewerSafeMarginInfo info(true, ratio);
|
ViewerSafeMarginInfo info(true, ratio);
|
||||||
EXPECT_TRUE(info.is_enabled());
|
EXPECT_TRUE(info.is_enabled());
|
||||||
EXPECT_TRUE(info.custom_ratio());
|
EXPECT_TRUE(info.custom_ratio());
|
||||||
EXPECT_DOUBLE_EQ(info.ratio(), ratio);
|
EXPECT_DOUBLE_EQ(info.ratio(), ratio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ViewerSmokeIntegration, ReversePlaybackScenario)
|
TEST(ViewerSmokeIntegration, ReversePlaybackScenario)
|
||||||
{
|
{
|
||||||
ViewerPlaybackTimer timer;
|
ViewerPlaybackTimer timer;
|
||||||
ViewerQueue queue;
|
ViewerQueue queue;
|
||||||
|
|
||||||
// Start reverse playback from frame 100
|
// Start reverse playback from frame 100
|
||||||
timer.Start(100, -1, 1.0 / 24.0);
|
timer.Start(100, -1, 1.0 / 24.0);
|
||||||
|
|
||||||
// Queue frames in reverse order
|
// Queue frames in reverse order
|
||||||
for (int i = 100; i >= 90; i--) {
|
for (int i = 100; i >= 90; i--) {
|
||||||
ViewerPlaybackFrame frame{rational(i, 24), QVariant(i)};
|
ViewerPlaybackFrame frame{ rational(i, 24), QVariant(i) };
|
||||||
queue.AppendTimewise(frame, -1);
|
queue.AppendTimewise(frame, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get timestamps - should decrease
|
// Get timestamps - should decrease
|
||||||
int64_t ts1 = timer.GetTimestampNow();
|
int64_t ts1 = timer.GetTimestampNow();
|
||||||
QThread::msleep(50);
|
QThread::msleep(50);
|
||||||
int64_t ts2 = timer.GetTimestampNow();
|
int64_t ts2 = timer.GetTimestampNow();
|
||||||
|
|
||||||
EXPECT_LT(ts2, ts1);
|
EXPECT_LT(ts2, ts1);
|
||||||
EXPECT_EQ(queue.front().timestamp, rational(100, 24));
|
EXPECT_EQ(queue.front().timestamp, rational(100, 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace test
|
} // namespace test
|
||||||
|
|||||||
Reference in New Issue
Block a user