add jni interface

dev
xufulong 3 years ago
parent 3fab7f9efe
commit f91ee199ce
  1. 1
      app/CMakeLists.txt
  2. 5
      app/src/main/cpp/visualizer/frank_visualizer.h
  3. 80
      app/src/main/cpp/visualizer/frank_visualizer_jni.cpp
  4. 53
      app/src/main/java/com/frank/ffmpeg/effect/FrankVisualizer.java

@ -38,6 +38,7 @@ add_library( # Sets the name of the library.
src/main/cpp/visualizer/fixed_fft.cpp
src/main/cpp/visualizer/block_queue.c
src/main/cpp/visualizer/frank_visualizer.cpp
src/main/cpp/visualizer/frank_visualizer_jni.cpp
src/main/cpp/visualizer/window.cpp
)

@ -36,12 +36,13 @@ typedef struct
class FrankVisualizer {
private:
std::mutex mFftLock;
public:
FrankVisualizer();
~FrankVisualizer();
std::mutex mFftLock;
filter_sys_t *fft_context = nullptr;
void fft_run();

@ -0,0 +1,80 @@
//
// Created by frank on 2021/8/28.
//
#include <jni.h>
#include "frank_visualizer.h"
#define VISUALIZER_FUNC(RETURN_TYPE, NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE \
Java_com_frank_ffmpeg_effect_FrankVisualizer_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
} \
JNIEXPORT RETURN_TYPE \
Java_com_frank_ffmpeg_effect_FrankVisualizer_ ## NAME \
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
struct fields_t {
jfieldID context;
};
static fields_t fields;
static const char *className = "com/frank/ffmpeg/effect/FrankVisualizer";
void setCustomVisualizer(JNIEnv *env, jobject thiz) {
auto *customVisualizer = new FrankVisualizer();
jclass clazz = env->FindClass(className);
if (!clazz) {
return;
}
fields.context = env->GetFieldID(clazz, "mNativeVisualizer", "J");
if (!fields.context) {
return;
}
env->SetLongField(thiz, fields.context, (jlong) customVisualizer);
}
FrankVisualizer *getCustomVisualizer(JNIEnv *env, jobject thiz) {
if (!fields.context) return nullptr;
return (FrankVisualizer *) env->GetLongField(thiz, fields.context);
}
void fft_callback(JNIEnv *jniEnv, int8_t * arg, int samples) {
jclass visual_class = jniEnv->FindClass(className);
jmethodID fft_method = jniEnv->GetStaticMethodID(visual_class, "onFftCallback", "([B)V");
jbyteArray dataArray = jniEnv->NewByteArray(samples);
jniEnv->SetByteArrayRegion(dataArray, 0, samples, arg);
jniEnv->CallStaticVoidMethod(visual_class, fft_method, dataArray);
jniEnv->DeleteLocalRef(dataArray);
}
VISUALIZER_FUNC(int, nativeInitVisualizer) {
setCustomVisualizer(env, thiz);
FrankVisualizer *mVisualizer = getCustomVisualizer(env, thiz);
if (!mVisualizer) return -2;
return mVisualizer->init_visualizer();
}
VISUALIZER_FUNC(int, nativeCaptureData, jobject buffer, jint size) {
if (!buffer) return -1;
FrankVisualizer *mVisualizer = getCustomVisualizer(env, thiz);
if (!mVisualizer || !mVisualizer->fft_context) return -2;
int nb_samples = size < MAX_FFT_SIZE ? size : MAX_FFT_SIZE;
if (nb_samples >= MIN_FFT_SIZE) {
mVisualizer->fft_context->nb_samples = nb_samples;
auto *direct_buffer = static_cast<uint8_t *>(env->GetDirectBufferAddress(buffer));
memcpy(mVisualizer->fft_context->data, direct_buffer, static_cast<size_t>(nb_samples));
mVisualizer->fft_run();
fft_callback(env, mVisualizer->fft_context->output, mVisualizer->fft_context->out_samples);
}
return 0;
}
VISUALIZER_FUNC(void, nativeReleaseVisualizer) {
FrankVisualizer *mVisualizer = getCustomVisualizer(env, thiz);
if (!mVisualizer) return;
mVisualizer->release_visualizer();
delete mVisualizer;
env->SetLongField(thiz, fields.context, 0);
}

@ -0,0 +1,53 @@
package com.frank.ffmpeg.effect;
import java.nio.ByteBuffer;
/**
* @author frank
* @date 2021/10/1 11:25
* @desc custom audio visualizer
*/
public class FrankVisualizer {
private long mNativeVisualizer;
private static OnFftDataListener mOnFftDataListener;
public FrankVisualizer() {}
public void setOnFftDataListener(OnFftDataListener onFftDataListener) {
mOnFftDataListener = onFftDataListener;
}
public int initVisualizer() {
return nativeInitVisualizer();
}
public void captureData(ByteBuffer data, int size) {
if (data == null || size <= 0) {
nativeCaptureData(data, size);
}
}
public void releaseVisualizer() {
mOnFftDataListener = null;
nativeReleaseVisualizer();
}
public interface OnFftDataListener {
void onFftData(byte[] data);
}
public static void onFftCallback(byte[] data) {
if (mOnFftDataListener != null) {
mOnFftDataListener.onFftData(data);
}
}
private native int nativeInitVisualizer();
private native int nativeCaptureData(ByteBuffer buffer, int size);
private native void nativeReleaseVisualizer();
}
Loading…
Cancel
Save