[*] 写了一点
This commit is contained in:
@@ -1,11 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
@@ -18,6 +13,7 @@
|
|||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/title_activity_main"
|
android:label="@string/title_activity_main"
|
||||||
|
android:launchMode="singleTask"
|
||||||
android:theme="@style/Theme.Taoyao">
|
android:theme="@style/Theme.Taoyao">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.acgist.taoyao.client;
|
package com.acgist.taoyao.client;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
@@ -9,6 +11,7 @@ import android.util.Log;
|
|||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
@@ -31,6 +34,8 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
protected void onCreate(Bundle bundle) {
|
protected void onCreate(Bundle bundle) {
|
||||||
Log.i(MainActivity.class.getSimpleName(), "onCreate");
|
Log.i(MainActivity.class.getSimpleName(), "onCreate");
|
||||||
super.onCreate(bundle);
|
super.onCreate(bundle);
|
||||||
|
// 请求权限
|
||||||
|
this.requestPermission();
|
||||||
// 启动点亮屏幕
|
// 启动点亮屏幕
|
||||||
this.setTurnScreenOn(true);
|
this.setTurnScreenOn(true);
|
||||||
// 锁屏显示屏幕
|
// 锁屏显示屏幕
|
||||||
@@ -64,6 +69,35 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求权限
|
||||||
|
*/
|
||||||
|
private void requestPermission() {
|
||||||
|
final String[] permissions = new String[]{
|
||||||
|
Manifest.permission.CAMERA,
|
||||||
|
Manifest.permission.INTERNET,
|
||||||
|
Manifest.permission.RECORD_AUDIO,
|
||||||
|
Manifest.permission.ACCESS_WIFI_STATE,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||||
|
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||||
|
Manifest.permission.RECEIVE_BOOT_COMPLETED,
|
||||||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
|
};
|
||||||
|
boolean allGranted = true;
|
||||||
|
for (String permission : permissions) {
|
||||||
|
if(this.getApplicationContext().checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.i(MediaService.class.getSimpleName(), "授权成功:" + permission);
|
||||||
|
} else {
|
||||||
|
allGranted = false;
|
||||||
|
Log.w(MediaService.class.getSimpleName(), "授权失败:" + permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!allGranted) {
|
||||||
|
Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 拉起媒体服务
|
* 拉起媒体服务
|
||||||
*/
|
*/
|
||||||
@@ -81,7 +115,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
intent.setAction(MediaService.Action.CONNECT.name());
|
intent.setAction(MediaService.Action.CONNECT.name());
|
||||||
intent.putExtra("mainHandler", this.mainHandler);
|
intent.putExtra("mainHandler", this.mainHandler);
|
||||||
intent.setAction("connect");
|
|
||||||
this.startService(intent);
|
this.startService(intent);
|
||||||
} else {
|
} else {
|
||||||
Log.w(MainActivity.class.getSimpleName(), "拉起媒体服务失败");
|
Log.w(MainActivity.class.getSimpleName(), "拉起媒体服务失败");
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.acgist.taoyao.client;
|
package com.acgist.taoyao.client;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
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.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
@@ -59,15 +61,15 @@ public class MediaService extends Service {
|
|||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
Log.i(MediaService.class.getSimpleName(), "onStartCommand");
|
Log.i(MediaService.class.getSimpleName(), "onStartCommand");
|
||||||
if(Action.CONNECT.name().equals(intent.getAction())) {
|
if (Action.CONNECT.name().equals(intent.getAction())) {
|
||||||
if(this.taoyao == null) {
|
if (this.taoyao == null) {
|
||||||
Log.d(MediaService.class.getSimpleName(), "打开信令连接");
|
Log.d(MediaService.class.getSimpleName(), "打开信令连接");
|
||||||
this.mainHandler = (Handler) intent.getSerializableExtra("mainHandler");
|
this.mainHandler = (Handler) intent.getSerializableExtra("mainHandler");
|
||||||
this.connect();
|
this.connect();
|
||||||
} else {
|
} else {
|
||||||
Log.d(MediaService.class.getSimpleName(), "信令已经连接");
|
Log.d(MediaService.class.getSimpleName(), "信令已经连接");
|
||||||
}
|
}
|
||||||
} else if(Action.RECONNECT.name().equals(intent.getAction())) {
|
} else if (Action.RECONNECT.name().equals(intent.getAction())) {
|
||||||
Log.d(MediaService.class.getSimpleName(), "重新连接信令");
|
Log.d(MediaService.class.getSimpleName(), "重新连接信令");
|
||||||
this.connect();
|
this.connect();
|
||||||
} else {
|
} else {
|
||||||
@@ -114,7 +116,7 @@ public class MediaService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void close() {
|
private synchronized void close() {
|
||||||
if(this.taoyao == null) {
|
if (this.taoyao == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Toast.makeText(this.getApplicationContext(), "关闭信令", Toast.LENGTH_SHORT).show();
|
Toast.makeText(this.getApplicationContext(), "关闭信令", Toast.LENGTH_SHORT).show();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.acgist.taoyao.boot.model.MessageCode;
|
|||||||
import com.acgist.taoyao.boot.model.MessageCodeException;
|
import com.acgist.taoyao.boot.model.MessageCodeException;
|
||||||
import com.acgist.taoyao.boot.utils.CloseableUtils;
|
import com.acgist.taoyao.boot.utils.CloseableUtils;
|
||||||
import com.acgist.taoyao.boot.utils.JSONUtils;
|
import com.acgist.taoyao.boot.utils.JSONUtils;
|
||||||
import com.acgist.taoyao.media.ClientRecorder;
|
import com.acgist.taoyao.media.MediaRecorder;
|
||||||
import com.acgist.taoyao.client.utils.IdUtils;
|
import com.acgist.taoyao.client.utils.IdUtils;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
@@ -499,7 +499,7 @@ public final class Taoyao {
|
|||||||
"signal", this.wifiSignal(),
|
"signal", this.wifiSignal(),
|
||||||
"battery", this.battery(),
|
"battery", this.battery(),
|
||||||
"charging", this.charging(),
|
"charging", this.charging(),
|
||||||
"recording", ClientRecorder.getInstance().isActive()
|
"recording", MediaRecorder.getInstance().isActive()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,7 +530,7 @@ public final class Taoyao {
|
|||||||
"signal", this.wifiSignal(),
|
"signal", this.wifiSignal(),
|
||||||
"battery", this.battery(),
|
"battery", this.battery(),
|
||||||
"charging", this.charging(),
|
"charging", this.charging(),
|
||||||
"recording", ClientRecorder.getInstance().isActive()
|
"recording", MediaRecorder.getInstance().isActive()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,4 +12,7 @@
|
|||||||
<string name="encrypt">DES</string>
|
<string name="encrypt">DES</string>
|
||||||
<!-- 信令加密密钥 -->
|
<!-- 信令加密密钥 -->
|
||||||
<string name="encryptSecret">2SPWy+TF1zM=</string>
|
<string name="encryptSecret">2SPWy+TF1zM=</string>
|
||||||
|
<!-- 文件存储目录 -->
|
||||||
|
<string name="storagePathImage">/taoyao/image</string>
|
||||||
|
<string name="storagePathVideo">/taoyao/video</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -25,10 +25,24 @@ set(
|
|||||||
|
|
||||||
set(
|
set(
|
||||||
SOURCE_FILES
|
SOURCE_FILES
|
||||||
${SOURCE_DIR}/rtp.hpp
|
${SOURCE_DIR}/include/LocalClient.hpp
|
||||||
${SOURCE_DIR}/rtp.cpp
|
${SOURCE_DIR}/include/MediaRecorder.hpp
|
||||||
${SOURCE_DIR}/webrtc.hpp
|
${SOURCE_DIR}/include/MediasoupClient.hpp
|
||||||
${SOURCE_DIR}/webrtc.cpp
|
${SOURCE_DIR}/include/P2PClient.hpp
|
||||||
|
${SOURCE_DIR}/include/RemoteClient.hpp
|
||||||
|
${SOURCE_DIR}/include/Room.hpp
|
||||||
|
${SOURCE_DIR}/include/RtpAudioPublisher.hpp
|
||||||
|
${SOURCE_DIR}/include/RtpClient.hpp
|
||||||
|
${SOURCE_DIR}/include/RtpVideoPublisher.hpp
|
||||||
|
${SOURCE_DIR}/media/LocalClient.cpp
|
||||||
|
${SOURCE_DIR}/media/MediaRecorder.cpp
|
||||||
|
${SOURCE_DIR}/media/P2PClient.cpp
|
||||||
|
${SOURCE_DIR}/media/RemoteClient.cpp
|
||||||
|
${SOURCE_DIR}/media/Room.cpp
|
||||||
|
${SOURCE_DIR}/rtp/RtpAudioPublisher.cpp
|
||||||
|
${SOURCE_DIR}/rtp/RtpClient.cpp
|
||||||
|
${SOURCE_DIR}/rtp/RtpVideoPublisher.cpp
|
||||||
|
${SOURCE_DIR}/webrtc/MediasoupClient.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBWEBRTC_BINARY_PATH ${LIBWEBRTC_BINARY_PATH}/${ANDROID_ABI} CACHE STRING "libwebrtc binary path" FORCE)
|
set(LIBWEBRTC_BINARY_PATH ${LIBWEBRTC_BINARY_PATH}/${ANDROID_ABI} CACHE STRING "libwebrtc binary path" FORCE)
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// 通道类型:rtp
|
|
||||||
#define TRANSPORT_RTP "RTP"
|
|
||||||
// 通道类型:webrtc
|
|
||||||
#define TRANSPORT_WEBRTC "WEBRTC"
|
|
||||||
|
|
||||||
namespace acgist {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace acgist {
|
namespace acgist {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace acgist {
|
namespace acgist {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "LocalClient.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include "MediaRecorder.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include "P2PClient.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include "RemoteClient.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include "Room.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include "RtpAudioPublisher.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include "RtpClient.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include "RtpVideoPublisher.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include <jni.h>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#include "../include/AudioPublisher.hpp"
|
|
||||||
|
|
||||||
namespace acgist {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#include "../include/MediaRecorder.hpp"
|
|
||||||
|
|
||||||
namespace acgist {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#include "MediasoupClient.hpp"
|
||||||
|
|
||||||
|
namespace acgist {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#include "../include/VideoPublisher.hpp"
|
|
||||||
|
|
||||||
namespace acgist {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,8 +6,7 @@ package com.acgist.taoyao.media;
|
|||||||
*
|
*
|
||||||
* @author acgist
|
* @author acgist
|
||||||
*/
|
*/
|
||||||
public class RoomClient {
|
public class LocalClient {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,310 @@
|
|||||||
|
package com.acgist.taoyao.media;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.webrtc.AudioSource;
|
||||||
|
import org.webrtc.AudioTrack;
|
||||||
|
import org.webrtc.Camera2Enumerator;
|
||||||
|
import org.webrtc.CameraEnumerator;
|
||||||
|
import org.webrtc.CameraVideoCapturer;
|
||||||
|
import org.webrtc.EglBase;
|
||||||
|
import org.webrtc.MediaConstraints;
|
||||||
|
import org.webrtc.MediaStream;
|
||||||
|
import org.webrtc.PeerConnectionFactory;
|
||||||
|
import org.webrtc.SurfaceTextureHelper;
|
||||||
|
import org.webrtc.SurfaceViewRenderer;
|
||||||
|
import org.webrtc.VideoCapturer;
|
||||||
|
import org.webrtc.VideoSource;
|
||||||
|
import org.webrtc.VideoTrack;
|
||||||
|
import org.webrtc.voiceengine.WebRtcAudioUtils;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 媒体来源管理器
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
public class MediaManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 来源类型
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
|
||||||
|
// 后置摄像头
|
||||||
|
BACK,
|
||||||
|
// 前置摄像头
|
||||||
|
FRONT,
|
||||||
|
// 屏幕共享
|
||||||
|
SCREEN;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频类型
|
||||||
|
*/
|
||||||
|
private Type type;
|
||||||
|
/**
|
||||||
|
* 上下文
|
||||||
|
*/
|
||||||
|
private Context context;
|
||||||
|
/**
|
||||||
|
* 媒体流:声音、主码流(预览流)、次码流
|
||||||
|
*/
|
||||||
|
private MediaStream mediaStream;
|
||||||
|
/**
|
||||||
|
* 屏幕捕获
|
||||||
|
*/
|
||||||
|
private VideoCapturer videoCapturer;
|
||||||
|
/**
|
||||||
|
* 摄像头捕获
|
||||||
|
*/
|
||||||
|
private CameraVideoCapturer cameraVideoCapturer;
|
||||||
|
/**
|
||||||
|
* Peer连接工厂
|
||||||
|
*/
|
||||||
|
private PeerConnectionFactory peerConnectionFactory;
|
||||||
|
/**
|
||||||
|
* 预览
|
||||||
|
*/
|
||||||
|
private SurfaceViewRenderer previewView;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 设置采样
|
||||||
|
// WebRtcAudioUtils.setDefaultSampleRateHz();
|
||||||
|
// 噪声消除
|
||||||
|
WebRtcAudioUtils.setWebRtcBasedNoiseSuppressor(true);
|
||||||
|
// 回声小丑
|
||||||
|
WebRtcAudioUtils.setWebRtcBasedAcousticEchoCanceler(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载媒体流
|
||||||
|
*/
|
||||||
|
public void init() {
|
||||||
|
this.peerConnectionFactory = PeerConnectionFactory.builder().createPeerConnectionFactory();
|
||||||
|
this.mediaStream = this.peerConnectionFactory.createLocalMediaStream("ARDAMS");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换视频来源
|
||||||
|
*
|
||||||
|
* @param type 来源类型
|
||||||
|
*
|
||||||
|
* TODO:设置分享
|
||||||
|
*/
|
||||||
|
public void exchange(Type type) {
|
||||||
|
if(this.type == type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.type = type;
|
||||||
|
Log.i(MediaManager.class.getSimpleName(), "设置视频来源:" + type);
|
||||||
|
if(this.type == Type.SCREEN || type == Type.SCREEN) {
|
||||||
|
this.initVideo();
|
||||||
|
} else {
|
||||||
|
// TODO:测试是否需要完全重置
|
||||||
|
this.cameraVideoCapturer.switchCamera(new CameraVideoCapturer.CameraSwitchHandler() {
|
||||||
|
@Override
|
||||||
|
public void onCameraSwitchDone(boolean success) {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onCameraSwitchError(String message) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载音频
|
||||||
|
*/
|
||||||
|
private void initAudio() {
|
||||||
|
// 关闭音频
|
||||||
|
this.closeAudioTrack();
|
||||||
|
// 加载音频
|
||||||
|
final MediaConstraints mediaConstraints = new MediaConstraints();
|
||||||
|
final AudioSource audioSource = this.peerConnectionFactory.createAudioSource(mediaConstraints);
|
||||||
|
final AudioTrack audioTrack = this.peerConnectionFactory.createAudioTrack("ARDAMSa0", audioSource);
|
||||||
|
audioTrack.setEnabled(true);
|
||||||
|
this.mediaStream.addTrack(audioTrack);
|
||||||
|
Log.i(MediaManager.class.getSimpleName(), "加载音频:" + audioTrack.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载视频
|
||||||
|
*/
|
||||||
|
private void initVideo() {
|
||||||
|
this.closeVideoTrack();
|
||||||
|
if(this.cameraVideoCapturer != null) {
|
||||||
|
this.cameraVideoCapturer.dispose();
|
||||||
|
}
|
||||||
|
final CameraEnumerator cameraEnumerator = new Camera2Enumerator(this.context);
|
||||||
|
final String[] names = cameraEnumerator.getDeviceNames();
|
||||||
|
for(String name : names) {
|
||||||
|
if(this.type == Type.FRONT && cameraEnumerator.isFrontFacing(name)) {
|
||||||
|
Log.i(MediaManager.class.getSimpleName(), "加载前置摄像头:" + name);
|
||||||
|
this.cameraVideoCapturer = cameraEnumerator.createCapturer(name, new MediaCameraEventsHandler());
|
||||||
|
} else if(this.type == Type.BACK && cameraEnumerator.isBackFacing(name)) {
|
||||||
|
Log.i(MediaManager.class.getSimpleName(), "加载后置摄像头:" + name);
|
||||||
|
this.cameraVideoCapturer = cameraEnumerator.createCapturer(name, new MediaCameraEventsHandler());
|
||||||
|
} else {
|
||||||
|
Log.i(MediaManager.class.getSimpleName(), "忽略摄像头:" + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载视频
|
||||||
|
*/
|
||||||
|
private void initVideoTrack() {
|
||||||
|
SurfaceTextureHelper surfaceTextureHelper = null;
|
||||||
|
// 设置预览
|
||||||
|
if(this.previewView != null) {
|
||||||
|
final EglBase eglBase = EglBase.create();
|
||||||
|
surfaceTextureHelper = SurfaceTextureHelper.create("MediaVideoThread", eglBase.getEglBaseContext());
|
||||||
|
this.previewView.setMirror(true);
|
||||||
|
this.previewView.setEnableHardwareScaler(true);
|
||||||
|
}
|
||||||
|
// 是否捕获屏幕
|
||||||
|
final boolean screen = this.type == Type.SCREEN;
|
||||||
|
final VideoSource videoSource = this.peerConnectionFactory.createVideoSource(screen);
|
||||||
|
if(screen) {
|
||||||
|
Log.i(MediaManager.class.getSimpleName(), "捕获屏幕");
|
||||||
|
} else {
|
||||||
|
Log.i(MediaManager.class.getSimpleName(), "捕获摄像头");
|
||||||
|
this.cameraVideoCapturer.initialize(surfaceTextureHelper, this.context, videoSource.getCapturerObserver());
|
||||||
|
this.cameraVideoCapturer.startCapture(640, 480, 30);
|
||||||
|
}
|
||||||
|
final VideoTrack videoTrack = this.peerConnectionFactory.createVideoTrack("ARDAMSv0", videoSource);
|
||||||
|
videoTrack.setEnabled(true);
|
||||||
|
this.mediaStream.addTrack(videoTrack);
|
||||||
|
Log.i(MediaManager.class.getSimpleName(), "加载视频:" + videoTrack.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPreview() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pauseAudio() {
|
||||||
|
synchronized (this.mediaStream.audioTracks) {
|
||||||
|
this.mediaStream.audioTracks.forEach(a -> a.setEnabled(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resumeAudio() {
|
||||||
|
synchronized (this.mediaStream.audioTracks) {
|
||||||
|
this.mediaStream.audioTracks.forEach(a -> a.setEnabled(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pauseVideo() {
|
||||||
|
synchronized (this.mediaStream.videoTracks) {
|
||||||
|
this.mediaStream.videoTracks.forEach(v -> v.setEnabled(false));
|
||||||
|
}
|
||||||
|
synchronized (this.mediaStream.preservedVideoTracks) {
|
||||||
|
this.mediaStream.preservedVideoTracks.forEach(v -> v.setEnabled(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resumeVideo() {
|
||||||
|
synchronized (this.mediaStream.videoTracks) {
|
||||||
|
this.mediaStream.videoTracks.forEach(v -> v.setEnabled(true));
|
||||||
|
}
|
||||||
|
synchronized (this.mediaStream.preservedVideoTracks) {
|
||||||
|
this.mediaStream.preservedVideoTracks.forEach(v -> v.setEnabled(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭声音
|
||||||
|
*/
|
||||||
|
private void closeAudioTrack() {
|
||||||
|
synchronized (this.mediaStream.audioTracks) {
|
||||||
|
AudioTrack track;
|
||||||
|
final Iterator<AudioTrack> iterator = this.mediaStream.audioTracks.iterator();
|
||||||
|
while(iterator.hasNext()) {
|
||||||
|
track = iterator.next();
|
||||||
|
iterator.remove();
|
||||||
|
track.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭视频
|
||||||
|
*/
|
||||||
|
private void closeVideoTrack() {
|
||||||
|
// 次码流
|
||||||
|
this.closeVideoTrack(this.mediaStream.videoTracks);
|
||||||
|
// 主码流
|
||||||
|
this.closeVideoTrack(this.mediaStream.preservedVideoTracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭视频
|
||||||
|
*
|
||||||
|
* @param list 视频列表
|
||||||
|
*/
|
||||||
|
private void closeVideoTrack(List<VideoTrack> list) {
|
||||||
|
synchronized (list) {
|
||||||
|
VideoTrack track;
|
||||||
|
final Iterator<VideoTrack> iterator = list.iterator();
|
||||||
|
while(iterator.hasNext()) {
|
||||||
|
track = iterator.next();
|
||||||
|
iterator.remove();
|
||||||
|
track.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放资源
|
||||||
|
*/
|
||||||
|
public void close() {
|
||||||
|
if(this.cameraVideoCapturer != null) {
|
||||||
|
this.cameraVideoCapturer.dispose();
|
||||||
|
}
|
||||||
|
if(this.mediaStream != null) {
|
||||||
|
this.mediaStream.dispose();
|
||||||
|
}
|
||||||
|
if(this.peerConnectionFactory != null) {
|
||||||
|
this.peerConnectionFactory.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 摄像头事件
|
||||||
|
*
|
||||||
|
* @author acgist
|
||||||
|
*/
|
||||||
|
private static class MediaCameraEventsHandler implements CameraVideoCapturer.CameraEventsHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraError(String message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraDisconnected() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraFreezed(String message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraOpening(String message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFirstFrameAvailable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCameraClosed() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,16 +5,16 @@ package com.acgist.taoyao.media;
|
|||||||
*
|
*
|
||||||
* @author acgist
|
* @author acgist
|
||||||
*/
|
*/
|
||||||
public final class ClientRecorder {
|
public final class MediaRecorder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否正在录像
|
* 是否正在录像
|
||||||
*/
|
*/
|
||||||
private boolean active;
|
private boolean active;
|
||||||
|
|
||||||
private static final ClientRecorder INSTANCE = new ClientRecorder();
|
private static final MediaRecorder INSTANCE = new MediaRecorder();
|
||||||
|
|
||||||
public static final ClientRecorder getInstance() {
|
public static final MediaRecorder getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.acgist.taoyao.p2p;
|
package com.acgist.taoyao.media;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* P2P终端
|
* P2P终端
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.acgist.taoyao.media;
|
package com.acgist.taoyao.media;
|
||||||
|
|
||||||
public class AudioPublisher {
|
public class RemoteClient {
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.acgist.taoyao.media;
|
package com.acgist.taoyao.media;
|
||||||
|
|
||||||
public class VideoPublisher {
|
public class Room {
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user