Changeset 181033 in webkit
- Timestamp:
- Mar 4, 2015, 2:29:25 PM (10 years ago)
- Location:
- branches/safari-600.5-branch/Source/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/safari-600.5-branch/Source/WebCore/ChangeLog
r181032 r181033 1 2015-03-04 Lucas Forschler <lforschler@apple.com> 2 3 Merge r181005 4 5 2015-03-04 Jer Noble <jer.noble@apple.com> 6 7 [MSE][EME][Mac] Calling close on a MediaKeysSession will cause many decoding errors to be emitted 8 https://bugs.webkit.org/show_bug.cgi?id=142285 9 10 Reviewed by Eric Carlson. 11 12 When a MediaKeySession (backed by CDMSessionMediaSourceAVFObjC) is closed and the 13 underlying AVStreamSession is invalidated, the decryption context for in-flight 14 CMSampleBuffers is also invalidated, and the AVSampleBufferDisplayLayer will issue 15 one error for each enqueued and un-displayed sample in its image-queue. -flush-ing 16 the AVSampleBufferDisplayLayer is not enough, as the flush only takes effect 17 asynchronously the next time the layer needs new samples. 18 19 Add a workaround until framework-level support lands to fully flush enqueued and 20 encrypted frames. 21 22 When the CDMSessionMediaSOurceAVFObjC object recieves an error from the layer, 23 check to see if the session has been stopped. If so, and if the error in question is 24 one that indicates that the samples decryption context has been invalidated, suppress 25 the error and instruct the sender to suppress the error as well. This workaround will 26 be removed once real support for synchronous flushing lands in <rdar://problem/20027434.> 27 28 Still, we'll make our best effort to flush undisplayed frames when our CDM session is 29 invalidated. Move away from std::map and instead use HashMap to store the set of 30 AVSampleBufferAudioRenderers. This allows us to use C++11 style loops against just 31 the HashMap's set of values. 32 33 * platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h: 34 * platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm: 35 (WebCore::CDMSessionMediaSourceAVFObjC::releaseKeys): Flush and set m_stopped. 36 (WebCore::CDMSessionMediaSourceAVFObjC::layerDidReceiveError): Check m_stopped and the 37 error code and bail before issuing the error. 38 (WebCore::CDMSessionMediaSourceAVFObjC::rendererDidReceiveError): Ditto. 39 * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h: 40 * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm: 41 (-[WebAVSampleBufferErrorListener layerFailedToDecode:]): Drive-by fix. Check whether 42 the layer is in the set of listened-to layers only back in the main thread; the 43 listnener may have been unregistered by the time the main thread was called. 44 (WebCore::SourceBufferPrivateAVFObjC::destroyRenderers): std::map -> HashMap. 45 (WebCore::SourceBufferPrivateAVFObjC::trackDidChangeEnabled): Ditto. 46 (WebCore::SourceBufferPrivateAVFObjC::flushAndEnqueueNonDisplayingSamples): Ditto. 47 (WebCore::SourceBufferPrivateAVFObjC::enqueueSample): Ditto. 48 (WebCore::SourceBufferPrivateAVFObjC::isReadyForMoreSamples): Ditto. 49 (WebCore::SourceBufferPrivateAVFObjC::didBecomeReadyForMoreSamples): Ditto. 50 (WebCore::SourceBufferPrivateAVFObjC::notifyClientWhenReadyForMoreSamples): Ditto. 51 (WebCore::SourceBufferPrivateAVFObjC::flush): Added; call -flush on all the display 52 layers and audio renderers. 53 (WebCore::SourceBufferPrivateAVFObjC::layerDidReceiveError): Check if any clients 54 asked to ignore the error, and if so, bail. 55 (WebCore::SourceBufferPrivateAVFObjC::rendererDidReceiveError): Ditto. 56 1 57 2015-03-04 Lucas Forschler <lforschler@apple.com> 2 58 -
branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.h
r178977 r181033 51 51 virtual bool update(Uint8Array*, RefPtr<Uint8Array>& nextMessage, unsigned short& errorCode, unsigned long& systemCode) override; 52 52 53 virtual void layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError * );54 virtual void rendererDidReceiveError(AVSampleBufferAudioRenderer *, NSError * );53 virtual void layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError *, bool& shouldIgnore); 54 virtual void rendererDidReceiveError(AVSampleBufferAudioRenderer *, NSError *, bool& shouldIgnore); 55 55 56 56 void setStreamSession(AVStreamSession *); … … 75 75 String m_sessionId; 76 76 enum { Normal, KeyRelease } m_mode; 77 bool m_stopped = { false }; 77 78 }; 78 79 -
branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionMediaSourceAVFObjC.mm
r179948 r181033 141 141 { 142 142 if (m_streamSession) { 143 m_stopped = true; 144 for (auto& sourceBuffer : m_sourceBuffers) 145 sourceBuffer->flush(); 146 143 147 LOG(Media, "CDMSessionMediaSourceAVFObjC::releaseKeys(%p) - expiring stream session", this); 144 148 [m_streamSession expire]; … … 282 286 } 283 287 284 void CDMSessionMediaSourceAVFObjC::layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError *error )288 void CDMSessionMediaSourceAVFObjC::layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError *error, bool& shouldIgnore) 285 289 { 286 290 if (!m_client) 287 291 return; 288 292 289 m_client->sendError(CDMSessionClient::MediaKeyErrorDomain, abs(systemCodeForError(error))); 290 } 291 292 void CDMSessionMediaSourceAVFObjC::rendererDidReceiveError(AVSampleBufferAudioRenderer *, NSError *error) 293 unsigned long code = abs(systemCodeForError(error)); 294 295 // FIXME(142246): Remove the following once <rdar://problem/20027434> is resolved. 296 shouldIgnore = m_stopped && code == 12785; 297 if (!shouldIgnore) 298 m_client->sendError(CDMSessionClient::MediaKeyErrorDomain, code); 299 } 300 301 void CDMSessionMediaSourceAVFObjC::rendererDidReceiveError(AVSampleBufferAudioRenderer *, NSError *error, bool& shouldIgnore) 293 302 { 294 303 if (!m_client) 295 304 return; 296 305 297 m_client->sendError(CDMSessionClient::MediaKeyErrorDomain, abs(systemCodeForError(error))); 306 unsigned long code = abs(systemCodeForError(error)); 307 308 // FIXME(142246): Remove the following once <rdar://problem/20027434> is resolved. 309 shouldIgnore = m_stopped && code == 12785; 310 if (!shouldIgnore) 311 m_client->sendError(CDMSessionClient::MediaKeyErrorDomain, code); 298 312 } 299 313 -
branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h
r181022 r181033 30 30 31 31 #include "SourceBufferPrivate.h" 32 #include <map>33 32 #include <wtf/Deque.h> 34 33 #include <wtf/HashMap.h> … … 65 64 public: 66 65 virtual ~SourceBufferPrivateAVFObjCErrorClient() { } 67 virtual void layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError * ) = 0;68 virtual void rendererDidReceiveError(AVSampleBufferAudioRenderer *, NSError * ) = 0;66 virtual void layerDidReceiveError(AVSampleBufferDisplayLayer *, NSError *, bool& shouldIgnore) = 0; 67 virtual void rendererDidReceiveError(AVSampleBufferAudioRenderer *, NSError *, bool& shouldIgnore) = 0; 69 68 }; 70 69 … … 98 97 int protectedTrackID() const { return m_protectedTrackID; } 99 98 AVStreamDataParser* parser() const { return m_parser.get(); } 99 100 void flush(); 100 101 101 102 void registerForErrorNotifications(SourceBufferPrivateAVFObjCErrorClient*); … … 139 140 RetainPtr<AVAsset> m_asset; 140 141 RetainPtr<AVSampleBufferDisplayLayer> m_displayLayer; 141 std::map<int, RetainPtr<AVSampleBufferAudioRenderer>> m_audioRenderers;142 HashMap<int, RetainPtr<AVSampleBufferAudioRenderer>> m_audioRenderers; 142 143 RetainPtr<WebAVStreamDataParserListener> m_delegate; 143 144 RetainPtr<WebAVSampleBufferErrorListener> m_errorListener; -
branches/safari-600.5-branch/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm
r181032 r181033 30 30 31 31 #import "BlockExceptions.h" 32 #import "CDMSessionMediaSourceAVFObjC.h" 32 33 #import "ExceptionCodePlaceholder.h" 33 34 #import "Logging.h" … … 148 149 - (void)enqueueSampleBuffer:(CMSampleBufferRef)sampleBuffer; 149 150 - (void)flush; 151 - (void)flushAndRemoveImage; 150 152 - (BOOL)isReadyForMoreMediaData; 151 153 - (void)requestMediaDataWhenReadyOnQueue:(dispatch_queue_t)queue usingBlock:(void (^)(void))block; … … 451 453 { 452 454 RetainPtr<AVSampleBufferDisplayLayer> layer = (AVSampleBufferDisplayLayer *)[note object]; 453 ASSERT(_layers.contains(layer.get()));454 455 455 RetainPtr<NSError> error = [[note userInfo] valueForKey:AVSampleBufferDisplayLayerFailedToDecodeNotificationErrorKey]; 456 456 457 457 RetainPtr<WebAVSampleBufferErrorListener> strongSelf = self; 458 458 callOnMainThread([strongSelf, layer, error] { 459 if (!strongSelf->_parent || !strongSelf->_layers.contains(layer.get())) 460 return; 459 461 strongSelf->_parent->layerDidReceiveError(layer.get(), error.get()); 460 462 }); … … 804 806 } 805 807 806 for (auto it = m_audioRenderers.begin(), end = m_audioRenderers.end(); it != end; ++it) { 807 AVSampleBufferAudioRenderer* renderer = it->second.get(); 808 for (auto& renderer : m_audioRenderers.values()) { 808 809 if (m_mediaSource) 809 m_mediaSource->player()->removeAudioRenderer(renderer );810 m_mediaSource->player()->removeAudioRenderer(renderer.get()); 810 811 [renderer flush]; 811 812 [renderer stopRequestingMediaData]; 812 [m_errorListener stopObservingRenderer:renderer ];813 [m_errorListener stopObservingRenderer:renderer.get()]; 813 814 } 814 815 … … 883 884 884 885 if (!track->enabled()) { 885 AVSampleBufferAudioRenderer* renderer = m_audioRenderers[trackID].get();886 RetainPtr<AVSampleBufferAudioRenderer> renderer = m_audioRenderers.get(trackID); 886 887 [m_parser setShouldProvideMediaData:NO forTrackID:trackID]; 887 888 if (m_mediaSource) 888 m_mediaSource->player()->removeAudioRenderer(renderer );889 m_mediaSource->player()->removeAudioRenderer(renderer.get()); 889 890 } else { 890 891 [m_parser setShouldProvideMediaData:YES forTrackID:trackID]; 891 892 RetainPtr<AVSampleBufferAudioRenderer> renderer; 892 if (!m_audioRenderers.co unt(trackID)) {893 if (!m_audioRenderers.contains(trackID)) { 893 894 renderer = adoptNS([[getAVSampleBufferAudioRendererClass() alloc] init]); 894 895 [renderer requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^{ 895 896 didBecomeReadyForMoreSamples(trackID); 896 897 }]; 897 m_audioRenderers [trackID] = renderer;898 m_audioRenderers.set(trackID, renderer); 898 899 [m_errorListener beginObservingRenderer:renderer.get()]; 899 900 } else 900 renderer = m_audioRenderers [trackID].get();901 renderer = m_audioRenderers.get(trackID); 901 902 902 903 if (m_mediaSource) … … 905 906 } 906 907 908 void SourceBufferPrivateAVFObjC::flush() 909 { 910 if (m_displayLayer) 911 [m_displayLayer flushAndRemoveImage]; 912 913 for (auto& renderer : m_audioRenderers.values()) 914 [renderer flush]; 915 } 916 907 917 void SourceBufferPrivateAVFObjC::registerForErrorNotifications(SourceBufferPrivateAVFObjCErrorClient* client) 908 918 { … … 920 930 { 921 931 LOG(MediaSource, "SourceBufferPrivateAVFObjC::layerDidReceiveError(%p): layer(%p), error(%@)", this, layer, [error description]); 922 for (auto& client : m_errorClients) 923 client->layerDidReceiveError(layer, error); 932 933 // FIXME(142246): Remove the following once <rdar://problem/20027434> is resolved. 934 bool anyIgnored = false; 935 for (auto& client : m_errorClients) { 936 bool shouldIgnore = false; 937 client->layerDidReceiveError(layer, error, shouldIgnore); 938 anyIgnored |= shouldIgnore; 939 } 940 if (anyIgnored) 941 return; 924 942 925 943 int errorCode = [[[error userInfo] valueForKey:@"OSStatus"] intValue]; … … 932 950 { 933 951 LOG(MediaSource, "SourceBufferPrivateAVFObjC::rendererDidReceiveError(%p): renderer(%p), error(%@)", this, renderer, [error description]); 934 for (auto& client : m_errorClients) 935 client->rendererDidReceiveError(renderer, error); 952 953 // FIXME(142246): Remove the following once <rdar://problem/20027434> is resolved. 954 bool anyIgnored = false; 955 for (auto& client : m_errorClients) { 956 bool shouldIgnore = false; 957 client->rendererDidReceiveError(renderer, error, shouldIgnore); 958 anyIgnored |= shouldIgnore; 959 } 960 if (anyIgnored) 961 return; 936 962 } 937 963 … … 959 985 if (trackID == m_enabledVideoTrackID) 960 986 flushAndEnqueueNonDisplayingSamples(mediaSamples, m_displayLayer.get()); 961 else if (m_audioRenderers.co unt(trackID))962 flushAndEnqueueNonDisplayingSamples(mediaSamples, m_audioRenderers [trackID].get());987 else if (m_audioRenderers.contains(trackID)) 988 flushAndEnqueueNonDisplayingSamples(mediaSamples, m_audioRenderers.get(trackID).get()); 963 989 } 964 990 … … 1003 1029 { 1004 1030 int trackID = trackIDString.toInt(); 1005 if (trackID != m_enabledVideoTrackID && !m_audioRenderers.co unt(trackID))1031 if (trackID != m_enabledVideoTrackID && !m_audioRenderers.contains(trackID)) 1006 1032 return; 1007 1033 … … 1019 1045 m_mediaSource->player()->setHasAvailableVideoFrame(true); 1020 1046 } else 1021 [m_audioRenderers [trackID]enqueueSampleBuffer:platformSample.sample.cmSampleBuffer];1047 [m_audioRenderers.get(trackID) enqueueSampleBuffer:platformSample.sample.cmSampleBuffer]; 1022 1048 } 1023 1049 … … 1027 1053 if (trackID == m_enabledVideoTrackID) 1028 1054 return [m_displayLayer isReadyForMoreMediaData]; 1029 else if (m_audioRenderers.co unt(trackID))1030 return [m_audioRenderers [trackID]isReadyForMoreMediaData];1055 else if (m_audioRenderers.contains(trackID)) 1056 return [m_audioRenderers.get(trackID) isReadyForMoreMediaData]; 1031 1057 else 1032 1058 ASSERT_NOT_REACHED(); … … 1063 1089 if (trackID == m_enabledVideoTrackID) 1064 1090 [m_displayLayer stopRequestingMediaData]; 1065 else if (m_audioRenderers.co unt(trackID))1066 [m_audioRenderers [trackID]stopRequestingMediaData];1091 else if (m_audioRenderers.contains(trackID)) 1092 [m_audioRenderers.get(trackID) stopRequestingMediaData]; 1067 1093 else { 1068 1094 ASSERT_NOT_REACHED(); … … 1081 1107 didBecomeReadyForMoreSamples(trackID); 1082 1108 }]; 1083 } else if (m_audioRenderers.co unt(trackID)) {1084 [m_audioRenderers [trackID]requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^{1109 } else if (m_audioRenderers.contains(trackID)) { 1110 [m_audioRenderers.get(trackID) requestMediaDataWhenReadyOnQueue:dispatch_get_main_queue() usingBlock:^{ 1085 1111 didBecomeReadyForMoreSamples(trackID); 1086 1112 }];
Note:
See TracChangeset
for help on using the changeset viewer.