Pārlūkot izejas kodu

mac-virtualcam: Fix incorrect PTS on Apple Silicon

The `fillFrame` method of the mac-virtualcam plugin is creating samples
directly using the value from `mach_absolute_time()` as `hostTime`.
This assumes this value is in nanoseconds, while it is in fact in mach
tick units. On Intel Macs mach tick units will be exactly 1 nanosecond
resulting in valid values, but on Apple Silicon macs this is no longer
the case.

This results in sample buffers with the placeholder image that have
much lower presentation time stamps than the samples containing content
produced by OBS. In previews/live streams this shows due to the last
content sample being shown frozen until the whole buffer is filled with
samples containing the placeholder image. Applications recording the
video stream are even more confused and crash or record videos with
wildly incorrect lengths.

In this PR `clock_gettime_nsec_np` is used to convert from mach tick units
to nanoseconds. This will make sure the `hostTime` value is correct on
both Apple Silicon and Intel macs. Making sure we produce stable
presentation time stamps from the virtual camera plugin at all times.
Mathijs Kadijk 2 gadi atpakaļ
vecāks
revīzija
ecaa5466cb

+ 1 - 1
plugins/mac-virtualcam/src/dal-plugin/CMSampleBufferUtils.mm

@@ -13,7 +13,7 @@ CMSampleTimingInfo CMSampleTimingInfoForTimestamp(uint64_t timestampNanos,
 {
 {
 	// The timing here is quite important. For frames to be delivered correctly and successfully be recorded by apps
 	// The timing here is quite important. For frames to be delivered correctly and successfully be recorded by apps
 	// like QuickTime Player, we need to be accurate in both our timestamps _and_ have a sensible scale. Using large
 	// like QuickTime Player, we need to be accurate in both our timestamps _and_ have a sensible scale. Using large
-	// timestamps and scales like mach_absolute_time() and NSEC_PER_SEC will work for display, but will error out
+	// timestamps and scales like clock_gettime_nsec_np() and NSEC_PER_SEC will work for display, but will error out
 	// when trying to record.
 	// when trying to record.
 	//
 	//
 	// 600 is a common default in Apple's docs https://developer.apple.com/documentation/avfoundation/avmutablemovie/1390622-timescale
 	// 600 is a common default in Apple's docs https://developer.apple.com/documentation/avfoundation/avmutablemovie/1390622-timescale

+ 4 - 4
plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.mm

@@ -316,7 +316,7 @@
 	CVPixelBufferRef pixelBuffer =
 	CVPixelBufferRef pixelBuffer =
 		[self createPixelBufferWithTestAnimation];
 		[self createPixelBufferWithTestAnimation];
 
 
-	uint64_t hostTime = mach_absolute_time();
+	uint64_t hostTime = clock_gettime_nsec_np(CLOCK_UPTIME_RAW);
 	CMSampleTimingInfo timingInfo =
 	CMSampleTimingInfo timingInfo =
 		CMSampleTimingInfoForTimestamp(hostTime, (uint32_t)self.fps, 1);
 		CMSampleTimingInfoForTimestamp(hostTime, (uint32_t)self.fps, 1);
 
 
@@ -365,9 +365,9 @@
 	CMSampleTimingInfo timingInfo = CMSampleTimingInfoForTimestamp(
 	CMSampleTimingInfo timingInfo = CMSampleTimingInfoForTimestamp(
 		timestamp, fpsNumerator, fpsDenominator);
 		timestamp, fpsNumerator, fpsDenominator);
 
 
-	err = CMIOStreamClockPostTimingEvent(timingInfo.presentationTimeStamp,
-					     mach_absolute_time(), true,
-					     self.clock);
+	err = CMIOStreamClockPostTimingEvent(
+		timingInfo.presentationTimeStamp,
+		clock_gettime_nsec_np(CLOCK_UPTIME_RAW), true, self.clock);
 	if (err != noErr) {
 	if (err != noErr) {
 		DLog(@"CMIOStreamClockPostTimingEvent err %d", err);
 		DLog(@"CMIOStreamClockPostTimingEvent err %d", err);
 	}
 	}