How to avoid 15 second delay/caching in Android Me

2019-03-27 13:01发布

问题:

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() {

    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
});
player.prepareAsync();

UPDATE: 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.

Input welcome!

Thanks! Daniel

回答1:

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


回答2:

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();


回答3:

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.



回答4:

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...