Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions WAVideoBox.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
3B90283821E1FF22001B1497 /* nature.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 3B90283321E1FF22001B1497 /* nature.mp4 */; };
3BCAF55621E72B8000663097 /* test2.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 3BCAF55521E72B8000663097 /* test2.mp4 */; };
3BD923AA21E44D8F007D85B8 /* test1.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 3BD923A921E44D8F007D85B8 /* test1.mp4 */; };
E43E6F47232E27BB0025C062 /* WAAVSECropCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = E43E6F46232E27BA0025C062 /* WAAVSECropCommand.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -103,6 +104,8 @@
3B90283321E1FF22001B1497 /* nature.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = nature.mp4; sourceTree = "<group>"; };
3BCAF55521E72B8000663097 /* test2.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = test2.mp4; sourceTree = "<group>"; };
3BD923A921E44D8F007D85B8 /* test1.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = test1.mp4; sourceTree = "<group>"; };
E43E6F45232E27BA0025C062 /* WAAVSECropCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WAAVSECropCommand.h; sourceTree = "<group>"; };
E43E6F46232E27BA0025C062 /* WAAVSECropCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WAAVSECropCommand.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -201,6 +204,8 @@
3B9027FF21E1F2F3001B1497 /* WAAVSeCommand */ = {
isa = PBXGroup;
children = (
E43E6F45232E27BA0025C062 /* WAAVSECropCommand.h */,
E43E6F46232E27BA0025C062 /* WAAVSECropCommand.m */,
3B90280A21E1F2F3001B1497 /* WAAVSEComposition.h */,
3B90281521E1F2F3001B1497 /* WAAVSEComposition.m */,
3B90280221E1F2F3001B1497 /* WAAVSECommand.h */,
Expand Down Expand Up @@ -387,6 +392,7 @@
3B222FF921E863DC0056CE83 /* WAAVSEExtractSoundCommand.m in Sources */,
3B90282121E1F2F3001B1497 /* WAAVSEReplaceSoundCommand.m in Sources */,
3B9027DB21E1F2E9001B1497 /* main.m in Sources */,
E43E6F47232E27BB0025C062 /* WAAVSECropCommand.m in Sources */,
3B90281B21E1F2F3001B1497 /* WAAVSEGearboxCommand.m in Sources */,
3B90281D21E1F2F3001B1497 /* WAAVSERotateCommand.m in Sources */,
3B9027CD21E1F2E7001B1497 /* AppDelegate.m in Sources */,
Expand Down
21 changes: 21 additions & 0 deletions WAVideoBox/WAVideoBox/WAAVSeCommand/WAAVSECropCommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// WAAVSECropCommand.h
// WAVideoBox
//
// Created by Hallfry on 2019/4/17
// Modified by Hallfry
// Copyright © 2019年 XPLO. All rights reserved.
// 区域裁剪


#import "WAAVSECommand.h"

NS_ASSUME_NONNULL_BEGIN

@interface WAAVSECropCommand : WAAVSECommand

- (void)performWithAsset:(AVAsset *)asset cropRect:(CGRect)cropRect;

@end

NS_ASSUME_NONNULL_END
84 changes: 84 additions & 0 deletions WAVideoBox/WAVideoBox/WAAVSeCommand/WAAVSECropCommand.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// WAAVSECropCommand.m
// WAVideoBox
//
// Created by Hallfry on 2019/4/17
// Modified by Hallfry
// Copyright © 2019年 XPLO. All rights reserved.
//


#import "WAAVSECropCommand.h"


@interface AVAssetTrack(XPAssetTrack)

- (CGAffineTransform)getTransformWithCropRect:(CGRect)cropRect;

@end

@implementation AVAssetTrack(XPAssetTrack)
- (CGAffineTransform)getTransformWithCropRect:(CGRect)cropRect {

CGSize renderSize = cropRect.size;
CGFloat renderScale = renderSize.width / cropRect.size.width;
CGPoint offset = CGPointMake(-cropRect.origin.x, -cropRect.origin.y);
double rotation = atan2(self.preferredTransform.b, self.preferredTransform.a);

CGPoint rotationOffset = CGPointMake(0, 0);
if (self.preferredTransform.b == -1.0) { // 倒着拍 -M_PI_2
rotationOffset.y = self.naturalSize.width;
} else if (self.preferredTransform.c == -1.0) { // 正着拍 M_PI_2
// 奇怪的偏移
rotationOffset.x = self.naturalSize.height;
} else if (self.preferredTransform.a == -1.0) { // 两侧拍 M_PI
rotationOffset.x = self.naturalSize.width;
rotationOffset.y = self.naturalSize.height;
}

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformScale(transform, renderScale, renderScale);
transform = CGAffineTransformTranslate(transform, offset.x + rotationOffset.x, offset.y + rotationOffset.y);
transform = CGAffineTransformRotate(transform, rotation);

return transform;
}

@end


@implementation WAAVSECropCommand

- (void)performWithAsset:(AVAsset *)asset cropRect:(CGRect)cropRect {
[super performWithAsset:asset];

if ([[self.composition.mutableComposition tracksWithMediaType:AVMediaTypeVideo] count] != 0) {

[super performVideoCompopsition];

// 绿边问题,是因为宽或高不是偶数
int64_t renderWidth = round(cropRect.size.width);
int64_t renderHeight = round(cropRect.size.height);
if (renderWidth % 2 != 0) {
renderWidth -= 1;
}
if (renderHeight % 2 != 0) {
renderHeight -= 1;
}

AVMutableVideoCompositionInstruction *instruction = [self.composition.instructions lastObject];
AVMutableVideoCompositionLayerInstruction *layerInstruction = (AVMutableVideoCompositionLayerInstruction *)instruction.layerInstructions[0];

// 获取父类的属性进行方向矫正
// 更安全的话,可以考虑让父类暴露属性
AVAssetTrack *videoTrack = [self valueForKey:@"assetVideoTrack"];

[layerInstruction setTransform:[videoTrack getTransformWithCropRect:cropRect] atTime:kCMTimeZero];
[layerInstruction setOpacity:1.0 atTime:kCMTimeZero];


self.composition.mutableVideoComposition.renderSize = CGSizeMake(renderWidth, renderHeight);
}
}

@end