[Libav-user] variable scope into callback av_log_set_callback and multi threading

Algarve Branqueira branqueira at gmail.com
Thu Mar 24 20:53:30 EET 2022

I never said the opposite.
I listened to your advice, you are right. there was never any question of
having a logging instance for each thread, but the object makes it possible
to have a link between the threads.

the logging is not based on an instance but on a static class.

I have nothing to hide, I show you my code, as you can see, there is never
any mention of an object in the code.

the question is just how to call code at the end of ffmpeg's worker thread.

because in the code in c to call java it is necessary.

1/ attach the c thread to the java thread
                 *res =(*javaVM)->AttachCurrentThreadAsDaemon(javaVM,
(void**)&jniEnv, NULL);  *
2/ make your code, your blah blah

3/ at the closure of the thread in c, detach the java thread


don't see evil everywhere, I asked a question, I heard your advice, I
followed it


*#include <jni.h>#include <libavdevice/avdevice.h>#include
<pthread.h>#define LOGGER_CLASS "fr/ms/ffmpeg/FFMPEG_LOG"#define
THREAD_FFMPEG_WORKER "FFMPEG-Worker-%i"JavaVM *javaVM;__thread JNIEnv
*jniEnv;jclass clazzLogger;jmethodID jMethodGetLogLevel;jmethodID
jMethodGetLogLevelValue;jmethodID callLoggerMethod;int compteur = 0;int
init_JNI() { if (jniEnv == NULL) { int res = (*javaVM)->GetEnv(javaVM,
(void**)&jniEnv, JNI_VERSION_1_8); if (res == JNI_EDETACHED) {
JavaVMAttachArgs args; args.version = JNI_VERSION_1_8; args.name
<http://args.name> = malloc(128); sprintf(args.name <http://args.name>,
THREAD_FFMPEG_WORKER, compteur); res
=(*javaVM)->AttachCurrentThreadAsDaemon(javaVM, (void**)&jniEnv, NULL); if
(res != JNI_OK) { return res; } compteur++; } } return JNI_OK;}void
wrapper_logger(void *ptr, int level, const char* fmt, va_list vl){ if
(init_JNI() != JNI_OK) { return; } jobject enumObjLogLevel =
(*jniEnv)->CallStaticObjectMethod(jniEnv, clazzLogger, jMethodGetLogLevel);
if ((*jniEnv)->ExceptionOccurred(jniEnv)) {
(*jniEnv)->ExceptionClear(jniEnv); (*jniEnv)->DeleteLocalRef(jniEnv,
enumObjLogLevel); return; } int av_level = (int)
(*jniEnv)->CallIntMethod(jniEnv, enumObjLogLevel, jMethodGetLogLevelValue);
(*jniEnv)->DeleteLocalRef(jniEnv, enumObjLogLevel); if
((*jniEnv)->ExceptionOccurred(jniEnv)) { (*jniEnv)->ExceptionClear(jniEnv);
return; } if (level > av_level) return; char buffer[1024]; int res =
vsprintf(buffer, fmt, vl); if (res < 0) return; jstring jstr =
(*jniEnv)->NewStringUTF(jniEnv, buffer); if (jstr != NULL) {
(*jniEnv)->CallStaticVoidMethod(jniEnv, clazzLogger, callLoggerMethod,
level, jstr); (*jniEnv)->DeleteLocalRef(jniEnv, jstr); if
((*jniEnv)->ExceptionOccurred(jniEnv)) { (*jniEnv)->ExceptionClear(jniEnv);
return; } }}int init_logger() { clazzLogger = (*jniEnv)->FindClass(jniEnv,
LOGGER_CLASS); clazzLogger = (*jniEnv)->NewGlobalRef(jniEnv,clazzLogger);
jMethodGetLogLevel = (*jniEnv)->GetStaticMethodID(jniEnv, clazzLogger,
"getLogLevel", "()Lfr/ms/ffmpeg/FFMPEG_AV_LOG;"); jobject enumObjLogLevel =
(*jniEnv)->CallStaticObjectMethod(jniEnv, clazzLogger, jMethodGetLogLevel);
jthrowable exc = (*jniEnv)->ExceptionOccurred(jniEnv); if (exc) {
(*jniEnv)->ExceptionClear(jniEnv); return -1; } jclass enumClass =
(*jniEnv)->GetObjectClass(jniEnv, enumObjLogLevel); jMethodGetLogLevelValue
= (*jniEnv)->GetMethodID(jniEnv, enumClass, "getValue", "()I"); int
av_level = (int) (*jniEnv)->CallIntMethod(jniEnv, enumObjLogLevel,
jMethodGetLogLevelValue); exc = (*jniEnv)->ExceptionOccurred(jniEnv); if
(exc) { (*jniEnv)->ExceptionClear(jniEnv); return -1; } callLoggerMethod =
(*jniEnv)->GetStaticMethodID(jniEnv, clazzLogger, "callLogger0",
"(ILjava/lang/String;)V"); return JNI_OK;}jint JNI_OnLoad(JavaVM *vm, void
*reserved) { javaVM = vm; if ((*vm)->GetEnv(vm, (void**)&jniEnv,
JNI_VERSION_1_8) != JNI_OK) return -1; if (init_logger() != JNI_OK) return
-1; av_log_set_callback(wrapper_logger); avdevice_register_all();
avformat_network_init(); return JNI_VERSION_1_8;}void JNI_OnUnload(JavaVM
*vm, void *reserved) { (*jniEnv)->DeleteLocalRef(jniEnv, clazzLogger);}*

Le jeu. 24 mars 2022 à 15:55, Dan Egnor <egnor at ofb.net> a écrit :

> On Thu, Mar 24, 2022, 3:59 AM Algarve Branqueira <branqueira at gmail.com>
> wrote:
>> I tried this method but it doesn't work with ffmpeg on windows with mingw.
>> I must have forgotten a few things.
>>  what disturbs me the most is that at the end of the video conversion,
>> ffmpeg kills its threads for decoding and encoding but we don't have a
>> simple solution to execute an end method.
>> I attached the jvm so I basically need to destroy the thread called a
>> simple "DetachCurrentThread" method.
>> Any idea :)
> As you know, my best idea is to rethink your life choices and not try to
> get log messages attributed to specific instances, instead treating them as
> a single global stream used for developer diagnostics. I think you're
> swimming against the flow trying to do anything else.
> But I don't think you'll find this helpful?
> -- egnor
>> _______________________________________________
> Libav-user mailing list
> Libav-user at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/libav-user
> To unsubscribe, visit link above, or email
> libav-user-request at ffmpeg.org with subject "unsubscribe".
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20220324/4cc57d2d/attachment.htm>

More information about the Libav-user mailing list