Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for sending slow motion videos #4541

Merged
merged 8 commits into from
Jul 12, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ Changes to be released in next version
*

🙌 Improvements
* Room Norification Settings: Ability to change between "All Messages", "Mentions and Keywords" and "None". Not yet exposed in Element UI. (#4458).
* Room Notification Settings: Ability to change between "All Messages", "Mentions and Keywords" and "None". Not yet exposed in Element UI. (#4458).
* Add support for sending slow motion videos (#4483).

🐛 Bugfix
* VoIP: Do not present ended calls.
Expand Down
4 changes: 2 additions & 2 deletions Riot/Modules/MediaPicker/MediaPickerCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ extension MediaPickerCoordinator: MediaPickerViewControllerDelegate {
self.delegate?.mediaPickerCoordinator(self, didSelectImageData: imageData, withUTI: uti)
}

func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelectVideo videoURL: URL!) {
self.delegate?.mediaPickerCoordinator(self, didSelectVideoAt: videoURL)
func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelectVideo videoAsset: AVAsset!) {
self.delegate?.mediaPickerCoordinator(self, didSelectVideo: videoAsset)
}

func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelect assets: [PHAsset]!) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Foundation

@objc protocol MediaPickerCoordinatorBridgePresenterDelegate {
func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectImageData imageData: Data, withUTI uti: MXKUTI?)
func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideoAt url: URL)
func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideo videoAsset: AVAsset)
func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectAssets assets: [PHAsset])
func mediaPickerCoordinatorBridgePresenterDidCancel(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter)
}
Expand Down Expand Up @@ -110,8 +110,8 @@ extension MediaPickerCoordinatorBridgePresenter: MediaPickerCoordinatorDelegate
self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectImageData: imageData, withUTI: uti)
}

func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideoAt url: URL) {
self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectVideoAt: url)
func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideo videoAsset: AVAsset) {
self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectVideo: videoAsset)
}

func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectAssets assets: [PHAsset]) {
Expand Down
2 changes: 1 addition & 1 deletion Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Foundation

protocol MediaPickerCoordinatorDelegate: class {
func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectImageData imageData: Data, withUTI uti: MXKUTI?)
func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideoAt url: URL)
func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideo videoAsset: AVAsset)
func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectAssets assets: [PHAsset])
func mediaPickerCoordinatorDidCancel(_ coordinator: MediaPickerCoordinatorType)
}
Expand Down
4 changes: 2 additions & 2 deletions Riot/Modules/MediaPicker/MediaPickerViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
Tells the delegate that the user select a video.

@param mediaPickerController the `MediaPickerViewController` instance.
@param videoURL the local url of the video to send.
@param videoAsset an `AVAsset` that represents the video to send.
*/
- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectVideo:(NSURL*)videoURL;
- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectVideo:(AVAsset*)videoAsset;

/**
Tells the delegate that the user wants to cancel media picking.
Expand Down
39 changes: 15 additions & 24 deletions Riot/Modules/MediaPicker/MediaPickerViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -608,28 +608,19 @@ - (void)didSelectAsset:(PHAsset *)asset

if (asset)
{
if ([asset isKindOfClass:[AVURLAsset class]])
{
MXLogDebug(@"[MediaPickerVC] didSelectAsset: Got AVAsset for video");
AVURLAsset *avURLAsset = (AVURLAsset*)asset;
MXLogDebug(@"[MediaPickerVC] didSelectAsset: Got AVAsset for video");

// Validate first the selected video
[self validateSelectedVideo:asset responseHandler:^(BOOL isValidated) {

if (isValidated)
{
[self.delegate mediaPickerController:self didSelectVideo:asset];
}

// Validate first the selected video
[self validateSelectedVideo:[avURLAsset URL] responseHandler:^(BOOL isValidated) {

if (isValidated)
{
[self.delegate mediaPickerController:self didSelectVideo:[avURLAsset URL]];
}

self->isValidationInProgress = NO;

}];
}
else
{
MXLogDebug(@"[MediaPickerVC] Selected video asset is not initialized from an URL!");
self->isValidationInProgress = NO;
}

}];
}
else
{
Expand Down Expand Up @@ -693,7 +684,7 @@ - (void)validateSelectedImage:(UIImage*)selectedImage responseHandler:(void (^)(
[self setNeedsStatusBarAppearanceUpdate];
}

- (void)validateSelectedVideo:(NSURL*)selectedVideoURL responseHandler:(void (^)(BOOL isValidated))handler
- (void)validateSelectedVideo:(AVAsset*)selectedVideo responseHandler:(void (^)(BOOL isValidated))handler
{
[self dismissImageValidationView];

Expand Down Expand Up @@ -727,15 +718,15 @@ - (void)validateSelectedVideo:(NSURL*)selectedVideoURL responseHandler:(void (^)
videoPlayer = [[AVPlayerViewController alloc] init];
if (videoPlayer)
{
AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:selectedVideo];
videoPlayer.allowsPictureInPicturePlayback = NO;
videoPlayer.updatesNowPlayingInfoCenter = NO;
videoPlayer.player = [AVPlayer playerWithURL:selectedVideoURL];
videoPlayer.player = [AVPlayer playerWithPlayerItem:item];
videoPlayer.videoGravity = AVLayerVideoGravityResizeAspect;
videoPlayer.showsPlaybackControls = NO;

// create a thumbnail for the first frame
AVAsset *asset = [AVAsset assetWithURL:selectedVideoURL];
AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:selectedVideo];
generator.appliesPreferredTrackTransform = YES;
CGImageRef thumbnailRef = [generator copyCGImageAtTime:kCMTimeZero actualTime:nil error:nil];

Expand Down
2 changes: 1 addition & 1 deletion Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ extension SingleImagePickerPresenter: MediaPickerCoordinatorBridgePresenterDeleg
self.delegate?.singleImagePickerPresenter(self, didSelectImageData: imageData, withUTI: uti)
}

func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideoAt url: URL) {
func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideo videoAsset: AVAsset) {
self.delegate?.singleImagePickerPresenterDidCancel(self)
}

Expand Down
4 changes: 3 additions & 1 deletion Riot/Modules/Room/DataSources/RoomDataSource.m
Original file line number Diff line number Diff line change
Expand Up @@ -887,8 +887,10 @@ - (void)sendVideo:(NSURL*)videoLocalURL
success:(void (^)(NSString *eventId))success
failure:(void (^)(NSError *error))failure
{
AVURLAsset *videoAsset = [AVURLAsset assetWithURL:videoLocalURL];
UIImage *videoThumbnail = [MXKVideoThumbnailGenerator.shared generateThumbnailFrom:videoLocalURL];
[self sendVideo:videoLocalURL withThumbnail:videoThumbnail success:success failure:failure];

[self sendVideo:videoAsset withThumbnail:videoThumbnail success:success failure:failure];
}

- (void)acceptVerificationRequestForEventId:(NSString*)eventId success:(void(^)(void))success failure:(void(^)(NSError*))failure
Expand Down
7 changes: 4 additions & 3 deletions Riot/Modules/Room/RoomViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -6056,7 +6056,8 @@ - (void)cameraPresenter:(CameraPresenter *)cameraPresenter didSelectVideoAt:(NSU
RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView];
if (roomInputToolbarView)
{
[roomInputToolbarView sendSelectedVideo:url isPhotoLibraryAsset:NO];
AVURLAsset *selectedVideo = [AVURLAsset assetWithURL:url];
[roomInputToolbarView sendSelectedVideo:selectedVideo isPhotoLibraryAsset:NO];
}
}

Expand All @@ -6080,15 +6081,15 @@ - (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePrese
}
}

- (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePresenter *)coordinatorBridgePresenter didSelectVideoAt:(NSURL *)url
- (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePresenter *)coordinatorBridgePresenter didSelectVideo:(AVAsset *)videoAsset
{
[coordinatorBridgePresenter dismissWithAnimated:YES completion:nil];
self.mediaPickerPresenter = nil;

RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView];
if (roomInputToolbarView)
{
[roomInputToolbarView sendSelectedVideo:url isPhotoLibraryAsset:YES];
[roomInputToolbarView sendSelectedVideo:videoAsset isPhotoLibraryAsset:YES];
}
}

Expand Down
6 changes: 3 additions & 3 deletions RiotShareExtension/Managers/ShareExtensionManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -1165,16 +1165,16 @@ - (void)sendVideo:(NSURL *)videoLocalUrl toRoom:(MXRoom *)room successBlock:(dis
}

// Retrieve the video frame at 1 sec to define the video thumbnail
AVURLAsset *urlAsset = [[AVURLAsset alloc] initWithURL:videoLocalUrl options:nil];
AVAssetImageGenerator *assetImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset];
AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoLocalUrl options:nil];
AVAssetImageGenerator *assetImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:videoAsset];
assetImageGenerator.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMake(1, 1);
CGImageRef imageRef = [assetImageGenerator copyCGImageAtTime:time actualTime:NULL error:nil];
// Finalize video attachment
UIImage *videoThumbnail = [[UIImage alloc] initWithCGImage:imageRef];
CFRelease(imageRef);

[room sendVideo:videoLocalUrl withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) {
[room sendVideoAsset:videoAsset withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) {
if (successBlock)
{
successBlock();
Expand Down