java - 如何将自定义 android.media.MediaDataSource 与 android.media.MediaPlayer 一起使用?

标签 java android android-mediaplayer url-scheme

我知道 Android 的 MediaPlayer 是个很棒的东西。它允许我们播放本地文件和媒体流。而且它非常易于使用(仅作为示例):

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

可以通过使用不同的参数集调用重载的 setDataSource() 来设置不同类型的数据源。 这个函数有一个有趣的原型(prototype):

void setDataSource(MediaDataSource dataSource) 

看起来可以用您自己的实现完全覆盖 DataSource。它确实有效:

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;
    }
}

在主要代码中:

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

是的,这很好用。但是,如果我尝试使用音频/aacp 广播流(例如:“http://111.223.51.8:8005”——它是“COOLfahrenheit 93”广播),播放器不会播放。 Logcat 跟踪:

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)

不过,当没有使用自定义 MediaDataSource 时,URL 工作正常(音乐播放):

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

有人知道管理这个的正确方法吗? 只是不要建议我直接使用 URL - 我需要自定义 MediaDataSource 来访问流的原始数据。

最佳答案

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.

那么,让我们了解幕后发生的事情。

当您将 URL 作为数据源传递时,然后 this正在执行检查:


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

媒体播放器 uses MediaHTTPService 类,which is responsible用于提供来自 httphttpswidevine 协议(protocol)的数据。 MediaHTTPService 内部使用 MediaHTTPConnection ,这需要处理那种类型的流的所有繁重工作。不幸的是,这些 API 尚未公开,但您可以在 MediaHTTPConnection 中看到如何建立连接。来源(特别是 seekTo method )。因此,您提供给 MediaPlayer 的自定义数据源应该描述大致的逻辑,即 MediaHTTPConnection类实现。

关于java - 如何将自定义 android.media.MediaDataSource 与 android.media.MediaPlayer 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44424424/

相关文章:

java - 使用 MediaPlayer 时,显示 "E/ExtMediaPlayer-JNI: env->IsInstanceOf fails "错误。如何解决?

java - 如何使用java断言视频 Action ?

Android:月日年的日期格式

android - ListView优化: Typeface makes listview very laggy

java - 使用 javascript 和 PHP 开发原生 android 应用程序

Titanium 中的 Android 视频控制位置

android - 如果我在 mp4parser 中合并更多视频,音频和视频无法正确同步

java - 输入 "1"和 "0"以外的字符时如何显示错误消息?

java - 在 Java 8 中创建方法引用数组的简写方法?

java - 在多模块 Maven 和 Gradle 项目中检测 Java 源代码级别的明确方法?