From 79f376b51267a57619879262a98cf9b7a6ef4976 Mon Sep 17 00:00:00 2001 From: Mike Solar Date: Mon, 5 Jan 2026 03:40:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 16 +++- app/pluginSupport/OliveClip.cpp | 49 ++++++---- app/pluginSupport/OlivePluginInstance.cpp | 12 ++- ext/core | 2 +- tests/gtest/CMakeLists.txt | 6 ++ tests/gtest/plugin_support_clip_test.cpp | 96 +++++++++++++++++++ tests/gtest/plugin_support_image_test.cpp | 91 ++++++++++++++++++ .../gtest/render_audioparams_branch_test.cpp | 42 ++++++++ tests/gtest/render_pixelformat_test.cpp | 28 ++++++ tests/gtest/render_sampleformat_test.cpp | 29 ++++++ .../gtest/render_videoparams_branch_test.cpp | 84 ++++++++++++++++ 11 files changed, 431 insertions(+), 24 deletions(-) create mode 100644 tests/gtest/plugin_support_clip_test.cpp create mode 100644 tests/gtest/plugin_support_image_test.cpp create mode 100644 tests/gtest/render_audioparams_branch_test.cpp create mode 100644 tests/gtest/render_pixelformat_test.cpp create mode 100644 tests/gtest/render_sampleformat_test.cpp create mode 100644 tests/gtest/render_videoparams_branch_test.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 043bba6f9..635e9fd7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, macos-13, windows-2022] + os: [ubuntu-22.04, macos-latest, windows-2022] env: CMAKE_BUILD_TYPE: Release steps: @@ -53,12 +53,22 @@ jobs: echo "VCPKG_ROOT=$env:VCPKG_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append echo "CMAKE_TOOLCHAIN_FILE=$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" | Out-File -FilePath $env:GITHUB_ENV -Append - - name: Configure (Linux/macOS) - if: runner.os != 'Windows' + - name: Configure (Linux) + if: runner.os == 'Linux' run: | cmake -S . -B build -G Ninja \ -DBUILD_TESTS=ON \ -DBUILD_QT6=ON \ + -DOCIO_LOCATION=/usr \ + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + + - name: Configure (macOS) + if: runner.os == 'macOS' + run: | + cmake -S . -B build -G Ninja \ + -DBUILD_TESTS=ON \ + -DBUILD_QT6=ON \ + -DOCIO_LOCATION=$(brew --prefix opencolorio) \ -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - name: Configure (Windows) diff --git a/app/pluginSupport/OliveClip.cpp b/app/pluginSupport/OliveClip.cpp index d4d7cf19a..bc2a655e7 100644 --- a/app/pluginSupport/OliveClip.cpp +++ b/app/pluginSupport/OliveClip.cpp @@ -39,21 +39,38 @@ extern "C" { #include } +namespace { +const std::string kBitDepthNoneStr(kOfxBitDepthNone); +const std::string kBitDepthByteStr(kOfxBitDepthByte); +const std::string kBitDepthShortStr(kOfxBitDepthShort); +const std::string kBitDepthHalfStr(kOfxBitDepthHalf); +const std::string kBitDepthFloatStr(kOfxBitDepthFloat); +const std::string kImageComponentNoneStr(kOfxImageComponentNone); +const std::string kImageComponentAlphaStr(kOfxImageComponentAlpha); +const std::string kImageComponentRGBStr(kOfxImageComponentRGB); +const std::string kImageComponentRGBAStr(kOfxImageComponentRGBA); +const std::string kImagePremultStr(kOfxImagePreMultiplied); +const std::string kImageUnPremultStr(kOfxImageUnPreMultiplied); +const std::string kImageFieldNoneStr(kOfxImageFieldNone); +const std::string kImageFieldUpperStr(kOfxImageFieldUpper); +const std::string kImageFieldLowerStr(kOfxImageFieldLower); +} + const std::string &olive::plugin::OliveClipInstance::getUnmappedBitDepth() const { switch (params_.format()) { case PixelFormat::INVALID: - return kOfxBitDepthNone; + return kBitDepthNoneStr; case PixelFormat::U8: - return kOfxBitDepthByte; + return kBitDepthByteStr; case PixelFormat::U16: - return kOfxBitDepthShort; + return kBitDepthShortStr; case PixelFormat::F16: - return kOfxBitDepthHalf; + return kBitDepthHalfStr; case PixelFormat::F32: - return kOfxBitDepthFloat; + return kBitDepthFloatStr; default: - return kOfxBitDepthNone; + return kBitDepthNoneStr; } } const std::string & @@ -61,21 +78,21 @@ olive::plugin::OliveClipInstance::getUnmappedComponents() const { switch (params_.channel_count()) { case 1: - return kOfxImageComponentAlpha; + return kImageComponentAlphaStr; case 3: - return kOfxImageComponentRGB; + return kImageComponentRGBStr; case 4: - return kOfxImageComponentRGBA; + return kImageComponentRGBAStr; default: - return kOfxImageComponentNone; + return kImageComponentNoneStr; } } const std::string &olive::plugin::OliveClipInstance::getPremult() const { if (params_.premultiplied_alpha()) { - return kOfxImagePreMultiplied; + return kImagePremultStr; } else { - return kOfxImageUnPreMultiplied; + return kImageUnPremultStr; } } double olive::plugin::OliveClipInstance::getAspectRatio() const @@ -97,13 +114,13 @@ const std::string &olive::plugin::OliveClipInstance::getFieldOrder() const { switch (params_.interlacing()) { case VideoParams::kInterlaceNone: - return kOfxImageFieldNone; + return kImageFieldNoneStr; case VideoParams::kInterlacedTopFirst: - return kOfxImageFieldUpper; + return kImageFieldUpperStr; case VideoParams::kInterlacedBottomFirst: - return kOfxImageFieldLower; + return kImageFieldLowerStr; } - return kOfxImageFieldNone; + return kImageFieldNoneStr; } bool olive::plugin::OliveClipInstance::getConnected() const { diff --git a/app/pluginSupport/OlivePluginInstance.cpp b/app/pluginSupport/OlivePluginInstance.cpp index 6b7212188..4f55f0e3d 100644 --- a/app/pluginSupport/OlivePluginInstance.cpp +++ b/app/pluginSupport/OlivePluginInstance.cpp @@ -43,17 +43,21 @@ namespace olive namespace plugin { namespace { +const std::string kImageFieldNoneStr(kOfxImageFieldNone); +const std::string kImageFieldUpperStr(kOfxImageFieldUpper); +const std::string kImageFieldLowerStr(kOfxImageFieldLower); + const std::string &FieldOrderForParams(const VideoParams ¶ms) { switch (params.interlacing()) { case VideoParams::kInterlaceNone: - return kOfxImageFieldNone; + return kImageFieldNoneStr; case VideoParams::kInterlacedTopFirst: - return kOfxImageFieldUpper; + return kImageFieldUpperStr; case VideoParams::kInterlacedBottomFirst: - return kOfxImageFieldLower; + return kImageFieldLowerStr; } - return kOfxImageFieldNone; + return kImageFieldNoneStr; } class DeferredRedoCommand : public UndoCommand { diff --git a/ext/core b/ext/core index 50caae473..0cf81e6e8 160000 --- a/ext/core +++ b/ext/core @@ -1 +1 @@ -Subproject commit 50caae473d6de11d129f1fb6a14d2c73dac83f51 +Subproject commit 0cf81e6e8759690f23d2b09811c71d0a55c9b33f diff --git a/tests/gtest/CMakeLists.txt b/tests/gtest/CMakeLists.txt index 07fca36b7..cc4de4fee 100644 --- a/tests/gtest/CMakeLists.txt +++ b/tests/gtest/CMakeLists.txt @@ -7,11 +7,17 @@ add_executable(olive-gtest node_keyframe_test.cpp node_serialization_test.cpp render_videoparams_test.cpp + render_videoparams_branch_test.cpp render_audioparams_test.cpp + render_audioparams_branch_test.cpp + render_sampleformat_test.cpp + render_pixelformat_test.cpp project_serializer_test.cpp timeline_marker_test.cpp undo_stack_test.cpp plugin_support_test.cpp + plugin_support_image_test.cpp + plugin_support_clip_test.cpp codec_frame_test.cpp task_taskmanager_test.cpp module_smoke_test.cpp diff --git a/tests/gtest/plugin_support_clip_test.cpp b/tests/gtest/plugin_support_clip_test.cpp new file mode 100644 index 000000000..75e218d66 --- /dev/null +++ b/tests/gtest/plugin_support_clip_test.cpp @@ -0,0 +1,96 @@ +#include + +#include "ofxImageEffect.h" +#include "ofxhClip.h" +#include "pluginSupport/OliveClip.h" + +namespace { +olive::VideoParams MakeParams(int width, int height, + olive::core::PixelFormat format, + int channels, + bool premultiplied) +{ + olive::VideoParams params; + params.set_width(width); + params.set_height(height); + params.set_format(format); + params.set_channel_count(channels); + params.set_premultiplied_alpha(premultiplied); + return params; +} +} + +TEST(PluginSupportClip, PropertyGetters) +{ + OFX::Host::ImageEffect::ClipDescriptor desc(kOfxImageEffectOutputClipName); + olive::VideoParams params = + MakeParams(1920, 1080, olive::core::PixelFormat::U16, 3, false); + params.set_pixel_aspect_ratio(olive::core::rational(2, 1)); + params.set_frame_rate(olive::core::rational(30, 1)); + params.set_start_time(2); + params.set_duration(4); + params.set_interlacing(olive::VideoParams::kInterlacedTopFirst); + + olive::plugin::OliveClipInstance clip(nullptr, desc, params); + + EXPECT_EQ(clip.getUnmappedBitDepth(), kOfxBitDepthShort); + EXPECT_EQ(clip.getUnmappedComponents(), kOfxImageComponentRGB); + EXPECT_EQ(clip.getPremult(), kOfxImageUnPreMultiplied); + EXPECT_DOUBLE_EQ(clip.getAspectRatio(), 2.0); + EXPECT_DOUBLE_EQ(clip.getFrameRate(), 30.0); + + double start_frame = 0.0; + double end_frame = 0.0; + clip.getFrameRange(start_frame, end_frame); + EXPECT_DOUBLE_EQ(start_frame, 60.0); + EXPECT_DOUBLE_EQ(end_frame, 180.0); + + EXPECT_EQ(clip.getFieldOrder(), kOfxImageFieldUpper); + EXPECT_DOUBLE_EQ(clip.getUnmappedFrameRate(), 30.0); + + clip.getUnmappedFrameRange(start_frame, end_frame); + EXPECT_DOUBLE_EQ(start_frame, 60.0); + EXPECT_DOUBLE_EQ(end_frame, 180.0); + + EXPECT_FALSE(clip.getContinuousSamples()); + EXPECT_FALSE(clip.getConnected()); +} + +TEST(PluginSupportClip, GetImageClampsBoundsAndCachesOutput) +{ + OFX::Host::ImageEffect::ClipDescriptor desc(kOfxImageEffectOutputClipName); + olive::VideoParams params = + MakeParams(100, 80, olive::core::PixelFormat::U8, 4, true); + olive::plugin::OliveClipInstance clip(nullptr, desc, params); + + OfxRectD optional_bounds = { -10.0, -10.0, 200.0, 200.0 }; + OFX::Host::ImageEffect::Image *image = + clip.getImage(0.0, &optional_bounds); + ASSERT_NE(image, nullptr); + + auto *olive_image = static_cast(image); + EXPECT_EQ(olive_image->width(), 100); + EXPECT_EQ(olive_image->height(), 80); + + OFX::Host::ImageEffect::Image *image_again = + clip.getImage(0.0, nullptr); + EXPECT_EQ(image, image_again); +} + +TEST(PluginSupportClip, GetImageReturnsNewImageForNonOutput) +{ + OFX::Host::ImageEffect::ClipDescriptor desc("Source"); + olive::VideoParams params = + MakeParams(64, 64, olive::core::PixelFormat::U8, 4, false); + olive::plugin::OliveClipInstance clip(nullptr, desc, params); + + OFX::Host::ImageEffect::Image *first = clip.getImage(0.0, nullptr); + OFX::Host::ImageEffect::Image *second = clip.getImage(0.0, nullptr); + + EXPECT_NE(first, nullptr); + EXPECT_NE(second, nullptr); + EXPECT_NE(first, second); + + first->releaseReference(); + second->releaseReference(); +} diff --git a/tests/gtest/plugin_support_image_test.cpp b/tests/gtest/plugin_support_image_test.cpp new file mode 100644 index 000000000..de426c68a --- /dev/null +++ b/tests/gtest/plugin_support_image_test.cpp @@ -0,0 +1,91 @@ +#include + +#include "ofxImageEffect.h" +#include "ofxhClip.h" +#include "pluginSupport/OliveClip.h" +#include "pluginSupport/image.h" + +namespace { +olive::VideoParams MakeParams(int width, int height, + olive::core::PixelFormat format, + int channels, + bool premultiplied) +{ + olive::VideoParams params; + params.set_width(width); + params.set_height(height); + params.set_format(format); + params.set_channel_count(channels); + params.set_premultiplied_alpha(premultiplied); + return params; +} +} + +TEST(PluginSupportImage, AllocateFromParamsSetsProperties) +{ + OFX::Host::ImageEffect::ClipDescriptor desc(kOfxImageEffectOutputClipName); + olive::VideoParams params = + MakeParams(640, 480, olive::core::PixelFormat::U8, 4, true); + olive::plugin::OliveClipInstance clip(nullptr, desc, params); + + olive::plugin::Image image(clip); + OfxRectI bounds = { 0, 0, 640, 480 }; + OfxRectI rod = bounds; + image.AllocateFromParams(params, bounds, rod, true); + + EXPECT_NE(image.data(), nullptr); + EXPECT_EQ(image.width(), 640); + EXPECT_EQ(image.height(), 480); + EXPECT_EQ(image.row_bytes(), 640 * 4); + EXPECT_EQ(image.pixel_format(), olive::core::PixelFormat::U8); + EXPECT_EQ(image.channel_count(), 4); + EXPECT_TRUE(image.premultiplied_alpha()); +} + +TEST(PluginSupportImage, EnsureAllocatedFromParamsClearsAndResizes) +{ + OFX::Host::ImageEffect::ClipDescriptor desc(kOfxImageEffectOutputClipName); + olive::VideoParams params = + MakeParams(64, 32, olive::core::PixelFormat::U8, 3, false); + olive::plugin::OliveClipInstance clip(nullptr, desc, params); + + olive::plugin::Image image(clip); + OfxRectI bounds = { 0, 0, 64, 32 }; + OfxRectI rod = bounds; + image.AllocateFromParams(params, bounds, rod, true); + ASSERT_NE(image.data(), nullptr); + image.data()[0] = 0xAB; + + image.EnsureAllocatedFromParams(params, bounds, rod, true); + EXPECT_EQ(image.data()[0], 0); + + OfxRectI new_bounds = { 0, 0, 16, 16 }; + image.EnsureAllocatedFromParams(params, new_bounds, rod, false); + EXPECT_EQ(image.width(), 16); + EXPECT_EQ(image.height(), 16); +} + +TEST(PluginSupportImage, PropertyFallbacks) +{ + OFX::Host::ImageEffect::ClipDescriptor desc(kOfxImageEffectOutputClipName); + olive::VideoParams params = + MakeParams(1, 1, olive::core::PixelFormat::INVALID, 0, false); + olive::plugin::OliveClipInstance clip(nullptr, desc, params); + + olive::plugin::Image image(clip); + image.setStringProperty(kOfxImageEffectPropPixelDepth, kOfxBitDepthHalf); + image.setStringProperty(kOfxImageEffectPropComponents, + kOfxImageComponentRGB); + image.setStringProperty(kOfxImageEffectPropPreMultiplication, + kOfxImagePreMultiplied); + image.setIntProperty(kOfxImagePropBounds, 10, 0); + image.setIntProperty(kOfxImagePropBounds, 20, 1); + image.setIntProperty(kOfxImagePropBounds, 42, 2); + image.setIntProperty(kOfxImagePropBounds, 70, 3); + + EXPECT_EQ(image.pixel_format(), olive::core::PixelFormat::F16); + EXPECT_EQ(image.channel_count(), 3); + EXPECT_TRUE(image.premultiplied_alpha()); + EXPECT_EQ(image.width(), 32); + EXPECT_EQ(image.height(), 50); +} diff --git a/tests/gtest/render_audioparams_branch_test.cpp b/tests/gtest/render_audioparams_branch_test.cpp new file mode 100644 index 000000000..60ba7595f --- /dev/null +++ b/tests/gtest/render_audioparams_branch_test.cpp @@ -0,0 +1,42 @@ +#include + +#include "olive/core/render/audioparams.h" + +TEST(RenderAudioParams, ValidityAndEquality) +{ + olive::core::AudioParams invalid; + EXPECT_FALSE(invalid.is_valid()); + + olive::core::AudioParams params( + 48000, AV_CH_LAYOUT_STEREO, olive::core::SampleFormat::S16); + EXPECT_TRUE(params.is_valid()); + + olive::core::AudioParams other( + 48000, AV_CH_LAYOUT_STEREO, olive::core::SampleFormat::S16); + EXPECT_TRUE(params == other); + + other.set_sample_rate(44100); + EXPECT_TRUE(params != other); +} + +TEST(RenderAudioParams, TimeAndSampleConversions) +{ + olive::core::AudioParams params( + 48000, AV_CH_LAYOUT_STEREO, olive::core::SampleFormat::S16); + + EXPECT_EQ(params.channel_count(), 2); + EXPECT_EQ(params.bytes_per_sample_per_channel(), 2); + EXPECT_EQ(params.bits_per_sample(), 16); + + EXPECT_EQ(params.time_to_samples(1.0), 48000); + EXPECT_EQ(params.time_to_bytes_per_channel(1.0), 96000); + EXPECT_EQ(params.time_to_bytes(1.0), 192000); + + EXPECT_EQ(params.samples_to_bytes(48000), 192000); + EXPECT_EQ(params.samples_to_bytes_per_channel(48000), 96000); + + EXPECT_EQ(params.bytes_to_samples(192000), 48000); + EXPECT_EQ(params.bytes_to_time(192000), olive::core::rational(1, 1)); + EXPECT_EQ(params.bytes_per_channel_to_time(96000), + olive::core::rational(1, 1)); +} diff --git a/tests/gtest/render_pixelformat_test.cpp b/tests/gtest/render_pixelformat_test.cpp new file mode 100644 index 000000000..d0cccbb02 --- /dev/null +++ b/tests/gtest/render_pixelformat_test.cpp @@ -0,0 +1,28 @@ +#include + +#include "olive/core/render/pixelformat.h" + +TEST(RenderPixelFormat, ByteCountAndString) +{ + using olive::core::PixelFormat; + + EXPECT_EQ(PixelFormat::byte_count(PixelFormat::INVALID), 0); + EXPECT_EQ(PixelFormat::byte_count(PixelFormat::U8), 1); + EXPECT_EQ(PixelFormat::byte_count(PixelFormat::U16), 2); + EXPECT_EQ(PixelFormat::byte_count(PixelFormat::F16), 2); + EXPECT_EQ(PixelFormat::byte_count(PixelFormat::F32), 4); + + EXPECT_EQ(PixelFormat(PixelFormat::U8).to_string(), std::string("u8")); + EXPECT_EQ(PixelFormat(PixelFormat::INVALID).to_string(), std::string("")); +} + +TEST(RenderPixelFormat, FloatChecks) +{ + using olive::core::PixelFormat; + + EXPECT_FALSE(PixelFormat::is_float(PixelFormat::U8)); + EXPECT_FALSE(PixelFormat::is_float(PixelFormat::U16)); + EXPECT_TRUE(PixelFormat::is_float(PixelFormat::F16)); + EXPECT_TRUE(PixelFormat::is_float(PixelFormat::F32)); + EXPECT_FALSE(PixelFormat::is_float(PixelFormat::INVALID)); +} diff --git a/tests/gtest/render_sampleformat_test.cpp b/tests/gtest/render_sampleformat_test.cpp new file mode 100644 index 000000000..811332061 --- /dev/null +++ b/tests/gtest/render_sampleformat_test.cpp @@ -0,0 +1,29 @@ +#include + +#include "olive/core/render/sampleformat.h" + +TEST(RenderSampleFormat, ByteCountAndStringRoundTrip) +{ + using olive::core::SampleFormat; + + EXPECT_EQ(SampleFormat::byte_count(SampleFormat::INVALID), 0); + EXPECT_EQ(SampleFormat::byte_count(SampleFormat::U8), 1); + EXPECT_EQ(SampleFormat::byte_count(SampleFormat::S16), 2); + EXPECT_EQ(SampleFormat::byte_count(SampleFormat::F32), 4); + EXPECT_EQ(SampleFormat::byte_count(SampleFormat::F64), 8); + + EXPECT_EQ(SampleFormat::to_string(SampleFormat::S16), "s16"); + EXPECT_EQ(SampleFormat::from_string("s16"), SampleFormat::S16); + EXPECT_EQ(SampleFormat::from_string(""), SampleFormat::INVALID); + EXPECT_EQ(SampleFormat::from_string("unknown"), SampleFormat::INVALID); +} + +TEST(RenderSampleFormat, PackedAndPlanarChecks) +{ + using olive::core::SampleFormat; + + EXPECT_TRUE(SampleFormat::is_packed(SampleFormat::S16)); + EXPECT_FALSE(SampleFormat::is_packed(SampleFormat::S16P)); + EXPECT_TRUE(SampleFormat::is_planar(SampleFormat::S16P)); + EXPECT_FALSE(SampleFormat::is_planar(SampleFormat::S16)); +} diff --git a/tests/gtest/render_videoparams_branch_test.cpp b/tests/gtest/render_videoparams_branch_test.cpp new file mode 100644 index 000000000..6db883d66 --- /dev/null +++ b/tests/gtest/render_videoparams_branch_test.cpp @@ -0,0 +1,84 @@ +#include + +extern "C" { +#include +} + +#include "render/videoparams.h" + +TEST(RenderVideoParams, BytesPerChannelAndPixel) +{ + EXPECT_EQ(olive::VideoParams::GetBytesPerChannel( + olive::core::PixelFormat::INVALID), + 0); + EXPECT_EQ(olive::VideoParams::GetBytesPerChannel( + olive::core::PixelFormat::U8), + 1); + EXPECT_EQ(olive::VideoParams::GetBytesPerChannel( + olive::core::PixelFormat::U16), + 2); + EXPECT_EQ(olive::VideoParams::GetBytesPerChannel( + olive::core::PixelFormat::F16), + 2); + EXPECT_EQ(olive::VideoParams::GetBytesPerChannel( + olive::core::PixelFormat::F32), + 4); + EXPECT_EQ(olive::VideoParams::GetBytesPerPixel( + olive::core::PixelFormat::U8, 4), + 4); +} + +TEST(RenderVideoParams, DividerAndFormatNames) +{ + EXPECT_EQ(olive::VideoParams::GetNameForDivider(1), + QStringLiteral("Full")); + EXPECT_EQ(olive::VideoParams::GetNameForDivider(3), + QStringLiteral("1/3")); + + const QString unknown = + olive::VideoParams::GetFormatName(olive::core::PixelFormat::INVALID); + EXPECT_TRUE(unknown.contains(QStringLiteral("Unknown"))); +} + +TEST(RenderVideoParams, ScalingAndDividerForTarget) +{ + EXPECT_EQ(olive::VideoParams::GetScaledDimension(100, 3), 33); + EXPECT_EQ(olive::VideoParams::GetDividerForTargetResolution( + 1920, 1080, 960, 540), + 2); + EXPECT_EQ(olive::VideoParams::GetDividerForTargetResolution( + 1920, 1080, 480, 270), + 4); +} + +TEST(RenderVideoParams, FrameRateStringsAndPixelAspect) +{ + const QString fps = + olive::VideoParams::FrameRateToString(olive::core::rational(24, 1)); + EXPECT_TRUE(fps.contains(QStringLiteral("24"))); + EXPECT_TRUE(fps.contains(QStringLiteral("FPS"))); + + const QStringList names = + olive::VideoParams::GetStandardPixelAspectRatioNames(); + ASSERT_EQ(names.size(), 6); + EXPECT_TRUE(names.at(0).contains(QStringLiteral("1.0000"))); +} + +TEST(RenderVideoParams, ValidityAndTimebase) +{ + olive::VideoParams params; + EXPECT_FALSE(params.is_valid()); + EXPECT_EQ(params.get_time_in_timebase_units(olive::core::rational(1, 1)), + AV_NOPTS_VALUE); + + params.set_width(1920); + params.set_height(1080); + params.set_format(olive::core::PixelFormat::U8); + params.set_channel_count(4); + params.set_pixel_aspect_ratio(olive::core::rational(1, 1)); + params.set_time_base(olive::core::rational(1, 1)); + params.set_start_time(10); + EXPECT_TRUE(params.is_valid()); + EXPECT_EQ(params.get_time_in_timebase_units(olive::core::rational(2, 1)), + 12); +}