Optimise rendering pipeline w/ PBOs & switch to H264.

This commit is contained in:
Lucio Andrés Illanes Albornoz 2018-07-04 10:26:41 +02:00
parent eff72be6ef
commit 4817313bbc
5 changed files with 148 additions and 28 deletions

View File

@ -10,8 +10,8 @@
# 3) Feature: include ETA @ progress bar # 3) Feature: include ETA @ progress bar
# 4) Feature: autodetect video width from widest mircart # 4) Feature: autodetect video width from widest mircart
# 5) Feature: render mircart as 3D blocks vs flat surface # 5) Feature: render mircart as 3D blocks vs flat surface
# 6) Optimisation: dont stall GPU w/ glReadPixels(), switch to asynchronous model w/ FBO or PBO (http://www.songho.ca/opengl/gl_fbo.html, http://www.songho.ca/opengl/gl_pbo.html) # 6) OpenGL: use VAOs + glVertexAttribFormat + glVertexAttribBinding
# 7) OpenGL: use VAOs + glVertexAttribFormat + glVertexAttribBinding # 7) use names @ optdict[] + set from optdefaults
# #
from getopt import getopt, GetoptError from getopt import getopt, GetoptError
@ -36,7 +36,7 @@ class ENNToolApp(object):
print(" [-p] [-r WxH] [-R WxH] [-s fname]", file=sys.stderr) print(" [-p] [-r WxH] [-R WxH] [-s fname]", file=sys.stderr)
print(" [-S] [-v] [--] fname..", file=sys.stderr) print(" [-S] [-v] [--] fname..", file=sys.stderr)
print("", file=sys.stderr) print("", file=sys.stderr)
print(" -a........: select animation mode", file=sys.stderr) print(" -a........: select animation mode (UNIMPLEMENTED)", file=sys.stderr)
print(" -f fps....: set video FPS; defaults to 25", file=sys.stderr) print(" -f fps....: set video FPS; defaults to 25", file=sys.stderr)
print(" -h........: show this screen", file=sys.stderr) print(" -h........: show this screen", file=sys.stderr)
print(" -o fname..: output video filename; extension determines video type", file=sys.stderr) print(" -o fname..: output video filename; extension determines video type", file=sys.stderr)
@ -85,12 +85,20 @@ class ENNToolApp(object):
# {{{ modeScroll(self, argv, optdict, GLVideoWriter, panelGLCanvas, fps=25, scrollRate=0.25): XXX # {{{ modeScroll(self, argv, optdict, GLVideoWriter, panelGLCanvas, fps=25, scrollRate=0.25): XXX
def modeScroll(self, argv, optdict, GLVideoWriter, panelGLCanvas, fps=25, scrollRate=0.25): def modeScroll(self, argv, optdict, GLVideoWriter, panelGLCanvas, fps=25, scrollRate=0.25):
MiRCART = [] MiRCART = []
if "-v" in optdict:
time0 = time.time()
for inFileArg in argv: for inFileArg in argv:
for inFile in sorted(glob(inFileArg)): for inFile in sorted(glob(inFileArg)):
MiRCART += ENNToolMiRCARTImporter(inFile).outMap MiRCART += ENNToolMiRCARTImporter(inFile).outMap
if "-v" in optdict:
print("mIRC art import delta {:.3f}ms".format((time.time() - time0) * 1000))
curY, rotateX, rotateY, translateY = 0, 0, 0, scrollRate curY, rotateX, rotateY, translateY = 0, 0, 0, scrollRate
if "-v" in optdict:
time0 = time.time()
artTextureId, artInfo = ENNToolGLTTFTexture(MiRCART, optdict["-R"], optdict["-r"]).getParams() artTextureId, artInfo = ENNToolGLTTFTexture(MiRCART, optdict["-R"], optdict["-r"]).getParams()
if "-v" in optdict:
print("TTF texture generation delta {:.3f}ms".format((time.time() - time0) * 1000))
artVbo, artVboLen, lastY, numVertices = panelGLCanvas.renderMiRCART(artInfo, MiRCART, cubeSize=optdict["-R"]) artVbo, artVboLen, lastY, numVertices = panelGLCanvas.renderMiRCART(artInfo, MiRCART, cubeSize=optdict["-R"])
if "-v" in optdict: if "-v" in optdict:
print("{} vertices".format(numVertices)) print("{} vertices".format(numVertices))

View File

@ -4,41 +4,65 @@
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de> # Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
# This project is licensed under the terms of the MIT license. # This project is licensed under the terms of the MIT license.
# #
# References:
# Tue, 03 Jul 2018 20:35:52 +0200 [1] <https://stackoverflow.com/questions/23930671/how-to-create-n-dim-numpy-array-from-a-pointer>
# Wed, 04 Jul 2018 10:02:22 +0200 [2] <http://www.songho.ca/opengl/gl_pbo.html>
#
from OpenGL.GL import * from OpenGL.GL import *
import numpy, subprocess import ctypes, cv2, numpy
class ENNToolGLVideoWriter(object): class ENNToolGLVideoWriter(object):
"""XXX""" """XXX"""
# {{{ _copyFrames(self): XXX
def _copyFrames(self):
for numPbo in range(self.pboCount):
glBindBuffer(GL_PIXEL_PACK_BUFFER, self.pboList[numPbo])
frameBufferPtr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY)
frameBufferPtr = ctypes.cast(frameBufferPtr, ctypes.POINTER(ctypes.c_ubyte))
frameBuffer = numpy.ctypeslib.as_array(frameBufferPtr, shape=(self.videoSize[1], self.videoSize[0], 3))
frameBuffer = numpy.flipud(frameBuffer)
self.videoWriter.write(frameBuffer)
glUnmapBuffer(GL_PIXEL_PACK_BUFFER)
# }}}
# {{{ _initCv2(self, videoFps, videoPath, videoSize): XXX
def _initCv2(self, videoFps, videoPath, videoSize):
fourcc = cv2.VideoWriter_fourcc(*"avc1")
videoWriter = cv2.VideoWriter(videoPath, fourcc, videoFps, tuple(videoSize), True)
return videoWriter
# }}}
# {{{ _initPbos(self, pboCount, videoSize): XXX
def _initPbos(self, pboCount, videoSize):
pboBufs, pboCur, pboList = [None] * pboCount, 0, [None] * pboCount
for numPbo in range(pboCount):
pboList[numPbo] = glGenBuffers(1)
glBindBuffer(GL_PIXEL_PACK_BUFFER, pboList[numPbo])
glBufferData(GL_PIXEL_PACK_BUFFER,
videoSize[0] * videoSize[1] * 3, None, GL_STREAM_READ)
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)
return pboBufs, pboCount, pboCur, pboList
# }}}
# {{{ saveFrame(self): XXX # {{{ saveFrame(self): XXX
def saveFrame(self): def saveFrame(self):
frameBuffer = glReadPixels(0, 0, self.videoSize[0], self.videoSize[1], GL_RGB, GL_UNSIGNED_BYTE) glBindBuffer(GL_PIXEL_PACK_BUFFER, self.pboList[self.pboCur])
frameBuffer = numpy.frombuffer(frameBuffer, numpy.uint8) glReadPixels(0, 0, self.videoSize[0], self.videoSize[1], GL_BGR, GL_UNSIGNED_BYTE, ctypes.c_void_p(0))
frameBuffer = frameBuffer.reshape((self.videoSize[1], self.videoSize[0], 3)) self.pboCur += 1
frameBuffer = numpy.flipud(frameBuffer) if self.pboCur >= self.pboCount:
self.videoFrames += [frameBuffer] self._copyFrames(); self.pboCur = 0;
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0)
# }}} # }}}
# {{{ saveVideo(self): XXX # {{{ saveVideo(self): XXX
def saveVideo(self): def saveVideo(self):
with subprocess.Popen([ return
"FFmpeg.exe",
"-pix_fmt", "rgb24",
"-r", str(self.videoFps),
"-s", "x".join([str(r) for r in self.videoSize]),
"-vcodec", "rawvideo",
"-f", "rawvideo",
"-i", "-",
"-an",
"-y",
self.videoPath], stdin=subprocess.PIPE) as procObject:
for videoFrame in self.videoFrames:
procObject.stdin.write(videoFrame.tobytes())
# }}} # }}}
# {{{ __init__(self, videoPath, videoSize, videoFps=25): XXX # {{{ __init__(self, videoPath, videoSize, videoFps=25): XXX
def __init__(self, videoPath, videoSize, videoFps=25): def __init__(self, videoPath, videoSize, videoFps=25):
self.videoFps, self.videoPath, self.videoSize = videoFps, videoPath, videoSize videoWriter = self._initCv2(videoFps, videoPath, videoSize)
self.videoFrames = [] self.pboBufs, self.pboCount, \
self.pboCur, self.pboList = self._initPbos(videoFps, videoSize)
self.videoFps, self.videoPath, \
self.videoSize, self.videoWriter = videoFps, videoPath, videoSize, videoWriter
# }}} # }}}
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120 # vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -1,6 +1,35 @@
# ENNTool -- mIRC art animation tool (for EFnet #MiRCART) (WIP) # ENNTool -- mIRC art animation tool (for EFnet #MiRCART) (WIP)
Copyright (c) 2018 Lucio Andrés Illanes Albornoz <<lucio@lucioillanes.de>> Copyright (c) 2018 Lucio Andrés Illanes Albornoz <<lucio@lucioillanes.de>>
This project is licensed under the terms of the MIT licence. This project is licensed under the terms of the MIT licence.
* Prerequisites on Windows: install Python v3.5.x and script dependencies w/ the following elevated command prompt command line:
## Installation instructions on Windows
1. Install Python v>=3.5.x[[4](#r4)]
2. Install script dependencies w/ the following elevated command prompt command line:
`pip install chardet numpy Pillow PyOpenGL wxPython` `pip install chardet numpy Pillow PyOpenGL wxPython`
* Additionally, FFmpeg.exe must be present in the current working directory and/or %PATH%. 3. Download OpenCV wheel[[1](#r1)] and install w/ the following elevated command prompt command line:
`pip install <path to OpenCV wheel>`
## How to run
```
usage: ENNTool.py
[-A] [-f fps] [-h] [-o fname]
[-p] [-r WxH] [-R WxH] [-s fname]
[-S] [-v] [--] fname..
-a........: select animation mode (UNIMPLEMENTED)
-f fps....: set video FPS; defaults to 25
-h........: show this screen
-o fname..: output video filename; extension determines video type
-p........: play video after rendering
-r WxH....: set video resolution; defaults to 1152x864
-R WxH....: set MiRCART cube resolution; defaults to 0.1x0.2
-s fname..: input script filename
-S........: select scrolling mode
-v........: be verbose
```
## References
``Wed, 04 Jul 2018 09:33:53 +0200 [1]`` <a href="https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv" id="r1">Python Extension Packages for Windows - Christoph Gohlke</a>
``Wed, 04 Jul 2018 09:38:28 +0200 [2]`` <a href="https://github.com/cisco/openh264/releases" id="r2">Releases · cisco/openh264 · GitHub</a>
``Wed, 04 Jul 2018 09:49:38 +0200 [3]`` <a href="https://github.com/opencv/opencv/issues/6080" id="r3">opencv_ffmpeg and OpenH264-x.y.z · Issue #6080 · opencv/opencv · GitHub</a>
``Wed, 04 Jul 2018 10:24:12 +0200 [4]`` <a href="https://www.python.org/downloads/windows" id="r4">Python Releases for Windows | Python.org</a>

BIN
openh264-1.7.0-win32.dll Executable file

Binary file not shown.

View File

@ -0,0 +1,59 @@
-------------------------------------------------------
About The Cisco-Provided Binary of OpenH264 Video Codec
-------------------------------------------------------
Cisco provides this program under the terms of the BSD license.
Additionally, this binary is licensed under Ciscos AVC/H.264 Patent Portfolio License from MPEG LA, at no cost to you, provided that the requirements and conditions shown below in the AVC/H.264 Patent Portfolio sections are met.
As with all AVC/H.264 codecs, you may also obtain your own patent license from MPEG LA or from the individual patent owners, or proceed at your own risk. Your rights from Cisco under the BSD license are not affected by this choice.
For more information on the OpenH264 binary licensing, please see the OpenH264 FAQ found at http://www.openh264.org/faq.html#binary
A corresponding source code to this binary program is available under the same BSD terms, which can be found at http://www.openh264.org
-----------
BSD License
-----------
Copyright © 2014 Cisco Systems, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------
AVC/H.264 Patent Portfolio License Notice
-----------------------------------------
The binary form of this Software is distributed by Cisco under the AVC/H.264 Patent Portfolio License from MPEG LA, and is subject to the following requirements, which may or may not be applicable to your use of this software:
THIS PRODUCT IS LICENSED UNDER THE AVC PATENT PORTFOLIO LICENSE FOR THE PERSONAL USE OF A CONSUMER OR OTHER USES IN WHICH IT DOES NOT RECEIVE REMUNERATION TO (i) ENCODE VIDEO IN COMPLIANCE WITH THE AVC STANDARD (“AVC VIDEO”) AND/OR (ii) DECODE AVC VIDEO THAT WAS ENCODED BY A CONSUMER ENGAGED IN A PERSONAL ACTIVITY AND/OR WAS OBTAINED FROM A VIDEO PROVIDER LICENSED TO PROVIDE AVC VIDEO. NO LICENSE IS GRANTED OR SHALL BE IMPLIED FOR ANY OTHER USE. ADDITIONAL INFORMATION MAY BE OBTAINED FROM MPEG LA, L.L.C. SEE HTTP://WWW.MPEGLA.COM
Accordingly, please be advised that content providers and broadcasters using AVC/H.264 in their service may be required to obtain a separate use license from MPEG LA, referred to as "(b) sublicenses" in the SUMMARY OF AVC/H.264 LICENSE TERMS from MPEG LA found at http://www.openh264.org/mpegla
---------------------------------------------
AVC/H.264 Patent Portfolio License Conditions
---------------------------------------------
In addition, the Cisco-provided binary of this Software is licensed under Cisco's license from MPEG LA only if the following conditions are met:
1. The Cisco-provided binary is separately downloaded to an end users device, and not integrated into or combined with third party software prior to being downloaded to the end users device;
2. The end user must have the ability to control (e.g., to enable, disable, or re-enable) the use of the Cisco-provided binary;
3. Third party software, in the location where end users can control the use of the Cisco-provided binary, must display the following text:
"OpenH264 Video Codec provided by Cisco Systems, Inc."
4. Any third-party software that makes use of the Cisco-provided binary must reproduce all of the above text, as well as this last condition, in the EULA and/or in another location where licensing information is to be presented to the end user.
v1.0