Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support switching codecs if supported by the browser #841

Merged
merged 28 commits into from
Jun 25, 2020

Conversation

brandonocasey
Copy link
Contributor

If the browser supports sourceBuffer.changeType stop excluding playlists that have a different codec than the initial selected rendition. If we switch to a playlist that has a different codec than the current rendition change codecs using changeType

index.html Outdated Show resolved Hide resolved
@brandonocasey brandonocasey force-pushed the feat/codec-switching branch from 555f42d to 2a88916 Compare May 8, 2020 15:39
@@ -589,15 +599,15 @@ export class MasterPlaylistController extends videojs.EventTarget {
*
* @private
*/
smoothQualityChange_() {
const media = this.selectPlaylist();
smoothQualityChange_(media = this.selectPlaylist()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allows us to easily change the media that is currently being used

}
return;
}
this.tryToCreateSourceBuffers_();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We won't throw an error that can be caught by this anymore

@@ -290,7 +290,8 @@ const transmuxAndNotify = ({
if (probeResult) {
trackInfoFn(segment, {
hasAudio: probeResult.hasAudio,
hasVideo: probeResult.hasVideo
hasVideo: probeResult.hasVideo,
isMuxed
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When messing around with renditions in safari I realized that we don't pass isMuxed up for ts segments. This is a problem because ts segments can contain video/audio and be appended to a "videoBuffer" that has both codecs.

@@ -450,6 +490,12 @@ export default class SegmentLoader extends videojs.EventTarget {
}
});

this.on('trackinfo', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since startingMedia_ is reset on media change now, we have to check if we have enough to append after trackinfo, which sets startingMedia_

src/rendition-mixin.js Outdated Show resolved Hide resolved
// When we have track info, determine what media types this loader is dealing with.
// Guard against cases where we're not getting track info at all until we are
// certain that all streams will provide it.
if (typeof this.startingMedia_ === 'undefined' && (trackInfo.hasAudio || trackInfo.hasVideo)) {
if ((trackInfo.hasVideo || trackInfo.hasAudio) && !shallowEqual(this.startingMedia_, trackInfo)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the trackinfo actually changed fire a new trackinfo event.

@@ -3,7 +3,7 @@
<Period>
<AdaptationSet mimeType="video/mp4" contentType="video" subsegmentAlignment="true" subsegmentStartsWithSAP="1" par="16:9">
<SegmentTemplate duration="120" timescale="30" media="$RepresentationID$/$RepresentationID$_$Number$.m4v" startNumber="1" initialization="$RepresentationID$/$RepresentationID$_0.m4v"/>
<Representation id="video_1" codecs="avc1.foo.bar" bandwidth="507246" width="320" height="180" frameRate="30" sar="1:1" scanType="progressive"/>
<Representation id="video_1" codecs="avc1.4d400d" bandwidth="507246" width="320" height="180" frameRate="30" sar="1:1" scanType="progressive"/>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These have to be real codecs now, as we don't blacklist on codec change.

@brandonocasey brandonocasey force-pushed the feat/codec-switching branch from da1e642 to d14d7f2 Compare May 18, 2020 19:00
@gkatsev gkatsev added this to the 2.1 milestone May 21, 2020
Copy link
Member

@gkatsev gkatsev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't understand the code that much still but LGTM.
One thing to note and not sure if it's a Safari thing or what, but I was test with the "Advanced Bipbop - Fmp4 hevc, demuxed" source and it cannot play continuously on safari.


mediaTypes.AUDIO.tracks[groupId].enabled = true;
mediaTypes.AUDIO.onTrackChanged();
if (audioGroup) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

@gesinger gesinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will review the tests soon, but wanted to get the comments in for the non tests portion.

src/master-playlist-controller.js Outdated Show resolved Hide resolved
// Therefore we must always wait for the segment loader's track info.
if (!mainStartingMedia || (hasAltAudio && !this.audioSegmentLoader_.startingMedia_)) {
// no codecs, no playback.
if (!codecs.audio && !codecs.video) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this blacklist playlists if content hasn't been downloaded when we try to create the source buffers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will see if I can add a check to make sure we have startingMedia at the top of this function, so that won't be possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

src/master-playlist-controller.js Outdated Show resolved Hide resolved
src/source-updater.js Show resolved Hide resolved
* The codec string to change type with on the source buffer.
*/
changeType(type, codec) {
if (!this.canChangeType()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this condition be reached by our code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we always check for this.canChangeType before trying to call changeType. Do you think we should remove this line or throw an Error here?

src/source-updater.js Outdated Show resolved Hide resolved
src/source-updater.js Outdated Show resolved Hide resolved
src/master-playlist-controller.js Outdated Show resolved Hide resolved
return;
if (changed) {
this.logger_('trackinfo update', trackInfo);
this.trigger('trackinfo');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worth renaming to newtrackinfo for clarity?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps: trackinfo and trackinfochange. I don't know if we should other than to prevent breaking people that may have been using the event.

src/master-playlist-controller.js Outdated Show resolved Hide resolved
@gkatsev gkatsev changed the base branch from master to main June 19, 2020 16:50
@brandonocasey brandonocasey force-pushed the feat/codec-switching branch 2 times, most recently from c148bca to 2657730 Compare June 22, 2020 18:13
@@ -553,7 +553,7 @@ export class MasterPlaylistController extends videojs.EventTarget {
const codecs = this.getCodecsOrExclude_();

// no codecs means that the playlist was excluded
if (!codecs || !this.sourceUpdater_.canChangeType()) {
if (!codecs) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not want to check canChangeType here, as we do it in getCodecsOrExclude and blacklist if the main part of the codec was changed, but sourcebuffers can not actually changetype.

@@ -1350,6 +1346,9 @@ export class MasterPlaylistController extends videojs.EventTarget {
if (usingAudioLoader && unsupportedAudio && this.media().attributes.AUDIO) {
const audioGroup = this.media().attributes.AUDIO;

this.mediaTypes_.AUDIO.activePlaylistLoader.pause();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is important because if we wait for the masterPlaylistLoader to mediachange and then call abort then we will already have appended unsupported codecs.

gkatsev
gkatsev previously approved these changes Jun 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants