Jun 12, 20264 min read62 views

Hi, I'm Ahmed

I'm Ahmed Mohamed Sobhy, a Computer Engineering student at Cairo University and I like low-level systems code in C. This summer, I'm working on something a few billion devices actually run: Google Summer of Code 2026 with VideoLAN, working on VLC's video output, mentored by Thomas Guillem. I plan to write a weekly blog post, writing down my journey week by week, sharing all the details and progress I make. I hope by the end of this, I come out with a well-organized timeline for the whole journey and have a journal to write all my learnings throughout.

The project in one paragraph

VLC can already decode video on the GPU: NVIDIA has NVDEC, Intel and AMD have VA-API, Android has MediaCodec. But VLC's modern renderer, built on a library called libplacebo, only understands frames in CPU memory. So a hardware-decoded frame gets downloaded from the GPU to the CPU, then uploaded right back to the GPU to be drawn. Two trips across the bus, per frame, for pixels that never needed to move. My job is to delete that round-trip.

How VLC plays a video

VLC is built out of plugins it calls modules, and playback is a little assembly line of them:

File / Network Access Demux Decoder Filters (optional) Video output Screen stream frame decoder device + video context (hardware only)
The VLC playback pipeline. My work is the handshake between the decoder and the video output.
Software picture

Actual pixels in CPU memory. Any renderer can read them. This is all VLC's libplacebo output understands today.

Hardware picture

The pixels live in GPU memory. VLC only passes around an opaque handle. The renderer can't read it without interop.

What is an "interop"?

Sharing GPU memory between two APIs that don't normally talk, here a hardware decoder and a Vulkan renderer, without copying it. The frame stays in the same video memory and the renderer just gets a new handle to it. Most of my summer is making that work, and making it safe, since two processors on the same memory have to agree on who reads when.

The gap I'm filling

The OpenGL vout solved this years ago with a family of modules called glinterop, one per decoder, that import GPU memory directly. The Vulkan/libplacebo output has no equivalent, so hardware frames take the wasteful CPU detour instead. I'm building that missing layer, vkinterop, following the pattern that already works.

Wait, what is libplacebo?

It’s a GPU-based rendering library (created by Niklas Haas and he will actually be helping with this project, especially if we need more APIs or something so shoutout to him), originally built for the mpv player, that handles things like high-quality scaling, color management, and HDR tone-mapping. In VLC, it acts as a video output backend. While VLC handles the complex job of decoding the compressed video file, it hands the raw frames off to libplacebo, which uses your GPU to make the final picture before it reaches your display.

What I'm building then

  1. Hardware decoder interop: frames from NVDEC (first target), VA-API, and Android MediaCodec, handed to libplacebo as Vulkan images with zero copies, plus the synchronization that keeps decode and render from stepping on each other.
  2. An external renderer mode, so another application, say a game engine or OBS, can hand VLC its own Vulkan device and get video rendered straight into its world.

Follow along

New posts land roughly weekly: what I did, what went wrong, what I learned, including the embarrassing parts. All of my code work will be written is as merge requests on VideoLAN's GitLab and will mention links on every blog post. I hope you are excited as I am and enjoy the read.

Did you enjoy this article?

Share this article

Comments(0)

Leave a comment

No comments yet. Be the first to share your thoughts!

© 2026 Ahmed Sobhy. All rights reserved.