继续上篇,从本篇开始正式在android ndk项目内引入之前已经编译完成的ffmpeg library,然后通过jni去调用。
首先建立android NDK c++项目,之前已经详细描述过了若何创建了ndk项目了,在src/main/jniLibs下可以放入需要的so文件,可以根据cpu架构区分建立不同的目录,比如
src/main/jniLibs/arm64-v8a 表示arm64
src/main/jinLibs/armeabi-v7a 表示armv7a
src/main/jinLibs/x86_64 表示模拟器支持
需要把以下文件复制到对应的架构文件夹下
set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/ffmpeg)
include_directories(${ffmpeg_head_dir}/include)
add_library( avutil
SHARED
IMPORTED )
set_target_properties( avutil
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavutil.so )
add_library( swresample
SHARED
IMPORTED )
set_target_properties( swresample
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libswresample.so )
add_library( avcodec
SHARED
IMPORTED )
set_target_properties( avcodec
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavcodec.so )
add_library( avfilter
SHARED
IMPORTED)
set_target_properties( avfilter
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavfilter.so )
add_library( swscale
SHARED
IMPORTED)
set_target_properties( swscale
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libswscale.so )
add_library( avformat
SHARED
IMPORTED)
set_target_properties( avformat
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavformat.so )
add_library( avdevice
SHARED
IMPORTED)
set_target_properties( avdevice
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavdevice.so )
add_library( postproc
SHARED
IMPORTED)
set_target_properties(postproc
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libpostproc.so
)
target_link_libraries( # Specifies the target library.
native-lib
# 4. 连接 FFmpeg 相关的库
avutil
swresample
avcodec
avfilter
swscale
avformat
avdevice
postproc
# Links the target library to the log library
# included in the NDK.
${log-lib} )
新建测试cpp文件ffmpeg-test.cpp,
//
// Created by Lokie on 2021/12/8.
//
#include <jni.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavcodec/jni.h>
JNIEXPORT jstring JNICALL Java_com_example_pthread_ffmpegActivity_testLoadFFMPEG(JNIEnv *env, jobject thiz) {
char info[40000] = {0};
AVCodec *c_temp = av_codec_next(NULL);
while (c_temp != NULL) {
if (c_temp->decode != NULL) {
sprintf(info, "%sdecode:", info);
switch (c_temp->type) {
case AVMEDIA_TYPE_VIDEO:
sprintf(info, "%s(video):", info);
break;
case AVMEDIA_TYPE_AUDIO:
sprintf(info, "%s(audio):", info);
break;
default:
sprintf(info, "%s(other):", info);
break;
}
sprintf(info, "%s[%10s]\n", info, c_temp->name);
}
c_temp = c_temp->next;
}
return env->NewStringUTF(info);
}
}
上述代码的作用是列举所有的支持的decoder,合成一个字符串返回给android kotlin
kotlin代码如下:
package com.example.pthread
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.method.ScrollingMovementMethod
import android.widget.Button
import android.widget.TextView
class ffmpegActivity : AppCompatActivity() {
private lateinit var testBtn:Button
private lateinit var testResultTestView:TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ffmpeg)
this.testBtn = findViewById(R.id.testBtn)
this.testResultTestView = findViewById(R.id.testResultTestView)
this.testResultTestView.movementMethod = ScrollingMovementMethod();
this.testBtn.setOnClickListener {
val ffmpegInfo = testLoadFFMPEG()
this.testResultTestView.text = ffmpegInfo
}
}
external fun testLoadFFMPEG():String
companion object {
init {
System.loadLibrary("native-lib")
}
}
}
本文为Lokie.Wang原创文章,转载无需和我联系,但请注明来自lokie博客http://lokie.wang