在尝试使用MediaCodec连接视频时,我尝试使用两个MediaExtractor
,每个MediaCodec
与private void videoExtractorLoop(MediaExtractor localVideoExtractor, MediaCodec destinationDecoder, ByteBuffer[] destinationDecoderInputBuffers)
{
boolean localExtractorIsOrig = (localVideoExtractor == videoExtractor);
boolean localDoneIndicator = localExtractorIsOrig ? videoExtractorDone : videoExtractorAppendDone;
while (mCopyVideo && !localDoneIndicator && (encoderOutputVideoFormat == null || muxing)) {
int decoderInputBufferIndex = destinationDecoder.dequeueInputBuffer(TIMEOUT_USEC);
if (decoderInputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
if (VERBOSE)
Log.d(TAG, "no video decoder input buffer");
break;
}
if (VERBOSE) {
Log.d(TAG, "video decoder: returned input buffer: "
+ decoderInputBufferIndex);
}
ByteBuffer decoderInputBuffer = destinationDecoderInputBuffers[decoderInputBufferIndex];
int size = localVideoExtractor.readSampleData(decoderInputBuffer, 0);
long presentationTime = localVideoExtractor.getSampleTime();
if (VERBOSE) {
Log.d(TAG, (localVideoExtractor == videoExtractor) + " video extractor: returned buffer of size "
+ size);
Log.d(TAG, (localVideoExtractor == videoExtractor) + " video extractor: returned buffer for time "
+ presentationTime);
}
if (size >= 0) {
if(localExtractorIsOrig)firstDecoderFinalFrameTimestamp = presentationTime;
destinationDecoder.queueInputBuffer(decoderInputBufferIndex, 0, size, presentationTime, localVideoExtractor.getSampleFlags());
}
if(localExtractorIsOrig)
{videoExtractorDone = !localVideoExtractor.advance();}
else
{
videoExtractorAppendDone = !localVideoExtractor.advance();
}
if (videoExtractorDone) {
if (VERBOSE)
Log.d(TAG, "video extractor: EOS");
if(localExtractorIsOrig && destinationDecoder == videoDecoder){destinationDecoder.queueInputBuffer(decoderInputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);}
else if(!localExtractorIsOrig && destinationDecoder == videoDecoderAppend){destinationDecoder.queueInputBuffer(decoderInputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);}
//videoDecoder.queueInputBuffer(decoderInputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
}
videoExtractedFrameCount++;
break;
}
//Video Extractor code end
}
private void localizedVideoDecoderLoop(MediaCodec localVideoDecoder, OutputSurface localVidDecoderOutputSurface, InputSurface dstEncoderInputSurface, ByteBuffer[] locDecoderOutputBuffers)
{
boolean localDecoderIsOrig = (localVideoDecoder == videoDecoder);
boolean localDoneIndicator = localDecoderIsOrig ? videoDecoderDone : videoDecoderAppendDone;
MediaFormat localDecoderOutFormat = localDecoderIsOrig ? decoderOutputVideoFormat : decoderOutputAppendVideoFormat;
Log.i("check_local_decoder", localDecoderIsOrig+"");
MediaCodec.BufferInfo localDecoderOutBufInfo = localDecoderIsOrig ? videoDecoderOutputBufferInfo : videoDecoderAppendOutputBufferInfo;
//Video Decoder code begin
while (mCopyVideo && !localDoneIndicator && (encoderOutputVideoFormat == null || muxing)) {
int decoderOutputBufferIndex = localVideoDecoder.dequeueOutputBuffer(localDecoderOutBufInfo, TIMEOUT_USEC);
if (decoderOutputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
if (VERBOSE)
Log.d(TAG, "no video decoder output buffer");
break;
}
if (decoderOutputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
if (VERBOSE)
Log.d(TAG, "video decoder: output buffers changed");
if(localDecoderIsOrig){videoDecoderOutputBuffers = localVideoDecoder.getOutputBuffers();}
else {videoDecoderAppendOutputBuffers = localVideoDecoder.getOutputBuffers();}
break;
}
if (decoderOutputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
if(localDecoderIsOrig){decoderOutputVideoFormat = localVideoDecoder.getOutputFormat();}
else{decoderOutputAppendVideoFormat = localVideoDecoder.getOutputFormat();}
Log.i("decoder_vid_out_format", localDecoderOutFormat+"");
if (VERBOSE) {
Log.d(TAG, "video decoder: output format changed: "
+ localDecoderOutFormat);
}
break;
}
if (VERBOSE) {
Log.d(TAG, "video decoder: returned output buffer: "
+ decoderOutputBufferIndex);
Log.d(TAG, "video decoder: returned buffer of size "
+ localDecoderOutBufInfo.size);
Log.d(TAG, "video decoder: returned buffer for time "
+ localDecoderOutBufInfo.presentationTimeUs);
}
ByteBuffer decoderOutputBuffer = locDecoderOutputBuffers[decoderOutputBufferIndex];
if ((localDecoderOutBufInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
if (VERBOSE)
Log.d(TAG, "video decoder: codec config buffer");
localVideoDecoder.releaseOutputBuffer(decoderOutputBufferIndex,
false);
break;
}
if (VERBOSE) {
Log.d(TAG, "video decoder: returned buffer for time "
+ localDecoderOutBufInfo.presentationTimeUs);
}
boolean render = localDecoderOutBufInfo.size != 0;
localVideoDecoder.releaseOutputBuffer(decoderOutputBufferIndex,
render);
if (render) {
renderingFrameSection(localVidDecoderOutputSurface, dstEncoderInputSurface, localDecoderOutBufInfo.presentationTimeUs);
}
videoDecodedFrameCount++;
if ((localDecoderOutBufInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
if (VERBOSE)
Log.d(TAG, "video decoder: EOS");
if(localDecoderIsOrig){videoDecoderDone = true;}
else{videoDecoderAppendDone = true;}
if(!localDecoderIsOrig){videoEncoder.signalEndOfInputStream();}
}
break;
}
//Video Decoder code end
}
s配对作为解码器。我尝试本地化Extractor和Decoder循环,使它们看起来像这样:
MediaExtractor
我在通常的ExtractDecodeEditEncodeTest中分别代替Extractor代码和Decoder代码使用这些函数。我只是传递了MediaCodec
和我想要使用的解码器destinationDecoder.queueInputBuffer(decoderInputBufferIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
,我希望该函数能够使用所述提取器和解码器进行通常的提取/解码循环。
当我将这些函数用于第一个提取器 - 解码器对时,它们工作正常。但是,当我在第一个工作完成后立即将它们用于第二个提取器 - 解码器对时,我从第W/System.err: android.media.MediaCodec$CodecException: Error 0xfffffff3
行得到以下异常:
10-07 10:37:39.697 3061-25956/? I/EXYNOS_BASE_COMP: [0xf1459700][Exynos_OMX_ComponentStateSet] current:(OMX_StateLoaded) dest:(OMX_StateIdle)
10-07 10:37:39.697 23904-25949/com.picmix.mobile I/ACodec: [OMX.Exynos.avc.dec] Now Loaded->Idle
10-07 10:37:39.707 23904-25949/com.picmix.mobile D/SurfaceUtils: set up nativeWindow 0x7f76e82010 for 400x224, color 0x105, rotation 0, usage 0x2900
10-07 10:37:39.707 23904-25949/com.picmix.mobile I/ACodec: [OMX.Exynos.avc.dec] configureOutputBuffersFromNativeWindow setBufferCount : 7, minUndequeuedBuffers : 5
10-07 10:37:39.707 3061-25956/? D/libexynosv4l2: try node: /dev/video6
10-07 10:37:39.707 3061-25956/? I/libexynosv4l2: node found for device s5p-mfc-dec: /dev/video6
10-07 10:37:39.707 23904-25929/com.picmix.mobile I/check_local_decoder: false
10-07 10:37:39.707 3061-25956/? I/libexynosv4l2: open video device /dev/video6
10-07 10:37:39.717 3061-25956/? I/EXYNOS_BASE_COMP: [0xf1459700][Exynos_OMX_ComponentStateSet]:567 OMX_EventCmdComplete
10-07 10:37:39.717 3061-25956/? I/EXYNOS_BASE_COMP: [0xf1459700][Exynos_OMX_ComponentStateSet] current:(OMX_StateIdle) dest:(OMX_StateExecuting)
10-07 10:37:39.717 3061-25956/? I/EXYNOS_BASE_COMP: [0xf1459700][Exynos_OMX_ComponentStateSet]:567 OMX_EventCmdComplete
10-07 10:37:39.717 23904-25949/com.picmix.mobile I/ACodec: [OMX.Exynos.avc.dec] Now Idle->Executing
10-07 10:37:39.717 23904-25949/com.picmix.mobile I/ACodec: [OMX.Exynos.avc.dec] Now Executing
10-07 10:37:39.717 3061-25979/? E/libexynosv4l2: failed to ioctl: VIDIOC_S_CTRL (22)
10-07 10:37:39.717 3061-25979/? E/EXYNOS_H264_DEC: Failed to set buffer process type(not supported)
10-07 10:37:39.717 3061-25979/? E/libexynosv4l2: failed to ioctl: VIDIOC_G_CTRL (22 - Invalid argument)
编辑:
我在堆栈跟踪中仔细观察并发现了这些:
class Vehicle {
...
}
class Car extends Vehicle {
...
}
class Motorcycle extends Vehicle {
...
}
我需要在解码器设置中更改什么?