-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy path0002-samplebufferdisplay-aspect.patch
More file actions
108 lines (106 loc) · 4.58 KB
/
Copy path0002-samplebufferdisplay-aspect.patch
File metadata and controls
108 lines (106 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
diff --git a/modules/video_output/apple/VLCSampleBufferDisplay.m b/modules/video_output/apple/VLCSampleBufferDisplay.m
index f13a4f4f8a..567a03a7b1 100644
--- a/modules/video_output/apple/VLCSampleBufferDisplay.m
+++ b/modules/video_output/apple/VLCSampleBufferDisplay.m
@@ -140,7 +140,7 @@ typedef NS_ENUM(NSUInteger, VLCSampleBufferPixelFlip) {
kCVPixelBufferMetalCompatibilityKey,
#if TARGET_OS_OSX
kCVPixelBufferOpenGLCompatibilityKey,
-#elif !defined(TARGET_OS_VISION) || !TARGET_OS_VISION
+#elif (!defined(TARGET_OS_VISION) || !TARGET_OS_VISION) && !TARGET_OS_MACCATALYST
kCVPixelBufferOpenGLESCompatibilityKey,
#endif
};
@@ -151,7 +151,7 @@ typedef NS_ENUM(NSUInteger, VLCSampleBufferPixelFlip) {
(__bridge CFNumberRef)(@(dstHeight)),
(__bridge CFDictionaryRef)@{},
kCFBooleanTrue,
-#if !defined(TARGET_OS_VISION) || !TARGET_OS_VISION
+#if (!defined(TARGET_OS_VISION) || !TARGET_OS_VISION) && !TARGET_OS_MACCATALYST
kCFBooleanTrue
#endif
};
@@ -660,8 +660,59 @@ shouldInheritContentsScale:(CGFloat)newScale
- (instancetype)initWithVoutDisplay:(vout_display_t *)vd;
@end
+/* The sample-buffer layer fits its enqueued frames by gravity, not by the
+ * core-computed place rectangle, so the display fitting mode is mapped to a
+ * gravity: the larger ("fit outside") mode covers and crops, every other mode
+ * preserves aspect inside the surface. */
+static AVLayerVideoGravity VLCGravityForDisplayCfg(const vout_display_cfg_t *cfg)
+{
+ if (cfg->display.fitting == VLC_VIDEO_FIT_LARGER)
+ return AVLayerVideoGravityResizeAspectFill;
+ return AVLayerVideoGravityResizeAspect;
+}
+
@implementation VLCSampleBufferDisplay
+/* A forced display aspect (libvlc_video_set_aspect_ratio) reaches the vout as a
+ * target place rectangle, but AVSampleBufferDisplayLayer still fits the natural
+ * pixel shape. Scale the natural aspect-fit box into VLC's computed place box so
+ * forced ratios visibly stretch while the default path remains identity. The
+ * fill (cover) path keeps its identity transform and uses layer gravity. */
+- (void)applyAspectStretch
+{
+ AVSampleBufferDisplayLayer *layer = self.displayLayer;
+ if (!layer)
+ return;
+ const vout_display_place_t *p = self.vd->place;
+ const video_format_t *source = self.vd->source;
+ const vout_display_cfg_t *cfg = self.vd->cfg;
+ CGAffineTransform t = CGAffineTransformIdentity;
+ if (source && cfg && p->width > 0 && p->height > 0
+ && cfg->display.width > 0 && cfg->display.height > 0
+ && source->i_visible_width > 0 && source->i_visible_height > 0
+ && cfg->display.fitting != VLC_VIDEO_FIT_LARGER)
+ {
+ const double displayW = (double)cfg->display.width;
+ const double displayH = (double)cfg->display.height;
+ const double naturalAR =
+ (double)source->i_visible_width / (double)source->i_visible_height;
+ const double displayAR = displayW / displayH;
+ double naturalW;
+ double naturalH;
+ if (naturalAR > displayAR) {
+ naturalW = displayW;
+ naturalH = displayW / naturalAR;
+ } else {
+ naturalW = displayH * naturalAR;
+ naturalH = displayH;
+ }
+ if (naturalW > 0.0 && naturalH > 0.0)
+ t = CGAffineTransformMakeScale((double)p->width / naturalW,
+ (double)p->height / naturalH);
+ }
+ layer.affineTransform = t;
+}
+
- (id<VLCPixelBufferRotationContext>)rotationContext
{
if (_rotationContext)
@@ -742,6 +793,8 @@ shouldInheritContentsScale:(CGFloat)newScale
@synchronized(sys.displayLayer) {
sys.displayLayer = displayView.displayLayer;
}
+ sys.displayLayer.videoGravity = VLCGravityForDisplayCfg(sys.vd->cfg);
+ [sys applyAspectStretch];
[sys preparePictureInPicture];
});
}
@@ -1055,7 +1108,16 @@ static int Control (vout_display_t *vd, int query)
case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT:
case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
case VOUT_DISPLAY_CHANGE_SOURCE_PLACE:
+ {
+ AVLayerVideoGravity gravity = VLCGravityForDisplayCfg(vd->cfg);
+ dispatch_async(dispatch_get_main_queue(), ^{
+ @synchronized(sys.displayLayer) {
+ sys.displayLayer.videoGravity = gravity;
+ }
+ [sys applyAspectStretch];
+ });
break;
+ }
default:
msg_Err (vd, "Unhandled request %d", query);
return VLC_EGENERIC;