<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[178472] branches/safari-600.5-branch/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/178472">178472</a></dd>
<dt>Author</dt> <dd>dburkart@apple.com</dd>
<dt>Date</dt> <dd>2015-01-14 18:40:11 -0800 (Wed, 14 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merged <a href="http://trac.webkit.org/projects/webkit/changeset/175000">r175000</a>. &lt;rdar://problem/19424156&gt;</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari6005branchSourceWebCoreChangeLog">branches/safari-600.5-branch/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCh">branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCmm">branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCh">branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCmm">branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCh">branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h</a></li>
<li><a href="#branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm">branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari6005branchSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/ChangeLog (178471 => 178472)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/ChangeLog        2015-01-15 02:16:06 UTC (rev 178471)
+++ branches/safari-600.5-branch/Source/WebCore/ChangeLog        2015-01-15 02:40:11 UTC (rev 178472)
</span><span class="lines">@@ -1,5 +1,60 @@
</span><span class="cx"> 2015-01-14  Dana Burkart  &lt;dburkart@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merged r175000. &lt;rdar://problem/19424156&gt;
+
+    2014-10-21  Jer Noble  &lt;jer.noble@apple.com&gt;
+
+            [EME][Mac] Update to match new AVStreamSession API and requirements.
+            https://bugs.webkit.org/show_bug.cgi?id=137923
+
+            Reviewed by Eric Carlson.
+
+            The session identifier has moved from AVStreamDataParser to -[AVStreamSession contentProtectionSessionIdentifier]
+            and the property is no longer KVObservable. A new notification key has been added in place of KVO.
+
+            Additionally, the requirements for using AVStreamDataParser with AVStreamSession have changed. It is now
+            required that AVStreamDataParsers be added to an AVStreamSession before the 
+            -streamSession:didProvideContentKeyRequestInitializationData:forTrackID delegate method is called. A
+            -streamParserWillProvideContentKeyRequestInitializationData:forTrackID delegate has been added, and
+            an AVStreamSession must be created and the AVStreamDataParser added to it during the scope of that delegate
+            method.
+
+            To facilitate this, the MediaPlayerPrivateMediaSourceAVFObjC object will lazily create and own a AVStreamSession
+            object when requested. The SourceBufferPrivateAVFObjC object will listen for the -willProvide delegate call
+            and will add its AVStreamDataParser to that AVStreamSession when called.
+
+            The CDMSessionMediaSourceAVFObjC object is no longer responsible for creating the AVStreamSession, and because
+            the session identifier has moved from many AVStreamDataParsers to a single AVStreamSession, the
+            CDMSessionMediaSourceAVFObjCObserver class can become much simpler, as it only has to observe a single object.
+
+            * platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h:
+            * platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm:
+            (-[CDMSessionMediaSourceAVFObjCObserver dealloc]): Deleted.
+            (-[CDMSessionMediaSourceAVFObjCObserver beginObserving:]): Deleted.
+            (-[CDMSessionMediaSourceAVFObjCObserver stopObserving:]): Deleted.
+            (-[CDMSessionMediaSourceAVFObjCObserver invalidate]): Deleted.
+            (-[CDMSessionMediaSourceAVFObjCObserver observeValueForKeyPath:ofObject:change:context:]): Deleted.
+            (-[CDMSessionMediaSourceAVFObjCObserver contentProtectionSessionIdentifierChanged:]): Added.
+            (WebCore::CDMSessionMediaSourceAVFObjC::~CDMSessionMediaSourceAVFObjC): Call setStreamSession(nullptr).
+            (WebCore::CDMSessionMediaSourceAVFObjC::releaseKeys): The sessionId is now a value in the dictionary, not the key.
+            (WebCore::CDMSessionMediaSourceAVFObjC::update): No longer create an AVStreamSession.
+            (WebCore::CDMSessionMediaSourceAVFObjC::setStreamSession): Add and remove observers as appropriate.
+            (WebCore::CDMSessionMediaSourceAVFObjC::addSourceBuffer): No longer add or remove parsers from AVStreamSessions.
+            (WebCore::CDMSessionMediaSourceAVFObjC::removeSourceBuffer): Ditto.
+            * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h:
+            * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+            (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::hasStreamSession): Simple getter.
+            (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::streamSession): Lazy initializing getter.
+            (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::setCDMSession): Call setStreamSession().
+            * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h:
+            * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+            (-[WebAVStreamDataParserListener streamParserWillProvideContentKeyRequestInitializationData:forTrackID:]): Synchronously pass to SourceBufferPrivateAVFObjC.
+            (WebCore::SourceBufferPrivateAVFObjC::willProvideContentKeyRequestInitializationDataForTrackID): Add the parser to an AVStreamSession.
+            (WebCore::SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID): Check the trackId.
+            * platform/mac/SoftLinking.h:
+
+2015-01-14  Dana Burkart  &lt;dburkart@apple.com&gt;
+
</ins><span class="cx">         Merged r174823. &lt;rdar://problem/19424155&gt;
</span><span class="cx"> 
</span><span class="cx">     2014-10-16  Jer Noble  &lt;jer.noble@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCh"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h (178471 => 178472)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h        2015-01-15 02:16:06 UTC (rev 178471)
+++ branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h        2015-01-15 02:40:11 UTC (rev 178472)
</span><span class="lines">@@ -53,6 +53,8 @@
</span><span class="cx">     virtual void layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError *);
</span><span class="cx">     virtual void rendererDidReceiveError(AVSampleBufferAudioRenderer *, NSError *);
</span><span class="cx"> 
</span><ins>+    void setStreamSession(AVStreamSession *);
+
</ins><span class="cx">     void addSourceBuffer(SourceBufferPrivateAVFObjC*);
</span><span class="cx">     void removeSourceBuffer(SourceBufferPrivateAVFObjC*);
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcCDMSessionMediaSourceAVFObjCmm"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm (178471 => 178472)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm        2015-01-15 02:16:06 UTC (rev 178471)
+++ branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm        2015-01-15 02:40:11 UTC (rev 178472)
</span><span class="lines">@@ -43,27 +43,27 @@
</span><span class="cx"> SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVStreamDataParser);
</span><span class="cx"> SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVStreamSession);
</span><ins>+SOFT_LINK_CONSTANT_MAY_FAIL(AVFoundation, AVStreamSessionContentProtectionSessionIdentifierChangedNotification, NSString *);
</ins><span class="cx"> 
</span><span class="cx"> @interface AVStreamDataParser : NSObject
</span><span class="cx"> - (void)processContentKeyResponseData:(NSData *)contentKeyResponseData forTrackID:(CMPersistentTrackID)trackID;
</span><span class="cx"> - (void)processContentKeyResponseError:(NSError *)error forTrackID:(CMPersistentTrackID)trackID;
</span><span class="cx"> - (void)renewExpiringContentKeyResponseDataForTrackID:(CMPersistentTrackID)trackID;
</span><span class="cx"> - (NSData *)streamingContentKeyRequestDataForApp:(NSData *)appIdentifier contentIdentifier:(NSData *)contentIdentifier trackID:(CMPersistentTrackID)trackID options:(NSDictionary *)options error:(NSError **)outError;
</span><del>-- (NSData *)sessionIdentifier;
</del><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @interface AVStreamSession : NSObject
</span><del>-- (instancetype)initWithAppIdentifier:(NSData *)appIdentifier storageDirectoryAtURL:(NSURL *)storageURL error:(NSError **)outError;
</del><ins>+- (BOOL)setStorageDirectoryAtURL:(NSURL *)storageURL appIdentifier:(NSData *)appIdentifier error:(NSError **)outError;
</ins><span class="cx"> - (void)addStreamDataParser:(AVStreamDataParser *)streamDataParser;
</span><span class="cx"> - (void)removeStreamDataParser:(AVStreamDataParser *)streamDataParser;
</span><span class="cx"> - (void)expire;
</span><ins>+- (NSData *)contentProtectionSessionIdentifier;
</ins><span class="cx"> + (NSArray *)pendingExpiredSessionReportsWithAppIdentifier:(NSData *)appIdentifier;
</span><span class="cx"> + (void)removePendingExpiredSessionReports:(NSArray *)expiredSessionReports withAppIdentifier:(NSData *)appIdentifier;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @interface CDMSessionMediaSourceAVFObjCObserver : NSObject {
</span><span class="cx">     WebCore::CDMSessionMediaSourceAVFObjC *m_parent;
</span><del>-    HashSet&lt;RetainPtr&lt;AVStreamDataParser&gt;&gt; m_parsers;
</del><span class="cx"> }
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="lines">@@ -75,55 +75,20 @@
</span><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)dealloc
</del><ins>+- (void)contentProtectionSessionIdentifierChanged:(NSNotification *)notification
</ins><span class="cx"> {
</span><del>-    [self invalidate];
-    [super dealloc];
-}
</del><ins>+    AVStreamSession* streamSession = (AVStreamSession*)[notification object];
</ins><span class="cx"> 
</span><del>-- (void)beginObserving:(AVStreamDataParser *)parser
-{
-    ASSERT(!m_parsers.contains(parser));
-    m_parsers.add(parser);
-    [parser addObserver:self forKeyPath:@&quot;sessionIdentifier&quot; options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial) context:nullptr];
-}
</del><ins>+    NSData* identifier = [streamSession contentProtectionSessionIdentifier];
+    RetainPtr&lt;NSString&gt; sessionIdentifierString = identifier ? adoptNS([[NSString alloc] initWithData:identifier encoding:NSUTF8StringEncoding]) : nil;
</ins><span class="cx"> 
</span><del>-- (void)stopObserving:(AVStreamDataParser *)parser
-{
-    ASSERT(m_parsers.contains(parser));
-    m_parsers.remove(parser);
-    [parser removeObserver:self forKeyPath:@&quot;sessionIdentifier&quot; context:nullptr];
</del><ins>+    if (m_parent)
+        m_parent-&gt;setSessionId(sessionIdentifierString.get());
</ins><span class="cx"> }
</span><del>-
-- (void)invalidate
-{
-    m_parent = nullptr;
-    for (auto&amp; parser : m_parsers)
-        [parser removeObserver:self forKeyPath:@&quot;sessionIdentifier&quot; context:nullptr];
-    m_parsers.clear();
-}
-
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context
-{
-    UNUSED_PARAM(object);
-    UNUSED_PARAM(change);
-    UNUSED_PARAM(context);
-
-    if ([keyPath isEqual:@&quot;sessionIdentifier&quot;]) {
-        NSData* identifier = [change valueForKey:NSKeyValueChangeNewKey];
-        if ([identifier isKindOfClass:[NSNull class]])
-            return;
-
-        RetainPtr&lt;NSString&gt; sessionIdentifierString = adoptNS([[NSString alloc] initWithData:identifier encoding:(NSUTF8StringEncoding)]);
-        if (m_parent)
-            m_parent-&gt;setSessionId(sessionIdentifierString.get());
-        return;
-    }
-
-    ASSERT_NOT_REACHED();
-}
</del><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+static const NSString *PlaybackSessionIdKey = @&quot;PlaybackSessionID&quot;;
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> CDMSessionMediaSourceAVFObjC::CDMSessionMediaSourceAVFObjC()
</span><span class="lines">@@ -138,12 +103,9 @@
</span><span class="cx">     for (auto&amp; sourceBuffer : m_sourceBuffers) {
</span><span class="cx">         if (m_streamSession)
</span><span class="cx">             [m_streamSession removeStreamDataParser:sourceBuffer-&gt;parser()];
</span><del>-
-        [sourceBuffer-&gt;parser() removeObserver:m_dataParserObserver.get() forKeyPath:@&quot;sessionIdentifier&quot; context:nullptr];
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_streamSession = nil;
-    [m_dataParserObserver invalidate];
</del><ins>+    setStreamSession(nullptr);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;Uint8Array&gt; CDMSessionMediaSourceAVFObjC::generateKeyRequest(const String&amp; mimeType, Uint8Array* initData, String&amp; destinationURL, unsigned short&amp; errorCode, unsigned long&amp; systemCode)
</span><span class="lines">@@ -181,7 +143,12 @@
</span><span class="cx">         NSArray* expiredSessions = [getAVStreamSessionClass() pendingExpiredSessionReportsWithAppIdentifier:certificateData.get()];
</span><span class="cx">         for (NSData* expiredSessionData in expiredSessions) {
</span><span class="cx">             NSDictionary *expiredSession = [NSPropertyListSerialization propertyListWithData:expiredSessionData options:kCFPropertyListImmutable format:nullptr error:nullptr];
</span><del>-            if ([expiredSession objectForKey:m_sessionId]) {
</del><ins>+            NSString *playbackSessionIdValue = (NSString *)[expiredSession objectForKey:PlaybackSessionIdKey];
+            if (![playbackSessionIdValue isKindOfClass:[NSString class]])
+                continue;
+
+            if (m_sessionId == String(playbackSessionIdValue)) {
+                LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::releaseKeys(%p) - found session, sending expiration message&quot;);
</ins><span class="cx">                 m_expiredSession = expiredSessionData;
</span><span class="cx">                 m_client-&gt;sendMessage(Uint8Array::create(static_cast&lt;const uint8_t*&gt;([m_expiredSession bytes]), [m_expiredSession length]).get(), emptyString());
</span><span class="cx">                 break;
</span><span class="lines">@@ -235,6 +202,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (isEqual(key, &quot;acknowledged&quot;)) {
</span><ins>+        LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::update(%p) - acknowleding secure stop message&quot;, this);
+
</ins><span class="cx">         if (!m_expiredSession) {
</span><span class="cx">             errorCode = MediaPlayer::InvalidPlayerState;
</span><span class="cx">             return false;
</span><span class="lines">@@ -243,6 +212,7 @@
</span><span class="cx">         RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
</span><span class="cx">         [getAVStreamSessionClass() removePendingExpiredSessionReports:@[m_expiredSession.get()] withAppIdentifier:certificateData.get()];
</span><span class="cx">         m_expiredSession = nullptr;
</span><ins>+        return true;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;SourceBufferPrivateAVFObjC&gt; protectedSourceBuffer;
</span><span class="lines">@@ -255,8 +225,8 @@
</span><span class="cx"> 
</span><span class="cx">     if (shouldGenerateKeyRequest) {
</span><span class="cx">         RetainPtr&lt;NSData&gt; certificateData = adoptNS([[NSData alloc] initWithBytes:m_certificate-&gt;data() length:m_certificate-&gt;length()]);
</span><del>-        if (getAVStreamSessionClass() &amp;&amp; [getAVStreamSessionClass() instancesRespondToSelector:@selector(initWithAppIdentifier:storageDirectoryAtURL:error:)]) {
-            m_streamSession = adoptNS([[getAVStreamSessionClass() alloc] initWithAppIdentifier:certificateData.get() storageDirectoryAtURL:[NSURL fileURLWithPath:sessionStorageDirectory()] error:nil]);
</del><ins>+        if (m_streamSession &amp;&amp; [m_streamSession respondsToSelector:@selector(setStorageDirectoryAtURL:storageURL:appIdentifier:error:)]) {
+            [m_streamSession setStorageDirectoryAtURL:[NSURL fileURLWithPath:sessionStorageDirectory()] appIdentifier:certificateData.get() error:nil];
</ins><span class="cx">             for (auto&amp; sourceBuffer : m_sourceBuffers)
</span><span class="cx">                 [m_streamSession addStreamDataParser:sourceBuffer-&gt;parser()];
</span><span class="cx">             LOG(Media, &quot;CDMSessionMediaSourceAVFObjC::update(%p) - created stream session %p&quot;, this, m_streamSession.get());
</span><span class="lines">@@ -273,7 +243,7 @@
</span><span class="cx">         NSError* error = nil;
</span><span class="cx">         RetainPtr&lt;NSData&gt; request = [protectedSourceBuffer-&gt;parser() streamingContentKeyRequestDataForApp:certificateData.get() contentIdentifier:initData.get() trackID:protectedSourceBuffer-&gt;protectedTrackID() options:nil error:&amp;error];
</span><span class="cx"> 
</span><del>-        if (![protectedSourceBuffer-&gt;parser() respondsToSelector:@selector(sessionIdentifier)])
</del><ins>+        if (![protectedSourceBuffer-&gt;parser() respondsToSelector:@selector(contentProtectionSessionIdentifier)])
</ins><span class="cx">             m_sessionId = createCanonicalUUIDString();
</span><span class="cx"> 
</span><span class="cx">         if (error) {
</span><span class="lines">@@ -314,6 +284,24 @@
</span><span class="cx">     m_client-&gt;sendError(CDMSessionClient::MediaKeyErrorDomain, abs([error code]));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void CDMSessionMediaSourceAVFObjC::setStreamSession(AVStreamSession *streamSession)
+{
+    if (m_streamSession &amp;&amp; canLoadAVStreamSessionContentProtectionSessionIdentifierChangedNotification())
+        [[NSNotificationCenter defaultCenter] removeObserver:m_dataParserObserver.get() name:getAVStreamSessionContentProtectionSessionIdentifierChangedNotification() object:m_streamSession.get()];
+
+    m_streamSession = streamSession;
+
+    if (!m_streamSession)
+        return;
+
+    if (canLoadAVStreamSessionContentProtectionSessionIdentifierChangedNotification())
+        [[NSNotificationCenter defaultCenter] addObserver:m_dataParserObserver.get() selector:@selector(contentProtectionSessionIdentifierChanged:) name:getAVStreamSessionContentProtectionSessionIdentifierChangedNotification() object:m_streamSession.get()];
+
+    NSData* identifier = [streamSession contentProtectionSessionIdentifier];
+    RetainPtr&lt;NSString&gt; sessionIdentifierString = identifier ? adoptNS([[NSString alloc] initWithData:identifier encoding:(NSUTF8StringEncoding)]) : nil;
+    setSessionId(sessionIdentifierString.get());
+}
+
</ins><span class="cx"> void CDMSessionMediaSourceAVFObjC::addSourceBuffer(SourceBufferPrivateAVFObjC* sourceBuffer)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_sourceBuffers.contains(sourceBuffer));
</span><span class="lines">@@ -321,11 +309,6 @@
</span><span class="cx"> 
</span><span class="cx">     m_sourceBuffers.append(sourceBuffer);
</span><span class="cx">     sourceBuffer-&gt;registerForErrorNotifications(this);
</span><del>-
-    if (m_streamSession)
-        [m_streamSession addStreamDataParser:sourceBuffer-&gt;parser()];
-
-    [m_dataParserObserver beginObserving:sourceBuffer-&gt;parser()];
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CDMSessionMediaSourceAVFObjC::removeSourceBuffer(SourceBufferPrivateAVFObjC* sourceBuffer)
</span><span class="lines">@@ -338,8 +321,6 @@
</span><span class="cx"> 
</span><span class="cx">     sourceBuffer-&gt;unregisterForErrorNotifications(this);
</span><span class="cx">     m_sourceBuffers.remove(m_sourceBuffers.find(sourceBuffer));
</span><del>-
-    [m_dataParserObserver stopObserving:sourceBuffer-&gt;parser()];
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PassRefPtr&lt;Uint8Array&gt; CDMSessionMediaSourceAVFObjC::generateKeyReleaseMessage(unsigned short&amp; errorCode, unsigned long&amp; systemCode)
</span></span></pre></div>
<a id="branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCh"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h (178471 => 178472)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h        2015-01-15 02:16:06 UTC (rev 178471)
+++ branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.h        2015-01-15 02:40:11 UTC (rev 178472)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> OBJC_CLASS AVSampleBufferAudioRenderer;
</span><span class="cx"> OBJC_CLASS AVSampleBufferDisplayLayer;
</span><span class="cx"> OBJC_CLASS AVSampleBufferRenderSynchronizer;
</span><ins>+OBJC_CLASS AVStreamSession;
</ins><span class="cx"> 
</span><span class="cx"> typedef struct OpaqueCMTimebase* CMTimebaseRef;
</span><span class="cx"> 
</span><span class="lines">@@ -83,6 +84,8 @@
</span><span class="cx">     void characteristicsChanged();
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><ins>+    bool hasStreamSession() { return m_streamSession; }
+    AVStreamSession *streamSession();
</ins><span class="cx">     virtual void setCDMSession(CDMSession*) override;
</span><span class="cx">     void keyNeeded(Uint8Array*);
</span><span class="cx"> #endif
</span><span class="lines">@@ -191,6 +194,7 @@
</span><span class="cx">     RetainPtr&lt;AVSampleBufferRenderSynchronizer&gt; m_synchronizer;
</span><span class="cx">     RetainPtr&lt;id&gt; m_timeJumpedObserver;
</span><span class="cx">     RetainPtr&lt;id&gt; m_durationObserver;
</span><ins>+    RetainPtr&lt;AVStreamSession&gt; m_streamSession;
</ins><span class="cx">     Timer&lt;MediaPlayerPrivateMediaSourceAVFObjC&gt; m_seekTimer;
</span><span class="cx">     CDMSessionMediaSourceAVFObjC* m_session;
</span><span class="cx">     MediaPlayer::NetworkState m_networkState;
</span></span></pre></div>
<a id="branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcMediaPlayerPrivateMediaSourceAVFObjCmm"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm (178471 => 178472)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm        2015-01-15 02:16:06 UTC (rev 178471)
+++ branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm        2015-01-15 02:40:11 UTC (rev 178472)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx"> SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVSampleBufferDisplayLayer)
</span><span class="cx"> SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVSampleBufferRenderSynchronizer)
</span><span class="cx"> SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVStreamDataParser)
</span><ins>+SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVStreamSession);
</ins><span class="cx"> SOFT_LINK_CLASS_OPTIONAL(AVFoundation, AVVideoPerformanceMetrics)
</span><span class="cx"> 
</span><span class="cx"> typedef struct opaqueCMNotificationCenter *CMNotificationCenterRef;
</span><span class="lines">@@ -654,6 +655,13 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ENCRYPTED_MEDIA_V2)
</span><ins>+AVStreamSession* MediaPlayerPrivateMediaSourceAVFObjC::streamSession()
+{
+    if (!m_streamSession)
+        m_streamSession = adoptNS([[getAVStreamSessionClass() alloc] init]);
+    return m_streamSession.get();
+}
+
</ins><span class="cx"> void MediaPlayerPrivateMediaSourceAVFObjC::setCDMSession(CDMSession* session)
</span><span class="cx"> {
</span><span class="cx">     if (m_session) {
</span><span class="lines">@@ -665,6 +673,7 @@
</span><span class="cx">     m_session = toCDMSessionMediaSourceAVFObjC(session);
</span><span class="cx"> 
</span><span class="cx">     if (m_session) {
</span><ins>+        m_session-&gt;setStreamSession(m_streamSession.get());
</ins><span class="cx">         for (auto&amp; sourceBuffer : m_mediaSourcePrivate-&gt;sourceBuffers())
</span><span class="cx">             m_session-&gt;addSourceBuffer(sourceBuffer.get());
</span><span class="cx">     }
</span></span></pre></div>
<a id="branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCh"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h (178471 => 178472)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h        2015-01-15 02:16:06 UTC (rev 178471)
+++ branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h        2015-01-15 02:40:11 UTC (rev 178472)
</span><span class="lines">@@ -80,6 +80,7 @@
</span><span class="cx">     void didFailToParseStreamDataWithError(NSError*);
</span><span class="cx">     void didProvideMediaDataForTrackID(int trackID, CMSampleBufferRef, const String&amp; mediaType, unsigned flags);
</span><span class="cx">     void didReachEndOfTrackWithTrackID(int trackID, const String&amp; mediaType);
</span><ins>+    void willProvideContentKeyRequestInitializationDataForTrackID(int trackID);
</ins><span class="cx">     void didProvideContentKeyRequestInitializationDataForTrackID(NSData*, int trackID);
</span><span class="cx"> 
</span><span class="cx">     bool processCodedFrame(int trackID, CMSampleBufferRef, const String&amp; mediaType);
</span></span></pre></div>
<a id="branchessafari6005branchSourceWebCoreplatformgraphicsavfoundationobjcSourceBufferPrivateAVFObjCmm"></a>
<div class="modfile"><h4>Modified: branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm (178471 => 178472)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2015-01-15 02:16:06 UTC (rev 178471)
+++ branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm        2015-01-15 02:40:11 UTC (rev 178472)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(MEDIA_SOURCE) &amp;&amp; USE(AVFOUNDATION)
</span><span class="cx"> 
</span><ins>+#import &quot;BlockExceptions.h&quot;
</ins><span class="cx"> #import &quot;ExceptionCodePlaceholder.h&quot;
</span><span class="cx"> #import &quot;Logging.h&quot;
</span><span class="cx"> #import &quot;MediaDescription.h&quot;
</span><span class="lines">@@ -62,6 +63,7 @@
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVStreamDataParser)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVSampleBufferAudioRenderer)
</span><span class="cx"> SOFT_LINK_CLASS(AVFoundation, AVSampleBufferDisplayLayer)
</span><ins>+SOFT_LINK_CLASS(AVFoundation, AVStreamSession)
</ins><span class="cx"> 
</span><span class="cx"> SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVMediaTypeVideo, NSString *)
</span><span class="cx"> SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVMediaTypeAudio, NSString *)
</span><span class="lines">@@ -115,6 +117,14 @@
</span><span class="cx"> #define AVMediaCharacteristicLegible getAVMediaCharacteristicLegible()
</span><span class="cx"> 
</span><span class="cx"> #pragma mark -
</span><ins>+#pragma mark AVStreamSession
+
+@interface AVStreamSession : NSObject
+- (void)addStreamDataParser:(AVStreamDataParser *)streamDataParser;
+- (void)removeStreamDataParser:(AVStreamDataParser *)streamDataParser;
+@end
+
+#pragma mark -
</ins><span class="cx"> #pragma mark AVStreamDataParser
</span><span class="cx"> 
</span><span class="cx"> @interface AVStreamDataParser : NSObject
</span><span class="lines">@@ -268,6 +278,27 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)streamParserWillProvideContentKeyRequestInitializationData:(AVStreamDataParser *)streamDataParser forTrackID:(CMPersistentTrackID)trackID
+{
+#if ASSERT_DISABLED
+    UNUSED_PARAM(streamDataParser);
+#endif
+    ASSERT(streamDataParser == _parser);
+
+    if (isMainThread()) {
+        _parent-&gt;willProvideContentKeyRequestInitializationDataForTrackID(trackID);
+        return;
+    }
+
+    // We must call synchronously to the main thread, as the AVStreamSession must be associated
+    // with the streamDataParser before the delegate method returns.
+    RetainPtr&lt;WebAVStreamDataParserListener&gt; strongSelf = self;
+    dispatch_sync(dispatch_get_main_queue(), [strongSelf, trackID]() {
+        if (strongSelf-&gt;_parent)
+            strongSelf-&gt;_parent-&gt;willProvideContentKeyRequestInitializationDataForTrackID(trackID);
+    });
+}
+
</ins><span class="cx"> - (void)streamDataParser:(AVStreamDataParser *)streamDataParser didProvideContentKeyRequestInitializationData:(NSData *)initData forTrackID:(CMPersistentTrackID)trackID
</span><span class="cx"> {
</span><span class="cx"> #if ASSERT_DISABLED
</span><span class="lines">@@ -658,6 +689,25 @@
</span><span class="cx">     notImplemented();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SourceBufferPrivateAVFObjC::willProvideContentKeyRequestInitializationDataForTrackID(int trackID)
+{
+    if (!m_mediaSource)
+        return;
+
+    ASSERT(m_parser);
+
+#if ENABLE(ENCRYPTED_MEDIA_V2)
+    LOG(MediaSource, &quot;SourceBufferPrivateAVFObjC::willProvideContentKeyRequestInitializationDataForTrackID(%p) - track:%d&quot;, this, trackID);
+    m_protectedTrackID = trackID;
+
+    BEGIN_BLOCK_OBJC_EXCEPTIONS;
+    [m_mediaSource-&gt;player()-&gt;streamSession() addStreamDataParser:m_parser.get()];
+    END_BLOCK_OBJC_EXCEPTIONS;
+#else
+    UNUSED_PARAM(trackID);
+#endif
+}
+
</ins><span class="cx"> void SourceBufferPrivateAVFObjC::didProvideContentKeyRequestInitializationDataForTrackID(NSData* initData, int trackID)
</span><span class="cx"> {
</span><span class="cx">     if (!m_mediaSource)
</span><span class="lines">@@ -733,6 +783,9 @@
</span><span class="cx"> 
</span><span class="cx"> void SourceBufferPrivateAVFObjC::destroyParser()
</span><span class="cx"> {
</span><ins>+    if (m_mediaSource-&gt;player()-&gt;hasStreamSession())
+        [m_mediaSource-&gt;player()-&gt;streamSession() removeStreamDataParser:m_parser.get()];
+
</ins><span class="cx">     [m_delegate invalidate];
</span><span class="cx">     m_delegate = nullptr;
</span><span class="cx">     m_parser = nullptr;
</span></span></pre>
</div>
</div>

</body>
</html>