Skip to content

Commit

Permalink
fix: Fix Opus support in Safari (#6607)
Browse files Browse the repository at this point in the history
In Safari:

```
> MediaSource.isTypeSupported('audio/mp4;codecs=Opus')
< true
> MediaSource.isTypeSupported('audio/mp4;codecs=opus')
< false
> MediaSource.isTypeSupported('audio/webm; codecs="Opus"')
< false
> MediaSource.isTypeSupported('audio/webm; codecs="opus"')
< true
```
  • Loading branch information
avelad committed May 14, 2024
1 parent c5af5c7 commit 0a4c9d1
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 17 deletions.
2 changes: 1 addition & 1 deletion lib/media/media_source_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ shaka.media.MediaSourceEngine = class {
if (contentType == ContentType.VIDEO) {
codecs = StreamUtils.getCorrectVideoCodecs(codecs);
} else if (contentType == ContentType.AUDIO) {
codecs = StreamUtils.getCorrectAudioCodecs(codecs);
codecs = StreamUtils.getCorrectAudioCodecs(codecs, mimeType);
}
const extendedMimeType = MimeUtils.getExtendedType(
stream, mimeType, codecs);
Expand Down
6 changes: 5 additions & 1 deletion lib/transmuxer/ts_transmuxer.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,17 @@ shaka.transmuxer.TsTransmuxer = class {
convertCodecs(contentType, mimeType) {
if (this.isTsContainer_(mimeType)) {
const ContentType = shaka.util.ManifestParserUtils.ContentType;
const StreamUtils = shaka.util.StreamUtils;
// The replace it's necessary because Firefox(the only browser that
// supports MP3 in MP4) only support the MP3 codec with the mp3 string.
// MediaSource.isTypeSupported('audio/mp4; codecs="mp4a.40.34"') -> false
// MediaSource.isTypeSupported('audio/mp4; codecs="mp3"') -> true
const codecs = shaka.util.MimeUtils.getCodecs(mimeType)
.replace('mp4a.40.34', 'mp3').split(',')
.map(shaka.util.StreamUtils.getCorrectVideoCodecs).join(',');
.map((codecs) => {
return StreamUtils.getCorrectAudioCodecs(codecs, 'audio/mp4');
})
.map(StreamUtils.getCorrectVideoCodecs).join(',');
if (contentType == ContentType.AUDIO) {
return `audio/mp4; codecs="${codecs}"`;
}
Expand Down
35 changes: 24 additions & 11 deletions lib/util/stream_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,8 @@ shaka.util.StreamUtils = class {
videoCodecs = StreamUtils.getCorrectVideoCodecs(videoCodecs);
let audioCodecs = ManifestParserUtils.guessCodecs(
ContentType.AUDIO, allCodecs);
audioCodecs = StreamUtils.getCorrectAudioCodecs(audioCodecs);
audioCodecs = StreamUtils.getCorrectAudioCodecs(
audioCodecs, video.mimeType);

const audioFullType = MimeUtils.getFullOrConvertedType(
video.mimeType, audioCodecs, ContentType.AUDIO);
Expand Down Expand Up @@ -475,7 +476,8 @@ shaka.util.StreamUtils = class {
}

if (audio) {
const codecs = StreamUtils.getCorrectAudioCodecs(audio.codecs);
const codecs = StreamUtils.getCorrectAudioCodecs(
audio.codecs, audio.mimeType);
const fullType = MimeUtils.getFullOrConvertedType(
audio.mimeType, codecs, ContentType.AUDIO);

Expand Down Expand Up @@ -764,17 +766,18 @@ shaka.util.StreamUtils = class {
// We ignore the multiplexed audio when there is normal audio also.
if (videoCodecs.includes(',') && !audio) {
const allCodecs = videoCodecs.split(',');
const baseMimeType = MimeUtils.getBasicType(fullMimeType);

videoCodecs = ManifestParserUtils.guessCodecs(
ContentType.VIDEO, allCodecs);

let audioCodecs = ManifestParserUtils.guessCodecs(
ContentType.AUDIO, allCodecs);
audioCodecs = StreamUtils.getCorrectAudioCodecs(audioCodecs);
audioCodecs = StreamUtils.getCorrectAudioCodecs(
audioCodecs, baseMimeType);

const audioFullType = MimeUtils.getFullOrConvertedType(
MimeUtils.getBasicType(fullMimeType), audioCodecs,
ContentType.AUDIO);
baseMimeType, audioCodecs, ContentType.AUDIO);

audioConfigs.push({
contentType: audioFullType,
Expand Down Expand Up @@ -825,10 +828,11 @@ shaka.util.StreamUtils = class {
}
if (audio) {
for (const fullMimeType of audio.fullMimeTypes) {
const codecs = StreamUtils.getCorrectAudioCodecs(MimeUtils.getCodecs(
fullMimeType));
const baseMimeType = MimeUtils.getBasicType(fullMimeType);
const codecs = StreamUtils.getCorrectAudioCodecs(
MimeUtils.getCodecs(fullMimeType), baseMimeType);
const fullType = MimeUtils.getFullOrConvertedType(
MimeUtils.getBasicType(fullMimeType), codecs, ContentType.AUDIO);
baseMimeType, codecs, ContentType.AUDIO);

// AudioConfiguration
audioConfigs.push({
Expand Down Expand Up @@ -991,9 +995,10 @@ shaka.util.StreamUtils = class {
* Generates the correct audio codec for MediaDecodingConfiguration and
* for MediaSource.isTypeSupported.
* @param {string} codecs
* @param {string} mimeType
* @return {string}
*/
static getCorrectAudioCodecs(codecs) {
static getCorrectAudioCodecs(codecs, mimeType) {
// According to RFC 6381 section 3.3, 'fLaC' is actually the correct
// codec string. We still need to map it to 'flac', as some browsers
// currently don't support 'fLaC', while 'flac' is supported by most
Expand All @@ -1008,8 +1013,16 @@ shaka.util.StreamUtils = class {
}

// The same is true for 'Opus'.
if (codecs === 'Opus') {
return 'opus';
if (codecs.toLowerCase() === 'opus') {
if (!shaka.util.Platform.isSafari()) {
return 'opus';
} else {
if (shaka.util.MimeUtils.getContainerType(mimeType) == 'mp4') {
return 'Opus';
} else {
return 'opus';
}
}
}

return codecs;
Expand Down
11 changes: 7 additions & 4 deletions test/test/util/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -319,15 +319,17 @@ shaka.test.Util = class {
*/
static async isTypeSupported(mimetype, width, height) {
const MimeUtils = shaka.util.MimeUtils;
const ContentType = shaka.util.ManifestParserUtils.ContentType;
const StreamUtils = shaka.util.StreamUtils;

/** @type {!MediaDecodingConfiguration} */
const mediaDecodingConfig = {
type: 'media-source',
};
if (mimetype.startsWith('audio')) {
const baseMimeType = MimeUtils.getBasicType(mimetype);
const codecs = StreamUtils.getCorrectAudioCodecs(
MimeUtils.getCodecs(mimetype));
MimeUtils.getCodecs(mimetype), baseMimeType);
if (codecs == 'ac-3' && shaka.util.Platform.isTizen()) {
// AC3 is flaky in some Tizen devices, so we need omit it for now.
return false;
Expand All @@ -341,18 +343,19 @@ shaka.test.Util = class {
// https://bugs.chromium.org/p/chromium/issues/detail?id=1450313
return false;
}
const baseMimeType = MimeUtils.getBasicType(mimetype);
// AudioConfiguration
mediaDecodingConfig.audio = {
contentType: MimeUtils.getFullType(baseMimeType, codecs),
contentType: MimeUtils.getFullOrConvertedType(
baseMimeType, codecs, ContentType.AUDIO),
};
} else {
const codecs = StreamUtils.getCorrectVideoCodecs(
MimeUtils.getCodecs(mimetype));
const baseMimeType = MimeUtils.getBasicType(mimetype);
// VideoConfiguration
mediaDecodingConfig.video = {
contentType: MimeUtils.getFullType(baseMimeType, codecs),
contentType: MimeUtils.getFullOrConvertedType(
baseMimeType, codecs, ContentType.VIDEO),

// NOTE: Some decoders strictly check the width and height fields and
// won't decode smaller than 64x64. So if we don't have this info (as
Expand Down

0 comments on commit 0a4c9d1

Please sign in to comment.