Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
ac13
GSYVideoPlayer
提交
1becbed5
G
GSYVideoPlayer
项目概览
ac13
/
GSYVideoPlayer
与 Fork 源项目一致
从无法访问的项目Fork
通知
7
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
GSYVideoPlayer
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
1becbed5
编写于
2月 19, 2017
作者:
S
shuyu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
* 增加了弹幕的显示逻辑
上级
62943836
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
130 addition
and
85 deletion
+130
-85
QUESTION.md
QUESTION.md
+5
-1
app/src/main/java/com/example/gsyvideoplayer/video/DanmakuVideoPlayer.java
.../com/example/gsyvideoplayer/video/DanmakuVideoPlayer.java
+124
-83
gsyVideoPlayer/src/main/java/com/shuyu/gsyvideoplayer/video/GSYBaseVideoPlayer.java
...va/com/shuyu/gsyvideoplayer/video/GSYBaseVideoPlayer.java
+1
-1
未找到文件。
QUESTION.md
浏览文件 @
1becbed5
...
...
@@ -53,11 +53,15 @@ android {
是否监听了列表滑动了,在监听里更新了列表之类的。
#### 4、目前不支持3gp或者mepg
,请保证视屏格式H264,AAC音频
。
#### 4、目前不支持3gp或者mepg。
如果拍摄的视频播放不了,可以尝试用使用系统录制的项目:
[
VideoRecord
](
https://github.com/CarGuo/VideoRecord
)
或者使用JAVACV录制的项目:
[
FFmpegRecorder
](
https://github.com/CrazyOrr/FFmpegRecorder
)
,测试视频是否可以播放。
黑屏相关issues:
https://github.com/Bilibili/ijkplayer/issues/2541
https://github.com/Bilibili/ijkplayer/pull/1875
#### 5、m3u8\HLS的格式视频请关闭cache
缓存不支持m3u8
\H
LS,播放m3u8
\H
LS格式,需要cacheWithPlay为false
...
...
app/src/main/java/com/example/gsyvideoplayer/video/DanmakuVideoPlayer.java
浏览文件 @
1becbed5
...
...
@@ -11,9 +11,16 @@ import android.text.style.BackgroundColorSpan;
import
android.text.style.ImageSpan
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.SeekBar
;
import
com.example.gsyvideoplayer.R
;
import
com.example.gsyvideoplayer.adapter.DanamakuAdapter
;
import
com.example.gsyvideoplayer.utils.BiliDanmukuParser
;
import
com.shuyu.gsyvideoplayer.GSYVideoManager
;
import
com.shuyu.gsyvideoplayer.GSYVideoPlayer
;
import
com.shuyu.gsyvideoplayer.video.GSYBaseVideoPlayer
;
import
com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
;
import
java.io.IOException
;
...
...
@@ -42,6 +49,10 @@ import master.flame.danmaku.ui.widget.DanmakuView;
/**
* Created by guoshuyu on 2017/2/16.
*
* 配置弹幕使用的播放器,目前使用的是本地模拟数据。
*
* 模拟数据的弹幕时常比较短,后面的时常点是没有数据的。
*/
public
class
DanmakuVideoPlayer
extends
StandardGSYVideoPlayer
{
...
...
@@ -50,6 +61,8 @@ public class DanmakuVideoPlayer extends StandardGSYVideoPlayer {
private
IDanmakuView
mDanmakuView
;
//弹幕view
private
DanmakuContext
mDanmakuContext
;
private
long
mDanmakuStartSeekPosition
=
-
1
;
public
DanmakuVideoPlayer
(
Context
context
,
Boolean
fullFlag
)
{
super
(
context
,
fullFlag
);
}
...
...
@@ -67,54 +80,6 @@ public class DanmakuVideoPlayer extends StandardGSYVideoPlayer {
return
R
.
layout
.
danmaku_layout
;
}
private
BaseCacheStuffer
.
Proxy
mCacheStufferAdapter
=
new
BaseCacheStuffer
.
Proxy
()
{
private
Drawable
mDrawable
;
@Override
public
void
prepareDrawing
(
final
BaseDanmaku
danmaku
,
boolean
fromWorkerThread
)
{
if
(
danmaku
.
text
instanceof
Spanned
)
{
// 根据你的条件检查是否需要需要更新弹幕
// FIXME 这里只是简单启个线程来加载远程url图片,请使用你自己的异步线程池,最好加上你的缓存池
new
Thread
()
{
@Override
public
void
run
()
{
String
url
=
"http://www.bilibili.com/favicon.ico"
;
InputStream
inputStream
=
null
;
Drawable
drawable
=
mDrawable
;
if
(
drawable
==
null
)
{
try
{
URLConnection
urlConnection
=
new
URL
(
url
).
openConnection
();
inputStream
=
urlConnection
.
getInputStream
();
drawable
=
BitmapDrawable
.
createFromStream
(
inputStream
,
"bitmap"
);
mDrawable
=
drawable
;
}
catch
(
MalformedURLException
e
)
{
e
.
printStackTrace
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
IOUtils
.
closeQuietly
(
inputStream
);
}
}
if
(
drawable
!=
null
)
{
drawable
.
setBounds
(
0
,
0
,
100
,
100
);
SpannableStringBuilder
spannable
=
createSpannable
(
drawable
);
danmaku
.
text
=
spannable
;
if
(
mDanmakuView
!=
null
)
{
mDanmakuView
.
invalidateDanmaku
(
danmaku
,
false
);
}
return
;
}
}
}.
start
();
}
}
@Override
public
void
releaseResource
(
BaseDanmaku
danmaku
)
{
// TODO 重要:清理含有ImageSpan的text中的一些占用内存的资源 例如drawable
}
};
@Override
protected
void
init
(
Context
context
)
{
...
...
@@ -129,13 +94,15 @@ public class DanmakuVideoPlayer extends StandardGSYVideoPlayer {
overlappingEnablePair
.
put
(
BaseDanmaku
.
TYPE_SCROLL_RL
,
true
);
overlappingEnablePair
.
put
(
BaseDanmaku
.
TYPE_FIX_TOP
,
true
);
DanamakuAdapter
danamakuAdapter
=
new
DanamakuAdapter
(
mDanmakuView
);
mDanmakuContext
=
DanmakuContext
.
create
();
mDanmakuContext
.
setDanmakuStyle
(
IDisplayer
.
DANMAKU_STYLE_STROKEN
,
3
).
setDuplicateMergingEnabled
(
false
).
setScrollSpeedFactor
(
1.2f
).
setScaleTextSize
(
1.2f
)
.
setCacheStuffer
(
new
SpannedCacheStuffer
(),
mCacheStuffer
Adapter
)
// 图文混排使用SpannedCacheStuffer
.
setCacheStuffer
(
new
SpannedCacheStuffer
(),
danamaku
Adapter
)
// 图文混排使用SpannedCacheStuffer
// .setCacheStuffer(new BackgroundCacheStuffer()) // 绘制背景使用BackgroundCacheStuffer
.
setMaximumLines
(
maxLinesPair
)
.
preventOverlapping
(
overlappingEnablePair
);
if
(
mDanmakuView
!=
null
)
{
//todo 替换成你的数据流
mParser
=
createParser
(
this
.
getResources
().
openRawResource
(
R
.
raw
.
comments
));
mDanmakuView
.
setCallback
(
new
master
.
flame
.
danmaku
.
controller
.
DrawHandler
.
Callback
()
{
@Override
...
...
@@ -149,34 +116,19 @@ public class DanmakuVideoPlayer extends StandardGSYVideoPlayer {
@Override
public
void
danmakuShown
(
BaseDanmaku
danmaku
)
{
// Log.d("DFM", "danmakuShown(): text=" + danmaku.text);
}
@Override
public
void
prepared
()
{
mDanmakuView
.
start
();
}
});
mDanmakuView
.
setOnDanmakuClickListener
(
new
IDanmakuView
.
OnDanmakuClickListener
()
{
@Override
public
boolean
onDanmakuClick
(
IDanmakus
danmakus
)
{
Log
.
d
(
"DFM"
,
"onDanmakuClick: danmakus size:"
+
danmakus
.
size
());
BaseDanmaku
latest
=
danmakus
.
last
();
if
(
null
!=
latest
)
{
Log
.
d
(
"DFM"
,
"onDanmakuClick: text of latest danmaku:"
+
latest
.
text
);
return
true
;
if
(
getDanmakuView
()
!=
null
)
{
getDanmakuView
().
start
();
if
(
getDanmakuStartSeekPosition
()
!=
-
1
)
{
resolveDanmakuSeek
(
DanmakuVideoPlayer
.
this
,
getDanmakuStartSeekPosition
());
setDanmakuStartSeekPosition
(-
1
);
}
}
return
false
;
}
@Override
public
boolean
onViewClick
(
IDanmakuView
view
)
{
// mMediaController.setVisibility(View.VISIBLE);
return
false
;
}
});
mDanmakuView
.
showFPS
(
true
);
mDanmakuView
.
enableDanmakuDrawingCache
(
true
);
}
}
...
...
@@ -184,15 +136,96 @@ public class DanmakuVideoPlayer extends StandardGSYVideoPlayer {
@Override
public
void
onPrepared
()
{
super
.
onPrepared
();
setDanmuKuUp
();
onPrepareDanmaku
(
this
);
}
@Override
public
void
onVideoPause
()
{
super
.
onVideoPause
();
if
(
mDanmakuView
!=
null
&&
mDanmakuView
.
isPrepared
())
{
mDanmakuView
.
pause
();
}
}
@Override
public
void
onVideoResume
()
{
super
.
onVideoResume
();
if
(
mDanmakuView
!=
null
&&
mDanmakuView
.
isPrepared
()
&&
mDanmakuView
.
isPaused
())
{
mDanmakuView
.
resume
();
}
}
@Override
public
void
release
()
{
super
.
release
();
if
(
mDanmakuView
!=
null
)
{
mDanmakuView
.
release
();
}
}
@Override
public
void
onSeekComplete
()
{
super
.
onSeekComplete
();
int
time
=
mProgressBar
.
getProgress
()
*
getDuration
()
/
100
;
//如果已经初始化过的,直接seek到对于位置
if
(
mHadPlay
&&
getDanmakuView
()
!=
null
&&
getDanmakuView
().
isPrepared
())
{
resolveDanmakuSeek
(
this
,
time
);
}
else
if
(
mHadPlay
&&
getDanmakuView
()
!=
null
&&
!
getDanmakuView
().
isPrepared
())
{
//如果没有初始化过的,记录位置等待
setDanmakuStartSeekPosition
(
time
);
}
}
/**
* 处理播放器在全屏切换时,弹幕显示的逻辑
*/
@Override
public
GSYBaseVideoPlayer
startWindowFullscreen
(
Context
context
,
boolean
actionBar
,
boolean
statusBar
)
{
GSYBaseVideoPlayer
gsyBaseVideoPlayer
=
super
.
startWindowFullscreen
(
context
,
actionBar
,
statusBar
);
if
(
gsyBaseVideoPlayer
!=
null
)
{
DanmakuVideoPlayer
gsyVideoPlayer
=
(
DanmakuVideoPlayer
)
gsyBaseVideoPlayer
;
//对弹幕设置偏移记录
gsyVideoPlayer
.
setDanmakuStartSeekPosition
(
getCurrentPositionWhenPlaying
());
onPrepareDanmaku
(
gsyVideoPlayer
);
}
return
gsyBaseVideoPlayer
;
}
/**
* 处理播放器在退出全屏时,弹幕显示的逻辑
*/
@Override
protected
void
resolveNormalVideoShow
(
View
oldF
,
ViewGroup
vp
,
GSYVideoPlayer
gsyVideoPlayer
)
{
super
.
resolveNormalVideoShow
(
oldF
,
vp
,
gsyVideoPlayer
);
if
(
gsyVideoPlayer
!=
null
)
{
DanmakuVideoPlayer
gsyDanmaVideoPlayer
=
(
DanmakuVideoPlayer
)
gsyVideoPlayer
;
if
(
gsyDanmaVideoPlayer
.
getDanmakuView
()
!=
null
&&
gsyDanmaVideoPlayer
.
getDanmakuView
().
isPrepared
())
{
resolveDanmakuSeek
(
this
,
gsyDanmaVideoPlayer
.
getCurrentPositionWhenPlaying
());
}
}
}
private
void
setDanmuKuUp
()
{
mDanmakuView
.
prepare
(
mParser
,
mDanmakuContext
);
//mDanmakuView.showFPS(true);
//mDanmakuView.enableDanmakuDrawingCache(true);
/**
* 开始播放弹幕
*/
private
void
onPrepareDanmaku
(
DanmakuVideoPlayer
gsyVideoPlayer
)
{
if
(
gsyVideoPlayer
.
getDanmakuView
()
!=
null
&&
!
gsyVideoPlayer
.
getDanmakuView
().
isPrepared
())
{
gsyVideoPlayer
.
getDanmakuView
().
prepare
(
gsyVideoPlayer
.
getParser
(),
gsyVideoPlayer
.
getDanmakuContext
());
}
}
/**
* 弹幕偏移
*/
private
void
resolveDanmakuSeek
(
DanmakuVideoPlayer
gsyVideoPlayer
,
long
time
)
{
if
(
GSYVideoManager
.
instance
().
getMediaPlayer
()
!=
null
&&
mHadPlay
&&
gsyVideoPlayer
.
getDanmakuView
()
!=
null
&&
gsyVideoPlayer
.
getDanmakuView
().
isPrepared
())
{
gsyVideoPlayer
.
getDanmakuView
().
seekTo
(
time
);
}
}
/**
* 创建解析器对象,解析输入流
...
...
@@ -226,15 +259,23 @@ public class DanmakuVideoPlayer extends StandardGSYVideoPlayer {
}
private
SpannableStringBuilder
createSpannable
(
Drawable
drawable
)
{
String
text
=
"bitmap"
;
SpannableStringBuilder
spannableStringBuilder
=
new
SpannableStringBuilder
(
text
);
ImageSpan
span
=
new
ImageSpan
(
drawable
);
//ImageSpan.ALIGN_BOTTOM);
spannableStringBuilder
.
setSpan
(
span
,
0
,
text
.
length
(),
Spannable
.
SPAN_INCLUSIVE_EXCLUSIVE
);
spannableStringBuilder
.
append
(
"图文混排"
);
spannableStringBuilder
.
setSpan
(
new
BackgroundColorSpan
(
Color
.
parseColor
(
"#8A2233B1"
)),
0
,
spannableStringBuilder
.
length
(),
Spannable
.
SPAN_INCLUSIVE_INCLUSIVE
);
return
spannableStringBuilder
;
public
BaseDanmakuParser
getParser
()
{
return
mParser
;
}
public
DanmakuContext
getDanmakuContext
()
{
return
mDanmakuContext
;
}
public
IDanmakuView
getDanmakuView
()
{
return
mDanmakuView
;
}
public
long
getDanmakuStartSeekPosition
()
{
return
mDanmakuStartSeekPosition
;
}
public
void
setDanmakuStartSeekPosition
(
long
danmakuStartSeekPosition
)
{
this
.
mDanmakuStartSeekPosition
=
danmakuStartSeekPosition
;
}
}
gsyVideoPlayer/src/main/java/com/shuyu/gsyvideoplayer/video/GSYBaseVideoPlayer.java
浏览文件 @
1becbed5
...
...
@@ -228,7 +228,7 @@ public abstract class GSYBaseVideoPlayer extends FrameLayout implements GSYMedia
/**
* 恢复
*/
pr
ivate
void
resolveNormalVideoShow
(
View
oldF
,
ViewGroup
vp
,
GSYVideoPlayer
gsyVideoPlayer
)
{
pr
otected
void
resolveNormalVideoShow
(
View
oldF
,
ViewGroup
vp
,
GSYVideoPlayer
gsyVideoPlayer
)
{
if
(
oldF
!=
null
&&
oldF
.
getParent
()
!=
null
)
{
ViewGroup
viewGroup
=
(
ViewGroup
)
oldF
.
getParent
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录