From 4e03a6e966e2cdff494457efa44ae368f86e016b Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Tue, 26 Feb 2013 23:11:42 +0100 Subject: [PATCH] work around GStreamer bug in flacdec for really short files --- morituri/common/checksum.py | 70 +++++++++++++++++++++++-------------- morituri/common/encode.py | 7 ++-- 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/morituri/common/checksum.py b/morituri/common/checksum.py index 68bf524..dea979f 100644 --- a/morituri/common/checksum.py +++ b/morituri/common/checksum.py @@ -101,49 +101,65 @@ class ChecksumTask(log.Loggable, gstreamer.GstPipelineTask): appsink name=sink sync=False emit-signals=True ''' % gstreamer.quoteParse(self._path).encode('utf-8') + def _getSampleLength(self): + # get length in samples of file + sink = self.pipeline.get_by_name('sink') + + self.debug('query duration') + try: + length, qformat = sink.query_duration(gst.FORMAT_DEFAULT) + except gst.QueryError, e: + self.setException(e) + return None + + # wavparse 0.10.14 returns in bytes + if qformat == gst.FORMAT_BYTES: + self.debug('query returned in BYTES format') + length /= 4 + self.debug('total sample length of file: %r', length) + + return length + + def paused(self): sink = self.pipeline.get_by_name('sink') - if self._sampleLength < 0: - self.debug('query duration') - try: - length, qformat = sink.query_duration(gst.FORMAT_DEFAULT) - except gst.QueryError, e: - self.setException(e) - return + length = self._getSampleLength() + if length is None: + return - # wavparse 0.10.14 returns in bytes - if qformat == gst.FORMAT_BYTES: - self.debug('query returned in BYTES format') - length /= 4 - self.debug('total sample length of file: %r', length) + if self._sampleLength < 0: self._sampleLength = length - self._sampleStart self.debug('sampleLength is queried as %d samples', self._sampleLength) else: self.debug('sampleLength is known, and is %d samples' % self._sampleLength) + self._sampleEnd = self._sampleStart + self._sampleLength - 1 self.debug('sampleEnd is sample %d' % self._sampleEnd) self.debug('event') - # the segment end only is respected since -good 0.10.14.1 - event = gst.event_new_seek(1.0, gst.FORMAT_DEFAULT, - gst.SEEK_FLAG_FLUSH, - gst.SEEK_TYPE_SET, self._sampleStart, - gst.SEEK_TYPE_SET, self._sampleEnd + 1) # half-inclusive interval - self.debug('CRCing %r from sector %d to sector %d' % ( - self._path, - self._sampleStart / common.SAMPLES_PER_FRAME, - (self._sampleEnd + 1) / common.SAMPLES_PER_FRAME)) - # FIXME: sending it with sampleEnd set screws up the seek, we don't get - # everything for flac; fixed in recent -good - result = sink.send_event(event) - self.debug('event sent, result %r', result) - if not result: - self.error('Failed to select samples with GStreamer seek event') + if self._sampleStart == 0 and self._sampleEnd + 1 == length: + self.debug('No need to seek, crcing full file') + else: + # the segment end only is respected since -good 0.10.14.1 + event = gst.event_new_seek(1.0, gst.FORMAT_DEFAULT, + gst.SEEK_FLAG_FLUSH, + gst.SEEK_TYPE_SET, self._sampleStart, + gst.SEEK_TYPE_SET, self._sampleEnd + 1) # half-inclusive + self.debug('CRCing %r from frame %d to frame %d (excluded)' % ( + self._path, + self._sampleStart / common.SAMPLES_PER_FRAME, + (self._sampleEnd + 1) / common.SAMPLES_PER_FRAME)) + # FIXME: sending it with sampleEnd set screws up the seek, we + # don't get # everything for flac; fixed in recent -good + result = sink.send_event(event) + self.debug('event sent, result %r', result) + if not result: + self.error('Failed to select samples with GStreamer seek event') sink.connect('new-buffer', self._new_buffer_cb) sink.connect('eos', self._eos_cb) diff --git a/morituri/common/encode.py b/morituri/common/encode.py index 1fbd2a1..4dfdc32 100644 --- a/morituri/common/encode.py +++ b/morituri/common/encode.py @@ -167,6 +167,7 @@ class EncodeTask(ctask.GstPipelineTask): self._inpath = inpath self._outpath = outpath self._taglist = taglist + self._length = 0 # in samples self._level = None self._peakdB = None @@ -299,8 +300,10 @@ class EncodeTask(ctask.GstPipelineTask): if self._duration: self.warning('GStreamer level element did not send messages.') - # workaround for when the file is too short to have volume ? - # self.peak = 0.0 + # workaround for when the file is too short to have volume ? + if self._length == common.SAMPLES_PER_FRAME: + self.warning('only one frame of audio, setting peak to 0.0') + self.peak = 0.0 class TagReadTask(ctask.GstPipelineTask):