graceful renderNode crash, code clean-up

This commit is contained in:
tassaron 2017-08-13 15:43:42 -04:00
parent 3f2834529f
commit a233d36ce2
2 changed files with 54 additions and 38 deletions

View File

@ -124,7 +124,7 @@ class Component(Component):
self.tickGrids = {0: self.startingGrid} self.tickGrids = {0: self.startingGrid}
tick = 0 tick = 0
for frameNo in range( for frameNo in range(
self.tickRate, len(self.completeAudioArray), self.sampleSize self.tickRate, self.audioArrayLen, self.sampleSize
): ):
if self.parent.canceled: if self.parent.canceled:
break break
@ -133,7 +133,7 @@ class Component(Component):
self.tickGrids[tick] = self.gridForTick(tick) self.tickGrids[tick] = self.gridForTick(tick)
# update progress bar # update progress bar
progress = int(100*(frameNo/len(self.completeAudioArray))) progress = int(100*(frameNo/self.audioArrayLen))
if progress >= 100: if progress >= 100:
progress = 100 progress = 100
pStr = "Computing evolution: "+str(progress)+'%' pStr = "Computing evolution: "+str(progress)+'%'

View File

@ -32,7 +32,7 @@ log = logging.getLogger("AVP.VideoThread")
class Worker(QtCore.QObject): class Worker(QtCore.QObject):
imageCreated = pyqtSignal(['QImage']) imageCreated = pyqtSignal('QImage')
videoCreated = pyqtSignal() videoCreated = pyqtSignal()
progressBarUpdate = pyqtSignal(int) progressBarUpdate = pyqtSignal(int)
progressBarSetText = pyqtSignal(str) progressBarSetText = pyqtSignal(str)
@ -50,6 +50,7 @@ class Worker(QtCore.QObject):
self.outputFile = outputFile self.outputFile = outputFile
self.inputFile = inputFile self.inputFile = inputFile
self.hertz = 44100
self.sampleSize = 1470 # 44100 / 30 = 1470 self.sampleSize = 1470 # 44100 / 30 = 1470
self.canceled = False self.canceled = False
self.error = False self.error = False
@ -62,30 +63,40 @@ class Worker(QtCore.QObject):
to create subframes & composite them into the final frame. to create subframes & composite them into the final frame.
The resulting frames are collected in the renderQueue The resulting frames are collected in the renderQueue
''' '''
def err():
self.closePipe()
self.cancelExport()
self.error = True
comp._error.emit('A render node failed critically.', str(e))
while not self.stopped: while not self.stopped:
audioI = self.compositeQueue.get() audioI = self.compositeQueue.get()
bgI = int(audioI / self.sampleSize) bgI = int(audioI / self.sampleSize)
frame = None frame = None
for layerNo, comp in enumerate(reversed((self.components))): for layerNo, comp in enumerate(reversed((self.components))):
if layerNo in self.staticComponents: try:
if self.staticComponents[layerNo] is None: if layerNo in self.staticComponents:
# this layer was merged into a following layer if self.staticComponents[layerNo] is None:
continue # this layer was merged into a following layer
# static component continue
if frame is None: # bottom-most layer # static component
frame = self.staticComponents[layerNo] if frame is None: # bottom-most layer
frame = self.staticComponents[layerNo]
else:
frame = Image.alpha_composite(
frame, self.staticComponents[layerNo]
)
else: else:
frame = Image.alpha_composite( # animated component
frame, self.staticComponents[layerNo] if frame is None: # bottom-most layer
) frame = comp.frameRender(bgI)
else: else:
# animated component frame = Image.alpha_composite(
if frame is None: # bottom-most layer frame, comp.frameRender(bgI)
frame = comp.frameRender(bgI) )
else: except Exception as e:
frame = Image.alpha_composite( err()
frame, comp.frameRender(bgI)
)
self.renderQueue.put([audioI, frame]) self.renderQueue.put([audioI, frame])
self.compositeQueue.task_done() self.compositeQueue.task_done()
@ -98,7 +109,7 @@ class Worker(QtCore.QObject):
''' '''
log.debug('Dispatching Frames for Compositing...') log.debug('Dispatching Frames for Compositing...')
for audioI in range(0, len(self.completeAudioArray), self.sampleSize): for audioI in range(0, self.audioArrayLen, self.sampleSize):
self.compositeQueue.put(audioI) self.compositeQueue.put(audioI)
def previewDispatch(self): def previewDispatch(self):
@ -150,17 +161,18 @@ class Worker(QtCore.QObject):
self.cancelExport() self.cancelExport()
return return
self.completeAudioArray, duration = audioFileTraits self.completeAudioArray, duration = audioFileTraits
self.audioArrayLen = len(self.completeAudioArray)
else: else:
duration = getAudioDuration(self.inputFile) duration = getAudioDuration(self.inputFile)
class FakeList: self.completeAudioArray = []
def __len__(self): self.audioArrayLen = int(
return int((duration * 44100) + 44100) - 1470 ((duration * self.hertz) +
self.completeAudioArray = FakeList() self.hertz) - self.sampleSize)
self.progressBarUpdate.emit(0) self.progressBarUpdate.emit(0)
self.progressBarSetText.emit("Starting components...") self.progressBarSetText.emit("Starting components...")
canceledByComponent = False canceledByComponent = False
initText = ", ".join([ initText = ", ".join([
"%s) %s" % (num, str(component)) "%s) %s" % (num, str(component))
for num, component in enumerate(reversed(self.components)) for num, component in enumerate(reversed(self.components))
]) ])
@ -172,6 +184,7 @@ class Worker(QtCore.QObject):
comp.preFrameRender( comp.preFrameRender(
audioFile=self.inputFile, audioFile=self.inputFile,
completeAudioArray=self.completeAudioArray, completeAudioArray=self.completeAudioArray,
audioArrayLen=self.audioArrayLen,
sampleSize=self.sampleSize, sampleSize=self.sampleSize,
progressBarUpdate=self.progressBarUpdate, progressBarUpdate=self.progressBarUpdate,
progressBarSetText=self.progressBarSetText progressBarSetText=self.progressBarSetText
@ -276,7 +289,7 @@ class Worker(QtCore.QObject):
self.progressBarSetText.emit("Exporting video...") self.progressBarSetText.emit("Exporting video...")
if not self.canceled: if not self.canceled:
for audioI in range( for audioI in range(
0, len(self.completeAudioArray), self.sampleSize): 0, self.audioArrayLen, self.sampleSize):
while True: while True:
if audioI in frameBuffer or self.canceled: if audioI in frameBuffer or self.canceled:
# if frame's in buffer, pipe it to ffmpeg # if frame's in buffer, pipe it to ffmpeg
@ -295,7 +308,7 @@ class Worker(QtCore.QObject):
break break
# increase progress bar value # increase progress bar value
completion = (audioI / len(self.completeAudioArray)) * 100 completion = (audioI / self.audioArrayLen) * 100
if progressBarValue + 1 <= completion: if progressBarValue + 1 <= completion:
progressBarValue = numpy.floor(completion) progressBarValue = numpy.floor(completion)
self.progressBarUpdate.emit(progressBarValue) self.progressBarUpdate.emit(progressBarValue)
@ -305,15 +318,7 @@ class Worker(QtCore.QObject):
numpy.seterr(all='print') numpy.seterr(all='print')
try: self.closePipe()
self.out_pipe.stdin.close()
except BrokenPipeError:
log.error('Broken pipe to ffmpeg!')
if self.out_pipe.stderr is not None:
log.error(self.out_pipe.stderr.read())
self.out_pipe.stderr.close()
self.error = True
self.out_pipe.wait()
for comp in reversed(self.components): for comp in reversed(self.components):
comp.postFrameRender() comp.postFrameRender()
@ -342,6 +347,17 @@ class Worker(QtCore.QObject):
self.encoding.emit(False) self.encoding.emit(False)
self.videoCreated.emit() self.videoCreated.emit()
def closePipe(self):
try:
self.out_pipe.stdin.close()
except BrokenPipeError:
log.error('Broken pipe to ffmpeg!')
if self.out_pipe.stderr is not None:
log.error(self.out_pipe.stderr.read())
self.out_pipe.stderr.close()
self.error = True
self.out_pipe.wait()
def cancelExport(self): def cancelExport(self):
self.progressBarUpdate.emit(0) self.progressBarUpdate.emit(0)
self.progressBarSetText.emit('Export Canceled') self.progressBarSetText.emit('Export Canceled')