|
180 | 180 | }); |
181 | 181 | } |
182 | 182 |
|
| 183 | +bool WebCoreDecompressionSession::shouldDecodeSample(CMSampleBufferRef sample, bool displaying) |
| 184 | +{ |
| 185 | + if (!displaying) |
| 186 | + return true; |
| 187 | + |
| 188 | + if (!m_timebase) |
| 189 | + return true; |
| 190 | + |
| 191 | + auto currentTime = CMTimebaseGetTime(m_timebase.get()); |
| 192 | + auto presentationTimeStamp = CMSampleBufferGetPresentationTimeStamp(sample); |
| 193 | + if (CMTimeCompare(presentationTimeStamp, currentTime) >= 0) |
| 194 | + return true; |
| 195 | + |
| 196 | + CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sample, false); |
| 197 | + if (!attachments) |
| 198 | + return true; |
| 199 | + |
| 200 | + for (CFIndex index = 0, count = CFArrayGetCount(attachments); index < count; ++index) { |
| 201 | + CFDictionaryRef attachmentDict = (CFDictionaryRef)CFArrayGetValueAtIndex(attachments, index); |
| 202 | + CFBooleanRef dependedOn = (CFBooleanRef)CFDictionaryGetValue(attachmentDict, kCMSampleAttachmentKey_IsDependedOnByOthers); |
| 203 | + if (dependedOn && !CFBooleanGetValue(dependedOn)) |
| 204 | + return false; |
| 205 | + } |
| 206 | + |
| 207 | + return true; |
| 208 | +} |
| 209 | + |
183 | 210 | void WebCoreDecompressionSession::decodeSample(CMSampleBufferRef sample, bool displaying) |
184 | 211 | { |
185 | 212 | if (isInvalidated()) |
|
212 | 239 | if (!displaying) |
213 | 240 | flags |= kVTDecodeFrame_DoNotOutputFrame; |
214 | 241 |
|
| 242 | + if (!shouldDecodeSample(sample, displaying)) { |
| 243 | + ++m_totalVideoFrames; |
| 244 | + ++m_droppedVideoFrames; |
| 245 | + return; |
| 246 | + } |
| 247 | + |
215 | 248 | VTDecompressionSessionDecodeFrame(m_decompressionSession.get(), sample, flags, reinterpret_cast<void*>(displaying), nullptr); |
216 | 249 | } |
217 | 250 |
|
|
224 | 257 |
|
225 | 258 | void WebCoreDecompressionSession::handleDecompressionOutput(bool displaying, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef rawImageBuffer, CMTime presentationTimeStamp, CMTime presentationDuration) |
226 | 259 | { |
227 | | - UNUSED_PARAM(status); |
228 | | - UNUSED_PARAM(infoFlags); |
| 260 | + ++m_totalVideoFrames; |
| 261 | + if (infoFlags & kVTDecodeInfo_FrameDropped) |
| 262 | + ++m_droppedVideoFrames; |
229 | 263 |
|
230 | 264 | CMVideoFormatDescriptionRef rawImageBufferDescription = nullptr; |
231 | | - if (noErr != CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, rawImageBuffer, &rawImageBufferDescription)) |
| 265 | + if (status != noErr || noErr != CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, rawImageBuffer, &rawImageBufferDescription)) { |
| 266 | + ++m_corruptedVideoFrames; |
232 | 267 | return; |
| 268 | + } |
233 | 269 | RetainPtr<CMVideoFormatDescriptionRef> imageBufferDescription = adoptCF(rawImageBufferDescription); |
234 | 270 |
|
235 | 271 | CMSampleTimingInfo imageBufferTiming { |
|
239 | 275 | }; |
240 | 276 |
|
241 | 277 | CMSampleBufferRef rawImageSampleBuffer = nullptr; |
242 | | - if (noErr != CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault, rawImageBuffer, imageBufferDescription.get(), &imageBufferTiming, &rawImageSampleBuffer)) |
| 278 | + if (noErr != CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault, rawImageBuffer, imageBufferDescription.get(), &imageBufferTiming, &rawImageSampleBuffer)) { |
| 279 | + ++m_corruptedVideoFrames; |
243 | 280 | return; |
244 | | - RefPtr<WebCoreDecompressionSession> protectedThis { this }; |
245 | | - RetainPtr<CMSampleBufferRef> imageSampleBuffer = adoptCF(rawImageSampleBuffer); |
246 | | - dispatch_async(m_enqueingQueue.get(), [protectedThis, imageSampleBuffer, displaying] { |
| 281 | + } |
| 282 | + |
| 283 | + auto currentTime = CMTimebaseGetTime(m_timebase.get()); |
| 284 | + if (m_timebase && CMTimeCompare(presentationTimeStamp, currentTime) < 0) |
| 285 | + m_totalFrameDelay += toMediaTime(CMTimeSubtract(currentTime, presentationTimeStamp)); |
| 286 | + |
| 287 | + dispatch_async(m_enqueingQueue.get(), [protectedThis = makeRefPtr(this), status, imageSampleBuffer = adoptCF(rawImageSampleBuffer), infoFlags, displaying] { |
| 288 | + UNUSED_PARAM(infoFlags); |
247 | 289 | protectedThis->enqueueDecodedSample(imageSampleBuffer.get(), displaying); |
248 | 290 | }); |
249 | 291 | } |
|
0 commit comments