Skip to content

Add core C++ support for otioz and otiod, take 2#2021

Open
darbyjohnston wants to merge 27 commits into
AcademySoftwareFoundation:mainfrom
darbyjohnston:bundles_cxx2
Open

Add core C++ support for otioz and otiod, take 2#2021
darbyjohnston wants to merge 27 commits into
AcademySoftwareFoundation:mainfrom
darbyjohnston:bundles_cxx2

Conversation

@darbyjohnston
Copy link
Copy Markdown
Contributor

@darbyjohnston darbyjohnston commented May 8, 2026

Fixes #1869

This PR adds support for otioz and otiod bundles to the C++ API. This PR is a second attempt at adding the functionality, superseding PR #1901.

The python otioz and otioz adapters still exist and work the same, but now they call into the C++ code for the bundle functionality.

Support for image sequences and multiple media references has been added.

Other changes:

  • Added the library "minizip-ng" for working with ZIP files. This also relies on either "zlib-ng" or "zlib" for compression. This seemed like a reasonable choice since OCIO also uses it.
  • Added a C++ example.
  • Replaced most of the Python bundle tests with C++ tests. Minimal Python tests remain to verify the adapters still work.

Questions:

  • Should the otioz/otiod file versions be bumped?
  • Should we use a third party library for URL handling? We currently only need a single function, to return a filename from a URL.

Follow up work for other PRs:

Assisted-by: Claude:claude-opus-4-7 [code-review] [debugging]

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 8, 2026

Codecov Report

❌ Patch coverage is 49.31238% with 258 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.13%. Comparing base (6944f10) to head (1f9c647).

Files with missing lines Patch % Lines
src/opentimelineio/bundle.cpp 42.61% 241 Missing ⚠️
...timelineio/opentimelineio-bindings/otio_bundle.cpp 69.04% 13 Missing ⚠️
...py-opentimelineio/opentimelineio/adapters/otioz.py 66.66% 2 Missing and 1 partial ⚠️
...py-opentimelineio/opentimelineio/adapters/otiod.py 87.50% 1 Missing ⚠️

❌ Your changes status has failed because you have indirect coverage changes. Learn more about Unexpected Coverage Changes and reasons for indirect coverage changes.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2021      +/-   ##
==========================================
- Coverage   84.51%   83.13%   -1.38%     
==========================================
  Files         181      180       -1     
  Lines       13239    13398     +159     
  Branches     1202     1234      +32     
==========================================
- Hits        11189    11139      -50     
- Misses       1867     2087     +220     
+ Partials      183      172      -11     
Flag Coverage Δ
py-unittests 83.13% <49.31%> (-1.38%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...melineio/opentimelineio-bindings/otio_bindings.cpp 98.63% <100.00%> (+<0.01%) ⬆️
src/py-opentimelineio/opentimelineio/__init__.py 100.00% <ø> (ø)
...opentimelineio/opentimelineio/adapters/__init__.py 85.18% <ø> (ø)
tests/test_otiod.py 91.30% <100.00%> (-5.58%) ⬇️
tests/test_otioz.py 91.30% <100.00%> (-6.64%) ⬇️
...py-opentimelineio/opentimelineio/adapters/otiod.py 84.61% <87.50%> (+3.66%) ⬆️
...py-opentimelineio/opentimelineio/adapters/otioz.py 71.42% <66.66%> (-13.19%) ⬇️
...timelineio/opentimelineio-bindings/otio_bundle.cpp 69.04% <69.04%> (ø)
src/opentimelineio/bundle.cpp 42.61% <42.61%> (ø)

... and 1 file with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6944f10...1f9c647. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
@darbyjohnston darbyjohnston marked this pull request as ready for review May 27, 2026 19:34
Copy link
Copy Markdown
Collaborator

@ssteinbach ssteinbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this work! Some questions and notes about the interface. As far as I can tell, this is 100% compatible with the way bundles work right now, right? Or is it the new library that would warrant the version bump?

Comment thread src/opentimelineio/bundle.h Outdated
Comment thread src/opentimelineio/bundle.h Outdated
Comment thread src/opentimelineio/bundle.h
Comment thread src/opentimelineio/bundle.h
@darbyjohnston
Copy link
Copy Markdown
Contributor Author

As far as I can tell, this is 100% compatible with the way bundles work right now, right? Or is it the new library that would warrant the version bump?

The file format is the same, I was just thinking about the library change. Like if we wanted to identify if a particular bundle was written with the original code vs. the new code. On second thought that probably shouldn't change the spec version, if it was useful we could add it as metadata to the timeline.

darbyjohnston and others added 6 commits May 27, 2026 16:03
Co-authored-by: Stephan Steinbach <61017+ssteinbach@users.noreply.github.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Comment thread src/opentimelineio/bundle.cpp
Comment thread tests/utils.cpp Outdated
Comment thread tests/utils.cpp Outdated

TempDir::TempDir()
{
auto const path = (std::filesystem::temp_directory_path() / "XXXXXX").u8string();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why windows gets a UUID and other platforms are X-Rated. Maybe just make a common unique identifier routine, perhaps building from pid. I don't think you need to be as safe as a UUID nor as dangerous as tripleX times 2.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK there is no mkdtemp on Windows. After some searching it looked like the guid method was one of the suggested alternatives or GetTempFileNameA. It would be nice if there was some sort of utility library all the ASWF projects could use for this stuff.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haha OMG TIL that mkdtemp says "put at least six X characters here". Insert "crazy face emoji". Could you add a little comment please? I didn't know this and thought it was simply peculiar and possibly left over temp code.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, it's still true that I am allergic to constructing strings with stringstream for many reasons, so although I don't specifically object to the pattern above, it is vaguely disconcerting for the reasons of performance and std::locale both being latent footguns. I don't disagree with your notion of a canonical UUID routine, but again point out that "Universally" unique IDs mean no collisions in the universe and UUIDs are therefore a wee bit expensive especially for a temp file name construction!

constructive alternatives

  1. use GetTempFileNameW() on windows mkdtemp on posix.

// Get the system's legitimate temp directory
    auto temp_dir = fs::temp_directory_path();
//  Use a fast, thread-safe pseudo-random generator for a local ID
// A high-entropy 64-bit hex string is plenty. mt19937 is terrible for games and most random needs tbh, but fine here.
    static thread_local std::mt19937_64 generator(std::random_device{}());
    uint64_t rand_num = generator();
// fast locale-independent string construction with hex formatting
    std::string filename = std::format("tmp_{:x}.tmp", rand_num);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#2 seems like a better alternative since it's OS independent. I updated the PR with Claude's take on it, check it out and see what you think.

Copy link
Copy Markdown
Collaborator

@meshula meshula left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall looks really good. general notes

  • maybe clean up TempDir as noted?
  • I think you could wire through much more descriptive error reporting for the CLI (or please correct me if I'm not spotting a verbose forensics path)
  • please beware of string construction stringstream, as I noted it's not especially problematic (aside from performance) where you are using it, but especially for string construction it is loaded with footguns due to locale, and you haven't enforced the C locale which at least makes its behavior reproducible from computer to computer.

Please consider using zstd; to my knowledge it's bullet proof vs common attacks, offers excellent compression at I believe best speeds, and is also a very lightweight library that is easy to vendor. https://github.com/facebook/zstd

These are minor compared to the overall solidity of the work.

@darbyjohnston
Copy link
Copy Markdown
Contributor Author

https://github.com/facebook/zstd

That's a different compression scheme from deflate? We could possibly add that as a separate feature at some point.

Somewhat related, what do you think about having otioz files conform to ISO/IEC 21320-1? (https://en.wikipedia.org/wiki/ZIP_(file_format)) As I understand it, it's a minimal ZIP format for the same use cases as otioz.

What do you suggest instead of stringstream? Aren't we constrained by our C++ version from using std::format?

Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
Signed-off-by: Darby Johnston <darbyjohnston@yahoo.com>
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

Successfully merging this pull request may close these issues.

Add core C++ support for otioz and otiod

4 participants