Skip to content

Commit

Permalink
Merge pull request videojs#6 from ldayananda/transmux-before-append-l…
Browse files Browse the repository at this point in the history
…hls-caption-id3-partial-tests

test: caption id3 partial tests
  • Loading branch information
gesinger authored Sep 27, 2018
2 parents 7a57cff + af7d40f commit 78114dc
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 2 deletions.
26 changes: 26 additions & 0 deletions docs/creating-content.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,30 @@ Copy only the first two audio frames, leave out video.
$ ffmpeg -i index0.ts -aframes 2 -vn -acodec copy audio.ts
```

### caption.ts

Copy the first two frames of video out of a ts segment that already includes CEA-608 captions.

`ffmpeg -i index0.ts -vframes 2 -an -vcodec copy caption.ts`

### id3.ts

Copy only the first five frames of video, leave out audio.

`ffmpeg -i index0.ts -vframes 5 -an -vcodec copy smaller.ts`

Create an ID3 tag using [id3taggenerator][apple_streaming_tools]:

`id3taggenerator -text "{\"id\":1, \"data\": \"id3\"}" -o tag.id3`

Create a file `macro.txt` with the following:

`0 id3 tag.id3`

Run [mediafilesegmenter][apple_streaming_tools] with the small video segment and macro file, to produce a new segment with ID3 tags inserted at the specified times.

`mediafilesegmenter -start-segments-with-iframe --target-duration=1 --meta-macro-file=macro.txt -s -A smaller.ts`

### mp4Video.mp4

Copy only the first two video frames, leave out audio.
Expand Down Expand Up @@ -62,3 +86,5 @@ Without specifying fmp4 for hls\_segment\_type, ffmpeg defaults to ts.
```
$ ffmpeg -i input.mp4 -f hls -hls_fmp4_init_filename init.mp4 -hls_segment_type fmp4 out.m3u8
```

[apple_streaming_tools]: https://developer.apple.com/documentation/http_live_streaming/about_apple_s_http_live_streaming_tools
174 changes: 172 additions & 2 deletions test/media-segment-request.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import {
mp4Video,
mp4VideoInit,
muxed as muxedSegment,
muxedString as muxedSegmentString
muxedString as muxedSegmentString,
caption as captionSegment,
captionString as captionSegmentString,
id3String as id3SegmentString,
id3 as id3Segment
} from './test-segments';
// needed for plugin registration
import '../src/videojs-http-streaming';
Expand Down Expand Up @@ -615,7 +619,7 @@ QUnit.test('non-TS segment will get parsed for captions on next segment request
this.standardXHRResponse(initReq, mp4VideoInit());
});

QUnit.test('all callbacks fire for TS segment with partial data', function(assert) {
QUnit.test('callbacks fire for TS segment with partial data', function(assert) {
const progressSpy = sinon.spy();
const trackInfoSpy = sinon.spy();
const timingInfoSpy = sinon.spy();
Expand Down Expand Up @@ -696,3 +700,169 @@ QUnit.test('data callback does not fire if too little partial data', function(as
request.downloadProgress(partialResponse);
this.standardXHRResponse(request, muxedSegment());
});

QUnit.test('caption callback fires for TS segment with partial data', function(assert) {
const progressSpy = sinon.spy();
const captionSpy = sinon.spy();
const dataSpy = sinon.spy();
const done = assert.async();

this.transmuxer = this.createTransmuxer(true);

mediaSegmentRequest({
xhr: this.xhr,
xhrOptions: this.xhrOptions,
decryptionWorker: this.mockDecrypter,
captionParser: this.mockCaptionParser,
segment: {
resolvedUri: 'caption.ts',
transmuxer: this.transmuxer
},
progressFn: progressSpy,
trackInfoFn: this.noop,
timingInfoFn: this.noop,
id3Fn: this.noop,
captionsFn: captionSpy,
dataFn: dataSpy,
doneFn: () => {
assert.strictEqual(progressSpy.callCount, 1, 'saw 1 progress event');
assert.strictEqual(captionSpy.callCount, 1, 'got one caption back');
assert.ok(dataSpy.callCount, 'got data event');
done();
},
handlePartialData: true
});

const request = this.requests.shift();
// Need to take enough of the segment to trigger
// a data and caption event
const partialResponse = captionSegmentString().substring(0, 190000);

// simulates progress event
request.downloadProgress(partialResponse);
this.standardXHRResponse(request, captionSegment());
});

QUnit.test('caption callback does not fire if partial data has no captions', function(assert) {
const progressSpy = sinon.spy();
const captionSpy = sinon.spy();
const dataSpy = sinon.spy();
const done = assert.async();

this.transmuxer = this.createTransmuxer(true);

mediaSegmentRequest({
xhr: this.xhr,
xhrOptions: this.xhrOptions,
decryptionWorker: this.mockDecrypter,
captionParser: this.mockCaptionParser,
segment: {
resolvedUri: 'caption.ts',
transmuxer: this.transmuxer
},
progressFn: progressSpy,
trackInfoFn: this.noop,
timingInfoFn: this.noop,
id3Fn: this.noop,
captionsFn: captionSpy,
dataFn: dataSpy,
doneFn: () => {
assert.strictEqual(progressSpy.callCount, 1, 'saw 1 progress event');
assert.strictEqual(captionSpy.callCount, 0, 'got no caption back');
assert.ok(dataSpy.callCount, 'got data event');
done();
},
handlePartialData: true
});

const request = this.requests.shift();
// Need to take enough of the segment to trigger a data event
const partialResponse = muxedSegmentString().substring(0, 1700);

// simulates progress event
request.downloadProgress(partialResponse);
this.standardXHRResponse(request, muxedSegment());
});

QUnit.test('id3 callback fires for TS segment with partial data', function(assert) {
const progressSpy = sinon.spy();
const id3Spy = sinon.spy();
const dataSpy = sinon.spy();
const done = assert.async();

this.transmuxer = this.createTransmuxer(true);

mediaSegmentRequest({
xhr: this.xhr,
xhrOptions: this.xhrOptions,
decryptionWorker: this.mockDecrypter,
captionParser: this.mockCaptionParser,
segment: {
resolvedUri: 'id3.ts',
transmuxer: this.transmuxer
},
progressFn: progressSpy,
trackInfoFn: this.noop,
timingInfoFn: this.noop,
id3Fn: id3Spy,
captionsFn: this.noop,
dataFn: dataSpy,
doneFn: () => {
assert.strictEqual(progressSpy.callCount, 1, 'saw 1 progress event');
assert.strictEqual(id3Spy.callCount, 1, 'got one id3Frame back');
assert.ok(dataSpy.callCount, 'got data event');
done();
},
handlePartialData: true
});

const request = this.requests.shift();
// Need to take enough of the segment to trigger
// a data and id3Frame event
const partialResponse = id3SegmentString().substring(0, 900);

// simulates progress event
request.downloadProgress(partialResponse);
this.standardXHRResponse(request, id3Segment());
});

QUnit.test('id3 callback does not fire if partial data has no ID3 tags', function(assert) {
const progressSpy = sinon.spy();
const id3Spy = sinon.spy();
const dataSpy = sinon.spy();
const done = assert.async();

this.transmuxer = this.createTransmuxer(true);

mediaSegmentRequest({
xhr: this.xhr,
xhrOptions: this.xhrOptions,
decryptionWorker: this.mockDecrypter,
captionParser: this.mockCaptionParser,
segment: {
resolvedUri: 'id3.ts',
transmuxer: this.transmuxer
},
progressFn: progressSpy,
trackInfoFn: this.noop,
timingInfoFn: this.noop,
id3Fn: id3Spy,
captionsFn: this.noop,
dataFn: dataSpy,
doneFn: () => {
assert.strictEqual(progressSpy.callCount, 1, 'saw 1 progress event');
assert.strictEqual(id3Spy.callCount, 0, 'got no id3Frames back');
assert.ok(dataSpy.callCount, 'got data event');
done();
},
handlePartialData: true
});

const request = this.requests.shift();
// Need to take enough of the segment to trigger a data event
const partialResponse = muxedSegmentString().substring(0, 1700);

// simulates progress event
request.downloadProgress(partialResponse);
this.standardXHRResponse(request, muxedSegment());
});
Binary file added test/segments/caption.ts
Binary file not shown.
Binary file added test/segments/id3.ts
Binary file not shown.

0 comments on commit 78114dc

Please sign in to comment.