Changeset 206518 in webkit
- Timestamp:
- Sep 28, 2016 7:52:48 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r206514 r206518 1 2016-09-28 Jer Noble <jer.noble@apple.com> 2 3 [MSE][Mac] In SourceBufferPrivateAVFObjC::abort(), support reseting parser to the last appended initialization segment. 4 https://bugs.webkit.org/show_bug.cgi?id=135164 5 6 Reviewed by Eric Carlson. 7 8 * media/media-source/media-source-abort-resets-parser-expected.txt: Added. 9 * media/media-source/media-source-abort-resets-parser.html: Added. 10 1 11 2016-09-28 Alejandro G. Castro <alex@igalia.com> 2 12 -
trunk/Source/WebCore/ChangeLog
r206517 r206518 1 2016-09-28 Jer Noble <jer.noble@apple.com> 2 3 [MSE][Mac] In SourceBufferPrivateAVFObjC::abort(), support reseting parser to the last appended initialization segment. 4 https://bugs.webkit.org/show_bug.cgi?id=135164 5 6 Reviewed by Eric Carlson. 7 8 Test: media/media-source/media-source-abort-resets-parser.html 9 10 Use the -[AVStreamDataParser appendStreamData:withFlags:] to implement "resetting" the parser. In this case, 11 the parser isn't explicitly reset during resetParserState(), but rather a flag is set so that the next append 12 signals a data discontinuity, and the parser is reset at that point. 13 14 Because a previous append operation may be in-flight during this abort(), care must be taken to invalidate any 15 operations which may have already started on a background thread. So SourceBufferPrivateAVFObjC will use a 16 separate WeakPtrFactory for its append operations, will invalidate any outstanding WeakPtrs during an abort(), 17 and will block until the previous append() operation completes. 18 19 This will require the WebAVStreamDataParserListener object to occasionally have it's WeakPtr pointing back to the 20 SourceBufferPrivateAVFObjC to be reset after an abort(), so make that ivar an @property. Rather than passing a 21 RetainPtr to itself in all the callbacks it handles, the WebAVStreamDataParserListener can just pass in a copy 22 of its own WeakPtr (which may be invalidated during an abort()). 23 24 Break the distinct operations of "abort()" and "resetParserState()" into their own methods in SourceBufferPrivate 25 and all its subclasses. 26 27 * Modules/mediasource/SourceBuffer.cpp: 28 (WebCore::SourceBuffer::resetParserState): 29 (WebCore::SourceBuffer::abortIfUpdating): 30 * platform/graphics/SourceBufferPrivate.h: 31 * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h: 32 * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm: 33 (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:]): 34 (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:withDiscontinuity:]): 35 (-[WebAVStreamDataParserListener streamDataParser:didFailToParseStreamDataWithError:]): 36 (-[WebAVStreamDataParserListener streamDataParser:didProvideMediaData:forTrackID:mediaType:flags:]): 37 (-[WebAVStreamDataParserListener streamDataParser:didReachEndOfTrackWithTrackID:mediaType:]): 38 (-[WebAVStreamDataParserListener streamDataParserWillProvideContentKeyRequestInitializationData:forTrackID:]): 39 (-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]): 40 (WebCore::SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC): 41 (WebCore::SourceBufferPrivateAVFObjC::append): 42 (WebCore::SourceBufferPrivateAVFObjC::abort): 43 (WebCore::SourceBufferPrivateAVFObjC::resetParserState): 44 (-[WebAVStreamDataParserListener initWithParser:parent:]): Deleted. 45 * platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp: 46 (WebCore::SourceBufferPrivateGStreamer::resetParserState): 47 * platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h: 48 * platform/mock/mediasource/MockSourceBufferPrivate.cpp: 49 (WebCore::MockSourceBufferPrivate::resetParserState): 50 * platform/mock/mediasource/MockSourceBufferPrivate.h: 51 * platform/spi/mac/AVFoundationSPI.h: 52 1 53 2016-09-28 Michael Catanzaro <mcatanzaro@igalia.com> 2 54 -
trunk/Source/WebCore/Modules/mediasource/SourceBuffer.cpp
r206300 r206518 279 279 m_appendState = WaitingForSegment; 280 280 281 m_private-> abort();281 m_private->resetParserState(); 282 282 } 283 283 … … 384 384 m_appendBufferTimer.stop(); 385 385 m_pendingAppendData.clear(); 386 m_private->abort(); 386 387 387 388 // 4.2. Set the updating attribute to false. -
trunk/Source/WebCore/platform/graphics/SourceBufferPrivate.h
r206301 r206518 53 53 virtual void append(const unsigned char* data, unsigned length) = 0; 54 54 virtual void abort() = 0; 55 virtual void resetParserState() = 0; 55 56 virtual void removedFromMediaSource() = 0; 56 57 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.h
r206025 r206518 30 30 31 31 #include "SourceBufferPrivate.h" 32 #include <dispatch/group.h> 32 33 #include <dispatch/semaphore.h> 33 34 #include <wtf/Deque.h> … … 116 117 void append(const unsigned char* data, unsigned length) override; 117 118 void abort() override; 119 void resetParserState() override; 118 120 void removedFromMediaSource() override; 119 121 MediaPlayer::ReadyState readyState() const override; … … 140 142 141 143 WeakPtrFactory<SourceBufferPrivateAVFObjC> m_weakFactory; 144 WeakPtrFactory<SourceBufferPrivateAVFObjC> m_appendWeakFactory; 142 145 143 146 RetainPtr<AVStreamDataParser> m_parser; … … 149 152 RetainPtr<NSError> m_hdcpError; 150 153 OSObjectPtr<dispatch_semaphore_t> m_hasSessionSemaphore; 154 OSObjectPtr<dispatch_group_t> m_isAppendingGroup; 151 155 152 156 MediaSourcePrivateAVFObjC* m_mediaSource; … … 157 161 FloatSize m_currentSize; 158 162 bool m_parsingSucceeded; 163 bool m_parserStateWasReset { false }; 159 164 int m_enabledVideoTrackID; 160 165 int m_protectedTrackID; -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm
r206025 r206518 132 132 AVStreamDataParser* _parser; 133 133 } 134 @property (assign) WeakPtr<WebCore::SourceBufferPrivateAVFObjC> parent; 134 135 - (id)initWithParser:(AVStreamDataParser*)parser parent:(WeakPtr<WebCore::SourceBufferPrivateAVFObjC>)parent; 135 136 @end … … 149 150 } 150 151 152 @synthesize parent=_parent; 153 151 154 - (void)dealloc 152 155 { … … 167 170 #endif 168 171 ASSERT(streamDataParser == _parser); 169 RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;170 172 171 173 RetainPtr<AVAsset*> protectedAsset = asset; 172 callOnMainThread([p rotectedSelf = WTFMove(protectedSelf), protectedAsset = WTFMove(protectedAsset)] {173 if (p rotectedSelf->_parent)174 p rotectedSelf->_parent->didParseStreamDataAsAsset(protectedAsset.get());174 callOnMainThread([parent = _parent, protectedAsset = WTFMove(protectedAsset)] { 175 if (parent) 176 parent->didParseStreamDataAsAsset(protectedAsset.get()); 175 177 }); 176 178 } … … 183 185 #endif 184 186 ASSERT(streamDataParser == _parser); 185 RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;186 187 187 188 RetainPtr<AVAsset*> protectedAsset = asset; 188 callOnMainThread([p rotectedSelf = WTFMove(protectedSelf), protectedAsset = WTFMove(protectedAsset)] {189 if (p rotectedSelf->_parent)190 p rotectedSelf->_parent->didParseStreamDataAsAsset(protectedAsset.get());189 callOnMainThread([parent = _parent, protectedAsset = WTFMove(protectedAsset)] { 190 if (parent) 191 parent->didParseStreamDataAsAsset(protectedAsset.get()); 191 192 }); 192 193 } … … 198 199 #endif 199 200 ASSERT(streamDataParser == _parser); 200 RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;201 201 202 202 RetainPtr<NSError> protectedError = error; 203 callOnMainThread([p rotectedSelf = WTFMove(protectedSelf), protectedError = WTFMove(protectedError)] {204 if (p rotectedSelf->_parent)205 p rotectedSelf->_parent->didFailToParseStreamDataWithError(protectedError.get());203 callOnMainThread([parent = _parent, protectedError = WTFMove(protectedError)] { 204 if (parent) 205 parent->didFailToParseStreamDataWithError(protectedError.get()); 206 206 }); 207 207 } … … 213 213 #endif 214 214 ASSERT(streamDataParser == _parser); 215 RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;216 215 217 216 RetainPtr<CMSampleBufferRef> protectedSample = sample; 218 217 String mediaType = nsMediaType; 219 callOnMainThread([p rotectedSelf = WTFMove(protectedSelf), protectedSample = WTFMove(protectedSample), trackID, mediaType, flags] {220 if (p rotectedSelf->_parent)221 p rotectedSelf->_parent->didProvideMediaDataForTrackID(trackID, protectedSample.get(), mediaType, flags);218 callOnMainThread([parent = _parent, protectedSample = WTFMove(protectedSample), trackID, mediaType, flags] { 219 if (parent) 220 parent->didProvideMediaDataForTrackID(trackID, protectedSample.get(), mediaType, flags); 222 221 }); 223 222 } … … 229 228 #endif 230 229 ASSERT(streamDataParser == _parser); 231 RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;232 230 233 231 String mediaType = nsMediaType; 234 callOnMainThread([p rotectedSelf = WTFMove(protectedSelf), trackID, mediaType] {235 if (p rotectedSelf->_parent)236 p rotectedSelf->_parent->didReachEndOfTrackWithTrackID(trackID, mediaType);232 callOnMainThread([parent = _parent, trackID, mediaType] { 233 if (parent) 234 parent->didReachEndOfTrackWithTrackID(trackID, mediaType); 237 235 }); 238 236 } … … 247 245 // We must call synchronously to the main thread, as the AVStreamSession must be associated 248 246 // with the streamDataParser before the delegate method returns. 249 RetainPtr<WebAVStreamDataParserListener> strongSelf = self; 250 dispatch_sync(dispatch_get_main_queue(), [strongSelf, trackID]() { 251 if (strongSelf->_parent) 252 strongSelf->_parent->willProvideContentKeyRequestInitializationDataForTrackID(trackID); 247 dispatch_sync(dispatch_get_main_queue(), [parent = _parent, trackID]() { 248 if (parent) 249 parent->willProvideContentKeyRequestInitializationDataForTrackID(trackID); 253 250 }); 254 251 } … … 260 257 #endif 261 258 ASSERT(streamDataParser == _parser); 262 RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;263 259 264 260 OSObjectPtr<dispatch_semaphore_t> hasSessionSemaphore = adoptOSObject(dispatch_semaphore_create(0)); 265 callOnMainThread([p rotectedSelf = WTFMove(protectedSelf), protectedInitData = RetainPtr<NSData>(initData), trackID, hasSessionSemaphore] {266 if (p rotectedSelf->_parent)267 p rotectedSelf->_parent->didProvideContentKeyRequestInitializationDataForTrackID(protectedInitData.get(), trackID, hasSessionSemaphore);261 callOnMainThread([parent = _parent, protectedInitData = RetainPtr<NSData>(initData), trackID, hasSessionSemaphore] { 262 if (parent) 263 parent->didProvideContentKeyRequestInitializationDataForTrackID(protectedInitData.get(), trackID, hasSessionSemaphore); 268 264 }); 269 265 dispatch_semaphore_wait(hasSessionSemaphore.get(), DISPATCH_TIME_FOREVER); … … 462 458 SourceBufferPrivateAVFObjC::SourceBufferPrivateAVFObjC(MediaSourcePrivateAVFObjC* parent) 463 459 : m_weakFactory(this) 460 , m_appendWeakFactory(this) 464 461 , m_parser(adoptNS([allocAVStreamDataParserInstance() init])) 465 462 , m_delegate(adoptNS([[WebAVStreamDataParserListener alloc] initWithParser:m_parser.get() parent:createWeakPtr()])) 466 463 , m_errorListener(adoptNS([[WebAVSampleBufferErrorListener alloc] initWithParent:this])) 464 , m_isAppendingGroup(adoptOSObject(dispatch_group_create())) 467 465 , m_mediaSource(parent) 468 466 , m_client(0) … … 642 640 643 641 RetainPtr<NSData> nsData = adoptNS([[NSData alloc] initWithBytes:data length:length]); 644 WeakPtr<SourceBufferPrivateAVFObjC> weakThis = createWeakPtr();642 WeakPtr<SourceBufferPrivateAVFObjC> weakThis = m_appendWeakFactory.createWeakPtr(); 645 643 RetainPtr<AVStreamDataParser> parser = m_parser; 646 644 RetainPtr<WebAVStreamDataParserListener> delegate = m_delegate; 647 645 648 646 m_parsingSucceeded = true; 649 650 dispatch_async(globalDataParserQueue(), [nsData, weakThis, parser, delegate] { 651 652 [parser appendStreamData:nsData.get()]; 647 dispatch_group_enter(m_isAppendingGroup.get()); 648 649 dispatch_async(globalDataParserQueue(), [nsData, weakThis, parser, delegate, isAppendingGroup = m_isAppendingGroup, parserStateWasReset = m_parserStateWasReset] { 650 if (parserStateWasReset) 651 [parser appendStreamData:nsData.get() withFlags:AVStreamDataParserStreamDataDiscontinuity]; 652 else 653 [parser appendStreamData:nsData.get()]; 653 654 654 655 callOnMainThread([weakThis] { … … 656 657 weakThis->appendCompleted(); 657 658 }); 659 dispatch_group_leave(isAppendingGroup.get()); 658 660 }); 661 m_parserStateWasReset = false; 659 662 } 660 663 … … 670 673 void SourceBufferPrivateAVFObjC::abort() 671 674 { 672 // The parser does not have a mechanism for resetting to a clean state, so destroy and re-create it. 673 // FIXME(135164): Support resetting parser to the last appended initialization segment. 674 destroyParser(); 675 676 m_parser = adoptNS([allocAVStreamDataParserInstance() init]); 677 m_delegate = adoptNS([[WebAVStreamDataParserListener alloc] initWithParser:m_parser.get() parent:createWeakPtr()]); 675 // The parsing queue may be blocked waiting for the main thread to provide it a AVStreamSession. We 676 // were asked to abort, and that cancels all outstanding append operations. Without cancelling this 677 // semaphore, the m_isAppendingGroup wait operation will deadlock. 678 if (m_hasSessionSemaphore) 679 dispatch_semaphore_signal(m_hasSessionSemaphore.get()); 680 dispatch_group_wait(m_isAppendingGroup.get(), DISPATCH_TIME_FOREVER); 681 m_appendWeakFactory.revokeAll(); 682 m_delegate.get().parent = m_appendWeakFactory.createWeakPtr(); 683 } 684 685 void SourceBufferPrivateAVFObjC::resetParserState() 686 { 687 m_parserStateWasReset = true; 678 688 } 679 689 -
trunk/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.cpp
r191174 r206518 76 76 } 77 77 78 void SourceBufferPrivateGStreamer::resetParserState() 79 { 80 notImplemented(); 81 } 82 78 83 void SourceBufferPrivateGStreamer::removedFromMediaSource() 79 84 { -
trunk/Source/WebCore/platform/graphics/gstreamer/SourceBufferPrivateGStreamer.h
r191174 r206518 51 51 virtual void append(const unsigned char* data, unsigned length); 52 52 virtual void abort(); 53 virtual void resetParserState(); 53 54 virtual void removedFromMediaSource(); 54 55 -
trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.cpp
r206306 r206518 204 204 } 205 205 206 void MockSourceBufferPrivate::resetParserState() 207 { 208 } 209 206 210 void MockSourceBufferPrivate::removedFromMediaSource() 207 211 { -
trunk/Source/WebCore/platform/mock/mediasource/MockSourceBufferPrivate.h
r206300 r206518 64 64 void append(const unsigned char* data, unsigned length) override; 65 65 void abort() override; 66 void resetParserState() override; 66 67 void removedFromMediaSource() override; 67 68 MediaPlayer::ReadyState readyState() const override; -
trunk/Source/WebCore/platform/spi/mac/AVFoundationSPI.h
r202434 r206518 117 117 }; 118 118 119 typedef NS_ENUM(NSUInteger, AVStreamDataParserStreamDataFlags) { 120 AVStreamDataParserStreamDataDiscontinuity = 1 << 0, 121 }; 122 119 123 @interface AVStreamDataParser : NSObject 120 124 - (void)setDelegate:(nullable id<AVStreamDataParserOutputHandling>)delegate; 121 125 - (void)appendStreamData:(NSData *)data; 126 - (void)appendStreamData:(NSData *)data withFlags:(AVStreamDataParserStreamDataFlags)flags; 122 127 - (void)setShouldProvideMediaData:(BOOL)shouldProvideMediaData forTrackID:(CMPersistentTrackID)trackID; 123 128 - (BOOL)shouldProvideMediaDataForTrackID:(CMPersistentTrackID)trackID;
Note: See TracChangeset
for help on using the changeset viewer.