# `VideoInterop`
[🔗](https://github.com/emerge-elixir/video_interop/blob/v0.1.2/lib/video_interop.ex#L1)

Video frame and ownership contract for Rust and Elixir.

A GPU-bound DMA-BUF frame requires image layout, synchronization, and lifetime
metadata in addition to its file descriptors. Copying its pixels into a BEAM
binary breaks zero-copy operation.

VideoInterop provides the shared representation for passing complete DMA-BUF
frames between native Rust producers and consumers through Elixir. Version 0.1
defines owned BEAM binary storage, borrowed Linux DMA-BUF storage, acquire
sync-file fences, producer leases, and ownership-aware consumer streams.

Binary frames use implicit synchronization and no lease. File descriptor
integers in Elixir are borrowed and local to one OS process. Native consumers
must validate and duplicate every descriptor before asynchronous retention.

# `close_consumer`

```elixir
@spec close_consumer(VideoInterop.ConsumerSession.t()) :: :ok
```

Closes a consumer session with its implementation's idempotent close operation.

# `consume`

```elixir
@spec consume(VideoInterop.ConsumerSession.t(), VideoInterop.Frame.t()) ::
  :ok | {:error, term()}
```

Transfers a frame to an opened consumer session and consumes its holder.

On every normal return the caller must not release the supplied frame. A known
caller-owned rejection is released here. A transferred rejection remains the
consumer's responsibility. Contract violations raise with ownership unknown
rather than guessing and risking double release.

# `open_consumer`

```elixir
@spec open_consumer(term(), VideoInterop.Format.t(), keyword()) ::
  {:ok, VideoInterop.ConsumerSession.t()} | {:error, term()}
```

Opens an ownership-aware consumer session for a validated format.

`owner:` defaults to the caller and must be a local PID. Consumer
implementations use it to close the stream if its logical owner dies.

# `release`

```elixir
@spec release(VideoInterop.Frame.t() | VideoInterop.Lease.t()) :: :ok
```

# `retain`

```elixir
@spec retain(VideoInterop.Frame.t(), timeout()) ::
  {:ok, VideoInterop.Frame.t()} | {:error, term()}
```

# `validate`

```elixir
@spec validate(
  VideoInterop.DMABuf.Descriptor.t()
  | VideoInterop.Frame.t()
  | VideoInterop.Format.t()
) ::
  :ok | {:error, VideoInterop.Validator.reason()}
```

# `validate`

```elixir
@spec validate(VideoInterop.Frame.t(), VideoInterop.Format.t()) ::
  :ok | {:error, VideoInterop.Validator.reason()}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
