Bug 147309 - [Cocoa] canPlayType('audio/mpeg; codecs="mp3"') returns ""
Summary: [Cocoa] canPlayType('audio/mpeg; codecs="mp3"') returns ""
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Media (show other bugs)
Version: 528+ (Nightly build)
Hardware: Mac OS X 10.10
: P2 Normal
Assignee: Eric Carlson
URL: http://jsbin.com/vubukodepo/edit?js,o...
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2015-07-26 12:12 PDT by Sajid Anwar
Modified: 2020-09-18 02:25 PDT (History)
10 users (show)

See Also:


Attachments
Patch (5.91 KB, patch)
2020-09-17 11:09 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff
Patch for landing (5.80 KB, patch)
2020-09-17 12:41 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff
Patch for landing (5.79 KB, patch)
2020-09-17 13:54 PDT, Eric Carlson
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Sajid Anwar 2015-07-26 12:12:58 PDT
I've reported part of this bug as <rdar://22000718>.

The Objective-C platform media player/source calls [AVFoundation isPlayableExtendedMIMEType:] to determine if a MIME type + codec string is supported. I've peeked inside with a debugger and found that it obtains the list of supported video/audio types and codecs from /System/Library/Frameworks/MediaToolbox.framework/Resources/MediaValidator.plist . Inside this plist is a list of supported "AudioCodecs", which contains strings like "aac " and ".mp3". However, "mp3" is nowhere to be found, despite the fact that virtually all examples, tutorials, and specifications online use canPlayType() to check the 'audio/mpeg; codecs="mp3"' MIME type.

Currently, canPlayType('audio/mpeg; codecs="mp3"') returns "maybe", but you can edit the plist and add the "mp3" entry, and then canPlayType will return "probably", which is expected since AV Foundation can obviously play MP3 audio.

On top of that, as I reported in the radar, there appears to be a bug in the implementation of [AVURLAsset isPlayableExtendedMIMEType:] that returns NO on the ".mp3" codec despite its existence in the plist, meaning even canPlayType('audio/mpeg; codecs=".mp3"') returns "maybe".

Should WebKit special-case the "mp3" audio codec to return "probably"? That might not be an elegant solution, but unless Apple adds the "mp3" entry to the "AudioCodecs" section of the plist, the call will always return "maybe" instead of "probably".

A little more information about the AV Foundation bug can be found at the radar, which I've duplicated on Open Radar: https://openradar.appspot.com/22000718
Comment 1 Alexey Proskuryakov 2015-07-26 15:20:29 PDT
Thank you for the report!

WebKit would need a workaround even once <rdar://22000718> is fixed, because it would be good to have this working on earlier OS X versions.
Comment 2 Sajid Anwar 2015-07-27 15:43:35 PDT
Good point with the earlier versions of WebKit. What would the approach be? Replacing the ends of both MediaPlayerPrivateAVFoundationObjC::supportsType and MediaPlayerPrivateMediaSourceAVFObjC::supportsType with something like this?

    NSString *typeString = [NSString stringWithFormat:@"%@; codecs=\"%@\"", (NSString *)parameters.type, (NSString *)parameters.codecs];
    
    if ([typeString isEqualToString:@"audio/mpeg; codecs=\"mp3\""])
        return MediaPlayer::IsSupported;

    return [AVURLAsset isPlayableExtendedMIMEType:typeString] ? MediaPlayer::IsSupported : MediaPlayer::MayBeSupported;

The assumption here is that this kind of special-casing is harmless if AV Foundation has always supported the MP3 codec (likely).
Comment 3 Alex Buznik 2020-09-17 01:57:24 PDT
Hello.
Currently in Safari 14 (15610.1.28.1.7, 15610), canPlayType('audio/mpeg; codecs="mp3"') returns "".
This is going to break a lot of streaming sites.
Comment 4 Eric Carlson 2020-09-17 11:09:44 PDT
Created attachment 409050 [details]
Patch
Comment 5 Darin Adler 2020-09-17 11:58:15 PDT
Comment on attachment 409050 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=409050&action=review

> Source/WebCore/platform/graphics/MIMETypeCache.cpp:145
> +    if (type.containerType().convertToASCIILowercase() == "audio/mpeg") {

Can be more efficient to use equalLettersIgnoringASCIICase or equalIgnoringASCIICase in a case like this.

> Source/WebCore/platform/graphics/MIMETypeCache.h:60
> +    Optional<bool> overrideExtendedType(const ContentType&);

This should be a static member function; it is a rule, not something  based on the contents of the cache itself. Or it could be a free function not mentioned in the header at all.

Sam has pointed out that Optional<bool> is confusing and often reminds us not to use it. We don’t *really* need it here. Have false mean don’t override, since we’re not using false at this time.

The name of this function has the form we try to avoid where it sounds like it might be the caller telling the cache to override, but really we are asking if we should override. So it could be more like shouldOverrideExtendedType?
Comment 6 Eric Carlson 2020-09-17 12:11:21 PDT
Comment on attachment 409050 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=409050&action=review

Thanks for the review!

>> Source/WebCore/platform/graphics/MIMETypeCache.cpp:145
>> +    if (type.containerType().convertToASCIILowercase() == "audio/mpeg") {
> 
> Can be more efficient to use equalLettersIgnoringASCIICase or equalIgnoringASCIICase in a case like this.

Good idea, changed.

>> Source/WebCore/platform/graphics/MIMETypeCache.h:60
>> +    Optional<bool> overrideExtendedType(const ContentType&);
> 
> This should be a static member function; it is a rule, not something  based on the contents of the cache itself. Or it could be a free function not mentioned in the header at all.
> 
> Sam has pointed out that Optional<bool> is confusing and often reminds us not to use it. We don’t *really* need it here. Have false mean don’t override, since we’re not using false at this time.
> 
> The name of this function has the form we try to avoid where it sounds like it might be the caller telling the cache to override, but really we are asking if we should override. So it could be more like shouldOverrideExtendedType?

I made it a member function because of the ASSERT, which I think is important because we should never override an extended type unless the content type is supported.

I had it return an Optional<bool> so we could have it return false for types in the future, but we clearly don't need that yet so I'll change the name to shouldOverrideExtendedType and have it return a simple bool.
Comment 7 Eric Carlson 2020-09-17 12:41:24 PDT
Created attachment 409057 [details]
Patch for landing
Comment 8 Darin Adler 2020-09-17 13:07:49 PDT
Comment on attachment 409057 [details]
Patch for landing

View in context: https://bugs.webkit.org/attachment.cgi?id=409057&action=review

> Source/WebCore/platform/graphics/MIMETypeCache.cpp:83
> +        if (auto override = shouldOverrideExtendedType(contentType)) {

Don’t need the local variable here any more now that we are doing the simplified version.
Comment 9 Eric Carlson 2020-09-17 13:54:09 PDT
Created attachment 409064 [details]
Patch for landing
Comment 10 Eric Carlson 2020-09-17 13:54:48 PDT
Comment on attachment 409057 [details]
Patch for landing

View in context: https://bugs.webkit.org/attachment.cgi?id=409057&action=review

>> Source/WebCore/platform/graphics/MIMETypeCache.cpp:83
>> +        if (auto override = shouldOverrideExtendedType(contentType)) {
> 
> Don’t need the local variable here any more now that we are doing the simplified version.

Good point, changed!
Comment 11 Eric Carlson 2020-09-17 15:33:45 PDT
The inspector/cpu-profiler/threads.html crash is unrelated.
Comment 12 EWS 2020-09-17 15:36:36 PDT
Committed r267210: <https://trac.webkit.org/changeset/267210>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 409064 [details].
Comment 13 Radar WebKit Bug Importer 2020-09-17 15:37:16 PDT
<rdar://problem/69101113>