Skip to content

Commit 75d66d4

Browse files
committed
Finished edit algorithms.
Added errorStatus. Finished unit tests.
1 parent 8f79ec5 commit 75d66d4

File tree

5 files changed

+190
-94
lines changed

5 files changed

+190
-94
lines changed

src/opentimelineio/algo/editAlgorithm.cpp

Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,26 @@ namespace otime = opentime::OPENTIME_VERSION;
1515
using otime::RationalTime;
1616
using otime::TimeRange;
1717

18-
std::ostream& operator << (std::ostream& os, const RationalTime& value)
18+
namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { namespace algo {
19+
20+
21+
namespace
1922
{
20-
os << std::fixed << value.value() << "/" << value.rate();
21-
return os;
22-
}
2323

24-
std::ostream& operator << (std::ostream& os, const TimeRange& value)
24+
std::vector<SerializableObject::Retainer<Item> >
25+
find_items_in_composition(
26+
Composition* composition,
27+
RationalTime const& time,
28+
ErrorStatus* error_status)
2529
{
26-
os << std::fixed << value.start_time().value() << "/" <<
27-
value.duration().value() << "/" <<
28-
value.duration().rate();
29-
return os;
30+
// Find the item to slice.
31+
TimeRange search_range(time, RationalTime(1.0, time.rate()));
32+
return composition->find_children<Item>(error_status, search_range, true);
3033
}
3134

32-
namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { namespace algo {
33-
35+
} // namespace
36+
37+
3438
void
3539
overwrite(
3640
Item* item,
@@ -65,26 +69,37 @@ overwrite(
6569
composition->find_children<Item>(error_status, range, true);
6670
TimeRange item_range =
6771
composition->trimmed_range_of_child(items.front()).value();
68-
if (1 == items.size() && item_range.contains(range))
72+
if (1 == items.size() && item_range.contains(range, 0.0))
6973
{
7074
// The item overwrites a portion inside an item.
7175
const RationalTime first_duration =
7276
range.start_time() - item_range.start_time();
7377
const RationalTime second_duration =
7478
item_range.duration() - range.duration() - first_duration;
75-
auto second_item = dynamic_cast<Item*>(items.front()->clone());
7679
int insert_index = composition->index_of_child(items.front()) + 1;
7780
TimeRange trimmed_range = items.front()->trimmed_range();
7881
TimeRange source_range(trimmed_range.start_time(), first_duration);
79-
items.front()->set_source_range(source_range);
80-
++insert_index;
82+
if (first_duration.value() <= 0.0)
83+
{
84+
--insert_index;
85+
composition->remove_child(insert_index);
86+
}
87+
else
88+
{
89+
items.front()->set_source_range(source_range);
90+
++insert_index;
91+
}
8192
composition->insert_child(insert_index, item);
82-
++insert_index;
83-
trimmed_range = second_item->trimmed_range();
84-
source_range =
85-
TimeRange(trimmed_range.start_time(), second_duration);
86-
second_item->set_source_range(source_range);
87-
composition->insert_child(insert_index, second_item);
93+
if (second_duration.value() > 0.0)
94+
{
95+
auto second_item = dynamic_cast<Item*>(items.front()->clone());
96+
trimmed_range = second_item->trimmed_range();
97+
source_range =
98+
TimeRange(trimmed_range.start_time(), second_duration);
99+
++insert_index;
100+
second_item->set_source_range(source_range);
101+
composition->insert_child(insert_index, second_item);
102+
}
88103
}
89104
else
90105
{
@@ -160,10 +175,9 @@ insert(
160175
Item* fill_template,
161176
ErrorStatus* error_status)
162177
{
163-
// Find the item to insert into (will be split).
164-
auto item = dynamic_retainer_cast<Item>(
165-
composition->child_at_time(time, error_status, true));
166-
if (!item)
178+
// Find the item to insert into.
179+
auto items = find_items_in_composition(composition, time, error_status);
180+
if (items.empty())
167181
{
168182
const TimeRange composition_range = composition->trimmed_range();
169183
if (time >= composition_range.end_time_exclusive())
@@ -188,6 +202,13 @@ insert(
188202
composition->insert_child(0, insert_item);
189203
return;
190204
}
205+
if (items.size() > 1)
206+
{
207+
if (error_status)
208+
*error_status = ErrorStatus::INTERNAL_ERROR;
209+
return;
210+
}
211+
auto item = items.front();
191212

192213
const int index = composition->index_of_child(item);
193214
const TimeRange range = composition->trimmed_range_of_child_at_index(index);
@@ -208,7 +229,7 @@ insert(
208229
composition->insert_child(insert_index, insert_item);
209230
const TimeRange insert_range = composition->trimmed_range_of_child_at_index(insert_index);
210231

211-
// Second item from splittin item
232+
// Second item from splitting item
212233
if (split)
213234
{
214235
const TimeRange second_source_range(
@@ -301,9 +322,7 @@ slice(
301322
bool const remove_transitions,
302323
ErrorStatus* error_status)
303324
{
304-
// Find the item to slice.
305-
TimeRange search_range(time, RationalTime(1.0, time.rate()));
306-
auto items = composition->find_children<Item>(error_status, search_range, true);
325+
auto items = find_items_in_composition(composition, time, error_status);
307326
if (items.empty())
308327
{
309328
if (error_status)
@@ -316,8 +335,8 @@ slice(
316335
*error_status = ErrorStatus::INTERNAL_ERROR;
317336
return;
318337
}
319-
auto item = items[0];
320-
338+
auto item = items.front();
339+
321340
const int index = composition->index_of_child(item);
322341
const TimeRange range = composition->trimmed_range_of_child_at_index(index);
323342

@@ -597,52 +616,59 @@ fill(
597616
ReferencePoint const reference_point,
598617
ErrorStatus* error_status)
599618
{
600-
// Find the item to insert/overwrite/fit.
619+
// Find the gap to replace.
601620
auto gap = dynamic_retainer_cast<Gap>(
602621
track->child_at_time(track_time, error_status, true));
603622
if (!gap)
604623
{
605624
if (error_status)
606-
*error_status = ErrorStatus::NOT_AN_ITEM;
625+
*error_status = ErrorStatus::NOT_A_GAP;
607626
return;
608627
}
609628

610-
const TimeRange clip_range = item->trimmed_range();
611-
const TimeRange gap_range = gap->trimmed_range();
612-
const TimeRange gap_track_range =
613-
track->trimmed_range_of_child(gap).value();
629+
const TimeRange clip_range = item->trimmed_range();
630+
const TimeRange gap_range = gap->trimmed_range();
631+
TimeRange gap_track_range = track->trimmed_range_of_child(gap).value();
632+
RationalTime duration = clip_range.duration();
614633

615634
switch (reference_point)
616635
{
617636
case ReferencePoint::Sequence: {
618637
RationalTime start_time = clip_range.start_time();
619-
RationalTime duration = clip_range.duration();
638+
const RationalTime gap_start_time = gap_range.start_time();
620639
auto track_item = dynamic_cast<Item*>(item->clone());
621640

622641
// Check if start time is less than gap's start time (trim it if so)
623-
if (start_time < gap_range.start_time())
642+
if (start_time < gap_start_time)
624643
{
625-
start_time = gap_range.start_time();
644+
duration -= gap_start_time - start_time;
645+
start_time = gap_start_time;
626646
}
627647

628-
// Check if duration is longer (trim it if it is)
629-
if (clip_range.end_time_exclusive() >
630-
gap_range.end_time_exclusive())
648+
// Check if end time is longer (trim it if it is)
649+
if (clip_range.end_time_exclusive()
650+
> gap_range.end_time_exclusive())
631651
{
632652
duration = gap_range.end_time_exclusive() - start_time;
633653
}
634654
const TimeRange new_clip_range(start_time, duration);
635655
track_item->set_source_range(new_clip_range);
636-
const TimeRange time_range(
637-
track_time,
638-
gap_track_range.end_time_exclusive() - track_time);
656+
657+
if (duration
658+
> gap_track_range.end_time_exclusive() - track_time)
659+
{
660+
duration =
661+
gap_track_range.end_time_exclusive() - track_time;
662+
}
663+
664+
const TimeRange time_range(track_time, duration);
639665
overwrite(track_item, track, time_range, nullptr, error_status);
640666
return;
641667
}
642668

643669
case ReferencePoint::Fit: {
644670
const double pct = gap_range.duration().to_seconds()
645-
/ clip_range.duration().to_seconds();
671+
/ duration.to_seconds();
646672
const std::string& name = item->name();
647673
LinearTimeWarp* timeWarp =
648674
new LinearTimeWarp(name, name + "_timeWarp", pct);
@@ -658,9 +684,7 @@ fill(
658684

659685
case ReferencePoint::Source:
660686
default: {
661-
const TimeRange time_range(
662-
track_time,
663-
track_time + clip_range.duration() - clip_range.start_time());
687+
const TimeRange time_range(track_time, duration);
664688
overwrite(item, track, time_range, nullptr, error_status);
665689
return;
666690
}

src/opentimelineio/algo/editAlgorithm.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ void overwrite(
4040
//
4141
// item = item to insert (usually a clip)
4242
// composition = usually a track item.
43-
// time = time to insert at.
43+
// time = time to insert at. If < composition's start time, it will insert at 0 index.
44+
// If > composition's end_time_exclusive, it will append at end.
4445
// fill_template = item to fill in (usually a gap),
4546
// when time > composition's time.
4647
void insert(

src/opentimelineio/errorStatus.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ ErrorStatus::outcome_to_string(Outcome o)
6464
return "active key not found in media references";
6565
case MEDIA_REFERENCES_CONTAIN_EMPTY_KEY:
6666
return "the media references cannot contain an empty key";
67+
case NOT_A_GAP:
68+
return "object is not descendent of Gap type";
6769
default:
6870
return "unknown/illegal ErrorStatus::Outcome code";
6971
};

src/opentimelineio/errorStatus.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ struct ErrorStatus
4141
OBJECT_CYCLE,
4242
CANNOT_COMPUTE_BOUNDS,
4343
MEDIA_REFERENCES_DO_NOT_CONTAIN_ACTIVE_KEY,
44-
MEDIA_REFERENCES_CONTAIN_EMPTY_KEY
44+
MEDIA_REFERENCES_CONTAIN_EMPTY_KEY,
45+
NOT_A_GAP
4546
};
4647

4748
ErrorStatus()

0 commit comments

Comments
 (0)