|
|
@@ -36,12 +36,19 @@ function HlsSegmentObject(seq, segment, meta, stream) {
|
|
|
function checknext(reader) {
|
|
|
var state = reader.readState;
|
|
|
var index = reader.index;
|
|
|
- if (!state.active || state.fetching || !index)
|
|
|
+ if (!state.active || state.fetching || state.nextSeq === -1 || !index)
|
|
|
return;
|
|
|
|
|
|
var seq = state.nextSeq;
|
|
|
var segment = index.getSegment(seq);
|
|
|
|
|
|
+ // check if we need to stop
|
|
|
+ if (reader.stopDate) {
|
|
|
+ var seqDate = index.dateForSeqNo(seq);
|
|
|
+ if (seqDate > reader.stopDate)
|
|
|
+ return reader.push(null);
|
|
|
+ }
|
|
|
+
|
|
|
if (segment) {
|
|
|
state.fetching = fetchfrom(reader, seq, segment, function(err, object) {
|
|
|
state.fetching = null;
|
|
|
@@ -121,6 +128,10 @@ function HlsStreamReader(src, options) {
|
|
|
this.fullStream = !!options.fullStream;
|
|
|
this.noData = !!options.noData;
|
|
|
|
|
|
+ // dates are inclusive
|
|
|
+ this.startDate = options.startDate;
|
|
|
+ this.stopDate = options.stopDate;
|
|
|
+
|
|
|
this.index = null;
|
|
|
this.readState = {
|
|
|
nextSeq:-1,
|
|
|
@@ -136,10 +147,34 @@ function HlsStreamReader(src, options) {
|
|
|
return self.index.target_duration / 2;
|
|
|
}
|
|
|
|
|
|
+ function initialSeqNo() {
|
|
|
+ var index = self.index;
|
|
|
+
|
|
|
+ if (self.startDate) {
|
|
|
+ var count = index.segments.length;
|
|
|
+ var time = 0, startTime = self.startDate.getTime();
|
|
|
+
|
|
|
+ for (var i=0; i<count; i++) {
|
|
|
+ var segment = index.segments[i];
|
|
|
+ if (segment.program_time) {
|
|
|
+ time = segment.program_time.getTime();
|
|
|
+ } else if (time === 0)
|
|
|
+ throw new Error('bad index, missing #EXT-X-PROGRAM-DATE-TIME');
|
|
|
+
|
|
|
+ time += 1000 * segment.duration;
|
|
|
+
|
|
|
+ if (time >= startTime)
|
|
|
+ return index.first_seq_no + i;
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return index.startSeqNo(self.fullStream);
|
|
|
+ }
|
|
|
+
|
|
|
function updatecheck(updated) {
|
|
|
if (updated) {
|
|
|
if (self.readState.nextSeq===-1)
|
|
|
- self.readState.nextSeq = self.index.startSeqNo(self.fullStream);
|
|
|
+ self.readState.nextSeq = initialSeqNo();
|
|
|
else if (self.readState.nextSeq < self.index.startSeqNo(true)) {
|
|
|
debug('skipping '+(self.index.startSeqNo(true)-self.readState.nextSeq)+' invalidated segments');
|
|
|
self.readState.nextSeq = self.index.startSeqNo(true);
|
|
|
@@ -165,7 +200,7 @@ function HlsStreamReader(src, options) {
|
|
|
}
|
|
|
checknext(self);
|
|
|
|
|
|
- if (!self.index.ended) {
|
|
|
+ if (self.index && !self.index.ended && self.readable) {
|
|
|
var updateInterval = getUpdateInterval(updated);
|
|
|
debug('scheduling index refresh', updateInterval);
|
|
|
setTimeout(updateindex, Math.max(1, updateInterval)*1000);
|
|
|
@@ -173,6 +208,7 @@ function HlsStreamReader(src, options) {
|
|
|
}
|
|
|
|
|
|
function updateindex() {
|
|
|
+ if (!self.readable) return;
|
|
|
var stream = uristream(url.format(self.url), { timeout:30*1000 });
|
|
|
stream.on('meta', function(meta) {
|
|
|
if (meta.mime !== 'application/vnd.apple.mpegurl' &&
|
|
|
@@ -201,9 +237,10 @@ function HlsStreamReader(src, options) {
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
- updateindex();
|
|
|
|
|
|
Readable.call(this, extend(options, {objectMode:true, highWaterMark:options.highWaterMark || 0}));
|
|
|
+
|
|
|
+ updateindex();
|
|
|
}
|
|
|
util.inherits(HlsStreamReader, Readable);
|
|
|
|