【问题标题】:MediaExtractor throws IllegalArgumentException when used with wav file与 wav 文件一起使用时,MediaExtractor 抛出 IllegalArgumentException
【发布时间】:2016-06-24 08:41:24
【问题描述】:

我正在像这样使用 Android MediaExtractor:

MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource("path/to/my/wav/file.wav");
extractor.selectTrack(0);

ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferIndex);
int sampleSize =  extractor.readSampleData(inputBuffer, 0);

inputBuffer 由配置为 AAC 编码器的 MediaCodec 提供。目标是将wave文件转换为aac。当然,上面的代码是缩写的,但我将错误跟踪到最后一行。

它也仅在使用带有 wav 文件的 MediaExtractor 时发生。例如,我改用 .m4a,一切正常。

MediaExtractor 的文档说:

MediaExtractor 有助于从数据源中提取解复用的(通常是编码的)媒体数据。

“通常编码”不排除未编码的 PCM 音频....对吗?任何人之前尝试过或知道另一种稳定(!)的方式:

  • 从 wav 中提取音频样本(不包括 44 字节或 46 字节标头)?
  • 在 Android 上将 wav 文件转换为 aac?

更新

这里是日志:

W/System.err: java.lang.IllegalArgumentException
W/System.err:     at android.media.MediaExtractor.readSampleData(Native Method)
W/System.err:     at com.myproject.android.audiosandbox.convert.MediaEncoder2.encodeLollipopStyle(MediaEncoder2.java:247)
W/System.err:     at com.myproject.android.audiosandbox.convert.MediaEncoder2.encodeSong(MediaEncoder2.java:119)
W/System.err:     at com.myproject.android.audiosandbox.convert.MediaEncoder2.encode(MediaEncoder2.java:70)
W/System.err:     at com.myproject.android.audiosandbox.fragments.AudioConvertFragment$1.onClick(AudioConvertFragment.java:40)
W/System.err:     at android.view.View.performClick(View.java:4763)
W/System.err:     at android.view.View$PerformClick.run(View.java:19821)
W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err:     at android.os.Looper.loop(Looper.java:135)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5272)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)

我使用的是 API 16,所以 MediaMuxer 不是一个选项(在 API 18 中添加)。

【问题讨论】:

  • 您能否分享确切的logcat 日志? IllegalArgumentException 可能来自多种情况。如果您有logcat,则更容易隔离并提出解决方案。在相关说明中,您是否确认该文件存在于此处path/to/my/wav/file.wav?。另外,能否请您指定您正在使用的 Android 版本是什么?
  • 从您的日志com.android.audiosandbox.convert.MediaEncoder2.encode 看来,正在使用自定义编码器。为了隔离这个问题,您能否将这个encodermedia_codecs.xml 中删除并尝试使用默认 软件编码器,即MediaCodec,如本例所示:androidxref.com/4.1.2/xref/frameworks/av/cmds/stagefright/…
  • 嗯,“自定义编码器”是我正在研究的类。我现在可以使用它,但不能使用 MediaExtractor。我将发布一个要点作为答案。如果您对使用带有 wav 文件的 MediaExtractor 有更多的了解,我很乐意听到。谢谢!
  • 您报告的错误的唯一原因是读取内容所需的缓冲区大小不足。 MediaExtractor 的原生实现由NuMediaExtractor 实现。在日志中引用的方法中,唯一的错误退出可能是由于-ENOMEM,如下所示:androidxref.com/4.1.1/xref/frameworks/av/media/libstagefright/…。您能否用大缓冲区重试MediaExtractor 并检查同样的工作是否正常?如果可行,我会将其发布为答案
  • 我已经在另一篇文章中读到缓冲区大小可能是此异常的原因。但我对缓冲区大小没有影响,因为我需要使用 MediaCodec 提供的输入和输出缓冲区。

标签: android audio wav android-mediacodec mediaextractor


【解决方案1】:

我无法弄清楚“如果”或“为什么不”,MediaExtractor 似乎无法从简单的 wav 文件中读取数据,因此我选择了不同的方法。由于 WAV 文件真的不需要解码,我现在使用一个简单的 FileInputStream 并跳过 44 字节的标头。

我在此要点中发布了一个工作示例: https://gist.github.com/muetzenflo/3e83975aba6abe63413abd98bb33c401

经过近一周的研究,尝试和错误,这段代码似乎很少见。我记录了几乎每一行代码,希望能帮助其他在 Android 上遇到 MediaCodec 类问题的人。

【讨论】:

    【解决方案2】:

    在调用decoder.configure(format, ...)之前,我建议先调用format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 65536);,它会使解码器使用更大的缓冲区。 这应该可以解决问题。如果不是,请尝试增加缓冲区大小。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-22
      • 2019-02-20
      • 2017-08-18
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 2014-09-18
      • 2014-11-05
      相关资源
      最近更新 更多