// Callback passed to the VideoToolbox decoder for returning data. // This needs to be static because the API takes a C-style pair of // function and userdata pointers. This validates parameters and // forwards the decoded image back to an object method. static void PlatformCallback(void* decompressionOutputRefCon, void* sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags flags, CVImageBufferRef image, CMTime presentationTimeStamp, CMTime presentationDuration) { LOG("AppleVideoDecoder %s status %d flags %d", __func__, status, flags); AppleVTDecoder* decoder = static_cast<AppleVTDecoder*>(decompressionOutputRefCon); nsAutoPtr<AppleVTDecoder::AppleFrameRef> frameRef( static_cast<AppleVTDecoder::AppleFrameRef*>(sourceFrameRefCon)); // Validate our arguments. if (status != noErr || !image) { NS_WARNING("VideoToolbox decoder returned no data"); image = nullptr; } else if (flags & kVTDecodeInfo_FrameDropped) { NS_WARNING(" ...frame tagged as dropped..."); } else { MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(), "VideoToolbox returned an unexpected image type"); } decoder->OutputFrame(image, *frameRef); }
// Callback passed to the VideoToolbox decoder for returning data. // This needs to be static because the API takes a C-style pair of // function and userdata pointers. This validates parameters and // forwards the decoded image back to an object method. static void PlatformCallback(void* decompressionOutputRefCon, void* sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags flags, CVImageBufferRef image, CMTime presentationTimeStamp, CMTime presentationDuration) { LOG("AppleVideoDecoder %s status %d flags %d", __func__, status, flags); AppleVTDecoder* decoder = static_cast<AppleVTDecoder*>(decompressionOutputRefCon); nsAutoPtr<AppleVTDecoder::AppleFrameRef> frameRef( static_cast<AppleVTDecoder::AppleFrameRef*>(sourceFrameRefCon)); // Validate our arguments. if (status != noErr || !image) { NS_WARNING("VideoToolbox decoder returned no data"); return; } if (flags & kVTDecodeInfo_FrameDropped) { NS_WARNING(" ...frame dropped..."); } MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(), "VideoToolbox returned an unexpected image type"); // Forward the data back to an object method which can access // the correct MP4Reader callback. decoder->OutputFrame(image, frameRef); }
GMPErr GMPVideoEncoderParent::Encode(GMPVideoi420Frame* aInputFrame, const nsTArray<uint8_t>& aCodecSpecificInfo, const nsTArray<GMPVideoFrameType>& aFrameTypes) { nsAutoRef<GMPVideoi420Frame> frameRef(aInputFrame); if (!mIsOpen) { NS_WARNING("Trying to use an dead GMP video encoder"); return GMPGenericErr; } MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread()); auto inputFrameImpl = static_cast<GMPVideoi420FrameImpl*>(aInputFrame); // Very rough kill-switch if the plugin stops processing. If it's merely // hung and continues, we'll come back to life eventually. // 3* is because we're using 3 buffers per frame for i420 data for now. if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) || (NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) { return GMPGenericErr; } GMPVideoi420FrameData frameData; inputFrameImpl->InitFrameData(frameData); if (!SendEncode(frameData, aCodecSpecificInfo, aFrameTypes)) { return GMPGenericErr; } // Async IPC, we don't have access to a return value. return GMPNoErr; }
// Callback passed to the VideoToolbox decoder for returning data. // This needs to be static because the API takes a C-style pair of // function and userdata pointers. This validates parameters and // forwards the decoded image back to an object method. static void PlatformCallback(void* decompressionOutputRefCon, CFDictionaryRef frameInfo, OSStatus status, VDADecodeInfoFlags infoFlags, CVImageBufferRef image) { LOG("AppleVDADecoder[%s] status %d flags %d retainCount %ld", __func__, status, infoFlags, CFGetRetainCount(frameInfo)); // Validate our arguments. // According to Apple's TN2267 // The output callback is still called for all flushed frames, // but no image buffers will be returned. // FIXME: Distinguish between errors and empty flushed frames. if (status != noErr || !image) { NS_WARNING("AppleVDADecoder decoder returned no data"); return; } MOZ_ASSERT(CFGetTypeID(image) == CVPixelBufferGetTypeID(), "AppleVDADecoder returned an unexpected image type"); if (infoFlags & kVDADecodeInfo_FrameDropped) { NS_WARNING(" ...frame dropped..."); return; } AppleVDADecoder* decoder = static_cast<AppleVDADecoder*>(decompressionOutputRefCon); AutoCFRelease<CFNumberRef> ptsref = (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_PTS")); AutoCFRelease<CFNumberRef> dtsref = (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_DTS")); AutoCFRelease<CFNumberRef> durref = (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_DURATION")); AutoCFRelease<CFNumberRef> boref = (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_OFFSET")); AutoCFRelease<CFNumberRef> kfref = (CFNumberRef)CFDictionaryGetValue(frameInfo, CFSTR("FRAME_KEYFRAME")); Microseconds dts; Microseconds pts; Microseconds duration; int64_t byte_offset; char is_sync_point; CFNumberGetValue(ptsref, kCFNumberSInt64Type, &pts); CFNumberGetValue(dtsref, kCFNumberSInt64Type, &dts); CFNumberGetValue(durref, kCFNumberSInt64Type, &duration); CFNumberGetValue(boref, kCFNumberSInt64Type, &byte_offset); CFNumberGetValue(kfref, kCFNumberSInt8Type, &is_sync_point); nsAutoPtr<AppleVDADecoder::AppleFrameRef> frameRef( new AppleVDADecoder::AppleFrameRef(dts, pts, duration, byte_offset, is_sync_point == 1)); // Forward the data back to an object method which can access // the correct MP4Reader callback. decoder->OutputFrame(image, frameRef); }