Пример Android-приложения для управления медиа-устройствами
Данный пример может использоваться как стример для публикации WebRTC-видеопотока с Web Call Server и позволяет выбрать медиа-устройства и параметры для публикуемого видео
...
Пример переключения объекта для вывода изображения с камеры
Работа с кодом примера
Для разбора кода возьмем класс MediaDevicesActivity.java примера media-devices, который доступен для скачивания в соответствующей сборке 1.0.1.46.
...
Code Block | ||||
---|---|---|---|---|
| ||||
case TEST_REQUEST_CODE: { if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "Permission has been denied by user"); } else { Flashphoner.getLocalMediaAccess(getConstraints(), localRender); mTestButton.setText(R.string.action_release); mTestButton.setTag(R.string.action_release); mStartButton.setEnabled(false); soundMeter = new SoundMeter(); soundMeter.start(); soundMeter..getTimer().scheduleAtFixedRate(new TimerTask() { Log.i(TAG, "Permission has @Override been granted public void run() {by user"); runOnUiThread(new Runnable() { @Override public void run() { String text = "Level: " + Math.floor(soundMeter.getAmplitude() * 10); mMicLevel.setText(text); } }); } }, 0, 300); Log.i(TAG, "Permission has been granted by user"); } break; |
5. Создание сессии
Flashphoner.createSession() код
Методу передается объект SessionOptions со следующими параметрами
- URL WCS-сервера
- SurfaceViewRenderer localRenderer, который будет использоваться для отображения видео с камеры
- SurfaceViewRenderer remoteRenderer, который будет использоваться для воспроизведения опубликованного видеопотока
Code Block | ||||
---|---|---|---|---|
| ||||
SessionOptions sessionOptions = new SessionOptions(url);
sessionOptions.setLocalRenderer(localRender);
sessionOptions.setRemoteRenderer(remoteRender);
/**
* Session for connection to WCS server is created with method createSession().
*/
session = Flashphoner.createSession(sessionOptions); |
6. Подключение к серверу.
Session.connect(). код
Code Block | ||||
---|---|---|---|---|
| ||||
session.connect(new Connection()); |
7. Получение от сервера события, подтверждающего успешное соединение.
session.onConnected() код
Code Block | ||||
---|---|---|---|---|
| ||||
@Override
public void onConnected(final Connection connection) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mStartButton.setText(R.string.action_stop);
mStartButton.setTag(R.string.action_stop);
mStartButton.setEnabled(true);
mTestButton.setEnabled(false);
mStatusView.setText(connection.getStatus());;
/**
* The options for the stream to publish are set.
* The stream name is passed when StreamOptions object is created.
* VideoConstraints object is used to set the source camera, FPS and resolution.
* Stream constraints are set with method StreamOptions.setConstraints().
*/
StreamOptions streamOptions = new StreamOptions(streamName);
Constraints constraints = getConstraints();
streamOptions.setConstraints(constraints);
String[] stripCodec = {(String) mStripStreamerCodec.getSpinner().getSelectedItem()};
streamOptions.setStripCodecs(stripCodec);
/**
* Stream is created with method Session.createStream().
*/
publishStream = session.createStream(streamOptions);
...
}
});
} |
8. Создание потока и подготовка к публикации
session.createStream() код
Code Block | ||||
---|---|---|---|---|
| ||||
publishStream = session.createStream(streamOptions);
if (mMuteAudio.isChecked()) {
publishStream.muteAudio();
}
if (mMuteVideo.isChecked()) {
publishStream.muteVideo();
}
...
ActivityCompat.requestPermissions(MediaDevicesActivity.this,
new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA},
PUBLISH_REQUEST_CODE); |
9. Публикация потока
Stream.publish() код
Code Block | ||||
---|---|---|---|---|
| ||||
case PUBLISH_REQUEST_CODE: {
if (grantResults.length == 0 ||
grantResults[0] != PackageManager.PERMISSION_GRANTED ||
grantResults[1] != PackageManager.PERMISSION_GRANTED) {
mStartButton.setEnabled(false);
mTestButton.setEnabled(false);
session.disconnect();
Log.i(TAG, "Permission has been denied by user");
} else {
/**
* Method Stream.publish() is called to publish stream.
*/
publishStream.publish();
Log.i(TAG, "Permission has been granted by user");
}
break;
} |
10. Получение от сервера события, подтверждающего успешную публикацию потока
StreamStatusEvent PUBLISHING код
При получении данного события создается превью-видеопоток при помощи Session.createStream() и вызывается Stream.play() для его воспроизведения.
Code Block | ||||
---|---|---|---|---|
| ||||
publishStream.on(new StreamStatusEvent() { @Override public void onStreamStatus(final Stream stream, final StreamStatus streamStatus) { runOnUiThread(new Runnable() { @Override public void run() { if (StreamStatus.PUBLISHING.equals(streamStatus)) { /** * The options for the stream to play are set. * The stream name is passed when StreamOptions object is created. */} break; |
5. Создание сессии
Flashphoner.createSession() код
Методу передается объект SessionOptions со следующими параметрами
- URL WCS-сервера
- SurfaceViewRenderer localRenderer, который будет использоваться для отображения видео с камеры
- SurfaceViewRenderer remoteRenderer, который будет использоваться для воспроизведения опубликованного видеопотока
Code Block | ||||
---|---|---|---|---|
| ||||
SessionOptions sessionOptions = new SessionOptions(url);
sessionOptions.setLocalRenderer(localRender);
sessionOptions.setRemoteRenderer(remoteRender);
/**
* Session for connection to WCS server is created with method createSession().
*/
session = Flashphoner.createSession(sessionOptions); |
6. Подключение к серверу.
Session.connect(). код
Code Block | ||||
---|---|---|---|---|
| ||||
session.connect(new Connection()); |
7. Получение от сервера события, подтверждающего успешное соединение.
session.onConnected() код
Code Block | ||||
---|---|---|---|---|
| ||||
@Override public void onConnected(final Connection connection) { runOnUiThread(new Runnable() { @Override public void run() { StreamOptions streamOptions = new StreamOptions(streamName mStartButton.setText(R.string.action_stop); streamOptions.setConstraints(new Constraints(mReceiveAudio.isChecked(), mReceiveVideo.isChecked())); mStartButton.setTag(R.string.action_stop); mStartButton.setEnabled(true); VideoConstraints videoConstraints = null mTestButton.setEnabled(false); mStatusView.setText(connection.getStatus());; if (mReceiveVideo.isChecked()) { /** * The options for the stream to publish are set. videoConstraints = new VideoConstraints(); * The stream name is passed when StreamOptions object is created. if (!mDefaultPlayResolution.isChecked() && mPlayWidth.getText().length() > 0 && mPlayHeight.getText().length() > 0) { * VideoConstraints object is used to set the source camera, FPS and resolution. * Stream constraints are set with method videoConstraints.setResolution(Integer.parseInt(mPlayWidth.getTextStreamOptions.setConstraints().toString()), */ StreamOptions streamOptions = new Integer.parseInt(mPlayHeight.getText().toString()))StreamOptions(streamName); Constraints constraints = getConstraints(); } streamOptions.setConstraints(constraints); String[] stripCodec = {(String) mStripStreamerCodec.getSpinner().getSelectedItem()}; if (!mDefaultPlayBitrate.isChecked() && mPlayBitrate.getText().length() > 0) { streamOptions.setStripCodecs(stripCodec); /** * Stream is created with method videoConstraints.setBitrate(Integer.parseInt(mPlayBitrate.getText().toString()));Session.createStream(). */ } publishStream = session.createStream(streamOptions); ... } }); } |
8. Создание потока и подготовка к публикации
session.createStream() код
Code Block | ||||
---|---|---|---|---|
| ||||
publishStream = session.createStream(streamOptions); if (!mDefaultPlayQualitymMuteAudio.isChecked()) && mPlayQuality.getText().length() > 0 { publishStream.muteAudio(); } if (mMuteVideo.isChecked()) { publishStream.muteVideo(); } ... ActivityCompat.requestPermissions(MediaDevicesActivity.this, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA}, videoConstraints.setQuality(Integer.parseInt(mPlayQuality.getText().toString()));PUBLISH_REQUEST_CODE); |
9. Публикация потока
Stream.publish() код
Code Block | ||||
---|---|---|---|---|
| ||||
case PUBLISH_REQUEST_CODE: { if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED || } grantResults[1] != PackageManager.PERMISSION_GRANTED) { }mStartButton.setEnabled(false); mTestButton.setEnabled(false); session.disconnect(); AudioConstraints audioConstraints = null; Log.i(TAG, "Permission has been denied by user"); } else { if (mReceiveAudio.isChecked()) { /** * Method Stream.publish() is called to publish stream. audioConstraints = new AudioConstraints(); */ publishStream.publish(); Log.i(TAG, "Permission has been } granted by user"); } streamOptions.setConstraints(new Constraints(audioConstraints, videoConstraints));break; } |
10. Получение от сервера события, подтверждающего успешную публикацию потока
StreamStatusEvent PUBLISHING код
При получении данного события создается превью-видеопоток при помощи Session.createStream() и вызывается Stream.play() для его воспроизведения.
Code Block | ||||
---|---|---|---|---|
| ||||
publishStream.on(new StreamStatusEvent() { @Override public void onStreamStatus(final Stream String[] stripCodec = {(String) mStripPlayerCodec.getSpinner().getSelectedItem()}; stream, final StreamStatus streamStatus) { runOnUiThread(new Runnable() { streamOptions.setStripCodecs(stripCodec); @Override public void /**run() { if (StreamStatus.PUBLISHING.equals(streamStatus)) { * Stream is created with method Session.createStream(). /** */ * The options for the stream to playStreamplay =are sessionset.createStream(streamOptions); /** The stream name is passed when StreamOptions object is created. * Callback function for stream status change is added to display*/ the status. StreamOptions streamOptions = */new StreamOptions(streamName); playStreamstreamOptions.onsetConstraints(new StreamStatusEvent() {Constraints(mReceiveAudio.isChecked(), mReceiveVideo.isChecked())); VideoConstraints videoConstraints = @Overridenull; public void onStreamStatus(final Stream stream, final StreamStatus streamStatusif (mReceiveVideo.isChecked()) { videoConstraints = runOnUiThread(new RunnableVideoConstraints() {; @Override... } public void run() { AudioConstraints audioConstraints = null; if (!StreamStatus.PLAYING.equals(streamStatusmReceiveAudio.isChecked()) { audioConstraints = new AudioConstraints(); Log.e(TAG, "Can not} play stream " + stream.getName() + " " + streamStatus); streamOptions.setConstraints(new Constraints(audioConstraints, videoConstraints)); String[] stripCodec = {(String) mStripPlayerCodec.getSpinner().getSelectedItem()}; streamOptions.setStripCodecs(stripCodec); mStatusView.setText(streamStatus.toString()); /** * Stream is created with }method Session.createStream(). });*/ playStream }= session.createStream(streamOptions); }); ... /** * Method Stream.play() is called to start playback of the stream. */ playStream.play(); if (mSendVideo.isChecked()) mSwitchCameraButton.setEnabled(true); mSwitchRendererButton.setEnabled(true); } else { Log.e(TAG, "Can not publish stream " + stream.getName() + " " + streamStatus); } mStatusView.setText(streamStatus.toString()); } }); } }); |
...