-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy path0003-samplebufferdisplay-lifetime-placement.patch
More file actions
193 lines (182 loc) · 7.54 KB
/
Copy path0003-samplebufferdisplay-lifetime-placement.patch
File metadata and controls
193 lines (182 loc) · 7.54 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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# Backports VideoLAN VLC commits da8b3130c0, af61becb6c, 82803f4e26,
# and 1729b74116 onto SwiftVLC's pinned c833c4be0 source.
# Adapted to c833's Control callback and the preceding SwiftVLC aspect patch.
diff --git a/modules/video_output/apple/VLCSampleBufferDisplay.m b/modules/video_output/apple/VLCSampleBufferDisplay.m
index 567a03a..2d90143 100644
--- a/modules/video_output/apple/VLCSampleBufferDisplay.m
+++ b/modules/video_output/apple/VLCSampleBufferDisplay.m
@@ -563,23 +563,20 @@ - (void)drawRect:(CGRect)dirtyRect {
#pragma mark -
@interface VLCSampleBufferDisplayView: VLCView <CALayerDelegate>
-@property (nonatomic, readonly) vout_display_t *vd;
-- (instancetype)initWithVoutDisplay:(vout_display_t *)vd;
- (AVSampleBufferDisplayLayer *)displayLayer;
@end
@implementation VLCSampleBufferDisplayView
-- (instancetype)initWithVoutDisplay:(vout_display_t *)vd {
+- (instancetype)init {
self = [super init];
if (!self)
return nil;
- _vd = vd;
#if TARGET_OS_OSX
- self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
+ self.autoresizingMask = NSViewNotSizable;
self.wantsLayer = YES;
#else
- self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ self.autoresizingMask = UIViewAutoresizingNone;
#endif
return self;
}
@@ -642,7 +639,6 @@ - (BOOL)acceptsFirstResponder
@interface VLCSampleBufferDisplay: NSObject
{
@public
- vout_display_place_t place;
filter_t *converter;
}
@property (nonatomic, readonly, weak) VLCView *window;
@@ -658,6 +654,7 @@ @interface VLCSampleBufferDisplay: NSObject
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)initWithVoutDisplay:(vout_display_t *)vd;
+ - (void)placeVideo:(vout_display_place_t)newPlace;
@end
/* The sample-buffer layer fits its enqueued frames by gravity, not by the
@@ -671,29 +668,28 @@ static AVLayerVideoGravity VLCGravityForDisplayCfg(const vout_display_cfg_t *cfg
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
+ * fill (cover) path keeps its identity transform and uses layer gravity.
+ *
+ * Compute the transform on the vout thread. A vout_display_t must never be
+ * retained or dereferenced by the asynchronous main-queue presentation block. */
+static CGAffineTransform VLCAspectStretchForDisplay(const vout_display_t *vd)
{
- 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;
+ const vout_display_place_t *p = vd->place;
+ const video_format_t *source = vd->source;
+ const vout_display_cfg_t *cfg = 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;
+ /* The display view is placed in p, so calculate the natural aspect-fit
+ * box in that coordinate space before stretching it to the full box. */
+ const double displayW = (double)p->width;
+ const double displayH = (double)p->height;
const double naturalAR =
(double)source->i_visible_width / (double)source->i_visible_height;
const double displayAR = displayW / displayH;
@@ -710,9 +706,11 @@ - (void)applyAspectStretch
t = CGAffineTransformMakeScale((double)p->width / naturalW,
(double)p->height / naturalH);
}
- layer.affineTransform = t;
+ return t;
}
+@implementation VLCSampleBufferDisplay
+
- (id<VLCPixelBufferRotationContext>)rotationContext
{
if (_rotationContext)
@@ -763,6 +761,23 @@ - (void)preparePictureInPicture {
}
}
+- (CGRect)frameForPlace:(const vout_display_place_t *)place
+{
+ VLCView *window = self.window;
+ CGRect frame = CGRectMake(place->x, place->y, place->width, place->height);
+#if TARGET_OS_OSX
+ frame = [window convertRectFromBacking:frame];
+ frame.origin.y = window.bounds.size.height - frame.origin.y - frame.size.height;
+#else
+ CGFloat scale = window.contentScaleFactor;
+ frame.origin.x /= scale;
+ frame.origin.y /= scale;
+ frame.size.width /= scale;
+ frame.size.height /= scale;
+#endif
+ return frame;
+}
+
- (void)prepareDisplay {
@synchronized(_displayLayer) {
if (_displayLayer)
@@ -770,6 +785,9 @@ - (void)prepareDisplay {
}
VLCSampleBufferDisplay *sys = self;
+ vout_display_place_t place = *_vd->place;
+ AVLayerVideoGravity gravity = VLCGravityForDisplayCfg(_vd->cfg);
+ CGAffineTransform aspectStretch = VLCAspectStretchForDisplay(_vd);
dispatch_async(dispatch_get_main_queue(), ^{
if (sys.displayView)
return;
@@ -778,27 +796,29 @@ - (void)prepareDisplay {
VLCSampleBufferSubpictureView *spuView;
VLCView *window = sys.window;
- displayView =
- [[VLCSampleBufferDisplayView alloc] initWithVoutDisplay:sys.vd];
+ displayView = [[VLCSampleBufferDisplayView alloc] init];
spuView = [VLCSampleBufferSubpictureView new];
[window addSubview:displayView];
[window addSubview:spuView];
- [displayView setFrame:[window bounds]];
+ displayView.frame = [sys frameForPlace:&place];
[spuView setFrame:[window bounds]];
- sys->place = *sys.vd->place;
-
sys.displayView = displayView;
sys.spuView = spuView;
@synchronized(sys.displayLayer) {
sys.displayLayer = displayView.displayLayer;
}
- sys.displayLayer.videoGravity = VLCGravityForDisplayCfg(sys.vd->cfg);
- [sys applyAspectStretch];
+ sys.displayLayer.videoGravity = gravity;
+ sys.displayLayer.affineTransform = aspectStretch;
[sys preparePictureInPicture];
});
}
+- (void)placeVideo:(vout_display_place_t)newPlace
+{
+ self.displayView.frame = [self frameForPlace:&newPlace];
+}
+
- (void)close {
VLCSampleBufferDisplay *sys = self;
dispatch_async(dispatch_get_main_queue(), ^{
@@ -1109,12 +1129,15 @@ static int Control (vout_display_t *vd, int query)
case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
case VOUT_DISPLAY_CHANGE_SOURCE_PLACE:
{
+ vout_display_place_t newPlace = *vd->place;
AVLayerVideoGravity gravity = VLCGravityForDisplayCfg(vd->cfg);
+ CGAffineTransform aspectStretch = VLCAspectStretchForDisplay(vd);
dispatch_async(dispatch_get_main_queue(), ^{
+ [sys placeVideo:newPlace];
@synchronized(sys.displayLayer) {
sys.displayLayer.videoGravity = gravity;
+ sys.displayLayer.affineTransform = aspectStretch;
}
- [sys applyAspectStretch];
});
break;
}