Changeset 174823 in webkit
- Timestamp:
- Oct 17, 2014 9:40:14 AM (10 years ago)
- Location:
- trunk
- Files:
-
- 16 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r174822 r174823 1 2014-10-16 Jer Noble <jer.noble@apple.com> 2 3 [Mac] Represent AVMediaSelectionOptions as AudioTracks 4 https://bugs.webkit.org/show_bug.cgi?id=137474 5 6 Reviewed by Brent Fulgham. 7 8 * http/tests/media/hls/hls-audio-tracks-expected.txt: Added. 9 * http/tests/media/hls/hls-audio-tracks.html: Added. 10 * http/tests/media/resources/hls/audio-tracks.m3u8: Added. 11 * http/tests/media/resources/hls/bipbop/iframe_index.m3u8: Added. 12 * http/tests/media/resources/hls/bipbop/main0.ts: Added. 13 * http/tests/media/resources/hls/bipbop/main1.ts: Added. 14 * http/tests/media/resources/hls/bipbop/prog_index.m3u8: Added. 15 * http/tests/media/resources/hls/french/main.aac: Added. 16 * http/tests/media/resources/hls/french/prog_index.m3u8: Added. 17 * http/tests/media/resources/hls/spanish/main.aac: Added. 18 * http/tests/media/resources/hls/spanish/prog_index.m3u8: Added. 19 1 20 2014-10-17 Brent Fulgham <bfulgham@apple.com> 2 21 -
trunk/Source/WebCore/ChangeLog
r174819 r174823 1 2014-10-16 Jer Noble <jer.noble@apple.com> 2 3 [Mac] Represent AVMediaSelectionOptions as AudioTracks 4 https://bugs.webkit.org/show_bug.cgi?id=137474 5 6 Reviewed by Brent Fulgham. 7 8 Test: http/tests/media/hls/hls-audio-tracks.html 9 10 Support selecting audio "tracks" in HLS streams by exposing AVMediaSelectionOptions 11 as entries in the video's AudioTrackList. 12 13 AVMediaSessionGroups and AVPlayerItems don't have KVO or notifications to track when options 14 are selected and deselected, so wrap AVMediaSessionGroup and AVMediaSessionOption in C++ 15 wrappers. Each AVMediaSelectionGroup can have only one AVMediaSelectionOption selected at a 16 time, so the wrapper will take care of answering which AVMediaSelectionOption is currently 17 selected, as without KVO notifications, asking the AVMediaSelectionGroup directly is 18 inconsistent. Because setting the selected option multiple times in the same run-loop can 19 cause flakiness, coalesce calls to setSelectedOption() by setting a one-shot timer to do 20 the actual selection in the next run-loop. 21 22 * platform/graphics/avfoundation/MediaSelectionGroupAVFObjC.h: Added. 23 (WebCore::MediaSelectionOptionAVFObjC::avMediaSelectionOption): 24 (WebCore::MediaSelectionOptionAVFObjC::clearGroup): Clear backpointer to group from option. 25 (WebCore::MediaSelectionGroupAVFObjC::selectedOption): Simple accessor. 26 (WebCore::MediaSelectionGroupAVFObjC::options): Simple accessor. 27 (WebCore::MediaSelectionGroupAVFObjC::avMediaSelectionGroup): Simple accessor. 28 * platform/graphics/avfoundation/MediaSelectionGroupAVFObjC.mm: Added. 29 (WebCore::MediaSelectionOptionAVFObjC::create): Simple factory method. 30 (WebCore::MediaSelectionOptionAVFObjC::MediaSelectionOptionAVFObjC): Simple constructor. 31 (WebCore::MediaSelectionOptionAVFObjC::setSelected): Pass through to MediaSelectionGroupAVFObjC. 32 (WebCore::MediaSelectionOptionAVFObjC::selected): Ditto. 33 (WebCore::MediaSelectionOptionAVFObjC::index): Return index of this object in the group's object. 34 (WebCore::MediaSelectionGroupAVFObjC::create): 35 (WebCore::MediaSelectionGroupAVFObjC::MediaSelectionGroupAVFObjC): 36 (WebCore::MediaSelectionGroupAVFObjC::~MediaSelectionGroupAVFObjC): 37 (WebCore::MediaSelectionGroupAVFObjC::updateOptions): Discover added or removed options. 38 (WebCore::MediaSelectionGroupAVFObjC::setSelectedOption): Set a one shot timer to coalesce multiple calls. 39 (WebCore::MediaSelectionGroupAVFObjC::selectionTimerFired): Set the selected AVSelectionOption. 40 41 Modify AVTrackPrivateAVFObjCImpl to support both AVPlayerItemTracks and these new 42 MediaSelectionOptionAVFObjC objects. 43 44 * platform/graphics/avfoundation/AVTrackPrivateAVFObjCImpl.h: 45 (WebCore::AVTrackPrivateAVFObjCImpl::mediaSelectionOption): Simple accessor. 46 * platform/graphics/avfoundation/AVTrackPrivateAVFObjCImpl.mm: 47 (WebCore::AVTrackPrivateAVFObjCImpl::AVTrackPrivateAVFObjCImpl): Simple constructor. 48 (WebCore::AVTrackPrivateAVFObjCImpl::~AVTrackPrivateAVFObjCImpl): Simple destructor. 49 (WebCore::AVTrackPrivateAVFObjCImpl::enabled): Use MediaSelectionOptionAVFObjC, if present. 50 (WebCore::AVTrackPrivateAVFObjCImpl::setEnabled): Ditto. 51 (WebCore::AVTrackPrivateAVFObjCImpl::audioKind): Ditto. 52 (WebCore::AVTrackPrivateAVFObjCImpl::videoKind): Ditto. 53 (WebCore::AVTrackPrivateAVFObjCImpl::index): Ditto. 54 (WebCore::AVTrackPrivateAVFObjCImpl::id): Ditto. 55 (WebCore::AVTrackPrivateAVFObjCImpl::label): Ditto. 56 (WebCore::AVTrackPrivateAVFObjCImpl::language): Ditto. 57 (WebCore::AVTrackPrivateAVFObjCImpl::languageForAVMediaSelectionOption): Ditto. 58 (WebCore::AVTrackPrivateAVFObjCImpl::trackID): Ditto. 59 60 Allow AudioTrackPrivateAVFObjC and VideoTrackPrivateAVFObjC to be created with 61 a MediaSelectionOptionAVFObjC. 62 63 * platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.h: 64 (WebCore::AudioTrackPrivateAVFObjC::create): Takes a MediaSelectionOptionAVFObjC. 65 * platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm: 66 (WebCore::AudioTrackPrivateAVFObjC::AudioTrackPrivateAVFObjC): Simple constructor. 67 (WebCore::AudioTrackPrivateAVFObjC::setMediaSelectionOption): Create a new AVTrackPrivateAVFObjCImpl. 68 (WebCore::AudioTrackPrivateAVFObjC::mediaSelectionOption): Simple accessor. 69 * platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.cpp: 70 (WebCore::VideoTrackPrivateAVFObjC::VideoTrackPrivateAVFObjC): Simple constructor. 71 (WebCore::VideoTrackPrivateAVFObjC::setMediaSelectonOption): Create a new AVTrackPrivateAVFObjCImpl. 72 (WebCore::VideoTrackPrivateAVFObjC::mediaSelectionOption): Simple accessor. 73 * platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.h: 74 75 Because IDs are not necessarily unique across AVPlayerItemTracks and AVMediaSelectionOptions, 76 use the index of the track or option instead of it's self-declared ID for ordering for the 77 trackIndex. 78 79 * platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm: 80 (WebCore::AudioTrackPrivateAVFObjC::resetPropertiesFromTrack): 81 * platform/graphics/avfoundation/objc/VideoTrackPrivateMediaSourceAVFObjC.mm: 82 (WebCore::VideoTrackPrivateMediaSourceAVFObjC::resetPropertiesFromTrack): 83 84 Rather than making allowing the AVPlayerItem to automatically select the "best" 85 AVMediaSelectionOption, select the automatic options when creating the AVPlayerItem 86 and thereafter allow the users manual selections "stick". 87 88 * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h: 89 * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm: 90 (WebCore::MediaPlayerPrivateAVFoundationObjC::ensureAVPlayer): 91 (WebCore::MediaPlayerPrivateAVFoundationObjC::ensureAVPlayerItem): 92 93 Determine whether any MediaSelectionOptionsAVFObjC have been added or removed and send trackChange events accordingly. 94 95 * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm: 96 (WebCore::determineChangedTracksFromNewTracksAndOldItems): Added. 97 (WebCore::MediaPlayerPrivateAVFoundationObjC::updateAudioTracks): Search for updated selection options. 98 (WebCore::MediaPlayerPrivateAVFoundationObjC::updateVideoTracks): Ditto. 99 (WebCore::MediaPlayerPrivateAVFoundationObjC::safeMediaSelectionGroupForAudibleMedia): Return selection group, if available. 100 (WebCore::MediaPlayerPrivateAVFoundationObjC::safeMediaSelectionGroupForVisualMedia): Ditto. 101 (WebCore::MediaPlayerPrivateAVFoundationObjC::tracksDidChange): Filter out AVPlayerItemTracks without 102 AVAssetTracks, as these will be represented by MediaSelectionGroupObjCs instead. 103 104 Add new files to project. 105 * WebCore.xcodeproj/project.pbxproj: 106 1 107 2014-10-17 Grzegorz Czajkowski <g.czajkowski@samsung.com> 2 108 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r174583 r174823 5685 5685 CDB859F7160D48A400E5B07F /* MediaKeyEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDB859F4160D489900E5B07F /* MediaKeyEvent.cpp */; }; 5686 5686 CDB859FA160D494900E5B07F /* JSMediaKeyEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDB859F8160D493E00E5B07F /* JSMediaKeyEvent.cpp */; }; 5687 CDBEAEAC19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDBEAEAA19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm */; }; 5688 CDBEAEAD19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CDBEAEAB19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h */; }; 5687 5689 CDC26B40160A8CC60026757B /* MockCDM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDC26B3C160A62B00026757B /* MockCDM.cpp */; }; 5688 5690 CDC26B41160A8CCE0026757B /* MockCDM.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC26B3D160A62B00026757B /* MockCDM.h */; }; … … 13149 13151 CDB859F8160D493E00E5B07F /* JSMediaKeyEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaKeyEvent.cpp; sourceTree = "<group>"; }; 13150 13152 CDB859F9160D493E00E5B07F /* JSMediaKeyEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaKeyEvent.h; sourceTree = "<group>"; }; 13153 CDBEAEAA19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MediaSelectionGroupAVFObjC.mm; sourceTree = "<group>"; }; 13154 CDBEAEAB19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaSelectionGroupAVFObjC.h; sourceTree = "<group>"; }; 13151 13155 CDC1DD4117CC2C48008CB55D /* mediaControlsApple.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = mediaControlsApple.css; sourceTree = "<group>"; }; 13152 13156 CDC26B3C160A62B00026757B /* MockCDM.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MockCDM.cpp; sourceTree = "<group>"; }; … … 21643 21647 CD8A7BB9197735FE00CBD643 /* AudioSourceProviderAVFObjC.mm */, 21644 21648 CD8A7BBA197735FE00CBD643 /* AudioSourceProviderAVFObjC.h */, 21649 CDBEAEAA19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm */, 21650 CDBEAEAB19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h */, 21645 21651 ); 21646 21652 name = objc; … … 23864 23870 BC1A37B5097C715F0019F3D8 /* DOMExtensions.h in Headers */, 23865 23871 BC00F0040E0A185500FD04E3 /* DOMFile.h in Headers */, 23872 CDBEAEAD19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h in Headers */, 23866 23873 2E3BC108117D479800B9409A /* DOMFileError.h in Headers */, 23867 23874 2E3BC10B117D47C800B9409A /* DOMFileErrorInternal.h in Headers */, … … 28172 28179 590E1B4B11E4EF700069F784 /* JSDeviceOrientationEventCustom.cpp in Sources */, 28173 28180 BCE438A2140C0DC0005E437E /* JSDictionary.cpp in Sources */, 28181 CDBEAEAC19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm in Sources */, 28174 28182 659DDC8209E198BA001BF3C6 /* JSDocument.cpp in Sources */, 28175 28183 49C7BA8D1042F5B10009D447 /* JSDocumentCustom.cpp in Sources */, -
trunk/Source/WebCore/platform/graphics/avfoundation/AVTrackPrivateAVFObjCImpl.h
r165676 r174823 32 32 #include "VideoTrackPrivate.h" 33 33 #include <wtf/OwnPtr.h> 34 #include <wtf/Ref.h> 34 35 #include <wtf/RetainPtr.h> 35 36 36 37 OBJC_CLASS AVAssetTrack; 38 OBJC_CLASS AVPlayerItem; 37 39 OBJC_CLASS AVPlayerItemTrack; 40 OBJC_CLASS AVMediaSelectionGroup; 41 OBJC_CLASS AVMediaSelectionOption; 38 42 39 43 namespace WebCore { 44 45 class MediaSelectionOptionAVFObjC; 40 46 41 47 class AVTrackPrivateAVFObjCImpl { … … 43 49 explicit AVTrackPrivateAVFObjCImpl(AVPlayerItemTrack*); 44 50 explicit AVTrackPrivateAVFObjCImpl(AVAssetTrack*); 51 explicit AVTrackPrivateAVFObjCImpl(MediaSelectionOptionAVFObjC&); 52 ~AVTrackPrivateAVFObjCImpl(); 45 53 46 54 AVPlayerItemTrack* playerItemTrack() const { return m_playerItemTrack.get(); } 47 55 AVAssetTrack* assetTrack() const { return m_assetTrack.get(); } 56 MediaSelectionOptionAVFObjC* mediaSelectionOption() const { return m_mediaSelectionOption.get(); } 48 57 49 58 bool enabled() const; … … 53 62 VideoTrackPrivate::Kind videoKind() const; 54 63 64 int index() const; 55 65 AtomicString id() const; 56 66 AtomicString label() const; … … 60 70 61 71 static String languageForAVAssetTrack(AVAssetTrack*); 72 static String languageForAVMediaSelectionOption(AVMediaSelectionOption *); 62 73 63 74 private: 64 75 RetainPtr<AVPlayerItemTrack> m_playerItemTrack; 65 76 RetainPtr<AVAssetTrack> m_assetTrack; 77 RetainPtr<AVPlayerItem> m_playerItem; 78 RefPtr<MediaSelectionOptionAVFObjC> m_mediaSelectionOption; 66 79 }; 67 80 -
trunk/Source/WebCore/platform/graphics/avfoundation/AVTrackPrivateAVFObjCImpl.mm
r165676 r174823 29 29 #if ENABLE(VIDEO_TRACK) 30 30 31 #import "MediaSelectionGroupAVFObjC.h" 31 32 #import "SoftLinking.h" 33 #import <AVFoundation/AVAssetTrack.h> 34 #import <AVFoundation/AVMediaSelectionGroup.h> 35 #import <AVFoundation/AVMetadataItem.h> 36 #import <AVFoundation/AVPlayerItem.h> 37 #import <AVFoundation/AVPlayerItemTrack.h> 32 38 #import <objc/runtime.h> 33 #import <AVFoundation/AVAssetTrack.h> 34 #import <AVFoundation/AVPlayerItemTrack.h> 35 #import <AVFoundation/AVMetadataItem.h> 39 40 @class AVMediaSelectionOption; 41 @interface AVMediaSelectionOption (WebKitInternal) 42 - (id)optionID; 43 @end 36 44 37 45 SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation) 38 46 39 47 SOFT_LINK_CLASS(AVFoundation, AVAssetTrack) 48 SOFT_LINK_CLASS(AVFoundation, AVPlayerItem) 40 49 SOFT_LINK_CLASS(AVFoundation, AVPlayerItemTrack) 50 SOFT_LINK_CLASS(AVFoundation, AVMediaSelectionGroup) 51 SOFT_LINK_CLASS(AVFoundation, AVMediaSelectionOption) 41 52 SOFT_LINK_CLASS(AVFoundation, AVMetadataItem) 42 53 … … 70 81 } 71 82 83 AVTrackPrivateAVFObjCImpl::AVTrackPrivateAVFObjCImpl(MediaSelectionOptionAVFObjC& option) 84 : m_mediaSelectionOption(&option) 85 { 86 } 87 88 AVTrackPrivateAVFObjCImpl::~AVTrackPrivateAVFObjCImpl() 89 { 90 } 91 72 92 bool AVTrackPrivateAVFObjCImpl::enabled() const 73 93 { 74 ASSERT(m_playerItemTrack); 75 return [m_playerItemTrack isEnabled]; 94 if (m_playerItemTrack) 95 return [m_playerItemTrack isEnabled]; 96 if (m_mediaSelectionOption) 97 return m_mediaSelectionOption->selected(); 98 ASSERT_NOT_REACHED(); 99 return false; 76 100 } 77 101 78 102 void AVTrackPrivateAVFObjCImpl::setEnabled(bool enabled) 79 103 { 80 ASSERT(m_playerItemTrack); 81 [m_playerItemTrack setEnabled:enabled]; 104 if (m_playerItemTrack) 105 [m_playerItemTrack setEnabled:enabled]; 106 else if (m_mediaSelectionOption) 107 m_mediaSelectionOption->setSelected(enabled); 108 else 109 ASSERT_NOT_REACHED(); 82 110 } 83 111 84 112 AudioTrackPrivate::Kind AVTrackPrivateAVFObjCImpl::audioKind() const 85 113 { 86 if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicIsAuxiliaryContent]) 87 return AudioTrackPrivate::Alternative; 88 else if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicIsMainProgramContent]) 89 return AudioTrackPrivate::Main; 114 if (m_assetTrack) { 115 if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicIsAuxiliaryContent]) 116 return AudioTrackPrivate::Alternative; 117 if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicIsMainProgramContent]) 118 return AudioTrackPrivate::Main; 119 return AudioTrackPrivate::None; 120 } 121 122 if (m_mediaSelectionOption) { 123 AVMediaSelectionOption *option = m_mediaSelectionOption->avMediaSelectionOption(); 124 if ([option hasMediaCharacteristic:AVMediaCharacteristicIsAuxiliaryContent]) 125 return AudioTrackPrivate::Alternative; 126 if ([option hasMediaCharacteristic:AVMediaCharacteristicIsMainProgramContent]) 127 return AudioTrackPrivate::Main; 128 return AudioTrackPrivate::None; 129 } 130 131 ASSERT_NOT_REACHED(); 90 132 return AudioTrackPrivate::None; 91 133 } … … 93 135 VideoTrackPrivate::Kind AVTrackPrivateAVFObjCImpl::videoKind() const 94 136 { 95 if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicDescribesVideoForAccessibility]) 96 return VideoTrackPrivate::Sign; 97 else if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicTranscribesSpokenDialogForAccessibility]) 98 return VideoTrackPrivate::Captions; 99 else if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicIsAuxiliaryContent]) 100 return VideoTrackPrivate::Alternative; 101 else if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicIsMainProgramContent]) 102 return VideoTrackPrivate::Main; 137 if (m_assetTrack) { 138 if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicDescribesVideoForAccessibility]) 139 return VideoTrackPrivate::Sign; 140 if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicTranscribesSpokenDialogForAccessibility]) 141 return VideoTrackPrivate::Captions; 142 if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicIsAuxiliaryContent]) 143 return VideoTrackPrivate::Alternative; 144 if ([m_assetTrack hasMediaCharacteristic:AVMediaCharacteristicIsMainProgramContent]) 145 return VideoTrackPrivate::Main; 146 return VideoTrackPrivate::None; 147 } 148 149 if (m_mediaSelectionOption) { 150 AVMediaSelectionOption *option = m_mediaSelectionOption->avMediaSelectionOption(); 151 if ([option hasMediaCharacteristic:AVMediaCharacteristicDescribesVideoForAccessibility]) 152 return VideoTrackPrivate::Sign; 153 if ([option hasMediaCharacteristic:AVMediaCharacteristicTranscribesSpokenDialogForAccessibility]) 154 return VideoTrackPrivate::Captions; 155 if ([option hasMediaCharacteristic:AVMediaCharacteristicIsAuxiliaryContent]) 156 return VideoTrackPrivate::Alternative; 157 if ([option hasMediaCharacteristic:AVMediaCharacteristicIsMainProgramContent]) 158 return VideoTrackPrivate::Main; 159 return VideoTrackPrivate::None; 160 } 161 162 ASSERT_NOT_REACHED(); 103 163 return VideoTrackPrivate::None; 104 164 } 105 165 166 int AVTrackPrivateAVFObjCImpl::index() const 167 { 168 if (m_assetTrack) 169 return [[[m_assetTrack asset] tracks] indexOfObject:m_assetTrack.get()]; 170 if (m_mediaSelectionOption) 171 return [[[m_playerItem asset] tracks] count] + m_mediaSelectionOption->index(); 172 ASSERT_NOT_REACHED(); 173 return 0; 174 } 175 106 176 AtomicString AVTrackPrivateAVFObjCImpl::id() const 107 177 { 108 return String::format("%d", [m_assetTrack trackID]); 178 if (m_assetTrack) 179 return String::format("%d", [m_assetTrack trackID]); 180 if (m_mediaSelectionOption) 181 return [[m_mediaSelectionOption->avMediaSelectionOption() optionID] stringValue]; 182 ASSERT_NOT_REACHED(); 183 return emptyAtom; 109 184 } 110 185 111 186 AtomicString AVTrackPrivateAVFObjCImpl::label() const 112 187 { 113 NSArray *titles = [AVMetadataItem metadataItemsFromArray:[m_assetTrack commonMetadata] withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon]; 188 NSArray *commonMetadata = nil; 189 if (m_assetTrack) 190 commonMetadata = [m_assetTrack commonMetadata]; 191 else if (m_mediaSelectionOption) 192 commonMetadata = [m_mediaSelectionOption->avMediaSelectionOption() commonMetadata]; 193 else 194 ASSERT_NOT_REACHED(); 195 196 NSArray *titles = [AVMetadataItem metadataItemsFromArray:commonMetadata withKey:AVMetadataCommonKeyTitle keySpace:AVMetadataKeySpaceCommon]; 114 197 if (![titles count]) 115 198 return emptyAtom; … … 124 207 AtomicString AVTrackPrivateAVFObjCImpl::language() const 125 208 { 126 return languageForAVAssetTrack(m_assetTrack.get()); 209 if (m_assetTrack) 210 return languageForAVAssetTrack(m_assetTrack.get()); 211 if (m_mediaSelectionOption) 212 return languageForAVMediaSelectionOption(m_mediaSelectionOption->avMediaSelectionOption()); 213 214 ASSERT_NOT_REACHED(); 215 return emptyAtom; 127 216 } 128 217 … … 144 233 } 145 234 235 String AVTrackPrivateAVFObjCImpl::languageForAVMediaSelectionOption(AVMediaSelectionOption* option) 236 { 237 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 238 NSString *language = [option extendedLanguageTag]; 239 #else 240 NSString *language = nil; 241 #endif 242 243 // If the language code is stored as a QuickTime 5-bit packed code there aren't enough bits for a full 244 // RFC 4646 language tag so extendedLanguageTag returns NULL. In this case languageCode will return the 245 // ISO 639-2/T language code so check it. 246 if (!language) 247 language = [[option locale] objectForKey:NSLocaleLanguageCode]; 248 249 // Some legacy tracks have "und" as a language, treat that the same as no language at all. 250 if (!language || [language isEqualToString:@"und"]) 251 return emptyString(); 252 253 return language; 254 } 255 146 256 int AVTrackPrivateAVFObjCImpl::trackID() const 147 257 { 148 return [m_assetTrack trackID]; 258 if (m_assetTrack) 259 return [m_assetTrack trackID]; 260 if (m_mediaSelectionOption) 261 return [[m_mediaSelectionOption->avMediaSelectionOption() optionID] intValue]; 262 ASSERT_NOT_REACHED(); 263 return 0; 149 264 } 150 265 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.h
r159368 r174823 32 32 #include <wtf/OwnPtr.h> 33 33 34 OBJC_CLASS AVAssetTrack; 35 OBJC_CLASS AVPlayerItem; 34 36 OBJC_CLASS AVPlayerItemTrack; 35 OBJC_CLASS AVAssetTrack; 37 OBJC_CLASS AVMediaSelectionGroup; 38 OBJC_CLASS AVMediaSelectionOption; 36 39 37 40 namespace WebCore { 38 41 39 42 class AVTrackPrivateAVFObjCImpl; 43 class MediaSelectionOptionAVFObjC; 40 44 41 45 class AudioTrackPrivateAVFObjC : public AudioTrackPrivateAVF { … … 52 56 } 53 57 58 static RefPtr<AudioTrackPrivateAVFObjC> create(MediaSelectionOptionAVFObjC& option) 59 { 60 return adoptRef(new AudioTrackPrivateAVFObjC(option)); 61 } 62 54 63 virtual void setEnabled(bool); 55 64 … … 60 69 AVAssetTrack* assetTrack(); 61 70 71 void setMediaSelectionOption(MediaSelectionOptionAVFObjC&); 72 MediaSelectionOptionAVFObjC* mediaSelectionOption(); 73 62 74 private: 75 friend class MediaPlayerPrivateAVFoundationObjC; 63 76 AudioTrackPrivateAVFObjC(AVPlayerItemTrack*); 64 77 AudioTrackPrivateAVFObjC(AVAssetTrack*); 78 AudioTrackPrivateAVFObjC(MediaSelectionOptionAVFObjC&); 65 79 66 80 void resetPropertiesFromTrack(); -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm
r174402 r174823 27 27 #import "AudioTrackPrivateAVFObjC.h" 28 28 #import "AVTrackPrivateAVFObjCImpl.h" 29 #import "MediaSelectionGroupAVFObjC.h" 29 30 30 31 #if ENABLE(VIDEO_TRACK) … … 38 39 } 39 40 41 AudioTrackPrivateAVFObjC::AudioTrackPrivateAVFObjC(MediaSelectionOptionAVFObjC& option) 42 : m_impl(std::make_unique<AVTrackPrivateAVFObjCImpl>(option)) 43 { 44 resetPropertiesFromTrack(); 45 } 46 40 47 void AudioTrackPrivateAVFObjC::resetPropertiesFromTrack() 41 48 { … … 44 51 AudioTrackPrivateAVF::setEnabled(m_impl->enabled()); 45 52 46 setTrackIndex(m_impl-> trackID());53 setTrackIndex(m_impl->index()); 47 54 setKind(m_impl->audioKind()); 48 55 setId(m_impl->id()); … … 79 86 } 80 87 88 void AudioTrackPrivateAVFObjC::setMediaSelectionOption(MediaSelectionOptionAVFObjC& option) 89 { 90 m_impl = std::make_unique<AVTrackPrivateAVFObjCImpl>(option); 91 resetPropertiesFromTrack(); 92 } 93 94 MediaSelectionOptionAVFObjC* AudioTrackPrivateAVFObjC::mediaSelectionOption() 95 { 96 return m_impl->mediaSelectionOption(); 97 } 98 81 99 void AudioTrackPrivateAVFObjC::setEnabled(bool enabled) 82 100 { -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
r173628 r174823 65 65 class AudioSourceProviderAVFObjC; 66 66 class AudioTrackPrivateAVFObjC; 67 class MediaSelectionGroupAVFObjC; 67 68 class VideoTrackPrivateAVFObjC; 68 69 … … 246 247 void processMediaSelectionOptions(); 247 248 AVMediaSelectionGroup* safeMediaSelectionGroupForLegibleMedia(); 249 AVMediaSelectionGroup* safeMediaSelectionGroupForAudibleMedia(); 250 AVMediaSelectionGroup* safeMediaSelectionGroupForVisualMedia(); 248 251 #endif 249 252 … … 326 329 Vector<RefPtr<AudioTrackPrivateAVFObjC>> m_audioTracks; 327 330 Vector<RefPtr<VideoTrackPrivateAVFObjC>> m_videoTracks; 331 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) 332 RefPtr<MediaSelectionGroupAVFObjC> m_audibleGroup; 333 RefPtr<MediaSelectionGroupAVFObjC> m_visualGroup; 334 #endif 328 335 #endif 329 336 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
r174563 r174823 47 47 #import "URL.h" 48 48 #import "Logging.h" 49 #import "MediaSelectionGroupAVFObjC.h" 49 50 #import "MediaTimeAVFoundation.h" 50 51 #import "PlatformTimeRanges.h" … … 67 68 #import <wtf/CurrentTime.h> 68 69 #import <wtf/Functional.h> 70 #import <wtf/ListHashSet.h> 69 71 #import <wtf/NeverDestroyed.h> 70 72 #import <wtf/text/CString.h> … … 88 90 #import <VideoToolbox/VideoToolbox.h> 89 91 #endif 92 93 namespace std { 94 template <> struct iterator_traits<HashSet<RefPtr<WebCore::MediaSelectionOptionAVFObjC>>::iterator> { 95 typedef RefPtr<WebCore::MediaSelectionOptionAVFObjC> value_type; 96 }; 97 } 90 98 91 99 @interface WebVideoContainerLayer : CALayer … … 124 132 typedef AVPlayer AVPlayerType; 125 133 typedef AVPlayerItem AVPlayerItemType; 134 typedef AVPlayerItemLegibleOutput AVPlayerItemLegibleOutputType; 135 typedef AVPlayerItemVideoOutput AVPlayerItemVideoOutputType; 126 136 typedef AVMetadataItem AVMetadataItemType; 137 typedef AVMediaSelectionGroup AVMediaSelectionGroupType; 138 typedef AVMediaSelectionOption AVMediaSelectionOptionType; 127 139 128 140 SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation) … … 859 871 860 872 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) && HAVE(AVFOUNDATION_LEGIBLE_OUTPUT_SUPPORT) 861 [m_avPlayer.get() setAppliesMediaSelectionCriteriaAutomatically: YES];873 [m_avPlayer.get() setAppliesMediaSelectionCriteriaAutomatically:NO]; 862 874 #endif 863 875 … … 913 925 [m_legibleOutput.get() setTextStylingResolution:AVPlayerItemLegibleOutputTextStylingResolutionSourceAndRulesOnly]; 914 926 [m_avPlayerItem.get() addOutput:m_legibleOutput.get()]; 927 #endif 928 929 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) && HAVE(AVFOUNDATION_LEGIBLE_OUTPUT_SUPPORT) 930 [m_avPlayerItem selectMediaOptionAutomaticallyInMediaSelectionGroup:safeMediaSelectionGroupForLegibleMedia()]; 931 [m_avPlayerItem selectMediaOptionAutomaticallyInMediaSelectionGroup:safeMediaSelectionGroupForAudibleMedia()]; 932 [m_avPlayerItem selectMediaOptionAutomaticallyInMediaSelectionGroup:safeMediaSelectionGroupForVisualMedia()]; 915 933 #endif 916 934 … … 1746 1764 RetainPtr<NSMutableSet> oldTracks = adoptNS([[NSMutableSet alloc] initWithCapacity:oldItems.size()]); 1747 1765 1748 typedef Vector<RefT> ItemVector; 1749 for (auto i = oldItems.begin(); i != oldItems.end(); ++i) 1750 [oldTracks addObject:(*i)->playerItemTrack()]; 1751 1766 for (auto& oldItem : oldItems) { 1767 if (oldItem->playerItemTrack()) 1768 [oldTracks addObject:oldItem->playerItemTrack()]; 1769 } 1770 1771 // Find the added & removed AVPlayerItemTracks: 1752 1772 RetainPtr<NSMutableSet> removedTracks = adoptNS([oldTracks mutableCopy]); 1753 1773 [removedTracks minusSet:newTracks.get()]; … … 1756 1776 [addedTracks minusSet:oldTracks.get()]; 1757 1777 1778 typedef Vector<RefT> ItemVector; 1758 1779 ItemVector replacementItems; 1759 1780 ItemVector addedItems; 1760 1781 ItemVector removedItems; 1761 for (auto i = oldItems.begin(); i != oldItems.end(); ++i) {1762 if ( [removedTracks containsObject:(*i)->playerItemTrack()])1763 removedItems.append( *i);1782 for (auto& oldItem : oldItems) { 1783 if (oldItem->playerItemTrack() && [removedTracks containsObject:oldItem->playerItemTrack()]) 1784 removedItems.append(oldItem); 1764 1785 else 1765 replacementItems.append( *i);1786 replacementItems.append(oldItem); 1766 1787 } 1767 1788 … … 1772 1793 oldItems.swap(replacementItems); 1773 1794 1774 for (auto i = removedItems.begin(); i != removedItems.end(); ++i) 1775 (player->*removedFunction)(*i); 1776 1777 for (auto i = addedItems.begin(); i != addedItems.end(); ++i) 1778 (player->*addedFunction)(*i); 1779 } 1795 for (auto& removedItem : removedItems) 1796 (player->*removedFunction)(removedItem); 1797 1798 for (auto& addedItem : addedItems) 1799 (player->*addedFunction)(addedItem); 1800 } 1801 1802 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) 1803 template <typename RefT, typename PassRefT> 1804 void determineChangedTracksFromNewTracksAndOldItems(MediaSelectionGroupAVFObjC* group, Vector<RefT>& oldItems, RefT (*itemFactory)(MediaSelectionOptionAVFObjC&), MediaPlayer* player, void (MediaPlayer::*removedFunction)(PassRefT), void (MediaPlayer::*addedFunction)(PassRefT)) 1805 { 1806 group->updateOptions(); 1807 1808 // Only add selection options which do not have an associated persistant track. 1809 ListHashSet<RefPtr<MediaSelectionOptionAVFObjC>> newSelectionOptions; 1810 for (auto& option : group->options()) { 1811 if (!option) 1812 continue; 1813 AVMediaSelectionOptionType* avOption = option->avMediaSelectionOption(); 1814 if (!avOption) 1815 continue; 1816 if (![avOption respondsToSelector:@selector(track)] || ![avOption performSelector:@selector(track)]) 1817 newSelectionOptions.add(option); 1818 } 1819 1820 ListHashSet<RefPtr<MediaSelectionOptionAVFObjC>> oldSelectionOptions; 1821 for (auto& oldItem : oldItems) { 1822 if (MediaSelectionOptionAVFObjC *option = oldItem->mediaSelectionOption()) 1823 oldSelectionOptions.add(option); 1824 } 1825 1826 // Find the added & removed AVMediaSelectionOptions: 1827 ListHashSet<RefPtr<MediaSelectionOptionAVFObjC>> removedSelectionOptions; 1828 for (auto& oldOption : oldSelectionOptions) { 1829 if (!newSelectionOptions.contains(oldOption)) 1830 removedSelectionOptions.add(oldOption); 1831 } 1832 1833 ListHashSet<RefPtr<MediaSelectionOptionAVFObjC>> addedSelectionOptions; 1834 for (auto& newOption : newSelectionOptions) { 1835 if (!oldSelectionOptions.contains(newOption)) 1836 addedSelectionOptions.add(newOption); 1837 } 1838 1839 typedef Vector<RefT> ItemVector; 1840 ItemVector replacementItems; 1841 ItemVector addedItems; 1842 ItemVector removedItems; 1843 for (auto& oldItem : oldItems) { 1844 if (oldItem->mediaSelectionOption() && removedSelectionOptions.contains(oldItem->mediaSelectionOption())) 1845 removedItems.append(oldItem); 1846 else 1847 replacementItems.append(oldItem); 1848 } 1849 1850 for (auto& option : addedSelectionOptions) 1851 addedItems.append(itemFactory(*option.get())); 1852 1853 replacementItems.appendVector(addedItems); 1854 oldItems.swap(replacementItems); 1855 1856 for (auto& removedItem : removedItems) 1857 (player->*removedFunction)(removedItem); 1858 1859 for (auto& addedItem : addedItems) 1860 (player->*addedFunction)(addedItem); 1861 } 1862 #endif 1780 1863 1781 1864 void MediaPlayerPrivateAVFoundationObjC::updateAudioTracks() … … 1787 1870 determineChangedTracksFromNewTracksAndOldItems(m_cachedTracks.get(), AVMediaTypeAudio, m_audioTracks, &AudioTrackPrivateAVFObjC::create, player(), &MediaPlayer::removeAudioTrack, &MediaPlayer::addAudioTrack); 1788 1871 1872 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) 1873 if (!m_audibleGroup) { 1874 if (AVMediaSelectionGroupType *group = safeMediaSelectionGroupForAudibleMedia()) 1875 m_audibleGroup = MediaSelectionGroupAVFObjC::create(m_avPlayerItem.get(), group); 1876 } 1877 1878 if (m_audibleGroup) 1879 determineChangedTracksFromNewTracksAndOldItems(m_audibleGroup.get(), m_audioTracks, &AudioTrackPrivateAVFObjC::create, player(), &MediaPlayer::removeAudioTrack, &MediaPlayer::addAudioTrack); 1880 #endif 1881 1882 for (auto& track : m_audioTracks) 1883 track->resetPropertiesFromTrack(); 1884 1789 1885 #if !LOG_DISABLED 1790 1886 LOG(Media, "MediaPlayerPrivateAVFoundationObjC::updateAudioTracks(%p) - audio track count was %lu, is %lu", this, count, m_audioTracks.size()); … … 1799 1895 1800 1896 determineChangedTracksFromNewTracksAndOldItems(m_cachedTracks.get(), AVMediaTypeVideo, m_videoTracks, &VideoTrackPrivateAVFObjC::create, player(), &MediaPlayer::removeVideoTrack, &MediaPlayer::addVideoTrack); 1897 1898 #if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) 1899 if (!m_visualGroup) { 1900 if (AVMediaSelectionGroupType *group = safeMediaSelectionGroupForVisualMedia()) 1901 m_visualGroup = MediaSelectionGroupAVFObjC::create(m_avPlayerItem.get(), group); 1902 } 1903 1904 if (m_visualGroup) 1905 determineChangedTracksFromNewTracksAndOldItems(m_visualGroup.get(), m_videoTracks, &VideoTrackPrivateAVFObjC::create, player(), &MediaPlayer::removeVideoTrack, &MediaPlayer::addVideoTrack); 1906 #endif 1907 1908 for (auto& track : m_audioTracks) 1909 track->resetPropertiesFromTrack(); 1801 1910 1802 1911 #if !LOG_DISABLED … … 2211 2320 2212 2321 return [m_avAsset.get() mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible]; 2322 } 2323 2324 AVMediaSelectionGroupType* MediaPlayerPrivateAVFoundationObjC::safeMediaSelectionGroupForAudibleMedia() 2325 { 2326 if (!m_avAsset) 2327 return nil; 2328 2329 if ([m_avAsset.get() statusOfValueForKey:@"availableMediaCharacteristicsWithMediaSelectionOptions" error:NULL] != AVKeyValueStatusLoaded) 2330 return nil; 2331 2332 return [m_avAsset.get() mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicAudible]; 2333 } 2334 2335 AVMediaSelectionGroupType* MediaPlayerPrivateAVFoundationObjC::safeMediaSelectionGroupForVisualMedia() 2336 { 2337 if (!m_avAsset) 2338 return nil; 2339 2340 if ([m_avAsset.get() statusOfValueForKey:@"availableMediaCharacteristicsWithMediaSelectionOptions" error:NULL] != AVKeyValueStatusLoaded) 2341 return nil; 2342 2343 return [m_avAsset.get() mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicVisual]; 2213 2344 } 2214 2345 … … 2603 2734 [track removeObserver:m_objcObserver.get() forKeyPath:@"enabled"]; 2604 2735 2605 m_cachedTracks = tracks; 2736 NSArray *assetTracks = [m_avAsset tracks]; 2737 2738 // Tracks which are not present in the AVAsset are streaming tracks, and will instead be represented by 2739 // AVMediaSelectionOptions. 2740 m_cachedTracks = [tracks objectsAtIndexes:[tracks indexesOfObjectsPassingTest:^(id obj, NSUInteger, BOOL*) { 2741 return [assetTracks containsObject:[obj assetTrack]]; 2742 }]]; 2743 2606 2744 for (AVPlayerItemTrack *track in m_cachedTracks.get()) 2607 2745 [track addObserver:m_objcObserver.get() forKeyPath:@"enabled" options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextPlayerItemTrack]; -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.cpp
r174402 r174823 27 27 #import "VideoTrackPrivateAVFObjC.h" 28 28 #import "AVTrackPrivateAVFObjCImpl.h" 29 #import "MediaSelectionGroupAVFObjC.h" 29 30 30 31 #if ENABLE(VIDEO_TRACK) … … 40 41 VideoTrackPrivateAVFObjC::VideoTrackPrivateAVFObjC(AVAssetTrack* track) 41 42 : m_impl(std::make_unique<AVTrackPrivateAVFObjCImpl>(track)) 43 { 44 resetPropertiesFromTrack(); 45 } 46 47 VideoTrackPrivateAVFObjC::VideoTrackPrivateAVFObjC(MediaSelectionOptionAVFObjC& option) 48 : m_impl(std::make_unique<AVTrackPrivateAVFObjCImpl>(option)) 42 49 { 43 50 resetPropertiesFromTrack(); … … 79 86 } 80 87 88 void VideoTrackPrivateAVFObjC::setMediaSelectonOption(MediaSelectionOptionAVFObjC& option) 89 { 90 m_impl = std::make_unique<AVTrackPrivateAVFObjCImpl>(option); 91 resetPropertiesFromTrack(); 92 } 93 94 MediaSelectionOptionAVFObjC* VideoTrackPrivateAVFObjC::mediaSelectionOption() 95 { 96 return m_impl->mediaSelectionOption(); 97 } 98 81 99 void VideoTrackPrivateAVFObjC::setSelected(bool enabled) 82 100 { -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.h
r162158 r174823 32 32 33 33 OBJC_CLASS AVAssetTrack; 34 OBJC_CLASS AVPlayerItem; 34 35 OBJC_CLASS AVPlayerItemTrack; 36 OBJC_CLASS AVMediaSelectionGroup; 37 OBJC_CLASS AVMediaSelectionOption; 35 38 36 39 namespace WebCore { 37 40 38 41 class AVTrackPrivateAVFObjCImpl; 42 class MediaSelectionOptionAVFObjC; 39 43 40 44 class VideoTrackPrivateAVFObjC final : public VideoTrackPrivateAVF { … … 51 55 } 52 56 57 static RefPtr<VideoTrackPrivateAVFObjC> create(MediaSelectionOptionAVFObjC& option) 58 { 59 return adoptRef(new VideoTrackPrivateAVFObjC(option)); 60 } 61 53 62 virtual void setSelected(bool) override; 54 63 … … 59 68 AVAssetTrack* assetTrack(); 60 69 70 void setMediaSelectonOption(MediaSelectionOptionAVFObjC&); 71 MediaSelectionOptionAVFObjC* mediaSelectionOption(); 72 61 73 private: 62 74 explicit VideoTrackPrivateAVFObjC(AVPlayerItemTrack*); 63 75 explicit VideoTrackPrivateAVFObjC(AVAssetTrack*); 76 explicit VideoTrackPrivateAVFObjC(MediaSelectionOptionAVFObjC&); 64 77 65 78 void resetPropertiesFromTrack(); -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoTrackPrivateMediaSourceAVFObjC.mm
r165676 r174823 48 48 m_trackID = m_impl->trackID(); 49 49 50 setTrackIndex(m_impl->index()); 50 51 setKind(m_impl->videoKind()); 51 52 setId(m_impl->id());
Note: See TracChangeset
for help on using the changeset viewer.