作者:试管婴儿 | 来源:互联网 | 2023-10-11 02:59
我正在使用Android4.3设备使用cv::Mat对视频进行编码.我看了grafikahacks和BigFrakesamples,我测试了它们并且它们正在工作.我在c中使用了cv
我正在使用Android 4.3设备使用cv :: Mat对视频进行编码.
我看了grafika hacks和BigFrake samples,我测试了它们并且它们正在工作.
我在c中使用了cv :: Mat,并且使用JNI我可以向Java发送缓冲区o缓冲区指针,我已经准备好了和编码器:
///////////////////////// 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.我尝试过使用我可以使用的3种编解码器:
//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的引用.
解决方法:
将FBO渲染到编解码器输入表面非常明显.你需要GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,framebuffer);
然后将frameBuffer的输出纹理id绑定到mediacodec上下文,即makeCurrent首先,
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
并使用类似于mediacodec stufs中存在的regural复制着色器,但没有OES纹理但具有纹理2D:例如
private static final String VERTEXT_SHADER =
"uniform mat4 uOrientationM;\n" +
"uniform mat4 uTransformM;\n" +
"attribute vec2 aPosition;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
"gl_Position = vec4(aPosition, 0.0, 1.0);\n" +
"vTextureCoord = (uTransformM * ((uOrientationM * gl_Position + 1.0) * 0.5)).xy;" +
"}";
private static final String FRAGMENT_SHADER =
"precision mediump float;\n" +
"uniform sampler2D sTexture;\n" +
"varying vec2 vTextureCoord;\n" +
"void main() {\n" +
"gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
"}";
适用于该副本的可用样本解决方案以及您可以在Android https://software.intel.com/en-us/articles/intel-inde-media-pack-for-android-tutorials的英特尔INDE样本中找到的FBO初始化