当使用wav文件时,MediaExtractor会抛出IllegalArgumentException异常。

5
我正在使用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);

输入缓冲区由配置为AAC编码器的MediaCodec提供。目标是将波形文件转换为AAC格式。当然,上面的代码是缩写的,但我把错误追踪到了最后一行。它也仅在使用MediaExtractor处理wav文件时发生。例如,我使用.m4a代替wav文件,一切都正常。MediaExtractor的文档说:“MediaExtractor便于从数据源中提取解复用的媒体数据,通常是已编码的。”“通常已编码”不排除未编码的PCM音频,对吧?有人尝试过这个方法或知道另一个稳定的方法来:从wav文件中提取音频样本(不包括44字节或46字节的头)?在Android上将wav文件转换为AAC吗?更新:下面是logcat:
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版本是哪个? - Ganesh
从您的日志com.android.audiosandbox.convert.MediaEncoder2.encode中可以看出,正在使用自定义编码器。为了隔离这个问题,请从media_codecs.xml中删除此encoder并尝试使用__default__软件编码器,即MediaCodec,如此示例所示:http://androidxref.com/4.1.2/xref/frameworks/av/cmds/stagefright/SimplePlayer.cpp#316 - Ganesh
“自定义编码器”是我正在开发的类。现在我已经让它工作了,但是还没有与MediaExtractor一起使用。我会将代码片段发布为答案。如果您对使用MediaExtractor处理wav文件有更多见解,我很乐意听取。谢谢! - muetzenflo
1
你所报告的错误唯一可能是由于读取内容所需缓冲区的大小不足。MediaExtractor的本地实现是由NuMediaExtractor实现的。在记录中引用的方法中,唯一的错误退出可能是由于-ENOMEM,如此处所示:http://androidxref.com/4.1.1/xref/frameworks/av/media/libstagefright/NuMediaExtractor.cpp#402。你能否使用较大的缓冲区重试`MediaExtractor`并检查是否正常工作?如果这样可以解决问题,我将把它发布为答案。 - Ganesh
我已经在另一篇帖子中读到缓冲区大小可能是这个异常的原因。但是,由于我需要使用MediaCodec提供的输入和输出缓冲区,所以我对缓冲区大小没有影响力。 - muetzenflo
显示剩余3条评论
2个回答

6
我无法确定为什么MediaExtractor似乎无法从简单的wav文件中读取数据,所以我选择了不同的方法。由于WAV文件实际上不需要解码,因此我现在使用一个简单的FileInputStream并跳过44字节的头部。
我在这个gist中发布了一个可工作的示例: https://gist.github.com/muetzenflo/3e83975aba6abe63413abd98bb33c401 经过近一周的研究、尝试和错误,这段代码似乎很罕见。我几乎记录了每一行,并希望我能帮助那些在Android上与MediaCodec类挣扎的人们。

你认为这个评论仍然是最新的吗?https://dev59.com/jMv6oIgBc1ULPQZFrnb3#74360916 - mavavilj
我不认识@mavavilj。这已经是6年前的事情了,所以情况可能已经发生了变化。不过话说回来:音频框架并不经常更新,因为它是Android框架的核心级别的东西。我看了你提供的链接中的问题,并确认当时我和你一样毫无头绪。抱歉啊伙计。 - muetzenflo
我在使用MediaExtractor时遇到了麻烦。不知道你的解决方案是否仍然有效。 - mavavilj
使用我的代码的应用程序不再存在了。抱歉,我想你需要自己尝试一下。 - muetzenflo
我对MediaExtractor感到困惑,似乎它没有产生我读取的文件中的数据。尽管MediaExtractor应该可以工作,但这听起来就像是这个答案。 - mavavilj

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

是的,对我来说缓冲区大小是个问题,但我不明白如何决定设置多大的缓冲区。 - mavavilj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接