< prev index next >

modules/javafx.media/src/main/native/jfxmedia/platform/osx/avf/AVFMediaPlayer.mm

Print this page
rev 10028 : 8156563: JavaFX Ensemble8 media sample hang and crash
Reviewed-by: almatvee, kcr

*** 1,7 **** /* ! * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 96,116 **** CVOptionFlags *flagsOut, void *displayLinkContext); + (BOOL) playerAvailable { // Check if AVPlayerItemVideoOutput exists, if not we're running on 10.7 or ! // earlier and have to fall back on QTKit Class klass = objc_getClass("AVPlayerItemVideoOutput"); return (klass != nil); } - (id) initWithURL:(NSURL *)source eventHandler:(CJavaPlayerEventDispatcher*)hdlr { if ((self = [super init]) != nil) { - _audioSyncDelay = 0LL; - _volume = 1.0f; - _balance = 0.0f; - previousWidth = -1; previousHeight = -1; previousPlayerState = kPlayerState_UNKNOWN; eventHandler = hdlr; --- 96,112 ---- CVOptionFlags *flagsOut, void *displayLinkContext); + (BOOL) playerAvailable { // Check if AVPlayerItemVideoOutput exists, if not we're running on 10.7 or ! // earlier which is no longer supported Class klass = objc_getClass("AVPlayerItemVideoOutput"); return (klass != nil); } - (id) initWithURL:(NSURL *)source eventHandler:(CJavaPlayerEventDispatcher*)hdlr { if ((self = [super init]) != nil) { previousWidth = -1; previousHeight = -1; previousPlayerState = kPlayerState_UNKNOWN; eventHandler = hdlr;
*** 121,143 **** // Create our own work queue playerQueue = dispatch_queue_create(NULL, NULL); // Create the player ! _player = [[AVPlayer alloc] init]; if (!_player) { return nil; } _player.volume = 1.0f; _player.muted = NO; - _playerItem = [AVPlayerItem playerItemWithURL:_movieURL]; - if (!_playerItem) { - return nil; - } - [_player replaceCurrentItemWithPlayerItem:_playerItem]; - // Set the player item end action to NONE since we'll handle it internally _player.actionAtItemEnd = AVPlayerActionAtItemEndNone; /* * AVPlayerItem notifications we could listen for: --- 117,133 ---- // Create our own work queue playerQueue = dispatch_queue_create(NULL, NULL); // Create the player ! _player = [AVPlayer playerWithURL:source]; if (!_player) { return nil; } _player.volume = 1.0f; _player.muted = NO; // Set the player item end action to NONE since we'll handle it internally _player.actionAtItemEnd = AVPlayerActionAtItemEndNone; /* * AVPlayerItem notifications we could listen for:
*** 149,176 **** playerObservers = [[NSMutableArray alloc] init]; id<NSObject> observer; __weak AVFMediaPlayer *blockSelf = self; // retain cycle avoidance NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; observer = [center addObserverForName:AVPlayerItemDidPlayToEndTimeNotification ! object:_playerItem queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { // promote FINISHED state... [blockSelf setPlayerState:kPlayerState_FINISHED]; }]; if (observer) { [playerObservers addObject:observer]; } keyPathsObserved = [[NSMutableArray alloc] init]; ! [self observeKeyPath:@"self.playerItem.status" withContext:AVFMediaPlayerItemStatusContext]; ! [self observeKeyPath:@"self.playerItem.duration" withContext:AVFMediaPlayerItemDurationContext]; ! [self observeKeyPath:@"self.playerItem.tracks" withContext:AVFMediaPlayerItemTracksContext]; [self setPlayerState:kPlayerState_UNKNOWN]; --- 139,166 ---- playerObservers = [[NSMutableArray alloc] init]; id<NSObject> observer; __weak AVFMediaPlayer *blockSelf = self; // retain cycle avoidance NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; observer = [center addObserverForName:AVPlayerItemDidPlayToEndTimeNotification ! object:_player.currentItem queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { // promote FINISHED state... [blockSelf setPlayerState:kPlayerState_FINISHED]; }]; if (observer) { [playerObservers addObject:observer]; } keyPathsObserved = [[NSMutableArray alloc] init]; ! [self observeKeyPath:@"self.player.currentItem.status" withContext:AVFMediaPlayerItemStatusContext]; ! [self observeKeyPath:@"self.player.currentItem.duration" withContext:AVFMediaPlayerItemDurationContext]; ! [self observeKeyPath:@"self.player.currentItem.tracks" withContext:AVFMediaPlayerItemTracksContext]; [self setPlayerState:kPlayerState_UNKNOWN];
*** 180,222 **** // Don't create video output until we know we have video _playerOutput = nil; _displayLink = NULL; ! _audioSpectrum = new AVFAudioSpectrumUnit(); ! _audioSpectrum->SetSpectrumCallbackProc(SpectrumCallbackProc, (__bridge void*)self); ! _audioEqualizer = new AVFAudioEqualizer(); } return self; } - (void) dealloc { [self dispose]; self.movieURL = nil; self.player = nil; - self.playerItem = nil; self.playerOutput = nil; - - if (_audioSpectrum) { - delete _audioSpectrum; - _audioSpectrum = NULL; - } - - if (_audioEqualizer) { - delete _audioEqualizer; - _audioEqualizer = NULL; - } } - (CAudioSpectrum*) audioSpectrum { ! return _audioSpectrum; } - (CAudioEqualizer*) audioEqualizer { ! return _audioEqualizer; } - (void) observeKeyPath:(NSString*)keyPath withContext:(void*)context { [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:context]; [keyPathsObserved addObject:keyPath]; --- 170,205 ---- // Don't create video output until we know we have video _playerOutput = nil; _displayLink = NULL; ! _audioProcessor = [[AVFAudioProcessor alloc] init]; ! if (_audioProcessor.audioSpectrum != nullptr) { ! _audioProcessor.audioSpectrum->SetSpectrumCallbackProc(SpectrumCallbackProc, (__bridge void*)self); ! } ! isDisposed = NO; } return self; } - (void) dealloc { [self dispose]; self.movieURL = nil; self.player = nil; self.playerOutput = nil; } - (CAudioSpectrum*) audioSpectrum { ! AVFAudioSpectrumUnitPtr asPtr = _audioProcessor.audioSpectrum; ! return static_cast<CAudioSpectrum*>(&(*asPtr)); } - (CAudioEqualizer*) audioEqualizer { ! AVFAudioEqualizerPtr eqPtr = _audioProcessor.audioEqualizer; ! return static_cast<CAudioEqualizer*>(&(*eqPtr)); } - (void) observeKeyPath:(NSString*)keyPath withContext:(void*)context { [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:context]; [keyPathsObserved addObject:keyPath];
*** 233,249 **** [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes: @{(id)kCVPixelBufferPixelFormatTypeKey: @(FALLBACK_VO_FORMAT)}]; if (newOutput) { CVDisplayLinkStop(_displayLink); ! [_playerItem removeOutput:_playerOutput]; [_playerOutput setDelegate:nil queue:nil]; self.playerOutput = newOutput; [_playerOutput setDelegate:blockSelf queue:playerQueue]; [_playerOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:ADVANCE_INTERVAL_IN_SECONDS]; ! [_playerItem addOutput:_playerOutput]; } }); } - (void) createVideoOutput { --- 216,232 ---- [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes: @{(id)kCVPixelBufferPixelFormatTypeKey: @(FALLBACK_VO_FORMAT)}]; if (newOutput) { CVDisplayLinkStop(_displayLink); ! [_player.currentItem removeOutput:_playerOutput]; [_playerOutput setDelegate:nil queue:nil]; self.playerOutput = newOutput; [_playerOutput setDelegate:blockSelf queue:playerQueue]; [_playerOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:ADVANCE_INTERVAL_IN_SECONDS]; ! [_player.currentItem addOutput:_playerOutput]; } }); } - (void) createVideoOutput {
*** 278,288 **** // Set up playerOutput delegate [_playerOutput setDelegate:self queue:playerQueue]; [_playerOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:ADVANCE_INTERVAL_IN_SECONDS]; ! [_playerItem addOutput:_playerOutput]; } } } - (void) setPlayerState:(int)newState { --- 261,271 ---- // Set up playerOutput delegate [_playerOutput setDelegate:self queue:playerQueue]; [_playerOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:ADVANCE_INTERVAL_IN_SECONDS]; ! [_player.currentItem addOutput:_playerOutput]; } } } - (void) setPlayerState:(int)newState {
*** 306,316 **** _movieReady = true; } } } else if (context == AVFMediaPlayerItemDurationContext) { // send update duration event ! double duration = CMTimeGetSeconds(_playerItem.duration); eventHandler->SendDurationUpdateEvent(duration); } else if (context == AVFMediaPlayerItemTracksContext) { [self extractTrackInfo]; } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; --- 289,299 ---- _movieReady = true; } } } else if (context == AVFMediaPlayerItemDurationContext) { // send update duration event ! double duration = CMTimeGetSeconds(_player.currentItem.duration); eventHandler->SendDurationUpdateEvent(duration); } else if (context == AVFMediaPlayerItemTracksContext) { [self extractTrackInfo]; } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
*** 333,369 **** - (void) setMute:(BOOL)state { self.player.muted = state; } - (void) setAudioSyncDelay:(int64_t)audioSyncDelay { - _audioSyncDelay = audioSyncDelay; - if (_audioProcessor) { _audioProcessor.audioDelay = audioSyncDelay; - } } - (float) balance { ! return _balance; } - (void) setBalance:(float)balance { - _balance = balance; - if (_audioProcessor) { _audioProcessor.balance = balance; - } } - (float) volume { ! return _volume; } - (void) setVolume:(float)volume { - _volume = volume; - if (_audioProcessor) { _audioProcessor.volume = volume; - } } - (float) rate { return self.player.rate; } --- 316,347 ---- - (void) setMute:(BOOL)state { self.player.muted = state; } + - (int64_t) audioSyncDelay { + return _audioProcessor.audioDelay; + } + - (void) setAudioSyncDelay:(int64_t)audioSyncDelay { _audioProcessor.audioDelay = audioSyncDelay; } - (float) balance { ! return _audioProcessor.balance; } - (void) setBalance:(float)balance { _audioProcessor.balance = balance; } - (float) volume { ! return _audioProcessor.volume; } - (void) setVolume:(float)volume { _audioProcessor.volume = volume; } - (float) rate { return self.player.rate; }
*** 371,382 **** - (void) setRate:(float)rate { self.player.rate = rate; } - (double) duration { ! if (self.playerItem.status == AVPlayerItemStatusReadyToPlay) { ! return CMTimeGetSeconds(self.playerItem.duration); } return -1.0; } - (void) play { --- 349,360 ---- - (void) setRate:(float)rate { self.player.rate = rate; } - (double) duration { ! if (self.player.currentItem.status == AVPlayerItemStatusReadyToPlay) { ! return CMTimeGetSeconds(self.player.currentItem.duration); } return -1.0; } - (void) play {
*** 400,415 **** - (void) dispose { @synchronized(self) { if (!isDisposed) { if (_player != nil) { ! // this should stop and dealloc the audio processor ! _player.currentItem.audioMix = nil; } if (_playerOutput != nil) { ! [_playerItem removeOutput:_playerOutput]; [_playerOutput setDelegate:nil queue:nil]; } [self setPlayerState:kPlayerState_HALTED]; --- 378,402 ---- - (void) dispose { @synchronized(self) { if (!isDisposed) { if (_player != nil) { ! // stop the player ! _player.rate = 0.0; ! [_player cancelPendingPrerolls]; ! } ! ! AVFAudioSpectrumUnitPtr asPtr = _audioProcessor.audioSpectrum; ! if (asPtr != nullptr) { ! // Prevent future spectrum callbacks ! asPtr->SetEnabled(FALSE); ! asPtr->SetSpectrumCallbackProc(NULL, NULL); ! asPtr->SetBands(0, NULL); } if (_playerOutput != nil) { ! [_player.currentItem removeOutput:_playerOutput]; [_playerOutput setDelegate:nil queue:nil]; } [self setPlayerState:kPlayerState_HALTED];
*** 434,446 **** - (void) extractTrackInfo { #if DUMP_TRACK_INFO NSMutableString *trackLog = [[NSMutableString alloc] initWithFormat: @"Parsing tracks for player item %@:\n", ! _playerItem]; #endif ! NSArray *tracks = self.playerItem.tracks; int videoIndex = 1; int audioIndex = 1; int textIndex = 1; BOOL createVideo = NO; --- 421,433 ---- - (void) extractTrackInfo { #if DUMP_TRACK_INFO NSMutableString *trackLog = [[NSMutableString alloc] initWithFormat: @"Parsing tracks for player item %@:\n", ! _player.currentItem]; #endif ! NSArray *tracks = self.player.currentItem.tracks; int videoIndex = 1; int audioIndex = 1; int textIndex = 1; BOOL createVideo = NO;
*** 530,551 **** createVideo = YES; } else if ([type isEqualTo:AVMediaTypeAudio]) { name = [NSString stringWithFormat:@"Audio Track %d", audioIndex++]; TRACK_LOG(@" track name: %@", name); ! // Create audio processor ! if (!_audioProcessor) { ! _audioProcessor = [[AVFAudioProcessor alloc] initWithPlayer:self ! assetTrack:track]; ! _audioProcessor.volume = _volume; ! _audioProcessor.balance = _balance; // Make sure the players volume is set to 1.0 self.player.volume = 1.0; ! // Set up EQ and spectrum ! _audioProcessor.audioSpectrum = _audioSpectrum; ! _audioProcessor.audioEqualizer = _audioEqualizer; } // We have to get the audio information from the format description const AudioStreamBasicDescription *asbd = CMAudioFormatDescriptionGetStreamBasicDescription(desc); size_t layoutSize; --- 517,534 ---- createVideo = YES; } else if ([type isEqualTo:AVMediaTypeAudio]) { name = [NSString stringWithFormat:@"Audio Track %d", audioIndex++]; TRACK_LOG(@" track name: %@", name); ! // Set up audio processing ! if (_audioProcessor) { // Make sure the players volume is set to 1.0 self.player.volume = 1.0; ! // set up the mixer ! _audioProcessor.audioTrack = track; ! self.player.currentItem.audioMix = _audioProcessor.mixer; } // We have to get the audio information from the format description const AudioStreamBasicDescription *asbd = CMAudioFormatDescriptionGetStreamBasicDescription(desc); size_t layoutSize;
*** 689,700 **** * for this has been to remove then re-add the video output * This causes the video to pause for a bit, but it's better * than not playing at all, and this should not happen once * the bug is fixed in AVFoundation. */ ! [self.playerItem removeOutput:playerItemVideoOutput]; ! [self.playerItem addOutput:playerItemVideoOutput]; self.hlsBugResetCount = 0; self.lastHostTime = inNow->hostTime; // fall through to allow it to stop the display link } else { self.hlsBugResetCount++; --- 672,683 ---- * for this has been to remove then re-add the video output * This causes the video to pause for a bit, but it's better * than not playing at all, and this should not happen once * the bug is fixed in AVFoundation. */ ! [self.player.currentItem removeOutput:playerItemVideoOutput]; ! [self.player.currentItem addOutput:playerItemVideoOutput]; self.hlsBugResetCount = 0; self.lastHostTime = inNow->hostTime; // fall through to allow it to stop the display link } else { self.hlsBugResetCount++;
< prev index next >