| Crates.io | amffi |
| lib.rs | amffi |
| version | 0.0.2 |
| created_at | 2025-11-17 22:38:39.00264+00 |
| updated_at | 2025-12-19 17:04:17.978505+00 |
| description | Rust bindings to Advanced Media Framework |
| homepage | |
| repository | https://github.com/AlsoSylv/amffi |
| max_upload_size | |
| id | 1937632 |
| size | 164,365 |
amffi is a wrapper of Advanced Media Framework's C++ API.
This works as a cross platform COM style API, in a similar way to AMDs own examples.
32-bit environments are currently supported through the usage of macros to change the calling convention between x86_64 and x86, and any breakage is considered a bug
#include "public/common/AMFFactory.h"
int main() {
AMF_RESULT res = AMF_OK;
res = g_AMFFactory.Init();
amf::AMFContextPtr context;
res = g_AMFFactory.GetFactory()->CreateContext(&context);
}
use amf_bindings::amf_init;
use amf_bindings::version::AMF_VERSION;
use amf_bindings::factory::AMFFactory;
use amf_bindings::context::AMFContext;
fn main() {
let library = amf_init().unwrap();
let factory: AMFFactory = library.init_factory(AMF_VERSION).unwrap();
let context: AMFContext = factory.create_context().unwrap();
}
This creates an AMF context, which can then be used like a COM-API
Certain APIs, such as buffer observers, have been wrapped to create a more idiomatic feeling API, such as
fn import_dx_buffer(context: &AMFContext, buffer: &ID3D11Texture2D) {
let surface: AMFSurface = context.create_surface_from_dx11_native(buffer);
surface.add_observer(|surface: AMFSurface| {
println!("Releasing!");
});
}
This is done by creating trait wrappers for the equivalent C++ interface, such as:
pub trait SurfaceObserver {
fn on_surface_data_release(&mut self, surface: AMFSurface);
}
And wrapping them in a struct equivalent to how the AMD driver expects them, like so:
#[repr(C)]
pub(crate) struct InternalSurfaceObserver<T: SurfaceObserver> {
vtbl: &'static AMFSurfaceObserverVtbl,
this: T,
}
impl<T: SurfaceObserver> InternalSurfaceObserver<T> {
pub(crate) fn new(observer: T) -> Self {
Self {
vtbl: &AMFSurfaceObserverVtbl {
on_surface_data_release: internal_observer::<T>,
},
this: observer,
}
}
}
stdcall! {
fn internal_observer<T: SurfaceObserver>(this: *mut *const AMFSurfaceObserverVtbl, surface: AMFSurface) {
let this = unsafe { &mut *(this as *mut InternalSurfaceObserver<T>) };
this.this.on_surface_data_release(surface);
}
}
class AMF_NO_VTABLE AMFSurfaceObserver
{
public:
virtual void AMF_STD_CALL OnSurfaceDataRelease(AMFSurface* pSurface) = 0;
};
Not all features are currently implemented, but are planned. Things such as Compute, D3D12 and AV1 are all going to be implemented as time and testing allow.