diaPlayer与ParcelFileDescriptor和c

diaPlayer与ParcelFileDescriptor和c

本文介绍了任何人有任何的MediaPlayer与ParcelFileDescriptor和createPipe()工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相关的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()工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 22:58