Diff
Modified: trunk/Source/WTF/ChangeLog (289945 => 289946)
--- trunk/Source/WTF/ChangeLog 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WTF/ChangeLog 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1,3 +1,12 @@
+2022-02-16 Jer Noble <[email protected]>
+
+ [Cocoa] Adopt -streamDataParser:didProvideContentKeySpecifier:forTrackID: delegate callback
+ https://bugs.webkit.org/show_bug.cgi?id=236109
+
+ Reviewed by Eric Carlson.
+
+ * wtf/PlatformHave.h:
+
2022-02-16 Eliot Hsu <[email protected]>
Move Safe Browsing knowledge into SafariSafeBrowsing framework
Modified: trunk/Source/WTF/wtf/PlatformHave.h (289945 => 289946)
--- trunk/Source/WTF/wtf/PlatformHave.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WTF/wtf/PlatformHave.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -388,6 +388,13 @@
#define HAVE_AVCONTENTKEYSESSION 1
#endif
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 110300) \
+ || (((PLATFORM(IOS) && !PLATFORM(IOS_FAMILY_SIMULATOR)) || PLATFORM(MACCATALYST)) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140500) \
+ || (PLATFORM(WATCHOS) && !PLATFORM(IOS_FAMILY_SIMULATOR) && __WATCH_OS_VERSION_MAX_ALLOWED >= 70400) \
+ || (PLATFORM(APPLETV) && !PLATFORM(IOS_FAMILY_SIMULATOR) && __TV_OS_VERSION_MAX_ALLOWED >= 140500)
+#define HAVE_AVCONTENTKEYSPECIFIER 1
+#endif
+
#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST)
#define HAVE_SEC_KEY_PROXY 1
#endif
Modified: trunk/Source/WebCore/ChangeLog (289945 => 289946)
--- trunk/Source/WebCore/ChangeLog 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/ChangeLog 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1,3 +1,125 @@
+2022-02-16 Jer Noble <[email protected]>
+
+ [Cocoa] Adopt -streamDataParser:didProvideContentKeySpecifier:forTrackID: delegate callback
+ https://bugs.webkit.org/show_bug.cgi?id=236109
+
+ Reviewed by Eric Carlson.
+
+ The current set of delegate callback methods have a significant shortcoming: clients must
+ attach an AVContentKeySession to the AVStreamDataParser before returning from the
+ -streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID: callback. This
+ is because the parser itself attaches the object required to decrypt each encrypted sample
+ to the sample itself at the parsing stage. If a client does not attach an
+ AVContentKeySession by the time that method returns, AVStreamDataParser will attach one of
+ its own.
+
+ The web-facing behavior this causes is that MSE appends will not complete (by firing
+ an "updateend" event) if an encrypted segment is parsed until the client creates and
+ attaches a MediaKeys object with a valid session.
+
+ A new delegate callback method, -streamDataParser:didProvideContentKeySpecifier:forTrackID:
+ allows us to work around this problem. When this delegate is present, AVStreamDataParser
+ will skip attaching a decryption object entirely, moving that responsibility to the
+ client. However, this comes with the requirement that the client (WebKit) won't enqueue
+ an encrypted sample before a decryption object is available via AVContentKeySession.
+
+ In order to meet this new requirement, WebKit will associate the key IDs necessary to
+ decrypt each sample in the MediaSample object that wraps the encrypted sample. Because not
+ every type of MediaSample will carry key IDs, this property was added to the
+ MediaSampleAVFObjC subclass, and therefore we need to be able to safely downcast from
+ MediaSample to MediaSampleAVFObjC. MediaSample subclasses can be distinguished by the
+ PlatformMediaSample type available through their platformSample() property, however this
+ call is not const, and may not be free, as it returns a non-POD type. So
+ PlatformMedia::Type was made an explicit enum type, and a new virtual method
+ platformSampleType() was added to MediaSample (and implemented by all subclasses), and a
+ type specialization macro was added to MediaSampleAVFObjC.
+
+ In order to check whether a given sample is capable of being enqueued, the CDMInstance
+ must be queried to determine if the sample's required keys are usable. For
+ CDMInstanceFairPlayStreamingAVFObjC, it has an existing keyStatus(), method, but that
+ method is also non-const, and may be expensive. So a KeyStatusMap instance variable
+ has been added to cache the key status for ease of querying. To notify an arbitrary number
+ of clients when the key statuses change, an Observer has been added.
+
+ When an encrypted sample is enqueued, if this new delegate method is available, the
+ source buffer will check if a CDM instance is available, and if so, whether the sample's
+ keys are usable. If any of these checks fail, the sample will be stored in a local queue
+ and new enqueues will be blocked. When the CDM's keyStatus observer is triggered, the
+ local queue will be processed, and all samples with usable key IDs will be enqueued.
+
+ Drive-by fix: Use SharedBuffer rather than Uint8Array, as the former is lighter weight
+ and can be more easily converted to and from a NSData.
+
+ * html/HTMLMediaElement.cpp:
+ (WebCore::HTMLMediaElement::mediaPlayerKeyNeeded):
+ * html/HTMLMediaElement.h:
+ * platform/MediaSample.h:
+ * platform/audio/cocoa/AudioFileReaderCocoa.cpp:
+ (WebCore::AudioFileReader::demuxWebMData const):
+ * platform/graphics/MediaPlayer.cpp:
+ (WebCore::MediaPlayer::keyNeeded):
+ * platform/graphics/MediaPlayer.h:
+ (WebCore::MediaPlayerClient::mediaPlayerKeyNeeded):
+ * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h:
+ * platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm:
+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::isAnyKeyUsable const):
+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::addKeyStatusesChangedObserver):
+ (WebCore::CDMInstanceFairPlayStreamingAVFObjC::sessionKeyStatusesChanged):
+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::requestDidSucceed):
+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::updateKeyStatuses):
+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::copyKeyStatuses const):
+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged):
+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::updateProtectionStatusForDisplayID):
+ (WebCore::CDMInstanceSessionFairPlayStreamingAVFObjC::keyStatuses const): Deleted.
+ * platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h:
+ * platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm:
+ (WebCore::CDMSessionAVContentKeySession::generateKeyRequest):
+ (WebCore::CDMSessionAVContentKeySession::update):
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+ (WebCore::MediaPlayerPrivateAVFoundationObjC::shouldWaitForLoadingOfResource):
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+ (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::keyNeeded):
+ * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h:
+ (WebCore::MediaSampleAVFObjC::setKeyIDs):
+ (WebCore::MediaSampleAVFObjC::keyIDs const):
+ (WebCore::MediaSampleAVFObjC::keyIDs):
+ (WTF::LogArgument<WebCore::MediaSampleAVFObjC>::toString):
+ (isType):
+ * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h:
+ * platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm:
+ (WebCore::MediaSourcePrivateAVFObjC::sourceBufferKeyNeeded):
+ * platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.h:
+ * platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.mm:
+ (-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeySpecifier:forTrackID:]):
+ (WebCore::SourceBufferParserAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID):
+ (WebCore::SourceBufferParserAVFObjC::didProvideContentKeyRequestSpecifierForTrackID):
+ * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
+ * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+ (WebCore::sampleBufferRenderersSupportKeySession):
+ (WebCore::copyKeyIDs):
+ (WebCore::SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC):
+ (WebCore::SourceBufferPrivateAVFObjC::didParseInitializationData):
+ (WebCore::SourceBufferPrivateAVFObjC::didProvideMediaDataForTrackId):
+ (WebCore::SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID):
+ (WebCore::SourceBufferPrivateAVFObjC::append):
+ (WebCore::SourceBufferPrivateAVFObjC::destroyRenderers):
+ (WebCore::SourceBufferPrivateAVFObjC::trackDidChangeEnabled):
+ (WebCore::SourceBufferPrivateAVFObjC::setCDMInstance):
+ (WebCore::SourceBufferPrivateAVFObjC::attemptToDecrypt):
+ (WebCore::SourceBufferPrivateAVFObjC::trackIsBlocked const):
+ (WebCore::SourceBufferPrivateAVFObjC::keyStatusesChanged):
+ (WebCore::SourceBufferPrivateAVFObjC::canEnqueueSample):
+ (WebCore::SourceBufferPrivateAVFObjC::enqueueSample):
+ (WebCore::SourceBufferPrivateAVFObjC::didBecomeReadyForMoreSamples):
+ (WebCore::SourceBufferPrivateAVFObjC::setVideoLayer):
+ * platform/graphics/cocoa/SourceBufferParser.h:
+ * platform/graphics/cocoa/SourceBufferParserWebM.cpp:
+ (WebCore::SourceBufferParserWebM::OnTrackEntry):
+ * platform/graphics/cocoa/SourceBufferParserWebM.h:
+ * platform/graphics/gstreamer/MediaSampleGStreamer.h:
+ * platform/mock/mediasource/MockSourceBufferPrivate.cpp:
+
2022-02-16 Eric Carlson <[email protected]>
[Cocoa] Update audio session category before setting NowPlaying status
Modified: trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.idl (289945 => 289946)
--- trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.idl 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/Modules/encryptedmedia/legacy/WebKitMediaKeys.idl 2022-02-16 20:49:59 UTC (rev 289946)
@@ -30,7 +30,7 @@
] interface WebKitMediaKeys {
constructor(DOMString keySystem);
- [CallWith=CurrentScriptExecutionContext] WebKitMediaKeySession createSession(DOMString type, Uint8Array initData);
+ [CallWith=CurrentDocument] WebKitMediaKeySession createSession(DOMString type, Uint8Array initData);
static boolean isTypeSupported(DOMString keySystem, optional DOMString type);
readonly attribute DOMString keySystem;
};
Modified: trunk/Source/WebCore/html/HTMLMediaElement.cpp (289945 => 289946)
--- trunk/Source/WebCore/html/HTMLMediaElement.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/html/HTMLMediaElement.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -2644,7 +2644,7 @@
return m_webKitMediaKeys ? m_webKitMediaKeys->cachedKeyForKeyId(keyId) : nullptr;
}
-void HTMLMediaElement::mediaPlayerKeyNeeded(Uint8Array* initData)
+void HTMLMediaElement::mediaPlayerKeyNeeded(const SharedBuffer& initData)
{
if (!document().settings().legacyEncryptedMediaAPIEnabled())
return;
@@ -2661,7 +2661,14 @@
return;
}
- auto event = WebKitMediaKeyNeededEvent::create(eventNames().webkitneedkeyEvent, initData);
+ WebKitMediaKeyNeededEvent::Init init;
+
+ if (auto initDataBuffer = initData.tryCreateArrayBuffer()) {
+ auto byteLength = initDataBuffer->byteLength();
+ init.initData = Uint8Array::tryCreate(initDataBuffer.releaseNonNull(), 0, byteLength);
+ }
+
+ auto event = WebKitMediaKeyNeededEvent::create(eventNames().webkitneedkeyEvent, init);
scheduleEvent(WTFMove(event));
}
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (289945 => 289946)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -706,7 +706,7 @@
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
RefPtr<ArrayBuffer> mediaPlayerCachedKeyForKeyId(const String& keyId) const final;
- void mediaPlayerKeyNeeded(Uint8Array*) final;
+ void mediaPlayerKeyNeeded(const SharedBuffer&) final;
String mediaPlayerMediaKeysStorageDirectory() const final;
#endif
Modified: trunk/Source/WebCore/platform/MediaSample.h (289945 => 289946)
--- trunk/Source/WebCore/platform/MediaSample.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/MediaSample.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -44,7 +44,7 @@
class MockSampleBox;
struct PlatformSample {
- enum {
+ enum Type {
None,
MockSampleBoxType,
CMSampleBufferType,
@@ -92,6 +92,7 @@
};
virtual SampleFlags flags() const = 0;
virtual PlatformSample platformSample() const = 0;
+ virtual PlatformSample::Type platformSampleType() const = 0;
struct ByteRange {
size_t byteOffset { 0 };
Modified: trunk/Source/WebCore/platform/audio/cocoa/AudioFileReaderCocoa.cpp (289945 => 289946)
--- trunk/Source/WebCore/platform/audio/cocoa/AudioFileReaderCocoa.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/audio/cocoa/AudioFileReaderCocoa.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -202,10 +202,10 @@
}
}
});
- parser->setDidProvideMediaDataCallback([&](Ref<MediaSample>&& sample, uint64_t trackID, const String&) {
+ parser->setDidProvideMediaDataCallback([&](Ref<MediaSampleAVFObjC>&& sample, uint64_t trackID, const String&) {
if (!audioTrackId || trackID != *audioTrackId)
return;
- samples.append(static_reference_cast<MediaSampleAVFObjC>(WTFMove(sample)));
+ samples.append(WTFMove(sample));
});
parser->setCallOnClientThreadCallback([](auto&& function) {
function();
Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1425,7 +1425,7 @@
return client().mediaPlayerCachedKeyForKeyId(keyId);
}
-void MediaPlayer::keyNeeded(Uint8Array* initData)
+void MediaPlayer::keyNeeded(const SharedBuffer& initData)
{
client().mediaPlayerKeyNeeded(initData);
}
Modified: trunk/Source/WebCore/platform/graphics/MediaPlayer.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/MediaPlayer.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/MediaPlayer.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -86,6 +86,7 @@
class NativeImage;
class PlatformMediaResourceLoader;
class PlatformTimeRanges;
+class SharedBuffer;
class TextTrackRepresentation;
class VideoTrackPrivate;
@@ -200,7 +201,7 @@
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
virtual RefPtr<ArrayBuffer> mediaPlayerCachedKeyForKeyId(const String&) const = 0;
- virtual void mediaPlayerKeyNeeded(Uint8Array*) { }
+ virtual void mediaPlayerKeyNeeded(const SharedBuffer&) { }
virtual String mediaPlayerMediaKeysStorageDirectory() const { return emptyString(); }
#endif
@@ -558,7 +559,7 @@
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
RefPtr<ArrayBuffer> cachedKeyForKeyId(const String& keyId) const;
- void keyNeeded(Uint8Array* initData);
+ void keyNeeded(const SharedBuffer& initData);
String mediaKeysStorageDirectory() const;
#endif
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1921,15 +1921,15 @@
// [4 bytes: keyURI size], [keyURI size bytes: keyURI]
unsigned keyURISize = keyURI.length() * sizeof(UChar);
auto initDataBuffer = ArrayBuffer::create(4 + keyURISize, 1);
- auto initDataView = JSC::DataView::create(initDataBuffer.copyRef(), 0, initDataBuffer->byteLength());
+ unsigned byteLength = initDataBuffer->byteLength();
+ auto initDataView = JSC::DataView::create(initDataBuffer.copyRef(), 0, byteLength);
initDataView->set<uint32_t>(0, keyURISize, true);
auto keyURIArray = Uint16Array::create(initDataBuffer.copyRef(), 4, keyURI.length());
keyURIArray->setRange(reinterpret_cast<const uint16_t*>(StringView(keyURI).upconvertedCharacters().get()), keyURI.length() / sizeof(unsigned char), 0);
- unsigned byteLength = initDataBuffer->byteLength();
- auto initData = Uint8Array::create(WTFMove(initDataBuffer), 0, byteLength);
- m_owner->player()->keyNeeded(initData.ptr());
+ auto initData = SharedBuffer::create(Vector<uint8_t> { static_cast<uint8_t*>(initDataBuffer->data()), byteLength });
+ m_owner->player()->keyNeeded(initData);
setRequestForKey(keyURI, avRequest);
return true;
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -30,7 +30,9 @@
#include "CDMInstance.h"
#include "CDMInstanceSession.h"
#include <wtf/Function.h>
+#include <wtf/Observer.h>
#include <wtf/RetainPtr.h>
+#include <wtf/WeakHashSet.h>
OBJC_CLASS AVContentKeyReportGroup;
OBJC_CLASS AVContentKeyRequest;
@@ -117,6 +119,13 @@
CDMInstanceSessionFairPlayStreamingAVFObjC* sessionForGroup(AVContentKeyReportGroup*) const;
CDMInstanceSessionFairPlayStreamingAVFObjC* sessionForRequest(AVContentKeyRequest*) const;
+ bool isAnyKeyUsable(const Keys&) const;
+
+ using KeyStatusesChangedObserver = Observer<void()>;
+ void addKeyStatusesChangedObserver(const KeyStatusesChangedObserver&);
+
+ void sessionKeyStatusesChanged(const CDMInstanceSessionFairPlayStreamingAVFObjC&);
+
private:
void handleUnexpectedRequests(Vector<RetainPtr<AVContentKeyRequest>>&&);
@@ -134,6 +143,7 @@
RetainPtr<NSURL> m_storageURL;
Vector<WeakPtr<CDMInstanceSessionFairPlayStreamingAVFObjC>> m_sessions;
HashSet<RetainPtr<AVContentKeyRequest>> m_unexpectedKeyRequests;
+ WeakHashSet<KeyStatusesChangedObserver> m_keyStatusChangedObservers;
#if !RELEASE_LOG_DISABLED
RefPtr<Logger> m_logger;
const void* m_logIdentifier { nullptr };
@@ -186,11 +196,14 @@
bool hasRequest(AVContentKeyRequest*) const;
+ const KeyStatusVector& keyStatuses() const { return m_keyStatuses; }
+ KeyStatusVector copyKeyStatuses() const;
+
private:
bool ensureSessionOrGroup();
bool isLicenseTypeSupported(LicenseType) const;
- KeyStatusVector keyStatuses(std::optional<PlatformDisplayID> = std::nullopt) const;
+ void updateKeyStatuses(std::optional<PlatformDisplayID> = std::nullopt);
void nextRequest();
AVContentKeyRequest* lastKeyRequest() const;
@@ -216,6 +229,7 @@
class UpdateResponseCollector;
std::unique_ptr<UpdateResponseCollector> m_updateResponseCollector;
+ KeyStatusVector m_keyStatuses;
Vector<Request> m_pendingRequests;
Vector<Request> m_requests;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMInstanceFairPlayStreamingAVFObjC.mm 2022-02-16 20:49:59 UTC (rev 289946)
@@ -617,6 +617,37 @@
return nullptr;
}
+bool CDMInstanceFairPlayStreamingAVFObjC::isAnyKeyUsable(const Keys& keys) const
+{
+ for (auto& sessionInterface : m_sessions) {
+ if (!sessionInterface)
+ continue;
+
+ for (auto& keyStatusPair : sessionInterface->keyStatuses()) {
+ if (keyStatusPair.second != CDMInstanceSession::KeyStatus::Usable)
+ continue;
+
+ if (keys.findIf([&] (auto& key) {
+ return key.get() == keyStatusPair.first.get();
+ }) != notFound)
+ return true;
+ }
+ }
+ return false;
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::addKeyStatusesChangedObserver(const KeyStatusesChangedObserver& observer)
+{
+ m_keyStatusChangedObservers.add(observer);
+}
+
+void CDMInstanceFairPlayStreamingAVFObjC::sessionKeyStatusesChanged(const CDMInstanceSessionFairPlayStreamingAVFObjC&)
+{
+ m_keyStatusChangedObservers.forEach([] (auto& observer) {
+ observer();
+ });
+}
+
CDMInstanceSessionFairPlayStreamingAVFObjC::CDMInstanceSessionFairPlayStreamingAVFObjC(Ref<CDMInstanceFairPlayStreamingAVFObjC>&& instance)
: m_instance(WTFMove(instance))
, m_delegate(adoptNS([[WebCoreFPSContentKeySessionDelegate alloc] initWithParent:this]))
@@ -1306,6 +1337,8 @@
void CDMInstanceSessionFairPlayStreamingAVFObjC::requestDidSucceed(AVContentKeyRequest *request)
{
+ updateKeyStatuses();
+
if (m_updateResponseCollector) {
m_updateResponseCollector->addSuccessfulResponse(request, nullptr);
return;
@@ -1312,7 +1345,7 @@
}
if (m_updateLicenseCallback) {
- m_updateLicenseCallback(false, std::make_optional(keyStatuses()), std::nullopt, std::nullopt, Succeeded);
+ m_updateLicenseCallback(false, std::make_optional(copyKeyStatuses()), std::nullopt, std::nullopt, Succeeded);
ASSERT(!m_updateLicenseCallback);
}
@@ -1405,7 +1438,7 @@
}
}
-CDMInstanceSession::KeyStatusVector CDMInstanceSessionFairPlayStreamingAVFObjC::keyStatuses(std::optional<PlatformDisplayID> displayID) const
+void CDMInstanceSessionFairPlayStreamingAVFObjC::updateKeyStatuses(std::optional<PlatformDisplayID> displayID)
{
KeyStatusVector keyStatuses;
@@ -1427,9 +1460,21 @@
}
}
- return keyStatuses;
+ m_keyStatuses.swap(keyStatuses);
+
+ m_instance->sessionKeyStatusesChanged(*this);
}
+auto CDMInstanceSessionFairPlayStreamingAVFObjC::copyKeyStatuses() const -> KeyStatusVector
+{
+ KeyStatusVector copiedKeyStatuses;
+ copiedKeyStatuses.reserveInitialCapacity(m_keyStatuses.size());
+ for (auto& status : m_keyStatuses)
+ copiedKeyStatuses.uncheckedAppend({ status.first.copyRef(), status.second });
+ return copiedKeyStatuses;
+
+}
+
void CDMInstanceSessionFairPlayStreamingAVFObjC::outputObscuredDueToInsufficientExternalProtectionChanged(bool obscured)
{
if (obscured == m_outputObscured)
@@ -1438,8 +1483,10 @@
ALWAYS_LOG_IF_POSSIBLE(LOGIDENTIFIER, obscured);
m_outputObscured = obscured;
+ updateKeyStatuses();
+
if (m_client)
- m_client->updateKeyStatuses(keyStatuses());
+ m_client->updateKeyStatuses(copyKeyStatuses());
}
void CDMInstanceSessionFairPlayStreamingAVFObjC::externalProtectionStatusDidChangeForContentKeyRequest(AVContentKeyRequest*)
@@ -1492,9 +1539,13 @@
void CDMInstanceSessionFairPlayStreamingAVFObjC::updateProtectionStatusForDisplayID(PlatformDisplayID displayID)
{
- if (m_requests.isEmpty() || !m_client)
+ if (m_requests.isEmpty())
return;
- m_client->updateKeyStatuses(keyStatuses(displayID));
+
+ updateKeyStatuses(displayID);
+
+ if (m_client)
+ m_client->updateKeyStatuses(copyKeyStatuses());
}
bool CDMInstanceSessionFairPlayStreamingAVFObjC::ensureSessionOrGroup()
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -70,7 +70,7 @@
RetainPtr<WebCDMSessionAVContentKeySessionDelegate> m_contentKeySessionDelegate;
RetainPtr<AVContentKeyRequest> m_keyRequest;
RefPtr<Uint8Array> m_identifier;
- RefPtr<Uint8Array> m_initData;
+ RefPtr<SharedBuffer> m_initData;
RetainPtr<NSData> m_expiredSession;
Vector<int> m_protocolVersions;
int m_cdmVersion;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVContentKeySession.mm 2022-02-16 20:49:59 UTC (rev 289946)
@@ -32,6 +32,7 @@
#import "LegacyCDM.h"
#import "Logging.h"
#import "MediaPlayer.h"
+#import "SharedBuffer.h"
#import "SourceBufferPrivateAVFObjC.h"
#import "WebCoreNSErrorExtras.h"
#import <AVFoundation/AVError.h>
@@ -146,7 +147,7 @@
if (m_cdmVersion == 2)
m_identifier = initData;
else
- m_initData = initData;
+ m_initData = SharedBuffer::create(initData->data(), initData->length());
ASSERT(!m_certificate);
String certificateString("certificate"_s);
@@ -268,12 +269,12 @@
}
if (!m_keyRequest) {
- NSData* nsInitData = m_initData ? [NSData dataWithBytes:m_initData->data() length:m_initData->length()] : nil;
+ RetainPtr<NSData> nsInitData = m_initData ? m_initData->createNSData() : nil;
NSData* nsIdentifier = m_identifier ? [NSData dataWithBytes:m_identifier->data() length:m_identifier->length()] : nil;
if ([contentKeySession() respondsToSelector:@selector(processContentKeyRequestWithIdentifier:initializationData:options:)])
- [contentKeySession() processContentKeyRequestWithIdentifier:nsIdentifier initializationData:nsInitData options:nil];
+ [contentKeySession() processContentKeyRequestWithIdentifier:nsIdentifier initializationData:nsInitData.get() options:nil];
else
- [contentKeySession() processContentKeyRequestInitializationData:nsInitData options:nil];
+ [contentKeySession() processContentKeyRequestInitializationData:nsInitData.get() options:nil];
}
if (shouldGenerateKeyRequest) {
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm 2022-02-16 20:49:59 UTC (rev 289946)
@@ -2114,8 +2114,8 @@
auto keyURIArray = Uint16Array::create(initDataBuffer.copyRef(), 4, keyURI.length());
keyURIArray->setRange(reinterpret_cast<const UniChar*>(StringView(keyURI).upconvertedCharacters().get()), keyURI.length() / sizeof(unsigned char), 0);
- auto initData = Uint8Array::create(WTFMove(initDataBuffer), 0, byteLength);
- player()->keyNeeded(initData.ptr());
+ auto initData = SharedBuffer::create(Vector<uint8_t> { static_cast<uint8_t*>(initDataBuffer->data()), byteLength });
+ player()->keyNeeded(initData);
#if ENABLE(ENCRYPTED_MEDIA)
if (!player()->shouldContinueAfterKeyNeeded())
return true;
@@ -2143,10 +2143,8 @@
if (scheme == "clearkey") {
String keyID = [[[avRequest request] URL] resourceSpecifier];
auto encodedKeyId = PAL::UTF8Encoding().encode(keyID, PAL::UnencodableHandling::URLEncodedEntities);
+ auto initData = SharedBuffer::create(WTFMove(encodedKeyId));
- auto initData = Uint8Array::create(encodedKeyId.size());
- initData->setRange(encodedKeyId.data(), encodedKeyId.size(), 0);
-
auto keyData = player()->cachedKeyForKeyId(keyID);
if (keyData) {
fulfillRequestWithKeyData(avRequest, keyData.get());
@@ -2153,7 +2151,7 @@
return false;
}
- player()->keyNeeded(initData.ptr());
+ player()->keyNeeded(initData);
if (!player()->shouldContinueAfterKeyNeeded())
return false;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -137,7 +137,7 @@
void endSimulatedHDCPError() override { outputObscuredDueToInsufficientExternalProtectionChanged(false); }
#if ENABLE(LEGACY_ENCRYPTED_MEDIA) || ENABLE(ENCRYPTED_MEDIA)
- void keyNeeded(Uint8Array*);
+ void keyNeeded(const SharedBuffer&);
#endif
#if ENABLE(ENCRYPTED_MEDIA)
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1143,7 +1143,7 @@
#endif // ENABLE(LEGACY_ENCRYPTED_MEDIA)
#if ENABLE(LEGACY_ENCRYPTED_MEDIA) || ENABLE(ENCRYPTED_MEDIA)
-void MediaPlayerPrivateMediaSourceAVFObjC::keyNeeded(Uint8Array* initData)
+void MediaPlayerPrivateMediaSourceAVFObjC::keyNeeded(const SharedBuffer& initData)
{
m_player->keyNeeded(initData);
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -29,11 +29,13 @@
#include <_javascript_Core/Forward.h>
#include <pal/avfoundation/MediaTimeAVFoundation.h>
#include <wtf/Forward.h>
+#include <wtf/TypeCasts.h>
using CVPixelBufferRef = struct __CVBuffer*;
namespace WebCore {
+class FragmentedSharedBuffer;
class PixelBuffer;
class MediaSampleAVFObjC : public MediaSample {
@@ -60,6 +62,7 @@
SampleFlags flags() const override;
PlatformSample platformSample() const override;
+ PlatformSample::Type platformSampleType() const override { return PlatformSample::CMSampleBufferType; }
std::optional<ByteRange> byteRange() const override;
WEBCORE_EXPORT void dump(PrintStream&) const override;
void offsetTimestampsBy(const MediaTime&) override;
@@ -80,6 +83,13 @@
void setByteRangeOffset(size_t);
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ using KeyIDs = Vector<Ref<FragmentedSharedBuffer>>;
+ void setKeyIDs(KeyIDs&& keyIDs) { m_keyIDs = WTFMove(keyIDs); }
+ const KeyIDs& keyIDs() const { return m_keyIDs; }
+ KeyIDs& keyIDs() { return m_keyIDs; }
+#endif
+
protected:
WEBCORE_EXPORT MediaSampleAVFObjC(RetainPtr<CMSampleBufferRef>&&);
WEBCORE_EXPORT MediaSampleAVFObjC(CMSampleBufferRef);
@@ -94,10 +104,27 @@
AtomString m_id;
VideoRotation m_rotation { VideoRotation::None };
bool m_mirrored { false };
+
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ Vector<Ref<FragmentedSharedBuffer>> m_keyIDs;
+#endif
};
} // namespace WebCore
+namespace WTF {
+
+template<typename Type> struct LogArgument;
+template <>
+struct LogArgument<WebCore::MediaSampleAVFObjC> {
+ static String toString(const WebCore::MediaSampleAVFObjC& sample)
+ {
+ return sample.toJSONString();
+ }
+};
+
+} // namespace WTF
+
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MediaSampleAVFObjC)
- static bool isType(const WebCore::MediaSample& mediaSample) { return mediaSample.platformSample().type == WebCore::PlatformSample::CMSampleBufferType; }
+static bool isType(const WebCore::MediaSample& sample) { return sample.platformSampleType() == WebCore::PlatformSample::CMSampleBufferType; }
SPECIALIZE_TYPE_TRAITS_END()
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -125,7 +125,7 @@
void sourceBufferPrivateDidChangeActiveState(SourceBufferPrivateAVFObjC*, bool active);
void sourceBufferPrivateDidReceiveInitializationSegment(SourceBufferPrivateAVFObjC*);
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
- void sourceBufferKeyNeeded(SourceBufferPrivateAVFObjC*, Uint8Array*);
+ void sourceBufferKeyNeeded(SourceBufferPrivateAVFObjC*, const SharedBuffer&);
#endif
void removeSourceBuffer(SourceBufferPrivate*);
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSourcePrivateAVFObjC.mm 2022-02-16 20:49:59 UTC (rev 289946)
@@ -195,9 +195,10 @@
}
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
-void MediaSourcePrivateAVFObjC::sourceBufferKeyNeeded(SourceBufferPrivateAVFObjC* buffer, Uint8Array* initData)
+void MediaSourcePrivateAVFObjC::sourceBufferKeyNeeded(SourceBufferPrivateAVFObjC* buffer, const SharedBuffer& initData)
{
m_sourceBuffersNeedingSessions.append(buffer);
+
if (m_player)
m_player->keyNeeded(initData);
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -68,6 +68,7 @@
void didProvideMediaDataForTrackID(uint64_t trackID, CMSampleBufferRef, const String& mediaType, unsigned flags);
void willProvideContentKeyRequestInitializationDataForTrackID(uint64_t trackID);
void didProvideContentKeyRequestInitializationDataForTrackID(NSData*, uint64_t trackID);
+ void didProvideContentKeyRequestSpecifierForTrackID(NSData*, uint64_t trackID);
private:
#if !RELEASE_LOG_DISABLED
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.mm (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.mm 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferParserAVFObjC.mm 2022-02-16 20:49:59 UTC (rev 289946)
@@ -57,6 +57,12 @@
#pragma mark -
#pragma mark WebAVStreamDataParserListener
+#if HAVE(AVCONTENTKEYSPECIFIER)
+@interface AVContentKeySpecifier (WebCorePrivate)
+@property (readonly) NSData *initializationData;
+@end
+#endif
+
@interface WebAVStreamDataParserListener : NSObject<AVStreamDataParserOutputHandling> {
WebCore::SourceBufferParserAVFObjC* _parent;
AVStreamDataParser* _parser;
@@ -133,6 +139,16 @@
ASSERT_UNUSED(streamDataParser, streamDataParser == _parser);
_parent->didProvideContentKeyRequestInitializationDataForTrackID(initData, trackID);
}
+
+#if HAVE(AVCONTENTKEYSPECIFIER)
+- (void)streamDataParser:(AVStreamDataParser *)streamDataParser didProvideContentKeySpecifier:(AVContentKeySpecifier *)keySpecifier forTrackID:(CMPersistentTrackID)trackID
+{
+ ASSERT_UNUSED(streamDataParser, streamDataParser == _parser);
+ if ([keySpecifier respondsToSelector:@selector(initializationData)])
+ _parent->didProvideContentKeyRequestSpecifierForTrackID(keySpecifier.initializationData, trackID);
+}
+#endif
+
@end
namespace WebCore {
@@ -334,10 +350,14 @@
void SourceBufferParserAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID(NSData* nsInitData, uint64_t trackID)
{
- auto initData = Uint8Array::create(nsInitData.length);
- [nsInitData getBytes:initData->data() length:initData->length()];
+ m_didProvideContentKeyRequestInitializationDataForTrackIDCallback(SharedBuffer::create(nsInitData), trackID);
+}
- m_didProvideContentKeyRequestInitializationDataForTrackIDCallback(WTFMove(initData), trackID);
+void SourceBufferParserAVFObjC::didProvideContentKeyRequestSpecifierForTrackID(NSData* nsInitData, uint64_t trackID)
+{
+ m_callOnClientThreadCallback([this, strongThis = Ref { *this }, nsInitData = retainPtr(nsInitData), trackID] {
+ m_didProvideContentKeyRequestIdentifierForTrackIDCallback(SharedBuffer::create(nsInitData.get()), trackID);
+ });
}
}
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -37,6 +37,7 @@
#include <wtf/LoggerHelper.h>
#include <wtf/MediaTime.h>
#include <wtf/OSObjectPtr.h>
+#include <wtf/Observer.h>
#include <wtf/RefPtr.h>
#include <wtf/RetainPtr.h>
#include <wtf/Vector.h>
@@ -95,8 +96,10 @@
void clearMediaSource() { m_mediaSource = nullptr; }
void willProvideContentKeyRequestInitializationDataForTrackID(uint64_t trackID);
- void didProvideContentKeyRequestInitializationDataForTrackID(Ref<Uint8Array>&&, uint64_t trackID, Box<BinarySemaphore>);
+ void didProvideContentKeyRequestInitializationDataForTrackID(Ref<SharedBuffer>&&, uint64_t trackID, Box<BinarySemaphore>);
+ void didProvideContentKeyRequestIdentifierForTrackID(Ref<SharedBuffer>&&, uint64_t trackID);
+
bool hasSelectedVideo() const;
void trackDidChangeSelected(VideoTrackPrivate&, bool selected);
@@ -132,7 +135,7 @@
void bufferWasConsumed();
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
- Uint8Array* initData() { return m_initData.get(); }
+ SharedBuffer* initData() { return m_initData.get(); }
#endif
#if !RELEASE_LOG_DISABLED
@@ -150,7 +153,7 @@
using InitializationSegment = SourceBufferPrivateClient::InitializationSegment;
void didParseInitializationData(InitializationSegment&&);
void didEncounterErrorDuringParsing(int32_t);
- void didProvideMediaDataForTrackId(Ref<MediaSample>&&, uint64_t trackId, const String& mediaType);
+ void didProvideMediaDataForTrackId(Ref<MediaSampleAVFObjC>&&, uint64_t trackId, const String& mediaType);
// SourceBufferPrivate overrides
void append(Ref<SharedBuffer>&&) final;
@@ -174,6 +177,7 @@
MediaTime currentMediaTime() const final;
MediaTime duration() const final;
+ void enqueueSample(Ref<MediaSampleAVFObjC>&&, uint64_t trackID);
void didBecomeReadyForMoreSamples(uint64_t trackID);
void appendCompleted();
void destroyStreamDataParser();
@@ -186,7 +190,13 @@
ALLOW_NEW_API_WITHOUT_GUARDS_END
MediaPlayerPrivateMediaSourceAVFObjC* player() const;
+ bool canEnqueueSample(uint64_t trackID, const MediaSampleAVFObjC&);
+ bool trackIsBlocked(uint64_t track) const;
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ void keyStatusesChanged();
+#endif
+
Vector<RefPtr<VideoTrackPrivate>> m_videoTracks;
Vector<RefPtr<AudioTrackPrivate>> m_audioTracks;
Vector<SourceBufferPrivateAVFObjCErrorClient*> m_errorClients;
@@ -197,7 +207,8 @@
bool m_processingInitializationSegment { false };
bool m_hasPendingAppendCompletedCallback { false };
Vector<Function<void()>> m_pendingTrackChangeCallbacks;
- Vector<std::pair<uint64_t, Ref<MediaSample>>> m_mediaSamples;
+ Vector<std::pair<uint64_t, Ref<MediaSampleAVFObjC>>> m_mediaSamples;
+ Deque<std::pair<uint64_t, Ref<MediaSampleAVFObjC>>> m_blockedSamples;
RetainPtr<AVSampleBufferDisplayLayer> m_displayLayer;
ALLOW_NEW_API_WITHOUT_GUARDS_BEGIN
@@ -215,13 +226,27 @@
MediaSourcePrivateAVFObjC* m_mediaSource;
bool m_isActive { false };
+
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
- RefPtr<Uint8Array> m_initData;
+ RefPtr<SharedBuffer> m_initData;
WeakPtr<CDMSessionMediaSourceAVFObjC> m_session { nullptr };
#endif
#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ using KeyIDs = Vector<Ref<FragmentedSharedBuffer>>;
+ struct TrackInitData {
+ RefPtr<SharedBuffer> initData;
+ KeyIDs keyIDs;
+ };
+ using TrackInitDataMap = HashMap<uint64_t, TrackInitData>;
+ TrackInitDataMap m_pendingProtectedTrackInitDataMap;
+ TrackInitDataMap m_protectedTrackInitDataMap;
+
+ using TrackKeyIDsMap = HashMap<uint64_t, KeyIDs>;
+ TrackKeyIDsMap m_currentTrackIDs;
+
RefPtr<CDMInstanceFairPlayStreamingAVFObjC> m_cdmInstance;
- Vector<Ref<FragmentedSharedBuffer>> m_keyIDs;
+ UniqueRef<Observer<void()>> m_keyStatusesChangedObserver;
+ KeyIDs m_keyIDs;
#endif
std::optional<FloatSize> m_cachedSize;
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm 2022-02-16 20:49:59 UTC (rev 289946)
@@ -76,6 +76,12 @@
- (void)resetUpcomingSampleBufferPresentationTimeExpectations;
@end
+@interface AVSampleBufferDisplayLayer (WebCoreSampleBufferKeySession) <AVContentKeyRecipient>
+@end
+
+@interface AVSampleBufferAudioRenderer (WebCoreSampleBufferKeySession) <AVContentKeyRecipient>
+@end
+
#pragma mark -
#pragma mark AVStreamSession
@@ -275,6 +281,24 @@
return ++mapID;
}
+static bool sampleBufferRenderersSupportKeySession()
+{
+ static bool supports = false;
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, [&] {
+ supports = [PAL::getAVSampleBufferAudioRendererClass() conformsToProtocol:@protocol(AVContentKeyRecipient)]
+ && [PAL::getAVSampleBufferDisplayLayerClass() conformsToProtocol:@protocol(AVContentKeyRecipient)];
+ });
+ return supports;
+}
+
+static Vector<Ref<FragmentedSharedBuffer>> copyKeyIDs(const Vector<Ref<FragmentedSharedBuffer>> keyIDs)
+{
+ return keyIDs.map([] (auto& keyID) {
+ return keyID.copyRef();
+ });
+}
+
static void bufferWasConsumedCallback(CMNotificationCenterRef, const void* listener, CFStringRef notificationName, const void*, CFTypeRef)
{
if (!CFEqual(PAL::kCMSampleBufferConsumerNotification_BufferConsumed, notificationName))
@@ -307,6 +331,9 @@
, m_errorListener(adoptNS([[WebAVSampleBufferErrorListener alloc] initWithParent:*this]))
, m_appendQueue(WorkQueue::create("SourceBufferPrivateAVFObjC data parser queue"))
, m_mediaSource(parent)
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ , m_keyStatusesChangedObserver(makeUniqueRef<Observer<void()>>([this] { keyStatusesChanged(); }))
+#endif
, m_mapID(nextMapID())
#if !RELEASE_LOG_DISABLED
, m_logger(parent->logger())
@@ -364,6 +391,9 @@
clearTracks();
+ m_protectedTrackInitDataMap.swap(m_pendingProtectedTrackInitDataMap);
+ m_pendingProtectedTrackInitDataMap.clear();
+
for (auto videoTrackInfo : segment.videoTracks) {
videoTrackInfo.track->setSelectedChangedCallback([weakThis = WeakPtr { *this }, this] (VideoTrackPrivate& track, bool selected) {
if (!weakThis)
@@ -458,10 +488,16 @@
m_parsingSucceeded = false;
}
-void SourceBufferPrivateAVFObjC::didProvideMediaDataForTrackId(Ref<MediaSample>&& mediaSample, uint64_t trackId, const String& mediaType)
+void SourceBufferPrivateAVFObjC::didProvideMediaDataForTrackId(Ref<MediaSampleAVFObjC>&& mediaSample, uint64_t trackId, const String& mediaType)
{
UNUSED_PARAM(mediaType);
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ auto findResult = m_protectedTrackInitDataMap.find(trackId);
+ if (findResult != m_protectedTrackInitDataMap.end())
+ mediaSample->setKeyIDs(copyKeyIDs(findResult->value.keyIDs));
+#endif
+
if (m_processingInitializationSegment) {
DEBUG_LOG(LOGIDENTIFIER, mediaSample.get());
m_mediaSamples.append(std::make_pair(trackId, WTFMove(mediaSample)));
@@ -508,7 +544,7 @@
#endif
}
-void SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID(Ref<Uint8Array>&& initData, uint64_t trackID, Box<BinarySemaphore> hasSessionSemaphore)
+void SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID(Ref<SharedBuffer>&& initData, uint64_t trackID, Box<BinarySemaphore> hasSessionSemaphore)
{
auto player = this->player();
if (!player)
@@ -519,11 +555,15 @@
m_protectedTrackID = trackID;
m_initData = WTFMove(initData);
- m_mediaSource->sourceBufferKeyNeeded(this, m_initData.get());
+ m_mediaSource->sourceBufferKeyNeeded(this, *m_initData);
+
if (auto session = player->cdmSession()) {
- if (auto parser = this->streamDataParser())
+ if (sampleBufferRenderersSupportKeySession()) {
+ // no-op.
+ } else if (auto parser = this->streamDataParser())
session->addParser(parser);
- hasSessionSemaphore->signal();
+ if (hasSessionSemaphore)
+ hasSessionSemaphore->signal();
return;
}
#endif
@@ -533,14 +573,17 @@
m_hasSessionSemaphore = hasSessionSemaphore;
#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
- auto initDataBuffer = SharedBuffer::create(m_initData->data(), m_initData->byteLength());
- auto keyIDs = CDMPrivateFairPlayStreaming::extractKeyIDsSinf(initDataBuffer);
+ auto keyIDs = CDMPrivateFairPlayStreaming::extractKeyIDsSinf(*m_initData);
if (!keyIDs)
return;
+ m_pendingProtectedTrackInitDataMap.set(trackID, TrackInitData { m_initData.copyRef(), *keyIDs });
+
if (m_cdmInstance) {
if (auto instanceSession = m_cdmInstance->sessionForKeyIDs(keyIDs.value())) {
- if (auto parser = this->streamDataParser())
+ if (sampleBufferRenderersSupportKeySession()) {
+ // no-op.
+ } else if (auto parser = this->streamDataParser())
[instanceSession->contentKeySession() addContentKeyRecipient:parser];
if (m_hasSessionSemaphore) {
m_hasSessionSemaphore->signal();
@@ -552,7 +595,7 @@
}
m_keyIDs = WTFMove(keyIDs.value());
- player->initializationDataEncountered("sinf", initDataBuffer->tryCreateArrayBuffer());
+ player->initializationDataEncountered("sinf", m_initData->tryCreateArrayBuffer());
m_waitingForKey = true;
player->waitingForKeyChanged();
@@ -587,7 +630,7 @@
weakThis->didEncounterErrorDuringParsing(errorCode);
});
- m_parser->setDidProvideMediaDataCallback([weakThis = WeakPtr { *this }, abortCalled = m_abortCalled] (Ref<MediaSample>&& sample, uint64_t trackId, const String& mediaType) {
+ m_parser->setDidProvideMediaDataCallback([weakThis = WeakPtr { *this }, abortCalled = m_abortCalled] (Ref<MediaSampleAVFObjC>&& sample, uint64_t trackId, const String& mediaType) {
ASSERT(isMainThread());
if (!weakThis || abortCalled != weakThis->m_abortCalled)
return;
@@ -616,7 +659,7 @@
}
});
- m_parser->setDidProvideContentKeyRequestInitializationDataForTrackIDCallback([weakThis = WeakPtr { *this }, abortSemaphore = m_abortSemaphore, abortCalled = m_abortCalled](Ref<Uint8Array>&& initData, uint64_t trackID) mutable {
+ m_parser->setDidProvideContentKeyRequestInitializationDataForTrackIDCallback([weakThis = WeakPtr { *this }, abortSemaphore = m_abortSemaphore, abortCalled = m_abortCalled](Ref<SharedBuffer>&& initData, uint64_t trackID) mutable {
// Called on the data parser queue.
Box<BinarySemaphore> hasSessionSemaphore = Box<BinarySemaphore>::create();
callOnMainThread([weakThis = WTFMove(weakThis), abortCalled, initData = WTFMove(initData), trackID, hasSessionSemaphore] () mutable {
@@ -636,6 +679,13 @@
}
});
+ m_parser->setDidProvideContentKeyRequestIdentifierForTrackIDCallback([weakThis = WeakPtr { *this }, abortCalled = m_abortCalled] (Ref<SharedBuffer>&& initData, uint64_t trackID) {
+ ASSERT(isMainThread());
+ if (!weakThis || abortCalled != weakThis->m_abortCalled)
+ return;
+ weakThis->didProvideContentKeyRequestInitializationDataForTrackID(WTFMove(initData), trackID, nullptr);
+ });
+
m_parsingSucceeded = true;
m_appendQueue->dispatch([data = "" weakThis = m_appendWeakFactory.createWeakPtr(*this), parser = m_parser, abortCalled = m_abortCalled]() mutable {
@@ -736,6 +786,11 @@
[renderer flush];
[renderer stopRequestingMediaData];
[m_errorListener stopObservingRenderer:renderer.get()];
+
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ if (m_cdmInstance && sampleBufferRenderersSupportKeySession())
+ [m_cdmInstance->contentKeySession() removeContentKeyRecipient:renderer.get()];
+#endif
}
[m_errorListener invalidate];
@@ -843,6 +898,11 @@
return;
}
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ if (m_cdmInstance && sampleBufferRenderersSupportKeySession())
+ [m_cdmInstance->contentKeySession() addContentKeyRecipient:renderer.get()];
+#endif
+
WeakPtr weakThis { *this };
[renderer requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^{
if (weakThis)
@@ -909,7 +969,24 @@
ALWAYS_LOG(LOGIDENTIFIER);
+ if (sampleBufferRenderersSupportKeySession() && m_cdmInstance) {
+ if (m_displayLayer)
+ [m_cdmInstance->contentKeySession() removeContentKeyRecipient:m_displayLayer.get()];
+
+ for (auto& audioRenderer : m_audioRenderers.values())
+ [m_cdmInstance->contentKeySession() removeContentKeyRecipient:audioRenderer.get()];
+ }
+
m_cdmInstance = fpsInstance;
+
+ if (sampleBufferRenderersSupportKeySession() && m_cdmInstance) {
+ if (m_displayLayer)
+ [m_cdmInstance->contentKeySession() addContentKeyRecipient:m_displayLayer.get()];
+
+ for (auto& audioRenderer : m_audioRenderers.values())
+ [m_cdmInstance->contentKeySession() addContentKeyRecipient:audioRenderer.get()];
+ }
+
attemptToDecrypt();
#else
UNUSED_PARAM(instance);
@@ -926,8 +1003,10 @@
if (!instanceSession)
return;
- if (auto parser = this->streamDataParser())
- [instanceSession->contentKeySession() addContentKeyRecipient:parser];
+ if (!sampleBufferRenderersSupportKeySession()) {
+ if (auto parser = this->streamDataParser())
+ [instanceSession->contentKeySession() addContentKeyRecipient:parser];
+ }
if (m_hasSessionSemaphore) {
m_hasSessionSemaphore->signal();
m_hasSessionSemaphore = nullptr;
@@ -1105,6 +1184,63 @@
player->setHasAvailableAudioSample(renderer, false);
}
+bool SourceBufferPrivateAVFObjC::trackIsBlocked(uint64_t trackID) const
+{
+ for (auto& samplePair : m_blockedSamples) {
+ if (samplePair.first == trackID)
+ return true;
+ }
+ return false;
+}
+
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+void SourceBufferPrivateAVFObjC::keyStatusesChanged()
+{
+ while (!m_blockedSamples.isEmpty()) {
+ auto& firstPair = m_blockedSamples.first();
+
+ // If we still can't enqueue the sample, bail.
+ if (!canEnqueueSample(firstPair.first, firstPair.second))
+ return;
+
+ auto firstPairTaken = m_blockedSamples.takeFirst();
+ enqueueSample(WTFMove(firstPairTaken.second), firstPairTaken.first);
+ }
+}
+#endif
+
+bool SourceBufferPrivateAVFObjC::canEnqueueSample(uint64_t trackID, const MediaSampleAVFObjC& sample)
+{
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ // If sample buffers don't support AVContentKeySession: enqueue sample
+ if (!sampleBufferRenderersSupportKeySession())
+ return true;
+
+ // if sample is unencrytped: enqueue sample
+ if (sample.keyIDs().isEmpty())
+ return true;
+
+ // if sample is encrypted, but we are not attached to a CDM: do not enqueue sample.
+ if (!m_cdmInstance)
+ return false;
+
+ // if sample is encrypted, and keyIDs match the current set of keyIDs: enqueue sample.
+ auto findResult = m_currentTrackIDs.find(trackID);
+ if (findResult != m_currentTrackIDs.end() && findResult->value == sample.keyIDs())
+ return true;
+
+ // if sample's set of keyIDs does not match the current set of keyIDs, consult with the CDM
+ // to determine if the keyIDs are usable; if so, update the current set of keyIDs and enqueue sample.
+ if (m_cdmInstance->isAnyKeyUsable(sample.keyIDs())) {
+ m_currentTrackIDs.set(trackID, sample.keyIDs());
+ return true;
+ }
+ return false;
+#else
+ return true;
+#endif
+}
+
void SourceBufferPrivateAVFObjC::enqueueSample(Ref<MediaSample>&& sample, const AtomString& trackIDString)
{
auto trackID = parseIntegerAllowingTrailingJunk<uint64_t>(trackIDString).value_or(0);
@@ -1111,13 +1247,26 @@
if (trackID != m_enabledVideoTrackID && !m_audioRenderers.contains(trackID))
return;
- PlatformSample platformSample = sample->platformSample();
- if (platformSample.type != PlatformSample::CMSampleBufferType)
+ ASSERT(is<MediaSampleAVFObjC>(sample));
+ if (!is<MediaSampleAVFObjC>(sample))
return;
+ Ref<MediaSampleAVFObjC> sampleAVFObjC = static_reference_cast<MediaSampleAVFObjC>(WTFMove(sample));
+ if (!sampleAVFObjC->keyIDs().isEmpty() && !canEnqueueSample(trackID, sampleAVFObjC)) {
+ m_blockedSamples.append({ trackID, WTFMove(sampleAVFObjC) });
+ return;
+ }
+
+ enqueueSample(WTFMove(sampleAVFObjC), trackID);
+}
+
+void SourceBufferPrivateAVFObjC::enqueueSample(Ref<MediaSampleAVFObjC>&& sample, uint64_t trackID)
+{
auto logSiteIdentifier = LOGIDENTIFIER;
DEBUG_LOG(logSiteIdentifier, "track ID = ", trackID, ", sample = ", sample.get());
+ PlatformSample platformSample = sample->platformSample();
+
CMFormatDescriptionRef formatDescription = PAL::CMSampleBufferGetFormatDescription(platformSample.sample.cmSampleBuffer);
ASSERT(formatDescription);
if (!formatDescription) {
@@ -1284,6 +1433,9 @@
else
return;
+ if (trackIsBlocked(trackID))
+ return;
+
provideMediaData(AtomString::number(trackID));
}
@@ -1375,11 +1527,21 @@
[m_displayLayer flush];
[m_displayLayer stopRequestingMediaData];
[m_errorListener stopObservingLayer:m_displayLayer.get()];
+
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ if (m_cdmInstance && sampleBufferRenderersSupportKeySession())
+ [m_cdmInstance->contentKeySession() removeContentKeyRecipient:m_displayLayer.get()];
+#endif
}
m_displayLayer = layer;
if (m_displayLayer) {
+#if ENABLE(ENCRYPTED_MEDIA) && HAVE(AVCONTENTKEYSESSION)
+ if (m_cdmInstance && sampleBufferRenderersSupportKeySession())
+ [m_cdmInstance->contentKeySession() addContentKeyRecipient:m_displayLayer.get()];
+#endif
+
WeakPtr weakThis { *this };
[m_displayLayer requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^ {
if (weakThis)
Modified: trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParser.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParser.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParser.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -44,7 +44,7 @@
namespace WebCore {
class ContentType;
-class MediaSample;
+class MediaSampleAVFObjC;
class SharedBuffer;
class WEBCORE_EXPORT SourceBufferParser : public ThreadSafeRefCounted<SourceBufferParser> {
@@ -123,7 +123,7 @@
}
// Will be called on the main thread.
- using DidProvideMediaDataCallback = Function<void(Ref<MediaSample>&&, uint64_t trackID, const String& mediaType)>;
+ using DidProvideMediaDataCallback = Function<void(Ref<MediaSampleAVFObjC>&&, uint64_t trackID, const String& mediaType)>;
void setDidProvideMediaDataCallback(DidProvideMediaDataCallback&& callback)
{
m_didProvideMediaDataCallback = WTFMove(callback);
@@ -137,12 +137,19 @@
}
// Will be called synchronously on the parser thead.
- using DidProvideContentKeyRequestInitializationDataForTrackIDCallback = Function<void(Ref<Uint8Array>&&, uint64_t trackID)>;
+ using DidProvideContentKeyRequestInitializationDataForTrackIDCallback = Function<void(Ref<SharedBuffer>&&, uint64_t trackID)>;
void setDidProvideContentKeyRequestInitializationDataForTrackIDCallback(DidProvideContentKeyRequestInitializationDataForTrackIDCallback&& callback)
{
m_didProvideContentKeyRequestInitializationDataForTrackIDCallback = WTFMove(callback);
}
+ // Will be called on the main thread.
+ using DidProvideContentKeyRequestIdentifierForTrackIDCallback = Function<void(Ref<SharedBuffer>&&, uint64_t trackID)>;
+ void setDidProvideContentKeyRequestIdentifierForTrackIDCallback(DidProvideContentKeyRequestIdentifierForTrackIDCallback&& callback)
+ {
+ m_didProvideContentKeyRequestIdentifierForTrackIDCallback = WTFMove(callback);
+ }
+
protected:
SourceBufferParser();
@@ -152,6 +159,7 @@
DidProvideMediaDataCallback m_didProvideMediaDataCallback;
WillProvideContentKeyRequestInitializationDataForTrackIDCallback m_willProvideContentKeyRequestInitializationDataForTrackIDCallback;
DidProvideContentKeyRequestInitializationDataForTrackIDCallback m_didProvideContentKeyRequestInitializationDataForTrackIDCallback;
+ DidProvideContentKeyRequestIdentifierForTrackIDCallback m_didProvideContentKeyRequestIdentifierForTrackIDCallback;
};
}
Modified: trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1032,7 +1032,7 @@
continue;
auto& keyId = keyIdElement.value();
- m_keyIds.append(std::make_pair(trackEntry.track_uid.value(), Uint8Array::create(keyId.data(), keyId.size())));
+ m_keyIds.append(std::make_pair(trackEntry.track_uid.value(), SharedBuffer::create(keyId.data(), keyId.size())));
}
}
Modified: trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/cocoa/SourceBufferParserWebM.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -269,7 +269,7 @@
webm::Status OnFrame(const webm::FrameMetadata&, webm::Reader*, uint64_t* bytesRemaining) final;
std::unique_ptr<InitializationSegment> m_initializationSegment;
- Vector<std::pair<uint64_t, Ref<Uint8Array>>> m_keyIds;
+ Vector<std::pair<uint64_t, Ref<SharedBuffer>>> m_keyIds;
webm::Status m_status;
std::unique_ptr<webm::WebmParser> m_parser;
bool m_initializationSegmentEncountered { false };
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h (289945 => 289946)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -62,6 +62,7 @@
Ref<MediaSample> createNonDisplayingCopy() const override;
SampleFlags flags() const override { return m_flags; }
PlatformSample platformSample() const override;
+ PlatformSample::Type platformSampleType() const override { return PlatformSample::GStreamerSampleType; }
std::optional<ByteRange> byteRange() const override { return std::nullopt; }
void dump(PrintStream&) const override;
RefPtr<JSC::Uint8ClampedArray> getRGBAImageData() const final;
Modified: trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp (289945 => 289946)
--- trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -61,6 +61,7 @@
size_t sizeInBytes() const override { return sizeof(m_box); }
SampleFlags flags() const override;
PlatformSample platformSample() const override;
+ PlatformSample::Type platformSampleType() const override { return PlatformSample::MockSampleBoxType; }
std::optional<ByteRange> byteRange() const override { return std::nullopt; }
FloatSize presentationSize() const override { return FloatSize(); }
void dump(PrintStream&) const override;
Modified: trunk/Source/WebKit/ChangeLog (289945 => 289946)
--- trunk/Source/WebKit/ChangeLog 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebKit/ChangeLog 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1,3 +1,24 @@
+2022-02-16 Jer Noble <[email protected]>
+
+ [Cocoa] Adopt -streamDataParser:didProvideContentKeySpecifier:forTrackID: delegate callback
+ https://bugs.webkit.org/show_bug.cgi?id=236109
+
+ Reviewed by Eric Carlson.
+
+ Add the newly requried virtual method changes to MediaSample subclasses, and use
+ SharedBuffer rather than Uint8Array.
+
+ * GPUProcess/media/RemoteMediaPlayerProxy.cpp:
+ (WebKit::RemoteMediaPlayerProxy::mediaPlayerKeyNeeded):
+ * GPUProcess/media/RemoteMediaPlayerProxy.h:
+ * Shared/mac/MediaFormatReader/MediaFormatReader.cpp:
+ (WebKit::MediaFormatReader::parseByteSource):
+ (WebKit::MediaFormatReader::didProvideMediaData):
+ * Shared/mac/MediaFormatReader/MediaFormatReader.h:
+ * Shared/mac/MediaFormatReader/MediaSampleByteRange.h:
+ * WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp:
+ (WebKit::MediaPlayerPrivateRemote::mediaPlayerKeyNeeded):
+
2022-02-16 Stephan Szabo <[email protected]>
[PlayStation] Build fix after r289872
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp (289945 => 289946)
--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -698,11 +698,10 @@
return nullptr;
}
-void RemoteMediaPlayerProxy::mediaPlayerKeyNeeded(Uint8Array* message)
+void RemoteMediaPlayerProxy::mediaPlayerKeyNeeded(const SharedBuffer& message)
{
IPC::DataReference messageReference;
- if (message)
- messageReference = { message->data(), message->byteLength() };
+ messageReference = { message.data(), message.size() };
m_webProcessConnection->send(Messages::MediaPlayerPrivateRemote::MediaPlayerKeyNeeded(WTFMove(messageReference)), m_id);
}
#endif
Modified: trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.h (289945 => 289946)
--- trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteMediaPlayerProxy.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -249,7 +249,7 @@
#if ENABLE(LEGACY_ENCRYPTED_MEDIA)
RefPtr<ArrayBuffer> mediaPlayerCachedKeyForKeyId(const String&) const final;
- void mediaPlayerKeyNeeded(Uint8Array*) final;
+ void mediaPlayerKeyNeeded(const WebCore::SharedBuffer&) final;
String mediaPlayerMediaKeysStorageDirectory() const final;
#endif
Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp (289945 => 289946)
--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -162,7 +162,7 @@
didParseTracks({ }, errorCode);
});
- parser->setDidProvideMediaDataCallback([this, protectedThis = Ref { *this }](Ref<MediaSample>&& mediaSample, uint64_t trackID, const String& mediaType) {
+ parser->setDidProvideMediaDataCallback([this, protectedThis = Ref { *this }](Ref<MediaSampleAVFObjC>&& mediaSample, uint64_t trackID, const String& mediaType) {
didProvideMediaData(WTFMove(mediaSample), trackID, mediaType);
});
@@ -224,7 +224,7 @@
m_init = true;
}
-void MediaFormatReader::didProvideMediaData(Ref<MediaSample>&& mediaSample, uint64_t trackID, const String&)
+void MediaFormatReader::didProvideMediaData(Ref<MediaSampleAVFObjC>&& mediaSample, uint64_t trackID, const String&)
{
ASSERT(!isMainRunLoop());
Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.h (289945 => 289946)
--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaFormatReader.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -36,6 +36,7 @@
DECLARE_CORE_MEDIA_TRAITS(FormatReader);
namespace WebCore {
+class MediaSampleAVFObjC;
class SourceBufferParser;
}
@@ -67,7 +68,7 @@
void didParseTracks(WebCore::SourceBufferPrivateClient::InitializationSegment&&, uint64_t errorCode);
void didSelectVideoTrack(WebCore::VideoTrackPrivate&, bool) { }
void didEnableAudioTrack(WebCore::AudioTrackPrivate&, bool) { }
- void didProvideMediaData(Ref<WebCore::MediaSample>&&, uint64_t, const String&);
+ void didProvideMediaData(Ref<WebCore::MediaSampleAVFObjC>&&, uint64_t, const String&);
void finishParsing(Ref<WebCore::SourceBufferParser>&&);
// CMBaseClass
Modified: trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.h (289945 => 289946)
--- trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebKit/Shared/mac/MediaFormatReader/MediaSampleByteRange.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -51,6 +51,7 @@
AtomString trackID() const final;
WebCore::PlatformSample platformSample() const final;
+ WebCore::PlatformSample::Type platformSampleType() const final { return WebCore::PlatformSample::ByteRangeSampleType; }
void offsetTimestampsBy(const MediaTime&) final;
void setTimestamps(const MediaTime&, const MediaTime&) final;
Modified: trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp (289945 => 289946)
--- trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebKit/WebProcess/GPU/media/MediaPlayerPrivateRemote.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1191,7 +1191,7 @@
void MediaPlayerPrivateRemote::mediaPlayerKeyNeeded(IPC::DataReference&& message)
{
if (RefPtr player = m_player.get())
- player->keyNeeded(Uint8Array::create(message.data(), message.size()).ptr());
+ player->keyNeeded(SharedBuffer::create(message));
}
#endif
Modified: trunk/Source/WebKit/WebProcess/GPU/media/RemoteVideoFrameProxy.h (289945 => 289946)
--- trunk/Source/WebKit/WebProcess/GPU/media/RemoteVideoFrameProxy.h 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Source/WebKit/WebProcess/GPU/media/RemoteVideoFrameProxy.h 2022-02-16 20:49:59 UTC (rev 289946)
@@ -102,6 +102,7 @@
uint32_t videoPixelFormat() const final;
// FIXME: When VideoFrame is not MediaSample, these will not be needed.
WebCore::PlatformSample platformSample() const final;
+ WebCore::PlatformSample::Type platformSampleType() const final { return WebCore::PlatformSample::RemoteVideoFrameProxyType; }
#if PLATFORM(COCOA)
void getPixelBuffer();
@@ -143,9 +144,9 @@
}
SPECIALIZE_TYPE_TRAITS_BEGIN(WebKit::RemoteVideoFrameProxy)
- static bool isType(const WebCore::MediaSample& mediaSample) { return mediaSample.platformSample().type == WebCore::PlatformSample::RemoteVideoFrameProxyType; }
+ static bool isType(const WebCore::MediaSample& mediaSample) { return mediaSample.platformSampleType() == WebCore::PlatformSample::RemoteVideoFrameProxyType; }
SPECIALIZE_TYPE_TRAITS_END()
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::VideoFrame)
- static bool isType(const WebCore::MediaSample& mediaSample) { return mediaSample.platformSample().type == WebCore::PlatformSample::RemoteVideoFrameProxyType; }
+ static bool isType(const WebCore::MediaSample& mediaSample) { return mediaSample.platformSampleType() == WebCore::PlatformSample::RemoteVideoFrameProxyType; }
SPECIALIZE_TYPE_TRAITS_END()
#endif
Modified: trunk/Tools/ChangeLog (289945 => 289946)
--- trunk/Tools/ChangeLog 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Tools/ChangeLog 2022-02-16 20:49:59 UTC (rev 289946)
@@ -1,3 +1,12 @@
+2022-02-16 Jer Noble <[email protected]>
+
+ [Cocoa] Adopt -streamDataParser:didProvideContentKeySpecifier:forTrackID: delegate callback
+ https://bugs.webkit.org/show_bug.cgi?id=236109
+
+ Reviewed by Eric Carlson.
+
+ * TestWebKitAPI/Tests/WebCore/SampleMap.cpp:
+
2022-02-16 David Kilzer <[email protected]>
Workaround ASAN false positive stack-buffer-underflow bmalloc_allocate_impl_casual_case
Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp (289945 => 289946)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp 2022-02-16 20:26:05 UTC (rev 289945)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp 2022-02-16 20:49:59 UTC (rev 289946)
@@ -71,6 +71,7 @@
}
SampleFlags flags() const final { return m_flags; }
PlatformSample platformSample() const final { return { PlatformSample::None, { nullptr } }; }
+ PlatformSample::Type platformSampleType() const final { return PlatformSample::None; }
std::optional<ByteRange> byteRange() const final { return std::nullopt; }
void dump(PrintStream&) const final { }