Add: jni method of media retriever

pull/209/head
xufulong 3 years ago
parent 84e64c159b
commit a8b1c59365
  1. 14
      app/src/main/cpp/ffmpeg_jni_define.h
  2. 71
      app/src/main/cpp/metadata/media_retriever_jni.cpp

@ -34,16 +34,16 @@ extern "C" { \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_VideoPlayer_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#define MEDIA_PLAYER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
#define PUSHER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_Pusher_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#define RETRIEVER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
extern "C" { \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_MediaPlayer_ ## FUNC_NAME \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_metadata_FFmpegMediaRetriever_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__);\
}\
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_MediaPlayer_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#define PUSHER_FUNC(RETURN_TYPE, FUNC_NAME, ...) \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_Pusher_ ## FUNC_NAME \
JNIEXPORT RETURN_TYPE JNICALL Java_com_frank_ffmpeg_metadata_FFmpegMediaRetriever_ ## FUNC_NAME \
(JNIEnv *env, jobject thiz, ##__VA_ARGS__)\
#endif //FFMPEGANDROID_FFMPEG_JNI_DEFINE_H

@ -9,14 +9,9 @@
#include "jni.h"
#include <android/bitmap.h>
#include "ffmpeg_jni_define.h"
#define LOG_TAG "FFmpegMediaRetrieverJNI"
extern "C" {
#include "ffmpeg_media_retriever.h"
}
using namespace std;
#define LOG_TAG "FFmpegMediaRetriever"
struct fields_t {
jfieldID context;
@ -26,16 +21,16 @@ static fields_t fields;
static ANativeWindow* theNativeWindow;
static const char* kClassPathName = "com/frank/ffmpeg/metadata/FFmpegMediaRetriever";
static jstring NewStringUTF(JNIEnv* env, const char * data) {
static jstring NewStringUTF(JNIEnv* env, const char* data) {
jstring str = nullptr;
int size = strlen(data);
jbyteArray array = env->NewByteArray(size);
if (!array) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "convertString: OutOfMemoryError is thrown.");
LOGE(LOG_TAG, "convertString: OutOfMemoryError is thrown.");
} else {
jbyte* bytes = env->GetByteArrayElements(array, nullptr);
if (bytes != nullptr) {
memcpy(bytes, data, size);
strcpy((char *)bytes, data);
env->ReleaseByteArrayElements(array, bytes, 0);
jclass string_Clazz = env->FindClass("java/lang/String");
@ -57,16 +52,16 @@ void jniThrowException(JNIEnv* env, const char* className,
env->ThrowNew(exception, msg);
}
static void process_retriever_call(JNIEnv *env, int opStatus, const char* exception, const char *message)
static void process_retriever_call(JNIEnv *env, int status, const char* exception, const char *message)
{
if (opStatus == -2) {
if (status == -2) {
jniThrowException(env, "java/lang/IllegalStateException", nullptr);
} else if (opStatus == -1) {
} else if (status == -1) {
if (strlen(message) > 520) {
jniThrowException( env, exception, message);
} else {
char msg[256];
sprintf(msg, "%s: status = 0x%X", message, opStatus);
sprintf(msg, "%s: status = 0x%X", message, status);
jniThrowException( env, exception, msg);
}
}
@ -80,17 +75,16 @@ static MediaRetriever* getRetriever(JNIEnv* env, jobject thiz)
static void setRetriever(JNIEnv* env, jobject thiz, long retriever)
{
auto *old = (MediaRetriever*) env->GetLongField(thiz, fields.context);
env->SetLongField(thiz, fields.context, retriever);
}
static void native_setup(JNIEnv *env, jobject thiz)
RETRIEVER_FUNC(void, native_setup)
{
auto* retriever = new MediaRetriever();
setRetriever(env, thiz, (long)retriever);
}
static void native_init(JNIEnv *env, jobject thiz)
RETRIEVER_FUNC(void, native_init)
{
jclass clazz = env->FindClass(kClassPathName);
if (!clazz) {
@ -106,7 +100,7 @@ static void native_init(JNIEnv *env, jobject thiz)
avformat_network_init();
}
static void native_set_dataSource(JNIEnv *env, jobject thiz, jstring path) {
RETRIEVER_FUNC(void, native_set_dataSource, jstring path) {
MediaRetriever* retriever = getRetriever(env, thiz);
if (retriever == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
@ -130,7 +124,7 @@ static void native_set_dataSource(JNIEnv *env, jobject thiz, jstring path) {
env->ReleaseStringUTFChars(path, tmp);
}
static int jniGetFDFromFileDescriptor(JNIEnv * env, jobject fileDescriptor) {
static int getFileDescriptor(JNIEnv * env, jobject fileDescriptor) {
jint fd = -1;
jclass fdClass = env->FindClass("java/io/FileDescriptor");
@ -144,8 +138,11 @@ static int jniGetFDFromFileDescriptor(JNIEnv * env, jobject fileDescriptor) {
return fd;
}
static void native_set_dataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
RETRIEVER_FUNC(void, native_set_dataSourceFD, jobject fileDescriptor, jlong offset, jlong length)
{
if (offset < 0 || length < 0) {
return;
}
MediaRetriever* retriever = getRetriever(env, thiz);
if (retriever == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
@ -155,39 +152,30 @@ static void native_set_dataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescr
jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
return;
}
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
if (offset < 0 || length < 0 || fd < 0) {
if (offset < 0) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "negative offset (%ld)", offset);
}
if (length < 0) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "negative length (%ld)", length);
}
if (fd < 0) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "invalid file descriptor");
}
int fd = getFileDescriptor(env, fileDescriptor);
if (fd < 0) {
LOGE(LOG_TAG, "invalid file descriptor!");
jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
return;
}
process_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed");
process_retriever_call(env, retriever->setDataSource(fd, offset, length),
"java/lang/RuntimeException", "setDataSource failed");
}
static void native_set_surface(JNIEnv *env, jclass thiz, jobject surface)
RETRIEVER_FUNC(void, native_set_surface, jobject surface)
{
MediaRetriever* retriever = getRetriever(env, thiz);
if (retriever == nullptr) {
jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
return;
}
theNativeWindow = ANativeWindow_fromSurface(env, surface);
if (theNativeWindow != nullptr) {
retriever->setNativeWindow(theNativeWindow);
}
}
static jobject native_extract_metadata(JNIEnv *env, jobject thiz, jstring jkey)
RETRIEVER_FUNC(jobject, native_extract_metadata, jstring jkey)
{
MediaRetriever* retriever = getRetriever(env, thiz);
if (retriever == nullptr) {
@ -210,7 +198,7 @@ static jobject native_extract_metadata(JNIEnv *env, jobject thiz, jstring jkey)
return NewStringUTF(env, value);
}
static jbyteArray native_get_frameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
RETRIEVER_FUNC(jbyteArray, native_get_frameAtTime, jlong timeUs, jint option)
{
MediaRetriever* retriever = getRetriever(env, thiz);
if (retriever == nullptr) {
@ -227,7 +215,7 @@ static jbyteArray native_get_frameAtTime(JNIEnv *env, jobject thiz, jlong timeUs
uint8_t* data = packet.data;
array = env->NewByteArray(size);
if (!array) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "getFrameAtTime: OutOfMemoryError is thrown.");
LOGE(LOG_TAG, "getFrameAtTime: OutOfMemoryError is thrown.");
} else {
jbyte* bytes = env->GetByteArrayElements(array, nullptr);
if (bytes != nullptr) {
@ -242,8 +230,7 @@ static jbyteArray native_get_frameAtTime(JNIEnv *env, jobject thiz, jlong timeUs
return array;
}
static jbyteArray native_get_scaleFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option,
jint width, jint height)
RETRIEVER_FUNC(jbyteArray, native_get_scaleFrameAtTime, jlong timeUs, jint option, jint width, jint height)
{
MediaRetriever* retriever = getRetriever(env, thiz);
if (retriever == nullptr) {
@ -260,7 +247,7 @@ static jbyteArray native_get_scaleFrameAtTime(JNIEnv *env, jobject thiz, jlong t
uint8_t* data = packet.data;
array = env->NewByteArray(size);
if (!array) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "getFrameAtTime: OutOfMemoryError is thrown.");
LOGE(LOG_TAG, "getFrameAtTime: OutOfMemoryError is thrown.");
} else {
jbyte* bytes = env->GetByteArrayElements(array, nullptr);
if (bytes != nullptr) {
@ -275,7 +262,7 @@ static jbyteArray native_get_scaleFrameAtTime(JNIEnv *env, jobject thiz, jlong t
return array;
}
static void native_release(JNIEnv *env, jobject thiz)
RETRIEVER_FUNC(void, native_release)
{
MediaRetriever* retriever = getRetriever(env, thiz);
delete retriever;

Loading…
Cancel
Save