我目前正在开发一个项目,该项目需要以字节数组格式对SceneView的内容(摄像机图像以及每帧的AR对象)进行数据流传输。
我试图将SceneView镜像到MediaCodec编码器的输入表面,并根据我从MediaRecorder示例中理解的内容以异步方式使用MediaCodec的输出缓冲区。
我无法像我期望的那样让它工作。 MediaCodec回调的输出缓冲区显示黑屏(转换为位图时)或缓冲区内容(<100字节)太少。我有一种感觉,表面的镜像没有像我期望的那样发生,如果有人能提供一个展示使用MediaCodec
和SceneForm
的正确方法的样本,我将不胜感激。
我目前用于访问ByteBuffer
的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());
生成的位图:
MediaCodec编码器的输入是一个Surface(在您的情况下,也可以是一个字节缓冲区),带有原始YUV数据(不能直接访问)。编码器的输出是编码的H264 / AVC比特流。
在您的情况下,您似乎正在尝试读取编码的比特流并将其解释为原始YUV数据。
您真的想将输入数据编码为视频格式(用于流式传输吗?),还是只是尝试使用MediaCodec将Surface中的数据转换为字节缓冲区中可访问的YUV数据?您可以获取YUV数据,创建MediaCodec解码器并立即将数据从编码器提供给解码器,但这一切都非常迂回。
通过Surface接收数据并访问像素数据的直接方式是通过ImageReader类。有关使用此功能的更大示例,请参阅Using Camera2 API with ImageReader。