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

fix: Fix Opus support in Safari #6607

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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