FreeRDP
Loading...
Searching...
No Matches
frame_rate.h
1
18#ifndef FREERDP_RDPECAM_AVFOUNDATION_FRAME_RATE_H
19#define FREERDP_RDPECAM_AVFOUNDATION_FRAME_RATE_H
20
21#include <math.h>
22#include <CoreMedia/CoreMedia.h>
23#include <winpr/assert.h>
24#include <winpr/wtypes.h>
25#include "capture_policy.h"
26
27WINPR_ATTR_NODISCARD
28static inline BOOL cam_avfoundation_frame_duration(UINT32 numerator, UINT32 denominator,
29 CMTime minimum, CMTime maximum, CMTime* duration)
30{
31 WINPR_ASSERT(duration);
32 if (!numerator || (numerator > INT32_MAX) || !denominator || !CMTIME_IS_NUMERIC(minimum) ||
33 !CMTIME_IS_NUMERIC(maximum) || (minimum.value <= 0) || (maximum.value <= 0) ||
34 (minimum.timescale <= 0) || (maximum.timescale <= 0) || minimum.epoch || maximum.epoch ||
35 (CMTimeCompare(minimum, maximum) > 0))
36 return FALSE;
37 const CMTime requested = CMTimeMake(denominator, (CMTimeScale)numerator);
38 CMTime supported = requested;
39 if (CMTimeCompare(requested, minimum) < 0)
40 supported = minimum;
41 else if (CMTimeCompare(requested, maximum) > 0)
42 supported = maximum;
43
44 /* Some drivers report nominal 30/15 fps as 30.000030/15.000015 fps.
45 * Clamp small endpoint rounding to a native duration using the capture policy's
46 * tolerance, without merging distinct rates such as 29.97 and 30. */
47 const double seconds = CMTimeGetSeconds(requested);
48 if (fabs(CMTimeGetSeconds(supported) - seconds) >
49 seconds * CAM_AVFOUNDATION_FRAME_DURATION_TOLERANCE)
50 return FALSE;
51 *duration = supported;
52 return TRUE;
53}
54
55WINPR_ATTR_NODISCARD
56static inline BOOL cam_avfoundation_frame_rate(CMTime duration, UINT32* numerator,
57 UINT32* denominator)
58{
59 WINPR_ASSERT(numerator);
60 WINPR_ASSERT(denominator);
61 if (!CMTIME_IS_NUMERIC(duration) || (duration.value <= 0) || (duration.timescale <= 0) ||
62 duration.epoch)
63 return FALSE;
64 /* Reduce the inverse duration to fit the wire fields without rounding the native rate. */
65 UINT64 num = (UINT32)duration.timescale;
66 UINT64 den = (UINT64)duration.value;
67 UINT64 a = num;
68 UINT64 b = den;
69 while (b)
70 {
71 const UINT64 remainder = a % b;
72 a = b;
73 b = remainder;
74 }
75 num /= a;
76 den /= a;
77 if ((num > UINT32_MAX) || (den > UINT32_MAX))
78 return FALSE;
79 *numerator = (UINT32)num;
80 *denominator = (UINT32)den;
81 return TRUE;
82}
83
84#endif