在Android Native层直接调用MediaCodec接口的实现
来源:互联网 发布:域名与服务器 编辑:程序博客网 时间:2024/05/29 03:36
因为工作需要,要在Native层直接调用MediaCodec接口。不使用Java层的MediaCodec.java,而是直接使用MediaCodec.cpp。
我们知道,Android上处理视频解码,一般地是使用Java层MediaCodec类开发应用,而MediaCodec.java通过JNI最终调用MediaCodec.cpp的接口。为方便视频流数据的传输和线程控制,提高解码效率,我在工作中,封装了一个基于MediaCodec.cpp的API库,命名为libmediacodec.so,用以被我的Native层应用调用实现视频解码功能。
实现思路比较简单,就是将原来的android_media_mediacodec.cpp中的接口去除JNI的特征,其对应关系如下表所示:
android_media_mediacodec.cpp接口libmediacodec.so接口static void android_media_MediaCodec_native_setup(JNIEnv *env, jobject thiz,
jstring name, jboolean nameIsType, jboolean encoder)int libmcodec_create(char* name, bool nameIsType, bool encoder)static void android_media_MediaCodec_native_configure(
JNIEnv *env,
jobject thiz,
jobjectArray keys, jobjectArray values,
jobject jsurface,
jobject jcrypto,
jint flags)void libmcodec_configure(void* inSurface, MCFormat format)static jobjectArray android_media_MediaCodec_getBuffers(
JNIEnv *env, jobject thiz, jboolean input)void mcodec_getBuffers(bool input, Vector<sp<ABuffer>> & buffers)static jint android_media_MediaCodec_dequeueInputBuffer(
JNIEnv *env, jobject thiz, jlong timeoutUs)int mcodec_dequeueInputBuffer(long timeoutUs)static void android_media_MediaCodec_queueInputBuffer(
JNIEnv *env,
jobject thiz,
jint index,
jint offset,
jint size,
jlong timestampUs,
jint flags)void mcodec_queueInputBuffer(int index, int offset, int size, long timestampUs, int flags)static jint android_media_MediaCodec_dequeueOutputBuffer(
JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs)int mcodec_dequeueOutputBuffer(BufferInfo& info, int64_t timeoutUs)static void android_media_MediaCodec_releaseOutputBuffer(
JNIEnv *env, jobject thiz, jint index, jboolean render)status_t mcodec_releaseOutputBuffer(size_t index, bool render)static void android_media_MediaCodec_start(JNIEnv *env, jobject thiz)void libmcodec_start()static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz)void libmcodec_stop()
上面表格libmediacodec.so一列的接口中,前缀带有lib的是对外开放的,其它的只在lib内部被调用。另外,在libmediacodec.so中实现一个libmcodec_decode接口,用于解码。
几个关键点:
1. suface是通过从Java层传下来的。
在JNI接口里获取Surface地址的方法是:
jint Java_com_xxx_SetSurface(JNIEnv* env, jobject thiz, jobject jsurface)
{
jclass clazz=env->FindClass("android/view/Surface");
jfieldID field_surface = env->GetFieldID(clazz, "mNativeObject","I");
if(field_surface==NULL)
return -1;
void* surface = (void*) env->GetIntField(jsurface,field_surface);
libmcodec_configure(surface, fomat);
return 0;
}
在libmcodec_configure中,需要将void*类型的surface进行如下转换:
sp<Surface> sur = reinterpret_castKSurface*>(inSurface);
2. 关于ABuffer和ByteBuffer转换的理解
在Native层,使用MediaCodec的接口getInputBuffers得到一个存有ABuffer指针的Vector,即指针数组。而Java层使用的是ByteBuffer的数组。 在JNI接口里,进行了相应的转换将ABuffer*的Vector转换为ByterBuffer的数组。转换操作有:
a. 获取input/outpu的sp<ABuffer>数组。
b. 创建ByteBuffer数组
c. 执行循环,循环体步骤如下
ca. 从sp<ABuffer>的Vector中获取一个元素(一个ABuffer的指针)。
cb. 使用这个ABuffer的起始地址和size, 使用NewDirectByteBuffer构建一个ByteBuffer,并按照Native层的字节序,对其进行排序。这里是重点,新创建的ByteBuffer与原ABuffer是同一个起始地址,相同的大小,因此实际上它们是同一个存储区,只是名称和类型不同,Buffer的基本元素都是一个字节。
cd. 使用SetObjectArrayElement将排好序的ByteBuffer放到ByteBuffer数组中。
3. 基于以上对ABuffer的理解,在Navtie使用ABuffer时,就不必做上述转换。直接使用memcpy,向其base()+offset的地址拷贝数据即可。
- 在Android Native层直接调用MediaCodec接口的实现
- 在android的Java层、JNI层、Native C++层都实现了类似的函数,它们是层层向下调用
- Android Studio NDK 开发之在Native中调用java层的函数
- MEDIACODEC在JNI层下的H264,H265视频硬解码实现(ACODEC )
- Android studio 中调用ndk-build 进行编译native 层直接编译
- Android下在C++环境实现native层binder服务
- android jni的使用,java中代码在native层实现
- android MediaCodec 音频编解码的实现
- 使用javascriptcore实现供h5调用的native接口
- AIR Native Extension:在Android的Flex应用中调用Android Intent实现分享功能
- Android中framework层的cpp文件中调用native层c函数的方法
- Android Ndk: 如何从native层直接获取 assets文件夹下的文件
- 关于DAL层使用静态方法,并在WEB层直接调用的问题
- 前端直接调用OC的native方法
- MVC层的接口调用
- Android开发Bitmap在Native层与Java层内存的两种生成方式
- Android开发Bitmap在Native层与Java层内存的两种生成方式
- 关于android native层的Ixxx 接口中Binder机制的探讨
- Multiple dex files define Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompat
- JAVA 之 面向对象
- Specified VM install not found: type Standard VM, name jre
- Codeforces 733B Parade(数列绝对值最大)
- Incarnation不完全恢复
- 在Android Native层直接调用MediaCodec接口的实现
- [深度学习论文笔记] Convolutional Neuron Networks and its Applications
- nrf52832 移植 fatfs
- android 端没有办法连接到指定端口(附带一些端口操作)
- 神奇的魔术师——简单工厂模式
- GDB初次调试案例
- 在PCB中搜索元件
- java动态代理和com.sun.proxy.$Proxy0源码解析
- Linux下的MBR分区