问题描述
相关的my在最近的问题 MediaRecorder
和 createPipe()
和的讨论 createPipe()
技术,this其他SO质疑,我现在试图让的MediaPlayer
通过由的ContentProvider
提供的内容合作 ParcelFileDescriptor
和 createPipe()
。
Related to my recent question on MediaRecorder
and createPipe()
, and a discussion of the createPipe()
technique in this other SO question, I am now trying to get MediaPlayer
to work with content served by a ContentProvider
via ParcelFileDescriptor
and createPipe()
.
此示例项目有我的工作至今。它是基于断早期样品,播放作为原始资源存储在OGG夹。因此,我知道,我的剪辑是好的。
This sample project has my work to date. It is based off of an earlier sample that plays an OGG clip stored as a raw resource. Hence, I know that my clip is fine.
我已经改变了我的的MediaPlayer
设置为:
I have changed my MediaPlayer
setup to:
private void loadClip() {
try {
mp=new MediaPlayer();
mp.setDataSource(this,
PipeProvider.CONTENT_URI.buildUpon()
.appendPath("clip.ogg")
.build());
mp.setOnCompletionListener(this);
mp.prepare();
}
catch (Exception e) {
goBlooey(e);
}
}
通过登录 PipeProvider
,我看到我的乌里
正在正确构造。
Through logging in PipeProvider
, I see that my Uri
is being properly constructed.
PipeProvider
是同一个中的,该工程提供的PDF文件到Adobe Reader,这限制了如何搞砸了我的code即可。 : - )
PipeProvider
is the same one as in this sample project, which works for serving PDFs to Adobe Reader, which limits how screwed up my code can be. :-)
具体而言,中openFile()
创建了一个从管 ParcelFileDescriptor
:
Specifically, openFile()
creates a pipe from ParcelFileDescriptor
:
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
ParcelFileDescriptor[] pipe=null;
try {
pipe=ParcelFileDescriptor.createPipe();
AssetManager assets=getContext().getResources().getAssets();
new TransferTask(assets.open(uri.getLastPathSegment()),
new AutoCloseOutputStream(pipe[1])).start();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception opening pipe", e);
throw new FileNotFoundException("Could not open pipe for: "
+ uri.toString());
}
return(pipe[0]);
}
,其中后台线程做了典型的流来流复制:
where the background thread does a typical stream-to-stream copy:
static class TransferTask extends Thread {
InputStream in;
OutputStream out;
TransferTask(InputStream in, OutputStream out) {
this.in=in;
this.out=out;
}
@Override
public void run() {
byte[] buf=new byte[1024];
int len;
try {
while ((len=in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(),
"Exception transferring file", e);
}
}
}
不过,的MediaPlayer
扼流圈:
10-16 13:33:13.203: E/MediaPlayer(3060): Unable to to create media player
10-16 13:33:13.203: D/MediaPlayer(3060): Couldn't open file on client side, trying server side
10-16 13:33:13.207: E/TransferTask(3060): Exception transferring file
10-16 13:33:13.207: E/TransferTask(3060): java.io.IOException: write failed: EPIPE (Broken pipe)
10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.IoBridge.write(IoBridge.java:462)
10-16 13:33:13.207: E/TransferTask(3060): at java.io.FileOutputStream.write(FileOutputStream.java:187)
10-16 13:33:13.207: E/TransferTask(3060): at com.commonsware.android.audiolstream.PipeProvider$TransferTask.run(PipeProvider.java:120)
10-16 13:33:13.207: E/TransferTask(3060): Caused by: libcore.io.ErrnoException: write failed: EPIPE (Broken pipe)
10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.Posix.writeBytes(Native Method)
10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.Posix.write(Posix.java:178)
10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191)
10-16 13:33:13.207: E/TransferTask(3060): at libcore.io.IoBridge.write(IoBridge.java:457)
10-16 13:33:13.207: E/TransferTask(3060): ... 2 more
10-16 13:33:13.211: E/MediaPlayer(3060): Unable to to create media player
10-16 13:33:13.218: E/TransferTask(3060): Exception transferring file
10-16 13:33:13.218: E/TransferTask(3060): java.io.IOException: write failed: EPIPE (Broken pipe)
10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.IoBridge.write(IoBridge.java:462)
10-16 13:33:13.218: E/TransferTask(3060): at java.io.FileOutputStream.write(FileOutputStream.java:187)
10-16 13:33:13.218: E/TransferTask(3060): at com.commonsware.android.audiolstream.PipeProvider$TransferTask.run(PipeProvider.java:120)
10-16 13:33:13.218: E/TransferTask(3060): Caused by: libcore.io.ErrnoException: write failed: EPIPE (Broken pipe)
10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.Posix.writeBytes(Native Method)
10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.Posix.write(Posix.java:178)
10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.BlockGuardOs.write(BlockGuardOs.java:191)
10-16 13:33:13.218: E/TransferTask(3060): at libcore.io.IoBridge.write(IoBridge.java:457)
10-16 13:33:13.218: E/TransferTask(3060): ... 2 more
有没有人见过工作$ C $下使用 createPipe()
服务媒体的MediaPlayer
?
在此先感谢!
推荐答案
我不知道这个都不能正常工作。当我运行此code我看到这样的痕迹:
I'm not sure this can ever work. When I run this code I see this trace:
I/AudioSystem(30916): getting audio flinger
I/AudioSystem(30916): returning new audio session id
D/IAudioFlinger(30916): newAudioSessionId In
D/AudioFlinger(28138): nextUniqueId, current 178
D/IAudioFlinger(30916): newAudioSessionId Out, id = 178
D/MediaPlayer(30916): setDataSource(Context context, content://com.commonsware.android.audiolstream/clip.ogg, Map<String, String> headers) in
D/MediaPlayer(30916): setDataSource(FileDescriptor fd) in
E/MediaPlayerService(28138): offset error
这是偏移误差来自于MediaPlayerService.cpp以下线AOSP,它确实在管道的读取端的fstat():
That "offset error" comes from the following lines in MediaPlayerService.cpp in AOSP, where it does a fstat() on the read side of the pipe:
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
{
struct stat sb;
int ret = fstat(fd, &sb);
....
if (offset >= sb.st_size) {
LOGE("offset error");
::close(fd);
return UNKNOWN_ERROR;
}
和sb.st_size报告为-1(通过getStatSize()的ParcelFileDescriptor在Java级别)。错误处理程序关闭描述符,因此断管误差不久之后。
And sb.st_size is reported as -1 (via getStatSize() on the ParcelFileDescriptor at the Java level). The error handler closes the descriptor, hence the broken pipe error shortly afterwards.
在我的经验中的MediaPlayer有很多细碎这样。我从来没有见过任何东西在本地文件HTTP流的工作,但直接,(非常buggily)。我结束了移植的FFmpeg来解决其众多缺陷。
In my experience MediaPlayer has many broken bits like this. I've never seen it work for anything but directly on local files, and (very buggily) for HTTP streaming. I ended up porting FFmpeg to work around its numerous failings.
这篇关于任何人有任何的MediaPlayer与ParcelFileDescriptor和createPipe()工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!