Skip to content

Commit

Permalink
Add support for gaps
Browse files Browse the repository at this point in the history
  • Loading branch information
darbyjohnston committed Aug 10, 2024
1 parent 16edb10 commit 203d621
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 31 deletions.
File renamed without changes.
103 changes: 103 additions & 0 deletions data/Gap.otio
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
"OTIO_SCHEMA": "Timeline.1",
"metadata": {},
"name": "SimpleOver",
"tracks": {
"OTIO_SCHEMA": "Stack.1",
"children": [
{
"OTIO_SCHEMA": "Track.1",
"children": [
{
"OTIO_SCHEMA": "Clip.1",
"media_reference": {
"OTIO_SCHEMA": "ExternalReference.1",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 24
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 0
}
},
"target_url": "Letter_A.png"
},
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 24
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 0
}
},
"name": "Letter_A"
},
{
"OTIO_SCHEMA": "Gap.1",
"name": "Gap",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 24
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 0
}
}
},
{
"OTIO_SCHEMA": "Clip.1",
"media_reference": {
"OTIO_SCHEMA": "ExternalReference.1",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 24
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 0
}
},
"target_url": "Letter_C.png"
},
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 24
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 0
}
},
"name": "Letter_C"
}
],
"kind": "Video",
"name": "Video"
}
],
"name": "Stack"
}
}
2 changes: 2 additions & 0 deletions lib/toucan/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
set(HEADERS
ImageComp.h
ImageFill.h
ImageRead.h
ImageOp.h
TimelineTraverse.h)
set(SOURCE
ImageComp.cpp
ImageFill.cpp
ImageRead.cpp
ImageOp.cpp
TimelineTraverse.cpp)
Expand Down
35 changes: 35 additions & 0 deletions lib/toucan/ImageFill.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2024 Darby Johnston
// All rights reserved.

#include "ImageFill.h"

#include <OpenImageIO/imagebufalgo.h>

namespace toucan
{
ImageFill::~ImageFill()
{}

void ImageFill::setSize(int width, int height)
{
_width = width;
_height = height;
}

void ImageFill::setColor(float r, float g, float b, float a)
{
_r = r;
_g = g;
_b = b;
_a = a;
}

OIIO::ImageBuf ImageFill::exec()
{
OIIO::ImageBuf buf = OIIO::ImageBufAlgo::fill(
{ _r, _g, _b, _a },
OIIO::ROI(0, _width, 0, _height, 0, 1, 0, 4));
return buf;
}
}
33 changes: 33 additions & 0 deletions lib/toucan/ImageFill.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2024 Darby Johnston
// All rights reserved.

#pragma once

#include <toucan/ImageOp.h>

#include <filesystem>

namespace toucan
{
//! Image fill.
class ImageFill : public IImageOp
{
public:
virtual ~ImageFill();

void setSize(int width, int height);

void setColor(float r, float g, float b, float a);

OIIO::ImageBuf exec() override;

private:
int _width = 0;
int _height = 0;
float _r = 0.F;
float _g = 0.F;
float _b = 0.F;
float _a = 0.F;
};
}
33 changes: 27 additions & 6 deletions lib/toucan/TimelineTraverse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "TimelineTraverse.h"

#include "ImageComp.h"
#include "ImageFill.h"
#include "ImageRead.h"

#include <opentimelineio/externalReference.h>
Expand All @@ -16,23 +17,43 @@ namespace toucan
const OTIO_NS::SerializableObject::Retainer<OTIO_NS::Timeline>& timeline) :
_path(path),
_timeline(timeline)
{}
{
for (auto clip : _timeline->find_clips())
{
if (auto externalRef = dynamic_cast<OTIO_NS::ExternalReference*>(clip->media_reference()))
{
const std::string url = externalRef->target_url();
const std::filesystem::path path = _path / url;
OIIO::ImageBuf buf(path.string());
const auto& spec = buf.spec();
if (spec.width > 0)
{
_width = spec.width;
_height = spec.height;
break;
}
}
}
}

TimelineTraverse::~TimelineTraverse()
{}

std::shared_ptr<IImageOp> TimelineTraverse::exec(const OTIO_NS::RationalTime& time)
{
//std::cout << "traverse: " << time.value() << std::endl;
_comp.reset();
auto fill = std::make_shared<ImageFill>();
fill->setSize(_width, _height);
fill->setColor(.5F, .5F, .5F, 1.F);
_op = fill;
for (const auto& trackIt : _timeline->tracks()->children())
{
if (auto track = OTIO_NS::dynamic_retainer_cast<OTIO_NS::Track>(trackIt))
{
_track(time, track);
}
}
return _comp;
return _op;
}

void TimelineTraverse::_track(
Expand Down Expand Up @@ -65,15 +86,15 @@ namespace toucan

auto comp = std::make_shared<ImageComp>();
comp->setPremult(true);
if (_comp)
if (_op)
{
comp->setInputs({ read, _comp });
comp->setInputs({ read, _op });
}
else
{
comp->setInputs({ read });
}
_comp = comp;
_op = comp;
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion lib/toucan/TimelineTraverse.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ namespace toucan

std::filesystem::path _path;
OTIO_NS::SerializableObject::Retainer<OTIO_NS::Timeline> _timeline;
std::shared_ptr<ImageComp> _comp;
int _width = 0;
int _height = 0;
std::shared_ptr<IImageOp> _op;
};
}
1 change: 0 additions & 1 deletion tests/ImageCompTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ namespace toucan
void imageCompTest(const std::filesystem::path& path)
{
std::cout << "imageCompTest" << std::endl;

auto fg = std::make_shared<ImageRead>();
fg->setPath(path / "Letter_A.png");
auto bg = std::make_shared<ImageRead>();
Expand Down
1 change: 0 additions & 1 deletion tests/ImageReadTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ namespace toucan
void imageReadTest(const std::filesystem::path& path)
{
std::cout << "imageReadTest" << std::endl;

auto read = std::make_shared<ImageRead>();
read->setPath(path / "Letter_A.png");
auto buf = read->exec();
Expand Down
52 changes: 30 additions & 22 deletions tests/TimelineTraverseTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,39 @@ namespace toucan
void timelineTraverseTest(const std::filesystem::path& path)
{
std::cout << "timelineTraverseTest" << std::endl;

const std::filesystem::path timelinePath = path / "SimpleOver.otio";
if (auto timeline = OTIO_NS::SerializableObject::Retainer<OTIO_NS::Timeline>(
dynamic_cast<OTIO_NS::Timeline*>(OTIO_NS::Timeline::from_json_file(timelinePath.string()))))
const std::vector<std::string> otioFiles =
{
const OTIO_NS::RationalTime startTime = timeline->global_start_time().has_value() ?
timeline->global_start_time().value() :
OTIO_NS::RationalTime(0.0, timeline->duration().rate());
const OTIO_NS::TimeRange timeRange(startTime, timeline->duration());
const OTIO_NS::RationalTime timeInc(1.0, timeline->duration().rate());

auto traverse = std::make_shared<TimelineTraverse>(path, timeline);
for (OTIO_NS::RationalTime time = startTime;
time <= timeRange.end_time_inclusive();
time += timeInc)
"CompOver",
"Gap"
};
for (const auto& otioFile : otioFiles)
{
const std::filesystem::path timelinePath = path / (otioFile + ".otio");
if (auto timeline = OTIO_NS::SerializableObject::Retainer<OTIO_NS::Timeline>(
dynamic_cast<OTIO_NS::Timeline*>(OTIO_NS::Timeline::from_json_file(timelinePath.string()))))
{
std::cout << " frame: " << time.value() << std::endl;
if (auto op = traverse->exec(time))
const OTIO_NS::RationalTime startTime = timeline->global_start_time().has_value() ?
timeline->global_start_time().value() :
OTIO_NS::RationalTime(0.0, timeline->duration().rate());
const OTIO_NS::TimeRange timeRange(startTime, timeline->duration());
const OTIO_NS::RationalTime timeInc(1.0, timeline->duration().rate());

auto traverse = std::make_shared<TimelineTraverse>(path, timeline);
for (OTIO_NS::RationalTime time = startTime;
time <= timeRange.end_time_inclusive();
time += timeInc)
{
auto buf = op->exec();
std::stringstream ss;
ss << "TimelineTraverseTest." <<
std::setw(6) << std::setfill('0') << time.to_frames() <<
".png";
buf.write(ss.str());
std::cout << " " << otioFile << ": " << time.value() << "/" <<
timeRange.duration().value() << std::endl;
if (auto op = traverse->exec(time))
{
auto buf = op->exec();
std::stringstream ss;
ss << "TimelineTraverseTest_" << otioFile << "." <<
std::setw(6) << std::setfill('0') << time.to_frames() <<
".png";
buf.write(ss.str());
}
}
}
}
Expand Down

0 comments on commit 203d621

Please sign in to comment.