Skip to content

Commit f7b7a29

Browse files
docs: record VA bridge status
1 parent 00c6d44 commit f7b7a29

2 files changed

Lines changed: 114 additions & 0 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# fake-media-accel
22

33
Experimental bridge bringing Android MediaCodec acceleration to Linux applications running in PRoot.
4+
5+
Current VA-API status and probes: [docs/va-api.md](docs/va-api.md).

docs/va-api.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# VA-API bridge status
2+
3+
FMA exposes H.264 MediaCodec decoding through an ordinary VA-API driver. On
4+
Android systems where `/dev/dma_heap/system` is accessible, decoded NV12
5+
surfaces are backed by linear DMA-BUFs and can be exported with
6+
`vaExportSurfaceHandle()` as `VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2`.
7+
The ownership and synchronization behavior follows the
8+
[libva core API](https://intel.github.io/libva/group__api__core.html).
9+
10+
```mermaid
11+
flowchart LR
12+
A[Linux VA-API client] --> B[FMA VA driver]
13+
B --> C[Android MediaCodec daemon]
14+
C --> D[AImage frame]
15+
D --> E[DMA-BUF NV12 VA surface]
16+
E --> F[Standard DRM PRIME export]
17+
F --> G[EGL / Vulkan / other Linux consumer]
18+
```
19+
20+
This route does not require a Termux:X11 patch. The X server is only one
21+
possible final consumer; FMA's contract ends at the standard DRM PRIME
22+
descriptor.
23+
24+
## Current contract
25+
26+
- H.264 constrained-baseline, main and high profile decode.
27+
- NV12 `vaCreateImage`, `vaDeriveImage`, `vaGetImage` and unscaled
28+
`vaPutImage`.
29+
- DMA-BUF cache synchronization around CPU access.
30+
- Composed NV12 and separate R8/GR88 DRM PRIME export layouts.
31+
- Legacy `vaAcquireBufferHandle()` / `vaReleaseBufferHandle()` PRIME export for
32+
consumers such as VLC's standard VA/EGL converter.
33+
- Macroblock-aligned backing storage while preserving the requested visible
34+
dimensions and exporting the correct UV-plane offset.
35+
- Per-context protocol serialization, so decode and presentation threads cannot
36+
consume each other's daemon replies.
37+
- Direct-output registration passes an exportable VA surface DMA-BUF to the
38+
daemon with its compressed packet. MediaCodec output is copied from the
39+
`AImage` directly into that final surface, bypassing the intermediate shared
40+
frame-pool copy.
41+
- A malloc-backed fallback when no DMA heap is available. It remains usable
42+
through VA image mapping but correctly reports DRM PRIME as unsupported.
43+
- `FMA_VA_DMA_HEAP=none` forces the fallback; a different heap path may be
44+
supplied through the same variable.
45+
46+
The neutral surface test covers both allocation modes:
47+
48+
```sh
49+
ctest --test-dir build --output-on-failure
50+
```
51+
52+
`fma-va-egl-probe` uploads known NV12 values through public VA-API, exports the
53+
surface, imports both planes through `EGL_EXT_image_dma_buf_import`, samples
54+
them on the GPU and checks the resulting pixel. On the Pixel test device it
55+
reported:
56+
57+
```text
58+
VA->DRM PRIME->EGL passed: renderer=Mali-G78 (Panfrost) pixel=64,96,160,255
59+
```
60+
61+
An unmodified VLC 3.0.16 run then selected `vaapi_vld`, the FMA driver and
62+
`glconv_vaapi_x11`. Three normal six-thread runs of the 152-frame 1080p sample
63+
completed with zero decode or VA/EGL interop failures. They reported 2, 4 and 3
64+
late-frame warnings respectively. This validates application-level use of the
65+
standard path; it is not a VLC-specific integration.
66+
67+
`FMA_VA_DEBUG=1` exposes protocol message flow plus context creation, packet
68+
submission, surface synchronization and drain durations. It is intended for
69+
short controlled probes, not normal playback.
70+
71+
## Cost measured on the current 1080p30 sample
72+
73+
Five runs decoding 152 frames through MediaCodec and downloading NV12 with
74+
FFmpeg:
75+
76+
| Surface backing | Mean wall time | Max RSS |
77+
| --- | ---: | ---: |
78+
| DMA-BUF | 1.247 s | 95.4 MB |
79+
| malloc | 1.185 s | 135.3 MB |
80+
81+
The DMA-BUF route is currently about 5% slower in this download-heavy probe
82+
because it adds cache-sync ioctls. Its benefit is that applications can import
83+
the decoded surface without another presentation copy. The output MD5 remains
84+
identical to software decode.
85+
86+
## VLC application cost
87+
88+
Three local, no-audio runs used the same file and Panfrost GL output. The FMA
89+
total includes CPU time charged to the Android decoder daemon (`CLK_TCK=100`),
90+
so offloaded work is not hidden.
91+
92+
| Decode route | Mean wall | VLC user | VLC system | Daemon CPU | Counted CPU total |
93+
| --- | ---: | ---: | ---: | ---: | ---: |
94+
| FMA VA-API | 10.925 s | 0.896 s | 3.067 s | 1.407 s | 5.369 s |
95+
| VLC software | 6.771 s | 5.987 s | 1.551 s | 0 s | 7.538 s |
96+
97+
FMA reduced counted CPU by about 29%, but wall time was about 61% worse. A
98+
traced run spent only 1.81 seconds across all 152 packet submissions, 95 ms
99+
across 300 surface-sync calls and 54 ms draining the context. The VA context
100+
finished around 6.1 seconds after driver initialization while VLC remained
101+
alive until roughly 10.3 seconds. The open performance issue is therefore
102+
frame pacing or video-output backlog after decode, not the context drain. This
103+
needs its own probe before changing the X server.
104+
105+
## Remaining copy
106+
107+
MediaCodec currently writes an `AImage`, and the Android daemon copies that
108+
image once into the registered exportable DMA-BUF surface. If direct output is
109+
unavailable, the compatible fallback still uses the shared frame pool and a
110+
second VA-driver copy. A later AHardwareBuffer-backed path can remove the final
111+
CPU copy. It does not require changing Termux:X11 unless a future presentation
112+
probe finds a server-specific failure after standard EGL import succeeds.

0 commit comments

Comments
 (0)