How to avoid 15 second delay/caching in Android Media Player when playing stream
I am implementing a media player that plays a stream from a remote machine. Via my app I can control the remote machine (e.g. seek to second). Works like charm, but: The Android Media Player buffers some insane 10-15 seconds(!!), which means each click ('seek') takes 10-15 seconds to take effect even though it is less than a second until the new data arrives.
My Question: Is there any way to control (limit) that caching? Or am I simply doing something wrong? Am I the only one having this issue?
My code is very simple:
player = new MediaPlayer()
player.setDataSource(url);
player.setOnPreparedListener(new OnPreparedListener() {
开发者_C百科 public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
player.prepareAsync();
I am using a local self built mini HTTP server to connect my byte stream to Androids media player. It seems like Android DRM is delaying / caching in this case. Still not quite clear why (and why not if I connect to my IIS that hosts a file). Also no idea how to workaround this.
Ok, meanwhile I got closer to the solution. Turned out the source of my problem is Android DRM! (No, I am not playing a protected file. Its standard mp3).
DRM seems to have been introduced in Android 3.1 (I was testing on a Galaxy Tab 10.1). It works fine on the Emulator (maybe DRM is not implemented there?)
Any idea how I can disable or accelerate this? There seems to be a 10 seconds timer somewhere deep in the Android DRM impl that waits for - whatever, no idea. My error log:
10-06 17:38:19.020: ERROR/MediaExtractor(226): **********MediaExtractor::Create
10-06 17:38:19.020: ERROR/IDrmManagerService(Native)(226): add uniqueid
10-06 17:38:19.020: ERROR/IDrmManagerService(Native)(225): Entering BnDrmManagerService::onTransact with code 1
10-06 17:38:19.020: ERROR/IDrmManagerService(Native)(225): BnDrmManagerService::onTransact :ADD_UNIQUEID
10-06 17:38:19.020: ERROR/IDrmManagerService(Native)(225): Entering BnDrmManagerService::onTransact with code 3
10-06 17:38:19.020: ERROR/IDrmManagerService(Native)(225): BnDrmManagerService::onTransact :ADD_CLIENT
10-06 17:38:19.020: ERROR/IDrmManagerService(Native)(226): Entering BpDrmManagerService::openDecryptSession
10-06 17:38:19.020: ERROR/IDrmManagerService(Native)(225): Entering BnDrmManagerService::onTransact with code 27
10-06 17:38:19.020: ERROR/IDrmManagerService(Native)(225): BnDrmManagerService::onTransact :OPEN_DECRYPT_SESSION_FROM_URI
10-06 17:38:19.020: ERROR/DrmManagerService(Native)(225): Entering DrmManagerService::openDecryptSession with uri
10 seconds wait
10-06 17:38:29.040: ERROR/DrmManager(Native)(225): DrmManager::openDecryptSession: no capable plug-in found
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(225): NULL decryptHandle is returned
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(226): no decryptHandle is generated in service side
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(226): remove uniqueid
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(225): Entering BnDrmManagerService::onTransact with code 2
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(225): BnDrmManagerService::onTransact :REMOVE_UNIQUEID
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(225): Entering BnDrmManagerService::onTransact with code 4
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(225): BnDrmManagerService::onTransact :REMOVE_CLIENT
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(226): setDrmServiceListener
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(225): Entering BnDrmManagerService::onTransact with code 5
10-06 17:38:29.040: ERROR/IDrmManagerService(Native)(225): BnDrmManagerService::onTransact :SET_DRM_SERVICE_LISTENER
10-06 17:38:29.040: ERROR/DrmManagerService(Native)(225): Entering setDrmServiceListener
One thing I realized in the newer Android versions is that it seems to have issues with VBR MP3 files. It plays them, but buffers way too much data before it starts. (3+ MB, the majority of my test files).
A (bad hack) workaround is to remove the XING
header from the MP3 files (this is where the VBR information is stored). This seems to make the player fall back to a simpler algorithm and start playback successfully for all my files after buffering only 100kb...
Try this. this will definatly help to you ::
private class TouchandshowTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... arg0) {
try {
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource("URL");
player.prepare();
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
protected void onPostExecute(final Void unused) {
}
}
OnCreate()
new TouchandshowTask().execute();
The problem might be not only at Android Media Player. Server that is streaming video should support need format.
If it's mp4's you need to install h264-pseudo-streaming module (same for HLS) If it's MSS (microsoft smooth streaming) - there are special modules for IIS.
Also, after user 'makes seek' that means Native Player will send range request, that should be supported by server. Nginx supports them by default, ISS & Apache have some issues with this. Though easy configurable.
精彩评论