在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硬編效果不及軟編。