Add channel count information for HLS audio tracks

Adding the count of channels, as a new field for tracks and streams.
Used for HLS audio tracks.

Resolves #826.

Change-Id: I1448b4a8cfaf6dd798670bb2f0f3981d6c7e40c3
This commit is contained in:
Michelle Zhuo
2017-06-20 18:24:38 -07:00
parent 678390b92a
commit f09999aa80
12 changed files with 86 additions and 27 deletions
+4 -1
View File
@@ -302,7 +302,8 @@ shakaExtern.GetSegmentReferenceFunction;
* primary: boolean,
* trickModeVideo: ?shakaExtern.Stream,
* containsEmsgBoxes: boolean,
* roles: !Array.<string>
* roles: !Array.<string>,
* channelsCount: ?number
* }}
*
* @description
@@ -393,6 +394,8 @@ shakaExtern.GetSegmentReferenceFunction;
* @property {!Array.<string>} roles
* The roles of the stream as they appear on the manifest,
* e.g. 'main', 'caption', or 'commentary'.
* @property {?number} channelsCount
* The channel count information for the audio stream.
* @exportDoc
*/
shakaExtern.Stream;
+5 -2
View File
@@ -142,7 +142,8 @@ shakaExtern.Stats;
* primary: boolean,
* roles: !Array.<string>,
* videoId: ?number,
* audioId: ?number
* audioId: ?number,
* channelsCount: ?number
* }}
*
* @description
@@ -182,7 +183,7 @@ shakaExtern.Stats;
* The audio/video codecs string provided in the manifest, if present.
* @property {?string} audioCodec
* The audio codecs string provided in the manifest, if present.
* @property {?string} videoCodec
* @property {?string} videoCodec
* The video codecs string provided in the manifest, if present.
* @property {boolean} primary
* True indicates that this in the primary language for the content.
@@ -196,6 +197,8 @@ shakaExtern.Stats;
* (only for variant tracks) The video stream id.
* @property {?number} audioId
* (only for variant tracks) The audio stream id.
* @property {?number} channelsCount
* The count of the audio track channels.
* @exportDoc
*/
shakaExtern.Track;
+2 -1
View File
@@ -1127,7 +1127,8 @@ shaka.dash.DashParser.prototype.parseRepresentation_ = function(
primary: isPrimary,
trickModeVideo: null,
containsEmsgBoxes: context.representation.containsEmsgBoxes,
roles: roles
roles: roles,
channelsCount: null
};
};
+31 -7
View File
@@ -508,17 +508,39 @@ shaka.hls.HlsParser.prototype.createStreamInfoFromMediaTag_ =
// FORCED, INSTREAM-ID, CHARACTERISTICS, CHANNELS?
// Attribute descriptions:
// https://tools.ietf.org/html/draft-pantos-http-live-streaming-20#section-4.3.4.1
var channelsAttribute = tag.getAttributeValue('CHANNELS');
var channelsCount = type == 'audio' ?
this.getChannelsCount_(channelsAttribute) : null;
var uri = HlsParser.getRequiredAttributeValue_(tag, 'URI');
var primary = !!defaultAttr || !!autoselectAttr;
return this.createStreamInfo_(uri, allCodecs, type, timeOffset, language,
primary, label).then(function(streamInfo) {
return this.createStreamInfo_(uri, allCodecs, type, timeOffset,
language, primary, label, channelsCount).then(function(streamInfo) {
this.mediaTagsToStreamInfosMap_[tag.id] = streamInfo;
return streamInfo;
}.bind(this));
};
/**
* Get the channels count information for HLS audio track.
* The channels value is a string that specifies an ordered, "/" separated list
* of parameters. If the type is audio, the first parameter will be a decimal
* integer, as the number of independent, simultaneous audio channels.
* No other channels parameters are currently defined.
*
* @param {?string} channels
*
* @return {?number} channelcount
* @private
*/
shaka.hls.HlsParser.prototype.getChannelsCount_ = function(channels) {
if (!channels) return null;
var channelscountstring = channels.split('/')[0];
var count = parseInt(channelscountstring, 10);
return count;
};
/**
* Parse EXT-X-STREAM-INF media tag into a Stream object.
*
@@ -537,7 +559,7 @@ shaka.hls.HlsParser.prototype.createStreamInfoFromVariantTag_ =
var uri = shaka.hls.HlsParser.getRequiredAttributeValue_(tag, 'URI');
return this.createStreamInfo_(uri, allCodecs, type, timeOffset,
/* language */ 'und', /* primary */ false,
/* label */ null);
/* label */ null, /* channelcount */ null);
};
@@ -549,12 +571,13 @@ shaka.hls.HlsParser.prototype.createStreamInfoFromVariantTag_ =
* @param {!string} language
* @param {boolean} primary
* @param {?string} label
* @param {?number} channelsCount
* @return {!Promise.<shaka.hls.HlsParser.StreamInfo>}
* @throws shaka.util.Error
* @private
*/
shaka.hls.HlsParser.prototype.createStreamInfo_ =
function(uri, allCodecs, type, timeOffset, language, primary, label) {
shaka.hls.HlsParser.prototype.createStreamInfo_ = function(uri, allCodecs,
type, timeOffset, language, primary, label, channelsCount) {
var Utils = shaka.hls.Utils;
var ContentType = shaka.util.ManifestParserUtils.ContentType;
var HlsParser = shaka.hls.HlsParser;
@@ -676,7 +699,8 @@ shaka.hls.HlsParser.prototype.createStreamInfo_ =
width: undefined,
height: undefined,
bandwidth: undefined,
roles: []
roles: [],
channelsCount: channelsCount
};
this.streamsToIndexMap_[stream.id] = segmentIndex;
+2 -1
View File
@@ -257,7 +257,8 @@ shaka.offline.OfflineUtils.createStream_ = function(streamDb) {
trickModeVideo: null,
// TODO(modmaker): Store offline?
containsEmsgBoxes: false,
roles: []
roles: [],
channelsCount: null
};
};
+2 -1
View File
@@ -1577,7 +1577,8 @@ shaka.Player.prototype.addTextTrack = function(
primary: false,
trickModeVideo: null,
containsEmsgBoxes: false,
roles: []
roles: [],
channelsCount: null
};
// Add the stream to the loading list to ensure it isn't switched to while it
+4 -2
View File
@@ -270,7 +270,8 @@ shaka.util.StreamUtils.getVariantTracks =
primary: variant.primary,
roles: roles,
videoId: variant.video ? variant.video.id : null,
audioId: variant.audio ? variant.audio.id : null
audioId: variant.audio ? variant.audio.id : null,
channelsCount: variant.audio ? variant.audio.channelsCount : null
};
});
@@ -300,7 +301,8 @@ shaka.util.StreamUtils.getTextTracks = function(period, activeStreamId) {
audioCodec: null,
videoCodec: null,
primary: stream.primary,
roles: stream.roles
roles: stream.roles,
channelsCount: null
};
});
};
+2 -1
View File
@@ -136,7 +136,7 @@ describe('HlsParser', function() {
'RESOLUTION=960x540,FRAME-RATE=60,AUDIO="aud1"\n',
'test://video\n',
'#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aud1",LANGUAGE="eng",',
'URI="test://audio"\n'
'CHANNELS="2",URI="test://audio"\n'
].join('');
var media = [
@@ -166,6 +166,7 @@ describe('HlsParser', function() {
.anyInitSegment()
.presentationTimeOffset(0)
.mime('audio/mp4', 'mp4a')
.channelsCount(2)
.build();
testHlsParser(master, media, manifest, done);
+2 -1
View File
@@ -262,7 +262,8 @@ describe('OfflineUtils', function() {
primary: streamDb.primary,
trickModeVideo: null,
containsEmsgBoxes: false,
roles: []
roles: [],
channelsCount: null
};
expect(stream).toEqual(expectedStream);
+4 -2
View File
@@ -107,7 +107,8 @@ describe('Storage', function() {
codecs: 'vorbis',
primary: true,
segments: [],
roles: []
roles: [],
channelsCount: null
}
]
}],
@@ -147,7 +148,8 @@ describe('Storage', function() {
videoCodec: 'avc1.4d401f',
roles: [],
videoId: 0,
audioId: 1
audioId: 1,
channelsCount: null
}
];
Promise
+14 -7
View File
@@ -899,7 +899,8 @@ describe('Player', function() {
primary: false,
roles: [],
videoId: 4,
audioId: 1
audioId: 1,
channelsCount: null
},
{
id: 2,
@@ -919,7 +920,8 @@ describe('Player', function() {
primary: false,
roles: [],
videoId: 5,
audioId: 1
audioId: 1,
channelsCount: null
},
{
id: 3,
@@ -939,7 +941,8 @@ describe('Player', function() {
primary: false,
roles: [],
videoId: 4,
audioId: 2
audioId: 2,
channelsCount: null
},
{
id: 4,
@@ -959,7 +962,8 @@ describe('Player', function() {
primary: false,
roles: [],
videoId: 5,
audioId: 2
audioId: 2,
channelsCount: null
},
{
id: 5,
@@ -979,7 +983,8 @@ describe('Player', function() {
primary: false,
roles: [],
videoId: 5,
audioId: 8
audioId: 8,
channelsCount: null
}
];
@@ -996,7 +1001,8 @@ describe('Player', function() {
audioCodec: null,
videoCodec: null,
primary: false,
roles: []
roles: [],
channelsCount: null
},
{
id: 7,
@@ -1010,7 +1016,8 @@ describe('Player', function() {
audioCodec: null,
videoCodec: null,
primary: false,
roles: []
roles: [],
channelsCount: null
}
];
});
+14 -1
View File
@@ -473,7 +473,8 @@ shaka.test.ManifestGenerator.prototype.createStream_ =
primary: false,
trickModeVideo: null,
containsEmsgBoxes: false,
roles: []
roles: [],
channelsCount: null
};
stream.createSegmentIndex.and.callFake(
function() { return Promise.resolve(); });
@@ -805,4 +806,16 @@ shaka.test.ManifestGenerator.prototype.currentStream_ = function() {
'Must add at least one stream.');
return this.lastStreamAdded_;
};
/**
* Sets the count of the channels of the current stream.
* @param {number} count
* @return {!shaka.test.ManifestGenerator}
*/
shaka.test.ManifestGenerator.prototype.channelsCount = function(count) {
var stream = this.currentStream_();
stream.channelsCount = count;
return this;
};
// }}}