zero_copy_video_player/mainwindow.cpp

157 lines
5.6 KiB
C++

#include "mainwindow.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QFileDialog>
#include <QScrollArea>
#include <QFrame>
#include <QGroupBox>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, m_updatingSeek(false)
{
setWindowTitle("Zero-Copy CUDA-GL Video Player");
resize(960, 600);
m_glWidget = new GLWidget(this);
m_videoDecoder = new VideoDecoder(this);
m_glWidget->setVideoDecoder(m_videoDecoder);
setupUI();
// Conectar las señales de posición y finalización del hilo descodificador
connect(m_videoDecoder, &VideoDecoder::positionChanged, this, &MainWindow::onPositionChanged);
connect(m_videoDecoder, &VideoDecoder::playbackFinished, this, &MainWindow::onPlaybackFinished);
}
MainWindow::~MainWindow() {
m_videoDecoder->stopThread();
}
void MainWindow::setupUI() {
// Aplicar hoja de estilos (QSS) para un look oscuro premium y retro-futurista
this->setStyleSheet(
"QMainWindow { background-color: #08080f; }"
"QWidget { color: #f0f0f5; font-family: 'Outfit', 'Segoe UI', sans-serif; font-size: 13px; }"
"QPushButton { background-color: #ff007f; color: white; border: none; padding: 8px 15px; border-radius: 6px; font-weight: bold; min-width: 60px; }"
"QPushButton:hover { background-color: #ff3399; }"
"QPushButton:pressed { background-color: #cc0066; }"
"QPushButton:disabled { background-color: #444; color: #888; }"
"QSlider::groove:horizontal { border: 1px solid #2d2d44; height: 6px; background: #1a1a2e; border-radius: 3px; }"
"QSlider::sub-page:horizontal { background: #ff007f; border-radius: 3px; }"
"QSlider::handle:horizontal { background: #ffffff; border: 1px solid #ff007f; width: 14px; height: 14px; margin: -4px 0; border-radius: 7px; }"
"QSlider::handle:horizontal:hover { background: #ff007f; }"
"QLabel { color: #a0a0c0; }"
);
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget);
mainLayout->setContentsMargins(10, 10, 10, 10);
mainLayout->setSpacing(10);
mainLayout->addWidget(m_glWidget, 1);
// Controles Multimedia
QHBoxLayout *controlsLayout = new QHBoxLayout();
QPushButton *openBtn = new QPushButton("Abrir Video", this);
openBtn->setStyleSheet("background-color: #00bfff;");
connect(openBtn, &QPushButton::clicked, this, &MainWindow::openVideoFile);
controlsLayout->addWidget(openBtn);
m_playBtn = new QPushButton("▶", this);
connect(m_playBtn, &QPushButton::clicked, this, &MainWindow::togglePlayPause);
controlsLayout->addWidget(m_playBtn);
m_muteBtn = new QPushButton("🔊", this);
m_muteBtn->setStyleSheet("background-color: #4a4e69;");
connect(m_muteBtn, &QPushButton::clicked, this, &MainWindow::toggleMute);
controlsLayout->addWidget(m_muteBtn);
m_seekBar = new QSlider(Qt::Horizontal, this);
m_seekBar->setRange(0, 1000);
m_seekBar->setEnabled(false);
connect(m_seekBar, &QSlider::sliderMoved, this, &MainWindow::setVideoPosition);
controlsLayout->addWidget(m_seekBar, 1);
m_timeLabel = new QLabel("00:00 / 00:00", this);
m_timeLabel->setMinimumWidth(90);
m_timeLabel->setAlignment(Qt::AlignCenter);
controlsLayout->addWidget(m_timeLabel);
mainLayout->addLayout(controlsLayout);
}
void MainWindow::openVideoFile() {
QString fileName = QFileDialog::getOpenFileName(this, "Abrir archivo de video", "", "Videos (*.mp4 *.avi *.mkv *.webm *.mov)");
if (!fileName.isEmpty()) {
openVideoFileDirect(fileName);
}
}
void MainWindow::openVideoFileDirect(const QString &fileName) {
m_glWidget->clearVideo();
m_videoDecoder->stopThread();
if (m_videoDecoder->openFile(fileName)) {
m_seekBar->setEnabled(m_videoDecoder->getDuration() > 0.0);
m_playBtn->setText("⏸");
m_videoDecoder->start(); // Arranca el hilo de decodificación
m_videoDecoder->play(); // Inicia la reproducción
}
}
void MainWindow::togglePlayPause() {
if (m_videoDecoder->isPaused()) {
m_videoDecoder->play();
m_playBtn->setText("⏸");
} else {
m_videoDecoder->pause();
m_playBtn->setText("▶");
}
}
void MainWindow::toggleMute() {
static bool muted = false;
muted = !muted;
m_muteBtn->setText(muted ? "🔇" : "🔊");
}
void MainWindow::setVideoPosition(int position) {
if (m_videoDecoder->getDuration() > 0.0) {
m_updatingSeek = true;
double targetSecs = (static_cast<double>(position) / 1000.0) * m_videoDecoder->getDuration();
m_videoDecoder->seek(targetSecs);
m_updatingSeek = false;
}
}
void MainWindow::onPositionChanged(qint64 positionMs) {
double durationSecs = m_videoDecoder->getDuration();
if (durationSecs > 0.0 && !m_updatingSeek) {
m_updatingSeek = true;
double progress = static_cast<double>(positionMs) / (durationSecs * 1000.0);
m_seekBar->setValue(static_cast<int>(progress * 1000.0));
m_updatingSeek = false;
}
// Formatear tiempos
auto format = [](qint64 ms) -> QString {
qint64 totalSecs = ms / 1000;
int mins = totalSecs / 60;
int secs = totalSecs % 60;
return QString("%1:%2").arg(mins, 2, 10, QChar('0')).arg(secs, 2, 10, QChar('0'));
};
m_timeLabel->setText(format(positionMs) + " / " + format(static_cast<qint64>(durationSecs * 1000.0)));
}
void MainWindow::onPlaybackFinished() {
m_playBtn->setText("▶");
m_seekBar->setValue(0);
}