Video editor fixes

This commit is contained in:
Ilya Laktyushin 2020-05-28 03:00:28 +03:00
parent ad4797f244
commit a182f8094f
17 changed files with 768 additions and 278 deletions

View File

@ -5,6 +5,8 @@
@class TGClipboardGalleryPhotoItem;
@protocol TGPhotoPaintStickersContext;
@interface TGClipboardGalleryMixin : NSObject
@property (nonatomic, copy) void (^itemFocused)(TGClipboardGalleryPhotoItem *);
@ -19,7 +21,7 @@
@property (nonatomic, copy) void (^editorOpened)(void);
@property (nonatomic, copy) void (^editorClosed)(void);
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context image:(UIImage *)image images:(NSArray *)images parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer recipientName:(NSString *)recipientName;
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context image:(UIImage *)image images:(NSArray *)images parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer recipientName:(NSString *)recipientName;
- (void)present;

View File

@ -10,10 +10,11 @@
@class TGSuggestionContext;
@protocol TGMediaSelectableItem;
@protocol TGPhotoPaintStickersContext;
@interface TGClipboardMenu : NSObject
+ (TGMenuSheetController *)presentInParentController:(TGViewController *)parentController context:(id<LegacyComponentsContext>)context images:(NSArray *)images hasCaption:(bool)hasCaption hasTimer:(bool)hasTimer recipientName:(NSString *)recipientName suggestionContext:(TGSuggestionContext *)suggestionContext completed:(void (^)(TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id<TGMediaSelectableItem> currentItem))completed dismissed:(void (^)(void))dismissed sourceView:(UIView *)sourceView sourceRect:(CGRect (^)(void))sourceRect;
+ (TGMenuSheetController *)presentInParentController:(TGViewController *)parentController context:(id<LegacyComponentsContext>)context images:(NSArray *)images hasCaption:(bool)hasCaption hasTimer:(bool)hasTimer recipientName:(NSString *)recipientName suggestionContext:(TGSuggestionContext *)suggestionContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext completed:(void (^)(TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id<TGMediaSelectableItem> currentItem))completed dismissed:(void (^)(void))dismissed sourceView:(UIView *)sourceView sourceRect:(CGRect (^)(void))sourceRect;
+ (NSArray *)resultSignalsForSelectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext currentItem:(id<TGMediaSelectableItem>)currentItem descriptionGenerator:(id (^)(id, NSString *, NSArray *, NSString *))descriptionGenerator;

View File

@ -7,7 +7,7 @@
@protocol TGPhotoPaintEntityRenderer <NSObject>
- (void)entitiesForTime:(CMTime)time size:(CGSize)size completion:(void(^)(NSArray<CIImage *> *))completion;
- (void)entitiesForTime:(CMTime)time fps:(NSInteger)fps size:(CGSize)size completion:(void(^)(NSArray<CIImage *> *))completion;
@end

View File

@ -867,6 +867,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
TGPhotoEditorController *controller = [[TGPhotoEditorController alloc] initWithContext:[windowManager context] item:asset intent:_disableStickers ? TGPhotoEditorControllerSignupAvatarIntent : TGPhotoEditorControllerAvatarIntent adjustments:nil caption:nil screenImage:thumbnailImage availableTabs:[TGPhotoEditorController defaultTabsForAvatarIntent] selectedTab:TGPhotoEditorCropTab];
controller.editingContext = _editingContext;
controller.stickersContext = _stickersContext;
controller.dontHideStatusBar = true;
TGMediaAvatarEditorTransition *transition = [[TGMediaAvatarEditorTransition alloc] initWithController:controller fromView:referenceViewForAsset(asset)];

View File

@ -1252,6 +1252,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
model.inhibitMute = self.inhibitMute;
model.controller = galleryController;
model.suggestionContext = self.suggestionContext;
model.stickersContext = self.stickersContext;
__weak TGModernGalleryController *weakGalleryController = galleryController;
__weak TGMediaPickerGalleryModel *weakModel = model;

View File

@ -35,7 +35,7 @@
@implementation TGClipboardGalleryMixin
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context image:(UIImage *)image images:(NSArray *)images parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer recipientName:(NSString *)recipientName
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context image:(UIImage *)image images:(NSArray *)images parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext suggestionContext:(TGSuggestionContext *)suggestionContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer recipientName:(NSString *)recipientName
{
self = [super init];
if (self != nil)
@ -61,7 +61,7 @@
}
}];
TGClipboardGalleryModel *model = [[TGClipboardGalleryModel alloc] initWithContext:_context images:images focusIndex:focusIndex selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions hasTimer:hasTimer hasSelectionPanel:false recipientName:recipientName];
TGClipboardGalleryModel *model = [[TGClipboardGalleryModel alloc] initWithContext:_context images:images focusIndex:focusIndex selectionContext:selectionContext editingContext:editingContext stickersContext:stickersContext hasCaptions:hasCaptions hasTimer:hasTimer hasSelectionPanel:false recipientName:recipientName];
_galleryModel = model;
model.controller = modernGallery;
model.suggestionContext = suggestionContext;

View File

@ -25,7 +25,8 @@
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context images:(NSArray *)images focusIndex:(NSUInteger)focusIndex selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSelectionPanel:(bool)hasSelectionPanel recipientName:(NSString *)recipientName;
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context images:(NSArray *)images focusIndex:(NSUInteger)focusIndex selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSelectionPanel:(bool)hasSelectionPanel recipientName:(NSString *)recipientName;
@end

View File

@ -34,7 +34,7 @@
@implementation TGClipboardGalleryModel
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context images:(NSArray *)images focusIndex:(NSUInteger)focusIndex selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSelectionPanel:(bool)hasSelectionPanel recipientName:(NSString *)recipientName
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context images:(NSArray *)images focusIndex:(NSUInteger)focusIndex selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasCaptions:(bool)hasCaptions hasTimer:(bool)hasTimer hasSelectionPanel:(bool)hasSelectionPanel recipientName:(NSString *)recipientName
{
self = [super init];
if (self != nil)
@ -49,6 +49,7 @@
TGClipboardGalleryPhotoItem *item = [[TGClipboardGalleryPhotoItem alloc] initWithImage:image];
item.selectionContext = selectionContext;
item.editingContext = editingContext;
item.stickersContext = stickersContext;
[items addObject:item];
if (i == focusIndex)
@ -61,6 +62,7 @@
_editingContext = editingContext;
_selectionContext = selectionContext;
_stickersContext = stickersContext;
__weak TGClipboardGalleryModel *weakSelf = self;
if (selectionContext != nil)
@ -322,6 +324,7 @@
TGPhotoEditorControllerIntent intent = isVideo ? TGPhotoEditorControllerVideoIntent : TGPhotoEditorControllerGenericIntent;
TGPhotoEditorController *controller = [[TGPhotoEditorController alloc] initWithContext:_context item:item.editableMediaItem intent:intent adjustments:editorValues caption:caption screenImage:screenImage availableTabs:_interfaceView.currentTabs selectedTab:tab];
controller.editingContext = _editingContext;
controller.stickersContext = _stickersContext;
self.editorController = controller;
controller.suggestionContext = self.suggestionContext;
controller.willFinishEditing = ^(id<TGMediaEditAdjustments> adjustments, id temporaryRep, bool hasChanges)

View File

@ -9,6 +9,7 @@
@synthesize selectionContext;
@synthesize editingContext;
@synthesize stickersContext;
- (instancetype)initWithImage:(UIImage *)image
{

View File

@ -9,7 +9,7 @@
@implementation TGClipboardMenu
+ (TGMenuSheetController *)presentInParentController:(TGViewController *)parentController context:(id<LegacyComponentsContext>)context images:(NSArray *)images hasCaption:(bool)hasCaption hasTimer:(bool)hasTimer recipientName:(NSString *)recipientName suggestionContext:(TGSuggestionContext *)suggestionContext completed:(void (^)(TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id<TGMediaSelectableItem> currentItem))completed dismissed:(void (^)(void))dismissed sourceView:(UIView *)sourceView sourceRect:(CGRect (^)(void))sourceRect
+ (TGMenuSheetController *)presentInParentController:(TGViewController *)parentController context:(id<LegacyComponentsContext>)context images:(NSArray *)images hasCaption:(bool)hasCaption hasTimer:(bool)hasTimer recipientName:(NSString *)recipientName suggestionContext:(TGSuggestionContext *)suggestionContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext completed:(void (^)(TGMediaSelectionContext *selectionContext, TGMediaEditingContext *editingContext, id<TGMediaSelectableItem> currentItem))completed dismissed:(void (^)(void))dismissed sourceView:(UIView *)sourceView sourceRect:(CGRect (^)(void))sourceRect
{
bool centered = false;
if (sourceRect == nil)
@ -41,7 +41,7 @@
TGClipboardPreviewItemView *previewItem = [[TGClipboardPreviewItemView alloc] initWithContext:context images:images];
__weak TGClipboardPreviewItemView *weakPreviewItem = previewItem;
previewItem.stickersContext = stickersContext;
previewItem.suggestionContext = suggestionContext;
previewItem.parentController = parentController;
previewItem.allowCaptions = hasCaption;

View File

@ -4,6 +4,8 @@
@class TGMediaEditingContext;
@class TGSuggestionContext;
@protocol TGPhotoPaintStickersContext;
@interface TGClipboardPreviewItemView : TGMenuSheetItemView
@property (nonatomic, weak) TGViewController *parentController;
@ -15,6 +17,7 @@
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
@property (nonatomic, readonly) TGMediaEditingContext *editingContext;
@property (nonatomic, strong) TGSuggestionContext *suggestionContext;
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
@property (nonatomic, copy) void (^selectionChanged)(NSUInteger);
@property (nonatomic, copy) void (^sendPressed)(UIImage *currentItem);

View File

@ -266,7 +266,7 @@ const CGFloat TGClipboardPreviewEdgeInset = 8.0f;
if ([cell isKindOfClass:[TGClipboardPreviewCell class]])
thumbnailImage = cell.imageView.image;
TGClipboardGalleryMixin *mixin = [[TGClipboardGalleryMixin alloc] initWithContext:_context image:image images:_images parentController:self.parentController thumbnailImage:thumbnailImage selectionContext:_selectionContext editingContext:_editingContext suggestionContext:self.suggestionContext hasCaptions:self.allowCaptions hasTimer:self.hasTimer recipientName:self.recipientName];
TGClipboardGalleryMixin *mixin = [[TGClipboardGalleryMixin alloc] initWithContext:_context image:image images:_images parentController:self.parentController thumbnailImage:thumbnailImage selectionContext:_selectionContext editingContext:_editingContext suggestionContext:self.suggestionContext stickersContext:self.stickersContext hasCaptions:self.allowCaptions hasTimer:self.hasTimer recipientName:self.recipientName];
[self _setupGalleryMixin:mixin];

View File

@ -347,6 +347,17 @@
AVMutableCompositionTrack *trimVideoTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
[trimVideoTrack insertTimeRange:timeRange ofTrack:videoTrack atTime:kCMTimeZero error:NULL];
CMTime frameDuration = CMTimeMake(1, 30);
if (videoTrack.nominalFrameRate > 0)
frameDuration = CMTimeMake(1, (int32_t)videoTrack.nominalFrameRate);
else if (CMTimeCompare(videoTrack.minFrameDuration, kCMTimeZero) == 1)
frameDuration = videoTrack.minFrameDuration;
if (CMTimeCompare(frameDuration, kCMTimeZero) != 1 || !CMTIME_IS_VALID(frameDuration) || image != nil)
frameDuration = CMTimeMake(1, 30);
NSInteger fps = (NSInteger)(1.0 / CMTimeGetSeconds(frameDuration));
UIImage *overlayImage = nil;
if (adjustments.paintingData.imagePath != nil)
overlayImage = [UIImage imageWithContentsOfFile:adjustments.paintingData.imagePath];
@ -390,7 +401,7 @@
}
if (entityRenderer != nil) {
[entityRenderer entitiesForTime:request.compositionTime size:size completion:^(NSArray<CIImage *> *images) {
[entityRenderer entitiesForTime:request.compositionTime fps:fps size:size completion:^(NSArray<CIImage *> *images) {
for (CIImage *image in images) {
resultImage = [image imageByCompositingOverImage:resultImage];
}
@ -417,22 +428,8 @@
instruction.layerInstructions = [NSArray arrayWithObject:transformer];
videoComposition.instructions = [NSArray arrayWithObject:instruction];
}
if (videoTrack.nominalFrameRate > 0)
videoComposition.frameDuration = CMTimeMake(1, (int32_t)videoTrack.nominalFrameRate);
else if (CMTimeCompare(videoTrack.minFrameDuration, kCMTimeZero) == 1)
videoComposition.frameDuration = videoTrack.minFrameDuration;
else
videoComposition.frameDuration = CMTimeMake(1, 30);
if (CMTimeCompare(videoComposition.frameDuration, kCMTimeZero) != 1)
videoComposition.frameDuration = CMTimeMake(1, 30);
if (!CMTIME_IS_VALID(videoComposition.frameDuration))
videoComposition.frameDuration = CMTimeMake(1, 30);
if (image != nil)
videoComposition.frameDuration = CMTimeMake(1, 30);
videoComposition.frameDuration = frameDuration;
videoComposition.renderSize = [self _renderSizeWithCropSize:cropRect.size rotateSideward:TGOrientationIsSideward(adjustments.cropOrientation, NULL)];
if (videoComposition.renderSize.width < FLT_EPSILON || videoComposition.renderSize.height < FLT_EPSILON)

View File

@ -367,7 +367,7 @@ public func legacyMenuPaletteFromTheme(_ theme: PresentationTheme) -> TGMenuShee
return TGMenuSheetPallete(dark: theme.overallDarkAppearance, backgroundColor: sheetTheme.opaqueItemBackgroundColor, selectionColor: sheetTheme.opaqueItemHighlightedBackgroundColor, separatorColor: sheetTheme.opaqueItemSeparatorColor, accentColor: sheetTheme.controlAccentColor, destructiveColor: sheetTheme.destructiveActionTextColor, textColor: sheetTheme.primaryTextColor, secondaryTextColor: sheetTheme.secondaryTextColor, spinnerColor: sheetTheme.secondaryTextColor, badgeTextColor: sheetTheme.controlAccentColor, badgeImage: nil, cornersImage: generateStretchableFilledCircleImage(diameter: 11.0, color: nil, strokeColor: nil, strokeWidth: nil, backgroundColor: sheetTheme.opaqueItemBackgroundColor))
}
public func presentLegacyPasteMenu(context: AccountContext, peer: Peer, saveEditedPhotos: Bool, allowGrouping: Bool, presentationData: PresentationData, images: [UIImage], sendMessagesWithSignals: @escaping ([Any]?) -> Void, present: (ViewController, Any?) -> Void, initialLayout: ContainerViewLayout? = nil) -> ViewController {
public func presentLegacyPasteMenu(context: AccountContext, peer: Peer, saveEditedPhotos: Bool, allowGrouping: Bool, presentationData: PresentationData, images: [UIImage], sendMessagesWithSignals: @escaping ([Any]?) -> Void, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?, present: (ViewController, Any?) -> Void, initialLayout: ContainerViewLayout? = nil) -> ViewController {
let defaultVideoPreset = defaultVideoPresetForContext(context)
UserDefaults.standard.set(defaultVideoPreset.rawValue as NSNumber, forKey: "TG_preferredVideoPreset_v0")
@ -396,7 +396,16 @@ public func presentLegacyPasteMenu(context: AccountContext, peer: Peer, saveEdit
let suggestionContext = legacySuggestionContext(context: context, peerId: peer.id)
let controller = TGClipboardMenu.present(inParentController: emptyController, context: legacyController.context, images: images, hasCaption: true, hasTimer: hasTimer, recipientName: recipientName, suggestionContext: suggestionContext, completed: { selectionContext, editingContext, currentItem in
let paintStickersContext = LegacyPaintStickersContext(context: context)
paintStickersContext.presentStickersController = { completion in
return presentStickers({ file, animated, view, rect in
let coder = PostboxEncoder()
coder.encodeRootObject(file)
completion?(coder.makeData(), animated, view, rect)
})
}
let controller = TGClipboardMenu.present(inParentController: emptyController, context: legacyController.context, images: images, hasCaption: true, hasTimer: hasTimer, recipientName: recipientName, suggestionContext: suggestionContext, stickersContext: paintStickersContext, completed: { selectionContext, editingContext, currentItem in
let signals = TGClipboardMenu.resultSignals(for: selectionContext, editingContext: editingContext, currentItem: currentItem, descriptionGenerator: legacyAssetPickerItemGenerator())
sendMessagesWithSignals(signals)
}, dismissed: { [weak legacyController] in

View File

@ -17,7 +17,7 @@ protocol LegacyPaintEntity {
var baseSize: CGSize? { get }
var mirrored: Bool { get }
func image(for time: CMTime, completion: @escaping (CIImage?) -> Void)
func image(for time: CMTime, fps: Int, completion: @escaping (CIImage?) -> Void)
}
private class LegacyPaintStickerEntity: LegacyPaintEntity {
@ -51,6 +51,9 @@ private class LegacyPaintStickerEntity: LegacyPaintEntity {
var frameSource: AnimatedStickerFrameSource?
var frameQueue: QueueLocalObject<AnimatedStickerFrameQueue>?
var frameCount: Int?
var frameRate: Int?
let queue = Queue()
let disposable = MetaDisposable()
@ -83,6 +86,9 @@ private class LegacyPaintStickerEntity: LegacyPaintEntity {
strongSelf.frameQueue = frameQueue
strongSelf.frameSource = frameSource
strongSelf.frameCount = frameSource.frameCount
strongSelf.frameRate = frameSource.frameRate
strongSelf.durationPromise.set(.single(Double(frameSource.frameCount) / Double(frameSource.frameRate)))
}
}
@ -138,7 +144,7 @@ private class LegacyPaintStickerEntity: LegacyPaintEntity {
}
var cachedCIImage: CIImage?
func image(for time: CMTime, completion: @escaping (CIImage?) -> Void) {
func image(for time: CMTime, fps: Int, completion: @escaping (CIImage?) -> Void) {
if self.animated {
let frameQueue = self.frameQueue
self.queue.async {
@ -208,7 +214,7 @@ private class LegacyPaintTextEntity: LegacyPaintEntity {
}
var cachedCIImage: CIImage?
func image(for time: CMTime, completion: @escaping (CIImage?) -> Void) {
func image(for time: CMTime, fps: Int, completion: @escaping (CIImage?) -> Void) {
var image: CIImage?
if let cachedImage = self.cachedCIImage {
image = cachedImage
@ -281,7 +287,7 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender
}
}
public func entities(for time: CMTime, size: CGSize, completion: (([CIImage]?) -> Void)!) {
public func entities(for time: CMTime, fps: Int, size: CGSize, completion: (([CIImage]?) -> Void)!) {
let entities = self.entities
let maxSide = max(size.width, size.height)
let paintingScale = maxSide / 1920.0
@ -306,7 +312,7 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender
let _ = count.modify { current -> Int in
return current + 1
}
entity.image(for: time, completion: { image in
entity.image(for: time, fps: fps, completion: { image in
if var image = image {
let index = i
var transform = CGAffineTransform(translationX: -image.extent.midX, y: -image.extent.midY)

View File

@ -6951,6 +6951,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.dismissInput()
let _ = presentLegacyPasteMenu(context: strongSelf.context, peer: peer, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true, presentationData: strongSelf.presentationData, images: images, sendMessagesWithSignals: { signals in
self?.enqueueMediaMessages(signals: signals, silentPosting: false)
}, presentStickers: { [weak self] completion in
if let strongSelf = self {
let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in
completion(fileReference.media, fileReference.media.isAnimatedSticker, node.view, rect)
return true
})
strongSelf.present(controller, in: .window(.root))
return controller
} else {
return nil
}
}, present: { [weak self] controller, arguments in
if let strongSelf = self {
strongSelf.present(controller, in: .window(.root), with: arguments)

File diff suppressed because it is too large Load Diff