我正在使用一台安卓4.3设备,使用cv::Mat编码视频。
我查看了grafika hacks和BigFrake samples, 我已经测试过它们并且可以工作。
我在c++中有我的cv::Mat,并且使用JNI可以将缓冲区或缓冲区指针发送到Java,在那里我已经准备好了编码器:
///////////////////////// Configure encoder
// QVGA at 2Mbps
mWidth = 320;
mHeight = 240;
mBitRate = 2000000;
//////////////////////////////////////
MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
if (codecInfo == null)
{
// Don't fail CTS if they don't have an AVC codec (not here, anyway).
Log.e(LOG_TAG, "Unable to find an appropriate codec for " + MIME_TYPE);
}
if (VERBOSE) Log.d(LOG_TAG, "found codec: " + codecInfo.getName());
mBufferInfo = new MediaCodec.BufferInfo();
MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an unhelpful exception.
format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
// format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
// format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 200);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); // PROBLEM: Color_formatSurface is the only want who works!!!!!
if (VERBOSE) Log.d(LOG_TAG, "format: " + format);
// Create a MediaCodec encoder, and configure it with our format.
//
mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
//mInputSurface = new CodecInputSurface(mEncoder.createInputSurface()); // I don't want to use a surface
mEncoder.start();
inputBuffers = mEncoder.getInputBuffers();
outputBuffers = mEncoder.getOutputBuffers();
问题在于,MediaFormat.KEY_COLOR_FORMAT 只支持 COLOR_FormatSurface 或 COLOR_FormatYUV420SemiPlanar,但我的数据是 RGB 格式的,没有表面元数据或者 YUV。我已经尝试使用了三种可用的编解码器:
//private static final String MIME_TYPE = "video/avc"; // H.264 Advanced Video Coding
//private static final String MIME_TYPE = "video/mp4v-es"; // Mp4
private static final String MIME_TYPE = "video/3gpp"; // 3gpp
1)这种情况下,颜色格式是否会成为问题?我的意思是,是否可以直接使用,我必须使用PixelBuffer来伪造COLOR_FormatSurface,或者将我的数据转换为YUV?
2)从cv :: Mat.data指针复制数据到MediaCodec缓冲区的最有效方法是什么?
更新1:
- 在提取CV:Mat之前,我有一个FBO OpenGL。我认为另一种解决方案是在InputSurface中呈现FBO,以直接使用MediaCodec对视频进行编码,而无需共享上下文。 但我没有找到将FBO从OpenGL上下文复制到CodecInputSurface的参考。
glTexImage2D
将RGB数据上传到纹理; Grafika中有一个基准测试(512x512 RGBA),表明它在当前设备上非常快。 - fadden