2015年3月31日 星期二

[Android] MediaPlayer RTSP streaming

For MediaPlayer, if we want to play internet streaming,
we only need to set the internet address in setDataSource().
But, we if it needs account and password?
There are two possible types:
1. Basic Authentication

Context context = getApplicationContext();  
sUrl = "rtsp://xxxx";  
sAccount = "xx";  
sPassword = "xx";  
Uri source = Uri.parse(sUrl);  
Map<String, String> headers = getRtspHeaders();  
mediaPlayer.setDataSource(context, source, headers);

Map<String, String> getRtspHeaders() {  
  Map<String, String> headers = new HashMap<String, String>();  
   String basicAuthValue = getBasicAuthValue(sAccount, sPassword);  
   headers.put("Authorization", basicAuthValue);  
   return headers;  
}  
private String getBasicAuthValue(String usr, String pwd) {  
   String credentials = usr + ":" + pwd;  
   int flags = Base64.URL_SAFE | Base64.NO_WRAP;  
   byte[] bytes = credentials.getBytes();  
   return "Basic " + Base64.encodeToString(bytes, flags);       
}    

The above codes show us how to deal with basic authentication.
There has another simpler way - add the account and password in the path.
e.g.  sUrl = "rtsp://admin:pwd@xxxx";


2. Digest Authentication
Originally, I thought that we can use sUrl = "rtsp://admin:pwd@xxxx" for digest authentication as well.
However, I always got the error message "error 100, Media server died".
When I googled it, the answer was that "MedisPlayer does not support rtsp digest authentication" or something like that.
One day, I thought that I might use Wireshark to check the packets for what happened.
As the result shown above, it seems that the format is correct in RTSP DESCRIBE packet.
It means that it does support digest authentication type.
So...why did we get the reply "401 unauthorized"?
(The above graph may be captured not by using MediaPlayer. But the analysis discussed here is for MediaPlayer indeed)
Check the DESCRIBE packet again... username is correct, uri is correct, nonce is correct...
Is response the suspect?
response= md5(md5(username:realm:password):nonce:md5(uri))
I calculated it manually. It did have something wrong.
The response in DESCEIBE packet is not as what expected.
To find out the reason, I need to investigate the Android kernel codes.
The related codes is in ARTSPConnection.cpp.
Finally, I found that when it calculated response, the realm it used is not from RTSP server Reply packet.
Instead, it was hard coded as "Streaming Server".
No wonder the response was not correct.
Although the reason is clear, I can do nothing since I cannot rebuild my Android kernel.
It seems that I cannot use MediaPlayer for RTSP Digest Authentication
Need to find another way...

沒有留言:

張貼留言