Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
NotesChapter
GSYVideoPlayer
提交
7f82058b
G
GSYVideoPlayer
项目概览
NotesChapter
/
GSYVideoPlayer
与 Fork 源项目一致
从无法访问的项目Fork
通知
8
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 搜索 >>
提交
7f82058b
编写于
12月 06, 2018
作者:
G
guoshuyu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
优化exoplayer的类型提取
增加exoplayer的类型覆盖支持
上级
d2a0d378
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
97 addition
and
27 deletion
+97
-27
app/src/main/java/com/example/gsyvideoplayer/DetailPlayer.java
...rc/main/java/com/example/gsyvideoplayer/DetailPlayer.java
+2
-2
app/src/main/java/com/example/gsyvideoplayer/exo/GSYExo2MediaPlayer.java
...va/com/example/gsyvideoplayer/exo/GSYExo2MediaPlayer.java
+1
-1
app/src/main/java/com/example/gsyvideoplayer/exo/GSYExoModel.java
...main/java/com/example/gsyvideoplayer/exo/GSYExoModel.java
+1
-1
app/src/main/java/com/example/gsyvideoplayer/video/FloatingVideo.java
.../java/com/example/gsyvideoplayer/video/FloatingVideo.java
+1
-1
app/src/main/java/com/example/gsyvideoplayer/video/SmartPickVideo.java
...java/com/example/gsyvideoplayer/video/SmartPickVideo.java
+1
-1
gsyVideoPlayer-base/src/main/java/com/shuyu/gsyvideoplayer/model/GSYModel.java
...rc/main/java/com/shuyu/gsyvideoplayer/model/GSYModel.java
+12
-1
gsyVideoPlayer-exo_player2/build.gradle
gsyVideoPlayer-exo_player2/build.gradle
+2
-2
gsyVideoPlayer-exo_player2/src/main/java/tv/danmaku/ijk/media/exo2/Exo2PlayerManager.java
...ain/java/tv/danmaku/ijk/media/exo2/Exo2PlayerManager.java
+1
-0
gsyVideoPlayer-exo_player2/src/main/java/tv/danmaku/ijk/media/exo2/ExoSourceManager.java
...main/java/tv/danmaku/ijk/media/exo2/ExoSourceManager.java
+12
-12
gsyVideoPlayer-exo_player2/src/main/java/tv/danmaku/ijk/media/exo2/IjkExo2MediaPlayer.java
...in/java/tv/danmaku/ijk/media/exo2/IjkExo2MediaPlayer.java
+13
-1
gsyVideoPlayer-java/build.gradle
gsyVideoPlayer-java/build.gradle
+2
-2
gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/GSYVideoBaseManager.java
...in/java/com/shuyu/gsyvideoplayer/GSYVideoBaseManager.java
+7
-2
gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/builder/GSYVideoOptionBuilder.java
...m/shuyu/gsyvideoplayer/builder/GSYVideoOptionBuilder.java
+13
-0
gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/video/base/GSYVideoView.java
...ava/com/shuyu/gsyvideoplayer/video/base/GSYVideoView.java
+16
-1
gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/video/base/GSYVideoViewBridge.java
...m/shuyu/gsyvideoplayer/video/base/GSYVideoViewBridge.java
+13
-0
未找到文件。
app/src/main/java/com/example/gsyvideoplayer/DetailPlayer.java
浏览文件 @
7f82058b
...
...
@@ -244,7 +244,7 @@ public class DetailPlayer extends AppCompatActivity {
//String url = "ijkhttphook:https://res.exexm.com/cw_145225549855002";
//String url = "http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f20.mp4";
String
url
=
"http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f20.mp4"
;
//
String url = "http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f20.mp4";
//String url = "http://7xjmzj.com1.z0.glb.clouddn.com/20171026175005_JObCxCE2.mp4";
//String url = "http://hjq-1257036536.cos.ap-shanghai.myqcloud.com/m3u8/m1/out2.m3u8";
//String url = "http://223.110.243.138/PLTV/2510088/224/3221227177/index.m3u8";
...
...
@@ -257,7 +257,7 @@ public class DetailPlayer extends AppCompatActivity {
//String url = "http://ipsimg-huabei2.speiyou.cn/010/video/other/20180424/40288b156290270d0162a3db8cdd033e/40288b156290270d0162a3e8207f074f/e787a64c-f2d0-48fe-896d-246af05f111a.mp4";
//String url = "http://video.7k.cn/app_video/20171202/6c8cf3ea/v.m3u8.mp4";
//
String url = "http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8";
String
url
=
"http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"
;
//String url = "https://cdn61.ytbbs.tv/cn/tv/55550/55550-1/play.m3u8?md5=v4sI4lWlo4XojzeAjgBGaQ&expires=1521204012&token=55550";
//String url = "http://1253492636.vod2.myqcloud.com/2e5fc148vodgzp1253492636/d08af82d4564972819086152830/plHZZoSkje0A.mp4";
...
...
app/src/main/java/com/example/gsyvideoplayer/exo/GSYExo2MediaPlayer.java
浏览文件 @
7f82058b
...
...
@@ -59,7 +59,7 @@ public class GSYExo2MediaPlayer extends IjkExo2MediaPlayer {
}
ConcatenatingMediaSource
concatenatedSource
=
new
ConcatenatingMediaSource
();
for
(
String
uri
:
uris
)
{
MediaSource
mediaSource
=
mExoHelper
.
getMediaSource
(
uri
,
isPreview
,
cache
,
false
,
mCacheDir
);
MediaSource
mediaSource
=
mExoHelper
.
getMediaSource
(
uri
,
isPreview
,
cache
,
false
,
mCacheDir
,
null
);
concatenatedSource
.
addMediaSource
(
mediaSource
);
}
mMediaSource
=
concatenatedSource
;
...
...
app/src/main/java/com/example/gsyvideoplayer/exo/GSYExoModel.java
浏览文件 @
7f82058b
...
...
@@ -17,7 +17,7 @@ public class GSYExoModel extends GSYModel {
List
<
String
>
urls
=
new
ArrayList
<>();
public
GSYExoModel
(
List
<
String
>
urls
,
Map
<
String
,
String
>
mapHeadData
,
boolean
loop
,
float
speed
,
boolean
cache
,
File
cachePath
)
{
super
(
""
,
mapHeadData
,
loop
,
speed
,
cache
,
cachePath
);
super
(
""
,
mapHeadData
,
loop
,
speed
,
cache
,
cachePath
,
""
);
this
.
urls
=
urls
;
}
...
...
app/src/main/java/com/example/gsyvideoplayer/video/FloatingVideo.java
浏览文件 @
7f82058b
...
...
@@ -84,7 +84,7 @@ public class FloatingVideo extends StandardGSYVideoPlayer {
mAudioManager
.
requestAudioFocus
(
onAudioFocusChangeListener
,
AudioManager
.
STREAM_MUSIC
,
AudioManager
.
AUDIOFOCUS_GAIN_TRANSIENT
);
//((Activity) getActivityContext()).getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mBackUpPlayingBufferState
=
-
1
;
getGSYVideoManager
().
prepare
(
mUrl
,
mMapHeadData
,
mLooping
,
mSpeed
,
mCache
,
mCachePath
);
getGSYVideoManager
().
prepare
(
mUrl
,
mMapHeadData
,
mLooping
,
mSpeed
,
mCache
,
mCachePath
,
null
);
setStateAndUi
(
CURRENT_STATE_PREPAREING
);
}
...
...
app/src/main/java/com/example/gsyvideoplayer/video/SmartPickVideo.java
浏览文件 @
7f82058b
...
...
@@ -302,7 +302,7 @@ public class SmartPickVideo extends StandardGSYVideoPlayer {
mTmpManager
=
GSYVideoManager
.
tmpInstance
(
gsyMediaPlayerListener
);
mTmpManager
.
initContext
(
getContext
().
getApplicationContext
());
resolveChangeUrl
(
mCache
,
mCachePath
,
url
);
mTmpManager
.
prepare
(
mUrl
,
mMapHeadData
,
mLooping
,
mSpeed
,
mCache
,
mCachePath
);
mTmpManager
.
prepare
(
mUrl
,
mMapHeadData
,
mLooping
,
mSpeed
,
mCache
,
mCachePath
,
null
);
changeUiToPlayingBufferingShow
();
}
}
else
{
...
...
gsyVideoPlayer-base/src/main/java/com/shuyu/gsyvideoplayer/model/GSYModel.java
浏览文件 @
7f82058b
...
...
@@ -22,13 +22,16 @@ public class GSYModel {
boolean
isCache
;
public
GSYModel
(
String
url
,
Map
<
String
,
String
>
mapHeadData
,
boolean
loop
,
float
speed
,
boolean
isCache
,
File
cachePath
)
{
String
overrideExtension
;
public
GSYModel
(
String
url
,
Map
<
String
,
String
>
mapHeadData
,
boolean
loop
,
float
speed
,
boolean
isCache
,
File
cachePath
,
String
overrideExtension
)
{
this
.
url
=
url
;
this
.
mapHeadData
=
mapHeadData
;
this
.
looping
=
loop
;
this
.
speed
=
speed
;
this
.
isCache
=
isCache
;
this
.
mCachePath
=
cachePath
;
this
.
overrideExtension
=
overrideExtension
;
}
public
String
getUrl
()
{
...
...
@@ -78,4 +81,12 @@ public class GSYModel {
public
void
setCachePath
(
File
cachePath
)
{
this
.
mCachePath
=
cachePath
;
}
public
String
getOverrideExtension
()
{
return
overrideExtension
;
}
public
void
setOverrideExtension
(
String
overrideExtension
)
{
this
.
overrideExtension
=
overrideExtension
;
}
}
gsyVideoPlayer-exo_player2/build.gradle
浏览文件 @
7f82058b
...
...
@@ -33,8 +33,8 @@ dependencies {
def
viewDependencies
=
rootProject
.
ext
.
viewDependencies
api
viewDependencies
.
exo_player2
api
viewDependencies
.
exo_player2_rtmp
//
api project(':gsyVideoPlayer-base')
api
"com.shuyu:gsyVideoPlayer-base:$gsyVideoVersion"
api
project
(
':gsyVideoPlayer-base'
)
//
api "com.shuyu:gsyVideoPlayer-base:$gsyVideoVersion"
// compile fileTree(dir: 'libs', include: ['*.jar'])
// def viewDependencies = rootProject.ext.viewDependencies
...
...
gsyVideoPlayer-exo_player2/src/main/java/tv/danmaku/ijk/media/exo2/Exo2PlayerManager.java
浏览文件 @
7f82058b
...
...
@@ -53,6 +53,7 @@ public class Exo2PlayerManager implements IPlayerManager {
//通过自己的内部缓存机制
mediaPlayer
.
setCache
(
gsyModel
.
isCache
());
mediaPlayer
.
setCacheDir
(
gsyModel
.
getCachePath
());
mediaPlayer
.
setOverrideExtension
(
gsyModel
.
getOverrideExtension
());
mediaPlayer
.
setDataSource
(
context
,
Uri
.
parse
(
gsyModel
.
getUrl
()),
gsyModel
.
getMapHeadData
());
}
if
(
gsyModel
.
getSpeed
()
!=
1
&&
gsyModel
.
getSpeed
()
>
0
)
{
...
...
gsyVideoPlayer-exo_player2/src/main/java/tv/danmaku/ijk/media/exo2/ExoSourceManager.java
浏览文件 @
7f82058b
package
tv.danmaku.ijk.media.exo2
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.net.Uri
;
import
android.support.annotation.Nullable
;
...
...
@@ -74,7 +75,7 @@ public class ExoSourceManager {
* @param isLooping 是否循环
* @param cacheDir 自定义缓存目录
*/
public
MediaSource
getMediaSource
(
String
dataSource
,
boolean
preview
,
boolean
cacheEnable
,
boolean
isLooping
,
File
cacheDir
)
{
public
MediaSource
getMediaSource
(
String
dataSource
,
boolean
preview
,
boolean
cacheEnable
,
boolean
isLooping
,
File
cacheDir
,
@Nullable
String
overrideExtension
)
{
MediaSource
mediaSource
=
null
;
if
(
sExoMediaSourceInterceptListener
!=
null
)
{
mediaSource
=
sExoMediaSourceInterceptListener
.
getMediaSource
(
dataSource
,
preview
,
cacheEnable
,
isLooping
,
cacheDir
);
...
...
@@ -84,7 +85,7 @@ public class ExoSourceManager {
}
mDataSource
=
dataSource
;
Uri
contentUri
=
Uri
.
parse
(
dataSource
);
int
contentType
=
inferContentType
(
dataSource
);
int
contentType
=
inferContentType
(
dataSource
,
overrideExtension
);
switch
(
contentType
)
{
case
C
.
TYPE_SS
:
mediaSource
=
new
SsMediaSource
.
Factory
(
...
...
@@ -136,23 +137,22 @@ public class ExoSourceManager {
}
@SuppressLint
(
"WrongConstant"
)
@C
.
ContentType
public
static
int
inferContentType
(
String
fileName
)
{
public
static
int
inferContentType
(
String
fileName
,
@Nullable
String
overrideExtension
)
{
fileName
=
Util
.
toLowerInvariant
(
fileName
);
if
(
fileName
.
endsWith
(
".mpd"
))
{
return
C
.
TYPE_DASH
;
}
else
if
(
fileName
.
endsWith
(
".m3u8"
))
{
return
C
.
TYPE_HLS
;
}
else
if
(
fileName
.
endsWith
(
".ism"
)
||
fileName
.
endsWith
(
".isml"
)
||
fileName
.
endsWith
(
".ism/manifest"
)
||
fileName
.
endsWith
(
".isml/manifest"
))
{
return
C
.
TYPE_SS
;
}
else
if
(
fileName
.
startsWith
(
"rtmp:"
))
{
if
(
fileName
.
startsWith
(
"rtmp:"
))
{
return
TYPE_RTMP
;
}
else
{
return
C
.
TYPE_OTHER
;
return
inferContentType
(
Uri
.
parse
(
fileName
),
overrideExtension
)
;
}
}
@C
.
ContentType
public
static
int
inferContentType
(
Uri
uri
,
@Nullable
String
overrideExtension
)
{
return
Util
.
inferContentType
(
uri
,
overrideExtension
);
}
/**
* 本地缓存目录
*/
...
...
gsyVideoPlayer-exo_player2/src/main/java/tv/danmaku/ijk/media/exo2/IjkExo2MediaPlayer.java
浏览文件 @
7f82058b
...
...
@@ -90,6 +90,10 @@ public class IjkExo2MediaPlayer extends AbstractMediaPlayer implements Player.Ev
* 缓存目录,可以为空
*/
protected
File
mCacheDir
;
/**
* 类型覆盖
*/
private
String
mOverrideExtension
;
protected
int
audioSessionId
=
C
.
AUDIO_SESSION_ID_UNSET
;
...
...
@@ -149,7 +153,7 @@ public class IjkExo2MediaPlayer extends AbstractMediaPlayer implements Player.Ev
@Override
public
void
setDataSource
(
Context
context
,
Uri
uri
)
{
mDataSource
=
uri
.
toString
();
mMediaSource
=
mExoHelper
.
getMediaSource
(
mDataSource
,
isPreview
,
isCache
,
isLooping
,
mCacheDir
);
mMediaSource
=
mExoHelper
.
getMediaSource
(
mDataSource
,
isPreview
,
isCache
,
isLooping
,
mCacheDir
,
mOverrideExtension
);
}
@Override
...
...
@@ -365,6 +369,14 @@ public class IjkExo2MediaPlayer extends AbstractMediaPlayer implements Player.Ev
);
}
public
String
getOverrideExtension
()
{
return
mOverrideExtension
;
}
public
void
setOverrideExtension
(
String
overrideExtension
)
{
this
.
mOverrideExtension
=
overrideExtension
;
}
public
void
stopPlayback
()
{
mInternalPlayer
.
stop
();
}
...
...
gsyVideoPlayer-java/build.gradle
浏览文件 @
7f82058b
...
...
@@ -37,8 +37,8 @@ dependencies {
api
viewDependencies
.
ijkplayer_exo
api
viewDependencies
.
transitionseverywhere
//api project(':gsyVideoPlayer-proxy_cache')
//
api project(':gsyVideoPlayer-base')
api
"com.shuyu:gsyVideoPlayer-base:$gsyVideoVersion"
api
project
(
':gsyVideoPlayer-base'
)
//
api "com.shuyu:gsyVideoPlayer-base:$gsyVideoVersion"
api
"com.shuyu:gsyvideoplayer-androidvideocache:$gsyVideoVersion"
...
...
gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/GSYVideoBaseManager.java
浏览文件 @
7f82058b
...
...
@@ -197,11 +197,16 @@ public abstract class GSYVideoBaseManager implements IMediaPlayer.OnPreparedList
}
@Override
public
void
prepare
(
final
String
url
,
final
Map
<
String
,
String
>
mapHeadData
,
boolean
loop
,
float
speed
,
boolean
cache
,
File
cachePath
)
{
public
void
prepare
(
String
url
,
Map
<
String
,
String
>
mapHeadData
,
boolean
loop
,
float
speed
,
boolean
cache
,
File
cachePath
)
{
prepare
(
url
,
mapHeadData
,
loop
,
speed
,
cache
,
cachePath
,
null
);
}
@Override
public
void
prepare
(
final
String
url
,
final
Map
<
String
,
String
>
mapHeadData
,
boolean
loop
,
float
speed
,
boolean
cache
,
File
cachePath
,
String
overrideExtension
)
{
if
(
TextUtils
.
isEmpty
(
url
))
return
;
Message
msg
=
new
Message
();
msg
.
what
=
HANDLER_PREPARE
;
GSYModel
fb
=
new
GSYModel
(
url
,
mapHeadData
,
loop
,
speed
,
cache
,
cachePath
);
GSYModel
fb
=
new
GSYModel
(
url
,
mapHeadData
,
loop
,
speed
,
cache
,
cachePath
,
overrideExtension
);
msg
.
obj
=
fb
;
sendMessage
(
msg
);
if
(
needTimeOutOther
)
{
...
...
gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/builder/GSYVideoOptionBuilder.java
浏览文件 @
7f82058b
...
...
@@ -122,6 +122,9 @@ public class GSYVideoOptionBuilder {
//视频title
protected
String
mVideoTitle
=
null
;
// 是否需要覆盖拓展类型
protected
String
mOverrideExtension
;
//是否自定义的缓冲文件路径
protected
File
mCachePath
;
...
...
@@ -527,6 +530,15 @@ public class GSYVideoOptionBuilder {
return
this
;
}
/**
* 是否需要覆盖拓展类型,目前只针对exoPlayer内核模式有效
* @param overrideExtension 比如传入 m3u8,mp4,avi 等类型
*/
public
GSYVideoOptionBuilder
setOverrideExtension
(
String
overrideExtension
)
{
this
.
mOverrideExtension
=
overrideExtension
;
return
this
;
}
/**
* 在播放前才真正执行setup
* 目前弃用,请使用正常setup
...
...
@@ -600,6 +612,7 @@ public class GSYVideoOptionBuilder {
if
(
mGSYVideoProgressListener
!=
null
)
{
gsyVideoPlayer
.
setGSYVideoProgressListener
(
mGSYVideoProgressListener
);
}
gsyVideoPlayer
.
setOverrideExtension
(
mOverrideExtension
);
gsyVideoPlayer
.
setAutoFullWithSize
(
mAutoFullWithSize
);
gsyVideoPlayer
.
setRotateViewAuto
(
mRotateViewAuto
);
gsyVideoPlayer
.
setLockLand
(
mLockLand
);
...
...
gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/video/base/GSYVideoView.java
浏览文件 @
7f82058b
...
...
@@ -140,6 +140,9 @@ public abstract class GSYVideoView extends GSYTextureRenderView implements GSYMe
//网络状态
protected
String
mNetSate
=
"NORMAL"
;
// 是否需要覆盖拓展类型
protected
String
mOverrideExtension
;
//缓存路径,可不设置
protected
File
mCachePath
;
...
...
@@ -328,7 +331,7 @@ public abstract class GSYVideoView extends GSYTextureRenderView implements GSYMe
mAudioManager
.
requestAudioFocus
(
onAudioFocusChangeListener
,
AudioManager
.
STREAM_MUSIC
,
AudioManager
.
AUDIOFOCUS_GAIN_TRANSIENT
);
((
Activity
)
getActivityContext
()).
getWindow
().
addFlags
(
WindowManager
.
LayoutParams
.
FLAG_KEEP_SCREEN_ON
);
mBackUpPlayingBufferState
=
-
1
;
getGSYVideoManager
().
prepare
(
mUrl
,
(
mMapHeadData
==
null
)
?
new
HashMap
<
String
,
String
>()
:
mMapHeadData
,
mLooping
,
mSpeed
,
mCache
,
mCachePath
);
getGSYVideoManager
().
prepare
(
mUrl
,
(
mMapHeadData
==
null
)
?
new
HashMap
<
String
,
String
>()
:
mMapHeadData
,
mLooping
,
mSpeed
,
mCache
,
mCachePath
,
mOverrideExtension
);
setStateAndUi
(
CURRENT_STATE_PREPAREING
);
}
...
...
@@ -1116,4 +1119,16 @@ public abstract class GSYVideoView extends GSYTextureRenderView implements GSYMe
this
.
mMapHeadData
=
headData
;
}
}
public
String
getOverrideExtension
()
{
return
mOverrideExtension
;
}
/**
* 是否需要覆盖拓展类型,目前只针对exoPlayer内核模式有效
* @param overrideExtension 比如传入 m3u8,mp4,avi 等类型
*/
public
void
setOverrideExtension
(
String
overrideExtension
)
{
this
.
mOverrideExtension
=
overrideExtension
;
}
}
gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/video/base/GSYVideoViewBridge.java
浏览文件 @
7f82058b
...
...
@@ -44,6 +44,19 @@ public interface GSYVideoViewBridge {
*/
void
prepare
(
final
String
url
,
final
Map
<
String
,
String
>
mapHeadData
,
boolean
loop
,
float
speed
,
boolean
cache
,
File
cachePath
);
/**
* 开始准备播放
*
* @param url 播放url
* @param mapHeadData 头部信息
* @param loop 是否循环
* @param speed 播放速度
* @param cache 是否缓存
* @param cachePath 缓存目录,可以为空,为空时使用默认
* @param overrideExtension 是否需要覆盖拓展类型
*/
void
prepare
(
final
String
url
,
final
Map
<
String
,
String
>
mapHeadData
,
boolean
loop
,
float
speed
,
boolean
cache
,
File
cachePath
,
String
overrideExtension
);
/**
* 获取当前播放内核
*/
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录