Пример Android-приложения с плеером и стримером
Данное приложение может использоваться для публикации WebRTC-видеопотока и воспроизведения любого из следующих типов потоков с Web Call Server:
...
Слева отображается видео с камеры, справа воспроизводится другой поток.
Работа с кодом примера
Для разбора кода возьмем класс StreamingMinActivity.java примера streaming-min, который доступен для скачивания в соответствующей сборке 1.0.1.38.
...
Flashphoner.init() код
Code Block | ||||
---|---|---|---|---|
| ||||
Flashphoner.init(this); |
...
- URL WCS-сервера
- SurfaceViewRenderer localRenderer, который будет использоваться для отображения видео с камеры
- SurfaceViewRenderer remoteRenderer, который будет использоваться для отображения воспроизводимого потока
Code Block | ||||
---|---|---|---|---|
| ||||
sessionOptions = new SessionOptions(mWcsUrlView.getText().toString()); sessionOptions.setLocalRenderer(localRender); sessionOptions.setRemoteRenderer(remoteRender); /** * Uncomment this code to use your own RTCConfiguration. For example, you can use custom TURN server */ //List<PeerConnection.IceServer> iceServers = new ArrayList<>(); //iceServers.add(new PeerConnection.IceServer("turn:your.turn-server.com:443?transport=tcp","username","passw0rd")); //PeerConnection.RTCConfiguration customConfig = new PeerConnection.RTCConfiguration(iceServers); //sessionOptions.setMediaOptions(customConfig); /** * Session for connection to WCS server is created with method createSession(). */ session = Flashphoner.createSession(sessionOptions); |
...
Session.connect(). код
Code Block | ||||
---|---|---|---|---|
| ||||
session.connect(new Connection()); |
...
session.onConnected() код
Code Block | ||||
---|---|---|---|---|
| ||||
@Override public void onConnected(final Connection connection) { runOnUiThread(new Runnable() { @Override public void run() { mConnectButton.setText(R.string.action_disconnect); mConnectButton.setTag(R.string.action_disconnect); mConnectButton.setEnabled(true); mConnectStatus.setText(connection.getStatus()); mPublishButton.setEnabled(true); mPlayButton.setEnabled(true); } }); |
...
ActivityCompat.requestPermissions() код
Code Block | ||||
---|---|---|---|---|
| ||||
mPublishButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (mPublishButton.getTag() == null || Integer.valueOf(R.string.action_publish).equals(mPublishButton.getTag())) { ActivityCompat.requestPermissions(StreamingMinActivity.this, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA}, PUBLISH_REQUEST_CODE); SharedPreferences sharedPref = StreamingMinActivity.this.getPreferences(Context.MODE_PRIVATE); } else { SharedPreferences.Editor editor = sharedPref.edit(); ... } editor.putString("publish_stream", mPublishStreamView.getText().toString()); ... } }); |
6. Публикация потока после предоставления соответствующих прав
Session.createStream(), Stream.publish() код
Code Block | ||||
---|---|---|---|---|
| ||||
case PUBLISH_REQUEST_CODE: { if (grantResults.length == 0 || editor.apply(); } else { grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != mPublishButton.setEnabled(false);PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "Permission has /**been denied by user"); } else { * Method Stream.stop() is called to unpublish the stream. mPublishButton.setEnabled(false); /** */ The options for the stream to publish are publishStream.stop();set. * The publishStreamstream = null;name is passed when StreamOptions object is created. } */ ViewStreamOptions currentFocusstreamOptions = getCurrentFocus(new StreamOptions(mPublishStreamView.getText().toString()); if (currentFocus != null) { /** * Uncomment this code to use InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); case WebRTC-as-RTMP. Stream will be republished to your rtmpUrl inputManager.hideSoftInputFromWindow(currentFocus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); */ } } }); |
6. Публикация потока после предоставления соответствующих прав
Session.createStream(), Stream.publish() код
Code Block | ||||
---|---|---|---|---|
| ||||
case PUBLISH_REQUEST_CODE: { //streamOptions.setRtmpUrl("rtmp://192.168.1.100:1935/live2"); if (grantResults.length == 0 || /** * Stream is created grantResults[0] != PackageManager.PERMISSION_GRANTED ||with method Session.createStream(). grantResults[1] != PackageManager.PERMISSION_GRANTED) { */ publishStream = Logsession.i(TAG, "Permission has been denied by user"createStream(streamOptions); } else { mPublishButton.setEnabled(false);... /** * The options for the stream Method Stream.publish() is called to publish are setstream. */ The stream name is passed when StreamOptions object is created.publishStream.publish(); Log.i(TAG, "Permission */ has been granted by user"); StreamOptions streamOptions = new StreamOptions(mPublishStreamView.getText().toString()); } } |
7. Воспроизведение потока при нажатии Play
Session.createStream(), Stream.play() код
Code Block | ||||
---|---|---|---|---|
| ||||
mPlayButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) /**{ mPlayButton.setEnabled(false); * Uncomment this code to use case WebRTC-as-RTMP. Stream will be republished to your rtmpUrl if (mPlayButton.getTag() == null || Integer.valueOf(R.string.action_play).equals(mPlayButton.getTag())) { /**/ //streamOptions.setRtmpUrl("rtmp://192.168.1.100:1935/live2"); * The options for the stream to play are set. /** * The stream name is passed when *StreamOptions Streamobject is created. with method Session.createStream(). */ publishStream StreamOptions streamOptions = session.createStream(streamOptions new StreamOptions(mPlayStreamView.getText().toString()); /** * Callback function for stream* status changeStream is addedcreated towith make appropriate changes in controls of the interface when publishing. method Session.createStream(). */ */ playStream = publishStreamsession.on(new StreamStatusEvent() {createStream(streamOptions); @Override... public/** void onStreamStatus(final Stream stream, final StreamStatus streamStatus) { * Method Stream.play() is called to start playback of the stream. runOnUiThread(new Runnable() { */ @Override playStream.play(); public void run() {... } else { if (StreamStatus.PUBLISHING.equals(streamStatus)) {... } ... mPublishButton.setText(R.string.action_unpublish); mPublishButton.setTag(R.string.action_unpublish); } else { } }); |
8. Остановка воспроизведение потока при нажатии Stop
Stream.stop() код
Code Block | ||||
---|---|---|---|---|
| ||||
playStream.stop();
playStream = null; |
9. Остановка публикации потока при нажатии Unpublish
Stream.stop() код
Code Block | ||||
---|---|---|---|---|
| ||||
publishStream.stop();
publishStream = null; |
10. Закрытие соединения.
Session.disconnect() код
Code Block | ||||
---|---|---|---|---|
| ||||
mConnectButton.setEnabled(false);
/**
* Connection to WCS server is closed with method Session.disconnect().
*/
session.disconnect(); |
11. Получение события, подтверждающего разъединение.
session.onDisconnection() код
Code Block | ||||
---|---|---|---|---|
| ||||
@Override public void onDisconnection(final Connection connection) { runOnUiThread(new Runnable() { @Override mPublishButton.setText(R.string.action_publish);public void run() { mConnectButton.setText(R.string.action_connect); mPublishButtonmConnectButton.setTag(R.string.action_publishconnect); mConnectButton.setEnabled(true); }mPublishButton.setText(R.string.action_publish); mPublishButton.setTag(R.string.action_publish); mPublishButton.setEnabled(truefalse); mPlayButton.setText(R.string.action_play); mPublishStatusmPlayButton.setTextsetTag(streamStatus.toString()R.string.action_play); }mPlayButton.setEnabled(false); }mConnectStatus.setText(connection.getStatus()); } }); /**mPublishStatus.setText(""); * Method StreammPlayStatus.publishsetText(""); is called to publish stream. } */ publishStream.publish(); Log.i(TAG, "Permission has been granted by user"); } } |
...
Session.createStream(), Stream.publish() код
Code Block | ||||
---|---|---|---|---|
| ||||
mPlayButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mPlayButton.setEnabled(false);
if (mPlayButton.getTag() == null || Integer.valueOf(R.string.action_play).equals(mPlayButton.getTag())) {
/**
* The options for the stream to play are set.
* The stream name is passed when StreamOptions object is created.
*/
StreamOptions streamOptions = new StreamOptions(mPlayStreamView.getText().toString());
/**
* Stream is created with method Session.createStream().
*/
playStream = session.createStream(streamOptions);
/**
* Callback function for stream status change is added to make appropriate changes in controls of the interface when playing.
*/
playStream.on(new StreamStatusEvent() {
@Override
public void onStreamStatus(final Stream stream, final StreamStatus streamStatus) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (StreamStatus.PLAYING.equals(streamStatus)) {
mPlayButton.setText(R.string.action_stop);
mPlayButton.setTag(R.string.action_stop);
} else if (StreamStatus.NOT_ENOUGH_BANDWIDTH.equals(streamStatus)) {
Log.w(TAG, "Not enough bandwidth stream " + stream.getName() + ", consider using lower video resolution or bitrate. " +
"Bandwidth " + (Math.round(stream.getNetworkBandwidth() / 1000)) + " " +
"bitrate " + (Math.round(stream.getRemoteBitrate() / 1000)));
} else {
mPlayButton.setText(R.string.action_play);
mPlayButton.setTag(R.string.action_play);
}
mPlayButton.setEnabled(true);
mPlayStatus.setText(streamStatus.toString());
}
});
}
});
/**
* Method Stream.play() is called to start playback of the stream.
*/
playStream.play();
SharedPreferences sharedPref = StreamingMinActivity.this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("play_stream", mPlayStreamView.getText().toString());
editor.apply();
} else {
/**
* Method Stream.stop() is called to stop playback of the stream.
*/
playStream.stop();
playStream = null;
}
View currentFocus = getCurrentFocus();
if (currentFocus != null) {
InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(currentFocus.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}); |
8. Остановка воспроизведение потока при нажатии Stop
Stream.stop() код
Code Block | ||||
---|---|---|---|---|
| ||||
playStream.stop();
playStream = null; |
9. Остановка публикации потока при нажатии Unpublish
Stream.stop() код
Code Block | ||||
---|---|---|---|---|
| ||||
publishStream.stop();
publishStream = null; |
10. Закрытие соединения.
Session.disconnect() код
Code Block | ||||
---|---|---|---|---|
| ||||
mConnectButton.setEnabled(false);
/**
* Connection to WCS server is closed with method Session.disconnect().
*/
session.disconnect(); |
11. Получение события, подтверждающего разъединение.
session.onDisconnection() код
Code Block | ||||
---|---|---|---|---|
| ||||
@Override
public void onDisconnection(final Connection connection) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mConnectButton.setText(R.string.action_connect);
mConnectButton.setTag(R.string.action_connect);
mConnectButton.setEnabled(true);
mPublishButton.setText(R.string.action_publish);
mPublishButton.setTag(R.string.action_publish);
mPublishButton.setEnabled(false);
mPlayButton.setText(R.string.action_play);
mPlayButton.setTag(R.string.action_play);
mPlayButton.setEnabled(false);
mConnectStatus.setText(connection.getStatus());
mPublishStatus.setText("");
mPlayStatus.setText("");
}
});
} |
...
});
} |