【问题标题】:Google glass live stream video using RTSP server of Wowza使用 Wowza 的 RTSP 服务器的谷歌玻璃直播视频
【发布时间】:2014-10-05 10:01:30
【问题描述】:

我正在尝试构建一个支持直播的 Google Glass 应用。我知道 Livestream 应用程序可以做到这一点,但我认为我们不能将它集成到我们的应用程序中,还是我错了?有没有办法将直播集成到我们的应用程序中?

我遇到了这个https://github.com/andermaco/GlassStream 开源项目,它使用Wowza 的RTSP 服务器做同样的事情。根据说明,我提供了用户名/密码并更新了 url。但是在运行应用程序时出现问题。我试图调试它但没有成功。这是我反复获取的日志

android.media.MediaCodec.dequeueOutputBuffer(本机方法)处的 java.lang.IllegalStateException 在 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)

一些用户已经使用并成功,请分享源代码或让我知道在设置服务器时是否遗漏了什么。即使有任何其他资源可以实现,也很棒。

提前致谢。

【问题讨论】:

  • 我确实在同一个 github 项目中发布了一个问题,所有者告诉它,它没有在最新更新 XE19.1 中测试。由于有很多变化,它没有工作
  • 如果您仍然对此感兴趣,我有一个使用 Libstreaming 和 Wowza 的工作应用程序。
  • 请分享我的源代码。这将非常有帮助。
  • 好的,我会添加它作为答案,只是我今天一直在玩这个分辨率,当我没有指定时只能以默认分辨率工作,或者如果我确实设置了分辨率,它似乎只能在640*480 工作,所以如果你碰巧让它在任何其他分辨率(更高或更低)下工作,你可以用你使用的参数在答案下方留下评论吗?

标签: google-glass live-streaming wowza


【解决方案1】:

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

我有两个班级 AppConfigMyActivity

应用配置:

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 = "";
}

我的活动:

    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 值似乎会导致应用无法启动。

【讨论】:

    猜你喜欢
    • 2014-11-16
    • 1970-01-01
    • 2013-12-20
    • 2021-01-23
    • 2015-02-05
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    相关资源
    最近更新 更多