FFmpegKit Android API 5.1
ffmpegkit.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018-2021 Taner Sener
3 *
4 * This file is part of FFmpegKit.
5 *
6 * FFmpegKit is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * FFmpegKit is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <pthread.h>
21#include <stdatomic.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24
25#include "config.h"
26#include "libavcodec/jni.h"
27#include "libavutil/bprint.h"
28#include "libavutil/file.h"
29#include "fftools_ffmpeg.h"
30#include "ffmpegkit.h"
31#include "ffprobekit.h"
32
33# define LogType 1
34# define StatisticsType 2
35
38 int type; // 1 (log callback) or 2 (statistics callback)
39 long sessionId; // session identifier
40
41 int logLevel; // log level
42 AVBPrint logData; // log data
43
44 int statisticsFrameNumber; // statistics frame number
45 float statisticsFps; // statistics fps
46 float statisticsQuality; // statistics quality
47 int64_t statisticsSize; // statistics size
48 int statisticsTime; // statistics time
49 double statisticsBitrate; // statistics bitrate
50 double statisticsSpeed; // statistics speed
51
53};
54
56#define SESSION_MAP_SIZE 1000
57static atomic_short sessionMap[SESSION_MAP_SIZE];
59
61static pthread_mutex_t lockMutex;
62static pthread_mutex_t monitorMutex;
63static pthread_cond_t monitorCondition;
64
67
70
72static JavaVM *globalVm;
73
75static jclass configClass;
76
78static jmethodID logMethod;
79
81static jmethodID statisticsMethod;
82
84static jmethodID safOpenMethod;
85
87static jmethodID safCloseMethod;
88
90static jclass stringClass;
91
93static jmethodID stringConstructor;
94
96const char *configClassName = "com/arthenica/ffmpegkit/FFmpegKitConfig";
97
99const char *stringClassName = "java/lang/String";
100
102volatile int handleSIGQUIT = 1;
103volatile int handleSIGINT = 1;
104volatile int handleSIGTERM = 1;
105volatile int handleSIGXCPU = 1;
106volatile int handleSIGPIPE = 1;
107
109__thread long globalSessionId = 0;
110
112int configuredLogLevel = AV_LOG_INFO;
113
115JNINativeMethod configMethods[] = {
116 {"enableNativeRedirection", "()V", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_enableNativeRedirection},
117 {"disableNativeRedirection", "()V", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_disableNativeRedirection},
118 {"setNativeLogLevel", "(I)V", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeLogLevel},
119 {"getNativeLogLevel", "()I", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeLogLevel},
120 {"getNativeFFmpegVersion", "()Ljava/lang/String;", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeFFmpegVersion},
121 {"getNativeVersion", "()Ljava/lang/String;", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeVersion},
122 {"nativeFFmpegExecute", "(J[Ljava/lang/String;)I", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegExecute},
123 {"nativeFFmpegCancel", "(J)V", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegCancel},
124 {"nativeFFprobeExecute", "(J[Ljava/lang/String;)I", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprobeExecute},
125 {"registerNewNativeFFmpegPipe", "(Ljava/lang/String;)I", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_registerNewNativeFFmpegPipe},
126 {"getNativeBuildDate", "()Ljava/lang/String;", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeBuildDate},
127 {"setNativeEnvironmentVariable", "(Ljava/lang/String;Ljava/lang/String;)I", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeEnvironmentVariable},
128 {"ignoreNativeSignal", "(I)V", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_ignoreNativeSignal},
129 {"messagesInTransmit", "(J)I", (void*) Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit}
130};
131
133int ffmpeg_execute(int argc, char **argv);
134
135static const char *avutil_log_get_level_str(int level) {
136 switch (level) {
137 case AV_LOG_STDERR:
138 return "stderr";
139 case AV_LOG_QUIET:
140 return "quiet";
141 case AV_LOG_DEBUG:
142 return "debug";
143 case AV_LOG_VERBOSE:
144 return "verbose";
145 case AV_LOG_INFO:
146 return "info";
147 case AV_LOG_WARNING:
148 return "warning";
149 case AV_LOG_ERROR:
150 return "error";
151 case AV_LOG_FATAL:
152 return "fatal";
153 case AV_LOG_PANIC:
154 return "panic";
155 default:
156 return "";
157 }
158}
159
160static void avutil_log_format_line(void *avcl, int level, const char *fmt, va_list vl, AVBPrint part[4], int *print_prefix) {
161 int flags = av_log_get_flags();
162 AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
163 av_bprint_init(part+0, 0, 1);
164 av_bprint_init(part+1, 0, 1);
165 av_bprint_init(part+2, 0, 1);
166 av_bprint_init(part+3, 0, 65536);
167
168 if (*print_prefix && avc) {
169 if (avc->parent_log_context_offset) {
170 AVClass** parent = *(AVClass ***) (((uint8_t *) avcl) +
171 avc->parent_log_context_offset);
172 if (parent && *parent) {
173 av_bprintf(part+0, "[%s @ %p] ",
174 (*parent)->item_name(parent), parent);
175 }
176 }
177 av_bprintf(part+1, "[%s @ %p] ",
178 avc->item_name(avcl), avcl);
179 }
180
181 if (*print_prefix && (level > AV_LOG_QUIET) && (flags & AV_LOG_PRINT_LEVEL))
182 av_bprintf(part+2, "[%s] ", avutil_log_get_level_str(level));
183
184 av_vbprintf(part+3, fmt, vl);
185
186 if(*part[0].str || *part[1].str || *part[2].str || *part[3].str) {
187 char lastc = part[3].len && part[3].len <= part[3].size ? part[3].str[part[3].len - 1] : 0;
188 *print_prefix = lastc == '\n' || lastc == '\r';
189 }
190}
191
192static void avutil_log_sanitize(uint8_t *line) {
193 while(*line){
194 if(*line < 0x08 || (*line > 0x0D && *line < 0x20))
195 *line='?';
196 line++;
197 }
198}
199
200void mutexInit() {
201 pthread_mutexattr_t attributes;
202 pthread_mutexattr_init(&attributes);
203 pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE_NP);
204
205 pthread_mutex_init(&lockMutex, &attributes);
206 pthread_mutexattr_destroy(&attributes);
207}
208
210 pthread_mutexattr_t attributes;
211 pthread_mutexattr_init(&attributes);
212 pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE_NP);
213
214 pthread_condattr_t cattributes;
215 pthread_condattr_init(&cattributes);
216 pthread_condattr_setpshared(&cattributes, PTHREAD_PROCESS_PRIVATE);
217
218 pthread_mutex_init(&monitorMutex, &attributes);
219 pthread_mutexattr_destroy(&attributes);
220
221 pthread_cond_init(&monitorCondition, &cattributes);
222 pthread_condattr_destroy(&cattributes);
223}
224
226 pthread_mutex_destroy(&lockMutex);
227}
228
230 pthread_mutex_destroy(&monitorMutex);
231 pthread_cond_destroy(&monitorCondition);
232}
233
234void mutexLock() {
236}
237
240}
241
242void monitorWait(int milliSeconds) {
243 struct timeval tp;
244 struct timespec ts;
245 int rc;
246
247 rc = gettimeofday(&tp, NULL);
248 if (rc) {
249 return;
250 }
251
252 ts.tv_sec = tp.tv_sec;
253 ts.tv_nsec = tp.tv_usec * 1000;
254 ts.tv_sec += milliSeconds / 1000;
255 ts.tv_nsec += (milliSeconds % 1000)*1000000;
256 ts.tv_sec += ts.tv_nsec / 1000000000L;
257 ts.tv_nsec = ts.tv_nsec % 1000000000L;
258
260 pthread_cond_timedwait(&monitorCondition, &monitorMutex, &ts);
262}
263
266 pthread_cond_signal(&monitorCondition);
268}
269
276void logCallbackDataAdd(int level, AVBPrint *data) {
277
278 // CREATE DATA STRUCT FIRST
279 struct CallbackData *newData = (struct CallbackData*)av_malloc(sizeof(struct CallbackData));
280 newData->type = LogType;
281 newData->sessionId = globalSessionId;
282 newData->logLevel = level;
283 av_bprint_init(&newData->logData, 0, AV_BPRINT_SIZE_UNLIMITED);
284 av_bprintf(&newData->logData, "%s", data->str);
285 newData->next = NULL;
286
287 mutexLock();
288
289 // INSERT IT TO THE END OF QUEUE
290 if (callbackDataTail == NULL) {
291 callbackDataTail = newData;
292
293 if (callbackDataHead != NULL) {
294 LOGE("Dangling callback data head detected. This can cause memory leak.");
295 } else {
296 callbackDataHead = newData;
297 }
298 } else {
299 struct CallbackData *oldTail = callbackDataTail;
300 oldTail->next = newData;
301
302 callbackDataTail = newData;
303 }
304
305 mutexUnlock();
306
308
310}
311
315void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed) {
316
317 // CREATE DATA STRUCT FIRST
318 struct CallbackData *newData = (struct CallbackData*)av_malloc(sizeof(struct CallbackData));
319 newData->type = StatisticsType;
320 newData->sessionId = globalSessionId;
321 newData->statisticsFrameNumber = frameNumber;
322 newData->statisticsFps = fps;
323 newData->statisticsQuality = quality;
324 newData->statisticsSize = size;
325 newData->statisticsTime = time;
326 newData->statisticsBitrate = bitrate;
327 newData->statisticsSpeed = speed;
328
329 newData->next = NULL;
330
331 mutexLock();
332
333 // INSERT IT TO THE END OF QUEUE
334 if (callbackDataTail == NULL) {
335 callbackDataTail = newData;
336
337 if (callbackDataHead != NULL) {
338 LOGE("Dangling callback data head detected. This can cause memory leak.");
339 } else {
340 callbackDataHead = newData;
341 }
342 } else {
343 struct CallbackData *oldTail = callbackDataTail;
344 oldTail->next = newData;
345
346 callbackDataTail = newData;
347 }
348
349 mutexUnlock();
350
352
354}
355
361void addSession(long id) {
362 atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 1);
363}
364
369 struct CallbackData *currentData;
370
371 mutexLock();
372
373 if (callbackDataHead == NULL) {
374 currentData = NULL;
375 } else {
376 currentData = callbackDataHead;
377
378 struct CallbackData *nextHead = currentData->next;
379 if (nextHead == NULL) {
381 LOGE("Head and tail callback data pointers do not match for single callback data element. This can cause memory leak.");
382 } else {
383 callbackDataTail = NULL;
384 }
385 callbackDataHead = NULL;
386
387 } else {
388 callbackDataHead = nextHead;
389 }
390 }
391
392 mutexUnlock();
393
394 return currentData;
395}
396
402void removeSession(long id) {
403 atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 0);
404}
405
411void cancelSession(long id) {
412 atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 2);
413}
414
421int cancelRequested(long id) {
422 if (atomic_load(&sessionMap[id % SESSION_MAP_SIZE]) == 2) {
423 return 1;
424 } else {
425 return 0;
426 }
427}
428
436}
437
446void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, va_list vargs) {
447 AVBPrint fullLine;
448 AVBPrint part[4];
449 int print_prefix = 1;
450
451 if (level >= 0) {
452 level &= 0xff;
453 }
454 int activeLogLevel = av_log_get_level();
455
456 // AV_LOG_STDERR logs are always redirected
457 if ((activeLogLevel == AV_LOG_QUIET && level != AV_LOG_STDERR) || (level > activeLogLevel)) {
458 return;
459 }
460
461 av_bprint_init(&fullLine, 0, AV_BPRINT_SIZE_UNLIMITED);
462
463 avutil_log_format_line(ptr, level, format, vargs, part, &print_prefix);
464 avutil_log_sanitize(part[0].str);
465 avutil_log_sanitize(part[1].str);
466 avutil_log_sanitize(part[2].str);
467 avutil_log_sanitize(part[3].str);
468
469 // COMBINE ALL 4 LOG PARTS
470 av_bprintf(&fullLine, "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str);
471
472 if (fullLine.len > 0) {
473 logCallbackDataAdd(level, &fullLine);
474 }
475
476 av_bprint_finalize(part, NULL);
477 av_bprint_finalize(part+1, NULL);
478 av_bprint_finalize(part+2, NULL);
479 av_bprint_finalize(part+3, NULL);
480 av_bprint_finalize(&fullLine, NULL);
481}
482
494void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed) {
495 statisticsCallbackDataAdd(frameNumber, fps, quality, size, time, bitrate, speed);
496}
497
502 JNIEnv *env;
503 jint getEnvRc = (*globalVm)->GetEnv(globalVm, (void**) &env, JNI_VERSION_1_6);
504 if (getEnvRc != JNI_OK) {
505 if (getEnvRc != JNI_EDETACHED) {
506 LOGE("Callback thread failed to GetEnv for class %s with rc %d.\n", configClassName, getEnvRc);
507 return NULL;
508 }
509
510 if ((*globalVm)->AttachCurrentThread(globalVm, &env, NULL) != 0) {
511 LOGE("Callback thread failed to AttachCurrentThread for class %s.\n", configClassName);
512 return NULL;
513 }
514 }
515
516 LOGD("Async callback block started.\n");
517
518 while(redirectionEnabled) {
519
520 struct CallbackData *callbackData = callbackDataRemove();
521 if (callbackData != NULL) {
522 if (callbackData->type == LogType) {
523
524 // LOG CALLBACK
525
526 int size = callbackData->logData.len;
527
528 jbyteArray byteArray = (jbyteArray) (*env)->NewByteArray(env, size);
529 (*env)->SetByteArrayRegion(env, byteArray, 0, size, callbackData->logData.str);
530 (*env)->CallStaticVoidMethod(env, configClass, logMethod, (jlong) callbackData->sessionId, callbackData->logLevel, byteArray);
531 (*env)->DeleteLocalRef(env, byteArray);
532
533 // CLEAN LOG DATA
534 av_bprint_finalize(&callbackData->logData, NULL);
535
536 } else {
537
538 // STATISTICS CALLBACK
539
540 (*env)->CallStaticVoidMethod(env, configClass, statisticsMethod,
541 (jlong) callbackData->sessionId, callbackData->statisticsFrameNumber,
542 callbackData->statisticsFps, callbackData->statisticsQuality,
543 callbackData->statisticsSize, callbackData->statisticsTime,
544 callbackData->statisticsBitrate, callbackData->statisticsSpeed);
545
546 }
547
548 atomic_fetch_sub(&sessionInTransitMessageCountMap[callbackData->sessionId % SESSION_MAP_SIZE], 1);
549
550 // CLEAN STRUCT
551 callbackData->next = NULL;
552 av_free(callbackData);
553
554 } else {
555 monitorWait(100);
556 }
557 }
558
559 (*globalVm)->DetachCurrentThread(globalVm);
560
561 LOGD("Async callback block stopped.\n");
562
563 return NULL;
564}
565
569int saf_open(int safId) {
570 JNIEnv *env = NULL;
571 (*globalVm)->GetEnv(globalVm, (void**) &env, JNI_VERSION_1_6);
572 return (*env)->CallStaticIntMethod(env, configClass, safOpenMethod, safId);
573}
574
578int saf_close(int fd) {
579 JNIEnv *env = NULL;
580 (*globalVm)->GetEnv(globalVm, (void**) &env, JNI_VERSION_1_6);
581 return (*env)->CallStaticIntMethod(env, configClass, safCloseMethod, fd);
582}
583
591jint JNI_OnLoad(JavaVM *vm, void *reserved) {
592 JNIEnv *env;
593 if ((*vm)->GetEnv(vm, (void**)(&env), JNI_VERSION_1_6) != JNI_OK) {
594 LOGE("OnLoad failed to GetEnv for class %s.\n", configClassName);
595 return JNI_FALSE;
596 }
597
598 jclass localConfigClass = (*env)->FindClass(env, configClassName);
599 if (localConfigClass == NULL) {
600 LOGE("OnLoad failed to FindClass %s.\n", configClassName);
601 return JNI_FALSE;
602 }
603
604 if ((*env)->RegisterNatives(env, localConfigClass, configMethods, 14) < 0) {
605 LOGE("OnLoad failed to RegisterNatives for class %s.\n", configClassName);
606 return JNI_FALSE;
607 }
608
609 jclass localStringClass = (*env)->FindClass(env, stringClassName);
610 if (localStringClass == NULL) {
611 LOGE("OnLoad failed to FindClass %s.\n", stringClassName);
612 return JNI_FALSE;
613 }
614
615 (*env)->GetJavaVM(env, &globalVm);
616
617 logMethod = (*env)->GetStaticMethodID(env, localConfigClass, "log", "(JI[B)V");
618 if (logMethod == NULL) {
619 LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "log");
620 return JNI_FALSE;
621 }
622
623 statisticsMethod = (*env)->GetStaticMethodID(env, localConfigClass, "statistics", "(JIFFJIDD)V");
624 if (statisticsMethod == NULL) {
625 LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "statistics");
626 return JNI_FALSE;
627 }
628
629 safOpenMethod = (*env)->GetStaticMethodID(env, localConfigClass, "safOpen", "(I)I");
630 if (safOpenMethod == NULL) {
631 LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "safOpen");
632 return JNI_FALSE;
633 }
634
635 safCloseMethod = (*env)->GetStaticMethodID(env, localConfigClass, "safClose", "(I)I");
636 if (safCloseMethod == NULL) {
637 LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "safClose");
638 return JNI_FALSE;
639 }
640
641 stringConstructor = (*env)->GetMethodID(env, localStringClass, "<init>", "([BLjava/lang/String;)V");
642 if (stringConstructor == NULL) {
643 LOGE("OnLoad thread failed to GetMethodID for %s.\n", "<init>");
644 return JNI_FALSE;
645 }
646
647 av_jni_set_java_vm(vm, NULL);
648
649 configClass = (jclass) ((*env)->NewGlobalRef(env, localConfigClass));
650 stringClass = (jclass) ((*env)->NewGlobalRef(env, localStringClass));
651
652 callbackDataHead = NULL;
653 callbackDataTail = NULL;
654
655 for(int i = 0; i<SESSION_MAP_SIZE; i++) {
656 atomic_init(&sessionMap[i], 0);
657 atomic_init(&sessionInTransitMessageCountMap[i], 0);
658 }
659
660 mutexInit();
661 monitorInit();
662
664
665 av_set_saf_open(saf_open);
666 av_set_saf_close(saf_close);
667
668 return JNI_VERSION_1_6;
669}
670
678JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeLogLevel(JNIEnv *env, jclass object, jint level) {
679 configuredLogLevel = level;
680}
681
688JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeLogLevel(JNIEnv *env, jclass object) {
689 return configuredLogLevel;
690}
691
698JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_enableNativeRedirection(JNIEnv *env, jclass object) {
699 mutexLock();
700
701 if (redirectionEnabled != 0) {
702 mutexUnlock();
703 return;
704 }
706
707 mutexUnlock();
708
709 int rc = pthread_create(&callbackThread, 0, callbackThreadFunction, 0);
710 if (rc != 0) {
711 LOGE("Failed to create callback thread (rc=%d).\n", rc);
712 return;
713 }
714
715 av_log_set_callback(ffmpegkit_log_callback_function);
717}
718
725JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_disableNativeRedirection(JNIEnv *env, jclass object) {
726
727 mutexLock();
728
729 if (redirectionEnabled != 1) {
730 mutexUnlock();
731 return;
732 }
734
735 mutexUnlock();
736
737 av_log_set_callback(av_log_default_callback);
739
741}
742
750JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeFFmpegVersion(JNIEnv *env, jclass object) {
751 return (*env)->NewStringUTF(env, FFMPEG_VERSION);
752}
753
761JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeVersion(JNIEnv *env, jclass object) {
762 return (*env)->NewStringUTF(env, FFMPEG_KIT_VERSION);
763}
764
774JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegExecute(JNIEnv *env, jclass object, jlong id, jobjectArray stringArray) {
775 jstring *tempArray = NULL;
776 int argumentCount = 1;
777 char **argv = NULL;
778
779 // SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW RUN
780 av_log_set_level(configuredLogLevel);
781
782 if (stringArray) {
783 int programArgumentCount = (*env)->GetArrayLength(env, stringArray);
784 argumentCount = programArgumentCount + 1;
785
786 tempArray = (jstring *) av_malloc(sizeof(jstring) * programArgumentCount);
787 }
788
789 /* PRESERVE USAGE FORMAT
790 *
791 * ffmpeg <arguments>
792 */
793 argv = (char **)av_malloc(sizeof(char*) * (argumentCount));
794 argv[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
795 strcpy(argv[0], LIB_NAME);
796
797 // PREPARE ARRAY ELEMENTS
798 if (stringArray) {
799 for (int i = 0; i < (argumentCount - 1); i++) {
800 tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
801 if (tempArray[i] != NULL) {
802 argv[i + 1] = (char *) (*env)->GetStringUTFChars(env, tempArray[i], 0);
803 }
804 }
805 }
806
807 // REGISTER THE ID BEFORE STARTING THE SESSION
808 globalSessionId = (long) id;
809 addSession((long) id);
810
812
813 // RUN
814 int returnCode = ffmpeg_execute(argumentCount, argv);
815
816 // ALWAYS REMOVE THE ID FROM THE MAP
817 removeSession((long) id);
818
819 // CLEANUP
820 if (tempArray) {
821 for (int i = 0; i < (argumentCount - 1); i++) {
822 (*env)->ReleaseStringUTFChars(env, tempArray[i], argv[i + 1]);
823 }
824
825 av_free(tempArray);
826 }
827 av_free(argv[0]);
828 av_free(argv);
829
830 return returnCode;
831}
832
840JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegCancel(JNIEnv *env, jclass object, jlong id) {
842}
843
852JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_registerNewNativeFFmpegPipe(JNIEnv *env, jclass object, jstring ffmpegPipePath) {
853 const char *ffmpegPipePathString = (*env)->GetStringUTFChars(env, ffmpegPipePath, 0);
854
855 return mkfifo(ffmpegPipePathString, S_IRWXU | S_IRWXG | S_IROTH);
856}
857
865JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeBuildDate(JNIEnv *env, jclass object) {
866 char buildDate[10];
867 sprintf(buildDate, "%d", FFMPEG_KIT_BUILD_DATE);
868 return (*env)->NewStringUTF(env, buildDate);
869}
870
880JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeEnvironmentVariable(JNIEnv *env, jclass object, jstring variableName, jstring variableValue) {
881 const char *variableNameString = (*env)->GetStringUTFChars(env, variableName, 0);
882 const char *variableValueString = (*env)->GetStringUTFChars(env, variableValue, 0);
883
884 int rc = setenv(variableNameString, variableValueString, 1);
885
886 (*env)->ReleaseStringUTFChars(env, variableName, variableNameString);
887 (*env)->ReleaseStringUTFChars(env, variableValue, variableValueString);
888 return rc;
889}
890
898JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_ignoreNativeSignal(JNIEnv *env, jclass object, jint signum) {
899 if (signum == SIGQUIT) {
900 handleSIGQUIT = 0;
901 } else if (signum == SIGINT) {
902 handleSIGINT = 0;
903 } else if (signum == SIGTERM) {
904 handleSIGTERM = 0;
905 } else if (signum == SIGXCPU) {
906 handleSIGXCPU = 0;
907 } else if (signum == SIGPIPE) {
908 handleSIGPIPE = 0;
909 }
910}
911
920JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit(JNIEnv *env, jclass object, jlong id) {
921 return atomic_load(&sessionInTransitMessageCountMap[id % SESSION_MAP_SIZE]);
922}
void monitorUnInit()
Definition: ffmpegkit.c:229
JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeBuildDate(JNIEnv *env, jclass object)
Definition: ffmpegkit.c:865
void ffmpegkit_log_callback_function(void *ptr, int level, const char *format, va_list vargs)
Definition: ffmpegkit.c:446
static atomic_short sessionMap[SESSION_MAP_SIZE]
Definition: ffmpegkit.c:57
static jclass stringClass
Definition: ffmpegkit.c:90
static pthread_mutex_t lockMutex
Definition: ffmpegkit.c:61
struct CallbackData * callbackDataRemove()
Definition: ffmpegkit.c:368
#define SESSION_MAP_SIZE
Definition: ffmpegkit.c:56
struct CallbackData * callbackDataTail
Definition: ffmpegkit.c:69
void addSession(long id)
Definition: ffmpegkit.c:361
JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegExecute(JNIEnv *env, jclass object, jlong id, jobjectArray stringArray)
Definition: ffmpegkit.c:774
void monitorNotify()
Definition: ffmpegkit.c:264
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_enableNativeRedirection(JNIEnv *env, jclass object)
Definition: ffmpegkit.c:698
static void avutil_log_sanitize(uint8_t *line)
Definition: ffmpegkit.c:192
volatile int handleSIGINT
Definition: ffmpegkit.c:103
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeLogLevel(JNIEnv *env, jclass object, jint level)
Definition: ffmpegkit.c:678
volatile int handleSIGTERM
Definition: ffmpegkit.c:104
int saf_close(int fd)
Definition: ffmpegkit.c:578
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegCancel(JNIEnv *env, jclass object, jlong id)
Definition: ffmpegkit.c:840
const char * configClassName
Definition: ffmpegkit.c:96
JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeLogLevel(JNIEnv *env, jclass object)
Definition: ffmpegkit.c:688
static const char * avutil_log_get_level_str(int level)
Definition: ffmpegkit.c:135
void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed)
Definition: ffmpegkit.c:494
static void avutil_log_format_line(void *avcl, int level, const char *fmt, va_list vl, AVBPrint part[4], int *print_prefix)
Definition: ffmpegkit.c:160
JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeFFmpegVersion(JNIEnv *env, jclass object)
Definition: ffmpegkit.c:750
void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_t size, int time, double bitrate, double speed)
Definition: ffmpegkit.c:315
const char * stringClassName
Definition: ffmpegkit.c:99
JNINativeMethod configMethods[]
Definition: ffmpegkit.c:115
void monitorWait(int milliSeconds)
Definition: ffmpegkit.c:242
static JavaVM * globalVm
Definition: ffmpegkit.c:72
struct CallbackData * callbackDataHead
Definition: ffmpegkit.c:68
pthread_t callbackThread
Definition: ffmpegkit.c:65
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_ignoreNativeSignal(JNIEnv *env, jclass object, jint signum)
Definition: ffmpegkit.c:898
static pthread_cond_t monitorCondition
Definition: ffmpegkit.c:63
JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeVersion(JNIEnv *env, jclass object)
Definition: ffmpegkit.c:761
void monitorInit()
Definition: ffmpegkit.c:209
void cancelSession(long id)
Definition: ffmpegkit.c:411
int saf_open(int safId)
Definition: ffmpegkit.c:569
__thread long globalSessionId
Definition: ffmpegkit.c:109
int redirectionEnabled
Definition: ffmpegkit.c:66
int cancelRequested(long id)
Definition: ffmpegkit.c:421
void mutexUnlock()
Definition: ffmpegkit.c:238
JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_registerNewNativeFFmpegPipe(JNIEnv *env, jclass object, jstring ffmpegPipePath)
Definition: ffmpegkit.c:852
static jmethodID safOpenMethod
Definition: ffmpegkit.c:84
void mutexUnInit()
Definition: ffmpegkit.c:225
#define LogType
Definition: ffmpegkit.c:33
void * callbackThreadFunction()
Definition: ffmpegkit.c:501
volatile int handleSIGPIPE
Definition: ffmpegkit.c:106
static pthread_mutex_t monitorMutex
Definition: ffmpegkit.c:62
jint JNI_OnLoad(JavaVM *vm, void *reserved)
Definition: ffmpegkit.c:591
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_disableNativeRedirection(JNIEnv *env, jclass object)
Definition: ffmpegkit.c:725
static jmethodID logMethod
Definition: ffmpegkit.c:78
volatile int handleSIGXCPU
Definition: ffmpegkit.c:105
static jmethodID safCloseMethod
Definition: ffmpegkit.c:87
void resetMessagesInTransmit(long id)
Definition: ffmpegkit.c:434
static jclass configClass
Definition: ffmpegkit.c:75
static atomic_int sessionInTransitMessageCountMap[SESSION_MAP_SIZE]
Definition: ffmpegkit.c:58
JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeEnvironmentVariable(JNIEnv *env, jclass object, jstring variableName, jstring variableValue)
Definition: ffmpegkit.c:880
void mutexLock()
Definition: ffmpegkit.c:234
void mutexInit()
Definition: ffmpegkit.c:200
int configuredLogLevel
Definition: ffmpegkit.c:112
#define StatisticsType
Definition: ffmpegkit.c:34
int ffmpeg_execute(int argc, char **argv)
static jmethodID stringConstructor
Definition: ffmpegkit.c:93
JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit(JNIEnv *env, jclass object, jlong id)
Definition: ffmpegkit.c:920
static jmethodID statisticsMethod
Definition: ffmpegkit.c:81
volatile int handleSIGQUIT
Definition: ffmpegkit.c:102
void logCallbackDataAdd(int level, AVBPrint *data)
Definition: ffmpegkit.c:276
void removeSession(long id)
Definition: ffmpegkit.c:402
#define FFMPEG_KIT_VERSION
Definition: ffmpegkit.h:30
#define LIB_NAME
Definition: ffmpegkit.h:33
#define LOGD(...)
Definition: ffmpegkit.h:39
#define LOGE(...)
Definition: ffmpegkit.h:48
JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprobeExecute(JNIEnv *env, jclass object, jlong id, jobjectArray stringArray)
Definition: ffprobekit.c:48
#define AV_LOG_STDERR
void set_report_callback(void(*callback)(int, float, float, int64_t, int, double, double))
void cancel_operation(long id)
#define pthread_mutex_lock(a)
#define pthread_mutex_unlock(a)
int logLevel
Definition: ffmpegkit.c:41
double statisticsBitrate
Definition: ffmpegkit.c:49
float statisticsQuality
Definition: ffmpegkit.c:46
struct CallbackData * next
Definition: ffmpegkit.c:52
double statisticsSpeed
Definition: ffmpegkit.c:50
int statisticsFrameNumber
Definition: ffmpegkit.c:44
int statisticsTime
Definition: ffmpegkit.c:48
float statisticsFps
Definition: ffmpegkit.c:45
long sessionId
Definition: ffmpegkit.c:39
AVBPrint logData
Definition: ffmpegkit.c:42
int64_t statisticsSize
Definition: ffmpegkit.c:47