You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

366 lines
10 KiB

#include "PlayerFFmpeg.h"
@implementation PlayerFFmpeg
@synthesize delegate = _delegate;
- (void)dealloc
{
[self stop];
}
- (id)init
{
self = [super init];
return self;
}
- (void)setupPlayer:(NSArray *)options
{
[FFMoviePlayerController setLogReport:NO];
[FFMoviePlayerController setLogLevel:k_LOG_SILENT];
[FFMoviePlayerController checkIfFFmpegVersionMatch:NO];
_ffOptions = [FFOptions optionsByDefault];
[_ffOptions setPlayerOptionIntValue:1 forKey:@"start-on-prepared"];
for(NSString *option in options)
{
NSArray *optionData = [option componentsSeparatedByString:@"="];
if ([optionData count] > 1)
{
[_ffOptions setPlayerOptionIntValue:[optionData[1] integerValue] forKey:optionData[0]];
}
else
{
if ([optionData[0] isEqual: @"play-in-background"])
{
_playInBackground = true;
continue;
}
if ([optionData[0] isEqual: @"rtsp-tcp"])
{
[_ffOptions setFormatOptionValue:@"tcp" forKey:@"rtsp_transport"];
continue;
}
[_ffOptions setPlayerOptionIntValue:1 forKey:optionData[0]];
}
}
[self initMediaPlayer];
}
- (void)initMediaPlayer
{
_player = [[FFMoviePlayerController alloc] initWithOptions:_ffOptions];
[_player setPauseInBackground:!_playInBackground];
_cachedPlaybackTime = -1;
_cachedBuffering = -1;
_hasVideoTrack = false;
_isBuffering = false;
[self installMovieNotificationObservers];
}
- (void)setDataSource:(NSString *)path
{
_videoPath = path;
}
- (void)play
{
if (_player == nil)
[self initMediaPlayer];
if (![_player isPreparedToPlay])
{
[_player setDataSourceURL:[NSURL URLWithString:_videoPath]];
[_player prepareToPlay];
if ([_delegate respondsToSelector:@selector(mediaPlayerStateChanged:)])
{
dispatch_async(dispatch_get_main_queue(), ^{
PlayerState *newState = [[PlayerState alloc] init];
newState.state = Opening;
[_delegate mediaPlayerStateChanged:newState];
});
}
}
else
[_player play];
}
- (void)pause
{
[_player pause];
}
- (void)stop
{
if (_player != nil)
{
[_player shutdown];
[self removeMovieNotificationObservers];
_player = nil;
if ([_delegate respondsToSelector:@selector(mediaPlayerStateChanged:)])
{
PlayerState *newState = [[PlayerState alloc] init];
newState.state = Stopped;
[_delegate mediaPlayerStateChanged:newState];
}
}
}
- (int)getDuration
{
return [_player duration] * 1000;
}
- (CVPixelBufferRef)getPixelBuffer
{
return [_player videoBuffer];
}
- (int)getFramesCounter
{
if (_isBuffering && _cachedBuffering != _player.bufferingProgress
&& _cachedBuffering < _player.bufferingProgress)
{
_cachedBuffering = _player.bufferingProgress;
if ([_delegate respondsToSelector:@selector(mediaPlayerStateChanged:)])
{
dispatch_async(dispatch_get_main_queue(), ^{
PlayerState *newState = [[PlayerState alloc] init];
newState.state = Buffering;
newState.valueFloat = (float)_cachedBuffering;
[_delegate mediaPlayerStateChanged:newState];
});
}
}
if ([self isReady] && [self isPlaying])
{
float currentTime = [_player currentPlaybackTime];
if (fabs(currentTime - _cachedPlaybackTime) > TIME_CHANGE_OFFSET)
{
if ([_delegate respondsToSelector:@selector(mediaPlayerStateChanged:)])
{
dispatch_async(dispatch_get_main_queue(), ^{
PlayerState *newState = [[PlayerState alloc] init];
newState.state = TimeChanged;
newState.valueLong = currentTime * 1000;
[_delegate mediaPlayerStateChanged:newState];
});
}
if ([_delegate respondsToSelector:@selector(mediaPlayerStateChanged:)])
{
dispatch_async(dispatch_get_main_queue(), ^{
PlayerState *newState = [[PlayerState alloc] init];
newState.state = PositionChanged;
newState.valueFloat = currentTime / [_player duration];
[_delegate mediaPlayerStateChanged:newState];
});
}
_cachedPlaybackTime = [_player currentPlaybackTime];
}
}
return (int)[_player frameCount];
}
- (int)getVolume
{
return [_player playbackVolume] * 100;
}
- (void)setVolume:(int)value
{
[_player setPlaybackVolume:(float)value / 100.0];
}
- (int)getTime
{
return [_player currentPlaybackTime] * 1000;
}
- (void)setTime:(int)value
{
[_player setCurrentPlaybackTime:value];
}
- (float)getPosition
{
float position = [_player currentPlaybackTime] / [_player duration];
return position;
}
- (void)setPosition:(float)value
{
float position = [_player duration] * value;
[_player setCurrentPlaybackTime:position];
}
- (float)getPlaybackRate
{
return [_player playbackRate];
}
- (void)setPlaybackRate:(float)value
{
[_player setPlaybackRate:value];
}
- (bool)isPlaying
{
return [_player isPlaying];
}
- (bool)isReady
{
return _hasVideoTrack ? [_player frameCount] > 0 : [_player isPreparedToPlay];
}
- (int)getVideoWidth
{
return [_player videoWidth];
}
- (int)getVideoHeight
{
return [_player videoHeight];
}
- (void)movieVideoDecoderOpen:(NSNotification*)notification
{
_hasVideoTrack = true;
}
- (void)loadStateDidChange:(NSNotification*)notification
{
switch (_player.loadState)
{
case MMPMovieLoadStateStalled:
_isBuffering = true;
break;
case MMPMovieLoadStatePlayable | MMPMovieLoadStatePlaythroughOK:
_isBuffering = false;
_cachedBuffering = -1;
break;
}
}
- (void)moviePlayBackDidFinish:(NSNotification*)notification
{
int reason = [[[notification userInfo] valueForKey:MMPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
switch (reason)
{
case MMPMovieFinishReasonPlaybackEnded:
if ([_delegate respondsToSelector:@selector(mediaPlayerStateChanged:)])
{
dispatch_async(dispatch_get_main_queue(), ^{
PlayerState *newState = [[PlayerState alloc] init];
newState.state = EndReached;
[_delegate mediaPlayerStateChanged:newState];
});
}
break;
case MMPMovieFinishReasonUserExited:
break;
case MMPMovieFinishReasonPlaybackError:
if ([_delegate respondsToSelector:@selector(mediaPlayerStateChanged:)])
{
dispatch_async(dispatch_get_main_queue(), ^{
PlayerState *newState = [[PlayerState alloc] init];
newState.state = EncounteredError;
[_delegate mediaPlayerStateChanged:newState];
});
}
break;
}
}
- (void)mediaIsPreparedToPlayDidChange:(NSNotification*)notification
{
NSLog(@"mediaIsPreparedToPlayDidChange\n");
}
- (void)moviePlayBackStateDidChange:(NSNotification*)notification
{
switch (_player.playbackState)
{
case MMPMoviePlaybackStatePlaying:
break;
case MMPMoviePlaybackStatePaused:
if ([_delegate respondsToSelector:@selector(mediaPlayerStateChanged:)])
{
dispatch_async(dispatch_get_main_queue(), ^{
PlayerState *newState = [[PlayerState alloc] init];
newState.state = Paused;
[_delegate mediaPlayerStateChanged:newState];
});
}
break;
case MMPMoviePlaybackStateInterrupted:
break;
case MMPMoviePlaybackStateSeekingForward:
case MMPMoviePlaybackStateSeekingBackward:
break;
default:
break;
}
}
-(void)installMovieNotificationObservers
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loadStateDidChange:)
name:MMPMoviePlayerLoadStateDidChangeNotification
object:_player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackDidFinish:)
name:MMPMoviePlayerPlaybackDidFinishNotification
object:_player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mediaIsPreparedToPlayDidChange:)
name:MMPMediaPlaybackIsPreparedToPlayDidChangeNotification
object:_player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(moviePlayBackStateDidChange:)
name:MMPMoviePlayerPlaybackStateDidChangeNotification
object:_player];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(movieVideoDecoderOpen:)
name:MMPMoviePlayerVideoDecoderOpenNotification
object:_player];
}
-(void)removeMovieNotificationObservers
{
[[NSNotificationCenter defaultCenter]removeObserver:self name:MMPMoviePlayerLoadStateDidChangeNotification object:_player];
[[NSNotificationCenter defaultCenter]removeObserver:self name:MMPMoviePlayerPlaybackDidFinishNotification object:_player];
[[NSNotificationCenter defaultCenter]removeObserver:self name:MMPMediaPlaybackIsPreparedToPlayDidChangeNotification object:_player];
[[NSNotificationCenter defaultCenter]removeObserver:self name:MMPMoviePlayerPlaybackStateDidChangeNotification object:_player];
[[NSNotificationCenter defaultCenter]removeObserver:self name:MMPMoviePlayerVideoDecoderOpenNotification object:_player];
}
@end