Skip to content

Commit e47eff9

Browse files
committed
Allow the preload functionality to work even when the setting cacheInitSegments is false
1 parent 968dafa commit e47eff9

3 files changed

Lines changed: 70 additions & 65 deletions

File tree

src/streaming/PreBufferSink.js

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ function PreBufferSink(onAppendedCallback) {
4545
let instance,
4646
logger,
4747
outstandingInit;
48+
49+
let initSegments = [];
4850
let chunks = [];
4951
let onAppended = onAppendedCallback;
5052

@@ -54,18 +56,23 @@ function PreBufferSink(onAppendedCallback) {
5456

5557
function reset() {
5658
chunks = [];
59+
initSegments = [];
5760
outstandingInit = null;
5861
onAppended = null;
5962
}
6063

6164
function append(chunk) {
62-
if (chunk.segmentType !== 'InitializationSegment') { //Init segments are stored in the initCache.
65+
if (chunk.segmentType !== 'InitializationSegment') {
6366
chunks.push(chunk);
6467
chunks.sort(function (a, b) {
6568
return a.start - b.start;
6669
});
6770
outstandingInit = null;
68-
} else {//We need to hold an init chunk for when a corresponding media segment is being downloaded when the discharge happens.
71+
} else {
72+
if (!initSegments.includes(chunk)) {
73+
initSegments.push(chunk);
74+
}
75+
//We might be in the process of downloading a media segment, this would be its init pair.
6976
outstandingInit = chunk;
7077
}
7178

@@ -79,7 +86,7 @@ function PreBufferSink(onAppendedCallback) {
7986
}
8087

8188
function remove(start, end) {
82-
chunks = chunks.filter(a => !((isNaN(end) || a.start < end) && (isNaN(start) || a.end > start))); //The opposite of the getChunks predicate.
89+
chunks = chunks.filter(a => !((isNaN(end) || a.start < end) && (isNaN(start) || a.end > start)));
8390
return Promise.resolve();
8491
}
8592

@@ -132,26 +139,32 @@ function PreBufferSink(onAppendedCallback) {
132139
* Because a chunk cannot be split, this returns the full chunk if any part of its time lies in the requested range.
133140
* Chunks are removed from the buffer when they are discharged.
134141
* @function PreBufferSink#discharge
135-
* @param {?Number} start The start time from which to discharge from the buffer. If NaN, it is regarded as unbounded.
136-
* @param {?Number} end The end time from which to discharge from the buffer. If NaN, it is regarded as unbounded.
137142
* @returns {Array} The set of chunks from the buffer within the time ranges.
138143
*/
139-
function discharge(start, end) {
140-
const result = getChunksAt(start, end);
144+
function discharge() {
145+
const result = chunks;
146+
let lastInit = null;
147+
148+
for (let i = 0; i < result.length; i++) {
149+
if (!lastInit || result[i].representation.id != lastInit.representation.id) {
150+
lastInit = initSegments.find(init => init.representation.id === result[i].representation.id);
151+
if (lastInit) {
152+
result.splice(i, 0, lastInit);
153+
i++;
154+
}
155+
}
156+
}
157+
141158
if (outstandingInit) {
142159
result.push(outstandingInit);
143-
outstandingInit = null;
144160
}
145161

146-
remove(start, end);
162+
chunks = [];
163+
initSegments = [];
147164

148165
return result;
149166
}
150167

151-
function getChunksAt(start, end) {
152-
return chunks.filter(a => ((isNaN(end) || a.start < end) && (isNaN(start) || a.end > start)));
153-
}
154-
155168
function waitForUpdateEnd(callback) {
156169
callback();
157170
}

src/streaming/controllers/BufferController.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -277,19 +277,8 @@ function BufferController(config) {
277277
//A list of fragments to supress bytesAppended events for. This makes transferring from a prebuffer to a sourcebuffer silent.
278278
dischargeFragments = [];
279279
let chunks = dischargeBuffer.discharge();
280-
let lastInit = null;
281280
for (let j = 0; j < chunks.length; j++) {
282281
const chunk = chunks[j];
283-
if (chunk.segmentType !== HTTPRequest.INIT_SEGMENT_TYPE) {
284-
const initChunk = initCache.extract(chunk.streamId, chunk.representation.id);
285-
if (initChunk) {
286-
if (lastInit !== initChunk) {
287-
dischargeFragments.push(initChunk);
288-
sourceBufferSink.append(initChunk);
289-
lastInit = initChunk;
290-
}
291-
}
292-
}
293282
dischargeFragments.push(chunk);
294283
sourceBufferSink.append(chunk);
295284
}

test/unit/test/streaming/streaming.controllers.PreBufferSink.js

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@ import {expect} from 'chai';
44
const context = {};
55

66
describe('PreBufferSink', function () {
7-
function makeChunk(start, end, data) {
7+
function makeInit(representation) {
8+
const init = {
9+
data: 'init segment',
10+
segmentType: 'InitializationSegment',
11+
representation: representation || { id: 'representation1' }
12+
};
13+
14+
return init;
15+
}
16+
17+
function makeChunk(start, end, representation) {
818
const chunk = {
919
start: start || 0,
1020
end: end || 4,
11-
data: data || 'chickens',
12-
segmentType: 'data'
21+
data: 'chickens',
22+
segmentType: 'data',
23+
representation: representation || { id: 'representation1' }
1324
};
1425

1526
return chunk;
@@ -34,15 +45,19 @@ describe('PreBufferSink', function () {
3445
expect(chunk.data).to.equal('chickens');
3546
});
3647

37-
it('should take a series of chunks and return them in chronological order on discharge', function () {
48+
it('should take a series of chunks and corresponding inits and return them in chronological order on discharge', function () {
49+
const representation2 = { id: 'representation2' };
50+
sink.append(makeInit());
3851
sink.append(makeChunk(4, 8));
39-
sink.append(makeChunk(12, 16));
40-
sink.append(makeChunk(16, 20));
52+
sink.append(makeInit(representation2));
53+
sink.append(makeChunk(12, 16, representation2));
54+
sink.append(makeChunk(16, 20, representation2));
55+
sink.append(makeInit());
4156
sink.append(makeChunk(0, 4));
4257
sink.append(makeChunk(8, 12));
4358

4459
const chunkList = sink.discharge();
45-
expect(chunkList).to.have.length(5);
60+
expect(chunkList).to.have.length(7);
4661

4762
let lastStart, lastEnd;
4863
for (let i = 0; i < chunkList.length; i++) {
@@ -54,65 +69,52 @@ describe('PreBufferSink', function () {
5469
lastStart = chunk.start;
5570
lastEnd = chunk.end;
5671
}
72+
73+
expect(chunkList[0].segmentType).to.equal('InitializationSegment');
74+
expect(chunkList[0].representation.id).to.equal('representation1');
75+
76+
expect(chunkList[4].segmentType).to.equal('InitializationSegment');
77+
expect(chunkList[4].representation.id).to.equal('representation2');
5778
});
5879

5980
it('should return an init segment if it is the last segment that is passed in', function () {
60-
const chunk = makeChunk();
61-
chunk.segmentType = 'InitializationSegment';
62-
63-
sink.append(chunk);
81+
sink.append(makeInit());
82+
sink.append(makeChunk());
83+
sink.append(makeInit({ id: 'representation2' }));
6484

6585
const chunkList = sink.discharge();
66-
expect(chunkList).to.have.length(1);
86+
expect(chunkList).to.have.length(3);
6787
});
6888

69-
it('should not return an init segment if other media segments are passed in afterwards', function () {
70-
const chunk = makeChunk();
71-
chunk.segmentType = 'InitializationSegment';
89+
it('should not return an init segment last if other media segments are passed in afterwards', function () {
90+
const init = makeInit();
7291

73-
sink.append(chunk);
92+
sink.append(init);
7493
sink.append(makeChunk(0, 4));
7594

7695
const chunkList = sink.discharge();
77-
expect(chunkList).to.have.length(1);
78-
expect(chunkList[0].segmentType).to.equal('data');
79-
});
80-
81-
it('should discharge only over a specified timerange', function () {
82-
sink.append(makeChunk(0, 4));
83-
sink.append(makeChunk(4, 8));
84-
sink.append(makeChunk(8, 12));
85-
sink.append(makeChunk(12, 16));
86-
sink.append(makeChunk(16, 20));
87-
88-
const chunkList = sink.discharge(0, 12);
89-
expect(chunkList).to.have.length(3);
90-
91-
expect(chunkList[0].start).to.equal(0);
92-
expect(chunkList[1].start).to.equal(4);
93-
expect(chunkList[2].start).to.equal(8);
96+
expect(chunkList).to.have.length(2);
97+
expect(chunkList[0].segmentType).to.equal('InitializationSegment');
98+
expect(chunkList[1].segmentType).to.equal('data');
9499
});
95100

96101
it('should remove chunks after they have been discharged', function () {
102+
sink.append(makeInit());
97103
sink.append(makeChunk(0, 4));
98104
sink.append(makeChunk(4, 8));
99105
sink.append(makeChunk(8, 12));
100106
sink.append(makeChunk(12, 16));
101107
sink.append(makeChunk(16, 20));
102108

103-
const chunkList = sink.discharge(0, 12);
104-
expect(chunkList).to.have.length(3);
105-
106-
const emptyChunkList = sink.discharge(0, 12);
107-
expect(emptyChunkList).to.have.length(0);
108-
109-
const remainingChunkList = sink.discharge(12, 20);
110-
expect(remainingChunkList).to.have.length(2);
109+
const chunkList = sink.discharge();
110+
expect(chunkList).to.have.length(6);
111+
expect(sink.getAllBufferRanges().length).to.equal(0);
111112
});
112113
});
113114

114115
describe('getAllBufferRanges', function () {
115116
it('should report the buffer ranges of the chunks that have been added', function () {
117+
sink.append(makeInit());
116118
sink.append(makeChunk(0, 4));
117119
sink.append(makeChunk(4, 8));
118120
sink.append(makeChunk(12, 16));
@@ -131,6 +133,7 @@ describe('PreBufferSink', function () {
131133

132134
describe('Reset', function () {
133135
it('should have no segments left after it has reset', function () {
136+
sink.append(makeInit());
134137
sink.append(makeChunk(0, 4));
135138
sink.append(makeChunk(4, 8));
136139
sink.append(makeChunk(8, 12));

0 commit comments

Comments
 (0)