Skip to content

Commit

Permalink
Fix: stop cutting the last few milliseconds of audio
Browse files Browse the repository at this point in the history
  • Loading branch information
FrancescoCeruti committed Feb 18, 2024
1 parent 715c965 commit 16c41c4
Showing 1 changed file with 60 additions and 45 deletions.
105 changes: 60 additions & 45 deletions lisp/plugins/gst_backend/gst_media.py
Expand Up @@ -140,7 +140,6 @@ def seek(self, position):
self.sought.emit(self, position)

def loop_release(self):
# if self.state == MediaState.Playing or self.state == MediaState.Paused:
self.__loop = 0

def element(self, class_name):
Expand All @@ -163,41 +162,54 @@ def update_properties(self, properties):
def __reset_media(self):
self.__loop = self.loop

def __seek(self, position, flush=True):
if self.state == MediaState.Playing or self.state == MediaState.Paused:
max_position = self.duration
if 0 < self.stop_time < self.duration:
max_position = self.stop_time

if position < max_position:
# Query segment info for the playback rate
query = Gst.Query.new_segment(Gst.Format.TIME)
self.__pipeline.query(query)
rate = Gst.Query.parse_segment(query)[0]

# Check stop_position value
stop_type = Gst.SeekType.NONE
if self.stop_time > 0:
stop_type = Gst.SeekType.SET

# Seek the pipeline
flags = Gst.SeekFlags.SEGMENT | Gst.SeekFlags.TRICKMODE
if flush:
flags |= Gst.SeekFlags.FLUSH

result = self.__pipeline.seek(
rate if rate > 0 else 1,
Gst.Format.TIME,
flags,
Gst.SeekType.SET,
position * Gst.MSECOND,
stop_type,
self.stop_time * Gst.MSECOND,
)
def __segment_stop_position(self):
if 0 < self.stop_time < self.duration:
return self.stop_time

return result
return self.duration

return False
def __seek(self, position, flush=True):
if (
self.state not in (MediaState.Playing, MediaState.Paused)
or position > self.__segment_stop_position()
):
return False

# Query segment info for the playback rate
query = Gst.Query.new_segment(Gst.Format.TIME)
self.__pipeline.query(query)
rate = Gst.Query.parse_segment(query)[0]

# Check if we need to set an early stop position
if self.stop_time > 0:
stop_type = Gst.SeekType.SET
else:
stop_type = Gst.SeekType.NONE

# Decide which SeekFlags we want to use
flags = Gst.SeekFlags.TRICKMODE

# We want to receive SEGMENT_DONE messages, allowing seamless loops,
# except for the "last" loop, were we want to receive a normal EOS
# to ensure that all pipeline buffers have been processed.
if self.__loop != 0:
flags |= Gst.SeekFlags.SEGMENT

# While seeking, we typically want to flush any buffered data. However,
# there are exceptions, such as during seamless looping, where flushing is undesirable.
if flush:
flags |= Gst.SeekFlags.FLUSH

# Seek the pipeline
return self.__pipeline.seek(
rate if rate > 0 else 1,
Gst.Format.TIME,
flags,
Gst.SeekType.SET,
position * Gst.MSECOND,
stop_type,
self.stop_time * Gst.MSECOND,
)

def __on_loops_changed(self, loops):
self.__loop = loops
Expand Down Expand Up @@ -266,24 +278,27 @@ def __init_pipeline(self):

def __on_message(self, bus, message):
if message.src == self.__pipeline:
if message.type in (
Gst.MessageType.SEGMENT_DONE,
Gst.MessageType.EOS,
):
if message.type == Gst.MessageType.SEGMENT_DONE:
if self.__loop != 0:
# If we still have loops to do then seek to start
self.__loop -= 1
self.__seek(self.start_time, flush=False)
else:
# Otherwise go in READY state
self.__pipeline.set_state(Gst.State.READY)
self.__pipeline.get_state(Gst.SECOND)
# We reached loop 0 earlier (e.g. due to a loop-release).
# We cannot stop the pipeline yet, likely there's still data in the buffers,
# to "force" an EOS event we seek to the end of the stream, without flushing.
self.__seek(self.__segment_stop_position(), flush=False)

elif message.type == Gst.MessageType.EOS:
self.__pipeline.set_state(Gst.State.READY)
self.__pipeline.get_state(Gst.SECOND)

for element in self.elements:
element.eos()

for element in self.elements:
element.eos()
self.__reset_media()
self.eos.emit(self)

self.__reset_media()
self.eos.emit(self)
elif message.type == Gst.MessageType.CLOCK_LOST:
self.__pipeline.set_state(Gst.State.PAUSED)
self.__pipeline.set_state(Gst.State.PLAYING)
Expand Down

0 comments on commit 16c41c4

Please sign in to comment.