Open UIApplicationMain opened 8 years ago
Would it be plausible to wrap
CGContextRef ctx = SCCreateContextFromPixelBuffer(outputPixelBuffer);
overlay.frame = CGRectMake(0, 0, CVPixelBufferGetWidth(outputPixelBuffer), CVPixelBufferGetHeight(outputPixelBuffer));
[overlay layoutIfNeeded];
[overlay.layer renderInContext:ctx];
CGContextRelease(ctx);
in a dispatch_sync(dispatch_get_main_queue(), ^{ });
?
Seems like UITextView requires to layout in the main thread. You can't just have a dispatch_sync every time since it will probably greatly slow down the encoding. I just added a new method in SCVideoOverlay: requiresUpdateOnMainThreadAtVideoTime:videoSize: that is called to determine whether setFrame:, updateWithVideoTime: and layoutIfNeeded should be called on the main thread.
Here is what I would do now:
That way your initial layout will be called in the main thread and it should be fast for any following frames. Let me know if that fix your issue. Thanks!
Hi rFlex,
Thanks for the turnaround. I'm trying to override requiresUpdateOnMainThreadAtVideoTime in my UIView subclass, but am running into the error: "Method does not override any method from its superclass"
I tried
override func requiresUpdateOnMainThreadAtVideoTime(videoSize: CGSize) -> Bool {
print("**requiresUpdateOnMainThreadAtVideoTime called**")
if videoSize == CGSizeZero || videoSize != self.bounds.size {
return true
}
return false
}
However if I do not override it in the new tempView subclass (which just inits a UIView with same dimensions as my captured video and copies the UITextView over into the UIView subclass and calls self.addSubview(UITextView)) it works. Or is that still synchronously putting it on the video?
Make sure to make your subview implement SCVideoOverlay. Your implementation will then look like this:
func requiresUpdateOnMainThreadAtVideoTime(videoTime: NSTimeInterval, videoSize: CGSize) -> Bool {
print("**requiresUpdateOnMainThreadAtVideoTime called**")
return videoTime == 0.0 || videoSize != self.bounds.size
}
I tried it two ways:
1) To programmatically re-create a new UITextView with attributes of my editable one scaled to video size, this is done in the subclass of UIView implementing SCVideoOverlay. This calls the override function and works 100% of the time. But here I assume it doesn't have to lay out anything since it isn't a direct copy of the original UITextView.
2) To create a UITextView attribute within my subclass and set it with
let tempView: SCVideoOverlayView = SCVideoOverlayView(frame: CGRectMake(0, 0, 720.0, 1080.0))
tempView.backgroundColor = UIColor.clearColor()
tempView.tempTextView = NSKeyedUnarchiver.unarchiveObjectWithData(NSKeyedArchiver.archivedDataWithRootObject(overlayText)) as! UITextView
This failed with
requiresUpdateOnMainThreadAtVideoTime called
2016-06-20 17:39:22.745 TallyyBeta[4845:1136198] ** Assertion failure in void UIPerformResizeOfTextViewForTextContainer(NSLayoutManager , UIView
It could be that my 2nd approach is not the correct way to tackle the feature.
Forgot to mention that in 2nd approach it still fails at [overlay.layer renderInContext:ctx];
EDIT: I tried switching the return argument to
return videoTime == 0.0 || videoSize != CGSizeMake(720, 1280)
since the UITextView that is being copied isn't the same size as the video bounds (video is 720x1280), and is instead the frame size of the view.
However it returns true because videoTime is 0, but if I force return true or false they still both end up failing.
Would you mind create a sample project so I can fix the issue directly? As a workaround in the mean time you could just create a UIImage out of your UITextView and use it instead. You could also try creating a snapshot view from the overlayText instead of making a deep copy using NSKeyedArchiver.
My app crashes when I try to add a UIView as an overlay for a video export session. I'm not sure if I am misunderstanding how to use overlay for videos
I have a UITextView that the user can edit on my screen, when time to save the video, I do the following:
It crashes at line
[overlay.layer renderInContext:ctx]; (Line 181)
in- (void)CGRenderWithInputPixelBuffer:(CVPixelBufferRef)inputPixelBuffer toOutputPixelBuffer:(CVPixelBufferRef)outputPixelBuffer atTimeInterval:(NSTimeInterval)timeSeconds
with the error: Assertion failure in void UIPerformResizeOfTextViewForTextContainer(NSLayoutManager , UIView , NSTextContainer , NSUInteger)(), /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIFoundation/UIFoundation-432.1/UIFoundation/TextSystem/NSLayoutManagerPrivate.m:1551
** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'