ynput / ayon-core

Apache License 2.0
27 stars 32 forks source link

AY-979_Collect OTIO subset resources - get_media_range_with_retimes returns negative range values #895

Open robin-ynput opened 1 week ago

robin-ynput commented 1 week ago

Is there an existing issue for this?

Current Behavior:

There seems to be something wrong when computing the retimed values from an image sequence. Issue was originally flagged by @jakubjezek001 on https://github.com/ynput/ayon-resolve/pull/15

Expected Behavior:

Currently retiming

otio.schema.Clip(name='a01vfxd_sh010_renderCompMain_v023.[1005-1056].exr', media_reference=ImageSequenceReference(target_url_base='C:\\projects\\AY01_VFX_demo\\shots\\sq001\\sh010\\publish\\render\\renderCompMain\\v023\\', name_prefix='a01vfxd_sh010_renderCompMain_v023.', name_suffix='.exr', start_frame=1005, frame_step=1, rate=23.97602397602398, frame_zero_padding=4, missing_frame_policy=<MissingFramePolicy.error: 0>, available_range=otio.opentime.TimeRange(start_time=otio.opentime.RationalTime(value=86530, rate=23.976), duration=otio.opentime.RationalTime(value=52, rate=23.976)), available_image_bounds=None, metadata={}), source_range=otio.opentime.TimeRange(start_time=otio.opentime.RationalTime(value=86530, rate=23.976), duration=otio.opentime.RationalTime(value=52, rate=23.976)), metadata={'Resolve_OTIO': {}}),

handleStart: 10
handleEnd: 10

returns this representation:

{'frameStart': 991, 'frameEnd': -85478, 'stagingDir': 'C:\\projects\\AY01_VFX_demo\\shots\\sq001\\sh010\\publish\\render\\renderCompMain\\v023\\', 'name': 'exr', 'ext': 'exr', 'files': []}

Note that the frameEnd being negative prevents the image file sequence from being properly retimed.

I think it should rather be:

{'frameStart': 995, 'frameEnd': 1066, 'stagingDir': 'C:\\projects\\AY01_VFX_demo\\shots\\sq001\\sh010\\publish\\render\\renderCompMain\\v023\\', 'name': 'exr', 'ext': 'exr', 'files': [file_sequence here]}

Version

1.0.0

What platform you are running on?

Windows

Steps To Reproduce:

  1. Download serialized clip file: out.json
  2. Run the following
    
    import clique

import optimelineio as otio from ayon_core.pipeline.editorial import get_media_range_with_retimes

handleStart = handleEnd = 10 clip = otio.schema.Clip.from_json_file("out.json") media_ref = clip.media_reference retimed_attributes = get_media_range_with_retimes(clip, handleStart, handleEnd)

break down into variables

media_in = int(retimed_attributes["mediaIn"]) media_out = int(retimed_attributes["mediaOut"]) handle_start = int(retimed_attributes["handleStart"]) handle_end = int(retimed_attributes["handleEnd"])

convert to available frame range with handles

a_frame_start_h = media_in - handle_start a_frame_end_h = media_out + handle_end

head = media_ref.name_prefix tail = media_ref.name_suffix collection = clique.Collection( head=head, tail=tail, padding=media_ref.frame_zero_padding )

collection.indexes.update( list(range(a_frame_start_h, (a_frame_end_h + 1))) )

import pprint pprint.pprint(collection) # collection pprint.pprint(list(collection)) # files == CURRENTLY EMPTY - shouldn't be



### Are there any labels you wish to add?

- [X] I have added the relevant labels to the bug report.

### Relevant log output:

_No response_

### Additional context:

_No response_

[AY-979](https://app.clickup.com/t/6658547/AY-979)
BigRoy commented 1 week ago

convert to available frame range with handles

a_frame_start_h = media_in - handle_start a_frame_end_h = media_out + handle_end

I think these are reversed @robin-ynput The media would never 'contain more' than media in/out right? That's it's "full" duration, no? If there are handles then they would subtract from the start range and end range.

So an image sequence 1001-1050 with five frame handles included means that without handles the range is 1006-1045.

frame_start_handle = frame_start - handle_start
frame_end_handle = frame_end + handle_start

This is what you may often see in AYON codebase - we have a frame start (which excludes handles) and the frame_start_handle which includes the handles. The clip range (files on disk) would basically be the frame_start_handle through frame_end_handle range. No?

Meaning:

# convert to available frame range with handles
a_frame_start_h = media_in + handle_start
a_frame_end_h = media_out - handle_end
robin-ynput commented 1 week ago

@BigRoy thanks for your comment but I'm not sure this is the fix actually. You're totally right that computing handle out of available media range might lead to issue, but from my investigation this is the purpose for get_media_range_with_retimes to enforce this thing and reset the handle to 0 if they go over the bound. hence the addition you mentioned is alright in the end.

Initial example I gave on the ticket is stolen from Jakub logs but I run another example with TIF sequence from Resolve and got a different issue:

#otioClip
Clip("output.[1000-1100].tif", ImageSequenceReference("C:\Users\robin\OneDrive\Bureau\dev_ayon\samples", "output.", ".tif", 1000, 1, 25.0, 4, MissingFramePolicy.error, TimeRange(RationalTime(0, 25), RationalTime(101, 25)), None, {}), TimeRange(RationalTime(0, 25), RationalTime(101, 25)), {'Resolve_OTIO': {}})
# Retimed values
{'frameStart': 1001, 'frameEnd': 1101, 'stagingDir': 'C:\\Users\\robin\\OneDrive\\Bureau\\dev_ayon\\samples', 'name': 'tif', 'ext': 'tif', 'files': ['output.0000.tif', ...]

So this time it looks like the retimed range was OK and handles were properly adjusted to not go over the bound, But the detected frame-range in the files attribute is wrong. That makes me believe maybe this whole retime logic was not stressed too much against img sequence and still requires some work.

@jakubjezek001 out of curiosity could you tell us what the status of this, is that WIP ? Was this ever bullet-proofed in prod ?

jakubjezek001 commented 1 week ago

From my tests, I've noticed that the issue lies with the "source in" frame value. It shouldn't match the "media in" value, as this is causing a significant offset. In this instance, the "source in" should be set to 0.0 to reference the first frame of the media source. Here's how it works:

It seems that there is no issue with the method rather with the incoming data. If you dont mind I will close the issue.

robin-ynput commented 1 week ago

@jakubjezek001 actually I found at least one culprit. Resolve native OTIO exporter does not compute an image sequence available range as we expect it to.

otio.schema.Clip(
name='output.[1000-1100].tif', 
media_reference=ImageSequenceReference(
    target_url_base='C:\\Users\\robin\\OneDrive\\Bureau\\dev_ayon\\samples', 
    name_prefix='output.', 
    name_suffix='.tif', 
    start_frame=1000, 
    frame_step=1, 
    rate=25.0, 
    frame_zero_padding=4, 
    missing_frame_policy=<MissingFramePolicy.error: 0>, 
    available_range=otio.opentime.TimeRange(
        start_time=otio.opentime.RationalTime(value=0, rate=25), 
        duration=otio.opentime.RationalTime(value=101, rate=25)), 
    available_image_bounds=None, metadata={}), 
    source_range=otio.opentime.TimeRange(
        start_time=otio.opentime.RationalTime(value=48, rate=25), 
        duration=otio.opentime.RationalTime(value=32, rate=25)),
    metadata={'Resolve_OTIO': {}})

My sequence is 1000-1100 so start_frame=1000 but resolve marks available_range as 0-101 instead of 1000-1101. (The AYON custom otio exporter correctly sets 1000-1101.)

Do we consider this to be a Resolve issue that needs to be work-arounded in the collector plugin ? Or do we anticipate that more Host native exporters could generate same issue and patch this in ayon-core ?