< 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 +1,7 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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,21 +96,17 @@
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
+ // 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) {
- _audioSyncDelay = 0LL;
- _volume = 1.0f;
- _balance = 0.0f;
-
previousWidth = -1;
previousHeight = -1;
previousPlayerState = kPlayerState_UNKNOWN;
eventHandler = hdlr;
@@ -121,23 +117,17 @@
// Create our own work queue
playerQueue = dispatch_queue_create(NULL, NULL);
// Create the player
- _player = [[AVPlayer alloc] init];
+ _player = [AVPlayer playerWithURL:source];
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:
@@ -149,28 +139,28 @@
playerObservers = [[NSMutableArray alloc] init];
id<NSObject> observer;
__weak AVFMediaPlayer *blockSelf = self; // retain cycle avoidance
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
observer = [center addObserverForName:AVPlayerItemDidPlayToEndTimeNotification
- object:_playerItem
+ 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.playerItem.status"
+ [self observeKeyPath:@"self.player.currentItem.status"
withContext:AVFMediaPlayerItemStatusContext];
- [self observeKeyPath:@"self.playerItem.duration"
+ [self observeKeyPath:@"self.player.currentItem.duration"
withContext:AVFMediaPlayerItemDurationContext];
- [self observeKeyPath:@"self.playerItem.tracks"
+ [self observeKeyPath:@"self.player.currentItem.tracks"
withContext:AVFMediaPlayerItemTracksContext];
[self setPlayerState:kPlayerState_UNKNOWN];
@@ -180,43 +170,36 @@
// Don't create video output until we know we have video
_playerOutput = nil;
_displayLink = NULL;
- _audioSpectrum = new AVFAudioSpectrumUnit();
- _audioSpectrum->SetSpectrumCallbackProc(SpectrumCallbackProc, (__bridge void*)self);
+ _audioProcessor = [[AVFAudioProcessor alloc] init];
+ if (_audioProcessor.audioSpectrum != nullptr) {
+ _audioProcessor.audioSpectrum->SetSpectrumCallbackProc(SpectrumCallbackProc, (__bridge void*)self);
+ }
- _audioEqualizer = new AVFAudioEqualizer();
+ isDisposed = NO;
}
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;
+ AVFAudioSpectrumUnitPtr asPtr = _audioProcessor.audioSpectrum;
+ return static_cast<CAudioSpectrum*>(&(*asPtr));
}
- (CAudioEqualizer*) audioEqualizer {
- return _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,17 +216,17 @@
[[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:
@{(id)kCVPixelBufferPixelFormatTypeKey: @(FALLBACK_VO_FORMAT)}];
if (newOutput) {
CVDisplayLinkStop(_displayLink);
- [_playerItem removeOutput:_playerOutput];
+ [_player.currentItem removeOutput:_playerOutput];
[_playerOutput setDelegate:nil queue:nil];
self.playerOutput = newOutput;
[_playerOutput setDelegate:blockSelf queue:playerQueue];
[_playerOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:ADVANCE_INTERVAL_IN_SECONDS];
- [_playerItem addOutput:_playerOutput];
+ [_player.currentItem addOutput:_playerOutput];
}
});
}
- (void) createVideoOutput {
@@ -278,11 +261,11 @@
// Set up playerOutput delegate
[_playerOutput setDelegate:self queue:playerQueue];
[_playerOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:ADVANCE_INTERVAL_IN_SECONDS];
- [_playerItem addOutput:_playerOutput];
+ [_player.currentItem addOutput:_playerOutput];
}
}
}
- (void) setPlayerState:(int)newState {
@@ -306,11 +289,11 @@
_movieReady = true;
}
}
} else if (context == AVFMediaPlayerItemDurationContext) {
// send update duration event
- double duration = CMTimeGetSeconds(_playerItem.duration);
+ 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,37 +316,32 @@
- (void) setMute:(BOOL)state {
self.player.muted = state;
}
+- (int64_t) audioSyncDelay {
+ return _audioProcessor.audioDelay;
+}
+
- (void) setAudioSyncDelay:(int64_t)audioSyncDelay {
- _audioSyncDelay = audioSyncDelay;
- if (_audioProcessor) {
_audioProcessor.audioDelay = audioSyncDelay;
- }
}
- (float) balance {
- return _balance;
+ return _audioProcessor.balance;
}
- (void) setBalance:(float)balance {
- _balance = balance;
- if (_audioProcessor) {
_audioProcessor.balance = balance;
- }
}
- (float) volume {
- return _volume;
+ return _audioProcessor.volume;
}
- (void) setVolume:(float)volume {
- _volume = volume;
- if (_audioProcessor) {
_audioProcessor.volume = volume;
- }
}
- (float) rate {
return self.player.rate;
}
@@ -371,12 +349,12 @@
- (void) setRate:(float)rate {
self.player.rate = rate;
}
- (double) duration {
- if (self.playerItem.status == AVPlayerItemStatusReadyToPlay) {
- return CMTimeGetSeconds(self.playerItem.duration);
+ if (self.player.currentItem.status == AVPlayerItemStatusReadyToPlay) {
+ return CMTimeGetSeconds(self.player.currentItem.duration);
}
return -1.0;
}
- (void) play {
@@ -400,16 +378,25 @@
- (void) dispose {
@synchronized(self) {
if (!isDisposed) {
if (_player != nil) {
- // this should stop and dealloc the audio processor
- _player.currentItem.audioMix = 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) {
- [_playerItem removeOutput:_playerOutput];
+ [_player.currentItem removeOutput:_playerOutput];
[_playerOutput setDelegate:nil queue:nil];
}
[self setPlayerState:kPlayerState_HALTED];
@@ -434,13 +421,13 @@
- (void) extractTrackInfo {
#if DUMP_TRACK_INFO
NSMutableString *trackLog = [[NSMutableString alloc] initWithFormat:
@"Parsing tracks for player item %@:\n",
- _playerItem];
+ _player.currentItem];
#endif
- NSArray *tracks = self.playerItem.tracks;
+ NSArray *tracks = self.player.currentItem.tracks;
int videoIndex = 1;
int audioIndex = 1;
int textIndex = 1;
BOOL createVideo = NO;
@@ -530,22 +517,18 @@
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;
+ // Set up audio processing
+ if (_audioProcessor) {
// 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;
+ // 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,12 +672,12 @@
* 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.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 >