How do I use custom android.media.MediaDataSource along with android.media.MediaPlayer?

不羁的心 提交于 2019-12-04 03:16:44

问题


I know Android's MediaPlayer is a great thing. It allows us to play local files as well as media streams. And it is quite easy to use (just for example):

MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource("http://streaming.shoutcast.com/80sPlanet"); // this steam broadcasts audio/mpeg
mediaPlayer.prepareAsync();
mediaPlayer.start();

It is possible to set different types of DataSource by calling the overloaded setDataSource() with different set of parameters. And there is an interesting prototype of this function:

void setDataSource(MediaDataSource dataSource) 

Looks like it is possible to completely override the DataSource with your own implementation. And it works indeed:

import android.media.MediaDataSource;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.HttpURLConnection;

public class UrlMediaDataSource extends MediaDataSource {
    URL url;
    HttpURLConnection connection;
    BufferedInputStream stream;

    public UrlMediaDataSource(URL url) throws IOException {
        this.url = url;
        connection = (HttpURLConnection) url.openConnection();
    }

    @Override
    public long getSize() {
        return 0;
    }

    @Override
    public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
        if (stream == null)
            stream = new BufferedInputStream(connection.getInputStream());
        return stream.read(buffer, offset, size);
    }

    @Override
    public void close() throws IOException {
        stream.close();
        stream = null;
        connection.disconnect();
        connection = null;
    }
}

and in the main code:

UrlMediaDataSource dataSource = new UrlMediaDataSource(new URL("http://streaming.shoutcast.com/80sPlanet"));
mediaPlayer.setDataSource(dataSource);

Yes, this works fine. But if I try audio/aacp broadcasting stream (for example: "http://111.223.51.8:8005" - it is "COOLfahrenheit 93" radio), the player does not play. Logcat trace:

06-07 23:26:01.680 1352-1147/? E/GenericSource: Failed to init from data source!
06-07 23:26:01.681 1352-1093/? D/NuPlayerDriver: notifyListener_l(0xf3e051e0), (100, 1, -2147483648)
06-07 23:26:01.735 1352-2013/? D/NuPlayerDriver: reset(0xf3e051e0)
06-07 23:26:01.735 1352-2013/? D/NuPlayerDriver: notifyListener_l(0xf3e051e0), (8, 0, 0)
06-07 23:26:01.736 1352-1093/? D/NuPlayerDriver: notifyResetComplete(0xf3e051e0)

Though, the URL works fine (the music plays) when no custom MediaDataSource is used:

mediaPlayer.setDataSource("http://111.223.51.8:8005");

Does anybody know the right way to manage this? Just don't propose me to use the URL directly - I need a custom MediaDataSource to get access to the raw data of the stream.


回答1:


The main point is that the MediaPlayer does playback audio/mpeg (both ways - through URL and through custom MediaDataSource), but audio/aacp streams could be played back only via URL as DataSource.

So, let's understand what's happening under the hoods.

When you are passing an URL as a data source, then this check is being performed:


    if ("file".equals(scheme)) {
        path = uri.getPath();
    } else if (scheme != null) {
        // handle non-file sources
        nativeSetDataSource(
            MediaHTTPService.createHttpServiceBinderIfNecessary(path),
            path,
            keys,
            values);
        return;
    }

MediaPlayer uses MediaHTTPService class, which is responsible for providing data from http, https and widevine protocols. MediaHTTPService internally uses MediaHTTPConnection, which takes all the heavy lifting for working with that type of streams. Unfortunately, these APIs are not public (yet), but you can see how connection establishing is done in MediaHTTPConnection sources (particularly seekTo method). So, the custom data source that you provide to MediaPlayer should depict approximately the logics, that MediaHTTPConnection class implements.



来源:https://stackoverflow.com/questions/44424424/how-do-i-use-custom-android-media-mediadatasource-along-with-android-media-media

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!