O AVPlayer reproduz o resultado da composição de vídeo incorretamente

Eu preciso de uma coisa simples:reproduzir um vídeo enquanto gira e aplicaCIFilter nele.

Primeiro, eu crio o item do player:

AVPlayerItem *item = [AVPlayerItem playerItemWithURL:videoURL];

// DEBUG LOGGING
AVAssetTrack *track = [[item.asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
NSLog(@"Natural size is: %@", NSStringFromCGSize(track.naturalSize));
NSLog(@"Preffered track transform is: %@", NSStringFromCGAffineTransform(track.preferredTransform));
NSLog(@"Preffered asset transform is: %@", NSStringFromCGAffineTransform(item.asset.preferredTransform));

Então eu preciso aplicar a composição do vídeo. Originalmente, eu estava pensando em criar umAVVideoComposition com 2 instruções - uma será aAVVideoCompositionLayerInstruction para rotação e o outro seráCIFilter inscrição. No entanto, recebi uma exceção dizendo"Esperando que a composição de vídeo contenha apenas AVCoreImageFilterVideoCompositionInstruction" o que significa que a Apple não permite combinar essas duas instruções. Como resultado, eu combinei ambos sob a filtragem, eis o código:

AVAsset *asset = playerItem.asset;
CGAffineTransform rotation = [self transformForItem:playerItem];

AVVideoComposition *composition = [AVVideoComposition videoCompositionWithAsset:asset applyingCIFiltersWithHandler:^(AVAsynchronousCIImageFilteringRequest * _Nonnull request) {
    // Step 1: get the input frame image (screenshot 1)
    CIImage *sourceImage = request.sourceImage;

    // Step 2: rotate the frame
    CIFilter *transformFilter = [CIFilter filterWithName:@"CIAffineTransform"];
    [transformFilter setValue:sourceImage forKey: kCIInputImageKey];
    [transformFilter setValue: [NSValue valueWithCGAffineTransform: rotation] forKey: kCIInputTransformKey];
    sourceImage = transformFilter.outputImage;
    CGRect extent = sourceImage.extent;
    CGAffineTransform translation = CGAffineTransformMakeTranslation(-extent.origin.x, -extent.origin.y);
    [transformFilter setValue:sourceImage forKey: kCIInputImageKey];
    [transformFilter setValue: [NSValue valueWithCGAffineTransform: translation] forKey: kCIInputTransformKey];
    sourceImage = transformFilter.outputImage;

    // Step 3: apply the custom filter chosen by the user
    extent = sourceImage.extent;
    sourceImage = [sourceImage imageByClampingToExtent];
    [filter setValue:sourceImage forKey:kCIInputImageKey];
    sourceImage = filter.outputImage;
    sourceImage = [sourceImage imageByCroppingToRect:extent];

    // Step 4: finish processing the frame (screenshot 2)
    [request finishWithImage:sourceImage context:nil];
}];

playerItem.videoComposition = composition;

As capturas de tela que eu fiz durante a depuração mostram que a imagem é rotacionada com sucesso e o filtro é aplicado (neste exemplo, era um filtro de identidade que não altera a imagem). Aqui estão as capturas de tela 1 e 2 que foram tiradas nos pontos marcados nos comentários acima:

Como você pode ver, a rotação foi bem-sucedida, a extensão do quadro resultante também estava correta.

O problema começa quando tento reproduzir este vídeo em um player. Aqui está o que eu recebo:

Parece que todos os quadros são redimensionados e deslocados para baixo. A área verde é a informação do quadro vazio. Quando aperto de forma a tornar o tamanho infinito do quadro, ele mostra pixels de borda em vez de verde. Sinto que o jogador ainda usa algumas informações de tamanho antigo antes da rotação doAVPlayerItem, é por isso que no primeiro trecho de código acima, eu estava registrando os tamanhos e transformações, existem os logs:

Natural size is: {1920, 1080}
Preffered track transform is: [0, 1, -1, 0, 1080, 0]
Preffered asset transform is: [1, 0, 0, 1, 0, 0]

O player está configurado assim:

layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
layer.needsDisplayOnBoundsChange = YES;

ATENÇÃO O mais importante: isso acontece apenas com vídeos que foram gravados pelo próprio aplicativo usando a câmerana paisagem orientação do iPhone [6s] e salva no armazenamento do dispositivo anteriormente. Os vídeos que o aplicativo grava no modo retrato são totalmente bons (a propósito, os vídeos retrato têm exatamente o mesmo tamanho e transformam o registro como vídeos em paisagem! Estranho ... talvez o iphone coloque as informações de rotação no vídeo e as conserte). Portanto, aplicar zoom e mudar o vídeo parece uma combinação de "preenchimento de aspecto" e informações antigas de resolução antes da rotação. A propósito, os quadros de vídeo retrato são mostrados parcialmente devido ao dimensionamento para preencher a área do player que possui uma proporção diferente, mas esse é o comportamento esperado.

Deixe-me saber sua opinião sobre isso e, se você souber uma maneira melhor de realizar o que eu preciso, seria ótimo saber.

questionAnswers(1)

yourAnswerToTheQuestion