#ifndef VIDEODECODER_H #define VIDEODECODER_H #include #include #include #include extern "C" { // Cabeceras multimedia de FFmpeg #include #include #include #include } /** * @brief Hilo de decodificación encargado de leer y decodificar video por hardware (CUDA). * Realiza la sincronización temporal basada en el reloj maestro del reproductor (PTS). */ class VideoDecoder : public QThread { Q_OBJECT public: explicit VideoDecoder(QObject *parent = nullptr); ~VideoDecoder() override; // Abre el archivo de video e inicializa el contexto de decodificación de hardware bool openFile(const QString &fileName); // Cierra el archivo y libera todos los contextos asignados void closeFile(); // Reanuda la reproducción de video void play(); // Pausa la reproducción de video void pause(); // Salta a una posición de tiempo específica en segundos void seek(double seconds); // Detiene de forma segura el bucle del hilo y espera a que finalice void stopThread(); // Métodos de acceso a propiedades del video (Thread-Safe mediante lectura simple) double getDuration() const { return m_duration; } int getVideoWidth() const { return m_videoWidth; } int getVideoHeight() const { return m_videoHeight; } bool isPaused() const { return m_isPaused; } // Retorna el tiempo actual de reproducción en milisegundos de acuerdo al reloj maestro qint64 getPlaybackTimeMs() const; // Método Thread-Safe para que OpenGL tome una referencia rápida al fotograma decodificado actual bool getCurrentFrameRef(AVFrame *destFrame); signals: // Señal emitida cuando hay un nuevo fotograma decodificado listo en la GPU void frameReady(); // Señal para actualizar la posición en tiempo real de la barra de progreso void positionChanged(qint64 positionMs); // Señal emitida al llegar al final del video void playbackFinished(); protected: // Bucle de decodificación principal que se ejecuta en el hilo secundario void run() override; private: QString m_fileName; // Ruta del archivo de video abierto bool m_running; // Controla si el bucle principal del hilo debe seguir ejecutándose bool m_isPaused; // Bandera de pausa bool m_seekRequested; // Bandera de solicitud de salto de tiempo (Seek) double m_seekTimeSecs; // Tiempo al que saltar en segundos QMutex m_mutex; // Mutex para proteger variables de control (pausa, running, seek) QWaitCondition m_waitCond; // Condición de espera para no consumir CPU cuando el video está en pausa double m_duration; // Duración total del video en segundos int m_videoWidth; // Ancho del video en píxeles int m_videoHeight; // Alto del video en píxeles int m_videoStreamIndex; // Índice del flujo de video dentro del contenedor (mp4, mkv, etc.) // Relojes de sincronización para reproducir al framerate correcto QElapsedTimer m_playbackTimer; // Reloj de alta resolución que mide el tiempo real transcurrido qint64 m_pausedElapsedMs; // Acumulador de tiempo transcurrido antes de la última pausa // Estructuras principales de FFmpeg AVFormatContext *m_formatContext; // Contexto de apertura y lectura del contenedor del archivo AVCodecContext *m_codecContext; // Contexto del decodificador (NVDEC / CUDA) AVBufferRef *m_hwDeviceCtx; // Contexto de hardware que asocia FFmpeg con el driver de CUDA // Fotograma de video en VRAM que contiene el frame actual listo para renderizar AVFrame *m_currentFrame; // Mutex de exclusión mutua para proteger el acceso a m_currentFrame entre hilos QMutex m_frameMutex; // Formato de pixel de hardware que FFmpeg debe solicitar (CUDA) static enum AVPixelFormat m_hwPixFmt; // Callback estático requerido por FFmpeg para negociar el formato de decodificación static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts); }; #endif // VIDEODECODER_H