| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 #include "core/html/HTMLMediaSource.h" | 45 #include "core/html/HTMLMediaSource.h" |
| 46 #include "core/html/HTMLSourceElement.h" | 46 #include "core/html/HTMLSourceElement.h" |
| 47 #include "core/html/HTMLTrackElement.h" | 47 #include "core/html/HTMLTrackElement.h" |
| 48 #include "core/html/MediaController.h" | 48 #include "core/html/MediaController.h" |
| 49 #include "core/html/MediaError.h" | 49 #include "core/html/MediaError.h" |
| 50 #include "core/html/MediaFragmentURIParser.h" | 50 #include "core/html/MediaFragmentURIParser.h" |
| 51 #include "core/html/TimeRanges.h" | 51 #include "core/html/TimeRanges.h" |
| 52 #include "core/html/shadow/MediaControls.h" | 52 #include "core/html/shadow/MediaControls.h" |
| 53 #include "core/html/track/AudioTrack.h" | 53 #include "core/html/track/AudioTrack.h" |
| 54 #include "core/html/track/AudioTrackList.h" | 54 #include "core/html/track/AudioTrackList.h" |
| 55 #include "core/html/track/AutomaticTrackSelection.h" |
| 55 #include "core/html/track/InbandTextTrack.h" | 56 #include "core/html/track/InbandTextTrack.h" |
| 56 #include "core/html/track/TextTrackCueList.h" | 57 #include "core/html/track/TextTrackCueList.h" |
| 57 #include "core/html/track/TextTrackList.h" | 58 #include "core/html/track/TextTrackList.h" |
| 58 #include "core/html/track/VideoTrack.h" | 59 #include "core/html/track/VideoTrack.h" |
| 59 #include "core/html/track/VideoTrackList.h" | 60 #include "core/html/track/VideoTrackList.h" |
| 60 #include "core/layout/compositing/LayerCompositor.h" | 61 #include "core/layout/compositing/LayerCompositor.h" |
| 61 #include "core/loader/FrameLoader.h" | 62 #include "core/loader/FrameLoader.h" |
| 62 #include "core/rendering/RenderVideo.h" | 63 #include "core/rendering/RenderVideo.h" |
| 63 #include "core/rendering/RenderView.h" | 64 #include "core/rendering/RenderView.h" |
| 64 #include "platform/ContentType.h" | 65 #include "platform/ContentType.h" |
| 65 #include "platform/Language.h" | |
| 66 #include "platform/Logging.h" | 66 #include "platform/Logging.h" |
| 67 #include "platform/MIMETypeFromURL.h" | 67 #include "platform/MIMETypeFromURL.h" |
| 68 #include "platform/MIMETypeRegistry.h" | 68 #include "platform/MIMETypeRegistry.h" |
| 69 #include "platform/RuntimeEnabledFeatures.h" | 69 #include "platform/RuntimeEnabledFeatures.h" |
| 70 #include "platform/UserGestureIndicator.h" | 70 #include "platform/UserGestureIndicator.h" |
| 71 #include "platform/graphics/GraphicsLayer.h" | 71 #include "platform/graphics/GraphicsLayer.h" |
| 72 #include "platform/weborigin/SecurityOrigin.h" | 72 #include "platform/weborigin/SecurityOrigin.h" |
| 73 #include "public/platform/Platform.h" | 73 #include "public/platform/Platform.h" |
| 74 #include "public/platform/WebContentDecryptionModule.h" | 74 #include "public/platform/WebContentDecryptionModule.h" |
| 75 #include "public/platform/WebInbandTextTrack.h" | 75 #include "public/platform/WebInbandTextTrack.h" |
| (...skipping 2760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2836 // When a track element's parent element changes and the old parent was a me
dia element, | 2836 // When a track element's parent element changes and the old parent was a me
dia element, |
| 2837 // then the user agent must remove the track element's corresponding text tr
ack from the | 2837 // then the user agent must remove the track element's corresponding text tr
ack from the |
| 2838 // media element's list of text tracks. | 2838 // media element's list of text tracks. |
| 2839 removeTextTrack(textTrack.get()); | 2839 removeTextTrack(textTrack.get()); |
| 2840 | 2840 |
| 2841 size_t index = m_textTracksWhenResourceSelectionBegan.find(textTrack.get()); | 2841 size_t index = m_textTracksWhenResourceSelectionBegan.find(textTrack.get()); |
| 2842 if (index != kNotFound) | 2842 if (index != kNotFound) |
| 2843 m_textTracksWhenResourceSelectionBegan.remove(index); | 2843 m_textTracksWhenResourceSelectionBegan.remove(index); |
| 2844 } | 2844 } |
| 2845 | 2845 |
| 2846 static int textTrackLanguageSelectionScore(const TextTrack& track) | |
| 2847 { | |
| 2848 if (track.language().isEmpty()) | |
| 2849 return 0; | |
| 2850 | |
| 2851 Vector<AtomicString> languages = userPreferredLanguages(); | |
| 2852 size_t languageMatchIndex = indexOfBestMatchingLanguageInList(track.language
(), languages); | |
| 2853 if (languageMatchIndex >= languages.size()) | |
| 2854 return 0; | |
| 2855 | |
| 2856 return languages.size() - languageMatchIndex; | |
| 2857 } | |
| 2858 | |
| 2859 static int textTrackSelectionScore(const TextTrack& track) | |
| 2860 { | |
| 2861 if (track.kind() != TextTrack::captionsKeyword() && track.kind() != TextTrac
k::subtitlesKeyword()) | |
| 2862 return 0; | |
| 2863 | |
| 2864 return textTrackLanguageSelectionScore(track); | |
| 2865 } | |
| 2866 | |
| 2867 void HTMLMediaElement::performAutomaticTextTrackSelection(const TrackGroup& grou
p) | |
| 2868 { | |
| 2869 ASSERT(group.tracks.size()); | |
| 2870 | |
| 2871 WTF_LOG(Media, "HTMLMediaElement::configureTextTrackGroup(%p, %d)", this, gr
oup.kind); | |
| 2872 | |
| 2873 // First, find the track in the group that should be enabled (if any). | |
| 2874 WillBeHeapVector<RefPtrWillBeMember<TextTrack>> currentlyEnabledTracks; | |
| 2875 RefPtrWillBeRawPtr<TextTrack> trackToEnable = nullptr; | |
| 2876 RefPtrWillBeRawPtr<TextTrack> defaultTrack = nullptr; | |
| 2877 RefPtrWillBeRawPtr<TextTrack> fallbackTrack = nullptr; | |
| 2878 int highestTrackScore = 0; | |
| 2879 for (size_t i = 0; i < group.tracks.size(); ++i) { | |
| 2880 RefPtrWillBeRawPtr<TextTrack> textTrack = group.tracks[i]; | |
| 2881 | |
| 2882 if (m_processingPreferenceChange && textTrack->mode() == TextTrack::show
ingKeyword()) | |
| 2883 currentlyEnabledTracks.append(textTrack); | |
| 2884 | |
| 2885 int trackScore = textTrackSelectionScore(*textTrack); | |
| 2886 if (trackScore) { | |
| 2887 // * If the text track kind is { [subtitles or captions] [descriptio
ns] } and the user has indicated an interest in having a | |
| 2888 // track with this text track kind, text track language, and text tr
ack label enabled, and there is no | |
| 2889 // other text track in the media element's list of text tracks with
a text track kind of either subtitles | |
| 2890 // or captions whose text track mode is showing | |
| 2891 // ... | |
| 2892 // * If the text track kind is chapters and the text track language
is one that the user agent has reason | |
| 2893 // to believe is appropriate for the user, and there is no other tex
t track in the media element's list of | |
| 2894 // text tracks with a text track kind of chapters whose text track m
ode is showing | |
| 2895 // Let the text track mode be showing. | |
| 2896 if (trackScore > highestTrackScore) { | |
| 2897 highestTrackScore = trackScore; | |
| 2898 trackToEnable = textTrack; | |
| 2899 } | |
| 2900 | |
| 2901 if (!defaultTrack && textTrack->isDefault()) | |
| 2902 defaultTrack = textTrack; | |
| 2903 if (!defaultTrack && !fallbackTrack) | |
| 2904 fallbackTrack = textTrack; | |
| 2905 } else if (!group.visibleTrack && !defaultTrack && textTrack->isDefault(
)) { | |
| 2906 // * If the track element has a default attribute specified, and the
re is no other text track in the media | |
| 2907 // element's list of text tracks whose text track mode is showing or
showing by default | |
| 2908 // Let the text track mode be showing by default. | |
| 2909 defaultTrack = textTrack; | |
| 2910 } | |
| 2911 } | |
| 2912 | |
| 2913 if (!trackToEnable && defaultTrack) | |
| 2914 trackToEnable = defaultTrack; | |
| 2915 | |
| 2916 // If no track matches the user's preferred language and non was marked 'def
ault', enable the first track | |
| 2917 // because the user has explicitly stated a preference for this kind of trac
k. | |
| 2918 if (!fallbackTrack && m_closedCaptionsVisible && group.kind == TrackGroup::C
aptionsAndSubtitles) | |
| 2919 fallbackTrack = group.tracks[0]; | |
| 2920 | |
| 2921 if (!trackToEnable && fallbackTrack) | |
| 2922 trackToEnable = fallbackTrack; | |
| 2923 | |
| 2924 if (currentlyEnabledTracks.size()) { | |
| 2925 for (size_t i = 0; i < currentlyEnabledTracks.size(); ++i) { | |
| 2926 RefPtrWillBeRawPtr<TextTrack> textTrack = currentlyEnabledTracks[i]; | |
| 2927 if (textTrack != trackToEnable) | |
| 2928 textTrack->setMode(TextTrack::disabledKeyword()); | |
| 2929 } | |
| 2930 } | |
| 2931 | |
| 2932 if (trackToEnable) | |
| 2933 trackToEnable->setMode(TextTrack::showingKeyword()); | |
| 2934 } | |
| 2935 | |
| 2936 void HTMLMediaElement::enableDefaultMetadataTextTracks(const TrackGroup& group) | |
| 2937 { | |
| 2938 ASSERT(group.tracks.size()); | |
| 2939 | |
| 2940 // https://html.spec.whatwg.org/multipage/embedded-content.html#honor-user-p
references-for-automatic-text-track-selection | |
| 2941 | |
| 2942 // 4. If there are any text tracks in the media element's list of text | |
| 2943 // tracks whose text track kind is metadata that correspond to track | |
| 2944 // elements with a default attribute set whose text track mode is set to | |
| 2945 // disabled, then set the text track mode of all such tracks to hidden | |
| 2946 for (auto& textTrack : group.tracks) { | |
| 2947 if (textTrack->mode() != TextTrack::disabledKeyword()) | |
| 2948 continue; | |
| 2949 if (!textTrack->isDefault()) | |
| 2950 continue; | |
| 2951 textTrack->setMode(TextTrack::hiddenKeyword()); | |
| 2952 } | |
| 2953 } | |
| 2954 | |
| 2955 void HTMLMediaElement::honorUserPreferencesForAutomaticTextTrackSelection() | 2846 void HTMLMediaElement::honorUserPreferencesForAutomaticTextTrackSelection() |
| 2956 { | 2847 { |
| 2957 TrackGroup captionAndSubtitleTracks(TrackGroup::CaptionsAndSubtitles); | 2848 if (!m_textTracks || !m_textTracks->length()) |
| 2958 TrackGroup descriptionTracks(TrackGroup::Description); | |
| 2959 TrackGroup chapterTracks(TrackGroup::Chapter); | |
| 2960 TrackGroup metadataTracks(TrackGroup::Metadata); | |
| 2961 | |
| 2962 if (!m_textTracks) | |
| 2963 return; | 2849 return; |
| 2964 | 2850 |
| 2965 for (size_t i = 0; i < m_textTracks->length(); ++i) { | 2851 AutomaticTrackSelection::Configuration configuration; |
| 2966 RefPtrWillBeRawPtr<TextTrack> textTrack = m_textTracks->item(i); | 2852 if (m_processingPreferenceChange) |
| 2967 if (!textTrack) | 2853 configuration.disableCurrentlyEnabledTracks = true; |
| 2968 continue; | 2854 if (m_closedCaptionsVisible) |
| 2855 configuration.forceEnableSubtitleOrCaptionTrack = true; |
| 2969 | 2856 |
| 2970 String kind = textTrack->kind(); | 2857 AutomaticTrackSelection trackSelection(configuration); |
| 2971 TrackGroup* currentGroup; | 2858 trackSelection.perform(*m_textTracks); |
| 2972 if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captions
Keyword()) { | |
| 2973 currentGroup = &captionAndSubtitleTracks; | |
| 2974 } else if (kind == TextTrack::descriptionsKeyword()) { | |
| 2975 currentGroup = &descriptionTracks; | |
| 2976 } else if (kind == TextTrack::chaptersKeyword()) { | |
| 2977 currentGroup = &chapterTracks; | |
| 2978 } else { | |
| 2979 ASSERT(kind == TextTrack::metadataKeyword()); | |
| 2980 currentGroup = &metadataTracks; | |
| 2981 } | |
| 2982 | |
| 2983 if (!currentGroup->visibleTrack && textTrack->mode() == TextTrack::showi
ngKeyword()) | |
| 2984 currentGroup->visibleTrack = textTrack; | |
| 2985 if (!currentGroup->defaultTrack && textTrack->isDefault()) | |
| 2986 currentGroup->defaultTrack = textTrack; | |
| 2987 | |
| 2988 // Do not add this track to the group if it has already been automatical
ly configured | |
| 2989 // as we only want to perform selection once per track so that adding an
other track | |
| 2990 // after the initial configuration doesn't reconfigure every track - onl
y those that | |
| 2991 // should be changed by the new addition. For example all metadata track
s are | |
| 2992 // disabled by default, and we don't want a track that has been enabled
by script | |
| 2993 // to be disabled automatically when a new metadata track is added later
. | |
| 2994 if (textTrack->hasBeenConfigured()) | |
| 2995 continue; | |
| 2996 | |
| 2997 if (textTrack->language().length()) | |
| 2998 currentGroup->hasSrcLang = true; | |
| 2999 currentGroup->tracks.append(textTrack); | |
| 3000 } | |
| 3001 | |
| 3002 if (captionAndSubtitleTracks.tracks.size()) | |
| 3003 performAutomaticTextTrackSelection(captionAndSubtitleTracks); | |
| 3004 if (descriptionTracks.tracks.size()) | |
| 3005 performAutomaticTextTrackSelection(descriptionTracks); | |
| 3006 if (chapterTracks.tracks.size()) | |
| 3007 performAutomaticTextTrackSelection(chapterTracks); | |
| 3008 if (metadataTracks.tracks.size()) | |
| 3009 enableDefaultMetadataTextTracks(metadataTracks); | |
| 3010 | 2859 |
| 3011 textTracksChanged(); | 2860 textTracksChanged(); |
| 3012 } | 2861 } |
| 3013 | 2862 |
| 3014 bool HTMLMediaElement::havePotentialSourceChild() | 2863 bool HTMLMediaElement::havePotentialSourceChild() |
| 3015 { | 2864 { |
| 3016 // Stash the current <source> node and next nodes so we can restore them aft
er checking | 2865 // Stash the current <source> node and next nodes so we can restore them aft
er checking |
| 3017 // to see there is another potential. | 2866 // to see there is another potential. |
| 3018 RefPtrWillBeRawPtr<HTMLSourceElement> currentSourceNode = m_currentSourceNod
e; | 2867 RefPtrWillBeRawPtr<HTMLSourceElement> currentSourceNode = m_currentSourceNod
e; |
| 3019 RefPtrWillBeRawPtr<Node> nextNode = m_nextChildNodeToConsider; | 2868 RefPtrWillBeRawPtr<Node> nextNode = m_nextChildNodeToConsider; |
| (...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3731 m_closedCaptionsVisible = closedCaptionVisible; | 3580 m_closedCaptionsVisible = closedCaptionVisible; |
| 3732 | 3581 |
| 3733 markCaptionAndSubtitleTracksAsUnconfigured(); | 3582 markCaptionAndSubtitleTracksAsUnconfigured(); |
| 3734 m_processingPreferenceChange = true; | 3583 m_processingPreferenceChange = true; |
| 3735 honorUserPreferencesForAutomaticTextTrackSelection(); | 3584 honorUserPreferencesForAutomaticTextTrackSelection(); |
| 3736 m_processingPreferenceChange = false; | 3585 m_processingPreferenceChange = false; |
| 3737 | 3586 |
| 3738 updateTextTrackDisplay(); | 3587 updateTextTrackDisplay(); |
| 3739 } | 3588 } |
| 3740 | 3589 |
| 3590 void HTMLMediaElement::markCaptionAndSubtitleTracksAsUnconfigured() |
| 3591 { |
| 3592 if (!m_textTracks) |
| 3593 return; |
| 3594 |
| 3595 // Mark all tracks as not "configured" so that |
| 3596 // honorUserPreferencesForAutomaticTextTrackSelection() will reconsider |
| 3597 // which tracks to display in light of new user preferences (e.g. default |
| 3598 // tracks should not be displayed if the user has turned off captions and |
| 3599 // non-default tracks should be displayed based on language preferences if |
| 3600 // the user has turned captions on). |
| 3601 for (unsigned i = 0; i < m_textTracks->length(); ++i) { |
| 3602 RefPtrWillBeRawPtr<TextTrack> textTrack = m_textTracks->item(i); |
| 3603 String kind = textTrack->kind(); |
| 3604 |
| 3605 if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captions
Keyword()) |
| 3606 textTrack->setHasBeenConfigured(false); |
| 3607 } |
| 3608 } |
| 3609 |
| 3741 unsigned HTMLMediaElement::webkitAudioDecodedByteCount() const | 3610 unsigned HTMLMediaElement::webkitAudioDecodedByteCount() const |
| 3742 { | 3611 { |
| 3743 if (!webMediaPlayer()) | 3612 if (!webMediaPlayer()) |
| 3744 return 0; | 3613 return 0; |
| 3745 return webMediaPlayer()->audioDecodedByteCount(); | 3614 return webMediaPlayer()->audioDecodedByteCount(); |
| 3746 } | 3615 } |
| 3747 | 3616 |
| 3748 unsigned HTMLMediaElement::webkitVideoDecodedByteCount() const | 3617 unsigned HTMLMediaElement::webkitVideoDecodedByteCount() const |
| 3749 { | 3618 { |
| 3750 if (!webMediaPlayer()) | 3619 if (!webMediaPlayer()) |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3848 if (!m_haveVisibleTextTrack && !hasMediaControls()) | 3717 if (!m_haveVisibleTextTrack && !hasMediaControls()) |
| 3849 return; | 3718 return; |
| 3850 | 3719 |
| 3851 ensureMediaControls(); | 3720 ensureMediaControls(); |
| 3852 mediaControls()->changedClosedCaptionsVisibility(); | 3721 mediaControls()->changedClosedCaptionsVisibility(); |
| 3853 | 3722 |
| 3854 updateActiveTextTrackCues(currentTime()); | 3723 updateActiveTextTrackCues(currentTime()); |
| 3855 updateTextTrackDisplay(); | 3724 updateTextTrackDisplay(); |
| 3856 } | 3725 } |
| 3857 | 3726 |
| 3858 void HTMLMediaElement::markCaptionAndSubtitleTracksAsUnconfigured() | |
| 3859 { | |
| 3860 if (!m_textTracks) | |
| 3861 return; | |
| 3862 | |
| 3863 // Mark all tracks as not "configured" so that | |
| 3864 // honorUserPreferencesForAutomaticTextTrackSelection() will reconsider | |
| 3865 // which tracks to display in light of new user preferences (e.g. default | |
| 3866 // tracks should not be displayed if the user has turned off captions and | |
| 3867 // non-default tracks should be displayed based on language preferences if | |
| 3868 // the user has turned captions on). | |
| 3869 for (unsigned i = 0; i < m_textTracks->length(); ++i) { | |
| 3870 RefPtrWillBeRawPtr<TextTrack> textTrack = m_textTracks->item(i); | |
| 3871 String kind = textTrack->kind(); | |
| 3872 | |
| 3873 if (kind == TextTrack::subtitlesKeyword() || kind == TextTrack::captions
Keyword()) | |
| 3874 textTrack->setHasBeenConfigured(false); | |
| 3875 } | |
| 3876 } | |
| 3877 | |
| 3878 void* HTMLMediaElement::preDispatchEventHandler(Event* event) | 3727 void* HTMLMediaElement::preDispatchEventHandler(Event* event) |
| 3879 { | 3728 { |
| 3880 if (event && event->type() == EventTypeNames::webkitfullscreenchange) | 3729 if (event && event->type() == EventTypeNames::webkitfullscreenchange) |
| 3881 configureMediaControls(); | 3730 configureMediaControls(); |
| 3882 | 3731 |
| 3883 return nullptr; | 3732 return nullptr; |
| 3884 } | 3733 } |
| 3885 | 3734 |
| 3886 void HTMLMediaElement::createMediaPlayer() | 3735 void HTMLMediaElement::createMediaPlayer() |
| 3887 { | 3736 { |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4123 | 3972 |
| 4124 #if ENABLE(WEB_AUDIO) | 3973 #if ENABLE(WEB_AUDIO) |
| 4125 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) | 3974 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) |
| 4126 { | 3975 { |
| 4127 if (!visitor->isAlive(m_audioSourceNode) && audioSourceProvider()) | 3976 if (!visitor->isAlive(m_audioSourceNode) && audioSourceProvider()) |
| 4128 audioSourceProvider()->setClient(nullptr); | 3977 audioSourceProvider()->setClient(nullptr); |
| 4129 } | 3978 } |
| 4130 #endif | 3979 #endif |
| 4131 | 3980 |
| 4132 } | 3981 } |
| OLD | NEW |