forked from j62/ctbrec
1
0
Fork 0

Improve segment download retry code

This commit is contained in:
0xboobface 2019-12-25 19:23:53 +01:00
parent 6cc8fd9cc2
commit a33d3045c1
1 changed files with 47 additions and 41 deletions

View File

@ -41,6 +41,8 @@ import okhttp3.Request;
import okhttp3.Response;
public class DashDownload extends AbstractDownload {
private static final String CONTENT_LENGTH = "Content-Length";
private static final Logger LOG = LoggerFactory.getLogger(DashDownload.class);
private int audioCounter = 0;
@ -139,16 +141,18 @@ public class DashDownload extends AbstractDownload {
private int downloadInitChunksForVideoAndAudio(boolean isVideo, MPDtype mpd, SegmentTemplateType segmentTemplate, RepresentationType representation)
throws IOException {
int loadedFileCount = 0;
if (isVideo && !videoInitLoaded || !isVideo && !audioInitLoaded) {
String initialization = segmentTemplate.getInitializationAttribute();
initialization = initialization.replaceAll("\\$RepresentationID\\$", representation.getId());
URL initUrl = new URL(new URL(mpd.getLocation().get(0)), initialization);
File file = download(downloadDir.toFile().getCanonicalPath(), initUrl, isVideo);
setInitState(isVideo, file);
return 1;
} else {
return 0;
if (file != null) {
setInitState(isVideo, file);
loadedFileCount++;
}
}
return loadedFileCount;
}
private void setInitState(boolean isVideo, File file) {
@ -177,34 +181,34 @@ public class DashDownload extends AbstractDownload {
.header("Connection", "keep-alive")
.build(); // @formatter:on
int tries = 1;
try (Response response = httpClient.execute(request)) {
InputStream in = response.body().byteStream();
String absFile = url.getFile();
String prefix = isVideo ? "video" : "audio";
int c = isVideo ? videoCounter++ : audioCounter++;
File segmentFile = new File(dir, prefix + '_' + df.format(c) + '_' + new File(absFile).getName());
while (tries <= 10) {
if (!segmentFile.exists() || segmentFile.length() == 0) {
if (tries == 10) {
LOG.debug("Loading segment, try {}, {} {} {}", tries, response.code(), response.headers().values("Content-Length"), url);
} else {
LOG.trace("Loading segment, try {}, {} {} {}", tries, response.code(), response.headers().values("Content-Length"), url);
}
try (FileOutputStream out = new FileOutputStream(segmentFile)) {
byte[] b = new byte[1024];
int len = -1;
while ((len = in.read(b)) >= 0) {
out.write(b, 0, len);
}
out.flush();
}
while (tries <= 10) {
try (Response response = httpClient.execute(request)) {
if (!response.isSuccessful()) {
LOG.trace("Loading segment failed, try {}, {} size:{} {}", tries, response.code(), response.headers().values(CONTENT_LENGTH), url);
tries++;
waitSomeTime(tries * 80);
} else {
break;
InputStream in = response.body().byteStream();
String absFile = url.getFile();
String prefix = isVideo ? "video" : "audio";
int c = isVideo ? videoCounter++ : audioCounter++;
File segmentFile = new File(dir, prefix + '_' + df.format(c) + '_' + new File(absFile).getName());
if (!segmentFile.exists() || segmentFile.length() == 0) {
try (FileOutputStream out = new FileOutputStream(segmentFile)) {
byte[] b = new byte[1024];
int len = -1;
while ((len = in.read(b)) >= 0) {
out.write(b, 0, len);
}
out.flush();
}
}
return segmentFile;
}
tries++;
}
return segmentFile;
}
LOG.warn("Loading segment finally failed after {} tries {}", --tries, url);
return null;
}
@Override
@ -266,16 +270,7 @@ public class DashDownload extends AbstractDownload {
for (PeriodType period : periods) {
List<AdaptationSetType> videoStreams = new ArrayList<>();
List<AdaptationSetType> audioStreams = new ArrayList<>();
List<AdaptationSetType> adaptationSets = period.getAdaptationSet();
for (AdaptationSetType adaptationSet : adaptationSets) {
String mimeType = adaptationSet.getMimeType();
if (mimeType.equalsIgnoreCase("video/mp4")) {
videoStreams.add(adaptationSet);
} else if (mimeType.equalsIgnoreCase("audio/mp4")) {
audioStreams.add(adaptationSet);
}
}
splitAdaptionSets(period.getAdaptationSet(), videoStreams, audioStreams);
downloadDir.toFile().mkdirs();
@ -290,12 +285,23 @@ public class DashDownload extends AbstractDownload {
if (downloaded == 0) {
LOG.trace("No new segments - Sleeping a bit");
waitSomeTime();
waitSomeTime(1000);
}
}
}
}
private void splitAdaptionSets(List<AdaptationSetType> adaptationSets, List<AdaptationSetType> videoStreams, List<AdaptationSetType> audioStreams) {
for (AdaptationSetType adaptationSet : adaptationSets) {
String mimeType = adaptationSet.getMimeType();
if (mimeType.equalsIgnoreCase("video/mp4")) {
videoStreams.add(adaptationSet);
} else if (mimeType.equalsIgnoreCase("audio/mp4")) {
audioStreams.add(adaptationSet);
}
}
}
private AdaptationSetType chooseBestVideo(List<AdaptationSetType> videoStreams) {
AdaptationSetType best = null;
int maxHeight = config.getSettings().maximumResolution;
@ -373,9 +379,9 @@ public class DashDownload extends AbstractDownload {
* Causes the current thread to sleep for a short amount of time. This is used to slow down retries, if something is wrong with the playlist. E.g. HTTP 403
* or 404
*/
private void waitSomeTime() {
private void waitSomeTime(long ms) {
try {
Thread.sleep(1000);
Thread.sleep(ms);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}