Unreviewed build fix
[WebKit-https.git] / Source / WebCore / platform / graphics / avfoundation / MediaPlayerPrivateAVFoundation.cpp
1 /*
2  * Copyright (C) 2011-2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if ENABLE(VIDEO) && USE(AVFOUNDATION)
29
30 #include "MediaPlayerPrivateAVFoundation.h"
31
32 #import "CustomHeaderFields.h"
33 #include "DeprecatedGlobalSettings.h"
34 #include "DocumentLoader.h"
35 #include "FloatConversion.h"
36 #include "GraphicsContext.h"
37 #include "InbandTextTrackPrivateAVF.h"
38 #include "InbandTextTrackPrivateClient.h"
39 #include "Logging.h"
40 #include "PlatformLayer.h"
41 #include "PlatformTimeRanges.h"
42 #include "Settings.h"
43 #include <CoreMedia/CoreMedia.h>
44 #include <JavaScriptCore/DataView.h>
45 #include <JavaScriptCore/HeapInlines.h>
46 #include <JavaScriptCore/TypedArrayInlines.h>
47 #include <JavaScriptCore/Uint16Array.h>
48 #include <wtf/MainThread.h>
49 #include <wtf/NeverDestroyed.h>
50 #include <wtf/SoftLinking.h>
51 #include <wtf/StringPrintStream.h>
52 #include <wtf/URL.h>
53 #include <wtf/text/CString.h>
54
55 namespace WebCore {
56
57 MediaPlayerPrivateAVFoundation::MediaPlayerPrivateAVFoundation(MediaPlayer* player)
58     : m_player(player)
59     , m_queuedNotifications()
60     , m_queueMutex()
61     , m_networkState(MediaPlayer::Empty)
62     , m_readyState(MediaPlayer::HaveNothing)
63     , m_preload(MediaPlayer::Auto)
64 #if !RELEASE_LOG_DISABLED
65     , m_logger(player->mediaPlayerLogger())
66     , m_logIdentifier(player->mediaPlayerLogIdentifier())
67 #endif
68     , m_cachedDuration(MediaTime::invalidTime())
69     , m_reportedDuration(MediaTime::invalidTime())
70     , m_maxTimeLoadedAtLastDidLoadingProgress(MediaTime::invalidTime())
71     , m_delayCallbacks(0)
72     , m_delayCharacteristicsChangedNotification(0)
73     , m_mainThreadCallPending(false)
74     , m_assetIsPlayable(false)
75     , m_visible(false)
76     , m_loadingMetadata(false)
77     , m_isAllowedToRender(false)
78     , m_cachedHasAudio(false)
79     , m_cachedHasVideo(false)
80     , m_cachedHasCaptions(false)
81     , m_ignoreLoadStateChanges(false)
82     , m_haveReportedFirstVideoFrame(false)
83     , m_inbandTrackConfigurationPending(false)
84     , m_characteristicsChanged(false)
85     , m_shouldMaintainAspectRatio(true)
86     , m_seeking(false)
87 {
88     INFO_LOG(LOGIDENTIFIER);
89 }
90
91 MediaPlayerPrivateAVFoundation::~MediaPlayerPrivateAVFoundation()
92 {
93     INFO_LOG(LOGIDENTIFIER);
94     setIgnoreLoadStateChanges(true);
95 }
96
97 MediaPlayerPrivateAVFoundation::MediaRenderingMode MediaPlayerPrivateAVFoundation::currentRenderingMode() const
98 {
99     if (platformLayer())
100         return MediaRenderingToLayer;
101
102     if (hasContextRenderer())
103         return MediaRenderingToContext;
104
105     return MediaRenderingNone;
106 }
107
108 MediaPlayerPrivateAVFoundation::MediaRenderingMode MediaPlayerPrivateAVFoundation::preferredRenderingMode() const
109 {
110     if (!m_player->visible() || assetStatus() == MediaPlayerAVAssetStatusUnknown)
111         return MediaRenderingNone;
112
113     if (supportsAcceleratedRendering() && m_player->client().mediaPlayerRenderingCanBeAccelerated(m_player))
114         return MediaRenderingToLayer;
115
116     return MediaRenderingToContext;
117 }
118
119 void MediaPlayerPrivateAVFoundation::setUpVideoRendering()
120 {
121     if (!isReadyForVideoSetup())
122         return;
123
124     MediaRenderingMode currentMode = currentRenderingMode();
125     MediaRenderingMode preferredMode = preferredRenderingMode();
126
127     if (preferredMode == MediaRenderingNone)
128         preferredMode = MediaRenderingToContext;
129
130     if (currentMode == preferredMode && currentMode != MediaRenderingNone)
131         return;
132
133     if (currentMode != MediaRenderingNone)
134         tearDownVideoRendering();
135
136     switch (preferredMode) {
137     case MediaRenderingNone:
138     case MediaRenderingToContext:
139         createContextVideoRenderer();
140         break;
141
142     case MediaRenderingToLayer:
143         createVideoLayer();
144         break;
145     }
146
147     // If using a movie layer, inform the client so the compositing tree is updated.
148     if (currentMode == MediaRenderingToLayer || preferredMode == MediaRenderingToLayer)
149         m_player->client().mediaPlayerRenderingModeChanged(m_player);
150 }
151
152 void MediaPlayerPrivateAVFoundation::tearDownVideoRendering()
153 {
154     INFO_LOG(LOGIDENTIFIER);
155
156     destroyContextVideoRenderer();
157
158     if (platformLayer())
159         destroyVideoLayer();
160 }
161
162 bool MediaPlayerPrivateAVFoundation::hasSetUpVideoRendering() const
163 {
164     return hasLayerRenderer() || hasContextRenderer();
165 }
166
167 void MediaPlayerPrivateAVFoundation::load(const String& url)
168 {
169     ALWAYS_LOG(LOGIDENTIFIER);
170
171     setNetworkState(m_preload == MediaPlayer::None ? MediaPlayer::Idle : MediaPlayer::Loading);
172     setReadyState(MediaPlayer::HaveNothing);
173
174     m_assetURL = URL({ }, url);
175     m_requestedOrigin = SecurityOrigin::create(m_assetURL);
176
177     // Don't do any more work if the url is empty.
178     if (!url.length())
179         return;
180
181     setPreload(m_preload);
182 }
183
184 #if ENABLE(MEDIA_SOURCE)
185 void MediaPlayerPrivateAVFoundation::load(const String&, MediaSourcePrivateClient*)
186 {
187     setNetworkState(MediaPlayer::FormatError);
188 }
189 #endif
190
191
192 void MediaPlayerPrivateAVFoundation::playabilityKnown()
193 {
194     INFO_LOG(LOGIDENTIFIER, "metadata loaded = ", assetStatus() > MediaPlayerAVAssetStatusLoading);
195
196     if (m_assetIsPlayable)
197         return;
198
199     // Nothing more to do if we already have all of the item's metadata.
200     if (assetStatus() > MediaPlayerAVAssetStatusLoading)
201         return;
202
203     // At this point we are supposed to load metadata. It is OK to ask the asset to load the same 
204     // information multiple times, because if it has already been loaded the completion handler 
205     // will just be called synchronously.
206     m_loadingMetadata = true;
207     beginLoadingMetadata();
208 }
209
210 void MediaPlayerPrivateAVFoundation::prepareToPlay()
211 {
212     ALWAYS_LOG(LOGIDENTIFIER);
213     setPreload(MediaPlayer::Auto);
214 }
215
216 void MediaPlayerPrivateAVFoundation::play()
217 {
218     ALWAYS_LOG(LOGIDENTIFIER);
219     platformPlay();
220 }
221
222 void MediaPlayerPrivateAVFoundation::pause()
223 {
224     ALWAYS_LOG(LOGIDENTIFIER);
225     platformPause();
226 }
227
228 MediaTime MediaPlayerPrivateAVFoundation::durationMediaTime() const
229 {
230     if (m_cachedDuration.isValid())
231         return m_cachedDuration;
232
233     MediaTime duration = platformDuration();
234     if (!duration || duration.isInvalid())
235         return MediaTime::zeroTime();
236
237     m_cachedDuration = duration;
238
239     return m_cachedDuration;
240 }
241
242 void MediaPlayerPrivateAVFoundation::seek(const MediaTime& time)
243 {
244     seekWithTolerance(time, MediaTime::zeroTime(), MediaTime::zeroTime());
245 }
246
247 void MediaPlayerPrivateAVFoundation::seekWithTolerance(const MediaTime& mediaTime, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance)
248 {
249     MediaTime time = mediaTime;
250
251     if (m_seeking) {
252         ALWAYS_LOG(LOGIDENTIFIER, "saving pending seek");
253         m_pendingSeek = [this, time, negativeTolerance, positiveTolerance]() {
254             seekWithTolerance(time, negativeTolerance, positiveTolerance);
255         };
256         return;
257     }
258     m_seeking = true;
259
260     if (!metaDataAvailable())
261         return;
262
263     if (time > durationMediaTime())
264         time = durationMediaTime();
265
266     if (currentTextTrack())
267         currentTextTrack()->beginSeeking();
268
269     ALWAYS_LOG(LOGIDENTIFIER, "seeking to  ", time);
270
271     seekToTime(time, negativeTolerance, positiveTolerance);
272 }
273
274 bool MediaPlayerPrivateAVFoundation::paused() const
275 {
276     if (!metaDataAvailable())
277         return true;
278
279     return platformPaused();
280 }
281
282 bool MediaPlayerPrivateAVFoundation::seeking() const
283 {
284     if (!metaDataAvailable())
285         return false;
286
287     return m_seeking;
288 }
289
290 FloatSize MediaPlayerPrivateAVFoundation::naturalSize() const
291 {
292     if (!metaDataAvailable())
293         return IntSize();
294
295     // In spite of the name of this method, return the natural size transformed by the 
296     // initial movie scale because the spec says intrinsic size is:
297     //
298     //    ... the dimensions of the resource in CSS pixels after taking into account the resource's 
299     //    dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the 
300     //    format used by the resource
301
302     return m_cachedNaturalSize;
303 }
304
305 void MediaPlayerPrivateAVFoundation::setNaturalSize(FloatSize size)
306 {
307     FloatSize oldSize = m_cachedNaturalSize;
308     m_cachedNaturalSize = size;
309     if (oldSize != m_cachedNaturalSize) {
310         INFO_LOG(LOGIDENTIFIER, "was ", oldSize.width(), " x ", oldSize.height(), ", is ", size.width(), " x ", size.height());
311         m_player->sizeChanged();
312     }
313 }
314
315 void MediaPlayerPrivateAVFoundation::setHasVideo(bool b)
316 {
317     if (m_cachedHasVideo != b) {
318         m_cachedHasVideo = b;
319         characteristicsChanged();
320     }
321 }
322
323 void MediaPlayerPrivateAVFoundation::setHasAudio(bool b)
324 {
325     if (m_cachedHasAudio != b) {
326         m_cachedHasAudio = b;
327         characteristicsChanged();
328     }
329 }
330
331 void MediaPlayerPrivateAVFoundation::setHasClosedCaptions(bool b)
332 {
333     if (m_cachedHasCaptions != b) {
334         m_cachedHasCaptions = b;
335         characteristicsChanged();
336     }
337 }
338
339 void MediaPlayerPrivateAVFoundation::setNetworkState(MediaPlayer::NetworkState state)
340 {
341     if (state == m_networkState)
342         return;
343
344     m_networkState = state;
345     m_player->networkStateChanged();
346 }
347
348 void MediaPlayerPrivateAVFoundation::setReadyState(MediaPlayer::ReadyState state)
349 {
350     if (state == m_readyState)
351         return;
352
353     m_readyState = state;
354     m_player->readyStateChanged();
355 }
356
357 void MediaPlayerPrivateAVFoundation::characteristicsChanged()
358 {
359     if (m_delayCharacteristicsChangedNotification) {
360         m_characteristicsChanged = true;
361         return;
362     }
363
364     m_characteristicsChanged = false;
365     m_player->characteristicChanged();
366 }
367
368 void MediaPlayerPrivateAVFoundation::setDelayCharacteristicsChangedNotification(bool delay)
369 {
370     if (delay) {
371         m_delayCharacteristicsChangedNotification++;
372         return;
373     }
374     
375     ASSERT(m_delayCharacteristicsChangedNotification);
376     m_delayCharacteristicsChangedNotification--;
377     if (!m_delayCharacteristicsChangedNotification && m_characteristicsChanged)
378         characteristicsChanged();
379 }
380
381 std::unique_ptr<PlatformTimeRanges> MediaPlayerPrivateAVFoundation::buffered() const
382 {
383     if (!m_cachedLoadedTimeRanges)
384         m_cachedLoadedTimeRanges = platformBufferedTimeRanges();
385
386     return std::make_unique<PlatformTimeRanges>(*m_cachedLoadedTimeRanges);
387 }
388
389 MediaTime MediaPlayerPrivateAVFoundation::maxMediaTimeSeekable() const
390 {
391     if (!metaDataAvailable())
392         return MediaTime::zeroTime();
393
394     if (!m_cachedMaxTimeSeekable)
395         m_cachedMaxTimeSeekable = platformMaxTimeSeekable();
396
397     return m_cachedMaxTimeSeekable;
398 }
399
400 MediaTime MediaPlayerPrivateAVFoundation::minMediaTimeSeekable() const
401 {
402     if (!metaDataAvailable())
403         return MediaTime::zeroTime();
404
405     if (!m_cachedMinTimeSeekable)
406         m_cachedMinTimeSeekable = platformMinTimeSeekable();
407
408     return m_cachedMinTimeSeekable;
409 }
410
411 double MediaPlayerPrivateAVFoundation::requestedRate() const
412 {
413     return m_player->requestedRate();
414 }
415
416 MediaTime MediaPlayerPrivateAVFoundation::maxTimeLoaded() const
417 {
418     if (!metaDataAvailable())
419         return MediaTime::zeroTime();
420
421     if (!m_cachedMaxTimeLoaded)
422         m_cachedMaxTimeLoaded = platformMaxTimeLoaded();
423
424     return m_cachedMaxTimeLoaded;   
425 }
426
427 bool MediaPlayerPrivateAVFoundation::didLoadingProgress() const
428 {
429     if (!durationMediaTime())
430         return false;
431     MediaTime currentMaxTimeLoaded = maxTimeLoaded();
432     bool didLoadingProgress = currentMaxTimeLoaded != m_maxTimeLoadedAtLastDidLoadingProgress;
433     m_maxTimeLoadedAtLastDidLoadingProgress = currentMaxTimeLoaded;
434
435     return didLoadingProgress;
436 }
437
438 bool MediaPlayerPrivateAVFoundation::isReadyForVideoSetup() const
439 {
440     // AVFoundation will not return true for firstVideoFrameAvailable until
441     // an AVPlayerLayer has been added to the AVPlayerItem, so allow video setup
442     // here if a video track to trigger allocation of a AVPlayerLayer.
443     return (m_isAllowedToRender || m_cachedHasVideo) && m_readyState >= MediaPlayer::HaveMetadata && m_player->visible();
444 }
445
446 void MediaPlayerPrivateAVFoundation::prepareForRendering()
447 {
448     if (m_isAllowedToRender)
449         return;
450     m_isAllowedToRender = true;
451
452     setUpVideoRendering();
453
454     if (currentRenderingMode() == MediaRenderingToLayer || preferredRenderingMode() == MediaRenderingToLayer)
455         m_player->client().mediaPlayerRenderingModeChanged(m_player);
456 }
457
458 bool MediaPlayerPrivateAVFoundation::supportsFullscreen() const
459 {
460 #if ENABLE(FULLSCREEN_API)
461     return true;
462 #else
463     // FIXME: WebVideoFullscreenController assumes a QTKit/QuickTime media engine
464 #if PLATFORM(IOS_FAMILY)
465     if (DeprecatedGlobalSettings::avKitEnabled())
466         return true;
467 #endif
468     return false;
469 #endif
470 }
471
472 bool MediaPlayerPrivateAVFoundation::hasSingleSecurityOrigin() const
473 {
474     if (m_resolvedOrigin && m_requestedOrigin)
475         return m_resolvedOrigin->isSameSchemeHostPort(*m_requestedOrigin);
476     return false;
477 }
478
479 void MediaPlayerPrivateAVFoundation::setResolvedURL(URL&& resolvedURL)
480 {
481     m_resolvedURL = WTFMove(resolvedURL);
482     m_resolvedOrigin = SecurityOrigin::create(m_resolvedURL);
483 }
484
485 void MediaPlayerPrivateAVFoundation::updateStates()
486 {
487     if (m_ignoreLoadStateChanges)
488         return;
489
490     MediaPlayer::NetworkState newNetworkState = m_networkState;
491     MediaPlayer::ReadyState newReadyState = m_readyState;
492
493     if (m_loadingMetadata)
494         newNetworkState = MediaPlayer::Loading;
495     else {
496         // -loadValuesAsynchronouslyForKeys:completionHandler: has invoked its handler; test status of keys and determine state.
497         AssetStatus assetStatus = this->assetStatus();
498         ItemStatus itemStatus = playerItemStatus();
499         
500         m_assetIsPlayable = (assetStatus == MediaPlayerAVAssetStatusPlayable);
501         if (m_readyState < MediaPlayer::HaveMetadata && assetStatus > MediaPlayerAVAssetStatusLoading) {
502             if (m_assetIsPlayable) {
503                 if (assetStatus >= MediaPlayerAVAssetStatusLoaded)
504                     newReadyState = MediaPlayer::HaveMetadata;
505                 if (itemStatus <= MediaPlayerAVPlayerItemStatusUnknown) {
506                     if (assetStatus == MediaPlayerAVAssetStatusFailed || m_preload > MediaPlayer::MetaData || isLiveStream()) {
507                         // The asset is playable but doesn't support inspection prior to playback (eg. streaming files),
508                         // or we are supposed to prepare for playback immediately, so create the player item now.
509                         newNetworkState = MediaPlayer::Loading;
510                         prepareToPlay();
511                     } else
512                         newNetworkState = MediaPlayer::Idle;
513                 }
514             } else {
515                 // FIX ME: fetch the error associated with the @"playable" key to distinguish between format 
516                 // and network errors.
517                 newNetworkState = MediaPlayer::FormatError;
518             }
519         }
520         
521         if (assetStatus >= MediaPlayerAVAssetStatusLoaded && itemStatus > MediaPlayerAVPlayerItemStatusUnknown) {
522             switch (itemStatus) {
523             case MediaPlayerAVPlayerItemStatusDoesNotExist:
524             case MediaPlayerAVPlayerItemStatusUnknown:
525             case MediaPlayerAVPlayerItemStatusFailed:
526                 break;
527
528             case MediaPlayerAVPlayerItemStatusPlaybackLikelyToKeepUp:
529             case MediaPlayerAVPlayerItemStatusPlaybackBufferFull:
530                 // If the status becomes PlaybackBufferFull, loading stops and the status will not
531                 // progress to LikelyToKeepUp. Set the readyState to  HAVE_ENOUGH_DATA, on the
532                 // presumption that if the playback buffer is full, playback will probably not stall.
533                 newReadyState = MediaPlayer::HaveEnoughData;
534                 break;
535
536             case MediaPlayerAVPlayerItemStatusReadyToPlay:
537                 if (m_readyState != MediaPlayer::HaveEnoughData && maxTimeLoaded() > currentMediaTime())
538                     newReadyState = MediaPlayer::HaveFutureData;
539                 break;
540
541             case MediaPlayerAVPlayerItemStatusPlaybackBufferEmpty:
542                 newReadyState = MediaPlayer::HaveCurrentData;
543                 break;
544             }
545
546             if (itemStatus == MediaPlayerAVPlayerItemStatusPlaybackBufferFull)
547                 newNetworkState = MediaPlayer::Idle;
548             else if (itemStatus == MediaPlayerAVPlayerItemStatusFailed)
549                 newNetworkState = MediaPlayer::DecodeError;
550             else if (itemStatus != MediaPlayerAVPlayerItemStatusPlaybackBufferFull && itemStatus >= MediaPlayerAVPlayerItemStatusReadyToPlay)
551                 newNetworkState = (maxTimeLoaded() == durationMediaTime()) ? MediaPlayer::Loaded : MediaPlayer::Loading;
552         }
553     }
554
555     if (isReadyForVideoSetup() && currentRenderingMode() != preferredRenderingMode())
556         setUpVideoRendering();
557
558     if (!m_haveReportedFirstVideoFrame && m_cachedHasVideo && hasAvailableVideoFrame()) {
559         if (m_readyState < MediaPlayer::HaveCurrentData)
560             newReadyState = MediaPlayer::HaveCurrentData;
561         m_haveReportedFirstVideoFrame = true;
562         m_player->firstVideoFrameAvailable();
563     } else if (!hasAvailableVideoFrame())
564         m_haveReportedFirstVideoFrame = false;
565
566     if (m_networkState != newNetworkState)
567         ALWAYS_LOG(LOGIDENTIFIER, "entered with networkState ", m_networkState, ", exiting with ", newNetworkState);
568     if (m_readyState != newReadyState)
569         ALWAYS_LOG(LOGIDENTIFIER, "entered with readyState ", m_readyState, ", exiting with ", newReadyState);
570
571     setNetworkState(newNetworkState);
572     setReadyState(newReadyState);
573 }
574
575 void MediaPlayerPrivateAVFoundation::setSize(const IntSize&) 
576
577 }
578
579 void MediaPlayerPrivateAVFoundation::setVisible(bool visible)
580 {
581     if (m_visible == visible)
582         return;
583
584     m_visible = visible;
585     if (visible)
586         setUpVideoRendering();
587     
588     platformSetVisible(visible);
589 }
590
591 void MediaPlayerPrivateAVFoundation::acceleratedRenderingStateChanged()
592 {
593     // Set up or change the rendering path if necessary.
594     setUpVideoRendering();
595 }
596
597 void MediaPlayerPrivateAVFoundation::setShouldMaintainAspectRatio(bool maintainAspectRatio)
598 {
599     if (maintainAspectRatio == m_shouldMaintainAspectRatio)
600         return;
601
602     m_shouldMaintainAspectRatio = maintainAspectRatio;
603     updateVideoLayerGravity();
604 }
605
606 void MediaPlayerPrivateAVFoundation::metadataLoaded()
607 {
608     m_loadingMetadata = false;
609     resolvedURLChanged();
610     tracksChanged();
611 }
612
613 void MediaPlayerPrivateAVFoundation::rateChanged()
614 {
615     m_player->rateChanged();
616 }
617
618 void MediaPlayerPrivateAVFoundation::loadedTimeRangesChanged()
619 {
620     m_cachedLoadedTimeRanges = nullptr;
621     m_cachedMaxTimeLoaded = MediaTime::zeroTime();
622     invalidateCachedDuration();
623 }
624
625 void MediaPlayerPrivateAVFoundation::seekableTimeRangesChanged()
626 {
627     m_cachedMaxTimeSeekable = MediaTime::zeroTime();
628     m_cachedMinTimeSeekable = MediaTime::zeroTime();
629 }
630
631 void MediaPlayerPrivateAVFoundation::timeChanged(const MediaTime& time)
632 {
633     UNUSED_PARAM(time);
634     INFO_LOG(LOGIDENTIFIER, "- ", time);
635 }
636
637 void MediaPlayerPrivateAVFoundation::seekCompleted(bool finished)
638 {
639     UNUSED_PARAM(finished);
640     ALWAYS_LOG(LOGIDENTIFIER, "finished = ", finished);
641
642     m_seeking = false;
643
644     WTF::Function<void()> pendingSeek;
645     std::swap(pendingSeek, m_pendingSeek);
646
647     if (pendingSeek) {
648         ALWAYS_LOG(LOGIDENTIFIER, "issuing pending seek");
649         pendingSeek();
650         return;
651     }
652
653     if (currentTextTrack())
654         currentTextTrack()->endSeeking();
655
656     updateStates();
657     m_player->timeChanged();
658 }
659
660 void MediaPlayerPrivateAVFoundation::didEnd()
661 {
662     // Hang onto the current time and use it as duration from now on since we are definitely at
663     // the end of the movie. Do this because the initial duration is sometimes an estimate.
664     MediaTime now = currentMediaTime();
665     if (now > MediaTime::zeroTime() && !m_seeking)
666         m_cachedDuration = now;
667
668     updateStates();
669     m_player->timeChanged();
670 }
671
672 void MediaPlayerPrivateAVFoundation::invalidateCachedDuration()
673 {
674     m_cachedDuration = MediaTime::invalidTime();
675
676     // For some media files, reported duration is estimated and updated as media is loaded
677     // so report duration changed when the estimate is upated.
678     MediaTime duration = this->durationMediaTime();
679     if (duration != m_reportedDuration) {
680         INFO_LOG(LOGIDENTIFIER, "- ", m_cachedDuration);
681         if (m_reportedDuration.isValid())
682             m_player->durationChanged();
683         m_reportedDuration = duration;
684     }
685     
686 }
687
688 void MediaPlayerPrivateAVFoundation::repaint()
689 {
690     m_player->repaint();
691 }
692
693 MediaPlayer::MovieLoadType MediaPlayerPrivateAVFoundation::movieLoadType() const
694 {
695     if (!metaDataAvailable() || assetStatus() == MediaPlayerAVAssetStatusUnknown)
696         return MediaPlayer::Unknown;
697
698     if (isLiveStream())
699         return MediaPlayer::LiveStream;
700
701     return MediaPlayer::Download;
702 }
703
704 void MediaPlayerPrivateAVFoundation::setPreload(MediaPlayer::Preload preload)
705 {
706     ALWAYS_LOG(LOGIDENTIFIER, " - ", static_cast<int>(preload));
707     m_preload = preload;
708     if (m_assetURL.isEmpty())
709         return;
710
711     setDelayCallbacks(true);
712
713     if (m_preload >= MediaPlayer::MetaData && assetStatus() == MediaPlayerAVAssetStatusDoesNotExist) {
714         createAVAssetForURL(m_assetURL);
715         checkPlayability();
716     }
717
718     // Don't force creation of the player and player item unless we already know that the asset is playable. If we aren't
719     // there yet, or if we already know it is not playable, creating them now won't help.
720     if (m_preload == MediaPlayer::Auto && m_assetIsPlayable) {
721         createAVPlayerItem();
722         createAVPlayer();
723     }
724
725     setDelayCallbacks(false);
726 }
727
728 void MediaPlayerPrivateAVFoundation::setDelayCallbacks(bool delay) const
729 {
730     LockHolder lock(m_queueMutex);
731     if (delay)
732         ++m_delayCallbacks;
733     else {
734         ASSERT(m_delayCallbacks);
735         --m_delayCallbacks;
736     }
737 }
738
739 void MediaPlayerPrivateAVFoundation::mainThreadCallback()
740 {
741     clearMainThreadPendingFlag();
742     dispatchNotification();
743 }
744
745 void MediaPlayerPrivateAVFoundation::clearMainThreadPendingFlag()
746 {
747     LockHolder lock(m_queueMutex);
748     m_mainThreadCallPending = false;
749 }
750
751 void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification::Type type, const MediaTime& time)
752 {
753     scheduleMainThreadNotification(Notification(type, time));
754 }
755
756 void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification::Type type, bool finished)
757 {
758     scheduleMainThreadNotification(Notification(type, finished));
759 }
760
761 void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification&& notification)
762 {
763     m_queueMutex.lock();
764
765     // It is important to always process the properties in the order that we are notified,
766     // so always go through the queue because notifications happen on different threads.
767     m_queuedNotifications.append(WTFMove(notification));
768
769 #if OS(WINDOWS)
770     bool delayDispatch = true;
771 #else
772     bool delayDispatch = m_delayCallbacks || !isMainThread();
773 #endif
774     if (delayDispatch && !m_mainThreadCallPending) {
775         m_mainThreadCallPending = true;
776
777         callOnMainThread([weakThis = makeWeakPtr(*this)] {
778             if (!weakThis)
779                 return;
780
781             weakThis->mainThreadCallback();
782         });
783     }
784
785     m_queueMutex.unlock();
786
787     if (delayDispatch)
788         return;
789
790     dispatchNotification();
791 }
792
793 void MediaPlayerPrivateAVFoundation::dispatchNotification()
794 {
795     ASSERT(isMainThread());
796
797     Notification notification;
798     {
799         LockHolder lock(m_queueMutex);
800         
801         if (m_queuedNotifications.isEmpty())
802             return;
803         
804         if (!m_delayCallbacks) {
805             // Only dispatch one notification callback per invocation because they can cause recursion.
806             notification = m_queuedNotifications.takeFirst();
807         }
808         
809         if (!m_queuedNotifications.isEmpty() && !m_mainThreadCallPending) {
810             callOnMainThread([weakThis = makeWeakPtr(*this)] {
811                 if (!weakThis)
812                     return;
813
814                 weakThis->mainThreadCallback();
815             });
816         }
817
818         if (!notification.isValid())
819             return;
820     }
821
822     switch (notification.type()) {
823     case Notification::ItemDidPlayToEndTime:
824         didEnd();
825         break;
826     case Notification::ItemTracksChanged:
827         tracksChanged();
828         updateStates();
829         break;
830     case Notification::ItemStatusChanged:
831         updateStates();
832         break;
833     case Notification::ItemSeekableTimeRangesChanged:
834         seekableTimeRangesChanged();
835         updateStates();
836         break;
837     case Notification::ItemLoadedTimeRangesChanged:
838         loadedTimeRangesChanged();
839         updateStates();
840         break;
841     case Notification::ItemPresentationSizeChanged:
842         sizeChanged();
843         updateStates();
844         break;
845     case Notification::ItemIsPlaybackLikelyToKeepUpChanged:
846         updateStates();
847         break;
848     case Notification::ItemIsPlaybackBufferEmptyChanged:
849         updateStates();
850         break;
851     case Notification::ItemIsPlaybackBufferFullChanged:
852         updateStates();
853         break;
854     case Notification::PlayerRateChanged:
855         updateStates();
856         rateChanged();
857         break;
858     case Notification::PlayerTimeChanged:
859         timeChanged(notification.time());
860         break;
861     case Notification::SeekCompleted:
862         seekCompleted(notification.finished());
863         break;
864     case Notification::AssetMetadataLoaded:
865         metadataLoaded();
866         updateStates();
867         break;
868     case Notification::AssetPlayabilityKnown:
869         updateStates();
870         playabilityKnown();
871         break;
872     case Notification::DurationChanged:
873         invalidateCachedDuration();
874         break;
875     case Notification::ContentsNeedsDisplay:
876         contentsNeedsDisplay();
877         break;
878     case Notification::InbandTracksNeedConfiguration:
879         m_inbandTrackConfigurationPending = false;
880         configureInbandTracks();
881         break;
882     case Notification::FunctionType:
883         notification.function()();
884         break;
885     case Notification::TargetIsWirelessChanged:
886 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
887         playbackTargetIsWirelessChanged();
888 #endif
889         break;
890
891     case Notification::None:
892         ASSERT_NOT_REACHED();
893         break;
894     }
895 }
896
897 void MediaPlayerPrivateAVFoundation::configureInbandTracks()
898 {
899     RefPtr<InbandTextTrackPrivateAVF> trackToEnable;
900     
901 #if ENABLE(AVF_CAPTIONS)
902     synchronizeTextTrackState();
903 #endif
904
905     // AVFoundation can only emit cues for one track at a time, so enable the first track that is showing, or the first that
906     // is hidden if none are showing. Otherwise disable all tracks.
907     for (unsigned i = 0; i < m_textTracks.size(); ++i) {
908         RefPtr<InbandTextTrackPrivateAVF> track = m_textTracks[i];
909         if (track->mode() == InbandTextTrackPrivate::Showing) {
910             trackToEnable = track;
911             break;
912         }
913         if (track->mode() == InbandTextTrackPrivate::Hidden)
914             trackToEnable = track;
915     }
916
917     setCurrentTextTrack(trackToEnable.get());
918 }
919
920 void MediaPlayerPrivateAVFoundation::trackModeChanged()
921 {
922     if (m_inbandTrackConfigurationPending)
923         return;
924     m_inbandTrackConfigurationPending = true;
925     scheduleMainThreadNotification(Notification::InbandTracksNeedConfiguration);
926 }
927
928 void MediaPlayerPrivateAVFoundation::clearTextTracks()
929 {
930     for (auto& track : m_textTracks) {
931         player()->removeTextTrack(*track);
932         track->disconnect();
933     }
934     m_textTracks.clear();
935 }
936
937 void MediaPlayerPrivateAVFoundation::processNewAndRemovedTextTracks(const Vector<RefPtr<InbandTextTrackPrivateAVF>>& removedTextTracks)
938 {
939     if (removedTextTracks.size()) {
940         for (unsigned i = 0; i < m_textTracks.size(); ) {
941             if (!removedTextTracks.contains(m_textTracks[i])) {
942                 ++i;
943                 continue;
944             }
945             player()->removeTextTrack(*m_textTracks[i]);
946             m_textTracks.remove(i);
947         }
948     }
949
950     unsigned trackCount = m_textTracks.size();
951     unsigned inBandCount = 0;
952     for (unsigned i = 0; i < trackCount; ++i) {
953         RefPtr<InbandTextTrackPrivateAVF> track = m_textTracks[i];
954
955 #if ENABLE(AVF_CAPTIONS)
956         if (track->textTrackCategory() == InbandTextTrackPrivateAVF::OutOfBand)
957             continue;
958 #endif
959
960         track->setTextTrackIndex(inBandCount);
961         ++inBandCount;
962         if (track->hasBeenReported())
963             continue;
964         
965         track->setHasBeenReported(true);
966         player()->addTextTrack(*track);
967     }
968
969     if (trackCount != m_textTracks.size())
970         INFO_LOG(LOGIDENTIFIER, "found ", m_textTracks.size(), " text tracks");
971 }
972
973 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
974 void MediaPlayerPrivateAVFoundation::playbackTargetIsWirelessChanged()
975 {
976     if (m_player)
977         m_player->currentPlaybackTargetIsWirelessChanged();
978 }
979 #endif
980
981 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
982 bool MediaPlayerPrivateAVFoundation::extractKeyURIKeyIDAndCertificateFromInitData(Uint8Array* initData, String& keyURI, String& keyID, RefPtr<Uint8Array>& certificate)
983 {
984     // initData should have the following layout:
985     // [4 bytes: keyURI length][N bytes: keyURI][4 bytes: contentID length], [N bytes: contentID], [4 bytes: certificate length][N bytes: certificate]
986     if (initData->byteLength() < 4)
987         return false;
988
989     RefPtr<ArrayBuffer> initDataBuffer = initData->unsharedBuffer();
990
991     // Use a DataView to read uint32 values from the buffer, as Uint32Array requires the reads be aligned on 4-byte boundaries. 
992     auto initDataView = JSC::DataView::create(initDataBuffer.copyRef(), 0, initDataBuffer->byteLength());
993     uint32_t offset = 0;
994     bool status = true;
995
996     uint32_t keyURILength = initDataView->get<uint32_t>(offset, true, &status);
997     offset += 4;
998     if (!status || offset + keyURILength > initData->length())
999         return false;
1000
1001     auto keyURIArray = Uint16Array::tryCreate(initDataBuffer.copyRef(), offset, keyURILength);
1002     if (!keyURIArray)
1003         return false;
1004
1005     keyURI = String(reinterpret_cast<UChar*>(keyURIArray->data()), keyURILength / sizeof(unsigned short));
1006     offset += keyURILength;
1007
1008     uint32_t keyIDLength = initDataView->get<uint32_t>(offset, true, &status);
1009     offset += 4;
1010     if (!status || offset + keyIDLength > initData->length())
1011         return false;
1012
1013     auto keyIDArray = Uint8Array::tryCreate(initDataBuffer.copyRef(), offset, keyIDLength);
1014     if (!keyIDArray)
1015         return false;
1016
1017     keyID = String(reinterpret_cast<UChar*>(keyIDArray->data()), keyIDLength / sizeof(unsigned short));
1018     offset += keyIDLength;
1019
1020     uint32_t certificateLength = initDataView->get<uint32_t>(offset, true, &status);
1021     offset += 4;
1022     if (!status || offset + certificateLength > initData->length())
1023         return false;
1024
1025     certificate = Uint8Array::tryCreate(WTFMove(initDataBuffer), offset, certificateLength);
1026     if (!certificate)
1027         return false;
1028
1029     return true;
1030 }
1031 #endif
1032
1033 bool MediaPlayerPrivateAVFoundation::canSaveMediaData() const
1034 {
1035     URL url = resolvedURL();
1036
1037     if (url.isLocalFile())
1038         return true;
1039
1040     if (!url.protocolIsInHTTPFamily())
1041         return false;
1042
1043     if (isLiveStream())
1044         return false;
1045
1046     return true;
1047 }
1048
1049 bool MediaPlayerPrivateAVFoundation::isUnsupportedMIMEType(const String& type)
1050 {
1051     String lowerCaseType = type.convertToASCIILowercase();
1052
1053     // AVFoundation will return non-video MIME types which it claims to support, but which we
1054     // do not support in the <video> element. Reject all non video/, audio/, and application/ types.
1055     if (!lowerCaseType.startsWith("video/") && !lowerCaseType.startsWith("audio/") && !lowerCaseType.startsWith("application/"))
1056         return true;
1057
1058     // Reject types we know AVFoundation does not support that sites commonly ask about.
1059     if (lowerCaseType == "video/webm" || lowerCaseType == "audio/webm" || lowerCaseType == "video/x-webm")
1060         return true;
1061
1062     if (lowerCaseType == "video/x-flv")
1063         return true;
1064
1065     if (lowerCaseType == "audio/ogg" || lowerCaseType == "video/ogg" || lowerCaseType == "application/ogg")
1066         return true;
1067
1068     if (lowerCaseType == "video/h264")
1069         return true;
1070
1071     return false;
1072 }
1073
1074 #if !RELEASE_LOG_DISABLED
1075 WTFLogChannel& MediaPlayerPrivateAVFoundation::logChannel() const
1076 {
1077     return LogMedia;
1078 }
1079 #endif
1080
1081 const HashSet<String, ASCIICaseInsensitiveHash>& MediaPlayerPrivateAVFoundation::staticMIMETypeList()
1082 {
1083     static const auto cache = makeNeverDestroyed(HashSet<String, ASCIICaseInsensitiveHash> {
1084         "application/vnd.apple.mpegurl",
1085         "application/x-mpegurl",
1086         "audio/3gpp",
1087         "audio/aac",
1088         "audio/aacp",
1089         "audio/aiff",
1090         "audio/basic",
1091         "audio/mp3",
1092         "audio/mp4",
1093         "audio/mpeg",
1094         "audio/mpeg3",
1095         "audio/mpegurl",
1096         "audio/mpg",
1097         "audio/vnd.wave",
1098         "audio/wav",
1099         "audio/wave",
1100         "audio/x-aac",
1101         "audio/x-aiff",
1102         "audio/x-m4a",
1103         "audio/x-mpegurl",
1104         "audio/x-wav",
1105         "video/3gpp",
1106         "video/3gpp2",
1107         "video/mp4",
1108         "video/mpeg",
1109         "video/mpeg2",
1110         "video/mpg",
1111         "video/quicktime",
1112         "video/x-m4v",
1113         "video/x-mpeg",
1114         "video/x-mpg",
1115     });
1116     return cache;
1117 }
1118
1119 } // namespace WebCore
1120
1121 #endif