dbeb3eac by David LaPalomento

Write out audio metadata frequently. Fixes #169.

If the source was switched among variant playlists that have different audio sampling rates and the initial audio metadata tag skipped, audio would dissapear. Instead, emit an audio meta tag at least once per second so that the decoder can get back on track after a change. Fix typo that caused audio DTS not to be written out properly.
1 parent 5662e402
......@@ -23,6 +23,7 @@ window.videojs.Hls.AacStream = function() {
pts_offset, // :int
state, // :uint
pes_length, // :int
lastMetaPts,
adtsProtectionAbsent, // :Boolean
adtsObjectType, // :int
......@@ -43,6 +44,11 @@ window.videojs.Hls.AacStream = function() {
// on the first invocation, capture the starting PTS value
pts_offset = pts;
// keep track of the last time a metadata tag was written out
// set the initial value so metadata will be generated before any
// payload data
lastMetaPts = pts - 1000;
// on subsequent invocations, calculate the PTS based on the starting offset
this.setNextTimeStamp = function(pts, pes_size, dataAligned) {
next_pts = pts - pts_offset;
......@@ -157,7 +163,11 @@ window.videojs.Hls.AacStream = function() {
newExtraData = (adtsObjectType << 11) |
(adtsSampleingIndex << 7) |
(adtsChanelConfig << 3);
if (newExtraData !== extraData) {
// write out metadata tags every 1 second so that the decoder
// is re-initialized quickly after seeking into a different
// audio configuration
if (newExtraData !== extraData || next_pts - lastMetaPts >= 1000) {
aacFrame = new FlvTag(FlvTag.METADATA_TAG);
aacFrame.pts = next_pts;
aacFrame.dts = next_pts;
......@@ -173,16 +183,19 @@ window.videojs.Hls.AacStream = function() {
extraData = newExtraData;
aacFrame = new FlvTag(FlvTag.AUDIO_TAG, true);
aacFrame.pts = aacFrame.dts;
// For audio, DTS is always the same as PTS. We want to set the DTS
// however so we can compare with video DTS to determine approximate
// packet order
aacFrame.pts = next_pts;
aacFrame.dts = aacFrame.pts;
aacFrame.view.setUint16(aacFrame.position, newExtraData);
aacFrame.position += 2;
aacFrame.length = Math.max(aacFrame.length, aacFrame.position);
this.tags.push(aacFrame);
lastMetaPts = next_pts;
}
// Skip the checksum if there is one
......
......@@ -341,14 +341,22 @@
currentPts = tag.pts;
// generic flv headers
ok(type === 8 || type === 9 || type === 18,
'the type field specifies audio, video or script');
switch (type) {
case 8: ok(true, 'the type is audio');
break;
case 9: ok(true, 'the type is video');
break;
case 18: ok(true, 'the type is script');
break;
default: ok(false, 'the type (' + type + ') is unrecognized');
}
byte = (tag.view.getUint32(1) & 0xFFFFFF00) >>> 8;
equal(tag.bytes.byteLength - 11 - 4, byte, 'the size field is correct');
byte = tag.view.getUint32(5) & 0xFFFFFF00;
ok(byte >= lastTime, 'the timestamp for the tag is greater than zero');
ok(byte >= lastTime,
'timestamp is increasing. last pts: ' + lastTime + ' this pts: ' + byte);
lastTime = byte;
// tag type-specific headers
......