Changeset 251626 in webkit


Ignore:
Timestamp:
Oct 25, 2019 7:38:39 PM (4 years ago)
Author:
eric.carlson@apple.com
Message:

Support for callbacks for manifest events
https://bugs.webkit.org/show_bug.cgi?id=202101
<rdar://problem/54277362>

Reviewed by Jer Noble.
Source/WebCore:

Use AVPlayerItemMetadataCollector to get manifest based time metadata. Use
AVPlayerItemMetadataOutput to get time metadata instead of listening for a "timedMetadata"
KVO on AVPlayer.

No new tests, existing test updated.

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

(WebCore::globalMetadataProcessingQueue):
(WebCore::MediaPlayerPrivateAVFoundationObjC::cancelLoad):
(WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem):
(WebCore::metadataType):
(WebCore::MediaPlayerPrivateAVFoundationObjC::metadataGroupDidArrive):
(WebCore::MediaPlayerPrivateAVFoundationObjC::metadataDidArrive):
(WebCore::itemKVOProperties):
(-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]):
(-[WebCoreAVFMovieObserver metadataOutput:didOutputTimedMetadataGroups:fromPlayerItemTrack:]):
(-[WebCoreAVFMovieObserver metadataCollector:didCollectDateRangeMetadataGroups:indexesOfNewGroups:indexesOfModifiedGroups:]):

Source/WebCore/PAL:

  • pal/cocoa/AVFoundationSoftLink.h:
  • pal/cocoa/AVFoundationSoftLink.mm:

LayoutTests:

  • http/tests/media/resources/hls/metadata/prog_index.m3u8:
  • http/tests/media/track-in-band-hls-metadata-expected.txt:
  • http/tests/media/track-in-band-hls-metadata.html:
Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r251625 r251626  
     12019-10-25  Eric Carlson  <eric.carlson@apple.com>
     2
     3        Support for callbacks for manifest events
     4        https://bugs.webkit.org/show_bug.cgi?id=202101
     5        <rdar://problem/54277362>
     6
     7        Reviewed by Jer Noble.
     8
     9        * http/tests/media/resources/hls/metadata/prog_index.m3u8:
     10        * http/tests/media/track-in-band-hls-metadata-expected.txt:
     11        * http/tests/media/track-in-band-hls-metadata.html:
     12
    1132019-10-25  Wenson Hsieh  <wenson_hsieh@apple.com>
    214
  • trunk/LayoutTests/http/tests/media/resources/hls/metadata/prog_index.m3u8

    r167632 r251626  
    44#EXT-X-MEDIA-SEQUENCE:0
    55#EXT-X-PLAYLIST-TYPE:VOD
     6#EXT-X-DATERANGE:ID="cue-1",START-DATE="2019-01-01T00:00:00.000Z",DURATION=5.000000,X-START-OFFSET="0.000000"
     7#EXT-X-DATERANGE:ID="cue-2",START-DATE="2019-01-01T00:00:05.000Z",DURATION=5.000000,X-END-OFFSET="5.000000"
    68#EXTINF:5.00000,       
    79fileSequence2.ts
  • trunk/LayoutTests/http/tests/media/track-in-band-hls-metadata-expected.txt

    r196131 r251626  
    1616** Start playback, wait for all cues to load
    1717RUN(video.play())
    18 EVENT(cuechange)
    19 EVENT(cuechange)
    20 EVENT(cuechange)
    21 EVENT(cuechange)
    22 EVENT(cuechange)
    23 EVENT(cuechange)
    2418
    2519** Validate cue data
    2620* 1
    2721EXPECTED (typeof(cue) != 'undefined') OK
     22EXPECTED (cue.data == 'null') OK
     23EXPECTED (cue.type == 'com.apple.quicktime.HLS') OK
     24EXPECTED (cue.value != 'null') OK
     25EXPECTED (cue.value.key == '"X-START-OFFSET"') OK
     26EXPECTED (cue.value.data == '"0.000000"') OK
     27
     28* 2
     29EXPECTED (typeof(cue) != 'undefined') OK
     30EXPECTED (cue.data == 'null') OK
     31EXPECTED (cue.type == 'com.apple.quicktime.HLS') OK
     32EXPECTED (cue.value != 'null') OK
     33EXPECTED (cue.value.key == '"X-END-OFFSET"') OK
     34EXPECTED (cue.value.data == '"5.000000"') OK
     35
     36* 3
     37EXPECTED (typeof(cue) != 'undefined') OK
     38EXPECTED (cue.data == 'null') OK
    2839EXPECTED (cue.type == 'org.id3') OK
    29 EXPECTED (cue.data == 'null') OK
    3040EXPECTED (cue.value != 'null') OK
    3141EXPECTED (cue.value.key == '"TIT2"') OK
    3242EXPECTED (cue.value.data == '"Stream Counting"') OK
    3343
    34 * 2
     44* 4
    3545EXPECTED (typeof(cue) != 'undefined') OK
     46EXPECTED (cue.data == 'null') OK
    3647EXPECTED (cue.type == 'org.id3') OK
    37 EXPECTED (cue.data == 'null') OK
    3848EXPECTED (cue.value != 'null') OK
    3949EXPECTED (cue.value.key == '"TPE1"') OK
    4050EXPECTED (cue.value.data == '"Andy"') OK
    4151
    42 * 3
     52* 5
    4353EXPECTED (typeof(cue) != 'undefined') OK
     54EXPECTED (cue.data == 'null') OK
    4455EXPECTED (cue.type == 'org.id3') OK
    45 EXPECTED (cue.data == 'null') OK
    4656EXPECTED (cue.value != 'null') OK
    4757EXPECTED (cue.value.key == '"TALB"') OK
    4858EXPECTED (cue.value.data == '"Greatest Hits"') OK
    4959
    50 * 4
     60* 6
    5161EXPECTED (typeof(cue) != 'undefined') OK
     62EXPECTED (cue.data == 'null') OK
    5263EXPECTED (cue.type == 'org.id3') OK
    53 EXPECTED (cue.data == 'null') OK
    5464EXPECTED (cue.value != 'null') OK
    5565EXPECTED (cue.value.key == '"GEOB"') OK
     
    5969EXPECTED (cue.value.name == '"abe.png"') OK
    6070
    61 * 5
     71* 7
    6272EXPECTED (typeof(cue) != 'undefined') OK
     73EXPECTED (cue.data == 'null') OK
    6374EXPECTED (cue.type == 'org.id3') OK
    64 EXPECTED (cue.data == 'null') OK
    6575EXPECTED (cue.value != 'null') OK
    6676EXPECTED (cue.value.key == '"APIC"') OK
     
    6878EXPECTED (cue.value.type == '"image/png"') OK
    6979
    70 * 6
     80* 8
    7181EXPECTED (typeof(cue) != 'undefined') OK
     82EXPECTED (cue.data == 'null') OK
    7283EXPECTED (cue.type == 'org.id3') OK
    73 EXPECTED (cue.data == 'null') OK
    7484EXPECTED (cue.value != 'null') OK
    7585EXPECTED (cue.value.key == '"TXXX"') OK
     
    7787
    7888** Extract images from cue data, validate by setting img.src
    79 RUN(cueImageData = track.cues[3].value.data)
     89RUN(cueImageData = track.cues[5].value.data)
    8090EXPECTED (cueImageData instanceof ArrayBuffer == 'true') OK
    8191RUN(blobUrl = URL.createObjectURL(new Blob([cueImageData], { type: 'image/png' })))
     
    8595EXPECTED (imageElement.height == '103') OK
    8696
    87 RUN(cueImageData = track.cues[4].value.data)
     97RUN(cueImageData = track.cues[6].value.data)
    8898EXPECTED (cueImageData instanceof ArrayBuffer == 'true') OK
    8999RUN(blobUrl = URL.createObjectURL(new Blob([cueImageData], { type: 'image/png' })))
  • trunk/LayoutTests/http/tests/media/track-in-band-hls-metadata.html

    r196131 r251626  
    1212            var loadCount = 0;
    1313            var cueData = [
    14                  {"key" : "TIT2", "data" : "Stream Counting"},
    15                  {"key" : "TPE1", "data" : "Andy"},
    16                  {"key" : "TALB", "data" : "Greatest Hits"},
    17                  {"key" : "GEOB", "data" : {}, "type" : "image/png", "info" : "Our Hero", "name" : "abe.png"},
    18                  {"key" : "APIC", "data" : {}, "type" : "image/png"},
    19                  {"key" : "TXXX", "data" : "Text Blob"},
     14                 {"key" : "X-START-OFFSET", "keySpace" : "com.apple.quicktime.HLS", "data" : "0.000000"},
     15                 {"key" : "X-END-OFFSET",   "keySpace" : "com.apple.quicktime.HLS", "data" : "5.000000"},
     16                 {"key" : "TIT2",           "keySpace" : "org.id3",                 "data" : "Stream Counting"},
     17                 {"key" : "TPE1",           "keySpace" : "org.id3",                 "data" : "Andy"},
     18                 {"key" : "TALB",           "keySpace" : "org.id3",                 "data" : "Greatest Hits"},
     19                 {"key" : "GEOB",           "keySpace" : "org.id3",                 "data" : {}, "type" : "image/png", "info" : "Our Hero", "name" : "abe.png"},
     20                 {"key" : "APIC",           "keySpace" : "org.id3",                 "data" : {}, "type" : "image/png"},
     21                 {"key" : "TXXX",           "keySpace" : "org.id3",                 "data" : "Text Blob"},
    2022            ];
    2123            var imageSizes = [ [76, 103], [100, 100] ];
     
    4446                }
    4547
    46                 testImage(4);
     48                testImage(6);
    4749            }
    4850
     
    6163                observed = JSON.parse(JSON.stringify(observed));
    6264                for (property in expected) {
     65                    if (property === "keySpace")
     66                        continue;
     67
    6368                    observedValue = observed[property];
    6469                    expectedValue = expected[property];
     
    8085            function cuechange(event)
    8186            {
    82                 consoleWrite("EVENT(cuechange)");
    83                 if (++cuechangeCount != 6)
     87                if (++cuechangeCount != cueData.length)
    8488                    return;
    8589
     
    8892                video.pause();
    8993
    90                 for (var i = 0; i < 6; i++) {
     94                for (var i = 0; i < cueData.length; i++) {
    9195                    consoleWrite(`<em>* ${i + 1}</em>`);
    9296                    cue = track.cues[i];
    9397
    9498                    testExpected("typeof(cue)", undefined, "!=");
    95                     testExpected("cue.type", "org.id3");
    9699                    testExpected("cue.data", null);
     100                    testExpected("cue.type", cueData[i].keySpace);
    97101                    testExpected("cue.value", null, "!=");
    98102                    if (typeof(cue.value) == undefined) {
     
    108112                imageElement = document.querySelector("#photo");
    109113                waitForEvent('load', imageLoad, false, false, imageElement)
    110                 testImage(3);
     114                testImage(5);
    111115            }
    112116
  • trunk/Source/WebCore/ChangeLog

    r251623 r251626  
     12019-10-25  Eric Carlson  <eric.carlson@apple.com>
     2
     3        Support for callbacks for manifest events
     4        https://bugs.webkit.org/show_bug.cgi?id=202101
     5        <rdar://problem/54277362>
     6
     7        Reviewed by Jer Noble.
     8       
     9        Use AVPlayerItemMetadataCollector to get manifest based time metadata. Use
     10        AVPlayerItemMetadataOutput to get time metadata instead of listening for a "timedMetadata"
     11        KVO on AVPlayer.
     12
     13        No new tests, existing test updated.
     14
     15        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h:
     16        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
     17        (WebCore::globalMetadataProcessingQueue):
     18        (WebCore::MediaPlayerPrivateAVFoundationObjC::cancelLoad):
     19        (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayerItem):
     20        (WebCore::metadataType):
     21        (WebCore::MediaPlayerPrivateAVFoundationObjC::metadataGroupDidArrive):
     22        (WebCore::MediaPlayerPrivateAVFoundationObjC::metadataDidArrive):
     23        (WebCore::itemKVOProperties):
     24        (-[WebCoreAVFMovieObserver observeValueForKeyPath:ofObject:change:context:]):
     25        (-[WebCoreAVFMovieObserver metadataOutput:didOutputTimedMetadataGroups:fromPlayerItemTrack:]):
     26        (-[WebCoreAVFMovieObserver metadataCollector:didCollectDateRangeMetadataGroups:indexesOfNewGroups:indexesOfModifiedGroups:]):
     27
    1282019-10-25  Andy Estes  <aestes@apple.com>
    229
  • trunk/Source/WebCore/PAL/ChangeLog

    r251623 r251626  
     12019-10-25  Eric Carlson  <eric.carlson@apple.com>
     2
     3        Support for callbacks for manifest events
     4        https://bugs.webkit.org/show_bug.cgi?id=202101
     5        <rdar://problem/54277362>
     6
     7        Reviewed by Jer Noble.
     8
     9        * pal/cocoa/AVFoundationSoftLink.h:
     10        * pal/cocoa/AVFoundationSoftLink.mm:
     11
    1122019-10-25  Andy Estes  <aestes@apple.com>
    213
  • trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h

    r244704 r251626  
    6363SOFT_LINK_CLASS_FOR_HEADER(PAL, AVPlayerItem)
    6464SOFT_LINK_CLASS_FOR_HEADER(PAL, AVPlayerItemLegibleOutput)
     65SOFT_LINK_CLASS_FOR_HEADER(PAL, AVPlayerItemMetadataCollector)
     66SOFT_LINK_CLASS_FOR_HEADER(PAL, AVPlayerItemMetadataOutput)
    6567SOFT_LINK_CLASS_FOR_HEADER(PAL, AVPlayerItemVideoOutput)
    6668SOFT_LINK_CLASS_FOR_HEADER(PAL, AVPlayerLayer)
     
    232234SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVMetadataKeySpaceISOUserData, NSString *)
    233235#define AVMetadataKeySpaceISOUserData PAL::get_AVFoundation_AVMetadataKeySpaceISOUserData()
     236SOFT_LINK_CONSTANT_FOR_HEADER(PAL, AVFoundation, AVMetadataKeySpaceHLSDateRange, NSString *)
     237#define AVMetadataKeySpaceHLSDateRange PAL::get_AVFoundation_AVMetadataKeySpaceHLSDateRange()
    234238
    235239#if PLATFORM(MAC)
  • trunk/Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm

    r244704 r251626  
    5555SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVPlayerItem, PAL_EXPORT)
    5656SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVPlayerItemLegibleOutput, PAL_EXPORT)
     57SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVPlayerItemMetadataCollector, PAL_EXPORT)
     58SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVPlayerItemMetadataOutput, PAL_EXPORT)
    5759SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVPlayerItemVideoOutput, PAL_EXPORT)
    5860SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVPlayerLayer, PAL_EXPORT)
     
    111113SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVMetadataCommonKeyTitle, NSString *, PAL_EXPORT)
    112114SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVMetadataKeySpaceCommon, NSString *, PAL_EXPORT)
     115SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVMetadataKeySpaceHLSDateRange, NSString *, PAL_EXPORT)
    113116SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVMetadataKeySpaceID3, NSString *, PAL_EXPORT)
    114117SOFT_LINK_CONSTANT_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVMetadataKeySpaceISOUserData, NSString *, PAL_EXPORT)
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h

    r247800 r251626  
    4040OBJC_CLASS AVPlayerItem;
    4141OBJC_CLASS AVPlayerItemLegibleOutput;
     42OBJC_CLASS AVPlayerItemMetadataCollector;
     43OBJC_CLASS AVPlayerItemMetadataOutput;
    4244OBJC_CLASS AVPlayerItemVideoOutput;
    4345OBJC_CLASS AVPlayerLayer;
     
    117119    void rateDidChange(double);
    118120    void timeControlStatusDidChange(int);
     121    void metadataGroupDidArrive(const RetainPtr<NSArray>&, const MediaTime&);
    119122    void metadataDidArrive(const RetainPtr<NSArray>&, const MediaTime&);
    120123    void firstFrameAvailableDidChange(bool);
     
    156159#endif
    157160
     161    MediaTime currentMediaTime() const override;
     162
    158163private:
    159164    // engine support
     
    170175    void platformPause() override;
    171176    bool platformPaused() const override;
    172     MediaTime currentMediaTime() const override;
    173177    void setVolume(float) override;
    174178    void setMuted(bool) override;
     
    411415#endif
    412416#endif
     417
     418    RetainPtr<AVPlayerItemMetadataCollector> m_metadataCollector;
     419    RetainPtr<AVPlayerItemMetadataOutput> m_metadataOutput;
    413420
    414421    mutable RetainPtr<NSArray> m_cachedSeekableRanges;
  • trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm

    r250566 r251626  
    175175}
    176176
    177 @interface WebCoreAVFMovieObserver : NSObject <AVPlayerItemLegibleOutputPushDelegate>
     177@interface WebCoreAVFMovieObserver : NSObject <AVPlayerItemLegibleOutputPushDelegate, AVPlayerItemMetadataOutputPushDelegate, AVPlayerItemMetadataCollectorPushDelegate>
    178178{
    179179    WeakPtr<MediaPlayerPrivateAVFoundationObjC> m_player;
     
    188188- (void)legibleOutput:(id)output didOutputAttributedStrings:(NSArray *)strings nativeSampleBuffers:(NSArray *)nativeSamples forItemTime:(CMTime)itemTime;
    189189- (void)outputSequenceWasFlushed:(id)output;
     190- (void)metadataCollector:(AVPlayerItemMetadataCollector *)metadataCollector didCollectDateRangeMetadataGroups:(NSArray<AVDateRangeMetadataGroup *> *)metadataGroups indexesOfNewGroups:(NSIndexSet *)indexesOfNewGroups indexesOfModifiedGroups:(NSIndexSet *)indexesOfModifiedGroups;
     191- (void)metadataOutput:(AVPlayerItemMetadataOutput *)output didOutputTimedMetadataGroups:(NSArray<AVTimedMetadataGroup *> *)groups fromPlayerItemTrack:(AVPlayerItemTrack *)track;
    190192@end
    191193
     
    436438            [m_avPlayerItem.get() removeOutput:m_legibleOutput.get()];
    437439        m_legibleOutput = nil;
     440    }
     441
     442    if (m_metadataCollector) {
     443        // FIXME - removeMediaDataCollector sometimes crashes, do not uncomment this until rdar://56617504 has been fixed.
     444        // if (m_avPlayerItem)
     445        //     [m_avPlayerItem.get() removeMediaDataCollector:m_metadataCollector.get()];
     446        m_metadataCollector = nil;
     447    }
     448
     449    if (m_metadataOutput) {
     450        if (m_avPlayerItem)
     451            [m_avPlayerItem.get() removeOutput:m_metadataOutput.get()];
     452        m_metadataOutput = nil;
    438453    }
    439454
     
    940955        setAVPlayerItem(m_avPlayerItem.get());
    941956
    942     const NSTimeInterval legibleOutputAdvanceInterval = 2;
     957    const NSTimeInterval avPlayerOutputAdvanceInterval = 2;
    943958
    944959    RetainPtr<NSArray> subtypes = adoptNS([[NSArray alloc] initWithObjects:[NSNumber numberWithUnsignedInt:kCMSubtitleFormatType_WebVTT], nil]);
     
    947962
    948963    [m_legibleOutput.get() setDelegate:m_objcObserver.get() queue:dispatch_get_main_queue()];
    949     [m_legibleOutput.get() setAdvanceIntervalForDelegateInvocation:legibleOutputAdvanceInterval];
     964    [m_legibleOutput.get() setAdvanceIntervalForDelegateInvocation:avPlayerOutputAdvanceInterval];
    950965    [m_legibleOutput.get() setTextStylingResolution:AVPlayerItemLegibleOutputTextStylingResolutionSourceAndRulesOnly];
    951966    [m_avPlayerItem.get() addOutput:m_legibleOutput.get()];
     
    961976    createVideoOutput();
    962977#endif
     978
     979    m_metadataCollector = adoptNS([PAL::allocAVPlayerItemMetadataCollectorInstance() initWithIdentifiers:nil classifyingLabels:nil]);
     980    [m_metadataCollector.get() setDelegate:m_objcObserver.get() queue:dispatch_get_main_queue()];
     981    [m_avPlayerItem.get() addMediaDataCollector:m_metadataCollector.get()];
     982
     983    m_metadataOutput = adoptNS([PAL::allocAVPlayerItemMetadataOutputInstance() initWithIdentifiers:nil]);
     984    [m_metadataOutput.get() setDelegate:m_objcObserver.get() queue:dispatch_get_main_queue()];
     985    [m_metadataOutput.get() setAdvanceIntervalForDelegateInvocation:avPlayerOutputAdvanceInterval];
     986    [m_avPlayerItem.get() addOutput:m_metadataOutput.get()];
    963987
    964988    setDelayCallbacks(false);
     
    29732997
    29742998#if ENABLE(DATACUE_VALUE)
    2975 
    29762999static const AtomString& metadataType(NSString *avMetadataKeySpace)
    29773000{
     
    29813004    static NeverDestroyed<const AtomString> iTunesMetadata("com.apple.itunes", AtomString::ConstructFromLiteral);
    29823005    static NeverDestroyed<const AtomString> id3Metadata("org.id3", AtomString::ConstructFromLiteral);
     3006    static NeverDestroyed<const AtomString> hlsDateRangeMetadata("com.apple.quicktime.HLS", AtomString::ConstructFromLiteral);
    29833007
    29843008    if ([avMetadataKeySpace isEqualToString:AVMetadataKeySpaceQuickTimeUserData])
     
    29923016    if ([avMetadataKeySpace isEqualToString:AVMetadataKeySpaceID3])
    29933017        return id3Metadata;
     3018    if ([avMetadataKeySpace isEqualToString:AVMetadataKeySpaceHLSDateRange])
     3019        return hlsDateRangeMetadata;
    29943020
    29953021    return emptyAtom();
    29963022}
    2997 
    2998 #endif
     3023#endif
     3024
     3025void MediaPlayerPrivateAVFoundationObjC::metadataGroupDidArrive(const RetainPtr<NSArray>& groups, const MediaTime& currentTime)
     3026{
     3027    for (AVDateRangeMetadataGroup *group in groups.get()) {
     3028        auto groupStartDate = group.startDate.timeIntervalSince1970;
     3029        auto groupEndDate = group.endDate.timeIntervalSince1970;
     3030        auto groupDuration = MediaTime::createWithDouble(groupEndDate - groupStartDate);
     3031
     3032        // A manifest without a #EXT-X-PROGRAM-DATE-TIME won't have a start date, so if currentDate
     3033        // is zero assume the metadata items start at the beginning of the stream.
     3034        double groupStartTime = 0;
     3035        if (auto currentDate = m_avPlayerItem.get().currentDate.timeIntervalSince1970)
     3036            groupStartTime = groupStartDate - currentDate - currentTime.toDouble();
     3037
     3038        auto groupCopy = adoptNS([[NSMutableArray alloc] init]);
     3039        for (AVMetadataItem *item in group.items) {
     3040            RetainPtr<AVMutableMetadataItem> itemCopy = adoptNS([item mutableCopy]);
     3041            if (!CMTIME_IS_VALID(itemCopy.get().time))
     3042                itemCopy.get().time = CMTimeMakeWithSeconds(groupStartTime, MediaTime::DefaultTimeScale);
     3043            if (!CMTIME_IS_VALID(itemCopy.get().duration))
     3044                itemCopy.get().duration = toCMTime(groupDuration);
     3045            [groupCopy addObject:itemCopy.get()];
     3046        }
     3047
     3048        metadataDidArrive(groupCopy, currentTime);
     3049    }
     3050}
    29993051
    30003052void MediaPlayerPrivateAVFoundationObjC::metadataDidArrive(const RetainPtr<NSArray>& metadata, const MediaTime& mediaTime)
     
    30263078
    30273079    for (AVMetadataItem *item in m_currentMetaData.get()) {
    3028         MediaTime start = std::max(PAL::toMediaTime(item.time), MediaTime::zeroTime());
     3080        MediaTime start;
     3081        if (CMTIME_IS_VALID(item.time))
     3082            start = std::max(PAL::toMediaTime(item.time), MediaTime::zeroTime());
     3083
    30293084        MediaTime end = MediaTime::positiveInfiniteTime();
    3030         if (CMTIME_IS_VALID(item.duration))
    3031             end = start + PAL::toMediaTime(item.duration);
     3085        auto duration = item.duration;
     3086        if (CMTIME_IS_VALID(duration) && CMTimeGetSeconds(duration) > 0.001)
     3087            end = start + PAL::toMediaTime(duration);
    30323088
    30333089        AtomString type = nullAtom();
     
    32553311        @"duration",
    32563312        @"hasEnabledAudio",
    3257         @"timedMetadata",
    32583313        @"canPlayFastForward",
    32593314        @"canPlayFastReverse",
     
    33763431                else if ([keyPath isEqualToString:@"duration"])
    33773432                    player->durationDidChange(PAL::toMediaTime([newValue CMTimeValue]));
    3378                 else if ([keyPath isEqualToString:@"timedMetadata"] && newValue) {
    3379                     MediaTime now;
    3380                     CMTime itemTime = [(AVPlayerItem *)object.get() currentTime];
    3381                     if (CMTIME_IS_NUMERIC(itemTime))
    3382                         now = std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime());
    3383                     player->metadataDidArrive(RetainPtr<NSArray>(newValue), now);
    3384                     shouldLogValue = false;
    3385                 } else if ([keyPath isEqualToString:@"canPlayFastReverse"])
     3433                else if ([keyPath isEqualToString:@"canPlayFastReverse"])
    33863434                    player->canPlayFastReverseDidChange([newValue boolValue]);
    33873435                else if ([keyPath isEqualToString:@"canPlayFastForward"])
     
    34503498}
    34513499
     3500- (void)metadataOutput:(AVPlayerItemMetadataOutput *)output didOutputTimedMetadataGroups:(NSArray<AVTimedMetadataGroup *> *)metadataGroups fromPlayerItemTrack:(AVPlayerItemTrack *)track
     3501{
     3502    ASSERT(isMainThread());
     3503    UNUSED_PARAM(output);
     3504    UNUSED_PARAM(track);
     3505
     3506    m_taskQueue.enqueueTask([player = m_player, metadataGroups = retainPtr(metadataGroups), currentTime = m_player->currentMediaTime()] {
     3507        if (!player)
     3508            return;
     3509
     3510        for (AVTimedMetadataGroup *group in metadataGroups.get())
     3511            player->metadataDidArrive(retainPtr(group.items), currentTime);
     3512    });
     3513}
     3514
     3515- (void)metadataCollector:(AVPlayerItemMetadataCollector *)metadataCollector didCollectDateRangeMetadataGroups:(NSArray<AVDateRangeMetadataGroup *> *)metadataGroups indexesOfNewGroups:(NSIndexSet *)indexesOfNewGroups indexesOfModifiedGroups:(NSIndexSet *)indexesOfModifiedGroups
     3516{
     3517    ASSERT(isMainThread());
     3518    UNUSED_PARAM(metadataCollector);
     3519    UNUSED_PARAM(indexesOfNewGroups);
     3520    UNUSED_PARAM(indexesOfModifiedGroups);
     3521
     3522    m_taskQueue.enqueueTask([player = m_player, metadataGroups = retainPtr(metadataGroups), currentTime = m_player->currentMediaTime()] {
     3523        if (!player)
     3524            return;
     3525
     3526        player->metadataGroupDidArrive(metadataGroups, currentTime);
     3527    });
     3528}
    34523529@end
    34533530
     
    35073584@end
    35083585
    3509 #endif
     3586#endif // HAVE(AVFOUNDATION_LOADER_DELEGATE)
    35103587
    35113588#if HAVE(AVFOUNDATION_VIDEO_OUTPUT)
     
    35353612@end
    35363613
    3537 #endif
    3538 
    3539 #endif
     3614#endif // HAVE(AVFOUNDATION_VIDEO_OUTPUT)
     3615
     3616#endif
Note: See TracChangeset for help on using the changeset viewer.