Skip to content

Add core C++ support for otioz and otiod #1869

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
darbyjohnston opened this issue Apr 3, 2025 · 4 comments
Open

Add core C++ support for otioz and otiod #1869

darbyjohnston opened this issue Apr 3, 2025 · 4 comments

Comments

@darbyjohnston
Copy link
Contributor

darbyjohnston commented Apr 3, 2025

After some discussion in Slack:
https://academysoftwarefdn.slack.com/archives/CMQ9J4BQC/p1729878665473649

I wanted to create a proposal for adding core C++ support for otioz and otiod. I think adding them to the C++ API would have a couple of benefits:

  • Broader adoption by users of the C++ API and other language bindings.
  • Provide a common interface to ensure bundles are created according to the specification.

I propose adding minizip-ng as a new dependency to support otioz. It has a permissive license (zlib), and is also used by OpenColorIO for their .ocioz files. The use of minizip-ng would be internal and not part of the OTIO public API.

Outline of the required work:

Add an enum for the media reference policy

(https://opentimelineio.readthedocs.io/en/stable/tutorials/otio-filebundles.html#mediareferencepolicy)

enum class MediaReferencePolicy
{
    ErrorIfNotFile,
    MissingIfNotFile,
    AllMissing
 };

Add constants for the file bundle versions

static std::string const otiozVersion = "1.0.0";
static std::string const otiodVersion = "1.0.0";

Add I/O functions to SerializableObject

bool to_otioz_file(
    std::string const&        file_name,
    MediaReferencePolicy      media_reference_policy   = MediaReferencePolicy::ErrorIfNotFile,
    ErrorStatus*              error_status             = nullptr,
    const schema_version_map* target_family_label_spec = nullptr,
    int                       indent                   = 4) const;
  • Create a new ZIP file.
  • Resolve external references based on the media reference policy and add them to the ZIP file.
  • Create the version file and add it to the ZIP file.
  • Clone the SerializableObject and modify it based upon the media reference policy, and to change the external reference paths.
  • Call to_json_string() to create content.otio and add it to the ZIP file.
static SerializableObject* from_otioz_file(
    std::string const& file_name,
    std::string const& temp_dir,
    ErrorStatus*       error_status = nullptr);
  • Unzip the file to the temporary directory.
  • Call from_json_file() on the content.otio file in the temporary directory.

Should we also add a version of this function that reads the otioz directly without unzipping it (i.e., memory-mapping)?

bool to_otiod_bundle(
    std::string const&        dir_name,
    MediaReferencePolicy      media_reference_policy   = MediaReferencePolicy::ErrorIfNotFile,
    ErrorStatus*              error_status             = nullptr,
    const schema_version_map* target_family_label_spec = nullptr,
    int                       indent                   = 4) const;
  • Create the given directory.
  • Resolve external references based on the media reference policy and copy them to the directory.
  • Create the version file in the directory.
  • Clone the SerializableObject and modify it based upon the media reference policy, and to change the external reference paths.
  • Call to_json_string() to create the content.otio file in the directory.
static SerializableObject* from_otiod_bundle(
    std::string const& file_name,
    ErrorStatus*       error_status = nullptr);
  • Call from_json_file() on the content.otio file in the otiod directory.

Python bindings

Add Python bindings for the new C++ functionality and update the otioz/otiod Python adapters to use the new code.

@ssteinbach
Copy link
Collaborator

ssteinbach commented Apr 3, 2025

Glad you're diving into this!

  • I suspect you might want to have the adapter as a shim to trigger a call to the otioz/d functions, similar to how there is a python shim around the otio_json adapter: https://github.com/AcademySoftwareFoundation/OpenTimelineIO/blob/main/src/py-opentimelineio/opentimelineio/adapters/otio_json.py
    This exposes options to the commandline interface (and, for example, to otiopluginfo) and streamlines the entry-level python API. For basic use cases you can use otio.adapters.read_from_file() and the adapter interface handles all the type dispatching without special casing the internal formats.
  • Whether you feel like an otiod read function is necessary is a good one for discussion. I'm not sure if folks use otiod separate from otioz development. The adapter notes that it also converts the relative media references in the otiod content.otio into absolute paths:
    # convert the media_reference paths to absolute paths

    ... but that could be left in the adapter and not moved into the core. The adapter would probably remain pretty unchanged in this scenario.
  • It might be worth poking the community to see if otiod should be separately exposed at all. Originally it was super easy to build while building otioz and helped me debug/stage otioz stuff but I'm not sure if anyone else finds it useful. If folks wanted to cut it or not expose it as its own thing that would make sense to me too.

Excited to see the otioz prototype move into the core!

@darbyjohnston
Copy link
Contributor Author

That makes sense about the adapters, I'll update the notes.

If we do keep otiod I think having the read function would be a good idea. It keeps the API symmetrical and let's us update the format in the future.

I also find otiod helpful for debugging, but I'm sure there are other use cases for it. Like if you had an .otio with media located in various different places, and wanted to copy it to a single high speed drive for playback.

@peter-targett
Copy link
Contributor

Kicking myself I should have proposed this earlier, it actually wasn't too difficult to write C++/Python-API code to call-down into the adapters to write otiod and otioz files, a C++ API would however simplify the call-setup-code!

@ssteinbach
Copy link
Collaborator

I also find otiod helpful for debugging, but I'm sure there are other use cases for it. Like if you had an .otio with media located in various different places, and wanted to copy it to a single high speed drive for playback.

This is argument enough to keep it around in my opinion. If you want to float it at a TSC meeting and get a temperature check, I'm fine with that too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants