加入了多房间登录操作来解决同一设备推流同时拉流

This commit is contained in:
董宏宇
2021-03-02 18:30:44 +08:00
parent 5e5980886d
commit c7b610efc8
13 changed files with 429 additions and 119 deletions

1
.idea/gradle.xml generated
View File

@@ -26,7 +26,6 @@
</set> </set>
</option> </option>
<option name="resolveModulePerSourceSet" value="false" /> <option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings> </GradleProjectSettings>
</option> </option>
</component> </component>

View File

@@ -43,12 +43,12 @@
android:label="配置信息" android:label="配置信息"
android:launchMode="singleTask" /> android:launchMode="singleTask" />
<activity <activity
android:name=".LivePushActivity" android:name=".LivePlayAndPushActivity"
android:label="直播播放" android:label="直播 推送 和 播放"
android:launchMode="singleTask" /> android:launchMode="singleTask" />
<activity <activity
android:name=".LivePlayActivity" android:name=".LivePlayActivity"
android:label="直播推送" android:label="直播播放"
android:launchMode="singleTask" /> android:launchMode="singleTask" />
<activity <activity
android:name="com.mogo.cloud.network.NetworkActivity" android:name="com.mogo.cloud.network.NetworkActivity"

View File

@@ -5,10 +5,11 @@ import android.support.v7.app.AppCompatActivity;
import android.util.Log; import android.util.Log;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import android.widget.ToggleButton; import android.widget.ToggleButton;
import com.mogo.cloud.util.YuvToolUtils; import com.mogo.cloud.util.YuvToolUtils;
import com.zhidao.manager.camera.FrameBufferCallBack; import com.zhidao.manager.camera.FrameBufferCallBack;
import com.zhidao.manager.camera.ZDCameraManager; import com.zhidao.manager.camera.ZDCameraManager;
@@ -34,16 +35,25 @@ public abstract class BaseLiveActivity extends AppCompatActivity {
// 当前直播的状态 // 当前直播的状态
protected ToggleButton tbLiveStatus; protected ToggleButton tbLiveStatus;
// 相机数据预览 // 相机数据预览
protected SurfaceView surfaceView; protected SurfaceView surfacePreviewView;
// 查看指定车机的画面
protected SurfaceView surfacePlayView;
// 查看直播按钮
protected ToggleButton liveToggleBtn;
// 要查看的车机SN
protected EditText etLookRoomId;
// WIFI状态
protected TextView tvWifiState;
private ZDCameraManager zdCameraManager; private ZDCameraManager zdCameraManager;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_push); setContentView(R.layout.activity_live_play_and_push);
surfaceView = findViewById(R.id.surfaceView); surfacePreviewView = findViewById(R.id.surfacePreviewView);
btnLive = findViewById(R.id.btnLive); btnLive = findViewById(R.id.btnLive);
btnLive.setOnCheckedChangeListener((buttonView, isChecked) -> { btnLive.setOnCheckedChangeListener((buttonView, isChecked) -> {
Toast.makeText(getApplicationContext(), buttonView.getText(), Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), buttonView.getText(), Toast.LENGTH_SHORT).show();
@@ -67,6 +77,15 @@ public abstract class BaseLiveActivity extends AppCompatActivity {
tbLiveStatus = findViewById(R.id.tbLiveStatus); tbLiveStatus = findViewById(R.id.tbLiveStatus);
surfacePlayView = findViewById(R.id.surfacePlayView);
etLookRoomId = findViewById(R.id.etLookRoomId);
liveToggleBtn = findViewById(R.id.liveToggleBtn);
liveToggleBtn.setOnCheckedChangeListener((buttonView, isChecked) -> {
Toast.makeText(getApplicationContext(), buttonView.getText(), Toast.LENGTH_SHORT).show();
togglePlay(isChecked);
});
tvWifiState = findViewById(R.id.tvWifiState);
initCamer(); initCamer();
} }
@@ -106,7 +125,7 @@ public abstract class BaseLiveActivity extends AppCompatActivity {
}); });
// 这里是纯预览 // 这里是纯预览
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { surfacePreviewView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override @Override
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "addSurfaceCallBack id"); Log.i(TAG, "addSurfaceCallBack id");
@@ -157,4 +176,11 @@ public abstract class BaseLiveActivity extends AppCompatActivity {
*/ */
public abstract void toggleCameraState(boolean isLive); public abstract void toggleCameraState(boolean isLive);
/**
* 开关查看直播
*
* @param isPlay true-查看直播false-不查看直播
*/
public abstract void togglePlay(boolean isPlay);
} }

View File

@@ -0,0 +1,126 @@
package com.mogo.cloud;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.util.Log;
import com.mogo.cloud.live.listener.ILiveStatusListener;
import com.mogo.cloud.live.manager.ILiveStreamManager;
import com.mogo.cloud.live.manager.LiveStreamManagerImpl;
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
import com.mogo.cloud.trafficlive.api.ITrafficLiveCallBack;
import com.mogo.cloud.trafficlive.api.MoGoAiCloudTrafficLive;
import com.mogo.cloud.wifi.IWifiStateListener;
import com.mogo.cloud.wifi.WifiStateManager;
/**
* 推流和拉流页面
*/
public class LivePlayAndPushActivity extends BaseLiveActivity implements ITrafficLiveCallBack, IWifiStateListener {
public static final String TAG = "PushActivity";
private String liveSn;
ILiveStreamManager liveStreamManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WifiStateManager.getInstance().registerWifiStateListener(this);
// 初始化直播流管理
liveStreamManager = LiveStreamManagerImpl.getInstance(this.getApplication(),
MoGoAiCloudClientConfig.getInstance().getThirdPartyDeviceId());
// 设置状态回调
liveStreamManager.setLiveStatusChangeCallback(new ILiveStatusListener() {
@Override
public void onChange(String camId, int status) {
tbLiveStatus.post(new Runnable() {
@Override
public void run() {
if (status == 0) {
tbLiveStatus.setTextColor(getResources().getColor(R.color.colorStartLive));
tbLiveStatus.setChecked(true);
} else {
tbLiveStatus.setTextColor(getResources().getColor(R.color.colorStopLive));
tbLiveStatus.setChecked(false);
}
}
});
}
});
}
@Override
public void onVideoFrame(byte[] bytes, int bytesLength) {
//Log.i(TAG, "onVideoFrame byte length: " + bytesLength);
if (liveStreamManager != null) {
// 将摄像头采集的YUV数据推送到ZEGO
liveStreamManager.notifyYUVData(bytes, 1280, 720, 3);
}
}
@Override
public void toggleLive(boolean isLive) {
}
@Override
public void toggleCameraState(boolean isLive) {
Log.i(TAG, "toggleCameraState isLive: " + isLive);
if (isLive) {
// 上报摄像头状态1-可用2-不可用
liveStreamManager.uploadCamStatus(1, 1);
} else {
liveStreamManager.uploadCamStatus(2, 2);
}
}
@Override
public void togglePlay(boolean isPlay) {
if (isPlay) {
liveSn = etLookRoomId.getText().toString().trim();
MoGoAiCloudTrafficLive.viewVehicleHeadLive(this.getApplication(),
liveSn, surfacePlayView, this);
} else {
MoGoAiCloudTrafficLive.stopLive(liveSn);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (liveStreamManager != null) {
// 停止
liveStreamManager.stopLiveStream();
// 释放资源
liveStreamManager.release();
}
MoGoAiCloudTrafficLive.stopLive(liveSn);
MoGoAiCloudTrafficLive.destroyLive();
WifiStateManager.getInstance().unRegisterWifiStateListener(this);
}
@Override
public void onLive() {
Log.d(TAG, "开始直播 onLive");
}
@Override
public void onDisConnect() {
Log.d(TAG, "失去连接 onDisConnect");
}
@Override
public void onError(String errorMsg) {
Log.d(TAG, "发生错误 onError msg: " + errorMsg);
}
@Override
public void onWifiState(WifiInfo wifiInfo) {
tvWifiState.setText("wifiLevel: " + Math.abs(wifiInfo.getRssi()));
}
}

View File

@@ -21,8 +21,10 @@ public class LivePushActivity extends BaseLiveActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// 初始化直播流管理 // 初始化直播流管理
liveStreamManager = LiveStreamManagerImpl.getInstance(this, liveStreamManager = LiveStreamManagerImpl.getInstance(this.getApplication(),
MoGoAiCloudClientConfig.getInstance().getThirdPartyDeviceId()); MoGoAiCloudClientConfig.getInstance().getThirdPartyDeviceId());
// 设置状态回调
liveStreamManager.setLiveStatusChangeCallback(new ILiveStatusListener() { liveStreamManager.setLiveStatusChangeCallback(new ILiveStatusListener() {
@Override @Override
public void onChange(String camId, int status) { public void onChange(String camId, int status) {
@@ -67,6 +69,11 @@ public class LivePushActivity extends BaseLiveActivity {
} }
} }
@Override
public void togglePlay(boolean isPlay) {
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();

View File

@@ -7,7 +7,6 @@ import android.text.TextUtils;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import com.mogo.cloud.network.NetworkActivity; import com.mogo.cloud.network.NetworkActivity;
import com.mogo.cloud.passport.IMoGoTokenCallback; import com.mogo.cloud.passport.IMoGoTokenCallback;
import com.mogo.cloud.passport.MoGoAiCloudClient; import com.mogo.cloud.passport.MoGoAiCloudClient;
@@ -19,6 +18,7 @@ public class MainActivity extends AppCompatActivity {
private Button btnJumpNetWorkPort; private Button btnJumpNetWorkPort;
private Button btnJumpRealTime; private Button btnJumpRealTime;
private Button btnJumpRoadCondition; private Button btnJumpRoadCondition;
private Button btnJumpLivePlayAndPush;
private Button btnJumpLivePush; private Button btnJumpLivePush;
private Button btnJumpLivePlay; private Button btnJumpLivePlay;
@@ -66,6 +66,12 @@ public class MainActivity extends AppCompatActivity {
startActivity(intent); startActivity(intent);
}); });
btnJumpLivePlayAndPush = findViewById(R.id.btnJumpLivePlayAndPush);
btnJumpLivePlayAndPush.setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, LivePlayAndPushActivity.class);
startActivity(intent);
});
btnJumpLivePush = findViewById(R.id.btnJumpLivePush); btnJumpLivePush = findViewById(R.id.btnJumpLivePush);
btnJumpLivePush.setOnClickListener(v -> { btnJumpLivePush.setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, LivePushActivity.class); Intent intent = new Intent(MainActivity.this, LivePushActivity.class);

View File

@@ -14,7 +14,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="请输入要查看的车机SN" android:hint="请输入要查看的车机SN"
android:text="F803BB2037EZD00071" android:text="F803EB2046PZD00149"
android:textColor="#FFFF" android:textColor="#FFFF"
app:layout_constraintBottom_toTopOf="@+id/liveToggleBtn" app:layout_constraintBottom_toTopOf="@+id/liveToggleBtn"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/surfacePreviewView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/surfacePlayView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<SurfaceView
android:id="@+id/surfacePlayView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/surfacePreviewView"
app:layout_constraintTop_toTopOf="parent" />
<ToggleButton
android:id="@+id/tbLiveStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFF"
android:padding="10dp"
android:textOff="直播已停止"
android:textOn="直播进行中"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/flTestPanel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ToggleButton
android:id="@+id/btnLive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textOff="@string/start"
android:textOn="@string/stop" />
<ToggleButton
android:id="@+id/btnChangeCameraState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textOff="设置不可直播"
android:textOn="设置可直播" />
<ToggleButton
android:id="@+id/btnSaveFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:textOff="开始录制"
android:textOn="停止录制"
android:visibility="gone" />
</LinearLayout>
<EditText
android:id="@+id/etLookRoomId"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="请输入要查看的车机SN"
android:text="F803EB2046PZD00149"
android:textColor="#FFFF"
app:layout_constraintBottom_toTopOf="@+id/liveToggleBtn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/surfacePlayView" />
<ToggleButton
android:id="@+id/liveToggleBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOff="开始拉流"
android:textOn="停止拉流"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/etLookRoomId" />
<TextView
android:id="@+id/tvWifiState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="wifi State :0"
android:textColor="#17FBF4"
android:textSize="32px"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>

View File

@@ -72,16 +72,25 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="路况服务测试" /> android:text="路况服务测试" />
<Button
android:id="@+id/btnJumpLivePlayAndPush"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="直播SDK 推送 和 播放" />
<Button <Button
android:id="@+id/btnJumpLivePush" android:id="@+id/btnJumpLivePush"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="直播SDK推流测试" /> android:text="直播SDK推流测试"
android:visibility="gone" />
<Button <Button
android:id="@+id/btnJumpLivePlay" android:id="@+id/btnJumpLivePlay"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:text="直播SDK观看测试" /> android:text="直播SDK观看测试"
android:visibility="gone" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@@ -1,6 +1,7 @@
package com.mogo.cloud.live.manager; package com.mogo.cloud.live.manager;
import android.content.Context; import android.app.Application;
import android.media.AudioFormat;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Log; import android.util.Log;
@@ -24,9 +25,8 @@ public class LiveStreamManagerImpl implements ILiveStreamManager {
private static final String TAG = "LiveStreamManagerImpl"; private static final String TAG = "LiveStreamManagerImpl";
private static volatile ILiveStreamManager sInstance; private static volatile ILiveStreamManager sInstance;
public static volatile String mDevicesId;
private final Context mContext; private final Application mApplication;
// 循环上报摄像头可直播状态间隔时间 // 循环上报摄像头可直播状态间隔时间
private static final int PUSH_CAM_TIME = 10 * 30 * 1000; private static final int PUSH_CAM_TIME = 10 * 30 * 1000;
@@ -40,13 +40,16 @@ public class LiveStreamManagerImpl implements ILiveStreamManager {
private Handler mHandler; // 循环上报摄像头状态 private Handler mHandler; // 循环上报摄像头状态
private SocketMsgUtils mSocketMsgUtils; // Socket 长链接 private SocketMsgUtils mSocketMsgUtils; // Socket 长链接
private ILiveStatusListener mLiveStatusCallback;// 直播状态回调 private ILiveStatusListener mLiveStatusCallback;// 直播状态回调
private MoGoLivePushConfig mLivePushConfig;// 直播参数
private static final int WIDTH = 1280;
private static final int HEIGHT = 720;
public static ILiveStreamManager getInstance(Context context, String devicesId) { public static ILiveStreamManager getInstance(Application application, String devicesId) {
if (sInstance == null) { if (sInstance == null) {
synchronized (LiveStreamManagerImpl.class) { synchronized (LiveStreamManagerImpl.class) {
if (sInstance == null) { if (sInstance == null) {
sInstance = new LiveStreamManagerImpl(context, devicesId); sInstance = new LiveStreamManagerImpl(application, devicesId);
} }
} }
} }
@@ -54,12 +57,26 @@ public class LiveStreamManagerImpl implements ILiveStreamManager {
} }
private LiveStreamManagerImpl(Context context, String devicesId) { private LiveStreamManagerImpl(Application application, String devicesId) {
mContext = context; mApplication = application;
mDevicesId = devicesId;
mHandler = new Handler(); mHandler = new Handler();
// 初始化配置文件
mLivePushConfig = MoGoLivePushConfig.getInstance();
mLivePushConfig.setWidth(WIDTH);
mLivePushConfig.setHeight(HEIGHT);
mLivePushConfig.setVideoBitrate(1500);
mLivePushConfig.setVideoFPS(15);
mLivePushConfig.setAudioChannels(2);
mLivePushConfig.setAudioSampleRate(44100);
mLivePushConfig.setAudioFormat(AudioFormat.ENCODING_PCM_16BIT);
mLivePushConfig.setMute(true);
mLivePushConfig.setDevicesId(devicesId);
// 初始化直播
MoGoLiveManager.getInstance().init(mApplication, mLivePushConfig);
// 初始化Socket长连接通道 // 初始化Socket长连接通道
mSocketMsgUtils = SocketMsgUtils.getInstance(mContext, mSocketMsgUtils = SocketMsgUtils.getInstance(mApplication,
new IMogoCloudSocketOnMessageListener<CommandModel>() { new IMogoCloudSocketOnMessageListener<CommandModel>() {
@Override @Override
@@ -75,6 +92,7 @@ public class LiveStreamManagerImpl implements ILiveStreamManager {
}); });
// 初始化查询摄像头状态 // 初始化查询摄像头状态
restartCamStatusLoop(); restartCamStatusLoop();
} }
/** /**
@@ -87,14 +105,14 @@ public class LiveStreamManagerImpl implements ILiveStreamManager {
@Override @Override
public void startLiveStream() { public void startLiveStream() {
Logger.d(TAG, "startLiveStream devices id:" + mDevicesId); Logger.d(TAG, "startLiveStream");
PushService.startService(mContext, PushService.ACTION_START_RTMP_PUSH, mDevicesId); PushService.startService(mApplication, PushService.ACTION_START_RTMP_PUSH);
} }
@Override @Override
public void stopLiveStream() { public void stopLiveStream() {
Logger.d(TAG, "stopLiveStream devices id:" + mDevicesId); Logger.d(TAG, "stopLiveStream");
PushService.startService(mContext, PushService.ACTION_STOP_RTMP_PUSH, mDevicesId); PushService.startService(mApplication, PushService.ACTION_STOP_RTMP_PUSH);
} }
@Override @Override
@@ -167,20 +185,17 @@ public class LiveStreamManagerImpl implements ILiveStreamManager {
if (C1.equals(videoChannel)) { if (C1.equals(videoChannel)) {
// 停止直播 // 停止直播
if (status == PUSH_STOP) { if (status == PUSH_STOP) {
PushService.startService(mContext, PushService.ACTION_STOP_RTMP_PUSH, PushService.startService(mApplication, PushService.ACTION_STOP_RTMP_PUSH);
LiveStreamManagerImpl.mDevicesId);
// 释放资源 // 释放资源
CameraFrameManager.getInstance().release(); CameraFrameManager.getInstance().release();
} }
// 开始直播 // 开始直播
else if (status == PUSH_START) { else if (status == PUSH_START) {
PushService.startService(mContext, PushService.ACTION_START_RTMP_PUSH, PushService.startService(mApplication, PushService.ACTION_START_RTMP_PUSH);
LiveStreamManagerImpl.mDevicesId);
} }
// 强制关闭直播 // 强制关闭直播
else if (status == PUSH_FORCED_STOP) { else if (status == PUSH_FORCED_STOP) {
PushService.startService(mContext, PushService.ACTION_FORCED_STOP_RTMP_PUSH, PushService.startService(mApplication, PushService.ACTION_FORCED_STOP_RTMP_PUSH);
LiveStreamManagerImpl.mDevicesId);
} }
// 记录直播状态 // 记录直播状态
sCam1LiveStatus = status; sCam1LiveStatus = status;

View File

@@ -66,6 +66,10 @@ public class MoGoLiveManager {
* 直播会议ID使用推流端的车机信息建立房间ID这里采用格式为ROOM_ID_车机SN编号 * 直播会议ID使用推流端的车机信息建立房间ID这里采用格式为ROOM_ID_车机SN编号
*/ */
public static final String ROOM_ID_PREFIX = "ROOM_ID_"; public static final String ROOM_ID_PREFIX = "ROOM_ID_";
/**
* 要查看的直播会议ID使用推流端的车机信息建立房间ID这里采用格式为ROOM_MULTI_ID_ 车机SN编号
*/
public static final String MULTI_ROOM_ID_PREFIX = "MULTI_ROOM_ID_";
/** /**
* 直播用户名称的 * 直播用户名称的
*/ */
@@ -94,10 +98,18 @@ public class MoGoLiveManager {
* 当前的房间ID * 当前的房间ID
*/ */
private String currentRoomId = ""; private String currentRoomId = "";
/**
* 当前的多房间ID
*/
private String multiRoomId = "";
/** /**
* 当前直播流ID * 当前直播流ID
*/ */
private String currentStreamId = ""; private String currentStreamId = "";
/**
* MultiRoom中直播流ID
*/
private String multiStreamId = "";
/** /**
* 自定义采集状态true-初始化完成false-没有初始化 * 自定义采集状态true-初始化完成false-没有初始化
*/ */
@@ -114,6 +126,10 @@ public class MoGoLiveManager {
* 当前在直播间的人数,只剩下一个人的时候需要停掉直播推送 * 当前在直播间的人数,只剩下一个人的时候需要停掉直播推送
*/ */
private int onlineNumber; private int onlineNumber;
/**
* 多房间配置
*/
private ZegoRoomConfig zeGoMultiRoomConfig;
private static final class Holder { private static final class Holder {
private static final MoGoLiveManager manager = new MoGoLiveManager(); private static final MoGoLiveManager manager = new MoGoLiveManager();
@@ -172,6 +188,9 @@ public class MoGoLiveManager {
zegoEngineConfig.logConfig = zegoLogConfig; zegoEngineConfig.logConfig = zegoLogConfig;
// 设置配置到引擎中 // 设置配置到引擎中
ZegoExpressEngine.setEngineConfig(zegoEngineConfig); ZegoExpressEngine.setEngineConfig(zegoEngineConfig);
// 登录以前用户SN为房间ID的房间
loginRoom(mLivePushConfig.getDevicesId(), mLivePushConfig.getDevicesId());
} }
/** /**
@@ -309,6 +328,21 @@ public class MoGoLiveManager {
+ " currentStreamId:" + currentStreamId); + " currentStreamId:" + currentStreamId);
} }
/**
* 进入多房间
*
* @param roomId 房间ID
*/
public void loginMultiRoom(String roomId) {
initCustomVideoCapture();
multiRoomId = MULTI_ROOM_ID_PREFIX + roomId;
multiStreamId = STREAM_ID_PREFIX + roomId;
zeGoMultiRoomConfig = new ZegoRoomConfig();
zeGoMultiRoomConfig.isUserStatusNotify = true;
mExpressEngine.loginMultiRoom(multiRoomId, zeGoMultiRoomConfig);
Logger.i(TAG, "loginMultiRoom currentMultiRoomId : " + multiRoomId);
}
/** /**
* 初始化自定义采集 * 初始化自定义采集
*/ */
@@ -394,39 +428,49 @@ public class MoGoLiveManager {
} }
/** /**
* 开始推送 * 退出多房间
*/ */
public void startPush(String streamId) { private void logOutMultiRoom() {
mExpressEngine.startPublishingStream(STREAM_ID_PREFIX + streamId); if (mExpressEngine == null) {
return;
}
if (!TextUtils.isEmpty(multiRoomId)) {
mExpressEngine.loginMultiRoom(multiRoomId, zeGoMultiRoomConfig);
}
} }
/** /**
* 开始直播 * 开始推送
*/
public void startPush() {
mExpressEngine.startPublishingStream(currentStreamId);
}
/**
* 开始播放直播
* *
* @param surfaceView 渲染直播的视图 * @param surfaceView 渲染直播的视图
*/ */
public String startLive(SurfaceView surfaceView) { public String startLive(SurfaceView surfaceView) {
if (!TextUtils.isEmpty(currentStreamId) && if (!TextUtils.isEmpty(multiStreamId) &&
!currentStreamId.equals(STREAM_ID_PREFIX)) { !multiStreamId.equals(STREAM_ID_PREFIX)) {
ZegoCanvas zegoCanvas = new ZegoCanvas(surfaceView); ZegoCanvas zegoCanvas = new ZegoCanvas(surfaceView);
zegoCanvas.viewMode = ZegoViewMode.SCALE_TO_FILL; zegoCanvas.viewMode = ZegoViewMode.SCALE_TO_FILL;
mExpressEngine.startPlayingStream(currentStreamId, zegoCanvas); mExpressEngine.startPlayingStream(multiStreamId, zegoCanvas);
} else { } else {
Logger.e(TAG, "直播ID有误请重试"); Logger.e(TAG, "直播ID有误请重试");
} }
return multiStreamId;
return currentStreamId;
} }
/** /**
* 停止直播 * 停止播放直播
*/ */
public void stopLive() { public void stopLive() {
if (!TextUtils.isEmpty(currentStreamId) && mExpressEngine != null) { if (!TextUtils.isEmpty(multiStreamId) && mExpressEngine != null) {
mExpressEngine.stopPlayingStream(currentStreamId); mExpressEngine.stopPlayingStream(multiStreamId);
} }
stopPreview(); stopPreview();
logOutRoom();
} }
/** /**
@@ -453,7 +497,6 @@ public class MoGoLiveManager {
*/ */
public void onDestroyPublish() { public void onDestroyPublish() {
stopPublish(); stopPublish();
logOutRoom();
destroyEngine(); destroyEngine();
} }
@@ -476,6 +519,8 @@ public class MoGoLiveManager {
return; return;
} }
mExpressEngine.stopPreview(); mExpressEngine.stopPreview();
// 退出正在查看的多房间
logOutMultiRoom();
} }
/** /**
@@ -483,7 +528,6 @@ public class MoGoLiveManager {
*/ */
public void stopPublish() { public void stopPublish() {
stopPublishingStream(); stopPublishingStream();
logOutRoom();
} }
/** /**

View File

@@ -3,7 +3,6 @@ package com.mogo.cloud.live.server;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.media.AudioFormat;
import android.os.IBinder; import android.os.IBinder;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Log; import android.util.Log;
@@ -11,7 +10,6 @@ import android.util.Log;
import com.mogo.cloud.live.listener.IYUVDataListener; import com.mogo.cloud.live.listener.IYUVDataListener;
import com.mogo.cloud.live.manager.CameraFrameManager; import com.mogo.cloud.live.manager.CameraFrameManager;
import com.mogo.cloud.live.manager.MoGoLiveManager; import com.mogo.cloud.live.manager.MoGoLiveManager;
import com.mogo.cloud.live.manager.MoGoLivePushConfig;
import com.mogo.cloud.live.utils.ByteUtils; import com.mogo.cloud.live.utils.ByteUtils;
import com.mogo.cloud.utils.logger.Logger; import com.mogo.cloud.utils.logger.Logger;
@@ -23,33 +21,18 @@ public class PushService extends Service
public static final String ACTION_FORCED_STOP_RTMP_PUSH = "action_forced_stop_rtmp_push"; public static final String ACTION_FORCED_STOP_RTMP_PUSH = "action_forced_stop_rtmp_push";
private static final String TAG = "PushService"; private static final String TAG = "PushService";
private static final String DEVICES_ID = "devices_id";
private static final int WIDTH = 1280;
private static final int HEIGHT = 720;
// 自研直播SDK // 自研直播SDK
private MoGoLivePushConfig mLivePushConfig;
private MoGoLiveManager mLivePusher; private MoGoLiveManager mLivePusher;
/**
* 当前设备ID作为推流端userID==roomId==streamID
*/
private volatile String mDevicesId;
/** /**
* 启动服务 * 启动服务
* *
* @param context 上下文 * @param context 上下文
* @param action 动作标志 * @param action 动作标志
* @param devicesId 设备ID
*/ */
public static void startService(Context context, String action, public static void startService(Context context, String action) {
String devicesId) {
Intent intent = new Intent(context, PushService.class); Intent intent = new Intent(context, PushService.class);
intent.setAction(action); intent.setAction(action);
intent.putExtra(DEVICES_ID, devicesId);
context.startService(intent); context.startService(intent);
} }
@@ -57,16 +40,6 @@ public class PushService extends Service
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
Log.d(TAG, "初始化推流服务……"); Log.d(TAG, "初始化推流服务……");
mLivePushConfig = MoGoLivePushConfig.getInstance();
mLivePushConfig.setWidth(WIDTH);
mLivePushConfig.setHeight(HEIGHT);
mLivePushConfig.setVideoBitrate(1500);
mLivePushConfig.setVideoFPS(15);
mLivePushConfig.setAudioChannels(2);
mLivePushConfig.setAudioSampleRate(44100);
mLivePushConfig.setAudioFormat(AudioFormat.ENCODING_PCM_16BIT);
mLivePushConfig.setMute(true);
initZeGoLivePusher(); initZeGoLivePusher();
} }
@@ -76,8 +49,7 @@ public class PushService extends Service
// 开启直播 // 开启直播
if (ACTION_START_RTMP_PUSH.equals(intent.getAction())) { if (ACTION_START_RTMP_PUSH.equals(intent.getAction())) {
try { try {
String devicesId = intent.getStringExtra(DEVICES_ID); startPush();
startPush(devicesId);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@@ -105,25 +77,19 @@ public class PushService extends Service
/** /**
* 启动发布直播视频流 * 启动发布直播视频流
*
* @param devicesId 设备ID
*/ */
private void startPush(String devicesId) { private void startPush() {
if (mDevicesId != null && mDevicesId.equals(devicesId) if (mLivePusher != null
&& mLivePusher != null
&& mLivePusher.isCaptureStatus() && mLivePusher.isCaptureStatus()
&& mLivePusher.isPushing()) { && mLivePusher.isPushing()) {
return; return;
} }
mDevicesId = devicesId;
initZeGoLivePusher(); initZeGoLivePusher();
// 登录房间
mLivePusher.loginRoom(mDevicesId, mDevicesId);
// 开始发布 // 开始发布
mLivePusher.startPush(mDevicesId); mLivePusher.startPush();
// 注册视频YUV回调监听 // 注册视频YUV回调监听
CameraFrameManager.getInstance().addYuvDataCallback(this); CameraFrameManager.getInstance().addYuvDataCallback(this);
Log.d(TAG, "startPush :mRoomId=" + mDevicesId + " mDevicesId=" + mDevicesId); Log.d(TAG, "startPush");
} }
/** /**
@@ -132,23 +98,6 @@ public class PushService extends Service
private void initZeGoLivePusher() { private void initZeGoLivePusher() {
if (mLivePusher == null) { if (mLivePusher == null) {
mLivePusher = MoGoLiveManager.getInstance(); mLivePusher = MoGoLiveManager.getInstance();
mLivePusher.init(getApplication(), mLivePushConfig);
// mLivePusher.setLiveRoomPersonListener(new ILiveRoomPersonListener() {
// @Override
// public void onRoomOnlineUserCountUpdate(int count) {
// Logger.i(TAG, "房间还有 " + count + " 位观众,不可以关闭直播");
// }
//
// @Override
// public void onRoomUserUpdate(ZegoUpdateType updateType, ArrayList<ZegoUser> userList) {
// if (userList.size() <= 1) {
// Logger.i(TAG, "房间没有观众了,主动关闭直播");
// stopPush();
// } else {
// Logger.i(TAG, "房间还有 " + mLivePusher.getOnlineNumber() + " 位观众,不可以关闭直播");
// }
// }
// });
} }
} }
@@ -157,7 +106,6 @@ public class PushService extends Service
*/ */
private void stopPush() { private void stopPush() {
try { try {
mDevicesId = "";
// 是否处于发布状态 // 是否处于发布状态
if (mLivePusher.isPushing()) { if (mLivePusher.isPushing()) {
// 停止发布 // 停止发布

View File

@@ -8,6 +8,7 @@ import android.view.SurfaceView;
import com.mogo.cloud.live.listener.ILiveProgressListener; import com.mogo.cloud.live.listener.ILiveProgressListener;
import com.mogo.cloud.live.listener.IRequestLiveListener; import com.mogo.cloud.live.listener.IRequestLiveListener;
import com.mogo.cloud.live.manager.MoGoLiveManager; import com.mogo.cloud.live.manager.MoGoLiveManager;
import com.mogo.cloud.live.manager.MoGoLivePushConfig;
import com.mogo.cloud.live.manager.RequestLiveManager; import com.mogo.cloud.live.manager.RequestLiveManager;
import com.mogo.cloud.passport.MoGoAiCloudClient; import com.mogo.cloud.passport.MoGoAiCloudClient;
import com.mogo.cloud.trafficlive.api.ITrafficLiveCallBack; import com.mogo.cloud.trafficlive.api.ITrafficLiveCallBack;
@@ -65,18 +66,27 @@ public class TrafficLiveManager implements ILiveProgressListener {
Logger.i(TAG, "主播开始直播了 systemClock :" + SystemClock.elapsedRealtime() + " SystemTime : " + System.currentTimeMillis()); Logger.i(TAG, "主播开始直播了 systemClock :" + SystemClock.elapsedRealtime() + " SystemTime : " + System.currentTimeMillis());
String sn = MoGoAiCloudClient.getInstance().getAiCloudClientConfig().getSn(); String sn = MoGoAiCloudClient.getInstance().getAiCloudClientConfig().getSn();
mStreamId = MoGoLiveManager.STREAM_ID_PREFIX + liveSn; mStreamId = MoGoLiveManager.STREAM_ID_PREFIX + liveSn;
MoGoLiveManager.getInstance().init(application, null);
MoGoLiveManager.getInstance().loginRoom(sn, liveSn); // 初始化配置文件
MoGoLivePushConfig mLivePushConfig = MoGoLivePushConfig.getInstance();
mLivePushConfig.setDevicesId(sn);
MoGoLiveManager.getInstance().init(application, mLivePushConfig);
MoGoLiveManager.getInstance().loginMultiRoom(liveSn);
MoGoLiveManager.getInstance().setLiveProgressListener(TrafficLiveManager.this); MoGoLiveManager.getInstance().setLiveProgressListener(TrafficLiveManager.this);
// 直接 查看对应SN的直播 // 直接 查看对应SN的直播
MoGoLiveManager.getInstance().startLive(surfaceView); MoGoLiveManager.getInstance().startLive(surfaceView);
callBack.onLive(); if (callBack != null) {
callBack.onLive();
}
} }
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
callBack.onError(e.getMessage()); if (callBack != null) {
callBack.onError(e.getMessage());
}
} }
}); });
} }
@@ -93,7 +103,9 @@ public class TrafficLiveManager implements ILiveProgressListener {
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
callBack.onError(e.getMessage()); if (callBack != null) {
callBack.onError(e.getMessage());
}
} }
}); });
MoGoLiveManager.getInstance().stopLive(); MoGoLiveManager.getInstance().stopLive();
@@ -109,34 +121,46 @@ public class TrafficLiveManager implements ILiveProgressListener {
@Override @Override
public void onEngineStart() { public void onEngineStart() {
callBack.onLiveStart(); if (callBack != null) {
callBack.onLiveStart();
}
} }
@Override @Override
public void onEngineStop() { public void onEngineStop() {
callBack.onLiveStop(); if (callBack != null) {
callBack.onLiveStop();
}
} }
@Override @Override
public void onConnecting() { public void onConnecting() {
callBack.onLiveConnecting(); if (callBack != null) {
callBack.onLiveConnecting();
}
} }
@Override @Override
public void onConnected(String roomId) { public void onConnected(String roomId) {
isLoginSuccess = true; isLoginSuccess = true;
callBack.onLiveConnected(); if (callBack != null) {
callBack.onLiveConnected();
}
} }
@Override @Override
public void onDisConnect() { public void onDisConnect() {
isLoginSuccess = false; isLoginSuccess = false;
callBack.onDisConnect(); if (callBack != null) {
callBack.onDisConnect();
}
} }
@Override @Override
public void onDebugError(int errorCode, String funcName, String errorInfo) { public void onDebugError(int errorCode, String funcName, String errorInfo) {
Logger.e(TAG, "onDebugError errorCode : " + errorCode + " funcName : " + funcName + " errorInfo : " + errorInfo); Logger.e(TAG, "onDebugError errorCode : " + errorCode + " funcName : " + funcName + " errorInfo : " + errorInfo);
callBack.onError(errorInfo); if (callBack != null) {
callBack.onError(errorInfo);
}
} }
} }