diff --git a/ENNTool.py b/ENNTool.py index 4628ae0..a593868 100755 --- a/ENNTool.py +++ b/ENNTool.py @@ -10,8 +10,8 @@ # 3) Feature: include ETA @ progress bar # 4) Feature: autodetect video width from widest mircart # 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) -# 7) OpenGL: use VAOs + glVertexAttribFormat + glVertexAttribBinding +# 6) OpenGL: use VAOs + glVertexAttribFormat + glVertexAttribBinding +# 7) use names @ optdict[] + set from optdefaults # from getopt import getopt, GetoptError @@ -36,7 +36,7 @@ class ENNToolApp(object): print(" [-p] [-r WxH] [-R WxH] [-s fname]", file=sys.stderr) print(" [-S] [-v] [--] fname..", 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(" -h........: show this screen", 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 def modeScroll(self, argv, optdict, GLVideoWriter, panelGLCanvas, fps=25, scrollRate=0.25): MiRCART = [] + if "-v" in optdict: + time0 = time.time() for inFileArg in argv: for inFile in sorted(glob(inFileArg)): 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 + if "-v" in optdict: + time0 = time.time() 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"]) if "-v" in optdict: print("{} vertices".format(numVertices)) diff --git a/ENNToolGLVideoWriter.py b/ENNToolGLVideoWriter.py index 8d5da00..7141b9f 100644 --- a/ENNToolGLVideoWriter.py +++ b/ENNToolGLVideoWriter.py @@ -4,41 +4,65 @@ # Copyright (c) 2018 Lucio Andrés Illanes Albornoz # This project is licensed under the terms of the MIT license. # +# References: +# Tue, 03 Jul 2018 20:35:52 +0200 [1] +# Wed, 04 Jul 2018 10:02:22 +0200 [2] +# from OpenGL.GL import * -import numpy, subprocess +import ctypes, cv2, numpy class ENNToolGLVideoWriter(object): """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 def saveFrame(self): - frameBuffer = glReadPixels(0, 0, self.videoSize[0], self.videoSize[1], GL_RGB, GL_UNSIGNED_BYTE) - frameBuffer = numpy.frombuffer(frameBuffer, numpy.uint8) - frameBuffer = frameBuffer.reshape((self.videoSize[1], self.videoSize[0], 3)) - frameBuffer = numpy.flipud(frameBuffer) - self.videoFrames += [frameBuffer] + glBindBuffer(GL_PIXEL_PACK_BUFFER, self.pboList[self.pboCur]) + glReadPixels(0, 0, self.videoSize[0], self.videoSize[1], GL_BGR, GL_UNSIGNED_BYTE, ctypes.c_void_p(0)) + self.pboCur += 1 + if self.pboCur >= self.pboCount: + self._copyFrames(); self.pboCur = 0; + glBindBuffer(GL_PIXEL_PACK_BUFFER, 0) # }}} # {{{ saveVideo(self): XXX def saveVideo(self): - with subprocess.Popen([ - "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()) + return # }}} # {{{ __init__(self, videoPath, videoSize, videoFps=25): XXX def __init__(self, videoPath, videoSize, videoFps=25): - self.videoFps, self.videoPath, self.videoSize = videoFps, videoPath, videoSize - self.videoFrames = [] + videoWriter = self._initCv2(videoFps, videoPath, videoSize) + 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 diff --git a/README.md b/README.md index 67c6256..a8dbc83 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,35 @@ # ENNTool -- mIRC art animation tool (for EFnet #MiRCART) (WIP) Copyright (c) 2018 Lucio Andrés Illanes Albornoz <> -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: - `pip install chardet numpy Pillow PyOpenGL wxPython` -* Additionally, FFmpeg.exe must be present in the current working directory and/or %PATH%. +This project is licensed under the terms of the MIT licence. + +## 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` +3. Download OpenCV wheel[[1](#r1)] and install w/ the following elevated command prompt command line: + `pip install ` + +## 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]`` Python Extension Packages for Windows - Christoph Gohlke +``Wed, 04 Jul 2018 09:38:28 +0200 [2]`` Releases · cisco/openh264 · GitHub +``Wed, 04 Jul 2018 09:49:38 +0200 [3]`` opencv_ffmpeg and OpenH264-x.y.z · Issue #6080 · opencv/opencv · GitHub +``Wed, 04 Jul 2018 10:24:12 +0200 [4]`` Python Releases for Windows | Python.org diff --git a/openh264-1.7.0-win32.dll b/openh264-1.7.0-win32.dll new file mode 100755 index 0000000..da08091 Binary files /dev/null and b/openh264-1.7.0-win32.dll differ diff --git a/openh264-1.7.0-win32_LICENSE.txt b/openh264-1.7.0-win32_LICENSE.txt new file mode 100644 index 0000000..ff24a29 --- /dev/null +++ b/openh264-1.7.0-win32_LICENSE.txt @@ -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 Cisco’s 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 user’s device, and not integrated into or combined with third party software prior to being downloaded to the end user’s 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