[PyQt] Fwd: QAbstractVideoSurface RTP player

Fran Raga franka1986 at gmail.com
Mon Nov 18 09:24:53 GMT 2019


hi all

I'm trying to play a video via RTP but strange things happen.

The video plays but not always and does not return any error message.
Sometimes when I open it it works and another does not

I don't know if I'm missing a flag or I'm doing it wrong.

Any suggestion about this?

this is my code

import sys
import os
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtNetwork import *
from PyQt5.QtMultimedia import *
from PyQt5.QtMultimediaWidgets import *
import time

fileName = 'rtp://127.0.0.1:8888'


class VideoWidgetSurface(QAbstractVideoSurface):

    def __init__(self, widget, parent=None):
        super(VideoWidgetSurface, self).__init__(parent)

        self.widget = widget
        self.imageFormat = QImage.Format_Invalid

    def supportedPixelFormats(self,
handleType=QAbstractVideoBuffer.NoHandle):
        formats = [QVideoFrame.PixelFormat()]
        if (handleType == QAbstractVideoBuffer.NoHandle):
            for f in [QVideoFrame.Format_RGB32,
            QVideoFrame.Format_ARGB32,
            QVideoFrame.Format_ARGB32_Premultiplied,
            QVideoFrame.Format_RGB565,
            QVideoFrame.Format_RGB555
            ]:
                formats.append(f)
        return formats

    def isFormatSupported(self, _format):
        imageFormat =
QVideoFrame.imageFormatFromPixelFormat(_format.pixelFormat())
        size = _format.frameSize()
        _bool = False
        if (imageFormat != QImage.Format_Invalid and not \
        size.isEmpty() and _format.handleType() ==
QAbstractVideoBuffer.NoHandle):
            _bool = True
        return _bool

    def start(self, _format):
        imageFormat =
QVideoFrame.imageFormatFromPixelFormat(_format.pixelFormat())
        size = _format.frameSize()
        if (imageFormat != QImage.Format_Invalid and not size.isEmpty()):
            self.imageFormat = imageFormat
            self.imageSize = size
            self.sourceRect = _format.viewport()
            QAbstractVideoSurface.start(self, _format)
            self.widget.updateGeometry()
            self.updateVideoRect()
            return True
        else:
            return False

    def stop(self):
        self.currentFrame = QVideoFrame()
        self.targetRect = QRect()
        QAbstractVideoSurface.stop(self)
        self.widget.update()

    def present(self, frame):
        if (self.surfaceFormat().pixelFormat() != frame.pixelFormat() or
self.surfaceFormat().frameSize() != frame.size()):
            self.setError(QAbstractVideoSurface.IncorrectFormatError)
            self.stop()
            return False
        else:
            self.currentFrame = frame
            self.widget.repaint(self.targetRect)
            return True

    def videoRect(self):
        return self.targetRect

    def updateVideoRect(self):
        size = self.surfaceFormat().sizeHint()
        size.scale(self.widget.size().boundedTo(size), Qt.KeepAspectRatio)
        self.targetRect = QRect(QPoint(0, 0), size)
        self.targetRect.moveCenter(self.widget.rect().center())

    def paint(self, painter):
        try:  # maybe raise no �cruuentFrame� error
            if (self.currentFrame.map(QAbstractVideoBuffer.ReadOnly)):
                oldTransform = painter.transform()

            if (self.surfaceFormat().scanLineDirection() ==
QVideoSurfaceFormat.BottomToTop):
                painter.scale(1, -1);
                painter.translate(0, -self.widget.height())

            image = QImage(self.currentFrame.bits(),
self.currentFrame.width(), \
                self.currentFrame.height(),
self.currentFrame.bytesPerLine(), self.imageFormat)

            painter.drawImage(self.targetRect, image, self.sourceRect)
            painter.setTransform(oldTransform)

            self.currentFrame.unmap()
        except Exception as e:
            print("Error paint : " , str(e))
            pass


class VideoWidget(QWidget):

    def __init__(self, parent=None):
        super(VideoWidget, self).__init__(parent)

        self.setAutoFillBackground(False)
        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAttribute(Qt.WA_PaintOnScreen, True)
        palette = self.palette()
        palette.setColor(QPalette.Background, Qt.black)
        self.setPalette(palette)
        self.setSizePolicy(QSizePolicy.MinimumExpanding,
QSizePolicy.MinimumExpanding)
        self.surface = VideoWidgetSurface(self)

    def videoSurface(self):
        return self.surface

    def closeEvent(self, event):
        del self.surface

    def sizeHint(self):
        return self.surface.surfaceFormat().sizeHint()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.HighQualityAntialiasing)
        print ("surface active : ", self.surface.isActive())
        if (self.surface.isActive()):
            self.surface.paint(painter)
        else:
            painter.fillRect(event.rect(), self.palette().window())

    def resizeEvent(self, event):
        QWidget.resizeEvent(self, event)
        self.surface.updateVideoRect()


class VideoPlayer(QWidget):

    def __init__(self, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface or
QMediaPlayer.StreamPlayback)
        self.videoWidget = VideoWidget()
        self.openButton = QPushButton("Open...")
        self.openButton.clicked.connect(self.openFile)
        self.playButton = QPushButton()
        self.playButton.setEnabled(False)

self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.controlLayout = QHBoxLayout()
        self.controlLayout.setContentsMargins(0, 0, 0, 0)
        self.controlLayout.addWidget(self.openButton)
        self.controlLayout.addWidget(self.playButton)
        self.controlLayout.addWidget(self.positionSlider)
        layout = QVBoxLayout()
        layout.addWidget(self.videoWidget)
        layout.addLayout(self.controlLayout)

        self.setLayout(layout)

        self.mediaPlayer.setVideoOutput(self.videoWidget.videoSurface())
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)

        url = QUrl(fileName)
        media = QMediaContent(url)

        self.mediaPlayer.setMedia(media)
        self.playButton.setEnabled(True)
        time.sleep(.300)
        self.mediaPlayer.play()

    def openFile(self):
        file_name = QFileDialog.getOpenFileName(self, "Open Movie",
QDir.homePath())[0]
        if os.path.exists(file_name):

self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(file_name)))
            self.playButton.setEnabled(True)

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if state == QMediaPlayer.PlayingState:

self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
        else:

self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    player = VideoPlayer()
    player.setGeometry(100, 300, 600, 380)
    player.setFixedSize(QSize(600, 600))  # setFixedSize(QSize)
    player.show()

    sys.exit(app.exec_())


And for start server I'm using

ffmpeg -fflags +genpts -stream_loop -1 -re -i "C:\Users\Fran
Raga\Desktop\video_test\Cheyenne.ts" -f rtp_mpegts -c copy -map 0:v -map
0:a -map 0:d rtp://127.0.0.1:8888

thanks

*Francisco Raga** | *Full-Stack Open Source GIS Developer

Móvil: (+34) 654275432* | *e-Mail: franka1986 at gmail.com *| *skype:
francisco_raga
Github: https://goo.gl/ydNTjY *| *Linkedin: https://goo.gl/TCfj8S *| *Site:
https://goo.gl/qiypDj

"La vida real no tiene ningún mapa.."  Ivy Compton Burnett
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20191118/cccb90a6/attachment.html>


More information about the PyQt mailing list