Skip to content

Commit

Permalink
feat: TS parser improvements (shaka-project#4612)
Browse files Browse the repository at this point in the history
  • Loading branch information
avelad authored Oct 25, 2022
1 parent 9531b07 commit 5157b44
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 6 deletions.
68 changes: 62 additions & 6 deletions lib/util/ts_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ shaka.util.TsParser = class {
/** @private {boolean} */
this.pmtParsed_ = false;

/** @private {?number} */
this.videoStartTime_ = null;

/** @private {?number} */
this.videoPid_ = null;

Expand All @@ -32,6 +35,9 @@ shaka.util.TsParser = class {
/** @private {!Array.<Uint8Array>} */
this.videoData_ = [];

/** @private {?number} */
this.audioStartTime_ = null;

/** @private {?number} */
this.audioPid_ = null;

Expand All @@ -55,6 +61,7 @@ shaka.util.TsParser = class {
* @return {!shaka.util.TsParser}
*/
parse(data) {
const timescale = shaka.util.TsParser.Timescale_;
const packetLength = shaka.util.TsParser.PacketLength_;

// A TS fragment should contain at least 3 TS packets, a PAT, a PMT, and
Expand Down Expand Up @@ -135,12 +142,28 @@ shaka.util.TsParser = class {
this.pmtParsed_ = true;
break;
}
case this.videoPid_:
this.videoData_.push(data.subarray(offset, start + packetLength));
case this.videoPid_: {
const videoData = data.subarray(offset, start + packetLength);
if (this.videoStartTime_ == null) {
const pes = this.parsePES(videoData);
if (pes && pes.pts != null) {
this.videoStartTime_ = pes.pts / timescale;
}
}
this.videoData_.push(videoData);
break;
case this.audioPid_:
this.audioData_.push(data.subarray(offset, start + packetLength));
}
case this.audioPid_: {
const audioData = data.subarray(offset, start + packetLength);
if (this.audioStartTime_ == null) {
const pes = this.parsePES(audioData);
if (pes && pes.pts != null) {
this.audioStartTime_ = pes.pts / timescale;
}
}
this.audioData_.push(audioData);
break;
}
case this.id3Pid_:
this.id3Data_.push(data.subarray(offset, start + packetLength));
break;
Expand Down Expand Up @@ -180,8 +203,8 @@ shaka.util.TsParser = class {
audio: -1,
video: -1,
id3: -1,
audioCodec: 'aac',
videoCodec: 'avc',
audioCodec: '',
videoCodec: '',
};
const sectionLength = ((data[offset + 1] & 0x0f) << 8) | data[offset + 2];
const tableEnd = offset + 3 + sectionLength - 4;
Expand All @@ -201,6 +224,7 @@ shaka.util.TsParser = class {
case 0x0f:
if (result.audio === -1) {
result.audio = pid;
result.audioCodec = 'aac';
}
break;
// Packetized metadata (ID3)
Expand All @@ -216,6 +240,7 @@ shaka.util.TsParser = class {
case 0x1b:
if (result.video === -1) {
result.video = pid;
result.videoCodec = 'avc';
}
break;
// ISO/IEC 11172-3 (MPEG-1 audio)
Expand Down Expand Up @@ -332,6 +357,30 @@ shaka.util.TsParser = class {
return metadata;
}

/**
* Return the start time for the audio and video
*
* @return {{audio: ?number, video: ?number}}
*/
getStartTime() {
return {
audio: this.audioStartTime_,
video: this.videoStartTime_,
};
}

/**
* Return the audio and video codecs
*
* @return {{audio: ?string, video: ?string}}
*/
getCodecs() {
return {
audio: this.audioCodec_,
video: this.videoCodec_,
};
}

/**
* Check if the passed data corresponds to an MPEG2-TS
*
Expand Down Expand Up @@ -385,6 +434,13 @@ shaka.util.TsParser = class {
shaka.util.TsParser.PacketLength_ = 188;


/**
* @const {number}
* @private
*/
shaka.util.TsParser.Timescale_ = 90000;


/**
* @typedef {{
* audio: number,
Expand Down
22 changes: 22 additions & 0 deletions test/util/ts_parser_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,26 @@ describe('TsParser', () => {
expect(metadata).toBeTruthy();
expect(metadata.length).toBe(2);
});

it('get the start time from a TS segment', async () => {
const responses = await Promise.all([
Util.fetch('/base/test/test/assets/id3-metadata.ts'),
]);
const tsSegment = BufferUtils.toUint8(responses[0]);
const starttime = new shaka.util.TsParser().parse(tsSegment)
.getStartTime();
expect(starttime.audio).toBeCloseTo(90019.586, 3);
expect(starttime.video).toBe(null);
});

it('get the codecs from a TS segment', async () => {
const responses = await Promise.all([
Util.fetch('/base/test/test/assets/id3-metadata.ts'),
]);
const tsSegment = BufferUtils.toUint8(responses[0]);
const codecs = new shaka.util.TsParser().parse(tsSegment)
.getCodecs();
expect(codecs.audio).toBe('aac');
expect(codecs.video).toBe('');
});
});

0 comments on commit 5157b44

Please sign in to comment.