Stream Timestamp Fixes (#22912)

* reset timestamps for streams that do not do so when first requested

* update inline comments to be more descriptive
This commit is contained in:
Jason Hunter 2019-04-09 02:24:51 -04:00 committed by Paulus Schoutsen
parent 590eead128
commit 43487aa0d6
2 changed files with 23 additions and 3 deletions

View File

@ -85,7 +85,7 @@ class M3U8Renderer:
for sequence in segments: for sequence in segments:
segment = track.get_segment(sequence) segment = track.get_segment(sequence)
playlist.extend([ playlist.extend([
"#EXTINF:{:.04},".format(float(segment.duration)), "#EXTINF:{:.04f},".format(float(segment.duration)),
"./segment/{}.ts".format(segment.sequence), "./segment/{}.ts".format(segment.sequence),
]) ])

View File

@ -55,10 +55,16 @@ def stream_worker(hass, stream, quit_event):
audio_frame = generate_audio_frame() audio_frame = generate_audio_frame()
outputs = {}
first_packet = True first_packet = True
# Holds the buffers for each stream provider
outputs = {}
# Keep track of the number of segments we've processed
sequence = 1 sequence = 1
# Holds the generated silence that needs to be muxed into the output
audio_packets = {} audio_packets = {}
# The presentation timestamp of the first video packet we recieve
first_pts = 0
# The decoder timestamp of the latest packet we processed
last_dts = None last_dts = None
while not quit_event.is_set(): while not quit_event.is_set():
@ -82,10 +88,18 @@ def stream_worker(hass, stream, quit_event):
continue continue
last_dts = packet.dts last_dts = packet.dts
# Reset timestamps from a 0 time base for this stream
packet.dts -= first_pts
packet.pts -= first_pts
# Reset segment on every keyframe # Reset segment on every keyframe
if packet.is_keyframe: if packet.is_keyframe:
# Save segment to outputs # Calculate the segment duration by multiplying the presentation
# timestamp by the time base, which gets us total seconds.
# By then dividing by the seqence, we can calculate how long
# each segment is, assuming the stream starts from 0.
segment_duration = (packet.pts * packet.time_base) / sequence segment_duration = (packet.pts * packet.time_base) / sequence
# Save segment to outputs
for fmt, buffer in outputs.items(): for fmt, buffer in outputs.items():
buffer.output.close() buffer.output.close()
del audio_packets[buffer.astream] del audio_packets[buffer.astream]
@ -112,6 +126,12 @@ def stream_worker(hass, stream, quit_event):
# First video packet tends to have a weird dts/pts # First video packet tends to have a weird dts/pts
if first_packet: if first_packet:
# If we are attaching to a live stream that does not reset
# timestamps for us, we need to do it ourselves by recording
# the first presentation timestamp and subtracting it from
# subsequent packets we recieve.
if (packet.pts * packet.time_base) > 1:
first_pts = packet.pts
packet.dts = 0 packet.dts = 0
packet.pts = 0 packet.pts = 0
first_packet = False first_packet = False