我正在尝试构建支持直播的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)
部分用户已经使用并且成功,请分享我的源代码,或者如果我在设置服务器时遗漏了一些内容,请告诉我。即使有任何其他资源可供实施,也会很棒。
先谢谢。
答案 0 :(得分:0)
这是我用过的代码,使用Wowza媒体服务器和libstreaming在Google Glass(XE22)上运行。
我有两个课程AppConfig
和MyActivity
。
的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值似乎导致应用无法启动。