<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <small>Hello Folks!<br>
      <br>
      I'm not a C++ programmer, but below is my best attempt at
      translating a C++ code example found in QtEnterprise<br>
      for creating a custom video widget using a custom video surface.
      Please feel free to use it ... if you can get it to <br>
      work! <br>
      <br>
      When I run the code the widget appears okay. The only error I'm
      getting is "QWidget::paintEngine: Should no longer be called",<br>
      but I'm not getting any video playback when I open a file. Looking
      at the code I don't see anything visible that would 'start' the<br>
      video surface, but I'm guessing that that is the responsibility of
      the QMediaPlayer instance? (self.mediaPlayer)<br>
      <br>
      If anyone has any suggestions, I'd love to hear them.<br>
      <br>
      I'm programming under Windows 7, with Python 3.3.2 and PyQt5-5.1,
      32 bit.<br>
      <br>
      Best regards,<br>
      Timothy Grove<br>
      <br>
      <br>
      <tt>#!/usr/bin/env python</tt><tt><br>
      </tt><tt># -*- coding: utf-8 -*-<br>
        <br>
      </tt><tt></tt><tt>"""The Video Widget example shows how to
        implement a video widget </tt><tt><br>
      </tt><tt>using QtMultimedia's QAbstractVideoSurface. <br>
        <br>
      </tt><tt></tt><tt>The following is a translation into PyQt5 from
        the C++ example found in</tt><tt><br>
      </tt><tt>C:\QtEnterprise\5.1.1\msvc2010\examples\multimediawidgets\customvideosurface\customvideowidget."""<br>
        <br>
      </tt><tt></tt><tt>import sys</tt><tt><br>
      </tt><tt>import os</tt><tt><br>
      </tt><tt>from PyQt5.QtGui import *</tt><tt><br>
      </tt><tt>from PyQt5.QtWidgets import *</tt><tt><br>
      </tt><tt>from PyQt5.QtCore import *</tt><tt><br>
      </tt><tt>from PyQt5.QtMultimedia import *</tt><tt><br>
      </tt><tt>from PyQt5.QtMultimediaWidgets import *<br>
        <br>
      </tt><tt></tt><tt>class VideoWidgetSurface(QAbstractVideoSurface):</tt><tt><br>
      </tt><tt>     </tt><tt><br>
      </tt><tt>    def __init__(self, widget, parent=None):</tt><tt><br>
      </tt><tt>        super(VideoWidgetSurface, self).__init__(parent)</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>        self.widget = widget</tt><tt><br>
      </tt><tt>        self.imageFormat = QImage.Format_Invalid<br>
        <br>
      </tt><tt></tt><tt>    def supportedPixelFormats(self,
        handleType=QAbstractVideoBuffer.NoHandle):</tt><tt><br>
      </tt><tt>        formats = [QVideoFrame.PixelFormat()]</tt><tt><br>
      </tt><tt>        if (handleType == QAbstractVideoBuffer.NoHandle):</tt><tt><br>
      </tt><tt>            for f in [QVideoFrame.Format_RGB32,</tt><tt><br>
      </tt><tt>                      QVideoFrame.Format_ARGB32,</tt><tt><br>
      </tt><tt>                     
        QVideoFrame.Format_ARGB32_Premultiplied,</tt><tt><br>
      </tt><tt>                      QVideoFrame.Format_RGB565,</tt><tt><br>
      </tt><tt>                      QVideoFrame.Format_RGB555</tt><tt><br>
      </tt><tt>                      ]:</tt><tt><br>
      </tt><tt>                formats.append(f)</tt><tt><br>
      </tt><tt>        return formats</tt><tt><br>
      </tt><tt>     </tt><tt><br>
      </tt><tt>    def isFormatSupported(self, _format):</tt><tt><br>
      </tt><tt>        imageFormat =
        QVideoFrame.imageFormatFromPixelFormat(_format.pixelFormat())</tt><tt><br>
      </tt><tt>        size = _format.frameSize()</tt><tt><br>
      </tt><tt>        _bool = False</tt><tt><br>
      </tt><tt>        if (imageFormat != QImage.Format_Invalid and not
      </tt><tt><br>
      </tt><tt>            size.isEmpty() and</tt><tt><br>
      </tt><tt>            _format.handleType() ==
        QAbstractVideoBuffer.NoHandle):</tt><tt><br>
      </tt><tt>            _bool = True</tt><tt><br>
      </tt><tt>        return _bool<br>
        <br>
      </tt><tt></tt><tt>    def start(self, _format):</tt><tt><br>
      </tt><tt>        imageFormat =
        QVideoFrame.imageFormatFromPixelFormat(_format.pixelFormat())</tt><tt><br>
      </tt><tt>        size = _format.frameSize()</tt><tt><br>
      </tt><tt>        if (imageFormat != QImage.Format_Invalid and not
        size.isEmpty()):</tt><tt><br>
      </tt><tt>            self.imageFormat = imageFormat</tt><tt><br>
      </tt><tt>            self.imageSize = size</tt><tt><br>
      </tt><tt>            self.sourceRect =
        _format.viewport()            </tt><tt><br>
      </tt><tt>            QAbstractVideoSurface.start(self, _format)   
      </tt><tt><br>
      </tt><tt>            self.widget.updateGeometry()</tt><tt><br>
      </tt><tt>            self.updateVideoRect()            </tt><tt><br>
      </tt><tt>            return True</tt><tt><br>
      </tt><tt>        else:</tt><tt><br>
      </tt><tt>            return False</tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>    def stop(self):</tt><tt><br>
      </tt><tt>        self.currentFrame = QVideoFrame()</tt><tt><br>
      </tt><tt>        self.targetRect = QRect()</tt><tt><br>
      </tt><tt>        QAbstractVideoSurface.stop(self)</tt><tt><br>
      </tt><tt>        self.widget.update()<br>
        <br>
      </tt><tt></tt><tt>    def present(self, frame):</tt><tt><br>
      </tt><tt>        if (self.surfaceFormat().pixelFormat() !=
        frame.pixelFormat() or</tt><tt><br>
      </tt><tt>            self.surfaceFormat().frameSize() !=
        frame.size()):</tt><tt><br>
      </tt><tt>           
        self.setError(QAbstractVideoSurface.IncorrectFormatError)</tt><tt><br>
      </tt><tt>            self.stop()</tt><tt><br>
      </tt><tt>            return False</tt><tt><br>
      </tt><tt>        else:</tt><tt><br>
      </tt><tt>            self.currentFrame = frame</tt><tt><br>
      </tt><tt>            self.widget.repaint(self.targetRect)</tt><tt><br>
      </tt><tt>            return True<br>
        <br>
      </tt><tt></tt><tt>    def videoRect(self):</tt><tt><br>
      </tt><tt>        return self.targetRect</tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>    def updateVideoRect(self):</tt><tt><br>
      </tt><tt>        size = self.surfaceFormat().sizeHint()</tt><tt><br>
      </tt><tt>        size.scale(self.widget.size().boundedTo(size),
        Qt.KeepAspectRatio)</tt><tt><br>
      </tt><tt>        self.targetRect = QRect(QPoint(0, 0), size);</tt><tt><br>
      </tt><tt>       
        self.targetRect.moveCenter(self.widget.rect().center())</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>    def paint(self, painter):</tt><tt><br>
      </tt><tt>        if
        (self.currentFrame.map(QAbstractVideoBuffer.ReadOnly)):</tt><tt><br>
      </tt><tt>            oldTransform = painter.transform()</tt><tt><br>
      </tt><tt> </tt><tt><br>
      </tt><tt>        if (self.surfaceFormat().scanLineDirection() ==
        QVideoSurfaceFormat.BottomToTop):</tt><tt><br>
      </tt><tt>            painter.scale(1, -1);</tt><tt><br>
      </tt><tt>            painter.translate(0, -self.widget.height())</tt><tt><br>
      </tt><tt> </tt><tt><br>
      </tt><tt>        image = QImage(self.currentFrame.bits(),</tt><tt><br>
      </tt><tt>                       self.currentFrame.width(),</tt><tt><br>
      </tt><tt>                       self.currentFrame.height(),</tt><tt><br>
      </tt><tt>                       self.currentFrame.bytesPerLine(),</tt><tt><br>
      </tt><tt>                       self.imageFormat</tt><tt><br>
      </tt><tt>                       )</tt><tt><br>
      </tt><tt> </tt><tt><br>
      </tt><tt>        painter.drawImage(self.targetRect, image,
        self.sourceRect)</tt><tt><br>
      </tt><tt>        painter.setTransform(oldTransform)</tt><tt><br>
      </tt><tt> </tt><tt><br>
      </tt><tt>        self.currentFrame.unmap()<br>
        <br>
      </tt><tt></tt><tt>class VideoWidget(QWidget):</tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>    def __init__(self, parent=None):</tt><tt><br>
      </tt><tt>        super(VideoWidget, self).__init__(parent)</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>        self.setAutoFillBackground(False)</tt><tt><br>
      </tt><tt>        self.setAttribute(Qt.WA_NoSystemBackground, True)</tt><tt><br>
      </tt><tt>        self.setAttribute(Qt.WA_PaintOnScreen, True)</tt><tt><br>
      </tt><tt>        palette = self.palette()</tt><tt><br>
      </tt><tt>        palette.setColor(QPalette.Background, Qt.black)</tt><tt><br>
      </tt><tt>        self.setPalette(palette)</tt><tt><br>
      </tt><tt>        self.setSizePolicy(QSizePolicy.MinimumExpanding,
        QSizePolicy.MinimumExpanding)</tt><tt><br>
      </tt><tt>        self.surface = VideoWidgetSurface(self)</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>    def videoSurface(self):</tt><tt><br>
      </tt><tt>        return self.surface                </tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>    def closeEvent(self, event):</tt><tt><br>
      </tt><tt>        del self.surface</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>    def sizeHint(self):</tt><tt><br>
      </tt><tt>        return self.surface.surfaceFormat().sizeHint()</tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>    def paintEvent(self, event):</tt><tt><br>
      </tt><tt>        painter = QPainter(self)</tt><tt><br>
      </tt><tt>        if (self.surface.isActive()):</tt><tt><br>
      </tt><tt>            videoRect = self.surface.videoRect()</tt><tt><br>
      </tt><tt>            if not videoRect.contains(event.rect()):</tt><tt><br>
      </tt><tt>                region = event.region()</tt><tt><br>
      </tt><tt>                region.subtract(videoRect)    </tt><tt><br>
      </tt><tt>                brush = self.palette().background()    </tt><tt><br>
      </tt><tt>                for rect in region.rects():</tt><tt><br>
      </tt><tt>                    painter.fillRect(rect, brush)    </tt><tt><br>
      </tt><tt>            self.surface.paint(painter)</tt><tt><br>
      </tt><tt>        else:</tt><tt><br>
      </tt><tt>            painter.fillRect(event.rect(),
        self.palette().window())</tt><tt><br>
      </tt><tt>            </tt><tt><br>
      </tt><tt>    def resizeEvent(self, event):</tt><tt><br>
      </tt><tt>        QWidget.resizeEvent(self, event)</tt><tt><br>
      </tt><tt>        self.surface.updateVideoRect()</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>class VideoPlayer(QWidget):</tt><tt><br>
      </tt><tt>    def __init__(self, parent=None):</tt><tt><br>
      </tt><tt>        super(VideoPlayer, self).__init__(parent)</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>        self.mediaPlayer = QMediaPlayer(None,
        QMediaPlayer.VideoSurface)</tt><tt><br>
      </tt><tt>        self.videoWidget = VideoWidget()</tt><tt><br>
      </tt><tt>        self.openButton = QPushButton("Open...")</tt><tt><br>
      </tt><tt>        self.openButton.clicked.connect(self.openFile)</tt><tt><br>
      </tt><tt>        self.playButton = QPushButton()</tt><tt><br>
      </tt><tt>        self.playButton.setEnabled(False)</tt><tt><br>
      </tt><tt>       
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))   
      </tt><tt><br>
      </tt><tt>        self.playButton.clicked.connect(self.play)</tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>        self.positionSlider = QSlider(Qt.Horizontal)</tt><tt><br>
      </tt><tt>        self.positionSlider.setRange(0, 0)</tt><tt><br>
      </tt><tt>       
        self.positionSlider.sliderMoved.connect(self.setPosition)</tt><tt><br>
      </tt><tt>        self.controlLayout = QHBoxLayout()</tt><tt><br>
      </tt><tt>        self.controlLayout.setContentsMargins(0, 0, 0, 0)</tt><tt><br>
      </tt><tt>        self.controlLayout.addWidget(self.openButton)</tt><tt><br>
      </tt><tt>        self.controlLayout.addWidget(self.playButton)</tt><tt><br>
      </tt><tt>        self.controlLayout.addWidget(self.positionSlider)</tt><tt><br>
      </tt><tt>        layout = QVBoxLayout()</tt><tt><br>
      </tt><tt>        layout.addWidget(self.videoWidget)</tt><tt><br>
      </tt><tt>        layout.addLayout(self.controlLayout)</tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>        self.setLayout(layout)</tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>       
        self.mediaPlayer.setVideoOutput(self.videoWidget.videoSurface())</tt><tt><br>
      </tt><tt>       
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)</tt><tt><br>
      </tt><tt>       
        self.mediaPlayer.positionChanged.connect(self.positionChanged)</tt><tt><br>
      </tt><tt>       
        self.mediaPlayer.durationChanged.connect(self.durationChanged)</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>    def openFile(self):</tt><tt><br>
      </tt><tt>        file_name = QFileDialog.getOpenFileName(self,
        "Open Movie", QDir.homePath())[0]</tt><tt><br>
      </tt><tt>        if os.path.exists(file_name):</tt><tt><br>
      </tt><tt>           
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(file_name)))</tt><tt><br>
      </tt><tt>            self.playButton.setEnabled(True)<br>
        <br>
      </tt><tt></tt><tt>    def play(self):</tt><tt><br>
      </tt><tt>        if self.mediaPlayer.state() ==
        QMediaPlayer.PlayingState:</tt><tt><br>
      </tt><tt>            self.mediaPlayer.pause()</tt><tt><br>
      </tt><tt>        else:</tt><tt><br>
      </tt><tt>            self.mediaPlayer.play()<br>
        <br>
      </tt><tt></tt><tt>    def mediaStateChanged(self, state):</tt><tt><br>
      </tt><tt>        if state == QMediaPlayer.PlayingState:</tt><tt><br>
      </tt><tt>           
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))</tt><tt><br>
      </tt><tt>        else:</tt><tt><br>
      </tt><tt>           
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))<br>
        <br>
      </tt><tt></tt><tt>    def positionChanged(self, position):</tt><tt><br>
      </tt><tt>        self.positionSlider.setValue(position)<br>
        <br>
      </tt><tt></tt><tt>    def durationChanged(self, duration):</tt><tt><br>
      </tt><tt>        self.positionSlider.setRange(0, duration)</tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>    def setPosition(self, position):</tt><tt><br>
      </tt><tt>        self.mediaPlayer.setPosition(position)</tt><tt><br>
      </tt><tt>                </tt><tt><br>
      </tt><tt>        </tt><tt><br>
      </tt><tt>if __name__ == '__main__':</tt><tt><br>
      </tt><tt>    app = QApplication(sys.argv)</tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>    player = VideoPlayer()</tt><tt><br>
      </tt><tt>    player.show() </tt><tt><br>
      </tt><tt>    </tt><tt><br>
      </tt><tt>    sys.exit(app.exec_()) </tt></small>
  </body>
</html>