2

在我尝试使用 MediaCodec 连接视频的过程中,我尝试使用两个MediaExtractors,每个都与 s 配对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
}

我在通常的 ExtractDecodeEditEncodeTest 中使用这些函数分别代替了 Extractor 代码和 Decoder 代码。我只是传入我想要使用MediaExtractor的解码器,我希望该函数使用所述提取器和解码器执行通常的提取/解码循环。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)

我需要在解码器设置中更改什么?

4

0 回答 0