I try to decode a mp3 audio data stream with Android Media Codec.
With a sample rate of 44100 the decoding works fine, but the latency is too big. So I set the sample rate to 16000, but now the decoder doesn't work anymore. I get an Illegal State Exception at dequeueOutputBuffer.
This is the part of the code where the problem might be:
bufferInfo = new MediaCodec.BufferInfo();
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, -1);
while (outputBufferIndex >= 0) {
outputBuffer = decoder.getOutputBuffer(outputBufferIndex);
outputBuffer.position(bufferInfo.offset);
outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
track.write(outData, 0, outData.length);
decoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = decoder.dequeueOutputBuffer(bufferInfo, -1);
}
I also tried to set the timeout of dequeueOutputBuffer to 0 but this doesn't change anything.
This is the error I receive:
E/SoftMP3: mp3 decoder returned error 1
E/ACodec: [OMX.google.mp3.decoder] ERROR(0x80001001)
E/ACodec: signalError(omxError 0x80001001, internalError -2147483648)
E/MediaCodec: Codec reported err 0x80001001, actionCode 0, while in state 6
E/AndroidRuntime: FATAL EXCEPTION: Thread-79054
Process: com.example.jonas.audio_client, PID: 26394
java.lang.IllegalStateException
at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:1107)
If I print the Audio Format that the Extractor gets, I see that the Sample-Rate is set to 16000.
D/Format:: {bitrate=32000, mime=audio/mpeg, durationUs=6509000, channel-count=1, sample-rate=16000, bit-rate=32000}
Thanks for any help!
If you are running this on an emulator make sure that you have selected Graphics as Hardware : GLES 2.0 in Emulator settings. There is some issue with the Software version it seems.
I had a similar problem to this but with a video encoder. I resolved my problem by messing around with my video's bit-rate until it worked. For now, I have settled my issue with a bit-rate of 32 * width * height * frameRate / 100. So I would recommend trying to mess with your bit-rate.
I was influenced by this answer to arrive at this solution.
Related
My app create several instance of MediaCodec which work parallel as video/audio decoders and encoders.
I know that video codec has limiting buffer space and this limit depends on device.
For example on tab Samsung SM-P600 I can create four MediaCodecs with resolution 720p:
1280*720*4=3686400
but not five:
1280*720*5=4608000
Because codec will return error during configuring:
E/OMX: setParam sum(4608000) > max resolution(4177920)
E/ACodec: [OMX.Exynos.AVC.Encoder] failed to set input port definition parameters.
E/ACodec: configureCodec multi window instance fail appPid : 17054
E/ACodec: [OMX.Exynos.AVC.Encoder] configureCodec returning error -1021
E/ACodec: signalError(omxError 0x80001001, internalError -1021)
E/MediaCodec: Codec reported err 0xfffffc03, actionCode 0, while in state 3
E/MediaCodec: configure failed with err 0xfffffc03, resetting...
How can I get max resolution(4177920) before configuring MediaCodecs to count max available resolutions for all MediaCodecs I need?
Try to use getMaxSupportedInstances () in MediaCodecInfo.CodecCapabilities.
https://developer.android.com/reference/android/media/MediaCodecInfo.CodecCapabilities.html
Or isSizeSupported(int width,
int height) in MediaCodecInfo.VideoCapabilities.
https://developer.android.com/reference/android/media/MediaCodecInfo.VideoCapabilities.html
Here is the stack trace:
E/ACodec: [OMX.qcom.video.encoder.avc] configureCodec returning error -1010
E/ACodec: signalError(omxError 0x80001001, internalError -1010)
E/MediaCodec: Codec reported err 0xfffffc0e, actionCode 0, while in state 3
E/MediaCodec: configure failed with err 0xfffffc0e, resetting...
W/System.err: android.media.MediaCodec$CodecException: Error 0xfffffc0e
W/System.err: at android.media.MediaCodec.native_configure(Native Method)
W/System.err: at android.media.MediaCodec.configure(MediaCodec.java:1778)
Crash is on Nexus 6P.
Initialization of mediaCodec:
videoCodec = MediaCodec.createEncoderByType(MIME_VIDEO_CODEC_H264);
MediaFormat videoFormat = MediaFormat.createVideoFormat(MIME_VIDEO_CODEC_H264, imageWidth, imageHeight);
videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, camera.getBitrate());
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, camera.getFrameRate());
videoFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 0);
videoCodec.configure(videoFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
I had this issue while i was trying to encode 16:9 videos to .h264 and change the frame size (it worked fine with 4:3).
The fix for me was to ensure that the height and width of the output format were divisible by 2. If they weren't, I just rounded them up so they did.
That appears to be an internal error reported by the Qualcomm codec implementation (OMX.qcom.video.encoder.avc).
It might be harmless, it might indicate a configuration problem, or a different configuration problem, or some other configuration problem. Mostly it just seems to indicate that it didn't like your configuration, without providing any particular insight into why.
The error code is somewhat useless, so you have to start with values that are known to work and change them one at a time until something breaks. What are the actual values you're passing for bit/frame rate?
In my i want encode yuv data into h264 using mediacodec software codec.
I use Google software encoder OMX.google.h264.encoder
when i use hardware encoder[OMX.qcom.video.encoder.avc] that time it work but when i use software encoder[OMX.google.h264.encoder] it not encode file.it will give error [see in log].
what is problem i couldn’t identify.
Source :
mediaCodec = MediaCodec.createByCodecName("OMX.google.h264.encoder");
//mediaCodec = MediaCodec.createByCodecName(codecInfo.getName());
Log.i(TAG,"codec name : "+ mediaCodec.getName());
int mBitrate = (int) ((MainActivity.mHeight * MainActivity.mWidth * MainActivity.frameRate)*2*0.07);
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc",MainActivity.mWidth,MainActivity.mHeight);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE,mBitrate);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, MainActivity.frameRate);
// mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 320*240);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,colorFormat);
//mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,MediaCodecInfo.CodecProfileLevel.AVCLevel12);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,1);
try{
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
Log.i(TAG,"H264 Encoder init success");
}catch(IllegalArgumentException e)
{
e.printStackTrace();
}catch (IllegalStateException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();// TODO: handle exception
}
But i getting this error.
Log :
I/H264Encoder(7772): outputStream initialized
I/OMXClient(7772): Using client-side OMX mux.
I/H264Encoder(7772): found colorFormat: 21
I/OMXClient(7772): Using client-side OMX mux.
E/OMXMaster(7772): A component of name 'OMX.qcom.audio.decoder.aac' already exists, ignoring this one.
I/SoftAVCEncoder(7772): Construct SoftAVCEncoder
I/H264Encoder(7772): codec name : OMX.google.h264.encoder
E/SoftAVCEncoder(7772): internalSetParameter: StoreMetadataInBuffersParams.nPortIndex not zero!
E/OMXNodeInstance(7772): OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x80001001
E/ACodec(7772): [OMX.google.h264.encoder] storeMetaDataInBuffers (output) failed w/ err -2147483648
I/ACodec(7772): setupVideoEncoder succeeded
I/H264Encoder(7772): H264 Encoder init success
E/SoftAVCEncoder(7772): Video frame size 1920x1080 must be a multiple of 16
E/SoftAVCEncoder(7772): Failed to initialized encoder params
E/ACodec(7772): [OMX.google.h264.encoder] ERROR(0x80001001)
E/MediaCodec(7772): Codec reported an error. (omx error 0x80001001, internalError -2147483648)
W/System.err(7772): java.lang.IllegalStateException
W/System.err(7772): at android.media.MediaCodec.getBuffers(Native Method)
W/System.err(7772): at android.media.MediaCodec.getInputBuffers(MediaCodec.java:542)
W/System.err(7772): at com.ei.encodertest.H264Encoder.offerEncoder(H264Encoder.java:170)
W/System.err(7772): at com.ei.encodertest.MainActivity$ReadRawFileTask.doInBackground(MainActivity.java:113)
W/System.err(7772): at com.ei.encodertest.MainActivity$ReadRawFileTask.doInBackground(MainActivity.java:1)
W/System.err(7772): at android.os.AsyncTask$2.call(AsyncTask.java:288)
W/System.err(7772): at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err(7772): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
W/System.err(7772): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
W/System.err(7772): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
W/System.err(7772): at java.lang.Thread.run(Thread.java:841)
The SW encoder OMX.google.h264.encoder is very limited at the moment (edit: On Android 5.0), close to being unusable.
This encoder doesn't allow using resolutions that aren't a multiple of 16. In your case, 1920x1080, the height 1080 isn't evenly dividable by 16, and thus isn't acceptable for this encoder. (See https://android-review.googlesource.com/38904 for an attempt at fixing this.)
If you'd change it into 1088, the multiple-of-16 wouldn't be an issue, but the encoder also won't allow you to use it with any resolution above 352x288 (see e.g. https://android-review.googlesource.com/82133).
Finally, on older Android versions (prior to 5.0), it also did output in a slightly different format (missing startcodes, see https://android-review.googlesource.com/42321), which meant that you would have to manually add startcodes at the start of each output packet to be able to use them in certain places (the MediaMuxer might have handled it as it was, though, mostly by chance).
In the current AOSP master (that is, maybe in the next major release, unless that already is being finalized and this change hasn't been included there), the encoder has been replaced with a more capable one, but for existing releases, there's not much you can do other than bundling a better SW encoder within your app.
Edit: The Android M preview that was released today does include the new SW encoder, which should work fine for this usecase.
Edit2: The new encoder was included in the Android 6.0 release (M), so since then, it should be usable.
I am well aware that there are a few other topics regarding this exception, but none of them seems to be the source of my problem. I'm trying to record a live video from Google Glass, but only one of the encoders seems to work (mime video/avc). Whenever I try a different encoder, I keep getting IllegalStateExceptions. Relevant code:
MediaFormat format = MediaFormat.createVideoFormat("video/svc", 1280, 720);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, 10000000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mEncoder = MediaCodec.createEncoderByType("video/svc");
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mEncoder.start();
As I said, the app crashes at mEncoder.configure, throwing an IllegalStateException at me:
E/ACodec﹕ [OMX.TI.DUCATI1.VIDEO.H264SVCE] configureCodec returning error -1010
E/MediaCodec﹕ Codec reported an error. (omx error 0x80001001, internalError -1010)
W/System.err﹕ java.lang.IllegalStateException
W/System.err﹕ at android.media.MediaCodec.native_configure(Native Method)
I hope someone can shed some light on what I have done wrong here.
Thanks in advance,
Wolfram
IllegalStateExceptions! It seems like that KEY_COLOR_FORMAT was not specified. As my testing result, Google glass' mediacodec api just support 'COLOR_TI_FormatYUV420PackedSemiPlanar', if encode type is ‘video/avc’.
I am using MediaCodec to encode video. Frames are coming through the camera preview callback to the MediaCodec instance (no Surface used). I am using JCodec library for muxing and I am able to stream produced video (video player is showing correct duration and I am able to change video position with seek bar).
Today I've tried to use MediaMuxer instead of JCodec and I've got video which still looks fine, but duration is absolutely incorrect (a few hours instead of one minute) and the seek bar is not working at all.
mediaMuxer = new MediaMuxer("/path/to/video.mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
The following code is lazily called when I receive MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
videoTrackIndex = mediaMuxer.addTrack(encoder.getMediaFormat());
mediaMuxer.start();
I am encoding the frames with the following code:
mediaMuxer.writeSampleData(videoTrackIndex, byteBuffer, bufferInfo);
byteBuffer and bufferInfo are coming directly from MediaCodec after some positioning stuff:
byteBuffer.position(bufferInfo.offset);
byteBuffer.limit(bufferInfo.offset + bufferInfo.size);
Presentation time is set correctly:
mMediaCodec.queueInputBuffer(inputBufferIndex, 0, getWidth() * getHeight() * 1.5, System.nanoTime() / 1000, 0);
And at the end of the record I do:
mediaMuxer.stop();
mediaMuxer.release();
Logs:
I/MPEG4Writer﹕ setStartTimestampUs: 0
I/MPEG4Writer﹕ Earliest track starting time: 0
D/MPEG4Writer﹕ Stopping Video track
I/MPEG4Writer﹕ Received total/0-length (770/0) buffers and encoded 770 frames. - video
D/MPEG4Writer﹕ Stopping Video track source
D/MPEG4Writer﹕ Video track stopped
D/MPEG4Writer﹕ Stopping writer thread
D/MPEG4Writer﹕ 0 chunks are written in the last batch
D/MPEG4Writer﹕ Writer thread stopped
I/MPEG4Writer﹕ The mp4 file will not be streamable.
D/MPEG4Writer﹕ Stopping Video track
I guess the The mp4 file will not be streamable. signals about problem.
Update:
I've tested my app on another device (LG G2) which does more verbose logging. The same file is produced with huge duration. Logs are here and the video file is here.
Thanks to #fadden I was able to figure out the problem. I was actually sending my first frame with presentationTimeUs = 0. It happened because I was not handling frames with MediaCodec.BUFFER_FLAG_CODEC_CONFIG flag properly. I was actually feeding them to the muxer, but what I should have done is to skip them with the following code (as per example):
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
mBufferInfo.size = 0;
}