提交 76b9e47d authored 作者: 汪显鹏's avatar 汪显鹏

GSY 多任务播放模式

上级 b66b178d
......@@ -42,21 +42,23 @@ dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.shuyu:gsyVideoPlayer-java:7.0.1'
implementation 'com.shuyu:gsyVideoPlayer-java:7.1.1'
//是否需要ExoPlayer模式
implementation 'com.shuyu:GSYVideoPlayer-exo2:7.0.1'
implementation 'com.shuyu:GSYVideoPlayer-exo2:7.1.1'
implementation 'com.shuyu:gsyVideoPlayer-armv7a:7.0.1'
implementation 'com.shuyu:gsyVideoPlayer-java:7.0.1'
implementation 'com.shuyu:gsyVideoPlayer-armv7a:7.1.1'
implementation 'com.shuyu:gsyVideoPlayer-java:7.1.1'
//是否需要ExoPlayer模式
implementation 'com.shuyu:GSYVideoPlayer-exo2:7.0.1'
implementation 'com.shuyu:GSYVideoPlayer-exo2:7.1.1'
//更多ijk的编码支持
implementation 'com.shuyu:gsyVideoPlayer-ex_so:7.0.1'
implementation 'com.shuyu:gsyVideoPlayer-ex_so:7.1.1'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
......
......@@ -3,7 +3,6 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.ubains.rtspdemo">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:appComponentFactory=""
......@@ -15,16 +14,40 @@
tools:ignore="GoogleAppIndexingWarning"
tools:replace="android:appComponentFactory">
<activity
android:name=".MainActivity"
android:name=".MutliActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="landscape"
android:theme="@style/Theme.AppCompat.NoActionBar">
</activity>
<activity
android:name=".ListMultiVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="landscape"
android:theme="@style/Theme.AppCompat.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".EmptyActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="landscape"
android:theme="@style/Theme.AppCompat.NoActionBar">
</activity>
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="landscape"
android:theme="@style/Theme.AppCompat.NoActionBar"></activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
\ No newline at end of file
package com.ubains.rtspdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.ViewCompat;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.cache.CacheFactory;
import com.shuyu.gsyvideoplayer.cache.ProxyCacheManager;
import com.shuyu.gsyvideoplayer.model.VideoOptionModel;
import com.shuyu.gsyvideoplayer.player.IjkPlayerManager;
import com.shuyu.gsyvideoplayer.player.PlayerFactory;
import com.shuyu.gsyvideoplayer.utils.OrientationUtils;
import com.ubains.rtspdemo.vedio.EmptyControlVideo;
import java.util.ArrayList;
import java.util.List;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
public class EmptyActivity extends AppCompatActivity {
public final static String IMG_TRANSITION = "IMG_TRANSITION";
public final static String TRANSITION = "TRANSITION";
OrientationUtils orientationUtils;
private boolean isTransition;
private android.transition.Transition transition;
private EmptyControlVideo videoPlayer1,videoPlayer2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_empty);
videoPlayer1 = findViewById(R.id.detail_player1);
videoPlayer2 = findViewById(R.id.detail_player2);
isTransition = getIntent().getBooleanExtra(TRANSITION, false);
init();
}
private void init() {
//PlayerFactory.setPlayManager(Exo2PlayerManager.class);
//系统内核模式
//PlayerFactory.setPlayManager(SystemPlayerManager.class);
//ijk内核,默认模式 ijk 模式才支持RTSP 播放
PlayerFactory.setPlayManager(IjkPlayerManager.class);
//exo缓存模式,支持m3u8,只支持exo
// CacheFactory.setCacheManager(ExoPlayerCacheManager.class);
//代理缓存模式,支持所有模式,不支持m3u8等,默认
CacheFactory.setCacheManager(ProxyCacheManager.class);
List<VideoOptionModel> list = new ArrayList<>();
//设置RTSP 连接方式
VideoOptionModel videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_flags", "prefer_tcp");
list.add(videoOptionModel);
//硬解码:1、打开,0、关闭
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
list.add(videoOptionModel);
//软解码:1、打开,0、关闭
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "videotoolbox", 1);
list.add(videoOptionModel);
//根据媒体类型来配置
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "allowed_media_types", "video");
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 20000);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "buffer_size", 1316);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "infbuf", 1); // 无限读
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzemaxduration", 100);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 10240);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);
list.add(videoOptionModel);
// 关闭播放器缓冲,这个必须关闭,否则会出现播放一段时间后,一直卡主,控制台打印 FFP_MSG_BUFFERING_START
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);
list.add(videoOptionModel);
GSYVideoManager.instance().setOptionModelList(list);
String url = "rtsp://admin:huawei@123@192.168.11.20/LiveMedia/ch1/Media1";
String ur2 = "rtsp://admin:huawei@123@192.168.11.20/LiveMedia/ch1/Media1";
videoPlayer1.setUp(url, true, "");
videoPlayer2.setUp(ur2, true, "");
//过渡动画
initTransition();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
}
@TargetApi(Build.VERSION_CODES.KITKAT)
@Override
protected void onDestroy() {
super.onDestroy();
videoPlayer2.release();
videoPlayer1.release();
if (orientationUtils != null)
orientationUtils.releaseListener();
}
@Override
public void onBackPressed() {
//释放所有
videoPlayer1.setVideoAllCallBack(null);
videoPlayer2.setVideoAllCallBack(null);
GSYVideoManager.releaseAllVideos();
if (isTransition && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
super.onBackPressed();
} else {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
finish();
overridePendingTransition(R.anim.abc_fade_in, R.anim.abc_fade_out);
}
}, 500);
}
}
private void initTransition() {
if (isTransition && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
postponeEnterTransition();
ViewCompat.setTransitionName(videoPlayer1, IMG_TRANSITION);
ViewCompat.setTransitionName(videoPlayer2, IMG_TRANSITION);
// addTransitionListener();
startPostponedEnterTransition();
} else {
videoPlayer1.startPlayLogic();
videoPlayer2.startPlayLogic();
}
}
// @TargetApi(Build.VERSION_CODES.LOLLIPOP)
// private boolean addTransitionListener() {
// transition = getWindow().getSharedElementEnterTransition();
// if (transition != null) {
// transition.addListener(new OnTransitionListener(){
// @Override
// public void onTransitionEnd(Transition transition) {
// super.onTransitionEnd(transition);
// videoPlayer.startPlayLogic();
// Transition transition1 = transition.removeListener(this);
// }
// });
// return true;
// }
// return false;
// }
}
package com.ubains.rtspdemo;
import android.os.Build;
import android.os.Bundle;
import android.transition.Explode;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.ListView;
import androidx.appcompat.app.AppCompatActivity;
import com.ubains.rtspdemo.vedio.ListMultiNormalAdapter;
import com.ubains.rtspdemo.vedio.manager.CustomManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 多个同时播放的demo
*/
public class ListMultiVideoActivity extends AppCompatActivity {
ListMultiNormalAdapter listMultiNormalAdapter;
private boolean isPause;
private ListView videoList;
@Override
protected void onCreate(Bundle savedInstanceState) {
// 设置一个exit transition
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setEnterTransition(new Explode());
getWindow().setExitTransition(new Explode());
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_video);
videoList = findViewById(R.id.video_list);
listMultiNormalAdapter = new ListMultiNormalAdapter(this);
videoList.setAdapter(listMultiNormalAdapter);
videoList.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
int lastVisibleItem = firstVisibleItem + visibleItemCount;
//大于0说明有播放
if (CustomManager.instance().size() >= 0) {
Map<String, CustomManager> map = CustomManager.instance();
List<String> removeKey = new ArrayList<>();
for (Map.Entry<String, CustomManager> customManagerEntry : map.entrySet()) {
CustomManager customManager = customManagerEntry.getValue();
//当前播放的位置
int position = customManager.getPlayPosition();
//对应的播放列表TAG
if (customManager.getPlayTag().equals(ListMultiNormalAdapter.TAG) && (position < firstVisibleItem || position > lastVisibleItem)) {
CustomManager.releaseAllVideos(customManagerEntry.getKey());
removeKey.add(customManagerEntry.getKey());
}
}
if(removeKey.size() > 0) {
for (String key : removeKey) {
map.remove(key);
}
listMultiNormalAdapter.notifyDataSetChanged();
}
}
}
});
}
@Override
public void onBackPressed() {
if (CustomManager.backFromWindowFull(this, listMultiNormalAdapter.getFullKey())) {
return;
}
super.onBackPressed();
}
@Override
protected void onPause() {
super.onPause();
CustomManager.onPauseAll();
isPause = true;
}
@Override
protected void onResume() {
super.onResume();
CustomManager.onResumeAll();
isPause = false;
}
@Override
protected void onDestroy() {
super.onDestroy();
CustomManager.clearAllVideo();
}
}
......@@ -3,8 +3,6 @@ package com.ubains.rtspdemo;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
......@@ -14,9 +12,8 @@ import com.shuyu.gsyvideoplayer.cache.ProxyCacheManager;
import com.shuyu.gsyvideoplayer.model.VideoOptionModel;
import com.shuyu.gsyvideoplayer.player.IjkPlayerManager;
import com.shuyu.gsyvideoplayer.player.PlayerFactory;
import com.shuyu.gsyvideoplayer.player.SystemPlayerManager;
import com.shuyu.gsyvideoplayer.utils.OrientationUtils;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;
import com.ubains.rtspdemo.vedio.EmptyControlVideo;
import java.util.ArrayList;
import java.util.List;
......@@ -28,7 +25,7 @@ import tv.danmaku.ijk.media.player.IjkMediaPlayer;
public class MainActivity extends AppCompatActivity {
private OrientationUtils orientationUtils;
private StandardGSYVideoPlayer videoPlayer;
private EmptyControlVideo videoPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -51,7 +48,7 @@ public class MainActivity extends AppCompatActivity {
private void init() {
videoPlayer = (StandardGSYVideoPlayer) findViewById(R.id.detail_player);
videoPlayer =findViewById(R.id.detail_player);
List<VideoOptionModel> list = new ArrayList<>();
......@@ -69,7 +66,8 @@ public class MainActivity extends AppCompatActivity {
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "videotoolbox", 1);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "allowed_media_types", "video"); //根据媒体类型来配置
//根据媒体类型来配置
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "allowed_media_types", "video");
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 20000);
......@@ -93,40 +91,48 @@ public class MainActivity extends AppCompatActivity {
/**
* 换成自己的流媒体地址
*/
String source1 = String.format(Locale.ENGLISH, "rtsp://admin:huawei@123@192.168.11.15/LiveMedia/ch1/Media1", "192.168.11.15");
String source1 = String.format(Locale.ENGLISH, "rtsp://admin:huawei@123@192.168.11.20/LiveMedia/ch1/Media1", "192.168.11.15");
//String source1 = String.format(Locale.ENGLISH, "rtsp://admin:HZ0000001988@192.168.10.21:554/h264/ch1/main/av_stream", "192.168.10.21");
videoPlayer.setUp(source1, true, "测试视频");
videoPlayer.setUp(source1, true, "");
//增加封面
ImageView imageView = new ImageView(this);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
// imageView.setImageResource(R.mipmap.xxx1);
videoPlayer.setThumbImageView(imageView);
//增加title
videoPlayer.getTitleTextView().setVisibility(View.VISIBLE);
//设置返回键
videoPlayer.getBackButton().setVisibility(View.VISIBLE);
// ImageView imageView = new ImageView(this);
// imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
// // imageView.setImageResource(R.mipmap.xxx1);
// videoPlayer.setThumbImageView(imageView);
// //增加title
// videoPlayer.getTitleTextView().setVisibility(View.INVISIBLE);
// //设置返回键
// videoPlayer.getBackButton().setVisibility(View.INVISIBLE);
//设置旋转
orientationUtils = new OrientationUtils(this, videoPlayer);
// orientationUtils.setEnable(false);
// orientationUtils.resolveByClick();
videoPlayer.startWindowFullscreen(this, false, false);
//设置全屏按键功能,这是使用的是选择屏幕,而不是全屏
videoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
orientationUtils.resolveByClick();
}
});
//是否可以滑动调整
videoPlayer.setIsTouchWiget(true);
//设置返回按键功能
videoPlayer.getBackButton().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
// videoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// orientationUtils.resolveByClick();
// }
// });
// //是否可以滑动调整
// videoPlayer.setIsTouchWiget(true);
// //设置返回按键功能
// videoPlayer.getBackButton().setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// onBackPressed();
// }
// });
videoPlayer.startPlayLogic();
}
......
package com.ubains.rtspdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Build;
import android.os.Bundle;
import android.transition.Explode;
import android.view.View;
import android.view.Window;
import com.shuyu.gsyvideoplayer.GSYVideoManager;
import com.shuyu.gsyvideoplayer.cache.CacheFactory;
import com.shuyu.gsyvideoplayer.cache.ProxyCacheManager;
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack;
import com.shuyu.gsyvideoplayer.model.VideoOptionModel;
import com.shuyu.gsyvideoplayer.player.IjkPlayerManager;
import com.shuyu.gsyvideoplayer.player.PlayerFactory;
import com.ubains.rtspdemo.vedio.MultiSampleVideo;
import com.ubains.rtspdemo.vedio.manager.CustomManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
public class MutliActivity extends AppCompatActivity {
MultiSampleVideo videoPlayer1, videoPlayer2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setEnterTransition(new Explode());
getWindow().setExitTransition(new Explode());
}
setContentView(R.layout.activity_mutli);
videoPlayer1 = findViewById(R.id.detail_player1);
videoPlayer2 = findViewById(R.id.detail_player2);
}
private void init() {
//PlayerFactory.setPlayManager(Exo2PlayerManager.class);
//系统内核模式
//PlayerFactory.setPlayManager(SystemPlayerManager.class);
//ijk内核,默认模式 ijk 模式才支持RTSP 播放
PlayerFactory.setPlayManager(IjkPlayerManager.class);
//exo缓存模式,支持m3u8,只支持exo
// CacheFactory.setCacheManager(ExoPlayerCacheManager.class);
//代理缓存模式,支持所有模式,不支持m3u8等,默认
CacheFactory.setCacheManager(ProxyCacheManager.class);
List<VideoOptionModel> list = new ArrayList<>();
//设置RTSP 连接方式
VideoOptionModel videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_flags", "prefer_tcp");
list.add(videoOptionModel);
//硬解码:1、打开,0、关闭
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
list.add(videoOptionModel);
//软解码:1、打开,0、关闭
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "videotoolbox", 1);
list.add(videoOptionModel);
//根据媒体类型来配置
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "allowed_media_types", "video");
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "timeout", 20000);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "buffer_size", 1316);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "infbuf", 1); // 无限读
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzemaxduration", 100);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 10240);
list.add(videoOptionModel);
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);
list.add(videoOptionModel);
// 关闭播放器缓冲,这个必须关闭,否则会出现播放一段时间后,一直卡主,控制台打印 FFP_MSG_BUFFERING_START
videoOptionModel = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);
list.add(videoOptionModel);
GSYVideoManager.instance().setOptionModelList(list);
String url = "rtsp://admin:huawei@123@192.168.11.20/LiveMedia/ch1/Media1";
String ur2 = "rtsp://admin:huawei@123@192.168.11.21/LiveMedia/ch1/Media1";
videoPlayer1.setPlayTag("videoPlayer1");
videoPlayer1.setPlayPosition(1);
videoPlayer2.setPlayTag("videoPlayer2");
videoPlayer2.setPlayPosition(2);
boolean isPlaying = videoPlayer1.getCurrentPlayer().isInPlayingState();
boolean isPlaying2 = videoPlayer2.getCurrentPlayer().isInPlayingState();
if (!isPlaying){
videoPlayer1.setUpLazy(url, false, null, null, "");
}
if (!isPlaying2){
videoPlayer2.setUpLazy(url, false, null, null, "");
}
videoPlayer1.getTitleTextView().setVisibility(View.GONE);
videoPlayer2.getTitleTextView().setVisibility(View.GONE);
videoPlayer1.getBackButton().setVisibility(View.GONE);
videoPlayer2.getBackButton().setVisibility(View.GONE);
videoPlayer2.setRotateViewAuto(true);
videoPlayer2.setLockLand(true);
videoPlayer2.setReleaseWhenLossAudio(false);
videoPlayer2.setShowFullAnimation(true);
videoPlayer2.setIsTouchWiget(false);
videoPlayer2.setNeedLockFull(true);
videoPlayer1.setRotateViewAuto(true);
videoPlayer1.setLockLand(true);
videoPlayer1.setReleaseWhenLossAudio(false);
videoPlayer1.setShowFullAnimation(true);
videoPlayer1.setIsTouchWiget(false);
videoPlayer1.setNeedLockFull(true);
videoPlayer1.startPlayLogic();
videoPlayer2.startPlayLogic();
// videoPlayer1.setVideoAllCallBack(new GSYSampleCallBack() {
//
//
// @Override
// public void onQuitFullscreen(String url, Object... objects) {
// super.onQuitFullscreen(url, objects);
// // fullKey = "null";
// }
//
// @Override
// public void onEnterFullscreen(String url, Object... objects) {
// super.onEnterFullscreen(url, objects);
// videoPlayer1.getCurrentPlayer().getTitleTextView().setText((String) objects[0]);
// //fullKey = holder.gsyVideoPlayer.getKey();
// }
//
// @Override
// public void onAutoComplete(String url, Object... objects) {
// super.onAutoComplete(url, objects);
// }
// });
//过渡动画
if (CustomManager.instance().size() >= 0) {
Map<String, CustomManager> map = CustomManager.instance();
List<String> removeKey = new ArrayList<>();
for (Map.Entry<String, CustomManager> customManagerEntry : map.entrySet()) {
CustomManager customManager = customManagerEntry.getValue();
//当前播放的位置
int position = customManager.getPlayPosition();
//对应的播放列表TAG
// if (customManager.getPlayTag().equals(ListMultiNormalAdapter.TAG) && (position < firstVisibleItem || position > lastVisibleItem)) {
CustomManager.releaseAllVideos(customManagerEntry.getKey());
removeKey.add(customManagerEntry.getKey());
// }
}
if(removeKey.size() > 0) {
for (String key : removeKey) {
map.remove(key);
}
//listMultiNormalAdapter.notifyDataSetChanged();
}
}
}
private boolean isPause;
// @Override
// public void onBackPressed() {
// if (CustomManager.backFromWindowFull(this, listMultiNormalAdapter.getFullKey())) {
// return;
// }
// super.onBackPressed();
// }
@Override
protected void onPause() {
super.onPause();
CustomManager.onPauseAll();
isPause = true;
}
@Override
protected void onResume() {
super.onResume();
CustomManager.onResumeAll();
isPause = false;
}
@Override
protected void onDestroy() {
super.onDestroy();
CustomManager.clearAllVideo();
}
}
package com.ubains.rtspdemo.vedio;
import android.content.Context;
import android.util.AttributeSet;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;
import com.ubains.rtspdemo.R;
public class EmptyControlVideo extends StandardGSYVideoPlayer {
public EmptyControlVideo(Context context, Boolean fullFlag) {
super(context, fullFlag);
}
public EmptyControlVideo(Context context) {
super(context);
}
public EmptyControlVideo(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public int getLayoutId() {
return R.layout.empty_video;
}
@Override
protected void touchSurfaceMoveFullLogic(float absDeltaX, float absDeltaY) {
super.touchSurfaceMoveFullLogic(absDeltaX, absDeltaY);
//不给触摸快进,如果需要,屏蔽下方代码即可
mChangePosition = false;
//不给触摸音量,如果需要,屏蔽下方代码即可
mChangeVolume = false;
//不给触摸亮度,如果需要,屏蔽下方代码即可
mBrightness = false;
}
@Override
protected void touchDoubleUp() {
//super.touchDoubleUp();
//不需要双击暂停
}
}
\ No newline at end of file
package com.ubains.rtspdemo.vedio;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;
import com.ubains.rtspdemo.R;
import java.util.ArrayList;
import java.util.List;
/**
* 多个播放的listview adapter
* Created by shuyu on 2016/11/12.
*/
public class ListMultiNormalAdapter extends BaseAdapter {
public static final String TAG = "ListMultiNormalAdapter";
private List<VideoModel> list = new ArrayList<>();
private LayoutInflater inflater = null;
private Context context;
private String fullKey = "null";
public ListMultiNormalAdapter(Context context) {
super();
this.context = context;
inflater = LayoutInflater.from(context);
for (int i = 0; i < 3; i++) {
list.add(new VideoModel());
}
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.list_video_item_mutli, null);
holder.gsyVideoPlayer = (MultiSampleVideo) convertView.findViewById(R.id.video_item_player);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// final String url = "http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f20.mp4";
final String url = "rtsp://admin:huawei@123@192.168.11.21/LiveMedia/ch1/Media1";
//多个播放时必须在setUpLazy、setUp和getGSYVideoManager()等前面设置
holder.gsyVideoPlayer.setPlayTag(TAG);
holder.gsyVideoPlayer.setPlayPosition(position);
boolean isPlaying = holder.gsyVideoPlayer.getCurrentPlayer().isInPlayingState();
if (!isPlaying) {
holder.gsyVideoPlayer.setUpLazy(url, false, null, null, "这是title");
}
//增加title
holder.gsyVideoPlayer.getTitleTextView().setVisibility(View.GONE);
//设置返回键
holder.gsyVideoPlayer.getBackButton().setVisibility(View.GONE);
//设置全屏按键功能
holder.gsyVideoPlayer.getFullscreenButton().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
resolveFullBtn(holder.gsyVideoPlayer);
}
});
holder.gsyVideoPlayer.setRotateViewAuto(true);
holder.gsyVideoPlayer.setLockLand(true);
holder.gsyVideoPlayer.setReleaseWhenLossAudio(false);
holder.gsyVideoPlayer.setShowFullAnimation(true);
holder.gsyVideoPlayer.setIsTouchWiget(false);
holder.gsyVideoPlayer.setNeedLockFull(true);
if (position % 2 == 0) {
holder.gsyVideoPlayer.loadCoverImage(url, R.mipmap.ic_launcher);
} else {
holder.gsyVideoPlayer.loadCoverImage(url, R.mipmap.ic_launcher);
}
holder.gsyVideoPlayer.setVideoAllCallBack(new GSYSampleCallBack() {
@Override
public void onQuitFullscreen(String url, Object... objects) {
super.onQuitFullscreen(url, objects);
fullKey = "null";
}
@Override
public void onEnterFullscreen(String url, Object... objects) {
super.onEnterFullscreen(url, objects);
holder.gsyVideoPlayer.getCurrentPlayer().getTitleTextView().setText((String) objects[0]);
fullKey = holder.gsyVideoPlayer.getKey();
}
@Override
public void onAutoComplete(String url, Object... objects) {
super.onAutoComplete(url, objects);
}
});
return convertView;
}
/**
* 全屏幕按键处理
*/
private void resolveFullBtn(final StandardGSYVideoPlayer standardGSYVideoPlayer) {
standardGSYVideoPlayer.startWindowFullscreen(context, false, true);
}
class ViewHolder {
MultiSampleVideo gsyVideoPlayer;
}
public String getFullKey() {
return fullKey;
}
}
package com.ubains.rtspdemo.vedio;
import android.content.Context;
import android.graphics.Point;
import android.media.AudioManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.shuyu.gsyvideoplayer.utils.Debuger;
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer;
import com.shuyu.gsyvideoplayer.video.base.GSYBaseVideoPlayer;
import com.shuyu.gsyvideoplayer.video.base.GSYVideoViewBridge;
import com.ubains.rtspdemo.R;
import com.ubains.rtspdemo.vedio.manager.CustomManager;
/**
* 多个同时播放的播放控件
* Created by guoshuyu on 2018/1/31.
*/
public class MultiSampleVideo extends StandardGSYVideoPlayer {
private final static String TAG = "MultiSampleVideo";
ImageView mCoverImage;
String mCoverOriginUrl;
int mDefaultRes;
public MultiSampleVideo(Context context, Boolean fullFlag) {
super(context, fullFlag);
}
public MultiSampleVideo(Context context) {
super(context);
}
public MultiSampleVideo(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void init(Context context) {
super.init(context);
mCoverImage = (ImageView) findViewById(R.id.thumbImage);
if (mThumbImageViewLayout != null &&
(mCurrentState == -1 || mCurrentState == CURRENT_STATE_NORMAL || mCurrentState == CURRENT_STATE_ERROR)) {
mThumbImageViewLayout.setVisibility(VISIBLE);
}
onAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
break;
case AudioManager.AUDIOFOCUS_LOSS:
//todo 判断如果不是外界造成的就不处理
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
//todo 判断如果不是外界造成的就不处理
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
break;
}
}
};
}
@Override
public GSYVideoViewBridge getGSYVideoManager() {
CustomManager.getCustomManager(getKey()).initContext(getContext().getApplicationContext());
return CustomManager.getCustomManager(getKey());
}
@Override
protected boolean backFromFull(Context context) {
return CustomManager.backFromWindowFull(context, getKey());
}
@Override
protected void releaseVideos() {
CustomManager.releaseAllVideos(getKey());
}
@Override
protected int getFullId() {
return CustomManager.FULLSCREEN_ID;
}
@Override
protected int getSmallId() {
return CustomManager.SMALL_ID;
}
@Override
public int getLayoutId() {
return R.layout.video_layout_cover;
}
public void loadCoverImage(String url, int res) {
mCoverOriginUrl = url;
mDefaultRes = res;
mCoverImage.setBackgroundResource(res);
// Glide.with(getContext().getApplicationContext())
// .setDefaultRequestOptions(
// new RequestOptions()
// .frame(1000000)
// .centerCrop()
// .error(res)
// .placeholder(res))
// .load(url)
// .into(mCoverImage);
}
@Override
public GSYBaseVideoPlayer startWindowFullscreen(Context context, boolean actionBar, boolean statusBar) {
GSYBaseVideoPlayer gsyBaseVideoPlayer = super.startWindowFullscreen(context, actionBar, statusBar);
MultiSampleVideo multiSampleVideo = (MultiSampleVideo) gsyBaseVideoPlayer;
multiSampleVideo.loadCoverImage(mCoverOriginUrl, mDefaultRes);
return multiSampleVideo;
}
@Override
public GSYBaseVideoPlayer showSmallVideo(Point size, boolean actionBar, boolean statusBar) {
//下面这里替换成你自己的强制转化
MultiSampleVideo multiSampleVideo = (MultiSampleVideo) super.showSmallVideo(size, actionBar, statusBar);
multiSampleVideo.mStartButton.setVisibility(GONE);
multiSampleVideo.mStartButton = null;
return multiSampleVideo;
}
public String getKey() {
if (mPlayPosition == -22) {
Debuger.printfError(getClass().getSimpleName() + " used getKey() " + "******* PlayPosition never set. ********");
}
if (TextUtils.isEmpty(mPlayTag)) {
Debuger.printfError(getClass().getSimpleName() + " used getKey() " + "******* PlayTag never set. ********");
}
return TAG + mPlayPosition + mPlayTag;
}
}
package com.ubains.rtspdemo.vedio;
/**
* Created by shuyu on 2016/11/11.
*/
public class VideoModel {
}
package com.ubains.rtspdemo.vedio.manager;
import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import com.shuyu.gsyvideoplayer.GSYVideoBaseManager;
import com.shuyu.gsyvideoplayer.player.IPlayerManager;
import com.shuyu.gsyvideoplayer.player.IjkPlayerManager;
import com.shuyu.gsyvideoplayer.utils.CommonUtil;
import com.shuyu.gsyvideoplayer.video.base.GSYVideoPlayer;
import com.ubains.rtspdemo.R;
import java.util.HashMap;
import java.util.Map;
import static com.shuyu.gsyvideoplayer.utils.CommonUtil.hideNavKey;
/**
* 多个播放的管理器
* Created by guoshuyu on 2018/1/31.
*/
public class CustomManager extends GSYVideoBaseManager {
public static final int SMALL_ID = R.id.custom_small_id;
public static final int FULLSCREEN_ID = R.id.custom_full_id;
public static String TAG = "GSYVideoManager";
private static Map<String, CustomManager> sMap = new HashMap<>();
public CustomManager() {
init();
}
@Override
protected IPlayerManager getPlayManager() {
return new IjkPlayerManager();
}
/**
* 退出全屏,主要用于返回键
*
* @return 返回是否全屏
*/
@SuppressWarnings("ResourceType")
public static boolean backFromWindowFull(Context context, String key) {
boolean backFrom = false;
ViewGroup vp = (ViewGroup) (CommonUtil.scanForActivity(context)).findViewById(Window.ID_ANDROID_CONTENT);
View oldF = vp.findViewById(FULLSCREEN_ID);
if (oldF != null) {
backFrom = true;
hideNavKey(context);
if (getCustomManager(key).lastListener() != null) {
getCustomManager(key).lastListener().onBackFullscreen();
}
}
return backFrom;
}
/**
* 页面销毁了记得调用是否所有的video
*/
public static void releaseAllVideos(String key) {
if (getCustomManager(key).listener() != null) {
getCustomManager(key).listener().onCompletion();
}
getCustomManager(key).releaseMediaPlayer();
}
/**
* 暂停播放
*/
public void onPause(String key) {
if (getCustomManager(key).listener() != null) {
getCustomManager(key).listener().onVideoPause();
}
}
/**
* 恢复播放
*/
public void onResume(String key) {
if (getCustomManager(key).listener() != null) {
getCustomManager(key).listener().onVideoResume();
}
}
/**
* 恢复暂停状态
*
* @param seek 是否产生seek动作,直播设置为false
*/
public void onResume(String key, boolean seek) {
if (getCustomManager(key).listener() != null) {
getCustomManager(key).listener().onVideoResume(seek);
}
}
/**
* 单例管理器
*/
public static synchronized Map<String, CustomManager> instance() {
return sMap;
}
/**
* 单例管理器
*/
public static synchronized CustomManager getCustomManager(String key) {
if (TextUtils.isEmpty(key)) {
throw new IllegalStateException("key not be empty");
}
CustomManager customManager = sMap.get(key);
if (customManager == null) {
customManager = new CustomManager();
sMap.put(key, customManager);
}
return customManager;
}
public static void onPauseAll() {
if (sMap.size() > 0) {
for (Map.Entry<String, CustomManager> header : sMap.entrySet()) {
header.getValue().onPause(header.getKey());
}
}
}
public static void onResumeAll() {
if (sMap.size() > 0) {
for (Map.Entry<String, CustomManager> header : sMap.entrySet()) {
header.getValue().onResume(header.getKey());
}
}
}
/**
* 恢复暂停状态
*
* @param seek 是否产生seek动作
*/
public static void onResumeAll(boolean seek) {
if (sMap.size() > 0) {
for (Map.Entry<String, CustomManager> header : sMap.entrySet()) {
header.getValue().onResume(header.getKey(), seek);
}
}
}
public static void clearAllVideo() {
if (sMap.size() > 0) {
for (Map.Entry<String, CustomManager> header : sMap.entrySet()) {
CustomManager.releaseAllVideos(header.getKey());
}
}
sMap.clear();
}
public static void removeManager(String key) {
sMap.remove(key);
}
/**
* 当前是否全屏状态
*
* @return 当前是否全屏状态, true代表是。
*/
@SuppressWarnings("ResourceType")
public static boolean isFullState(Activity activity) {
ViewGroup vp = (ViewGroup) (CommonUtil.scanForActivity(activity)).findViewById(Window.ID_ANDROID_CONTENT);
final View full = vp.findViewById(FULLSCREEN_ID);
GSYVideoPlayer gsyVideoPlayer = null;
if (full != null) {
gsyVideoPlayer = (GSYVideoPlayer) full;
}
return gsyVideoPlayer != null;
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ubains.rtspdemo.vedio.EmptyControlVideo
android:layout_weight="1"
android:id="@+id/detail_player1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.ubains.rtspdemo.vedio.EmptyControlVideo
android:layout_weight="1"
android:id="@+id/detail_player2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_list_video"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/video_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<FrameLayout
android:id="@+id/video_full_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
......@@ -6,7 +6,7 @@
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
<com.ubains.rtspdemo.vedio.EmptyControlVideo
android:id="@+id/detail_player"
android:layout_width="match_parent"
android:layout_height="match_parent" />
......
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MutliActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.ubains.rtspdemo.vedio.MultiSampleVideo
android:layout_weight="1"
android:id="@+id/detail_player1"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.ubains.rtspdemo.vedio.MultiSampleVideo
android:layout_weight="1"
android:id="@+id/detail_player2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<FrameLayout
android:id="@+id/surface_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
</FrameLayout>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.ubains.rtspdemo.vedio.MultiSampleVideo
android:id="@+id/video_item_player"
android:layout_width="match_parent"
android:layout_height="200dp" />
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<ImageView
android:id="@+id/back_tiny"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="6dp"
android:layout_marginTop="6dp"
android:visibility="gone" />
<ImageView
android:id="@+id/small_close"
android:layout_width="30dp"
android:layout_height="30dp"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:scaleType="centerInside"
android:src="@drawable/video_small_close"
android:visibility="gone" />
<ImageView
android:id="@+id/lock_screen"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="50dp"
android:scaleType="centerInside"
android:src="@drawable/unlock"
android:visibility="gone" />
<LinearLayout
android:id="@+id/layout_bottom"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_alignParentBottom="true"
android:background="#99000000"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="invisible">
<ImageView
android:id="@+id/fullscreen"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:paddingRight="16dp"
android:scaleType="center"
android:src="@drawable/video_enlarge" />
<SeekBar
android:id="@+id/progress"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1.0"
android:background="@null"
android:max="100"
android:maxHeight="4dp"
android:minHeight="4dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:progressDrawable="@drawable/video_seek_progress"
android:thumb="@drawable/video_seek_thumb" />
<TextView
android:id="@+id/total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:text="00:00"
android:textColor="#ffffff" />
<TextView
android:id="@+id/current"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="00:00"
android:textColor="#ffffff" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout_top"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@drawable/video_title_bg"
android:gravity="center_vertical">
<ImageView
android:id="@+id/back"
android:layout_width="48dp"
android:layout_height="48dp"
android:paddingLeft="10dp"
android:scaleType="centerInside"
android:src="@drawable/video_back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:textColor="@android:color/white"
android:textSize="18sp" />
</LinearLayout>
<ProgressBar
android:id="@+id/bottom_progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:layout_alignParentBottom="true"
android:max="100"
android:progressDrawable="@drawable/video_progress" />
<RelativeLayout
android:id="@+id/surface_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"></RelativeLayout>
<RelativeLayout
android:id="@+id/thumb"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:background="#000000"
android:scaleType="fitCenter">
<ImageView
android:id="@+id/thumbImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
</RelativeLayout>
<moe.codeest.enviews.ENDownloadView
android:id="@+id/loading"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="invisible" />
<moe.codeest.enviews.ENPlayView
android:id="@+id/start"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center_vertical" />
</RelativeLayout>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论