如何将自定义 android.media.MediaDataSource 与 android.media.MediaPlayer 一起使用?
How do I use custom android.media.MediaDataSource along with android.media.MediaPlayer?
我知道 Android 的 MediaPlayer
很棒。它允许我们播放本地文件和媒体流。而且它非常容易使用(仅作为示例):
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource("http://streaming.shoutcast.com/80sPlanet"); // this steam broadcasts audio/mpeg
mediaPlayer.prepareAsync();
mediaPlayer.start();
可以通过使用不同的参数集调用重载 setDataSource()
来设置不同类型的数据源。
这个函数有一个有趣的原型:
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);
是的,这很好用。但是如果我尝试 audio/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)
不过,URL 在没有使用自定义 MediaDataSource
时工作正常(音乐播放):
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;
}
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 实施。
我知道 Android 的 MediaPlayer
很棒。它允许我们播放本地文件和媒体流。而且它非常容易使用(仅作为示例):
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource("http://streaming.shoutcast.com/80sPlanet"); // this steam broadcasts audio/mpeg
mediaPlayer.prepareAsync();
mediaPlayer.start();
可以通过使用不同的参数集调用重载 setDataSource()
来设置不同类型的数据源。
这个函数有一个有趣的原型:
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);
是的,这很好用。但是如果我尝试 audio/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)
不过,URL 在没有使用自定义 MediaDataSource
时工作正常(音乐播放):
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 customMediaDataSource
), but audio/aacp streams could be played back only via URL asDataSource
.
那么,让我们了解幕后发生的事情。
当您将 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;
}
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 实施。