From b28ffb0d1ac3c7f475741bbfa76c24c1aab4371c Mon Sep 17 00:00:00 2001 From: Evan Harris Date: Wed, 19 Jun 2019 05:14:58 -0500 Subject: [PATCH] Added isRangeAllowed() function for transcoded sources This isn't a perfect solution, but it should help increase confidence that the transcoder in use is likely to produce an approximately correct-sized stream. --- .../player/controller/StreamController.java | 6 ++-- .../player/service/TranscodingService.java | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/airsonic-main/src/main/java/org/airsonic/player/controller/StreamController.java b/airsonic-main/src/main/java/org/airsonic/player/controller/StreamController.java index b0070fb7..050791bb 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/controller/StreamController.java +++ b/airsonic-main/src/main/java/org/airsonic/player/controller/StreamController.java @@ -159,13 +159,13 @@ public class StreamController { // Wrangle response length and ranges. // - // Support ranges as long as we're not transcoding; video is always assumed to transcode - if (file.isVideo()) { + // Support ranges as long as we're not transcoding blindly; video is always assumed to transcode + if (file.isVideo() || ! parameters.isRangeAllowed()) { // Use chunked transfer; do not accept range requests response.setStatus(HttpServletResponse.SC_OK); response.setHeader("Accept-Ranges", "none"); } else { - // Not transcoding, partial content permitted because we know the final size + // Partial content permitted because either know or expect to be able to predict the final size long contentLength; // If range was requested, respond in kind range = getRange(request, file.getDurationSeconds(), fileLengthExpected); diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/TranscodingService.java b/airsonic-main/src/main/java/org/airsonic/player/service/TranscodingService.java index f7bf98dc..a98ca944 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/TranscodingService.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/TranscodingService.java @@ -216,6 +216,7 @@ public class TranscodingService { } parameters.setMaxBitRate(maxBitRate); + parameters.setRangeAllowed(isRangeAllowed(parameters)); return parameters; } @@ -487,6 +488,28 @@ public class TranscodingService { return matches != null && matches.length > 0; } + private boolean isRangeAllowed(Parameters parameters) { + Transcoding transcoding = parameters.getTranscoding(); + List steps = Arrays.asList(); + if (transcoding != null) { + steps = Arrays.asList(transcoding.getStep3(), transcoding.getStep2(), transcoding.getStep1()); + } + else if (parameters.isDownsample()) { + steps = Arrays.asList(settingsService.getDownsamplingCommand()); + } + else { + return true; // neither transcoding or downsampling + } + + // Check if last configured step uses the bitrate, if so, range should be pretty safe + for (String step : steps) { + if (step != null) { + return step.contains("%b"); + } + } + return false; + } + /** * Returns the directory in which all transcoders are installed. */ @@ -517,6 +540,7 @@ public class TranscodingService { public static class Parameters { private boolean downsample; + private boolean rangeAllowed; private final MediaFile mediaFile; private final VideoTranscodingSettings videoTranscodingSettings; private Integer maxBitRate; @@ -543,6 +567,14 @@ public class TranscodingService { return transcoding != null; } + public boolean isRangeAllowed() { + return this.rangeAllowed; + } + + public void setRangeAllowed(boolean rangeAllowed) { + this.rangeAllowed = rangeAllowed; + } + public void setTranscoding(Transcoding transcoding) { this.transcoding = transcoding; }