如何使用自定义android.media.MediaDataSource和android.media.MediaPlayer? [英] How do I use custom android.media.MediaDataSource along with 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 customMediaDataSource
), but audio/aacp streams could be played back only via URL asDataSource
.
所以,让我们了解一下发生了什么。
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屋!