Changeset 174823 in webkit


Ignore:
Timestamp:
Oct 17, 2014 9:40:14 AM (10 years ago)
Author:
jer.noble@apple.com
Message:

[Mac] Represent AVMediaSelectionOptions as AudioTracks
https://bugs.webkit.org/show_bug.cgi?id=137474

Reviewed by Brent Fulgham.

Source/WebCore:

Test: http/tests/media/hls/hls-audio-tracks.html

Support selecting audio "tracks" in HLS streams by exposing AVMediaSelectionOptions
as entries in the video's AudioTrackList.

AVMediaSessionGroups and AVPlayerItems don't have KVO or notifications to track when options
are selected and deselected, so wrap AVMediaSessionGroup and AVMediaSessionOption in C++
wrappers. Each AVMediaSelectionGroup can have only one AVMediaSelectionOption selected at a
time, so the wrapper will take care of answering which AVMediaSelectionOption is currently
selected, as without KVO notifications, asking the AVMediaSelectionGroup directly is
inconsistent. Because setting the selected option multiple times in the same run-loop can
cause flakiness, coalesce calls to setSelectedOption() by setting a one-shot timer to do
the actual selection in the next run-loop.

  • platform/graphics/avfoundation/MediaSelectionGroupAVFObjC.h: Added.

(WebCore::MediaSelectionOptionAVFObjC::avMediaSelectionOption):
(WebCore::MediaSelectionOptionAVFObjC::clearGroup): Clear backpointer to group from option.
(WebCore::MediaSelectionGroupAVFObjC::selectedOption): Simple accessor.
(WebCore::MediaSelectionGroupAVFObjC::options): Simple accessor.
(WebCore::MediaSelectionGroupAVFObjC::avMediaSelectionGroup): Simple accessor.

  • platform/graphics/avfoundation/MediaSelectionGroupAVFObjC.mm: Added.

(WebCore::MediaSelectionOptionAVFObjC::create): Simple factory method.
(WebCore::MediaSelectionOptionAVFObjC::MediaSelectionOptionAVFObjC): Simple constructor.
(WebCore::MediaSelectionOptionAVFObjC::setSelected): Pass through to MediaSelectionGroupAVFObjC.
(WebCore::MediaSelectionOptionAVFObjC::selected): Ditto.
(WebCore::MediaSelectionOptionAVFObjC::index): Return index of this object in the group's object.
(WebCore::MediaSelectionGroupAVFObjC::create):
(WebCore::MediaSelectionGroupAVFObjC::MediaSelectionGroupAVFObjC):
(WebCore::MediaSelectionGroupAVFObjC::~MediaSelectionGroupAVFObjC):
(WebCore::MediaSelectionGroupAVFObjC::updateOptions): Discover added or removed options.
(WebCore::MediaSelectionGroupAVFObjC::setSelectedOption): Set a one shot timer to coalesce multiple calls.
(WebCore::MediaSelectionGroupAVFObjC::selectionTimerFired): Set the selected AVSelectionOption.

Modify AVTrackPrivateAVFObjCImpl to support both AVPlayerItemTracks and these new
MediaSelectionOptionAVFObjC objects.

  • platform/graphics/avfoundation/AVTrackPrivateAVFObjCImpl.h:

(WebCore::AVTrackPrivateAVFObjCImpl::mediaSelectionOption): Simple accessor.

  • platform/graphics/avfoundation/AVTrackPrivateAVFObjCImpl.mm:

(WebCore::AVTrackPrivateAVFObjCImpl::AVTrackPrivateAVFObjCImpl): Simple constructor.
(WebCore::AVTrackPrivateAVFObjCImpl::~AVTrackPrivateAVFObjCImpl): Simple destructor.
(WebCore::AVTrackPrivateAVFObjCImpl::enabled): Use MediaSelectionOptionAVFObjC, if present.
(WebCore::AVTrackPrivateAVFObjCImpl::setEnabled): Ditto.
(WebCore::AVTrackPrivateAVFObjCImpl::audioKind): Ditto.
(WebCore::AVTrackPrivateAVFObjCImpl::videoKind): Ditto.
(WebCore::AVTrackPrivateAVFObjCImpl::index): Ditto.
(WebCore::AVTrackPrivateAVFObjCImpl::id): Ditto.
(WebCore::AVTrackPrivateAVFObjCImpl::label): Ditto.
(WebCore::AVTrackPrivateAVFObjCImpl::language): Ditto.
(WebCore::AVTrackPrivateAVFObjCImpl::languageForAVMediaSelectionOption): Ditto.
(WebCore::AVTrackPrivateAVFObjCImpl::trackID): Ditto.

Allow AudioTrackPrivateAVFObjC and VideoTrackPrivateAVFObjC to be created with
a MediaSelectionOptionAVFObjC.

  • platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.h:

(WebCore::AudioTrackPrivateAVFObjC::create): Takes a MediaSelectionOptionAVFObjC.

  • platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm:

(WebCore::AudioTrackPrivateAVFObjC::AudioTrackPrivateAVFObjC): Simple constructor.
(WebCore::AudioTrackPrivateAVFObjC::setMediaSelectionOption): Create a new AVTrackPrivateAVFObjCImpl.
(WebCore::AudioTrackPrivateAVFObjC::mediaSelectionOption): Simple accessor.

  • platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.cpp:

(WebCore::VideoTrackPrivateAVFObjC::VideoTrackPrivateAVFObjC): Simple constructor.
(WebCore::VideoTrackPrivateAVFObjC::setMediaSelectonOption): Create a new AVTrackPrivateAVFObjCImpl.
(WebCore::VideoTrackPrivateAVFObjC::mediaSelectionOption): Simple accessor.

  • platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.h:

Because IDs are not necessarily unique across AVPlayerItemTracks and AVMediaSelectionOptions,
use the index of the track or option instead of it's self-declared ID for ordering for the
trackIndex.

  • platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm:

(WebCore::AudioTrackPrivateAVFObjC::resetPropertiesFromTrack):

  • platform/graphics/avfoundation/objc/VideoTrackPrivateMediaSourceAVFObjC.mm:

(WebCore::VideoTrackPrivateMediaSourceAVFObjC::resetPropertiesFromTrack):

Rather than making allowing the AVPlayerItem to automatically select the "best"
AVMediaSelectionOption, select the automatic options when creating the AVPlayerItem
and thereafter allow the users manual selections "stick".

  • platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
  • platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:

(WebCore::MediaPlayerPrivateAVFoundationObjC::ensureAVPlayer):
(WebCore::MediaPlayerPrivateAVFoundationObjC::ensureAVPlayerItem):

Determine whether any MediaSelectionOptionsAVFObjC have been added or removed and send trackChange events accordingly.

  • platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:

(WebCore::determineChangedTracksFromNewTracksAndOldItems): Added.
(WebCore::MediaPlayerPrivateAVFoundationObjC::updateAudioTracks): Search for updated selection options.
(WebCore::MediaPlayerPrivateAVFoundationObjC::updateVideoTracks): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationObjC::safeMediaSelectionGroupForAudibleMedia): Return selection group, if available.
(WebCore::MediaPlayerPrivateAVFoundationObjC::safeMediaSelectionGroupForVisualMedia): Ditto.
(WebCore::MediaPlayerPrivateAVFoundationObjC::tracksDidChange): Filter out AVPlayerItemTracks without

AVAssetTracks, as these will be represented by MediaSelectionGroupObjCs instead.

Add new files to project.

  • WebCore.xcodeproj/project.pbxproj:

LayoutTests:

  • http/tests/media/hls/hls-audio-tracks-expected.txt: Added.
  • http/tests/media/hls/hls-audio-tracks.html: Added.
  • http/tests/media/resources/hls/audio-tracks.m3u8: Added.
  • http/tests/media/resources/hls/bipbop/iframe_index.m3u8: Added.
  • http/tests/media/resources/hls/bipbop/main0.ts: Added.
  • http/tests/media/resources/hls/bipbop/main1.ts: Added.
  • http/tests/media/resources/hls/bipbop/prog_index.m3u8: Added.
  • http/tests/media/resources/hls/french/main.aac: Added.
  • http/tests/media/resources/hls/french/prog_index.m3u8: Added.
  • http/tests/media/resources/hls/spanish/main.aac: Added.
  • http/tests/media/resources/hls/spanish/prog_index.m3u8: Added.
Location:
trunk
Files:
16 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r174822 r174823  
     12014-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
    1202014-10-17  Brent Fulgham  <bfulgham@apple.com>
    221
  • trunk/Source/WebCore/ChangeLog

    r174819 r174823  
     12014-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
    11072014-10-17  Grzegorz Czajkowski  <g.czajkowski@samsung.com>
    2108
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r174583 r174823  
    56855685                CDB859F7160D48A400E5B07F /* MediaKeyEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDB859F4160D489900E5B07F /* MediaKeyEvent.cpp */; };
    56865686                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 */; };
    56875689                CDC26B40160A8CC60026757B /* MockCDM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDC26B3C160A62B00026757B /* MockCDM.cpp */; };
    56885690                CDC26B41160A8CCE0026757B /* MockCDM.h in Headers */ = {isa = PBXBuildFile; fileRef = CDC26B3D160A62B00026757B /* MockCDM.h */; };
     
    1314913151                CDB859F8160D493E00E5B07F /* JSMediaKeyEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaKeyEvent.cpp; sourceTree = "<group>"; };
    1315013152                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>"; };
    1315113155                CDC1DD4117CC2C48008CB55D /* mediaControlsApple.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = mediaControlsApple.css; sourceTree = "<group>"; };
    1315213156                CDC26B3C160A62B00026757B /* MockCDM.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MockCDM.cpp; sourceTree = "<group>"; };
     
    2164321647                                CD8A7BB9197735FE00CBD643 /* AudioSourceProviderAVFObjC.mm */,
    2164421648                                CD8A7BBA197735FE00CBD643 /* AudioSourceProviderAVFObjC.h */,
     21649                                CDBEAEAA19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm */,
     21650                                CDBEAEAB19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h */,
    2164521651                        );
    2164621652                        name = objc;
     
    2386423870                                BC1A37B5097C715F0019F3D8 /* DOMExtensions.h in Headers */,
    2386523871                                BC00F0040E0A185500FD04E3 /* DOMFile.h in Headers */,
     23872                                CDBEAEAD19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.h in Headers */,
    2386623873                                2E3BC108117D479800B9409A /* DOMFileError.h in Headers */,
    2386723874                                2E3BC10B117D47C800B9409A /* DOMFileErrorInternal.h in Headers */,
     
    2817228179                                590E1B4B11E4EF700069F784 /* JSDeviceOrientationEventCustom.cpp in Sources */,
    2817328180                                BCE438A2140C0DC0005E437E /* JSDictionary.cpp in Sources */,
     28181                                CDBEAEAC19D92B6C00BEBA88 /* MediaSelectionGroupAVFObjC.mm in Sources */,
    2817428182                                659DDC8209E198BA001BF3C6 /* JSDocument.cpp in Sources */,
    2817528183                                49C7BA8D1042F5B10009D447 /* JSDocumentCustom.cpp in Sources */,
  • trunk/Source/WebCore/platform/graphics/avfoundation/AVTrackPrivateAVFObjCImpl.h

    r165676 r174823  
    3232#include "VideoTrackPrivate.h"
    3333#include <wtf/OwnPtr.h>
     34#include <wtf/Ref.h>
    3435#include <wtf/RetainPtr.h>
    3536
    3637OBJC_CLASS AVAssetTrack;
     38OBJC_CLASS AVPlayerItem;
    3739OBJC_CLASS AVPlayerItemTrack;
     40OBJC_CLASS AVMediaSelectionGroup;
     41OBJC_CLASS AVMediaSelectionOption;
    3842
    3943namespace WebCore {
     44
     45class MediaSelectionOptionAVFObjC;
    4046
    4147class AVTrackPrivateAVFObjCImpl {
     
    4349    explicit AVTrackPrivateAVFObjCImpl(AVPlayerItemTrack*);
    4450    explicit AVTrackPrivateAVFObjCImpl(AVAssetTrack*);
     51    explicit AVTrackPrivateAVFObjCImpl(MediaSelectionOptionAVFObjC&);
     52    ~AVTrackPrivateAVFObjCImpl();
    4553
    4654    AVPlayerItemTrack* playerItemTrack() const { return m_playerItemTrack.get(); }
    4755    AVAssetTrack* assetTrack() const { return m_assetTrack.get(); }
     56    MediaSelectionOptionAVFObjC* mediaSelectionOption() const { return m_mediaSelectionOption.get(); }
    4857
    4958    bool enabled() const;
     
    5362    VideoTrackPrivate::Kind videoKind() const;
    5463
     64    int index() const;
    5565    AtomicString id() const;
    5666    AtomicString label() const;
     
    6070
    6171    static String languageForAVAssetTrack(AVAssetTrack*);
     72    static String languageForAVMediaSelectionOption(AVMediaSelectionOption *);
    6273
    6374private:
    6475    RetainPtr<AVPlayerItemTrack> m_playerItemTrack;
    6576    RetainPtr<AVAssetTrack> m_assetTrack;
     77    RetainPtr<AVPlayerItem> m_playerItem;
     78    RefPtr<MediaSelectionOptionAVFObjC> m_mediaSelectionOption;
    6679};
    6780
  • trunk/Source/WebCore/platform/graphics/avfoundation/AVTrackPrivateAVFObjCImpl.mm

    r165676 r174823  
    2929#if ENABLE(VIDEO_TRACK)
    3030
     31#import "MediaSelectionGroupAVFObjC.h"
    3132#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>
    3238#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
    3644
    3745SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
    3846
    3947SOFT_LINK_CLASS(AVFoundation, AVAssetTrack)
     48SOFT_LINK_CLASS(AVFoundation, AVPlayerItem)
    4049SOFT_LINK_CLASS(AVFoundation, AVPlayerItemTrack)
     50SOFT_LINK_CLASS(AVFoundation, AVMediaSelectionGroup)
     51SOFT_LINK_CLASS(AVFoundation, AVMediaSelectionOption)
    4152SOFT_LINK_CLASS(AVFoundation, AVMetadataItem)
    4253
     
    7081}
    7182
     83AVTrackPrivateAVFObjCImpl::AVTrackPrivateAVFObjCImpl(MediaSelectionOptionAVFObjC& option)
     84    : m_mediaSelectionOption(&option)
     85{
     86}
     87
     88AVTrackPrivateAVFObjCImpl::~AVTrackPrivateAVFObjCImpl()
     89{
     90}
     91   
    7292bool AVTrackPrivateAVFObjCImpl::enabled() const
    7393{
    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;
    76100}
    77101
    78102void AVTrackPrivateAVFObjCImpl::setEnabled(bool enabled)
    79103{
    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();
    82110}
    83111
    84112AudioTrackPrivate::Kind AVTrackPrivateAVFObjCImpl::audioKind() const
    85113{
    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();
    90132    return AudioTrackPrivate::None;
    91133}
     
    93135VideoTrackPrivate::Kind AVTrackPrivateAVFObjCImpl::videoKind() const
    94136{
    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();
    103163    return VideoTrackPrivate::None;
    104164}
    105165
     166int 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
    106176AtomicString AVTrackPrivateAVFObjCImpl::id() const
    107177{
    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;
    109184}
    110185
    111186AtomicString AVTrackPrivateAVFObjCImpl::label() const
    112187{
    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];
    114197    if (![titles count])
    115198        return emptyAtom;
     
    124207AtomicString AVTrackPrivateAVFObjCImpl::language() const
    125208{
    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;
    127216}
    128217
     
    144233}
    145234
     235String 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
    146256int AVTrackPrivateAVFObjCImpl::trackID() const
    147257{
    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;
    149264}
    150265
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.h

    r159368 r174823  
    3232#include <wtf/OwnPtr.h>
    3333
     34OBJC_CLASS AVAssetTrack;
     35OBJC_CLASS AVPlayerItem;
    3436OBJC_CLASS AVPlayerItemTrack;
    35 OBJC_CLASS AVAssetTrack;
     37OBJC_CLASS AVMediaSelectionGroup;
     38OBJC_CLASS AVMediaSelectionOption;
    3639
    3740namespace WebCore {
    3841
    3942class AVTrackPrivateAVFObjCImpl;
     43class MediaSelectionOptionAVFObjC;
    4044
    4145class AudioTrackPrivateAVFObjC : public AudioTrackPrivateAVF {
     
    5256    }
    5357
     58    static RefPtr<AudioTrackPrivateAVFObjC> create(MediaSelectionOptionAVFObjC& option)
     59    {
     60        return adoptRef(new AudioTrackPrivateAVFObjC(option));
     61    }
     62
    5463    virtual void setEnabled(bool);
    5564
     
    6069    AVAssetTrack* assetTrack();
    6170
     71    void setMediaSelectionOption(MediaSelectionOptionAVFObjC&);
     72    MediaSelectionOptionAVFObjC* mediaSelectionOption();
     73
    6274private:
     75    friend class MediaPlayerPrivateAVFoundationObjC;
    6376    AudioTrackPrivateAVFObjC(AVPlayerItemTrack*);
    6477    AudioTrackPrivateAVFObjC(AVAssetTrack*);
     78    AudioTrackPrivateAVFObjC(MediaSelectionOptionAVFObjC&);
    6579
    6680    void resetPropertiesFromTrack();
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/AudioTrackPrivateAVFObjC.mm

    r174402 r174823  
    2727#import "AudioTrackPrivateAVFObjC.h"
    2828#import "AVTrackPrivateAVFObjCImpl.h"
     29#import "MediaSelectionGroupAVFObjC.h"
    2930
    3031#if ENABLE(VIDEO_TRACK)
     
    3839}
    3940
     41AudioTrackPrivateAVFObjC::AudioTrackPrivateAVFObjC(MediaSelectionOptionAVFObjC& option)
     42    : m_impl(std::make_unique<AVTrackPrivateAVFObjCImpl>(option))
     43{
     44    resetPropertiesFromTrack();
     45}
     46
    4047void AudioTrackPrivateAVFObjC::resetPropertiesFromTrack()
    4148{
     
    4451    AudioTrackPrivateAVF::setEnabled(m_impl->enabled());
    4552
    46     setTrackIndex(m_impl->trackID());
     53    setTrackIndex(m_impl->index());
    4754    setKind(m_impl->audioKind());
    4855    setId(m_impl->id());
     
    7986}
    8087
     88void AudioTrackPrivateAVFObjC::setMediaSelectionOption(MediaSelectionOptionAVFObjC& option)
     89{
     90    m_impl = std::make_unique<AVTrackPrivateAVFObjCImpl>(option);
     91    resetPropertiesFromTrack();
     92}
     93
     94MediaSelectionOptionAVFObjC* AudioTrackPrivateAVFObjC::mediaSelectionOption()
     95{
     96    return m_impl->mediaSelectionOption();
     97}
     98
    8199void AudioTrackPrivateAVFObjC::setEnabled(bool enabled)
    82100{
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h

    r173628 r174823  
    6565class AudioSourceProviderAVFObjC;
    6666class AudioTrackPrivateAVFObjC;
     67class MediaSelectionGroupAVFObjC;
    6768class VideoTrackPrivateAVFObjC;
    6869
     
    246247    void processMediaSelectionOptions();
    247248    AVMediaSelectionGroup* safeMediaSelectionGroupForLegibleMedia();
     249    AVMediaSelectionGroup* safeMediaSelectionGroupForAudibleMedia();
     250    AVMediaSelectionGroup* safeMediaSelectionGroupForVisualMedia();
    248251#endif
    249252
     
    326329    Vector<RefPtr<AudioTrackPrivateAVFObjC>> m_audioTracks;
    327330    Vector<RefPtr<VideoTrackPrivateAVFObjC>> m_videoTracks;
     331#if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP)
     332    RefPtr<MediaSelectionGroupAVFObjC> m_audibleGroup;
     333    RefPtr<MediaSelectionGroupAVFObjC> m_visualGroup;
     334#endif
    328335#endif
    329336
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm

    r174563 r174823  
    4747#import "URL.h"
    4848#import "Logging.h"
     49#import "MediaSelectionGroupAVFObjC.h"
    4950#import "MediaTimeAVFoundation.h"
    5051#import "PlatformTimeRanges.h"
     
    6768#import <wtf/CurrentTime.h>
    6869#import <wtf/Functional.h>
     70#import <wtf/ListHashSet.h>
    6971#import <wtf/NeverDestroyed.h>
    7072#import <wtf/text/CString.h>
     
    8890#import <VideoToolbox/VideoToolbox.h>
    8991#endif
     92
     93namespace std {
     94template <> struct iterator_traits<HashSet<RefPtr<WebCore::MediaSelectionOptionAVFObjC>>::iterator> {
     95    typedef RefPtr<WebCore::MediaSelectionOptionAVFObjC> value_type;
     96};
     97}
    9098
    9199@interface WebVideoContainerLayer : CALayer
     
    124132typedef AVPlayer AVPlayerType;
    125133typedef AVPlayerItem AVPlayerItemType;
     134typedef AVPlayerItemLegibleOutput AVPlayerItemLegibleOutputType;
     135typedef AVPlayerItemVideoOutput AVPlayerItemVideoOutputType;
    126136typedef AVMetadataItem AVMetadataItemType;
     137typedef AVMediaSelectionGroup AVMediaSelectionGroupType;
     138typedef AVMediaSelectionOption AVMediaSelectionOptionType;
    127139
    128140SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
     
    859871
    860872#if HAVE(AVFOUNDATION_MEDIA_SELECTION_GROUP) && HAVE(AVFOUNDATION_LEGIBLE_OUTPUT_SUPPORT)
    861     [m_avPlayer.get() setAppliesMediaSelectionCriteriaAutomatically:YES];
     873    [m_avPlayer.get() setAppliesMediaSelectionCriteriaAutomatically:NO];
    862874#endif
    863875
     
    913925    [m_legibleOutput.get() setTextStylingResolution:AVPlayerItemLegibleOutputTextStylingResolutionSourceAndRulesOnly];
    914926    [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()];
    915933#endif
    916934
     
    17461764    RetainPtr<NSMutableSet> oldTracks = adoptNS([[NSMutableSet alloc] initWithCapacity:oldItems.size()]);
    17471765
    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:
    17521772    RetainPtr<NSMutableSet> removedTracks = adoptNS([oldTracks mutableCopy]);
    17531773    [removedTracks minusSet:newTracks.get()];
     
    17561776    [addedTracks minusSet:oldTracks.get()];
    17571777
     1778    typedef Vector<RefT> ItemVector;
    17581779    ItemVector replacementItems;
    17591780    ItemVector addedItems;
    17601781    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);
    17641785        else
    1765             replacementItems.append(*i);
     1786            replacementItems.append(oldItem);
    17661787    }
    17671788
     
    17721793    oldItems.swap(replacementItems);
    17731794
    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)
     1803template <typename RefT, typename PassRefT>
     1804void 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
    17801863
    17811864void MediaPlayerPrivateAVFoundationObjC::updateAudioTracks()
     
    17871870    determineChangedTracksFromNewTracksAndOldItems(m_cachedTracks.get(), AVMediaTypeAudio, m_audioTracks, &AudioTrackPrivateAVFObjC::create, player(), &MediaPlayer::removeAudioTrack, &MediaPlayer::addAudioTrack);
    17881871
     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
    17891885#if !LOG_DISABLED
    17901886    LOG(Media, "MediaPlayerPrivateAVFoundationObjC::updateAudioTracks(%p) - audio track count was %lu, is %lu", this, count, m_audioTracks.size());
     
    17991895
    18001896    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();
    18011910
    18021911#if !LOG_DISABLED
     
    22112320   
    22122321    return [m_avAsset.get() mediaSelectionGroupForMediaCharacteristic:AVMediaCharacteristicLegible];
     2322}
     2323
     2324AVMediaSelectionGroupType* 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
     2335AVMediaSelectionGroupType* 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];
    22132344}
    22142345
     
    26032734        [track removeObserver:m_objcObserver.get() forKeyPath:@"enabled"];
    26042735
    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
    26062744    for (AVPlayerItemTrack *track in m_cachedTracks.get())
    26072745        [track addObserver:m_objcObserver.get() forKeyPath:@"enabled" options:NSKeyValueObservingOptionNew context:(void *)MediaPlayerAVFoundationObservationContextPlayerItemTrack];
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.cpp

    r174402 r174823  
    2727#import "VideoTrackPrivateAVFObjC.h"
    2828#import "AVTrackPrivateAVFObjCImpl.h"
     29#import "MediaSelectionGroupAVFObjC.h"
    2930
    3031#if ENABLE(VIDEO_TRACK)
     
    4041VideoTrackPrivateAVFObjC::VideoTrackPrivateAVFObjC(AVAssetTrack* track)
    4142    : m_impl(std::make_unique<AVTrackPrivateAVFObjCImpl>(track))
     43{
     44    resetPropertiesFromTrack();
     45}
     46
     47VideoTrackPrivateAVFObjC::VideoTrackPrivateAVFObjC(MediaSelectionOptionAVFObjC& option)
     48    : m_impl(std::make_unique<AVTrackPrivateAVFObjCImpl>(option))
    4249{
    4350    resetPropertiesFromTrack();
     
    7986}
    8087
     88void VideoTrackPrivateAVFObjC::setMediaSelectonOption(MediaSelectionOptionAVFObjC& option)
     89{
     90    m_impl = std::make_unique<AVTrackPrivateAVFObjCImpl>(option);
     91    resetPropertiesFromTrack();
     92}
     93
     94MediaSelectionOptionAVFObjC* VideoTrackPrivateAVFObjC::mediaSelectionOption()
     95{
     96    return m_impl->mediaSelectionOption();
     97}
     98
    8199void VideoTrackPrivateAVFObjC::setSelected(bool enabled)
    82100{
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoTrackPrivateAVFObjC.h

    r162158 r174823  
    3232
    3333OBJC_CLASS AVAssetTrack;
     34OBJC_CLASS AVPlayerItem;
    3435OBJC_CLASS AVPlayerItemTrack;
     36OBJC_CLASS AVMediaSelectionGroup;
     37OBJC_CLASS AVMediaSelectionOption;
    3538
    3639namespace WebCore {
    3740
    3841class AVTrackPrivateAVFObjCImpl;
     42class MediaSelectionOptionAVFObjC;
    3943
    4044class VideoTrackPrivateAVFObjC final : public VideoTrackPrivateAVF {
     
    5155    }
    5256
     57    static RefPtr<VideoTrackPrivateAVFObjC> create(MediaSelectionOptionAVFObjC& option)
     58    {
     59        return adoptRef(new VideoTrackPrivateAVFObjC(option));
     60    }
     61
    5362    virtual void setSelected(bool) override;
    5463
     
    5968    AVAssetTrack* assetTrack();
    6069
     70    void setMediaSelectonOption(MediaSelectionOptionAVFObjC&);
     71    MediaSelectionOptionAVFObjC* mediaSelectionOption();
     72
    6173private:
    6274    explicit VideoTrackPrivateAVFObjC(AVPlayerItemTrack*);
    6375    explicit VideoTrackPrivateAVFObjC(AVAssetTrack*);
     76    explicit VideoTrackPrivateAVFObjC(MediaSelectionOptionAVFObjC&);
    6477
    6578    void resetPropertiesFromTrack();
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/VideoTrackPrivateMediaSourceAVFObjC.mm

    r165676 r174823  
    4848    m_trackID = m_impl->trackID();
    4949
     50    setTrackIndex(m_impl->index());
    5051    setKind(m_impl->videoKind());
    5152    setId(m_impl->id());
Note: See TracChangeset for help on using the changeset viewer.