diff --git a/ffmpeg/audiodisplay.cc b/ffmpeg/audiodisplay.cc index 0a4b321..c4844b4 100644 --- a/ffmpeg/audiodisplay.cc +++ b/ffmpeg/audiodisplay.cc @@ -106,7 +106,7 @@ void AudioDisplay::runDecoder() continue; } auto emitPosition = qScopeGuard([=]() { emit positionChanged(pts); }); - if (!Clock::adjustDelay(delay)) { + if (!d_ptr->clock->adjustDelay(delay)) { qDebug() << "Audio Delay: " << delay; dropNum++; continue; diff --git a/ffmpeg/clock.cc b/ffmpeg/clock.cc index dc4795a..cac20e1 100644 --- a/ffmpeg/clock.cc +++ b/ffmpeg/clock.cc @@ -145,6 +145,11 @@ auto Clock::adjustDelay(qint64 &delay) -> bool if (speed() > 1.0 && delay < 0) { return false; } else if (delay < -Clock::ClockPrivate::s_diffThreshold) { + reset(pts()); // 有可能是因为网络下载过慢导致的延迟,需要重置 + if (this == Clock::ClockPrivate::s_clock) { // 主时钟不丢帧 + delay = 0; + return true; + } return false; } else if (qAbs(delay) <= Clock::ClockPrivate::s_diffThreshold) { delay = 0; diff --git a/ffmpeg/clock.hpp b/ffmpeg/clock.hpp index 5be3f7e..3b36100 100644 --- a/ffmpeg/clock.hpp +++ b/ffmpeg/clock.hpp @@ -32,7 +32,7 @@ class Clock : public QObject auto getDelayWithMaster(qint64 &delay) const -> bool; // return true if delay is valid - static auto adjustDelay(qint64 &delay) -> bool; + auto adjustDelay(qint64 &delay) -> bool; static void globalSerialRef(); static void globalSerialReset(); diff --git a/ffmpeg/subtitledisplay.cc b/ffmpeg/subtitledisplay.cc index 982d951..dd83f1a 100644 --- a/ffmpeg/subtitledisplay.cc +++ b/ffmpeg/subtitledisplay.cc @@ -129,12 +129,12 @@ void SubtitleDisplay::runDecoder() continue; } auto delayDuration = delay + subtitlePtr->duration(); - if (!Clock::adjustDelay(delayDuration)) { + if (!d_ptr->clock->adjustDelay(delayDuration)) { qDebug() << "Subtitle Delay: " << delay; dropNum++; continue; } - if (Clock::adjustDelay(delay)) { + if (d_ptr->clock->adjustDelay(delay)) { if (delay > 0) { QMutexLocker locker(&d_ptr->mutex); d_ptr->waitCondition.wait(&d_ptr->mutex, delay / 1000); diff --git a/ffmpeg/videodisplay.cc b/ffmpeg/videodisplay.cc index e5d65bd..77fea2e 100644 --- a/ffmpeg/videodisplay.cc +++ b/ffmpeg/videodisplay.cc @@ -111,7 +111,7 @@ void VideoDisplay::runDecoder() continue; } auto emitPosition = qScopeGuard([=]() { emit positionChanged(pts); }); - if (!Clock::adjustDelay(delay)) { + if (!d_ptr->clock->adjustDelay(delay)) { qDebug() << "Video Delay: " << delay; dropNum++; continue; diff --git a/ffmpeg/videorender/openglrender.cc b/ffmpeg/videorender/openglrender.cc index 5174e79..67c4f22 100644 --- a/ffmpeg/videorender/openglrender.cc +++ b/ffmpeg/videorender/openglrender.cc @@ -200,23 +200,6 @@ void OpenglRender::initSubTexture() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } -void OpenglRender::resizeViewport() -{ - auto avframe = d_ptr->framePtr->avFrame(); - auto size = QSize(avframe->width, avframe->height); - size.scale(this->size(), Qt::KeepAspectRatio); - auto rect = QRectF((width() - size.width()) / 2.0, - (height() - size.height()) / 2.0, - size.width(), - size.height()); - // 设置视图大小实现图片自适应 - auto devicePixelRatio = this->devicePixelRatio(); - glViewport(rect.x() * devicePixelRatio, - rect.y() * devicePixelRatio, - rect.width() * devicePixelRatio, - rect.height() * devicePixelRatio); -} - void OpenglRender::setColorSpace() { auto avFrame = d_ptr->framePtr->avFrame(); @@ -239,9 +222,21 @@ void OpenglRender::setColorSpace() } } +auto OpenglRender::fitToScreen(const QSize &size) -> QMatrix4x4 +{ + auto factor_w = qreal(width()) / size.width(); + auto factor_h = qreal(height()) / size.height(); + auto factor = qMin(factor_w, factor_h); + QMatrix4x4 matrix; + matrix.setToIdentity(); + matrix.scale(factor / factor_w, factor / factor_h); + return matrix; +} + void OpenglRender::paintVideoFrame() { - auto format = d_ptr->framePtr->avFrame()->format; + auto avFrame = d_ptr->framePtr->avFrame(); + auto format = avFrame->format; //qDebug() << format; // 绑定纹理 switch (format) { @@ -272,7 +267,7 @@ void OpenglRender::paintVideoFrame() } d_ptr->programPtr->bind(); // 绑定着色器 d_ptr->programPtr->setUniformValue("format", format); - + d_ptr->programPtr->setUniformValue("transform", fitToScreen({avFrame->width, avFrame->height})); setColorSpace(); draw(); d_ptr->programPtr->release(); @@ -302,6 +297,7 @@ void OpenglRender::paintSubTitleFrame() img.constBits()); glEnable(GL_BLEND); d_ptr->subProgramPtr->bind(); + d_ptr->subProgramPtr->setUniformValue("transform", fitToScreen(img.size())); draw(); d_ptr->subProgramPtr->release(); glDisable(GL_BLEND); @@ -366,6 +362,12 @@ void OpenglRender::initializeGL() glBindVertexArray(0); // 设置为零以破坏现有的顶点数组对象绑定} } +void OpenglRender::resizeGL(int w, int h) +{ + auto ratioF = devicePixelRatioF(); + glViewport(0, 0, w * ratioF, w * ratioF); +} + void OpenglRender::paintGL() { clear(); @@ -374,8 +376,6 @@ void OpenglRender::paintGL() return; } - resizeViewport(); - paintVideoFrame(); paintSubTitleFrame(); } diff --git a/ffmpeg/videorender/openglrender.hpp b/ffmpeg/videorender/openglrender.hpp index 673de5b..b3f7b42 100644 --- a/ffmpeg/videorender/openglrender.hpp +++ b/ffmpeg/videorender/openglrender.hpp @@ -28,6 +28,7 @@ class FFMPEG_EXPORT OpenglRender : public VideoRender, protected: void initializeGL() override; + void resizeGL(int w, int h) override; void paintGL() override; void updateFrame(QSharedPointer frame) override; @@ -38,8 +39,8 @@ class FFMPEG_EXPORT OpenglRender : public VideoRender, void draw(); void initTexture(); void initSubTexture(); - void resizeViewport(); void setColorSpace(); + auto fitToScreen(const QSize &size) -> QMatrix4x4; void paintVideoFrame(); void paintSubTitleFrame(); diff --git a/ffmpeg/videorender/shader/video.vert b/ffmpeg/videorender/shader/video.vert index c9c6918..78d847d 100644 --- a/ffmpeg/videorender/shader/video.vert +++ b/ffmpeg/videorender/shader/video.vert @@ -1,10 +1,13 @@ #version 330 core + layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTexCord; out vec2 TexCord; // 纹理坐标 +uniform mat4 transform; + void main() { - gl_Position = vec4(aPos.x, -aPos.y, aPos.z, 1.0); // 图像坐标和OpenGL坐标Y轴相反, - TexCord = aTexCord; + gl_Position = transform * vec4(aPos, 1.0); + TexCord = vec2(aTexCord.x, 1.0 - aTexCord.y); }