diff --git a/README.md b/README.md index 78d934f..eafc51a 100644 --- a/README.md +++ b/README.md @@ -110,4 +110,41 @@ Al indicarle previamente `w / 2`, solo se copiaba el lado izquierdo de los datos --- +## 5. Conceptos Arquitectónicos de Alto Nivel + +Para comprender mejor cómo esta solución maximiza el rendimiento del hardware gráfico, aquí se detallan los principios de diseño y concurrencia implementados: + +### A. Representación de Formatos de Video en OpenGL (¿Por qué dos texturas?) +Las pantallas físicas (monitores) funcionan proyectando subpíxeles de color **RGB** (Rojo, Verde y Azul). Sin embargo, por cuestiones de compresión y eficiencia, los videos se almacenan en formatos **YUV (como NV12)**, separando la información de brillo (Luminancia / $Y$) y la de color (Crominancia / $UV$ submuestreada a la mitad de resolución). + +Dado que OpenGL estándar no cuenta con un formato nativo para "NV12" en una única textura: +1. **Separación física**: Dividimos la información del fotograma en dos texturas de OpenGL: una para luminancia $Y$ (con formato `GL_RED` a resolución completa) y otra para crominancia $UV$ (con formato `GL_RG` a la mitad de la resolución en píxeles, pero con 2 bytes por píxel que contienen $U$ y $V$ entrelazados). +2. **Conversión en GPU**: El Fragment Shader ([shader.frag](file:///home/sebastian/repos/zero_copy_video_player/shader.frag)) muestrea ambas texturas simultáneamente en la misma coordenada normalizada y ejecuta la ecuación matemática de conversión YUV-a-RGB en el chip gráfico a la velocidad del hardware. + +--- + +### B. Sincronización Concurrente mediante Mutex +La reproducción interactiva y fluida de video se basa en un diseño multihilo. Tenemos dos hilos que acceden concurrentemente a la variable compartida del fotograma activo (`m_currentFrame`): +- **Hilo de Decodificación (FFmpeg/CUDA)**: Escribe un nuevo fotograma en memoria tan pronto como se descomprime del archivo. +- **Hilo de Pintado (OpenGL/Qt)**: Lee la referencia del fotograma para actualizar las texturas en cada ciclo de dibujo (`paintGL`). + +Si estos accesos ocurrieran al mismo tiempo sin control, se produciría una condición de carrera (*Race Condition*), provocando que OpenGL intente renderizar un fotograma a medio escribir. Esto resultaría en corrupciones visuales (*tearing*) o caídas del programa. + +Para resolverlo, implementamos un cerrojo de exclusión mutua (`m_frameMutex`): +- El decodificador bloquea el mutex justo cuando va a guardar el frame (`av_frame_ref`). +- El componente OpenGL bloquea el mutex brevemente mediante `getCurrentFrameRef(...)` para clonar la referencia de manera atómica. +- El bloqueo es instantáneo (solo se copian punteros y metadatos, no los píxeles en sí), por lo que no degrada el rendimiento de la aplicación. + +--- + +### C. Control de Framerate y Reloj de Referencia (Master Clock) +Para evitar que el video se reproduzca desordenado o excesivamente rápido (a la velocidad máxima del decodificador de hardware), el hilo de decodificación sincroniza su bucle con un reloj en tiempo real: + +1. **La Base de Tiempo del Video**: Cada fotograma decodificado contiene un indicador de tiempo llamado **PTS (Presentation Time Stamp)**. Este número viene expresado en "ticks" de reloj internos del archivo multimedia. Multiplicamos el PTS por la base de tiempo fraccionaria del video para convertirlo a segundos, y luego a **milisegundos reales**: + $$\text{PTS en ms} = \text{PTS en ticks} \times \text{Base de tiempo} \times 1000$$ +2. **Sincronización contra el reloj del sistema**: Mantenemos un reloj real (`QElapsedTimer`) que mide el tiempo transcurrido desde que pulsamos "Play". +3. **Control de Demora**: Si el fotograma decodificado tiene un PTS del futuro con respecto al reloj (`ptsMs > playbackTime`), calculamos la diferencia y ponemos a dormir al hilo decodificador (`QThread::msleep(delay)`) para ralentizarlo. Si el fotograma viene atrasado o al tiempo justo, el hilo no duerme y lo entrega a la GPU inmediatamente para evitar saltos o pérdida de sincronización. + +--- + *Guía de Integración Técnica • Debian 13 • GPU NVIDIA*