| FFmpegKit Android API 6.0

Loading...
Searching...
No Matches
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
37 struct CallbackData {
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 double statisticsTime; // statistics time
49 double statisticsBitrate; // statistics bitrate
50 double statisticsSpeed; // statistics speed
51
52 struct CallbackData *next;
53};
54
56#define SESSION_MAP_SIZE 1000
57 static atomic_short sessionMap[SESSION_MAP_SIZE];
58 static atomic_int sessionInTransitMessageCountMap[SESSION_MAP_SIZE];
59
61 static pthread_mutex_t lockMutex;
62 static pthread_mutex_t monitorMutex;
63 static pthread_cond_t monitorCondition;
64
65pthread_t callbackThread;
66 int redirectionEnabled;
67
68 struct CallbackData *callbackDataHead;
69 struct CallbackData *callbackDataTail;
70
72 static JavaVM *globalVm;
73
75 static jclass configClass;
76
78 static jmethodID logMethod;
79
81 static jmethodID statisticsMethod;
82
84 static jmethodID safOpenMethod;
85
87 static jmethodID safCloseMethod;
88
90 static jclass stringClass;
91
93 static jmethodID stringConstructor;
94
96 const char *configClassName = "com/arthenica/ffmpegkit/FFmpegKitConfig";
97
99 const char *stringClassName = "java/lang/String";
100
102 volatile int handleSIGQUIT = 1;
103 volatile int handleSIGINT = 1;
104 volatile int handleSIGTERM = 1;
105 volatile int handleSIGXCPU = 1;
106 volatile int handleSIGPIPE = 1;
107
109__thread long globalSessionId = 0;
110
112 int 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
133 int ffmpeg_execute(int argc, char **argv);
134
135 static 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
160 static 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
192 static 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
200 void 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
209 void monitorInit() {
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
225 void mutexUnInit() {
226 pthread_mutex_destroy(&lockMutex);
227}
228
229 void monitorUnInit() {
230 pthread_mutex_destroy(&monitorMutex);
231 pthread_cond_destroy(&monitorCondition);
232}
233
234 void mutexLock() {
235 pthread_mutex_lock(&lockMutex);
236}
237
238 void mutexUnlock() {
239 pthread_mutex_unlock(&lockMutex);
240}
241
242 void 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
259 pthread_mutex_lock(&monitorMutex);
260 pthread_cond_timedwait(&monitorCondition, &monitorMutex, &ts);
261 pthread_mutex_unlock(&monitorMutex);
262}
263
264 void monitorNotify() {
265 pthread_mutex_lock(&monitorMutex);
266 pthread_cond_signal(&monitorCondition);
267 pthread_mutex_unlock(&monitorMutex);
268}
269
276 void 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
307 monitorNotify();
308
309 atomic_fetch_add(&sessionInTransitMessageCountMap[globalSessionId % SESSION_MAP_SIZE], 1);
310}
311
315 void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_t size, double 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
351 monitorNotify();
352
353 atomic_fetch_add(&sessionInTransitMessageCountMap[globalSessionId % SESSION_MAP_SIZE], 1);
354}
355
361 void addSession(long id) {
362 atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 1);
363}
364
368 struct CallbackData *callbackDataRemove() {
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) {
380 if (callbackDataHead != callbackDataTail) {
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
402 void removeSession(long id) {
403 atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 0);
404}
405
411 void cancelSession(long id) {
412 atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 2);
413}
414
421 int cancelRequested(long id) {
422 if (atomic_load(&sessionMap[id % SESSION_MAP_SIZE]) == 2) {
423 return 1;
424 } else {
425 return 0;
426 }
427}
428
434 void resetMessagesInTransmit(long id) {
435 atomic_store(&sessionInTransitMessageCountMap[id % SESSION_MAP_SIZE], 0);
436}
437
446 void 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
494 void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float quality, int64_t size, double time, double bitrate, double speed) {
495 statisticsCallbackDataAdd(frameNumber, fps, quality, size, time, bitrate, speed);
496}
497
501 void *callbackThreadFunction() {
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
569 int 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
578 int 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
587 static void enableNativeRedirection() {
588 mutexLock();
589
590 if (redirectionEnabled != 0) {
591 mutexUnlock();
592 return;
593 }
594 redirectionEnabled = 1;
595
596 mutexUnlock();
597
598 int rc = pthread_create(&callbackThread, 0, callbackThreadFunction, 0);
599 if (rc != 0) {
600 LOGE("Failed to create callback thread (rc=%d).\n", rc);
601 return;
602 }
603
604 av_log_set_callback(ffmpegkit_log_callback_function);
605 set_report_callback(ffmpegkit_statistics_callback_function);
606}
607
615jint JNI_OnLoad(JavaVM *vm, void *reserved) {
616 JNIEnv *env;
617 if ((*vm)->GetEnv(vm, (void**)(&env), JNI_VERSION_1_6) != JNI_OK) {
618 LOGE("OnLoad failed to GetEnv for class %s.\n", configClassName);
619 return JNI_FALSE;
620 }
621
622 jclass localConfigClass = (*env)->FindClass(env, configClassName);
623 if (localConfigClass == NULL) {
624 LOGE("OnLoad failed to FindClass %s.\n", configClassName);
625 return JNI_FALSE;
626 }
627
628 if ((*env)->RegisterNatives(env, localConfigClass, configMethods, 14) < 0) {
629 LOGE("OnLoad failed to RegisterNatives for class %s.\n", configClassName);
630 return JNI_FALSE;
631 }
632
633 jclass localStringClass = (*env)->FindClass(env, stringClassName);
634 if (localStringClass == NULL) {
635 LOGE("OnLoad failed to FindClass %s.\n", stringClassName);
636 return JNI_FALSE;
637 }
638
639 (*env)->GetJavaVM(env, &globalVm);
640
641 logMethod = (*env)->GetStaticMethodID(env, localConfigClass, "log", "(JI[B)V");
642 if (logMethod == NULL) {
643 LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "log");
644 return JNI_FALSE;
645 }
646
647 statisticsMethod = (*env)->GetStaticMethodID(env, localConfigClass, "statistics", "(JIFFJDDD)V");
648 if (statisticsMethod == NULL) {
649 LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "statistics");
650 return JNI_FALSE;
651 }
652
653 safOpenMethod = (*env)->GetStaticMethodID(env, localConfigClass, "safOpen", "(I)I");
654 if (safOpenMethod == NULL) {
655 LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "safOpen");
656 return JNI_FALSE;
657 }
658
659 safCloseMethod = (*env)->GetStaticMethodID(env, localConfigClass, "safClose", "(I)I");
660 if (safCloseMethod == NULL) {
661 LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "safClose");
662 return JNI_FALSE;
663 }
664
665 stringConstructor = (*env)->GetMethodID(env, localStringClass, "<init>", "([BLjava/lang/String;)V");
666 if (stringConstructor == NULL) {
667 LOGE("OnLoad thread failed to GetMethodID for %s.\n", "<init>");
668 return JNI_FALSE;
669 }
670
671 av_jni_set_java_vm(vm, NULL);
672
673 configClass = (jclass) ((*env)->NewGlobalRef(env, localConfigClass));
674 stringClass = (jclass) ((*env)->NewGlobalRef(env, localStringClass));
675
676 callbackDataHead = NULL;
677 callbackDataTail = NULL;
678
679 for(int i = 0; i<SESSION_MAP_SIZE; i++) {
680 atomic_init(&sessionMap[i], 0);
681 atomic_init(&sessionInTransitMessageCountMap[i], 0);
682 }
683
684 mutexInit();
685 monitorInit();
686
687 redirectionEnabled = 0;
688
689 av_set_saf_open(saf_open);
690 av_set_saf_close(saf_close);
691
692 enableNativeRedirection();
693
694 return JNI_VERSION_1_6;
695}
696
704JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeLogLevel(JNIEnv *env, jclass object, jint level) {
705 configuredLogLevel = level;
706}
707
714JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeLogLevel(JNIEnv *env, jclass object) {
715 return configuredLogLevel;
716}
717
724JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_enableNativeRedirection(JNIEnv *env, jclass object) {
725 enableNativeRedirection();
726}
727
734JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_disableNativeRedirection(JNIEnv *env, jclass object) {
735
736 mutexLock();
737
738 if (redirectionEnabled != 1) {
739 mutexUnlock();
740 return;
741 }
742 redirectionEnabled = 0;
743
744 mutexUnlock();
745
746 av_log_set_callback(av_log_default_callback);
747 set_report_callback(NULL);
748
749 monitorNotify();
750}
751
759JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeFFmpegVersion(JNIEnv *env, jclass object) {
760 return (*env)->NewStringUTF(env, FFMPEG_VERSION);
761}
762
770JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeVersion(JNIEnv *env, jclass object) {
771 return (*env)->NewStringUTF(env, FFMPEG_KIT_VERSION);
772}
773
783JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegExecute(JNIEnv *env, jclass object, jlong id, jobjectArray stringArray) {
784 jstring *tempArray = NULL;
785 int argumentCount = 1;
786 char **argv = NULL;
787
788 // SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW RUN
789 av_log_set_level(configuredLogLevel);
790
791 if (stringArray) {
792 int programArgumentCount = (*env)->GetArrayLength(env, stringArray);
793 argumentCount = programArgumentCount + 1;
794
795 tempArray = (jstring *) av_malloc(sizeof(jstring) * programArgumentCount);
796 }
797
798 /* PRESERVE USAGE FORMAT
799 *
800 * ffmpeg <arguments>
801 */
802 argv = (char **)av_malloc(sizeof(char*) * (argumentCount));
803 argv[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
804 strcpy(argv[0], LIB_NAME);
805
806 // PREPARE ARRAY ELEMENTS
807 if (stringArray) {
808 for (int i = 0; i < (argumentCount - 1); i++) {
809 tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
810 if (tempArray[i] != NULL) {
811 argv[i + 1] = (char *) (*env)->GetStringUTFChars(env, tempArray[i], 0);
812 }
813 }
814 }
815
816 // REGISTER THE ID BEFORE STARTING THE SESSION
817 globalSessionId = (long) id;
818 addSession((long) id);
819
820 resetMessagesInTransmit(globalSessionId);
821
822 // RUN
823 int returnCode = ffmpeg_execute(argumentCount, argv);
824
825 // ALWAYS REMOVE THE ID FROM THE MAP
826 removeSession((long) id);
827
828 // CLEANUP
829 if (tempArray) {
830 for (int i = 0; i < (argumentCount - 1); i++) {
831 (*env)->ReleaseStringUTFChars(env, tempArray[i], argv[i + 1]);
832 }
833
834 av_free(tempArray);
835 }
836 av_free(argv[0]);
837 av_free(argv);
838
839 return returnCode;
840}
841
849JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegCancel(JNIEnv *env, jclass object, jlong id) {
850 cancel_operation(id);
851}
852
861JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_registerNewNativeFFmpegPipe(JNIEnv *env, jclass object, jstring ffmpegPipePath) {
862 const char *ffmpegPipePathString = (*env)->GetStringUTFChars(env, ffmpegPipePath, 0);
863
864 return mkfifo(ffmpegPipePathString, S_IRWXU | S_IRWXG | S_IROTH);
865}
866
874JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeBuildDate(JNIEnv *env, jclass object) {
875 char buildDate[10];
876 sprintf(buildDate, "%d", FFMPEG_KIT_BUILD_DATE);
877 return (*env)->NewStringUTF(env, buildDate);
878}
879
889JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeEnvironmentVariable(JNIEnv *env, jclass object, jstring variableName, jstring variableValue) {
890 const char *variableNameString = (*env)->GetStringUTFChars(env, variableName, 0);
891 const char *variableValueString = (*env)->GetStringUTFChars(env, variableValue, 0);
892
893 int rc = setenv(variableNameString, variableValueString, 1);
894
895 (*env)->ReleaseStringUTFChars(env, variableName, variableNameString);
896 (*env)->ReleaseStringUTFChars(env, variableValue, variableValueString);
897 return rc;
898}
899
907JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_ignoreNativeSignal(JNIEnv *env, jclass object, jint signum) {
908 if (signum == SIGQUIT) {
909 handleSIGQUIT = 0;
910 } else if (signum == SIGINT) {
911 handleSIGINT = 0;
912 } else if (signum == SIGTERM) {
913 handleSIGTERM = 0;
914 } else if (signum == SIGXCPU) {
915 handleSIGXCPU = 0;
916 } else if (signum == SIGPIPE) {
917 handleSIGPIPE = 0;
918 }
919}
920
929JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit(JNIEnv *env, jclass object, jlong id) {
930 return atomic_load(&sessionInTransitMessageCountMap[id % SESSION_MAP_SIZE]);
931}
monitorUnInit
void monitorUnInit()
Definition ffmpegkit.c:229
statisticsCallbackDataAdd
void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_t size, double time, double bitrate, double speed)
Definition ffmpegkit.c:315
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeBuildDate
JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeBuildDate(JNIEnv *env, jclass object)
Definition ffmpegkit.c:874
ffmpegkit_log_callback_function
void ffmpegkit_log_callback_function(void *ptr, int level, const char *format, va_list vargs)
Definition ffmpegkit.c:446
sessionMap
static atomic_short sessionMap[SESSION_MAP_SIZE]
Definition ffmpegkit.c:57
stringClass
static jclass stringClass
Definition ffmpegkit.c:90
lockMutex
static pthread_mutex_t lockMutex
Definition ffmpegkit.c:61
callbackDataRemove
struct CallbackData * callbackDataRemove()
Definition ffmpegkit.c:368
SESSION_MAP_SIZE
#define SESSION_MAP_SIZE
Definition ffmpegkit.c:56
callbackDataTail
struct CallbackData * callbackDataTail
Definition ffmpegkit.c:69
addSession
void addSession(long id)
Definition ffmpegkit.c:361
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegExecute
JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegExecute(JNIEnv *env, jclass object, jlong id, jobjectArray stringArray)
Definition ffmpegkit.c:783
monitorNotify
void monitorNotify()
Definition ffmpegkit.c:264
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_enableNativeRedirection
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_enableNativeRedirection(JNIEnv *env, jclass object)
Definition ffmpegkit.c:724
avutil_log_sanitize
static void avutil_log_sanitize(uint8_t *line)
Definition ffmpegkit.c:192
handleSIGINT
volatile int handleSIGINT
Definition ffmpegkit.c:103
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeLogLevel
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeLogLevel(JNIEnv *env, jclass object, jint level)
Definition ffmpegkit.c:704
handleSIGTERM
volatile int handleSIGTERM
Definition ffmpegkit.c:104
saf_close
int saf_close(int fd)
Definition ffmpegkit.c:578
ffmpegkit_statistics_callback_function
void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float quality, int64_t size, double time, double bitrate, double speed)
Definition ffmpegkit.c:494
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegCancel
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpegCancel(JNIEnv *env, jclass object, jlong id)
Definition ffmpegkit.c:849
configClassName
const char * configClassName
Definition ffmpegkit.c:96
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeLogLevel
JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeLogLevel(JNIEnv *env, jclass object)
Definition ffmpegkit.c:714
avutil_log_get_level_str
static const char * avutil_log_get_level_str(int level)
Definition ffmpegkit.c:135
avutil_log_format_line
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
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeFFmpegVersion
JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeFFmpegVersion(JNIEnv *env, jclass object)
Definition ffmpegkit.c:759
stringClassName
const char * stringClassName
Definition ffmpegkit.c:99
configMethods
JNINativeMethod configMethods[]
Definition ffmpegkit.c:115
monitorWait
void monitorWait(int milliSeconds)
Definition ffmpegkit.c:242
globalVm
static JavaVM * globalVm
Definition ffmpegkit.c:72
callbackDataHead
struct CallbackData * callbackDataHead
Definition ffmpegkit.c:68
callbackThread
pthread_t callbackThread
Definition ffmpegkit.c:65
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_ignoreNativeSignal
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_ignoreNativeSignal(JNIEnv *env, jclass object, jint signum)
Definition ffmpegkit.c:907
monitorCondition
static pthread_cond_t monitorCondition
Definition ffmpegkit.c:63
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeVersion
JNIEXPORT jstring JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_getNativeVersion(JNIEnv *env, jclass object)
Definition ffmpegkit.c:770
monitorInit
void monitorInit()
Definition ffmpegkit.c:209
cancelSession
void cancelSession(long id)
Definition ffmpegkit.c:411
saf_open
int saf_open(int safId)
Definition ffmpegkit.c:569
globalSessionId
__thread long globalSessionId
Definition ffmpegkit.c:109
redirectionEnabled
int redirectionEnabled
Definition ffmpegkit.c:66
cancelRequested
int cancelRequested(long id)
Definition ffmpegkit.c:421
mutexUnlock
void mutexUnlock()
Definition ffmpegkit.c:238
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_registerNewNativeFFmpegPipe
JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_registerNewNativeFFmpegPipe(JNIEnv *env, jclass object, jstring ffmpegPipePath)
Definition ffmpegkit.c:861
safOpenMethod
static jmethodID safOpenMethod
Definition ffmpegkit.c:84
mutexUnInit
void mutexUnInit()
Definition ffmpegkit.c:225
LogType
#define LogType
Definition ffmpegkit.c:33
enableNativeRedirection
static void enableNativeRedirection()
Definition ffmpegkit.c:587
callbackThreadFunction
void * callbackThreadFunction()
Definition ffmpegkit.c:501
handleSIGPIPE
volatile int handleSIGPIPE
Definition ffmpegkit.c:106
monitorMutex
static pthread_mutex_t monitorMutex
Definition ffmpegkit.c:62
JNI_OnLoad
jint JNI_OnLoad(JavaVM *vm, void *reserved)
Definition ffmpegkit.c:615
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_disableNativeRedirection
JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_disableNativeRedirection(JNIEnv *env, jclass object)
Definition ffmpegkit.c:734
logMethod
static jmethodID logMethod
Definition ffmpegkit.c:78
handleSIGXCPU
volatile int handleSIGXCPU
Definition ffmpegkit.c:105
safCloseMethod
static jmethodID safCloseMethod
Definition ffmpegkit.c:87
resetMessagesInTransmit
void resetMessagesInTransmit(long id)
Definition ffmpegkit.c:434
configClass
static jclass configClass
Definition ffmpegkit.c:75
sessionInTransitMessageCountMap
static atomic_int sessionInTransitMessageCountMap[SESSION_MAP_SIZE]
Definition ffmpegkit.c:58
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeEnvironmentVariable
JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_setNativeEnvironmentVariable(JNIEnv *env, jclass object, jstring variableName, jstring variableValue)
Definition ffmpegkit.c:889
mutexLock
void mutexLock()
Definition ffmpegkit.c:234
mutexInit
void mutexInit()
Definition ffmpegkit.c:200
configuredLogLevel
int configuredLogLevel
Definition ffmpegkit.c:112
StatisticsType
#define StatisticsType
Definition ffmpegkit.c:34
ffmpeg_execute
int ffmpeg_execute(int argc, char **argv)
Definition fftools_ffmpeg.c:4378
stringConstructor
static jmethodID stringConstructor
Definition ffmpegkit.c:93
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit
JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit(JNIEnv *env, jclass object, jlong id)
Definition ffmpegkit.c:929
statisticsMethod
static jmethodID statisticsMethod
Definition ffmpegkit.c:81
handleSIGQUIT
volatile int handleSIGQUIT
Definition ffmpegkit.c:102
logCallbackDataAdd
void logCallbackDataAdd(int level, AVBPrint *data)
Definition ffmpegkit.c:276
removeSession
void removeSession(long id)
Definition ffmpegkit.c:402
ffmpegkit.h
FFMPEG_KIT_VERSION
#define FFMPEG_KIT_VERSION
Definition ffmpegkit.h:30
LIB_NAME
#define LIB_NAME
Definition ffmpegkit.h:33
LOGD
#define LOGD(...)
Definition ffmpegkit.h:39
LOGE
#define LOGE(...)
Definition ffmpegkit.h:48
Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprobeExecute
JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprobeExecute(JNIEnv *env, jclass object, jlong id, jobjectArray stringArray)
Definition ffprobekit.c:48
ffprobekit.h
AV_LOG_STDERR
#define AV_LOG_STDERR
Definition fftools_cmdutils.h:82
set_report_callback
void set_report_callback(void(*callback)(int, float, float, int64_t, double, double, double))
Definition fftools_ffmpeg.c:4362
cancel_operation
void cancel_operation(long id)
Definition fftools_ffmpeg.c:4367
fftools_ffmpeg.h
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition fftools_ffprobe.c:102
pthread_mutex_unlock
#define pthread_mutex_unlock(a)
Definition fftools_ffprobe.c:106
CallbackData
Definition ffmpegkit.c:37
CallbackData::logLevel
int logLevel
Definition ffmpegkit.c:41
CallbackData::statisticsBitrate
double statisticsBitrate
Definition ffmpegkit.c:49
CallbackData::statisticsQuality
float statisticsQuality
Definition ffmpegkit.c:46
CallbackData::statisticsTime
double statisticsTime
Definition ffmpegkit.c:48
CallbackData::type
int type
Definition ffmpegkit.c:38
CallbackData::next
struct CallbackData * next
Definition ffmpegkit.c:52
CallbackData::statisticsSpeed
double statisticsSpeed
Definition ffmpegkit.c:50
CallbackData::statisticsFrameNumber
int statisticsFrameNumber
Definition ffmpegkit.c:44
CallbackData::statisticsFps
float statisticsFps
Definition ffmpegkit.c:45
CallbackData::sessionId
long sessionId
Definition ffmpegkit.c:39
CallbackData::logData
AVBPrint logData
Definition ffmpegkit.c:42
CallbackData::statisticsSize
int64_t statisticsSize
Definition ffmpegkit.c:47