我想在安卓设备上观看RTSP视频流。但如果服务器为视频流设置了密码,我的安卓设备就无法播放。如果没有密码,则可以正常播放。以下是我的代码。
public class VideoFragment extends Fragment implements View.OnClickListener, SurfaceHolder.Callback, MediaPlayer.OnPreparedListener {
VideoView m_videoView;
SurfaceView m_surfaceView;
SurfaceHolder m_surfaceHolder;
MediaPlayer m_mediaPlayer;
SharedPreferences m_sharedPref;
Boolean m_videoStarted;
public VideoFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_video, container, false);
m_sharedPref = this.getActivity().getSharedPreferences(MainActivity.class.getSimpleName(), Context.MODE_PRIVATE);
m_surfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
m_surfaceHolder = m_surfaceView.getHolder();
m_surfaceHolder.addCallback(this);
m_surfaceHolder.setFixedSize(320, 240);
m_videoStarted = false;
ToggleButton togglePlay = (ToggleButton) view.findViewById(R.id.toggleVideo);
togglePlay.setOnClickListener(this);
return view;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.toggleVideo:
if(m_videoStarted == false) {
play();
m_videoStarted = true;
}
else {
m_mediaPlayer.reset();
}
break;
default:
Log.i(AppConfig.TAG, "DEFAULT");
break;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.e(AppConfig.TAG, "surfaceCreated");
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
m_mediaPlayer.release();
}
@Override
public void onPrepared(MediaPlayer mp) {
Log.e(AppConfig.TAG, "Media Player Prepared");
m_mediaPlayer.start();
}
private void play() {
if(m_mediaPlayer == null) {
m_mediaPlayer = new MediaPlayer();
}
setErrorListener();
m_mediaPlayer.setDisplay(m_surfaceHolder);
m_mediaPlayer.setOnPreparedListener(this);
try {
Map<String, String> headers = createHeaders();
String videoUri = "rtsp://192.168.1.100:554/video/3gpp";
Log.i(AppConfig.TAG, "Video URI: " + videoUri);
m_mediaPlayer.setDataSource(getActivity(), Uri.parse(videoUri), headers);
m_mediaPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setErrorListener() {
m_mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
if(extra == MediaPlayer.MEDIA_ERROR_IO) {
Log.e(AppConfig.TAG, "MEDIA ERROR");
}
else if(extra == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
Log.e(AppConfig.TAG, "SERVER DIED ERROR");
}
else if(extra == MediaPlayer.MEDIA_ERROR_UNSUPPORTED) {
Log.e(AppConfig.TAG, "MEDIA UNSUPPORTED");
}
else if(extra == MediaPlayer.MEDIA_ERROR_UNKNOWN) {
Log.e(AppConfig.TAG, "MEDIA ERROR UNKOWN");
}
else if(extra == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
Log.e(AppConfig.TAG, "NOT VALID PROGRESSIVE PLAYBACK");
}
else {
Log.e(AppConfig.TAG, String.valueOf(what));
Log.e(AppConfig.TAG, String.valueOf(extra));
Log.e(AppConfig.TAG, "ERROR UNKNOWN!");
}
return false;
}
});
}
private Map<String, String> createHeaders() {
String videoUri = "rtsp://192.168.1.100:554/video/3gpp";
Map<String, String> headers = new HashMap<String, String>();
String camUser = "guest";//m_sharedPref.getString(AppConfig.CAM_USER,"");
String camPassword = "tseug";//m_sharedPref.getString(AppConfig.CAM_PASSWORD,"");
String describe = "DESCRIBE " + videoUri + " RTSP/1.0";
String accept = "application/sdp";
String basicAuthValue = "";
if (camUser != "") {
String credentials = camUser + ":" + camPassword;
byte[] bytes = credentials.getBytes();
int flags = Base64.URL_SAFE|Base64.NO_WRAP;
basicAuthValue = "Basic " + Base64.encodeToString(bytes, flags);
headers.put("Authorization", basicAuthValue);
}
headers.put("Request", describe);
headers.put("Accept", accept);
Log.i(AppConfig.TAG, "Describe: " + describe);
Log.i(AppConfig.TAG, "Authorization: " + basicAuthValue);
Log.i(AppConfig.TAG, "Accept: " + accept);
return headers;
}
我使用的IP摄像头是D-link DCS 942L。但每次连接时,尽管我的用户名和密码都正确,仍然会收到401错误响应。下面是我获得的日志:
05-25 21:45:31.640 1917-19687/? W/ARTSPConnection﹕ RTSP Response: 401
05-25 21:45:31.640 1917-19687/? I/MyHandler﹕ DESCRIBE completed with result 0 (Success)
05-25 21:45:31.640 1917-19687/? E/MyHandler﹕ Server responses [401] ERROR for the DESCRIBE request
05-25 21:45:31.645 1917-19687/? W/ARTSPConnection﹕ onReceiveResponse >>> State is not CONNECTED !!!
05-25 21:45:31.665 1917-19685/? V/NuPlayer﹕ scanning sources haveAudio=0, haveVideo=0
05-25 21:45:31.665 1917-19685/? V/MediaPlayerService﹕ [152] notify (0x41c61ca0, 100, 1, -2147483648)
05-25 21:45:31.665 19534-19547/com.cameraalert.app V/MediaPlayer﹕ message received msg=100, ext1=1, ext2=-2147483648
05-25 21:45:31.665 19534-19547/com.cameraalert.app E/MediaPlayer﹕ error (1, -2147483648)
05-25 21:45:31.665 19534-19547/com.cameraalert.app V/MediaPlayer﹕ callback application
05-25 21:45:31.665 19534-19547/com.cameraalert.app V/MediaPlayer﹕ back from callback
05-25 21:45:31.665 19534-19534/com.cameraalert.app E/MediaPlayer﹕ Error (1,-2147483648)
05-25 21:45:31.665 19534-19534/com.cameraalert.app E/CameraAlert﹕ 1
05-25 21:45:31.665 19534-19534/com.cameraalert.app E/CameraAlert﹕ -2147483648
05-25 21:45:31.665 19534-19534/com.cameraalert.app E/CameraAlert﹕ ERROR UNKNOWN!
我不确定我的请求头是否正确。这里有一篇文章http://www.tuicool.com/articles/R7ZF7bF,讲述如何使用与我相同的摄像头进行带身份验证的RTSP播放。
非常感谢您的任何帮助或解释。
"rtsp://guest:tseug@192.168.1.100:554/video/3gpp"
吗? - Alex Cohn