Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions src/containers/hls/lib/playlists.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,16 @@ def measure(playlist)
# small TARGETDURATION and must not be dragged up.
def harmonize_target_duration
playlists = @video_rungs.map(&:playlist) + [@audio.playlist]
target = playlists.map { |pl| required_target_duration(pl) }.max

longest = playlists.map { |pl| required_target_duration(pl) }.max
range = @s::TARGET_DURATION_RANGE
unless range.cover?(target)
raise "EXT-X-TARGETDURATION is #{target}s, outside the allowed range " \
"#{range.min}-#{range.max}s. Adjust TARGET (and HLS_TIME, which is " \
"the min_segment floor that evicts grid points near a break and so " \
"lengthens the adjacent segment)."

# use the range min as a floor (b/c of breaks, there may be shorter segments; that's fine)
# the boundaries logic should prevent this from happening, but just in case,
# do check no segment exceeds the range max; that's not ok (re: RFC 8216)
target = [longest, range.min].max
if target > range.max
raise "EXT-X-TARGETDURATION is #{target}s, above the allowed maximum " \
"#{range.max}s. Lower MAX_SEG, which caps segment length."
end

playlists.each do |pl|
Expand Down
15 changes: 13 additions & 2 deletions src/containers/hls/test/playlists_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,26 @@ def playlists_for(dir, breaks: [])
end
end

it "refuses to write a playlist outside the allowed range" do
it "refuses to write a playlist whose segments exceed the allowed maximum" do
Dir.mktmpdir do |dir|
build_package(dir, video_durations: [14.0, 6.0])
err = _ { playlists_for(dir).write_all }.must_raise RuntimeError
_(err.message).must_match(/outside the allowed range/)
_(err.message).must_match(/above the allowed maximum/)
# and must not leave a master behind
_(File.exist?(File.join(dir, "index.m3u8"))).must_equal false
end
end

it "declares the range floor when every segment is shorter than it" do
Dir.mktmpdir do |dir|
build_package(dir, video_durations: [5.3, 4.9, 3.55],
audio_durations: [5.290667, 4.9, 3.55])
playlists_for(dir).write_all
%w[720p.m3u8 480p.m3u8 audio.m3u8].each do |name|
_(File.read(File.join(dir, name))).must_include "#EXT-X-TARGETDURATION:6"
end
end
end
end

describe "EXT-X-VERSION floor" do
Expand Down
Loading