forked from j62/ctbrec
Improve segment download retry code
This commit is contained in:
parent
6cc8fd9cc2
commit
a33d3045c1
|
@ -41,6 +41,8 @@ import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
public class DashDownload extends AbstractDownload {
|
public class DashDownload extends AbstractDownload {
|
||||||
|
private static final String CONTENT_LENGTH = "Content-Length";
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(DashDownload.class);
|
private static final Logger LOG = LoggerFactory.getLogger(DashDownload.class);
|
||||||
|
|
||||||
private int audioCounter = 0;
|
private int audioCounter = 0;
|
||||||
|
@ -139,16 +141,18 @@ public class DashDownload extends AbstractDownload {
|
||||||
|
|
||||||
private int downloadInitChunksForVideoAndAudio(boolean isVideo, MPDtype mpd, SegmentTemplateType segmentTemplate, RepresentationType representation)
|
private int downloadInitChunksForVideoAndAudio(boolean isVideo, MPDtype mpd, SegmentTemplateType segmentTemplate, RepresentationType representation)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
int loadedFileCount = 0;
|
||||||
if (isVideo && !videoInitLoaded || !isVideo && !audioInitLoaded) {
|
if (isVideo && !videoInitLoaded || !isVideo && !audioInitLoaded) {
|
||||||
String initialization = segmentTemplate.getInitializationAttribute();
|
String initialization = segmentTemplate.getInitializationAttribute();
|
||||||
initialization = initialization.replaceAll("\\$RepresentationID\\$", representation.getId());
|
initialization = initialization.replaceAll("\\$RepresentationID\\$", representation.getId());
|
||||||
URL initUrl = new URL(new URL(mpd.getLocation().get(0)), initialization);
|
URL initUrl = new URL(new URL(mpd.getLocation().get(0)), initialization);
|
||||||
File file = download(downloadDir.toFile().getCanonicalPath(), initUrl, isVideo);
|
File file = download(downloadDir.toFile().getCanonicalPath(), initUrl, isVideo);
|
||||||
setInitState(isVideo, file);
|
if (file != null) {
|
||||||
return 1;
|
setInitState(isVideo, file);
|
||||||
} else {
|
loadedFileCount++;
|
||||||
return 0;
|
}
|
||||||
}
|
}
|
||||||
|
return loadedFileCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setInitState(boolean isVideo, File file) {
|
private void setInitState(boolean isVideo, File file) {
|
||||||
|
@ -177,34 +181,34 @@ public class DashDownload extends AbstractDownload {
|
||||||
.header("Connection", "keep-alive")
|
.header("Connection", "keep-alive")
|
||||||
.build(); // @formatter:on
|
.build(); // @formatter:on
|
||||||
int tries = 1;
|
int tries = 1;
|
||||||
try (Response response = httpClient.execute(request)) {
|
while (tries <= 10) {
|
||||||
InputStream in = response.body().byteStream();
|
try (Response response = httpClient.execute(request)) {
|
||||||
String absFile = url.getFile();
|
if (!response.isSuccessful()) {
|
||||||
String prefix = isVideo ? "video" : "audio";
|
LOG.trace("Loading segment failed, try {}, {} size:{} {}", tries, response.code(), response.headers().values(CONTENT_LENGTH), url);
|
||||||
int c = isVideo ? videoCounter++ : audioCounter++;
|
tries++;
|
||||||
File segmentFile = new File(dir, prefix + '_' + df.format(c) + '_' + new File(absFile).getName());
|
waitSomeTime(tries * 80);
|
||||||
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();
|
|
||||||
}
|
|
||||||
} else {
|
} 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
|
@Override
|
||||||
|
@ -266,16 +270,7 @@ public class DashDownload extends AbstractDownload {
|
||||||
for (PeriodType period : periods) {
|
for (PeriodType period : periods) {
|
||||||
List<AdaptationSetType> videoStreams = new ArrayList<>();
|
List<AdaptationSetType> videoStreams = new ArrayList<>();
|
||||||
List<AdaptationSetType> audioStreams = new ArrayList<>();
|
List<AdaptationSetType> audioStreams = new ArrayList<>();
|
||||||
|
splitAdaptionSets(period.getAdaptationSet(), videoStreams, audioStreams);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadDir.toFile().mkdirs();
|
downloadDir.toFile().mkdirs();
|
||||||
|
|
||||||
|
@ -290,12 +285,23 @@ public class DashDownload extends AbstractDownload {
|
||||||
|
|
||||||
if (downloaded == 0) {
|
if (downloaded == 0) {
|
||||||
LOG.trace("No new segments - Sleeping a bit");
|
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) {
|
private AdaptationSetType chooseBestVideo(List<AdaptationSetType> videoStreams) {
|
||||||
AdaptationSetType best = null;
|
AdaptationSetType best = null;
|
||||||
int maxHeight = config.getSettings().maximumResolution;
|
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
|
* 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
|
* or 404
|
||||||
*/
|
*/
|
||||||
private void waitSomeTime() {
|
private void waitSomeTime(long ms) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(ms);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue