Skip to content

Commit

Permalink
Merge branch 'develop' into bugfix/publisher_ui_convert_legacy_instan…
Browse files Browse the repository at this point in the history
…ces_emit_signal
  • Loading branch information
BigRoy authored Jan 13, 2025
2 parents f4ea9ae + b001a4c commit 3323e4b
Show file tree
Hide file tree
Showing 7 changed files with 360 additions and 59 deletions.
117 changes: 74 additions & 43 deletions client/ayon_core/pipeline/editorial.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,11 @@ def is_clip_from_media_sequence(otio_clip):
return is_input_sequence or is_input_sequence_legacy


def remap_range_on_file_sequence(otio_clip, in_out_range):
def remap_range_on_file_sequence(otio_clip, otio_range):
"""
Args:
otio_clip (otio.schema.Clip): The OTIO clip to check.
in_out_range (tuple[float, float]): The in-out range to remap.
otio_range (otio.schema.TimeRange): The trim range to apply.
Returns:
tuple(int, int): The remapped range as discrete frame number.
Expand All @@ -211,17 +211,24 @@ def remap_range_on_file_sequence(otio_clip, in_out_range):
if not is_clip_from_media_sequence(otio_clip):
raise ValueError(f"Cannot map on non-file sequence clip {otio_clip}.")

try:
media_in_trimmed, media_out_trimmed = in_out_range

except ValueError as error:
raise ValueError("Invalid in_out_range provided.") from error

media_ref = otio_clip.media_reference
available_range = otio_clip.available_range()
source_range = otio_clip.source_range
available_range_rate = available_range.start_time.rate
media_in = available_range.start_time.value

# Backward-compatibility for Hiero OTIO exporter.
# NTSC compatibility might introduce floating rates, when these are
# not exactly the same (23.976 vs 23.976024627685547)
# this will cause precision issue in computation.
# Currently round to 2 decimals for comparison,
# but this should always rescale after that.
rounded_av_rate = round(available_range_rate, 2)
rounded_range_rate = round(otio_range.start_time.rate, 2)

if rounded_av_rate != rounded_range_rate:
raise ValueError("Inconsistent range between clip and provided clip")

source_range = otio_clip.source_range
media_in = available_range.start_time
available_range_start_frame = (
available_range.start_time.to_frames()
)
Expand All @@ -231,19 +238,26 @@ def remap_range_on_file_sequence(otio_clip, in_out_range):
# source range for image sequence. Following code maintain
# backward-compatibility by adjusting media_in
# while we are updating those.
conformed_src_in = source_range.start_time.rescaled_to(
available_range_rate
)
if (
is_clip_from_media_sequence(otio_clip)
and available_range_start_frame == media_ref.start_frame
and source_range.start_time.to_frames() < media_ref.start_frame
and conformed_src_in.to_frames() < media_ref.start_frame
):
media_in = 0
media_in = otio.opentime.RationalTime(
0, rate=available_range_rate
)

src_offset_in = otio_range.start_time - media_in
frame_in = otio.opentime.RationalTime.from_frames(
media_in_trimmed - media_in + media_ref.start_frame,
media_ref.start_frame + src_offset_in.to_frames(),
rate=available_range_rate,
).to_frames()

frame_out = otio.opentime.RationalTime.from_frames(
media_out_trimmed - media_in + media_ref.start_frame,
frame_in + otio_range.duration.to_frames() - 1,
rate=available_range_rate,
).to_frames()

Expand All @@ -261,21 +275,6 @@ def get_media_range_with_retimes(otio_clip, handle_start, handle_end):
media_ref = otio_clip.media_reference
is_input_sequence = is_clip_from_media_sequence(otio_clip)

# Temporary.
# Some AYON custom OTIO exporter were implemented with relative
# source range for image sequence. Following code maintain
# backward-compatibility by adjusting available range
# while we are updating those.
if (
is_input_sequence
and available_range.start_time.to_frames() == media_ref.start_frame
and source_range.start_time.to_frames() < media_ref.start_frame
):
available_range = _ot.TimeRange(
_ot.RationalTime(0, rate=available_range_rate),
available_range.duration,
)

# Conform source range bounds to available range rate
# .e.g. embedded TC of (3600 sec/ 1h), duration 100 frames
#
Expand Down Expand Up @@ -320,6 +319,22 @@ def get_media_range_with_retimes(otio_clip, handle_start, handle_end):
else:
conformed_source_range = source_range

# Temporary.
# Some AYON custom OTIO exporter were implemented with relative
# source range for image sequence. Following code maintain
# backward-compatibility by adjusting available range
# while we are updating those.
if (
is_input_sequence
and available_range.start_time.to_frames() == media_ref.start_frame
and conformed_source_range.start_time.to_frames() <
media_ref.start_frame
):
available_range = _ot.TimeRange(
_ot.RationalTime(0, rate=available_range_rate),
available_range.duration,
)

# modifiers
time_scalar = 1.
offset_in = 0
Expand Down Expand Up @@ -374,31 +389,47 @@ def get_media_range_with_retimes(otio_clip, handle_start, handle_end):
offset_in, offset_out = offset_out, offset_in
handle_start, handle_end = handle_end, handle_start

# compute retimed range
media_in_trimmed = conformed_source_range.start_time.value + offset_in
media_out_trimmed = media_in_trimmed + (
(
conformed_source_range.duration.value
* abs(time_scalar)
+ offset_out
) - 1
)

media_in = available_range.start_time.value
media_out = available_range.end_time_inclusive().value

# If media source is an image sequence, returned
# mediaIn/mediaOut have to correspond
# to frame numbers from source sequence.
if is_input_sequence:

src_in = conformed_source_range.start_time
src_duration = conformed_source_range.duration

offset_in = otio.opentime.RationalTime(offset_in, rate=src_in.rate)
offset_duration = otio.opentime.RationalTime(
offset_out,
rate=src_duration.rate
)

trim_range = otio.opentime.TimeRange(
start_time=src_in + offset_in,
duration=src_duration + offset_duration
)

# preserve discrete frame numbers
media_in_trimmed, media_out_trimmed = remap_range_on_file_sequence(
otio_clip,
(media_in_trimmed, media_out_trimmed)
trim_range,
)
media_in = media_ref.start_frame
media_out = media_in + available_range.duration.to_frames() - 1

else:
# compute retimed range
media_in_trimmed = conformed_source_range.start_time.value + offset_in
media_out_trimmed = media_in_trimmed + (
(
conformed_source_range.duration.value
* abs(time_scalar)
+ offset_out
) - 1
)

media_in = available_range.start_time.value
media_out = available_range.end_time_inclusive().value

# adjust available handles if needed
if (media_in_trimmed - media_in) < handle_start:
handle_start = max(0, media_in_trimmed - media_in)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def process(self, context):
# NOTE we should use 'context.data["user"]' but that has higher
# order.
("AYON_USERNAME", get_ayon_username()),
("AYON_HOST_NAME", context.data["hostName"]),
):
if value:
self.log.debug(f"Setting job env: {key}: {value}")
Expand Down
6 changes: 1 addition & 5 deletions client/ayon_core/plugins/publish/extract_otio_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,9 @@ def process(self, instance):
# File sequence way
if is_sequence:
# Remap processing range to input file sequence.
processing_range_as_frames = (
processing_range.start_time.to_frames(),
processing_range.end_time_inclusive().to_frames()
)
first, last = remap_range_on_file_sequence(
r_otio_cl,
processing_range_as_frames,
processing_range,
)
input_fps = processing_range.start_time.rate

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"OTIO_SCHEMA": "Clip.2",
"metadata": {},
"name": "",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 23.976,
"value": 108.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 23.976,
"value": 883159.0
}
},
"effects": [],
"markers": [],
"enabled": true,
"media_references": {
"DEFAULT_MEDIA": {
"OTIO_SCHEMA": "ImageSequenceReference.1",
"metadata": {},
"name": "",
"available_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24.0,
"value": 755.0
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24.0,
"value": 883750.0
}
},
"available_image_bounds": null,
"target_url_base": "/mnt/jobs/yahoo_theDog_1132/IN/FOOTAGE/SCANS_LINEAR/Panasonic Rec 709 to ACESCG/Panasonic P2 /A001_S001_S001_T004/",
"name_prefix": "A001_S001_S001_T004.",
"name_suffix": ".exr",
"start_frame": 883750,
"frame_step": 1,
"rate": 1.0,
"frame_zero_padding": 0,
"missing_frame_policy": "error"
}
},
"active_media_reference_key": "DEFAULT_MEDIA"
}
Loading

0 comments on commit 3323e4b

Please sign in to comment.