Changeset 258846 in webkit
- Timestamp:
- Mar 23, 2020 8:38:54 AM (4 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r258844 r258846 1 2020-03-23 Jer Noble <jer.noble@apple.com> 2 3 [MSE] Handle the case where AVStreamDataParser packages sync and non-sync samples together in a CMSampleBufferRef. 4 https://bugs.webkit.org/show_bug.cgi?id=209365 5 <rdar://problem/60625209> 6 7 Reviewed by Eric Carlson. 8 9 AVStreamDataParser will package together muliple samples into a single CMSampleBufferRef for efficiency's sake. When 10 this occurs, it may include sync and non-sync samples together into the same CMSampleBufferRef, which is problematic 11 as we consider a CMSampleBufferRef to be "sync" only when every sample inside the buffer is also sync. 12 13 To handle this scenario, when receiving a CMSampleBufferRef from AVStreamDataParser, first check whether that buffer 14 is "homogeneous", meaning every sample within the buffer has the same effective MediaSample flags. Then, if the buffer 15 is not homogenous, break the buffer into muliple homogenious CMSampleBufferRefs. Then, each of those resulting buffers 16 is passed up to SourceBuffer as a MediaSample individually. 17 18 * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h: 19 * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm: 20 (WebCore::isCMSampleBufferAttachmentRandomAccess): 21 (WebCore::isCMSampleBufferRandomAccess): 22 (WebCore::isCMSampleBufferAttachmentNonDisplaying): 23 (WebCore::isCMSampleBufferNonDisplaying): 24 (WebCore::MediaSampleAVFObjC::flags const): 25 (WebCore::MediaSampleAVFObjC::isHomogeneous const): 26 (WebCore::MediaSampleAVFObjC::divideIntoHomogeneousSamples): 27 * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm: 28 (WebCore::SourceBufferPrivateAVFObjC::processCodedFrame): 29 1 30 2020-03-23 Alicia Boya García <aboya@igalia.com> 2 31 -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h
r258807 r258846 69 69 CMSampleBufferRef sampleBuffer() const { return m_sample.get(); } 70 70 71 bool isHomogeneous() const; 72 Vector<Ref<MediaSampleAVFObjC>> divideIntoHomogeneousSamples(); 73 71 74 protected: 72 75 MediaSampleAVFObjC(RetainPtr<CMSampleBufferRef>&& sample) -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm
r258807 r258846 116 116 } 117 117 118 static bool isCMSampleBufferAttachmentRandomAccess(CFDictionaryRef attachmentDict) 119 { 120 return !CFDictionaryContainsKey(attachmentDict, kCMSampleAttachmentKey_NotSync); 121 } 122 118 123 static bool isCMSampleBufferRandomAccess(CMSampleBufferRef sample) 119 124 { … … 123 128 124 129 for (CFIndex i = 0, count = CFArrayGetCount(attachments); i < count; ++i) { 125 CFDictionaryRef attachmentDict = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, i)); 126 if (CFDictionaryContainsKey(attachmentDict, kCMSampleAttachmentKey_NotSync)) 130 if (!isCMSampleBufferAttachmentRandomAccess(checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, i)))) 127 131 return false; 128 132 } 129 133 return true; 134 } 135 136 static bool isCMSampleBufferAttachmentNonDisplaying(CFDictionaryRef attachmentDict) 137 { 138 return CFDictionaryContainsKey(attachmentDict, kCMSampleAttachmentKey_DoNotDisplay); 130 139 } 131 140 … … 137 146 138 147 for (CFIndex i = 0; i < CFArrayGetCount(attachments); ++i) { 139 CFDictionaryRef attachmentDict = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, i)); 140 if (CFDictionaryContainsKey(attachmentDict, kCMSampleAttachmentKey_DoNotDisplay)) 148 if (isCMSampleBufferAttachmentNonDisplaying(checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachments, i)))) 141 149 return true; 142 150 } … … 148 156 { 149 157 int returnValue = MediaSample::None; 150 158 151 159 if (isCMSampleBufferRandomAccess(m_sample.get())) 152 160 returnValue |= MediaSample::IsSync; … … 154 162 if (isCMSampleBufferNonDisplaying(m_sample.get())) 155 163 returnValue |= MediaSample::IsNonDisplaying; 156 164 157 165 return SampleFlags(returnValue); 158 166 } … … 317 325 } 318 326 319 } 327 bool MediaSampleAVFObjC::isHomogeneous() const 328 { 329 CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(m_sample.get(), true); 330 if (!attachmentsArray) 331 return true; 332 333 auto count = CFArrayGetCount(attachmentsArray); 334 if (count <= 1) 335 return true; 336 337 CFDictionaryRef firstAttachment = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachmentsArray, 0)); 338 bool isSync = isCMSampleBufferAttachmentRandomAccess(firstAttachment); 339 bool isNonDisplaying = isCMSampleBufferAttachmentNonDisplaying(firstAttachment); 340 341 for (CFIndex i = 1; i < count; ++i) { 342 auto attachmentDict = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachmentsArray, i)); 343 if (isSync != isCMSampleBufferAttachmentRandomAccess(attachmentDict)) 344 return false; 345 346 if (isNonDisplaying != isCMSampleBufferAttachmentNonDisplaying(attachmentDict)) 347 return false; 348 }; 349 350 return true; 351 } 352 353 Vector<Ref<MediaSampleAVFObjC>> MediaSampleAVFObjC::divideIntoHomogeneousSamples() 354 { 355 using SampleVector = Vector<Ref<MediaSampleAVFObjC>>; 356 357 CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(m_sample.get(), true); 358 if (!attachmentsArray) 359 return SampleVector::from(makeRef(*this)); 360 361 auto count = CFArrayGetCount(attachmentsArray); 362 if (count <= 1) 363 return SampleVector::from(makeRef(*this)); 364 365 CFDictionaryRef firstAttachment = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachmentsArray, 0)); 366 bool isSync = isCMSampleBufferAttachmentRandomAccess(firstAttachment); 367 bool isNonDisplaying = isCMSampleBufferAttachmentNonDisplaying(firstAttachment); 368 Vector<CFRange> ranges; 369 CFIndex currentRangeStart = 0; 370 CFIndex currentRangeLength = 1; 371 372 for (CFIndex i = 1; i < count; ++i, ++currentRangeLength) { 373 CFDictionaryRef attachmentDict = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(attachmentsArray, i)); 374 if (isSync == isCMSampleBufferAttachmentRandomAccess(attachmentDict) && isNonDisplaying == isCMSampleBufferAttachmentNonDisplaying(attachmentDict)) 375 continue; 376 377 ranges.append(CFRangeMake(currentRangeStart, currentRangeLength)); 378 currentRangeStart = i; 379 currentRangeLength = 0; 380 } 381 ranges.append(CFRangeMake(currentRangeStart, currentRangeLength)); 382 383 if (ranges.size() == 1) 384 return SampleVector::from(makeRef(*this)); 385 386 SampleVector samples; 387 samples.reserveInitialCapacity(ranges.size()); 388 for (auto& range : ranges) { 389 CMSampleBufferRef rawSample = nullptr; 390 if (CMSampleBufferCopySampleBufferForRange(kCFAllocatorDefault, m_sample.get(), range, &rawSample) != noErr || !rawSample) 391 return { }; 392 samples.uncheckedAppend(MediaSampleAVFObjC::create(adoptCF(rawSample).get(), m_id)); 393 } 394 return samples; 395 } 396 397 } -
trunk/Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm
r256770 r258846 599 599 return false; 600 600 601 if (m_client) { 602 Ref<MediaSample> mediaSample = MediaSampleAVFObjC::create(sampleBuffer, trackID); 603 DEBUG_LOG(LOGIDENTIFIER, mediaSample.get()); 601 if (!m_client) 602 return true; 603 604 auto mediaSample = MediaSampleAVFObjC::create(sampleBuffer, trackID); 605 606 if (mediaSample->isHomogeneous()) { 607 DEBUG_LOG(LOGIDENTIFIER, mediaSample->toJSONString()); 604 608 m_client->sourceBufferPrivateDidReceiveSample(mediaSample); 609 return true; 610 } 611 612 auto mediaSamples = mediaSample->divideIntoHomogeneousSamples(); 613 for (auto& sample : mediaSamples) { 614 DEBUG_LOG(LOGIDENTIFIER, sample->toJSONString()); 615 m_client->sourceBufferPrivateDidReceiveSample(sample); 605 616 } 606 617
Note: See TracChangeset
for help on using the changeset viewer.