diff --git a/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java index eb5a3011..607cdca3 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java @@ -1,52 +1,10 @@ package ctbrec.recorder.download.hls; -import static ctbrec.io.HttpConstants.*; -import static ctbrec.recorder.download.StreamSource.*; -import static java.nio.charset.StandardCharsets.*; -import static java.nio.file.StandardOpenOption.*; - -import java.io.BufferedWriter; -import java.io.ByteArrayInputStream; -import java.io.EOFException; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.nio.file.Files; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.time.Duration; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorCompletionService; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.stream.Collectors; - -import javax.xml.bind.JAXBException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.iheartradio.m3u8.Encoding; -import com.iheartradio.m3u8.Format; -import com.iheartradio.m3u8.ParseException; -import com.iheartradio.m3u8.ParsingMode; -import com.iheartradio.m3u8.PlaylistException; -import com.iheartradio.m3u8.PlaylistParser; +import com.iheartradio.m3u8.*; import com.iheartradio.m3u8.data.EncryptionData; import com.iheartradio.m3u8.data.MediaPlaylist; import com.iheartradio.m3u8.data.Playlist; import com.iheartradio.m3u8.data.TrackData; - import ctbrec.Config; import ctbrec.Model; import ctbrec.Model.State; @@ -64,6 +22,32 @@ import ctbrec.sites.Site; import okhttp3.Request; import okhttp3.Request.Builder; import okhttp3.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.JAXBException; +import java.io.*; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.nio.file.Files; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import static ctbrec.io.HttpConstants.*; +import static ctbrec.recorder.download.StreamSource.UNKNOWN; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.nio.file.StandardOpenOption.*; public abstract class AbstractHlsDownload extends AbstractDownload { @@ -85,7 +69,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { private Instant beforeLastPlaylistRequest= Instant.EPOCH; private int consecutivePlaylistTimeouts = 0; private int consecutivePlaylistErrors = 0; - private Instant lastSegmentDownload = Instant.MAX; + private Instant lastSegmentDownload = Instant.MIN; private int selectedResolution = UNKNOWN; private final List recordingEvents = new LinkedList<>(); @@ -99,6 +83,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { public void init(Config config, Model model, Instant startTime, ExecutorService executorService) throws IOException { super.init(config, model, startTime, executorService); segmentDownloadService = new ExecutorCompletionService<>(downloadExecutor); + lastSegmentDownload = Instant.now(); } protected abstract OutputStream getSegmentOutputStream(Segment segment) throws IOException; @@ -245,7 +230,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { List filteredStreamSources = streamSources.stream() .filter(src -> src.height == 0 || src.height == UNKNOWN || minRes <= src.height) .filter(src -> src.height == 0 || src.height == UNKNOWN || maxRes >= src.height) - .collect(Collectors.toList()); + .toList(); if (filteredStreamSources.isEmpty()) { throw new ExecutionException(new NoStreamFoundException("No stream left in playlist")); diff --git a/common/src/main/java/ctbrec/recorder/download/hls/SegmentDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/SegmentDownload.java index 578245e0..c2fc8497 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/SegmentDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/SegmentDownload.java @@ -13,6 +13,7 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.HashMap; +import java.util.Objects; import java.util.Optional; import java.util.concurrent.Callable; @@ -34,12 +35,12 @@ import okhttp3.Response; public class SegmentDownload implements Callable { private static final Logger LOG = LoggerFactory.getLogger(SegmentDownload.class); - private URL url; - private HttpClient client; - private SegmentPlaylist playlist; - private Segment segment; - private Model model; - private OutputStream out; + private final URL url; + private final HttpClient client; + private final SegmentPlaylist playlist; + private final Segment segment; + private final Model model; + private final OutputStream out; public SegmentDownload(Model model, SegmentPlaylist playlist, Segment segment, HttpClient client, OutputStream out) throws MalformedURLException { this.model = model; @@ -52,7 +53,7 @@ public class SegmentDownload implements Callable { @Override public SegmentDownload call() { - for (int tries = 1; tries <= 3 && !Thread.currentThread().isInterrupted(); tries++) { + for (int tries = 1; tries <= 3 && !Thread.currentThread().isInterrupted(); tries++) { // NOSONAR Request request = createRequest(); try (Response response = client.execute(request)) { handleResponse(response); @@ -73,20 +74,19 @@ public class SegmentDownload implements Callable { return this; } - private boolean handleResponse(Response response) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IOException { + private void handleResponse(Response response) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, IOException { if (response.isSuccessful()) { - InputStream in = response.body().byteStream(); + InputStream in = Objects.requireNonNull(response.body(), "HTTP response body is null").byteStream(); if (playlist.encrypted) { in = new Crypto(playlist.encryptionKeyUrl, client).wrap(in); } byte[] b = new byte[1024 * 100]; - int length = -1; + int length; while ((length = in.read(b)) >= 0 && !Thread.currentThread().isInterrupted()) { out.write(b, 0, length); BandwidthMeter.add(length); } out.flush(); - return true; } else { throw new HttpException(response.code(), response.message()); } @@ -105,4 +105,4 @@ public class SegmentDownload implements Callable { public Segment getSegment() { return segment; } -} \ No newline at end of file +}