Changeset 276870 in webkit
- Timestamp:
- Apr 30, 2021 7:11:51 PM (3 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r276867 r276870 1 2021-04-30 Jer Noble <jer.noble@apple.com> 2 3 [Cocoa] Calling into -[AVPlayerItem currentTime] is very expensive 4 https://bugs.webkit.org/show_bug.cgi?id=225254 5 6 Reviewed by Eric Carlson. 7 8 Calling into -currentTime is an expensive operation that synchronously calls a shared 9 background thread, and so can block for potentially long periods of time. Instead, 10 AVPlayerItem offers an API which will push currentTime changes on a specified dispatch 11 queue. We can use that API to occasionally update a cached view of the item's currentTime 12 and combine that cached value with other cached states to accurately calculate an 13 approximation of the currentTime during playback. 14 15 * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h: 16 * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm: 17 (WebCore::MediaPlayerPrivateAVFoundationObjC::cancelLoad): 18 (WebCore::MediaPlayerPrivateAVFoundationObjC::createAVPlayer): 19 (WebCore::MediaPlayerPrivateAVFoundationObjC::currentMediaTime const): 20 (WebCore::MediaPlayerPrivateAVFoundationObjC::currentMediaTimeDidChange): 21 (WebCore::MediaPlayerPrivateAVFoundationObjC::setRateDouble): 22 (WebCore::MediaPlayerPrivateAVFoundationObjC::setPlayerRate): 23 (WebCore::MediaPlayerPrivateAVFoundationObjC::timeControlStatusDidChange): 24 1 25 2021-04-30 Cameron McCormack <heycam@apple.com> 2 26 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h
r274021 r276870 322 322 void audioOutputDeviceChanged() final; 323 323 324 void currentMediaTimeDidChange(MediaTime&&) const; 325 324 326 RetainPtr<AVURLAsset> m_avAsset; 325 327 RetainPtr<AVPlayer> m_avPlayer; … … 385 387 RetainPtr<AVPlayerItemMetadataCollector> m_metadataCollector; 386 388 RetainPtr<AVPlayerItemMetadataOutput> m_metadataOutput; 389 RetainPtr<id> m_currentTimeObserver; 387 390 388 391 mutable RetainPtr<NSArray> m_cachedSeekableRanges; … … 392 395 FloatSize m_cachedPresentationSize; 393 396 MediaTime m_cachedDuration; 397 mutable MediaTime m_cachedCurrentMediaTime; 398 mutable Optional<WallTime> m_wallClockAtCachedCurrentTime; 399 mutable int m_timeControlStatusAtCachedCurrentTime { 0 }; 400 mutable double m_requestedRateAtCachedCurrentTime { 0 }; 394 401 RefPtr<SharedBuffer> m_keyID; 395 402 double m_cachedRate { 0 }; -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
r276621 r276870 519 519 [m_avPlayer setOutputContext:nil]; 520 520 #endif 521 522 if (m_currentTimeObserver) 523 [m_avPlayer removeTimeObserver:m_currentTimeObserver.get()]; 524 m_currentTimeObserver = nil; 525 521 526 m_avPlayer = nil; 522 527 } … … 1101 1106 #endif 1102 1107 1108 ASSERT(!m_currentTimeObserver); 1109 m_currentTimeObserver = [m_avPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 10) queue:dispatch_get_main_queue() usingBlock:[weakThis = makeWeakPtr(*this)] (CMTime time) { 1110 if (weakThis) 1111 weakThis->currentMediaTimeDidChange(PAL::toMediaTime(time)); 1112 }]; 1113 1103 1114 setDelayCallbacks(false); 1104 1115 } … … 1429 1440 return MediaTime::zeroTime(); 1430 1441 1431 CMTime itemTime = [m_avPlayerItem.get() currentTime]; 1432 if (CMTIME_IS_NUMERIC(itemTime)) 1433 return std::max(PAL::toMediaTime(itemTime), MediaTime::zeroTime()); 1434 1435 return MediaTime::zeroTime(); 1442 if (!m_wallClockAtCachedCurrentTime) 1443 currentMediaTimeDidChange(toMediaTime([m_avPlayerItem.get() currentTime])); 1444 ASSERT(m_wallClockAtCachedCurrentTime); 1445 1446 auto itemTime = m_cachedCurrentMediaTime; 1447 if (!itemTime.isFinite()) 1448 return MediaTime::zeroTime(); 1449 1450 if (m_timeControlStatusAtCachedCurrentTime == AVPlayerTimeControlStatusPlaying) { 1451 auto elapsedMediaTime = (WallTime::now() - *m_wallClockAtCachedCurrentTime) * m_requestedRateAtCachedCurrentTime; 1452 itemTime += MediaTime::createWithDouble(elapsedMediaTime.seconds()); 1453 } 1454 1455 return std::min(std::max(itemTime, MediaTime::zeroTime()), m_cachedDuration); 1456 } 1457 1458 void MediaPlayerPrivateAVFoundationObjC::currentMediaTimeDidChange(WTF::MediaTime&& time) const 1459 { 1460 m_cachedCurrentMediaTime = time; 1461 m_wallClockAtCachedCurrentTime = WallTime::now(); 1462 m_timeControlStatusAtCachedCurrentTime = m_cachedTimeControlStatus; 1463 m_requestedRateAtCachedCurrentTime = m_requestedRate; 1436 1464 } 1437 1465 … … 1509 1537 if (m_requestedPlaying) 1510 1538 setPlayerRate(rate); 1539 m_wallClockAtCachedCurrentTime = WTF::nullopt; 1511 1540 } 1512 1541 … … 1522 1551 setShouldObserveTimeControlStatus(true); 1523 1552 setDelayCallbacks(false); 1553 1554 m_wallClockAtCachedCurrentTime = WTF::nullopt; 1524 1555 } 1525 1556 … … 3346 3377 m_cachedTimeControlStatus = timeControlStatus; 3347 3378 rateChanged(); 3379 m_wallClockAtCachedCurrentTime = WTF::nullopt; 3348 3380 3349 3381 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
Note: See TracChangeset
for help on using the changeset viewer.