使用Wowza的RTSP服务器的谷歌玻璃直播视频

时间:2014-08-12 10:56:12

标签: google-glass live-streaming wowza

我正在尝试构建支持直播的Google Glass应用。我知道可以使用Livestream应用程序,但我不认为我们可以将它集成到我们的应用程序中,或者我错了吗?有没有办法在我们的应用程序中集成直播?

我遇到了这个https://github.com/andermaco/GlassStream开源项目,该项目使用Wowza的RTSP服务器执行相同的操作。根据我给出的用户名/密码的说明并更新了网址。但是在运行时运行应用程序时出现问题。我尝试调试但是没有成功。这是重复的日志

android.media.MediaCodec.dequeueOutputBuffer(Native Method)中的java.lang.IllegalStateException at net.majorkernelpanic.streaming.rtp.MediaCodecInputStream.read(MediaCodecInputStream.java:75) 在net.majorkernelpanic.streaming.rtp.AACLATMPacketizer.run(AACLATMPacketizer.java:88) 在java.lang.Thread.run(Thread.java:841)

部分用户已经使用并且成功,请分享我的源代码,或者如果我在设置服务器时遗漏了一些内容,请告诉我。即使有任何其他资源可供实施,也会很棒。

先谢谢。

1 个答案:

答案 0 :(得分:0)

这是我用过的代码,使用Wowza媒体服务器和libstreaming在Google Glass(XE22)上运行。

我有两个课程AppConfigMyActivity

的AppConfig:

package com.example.GlassApp;

/**
 * User: Colin Shewell
 * Date: 21/08/14
 * Time: 15:30
 */
public class AppConfig {
  public static final String STREAM_URL = "rtsp://193.61.148.73:1935/serg/android_test";
  //public static final String STREAM_URL = "rtsp://192.168.2.2:1935/serg/android_test";
  public static final String PUBLISHER_USERNAME = "";
  public static final String PUBLISHER_PASSWORD = "";
}

MyActivity:

    package com.example.GlassApp;

/**
 * User: Colin Shewell
 * Date: 21/08/14
 * Time: 15:30
 */
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;

    import net.majorkernelpanic.streaming.Session;
    import net.majorkernelpanic.streaming.SessionBuilder;
    import net.majorkernelpanic.streaming.audio.AudioQuality;
    import net.majorkernelpanic.streaming.gl.SurfaceView;
    import net.majorkernelpanic.streaming.rtsp.RtspClient;
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.DialogInterface;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.SurfaceHolder;
    import android.view.Window;
    import android.view.WindowManager;
    import net.majorkernelpanic.streaming.video.VideoQuality;

    public class MyActivity extends Activity implements RtspClient.Callback, Session.Callback, SurfaceHolder.Callback {
      // log tag
      public final static String TAG = MyActivity.class.getSimpleName();

      // surfaceview
      private static SurfaceView mSurfaceView;

      // Rtsp session
      private Session mSession;
      private static RtspClient mClient;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        // getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.activity_main);

        mSurfaceView = (SurfaceView) findViewById(R.id.surface);

        mSurfaceView.getHolder().addCallback(this);

        // Initialize RTSP client
        initRtspClient();
      }

      @Override
      protected void onResume() {
        super.onResume();

        toggleStreaming();
      }

      @Override
      protected void onPause(){
        super.onPause();

        toggleStreaming();
      }

      private void initRtspClient() {
        // Configures the SessionBuilder
        mSession = SessionBuilder.getInstance()
            .setContext(getApplicationContext())
            .setAudioEncoder(SessionBuilder.AUDIO_NONE)
            .setVideoEncoder(SessionBuilder.VIDEO_H264)
            .setVideoQuality(new VideoQuality(640, 480, 20, 500000)) //only need if you want to change the resolution from default
            .setSurfaceView(mSurfaceView).setPreviewOrientation(0)
            .setCallback(this).build();

        // Configures the RTSP client
        mClient = new RtspClient();
        mClient.setSession(mSession);
        mClient.setCallback(this);
        mSurfaceView.setAspectRatioMode(SurfaceView.ASPECT_RATIO_PREVIEW);
        String ip, port, path;

        // We parse the URI written in the Editext
        Pattern uri = Pattern.compile("rtsp://(.+):(\\d+)/(.+)");  
        Matcher m = uri.matcher(AppConfig.STREAM_URL);
        m.find();
        ip = m.group(1);
        port = m.group(2);
        path = m.group(3);

        mClient.setCredentials(AppConfig.PUBLISHER_USERNAME,
            AppConfig.PUBLISHER_PASSWORD);
        mClient.setServerAddress(ip, Integer.parseInt(port));
        mClient.setStreamPath("/" + path);
      }

      private void toggleStreaming() {
        if (!mClient.isStreaming()) {
          // Start camera preview
          mSession.startPreview();

          // Start video stream
          mClient.startStream();
        } else {
          // already streaming, stop streaming
          // stop camera preview
          mSession.stopPreview();

          // stop streaming
          mClient.stopStream();
        }
      }

      @Override
      public void onDestroy() {
        super.onDestroy();
        mClient.release();
        mSession.release();
        mSurfaceView.getHolder().removeCallback(this);
      }

      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
      }

      @Override
      public void onSessionError(int reason, int streamType, Exception e) {
        switch (reason) {
          case Session.ERROR_CAMERA_ALREADY_IN_USE:
            break;
          case Session.ERROR_CAMERA_HAS_NO_FLASH:
            break;
          case Session.ERROR_INVALID_SURFACE:
            break;
          case Session.ERROR_STORAGE_NOT_READY:
            break;
          case Session.ERROR_CONFIGURATION_NOT_SUPPORTED:
            break;
          case Session.ERROR_OTHER:
            break;
        }

        if (e != null) {
          alertError(e.getMessage());
          e.printStackTrace();
        }
      }

      private void alertError(final String msg) {
        final String error = (msg == null) ? "Unknown error: " : msg;
        AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
        builder.setMessage(error).setPositiveButton("Ok",
            new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int id) {
              }
            });
        AlertDialog dialog = builder.create();
        dialog.show();
      }

      @Override
      public void onRtspUpdate(int message, Exception exception) {
        switch (message) {
          case RtspClient.ERROR_CONNECTION_FAILED:
          case RtspClient.ERROR_WRONG_CREDENTIALS:
            alertError(exception.getMessage());
            exception.printStackTrace();
            break;
        }
      }

      @Override
      public void onPreviewStarted() {
      }

      @Override
      public void onSessionConfigured() {
      }

      @Override
      public void onSessionStarted() {
      }

      @Override
      public void onSessionStopped() {
      }

      @Override
      public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
      }

      @Override
      public void surfaceCreated(SurfaceHolder holder) {
      }

      @Override
      public void surfaceDestroyed(SurfaceHolder holder) {
      }

      // @Override
      public void onBitrateUpdate(long bitrate) {
      }
    }

编辑: 我可以确认以下视频质量设置有效:

.setVideoQuality(new VideoQuality(640, 480, 20, 500000))
.setVideoQuality(new VideoQuality(960, 720, 20, 500000))

我还想补充说,超过20的fps值似乎导致应用无法启动。