Skip to content

feat(vdo): Add safe Rust bindings for VDO API - #223

Merged
guoxe merged 31 commits into
AxisCommunications:mainfrom
vsem-azamat:feature/vdo-completion
Jul 3, 2026
Merged

guoxe merged 31 commits into
AxisCommunications:mainfrom
vsem-azamat:feature/vdo-completion

Conversation

@vsem-azamat

Copy link
Copy Markdown
Contributor

Safe Rust bindings for VDO (Video Capture) API

Safe wrappers over vdo-sys with builder pattern for stream creation, iterator-based frame capture, and automatic resource cleanup.

Tested on device: YUV, JPEG, H.264, H.265 formats work correctly.

Describe your changes

This PR adds a new vdo crate providing safe Rust bindings for the VDO API, enabling video capture from Axis cameras.

Based on the work from PR #153 by @JsGjKJzi — completed the implementation, added comprehensive tests, and updated the example application.

Note: @JsGjKJzi hasn't responded since January 2024.

Key features:

  • StreamBuilder with builder pattern for configuring video streams
  • Stream, RunningStream, StreamIterator for lifecycle management
  • StreamBuffer and Frame for zero-copy frame access
  • Automatic resource cleanup via Drop implementations
  • Comprehensive error handling with VdoError including error code names
  • Platform compatibility documentation (Artpec-6/7/8/9, Ambarella CV)

Changes:

  • New crates/vdo/ crate with safe bindings
  • Updated apps/vdo_encode_client/ to use the new vdo crate
  • Unit tests (no device required) + device tests (gated by device-tests feature)

Issue ticket number and link

Checklist before requesting a review

  • I have performed a self-review of my own code
  • I have verified that the code builds perfectly fine on my local system
  • I have added tests that prove my fix is effective or that my feature works
  • I have commented my code, particularly in hard-to-understand areas
  • I have verified that my code follows the style already available in the repository
  • I have made corresponding changes to the documentation

Safe wrappers over vdo-sys with builder pattern for stream creation,
iterator-based frame capture, and automatic resource cleanup.

Tested on device: YUV, JPEG, H.264, H.265 formats work correctly.
Copilot AI review requested due to automatic review settings December 28, 2025 15:09
@vsem-azamat
vsem-azamat requested a review from a team as a code owner December 28, 2025 15:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds safe Rust bindings for the VDO (Video Capture) API, enabling video capture from Axis cameras. The implementation provides a builder pattern for stream configuration, iterator-based frame capture, and automatic resource cleanup through RAII principles.

Key changes:

  • New vdo crate with safe abstractions over vdo-sys FFI bindings
  • Comprehensive error handling with detailed error code mapping
  • Builder pattern for ergonomic stream configuration
  • Updated vdo_encode_client application demonstrating multiple video formats

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
crates/vdo/src/lib.rs Core library implementation with safe wrappers for VDO API, including Stream, StreamBuffer, Frame types, and comprehensive tests
crates/vdo/examples/basic.rs Simple example demonstrating video stream capture with YUV format
crates/vdo/Cargo.toml Package configuration for the new vdo crate with device-tests feature flag
apps/vdo_encode_client/src/main.rs Updated example application testing multiple video formats (YUV, JPEG, H.264, H.265)
apps/vdo_encode_client/Cargo.toml Updated dependency from vdo-sys to the new vdo crate
Cargo.toml Added vdo workspace member
Cargo.lock Updated lock file with vdo crate dependencies

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
@vsem-azamat

Copy link
Copy Markdown
Contributor Author

I'll wait for feedback from the maintainers before addressing these suggestions, as some may be more relevant than others for this codebase.

@apljungquist

Copy link
Copy Markdown
Collaborator

I won't have time to look at the code before new year, but I would like to say already now that I'm happy you are interested in carrying on the work that Jonathan started 🙂

@apljungquist apljungquist left a comment

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 skimmed the PR and I think it looks pretty good. I'll try to do a more thorough read in the before next weekend focusing on safety and I'll try to respond to comments within 24h.

Comment thread apps/vdo_encode_client/src/main.rs
Comment thread apps/vdo_encode_client/src/main.rs Outdated
Comment thread crates/vdo/src/lib.rs
Comment thread crates/vdo/src/lib.rs
Comment thread crates/vdo/src/lib.rs
Comment thread Cargo.toml
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs

@apljungquist apljungquist left a comment

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.

Some API design related questions.

API design is difficult and typically subjective. I don't want it to stall this PR, so consider this inspiration. (that's not to say that the previous review was not subjective or disputable, only that this is even more so)

Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
@apljungquist

Copy link
Copy Markdown
Collaborator

I created this to help with my understanding of VDO, posting it here in case you find it usefule: https://github.com/apljungquist/acap-rs/blob/f778576222874210e51f0c46ab4d6ffbdd877572/crates/vdo-sys/README.md

@apljungquist apljungquist left a comment

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 have focused this review on the Map type, which looks good. Once we have decided if/how to change it I will continue reviewing other parts.

I do this to not overwhelm you with comments and to not overwhelm myself with different discussions to keep track of and large diffs that need to be reviewed with every now commit.

Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
vsem-azamat added a commit to vsem-azamat/acap-rs that referenced this pull request Feb 10, 2026
Address all review comments. Fix GObject leak in Stream::drop.

- Consume-by-value ownership: start(self), stop(self), unref(self)
- Replace Iterator with next_buffer() -> Result
- Merge Frame into StreamBuffer (VdoBuffer = VdoFrame)
- Extract Map to separate module, keys as &CStr
- Add Resolution enum, remove buffer_strategy, rename to custom_timestamp_us
- Replace as_mut_slice with data_copy(), file_descriptor() returns Result

Tested: cargo clippy clean, 33/33 tests pass on Artpec-9 device.
@vsem-azamat
vsem-azamat force-pushed the feature/vdo-completion branch from 2326701 to 70e2962 Compare February 10, 2026 20:47
@vsem-azamat

Copy link
Copy Markdown
Contributor Author

@apljungquist @guoxe
I've tried to fix all things. Pls, review

@apljungquist

Copy link
Copy Markdown
Collaborator

Will try to get around to this tomorrow

apljungquist and others added 2 commits February 12, 2026 23:21
Address all review comments. Fix GObject leak in Stream::drop.

- Consume-by-value ownership: start(self), stop(self), unref(self)
- Replace Iterator with next_buffer() -> Result
- Merge Frame into StreamBuffer (VdoBuffer = VdoFrame)
- Extract Map to separate module, keys as &CStr
- Add Resolution enum, remove buffer_strategy, rename to custom_timestamp_us
- Replace as_mut_slice with data_copy(), file_descriptor() returns Result

Tested: cargo clippy clean, 33/33 tests pass on Artpec-9 device.
@apljungquist
apljungquist force-pushed the feature/vdo-completion branch from 70e2962 to 2326701 Compare February 12, 2026 22:22
@apljungquist

apljungquist commented Feb 12, 2026

Copy link
Copy Markdown
Collaborator

@vsem-azamat nice progress!

Please refrain from force pushing in the future as it makes it difficult to review the changes and keep track of comments. I took the liberty of cherry-picking your fix onto the branch before it was force pushed and force pushing that, so now the git history looks as it should.

A few of my comments seem to have gone unaddressed. You don't have to always to things the way I think is the best, but I would appreciate if you at least acknowledge on each comment that you have read it and state what, if anything, you will do to address it 🙂

I haven't seen the results of the CI yet, but if we get more revisions in on this I will make sure to start it as soon as I can instead of waiting until I have time to do human review like this time around.

@apljungquist

apljungquist commented Feb 13, 2026

Copy link
Copy Markdown
Collaborator

It looks like something changed with github actions and it now hangs after starting the dev container: [2026-02-13T18:09:55.811Z] Container started 😮‍💨

I will try to look into this in the next week or so. In the meanwhile I encourage you to run the same check locally so that we have a good PR ready to go when CI gets fixed. The check that compares checksums can be a bit unreliable and is easy to fix, so if that is the only one that is failing we should be all right.

@apljungquist apljungquist left a comment

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 forgot to submit this review, sorry. Among the new comments I only feel strongly about the glob import, but as I said, please respond to all new and old comments.

Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs
…ct-test

Replace `use vdo_sys::*` with explicit type imports and `vdo_sys::`-qualified
function/constant calls at call sites. This addresses the PR review feedback
about avoiding glob imports. Also adds the missing VDO_ERROR_NO_VIDEO error
code and adopts expect-test for display/formatting tests.
- Clamp size to capacity in data_copy to prevent out-of-bounds reads
- Replace debug_assert with assert in unsafe constructors (from_ptr, from_raw)
- Document BorrowedFd lifetime constraints on file_descriptor()
- Fix double vdo_stream_stop by delegating to Drop
- Add Error::InvalidFd instead of overloading NullPointer for bad fds
- Return Option<usize> from header_size() for negative (no header) values
- Fix from_gerror safety comment to match actual code order
- Add Debug for Map and CStringPtr, Deref<Target=CStr> for CStringPtr
- Use explicit ptr::null::<c_char>(), comment as_ptr GLib convention
@socket-security

socket-security Bot commented Feb 21, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedcargo/​expect-test@​1.5.19910093100100

View full report

@apljungquist apljungquist left a comment

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.

Some nice improvements in this iteration. But there are still old comments that remain unaddressed. You may want to also take at least a quick look at Gustaf's comments as he he the person who will ultimately merge your PR if approved 😉

Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/map.rs Outdated
Comment thread crates/vdo/src/map.rs
Comment thread crates/vdo/src/map.rs Outdated
Comment thread crates/vdo/src/map.rs
Comment thread Cargo.toml
Comment thread crates/vdo/src/lib.rs
Comment thread crates/vdo/src/lib.rs Outdated
@apljungquist

Copy link
Copy Markdown
Collaborator

I took the liberty of fixing a couple of outstanding issues, I hope that's ok.

apljungquist
apljungquist previously approved these changes Mar 7, 2026
@vsem-azamat

Copy link
Copy Markdown
Contributor Author

I took the liberty of fixing a couple of outstanding issues, I hope that's ok.

Sure. Thanks)

apljungquist
apljungquist previously approved these changes Mar 8, 2026
@vsem-azamat

Copy link
Copy Markdown
Contributor Author

@guoxe
Hi!
please take a look when you have time 😄
I addressed ur comments

vsem-azamat added a commit to vsem-azamat/acap-rs that referenced this pull request Mar 11, 2026
…fety

Remove async load/run APIs (overengineering for typical load-once + sync
inference workflow). Fix Send soundness for Tensors and JobRequest by
storing raw connection pointer instead of &Connection, avoiding the
Connection: Sync requirement. Apply PR AxisCommunications#223 review feedback: rename
Map::new to try_new, add SAFETY comments on unsafe blocks, fix error
handling to use from_utf8_lossy. Harden Drop impls to free larodError
even on success, fix panic safety in devices()/models() array handling,
add #[must_use] to OwnedTensorPtrs, fix PhantomData invariance in
JobRequest.

@guoxe guoxe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I have some questions relating to some of the functions added.
Overall I think it looks good!

Comment thread crates/vdo/src/map.rs Outdated
Comment thread crates/vdo/src/map.rs Outdated
Comment thread crates/vdo/src/map.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
Comment thread crates/vdo/src/lib.rs Outdated
@vsem-azamat

Copy link
Copy Markdown
Contributor Author

Hi!
@guoxe
I've brought some updates 😄

guoxe
guoxe previously approved these changes Jul 2, 2026

@guoxe guoxe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice work!

Sorry it took a while for me to get around to reviewing, unless there is something else you want to address I am happy with merging this PR as is.

Comment thread crates/vdo/src/lib.rs Outdated
@vsem-azamat

Copy link
Copy Markdown
Contributor Author

@guoxe
I've fixed checksum. Please, approve it again

@vsem-azamat

Copy link
Copy Markdown
Contributor Author

@guoxe I've fixed checksum. Please, approve it again

@apljungquist @guoxe

Thanks you so much for for helping and reviewing this PR. It was tough for me.

I'd like to merge this PR and in anything appears I'll open new FollowUp MR.

Thanks)

@guoxe
guoxe merged commit 8e58acb into AxisCommunications:main Jul 3, 2026
8 checks passed
@apljungquist

Copy link
Copy Markdown
Collaborator

I'm happy you were up for the challenge and that it hasn't discouraged you :)

vsem-azamat added a commit to vsem-azamat/acap-rs that referenced this pull request Jul 5, 2026
…fety

Remove async load/run APIs (overengineering for typical load-once + sync
inference workflow). Fix Send soundness for Tensors and JobRequest by
storing raw connection pointer instead of &Connection, avoiding the
Connection: Sync requirement. Apply PR AxisCommunications#223 review feedback: rename
Map::new to try_new, add SAFETY comments on unsafe blocks, fix error
handling to use from_utf8_lossy. Harden Drop impls to free larodError
even on success, fix panic safety in devices()/models() array handling,
add #[must_use] to OwnedTensorPtrs, fix PhantomData invariance in
JobRequest.
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.

4 participants