Open douglascomet opened 1 year ago
I had the same thought - but it seems that 'source_range' requires a negative number here or a lot of the test_cmx3600_adapter tests fail.
I had the same thought - but it seems that 'source_range' requires a negative number here or a lot of the test_cmx3600_adapter tests fail.
I've narrowed down the culprit for this to the use of transformed_time_range
. Afaik, there aren't any docs for what this function is supposed to do but through debugging I found that it generates the negative offset.
range_in_timeline = clip.transformed_time_range(
clip.trimmed_range(),
tracks
)
Found a (stale?) explanation of how record-in + out should be calculated, using transformed_time_range, rather than stored.
I also found the definition in src/item.cpp but am too ignorant to figure out what's going on...
RationalTime
Item::transformed_time(
RationalTime time,
Item const* to_item,
ErrorStatus* error_status) const
{
if (!to_item)
{
return time;
}
auto root = _highest_ancestor();
auto item = this;
auto result = time;
while (item != root && item != to_item)
{
auto parent = item->parent();
result -= item->trimmed_range(error_status).start_time();
if (is_error(error_status))
{
return result;
}
result += parent->range_of_child(item, error_status).start_time();
item = parent;
}
auto ancestor = item;
item = to_item;
while (item != root && item != ancestor)
{
auto parent = item->parent();
result += item->trimmed_range(error_status).start_time();
if (is_error(error_status))
{
return result;
}
result -= parent->range_of_child(item, error_status).start_time();
if (is_error(error_status))
{
return result;
}
item = parent;
}
assert(item == ancestor);
return result;
}
TimeRange
Item::transformed_time_range(
TimeRange time_range,
Item const* to_item,
ErrorStatus* error_status) const
{
return TimeRange(
transformed_time(time_range.start_time(), to_item, error_status),
time_range.duration());
}
So I asked chatgpt:
The code you provided appears to be C++ code related to the OpenTimelineIO library, specifically dealing with the transformation of time and time ranges within a timeline. Let's break down what these functions do:
RationalTime Item::transformed_time(RationalTime time, Item const* to_item, ErrorStatus* error_status) const
: This function is a method of anItem
in OpenTimelineIO. It's used to transform a givenRationalTime
(a type representing time with a numerator and denominator, often used for frame-based timecode) relative to anotherItem
in the timeline. Here's a step-by-step explanation of how it works:
- It takes three parameters:
time
(the time to transform),to_item
(the target item relative to which the transformation is performed), anderror_status
(a pointer to anErrorStatus
object that can hold error information).- If
to_item
is not provided (null), it returns the originaltime
as there's no need to perform any transformation.- It iterates through the items in the timeline, calculating the transformation of
time
to be relative toto_item
. This is done by adjusting the time based on the trimmed ranges and parent-child relationships between items in the timeline.- It returns the transformed
RationalTime
.
TimeRange Item::transformed_time_range(TimeRange time_range, Item const* to_item, ErrorStatus* error_status) const
: This function also belongs to anItem
in OpenTimelineIO. It's used to transform a givenTimeRange
relative to anotherItem
in the timeline. Here's how it works:
- It takes three parameters:
time_range
(the time range to transform, which includes a start time and duration),to_item
(the target item relative to which the transformation is performed), anderror_status
(a pointer to anErrorStatus
object that can hold error information).- It calls the
transformed_time
function to transform the start time of thetime_range
relative toto_item
.- It returns a new
TimeRange
with the transformed start time and the original duration.These functions are crucial for manipulating timelines and managing time-related data in the OpenTimelineIO library, especially when you need to perform edits, effects, or other transformations within a timeline. They help ensure that timecode and time ranges are adjusted correctly as items are moved or transformed within the timeline structure.
The editors I work with generate
.edl
(s) that typically start at or around01:00:00:00
. The reason they do this is because of the convention established by broadcast television to start at 1 hour. The editors also relayed that most, if not all, NLEs default their timelines to start at01:00:00:00
. Ideally, we would not have to conform how editors initialize their timelines and the adapters just react to what an editor choose to set up their timeline.Here is a sample
.edl
When I run he following code, the
cmx3600
adapter throws an error.I looked through the
cmx3600
adapter code and stumbled across this snippet, where aRationalTime
is constructed at00:00:00:00
.This code explains how the track in the above example becomes negative. This code is use to initialize the the track's source range and I think the source range should be based on the timing of the first clip found in the
.edl
instead of zero. I think this can be accomplished by doing the following:This simple change has the
start time
of the track be therecord_in
determined from the clip and the duration be zero. From what I can tell, the duration of the track starts at zero because it gets extended later in thecmx3600
adapter based on the clips found during parsing of the.edl
.Another QOL of improvement that could be made to the
cmx3600
adapter would be setting the timeline'sglobal_start_time
in this same code block. Currently theglobal_start_time
is never set. Like thestart_time
of the track, thestart_time
of timeline should also be based on the first clip found in the.edl.
With that in mind, the previous code suggestion would look like this: