Skip to content

feat(sdk): add OGG Vorbis and Opus C2PA manifest support#2073

Open
harsha-verda wants to merge 8 commits into
contentauth:mainfrom
VerdaAI:feat/ogg-support
Open

feat(sdk): add OGG Vorbis and Opus C2PA manifest support#2073
harsha-verda wants to merge 8 commits into
contentauth:mainfrom
VerdaAI:feat/ogg-support

Conversation

@harsha-verda
Copy link
Copy Markdown

Changes in this pull request

Add OGG Vorbis and Opus C2PA manifest support, implementing the first reference for C2PA spec v2.3 Section A.3.5.

Resolves #2072.

What it does

The manifest store is embedded as a dedicated OGG logical bitstream whose first packet begins with the 5-byte identifier \x00c2pa (per spec Section A.3.5). Hash binding follows Section 18.7.3.7, treating each logical bitstream as a "box" named Stream-{serial} (decimal). Both OGG Vorbis and OGG Opus containers are supported via the same handler since the embedding mechanism operates at the OGG container level.

Implementation highlights

  • No new crate dependencies -- OGG page parsing/writing is ~200 lines of binary I/O using the existing byteorder dependency. CRC-32 uses a const precomputed lookup table for the OGG polynomial 0x04c11db7.
  • Traits: CAIReader, CAIWriter, AssetIO, AssetPatch, AssetBoxHash
  • Supported types: ogg, audio/ogg, opus, audio/opus
  • Write ordering follows RFC 3533: all BOS pages grouped before any data pages. For large manifests spanning multiple pages, C2PA BOS is in the BOS group while continuation/EOS pages follow after.
  • RemoteRefEmbed is not implemented -- the C2PA spec does not define XMP embedding for OGG containers.

Files changed

File Change
sdk/src/asset_handlers/ogg_io.rs New OGG handler (~1400 lines incl. tests)
sdk/src/asset_handlers/mod.rs Register module
sdk/src/error.rs Add OggError variant
sdk/src/jumbf_io.rs Register in readers/writers + integration tests
sdk/src/utils/mime.rs Add opus/audio/opus MIME mappings
sdk/tests/fixtures/sample1.ogg Minimal OGG Vorbis test fixture
sdk/tests/fixtures/sample1.opus Minimal OGG Opus test fixture
docs/formats/ogg.md Format documentation
docs/supported-formats.md Add to format table
sdk/src/asset_handlers/README.md Add to trait matrix
CHANGELOG.md Add entry

Checklist

  • This PR represents a single feature, fix, or change.
  • All applicable changes have been documented.
  • Any TO DO items (or similar) have been entered as GitHub issues and the link to that issue has been included in a comment.

Test plan

  • 29 unit tests covering: CRC-32, page roundtrip, read/write (Vorbis + Opus), large manifests (100KB, multi-page), 255-byte boundary, BOS grouping (small + large), patch, removal, BoxMap contiguity, object locations, audio preservation, error cases, file I/O
  • 2 integration tests in jumbf_io.rs (test_streams_ogg, test_streams_opus)
  • End-to-end verified with c2patool on real 9MB+ audio files (Steve Jobs speech) -- validation_state: Valid for both Vorbis and Opus
  • Signed files verified playable via ffprobe and ffmpeg decode (full 10:30 duration, no errors)
  • All 725 existing tests continue to pass
  • 0 clippy errors

harshaampar and others added 8 commits April 17, 2026 21:01
Implement C2PA spec v2.3 Section A.3.5 for OGG containers. The manifest
store is embedded as a dedicated logical bitstream with the `\x00c2pa`
packet identifier. Hash binding follows Section 18.7.3.7, mapping each
bitstream to a box named `Stream-{serial}`.

Supports both OGG Vorbis and OGG Opus containers via the same handler,
since the embedding mechanism operates at the OGG container level.

No new crate dependencies — OGG page parsing/writing is implemented
inline (~150 lines of binary I/O).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Restructure write ordering so all BOS pages appear before any data
  pages (RFC 3533 compliance). For multi-page manifests, C2PA BOS is
  in the BOS group while continuation/EOS pages follow after.
- Rewrite BoxHash to emit one entry per contiguous run of pages,
  handling the case where C2PA pages are split across the BOS group
  and the data section.
- Remove RemoteRefEmbed impl (C2PA spec does not define XMP for OGG).
  remote_ref_writer_ref() now returns None instead of falsely
  advertising support.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
After the BOS-grouping fix, C2PA pages can be split (BOS in the BOS
group, continuation pages after). Fix get_object_locations_from_stream
to emit multiple Cai/Other regions as needed rather than assuming a
single contiguous C2PA block.

Also:
- Add TooManyManifestStores unit test
- Fix clippy map_or → is_some_and suggestions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace custom tempfile::Builder + reopen() with the codebase
  tempfile_builder() utility (handles WASI correctly)
- Narrow #[allow(dead_code)] to specific struct fields instead of
  the whole struct
- Remove unused Clone derive from OggPage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix ogg.md incorrectly listing RemoteRefEmbed as implemented
- Add test for 255-byte boundary (zero-length terminator segment)
- Add test for BOS grouping with large multi-page manifest
- Add BoxMap contiguity assertion (no gaps between entries)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move ogg/opus rows after mov, before pdf (alphabetical order)
- Update ogg.md layout to match BOS-compliant write ordering:
  C2PA BOS → Audio BOS → C2PA data → Audio data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use single OpenOptions read+write open instead of two separate
  file opens, eliminating race condition window
- Fix ogg.md Write flow description to match BOS-compliant ordering

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make test_read_cai_too_short match specific error (InvalidCapture)
- Add test_get_box_map_large_manifest: verifies non-contiguous C2PA
  BoxMap entries for multi-page manifests
- Add test_audio_preserved_after_write_remove: verifies original
  audio pages are byte-identical after sign+remove cycle

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.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.

feat(sdk): Add OGG Vorbis and Opus C2PA manifest support

2 participants