aboutsummaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/video.py80
-rw-r--r--components/video.ui7
2 files changed, 77 insertions, 10 deletions
diff --git a/components/video.py b/components/video.py
index 841f77b..5f55211 100644
--- a/components/video.py
+++ b/components/video.py
@@ -11,13 +11,15 @@ class Video:
'''Video Component Frame-Fetcher'''
def __init__(self, **kwargs):
mandatoryArgs = [
- 'ffmpeg', # path to ffmpeg, usually core.FFMPEG_BIN
+ 'ffmpeg', # path to ffmpeg, usually core.FFMPEG_BIN
'videoPath',
'width',
'height',
+ 'scale', # percentage scale
'frameRate', # frames per second
'chunkSize', # number of bytes in one frame
- 'parent'
+ 'parent', # mainwindow object
+ 'component', # component object
]
for arg in mandatoryArgs:
try:
@@ -39,7 +41,8 @@ class Video:
'-i', self.videoPath,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
- '-filter:v', 'scale='+str(self.width)+':'+str(self.height),
+ '-filter:v', 'scale=%s:%s' %
+ scale(self.scale, self.width, self.height, str),
'-vcodec', 'rawvideo', '-',
]
@@ -58,7 +61,9 @@ class Video:
while True:
if num in self.finishedFrames:
image = self.finishedFrames.pop(num)
- return Image.frombytes('RGBA', (self.width, self.height), image)
+ return finalizeFrame(
+ self.component, image, self.width, self.height)
+
i, image = self.frameBuffer.get()
self.finishedFrames[i] = image
self.frameBuffer.task_done()
@@ -104,6 +109,10 @@ class Component(__base__.Component):
page.lineEdit_video.textChanged.connect(self.update)
page.pushButton_video.clicked.connect(self.pickVideo)
page.checkBox_loop.stateChanged.connect(self.update)
+ page.checkBox_distort.stateChanged.connect(self.update)
+ page.spinBox_scale.valueChanged.connect(self.update)
+ page.spinBox_x.valueChanged.connect(self.update)
+ page.spinBox_y.valueChanged.connect(self.update)
self.page = page
return page
@@ -111,13 +120,17 @@ class Component(__base__.Component):
def update(self):
self.videoPath = self.page.lineEdit_video.text()
self.loopVideo = self.page.checkBox_loop.isChecked()
+ self.distort = self.page.checkBox_distort.isChecked()
+ self.scale = self.page.spinBox_scale.value()
+ self.xPosition = self.page.spinBox_x.value()
+ self.yPosition = self.page.spinBox_y.value()
self.parent.drawPreview()
super().update()
def previewRender(self, previewWorker):
width = int(previewWorker.core.settings.value('outputWidth'))
height = int(previewWorker.core.settings.value('outputHeight'))
- self.chunkSize = 4*width*height
+ self.updateChunksize(width, height)
frame = self.getPreviewFrame(width, height)
if not frame:
return Image.new("RGBA", (width, height), (0, 0, 0, 0))
@@ -128,12 +141,13 @@ class Component(__base__.Component):
super().preFrameRender(**kwargs)
width = int(self.worker.core.settings.value('outputWidth'))
height = int(self.worker.core.settings.value('outputHeight'))
- self.chunkSize = 4*width*height
+ self.updateChunksize(width, height)
self.video = Video(
ffmpeg=self.parent.core.FFMPEG_BIN, videoPath=self.videoPath,
width=width, height=height, chunkSize=self.chunkSize,
frameRate=int(self.settings.value("outputFrameRate")),
- parent=self.parent, loopVideo=self.loopVideo
+ parent=self.parent, loopVideo=self.loopVideo,
+ component=self, scale=self.scale
)
def frameRender(self, moduleNo, arrayNo, frameNo):
@@ -143,12 +157,20 @@ class Component(__base__.Component):
super().loadPreset(pr, presetName)
self.page.lineEdit_video.setText(pr['video'])
self.page.checkBox_loop.setChecked(pr['loop'])
+ self.page.checkBox_distort.setChecked(pr['distort'])
+ self.page.spinBox_scale.setValue(pr['scale'])
+ self.page.spinBox_x.setValue(pr['x'])
+ self.page.spinBox_y.setValue(pr['y'])
def savePreset(self):
return {
'preset': self.currentPreset,
'video': self.videoPath,
'loop': self.loopVideo,
+ 'distort': self.distort,
+ 'scale': self.scale,
+ 'x': self.xPosition,
+ 'y': self.yPosition,
}
def pickVideo(self):
@@ -165,13 +187,15 @@ class Component(__base__.Component):
def getPreviewFrame(self, width, height):
if not self.videoPath or not os.path.exists(self.videoPath):
return
+
command = [
self.parent.core.FFMPEG_BIN,
'-thread_queue_size', '512',
'-i', self.videoPath,
'-f', 'image2pipe',
'-pix_fmt', 'rgba',
- '-filter:v', 'scale='+str(width)+':'+str(height),
+ '-filter:v', 'scale=%s:%s' %
+ scale(self.scale, width, height, str),
'-vcodec', 'rawvideo', '-',
'-ss', '90',
'-vframes', '1',
@@ -181,7 +205,43 @@ class Component(__base__.Component):
stderr=subprocess.DEVNULL, bufsize=10**8
)
byteFrame = pipe.stdout.read(self.chunkSize)
- image = Image.frombytes('RGBA', (width, height), byteFrame)
+ frame = finalizeFrame(self, byteFrame, width, height)
pipe.stdout.close()
pipe.kill()
- return image
+
+ return frame
+
+ def updateChunksize(self, width, height):
+ if self.scale != 100 and not self.distort:
+ width, height = scale(self.scale, width, height, int)
+ self.chunkSize = 4*width*height
+
+def scale(scale, width, height, returntype=None):
+ width = (float(width) / 100.0) * float(scale)
+ height = (float(height) / 100.0) * float(scale)
+ if returntype == str:
+ return (str(int(width)), str(int(height)))
+ elif returntype == int:
+ return (int(width), int(height))
+ else:
+ return (width, height)
+
+def finalizeFrame(self, imageData, width, height):
+ if self.distort:
+ image = Image.frombytes(
+ 'RGBA',
+ (width, height),
+ imageData)
+ else:
+ image = Image.frombytes(
+ 'RGBA',
+ scale(self.scale, width, height, int),
+ imageData)
+
+ if self.scale != 100 \
+ or self.xPosition != 0 or self.yPosition != 0:
+ frame = Image.new("RGBA", (width, height), (0, 0, 0, 0))
+ frame.paste(image, box=(self.xPosition, self.yPosition))
+ else:
+ frame = image
+ return frame
diff --git a/components/video.ui b/components/video.ui
index aca46b4..fa088fa 100644
--- a/components/video.ui
+++ b/components/video.ui
@@ -206,6 +206,13 @@
</spacer>
</item>
<item>
+ <widget class="QCheckBox" name="checkBox_distort">
+ <property name="text">
+ <string>Distort by scale</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QLabel" name="label">
<property name="text">
<string>Scale</string>