在android平台中开发webrtc相关项目,可以直接使用webrtc提供的java SDK。当然,也可以选择native的方式来实现。后者相对前者来说,不容易被反编译。所以我们选择的后者的开发方式。
要实现硬件加速,在我脑海中出现了两种方案:
方案一. 通过ffmpeg来实现硬件加速
方案二. 通过webrtc SDK来实现硬件加速
方案一调研:
如果想要实现硬件加速,理论上来说,直接开启ffmpeg中的硬件加速,即可实现自己想要的功能。但现实并不是那么简单,具体看图(参考来源):
也就是说,如果想要通过ffmpeg在android平台中来实现硬件加速,只能通过调用MediaCodec API来实现。但可惜的是,ffmpeg只实现了调用MediaCodec API来实现硬件解码加速,硬件编译加速并没能实现。
所以,通过ffmpeg在android平台中实现硬件编解码加速,目前无法实现。方案一行不通。
方案二调研
- 在java层创建HardwareVideoEncoderFactory与HardwareVideoDecoderFactory类对象
- 把以上两个实例传递到native层,在native层通过JavaToNativeVideoEncoderFactory
和JavaToNativeVideoDecoderFactory把Java类实例转换成native层实例
方案二在调研过程中,确实成功了,因为我使用的测试机是android 9.0。但在真正开发的时候,使用android 8.0及以下手机时,一直报错(很诡异的错误),最终在寻找了两天BUG后,我放弃了方案二,开始寻找方案三。
方案三
与方案二类似,但不通过android SDK来创建HardwareVideoEncoderFactory及HardwareVideoDecoderFactory实例,而是直接在native层创建两者的实例。该方案与webrtc源码中提供的test代码思路一致(源码太多,test代码找了好久才找到,否则也没有方案一和方案二的调研了,test代码src/modules/video_coding/codecs/test/android_codec_factory_helper.cc)源码如下:
std::unique_ptr<VideoEncoderFactory> CreateAndroidEncoderFactory() {
JNIEnv* env = AttachCurrentThreadIfNeeded();
ScopedJavaLocalRef<jclass> factory_class =
GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
jmethodID factory_constructor = env->GetMethodID(
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V");
ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor,
nullptr /* shared_context */,
false /* enable_intel_vp8_encoder */,
true /* enable_h264_high_profile */));
return JavaToNativeVideoEncoderFactory(env, factory_object.obj());
}
std::unique_ptr<VideoDecoderFactory> CreateAndroidDecoderFactory() {
JNIEnv* env = AttachCurrentThreadIfNeeded();
ScopedJavaLocalRef<jclass> factory_class =
GetClass(env, "org/webrtc/HardwareVideoDecoderFactory");
jmethodID factory_constructor = env->GetMethodID(
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;)V");
ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor,
nullptr /* shared_context */));
return JavaToNativeVideoDecoderFactory(env, factory_object.obj());
}
柳暗花明,方案三终于实现了在android下的硬件加速了。不过测试结果发现,H.264硬编效果不及软编。