У меня есть приложение для воспроизведения видео, которое ничего не отображает в AVPlayerLayer
после многократного представления и скрытия модального представления, в котором оно содержится. Если я отклоняю модальное представление, когда это происходит, следующая загрузка обычно отображается нормально (? !!) .Проблема с черным экраном возникает примерно в 20% случаев.
Я строю AVMutableComposition
для создания AVPlayerItem
, но эта ошибка возникает, даже если задействован только один образец.
Проблема также может быть воспроизведена с большим количеством приложений, включающих и выключающих музыку.Я включаю элементы управления музыкой в свое приложение (вместе с простым представлением, отображающим текущую воспроизводимую дорожку iTunes).
Это происходит только в iOS 4. Раньше это происходило и в iOS 5, но когда я начиналперерабатывая представление, содержащее AVPlayerLayer
, все работало нормально.Единственные вещи, которые я не перерабатываю, это AVPlayer
и соответствующий AVPlayerItem.
Вот как я загружаю ресурсы и собираю игрока:
- (void)loadAssetsFromFiles:(id)sender {
NSLog(@"loadAssetsFromFiles called");
assert ([assetURL2clipID count] > 0);
self.isWaitingToLoadAssets = NO;
composition = [AVMutableComposition new];
videoComposition = [AVMutableVideoComposition new];
[self releaseAssets];
//We're going to add this asset to a composition, so we'll need to have random access available
//WARNING: This can cause slow initial loading, so consider loading files later and as needed.
NSDictionary *assetOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
//iterate through the asset urls we know we need to load
for (NSURL *fileURL in [assetURL2clipID allKeys])
{
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:assetOptions];
assert(asset);
//index assets by clipID
[assets setObject:asset forKey:[assetURL2clipID objectForKey:fileURL]];
NSString *tracksKey = @"tracks";
[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler:
^{
NSLog(@"an asset completed loading values for keys.");
NSLog(@"Tracks loaded:");
[asset.tracks enumerateObjectsUsingBlock:
^(AVAssetTrack *obj, NSUInteger index, BOOL *stop)
{
NSLog(@"\n mediaType: %@\n trackID: %d\n", obj.mediaType, obj.trackID);
}];
NSArray *metadata = [asset commonMetadata];
for ( AVMetadataItem* item in metadata ) {
NSString *key = [item commonKey];
NSString *value = [item stringValue];
NSLog(@" metadata key = %@, value = %@", key, value);
}
if (!viewIsActive)
{
NSLog(@"An asset finished loading while the player view was inactive! Did you make sure cancelLoading called on this asset?");
}
// Completion handler block.
NSError *error = nil;
AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error];
if (status == AVKeyValueStatusLoaded && error == nil) {
//if we've loaded all of our assets, it's time to build the composition and prepare the player!
loadedAssets++;
if (loadedAssets == [assets count])
{
CGSize videoSize = [asset naturalSize];
//every video composition needs these set
videoComposition.renderSize = videoSize;
videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps. TODO: Set this to the framerate of one of the assets
//using the assets we've already got
[self buildCompositions];
self.playerItem = [AVPlayerItem playerItemWithAsset:composition];
self.playerItem.videoComposition = videoComposition;
//TODO: Adding observer stuff should be on the main thread to prevent a partial notification from happening
[playerItem addObserver:self forKeyPath:@"status"
options:0 context:&ItemStatusContext];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:playerItem];
self.player = [AVPlayer playerWithPlayerItem:playerItem];
[playerView setPlayer:player];
[self.player addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
self.isObservingPlayerStatus = YES;
}
} else if (error != nil) {
// Deal with the error appropriately.
NSLog(@"WARNING: An asset's tracks were not loaded, so the composition cannot be completed. Error:\n%@\nstatus of asset: %d", [error localizedDescription], status);
}
else
{
//There was no error but we don't know what the problem was.
NSLog(@"WARNING: An asset's tracks were not loaded, so the composition cannot be completed. No error was reported.\nstatus of asset: %d", status);
}
}];
}
}
Эта функция [self buildCompositions]Вы видите, что создает AVVideoComposition
для изменения прозрачности, но я попытался обойти его и получить ту же проблему.
При профилировании программы CoreAnimation сообщает о частоте кадров ~ 45 FPS, когда все работает правильно, и 0-4 FPS, когда пустой экран поднимает свою предположительно уродливую голову.
У этого парня, похоже, была похожая проблема, но для меня переработка просмотров действительно исправляла только вещи для iOS 5: Воспроизведение множества разных видеона iphone с помощью AVPlayer