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

时间:2019-02-13 11:14:57

标签: android augmented-reality mediacodec arcore sceneform

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

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

我一直无法使它正常工作。 MediaCodec回调的输出缓冲区要么显示黑屏(转换为位图时),要么缓冲区内容太少(<100字节)。 我有种感觉,并没有像我期望的那样镜像到表面。如果有人可以提供一个示例来展示将SceneFormByteBuffer一起使用的正确方式,将不胜感激

我当前用于从MediaCodec访问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()); 的代码:

std::variant

生成的位图:

Generated bitmap

1 个答案:

答案 0 :(得分:0)

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

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

您是否真的要将输入数据编码为视频格式(用于流式传输?),还是只是尝试使用MediaCodec将Surface中的数据转换为可在字节缓冲区中访问的YUV数据?您可以使用YUV数据创建MediaCodec解码器,并立即将数据从编码器馈送到解码器,但这一切都是绕行的。

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