mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Memory leak fixes
This commit is contained in:
parent
7afa98c52c
commit
30639d9a88
@ -785,6 +785,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
|||||||
}, openArchiveSettings: { [weak self] in
|
}, openArchiveSettings: { [weak self] in
|
||||||
self?.openArchiveSettings()
|
self?.openArchiveSettings()
|
||||||
}, autoSetReady: !animated, isMainTab: index == 0)
|
}, autoSetReady: !animated, isMainTab: index == 0)
|
||||||
|
self.pendingItemNode?.2.dispose()
|
||||||
let disposable = MetaDisposable()
|
let disposable = MetaDisposable()
|
||||||
self.pendingItemNode = (id, itemNode, disposable)
|
self.pendingItemNode = (id, itemNode, disposable)
|
||||||
|
|
||||||
@ -801,6 +802,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strongSelf.pendingItemNode?.2.dispose()
|
||||||
strongSelf.pendingItemNode = nil
|
strongSelf.pendingItemNode = nil
|
||||||
itemNode.listNode.tempTopInset = strongSelf.tempTopInset
|
itemNode.listNode.tempTopInset = strongSelf.tempTopInset
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#import <CoreVideo/CoreVideo.h>
|
#import <CoreVideo/CoreVideo.h>
|
||||||
#import <AVFoundation/AVFoundation.h>
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
|
@class TGVideoCameraRendererBuffer;
|
||||||
|
|
||||||
@interface TGVideoCameraGLRenderer : NSObject
|
@interface TGVideoCameraGLRenderer : NSObject
|
||||||
|
|
||||||
@property (nonatomic, readonly) __attribute__((NSObject)) CMFormatDescriptionRef outputFormatDescription;
|
@property (nonatomic, readonly) __attribute__((NSObject)) CMFormatDescriptionRef outputFormatDescription;
|
||||||
@ -13,7 +15,7 @@
|
|||||||
- (void)prepareForInputWithFormatDescription:(CMFormatDescriptionRef)inputFormatDescription outputRetainedBufferCountHint:(size_t)outputRetainedBufferCountHint;
|
- (void)prepareForInputWithFormatDescription:(CMFormatDescriptionRef)inputFormatDescription outputRetainedBufferCountHint:(size_t)outputRetainedBufferCountHint;
|
||||||
- (void)reset;
|
- (void)reset;
|
||||||
|
|
||||||
- (CVPixelBufferRef)copyRenderedPixelBuffer:(CVPixelBufferRef)pixelBuffer;
|
- (TGVideoCameraRendererBuffer *)copyRenderedPixelBuffer:(TGVideoCameraRendererBuffer *)pixelBuffer;
|
||||||
- (void)setPreviousPixelBuffer:(CVPixelBufferRef)previousPixelBuffer;
|
- (void)setPreviousPixelBuffer:(TGVideoCameraRendererBuffer *)previousPixelBuffer;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <CoreVideo/CoreVideo.h>
|
#import <CoreVideo/CoreVideo.h>
|
||||||
|
|
||||||
|
@class TGVideoCameraRendererBuffer;
|
||||||
|
|
||||||
@interface TGVideoCameraGLView : UIView
|
@interface TGVideoCameraGLView : UIView
|
||||||
|
|
||||||
- (void)displayPixelBuffer:(CVPixelBufferRef)pixelBuffer;
|
- (void)displayPixelBuffer:(TGVideoCameraRendererBuffer *)pixelBuffer;
|
||||||
- (void)flushPixelBufferCache;
|
- (void)flushPixelBufferCache;
|
||||||
- (void)reset;
|
- (void)reset;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#import <CoreMedia/CoreMedia.h>
|
#import <CoreMedia/CoreMedia.h>
|
||||||
|
|
||||||
@protocol TGVideoCameraMovieRecorderDelegate;
|
@protocol TGVideoCameraMovieRecorderDelegate;
|
||||||
|
@class TGVideoCameraRendererBuffer;
|
||||||
|
|
||||||
@interface TGVideoCameraMovieRecorder : NSObject
|
@interface TGVideoCameraMovieRecorder : NSObject
|
||||||
|
|
||||||
@ -15,7 +16,7 @@
|
|||||||
|
|
||||||
- (void)prepareToRecord;
|
- (void)prepareToRecord;
|
||||||
|
|
||||||
- (void)appendVideoPixelBuffer:(CVPixelBufferRef)pixelBuffer withPresentationTime:(CMTime)presentationTime;
|
- (void)appendVideoPixelBuffer:(TGVideoCameraRendererBuffer *)pixelBuffer withPresentationTime:(CMTime)presentationTime;
|
||||||
- (void)appendVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer;
|
- (void)appendVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer;
|
||||||
- (void)appendAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer;
|
- (void)appendAudioSampleBuffer:(CMSampleBufferRef)sampleBuffer;
|
||||||
|
|
||||||
|
@ -1387,6 +1387,14 @@ UIImage *TGSecretBlurredAttachmentImage(UIImage *source, CGSize size, uint32_t *
|
|||||||
return TGSecretBlurredAttachmentWithCornerRadiusImage(source, size, averageColor, attachmentBorder, 13, position);
|
return TGSecretBlurredAttachmentWithCornerRadiusImage(source, size, averageColor, attachmentBorder, 13, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
@interface DebugTGSecretBlurredAttachmentWithCornerRadiusImage : UIImage
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation DebugTGSecretBlurredAttachmentWithCornerRadiusImage
|
||||||
|
@end
|
||||||
|
#endif
|
||||||
|
|
||||||
UIImage *TGSecretBlurredAttachmentWithCornerRadiusImage(UIImage *source, CGSize size, uint32_t *averageColor, bool attachmentBorder, CGFloat cornerRadius, int position)
|
UIImage *TGSecretBlurredAttachmentWithCornerRadiusImage(UIImage *source, CGSize size, uint32_t *averageColor, bool attachmentBorder, CGFloat cornerRadius, int position)
|
||||||
{
|
{
|
||||||
CGFloat scale = TGScreenScaling(); //TGIsRetina() ? 2.0f : 1.0f;
|
CGFloat scale = TGScreenScaling(); //TGIsRetina() ? 2.0f : 1.0f;
|
||||||
@ -1496,7 +1504,11 @@ UIImage *TGSecretBlurredAttachmentWithCornerRadiusImage(UIImage *source, CGSize
|
|||||||
}
|
}
|
||||||
|
|
||||||
CGImageRef bitmapImage = CGBitmapContextCreateImage(targetContext);
|
CGImageRef bitmapImage = CGBitmapContextCreateImage(targetContext);
|
||||||
|
#if DEBUG
|
||||||
|
UIImage *image = [[DebugTGSecretBlurredAttachmentWithCornerRadiusImage alloc] initWithCGImage:bitmapImage];
|
||||||
|
#else
|
||||||
UIImage *image = [[UIImage alloc] initWithCGImage:bitmapImage];
|
UIImage *image = [[UIImage alloc] initWithCGImage:bitmapImage];
|
||||||
|
#endif
|
||||||
CGImageRelease(bitmapImage);
|
CGImageRelease(bitmapImage);
|
||||||
|
|
||||||
CGContextRelease(targetContext);
|
CGContextRelease(targetContext);
|
||||||
|
@ -213,62 +213,8 @@ typedef enum
|
|||||||
_trimView.startHandleMoved = ^(CGPoint translation)
|
_trimView.startHandleMoved = ^(CGPoint translation)
|
||||||
{
|
{
|
||||||
__strong TGMediaPickerGalleryVideoScrubber *strongSelf = weakSelf;
|
__strong TGMediaPickerGalleryVideoScrubber *strongSelf = weakSelf;
|
||||||
if (strongSelf == nil)
|
if (strongSelf) {
|
||||||
return;
|
[strongSelf startHandleMoved:translation];
|
||||||
|
|
||||||
if (strongSelf->_animatingZoomIn)
|
|
||||||
return;
|
|
||||||
|
|
||||||
UIView *trimView = strongSelf->_trimView;
|
|
||||||
|
|
||||||
CGRect availableTrimRect = [strongSelf _scrubbingRect];
|
|
||||||
CGRect normalScrubbingRect = [strongSelf _scrubbingRectZoomedIn:false];
|
|
||||||
CGFloat originX = MAX(0, trimView.frame.origin.x + translation.x);
|
|
||||||
CGFloat delta = originX - trimView.frame.origin.x;
|
|
||||||
CGFloat maxWidth = availableTrimRect.size.width + normalScrubbingRect.origin.x * 2 - originX;
|
|
||||||
|
|
||||||
CGRect trimViewRect = CGRectMake(originX, trimView.frame.origin.y, MIN(maxWidth, trimView.frame.size.width - delta), trimView.frame.size.height);
|
|
||||||
|
|
||||||
NSTimeInterval trimStartPosition = 0.0;
|
|
||||||
NSTimeInterval trimEndPosition = 0.0;
|
|
||||||
[strongSelf _trimStartPosition:&trimStartPosition trimEndPosition:&trimEndPosition forTrimFrame:trimViewRect duration:strongSelf.duration];
|
|
||||||
|
|
||||||
NSTimeInterval duration = trimEndPosition - trimStartPosition;
|
|
||||||
|
|
||||||
if (trimEndPosition - trimStartPosition < self.minimumLength)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (strongSelf.maximumLength > DBL_EPSILON && duration > strongSelf.maximumLength)
|
|
||||||
{
|
|
||||||
trimViewRect = CGRectMake(trimView.frame.origin.x + delta, trimView.frame.origin.y, trimView.frame.size.width, trimView.frame.size.height);
|
|
||||||
|
|
||||||
[strongSelf _trimStartPosition:&trimStartPosition trimEndPosition:&trimEndPosition forTrimFrame:trimViewRect duration:strongSelf.duration];
|
|
||||||
}
|
|
||||||
|
|
||||||
trimView.frame = trimViewRect;
|
|
||||||
|
|
||||||
[strongSelf _layoutTrimCurtainViews];
|
|
||||||
|
|
||||||
strongSelf->_trimStartValue = trimStartPosition;
|
|
||||||
strongSelf->_trimEndValue = trimEndPosition;
|
|
||||||
|
|
||||||
[strongSelf setValue:trimStartPosition];
|
|
||||||
|
|
||||||
UIView *handle = strongSelf->_scrubberHandle;
|
|
||||||
handle.center = CGPointMake(trimView.frame.origin.x + 12 + handle.frame.size.width / 2, handle.center.y);
|
|
||||||
|
|
||||||
UIView *dotHandle = strongSelf->_dotHandle;
|
|
||||||
dotHandle.center = CGPointMake(trimView.frame.origin.x + 12 + dotHandle.frame.size.width / 2, dotHandle.center.y);
|
|
||||||
|
|
||||||
id<TGMediaPickerGalleryVideoScrubberDelegate> delegate = strongSelf.delegate;
|
|
||||||
if ([delegate respondsToSelector:@selector(videoScrubber:editingStartValueDidChange:)])
|
|
||||||
[delegate videoScrubber:strongSelf editingStartValueDidChange:trimStartPosition];
|
|
||||||
|
|
||||||
[strongSelf cancelZoomIn];
|
|
||||||
if ([strongSelf zoomAvailable])
|
|
||||||
{
|
|
||||||
strongSelf->_pivotSource = TGMediaPickerGalleryVideoScrubberPivotSourceTrimStart;
|
|
||||||
[strongSelf performSelector:@selector(zoomIn) withObject:nil afterDelay:TGVideoScrubberZoomActivationInterval];
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
_trimView.endHandleMoved = ^(CGPoint translation)
|
_trimView.endHandleMoved = ^(CGPoint translation)
|
||||||
@ -418,6 +364,65 @@ typedef enum
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)startHandleMoved:(CGPoint)translation {
|
||||||
|
TGMediaPickerGalleryVideoScrubber *strongSelf = self;
|
||||||
|
|
||||||
|
if (strongSelf->_animatingZoomIn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UIView *trimView = strongSelf->_trimView;
|
||||||
|
|
||||||
|
CGRect availableTrimRect = [strongSelf _scrubbingRect];
|
||||||
|
CGRect normalScrubbingRect = [strongSelf _scrubbingRectZoomedIn:false];
|
||||||
|
CGFloat originX = MAX(0, trimView.frame.origin.x + translation.x);
|
||||||
|
CGFloat delta = originX - trimView.frame.origin.x;
|
||||||
|
CGFloat maxWidth = availableTrimRect.size.width + normalScrubbingRect.origin.x * 2 - originX;
|
||||||
|
|
||||||
|
CGRect trimViewRect = CGRectMake(originX, trimView.frame.origin.y, MIN(maxWidth, trimView.frame.size.width - delta), trimView.frame.size.height);
|
||||||
|
|
||||||
|
NSTimeInterval trimStartPosition = 0.0;
|
||||||
|
NSTimeInterval trimEndPosition = 0.0;
|
||||||
|
[strongSelf _trimStartPosition:&trimStartPosition trimEndPosition:&trimEndPosition forTrimFrame:trimViewRect duration:strongSelf.duration];
|
||||||
|
|
||||||
|
NSTimeInterval duration = trimEndPosition - trimStartPosition;
|
||||||
|
|
||||||
|
if (trimEndPosition - trimStartPosition < self.minimumLength)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strongSelf.maximumLength > DBL_EPSILON && duration > strongSelf.maximumLength)
|
||||||
|
{
|
||||||
|
trimViewRect = CGRectMake(trimView.frame.origin.x + delta, trimView.frame.origin.y, trimView.frame.size.width, trimView.frame.size.height);
|
||||||
|
|
||||||
|
[strongSelf _trimStartPosition:&trimStartPosition trimEndPosition:&trimEndPosition forTrimFrame:trimViewRect duration:strongSelf.duration];
|
||||||
|
}
|
||||||
|
|
||||||
|
trimView.frame = trimViewRect;
|
||||||
|
|
||||||
|
[strongSelf _layoutTrimCurtainViews];
|
||||||
|
|
||||||
|
strongSelf->_trimStartValue = trimStartPosition;
|
||||||
|
strongSelf->_trimEndValue = trimEndPosition;
|
||||||
|
|
||||||
|
[strongSelf setValue:trimStartPosition];
|
||||||
|
|
||||||
|
UIView *handle = strongSelf->_scrubberHandle;
|
||||||
|
handle.center = CGPointMake(trimView.frame.origin.x + 12 + handle.frame.size.width / 2, handle.center.y);
|
||||||
|
|
||||||
|
UIView *dotHandle = strongSelf->_dotHandle;
|
||||||
|
dotHandle.center = CGPointMake(trimView.frame.origin.x + 12 + dotHandle.frame.size.width / 2, dotHandle.center.y);
|
||||||
|
|
||||||
|
id<TGMediaPickerGalleryVideoScrubberDelegate> delegate = strongSelf.delegate;
|
||||||
|
if ([delegate respondsToSelector:@selector(videoScrubber:editingStartValueDidChange:)])
|
||||||
|
[delegate videoScrubber:strongSelf editingStartValueDidChange:trimStartPosition];
|
||||||
|
|
||||||
|
[strongSelf cancelZoomIn];
|
||||||
|
if ([strongSelf zoomAvailable])
|
||||||
|
{
|
||||||
|
strongSelf->_pivotSource = TGMediaPickerGalleryVideoScrubberPivotSourceTrimStart;
|
||||||
|
[strongSelf performSelector:@selector(zoomIn) withObject:nil afterDelay:TGVideoScrubberZoomActivationInterval];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setHasDotPicker:(bool)hasDotPicker {
|
- (void)setHasDotPicker:(bool)hasDotPicker {
|
||||||
_hasDotPicker = hasDotPicker;
|
_hasDotPicker = hasDotPicker;
|
||||||
_tapGestureRecognizer.enabled = hasDotPicker;
|
_tapGestureRecognizer.enabled = hasDotPicker;
|
||||||
|
@ -3,6 +3,56 @@
|
|||||||
#import <OpenGLES/ES2/glext.h>
|
#import <OpenGLES/ES2/glext.h>
|
||||||
|
|
||||||
#import <LegacyComponents/TGPaintShader.h>
|
#import <LegacyComponents/TGPaintShader.h>
|
||||||
|
#import "TGVideoCameraPipeline.h"
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
|
||||||
|
#ifndef GLES_SILENCE_DEPRECATION
|
||||||
|
#define GLES_SILENCE_DEPRECATION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface TGVideoCameraGLRendererBufferPool : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, assign) CVPixelBufferPoolRef pool;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TGVideoCameraGLRendererBufferPool
|
||||||
|
|
||||||
|
- (instancetype)initWithRetainedPool:(CVPixelBufferPoolRef)pool {
|
||||||
|
self = [super init];
|
||||||
|
if (self != nil) {
|
||||||
|
_pool = pool;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
if (_pool) {
|
||||||
|
CVPixelBufferPoolRelease(_pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation TGVideoCameraRendererBuffer
|
||||||
|
|
||||||
|
- (instancetype)initWithRetainedBuffer:(CVPixelBufferRef)buffer {
|
||||||
|
self = [super init];
|
||||||
|
if (self != nil) {
|
||||||
|
_buffer = buffer;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
if (_buffer) {
|
||||||
|
CVPixelBufferRelease(_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface TGVideoCameraGLRenderer ()
|
@interface TGVideoCameraGLRenderer ()
|
||||||
{
|
{
|
||||||
@ -10,11 +60,11 @@
|
|||||||
CVOpenGLESTextureCacheRef _textureCache;
|
CVOpenGLESTextureCacheRef _textureCache;
|
||||||
CVOpenGLESTextureCacheRef _prevTextureCache;
|
CVOpenGLESTextureCacheRef _prevTextureCache;
|
||||||
CVOpenGLESTextureCacheRef _renderTextureCache;
|
CVOpenGLESTextureCacheRef _renderTextureCache;
|
||||||
CVPixelBufferPoolRef _bufferPool;
|
TGVideoCameraGLRendererBufferPool *_bufferPool;
|
||||||
CFDictionaryRef _bufferPoolAuxAttributes;
|
CFDictionaryRef _bufferPoolAuxAttributes;
|
||||||
CMFormatDescriptionRef _outputFormatDescription;
|
CMFormatDescriptionRef _outputFormatDescription;
|
||||||
|
|
||||||
CVPixelBufferRef _previousPixelBuffer;
|
TGVideoCameraRendererBuffer *_previousPixelBuffer;
|
||||||
|
|
||||||
TGPaintShader *_shader;
|
TGPaintShader *_shader;
|
||||||
GLint _frameUniform;
|
GLint _frameUniform;
|
||||||
@ -194,20 +244,12 @@
|
|||||||
return _previousPixelBuffer != NULL;
|
return _previousPixelBuffer != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setPreviousPixelBuffer:(CVPixelBufferRef)previousPixelBuffer
|
- (void)setPreviousPixelBuffer:(TGVideoCameraRendererBuffer *)previousPixelBuffer
|
||||||
{
|
{
|
||||||
if (_previousPixelBuffer != NULL)
|
|
||||||
{
|
|
||||||
CFRelease(_previousPixelBuffer);
|
|
||||||
_previousPixelBuffer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_previousPixelBuffer = previousPixelBuffer;
|
_previousPixelBuffer = previousPixelBuffer;
|
||||||
if (_previousPixelBuffer != NULL)
|
|
||||||
CFRetain(_previousPixelBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CVPixelBufferRef)copyRenderedPixelBuffer:(CVPixelBufferRef)pixelBuffer
|
- (TGVideoCameraRendererBuffer *)copyRenderedPixelBuffer:(TGVideoCameraRendererBuffer *)pixelBuffer
|
||||||
{
|
{
|
||||||
static const GLfloat squareVertices[] =
|
static const GLfloat squareVertices[] =
|
||||||
{
|
{
|
||||||
@ -217,13 +259,15 @@
|
|||||||
1.0f, 1.0f,
|
1.0f, 1.0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (_offscreenBufferHandle == 0)
|
if (_offscreenBufferHandle == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (pixelBuffer == NULL)
|
if (pixelBuffer == NULL) {
|
||||||
return NULL;
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
const CMVideoDimensions srcDimensions = { (int32_t)CVPixelBufferGetWidth(pixelBuffer), (int32_t)CVPixelBufferGetHeight(pixelBuffer) };
|
const CMVideoDimensions srcDimensions = { (int32_t)CVPixelBufferGetWidth(pixelBuffer.buffer), (int32_t)CVPixelBufferGetHeight(pixelBuffer.buffer) };
|
||||||
const CMVideoDimensions dstDimensions = CMVideoFormatDescriptionGetDimensions(_outputFormatDescription);
|
const CMVideoDimensions dstDimensions = CMVideoFormatDescriptionGetDimensions(_outputFormatDescription);
|
||||||
|
|
||||||
EAGLContext *oldContext = [EAGLContext currentContext];
|
EAGLContext *oldContext = [EAGLContext currentContext];
|
||||||
@ -237,35 +281,72 @@
|
|||||||
CVOpenGLESTextureRef srcTexture = NULL;
|
CVOpenGLESTextureRef srcTexture = NULL;
|
||||||
CVOpenGLESTextureRef prevTexture = NULL;
|
CVOpenGLESTextureRef prevTexture = NULL;
|
||||||
CVOpenGLESTextureRef dstTexture = NULL;
|
CVOpenGLESTextureRef dstTexture = NULL;
|
||||||
CVPixelBufferRef dstPixelBuffer = NULL;
|
CVPixelBufferRef dstPixelBufferValue = NULL;
|
||||||
|
|
||||||
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, srcDimensions.width, srcDimensions.height, GL_BGRA, GL_UNSIGNED_BYTE, 0, &srcTexture);
|
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, pixelBuffer.buffer, NULL, GL_TEXTURE_2D, GL_RGBA, srcDimensions.width, srcDimensions.height, GL_BGRA, GL_UNSIGNED_BYTE, 0, &srcTexture);
|
||||||
|
|
||||||
if (!srcTexture || err)
|
if (!srcTexture || err) {
|
||||||
goto bail;
|
if (oldContext != _context) {
|
||||||
|
[EAGLContext setCurrentContext:oldContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcTexture) {
|
||||||
|
CFRelease(srcTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevTexture) {
|
||||||
|
CFRelease(prevTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstTexture) {
|
||||||
|
CFRelease(dstTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasPreviousTexture = false;
|
bool hasPreviousTexture = false;
|
||||||
if (_previousPixelBuffer != NULL)
|
if (_previousPixelBuffer != NULL)
|
||||||
{
|
{
|
||||||
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _prevTextureCache, _previousPixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, srcDimensions.width, srcDimensions.height, GL_BGRA, GL_UNSIGNED_BYTE, 0, &prevTexture);
|
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _prevTextureCache, _previousPixelBuffer.buffer, NULL, GL_TEXTURE_2D, GL_RGBA, srcDimensions.width, srcDimensions.height, GL_BGRA, GL_UNSIGNED_BYTE, 0, &prevTexture);
|
||||||
|
|
||||||
if (!prevTexture || err)
|
if (!prevTexture || err) {
|
||||||
goto bail;
|
if (oldContext != _context) {
|
||||||
|
[EAGLContext setCurrentContext:oldContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcTexture) {
|
||||||
|
CFRelease(srcTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevTexture) {
|
||||||
|
CFRelease(prevTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dstTexture) {
|
||||||
|
CFRelease(dstTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
hasPreviousTexture = true;
|
hasPreviousTexture = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, _bufferPool, _bufferPoolAuxAttributes, &dstPixelBuffer);
|
err = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, _bufferPool.pool, _bufferPoolAuxAttributes, &dstPixelBufferValue);
|
||||||
if (err == kCVReturnWouldExceedAllocationThreshold)
|
if (err == kCVReturnWouldExceedAllocationThreshold) {
|
||||||
{
|
|
||||||
CVOpenGLESTextureCacheFlush(_renderTextureCache, 0);
|
CVOpenGLESTextureCacheFlush(_renderTextureCache, 0);
|
||||||
err = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, _bufferPool, _bufferPoolAuxAttributes, &dstPixelBuffer);
|
err = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, _bufferPool.pool, _bufferPoolAuxAttributes, &dstPixelBufferValue);
|
||||||
|
}
|
||||||
|
TGVideoCameraRendererBuffer *dstPixelBuffer = nil;
|
||||||
|
if (dstPixelBufferValue) {
|
||||||
|
dstPixelBuffer = [[TGVideoCameraRendererBuffer alloc] initWithRetainedBuffer:dstPixelBufferValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto bail;
|
goto bail;
|
||||||
|
|
||||||
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _renderTextureCache, dstPixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, dstDimensions.width, dstDimensions.height, GL_BGRA, GL_UNSIGNED_BYTE, 0, &dstTexture);
|
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _renderTextureCache, dstPixelBuffer.buffer, NULL, GL_TEXTURE_2D, GL_RGBA, dstDimensions.width, dstDimensions.height, GL_BGRA, GL_UNSIGNED_BYTE, 0, &dstTexture);
|
||||||
|
|
||||||
if (!dstTexture || err)
|
if (!dstTexture || err)
|
||||||
goto bail;
|
goto bail;
|
||||||
@ -388,7 +469,10 @@ bail:
|
|||||||
_noMirrorUniform = [_shader uniformForKey:@"noMirror"];
|
_noMirrorUniform = [_shader uniformForKey:@"noMirror"];
|
||||||
|
|
||||||
size_t maxRetainedBufferCount = clientRetainedBufferCountHint + 1;
|
size_t maxRetainedBufferCount = clientRetainedBufferCountHint + 1;
|
||||||
_bufferPool = [TGVideoCameraGLRenderer createPixelBufferPoolWithWidth:(int32_t)outputSize.width height:(int32_t)outputSize.height pixelFormat:kCVPixelFormatType_32BGRA maxBufferCount:(int32_t)maxRetainedBufferCount];
|
CVPixelBufferPoolRef bufferPoolValue = [TGVideoCameraGLRenderer createPixelBufferPoolWithWidth:(int32_t)outputSize.width height:(int32_t)outputSize.height pixelFormat:kCVPixelFormatType_32BGRA maxBufferCount:(int32_t)maxRetainedBufferCount];
|
||||||
|
if (bufferPoolValue) {
|
||||||
|
_bufferPool = [[TGVideoCameraGLRendererBufferPool alloc] initWithRetainedPool:bufferPoolValue];
|
||||||
|
}
|
||||||
|
|
||||||
if (!_bufferPool)
|
if (!_bufferPool)
|
||||||
{
|
{
|
||||||
@ -397,11 +481,11 @@ bail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
_bufferPoolAuxAttributes = [TGVideoCameraGLRenderer createPixelBufferPoolAuxAttribute:(int32_t)maxRetainedBufferCount];
|
_bufferPoolAuxAttributes = [TGVideoCameraGLRenderer createPixelBufferPoolAuxAttribute:(int32_t)maxRetainedBufferCount];
|
||||||
[TGVideoCameraGLRenderer preallocatePixelBuffersInPool:_bufferPool auxAttributes:_bufferPoolAuxAttributes];
|
[TGVideoCameraGLRenderer preallocatePixelBuffersInPool:_bufferPool.pool auxAttributes:_bufferPoolAuxAttributes];
|
||||||
|
|
||||||
CMFormatDescriptionRef outputFormatDescription = NULL;
|
CMFormatDescriptionRef outputFormatDescription = NULL;
|
||||||
CVPixelBufferRef testPixelBuffer = NULL;
|
CVPixelBufferRef testPixelBuffer = NULL;
|
||||||
CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, _bufferPool, _bufferPoolAuxAttributes, &testPixelBuffer);
|
CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(kCFAllocatorDefault, _bufferPool.pool, _bufferPoolAuxAttributes, &testPixelBuffer);
|
||||||
if (!testPixelBuffer)
|
if (!testPixelBuffer)
|
||||||
{
|
{
|
||||||
success = false;
|
success = false;
|
||||||
@ -460,11 +544,7 @@ bail:
|
|||||||
_renderTextureCache = 0;
|
_renderTextureCache = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_bufferPool)
|
_bufferPool = nil;
|
||||||
{
|
|
||||||
CFRelease(_bufferPool);
|
|
||||||
_bufferPool = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_bufferPoolAuxAttributes)
|
if (_bufferPoolAuxAttributes)
|
||||||
{
|
{
|
||||||
@ -525,3 +605,5 @@ bail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#import <LegacyComponents/TGPaintShader.h>
|
#import <LegacyComponents/TGPaintShader.h>
|
||||||
|
|
||||||
#import "LegacyComponentsInternal.h"
|
#import "LegacyComponentsInternal.h"
|
||||||
|
#import "TGVideoCameraPipeline.h"
|
||||||
|
|
||||||
@interface TGVideoCameraGLView ()
|
@interface TGVideoCameraGLView ()
|
||||||
{
|
{
|
||||||
@ -134,7 +135,7 @@ bail:
|
|||||||
[self reset];
|
[self reset];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)displayPixelBuffer:(CVPixelBufferRef)pixelBuffer
|
- (void)displayPixelBuffer:(TGVideoCameraRendererBuffer *)pixelBuffer
|
||||||
{
|
{
|
||||||
static const GLfloat squareVertices[] =
|
static const GLfloat squareVertices[] =
|
||||||
{
|
{
|
||||||
@ -161,10 +162,10 @@ bail:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t frameWidth = CVPixelBufferGetWidth(pixelBuffer);
|
size_t frameWidth = CVPixelBufferGetWidth(pixelBuffer.buffer);
|
||||||
size_t frameHeight = CVPixelBufferGetHeight(pixelBuffer);
|
size_t frameHeight = CVPixelBufferGetHeight(pixelBuffer.buffer);
|
||||||
CVOpenGLESTextureRef texture = NULL;
|
CVOpenGLESTextureRef texture = NULL;
|
||||||
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, pixelBuffer, NULL, GL_TEXTURE_2D, GL_RGBA, (GLsizei)frameWidth, (GLsizei)frameHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture);
|
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, pixelBuffer.buffer, NULL, GL_TEXTURE_2D, GL_RGBA, (GLsizei)frameWidth, (GLsizei)frameHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture);
|
||||||
|
|
||||||
if (!texture || err)
|
if (!texture || err)
|
||||||
return;
|
return;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#import "TGVideoCameraMovieRecorder.h"
|
#import "TGVideoCameraMovieRecorder.h"
|
||||||
#import <AVFoundation/AVFoundation.h>
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
|
#import "TGVideoCameraPipeline.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TGMovieRecorderStatusIdle = 0,
|
TGMovieRecorderStatusIdle = 0,
|
||||||
TGMovieRecorderStatusPreparingToRecord,
|
TGMovieRecorderStatusPreparingToRecord,
|
||||||
@ -146,7 +148,7 @@ typedef enum {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)appendVideoPixelBuffer:(CVPixelBufferRef)pixelBuffer withPresentationTime:(CMTime)presentationTime
|
- (void)appendVideoPixelBuffer:(TGVideoCameraRendererBuffer *)pixelBuffer withPresentationTime:(CMTime)presentationTime
|
||||||
{
|
{
|
||||||
CMSampleBufferRef sampleBuffer = NULL;
|
CMSampleBufferRef sampleBuffer = NULL;
|
||||||
|
|
||||||
@ -155,7 +157,7 @@ typedef enum {
|
|||||||
timingInfo.decodeTimeStamp = kCMTimeInvalid;
|
timingInfo.decodeTimeStamp = kCMTimeInvalid;
|
||||||
timingInfo.presentationTimeStamp = presentationTime;
|
timingInfo.presentationTimeStamp = presentationTime;
|
||||||
|
|
||||||
CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, true, NULL, NULL, _videoTrackSourceFormatDescription, &timingInfo, &sampleBuffer);
|
CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer.buffer, true, NULL, NULL, _videoTrackSourceFormatDescription, &timingInfo, &sampleBuffer);
|
||||||
|
|
||||||
if (sampleBuffer)
|
if (sampleBuffer)
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,13 @@
|
|||||||
|
|
||||||
@protocol TGVideoCameraPipelineDelegate;
|
@protocol TGVideoCameraPipelineDelegate;
|
||||||
|
|
||||||
|
@interface TGVideoCameraRendererBuffer : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic, assign) CVPixelBufferRef buffer;
|
||||||
|
|
||||||
|
- (instancetype)initWithRetainedBuffer:(CVPixelBufferRef)buffer;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface TGVideoCameraPipeline : NSObject
|
@interface TGVideoCameraPipeline : NSObject
|
||||||
|
|
||||||
@ -40,7 +47,7 @@
|
|||||||
|
|
||||||
- (void)capturePipeline:(TGVideoCameraPipeline *)capturePipeline didStopRunningWithError:(NSError *)error;
|
- (void)capturePipeline:(TGVideoCameraPipeline *)capturePipeline didStopRunningWithError:(NSError *)error;
|
||||||
|
|
||||||
- (void)capturePipeline:(TGVideoCameraPipeline *)capturePipeline previewPixelBufferReadyForDisplay:(CVPixelBufferRef)previewPixelBuffer;
|
- (void)capturePipeline:(TGVideoCameraPipeline *)capturePipeline previewPixelBufferReadyForDisplay:(TGVideoCameraRendererBuffer *)previewPixelBuffer;
|
||||||
- (void)capturePipelineDidRunOutOfPreviewBuffers:(TGVideoCameraPipeline *)capturePipeline;
|
- (void)capturePipelineDidRunOutOfPreviewBuffers:(TGVideoCameraPipeline *)capturePipeline;
|
||||||
|
|
||||||
- (void)capturePipelineRecordingDidStart:(TGVideoCameraPipeline *)capturePipeline;
|
- (void)capturePipelineRecordingDidStart:(TGVideoCameraPipeline *)capturePipeline;
|
||||||
|
@ -57,7 +57,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
|
|
||||||
NSTimeInterval _resultDuration;
|
NSTimeInterval _resultDuration;
|
||||||
|
|
||||||
CVPixelBufferRef _previousPixelBuffer;
|
TGVideoCameraRendererBuffer *_previousPixelBuffer;
|
||||||
int32_t _repeatingCount;
|
int32_t _repeatingCount;
|
||||||
|
|
||||||
int16_t _micLevelPeak;
|
int16_t _micLevelPeak;
|
||||||
@ -72,7 +72,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
os_unfair_lock _recordLock;
|
os_unfair_lock _recordLock;
|
||||||
bool _startRecordAfterAudioBuffer;
|
bool _startRecordAfterAudioBuffer;
|
||||||
|
|
||||||
CVPixelBufferRef _currentPreviewPixelBuffer;
|
TGVideoCameraRendererBuffer *_currentPreviewPixelBuffer;
|
||||||
NSMutableDictionary *_thumbnails;
|
NSMutableDictionary *_thumbnails;
|
||||||
|
|
||||||
NSTimeInterval _firstThumbnailTime;
|
NSTimeInterval _firstThumbnailTime;
|
||||||
@ -332,13 +332,10 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
self.outputVideoFormatDescription = NULL;
|
self.outputVideoFormatDescription = NULL;
|
||||||
|
|
||||||
[_renderer reset];
|
[_renderer reset];
|
||||||
|
|
||||||
if (_currentPreviewPixelBuffer != NULL)
|
_currentPreviewPixelBuffer = nil;
|
||||||
{
|
|
||||||
CFRelease(_currentPreviewPixelBuffer);
|
|
||||||
_currentPreviewPixelBuffer = NULL;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,23 +437,23 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIImage *)imageFromImageBuffer:(CVPixelBufferRef)imageBuffer
|
- (UIImage *)imageFromImageBuffer:(TGVideoCameraRendererBuffer *)imageBuffer
|
||||||
{
|
{
|
||||||
CVPixelBufferLockBaseAddress(imageBuffer, 0);
|
CVPixelBufferLockBaseAddress(imageBuffer.buffer, 0);
|
||||||
|
|
||||||
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
|
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer.buffer);
|
||||||
|
|
||||||
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
|
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer.buffer);
|
||||||
|
|
||||||
size_t width = CVPixelBufferGetWidth(imageBuffer);
|
size_t width = CVPixelBufferGetWidth(imageBuffer.buffer);
|
||||||
size_t height = CVPixelBufferGetHeight(imageBuffer);
|
size_t height = CVPixelBufferGetHeight(imageBuffer.buffer);
|
||||||
|
|
||||||
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
||||||
|
|
||||||
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
|
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
|
||||||
|
|
||||||
CGImageRef cgImage = CGBitmapContextCreateImage(context);
|
CGImageRef cgImage = CGBitmapContextCreateImage(context);
|
||||||
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
|
CVPixelBufferUnlockBaseAddress(imageBuffer.buffer, 0);
|
||||||
|
|
||||||
CGContextRelease(context);
|
CGContextRelease(context);
|
||||||
CGColorSpaceRelease(colorSpace);
|
CGColorSpaceRelease(colorSpace);
|
||||||
@ -470,7 +467,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
|
|
||||||
- (void)renderVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
- (void)renderVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
{
|
{
|
||||||
CVPixelBufferRef renderedPixelBuffer = NULL;
|
TGVideoCameraRendererBuffer *renderedPixelBuffer = nil;
|
||||||
CMTime timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
|
CMTime timestamp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
|
||||||
|
|
||||||
@synchronized (_renderer)
|
@synchronized (_renderer)
|
||||||
@ -486,8 +483,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
_repeatingCount = 11;
|
_repeatingCount = 11;
|
||||||
|
|
||||||
[_renderer setPreviousPixelBuffer:_previousPixelBuffer];
|
[_renderer setPreviousPixelBuffer:_previousPixelBuffer];
|
||||||
CFRelease(_previousPixelBuffer);
|
_previousPixelBuffer = nil;
|
||||||
_previousPixelBuffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_repeatingCount > 0)
|
if (_repeatingCount > 0)
|
||||||
@ -506,7 +502,11 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
[_renderer setPreviousPixelBuffer:NULL];
|
[_renderer setPreviousPixelBuffer:NULL];
|
||||||
}
|
}
|
||||||
|
|
||||||
CVPixelBufferRef sourcePixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
|
CVPixelBufferRef sourcePixelBufferValue = CMSampleBufferGetImageBuffer(sampleBuffer);
|
||||||
|
TGVideoCameraRendererBuffer *sourcePixelBuffer = nil;
|
||||||
|
if (sourcePixelBufferValue) {
|
||||||
|
sourcePixelBuffer = [[TGVideoCameraRendererBuffer alloc] initWithRetainedBuffer:CVPixelBufferRetain(sourcePixelBufferValue)];
|
||||||
|
}
|
||||||
renderedPixelBuffer = [_renderer copyRenderedPixelBuffer:sourcePixelBuffer];
|
renderedPixelBuffer = [_renderer copyRenderedPixelBuffer:sourcePixelBuffer];
|
||||||
|
|
||||||
@synchronized (self)
|
@synchronized (self)
|
||||||
@ -542,14 +542,11 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
|
|
||||||
if (!repeatingFrames)
|
if (!repeatingFrames)
|
||||||
{
|
{
|
||||||
if (_previousPixelBuffer != NULL)
|
if (_previousPixelBuffer != NULL) {
|
||||||
{
|
|
||||||
CFRelease(_previousPixelBuffer);
|
|
||||||
_previousPixelBuffer = NULL;
|
_previousPixelBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_previousPixelBuffer = sourcePixelBuffer;
|
_previousPixelBuffer = sourcePixelBuffer;
|
||||||
CFRetain(sourcePixelBuffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -568,8 +565,6 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
if (_recordingStatus == TGVideoCameraRecordingStatusRecording)
|
if (_recordingStatus == TGVideoCameraRecordingStatusRecording)
|
||||||
[_recorder appendVideoPixelBuffer:renderedPixelBuffer withPresentationTime:timestamp];
|
[_recorder appendVideoPixelBuffer:renderedPixelBuffer withPresentationTime:timestamp];
|
||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(renderedPixelBuffer);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -577,33 +572,27 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)outputPreviewPixelBuffer:(CVPixelBufferRef)previewPixelBuffer
|
- (void)outputPreviewPixelBuffer:(TGVideoCameraRendererBuffer *)previewPixelBuffer
|
||||||
{
|
{
|
||||||
if (_currentPreviewPixelBuffer != NULL)
|
if (_currentPreviewPixelBuffer != NULL)
|
||||||
{
|
{
|
||||||
CFRelease(_currentPreviewPixelBuffer);
|
|
||||||
_currentPreviewPixelBuffer = NULL;
|
_currentPreviewPixelBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_previousPixelBuffer != NULL)
|
if (_previousPixelBuffer != NULL)
|
||||||
{
|
{
|
||||||
_currentPreviewPixelBuffer = previewPixelBuffer;
|
_currentPreviewPixelBuffer = previewPixelBuffer;
|
||||||
CFRetain(_currentPreviewPixelBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[self invokeDelegateCallbackAsync:^
|
[self invokeDelegateCallbackAsync:^
|
||||||
{
|
{
|
||||||
CVPixelBufferRef currentPreviewPixelBuffer = NULL;
|
TGVideoCameraRendererBuffer *currentPreviewPixelBuffer = nil;
|
||||||
@synchronized (self)
|
@synchronized (self)
|
||||||
{
|
{
|
||||||
currentPreviewPixelBuffer = _currentPreviewPixelBuffer;
|
currentPreviewPixelBuffer = _currentPreviewPixelBuffer;
|
||||||
if (currentPreviewPixelBuffer != NULL)
|
if (currentPreviewPixelBuffer != NULL) {
|
||||||
{
|
if (_currentPreviewPixelBuffer != NULL) {
|
||||||
CFRetain(currentPreviewPixelBuffer);
|
_currentPreviewPixelBuffer = nil;
|
||||||
if (_currentPreviewPixelBuffer != NULL)
|
|
||||||
{
|
|
||||||
CFRelease(_currentPreviewPixelBuffer);
|
|
||||||
_currentPreviewPixelBuffer = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -611,7 +600,6 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
if (currentPreviewPixelBuffer != NULL)
|
if (currentPreviewPixelBuffer != NULL)
|
||||||
{
|
{
|
||||||
[_delegate capturePipeline:self previewPixelBufferReadyForDisplay:currentPreviewPixelBuffer];
|
[_delegate capturePipeline:self previewPixelBufferReadyForDisplay:currentPreviewPixelBuffer];
|
||||||
CFRelease(currentPreviewPixelBuffer);
|
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -1273,7 +1273,7 @@ typedef enum
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)capturePipeline:(TGVideoCameraPipeline *)__unused capturePipeline previewPixelBufferReadyForDisplay:(CVPixelBufferRef)previewPixelBuffer
|
- (void)capturePipeline:(TGVideoCameraPipeline *)__unused capturePipeline previewPixelBufferReadyForDisplay:(TGVideoCameraRendererBuffer *)previewPixelBuffer
|
||||||
{
|
{
|
||||||
if (!_gpuAvailable)
|
if (!_gpuAvailable)
|
||||||
return;
|
return;
|
||||||
|
@ -132,6 +132,10 @@ static inline int writeOggPage(ogg_page *page, TGDataItem *fileItem)
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[self cleanup];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)cleanup
|
- (void)cleanup
|
||||||
{
|
{
|
||||||
if (_encoder != NULL)
|
if (_encoder != NULL)
|
||||||
|
@ -3241,7 +3241,20 @@ final class PostboxImpl {
|
|||||||
let disposable = signal.start(next: { next in
|
let disposable = signal.start(next: { next in
|
||||||
subscriber.putNext((next.0, next.1, nil))
|
subscriber.putNext((next.0, next.1, nil))
|
||||||
})
|
})
|
||||||
return ActionDisposable { [weak self] in
|
|
||||||
|
final class MarkedActionDisposable: Disposable {
|
||||||
|
let disposable: ActionDisposable
|
||||||
|
|
||||||
|
init(_ f: @escaping () -> Void) {
|
||||||
|
self.disposable = ActionDisposable(action: f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func dispose() {
|
||||||
|
self.disposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MarkedActionDisposable { [weak self] in
|
||||||
disposable.dispose()
|
disposable.dispose()
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.queue.justDispatch {
|
strongSelf.queue.justDispatch {
|
||||||
@ -4268,7 +4281,7 @@ public class Postbox {
|
|||||||
).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion))
|
).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion))
|
||||||
}
|
}
|
||||||
|
|
||||||
return disposable
|
return disposable.strict()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4306,7 +4319,7 @@ public class Postbox {
|
|||||||
).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion))
|
).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion))
|
||||||
}
|
}
|
||||||
|
|
||||||
return disposable
|
return disposable.strict()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4346,7 +4359,7 @@ public class Postbox {
|
|||||||
).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion))
|
).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion))
|
||||||
}
|
}
|
||||||
|
|
||||||
return disposable
|
return disposable.strict()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +84,9 @@ final class ViewTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func removeMessageHistoryView(index: Bag<(MutableMessageHistoryView, ValuePipe<(MessageHistoryView, ViewUpdateType)>)>.Index) {
|
func removeMessageHistoryView(index: Bag<(MutableMessageHistoryView, ValuePipe<(MessageHistoryView, ViewUpdateType)>)>.Index) {
|
||||||
|
#if DEBUG
|
||||||
|
assert(self.messageHistoryViews.get(index) != nil)
|
||||||
|
#endif
|
||||||
self.messageHistoryViews.remove(index)
|
self.messageHistoryViews.remove(index)
|
||||||
|
|
||||||
self.updateTrackedHoles()
|
self.updateTrackedHoles()
|
||||||
|
@ -191,10 +191,22 @@ private final class MultipartUploadManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
let uploadingParts = self.uploadingParts
|
||||||
|
let dataDisposable = self.dataDisposable
|
||||||
|
|
||||||
|
self.queue.async {
|
||||||
|
for (_, (_, disposable)) in uploadingParts {
|
||||||
|
disposable.dispose()
|
||||||
|
}
|
||||||
|
dataDisposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
self.queue.async {
|
self.queue.async {
|
||||||
self.dataDisposable.set((self.dataSignal
|
self.dataDisposable.set((self.dataSignal
|
||||||
|> deliverOn(self.queue)).start(next: { [weak self] data in
|
|> deliverOn(self.queue)).startStrict(next: { [weak self] data in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.resourceData = data
|
strongSelf.resourceData = data
|
||||||
strongSelf.checkState()
|
strongSelf.checkState()
|
||||||
@ -276,11 +288,11 @@ private final class MultipartUploadManager {
|
|||||||
self.headerPartState = .uploading
|
self.headerPartState = .uploading
|
||||||
let part = self.uploadPart(UploadPart(fileId: self.fileId, index: partIndex, data: partData, bigTotalParts: currentBigTotalParts, bigPart: self.bigParts))
|
let part = self.uploadPart(UploadPart(fileId: self.fileId, index: partIndex, data: partData, bigTotalParts: currentBigTotalParts, bigPart: self.bigParts))
|
||||||
|> deliverOn(self.queue)
|
|> deliverOn(self.queue)
|
||||||
self.uploadingParts[0] = (partSize, part.start(error: { [weak self] _ in
|
self.uploadingParts[0] = (partSize, part.startStrict(error: { [weak self] _ in
|
||||||
self?.completed(nil)
|
self?.completed(nil)
|
||||||
}, completed: { [weak self] in
|
}, completed: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let _ = strongSelf.uploadingParts.removeValue(forKey: 0)
|
strongSelf.uploadingParts.removeValue(forKey: 0)?.1.dispose()
|
||||||
strongSelf.headerPartState = .ready
|
strongSelf.headerPartState = .ready
|
||||||
strongSelf.checkState()
|
strongSelf.checkState()
|
||||||
}
|
}
|
||||||
@ -350,11 +362,11 @@ private final class MultipartUploadManager {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.uploadingParts[nextOffset] = (partSize, part.start(error: { [weak self] _ in
|
self.uploadingParts[nextOffset] = (partSize, part.startStrict(error: { [weak self] _ in
|
||||||
self?.completed(nil)
|
self?.completed(nil)
|
||||||
}, completed: { [weak self] in
|
}, completed: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let _ = strongSelf.uploadingParts.removeValue(forKey: nextOffset)
|
strongSelf.uploadingParts.removeValue(forKey: nextOffset)?.1.dispose()
|
||||||
strongSelf.uploadedParts[partOffset] = partSize
|
strongSelf.uploadedParts[partOffset] = partSize
|
||||||
if partIndex == 0 {
|
if partIndex == 0 {
|
||||||
strongSelf.headerPartState = .ready
|
strongSelf.headerPartState = .ready
|
||||||
|
@ -1515,7 +1515,6 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
if !buildConfig.isAppStoreBuild {
|
if !buildConfig.isAppStoreBuild {
|
||||||
if value >= 2000 * 1024 * 1024 {
|
if value >= 2000 * 1024 * 1024 {
|
||||||
if self.contextValue?.context.sharedContext.immediateExperimentalUISettings.crashOnMemoryPressure == true {
|
if self.contextValue?.context.sharedContext.immediateExperimentalUISettings.crashOnMemoryPressure == true {
|
||||||
preconditionFailure()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ private final class PeerChannelMemberCategoriesContextsManagerImpl {
|
|||||||
self.profileDataPreloadContexts[peerId] = context
|
self.profileDataPreloadContexts[peerId] = context
|
||||||
|
|
||||||
if let customData = customData {
|
if let customData = customData {
|
||||||
disposable.add(customData.start())
|
disposable.add(customData.startStrict())
|
||||||
}
|
}
|
||||||
|
|
||||||
/*disposable.set(signal.start(next: { [weak context] value in
|
/*disposable.set(signal.start(next: { [weak context] value in
|
||||||
@ -195,7 +195,7 @@ private final class PeerChannelMemberCategoriesContextsManagerImpl {
|
|||||||
current.subscribers.remove(index)
|
current.subscribers.remove(index)
|
||||||
if current.subscribers.isEmpty {
|
if current.subscribers.isEmpty {
|
||||||
if current.emptyTimer == nil {
|
if current.emptyTimer == nil {
|
||||||
let timer = SwiftSignalKit.Timer(timeout: 60.0, repeat: false, completion: { [weak context] in
|
let timer = SwiftSignalKit.Timer(timeout: 1.0, repeat: false, completion: { [weak context] in
|
||||||
if let current = strongSelf.profileDataPreloadContexts[peerId], let context = context, current === context {
|
if let current = strongSelf.profileDataPreloadContexts[peerId], let context = context, current === context {
|
||||||
if current.subscribers.isEmpty {
|
if current.subscribers.isEmpty {
|
||||||
strongSelf.profileDataPreloadContexts.removeValue(forKey: peerId)
|
strongSelf.profileDataPreloadContexts.removeValue(forKey: peerId)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user