diff options
author | Andy Nichols <andy.nichols@digia.com> | 2013-08-15 15:08:35 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-08-27 14:16:10 +0200 |
commit | 51d0f852b9be9c5753e28e2bb4a7f2f6c35dc533 (patch) | |
tree | 92fdcdc94ca120d33363d7b827b5c2f4e3fbf4f5 /src/plugins/avfoundation/mediaplayer/avfvideowidget.mm | |
parent | 17a700292ad9289e8de199dc50b3e222ede42e1d (diff) |
AVFoundation: Use CoreAnimation to render video to QVideoWidget
Previously a QGLWidget was used as a target for the
AVFVideoFrameRenderer. This was uncessary as it is possible to render
directly on top of the QWidget using the CoreAnimation Framework.
Change-Id: I08923c85fd56c8874c1d8c187ae5145e220fab92
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@digia.com>
Diffstat (limited to 'src/plugins/avfoundation/mediaplayer/avfvideowidget.mm')
-rw-r--r-- | src/plugins/avfoundation/mediaplayer/avfvideowidget.mm | 193 |
1 files changed, 84 insertions, 109 deletions
diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm index 518a6bcea..2e4de37f1 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm @@ -41,15 +41,19 @@ #include "avfvideowidget.h" #include <QtCore/QDebug> -#include <QtGui/QOpenGLShaderProgram> + +#include <AVFoundation/AVFoundation.h> +#include <QtGui/QResizeEvent> +#include <QtGui/QPaintEvent> +#include <QtGui/QPainter> QT_USE_NAMESPACE -AVFVideoWidget::AVFVideoWidget(QWidget *parent, const QGLFormat &format) - : QGLWidget(format, parent) - , m_textureId(0) +AVFVideoWidget::AVFVideoWidget(QWidget *parent) + : QWidget(parent) , m_aspectRatioMode(Qt::KeepAspectRatio) - , m_shaderProgram(0) + , m_playerLayer(0) + , m_nativeView(0) { setAutoFillBackground(false); } @@ -59,143 +63,114 @@ AVFVideoWidget::~AVFVideoWidget() #ifdef QT_DEBUG_AVF qDebug() << Q_FUNC_INFO; #endif - delete m_shaderProgram; + + if (m_playerLayer) + [m_playerLayer release]; } -void AVFVideoWidget::initializeGL() +QSize AVFVideoWidget::sizeHint() const { - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - - m_shaderProgram = new QOpenGLShaderProgram; - - static const char *textureVertexProgram = - "uniform highp mat4 matrix;\n" - "attribute highp vec3 vertexCoordEntry;\n" - "attribute highp vec2 textureCoordEntry;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " textureCoord = textureCoordEntry;\n" - " gl_Position = matrix * vec4(vertexCoordEntry, 1);\n" - "}\n"; - - static const char *textureFragmentProgram = - "uniform sampler2D texture;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(texture, textureCoord);\n" - "}\n"; - - m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); - m_shaderProgram->link(); + return m_nativeSize; } -void AVFVideoWidget::resizeGL(int w, int h) +Qt::AspectRatioMode AVFVideoWidget::aspectRatioMode() const { - glViewport(0, 0, GLsizei(w), GLsizei(h)); - updateGL(); + return m_aspectRatioMode; } -void AVFVideoWidget::paintGL() +void AVFVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode) { - glClear(GL_COLOR_BUFFER_BIT); - if (!m_textureId) - return; - - QRect targetRect = displayRect(); - GLfloat x1 = targetRect.left(); - GLfloat x2 = targetRect.right(); - GLfloat y1 = targetRect.bottom(); - GLfloat y2 = targetRect.top(); - GLfloat zValue = 0; + if (m_aspectRatioMode != mode) { + m_aspectRatioMode = mode; - const GLfloat textureCoordinates[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; + updateAspectRatio(); + } +} - const GLfloat vertexCoordinates[] = { - x1, y1, zValue, - x2, y1, zValue, - x2, y2, zValue, - x1, y2, zValue - }; +void AVFVideoWidget::setPlayerLayer(AVPlayerLayer *layer) +{ + if (m_playerLayer == layer) + return; - //Set matrix to transfrom geometry values into gl coordinate space. - m_transformMatrix.setToIdentity(); - m_transformMatrix.scale( 2.0f / size().width(), 2.0f / size().height() ); - m_transformMatrix.translate(-size().width() / 2.0f, -size().height() / 2.0f); + if (!m_nativeView) { + //make video widget a native window +#if defined(Q_OS_OSX) + m_nativeView = (NSView*)this->winId(); + [m_nativeView setWantsLayer:YES]; +#else + m_nativeView = (UIView*)this->winId(); +#endif + } - m_shaderProgram->bind(); + if (m_playerLayer) { + [m_playerLayer removeFromSuperlayer]; + [m_playerLayer release]; + } - m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry"); - m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry"); - m_matrixLocation = m_shaderProgram->uniformLocation("matrix"); + m_playerLayer = layer; - //attach the data! - glEnableVertexAttribArray(m_vertexCoordEntry); - glEnableVertexAttribArray(m_textureCoordEntry); + CALayer *nativeLayer = [m_nativeView layer]; - glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates); - glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); - m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix); + if (layer) { + [layer retain]; - glBindTexture(GL_TEXTURE_2D, m_textureId); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + m_nativeSize = QSize(m_playerLayer.bounds.size.width, + m_playerLayer.bounds.size.height); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + updateAspectRatio(); + [nativeLayer addSublayer:m_playerLayer]; + updatePlayerLayerBounds(this->size()); + } - glBindTexture(GL_TEXTURE_2D, 0); + NSArray *sublayers = [nativeLayer sublayers]; + qDebug() << "playerlayer: " << "at z:" << [m_playerLayer zPosition] + << " frame: " << m_playerLayer.frame.size.width << "x" << m_playerLayer.frame.size.height; + qDebug() << "superlayer: " << "at z:" << [nativeLayer zPosition] + << " frame: " << nativeLayer.frame.size.width << "x" << nativeLayer.frame.size.height; + int i = 0; + for (CALayer *layer in sublayers) { + qDebug() << "layer " << i << ": at z:" << [layer zPosition] + << " frame: " << layer.frame.size.width << "x" << layer.frame.size.height; + i++; + } - glDisableVertexAttribArray(m_vertexCoordEntry); - glDisableVertexAttribArray(m_textureCoordEntry); - m_shaderProgram->release(); } -void AVFVideoWidget::setTexture(GLuint texture) +void AVFVideoWidget::resizeEvent(QResizeEvent *event) { - m_textureId = texture; - - if (isVisible()) { - makeCurrent(); - updateGL(); - } + updatePlayerLayerBounds(event->size()); + QWidget::resizeEvent(event); } -QSize AVFVideoWidget::sizeHint() const +void AVFVideoWidget::paintEvent(QPaintEvent *event) { - return m_nativeSize; -} + QPainter painter(this); + painter.fillRect(rect(), Qt::black); -void AVFVideoWidget::setNativeSize(const QSize &size) -{ - m_nativeSize = size; + QWidget::paintEvent(event); } -void AVFVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode) +void AVFVideoWidget::updateAspectRatio() { - if (m_aspectRatioMode != mode) { - m_aspectRatioMode = mode; - update(); + if (m_playerLayer) { + switch (m_aspectRatioMode) { + case Qt::IgnoreAspectRatio: + [m_playerLayer setVideoGravity:AVLayerVideoGravityResize]; + break; + case Qt::KeepAspectRatio: + [m_playerLayer setVideoGravity:AVLayerVideoGravityResizeAspect]; + break; + case Qt::KeepAspectRatioByExpanding: + [m_playerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; + break; + default: + break; + } } } -QRect AVFVideoWidget::displayRect() const +void AVFVideoWidget::updatePlayerLayerBounds(const QSize &size) { - QRect displayRect = rect(); - - if (m_aspectRatioMode == Qt::KeepAspectRatio) { - QSize size = m_nativeSize; - size.scale(displayRect.size(), Qt::KeepAspectRatio); - - displayRect = QRect(QPoint(0, 0), size); - displayRect.moveCenter(rect().center()); - } - return displayRect; + m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, (float)size.width(), (float)size.height()); } |