如何使用自定义android.media.MediaDataSource和android.media.MediaPlayer? [英] How do I use custom android.media.MediaDataSource along with android.media.MediaPlayer?

查看:2320
本文介绍了如何使用自定义android.media.MediaDataSource和android.media.MediaPlayer?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道Android的 MediaPlayer 是件好事。它允许我们播放本地文件和媒体流。并且它非常容易使用(例如):

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

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

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) 

看起来可以使用您自己的实现完全覆盖 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;
    }
}

以及主码:

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

是的,这样可行。但是,如果我尝试音频/ aacp广播流(例如: http://111.223.51.8:8005 - 它是COOLfahrenheit 93收音机),播放器不播放。 Logcat追踪:

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)

尽管如此,当没有时,URL工作正常(音乐播放)使用自定义 MediaDataSource

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

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

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

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.

推荐答案


重点是 MediaPlayer 播放 audio / mpeg (两种方式 - 通过URL和自定义 MediaDataSource ),但 audio / aacp 流只能通过URL播放为 DataSource

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.

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

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 使用 MediaHTTPService class,负责提供来自 http https 和<$的数据c $ c> widevine 协议。 MediaHTTPService 在内部使用 MediaHTTPConnection ,它可以解决所有繁重的工作问题。不幸的是,这些API尚未公开(但),但你可以看到如何在 MediaHTTPConnection 来源(特别是 seekTo 方法)。因此,您提供给 MediaPlayer 的自定义数据源应该描述大致的逻辑, MediaHTTPConnection 类实现。

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.

这篇关于如何使用自定义android.media.MediaDataSource和android.media.MediaPlayer?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆