当前位置: 首页 > 知识库问答 >
问题:

MediaCodec H264编码器不能在Snapdragon 800设备上工作

韶浩博
2023-03-14
        mBufferInfo = new MediaCodec.BufferInfo();
        encoder = MediaCodec.createEncoderByType("video/avc");
        MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480);
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 768000);
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, mEncoderColorFormat);
        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
        encoder.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
MediaCodecInfo.CodecCapabilities capabilities = mCodecInfo.getCapabilitiesForType(MIME_TYPE);
            for (int i = 0; i < capabilities.colorFormats.length && selectedColorFormat == 0; i++)
            {
                int format = capabilities.colorFormats[i];
                switch (format) {
                    case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
                    case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
                    case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
                    case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
                    case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
                    case MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar:
                        selectedColorFormat = format;
                        break;
                    default:
                        LogHandler.e(LOG_TAG, "Unsupported color format " + format);
                        break;
                }
            }
            ByteBuffer[] inputBuffers = mEncoder.getInputBuffers();
        ByteBuffer[] outputBuffers = mEncoder.getOutputBuffers();

        int inputBufferIndex = mEncoder.dequeueInputBuffer(-1);
        if (inputBufferIndex >= 0)
        {
            // fill inputBuffers[inputBufferIndex] with valid data
            ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
            inputBuffer.clear();
            inputBuffer.put(rawFrame);
            mEncoder.queueInputBuffer(inputBufferIndex, 0, rawFrame.length, 0, 0);
            LogHandler.e(LOG_TAG, "Queue Buffer in " + inputBufferIndex);
        }

        while(true)
        {
            int outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, 0);
            if (outputBufferIndex >= 0)
            {
                Log.d(LOG_TAG, "Queue Buffer out " + outputBufferIndex);
                ByteBuffer buffer = outputBuffers[outputBufferIndex];
                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0)
                {
                    // Config Bytes means SPS and PPS
                    Log.d(LOG_TAG, "Got config bytes");
                }

                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0)
                {
                    // Marks a Keyframe
                    Log.d(LOG_TAG, "Got Sync Frame");
                }

                if (mBufferInfo.size != 0)
                {
                    // adjust the ByteBuffer values to match BufferInfo (not needed?)
                    buffer.position(mBufferInfo.offset);
                    buffer.limit(mBufferInfo.offset + mBufferInfo.size);

                    int nalUnitLength = 0;
                    while((nalUnitLength = parseNextNalUnit(buffer)) != 0)
                    {
                        switch(mVideoData[0] & 0x0f)
                        {
                            // SPS
                            case 0x07:
                            {
                                Log.d(LOG_TAG, "Got SPS");
                                break;
                            }

                            // PPS
                            case 0x08:
                            {
                                Log.d(LOG_TAG, "Got PPS");
                                break;
                            }

                            // Key Frame
                            case 0x05:
                            {
                                Log.d(LOG_TAG, "Got Keyframe");
                            }

                            //$FALL-THROUGH$
                            default:
                            {
                                // Process Data
                                break;
                            }
                        }
                    }
                }

                mEncoder.releaseOutputBuffer(outputBufferIndex, false);

                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0)
                {
                    // Stream is marked as done,
                    // break out of while
                    Log.d(LOG_TAG, "Marked EOS");
                    break;
                }
            }
            else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
            {
                outputBuffers = mEncoder.getOutputBuffers();
                Log.d(LOG_TAG, "Output Buffer changed " + outputBuffers);
            }
            else if(outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
            {
                MediaFormat newFormat = mEncoder.getOutputFormat();
                Log.d(LOG_TAG, "Media Format Changed " + newFormat);
            }
            else if(outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER)
            {
                // No Data, break out
                break;
            }
            else
            {
                // Unexpected State, ignore it
                Log.d(LOG_TAG, "Unexpected State " + outputBufferIndex);
            }
        }

谢谢你的帮助!

共有1个答案

酆耀
2023-03-14

您需要在对QueueInputBuffer的调用中设置presentationTimeUs参数。大多数编码器忽略了这一点,您可以为流式编码而没有问题。用于Snapdragon 800设备的编码器不是。

此参数表示帧的录制时间,因此需要在要编码的帧和前一帧之间增加我们的数量。

如果参数集与前一帧中的值相同,编码器将其丢弃。如果参数设置得太小(例如30 FPS录音时为100000),则编码帧的质量下降。

 类似资料:
  • 这个小部件在模拟器4.1.2上工作得很好,当安装在真正的设备上时,它甚至不会显示在小部件列表上,就像安装了一样,但我不能让它正常工作。 下面是manifest.xml 和小部件提供程序

  • 问题内容: 我已经使用Android的MediaCodec API编写了H264流编码器。我在大约十种使用不同处理器的不同设备上对其进行了测试,并且可以在所有这些设备上正常工作,除了在使用Snapdragon 800的设备(Google Nexus 5和Sony Xperia Z1)上。在这些设备上,我得到了SPS和PPS以及第一个关键帧,但是在那之后,mEncoder.dequeueOutput

  • 我是android新手,我能够在kotlin中为我的应用程序设置firebase。如果我在Nexus 5X API 27 emulator中运行该应用程序,我就能够获取数据库,但当我在实际设备三星S5(Google play Services V 12.5.29,android V 5.0)中运行该应用程序时,我无法获得addValueEventListener回调。 Gradle文件: 我知道这

  • 好的,这需要详细说明:首先,当我问“出发地点”的意图时,developer.amazon.com它工作得很好。当我使用真正的设备时,它称之为“unHandledIntent”。其次,当它被重新提示时,它确实工作,比如:“嘿,阿列克谢,问调用名。”在它回复未处理的消息之前,不要说任何话。然后我可以正常地说出话语,它会有反应。第三也是最后一点,它正在与“便利位置”的意图一起工作。我不确定发生了什么或者

  • 我使用以下方法计算行数 和列中的条目 这两种方法在模拟器上都可以正常工作,但在真实设备上会出错...... 知道哪里出问题了吗?谢谢你。 我得到一个错误日志:-

  • 我在OS X(10.10.1)上使用Kivy和buildozer,但我无法在我的android设备上运行Kivy相机应用程序。不使用相机的情况很好。代码如下,我还可以发布buildozer规范文件和调试信息。任何帮助都很感激。 从kivy.App导入应用程序从kivy.uix.Widget导入小部件从kivy.uix.Camera导入相机从kivy.uix.Button导入按钮从kivy.core