Ferigolo
Todos os projetos

Projeto próprio / Em desenvolvimento

Remote Desktop App

Engine nativa H.264, captura PipeWire e aceleração NVIDIA/Intel com renderização fora da WebView.

Minha atuação
Desenvolvimento próprio · engine de mídia e arquitetura
Tecnologias
C++26 · FFmpeg · CUDA / QSV · SDL3 · WebRTC · Tauri
Estágio
Em desenvolvimento

01 /O contexto

Compartilhamento de tela separando a interface de gestão do processamento de vídeo. O caminho Linux/Wayland reúne captura pelo portal do sistema, codificação H.264, transporte WebRTC e apresentação em janela nativa.

02 /Minha contribuição

Desenvolvimento da engine C++26, captura, encoders, decoders, transporte de mídia e cliente SDL3. Next.js/Tauri inicia o executável C++ como sidecar por um comando Rust; Python/asyncio/websockets faz o rendezvous de SDP e ICE. A organização da engine explicita o percurso dos frames, as transferências de memória e os pontos de sincronização.

Da captura à janela nativa

01 / Host · captura e memória

  1. Wayland → portalQt6/DBus autoriza a sessão ScreenCast.
  2. PipeWire / SPAThread de captura negocia formato, stride e DRM modifier.
  3. DMA-BUF → DRM PRIMEFD descreve a superfície; av_hwframe_map tenta mapear para CUDA ou QSV.

Alternativa NVIDIA em MemFd: mmap → libswscale na CPU (RGB/BGRA → NV12) → av_hwframe_transfer_data para a GPU. O suporte ao mapeamento depende dos formatos e drivers.

02 / Host → cliente · H.264 e rede

  1. Encoder FFmpegh264_nvenc / CUDA · h264_qsv / Intel · AVFrame → AVPacket
  2. libdatachannelH264RtpPacketizer + RTCP SR/NACK → WebRTC → H264RtpDepacketizer
  3. Decoder FFmpegh264_cuvid / CUDA, h264_qsv / Intel ou H.264 por software.

NVENC configura bitrate de 5 Mb/s, zero B-frames e GOP de 2 s. O timestamp RTP avança a 90 kHz conforme o FPS.

03 / Cliente · GPU e apresentação

  1. Frame decodificadoCUDA mantém AVFrame na GPU. QSV contém download para RAM; software converte para NV12.
  2. Texturas Y / UVCUDA–OpenGL: registro, map e cópias assíncronas device-to-device dos planos NV12.
  3. SDL3 / OpenGLUnmap → cudaStreamSynchronize(0) → SDL_RenderTexture → SDL_RenderPresent

std::mutex e av_frame_clone protegem a troca de frames. A espera CUDA precede o desenho SDL; os caminhos em RAM usam SDL_UpdateNVTexture. Os planos NV12 são copiados entre superfícies na memória da GPU.

04 / Controle · interface e handshake

  1. Next.js / TauriComando Rust start_engine inicia o sidecar core-engine.
  2. Python / WebSocketasyncio + websockets retransmitem registro, SDP e candidatos ICE.
  3. Peers nativoslibdatachannel estabelece mídia P2P; DataChannel transporta a resolução.

A sinalização troca metadados; o vídeo segue pelo canal de mídia entre peers.

05 / Próximas etapas

  1. macOSExpandir captura e codecs nativos com ScreenCaptureKit / VideoToolbox.
  2. VPP e memória de vídeoLevar a conversão de cor à GPU e reduzir transferências para RAM.
  3. Áudio e controle remotoAdicionar áudio de sistema/microfone e injeção de teclado/mouse.
Arquitetura de captura, codecs, transporte e apresentação nativa. Nós tracejados indicam as próximas etapas de implementação.

03 /Arquitetura e implementação

Captura e buffers

Qt6/DBus acessa o portal XDG ScreenCast; PipeWire entrega buffers em thread própria. A engine encaminha FD, dimensões, stride, formato SPA e DRM modifier ao encoder e devolve o buffer ao stream após o callback. AVDRMFrameDescriptor descreve o DMA-BUF. A duplicação do FD mantém a referência ao buffer durante seu processamento.

Encoders e conversão de cor

CudaEncoder usa FFmpeg h264_nvenc, contexto CUDA e superfícies NV12. IntelIrisEncoder configura h264_qsv e pool de 32 superfícies QSV. Ambos contêm mapeamento DRM PRIME por av_hwframe_map. No fallback MemFd da NVIDIA, libswscale converte pixels na CPU antes do upload por av_hwframe_transfer_data; a próxima etapa é levar a conversão de cor integral à GPU.

Decoders e alternativas

CudaDecoder seleciona h264_cuvid e negocia AV_PIX_FMT_CUDA para entregar frames na GPU. O módulo Intel usa h264_qsv e contém mapeamento DRM PRIME, mas também transfere o frame para RAM. SoftwareDecoder usa AV_CODEC_ID_H264 e libswscale para NV12. A seleção automática de codecs e a integração entre variantes compõem as próximas etapas.

Sincronização CPU–GPU

std::mutex serializa a substituição e leitura do frame; av_frame_clone mantém suas referências. O renderer registra texturas OpenGL de SDL3, mapeia Y/UV e usa cudaMemcpy2DToArrayAsync com cudaMemcpyDeviceToDevice. Após desmapear, cudaStreamSynchronize(0) aguarda a conclusão antes do desenho. Essa espera coordena a thread da CPU com a conclusão das cópias na GPU antes da apresentação.

Transporte e tempo

O código usa libdatachannel, diferente da libwebrtc citada no blueprint inicial. NAL units H.264 são packetizadas em RTP, com RTCP Sender Reports e NACK no host; o cliente depacketiza e solicita keyframe ao abrir a track. O timestamp avança 90.000/FPS. Uma condition_variable aguarda a track abrir antes do envio: coordenação de rede, separada da disponibilidade local do frame no renderer.

Bibliotecas por responsabilidade

FFmpeg: libavcodec/libavutil para codecs e contextos de hardware, libswscale para conversão na CPU; libavfilter integra as dependências da camada de filtros. PipeWire/SPA, Qt6/DBus, libdrm e EGL/GBM cobrem captura e formatos Linux. CUDA e QSV/libmfx/libva sustentam variantes de hardware; SDL3/OpenGL apresenta os frames, libdatachannel transporta mídia e nlohmann/json serializa mensagens.

04 /Estado e próximas etapas

Em desenvolvimento. Próximas etapas: consolidar a seleção de codecs, levar a conversão de cor à GPU, expandir o suporte macOS e adicionar áudio e controle remoto.

Próximo projetoDev Blog

Vamos construir a próxima ideia.

Para conversar sobre oportunidades, projetos e os desafios de engenharia que vêm a seguir.

Conversar no LinkedIn
Também por aquiGitHub