Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Пример Android-приложения для управления медиа-устройствами

Данный пример может использоваться как стример для публикации WebRTC-видеопотока с Web Call Server и позволяет выбрать медиа-устройства и параметры для публикуемого видео

...

Пример переключения объекта для вывода изображения с камеры

Работа с кодом примера

Для разбора кода возьмем класс MediaDevicesActivity.java примера media-devices, который доступен для скачивания в соответствующей сборке 1.0.1.46.

...

Code Block
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
session.connect(new Connection());

7. Получение от сервера события, подтверждающего успешное соединение.

session.onConnected() код

Code Block
languagejs
themeRDark
@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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
session.connect(new Connection());


7. Получение от сервера события, подтверждающего успешное соединение.

session.onConnected() код

Code Block
languagejs
themeRDark
@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
languagejs
themeRDark
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
languagejs
themeRDark
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
languagejs
themeRDark
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());
           }
       });
    }
});

...