feat(apv): add APV (Advanced Professional Video) reader and writer - #5367
Draft
zachlewis wants to merge 3 commits into
Draft
feat(apv): add APV (Advanced Professional Video) reader and writer#5367zachlewis wants to merge 3 commits into
zachlewis wants to merge 3 commits into
Conversation
Add an apv.imageio plugin using the OpenAPV library (https://github.com/openapv/openapv, BSD-3-Clause). APV is an all-intra professional video codec, so a raw .apv bitstream is naturally addressable as a sequence of individual images: the reader exposes one subimage per access unit (decoding its primary frame), and the writer emits one access unit per subimage, so appending subimages produces a valid multi-frame bitstream. - 10/12-bit YCbCr 4:2:2 / 4:4:4 / 4:4:4:4 (alpha) / 4:0:0 presented as full-range uint16 RGB(A)/grayscale, converted with the matrix coefficients signaled in the bitstream (709/601/2020). - CICP round trip: bitstream color descriptions surface as the CICP attribute (and oiio:ColorSpace interop ID when known); a CICP attribute on output is signaled in the bitstream. - Output controls: apv:profile (default 422-10 / 4444-10 / 400-10 by channel count), apv:qp, apv:bitrate, apv:preset, FramesPerSecond. - FindAPV.cmake module (OpenAPV installs into lib/oapv and needs OAPV_STATIC_DEFINE for static libs), build_APV.cmake local-build recipe with pinned tag+commit, testsuite/apv round-trip tests, and builtinplugins.rst documentation. Auxiliary frames within an access unit (preview, depth, alpha, non-primary) are not yet exposed; chroma resampling is simple co-sited linear. Assisted-by: Claude Code (Fable 5) Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
Assisted-by: Claude Code (Fable 5) Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
Two Color Interop Forum alignment improvements to the writer: - If no explicit CICP attribute is present but oiio:ColorSpace names a color space the default ColorConfig can map to CICP code points (e.g. a color interop ID), derive the bitstream color description from it via ColorConfig::get_cicp(). Untagged input still writes no color description rather than guessing. - Choose the encode matrix coefficients to match the primaries (BT.2020 with the 2020 NCL matrix, BT.601 families with theirs, everything else including P3 with BT.709) instead of always BT.709, and signal the matrix actually used. Testsuite gains an interop-ID-only round trip. Assisted-by: Claude Code (Fable 5) Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
APV is a royalty-free, all-intra professional video codec (via the BSD-3-Clause OpenAPV library). Because every frame is coded independently, a raw
.apvbitstream is naturally addressable as a sequence of individual images — a good fit for OIIO's subimage model, in both directions.What this does
apv.imageioplugin: the reader exposes one subimage per access unit (decoding its primary frame); the writer emits one access unit per subimage, so appending subimages produces a valid multi-frame bitstream.uint16RGB(A)/grayscale, converted with the matrix coefficients signaled in the bitstream (709 default, 601/2020 honored, limited/full range respected). Writing converts with BT.709.CICPattribute plus anoiio:ColorSpacecolor-interop ID when known (same pattern as the JPEG XL reader); aCICPattribute on output is signaled into the bitstream.apv:profile(defaults 422-10 / 4444-10 / 400-10 by channel count),apv:qp,apv:bitrate,apv:preset,FramesPerSecond.FindAPV.cmake(OpenAPV installs libraries intolib/oapvand static consumers must defineOAPV_STATIC_DEFINE), a pinnedbuild_APV.cmakelocal-build recipe, testsuite, andbuiltinplugins.rstdocs.What it deliberately does not do
Auxiliary AU frames (preview, depth, alpha-as-separate-PBU, non-primary) and metadata payloads (MDCV/CLL) are parsed past but not exposed yet; chroma resampling is simple co-sited linear. All noted in the code as future work.
Notes
oapvd_info()header probe misparses the color-description fields (reproducible with OpenAPV's own reference encoder; its full decoder parses them correctly). The reader therefore takes color metadata from the decode's frame info. Will report upstream.Testing
New
testsuite/apv: write/read round trips over 422/444/4444/400 profiles at 10 and 12 bits withoiiotool --diffthresholds, multi-subimage append, CICP carry-through (verified 9/16 →pq_rec2020_displayinterop ID). Also verified against a bitstream produced by OpenAPV's own reference encoder.Assisted-by: Claude Code (Fable 5)