当MediaCodec输出缓冲区的输入表面镜像到AR场景视图表面时,它不会生成正确的输出

问题描述 投票:0回答:1

我目前正在开发一个项目,该项目需要以字节数组格式对SceneView的内容(摄像机图像以及每帧的AR对象)进行数据流传输。

我试图将SceneView镜像到MediaCodec编码器的输入表面,并根据我从MediaRecorder示例中理解的内容以异步方式使用MediaCodec的输出缓冲区。

我无法像我期望的那样让它工作。 MediaCodec回调的输出缓冲区显示黑屏(转换为位图时)或缓冲区内容(<100字节)太少。我有一种感觉,表面的镜像没有像我期望的那样发生,如果有人能提供一个展示使用MediaCodecSceneForm的正确方法的样本,我将不胜感激。

我目前用于访问ByteBufferMediaCodec的代码:

MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC,
        arFragment.getArSceneView().getWidth(),
        arFragment.getArSceneView().getHeight());

// Set some properties to prevent configure() from throwing an unhelpful exception.
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
        MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, 50000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 0); //All key frame stream

MediaCodec mediaCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);

mediaCodec.setCallback(new MediaCodec.Callback() {
    @Override
    public void onInputBufferAvailable(@NonNull MediaCodec codec, int index) {
    }

    @Override
    public void onOutputBufferAvailable(@NonNull MediaCodec codec, int index, @NonNull MediaCodec.BufferInfo info) {
        ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(index);
        outputBuffer.position(info.offset);
        outputBuffer.limit(info.offset + info.size);
        byte[] data = new byte[outputBuffer.remaining()];
        outputBuffer.get(data);
        Bitmap bitmap = BitmapFactory.decodeByteArray(
                NV21toJPEG(data, videoWidth, videoHeight, 100),
                0, data.length);
        Log.d(TAG, "onOutputBufferAvailable: "+bitmap);
        mediaCodec.releaseOutputBuffer(index, false);
    }

    @Override
    public void onError(@NonNull MediaCodec codec, @NonNull MediaCodec.CodecException e) {
        Log.e(TAG, "onError: ");
    }

    @Override
    public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) 
   {
        Log.d(TAG, "onOutputFormatChanged: " + format);
    }
});

mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Surface surface = mediaCodec.createInputSurface();
mediaCodec.start();
arFragment.getArSceneView().startMirroringToSurface(surface, 0, 0, arFragment.getArSceneView().getWidth(), arFragment.getArSceneView().getHeight());

生成的位图:

android augmented-reality mediacodec arcore sceneform
1个回答
0
投票

MediaCodec编码器的输入是一个Surface(在您的情况下,也可以是一个字节缓冲区),带有原始YUV数据(不能直接访问)。编码器的输出是编码的H264 / AVC比特流。

在您的情况下,您似乎正在尝试读取编码的比特流并将其解释为原始YUV数据。

您真的想将输入数据编码为视频格式(用于流式传输吗?),还是只是尝试使用MediaCodec将Surface中的数据转换为字节缓冲区中可访问的YUV数据?您可以获取YUV数据,创建MediaCodec解码器并立即将数据从编码器提供给解码器,但这一切都非常迂回。

通过Surface接收数据并访问像素数据的直接方式是通过ImageReader类。有关使用此功能的更大示例,请参阅Using Camera2 API with ImageReader

© www.soinside.com 2019 - 2024. All rights reserved.