Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_25606643
ijkplayer
提交
25ce853b
I
ijkplayer
项目概览
qq_25606643
/
ijkplayer
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
I
ijkplayer
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
25ce853b
编写于
10月 11, 2014
作者:
Z
Zhang Rui
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ios: improve AVPlayer stall handle
上级
a99b68aa
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
127 addition
and
50 deletion
+127
-50
ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.m
ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.m
+1
-1
ios/IJKMediaPlayer/IJKMediaPlayer/IJKAVMoviePlayerController.m
...JKMediaPlayer/IJKMediaPlayer/IJKAVMoviePlayerController.m
+126
-49
未找到文件。
ios/IJKMediaDemo/IJKMediaDemo/IJKMoviePlayerViewController.m
浏览文件 @
25ce853b
...
...
@@ -42,7 +42,7 @@
// NSURL *theMovieURL = [NSURL URLWithString:@"rtsp://l.m.cztv.com:554/hdmi/hntv1hd.stream"];
// NSURL *theMovieURL = [NSURL URLWithString:@"http://edge.v.iask.com/115151121.hlv?KID=sina,viask&Expires=1380297600&ssig=SjfwCmaiLe"];
// NSURL *theMovieURL = [NSURL URLWithString:@"http://edge.v.iask.com/115279108.hlv?KID=sina,viask&Expires=1380297600&ssig=KpcdjFjrhW"];
NSURL
*
theMovieURL
=
[
NSURL
URLWithString
:
@"http://
devimages.apple.com/iphone/samples/bipbop/gear1/prog_index.m3u8
"
];
NSURL
*
theMovieURL
=
[
NSURL
URLWithString
:
@"http://
main.gslb.ku6.com/s0/8TB4LuyxYUrZXt6z/1287229516641/eba316981ad6d370d2fe6d6513347666/1412822149101/v426/0/4/8WaVhPqDSgmUICwLruXaTwA.f4v?stype=mp4
"
];
self
.
player
=
[[
IJKFFMoviePlayerController
alloc
]
initWithContentURL
:
theMovieURL
withOptions
:
nil
];
self
.
player
.
view
.
autoresizingMask
=
UIViewAutoresizingFlexibleWidth
|
UIViewAutoresizingFlexibleHeight
;
...
...
ios/IJKMediaPlayer/IJKMediaPlayer/IJKAVMoviePlayerController.m
浏览文件 @
25ce853b
...
...
@@ -75,6 +75,12 @@
#import "IJKKVOController.h"
#import <AVFoundation/AVFoundation.h>
// avoid float equal compare
static
const
float
kMinPlayingRate
=
0
.
00001
f
;
// resume play after stall
static
const
float
kMaxHighWaterMarkMilli
=
15
*
1000
;
static
NSString
*
kErrorDomain
=
@"IJKAVMoviePlayer"
;
static
const
NSInteger
kEC_CurrentPlayerItemIsNil
=
5001
;
static
const
NSInteger
kEC_PlayerItemCancelled
=
5002
;
...
...
@@ -111,7 +117,11 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
IJKKVOController
*
_playerKVO
;
IJKKVOController
*
_playerItemKVO
;
id
_timeObserver
;
id
_timeObserver
;
// while AVPlayer is prerolling, it could resume itself.
// foring start could
BOOL
_isPrerolling
;
BOOL
_isSeeking
;
BOOL
_isError
;
...
...
@@ -158,10 +168,12 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
// TODO:
[[
IJKAudioKit
sharedInstance
]
setupAudioSession
:
self
];
_isPrerolling
=
NO
;
_isSeeking
=
NO
;
_isError
=
NO
;
_isCompleted
=
NO
;
self
.
bufferingProgress
=
-
1
;
self
.
bufferingProgress
=
0
;
_playbackLikelyToKeeyUp
=
NO
;
_playbackBufferEmpty
=
YES
;
...
...
@@ -204,28 +216,37 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
-
(
void
)
play
{
if
(
_isCompleted
)
{
{
_isCompleted
=
NO
;
[
_player
seekToTime
:
kCMTimeZero
];
}
}
[
_player
play
];
[
_player
play
];
}
-
(
void
)
pause
{
[
_player
pause
];
_isPrerolling
=
NO
;
[
_player
pause
];
}
-
(
void
)
stop
{
[
_player
pause
];
[
_player
pause
];
_isCompleted
=
YES
;
}
-
(
BOOL
)
isPlaying
{
return
_player
.
rate
>=
0
.
00001
f
;
if
(
_player
.
rate
>=
kMinPlayingRate
)
{
return
YES
;
}
else
{
if
(
_isPrerolling
)
{
return
YES
;
}
else
{
return
NO
;
}
}
}
-
(
void
)
shutdown
...
...
@@ -336,16 +357,20 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
if
(
playerItem
==
nil
)
return
MPMovieLoadStateUnknown
;
if
([
playerItem
isPlaybackBufferFull
])
{
if
([
playerItem
isPlaybackLikelyToKeepUp
])
{
return
MPMovieLoadStatePlayable
|
MPMovieLoadStatePlaythroughOK
;
}
return
MPMovieLoadStatePlayable
;
if
(
_player
!=
nil
&&
_player
.
rate
>
kMinPlayingRate
)
{
NSLog
(
@"loadState: playing"
);
return
MPMovieLoadStatePlayable
|
MPMovieLoadStatePlaythroughOK
;
}
else
if
([
playerItem
isPlaybackBufferFull
])
{
NSLog
(
@"loadState: isPlaybackBufferFull"
);
return
MPMovieLoadStatePlayable
|
MPMovieLoadStatePlaythroughOK
;
}
else
if
([
playerItem
isPlaybackLikelyToKeepUp
])
{
return
MPMovieLoadStatePlaythroughOK
;
NSLog
(
@"loadState: isPlaybackLikelyToKeepUp"
);
return
MPMovieLoadStatePlayable
|
MPMovieLoadStatePlaythroughOK
;
}
else
if
([
playerItem
isPlaybackBufferEmpty
])
{
NSLog
(
@"loadState: isPlaybackBufferEmpty"
);
return
MPMovieLoadStateStalled
;
}
else
{
NSLog
(
@"loadState: unknown"
);
return
MPMovieLoadStateUnknown
;
}
}
...
...
@@ -356,37 +381,37 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
-
(
void
)
didPrepareToPlayAsset
:(
AVURLAsset
*
)
asset
withKeys
:(
NSArray
*
)
requestedKeys
{
/* Make sure that the value of each key has loaded successfully. */
for
(
NSString
*
thisKey
in
requestedKeys
)
{
NSError
*
error
=
nil
;
AVKeyValueStatus
keyStatus
=
[
asset
statusOfValueForKey
:
thisKey
error
:
&
error
];
if
(
keyStatus
==
AVKeyValueStatusFailed
)
{
[
self
assetFailedToPrepareForPlayback
:
error
];
return
;
}
else
if
(
keyStatus
==
AVKeyValueStatusCancelled
)
{
for
(
NSString
*
thisKey
in
requestedKeys
)
{
NSError
*
error
=
nil
;
AVKeyValueStatus
keyStatus
=
[
asset
statusOfValueForKey
:
thisKey
error
:
&
error
];
if
(
keyStatus
==
AVKeyValueStatusFailed
)
{
[
self
assetFailedToPrepareForPlayback
:
error
];
return
;
}
else
if
(
keyStatus
==
AVKeyValueStatusCancelled
)
{
// TODO [AVAsset cancelLoading]
error
=
[
self
createErrorWithCode
:
kEC_PlayerItemCancelled
description:
@"player item cancelled"
reason:
nil
];
[
self
assetFailedToPrepareForPlayback
:
error
];
return
;
[
self
assetFailedToPrepareForPlayback
:
error
];
return
;
}
}
}
/* Use the AVAsset playable property to detect whether the asset can be played. */
if
(
!
asset
.
playable
)
{
NSError
*
assetCannotBePlayedError
=
[
NSError
errorWithDomain
:
@"AVMoviePlayer"
NSError
*
assetCannotBePlayedError
=
[
NSError
errorWithDomain
:
@"AVMoviePlayer"
code:
0
userInfo:
nil
];
[
self
assetFailedToPrepareForPlayback
:
assetCannotBePlayedError
];
return
;
}
/* At this point we're ready to set up for playback of the asset. */
/* At this point we're ready to set up for playback of the asset. */
/* Stop observing our prior AVPlayerItem, if we have one. */
[
_playerItemKVO
safelyRemoveAllObservers
];
[[
NSNotificationCenter
defaultCenter
]
removeObserver
:
self
...
...
@@ -464,9 +489,9 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
asynchronously; observe the currentItem property to find out when the
replacement will/did occur
If needed, configure player item here (example: adding outputs, setting text style rules,
selecting media options) before associating it with a player
*/
If needed, configure player item here (example: adding outputs, setting text style rules,
selecting media options) before associating it with a player
*/
[
_player
replaceCurrentItemWithPlayerItem
:
_playerItem
];
// TODO: notify state change
...
...
@@ -482,19 +507,60 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
object:
self
];
}
-
(
void
)
fetchLoadStateFromItem
:(
AVPlayerItem
*
)
playerItem
{
if
(
playerItem
==
nil
)
return
;
_playbackLikelyToKeeyUp
=
playerItem
.
isPlaybackLikelyToKeepUp
;
_playbackBufferEmpty
=
playerItem
.
isPlaybackBufferEmpty
;
_playbackBufferFull
=
playerItem
.
isPlaybackBufferFull
;
}
-
(
void
)
didLoadStateChange
{
// NOTE: do not force play after stall,
// which may cause AVPlayer get into wrong state
//
// Rely on AVPlayer's auto resume.
[[
NSNotificationCenter
defaultCenter
]
postNotificationName:
IJKMoviePlayerLoadStateDidChangeNotification
object:
self
];
}
-
(
void
)
didPlayableDurationUpdate
{
NSTimeInterval
currentPlaybackTime
=
self
.
currentPlaybackTime
;
int
playableDurationMilli
=
(
int
)(
self
.
playableDuration
*
1000
);
int
currentPlaybackTimeMilli
=
(
int
)(
currentPlaybackTime
*
1000
);
int
bufferedDurationMilli
=
playableDurationMilli
-
currentPlaybackTimeMilli
;
if
(
bufferedDurationMilli
>
0
)
{
self
.
bufferingProgress
=
bufferedDurationMilli
*
100
/
kMaxHighWaterMarkMilli
;
if
(
self
.
bufferingProgress
>
100
)
{
dispatch_async
(
dispatch_get_main_queue
(),
^
{
if
(
self
.
bufferingProgress
>
100
)
{
_player
.
rate
=
1
.
0
f
;
}
});
}
}
NSLog
(
@"KVO_AVPlayerItem_loadedTimeRanges: %d / %d
\n
"
,
bufferedDurationMilli
,
(
int
)
kMaxHighWaterMarkMilli
);
}
-
(
void
)
onError
:(
NSError
*
)
error
{
_isError
=
YES
;
__block
NSError
*
blockError
=
error
;
NSLog
(
@"AVPlayer: onError
\n
"
);
dispatch_async
(
dispatch_get_main_queue
(),
^
{
[
self
didPlaybackStateChange
];
[
self
didLoadStateChange
];
...
...
@@ -544,8 +610,8 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
change
:(
NSDictionary
*
)
change
context
:(
void
*
)
context
{
if
(
context
==
KVO_AVPlayerItem_state
)
{
if
(
context
==
KVO_AVPlayerItem_state
)
{
/* AVPlayerItem "status" property value observer. */
AVPlayerItemStatus
status
=
[[
change
objectForKey
:
NSKeyValueChangeNewKey
]
integerValue
];
switch
(
status
)
...
...
@@ -588,7 +654,7 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
[
self
didPlaybackStateChange
];
[
self
didLoadStateChange
];
}
}
else
if
(
context
==
KVO_AVPlayerItem_loadedTimeRanges
)
{
AVPlayerItem
*
playerItem
=
(
AVPlayerItem
*
)
object
;
...
...
@@ -610,8 +676,10 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
if
(
foundRange
)
{
CMTime
maxTime
=
CMTimeRangeGetEnd
(
aTimeRange
);
NSTimeInterval
playableDuration
=
CMTimeGetSeconds
(
maxTime
);
if
(
playableDuration
>
0
)
if
(
playableDuration
>
0
)
{
self
.
playableDuration
=
playableDuration
;
[
self
didPlayableDurationUpdate
];
}
}
}
else
...
...
@@ -621,27 +689,36 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
}
else
if
(
context
==
KVO_AVPlayerItem_playbackLikelyToKeepUp
)
{
AVPlayerItem
*
playerItem
=
(
AVPlayerItem
*
)
object
;
_playbackLikelyToKeeyUp
=
playerItem
.
isPlaybackLikelyToKeepUp
;
NSLog
(
@"KVO_AVPlayerItem_playbackLikelyToKeepUp: %@
\n
"
,
playerItem
.
isPlaybackLikelyToKeepUp
?
@"YES"
:
@"NO"
);
[
self
fetchLoadStateFromItem
:
playerItem
];
[
self
didLoadStateChange
];
}
else
if
(
context
==
KVO_AVPlayerItem_playbackBufferEmpty
)
{
AVPlayerItem
*
playerItem
=
(
AVPlayerItem
*
)
object
;
_playbackBufferEmpty
=
playerItem
.
isPlaybackBufferEmpty
;
BOOL
isPlaybackBufferEmpty
=
playerItem
.
isPlaybackBufferEmpty
;
NSLog
(
@"KVO_AVPlayerItem_playbackBufferEmpty: %@
\n
"
,
isPlaybackBufferEmpty
?
@"YES"
:
@"NO"
);
if
(
isPlaybackBufferEmpty
)
_isPrerolling
=
YES
;
[
self
fetchLoadStateFromItem
:
playerItem
];
[
self
didLoadStateChange
];
}
else
if
(
context
==
KVO_AVPlayerItem_playbackBufferFull
)
{
AVPlayerItem
*
playerItem
=
(
AVPlayerItem
*
)
object
;
_playbackBufferFull
=
playerItem
.
isPlaybackBufferFull
;
NSLog
(
@"KVO_AVPlayerItem_playbackBufferFull: %@
\n
"
,
playerItem
.
isPlaybackBufferFull
?
@"YES"
:
@"NO"
);
[
self
fetchLoadStateFromItem
:
playerItem
];
[
self
didLoadStateChange
];
}
else
if
(
context
==
KVO_AVPlayer_rate
)
{
else
if
(
context
==
KVO_AVPlayer_rate
)
{
if
(
_player
!=
nil
&&
_player
.
rate
>=
kMinPlayingRate
)
_isPrerolling
=
NO
;
/* AVPlayer "rate" property value observer. */
[
self
didPlaybackStateChange
];
[
self
didLoadStateChange
];
}
else
if
(
context
==
KVO_AVPlayer_currentItem
)
{
}
else
if
(
context
==
KVO_AVPlayer_currentItem
)
{
_isPrerolling
=
NO
;
/* AVPlayer "currentItem" property observer.
Called when the AVPlayer replaceCurrentItemWithPlayerItem:
replacement will/did occur. */
...
...
@@ -660,11 +737,11 @@ static void *KVO_AVPlayerItem_playbackBufferEmpty = &KVO_AVPlayerItem_play
[
self
didPlaybackStateChange
];
[
self
didLoadStateChange
];
}
}
else
{
[
super
observeValueForKeyPath
:
path
ofObject
:
object
change
:
change
context
:
context
];
}
}
else
{
[
super
observeValueForKeyPath
:
path
ofObject
:
object
change
:
change
context
:
context
];
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录