[英]MediaCodec.Callback handle IllegalStateException from MediaExtractor
I am using MediaCodec
in asynchronous mode to transcode a video based on the example by mstorsjo . 我基于mstorsjo的示例,以异步模式使用
MediaCodec
对视频进行转码。 With some video files I am getting IllegalStateException
's thrown when I call either MediaExtractor.advance()
or MediaExtractor.getSampleTime()
. 对于某些视频文件,调用
MediaExtractor.advance()
或MediaExtractor.getSampleTime()
时会IllegalStateException
。 Eg in my audio decoder: 例如在我的音频解码器中:
MediaCodec decoder = MediaCodec.createDecoderByType(type);
decoder.setCallback(new MediaCodec.Callback() {
public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
ByteBuffer decoderInputBuffer = codec.getInputBuffer(index);
while (!mExtractorDone) {
int size = mExtractor.readSampleData(decoderInputBuffer, 0);
long presentationTimeUs = mExtractor.getSampleTime();
boolean queuedInputBuffer = false;
if (size >= 0) {
codec.queueInputBuffer(
index,
0,
size,
presentationTimeUs,
mExtractor.getSampleFlags());
queuedInputBuffer = true;
}
mExtractorDone = !mExtractor.advance();
if (mExtractorDone) {
queueEOS();
}
if (queuedInputBuffer) {
break;
}
}
}
...
});
decoder.configure(inputFormat, null, null, 0);
decoder.start();
And similarly in my video decoder, which is run in a separate HandlerThread . 同样,在我的视频解码器中,该视频解码器在单独的HandlerThread中运行。
Is there a way I can catch all exceptions thrown in the MediaCodec.Callback
and pass them back to the main awaitEncode function, so I can close everything and exit nicely? 有没有一种方法可以捕获
MediaCodec.Callback
引发的所有异常,并将它们传递回主awaitEncode函数,以便我可以关闭所有内容并正常退出? Should I be putting try catch
s around every callback and then notify
the main processing thread? 我是否应该在每个回调中加入
try catch
,然后notify
主处理线程?
It would be great to figure out what is causing the original IllegalStateException
, but I would also feel more comfortable knowing all problems with my video transcoder were being caught and explained to the user. 弄清楚是什么原因导致了最初的
IllegalStateException
,这将是非常不错的选择,但我也很高兴知道视频转码器的所有问题都已被捕获并向用户解释了。
My best solution so far is to just wrap everything in a try catch
block. 到目前为止,我最好的解决方案是将所有内容包装在
try catch
块中。 I use a utility class that extends MediaCodec.Callback
: 我使用扩展
MediaCodec.Callback
的实用程序类:
public abstract class SafeMediaCodecCallback extends MediaCodec.Callback {
private final OnExceptionListener exceptionListener;
public SafeMediaCodecCallback(OnExceptionListener exceptionListener) {
this.exceptionListener = exceptionListener;
}
@Override
public final void onInputBufferAvailable(@NonNull MediaCodec mediaCodec, int i) {
try {
onInputBufferAvailableSafe(mediaCodec, i);
} catch (Exception exception) {
handleException(exception);
}
}
@Override
public final void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec, int i, @NonNull MediaCodec.BufferInfo bufferInfo) {
try {
onOutputBufferAvailableSafe(mediaCodec, i, bufferInfo);
} catch (Exception exception) {
handleException(exception);
}
}
@Override
public final void onError(@NonNull MediaCodec mediaCodec, @NonNull MediaCodec.CodecException e) {
handleException(e);
}
@Override
public final void onOutputFormatChanged(@NonNull MediaCodec mediaCodec, @NonNull MediaFormat mediaFormat) {
try {
onOutputFormatChangedSafe(mediaCodec, mediaFormat);
} catch (Exception exception) {
handleException(exception);
}
}
private void handleException(Exception e) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (e instanceof CodecException) {
CodecException codecExc = (CodecException) e;
if (codecExc.isTransient()) {
// We'll let transient exceptions go
return;
}
}
}
exceptionListener.onException(e);
}
public abstract void onInputBufferAvailableSafe(@NonNull MediaCodec mediaCodec, int i);
public abstract void onOutputBufferAvailableSafe(@NonNull MediaCodec mediaCodec, int i, @NonNull MediaCodec.BufferInfo bufferInfo);
public abstract void onOutputFormatChangedSafe(@NonNull MediaCodec mediaCodec, @NonNull MediaFormat mediaFormat);
}
And then I can bubble exceptions back up to the top thread, and if we can't recover, kill all the threads, tidy up, and throw the original Exception
. 然后,我可以将异常冒泡回到顶部线程,如果我们无法恢复,请杀死所有线程,整理一下并抛出原始
Exception
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.