CALayer.contents не отображается правильно в AVMutableComposition

У меня есть очень простой метод, который генерирует видео со статическим фоновым изображением, которое покрывает всю композицию видео, и меньшим, частично прозрачным изображением (стиль водяного знака), которое 's расположен в нижней части видео.

Фоновое изображение отображается правильно и выглядит точно так же, как выглядит в средстве просмотра изображений. Тем не менее, изображение, котороеПредполагается, что рендеринг внизу видео искажен / искажен.

Исходный код можно скачать здесь, на GitHub.

Ожидаемый вывод моего кода (макет нужного видео выхода):

Фактический вывод моего кода (частичный скриншот из iOS Simulator):

Как вы можете видеть, изображение нижнего колонтитула выглядит искаженным под углом 45 градусов и немного волнистым.

Ниже приведен код, который ям в настоящее время используется для создания видео. Я'Мы испробовали все возможные комбинации содержимого Gravity для изображения нижнего колонтитула, но не повезло. Любой другой пример, который яВидно, просто устанавливает CGImageRef для слояcontents затем устанавливает,boundsposition а такжеanchorPoint к их соответствующим значениям. У меня нетЯ видел другие примеры, которые устанавливают любые другие свойства. Я'Вы прочитали почти всю документацию для AVFoundation, чтобы увидеть, есть ли настройка, что я 'м отсутствует, но у меня нетпока не встречал ничего очевидного.

Любые предложения будут ценны. Спасибо!

Декларации интерфейса:

CGSize _renderingSize;
float _displayDuration;

AVMutableComposition *mutableComposition;
AVMutableVideoComposition *videoComposition;
AVMutableCompositionTrack *mutableCompositionVideoTrack;
AVAssetExportSession *exporter;

Настройки ViewDidLoad:

_renderingSize = CGSizeMake(640, 360);
_displayDuration = 2.0;

Блок кода рендеринга:

    mutableComposition = [AVMutableComposition composition];
    mutableCompositionVideoTrack = [mutableComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];

    videoComposition = [AVMutableVideoComposition videoComposition];
    videoComposition.renderSize = _renderingSize;
    videoComposition.frameDuration = CMTimeMake(1, 30);

    CALayer *parentLayer = [CALayer layer];
    CALayer *videoLayer = [CALayer layer];
    parentLayer.frame = CGRectMake(0, 0, videoComposition.renderSize.width, videoComposition.renderSize.height);
    videoLayer.frame = CGRectMake(0, 0, videoComposition.renderSize.width, videoComposition.renderSize.height);
    [parentLayer addSublayer:videoLayer];

    videoComposition.animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"blank_1080p" ofType:@"mp4"];
    NSURL *url = [NSURL fileURLWithPath:path];
    AVAsset *asset = [AVAsset assetWithURL:url];
    AVAssetTrack *track = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
    [mutableCompositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,CMTimeMakeWithSeconds(_displayDuration, 600)) ofTrack:track atTime:kCMTimeZero error:nil];

    CALayer *imageLayer = [CALayer layer];
    imageLayer.bounds = parentLayer.frame;
    imageLayer.anchorPoint = CGPointMake(0.5, 0.5);
    imageLayer.position = CGPointMake(CGRectGetMidX(imageLayer.bounds), CGRectGetMidY(imageLayer.bounds));
    imageLayer.contents = (id)[UIImage imageNamed:@"background.png"].CGImage;
    imageLayer.contentsGravity = kCAGravityResizeAspectFill;
    [parentLayer addSublayer:imageLayer];

    UIImage *testImage = [UIImage imageNamed:@"bannerTextLayer.png"];

    CALayer *footerLayer = [CALayer layer];
    footerLayer.bounds = CGRectMake(0, 0, 540, 40);
    footerLayer.anchorPoint = CGPointMake(0.5, 0.5);
    footerLayer.position = CGPointMake(CGRectGetMidX(footerLayer.bounds), CGRectGetMidY(footerLayer.bounds));
    footerLayer.contents = (id)testImage.CGImage;
    footerLayer.contentsGravity = kCAGravityResizeAspectFill;
    [parentLayer addSublayer:footerLayer];

    AVMutableVideoCompositionInstruction *instruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(_displayDuration, 600));
    videoComposition.instructions = @[instruction];

    exporter = [[AVAssetExportSession alloc] initWithAsset:mutableComposition presetName:AVAssetExportPresetHighestQuality];
    exporter.outputURL = videoURL ;
    exporter.videoComposition = videoComposition;
    exporter.outputFileType= AVFileTypeMPEG4;
    exporter.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(_displayDuration, 600));
    exporter.shouldOptimizeForNetworkUse = YES;

    [exporter exportAsynchronouslyWithCompletionHandler:^(void){
        switch (exporter.status) {
            case AVAssetExportSessionStatusFailed:{
                NSLog(@"Fail: %@", exporter.error);
                break;
            }
            case AVAssetExportSessionStatusCompleted:{
                NSLog(@"Success");

                dispatch_async(dispatch_get_main_queue(), ^{
                    if (self.moviePlayer)
                        [self.moviePlayer.view removeFromSuperview];

                    self.moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];

                    self.moviePlayer.view.frame = CGRectMake(0, 0, 320, 180);
                    [self.moviePlayer setControlStyle:MPMovieControlStyleNone];

                    [self.previewView addSubview:self.moviePlayer.view];
                    [self.moviePlayer play];

                });

                break;
            }
            default:
                break;
        }
    }];

Ответы на вопрос(1)

Ваш ответ на вопрос