5

I am using the Android MediaExtractor like this:

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);

The inputBuffer is provided by MediaCodec which is configured as AAC Encoder. The goal is to convert the wave file to aac. The above code is abbreviated, of course, but I tracked the error down to the last line.

It also only occurs when using the MediaExtractor with a wav file. For example, I used a .m4a instead and everything worked fine.

The documentation of MediaExtractor says:

MediaExtractor facilitates extraction of demuxed, typically encoded, media data from a data source.

"typically encdoded" does not exclude un-encodec PCM audio....right? Anyone tried this before or knows another stable(!) way to:

  • extract the audio samples from a wav (excluding 44byte or 46byte header)?
  • convert an wav file to aac on Android?

UPDATE

Here is the 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)

I am using API 16, so MediaMuxer is not an option (was added in API 18).

muetzenflo
  • 5,653
  • 4
  • 41
  • 82
  • Can you please share the exact `logcat` logs? `IllegalArgumentException` could come due to multiple scenarios. If you have `logcat`, it would be easier to isolate and suggest a solution. On a related note, have you confirmed that the file exists here `path/to/my/wav/file.wav`?. Also, could you please specify which version of Android you are working on? – Ganesh Jun 25 '16 at 04:25
  • From your logs `com.android.audiosandbox.convert.MediaEncoder2.encode`, it looks like a custom encoder is being used. To isolate this problem, can you please remove this `encoder` from `media_codecs.xml` and try to use the __default__ software encoder i.e. `MediaCodec` as in this example: http://androidxref.com/4.1.2/xref/frameworks/av/cmds/stagefright/SimplePlayer.cpp#316 – Ganesh Jun 25 '16 at 17:14
  • Well, the "custom encoder" is the class I am working on. I got it work now, but not with MediaExtractor. I will post a gist as an answer. If you have more insight on using the MediaExtractor with wav files, I'd gladly hear it. Thanks! – muetzenflo Jun 26 '16 at 10:00
  • 1
    The only reason why there could be an error as reported by you is due to insufficient size of the buffer required to read the content. The native implementation of `MediaExtractor` is implemented by `NuMediaExtractor`. In the method quoted in the log, the only erroneous exit could be due to `-ENOMEM` as shown here: http://androidxref.com/4.1.1/xref/frameworks/av/media/libstagefright/NuMediaExtractor.cpp#402. Can you please retry with `MediaExtractor` with a big buffer and check if the same works fine? If this works, I will post it as answer – Ganesh Jun 27 '16 at 03:31
  • I already read in another post that the buffer size might be the reason for this Exception. But I have no influence on the buffer size, since I need to use the input- and outputBuffers provided by MediaCodec. – muetzenflo Jun 27 '16 at 07:25
  • If I understood correctly, I presume you are creating the `MediaCodec`. If so, then can't you allocate a large enough buffer? – Ganesh Jun 27 '16 at 09:18
  • No, I am using the MediaCodec class from Android to encode a wav file to another file format: https://developer.android.com/reference/android/media/MediaCodec.html – muetzenflo Jun 27 '16 at 09:38
  • My comment was for this statement: `ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferIndex);`. This buffer is allocated by the `codec`. Hence, my earlier comment was for increasing the buffer size in the implementation of `codec` – Ganesh Jun 27 '16 at 14:22

2 Answers2

6

I could not figure out "if" or "why not" the MediaExtractor seems to be unable to read data from a simple wav file, so I chose a different approach. Since WAV file don't really need to be decoded, I now use a simple FileInputStream and skip the 44-byte header.

I got a working sample published in this gist: https://gist.github.com/muetzenflo/3e83975aba6abe63413abd98bb33c401

After almost one week of research, try and error, this piece of code seems to be rare. I documented almost every line and hope that I can help others who struggle with the MediaCodec class on Android.

muetzenflo
  • 5,653
  • 4
  • 41
  • 82
  • Do you think this comment is still up to date? https://stackoverflow.com/a/74360916/4959635 – mavavilj Nov 09 '22 at 07:49
  • I don't know @mavavilj This was over 6 years ago, so things might have changed, of course. Then again: The audio framework is not something that is updated often, since it is something on the core-level of the Android framework. I read the question you linked and can confirm that I was as clueless as you back then. Sorry mate. – muetzenflo Nov 09 '22 at 13:27
  • I'm having troubles with MediaExtractor. I wonder if your solution still works though. – mavavilj Nov 10 '22 at 09:21
  • The app that used my code does not exist anymore. Sorry, I guess you need to try it out on your own. – muetzenflo Nov 10 '22 at 13:20
  • I'm having confusion with MediaExtractor seemingly not producing the data that's in the file that I read. And this just sounds like this answer, even though MediaExtractor probably should work. – mavavilj Nov 14 '22 at 13:55
1

Before calling decoder.configure(format, ...), I suggest to call format.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 65536);, it will make decoder use bigger buffers. This should fix the issue. If not, try to increase buffer size.

xapienz
  • 179
  • 5
  • Yes, for me buffer size was the problem, but I don't understand how to decide how large buffer to set. – mavavilj Nov 10 '22 at 09:23