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