Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring #27

Merged
merged 3 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/SuperBuild/Builddtk-deps.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
include(ExternalProject)

set(dtk_GIT_REPOSITORY "https://github.com/darbyjohnston/dtk.git")
set(dtk_GIT_TAG "11e0c38016c8c7b860a7bc03dbc0adec7a1f0d91")
set(dtk_GIT_TAG "957d7bb8e6f7e12fc291e8c31a4180ee4a9dfd8f")

set(dtk-deps_ARGS
${toucan_EXTERNAL_PROJECT_ARGS}
Expand Down
2 changes: 1 addition & 1 deletion cmake/SuperBuild/Builddtk.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
include(ExternalProject)

set(dtk_GIT_REPOSITORY "https://github.com/darbyjohnston/dtk.git")
set(dtk_GIT_TAG "11e0c38016c8c7b860a7bc03dbc0adec7a1f0d91")
set(dtk_GIT_TAG "957d7bb8e6f7e12fc291e8c31a4180ee4a9dfd8f")

set(dtk_DEPS dtk-deps)
set(dtk_ARGS
Expand Down
2 changes: 2 additions & 0 deletions lib/toucan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ set(HEADERS
PropertySet.h
Read.h
TimeWarp.h
TimelineAlgo.h
TimelineWrapper.h
Util.h)
set(HEADERS_PRIVATE
Expand All @@ -30,6 +31,7 @@ set(SOURCE
PropertySet.cpp
Read.cpp
TimeWarp.cpp
TimelineAlgo.cpp
TimelineWrapper.cpp
Util.cpp)
if(WIN32)
Expand Down
115 changes: 70 additions & 45 deletions lib/toucan/ImageGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "ImageEffectHost.h"
#include "Read.h"
#include "TimeWarp.h"
#include "TimelineAlgo.h"
#include "Util.h"

#include <opentimelineio/clip.h>
Expand All @@ -21,6 +22,19 @@ namespace toucan
namespace
{
const std::string logPrefix = "toucan::ImageGraph";

std::string toImageDataType(const OIIO::TypeDesc& value)
{
std::string out = "Unknown";
switch (value.basetype)
{
case OIIO::TypeDesc::UINT8: out = "u8"; break;
case OIIO::TypeDesc::UINT16: out = "u16"; break;
case OIIO::TypeDesc::HALF: out = "half"; break;
case OIIO::TypeDesc::FLOAT: out = "float"; break;
}
return out;
}
}

ImageGraph::ImageGraph(
Expand All @@ -34,54 +48,55 @@ namespace toucan
{
_loadCache.setMax(10);

// Get the image size from the first video clip.
for (auto track : _timelineWrapper->getTimeline()->find_children<OTIO_NS::Track>())
// Get the image information from the first video clip.
for (auto clip : getVideoClips(_timelineWrapper->getTimeline()))
{
if (OTIO_NS::Track::Kind::video == track->kind())
if (auto externalRef = dynamic_cast<OTIO_NS::ExternalReference*>(clip->media_reference()))
{
for (auto clip : track->find_clips())
auto read = std::make_shared<ReadNode>(
_timelineWrapper->getMediaPath(externalRef->target_url()),
_timelineWrapper->getMemoryReference(externalRef->target_url()));
const auto& spec = read->getSpec();
if (spec.width > 0)
{
if (auto externalRef = dynamic_cast<OTIO_NS::ExternalReference*>(clip->media_reference()))
{
auto read = std::make_shared<ReadNode>(
_timelineWrapper->getMediaPath(externalRef->target_url()),
_timelineWrapper->getMemoryReference(externalRef->target_url()));
const auto& spec = read->getSpec();
if (spec.width > 0)
{
_imageSize.x = spec.width;
_imageSize.y = spec.height;
break;
}
}
else if (auto sequenceRef = dynamic_cast<OTIO_NS::ImageSequenceReference*>(clip->media_reference()))
{
auto read = std::make_shared<SequenceReadNode>(
_timelineWrapper->getMediaPath(sequenceRef->target_url_base()),
sequenceRef->name_prefix(),
sequenceRef->name_suffix(),
sequenceRef->start_frame(),
sequenceRef->frame_step(),
sequenceRef->rate(),
sequenceRef->frame_zero_padding(),
_timelineWrapper->getMemoryReferences());
const auto& spec = read->getSpec();
if (spec.width > 0)
{
_imageSize.x = spec.width;
_imageSize.y = spec.height;
break;
}
}
else if (auto generatorRef = dynamic_cast<OTIO_NS::GeneratorReference*>(clip->media_reference()))
{
auto parameters = generatorRef->parameters();
auto i = parameters.find("size");
if (i != parameters.end() && i->second.has_value())
{
anyToVec(std::any_cast<OTIO_NS::AnyVector>(i->second), _imageSize);
}
}
_imageSize.x = spec.width;
_imageSize.y = spec.height;
_imageChannels = spec.nchannels;
_imageDataType = toImageDataType(spec.format);
break;
}
}
else if (auto sequenceRef = dynamic_cast<OTIO_NS::ImageSequenceReference*>(clip->media_reference()))
{
auto read = std::make_shared<SequenceReadNode>(
_timelineWrapper->getMediaPath(sequenceRef->target_url_base()),
sequenceRef->name_prefix(),
sequenceRef->name_suffix(),
sequenceRef->start_frame(),
sequenceRef->frame_step(),
sequenceRef->rate(),
sequenceRef->frame_zero_padding(),
_timelineWrapper->getMemoryReferences());
const auto& spec = read->getSpec();
if (spec.width > 0)
{
_imageSize.x = spec.width;
_imageSize.y = spec.height;
_imageChannels = spec.nchannels;
_imageDataType = toImageDataType(spec.format);
break;
}
}
else if (auto generatorRef = dynamic_cast<OTIO_NS::GeneratorReference*>(clip->media_reference()))
{
auto parameters = generatorRef->parameters();
auto i = parameters.find("size");
if (i != parameters.end() && i->second.has_value())
{
anyToVec(std::any_cast<OTIO_NS::AnyVector>(i->second), _imageSize);
//! \bug Hard coded:
_imageChannels = 4;
_imageDataType = toImageDataType(OIIO::TypeDesc::UINT8);
}
}
}
Expand All @@ -95,6 +110,16 @@ namespace toucan
return _imageSize;
}

int ImageGraph::getImageChannels() const
{
return _imageChannels;
}

const std::string& ImageGraph::getImageDataType() const
{
return _imageDataType;
}

std::shared_ptr<IImageNode> ImageGraph::exec(
const std::shared_ptr<ImageEffectHost>& host,
const OTIO_NS::RationalTime& time)
Expand Down
8 changes: 8 additions & 0 deletions lib/toucan/ImageGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ namespace toucan
//! Get the timeline image size.
const IMATH_NAMESPACE::V2i& getImageSize() const;

//! Get the timeline image channels.
int getImageChannels() const;

//! Get the timeline image data type.
const std::string& getImageDataType() const;

//! Get an image graph for the given time.
std::shared_ptr<IImageNode> exec(
const std::shared_ptr<ImageEffectHost>&,
Expand Down Expand Up @@ -66,6 +72,8 @@ namespace toucan
OTIO_NS::TimeRange _timeRange;
ImageGraphOptions _options;
IMATH_NAMESPACE::V2i _imageSize = IMATH_NAMESPACE::V2i(0, 0);
int _imageChannels = 0;
std::string _imageDataType;
LRUCache<OTIO_NS::MediaReference*, std::shared_ptr<ReadNode> > _loadCache;
};
}
67 changes: 67 additions & 0 deletions lib/toucan/TimelineAlgo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Contributors to the toucan project.

#include "TimelineAlgo.h"

#include <opentimelineio/clip.h>

namespace toucan
{
std::vector<OTIO_NS::SerializableObject::Retainer<OTIO_NS::Clip> >
getVideoClips(const OTIO_NS::SerializableObject::Retainer<OTIO_NS::Timeline>& timeline)
{
std::vector<OTIO_NS::SerializableObject::Retainer<OTIO_NS::Clip> > out;
for (const auto& child : timeline->tracks()->children())
{
if (auto track = OTIO_NS::dynamic_retainer_cast<OTIO_NS::Track>(child))
{
if (OTIO_NS::Track::Kind::video == track->kind())
{
const auto clips = track->find_clips(nullptr, std::nullopt, true);
out.insert(out.end(), clips.begin(), clips.end());
}
}
}
return out;
}

std::optional<OTIO_NS::TimeRange> getTimeRange(
const std::vector<OTIO_NS::SerializableObject::Retainer<OTIO_NS::Item> >& items,
const OTIO_NS::RationalTime& startTime,
double rate)
{
std::optional<OTIO_NS::TimeRange> out;
for (const auto& item : items)
{
//! \bug Shouldn't trimmed_range_in_parent() check whether the parent
//! is null?
if (item->parent())
{
const auto timeRangeOpt = item->trimmed_range_in_parent();
if (timeRangeOpt.has_value())
{
const OTIO_NS::TimeRange timeRange(
timeRangeOpt.value().start_time() + startTime,
timeRangeOpt.value().duration());
if (out.has_value())
{
out = OTIO_NS::TimeRange::range_from_start_end_time_inclusive(
std::min(
out.value().start_time(),
timeRange.start_time().rescaled_to(rate).round()),
std::max(
out.value().end_time_inclusive(),
timeRange.end_time_inclusive().rescaled_to(rate).round()));
}
else
{
out = OTIO_NS::TimeRange(
timeRange.start_time().rescaled_to(rate).round(),
timeRange.duration().rescaled_to(rate).round());
}
}
}
}
return out;
}
}
19 changes: 19 additions & 0 deletions lib/toucan/TimelineAlgo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Contributors to the toucan project.

#pragma once

#include <opentimelineio/timeline.h>

namespace toucan
{
//! Get the video clips in a timeline.
std::vector<OTIO_NS::SerializableObject::Retainer<OTIO_NS::Clip> >
getVideoClips(const OTIO_NS::SerializableObject::Retainer<OTIO_NS::Timeline>&);

//! Get the range of multiple items.
std::optional<OTIO_NS::TimeRange> getTimeRange(
const std::vector<OTIO_NS::SerializableObject::Retainer<OTIO_NS::Item> >&,
const OTIO_NS::RationalTime& startTime,
double rate);
}
2 changes: 2 additions & 0 deletions lib/toucan/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include "Util.h"

#include <opentimelineio/clip.h>

#include <OpenFX/ofxImageEffect.h>

#include <algorithm>
Expand Down
10 changes: 10 additions & 0 deletions lib/toucanView/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ namespace toucan
return _graph->getImageSize();
}

int Document::getImageChannels() const
{
return _graph->getImageChannels();
}

const std::string& Document::getImageDataType() const
{
return _graph->getImageDataType();
}

std::shared_ptr<dtk::IObservableValue<std::shared_ptr<dtk::Image> > > Document::observeCurrentImage() const
{
return _currentImage;
Expand Down
2 changes: 2 additions & 0 deletions lib/toucanView/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ namespace toucan
const std::shared_ptr<ThumbnailGenerator>& getThumbnailGenerator() const;

const IMATH_NAMESPACE::V2i& getImageSize() const;
int getImageChannels() const;
const std::string& getImageDataType() const;

std::shared_ptr<dtk::IObservableValue<std::shared_ptr<dtk::Image> > > observeCurrentImage() const;

Expand Down
12 changes: 8 additions & 4 deletions lib/toucanView/InfoBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,22 @@ namespace toucan
const IMATH_NAMESPACE::V2i& imageSize = document->getImageSize();
const size_t trackCount = document->getTimeline()->find_children<OTIO_NS::Track>().size();

text = dtk::Format("{0}: {1}x{2}, {3} tracks").
text = dtk::Format("{0}: {1}x{2}, {3} channels, {4} data, {5} tracks").
arg(dtk::elide(document->getPath().filename().string())).
arg(imageSize.x).
arg(imageSize.y).
arg(document->getImageChannels()).
arg(document->getImageDataType()).
arg(trackCount);
tooltip = dtk::Format(
"path: {0}\n"
"resolution: {1}x{2}\n"
"tracks: {3}").
"Path: {0}\n"
"Render: {1}x{2}, {3} channels, {4} data\n"
"Tracks: {5}").
arg(document->getPath().string()).
arg(imageSize.x).
arg(imageSize.y).
arg(document->getImageChannels()).
arg(document->getImageDataType()).
arg(trackCount);
}
_label->setText(text);
Expand Down
Loading