Skip to content

Commit

Permalink
feat(MSS): Add support for MediaQualityInfo events (#6923)
Browse files Browse the repository at this point in the history
  • Loading branch information
avelad authored Jun 27, 2024
1 parent e67504a commit 767cbed
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 21 deletions.
66 changes: 49 additions & 17 deletions lib/media/quality_observer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ goog.require('shaka.log');
goog.require('shaka.util.ArrayUtils');
goog.require('shaka.util.FakeEvent');
goog.require('shaka.util.FakeEventTarget');
goog.require('shaka.util.ManifestParserUtils');

/**
* Monitors the quality of content being appended to the source buffers and
Expand Down Expand Up @@ -153,29 +154,23 @@ shaka.media.QualityObserver = class extends shaka.util.FakeEventTarget {
/** @override */
poll(positionInSeconds, wasSeeking) {
for (const contentTypeState of this.contentTypeStates_.values()) {
const currentQuality = contentTypeState.currentQuality;
const qualityAtPosition =
shaka.media.QualityObserver.getMediaQualityAtPosition_(
positionInSeconds, contentTypeState);

const differentQualities = qualityAtPosition &&
!shaka.media.QualityObserver.mediaQualitiesAreTheSame_(
contentTypeState.currentQuality, qualityAtPosition);
const differentLabel = qualityAtPosition &&
contentTypeState.currentQuality &&
qualityAtPosition.label &&
contentTypeState.currentQuality.label &&
contentTypeState.currentQuality.label !== qualityAtPosition.label;
const differentLanguage = qualityAtPosition &&
contentTypeState.currentQuality &&
qualityAtPosition.language &&
contentTypeState.currentQuality.language &&
contentTypeState.currentQuality.language !==
qualityAtPosition.language;
const differentRoles = qualityAtPosition &&
contentTypeState.currentQuality &&
qualityAtPosition.roles &&
contentTypeState.currentQuality.roles &&
!shaka.util.ArrayUtils.equal(contentTypeState.currentQuality.roles,
currentQuality, qualityAtPosition);
const differentLabel = qualityAtPosition && currentQuality &&
qualityAtPosition.label && currentQuality.label &&
currentQuality.label !== qualityAtPosition.label;
const differentLanguage = qualityAtPosition && currentQuality &&
qualityAtPosition.language && currentQuality.language &&
currentQuality.language !== qualityAtPosition.language;
const differentRoles = qualityAtPosition && currentQuality &&
qualityAtPosition.roles && currentQuality.roles &&
!shaka.util.ArrayUtils.equal(currentQuality.roles,
qualityAtPosition.roles);

if (differentLabel || differentLanguage || differentRoles) {
Expand Down Expand Up @@ -266,6 +261,43 @@ shaka.media.QualityObserver = class extends shaka.util.FakeEventTarget {
contentTypeState.qualityChangePositions = [];
}
}

/**
* Create a MediaQualityInfo object from a stream object.
*
* @param {!shaka.extern.Stream} stream
* @return {!shaka.extern.MediaQualityInfo}
*/
static createQualityInfo(stream) {
const basicQuality = {
bandwidth: stream.bandwidth || 0,
audioSamplingRate: null,
codecs: stream.codecs,
contentType: stream.type,
frameRate: null,
height: null,
mimeType: stream.mimeType,
channelsCount: null,
pixelAspectRatio: null,
width: null,
label: null,
roles: stream.roles,
language: null,
};
if (stream.type == shaka.util.ManifestParserUtils.ContentType.VIDEO) {
basicQuality.frameRate = stream.frameRate || null;
basicQuality.height = stream.height || null;
basicQuality.pixelAspectRatio = stream.pixelAspectRatio || null;
basicQuality.width = stream.width || null;
}
if (stream.type == shaka.util.ManifestParserUtils.ContentType.AUDIO) {
basicQuality.audioSamplingRate = stream.audioSamplingRate;
basicQuality.channelsCount = stream.channelsCount;
basicQuality.label = stream.label || null;
basicQuality.language = stream.language;
}
return basicQuality;
}
};

/**
Expand Down
7 changes: 5 additions & 2 deletions lib/mss/mss_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ goog.require('shaka.log');
goog.require('shaka.media.InitSegmentReference');
goog.require('shaka.media.ManifestParser');
goog.require('shaka.media.PresentationTimeline');
goog.require('shaka.media.QualityObserver');
goog.require('shaka.media.SegmentIndex');
goog.require('shaka.media.SegmentReference');
goog.require('shaka.mss.ContentProtection');
Expand Down Expand Up @@ -708,12 +709,14 @@ shaka.mss.MssParser = class {
initSegmentData = mp4Generator.initSegment();
this.initSegmentDataByStreamId_.set(stream.id, initSegmentData);
}
const qualityInfo =
shaka.media.QualityObserver.createQualityInfo(stream);
const initSegmentRef = new shaka.media.InitSegmentReference(
() => [],
/* startByte= */ 0,
/* endByte= */ null,
/* mediaQuality= */ null,
/* timescale= */ undefined,
qualityInfo,
stream.mssPrivateData.timescale,
initSegmentData);

const segments = this.createSegments_(initSegmentRef,
Expand Down
4 changes: 2 additions & 2 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ goog.requireType('shaka.media.PresentationTimeline');
* @description Fired when the media quality changes at the playhead.
* That may be caused by an adaptation change or a DASH period transition.
* Separate events are emitted for audio and video contentTypes.
* This is supported for only DASH streams at this time.
* This is supported for only DASH and MSS streams at this time.
* @property {string} type
* 'mediaqualitychanged'
* @property {shaka.extern.MediaQualityInfo} mediaQuality
Expand All @@ -188,7 +188,7 @@ goog.requireType('shaka.media.PresentationTimeline');
* @event shaka.Player.AudioTrackChangedEvent
* @description Fired when the audio track changes at the playhead.
* That may be caused by a user requesting to chang audio tracks.
* This is supported for only DASH streams at this time.
* This is supported for only DASH and MSS streams at this time.
* @property {string} type
* 'audiotrackchanged'
* @property {shaka.extern.MediaQualityInfo} mediaQuality
Expand Down

0 comments on commit 767cbed

Please sign in to comment.