我一直在尝试使用新的低级MediaCodec使Android平板电脑拍摄的输入图像进行H264编码。由于MediaCodecAPI文档质量欠佳,我遇到了一些困难,但最终我已经让它可以工作。
我是如下设置相机:
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewFormat(ImageFormat.YV12); // <1>
parameters.setPreviewFpsRange(4000,60000);
parameters.setPreviewSize(640, 480);
mCamera.setParameters(parameters);
对于编码部分,我正在通过以下方式实例化MediaCodec对象:
mediaCodec = MediaCodec.createEncoderByType("video/avc");
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", 640, 480);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 500000);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar); // <2>
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);
mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
最终目标是创建一个RTP流(并与Skype通信),但目前我只是将原始H264直接流式传输到我的桌面。在那里,我使用以下GStreamer管道来显示结果:gst-launch udpsrc port=5555 ! video/x-h264,width=640,height=480,framerate=15/1 ! ffdec_h264 ! autovideosink
除了颜色问题,一切正常。我需要在计算机中设置两种颜色格式:一种用于相机预览(标有<1>
),一种用于MediaCodec对象(标有<2>
)。为确定行
<1>
的可接受值,我使用了parameters.getSupportedPreviewFormats()
。从这个函数返回值,我知道相机仅支持ImageFormat.NV21和ImageFormat.YV2这两种格式。对于
<2>
,我获取了类型为video/avc的MediaCodecInfo.CodecCapabilities对象,它对应的整数值为19(对应于MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar)和2130708361(这不对应任何一个MediaCodecInfo.CodecCapabilities的值)。除此之外的任何值都会导致崩溃。
将这些设置组合起来会产生不同的结果,下面我将展示这些结果。以下是在Android上的屏幕截图(即“真实”颜色):
![Input on Android-tablet](https://istack.dev59.com/fjFXp.webp)
<1>
= NV21,<2>
= COLOR_FormatYUV420Planar
![Gstreamer-output for NV21-COLOR_FormatYUV420Planar](https://istack.dev59.com/kyrMZ.webp)
<1>
= NV21,<2>
= 2130708361
![Gstreamer-output for NV21-2130708361](https://istack.dev59.com/C2MZN.webp)
<1>
= YV2,<2>
= COLOR_FormatYUV420Planar
![Gstreamer-output for YV2-COLOR_FormatYUV420Planar](https://istack.dev59.com/FdJZN.webp)
<1>
= YV2,<2>
= 2130708361
![Gstreamer-output for YV2-2130708361](https://istack.dev59.com/rl8xb.webp)
由于目的是与Skype通信,我假设我不应更改解码器(即Gstreamer命令),对吗?这可以在Android中解决吗?如果可以,怎么解决?还有其他的建议吗?