Skip to content

Commit fa2f161

Browse files
authored
Merge pull request #327 from BoleLiu/dev
Release v3.1.0
2 parents 7d50a61 + f1dcc5d commit fa2f161

File tree

79 files changed

+229
-41
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+229
-41
lines changed

PLDroidMediaStreamingDemo/app/build.gradle

+9-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,21 @@ android {
88
applicationId "com.qiniu.pili.droid.streaming.demo"
99
minSdkVersion 18
1010
targetSdkVersion 29
11-
versionCode 72
12-
versionName "3.0.2"
11+
versionCode 73
12+
versionName "3.1.0"
1313
}
1414
buildTypes {
1515
release {
1616
minifyEnabled false
1717
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
1818
}
1919
}
20+
lintOptions {
21+
checkReleaseBuilds false
22+
// Or, if you prefer, you can continue to check for errors in release builds,
23+
// but continue the build even when errors are found:
24+
abortOnError false
25+
}
2026
}
2127

2228
dependencies {
@@ -35,6 +41,6 @@ dependencies {
3541
implementation project(':library')
3642
} else {
3743
// 推流 SDK jar 包,为推流 SDK 必须依赖的库
38-
implementation files('libs/pldroid-media-streaming-3.0.2.jar')
44+
implementation files('libs/pldroid-media-streaming-3.1.0.jar')
3945
}
4046
}
Binary file not shown.
Binary file not shown.

PLDroidMediaStreamingDemo/app/src/main/java/com/qiniu/pili/droid/streaming/demo/MainActivity.java

+78-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.zxing.integration.android.IntentResult;
2525
import com.qiniu.pili.droid.streaming.PLAuthenticationResultCallback;
2626
import com.qiniu.pili.droid.streaming.StreamingEnv;
27+
import com.qiniu.pili.droid.streaming.common.FileLogHelper;
2728
import com.qiniu.pili.droid.streaming.demo.activity.AVStreamingActivity;
2829
import com.qiniu.pili.droid.streaming.demo.activity.AudioStreamingActivity;
2930
import com.qiniu.pili.droid.streaming.demo.activity.ImportStreamingActivity;
@@ -35,7 +36,10 @@
3536
import com.qiniu.pili.droid.streaming.demo.utils.PermissionChecker;
3637
import com.qiniu.pili.droid.streaming.demo.utils.Util;
3738

39+
import java.net.URI;
40+
import java.net.URISyntaxException;
3841
import java.util.Arrays;
42+
import java.util.List;
3943
import java.util.UUID;
4044

4145
public class MainActivity extends FragmentActivity {
@@ -56,7 +60,9 @@ public class MainActivity extends FragmentActivity {
5660
private TextView mInputTextTV;
5761
private Spinner mStreamTypeSpinner;
5862
private CheckBox mDebugModeCheckBox;
63+
private RadioButton mRtmpPushButton;
5964
private RadioButton mQuicPushButton;
65+
private RadioButton mSrtPushButton;
6066

6167
private EncodingConfigFragment mEncodingConfigFragment;
6268
private CameraConfigFragment mCameraConfigFragment;
@@ -67,31 +73,58 @@ public class MainActivity extends FragmentActivity {
6773
protected void onCreate(Bundle savedInstanceState) {
6874
super.onCreate(savedInstanceState);
6975
setContentView(R.layout.activity_main);
70-
// 开启日志的本地保存,保存在应用私有目录(getExternalFilesDir) 或者 getFilesDir 文件目录下的 Pili 文件夹中
71-
StreamingEnv.setLogLevel(Log.INFO);
72-
StreamingEnv.startLogFile();
7376

7477
TextView versionInfo = (TextView) findViewById(R.id.version_info);
7578
mInputTextTV = (TextView) findViewById(R.id.input_url);
7679
mStreamTypeSpinner = (Spinner) findViewById(R.id.stream_types);
7780
mDebugModeCheckBox = (CheckBox) findViewById(R.id.debug_mode);
81+
mRtmpPushButton = (RadioButton) findViewById(R.id.transfer_rtmp);
7882
mQuicPushButton = (RadioButton) findViewById(R.id.transfer_quic);
83+
mSrtPushButton = (RadioButton) findViewById(R.id.transfer_srt);
7984

80-
mInputTextTV.setText(Cache.retrieveURL(this));
85+
String publishUrl = Cache.retrieveURL(this);
86+
if (publishUrl.startsWith("srt")) {
87+
mSrtPushButton.setChecked(true);
88+
} else {
89+
mRtmpPushButton.setChecked(true);
90+
}
91+
mInputTextTV.setText(publishUrl);
8192

8293
FragmentManager fragmentManager = getSupportFragmentManager();
8394
mEncodingConfigFragment = (EncodingConfigFragment) fragmentManager.findFragmentById(R.id.encoding_config_fragment);
8495
mCameraConfigFragment = (CameraConfigFragment) fragmentManager.findFragmentById(R.id.camera_config_fragment);
8596

8697
versionInfo.setText("versionName: " + BuildConfig.VERSION_NAME + " versionCode: " + BuildConfig.VERSION_CODE);
98+
versionInfo.setOnLongClickListener(new View.OnLongClickListener() {
99+
@Override
100+
public boolean onLongClick(View v) {
101+
StreamingEnv.reportLogFiles(new FileLogHelper.LogReportCallback() {
102+
@Override
103+
public void onReportSuccess(List<String> logNames) {
104+
if (logNames.size() == 0) {
105+
return;
106+
}
107+
for (String logName : logNames) {
108+
Log.i(TAG, logName);
109+
}
110+
Log.i(TAG, "日志已上传");
111+
Toast.makeText(MainActivity.this, "日志已上传!", Toast.LENGTH_SHORT).show();
112+
}
113+
114+
@Override
115+
public void onReportError(String name, String errorMsg) {
116+
Toast.makeText(MainActivity.this, "日志 " + name + " 上传失败: " + errorMsg, Toast.LENGTH_SHORT).show();
117+
}
118+
});
119+
return true;
120+
}
121+
});
87122
initStreamTypeSpinner();
88123
}
89124

90125
@Override
91126
protected void onDestroy() {
92127
super.onDestroy();
93-
StreamingEnv.stopLogFile();
94-
Log.i(TAG, "Log file path : " + StreamingEnv.getLogFilePath());
95128
}
96129

97130
@Override
@@ -129,17 +162,24 @@ public void launchStreaming(View v) {
129162
Util.showToast(this, "推流地址不能为空!!!");
130163
return;
131164
}
165+
if ((mSrtPushButton.isChecked() && !streamText.startsWith("srt"))
166+
|| (!mSrtPushButton.isChecked() && !streamText.startsWith("rtmp"))) {
167+
Util.showToast(this, "请检查推流地址和协议是否匹配!!!");
168+
return;
169+
}
132170

133171
if (mDebugModeCheckBox.isChecked()) {
134172
StreamingEnv.setLogLevel(Log.VERBOSE);
135173
}
136174

137175
boolean quicEnable = mQuicPushButton.isChecked();
176+
boolean srtEnable = mSrtPushButton.isChecked();
138177

139178
int pos = mStreamTypeSpinner.getSelectedItemPosition();
140179
Intent intent = new Intent(this, ACTIVITY_CLASSES[pos]);
141180
intent.putExtra(Config.PUBLISH_URL, streamText);
142181
intent.putExtra(Config.TRANSFER_MODE_QUIC, quicEnable);
182+
intent.putExtra(Config.TRANSFER_MODE_SRT, srtEnable);
143183
intent.putExtras(mEncodingConfigFragment.getIntent());
144184
boolean isAudioStereo = ((CheckBox) findViewById(R.id.audio_channel_stereo)).isChecked();
145185
intent.putExtra(Config.AUDIO_CHANNEL_STEREO, isAudioStereo);
@@ -182,6 +222,9 @@ public void onClickGenPublishURL(View v) {
182222
@Override
183223
public void run() {
184224
String publishUrl = genPublishURL();
225+
if (mSrtPushButton.isChecked() && publishUrl.startsWith("rtmp://")) {
226+
publishUrl = getSrtPublishUrl(publishUrl);
227+
}
185228
if (publishUrl != null) {
186229
Cache.saveURL(MainActivity.this, publishUrl);
187230
updateInputTextView(publishUrl);
@@ -255,6 +298,35 @@ private String genPublishURL() {
255298
return publishUrl;
256299
}
257300

301+
/**
302+
* 自定义组装 SRT 推流地址
303+
*
304+
* 建议由您业务服务端生成符合规范的 SRT 推流地址
305+
* 地址规范可参考:https://github.com/Haivision/srt/blob/master/docs/features/access-control.md#general-syntax
306+
*
307+
* @param rtmpUrl rtmp 地址
308+
* @return 组装的 SRT 地址
309+
*/
310+
private String getSrtPublishUrl(String rtmpUrl) {
311+
URI u;
312+
try {
313+
u = new URI(rtmpUrl);
314+
String path = u.getPath().substring(1);
315+
String query = u.getQuery();
316+
StringBuilder publishUrl = new StringBuilder(String.format("srt://%s?streamid=#!::h=%s,m=publish", u.getHost(), path));
317+
if (query != null) {
318+
String[] queries = query.split("&");
319+
for (String q : queries) {
320+
publishUrl.append(",").append(q);
321+
}
322+
}
323+
return publishUrl.toString();
324+
} catch (URISyntaxException e) {
325+
e.printStackTrace();
326+
}
327+
return "";
328+
}
329+
258330
private void updateInputTextView(final String url) {
259331
runOnUiThread(new Runnable() {
260332
@Override

PLDroidMediaStreamingDemo/app/src/main/java/com/qiniu/pili/droid/streaming/demo/StreamingApplication.java

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import android.app.Application;
44
import android.content.Intent;
5+
import android.util.Log;
56

67
import com.qiniu.pili.droid.streaming.StreamingEnv;
78
import com.qiniu.pili.droid.streaming.demo.service.KeepAppAliveService;
@@ -22,6 +23,11 @@ public void onCreate() {
2223
* 注意:参数 userId 代表用户的唯一标识符,用于区分不同的用户
2324
*/
2425
StreamingEnv.init(getApplicationContext(), Util.getUserId(getApplicationContext()));
26+
// 设置日志等级
27+
StreamingEnv.setLogLevel(Log.INFO);
28+
// 开启日志的本地保存,保存在应用私有目录(getExternalFilesDir) 或者 getFilesDir 文件目录下的 Pili 文件夹中
29+
// 默认为关闭
30+
StreamingEnv.setLogfileEnabled(true);
2531

2632
/**
2733
* track app background state to avoid possibly stopping microphone recording

PLDroidMediaStreamingDemo/app/src/main/java/com/qiniu/pili/droid/streaming/demo/activity/AVStreamingActivity.java

+30-11
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ public class AVStreamingActivity extends Activity implements
100100

101101
private String mPublishUrl;
102102
private boolean mIsQuicEnabled;
103+
private boolean mIsSrtEnabled;
103104
private String mPicStreamingFilePath;
104105

105106
// 推流操作管理类实例
@@ -134,6 +135,7 @@ protected void onCreate(Bundle savedInstanceState) {
134135
Intent intent = getIntent();
135136
mPublishUrl = intent.getStringExtra(Config.PUBLISH_URL);
136137
mIsQuicEnabled = intent.getBooleanExtra(Config.TRANSFER_MODE_QUIC, false);
138+
mIsSrtEnabled = intent.getBooleanExtra(Config.TRANSFER_MODE_SRT, false);
137139
mAudioStereoEnable = intent.getBooleanExtra(Config.AUDIO_CHANNEL_STEREO, false);
138140

139141
HandlerThread handlerThread = new HandlerThread(TAG);
@@ -178,10 +180,12 @@ protected void onPause() {
178180
protected void onStop() {
179181
super.onStop();
180182
// 如果当前正在图片推流,则退后台不会终止推流
181-
if (!mIsPictureStreaming) {
183+
if (isFinishing() || !mIsPictureStreaming) {
182184
mIsReady = false;
185+
if (mIsStreaming) {
186+
Toast.makeText(this, "推流已停止!!!", Toast.LENGTH_SHORT).show();
187+
}
183188
mMediaStreamingManager.pause();
184-
Toast.makeText(this, "推流已停止!!!", Toast.LENGTH_SHORT).show();
185189
} else {
186190
Toast.makeText(this, "当前正在图片推流!!!", Toast.LENGTH_SHORT).show();
187191
}
@@ -192,6 +196,7 @@ protected void onDestroy() {
192196
super.onDestroy();
193197
if (mSubThreadHandler != null) {
194198
mSubThreadHandler.getLooper().quit();
199+
mSubThreadHandler = null;
195200
}
196201
// 销毁推流 Manager 的资源
197202
mMediaStreamingManager.destroy();
@@ -239,6 +244,7 @@ private void initEncodingProfile() {
239244
// 是否开启 QUIC 推流。
240245
// QUIC 是基于 UDP 开发的可靠传输协议,在弱网下拥有更好的推流效果,相比于 TCP 拥有更低的延迟,可抵抗更高的丢包率。
241246
mProfile.setQuicEnable(mIsQuicEnabled);
247+
mProfile.setSrtEnabled(mIsSrtEnabled);
242248

243249
// 自定义配置音频的采样率、码率以及声道数的对象,如果使用预设配置,则无需实例化
244250
StreamingProfile.AudioProfile aProfile = null;
@@ -593,6 +599,10 @@ public void onAudioMixFileSelectionClicked() {
593599
dialog.setDialogSelectionListener(new DialogSelectionListener() {
594600
@Override
595601
public void onSelectedFilePaths(String[] files) {
602+
if (files == null || files.length == 0) {
603+
Toast.makeText(AVStreamingActivity.this, "Choose an audio please!", Toast.LENGTH_SHORT).show();
604+
return;
605+
}
596606
String filePath = files[0];
597607
try {
598608
mAudioMixer.setFile(filePath, true);
@@ -743,7 +753,9 @@ public boolean onOrientationChanged(boolean isPortrait) {
743753
return false;
744754
}
745755
Log.i(TAG, "isPortrait : " + isPortrait);
746-
mOrientationChanged = true;
756+
if (mIsStreaming) {
757+
mOrientationChanged = true;
758+
}
747759
mProfile.setEncodingOrientation(isPortrait ? StreamingProfile.ENCODING_ORIENTATION.PORT : StreamingProfile.ENCODING_ORIENTATION.LAND);
748760

749761
// 更新 StreamingProfile 的时候,需要重新推流才可以生效!!!
@@ -1298,16 +1310,23 @@ public void run() {
12981310
}
12991311

13001312
private void stopStreamingInternal() {
1301-
if (mMediaStreamingManager == null) {
1313+
if (mMediaStreamingManager == null || !mIsStreaming) {
13021314
return;
13031315
}
1304-
final boolean res = mMediaStreamingManager.stopStreaming();
1305-
runOnUiThread(new Runnable() {
1306-
@Override
1307-
public void run() {
1308-
mControlFragment.setShutterButtonPressed(!res);
1309-
}
1310-
});
1316+
if (mSubThreadHandler != null) {
1317+
mSubThreadHandler.post(new Runnable() {
1318+
@Override
1319+
public void run() {
1320+
final boolean res = mMediaStreamingManager.stopStreaming();
1321+
runOnUiThread(new Runnable() {
1322+
@Override
1323+
public void run() {
1324+
mControlFragment.setShutterButtonPressed(!res);
1325+
}
1326+
});
1327+
}
1328+
});
1329+
}
13111330
}
13121331

13131332
private boolean isPictureStreaming() {

PLDroidMediaStreamingDemo/app/src/main/java/com/qiniu/pili/droid/streaming/demo/activity/AudioStreamingActivity.java

+20-7
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class AudioStreamingActivity extends Activity {
4444
private boolean mShutterButtonPressed = false;
4545
private String mPublishUrl;
4646
private boolean mIsQuicEnabled;
47+
private boolean mIsSrtEnabled;
4748
private boolean mIsReady;
4849
private boolean mAudioStereoEnable = false;
4950

@@ -65,6 +66,7 @@ protected void onCreate(Bundle savedInstanceState) {
6566
Intent intent = getIntent();
6667
mPublishUrl = intent.getStringExtra(Config.PUBLISH_URL);
6768
mIsQuicEnabled = intent.getBooleanExtra(Config.TRANSFER_MODE_QUIC, false);
69+
mIsSrtEnabled = intent.getBooleanExtra(Config.TRANSFER_MODE_SRT, false);
6870
mAudioStereoEnable = intent.getBooleanExtra(Config.AUDIO_CHANNEL_STEREO, false);
6971

7072
HandlerThread handlerThread = new HandlerThread(TAG);
@@ -145,6 +147,7 @@ private void initEncodingProfile() {
145147
// 是否开启 QUIC 推流。
146148
// QUIC 是基于 UDP 开发的可靠传输协议,在弱网下拥有更好的推流效果,相比于 TCP 拥有更低的延迟,可抵抗更高的丢包率。
147149
mProfile.setQuicEnable(mIsQuicEnabled);
150+
mProfile.setSrtEnabled(mIsSrtEnabled);
148151

149152
// 自定义配置音频的采样率、码率以及声道数的对象,如果使用预设配置,则无需实例化
150153
StreamingProfile.AudioProfile aProfile = null;
@@ -396,15 +399,25 @@ public void run() {
396399
* 停止推流
397400
*/
398401
private void stopStreamingInternal() {
399-
if (mShutterButtonPressed) {
402+
if (mShutterButtonPressed && mSubThreadHandler != null) {
400403
// disable the shutter button before stopStreaming
401404
setShutterButtonEnabled(false);
402-
boolean res = mMediaStreamingManager.stopStreaming();
403-
if (!res) {
404-
mShutterButtonPressed = true;
405-
setShutterButtonEnabled(true);
406-
}
407-
setShutterButtonPressed(mShutterButtonPressed);
405+
mSubThreadHandler.post(new Runnable() {
406+
@Override
407+
public void run() {
408+
final boolean res = mMediaStreamingManager.stopStreaming();
409+
runOnUiThread(new Runnable() {
410+
@Override
411+
public void run() {
412+
if (!res) {
413+
mShutterButtonPressed = true;
414+
setShutterButtonEnabled(true);
415+
}
416+
setShutterButtonPressed(mShutterButtonPressed);
417+
}
418+
});
419+
}
420+
});
408421
}
409422
}
410423

0 commit comments

Comments
 (0)