refactor api

pull/7/head
Taner Sener 5 years ago
parent 2fceb5f5ed
commit 4680721cef
  1. 133
      android/ffmpeg-kit-android-lib/src/main/cpp/ffmpegkit.c
  2. 3
      android/ffmpeg-kit-android-lib/src/main/cpp/ffmpegkit_exception.c
  3. 16
      android/ffmpeg-kit-android-lib/src/main/cpp/ffprobekit.c
  4. 36
      android/ffmpeg-kit-android-lib/src/main/cpp/saf_wrapper.c
  5. 12
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Abi.java
  6. 36
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AbiDetect.java
  7. 241
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AbstractSession.java
  8. 2
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AsyncFFmpegExecuteTask.java
  9. 4
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AsyncFFprobeExecuteTask.java
  10. 4
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AsyncGetMediaInformationTask.java
  11. 10
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/CameraSupport.java
  12. 22
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/ExecuteCallback.java
  13. 120
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFmpegKit.java
  14. 476
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFmpegKitConfig.java
  15. 150
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFmpegSession.java
  16. 338
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFprobeKit.java
  17. 76
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFprobeSession.java
  18. 6
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Level.java
  19. 2
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Log.java
  20. 2
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/LogCallback.java
  21. 10
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/MediaInformationJsonParser.java
  22. 54
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/MediaInformationSession.java
  23. 183
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/NativeLoader.java
  24. 48
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Packages.java
  25. 29
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/ReturnCode.java
  26. 193
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Session.java
  27. 11
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Statistics.java
  28. 2
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/StatisticsCallback.java
  29. 36
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/StreamInformation.java
  30. 44
      android/ffmpeg-kit-android-lib/src/test/java/com/arthenica/ffmpegkit/AbstractSessionTest.java
  31. 12
      android/ffmpeg-kit-android-lib/src/test/java/com/arthenica/ffmpegkit/FFmpegKitTest.java
  32. 350
      android/ffmpeg-kit-android-lib/src/test/java/com/arthenica/ffmpegkit/FFmpegSessionTest.java
  33. 334
      android/ffmpeg-kit-android-lib/src/test/java/com/arthenica/ffmpegkit/FFprobeSessionTest.java
  34. 2
      android/settings.gradle
  35. 6
      apple/Makefile.in
  36. 13
      apple/aclocal.m4
  37. 221
      apple/config.guess
  38. 59
      apple/config.sub
  39. 7
      apple/configure
  40. 148
      apple/install-sh
  41. 56
      apple/src/AbstractSession.h
  42. 235
      apple/src/AbstractSession.m
  43. 27
      apple/src/ArchDetect.h
  44. 48
      apple/src/ArchDetect.m
  45. 11
      apple/src/AtomicLong.h
  46. 35
      apple/src/AtomicLong.m
  47. 37
      apple/src/ExecuteDelegate.h
  48. 35
      apple/src/FFmpegExecution.h
  49. 52
      apple/src/FFmpegExecution.m
  50. 179
      apple/src/FFmpegKit.h
  51. 252
      apple/src/FFmpegKit.m
  52. 362
      apple/src/FFmpegKitConfig.h
  53. 1334
      apple/src/FFmpegKitConfig.m
  54. 119
      apple/src/FFmpegSession.h
  55. 137
      apple/src/FFmpegSession.m
  56. 228
      apple/src/FFprobeKit.h
  57. 200
      apple/src/FFprobeKit.m
  58. 67
      apple/src/FFprobeSession.h
  59. 64
      apple/src/FFprobeSession.m
  60. 85
      apple/src/Level.h
  61. 40
      apple/src/Log.h
  62. 51
      apple/src/Log.m
  63. 19
      apple/src/LogDelegate.h
  64. 31
      apple/src/LogRedirectionStrategy.h
  65. 42
      apple/src/Makefile.am
  66. 243
      apple/src/Makefile.in
  67. 19
      apple/src/MediaInformation.h
  68. 40
      apple/src/MediaInformation.m
  69. 25
      apple/src/MediaInformationJsonParser.h
  70. 4
      apple/src/MediaInformationJsonParser.m
  71. 74
      apple/src/MediaInformationSession.h
  72. 59
      apple/src/MediaInformationSession.m
  73. 46
      apple/src/Packages.h
  74. 263
      apple/src/Packages.m
  75. 44
      apple/src/ReturnCode.h
  76. 51
      apple/src/ReturnCode.m
  77. 255
      apple/src/Session.h
  78. 30
      apple/src/SessionState.h
  79. 17
      apple/src/Statistics.h
  80. 99
      apple/src/Statistics.m
  81. 17
      apple/src/StatisticsDelegate.h
  82. 26
      apple/src/StreamInformation.h
  83. 76
      apple/src/StreamInformation.m
  84. 18
      apple/src/fftools_ffmpeg.c
  85. 4
      ios.sh
  86. 4
      macos.sh
  87. 4
      tvos.sh

@ -18,6 +18,7 @@
*/ */
#include <pthread.h> #include <pthread.h>
#include <stdatomic.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -28,6 +29,9 @@
#include "ffmpegkit.h" #include "ffmpegkit.h"
#include "ffprobekit.h" #include "ffprobekit.h"
# define LogType 1
# define StatisticsType 2
/** Callback data structure */ /** Callback data structure */
struct CallbackData { struct CallbackData {
int type; // 1 (log callback) or 2 (statistics callback) int type; // 1 (log callback) or 2 (statistics callback)
@ -47,11 +51,10 @@ struct CallbackData {
struct CallbackData *next; struct CallbackData *next;
}; };
/** Session map variables */ /** Session control variables */
const int SESSION_MAP_SIZE = 1000; const int SESSION_MAP_SIZE = 1000;
static volatile int sessionMap[SESSION_MAP_SIZE]; static atomic_short sessionMap[SESSION_MAP_SIZE];
static volatile int sessionInTransitMessageCountMap[SESSION_MAP_SIZE]; static atomic_int sessionInTransitMessageCountMap[SESSION_MAP_SIZE];
static pthread_mutex_t sessionMapMutex;
/** Redirection control variables */ /** Redirection control variables */
static pthread_mutex_t lockMutex; static pthread_mutex_t lockMutex;
@ -215,15 +218,6 @@ void monitorInit() {
pthread_condattr_destroy(&cattributes); pthread_condattr_destroy(&cattributes);
} }
void sessionMapLockInit() {
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE_NP);
pthread_mutex_init(&sessionMapMutex, &attributes);
pthread_mutexattr_destroy(&attributes);
}
void mutexUnInit() { void mutexUnInit() {
pthread_mutex_destroy(&lockMutex); pthread_mutex_destroy(&lockMutex);
} }
@ -233,26 +227,14 @@ void monitorUnInit() {
pthread_cond_destroy(&monitorCondition); pthread_cond_destroy(&monitorCondition);
} }
void sessionMapLockUnInit() {
pthread_mutex_destroy(&sessionMapMutex);
}
void mutexLock() { void mutexLock() {
pthread_mutex_lock(&lockMutex); pthread_mutex_lock(&lockMutex);
} }
void sessionMapLock() {
pthread_mutex_lock(&sessionMapMutex);
}
void mutexUnlock() { void mutexUnlock() {
pthread_mutex_unlock(&lockMutex); pthread_mutex_unlock(&lockMutex);
} }
void sessionMapUnlock() {
pthread_mutex_unlock(&sessionMapMutex);
}
void monitorWait(int milliSeconds) { void monitorWait(int milliSeconds) {
struct timeval tp; struct timeval tp;
struct timespec ts; struct timespec ts;
@ -291,7 +273,7 @@ void logCallbackDataAdd(int level, AVBPrint *data) {
// CREATE DATA STRUCT FIRST // CREATE DATA STRUCT FIRST
struct CallbackData *newData = (struct CallbackData*)av_malloc(sizeof(struct CallbackData)); struct CallbackData *newData = (struct CallbackData*)av_malloc(sizeof(struct CallbackData));
newData->type = 1; newData->type = LogType;
newData->sessionId = sessionId; newData->sessionId = sessionId;
newData->logLevel = level; newData->logLevel = level;
av_bprint_init(&newData->logData, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprint_init(&newData->logData, 0, AV_BPRINT_SIZE_UNLIMITED);
@ -316,12 +298,11 @@ void logCallbackDataAdd(int level, AVBPrint *data) {
callbackDataTail = newData; callbackDataTail = newData;
} }
int key = sessionId % SESSION_MAP_SIZE;
sessionInTransitMessageCountMap[key] += 1;
mutexUnlock(); mutexUnlock();
monitorNotify(); monitorNotify();
atomic_fetch_add(&sessionInTransitMessageCountMap[sessionId % SESSION_MAP_SIZE], 1);
} }
/** /**
@ -331,7 +312,7 @@ void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_
// CREATE DATA STRUCT FIRST // CREATE DATA STRUCT FIRST
struct CallbackData *newData = (struct CallbackData*)av_malloc(sizeof(struct CallbackData)); struct CallbackData *newData = (struct CallbackData*)av_malloc(sizeof(struct CallbackData));
newData->type = 2; newData->type = StatisticsType;
newData->sessionId = sessionId; newData->sessionId = sessionId;
newData->statisticsFrameNumber = frameNumber; newData->statisticsFrameNumber = frameNumber;
newData->statisticsFps = fps; newData->statisticsFps = fps;
@ -361,12 +342,11 @@ void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_
callbackDataTail = newData; callbackDataTail = newData;
} }
int key = sessionId % SESSION_MAP_SIZE;
sessionInTransitMessageCountMap[key] += 1;
mutexUnlock(); mutexUnlock();
monitorNotify(); monitorNotify();
atomic_fetch_add(&sessionInTransitMessageCountMap[sessionId % SESSION_MAP_SIZE], 1);
} }
/** /**
@ -375,12 +355,7 @@ void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_
* @param id session id * @param id session id
*/ */
void addSession(long id) { void addSession(long id) {
sessionMapLock(); atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 1);
int key = id % SESSION_MAP_SIZE;
sessionMap[key] = 1;
sessionMapUnlock();
} }
/** /**
@ -421,12 +396,7 @@ struct CallbackData *callbackDataRemove() {
* @param id session id * @param id session id
*/ */
void removeSession(long id) { void removeSession(long id) {
sessionMapLock(); atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 0);
int key = id % SESSION_MAP_SIZE;
sessionMap[key] = 0;
sessionMapUnlock();
} }
/** /**
@ -435,12 +405,7 @@ void removeSession(long id) {
* @param id session id * @param id session id
*/ */
void cancelSession(long id) { void cancelSession(long id) {
sessionMapLock(); atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 2);
int key = id % SESSION_MAP_SIZE;
sessionMap[key] = 2;
sessionMapUnlock();
} }
/** /**
@ -450,18 +415,11 @@ void cancelSession(long id) {
* @return 1 if exists, false otherwise * @return 1 if exists, false otherwise
*/ */
int cancelRequested(long id) { int cancelRequested(long id) {
int found = 0; if (atomic_load(&sessionMap[id % SESSION_MAP_SIZE]) == 2) {
return 1;
sessionMapLock(); } else {
return 0;
int key = id % SESSION_MAP_SIZE;
if (sessionMap[key] == 2) {
found = 1;
} }
sessionMapUnlock();
return found;
} }
/** /**
@ -470,12 +428,7 @@ int cancelRequested(long id) {
* @param id session id * @param id session id
*/ */
void resetMessagesInTransmit(long id) { void resetMessagesInTransmit(long id) {
mutexLock(); atomic_store(&sessionInTransitMessageCountMap[id % SESSION_MAP_SIZE], 0);
int key = id % SESSION_MAP_SIZE;
sessionInTransitMessageCountMap[key] = 0;
mutexUnlock();
} }
/** /**
@ -556,13 +509,13 @@ void *callbackThreadFunction() {
} }
} }
LOGD("Callback thread started.\n"); LOGD("Async callback block started.\n");
while(redirectionEnabled) { while(redirectionEnabled) {
struct CallbackData *callbackData = callbackDataRemove(); struct CallbackData *callbackData = callbackDataRemove();
if (callbackData != NULL) { if (callbackData != NULL) {
if (callbackData->type == 1) { if (callbackData->type == LogType) {
// LOG CALLBACK // LOG CALLBACK
@ -588,8 +541,7 @@ void *callbackThreadFunction() {
} }
int key = callbackData->sessionId % SESSION_MAP_SIZE; atomic_fetch_sub(&sessionInTransitMessageCountMap[callbackData->sessionId % SESSION_MAP_SIZE], 1);
sessionInTransitMessageCountMap[key] -= 1;
// CLEAN STRUCT // CLEAN STRUCT
callbackData->next = NULL; callbackData->next = NULL;
@ -602,7 +554,7 @@ void *callbackThreadFunction() {
(*globalVm)->DetachCurrentThread(globalVm); (*globalVm)->DetachCurrentThread(globalVm);
LOGD("Callback thread stopped.\n"); LOGD("Async callback block stopped.\n");
return NULL; return NULL;
} }
@ -678,18 +630,18 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
configClass = (jclass) ((*env)->NewGlobalRef(env, localConfigClass)); configClass = (jclass) ((*env)->NewGlobalRef(env, localConfigClass));
stringClass = (jclass) ((*env)->NewGlobalRef(env, localStringClass)); stringClass = (jclass) ((*env)->NewGlobalRef(env, localStringClass));
redirectionEnabled = 0;
callbackDataHead = NULL; callbackDataHead = NULL;
callbackDataTail = NULL; callbackDataTail = NULL;
for(int i = 0; i<SESSION_MAP_SIZE; i++) { for(int i = 0; i<SESSION_MAP_SIZE; i++) {
sessionMap[i] = 0; atomic_init(&sessionMap[i], 0);
atomic_init(&sessionInTransitMessageCountMap[i], 0);
} }
mutexInit(); mutexInit();
monitorInit(); monitorInit();
sessionMapLockInit();
redirectionEnabled = 0;
return JNI_VERSION_1_6; return JNI_VERSION_1_6;
} }
@ -802,10 +754,10 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpeg
int argumentCount = 1; int argumentCount = 1;
char **argv = NULL; char **argv = NULL;
// SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW EXECUTION // SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW RUN
av_log_set_level(configuredLogLevel); av_log_set_level(configuredLogLevel);
if (stringArray != NULL) { if (stringArray) {
int programArgumentCount = (*env)->GetArrayLength(env, stringArray); int programArgumentCount = (*env)->GetArrayLength(env, stringArray);
argumentCount = programArgumentCount + 1; argumentCount = programArgumentCount + 1;
@ -820,8 +772,8 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpeg
argv[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1)); argv[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
strcpy(argv[0], LIB_NAME); strcpy(argv[0], LIB_NAME);
// PREPARE // PREPARE ARRAY ELEMENTS
if (stringArray != NULL) { if (stringArray) {
for (int i = 0; i < (argumentCount - 1); i++) { for (int i = 0; i < (argumentCount - 1); i++) {
tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i); tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
if (tempArray[i] != NULL) { if (tempArray[i] != NULL) {
@ -830,20 +782,20 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpeg
} }
} }
// REGISTER THE ID BEFORE STARTING THE EXECUTION // REGISTER THE ID BEFORE STARTING THE SESSION
sessionId = (long) id; sessionId = (long) id;
addSession((long) id); addSession((long) id);
resetMessagesInTransmit(sessionId); resetMessagesInTransmit(sessionId);
// RUN // RUN
int retCode = ffmpeg_execute(argumentCount, argv); int returnCode = ffmpeg_execute(argumentCount, argv);
// ALWAYS REMOVE THE ID FROM THE MAP // ALWAYS REMOVE THE ID FROM THE MAP
removeSession((long) id); removeSession((long) id);
// CLEANUP // CLEANUP
if (tempArray != NULL) { if (tempArray) {
for (int i = 0; i < (argumentCount - 1); i++) { for (int i = 0; i < (argumentCount - 1); i++) {
(*env)->ReleaseStringUTFChars(env, tempArray[i], argv[i + 1]); (*env)->ReleaseStringUTFChars(env, tempArray[i], argv[i + 1]);
} }
@ -853,7 +805,7 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpeg
av_free(argv[0]); av_free(argv[0]);
av_free(argv); av_free(argv);
return retCode; return returnCode;
} }
/** /**
@ -944,12 +896,5 @@ JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_ignoreNative
* @param id session id * @param id session id
*/ */
JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit(JNIEnv *env, jclass object, jlong id) { JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit(JNIEnv *env, jclass object, jlong id) {
mutexLock(); return atomic_load(&sessionInTransitMessageCountMap[id % SESSION_MAP_SIZE]);
int key = id % SESSION_MAP_SIZE;
int count = sessionInTransitMessageCountMap[key];
mutexUnlock();
return count;
} }

@ -17,8 +17,7 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h> #include "ffmpegkit_exception.h"
#include <setjmp.h>
/** Holds information to implement exception handling. */ /** Holds information to implement exception handling. */
__thread jmp_buf ex_buf__; __thread jmp_buf ex_buf__;

@ -49,10 +49,10 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprob
int argumentCount = 1; int argumentCount = 1;
char **argv = NULL; char **argv = NULL;
// SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW EXECUTION // SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW RUN
av_log_set_level(configuredLogLevel); av_log_set_level(configuredLogLevel);
if (stringArray != NULL) { if (stringArray) {
int programArgumentCount = (*env)->GetArrayLength(env, stringArray); int programArgumentCount = (*env)->GetArrayLength(env, stringArray);
argumentCount = programArgumentCount + 1; argumentCount = programArgumentCount + 1;
@ -67,8 +67,8 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprob
argv[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1)); argv[0] = (char *)av_malloc(sizeof(char) * (strlen(LIB_NAME) + 1));
strcpy(argv[0], LIB_NAME); strcpy(argv[0], LIB_NAME);
// PREPARE // PREPARE ARRAY ELEMENTS
if (stringArray != NULL) { if (stringArray) {
for (int i = 0; i < (argumentCount - 1); i++) { for (int i = 0; i < (argumentCount - 1); i++) {
tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i); tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
if (tempArray[i] != NULL) { if (tempArray[i] != NULL) {
@ -77,20 +77,20 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprob
} }
} }
// REGISTER THE ID BEFORE STARTING THE EXECUTION // REGISTER THE ID BEFORE STARTING THE SESSION
sessionId = (long) id; sessionId = (long) id;
addSession((long) id); addSession((long) id);
resetMessagesInTransmit(sessionId); resetMessagesInTransmit(sessionId);
// RUN // RUN
int retCode = ffprobe_execute(argumentCount, argv); int returnCode = ffprobe_execute(argumentCount, argv);
// ALWAYS REMOVE THE ID FROM THE MAP // ALWAYS REMOVE THE ID FROM THE MAP
removeSession((long) id); removeSession((long) id);
// CLEANUP // CLEANUP
if (tempArray != NULL) { if (tempArray) {
for (int i = 0; i < (argumentCount - 1); i++) { for (int i = 0; i < (argumentCount - 1); i++) {
(*env)->ReleaseStringUTFChars(env, tempArray[i], argv[i + 1]); (*env)->ReleaseStringUTFChars(env, tempArray[i], argv[i + 1]);
} }
@ -100,5 +100,5 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprob
av_free(argv[0]); av_free(argv[0]);
av_free(argv); av_free(argv);
return retCode; return returnCode;
} }

@ -38,13 +38,11 @@ void closeParcelFileDescriptor(int fd);
#undef avformat_open_input #undef avformat_open_input
static int fd_read_packet(void* opaque, uint8_t* buf, int buf_size) { static int fd_read_packet(void* opaque, uint8_t* buf, int buf_size) {
int *fd = opaque; return read(*(int*)opaque, buf, buf_size);
return read(*fd, buf, buf_size);
} }
static int fd_write_packet(void* opaque, uint8_t* buf, int buf_size) { static int fd_write_packet(void* opaque, uint8_t* buf, int buf_size) {
int *fd = opaque; return write(*(int*)opaque, buf, buf_size);
return write(*fd, buf, buf_size);
} }
static int64_t fd_seek(void *opaque, int64_t offset, int whence) { static int64_t fd_seek(void *opaque, int64_t offset, int whence) {
@ -70,31 +68,36 @@ static int64_t fd_seek(void *opaque, int64_t offset, int whence) {
* returns NULL if the filename is not of expected format (e.g. 'saf:72/video.md4') * returns NULL if the filename is not of expected format (e.g. 'saf:72/video.md4')
*/ */
static AVIOContext *create_fd_avio_context(const char *filename, int flags) { static AVIOContext *create_fd_avio_context(const char *filename, int flags) {
int *fd = av_mallocz(sizeof(int)); int fd = -1;
*fd = -1; const char* fd_ptr = NULL;
const char *fd_ptr = NULL;
if (av_strstart(filename, "saf:", &fd_ptr)) { if (av_strstart(filename, "saf:", &fd_ptr)) {
char *final; char *final;
*fd = strtol(fd_ptr, &final, 10); fd = strtol(fd_ptr, &final, 10);
if (fd_ptr == final) { /* No digits found */ if (fd_ptr == final) { /* No digits found */
*fd = -1; fd = -1;
} }
} }
if (*fd >= 0) { if (fd >= 0) {
int *opaque = av_mallocz(sizeof(int));
*opaque = fd;
int write_flag = flags & AVIO_FLAG_WRITE ? 1 : 0; int write_flag = flags & AVIO_FLAG_WRITE ? 1 : 0;
return avio_alloc_context(av_malloc(4096), 4096, write_flag, fd, fd_read_packet, write_flag ? fd_write_packet : NULL, fd_seek); return avio_alloc_context(av_malloc(4096), 4096, write_flag, opaque, fd_read_packet, write_flag ? fd_write_packet : NULL, fd_seek);
} }
return NULL; return NULL;
} }
static void close_fd_avio_context(AVIOContext *ctx) { static void close_fd_avio_context(AVIOContext *ctx) {
if (fd_seek(ctx->opaque, 0, AVSEEK_SIZE) >= 0) { if (ctx) {
int *fd = ctx->opaque; if (fd_seek(ctx->opaque, 0, AVSEEK_SIZE) >= 0) {
closeParcelFileDescriptor(*fd); int *fd = ctx->opaque;
av_freep(&fd); closeParcelFileDescriptor(*fd);
av_freep(&fd);
}
ctx->opaque = NULL;
} }
ctx->opaque = NULL;
} }
int android_avformat_open_input(AVFormatContext **ps, const char *filename, int android_avformat_open_input(AVFormatContext **ps, const char *filename,
@ -115,6 +118,7 @@ int android_avio_open2(AVIOContext **s, const char *filename, int flags,
*s = fd_context; *s = fd_context;
return 0; return 0;
} }
return avio_open2(s, filename, flags, int_cb, options); return avio_open2(s, filename, flags, int_cb, options);
} }

@ -20,9 +20,7 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
/** /**
* <p>Enumeration type for Android ABIs. * <p>Enumeration for Android ABIs.
*
* @author Taner Sener
*/ */
public enum Abi { public enum Abi {
@ -64,10 +62,10 @@ public enum Abi {
private final String name; private final String name;
/** /**
* <p>Returns enumeration defined by ABI name. * <p>Returns the enumeration defined for the given ABI name.
* *
* @param abiName ABI name * @param abiName ABI name
* @return enumeration defined by ABI name * @return enumeration defined for the ABI name
*/ */
public static Abi from(final String abiName) { public static Abi from(final String abiName) {
if (abiName == null) { if (abiName == null) {
@ -90,9 +88,9 @@ public enum Abi {
} }
/** /**
* Returns ABI name as defined in Android NDK documentation. * Returns the ABI name.
* *
* @return ABI name * @return ABI name as defined in Android NDK documentation
*/ */
public String getName() { public String getName() {
return name; return name;

@ -20,18 +20,19 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
/** /**
* <p>Detects running ABI name using Google <code>cpu-features</code> library. * <p>Detects the running ABI name natively using Google <code>cpu-features</code> library.
*/ */
public class AbiDetect { public class AbiDetect {
static { static {
armV7aNeonLoaded = false; armV7aNeonLoaded = false;
System.loadLibrary("ffmpegkit_abidetect"); NativeLoader.loadFFmpegKitAbiDetect();
/* ALL LIBRARIES LOADED AT STARTUP */ /* ALL LIBRARIES LOADED AT STARTUP */
FFmpegKitConfig.class.getName();
FFmpegKit.class.getName(); FFmpegKit.class.getName();
FFmpegKitConfig.class.getName();
FFprobeKit.class.getName();
} }
static final String ARM_V7A = "arm-v7a"; static final String ARM_V7A = "arm-v7a";
@ -51,9 +52,9 @@ public class AbiDetect {
} }
/** /**
* <p>Returns loaded ABI name. * <p>Returns the ABI name loaded.
* *
* @return loaded ABI name * @return ABI name loaded
*/ */
public static String getAbi() { public static String getAbi() {
if (armV7aNeonLoaded) { if (armV7aNeonLoaded) {
@ -64,28 +65,37 @@ public class AbiDetect {
} }
/** /**
* <p>Returns loaded ABI name. * <p>Returns the ABI name of the cpu running.
*
* @return ABI name of the cpu running
*/
public static String getCpuAbi() {
return getNativeCpuAbi();
}
/**
* <p>Returns the ABI name loaded natively.
* *
* @return loaded ABI name * @return ABI name loaded
*/ */
public native static String getNativeAbi(); native static String getNativeAbi();
/** /**
* <p>Returns ABI name of the running cpu. * <p>Returns the ABI name of the cpu running natively.
* *
* @return ABI name of the running cpu * @return ABI name of the cpu running
*/ */
public native static String getNativeCpuAbi(); native static String getNativeCpuAbi();
/** /**
* <p>Returns whether FFmpegKit release is a long term release or not. * <p>Returns whether FFmpegKit release is a long term release or not natively.
* *
* @return yes or no * @return yes or no
*/ */
native static boolean isNativeLTSBuild(); native static boolean isNativeLTSBuild();
/** /**
* <p>Returns build configuration for <code>FFmpeg</code>. * <p>Returns the build configuration for <code>FFmpeg</code> natively.
* *
* @return build configuration string * @return build configuration string
*/ */

@ -22,54 +22,121 @@ package com.arthenica.ffmpegkit;
import com.arthenica.smartexception.java.Exceptions; import com.arthenica.smartexception.java.Exceptions;
import java.util.Date; import java.util.Date;
import java.util.Queue; import java.util.LinkedList;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.List;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
/**
* Abstract session implementation which includes common features shared by <code>FFmpeg</code>
* and <code>FFprobe</code> sessions.
*/
public abstract class AbstractSession implements Session { public abstract class AbstractSession implements Session {
/** /**
* Generates ids for execute sessions. * Generates unique ids for sessions.
*/ */
protected static final AtomicLong sessionIdGenerator = new AtomicLong(1); protected static final AtomicLong sessionIdGenerator = new AtomicLong(1);
/** /**
* Defines how long default `getAll` methods wait. * Defines how long default "getAll" methods wait, in milliseconds.
*/ */
protected static final int DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT = 5000; public static final int DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT = 5000;
/**
* Session identifier.
*/
protected final long sessionId;
/**
* Session specific execute callback function.
*/
protected final ExecuteCallback executeCallback; protected final ExecuteCallback executeCallback;
/**
* Session specific log callback function.
*/
protected final LogCallback logCallback; protected final LogCallback logCallback;
protected final StatisticsCallback statisticsCallback;
protected final long sessionId; /**
* Date and time the session was created.
*/
protected final Date createTime; protected final Date createTime;
/**
* Date and time the session was started.
*/
protected Date startTime; protected Date startTime;
/**
* Date and time the session has ended.
*/
protected Date endTime; protected Date endTime;
/**
* Command arguments as an array.
*/
protected final String[] arguments; protected final String[] arguments;
protected final Queue<Log> logs;
/**
* Log entries received for this session.
*/
protected final List<Log> logs;
/**
* Log entry lock.
*/
protected final Object logsLock;
/**
* Future created for sessions executed asynchronously.
*/
protected Future<?> future; protected Future<?> future;
/**
* State of the session.
*/
protected SessionState state; protected SessionState state;
protected int returnCode;
/**
* Return code for the completed sessions.
*/
protected ReturnCode returnCode;
/**
* Stack trace of the error received while trying to execute this session.
*/
protected String failStackTrace; protected String failStackTrace;
/**
* Session specific log redirection strategy.
*/
protected final LogRedirectionStrategy logRedirectionStrategy; protected final LogRedirectionStrategy logRedirectionStrategy;
/**
* Creates a new abstract session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param logCallback session specific log callback function
* @param logRedirectionStrategy session specific log redirection strategy
*/
public AbstractSession(final String[] arguments, public AbstractSession(final String[] arguments,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final LogRedirectionStrategy logRedirectionStrategy) { final LogRedirectionStrategy logRedirectionStrategy) {
this.sessionId = sessionIdGenerator.getAndIncrement(); this.sessionId = sessionIdGenerator.getAndIncrement();
this.executeCallback = executeCallback;
this.logCallback = logCallback;
this.createTime = new Date(); this.createTime = new Date();
this.startTime = null; this.startTime = null;
this.endTime = null;
this.arguments = arguments; this.arguments = arguments;
this.executeCallback = executeCallback; this.logs = new LinkedList<>();
this.logCallback = logCallback; this.logsLock = new Object();
this.statisticsCallback = statisticsCallback;
this.logs = new ConcurrentLinkedQueue<>();
this.future = null; this.future = null;
this.state = SessionState.CREATED; this.state = SessionState.CREATED;
this.returnCode = ReturnCode.NOT_SET; this.returnCode = null;
this.failStackTrace = null; this.failStackTrace = null;
this.logRedirectionStrategy = logRedirectionStrategy; this.logRedirectionStrategy = logRedirectionStrategy;
} }
@ -84,11 +151,6 @@ public abstract class AbstractSession implements Session {
return logCallback; return logCallback;
} }
@Override
public StatisticsCallback getStatisticsCallback() {
return statisticsCallback;
}
@Override @Override
public long getSessionId() { public long getSessionId() {
return sessionId; return sessionId;
@ -117,7 +179,7 @@ public abstract class AbstractSession implements Session {
return (endTime.getTime() - startTime.getTime()); return (endTime.getTime() - startTime.getTime());
} }
return -1; return 0;
} }
@Override @Override
@ -130,77 +192,84 @@ public abstract class AbstractSession implements Session {
return FFmpegKit.argumentsToString(arguments); return FFmpegKit.argumentsToString(arguments);
} }
protected void waitForCallbackMessagesInTransmit(final int timeout) {
final long start = System.currentTimeMillis();
/*
* WE GIVE MAX 5 SECONDS TO TRANSMIT ALL NATIVE MESSAGES
*/
while (thereAreCallbackMessagesInTransmit() && (System.currentTimeMillis() < (start + timeout))) {
synchronized (this) {
try {
wait(100);
} catch (InterruptedException ignored) {
}
}
}
}
@Override @Override
public Queue<Log> getAllLogs(final int waitTimeout) { public List<Log> getAllLogs(final int waitTimeout) {
waitForCallbackMessagesInTransmit(waitTimeout); waitForAsynchronousMessagesInTransmit(waitTimeout);
if (thereAreCallbackMessagesInTransmit()) { if (thereAreAsynchronousMessagesInTransmit()) {
android.util.Log.i(FFmpegKitConfig.TAG, String.format("getAllLogs was asked to return all logs but there are still logs being transmitted for session id %d.", sessionId)); android.util.Log.i(FFmpegKitConfig.TAG, String.format("getAllLogs was called to return all logs but there are still logs being transmitted for session id %d.", sessionId));
} }
return logs; return getLogs();
} }
/**
* Returns all log entries generated for this session. If there are asynchronous
* messages that are not delivered yet, this method waits for them until
* {@link #DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT} expires.
*
* @return list of log entries generated for this session
*/
@Override @Override
public Queue<Log> getAllLogs() { public List<Log> getAllLogs() {
return getAllLogs(DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT); return getAllLogs(DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
} }
@Override @Override
public Queue<Log> getLogs() { public List<Log> getLogs() {
return logs; synchronized (logsLock) {
return new LinkedList<>(logs);
}
} }
@Override @Override
public String getAllLogsAsString(final int waitTimeout) { public String getAllLogsAsString(final int waitTimeout) {
waitForCallbackMessagesInTransmit(waitTimeout); waitForAsynchronousMessagesInTransmit(waitTimeout);
if (thereAreCallbackMessagesInTransmit()) { if (thereAreAsynchronousMessagesInTransmit()) {
android.util.Log.i(FFmpegKitConfig.TAG, String.format("getAllLogsAsString was asked to return all logs but there are still logs being transmitted for session id %d.", sessionId)); android.util.Log.i(FFmpegKitConfig.TAG, String.format("getAllLogsAsString was called to return all logs but there are still logs being transmitted for session id %d.", sessionId));
} }
return getLogsAsString(); return getLogsAsString();
} }
/**
* Returns all log entries generated for this session as a concatenated string. If there are
* asynchronous messages that are not delivered yet, this method waits for them until
* {@link #DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT} expires.
*
* @return all log entries generated for this session as a concatenated string
*/
@Override @Override
public String getAllLogsAsString() { public String getAllLogsAsString() {
return getAllLogsAsString(DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT); return getAllLogsAsString(DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
} }
@Override @Override
public String getLogsAsString() { public String getLogsAsString() {
final StringBuilder concatenatedString = new StringBuilder(); final StringBuilder concatenatedString = new StringBuilder();
for (Log log : logs) { synchronized (logsLock) {
concatenatedString.append(log.getMessage()); for (Log log : logs) {
concatenatedString.append(log.getMessage());
}
} }
return concatenatedString.toString(); return concatenatedString.toString();
} }
@Override
public String getOutput() {
return getAllLogsAsString();
}
@Override @Override
public SessionState getState() { public SessionState getState() {
return state; return state;
} }
@Override @Override
public int getReturnCode() { public ReturnCode getReturnCode() {
return returnCode; return returnCode;
} }
@ -215,13 +284,15 @@ public abstract class AbstractSession implements Session {
} }
@Override @Override
public boolean thereAreCallbackMessagesInTransmit() { public boolean thereAreAsynchronousMessagesInTransmit() {
return (FFmpegKitConfig.messagesInTransmit(sessionId) != 0); return (FFmpegKitConfig.messagesInTransmit(sessionId) != 0);
} }
@Override @Override
public void addLog(final Log log) { public void addLog(final Log log) {
this.logs.add(log); synchronized (logsLock) {
this.logs.add(log);
}
} }
@Override @Override
@ -230,35 +301,67 @@ public abstract class AbstractSession implements Session {
} }
@Override @Override
public void setFuture(final Future<?> future) { public void cancel() {
if (state == SessionState.RUNNING) {
FFmpegKit.cancel(sessionId);
}
}
/**
* Waits for all asynchronous messages to be transmitted until the given timeout.
*
* @param timeout wait timeout in milliseconds
*/
protected void waitForAsynchronousMessagesInTransmit(final int timeout) {
final long start = System.currentTimeMillis();
while (thereAreAsynchronousMessagesInTransmit() && (System.currentTimeMillis() < (start + timeout))) {
synchronized (this) {
try {
wait(100);
} catch (InterruptedException ignored) {
}
}
}
}
/**
* Sets the future created for this session.
*
* @param future future that runs this session asynchronously
*/
void setFuture(final Future<?> future) {
this.future = future; this.future = future;
} }
@Override /**
public void startRunning() { * Starts running the session.
*/
void startRunning() {
this.state = SessionState.RUNNING; this.state = SessionState.RUNNING;
this.startTime = new Date(); this.startTime = new Date();
} }
@Override /**
public void complete(final int returnCode) { * Completes running the session with the provided return code.
*
* @param returnCode return code of the execution
*/
void complete(final ReturnCode returnCode) {
this.returnCode = returnCode; this.returnCode = returnCode;
this.state = SessionState.COMPLETED; this.state = SessionState.COMPLETED;
this.endTime = new Date(); this.endTime = new Date();
} }
@Override /**
public void fail(final Exception exception) { * Ends running the session with a failure.
*
* @param exception execution received
*/
void fail(final Exception exception) {
this.failStackTrace = Exceptions.getStackTraceString(exception); this.failStackTrace = Exceptions.getStackTraceString(exception);
this.state = SessionState.FAILED; this.state = SessionState.FAILED;
this.endTime = new Date(); this.endTime = new Date();
} }
@Override
public void cancel() {
if (state == SessionState.RUNNING) {
FFmpegKit.cancel(sessionId);
}
}
} }

@ -35,7 +35,7 @@ public class AsyncFFmpegExecuteTask implements Runnable {
public void run() { public void run() {
FFmpegKitConfig.ffmpegExecute(ffmpegSession); FFmpegKitConfig.ffmpegExecute(ffmpegSession);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getGlobalExecuteCallbackFunction(); final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback();
if (globalExecuteCallbackFunction != null) { if (globalExecuteCallbackFunction != null) {
globalExecuteCallbackFunction.apply(ffmpegSession); globalExecuteCallbackFunction.apply(ffmpegSession);
} }

@ -20,7 +20,7 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
/** /**
* <p>Executes an FFprobe execution asynchronously. * <p>Executes an FFprobe session asynchronously.
*/ */
public class AsyncFFprobeExecuteTask implements Runnable { public class AsyncFFprobeExecuteTask implements Runnable {
private final FFprobeSession ffprobeSession; private final FFprobeSession ffprobeSession;
@ -35,7 +35,7 @@ public class AsyncFFprobeExecuteTask implements Runnable {
public void run() { public void run() {
FFmpegKitConfig.ffprobeExecute(ffprobeSession); FFmpegKitConfig.ffprobeExecute(ffprobeSession);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getGlobalExecuteCallbackFunction(); final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback();
if (globalExecuteCallbackFunction != null) { if (globalExecuteCallbackFunction != null) {
globalExecuteCallbackFunction.apply(ffprobeSession); globalExecuteCallbackFunction.apply(ffprobeSession);
} }

@ -28,7 +28,7 @@ public class AsyncGetMediaInformationTask implements Runnable {
private final Integer waitTimeout; private final Integer waitTimeout;
public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession) { public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession) {
this(mediaInformationSession, AbstractSession.DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT); this(mediaInformationSession, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
} }
public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession, final Integer waitTimeout) { public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession, final Integer waitTimeout) {
@ -41,7 +41,7 @@ public class AsyncGetMediaInformationTask implements Runnable {
public void run() { public void run() {
FFmpegKitConfig.getMediaInformationExecute(mediaInformationSession, waitTimeout); FFmpegKitConfig.getMediaInformationExecute(mediaInformationSession, waitTimeout);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getGlobalExecuteCallbackFunction(); final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback();
if (globalExecuteCallbackFunction != null) { if (globalExecuteCallbackFunction != null) {
globalExecuteCallbackFunction.apply(mediaInformationSession); globalExecuteCallbackFunction.apply(mediaInformationSession);
} }

@ -34,17 +34,17 @@ import static android.content.Context.CAMERA_SERVICE;
import static com.arthenica.ffmpegkit.FFmpegKitConfig.TAG; import static com.arthenica.ffmpegkit.FFmpegKitConfig.TAG;
/** /**
* <p>Helper class to find camera devices supported. * <p>Helper class to detect camera devices that can be used in
* <p>Note that camera devices can only be detected on Android API Level 24+. On older API levels * <code>FFmpeg</code>/<code>FFprobe</code> commands.
* an empty list will be returned.
*/ */
class CameraSupport { class CameraSupport {
/** /**
* <p>Compatibility method for extracting supported camera ids. * <p>Lists camera ids that can be used in <code>FFmpeg</code>/<code>FFprobe</code> commands.
* *
* @param context application context * @param context application context
* @return returns the list of supported camera ids * @return the list of supported camera ids on Android API Level 24+, an empty list on older
* API levels
*/ */
static List<String> extractSupportedCameraIds(final Context context) { static List<String> extractSupportedCameraIds(final Context context) {
final List<String> detectedCameraIdList = new ArrayList<>(); final List<String> detectedCameraIdList = new ArrayList<>();

@ -20,15 +20,31 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
/** /**
* <p>Callback function to receive execution results. * <p>Callback function invoked when an asynchronous session ends running.
* <p>Session has either {@link SessionState#COMPLETED} or {@link SessionState#FAILED} state when
* the callback is invoked.
* <p>If it has {@link SessionState#COMPLETED} state, <code>ReturnCode</code> should be checked to
* see the execution result.
* <p>If <code>getState</code> returns {@link SessionState#FAILED} then
* <code>getFailStackTrace</code> should be used to get the failure reason.
* <pre>
* switch (session.getState()) {
* case COMPLETED: {
* ReturnCode returnCode = session.getReturnCode();
* } break;
* case FAILED: {
* String failStackTrace = session.getFailStackTrace();
* } break;
* }
* </pre>
*/ */
@FunctionalInterface @FunctionalInterface
public interface ExecuteCallback { public interface ExecuteCallback {
/** /**
* <p>Called when an execution is completed. * <p>Called when an asynchronous session ends running.
* *
* @param session of with completed execution * @param session session
*/ */
void apply(final Session session); void apply(final Session session);

@ -21,18 +21,19 @@ package com.arthenica.ffmpegkit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService;
/** /**
* <p>Main class for FFmpeg operations. Supports synchronous {@link #execute(String...)} and * <p>Main class to run <code>FFmpeg</code> commands. Supports executing commands both
* asynchronous {@link #executeAsync(String, ExecuteCallback)} methods to execute FFmpeg commands. * synchronously and asynchronously.
* <pre> * <pre>
* FFmpegSession session = FFmpeg.execute("-i file1.mp4 -c:v libxvid file1.avi"); * FFmpegSession session = FFmpegKit.execute("-i file1.mp4 -c:v libxvid file1.avi");
* Log.i(Config.TAG, String.format("Command execution completed with %d.", session.getReturnCode()); *
* FFmpegSession asyncSession = FFmpegKit.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", executeCallback);
* </pre> * </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre> * <pre>
* FFmpegSession session = FFmpeg.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", executeCallback); * FFmpegSession asyncSession = FFmpegKit.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", executeCallback, logCallback, statisticsCallback);
* Log.i(Config.TAG, String.format("Asynchronous session %d started.", session.getSessionId()));
* </pre> * </pre>
*/ */
public class FFmpegKit { public class FFmpegKit {
@ -52,10 +53,10 @@ public class FFmpegKit {
* <p>Synchronously executes FFmpeg with arguments provided. * <p>Synchronously executes FFmpeg with arguments provided.
* *
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession execute(final String[] arguments) { public static FFmpegSession execute(final String[] arguments) {
final FFmpegSession session = new FFmpegSession(arguments, null, null, null); final FFmpegSession session = new FFmpegSession(arguments);
FFmpegKitConfig.ffmpegExecute(session); FFmpegKitConfig.ffmpegExecute(session);
@ -66,12 +67,12 @@ public class FFmpegKit {
* <p>Asynchronously executes FFmpeg with arguments provided. * <p>Asynchronously executes FFmpeg with arguments provided.
* *
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be notified when the execution is completed * @param executeCallback callback that will be called when the execution is completed
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String[] arguments, public static FFmpegSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback) { final ExecuteCallback executeCallback) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, null, null); final FFmpegSession session = new FFmpegSession(arguments, executeCallback);
FFmpegKitConfig.asyncFFmpegExecute(session); FFmpegKitConfig.asyncFFmpegExecute(session);
@ -82,10 +83,10 @@ public class FFmpegKit {
* <p>Asynchronously executes FFmpeg with arguments provided. * <p>Asynchronously executes FFmpeg with arguments provided.
* *
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive log entries * @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String[] arguments, public static FFmpegSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
@ -102,17 +103,16 @@ public class FFmpegKit {
* <p>Asynchronously executes FFmpeg with arguments provided. * <p>Asynchronously executes FFmpeg with arguments provided.
* *
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param executor executor that will be used to run this asynchronous operation * @param executorService executor service that will be used to run this asynchronous operation
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String[] arguments, public static FFmpegSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final Executor executor) { final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, null, null); final FFmpegSession session = new FFmpegSession(arguments, executeCallback);
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(session); FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
executor.execute(asyncFFmpegExecuteTask);
return session; return session;
} }
@ -121,32 +121,31 @@ public class FFmpegKit {
* <p>Asynchronously executes FFmpeg with arguments provided. * <p>Asynchronously executes FFmpeg with arguments provided.
* *
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive log entries * @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @param executor executor that will be used to run this asynchronous operation * @param executorService executor service that will be used to run this asynchronous operation
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String[] arguments, public static FFmpegSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback, final StatisticsCallback statisticsCallback,
final Executor executor) { final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, logCallback, statisticsCallback); final FFmpegSession session = new FFmpegSession(arguments, executeCallback, logCallback, statisticsCallback);
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(session); FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
executor.execute(asyncFFmpegExecuteTask);
return session; return session;
} }
/** /**
* <p>Synchronously executes FFmpeg command provided. Space character is used to split command * <p>Synchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single and double quote characters to specify arguments inside * into arguments. You can use single or double quote characters to specify arguments inside
* your command. * your command.
* *
* @param command FFmpeg command * @param command FFmpeg command
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession execute(final String command) { public static FFmpegSession execute(final String command) {
return execute(parseArguments(command)); return execute(parseArguments(command));
@ -154,12 +153,12 @@ public class FFmpegKit {
/** /**
* <p>Asynchronously executes FFmpeg command provided. Space character is used to split command * <p>Asynchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single and double quote characters to specify arguments inside * into arguments. You can use single or double quote characters to specify arguments inside
* your command. * your command.
* *
* @param command FFmpeg command * @param command FFmpeg command
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String command, public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback) { final ExecuteCallback executeCallback) {
@ -168,14 +167,14 @@ public class FFmpegKit {
/** /**
* <p>Asynchronously executes FFmpeg command provided. Space character is used to split command * <p>Asynchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single and double quote characters to specify arguments inside * into arguments. You can use single or double quote characters to specify arguments inside
* your command. * your command.
* *
* @param command FFmpeg command * @param command FFmpeg command
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive log entries * @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String command, public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
@ -186,52 +185,50 @@ public class FFmpegKit {
/** /**
* <p>Asynchronously executes FFmpeg command provided. Space character is used to split command * <p>Asynchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single and double quote characters to specify arguments inside * into arguments. You can use single or double quote characters to specify arguments inside
* your command. * your command.
* *
* @param command FFmpeg command * @param command FFmpeg command
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param executor executor that will be used to run this asynchronous operation * @param executorService executor service that will be used to run this asynchronous operation
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String command, public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final Executor executor) { final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(parseArguments(command), executeCallback, null, null); final FFmpegSession session = new FFmpegSession(parseArguments(command), executeCallback);
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(session); FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
executor.execute(asyncFFmpegExecuteTask);
return session; return session;
} }
/** /**
* <p>Asynchronously executes FFmpeg command provided. Space character is used to split command * <p>Asynchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single and double quote characters to specify arguments inside * into arguments. You can use single or double quote characters to specify arguments inside
* your command. * your command.
* *
* @param command FFmpeg command * @param command FFmpeg command
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive log entries * @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @param executor executor that will be used to run this asynchronous operation * @param executorService executor service that will be used to run this asynchronous operation
* @return ffmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String command, public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback, final StatisticsCallback statisticsCallback,
final Executor executor) { final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(parseArguments(command), executeCallback, logCallback, statisticsCallback); final FFmpegSession session = new FFmpegSession(parseArguments(command), executeCallback, logCallback, statisticsCallback);
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(session); FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
executor.execute(asyncFFmpegExecuteTask);
return session; return session;
} }
/** /**
* <p>Cancels all ongoing executions. * <p>Cancels all running sessions.
* *
* <p>This function does not wait for termination to complete and returns immediately. * <p>This function does not wait for termination to complete and returns immediately.
*/ */
@ -240,13 +237,13 @@ public class FFmpegKit {
/* /*
* ZERO (0) IS A SPECIAL SESSION ID * ZERO (0) IS A SPECIAL SESSION ID
* WHEN IT IS PASSED TO THIS METHOD, A SIGINT IS GENERATED WHICH CANCELS ALL ONGOING * WHEN IT IS PASSED TO THIS METHOD, A SIGINT IS GENERATED WHICH CANCELS ALL ONGOING
* EXECUTIONS * SESSIONS
*/ */
FFmpegKitConfig.nativeFFmpegCancel(0); FFmpegKitConfig.nativeFFmpegCancel(0);
} }
/** /**
* <p>Cancels the given execution. * <p>Cancels the session specified with <code>sessionId</code>.
* *
* <p>This function does not wait for termination to complete and returns immediately. * <p>This function does not wait for termination to complete and returns immediately.
* *
@ -257,7 +254,7 @@ public class FFmpegKit {
} }
/** /**
* <p>Lists all FFmpeg sessions in the session history * <p>Lists all FFmpeg sessions in the session history.
* *
* @return all FFmpeg sessions in the session history * @return all FFmpeg sessions in the session history
*/ */
@ -266,7 +263,8 @@ public class FFmpegKit {
} }
/** /**
* <p>Parses the given command into arguments. * <p>Parses the given command into arguments. Uses space character to split the arguments.
* Supports single and double quote characters.
* *
* @param command string command * @param command string command
* @return array of arguments * @return array of arguments
@ -323,10 +321,10 @@ public class FFmpegKit {
} }
/** /**
* <p>Combines arguments into a string. * <p>Concatenates arguments into a string adding a space character between two arguments.
* *
* @param arguments arguments * @param arguments arguments
* @return string containing all arguments * @return concatenated string containing all arguments
*/ */
static String argumentsToString(final String[] arguments) { static String argumentsToString(final String[] arguments) {
if (arguments == null) { if (arguments == null) {

@ -40,7 +40,6 @@ import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -48,58 +47,43 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
/** /**
* <p>This class is used to configure FFmpegKit library and tools coming with it. * <p>Configuration class of <code>FFmpegKit</code> library. Allows customizing the global library
* * options. Provides helper methods to support additional resources.
* <p>1. {@link LogCallback}: This class redirects FFmpeg/FFprobe output to Logcat by default. As
* an alternative, it is possible not to print messages to Logcat and pass them to a
* {@link LogCallback} function. This function can decide whether to print these logs, show them
* inside another container or ignore them.
*
* <p>2. {@link #setLogLevel(Level)}/{@link #getLogLevel()}: Use this methods to set/get
* FFmpeg/FFprobe log severity.
*
* <p>3. {@link StatisticsCallback}: It is possible to receive statistics about an ongoing
* operation by defining a {@link StatisticsCallback} function or by calling
* {@link #getLastReceivedStatistics()} method.
*
* <p>4. Font configuration: It is possible to register custom fonts with
* {@link #setFontconfigConfigurationPath(String)} and
* {@link #setFontDirectory(Context, String, Map)} methods.
*/ */
public class FFmpegKitConfig { public class FFmpegKitConfig {
/** /**
* The tag used for logging. * The tag used for logging.
*/ */
public static final String TAG = "ffmpeg-kit"; static final String TAG = "ffmpeg-kit";
/** /**
* Prefix of named pipes created by ffmpeg kit. * Prefix of named pipes created by ffmpeg kit.
*/ */
public static final String FFMPEG_KIT_NAMED_PIPE_PREFIX = "fk_pipe_"; static final String FFMPEG_KIT_NAMED_PIPE_PREFIX = "fk_pipe_";
/** /**
* Generates ids for named ffmpeg kit pipes. * Generates ids for named ffmpeg kit pipes.
*/ */
private static final AtomicLong pipeIndexGenerator; private static final AtomicLong pipeIndexGenerator;
/* SESSION HISTORY VARIABLES */ private static Level activeLogLevel;
/* Session history variables */
private static int sessionHistorySize; private static int sessionHistorySize;
private static final Map<Long, Session> sessionHistoryMap; private static final Map<Long, Session> sessionHistoryMap;
private static final Queue<Session> sessionHistoryQueue; private static final List<Session> sessionHistoryList;
private static final Object sessionHistoryLock; private static final Object sessionHistoryLock;
/** private static int asyncConcurrencyLimit;
* Executor service for async executions.
*/
private static ExecutorService asyncExecutorService; private static ExecutorService asyncExecutorService;
/* Global callbacks */
private static LogCallback globalLogCallbackFunction; private static LogCallback globalLogCallbackFunction;
private static StatisticsCallback globalStatisticsCallbackFunction; private static StatisticsCallback globalStatisticsCallbackFunction;
private static ExecuteCallback globalExecuteCallbackFunction; private static ExecuteCallback globalExecuteCallbackFunction;
private static Level activeLogLevel;
private static int asyncConcurrencyLimit;
private static final SparseArray<ParcelFileDescriptor> pfdMap; private static final SparseArray<ParcelFileDescriptor> pfdMap;
private static LogRedirectionStrategy logRedirectionStrategy; private static LogRedirectionStrategy globalLogRedirectionStrategy;
static { static {
@ -107,92 +91,44 @@ public class FFmpegKitConfig {
android.util.Log.i(FFmpegKitConfig.TAG, "Loading ffmpeg-kit."); android.util.Log.i(FFmpegKitConfig.TAG, "Loading ffmpeg-kit.");
boolean nativeFFmpegLoaded = false; final boolean nativeFFmpegTriedAndFailed = NativeLoader.loadFFmpeg();
boolean nativeFFmpegTriedAndFailed = false;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
/* LOADING LIBRARIES MANUALLY ON API < 21 */
final List<String> externalLibrariesEnabled = getExternalLibraries();
if (externalLibrariesEnabled.contains("tesseract") || externalLibrariesEnabled.contains("x265") || externalLibrariesEnabled.contains("snappy") || externalLibrariesEnabled.contains("openh264") || externalLibrariesEnabled.contains("rubberband")) {
System.loadLibrary("c++_shared");
}
if (AbiDetect.ARM_V7A.equals(AbiDetect.getNativeAbi())) {
try {
System.loadLibrary("avutil_neon");
System.loadLibrary("swscale_neon");
System.loadLibrary("swresample_neon");
System.loadLibrary("avcodec_neon");
System.loadLibrary("avformat_neon");
System.loadLibrary("avfilter_neon");
System.loadLibrary("avdevice_neon");
nativeFFmpegLoaded = true;
} catch (final UnsatisfiedLinkError e) {
android.util.Log.i(FFmpegKitConfig.TAG, String.format("NEON supported armeabi-v7a ffmpeg library not found. Loading default armeabi-v7a library.%s", Exceptions.getStackTraceString(e)));
nativeFFmpegTriedAndFailed = true;
}
}
if (!nativeFFmpegLoaded) {
System.loadLibrary("avutil");
System.loadLibrary("swscale");
System.loadLibrary("swresample");
System.loadLibrary("avcodec");
System.loadLibrary("avformat");
System.loadLibrary("avfilter");
System.loadLibrary("avdevice");
}
}
/* ALL FFMPEG-KIT LIBRARIES LOADED AT STARTUP */ /* ALL FFMPEG-KIT LIBRARIES LOADED AT STARTUP */
Abi.class.getName(); Abi.class.getName();
FFmpegKit.class.getName(); FFmpegKit.class.getName();
FFprobeKit.class.getName(); FFprobeKit.class.getName();
boolean nativeFFmpegKitLoaded = false; NativeLoader.loadFFmpegKit(nativeFFmpegTriedAndFailed);
if (!nativeFFmpegTriedAndFailed && AbiDetect.ARM_V7A.equals(AbiDetect.getNativeAbi())) {
try {
/*
* THE TRY TO LOAD ARM-V7A-NEON FIRST. IF NOT LOAD DEFAULT ARM-V7A
*/
System.loadLibrary("ffmpegkit_armv7a_neon"); android.util.Log.i(FFmpegKitConfig.TAG, String.format("Loaded ffmpeg-kit-%s-%s-%s-%s.", NativeLoader.loadPackageName(), NativeLoader.loadAbi(), NativeLoader.loadVersion(), NativeLoader.loadBuildDate()));
nativeFFmpegKitLoaded = true;
AbiDetect.setArmV7aNeonLoaded();
} catch (final UnsatisfiedLinkError e) {
android.util.Log.i(FFmpegKitConfig.TAG, String.format("NEON supported armeabi-v7a ffmpegkit library not found. Loading default armeabi-v7a library.%s", Exceptions.getStackTraceString(e)));
}
}
if (!nativeFFmpegKitLoaded) { pipeIndexGenerator = new AtomicLong(1);
System.loadLibrary("ffmpegkit");
}
android.util.Log.i(FFmpegKitConfig.TAG, String.format("Loaded ffmpeg-kit-%s-%s-%s-%s.", getPackageName(), AbiDetect.getAbi(), getVersion(), getBuildDate())); /* NATIVE LOG LEVEL IS RECEIVED ONLY ON STARTUP */
activeLogLevel = Level.from(NativeLoader.loadLogLevel());
pipeIndexGenerator = new AtomicLong(1);
asyncConcurrencyLimit = 10; asyncConcurrencyLimit = 10;
asyncExecutorService = Executors.newFixedThreadPool(asyncConcurrencyLimit); asyncExecutorService = Executors.newFixedThreadPool(asyncConcurrencyLimit);
/* NATIVE LOG LEVEL IS RECEIVED ONLY ON STARTUP */
activeLogLevel = Level.from(getNativeLogLevel());
sessionHistorySize = 10; sessionHistorySize = 10;
sessionHistoryMap = Collections.synchronizedMap(new LinkedHashMap<Long, Session>() { sessionHistoryMap = new LinkedHashMap<Long, Session>() {
@Override @Override
protected boolean removeEldestEntry(Map.Entry<Long, Session> eldest) { protected boolean removeEldestEntry(Map.Entry<Long, Session> eldest) {
return (this.size() > sessionHistorySize); return (this.size() > sessionHistorySize);
} }
}); };
sessionHistoryQueue = new LinkedList<>(); sessionHistoryList = new LinkedList<>();
sessionHistoryLock = new Object(); sessionHistoryLock = new Object();
globalLogCallbackFunction = null;
globalStatisticsCallbackFunction = null;
globalExecuteCallbackFunction = null;
pfdMap = new SparseArray<>(); pfdMap = new SparseArray<>();
logRedirectionStrategy = LogRedirectionStrategy.PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED; globalLogRedirectionStrategy = LogRedirectionStrategy.PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED;
enableRedirection(); NativeLoader.enableRedirection();
} }
/** /**
@ -203,13 +139,11 @@ public class FFmpegKitConfig {
/** /**
* <p>Enables log and statistics redirection. * <p>Enables log and statistics redirection.
* <p>When redirection is not enabled FFmpeg/FFprobe logs are printed to stderr. By enabling *
* redirection, they are routed to Logcat and can be routed further to a callback function. * <p>When redirection is enabled FFmpeg/FFprobe logs are redirected to Logcat and sessions
* <p>Statistics redirection behaviour is similar. Statistics are not printed at all if * collect log and statistics entries for the executions. It is possible to define global or
* redirection is not enabled. If it is enabled then it is possible to define a statistics * session specific log/statistics callbacks as well.
* callback function but if you don't, they are not printed anywhere and only saved as *
* <code>lastReceivedStatistics</code> data which can be polled with
* {@link #getLastReceivedStatistics()}.
* <p>Note that redirection is enabled by default. If you do not want to use its functionality * <p>Note that redirection is enabled by default. If you do not want to use its functionality
* please use {@link #disableRedirection()} to disable it. * please use {@link #disableRedirection()} to disable it.
*/ */
@ -219,17 +153,22 @@ public class FFmpegKitConfig {
/** /**
* <p>Disables log and statistics redirection. * <p>Disables log and statistics redirection.
*
* <p>When redirection is disabled logs are printed to stderr, all logs and statistics
* callbacks are disabled and <code>FFprobe</code>'s <code>getMediaInformation</code> methods
* do not work.
*/ */
public static void disableRedirection() { public static void disableRedirection() {
disableNativeRedirection(); disableNativeRedirection();
} }
/** /**
* <p>Log redirection method called by JNI/native part. * <p>Log redirection method called by the native library.
* *
* @param sessionId id of the session that generated this log, 0 by default * @param sessionId id of the session that generated this log, 0 for logs that do not belong
* to a specific session
* @param levelValue log level as defined in {@link Level} * @param levelValue log level as defined in {@link Level}
* @param logMessage redirected log message * @param logMessage redirected log message data
*/ */
private static void log(final long sessionId, final int levelValue, final byte[] logMessage) { private static void log(final long sessionId, final int levelValue, final byte[] logMessage) {
final Level level = Level.from(levelValue); final Level level = Level.from(levelValue);
@ -237,7 +176,7 @@ public class FFmpegKitConfig {
final Log log = new Log(sessionId, level, text); final Log log = new Log(sessionId, level, text);
boolean globalCallbackDefined = false; boolean globalCallbackDefined = false;
boolean sessionCallbackDefined = false; boolean sessionCallbackDefined = false;
LogRedirectionStrategy activeLogRedirectionStrategy = FFmpegKitConfig.logRedirectionStrategy; LogRedirectionStrategy activeLogRedirectionStrategy = globalLogRedirectionStrategy;
// AV_LOG_STDERR logs are always redirected // AV_LOG_STDERR logs are always redirected
if ((activeLogLevel == Level.AV_LOG_QUIET && levelValue != Level.AV_LOG_STDERR.getValue()) || levelValue > activeLogLevel.getValue()) { if ((activeLogLevel == Level.AV_LOG_QUIET && levelValue != Level.AV_LOG_STDERR.getValue()) || levelValue > activeLogLevel.getValue()) {
@ -254,7 +193,7 @@ public class FFmpegKitConfig {
sessionCallbackDefined = true; sessionCallbackDefined = true;
try { try {
// NOTIFY SESSION CALLBACK IF DEFINED // NOTIFY SESSION CALLBACK DEFINED
session.getLogCallback().apply(log); session.getLogCallback().apply(log);
} catch (final Exception e) { } catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session LogCallback block.%s", Exceptions.getStackTraceString(e))); android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session LogCallback block.%s", Exceptions.getStackTraceString(e)));
@ -267,7 +206,7 @@ public class FFmpegKitConfig {
globalCallbackDefined = true; globalCallbackDefined = true;
try { try {
// NOTIFY GLOBAL CALLBACK IF DEFINED // NOTIFY GLOBAL CALLBACK DEFINED
globalLogCallbackFunction.apply(log); globalLogCallbackFunction.apply(log);
} catch (final Exception e) { } catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global LogCallback block.%s", Exceptions.getStackTraceString(e))); android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global LogCallback block.%s", Exceptions.getStackTraceString(e)));
@ -295,6 +234,8 @@ public class FFmpegKitConfig {
return; return;
} }
} }
case ALWAYS_PRINT_LOGS: {
}
} }
// PRINT LOGS // PRINT LOGS
@ -332,11 +273,11 @@ public class FFmpegKitConfig {
} }
/** /**
* <p>Statistics redirection method called by JNI/native part. * <p>Statistics redirection method called by the native library.
* *
* @param sessionId id of the session that generated this statistics, 0 by default * @param sessionId id of the session that generated this statistics, 0 by default
* @param videoFrameNumber last processed frame number for videos * @param videoFrameNumber frame number for videos
* @param videoFps frames processed per second for videos * @param videoFps frames per second value for videos
* @param videoQuality quality of the video stream * @param videoQuality quality of the video stream
* @param size size in bytes * @param size size in bytes
* @param time processed duration in milliseconds * @param time processed duration in milliseconds
@ -349,13 +290,14 @@ public class FFmpegKitConfig {
final Statistics statistics = new Statistics(sessionId, videoFrameNumber, videoFps, videoQuality, size, time, bitrate, speed); final Statistics statistics = new Statistics(sessionId, videoFrameNumber, videoFps, videoQuality, size, time, bitrate, speed);
final Session session = getSession(sessionId); final Session session = getSession(sessionId);
if (session != null) { if (session != null && session.isFFmpeg()) {
session.addStatistics(statistics); FFmpegSession ffmpegSession = (FFmpegSession) session;
ffmpegSession.addStatistics(statistics);
if (session.getStatisticsCallback() != null) { if (ffmpegSession.getStatisticsCallback() != null) {
try { try {
// NOTIFY SESSION CALLBACK IF DEFINED // NOTIFY SESSION CALLBACK IF DEFINED
session.getStatisticsCallback().apply(statistics); ffmpegSession.getStatisticsCallback().apply(statistics);
} catch (final Exception e) { } catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session StatisticsCallback block.%s", Exceptions.getStackTraceString(e))); android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session StatisticsCallback block.%s", Exceptions.getStackTraceString(e)));
} }
@ -373,24 +315,10 @@ public class FFmpegKitConfig {
} }
} }
/**
* <p>Returns the last received statistics data.
*
* @return last received statistics data or null if no statistics data is available
*/
public static Statistics getLastReceivedStatistics() {
final Session lastSession = getLastSession();
if (lastSession != null) {
return lastSession.getStatistics().peek();
} else {
return null;
}
}
/** /**
* <p>Sets and overrides <code>fontconfig</code> configuration directory. * <p>Sets and overrides <code>fontconfig</code> configuration directory.
* *
* @param path directory which contains fontconfig configuration (fonts.conf) * @param path directory that contains fontconfig configuration (fonts.conf)
* @return zero on success, non-zero on error * @return zero on success, non-zero on error
*/ */
public static int setFontconfigConfigurationPath(final String path) { public static int setFontconfigConfigurationPath(final String path) {
@ -402,10 +330,11 @@ public class FFmpegKitConfig {
* filters. * filters.
* *
* <p>Note that you need to build <code>FFmpegKit</code> with <code>fontconfig</code> * <p>Note that you need to build <code>FFmpegKit</code> with <code>fontconfig</code>
* enabled or use a prebuilt package with <code>fontconfig</code> inside to use this feature. * enabled or use a prebuilt package with <code>fontconfig</code> inside to be able to use
* fonts in <code>FFmpeg</code>.
* *
* @param context application context to access application data * @param context application context to access application data
* @param fontDirectoryPath directory which contains fonts (.ttf and .otf files) * @param fontDirectoryPath directory that contains fonts (.ttf and .otf files)
* @param fontNameMapping custom font name mappings, useful to access your fonts with more * @param fontNameMapping custom font name mappings, useful to access your fonts with more
* friendly names * friendly names
*/ */
@ -418,10 +347,11 @@ public class FFmpegKitConfig {
* to use in FFmpeg filters. * to use in FFmpeg filters.
* *
* <p>Note that you need to build <code>FFmpegKit</code> with <code>fontconfig</code> * <p>Note that you need to build <code>FFmpegKit</code> with <code>fontconfig</code>
* enabled or use a prebuilt package with <code>fontconfig</code> inside to use this feature. * enabled or use a prebuilt package with <code>fontconfig</code> inside to be able to use
* fonts in <code>FFmpeg</code>.
* *
* @param context application context to access application data * @param context application context to access application data
* @param fontDirectoryList list of directories which contain fonts (.ttf and .otf files) * @param fontDirectoryList list of directories that contain fonts (.ttf and .otf files)
* @param fontNameMapping custom font name mappings, useful to access your fonts with more * @param fontNameMapping custom font name mappings, useful to access your fonts with more
* friendly names * friendly names
*/ */
@ -506,24 +436,6 @@ public class FFmpegKitConfig {
} }
} }
/**
* <p>Returns <code>FFmpegKit</code> package name.
*
* @return FFmpegKit package name
*/
public static String getPackageName() {
return Packages.getPackageName();
}
/**
* <p>Returns the list of supported external libraries.
*
* @return list of supported external libraries
*/
public static List<String> getExternalLibraries() {
return Packages.getExternalLibraries();
}
/** /**
* <p>Creates a new named pipe to use in <code>FFmpeg</code> operations. * <p>Creates a new named pipe to use in <code>FFmpeg</code> operations.
* *
@ -563,7 +475,7 @@ public class FFmpegKitConfig {
/** /**
* <p>Closes a previously created <code>FFmpeg</code> pipe. * <p>Closes a previously created <code>FFmpeg</code> pipe.
* *
* @param ffmpegPipePath full path of ffmpeg pipe * @param ffmpegPipePath full path of the FFmpeg pipe
*/ */
public static void closeFFmpegPipe(final String ffmpegPipePath) { public static void closeFFmpegPipe(final String ffmpegPipePath) {
final File file = new File(ffmpegPipePath); final File file = new File(ffmpegPipePath);
@ -573,13 +485,14 @@ public class FFmpegKitConfig {
} }
/** /**
* Returns the list of camera ids supported. * Returns the list of camera ids supported. These devices can be used in <code>FFmpeg</code>
* commands.
* *
* <p>Note that this method requires API Level >= 24. On older API levels it returns an empty * <p>Note that this method requires API Level >= 24. On older API levels it returns an empty
* list. * list.
* *
* @param context application context * @param context application context
* @return the list of camera ids supported or an empty list if no supported cameras are found * @return list of camera ids supported or an empty list if no supported cameras are found
*/ */
public static List<String> getSupportedCameraIds(final Context context) { public static List<String> getSupportedCameraIds(final Context context) {
final List<String> detectedCameraIdList = new ArrayList<>(); final List<String> detectedCameraIdList = new ArrayList<>();
@ -592,9 +505,9 @@ public class FFmpegKitConfig {
} }
/** /**
* <p>Returns FFmpeg version bundled within the library. * <p>Returns the version of FFmpeg bundled within <code>FFmpegKit</code> library.
* *
* @return FFmpeg version * @return the version of FFmpeg
*/ */
public static String getFFmpegVersion() { public static String getFFmpegVersion() {
return getNativeFFmpegVersion(); return getNativeFFmpegVersion();
@ -632,41 +545,8 @@ public class FFmpegKitConfig {
} }
/** /**
* <p>Returns the return code of the last completed execution. * <p>Prints the given string to Logcat using the given priority. If string provided is bigger
* * than the Logcat buffer, the string is printed in multiple lines.
* @return return code of the last completed execution
*/
public static int getLastReturnCode() {
final Session lastSession = getLastSession();
if (lastSession != null) {
return lastSession.getReturnCode();
} else {
return 0;
}
}
/**
* <p>Returns the log output of the last executed FFmpeg/FFprobe command.
*
* <p>Please note that disabling redirection using {@link FFmpegKitConfig#disableRedirection()}
* method also disables this functionality.
*
* @return output of the last executed command
*/
public static String getLastCommandOutput() {
final Session lastSession = getLastSession();
if (lastSession != null) {
// REPLACING CH(13) WITH CH(10)
return lastSession.getAllLogsAsString().replace('\r', '\n');
} else {
return "";
}
}
/**
* <p>Prints the output of the last executed FFmpeg/FFprobe command to the Logcat at the
* specified priority.
* *
* @param logPriority one of {@link android.util.Log#VERBOSE}, * @param logPriority one of {@link android.util.Log#VERBOSE},
* {@link android.util.Log#DEBUG}, * {@link android.util.Log#DEBUG},
@ -674,26 +554,27 @@ public class FFmpegKitConfig {
* {@link android.util.Log#WARN}, * {@link android.util.Log#WARN},
* {@link android.util.Log#ERROR}, * {@link android.util.Log#ERROR},
* {@link android.util.Log#ASSERT} * {@link android.util.Log#ASSERT}
* @param string string to be printed
*/ */
public static void printLastCommandOutput(final int logPriority) { public static void printToLogcat(final int logPriority, final String string) {
final int LOGGER_ENTRY_MAX_LEN = 4 * 1000; final int LOGGER_ENTRY_MAX_LEN = 4 * 1000;
String buffer = getLastCommandOutput(); String remainingString = string;
do { do {
if (buffer.length() <= LOGGER_ENTRY_MAX_LEN) { if (remainingString.length() <= LOGGER_ENTRY_MAX_LEN) {
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, buffer); android.util.Log.println(logPriority, FFmpegKitConfig.TAG, remainingString);
buffer = ""; remainingString = "";
} else { } else {
final int index = buffer.substring(0, LOGGER_ENTRY_MAX_LEN).lastIndexOf('\n'); final int index = remainingString.substring(0, LOGGER_ENTRY_MAX_LEN).lastIndexOf('\n');
if (index < 0) { if (index < 0) {
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, buffer.substring(0, LOGGER_ENTRY_MAX_LEN)); android.util.Log.println(logPriority, FFmpegKitConfig.TAG, remainingString.substring(0, LOGGER_ENTRY_MAX_LEN));
buffer = buffer.substring(LOGGER_ENTRY_MAX_LEN); remainingString = remainingString.substring(LOGGER_ENTRY_MAX_LEN);
} else { } else {
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, buffer.substring(0, index)); android.util.Log.println(logPriority, FFmpegKitConfig.TAG, remainingString.substring(0, index));
buffer = buffer.substring(index); remainingString = remainingString.substring(index);
} }
} }
} while (buffer.length() > 0); } while (remainingString.length() > 0);
} }
/** /**
@ -708,26 +589,27 @@ public class FFmpegKitConfig {
} }
/** /**
* <p>Registers a new ignored signal. Ignored signals are not handled by the library. * <p>Registers a new ignored signal. Ignored signals are not handled by <code>FFmpegKit</code>
* library.
* *
* @param signal signal number to ignore * @param signal signal to be ignored
*/ */
public static void ignoreSignal(final Signal signal) { public static void ignoreSignal(final Signal signal) {
ignoreNativeSignal(signal.getValue()); ignoreNativeSignal(signal.getValue());
} }
/** /**
* <p>Synchronously executes the ffmpeg session provided. * <p>Synchronously executes the FFmpeg session provided.
* *
* @param ffmpegSession FFmpeg session which includes command options/arguments * @param ffmpegSession FFmpeg session which includes command options/arguments
*/ */
static void ffmpegExecute(final FFmpegSession ffmpegSession) { public static void ffmpegExecute(final FFmpegSession ffmpegSession) {
addSession(ffmpegSession); addSession(ffmpegSession);
ffmpegSession.startRunning(); ffmpegSession.startRunning();
try { try {
final int returnCode = nativeFFmpegExecute(ffmpegSession.getSessionId(), ffmpegSession.getArguments()); final int returnCode = nativeFFmpegExecute(ffmpegSession.getSessionId(), ffmpegSession.getArguments());
ffmpegSession.complete(returnCode); ffmpegSession.complete(new ReturnCode(returnCode));
} catch (final Exception e) { } catch (final Exception e) {
ffmpegSession.fail(e); ffmpegSession.fail(e);
android.util.Log.w(FFmpegKitConfig.TAG, String.format("FFmpeg execute failed: %s.%s", FFmpegKit.argumentsToString(ffmpegSession.getArguments()), Exceptions.getStackTraceString(e))); android.util.Log.w(FFmpegKitConfig.TAG, String.format("FFmpeg execute failed: %s.%s", FFmpegKit.argumentsToString(ffmpegSession.getArguments()), Exceptions.getStackTraceString(e)));
@ -735,17 +617,17 @@ public class FFmpegKitConfig {
} }
/** /**
* <p>Synchronously executes the ffprobe session provided. * <p>Synchronously executes the FFprobe session provided.
* *
* @param ffprobeSession FFprobe session which includes command options/arguments * @param ffprobeSession FFprobe session which includes command options/arguments
*/ */
static void ffprobeExecute(final FFprobeSession ffprobeSession) { public static void ffprobeExecute(final FFprobeSession ffprobeSession) {
addSession(ffprobeSession); addSession(ffprobeSession);
ffprobeSession.startRunning(); ffprobeSession.startRunning();
try { try {
final int returnCode = nativeFFprobeExecute(ffprobeSession.getSessionId(), ffprobeSession.getArguments()); final int returnCode = nativeFFprobeExecute(ffprobeSession.getSessionId(), ffprobeSession.getArguments());
ffprobeSession.complete(returnCode); ffprobeSession.complete(new ReturnCode(returnCode));
} catch (final Exception e) { } catch (final Exception e) {
ffprobeSession.fail(e); ffprobeSession.fail(e);
android.util.Log.w(FFmpegKitConfig.TAG, String.format("FFprobe execute failed: %s.%s", FFmpegKit.argumentsToString(ffprobeSession.getArguments()), Exceptions.getStackTraceString(e))); android.util.Log.w(FFmpegKitConfig.TAG, String.format("FFprobe execute failed: %s.%s", FFmpegKit.argumentsToString(ffprobeSession.getArguments()), Exceptions.getStackTraceString(e)));
@ -758,15 +640,16 @@ public class FFmpegKitConfig {
* @param mediaInformationSession media information session which includes command options/arguments * @param mediaInformationSession media information session which includes command options/arguments
* @param waitTimeout max time to wait until media information is transmitted * @param waitTimeout max time to wait until media information is transmitted
*/ */
static void getMediaInformationExecute(final MediaInformationSession mediaInformationSession, final int waitTimeout) { public static void getMediaInformationExecute(final MediaInformationSession mediaInformationSession, final int waitTimeout) {
addSession(mediaInformationSession); addSession(mediaInformationSession);
mediaInformationSession.startRunning(); mediaInformationSession.startRunning();
try { try {
final int returnCode = nativeFFprobeExecute(mediaInformationSession.getSessionId(), mediaInformationSession.getArguments()); final int returnCodeValue = nativeFFprobeExecute(mediaInformationSession.getSessionId(), mediaInformationSession.getArguments());
final ReturnCode returnCode = new ReturnCode(returnCodeValue);
mediaInformationSession.complete(returnCode); mediaInformationSession.complete(returnCode);
if (returnCode == ReturnCode.SUCCESS) { if (returnCode.isSuccess()) {
MediaInformation mediaInformation = MediaInformationParser.fromWithError(mediaInformationSession.getAllLogsAsString(waitTimeout)); MediaInformation mediaInformation = MediaInformationJsonParser.fromWithError(mediaInformationSession.getAllLogsAsString(waitTimeout));
mediaInformationSession.setMediaInformation(mediaInformation); mediaInformationSession.setMediaInformation(mediaInformation);
} }
} catch (final Exception e) { } catch (final Exception e) {
@ -776,51 +659,88 @@ public class FFmpegKitConfig {
} }
/** /**
* <p>Asynchronously executes the ffmpeg session provided. * <p>Asynchronously executes the FFmpeg session provided.
* *
* @param ffmpegSession FFmpeg session which includes command options/arguments * @param ffmpegSession FFmpeg session which includes command options/arguments
*/ */
static void asyncFFmpegExecute(final FFmpegSession ffmpegSession) { public static void asyncFFmpegExecute(final FFmpegSession ffmpegSession) {
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(ffmpegSession); AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(ffmpegSession);
Future<?> future = asyncExecutorService.submit(asyncFFmpegExecuteTask); Future<?> future = asyncExecutorService.submit(asyncFFmpegExecuteTask);
ffmpegSession.setFuture(future); ffmpegSession.setFuture(future);
} }
/** /**
* <p>Asynchronously executes the ffprobe session provided. * <p>Asynchronously executes the FFmpeg session provided.
*
* @param ffmpegSession FFmpeg session which includes command options/arguments
* @param executorService executor service that will be used to run this asynchronous operation
*/
public static void asyncFFmpegExecute(final FFmpegSession ffmpegSession, final ExecutorService executorService) {
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(ffmpegSession);
Future<?> future = executorService.submit(asyncFFmpegExecuteTask);
ffmpegSession.setFuture(future);
}
/**
* <p>Asynchronously executes the FFprobe session provided.
* *
* @param ffprobeSession FFprobe session which includes command options/arguments * @param ffprobeSession FFprobe session which includes command options/arguments
*/ */
static void asyncFFprobeExecute(final FFprobeSession ffprobeSession) { public static void asyncFFprobeExecute(final FFprobeSession ffprobeSession) {
AsyncFFprobeExecuteTask asyncFFmpegExecuteTask = new AsyncFFprobeExecuteTask(ffprobeSession); AsyncFFprobeExecuteTask asyncFFmpegExecuteTask = new AsyncFFprobeExecuteTask(ffprobeSession);
Future<?> future = asyncExecutorService.submit(asyncFFmpegExecuteTask); Future<?> future = asyncExecutorService.submit(asyncFFmpegExecuteTask);
ffprobeSession.setFuture(future); ffprobeSession.setFuture(future);
} }
/**
* <p>Asynchronously executes the FFprobe session provided.
*
* @param ffprobeSession FFprobe session which includes command options/arguments
* @param executorService executor service that will be used to run this asynchronous operation
*/
public static void asyncFFprobeExecute(final FFprobeSession ffprobeSession, final ExecutorService executorService) {
AsyncFFprobeExecuteTask asyncFFmpegExecuteTask = new AsyncFFprobeExecuteTask(ffprobeSession);
Future<?> future = executorService.submit(asyncFFmpegExecuteTask);
ffprobeSession.setFuture(future);
}
/** /**
* <p>Asynchronously executes the media information session provided. * <p>Asynchronously executes the media information session provided.
* *
* @param mediaInformationSession media information session which includes command options/arguments * @param mediaInformationSession media information session which includes command options/arguments
* @param waitTimeout max time to wait until media information is transmitted * @param waitTimeout max time to wait until media information is transmitted
*/ */
static void asyncGetMediaInformationExecute(final MediaInformationSession mediaInformationSession, final Integer waitTimeout) { public static void asyncGetMediaInformationExecute(final MediaInformationSession mediaInformationSession, final int waitTimeout) {
AsyncGetMediaInformationTask asyncGetMediaInformationTask = new AsyncGetMediaInformationTask(mediaInformationSession, waitTimeout); AsyncGetMediaInformationTask asyncGetMediaInformationTask = new AsyncGetMediaInformationTask(mediaInformationSession, waitTimeout);
Future<?> future = asyncExecutorService.submit(asyncGetMediaInformationTask); Future<?> future = asyncExecutorService.submit(asyncGetMediaInformationTask);
mediaInformationSession.setFuture(future); mediaInformationSession.setFuture(future);
} }
/** /**
* Returns the maximum number of async operations that will be executed in parallel. * <p>Asynchronously executes the media information session provided.
* *
* @return maximum number of async operations that will be executed in parallel * @param mediaInformationSession media information session which includes command options/arguments
* @param executorService executor service that will be used to run this asynchronous operation
* @param waitTimeout max time to wait until media information is transmitted
*/
public static void asyncGetMediaInformationExecute(final MediaInformationSession mediaInformationSession, final ExecutorService executorService, final int waitTimeout) {
AsyncGetMediaInformationTask asyncGetMediaInformationTask = new AsyncGetMediaInformationTask(mediaInformationSession, waitTimeout);
Future<?> future = executorService.submit(asyncGetMediaInformationTask);
mediaInformationSession.setFuture(future);
}
/**
* Returns the maximum number of async sessions that will be executed in parallel.
*
* @return maximum number of async sessions that will be executed in parallel
*/ */
public static int getAsyncConcurrencyLimit() { public static int getAsyncConcurrencyLimit() {
return asyncConcurrencyLimit; return asyncConcurrencyLimit;
} }
/** /**
* Sets the maximum number of async operations that will be executed in parallel. If more * Sets the maximum number of async sessions that will be executed in parallel. If more
* operations are submitted those will be queued. * sessions are submitted those will be queued.
* *
* @param asyncConcurrencyLimit new async concurrency limit * @param asyncConcurrencyLimit new async concurrency limit
*/ */
@ -843,17 +763,17 @@ public class FFmpegKitConfig {
/** /**
* <p>Sets a global callback function to redirect FFmpeg/FFprobe logs. * <p>Sets a global callback function to redirect FFmpeg/FFprobe logs.
* *
* @param newLogCallback new log callback function or null to disable a previously defined * @param logCallback log callback function or null to disable a previously defined
* callback * callback
*/ */
public static void enableLogCallback(final LogCallback newLogCallback) { public static void enableLogCallback(final LogCallback logCallback) {
globalLogCallbackFunction = newLogCallback; globalLogCallbackFunction = logCallback;
} }
/** /**
* <p>Sets a global callback function to redirect FFmpeg statistics. * <p>Sets a global callback function to redirect FFmpeg statistics.
* *
* @param statisticsCallback new statistics callback function or null to disable a previously * @param statisticsCallback statistics callback function or null to disable a previously
* defined callback * defined callback
*/ */
public static void enableStatisticsCallback(final StatisticsCallback statisticsCallback) { public static void enableStatisticsCallback(final StatisticsCallback statisticsCallback) {
@ -863,7 +783,7 @@ public class FFmpegKitConfig {
/** /**
* <p>Sets a global callback function to receive execution results. * <p>Sets a global callback function to receive execution results.
* *
* @param executeCallback new execute callback function or null to disable a previously * @param executeCallback execute callback function or null to disable a previously
* defined callback * defined callback
*/ */
public static void enableExecuteCallback(final ExecuteCallback executeCallback) { public static void enableExecuteCallback(final ExecuteCallback executeCallback) {
@ -871,11 +791,11 @@ public class FFmpegKitConfig {
} }
/** /**
* <p>Returns global execute callback function. * <p>Returns the global execute callback function.
* *
* @return global execute callback function * @return global execute callback function
*/ */
static ExecuteCallback getGlobalExecuteCallbackFunction() { static ExecuteCallback getExecuteCallback() {
return globalExecuteCallbackFunction; return globalExecuteCallbackFunction;
} }
@ -902,7 +822,7 @@ public class FFmpegKitConfig {
/** /**
* <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an * <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an
* input/output url that can be used in FFmpegKit and FFprobeKit. * input/output url that can be used in FFmpeg and FFprobe commands.
* *
* <p>Requires API Level >= 19. On older API levels it returns an empty url. * <p>Requires API Level >= 19. On older API levels it returns an empty url.
* *
@ -944,7 +864,7 @@ public class FFmpegKitConfig {
/** /**
* <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an * <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an
* input url that can be used in FFmpegKit and FFprobeKit. * input url that can be used in FFmpeg and FFprobe commands.
* *
* <p>Requires API Level >= 19. On older API levels it returns an empty url. * <p>Requires API Level >= 19. On older API levels it returns an empty url.
* *
@ -956,7 +876,7 @@ public class FFmpegKitConfig {
/** /**
* <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an * <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an
* output url that can be used in FFmpegKit and FFprobeKit. * output url that can be used in FFmpeg and FFprobe commands.
* *
* <p>Requires API Level >= 19. On older API levels it returns an empty url. * <p>Requires API Level >= 19. On older API levels it returns an empty url.
* *
@ -967,7 +887,7 @@ public class FFmpegKitConfig {
} }
/** /**
* Called by saf_wrapper from JNI/native part to close a parcel file descriptor. * Called by saf_wrapper from native library to close a parcel file descriptor.
* *
* @param fd parcel file descriptor created for a saf uri * @param fd parcel file descriptor created for a saf uri
*/ */
@ -995,7 +915,7 @@ public class FFmpegKitConfig {
/** /**
* Sets the session history size. * Sets the session history size.
* *
* @param sessionHistorySize new session history size, should be smaller than 1000 * @param sessionHistorySize session history size, should be smaller than 1000
*/ */
public static void setSessionHistorySize(final int sessionHistorySize) { public static void setSessionHistorySize(final int sessionHistorySize) {
if (sessionHistorySize >= 1000) { if (sessionHistorySize >= 1000) {
@ -1004,8 +924,9 @@ public class FFmpegKitConfig {
* THERE IS A HARD LIMIT ON THE NATIVE SIDE. HISTORY SIZE MUST BE SMALLER THAN 1000 * THERE IS A HARD LIMIT ON THE NATIVE SIDE. HISTORY SIZE MUST BE SMALLER THAN 1000
*/ */
throw new IllegalArgumentException("Session history size must not exceed the hard limit!"); throw new IllegalArgumentException("Session history size must not exceed the hard limit!");
} else if (sessionHistorySize > 0) {
FFmpegKitConfig.sessionHistorySize = sessionHistorySize;
} }
FFmpegKitConfig.sessionHistorySize = sessionHistorySize;
} }
/** /**
@ -1016,19 +937,18 @@ public class FFmpegKitConfig {
static void addSession(final Session session) { static void addSession(final Session session) {
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
sessionHistoryMap.put(session.getSessionId(), session); sessionHistoryMap.put(session.getSessionId(), session);
sessionHistoryQueue.offer(session); sessionHistoryList.add(session);
if (sessionHistoryList.size() > sessionHistorySize) {
if (sessionHistoryQueue.size() > sessionHistorySize) { try {
final Session oldestElement = sessionHistoryQueue.poll(); sessionHistoryList.remove(0);
if (oldestElement != null) { } catch (final IndexOutOfBoundsException ignored) {
sessionHistoryMap.remove(oldestElement.getSessionId());
} }
} }
} }
} }
/** /**
* Returns the session specified with sessionId from the session history. * Returns the session specified with <code>sessionId</code> from the session history.
* *
* @param sessionId session identifier * @param sessionId session identifier
* @return session specified with sessionId or null if it is not found in the history * @return session specified with sessionId or null if it is not found in the history
@ -1040,14 +960,37 @@ public class FFmpegKitConfig {
} }
/** /**
* Returns the last session from the session history. * Returns the last session created from the session history.
* *
* @return the last session from the session history * @return the last session created or null if session history is empty
*/ */
public static Session getLastSession() { public static Session getLastSession() {
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
return sessionHistoryQueue.peek(); if (sessionHistoryList.size() > 0) {
return sessionHistoryList.get(sessionHistoryList.size() - 1);
}
}
return null;
}
/**
* Returns the last session completed from the session history.
*
* @return the last session completed. If there are no completed sessions in the history this
* method will return null
*/
public static Session getLastCompletedSession() {
synchronized (sessionHistoryLock) {
for (int i = sessionHistoryList.size() - 1; i >= 0; i--) {
final Session session = sessionHistoryList.get(i);
if (session.getState() == SessionState.COMPLETED) {
return session;
}
}
} }
return null;
} }
/** /**
@ -1057,7 +1000,7 @@ public class FFmpegKitConfig {
*/ */
public static List<Session> getSessions() { public static List<Session> getSessions() {
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
return new LinkedList<>(sessionHistoryQueue); return new LinkedList<>(sessionHistoryList);
} }
} }
@ -1070,7 +1013,7 @@ public class FFmpegKitConfig {
final LinkedList<FFmpegSession> list = new LinkedList<>(); final LinkedList<FFmpegSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
for (Session session : sessionHistoryQueue) { for (Session session : sessionHistoryList) {
if (session.isFFmpeg()) { if (session.isFFmpeg()) {
list.add((FFmpegSession) session); list.add((FFmpegSession) session);
} }
@ -1089,7 +1032,7 @@ public class FFmpegKitConfig {
final LinkedList<FFprobeSession> list = new LinkedList<>(); final LinkedList<FFprobeSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
for (Session session : sessionHistoryQueue) { for (Session session : sessionHistoryList) {
if (session.isFFprobe()) { if (session.isFFprobe()) {
list.add((FFprobeSession) session); list.add((FFprobeSession) session);
} }
@ -1108,7 +1051,7 @@ public class FFmpegKitConfig {
final LinkedList<Session> list = new LinkedList<>(); final LinkedList<Session> list = new LinkedList<>();
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
for (Session session : sessionHistoryQueue) { for (Session session : sessionHistoryList) {
if (session.getState() == state) { if (session.getState() == state) {
list.add(session); list.add(session);
} }
@ -1124,25 +1067,25 @@ public class FFmpegKitConfig {
* @return log redirection strategy * @return log redirection strategy
*/ */
public static LogRedirectionStrategy getLogRedirectionStrategy() { public static LogRedirectionStrategy getLogRedirectionStrategy() {
return logRedirectionStrategy; return globalLogRedirectionStrategy;
} }
/** /**
* <p>Sets the log redirection strategy * <p>Sets the log redirection strategy
* *
* @param logRedirectionStrategy new log redirection strategy * @param logRedirectionStrategy log redirection strategy
*/ */
public static void setLogRedirectionStrategy(final LogRedirectionStrategy logRedirectionStrategy) { public static void setLogRedirectionStrategy(final LogRedirectionStrategy logRedirectionStrategy) {
FFmpegKitConfig.logRedirectionStrategy = logRedirectionStrategy; FFmpegKitConfig.globalLogRedirectionStrategy = logRedirectionStrategy;
} }
/** /**
* <p>Enables native redirection. Necessary for log and statistics callback functions. * <p>Enables redirection natively.
*/ */
private static native void enableNativeRedirection(); private static native void enableNativeRedirection();
/** /**
* <p>Disables native redirection * <p>Disables redirection natively.
*/ */
private static native void disableNativeRedirection(); private static native void disableNativeRedirection();
@ -1151,7 +1094,7 @@ public class FFmpegKitConfig {
* *
* @return log level * @return log level
*/ */
private static native int getNativeLogLevel(); static native int getNativeLogLevel();
/** /**
* Sets native log level * Sets native log level
@ -1185,14 +1128,6 @@ public class FFmpegKitConfig {
*/ */
private native static int nativeFFmpegExecute(final long sessionId, final String[] arguments); private native static int nativeFFmpegExecute(final long sessionId, final String[] arguments);
/**
* <p>Cancels an ongoing FFmpeg operation natively. This function does not wait for termination
* to complete and returns immediately.
*
* @param sessionId id of the session
*/
native static void nativeFFmpegCancel(final long sessionId);
/** /**
* <p>Synchronously executes FFprobe natively. * <p>Synchronously executes FFprobe natively.
* *
@ -1205,14 +1140,22 @@ public class FFmpegKitConfig {
native static int nativeFFprobeExecute(final long sessionId, final String[] arguments); native static int nativeFFprobeExecute(final long sessionId, final String[] arguments);
/** /**
* <p>Returns the number of native messages which are not transmitted to the Java callbacks for * <p>Cancels an ongoing FFmpeg operation natively. This function does not wait for termination
* to complete and returns immediately.
*
* @param sessionId id of the session
*/
native static void nativeFFmpegCancel(final long sessionId);
/**
* <p>Returns the number of native messages that are not transmitted to the Java callbacks for
* this session natively. * this session natively.
* *
* @param sessionId id of the session * @param sessionId id of the session
* @return number of native messages which are not transmitted to the Java callbacks for * @return number of native messages that are not transmitted to the Java callbacks for
* this session natively * this session natively
*/ */
native static int messagesInTransmit(final long sessionId); public native static int messagesInTransmit(final long sessionId);
/** /**
* <p>Creates a new named pipe to use in <code>FFmpeg</code> operations natively. * <p>Creates a new named pipe to use in <code>FFmpeg</code> operations natively.
@ -1241,7 +1184,8 @@ public class FFmpegKitConfig {
private native static int setNativeEnvironmentVariable(final String variableName, final String variableValue); private native static int setNativeEnvironmentVariable(final String variableName, final String variableValue);
/** /**
* <p>Registers a new ignored signal natively. Ignored signals are not handled by the library. * <p>Registers a new ignored signal natively. Ignored signals are not handled by
* <code>FFmpegKit</code> library.
* *
* @param signum signal number * @param signum signal number
*/ */

@ -19,48 +19,160 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
import java.util.Queue; import java.util.LinkedList;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.List;
/** /**
* <p>An FFmpeg execute session. * <p>An FFmpeg session.
*/ */
public class FFmpegSession extends AbstractSession implements Session { public class FFmpegSession extends AbstractSession implements Session {
private final Queue<Statistics> statistics;
/**
* Session specific statistics callback function.
*/
private final StatisticsCallback statisticsCallback;
/**
* Statistics entries received for this session.
*/
private final List<Statistics> statistics;
/**
* Statistics entry lock.
*/
private final Object statisticsLock;
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
*/
public FFmpegSession(final String[] arguments) {
this(arguments, null);
}
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
*/
public FFmpegSession(final String[] arguments, final ExecuteCallback executeCallback) {
this(arguments, executeCallback, null, null);
}
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param logCallback session specific log callback function
* @param statisticsCallback session specific statistics callback function
*/
public FFmpegSession(final String[] arguments, public FFmpegSession(final String[] arguments,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback) { final StatisticsCallback statisticsCallback) {
super(arguments, executeCallback, logCallback, statisticsCallback, FFmpegKitConfig.getLogRedirectionStrategy()); this(arguments, executeCallback, logCallback, statisticsCallback, FFmpegKitConfig.getLogRedirectionStrategy());
}
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param logCallback session specific log callback function
* @param statisticsCallback session specific statistics callback function
* @param logRedirectionStrategy session specific log redirection strategy
*/
public FFmpegSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
super(arguments, executeCallback, logCallback, logRedirectionStrategy);
this.statisticsCallback = statisticsCallback;
this.statistics = new ConcurrentLinkedQueue<>(); this.statistics = new LinkedList<>();
this.statisticsLock = new Object();
} }
@Override /**
public Queue<Statistics> getAllStatistics(final int waitTimeout) { * Returns the session specific statistics callback function.
waitForCallbackMessagesInTransmit(waitTimeout); *
* @return session specific statistics callback function
*/
public StatisticsCallback getStatisticsCallback() {
return statisticsCallback;
}
if (thereAreCallbackMessagesInTransmit()) { /**
android.util.Log.i(FFmpegKitConfig.TAG, String.format("getAllStatistics was asked to return all statistics but there are still statistics being transmitted for session id %d.", sessionId)); * Returns all statistics entries generated for this session. If there are asynchronous
* messages that are not delivered yet, this method waits for them until the given timeout.
*
* @param waitTimeout wait timeout for asynchronous messages in milliseconds
* @return list of statistics entries generated for this session
*/
public List<Statistics> getAllStatistics(final int waitTimeout) {
waitForAsynchronousMessagesInTransmit(waitTimeout);
if (thereAreAsynchronousMessagesInTransmit()) {
android.util.Log.i(FFmpegKitConfig.TAG, String.format("getAllStatistics was called to return all statistics but there are still statistics being transmitted for session id %d.", sessionId));
} }
return getStatistics(); return getStatistics();
} }
@Override /**
public Queue<Statistics> getAllStatistics() { * Returns all statistics entries generated for this session. If there are asynchronous
return getAllStatistics(DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT); * messages that are not delivered yet, this method waits for them until
* {@link #DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT} expires.
*
* @return list of statistics entries generated for this session
*/
public List<Statistics> getAllStatistics() {
return getAllStatistics(DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
} }
@Override /**
public Queue<Statistics> getStatistics() { * Returns all statistics entries delivered for this session. Note that if there are
return statistics; * asynchronous messages that are not delivered yet, this method will not wait for
* them and will return immediately.
*
* @return list of statistics entries received for this session
*/
public List<Statistics> getStatistics() {
synchronized (statisticsLock) {
return statistics;
}
} }
@Override /**
* Returns the last received statistics entry.
*
* @return the last received statistics entry or null if there are not any statistics entries
* received
*/
public Statistics getLastReceivedStatistics() {
synchronized (statisticsLock) {
if (statistics.size() > 0) {
return statistics.get(0);
} else {
return null;
}
}
}
/**
* Adds a new statistics entry for this session.
*
* @param statistics statistics entry
*/
public void addStatistics(final Statistics statistics) { public void addStatistics(final Statistics statistics) {
this.statistics.add(statistics); synchronized (statisticsLock) {
this.statistics.add(statistics);
}
} }
@Override @Override

@ -20,19 +20,23 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService;
/** /**
* <p>Main class for FFprobe operations. * <p>Main class to run <code>FFprobe</code> commands. Supports executing commands both
* <p>Supports running FFprobe commands using {@link #execute(String...)} method. * synchronously and asynchronously.
* <pre> * <pre>
* FFprobeSession session = FFprobe.execute("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4"); * FFprobeSession session = FFprobeKit.execute("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4");
* Log.i(FFmpegKitConfig.TAG, String.format("Command execution %s.", (session.getReturnCode() == 0?"completed successfully":"failed with rc=" + session.getReturnCode())); *
* FFprobeSession asyncSession = FFprobeKit.executeAsync("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4", executeCallback);
* </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre>
* FFprobeSession session = FFprobeKit.executeAsync("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4", executeCallback, logCallback);
* </pre> * </pre>
* <p>It can also extract media information for a file or a url, using {@link #getMediaInformation(String)} method. * <p>It can extract media information for a file or a url, using {@link #getMediaInformation(String)} method.
* <pre> * <pre>
* MediaInformationSession session = FFprobe.getMediaInformation("file1.mp4"); * MediaInformationSession session = FFprobeKit.getMediaInformation("file1.mp4");
* Log.i(FFmpegKitConfig.TAG, String.format("Media information %s.", (session.getReturnCode() == 0?"extracted successfully":"was not extracted due to rc=" + session.getReturnCode()));
* </pre> * </pre>
*/ */
public class FFprobeKit { public class FFprobeKit {
@ -52,10 +56,10 @@ public class FFprobeKit {
* <p>Synchronously executes FFprobe with arguments provided. * <p>Synchronously executes FFprobe with arguments provided.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe command options/arguments as string array
* @return ffprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession execute(final String[] arguments) { public static FFprobeSession execute(final String[] arguments) {
final FFprobeSession session = new FFprobeSession(arguments, null, null, null); final FFprobeSession session = new FFprobeSession(arguments);
FFmpegKitConfig.ffprobeExecute(session); FFmpegKitConfig.ffprobeExecute(session);
@ -63,41 +67,33 @@ public class FFprobeKit {
} }
/** /**
* <p>Synchronously executes FFprobe command provided. Space character is used to split command * <p>Asynchronously executes FFprobe with arguments provided.
* into arguments. You can use single and double quote characters to specify arguments inside
* your command.
*
* @param command FFprobe command
* @return ffprobe session created for this execution
*/
public static FFprobeSession execute(final String command) {
return execute(FFmpegKit.parseArguments(command));
}
/**
* <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single and double quote characters to specify arguments inside
* your command.
* *
* @param command FFprobe command * @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when the execution is completed * @param executeCallback callback that will be called when the execution is completed
* @return ffprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String command, public static FFprobeSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback) { final ExecuteCallback executeCallback) {
return executeAsync(FFmpegKit.parseArguments(command), executeCallback); final FFprobeSession session = new FFprobeSession(arguments, executeCallback);
FFmpegKitConfig.asyncFFprobeExecute(session);
return session;
} }
/** /**
* <p>Asynchronously executes FFprobe with arguments provided. * <p>Asynchronously executes FFprobe with arguments provided.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when the execution is completed * @param executeCallback callback that will be notified when execution is completed
* @return ffprobe session created for this execution * @param logCallback callback that will receive logs
* @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String[] arguments, public static FFprobeSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback) { final ExecuteCallback executeCallback,
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, null, null); final LogCallback logCallback) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session); FFmpegKitConfig.asyncFFprobeExecute(session);
@ -105,147 +101,187 @@ public class FFprobeKit {
} }
/** /**
* <p>Asynchronously executes FFprobe command provided. Space character is used to split command * <p>Asynchronously executes FFprobe with arguments provided.
* into arguments. You can use single and double quote characters to specify arguments inside
* your command.
* *
* @param command FFprobe command * @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive log entries * @param executorService executor service that will be used to run this asynchronous operation
* @param statisticsCallback callback that will receive statistics * @return FFprobe session created for this execution
* @return ffprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String command, public static FFprobeSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final ExecutorService executorService) {
final StatisticsCallback statisticsCallback) { final FFprobeSession session = new FFprobeSession(arguments, executeCallback);
return executeAsync(FFmpegKit.parseArguments(command), executeCallback, logCallback, statisticsCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
return session;
} }
/** /**
* <p>Asynchronously executes FFprobe with arguments provided. * <p>Asynchronously executes FFprobe with arguments provided.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries * @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param executorService executor service that will be used to run this asynchronous operation
* @return ffprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String[] arguments, public static FFprobeSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback) { final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback, statisticsCallback); final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session); FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
return session; return session;
} }
/** /**
* <p>Asynchronously executes FFprobe with arguments provided. * <p>Synchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* @param arguments FFprobe command options/arguments as string array * @param command FFprobe command
* @param executeCallback callback that will be notified when the execution is completed * @return FFprobe session created for this execution
* @param executor executor that will be used to run this asynchronous operation
* @return ffprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String[] arguments, public static FFprobeSession execute(final String command) {
final ExecuteCallback executeCallback, return execute(FFmpegKit.parseArguments(command));
final Executor executor) { }
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, null, null);
AsyncFFprobeExecuteTask asyncFFprobeExecuteTask = new AsyncFFprobeExecuteTask(session); /**
executor.execute(asyncFFprobeExecuteTask); * <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
*
* @param command FFprobe command
* @param executeCallback callback that will be called when the execution is completed
* @return FFprobe session created for this execution
*/
public static FFprobeSession executeAsync(final String command,
final ExecuteCallback executeCallback) {
return executeAsync(FFmpegKit.parseArguments(command), executeCallback);
}
return session; /**
* <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
*
* @param command FFprobe command
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive logs
* @return FFprobe session created for this execution
*/
public static FFprobeSession executeAsync(final String command,
final ExecuteCallback executeCallback,
final LogCallback logCallback) {
return executeAsync(FFmpegKit.parseArguments(command), executeCallback, logCallback);
} }
/** /**
* <p>Asynchronously executes FFprobe with arguments provided. * <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* @param arguments FFprobe command options/arguments as string array * @param command FFprobe command
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive log entries * @param executorService executor service that will be used to run this asynchronous operation
* @param statisticsCallback callback that will receive statistics * @return FFprobe session created for this execution
* @param executor executor that will be used to run this asynchronous operation
* @return ffprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String[] arguments, public static FFprobeSession executeAsync(final String command,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final ExecutorService executorService) {
final StatisticsCallback statisticsCallback, final FFprobeSession session = new FFprobeSession(FFmpegKit.parseArguments(command), executeCallback);
final Executor executor) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback, statisticsCallback);
AsyncFFprobeExecuteTask asyncFFprobeExecuteTask = new AsyncFFprobeExecuteTask(session); FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
executor.execute(asyncFFprobeExecuteTask);
return session; return session;
} }
/** /**
* <p>Lists all FFprobe sessions in the session history * <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* @return all FFprobe sessions in the session history * @param command FFprobe command
* @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive logs
* @param executorService executor service that will be used to run this asynchronous operation
* @return FFprobe session created for this execution
*/ */
public static List<FFprobeSession> listSessions() { public static FFprobeSession executeAsync(final String command,
return FFmpegKitConfig.getFFprobeSessions(); final ExecuteCallback executeCallback,
final LogCallback logCallback,
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(FFmpegKit.parseArguments(command), executeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
return session;
} }
/** /**
* <p>Returns media information for the given path. * <p>Extracts media information for the file specified with path.
* *
* @param path path or uri of a media file * @param path path or uri of a media file
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformation(final String path) { public static MediaInformationSession getMediaInformation(final String path) {
return getMediaInformationFromCommandArguments(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, null, null, null, AbstractSession.DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT); final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path});
FFmpegKitConfig.getMediaInformationExecute(session, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
return session;
} }
/** /**
* <p>Returns media information for the given path. * <p>Extracts media information for the file specified with path.
* *
* @param path path or uri of a media file * @param path path or uri of a media file
* @param waitTimeout max time to wait until media information is transmitted * @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformation(final String path, final Integer waitTimeout) { public static MediaInformationSession getMediaInformation(final String path,
return getMediaInformationFromCommandArguments(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, null, null, null, waitTimeout); final int waitTimeout) {
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path});
FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout);
return session;
} }
/** /**
* <p>Returns media information for the given path asynchronously. * <p>Extracts media information for the file specified with path asynchronously.
* *
* @param path path or uri of a media file * @param path path or uri of a media file
* @param executeCallback callback that will be notified when the execution is completed * @param executeCallback callback that will be called when the execution is completed
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationAsync(final String path, public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback) { final ExecuteCallback executeCallback) {
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, null, null); final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, AbstractSession.DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT); FFmpegKitConfig.asyncGetMediaInformationExecute(session, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
return session; return session;
} }
/** /**
* <p>Returns media information for the given path asynchronously. * <p>Extracts media information for the file specified with path asynchronously.
* *
* @param path path or uri of a media file * @param path path or uri of a media file
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries * @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param waitTimeout max time to wait until media information is transmitted
* @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationAsync(final String path, public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback, final int waitTimeout) {
final Integer waitTimeout) { final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, logCallback);
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, logCallback, statisticsCallback);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, waitTimeout); FFmpegKitConfig.asyncGetMediaInformationExecute(session, waitTimeout);
@ -253,88 +289,102 @@ public class FFprobeKit {
} }
/** /**
* <p>Returns media information for the given path asynchronously. * <p>Extracts media information for the file specified with path asynchronously.
* *
* @param path path or uri of a media file * @param path path or uri of a media file
* @param executeCallback callback that will be notified when the execution is completed * @param executeCallback callback that will be called when the execution is completed
* @param executor executor that will be used to run this asynchronous operation * @param executorService executor service that will be used to run this asynchronous operation
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationAsync(final String path, public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final Executor executor) { final ExecutorService executorService) {
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, null, null); final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback);
AsyncGetMediaInformationTask asyncGetMediaInformationTask = new AsyncGetMediaInformationTask(session); FFmpegKitConfig.asyncGetMediaInformationExecute(session, executorService, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
executor.execute(asyncGetMediaInformationTask);
return session; return session;
} }
/** /**
* <p>Returns media information for the given path asynchronously. * <p>Extracts media information for the file specified with path asynchronously.
* *
* @param path path or uri of a media file * @param path path or uri of a media file
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries * @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param executorService executor service that will be used to run this asynchronous operation
* @param executor executor that will be used to run this asynchronous operation * @param waitTimeout max time to wait until media information is transmitted
* @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationAsync(final String path, public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback, final ExecutorService executorService,
final Executor executor, final int waitTimeout) {
final Integer waitTimeout) { final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, logCallback);
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, logCallback, statisticsCallback);
AsyncGetMediaInformationTask asyncGetMediaInformationTask = new AsyncGetMediaInformationTask(session, waitTimeout); FFmpegKitConfig.asyncGetMediaInformationExecute(session, executorService, waitTimeout);
executor.execute(asyncGetMediaInformationTask);
return session; return session;
} }
/** /**
* <p>Returns media information for the given command. * <p>Extracts media information using the command provided asynchronously.
* *
* @param command command to execute * @param command FFprobe command that prints media information for a file in JSON format
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationFromCommand(final String command) { public static MediaInformationSession getMediaInformationFromCommand(final String command) {
return getMediaInformationFromCommandArguments(FFmpegKit.parseArguments(command), null, null, null, AbstractSession.DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT); final MediaInformationSession session = new MediaInformationSession(FFmpegKit.parseArguments(command));
}
FFmpegKitConfig.asyncGetMediaInformationExecute(session, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
return session;
}
/** /**
* <p>Returns media information for the given command. * <p>Extracts media information using the command provided asynchronously.
* *
* @param command command to execute * @param command FFprobe command that prints media information for a file in JSON format
* @param executeCallback callback that will be notified when execution is completed * @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries * @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param waitTimeout max time to wait until media information is transmitted
* @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationFromCommand(final String command, public static MediaInformationSession getMediaInformationFromCommandAsync(final String command,
final ExecuteCallback executeCallback, final ExecuteCallback executeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback, final int waitTimeout) {
final Integer waitTimeout) { return getMediaInformationFromCommandArgumentsAsync(FFmpegKit.parseArguments(command), executeCallback, logCallback, waitTimeout);
return getMediaInformationFromCommandArguments(FFmpegKit.parseArguments(command), executeCallback, logCallback, statisticsCallback, waitTimeout);
} }
private static MediaInformationSession getMediaInformationFromCommandArguments(final String[] arguments, /**
final ExecuteCallback executeCallback, * Extracts media information using the command arguments provided asynchronously.
final LogCallback logCallback, *
final StatisticsCallback statisticsCallback, * @param arguments FFprobe command arguments that print media information for a file in JSON format
final Integer waitTimeout) { * @param executeCallback callback that will be notified when execution is completed
final MediaInformationSession session = new MediaInformationSession(arguments, executeCallback, logCallback, statisticsCallback); * @param logCallback callback that will receive logs
* @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution
*/
private static MediaInformationSession getMediaInformationFromCommandArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final int waitTimeout) {
final MediaInformationSession session = new MediaInformationSession(arguments, executeCallback, logCallback);
FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout); FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout);
return session; return session;
} }
/**
* <p>Lists all FFprobe sessions in the session history.
*
* @return all FFprobe sessions in the session history
*/
public static List<FFprobeSession> listSessions() {
return FFmpegKitConfig.getFFprobeSessions();
}
} }

@ -19,52 +19,56 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
import java.text.MessageFormat;
import java.util.LinkedList;
import java.util.Queue;
/** /**
* <p>An FFprobe execute session. * <p>An FFprobe session.
*/ */
public class FFprobeSession extends AbstractSession implements Session { public class FFprobeSession extends AbstractSession implements Session {
public FFprobeSession(final String[] arguments, /**
final ExecuteCallback executeCallback, * Builds a new FFprobe session.
final LogCallback logCallback, *
final StatisticsCallback statisticsCallback) { * @param arguments command arguments
this(arguments, executeCallback, logCallback, statisticsCallback, FFmpegKitConfig.getLogRedirectionStrategy()); */
} public FFprobeSession(final String[] arguments) {
this(arguments, null);
FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
super(arguments, executeCallback, logCallback, statisticsCallback, logRedirectionStrategy);
} }
@Override /**
public Queue<Statistics> getAllStatistics(final int waitTimeout) { * Builds a new FFprobe session.
return new LinkedList<>(); *
* @param arguments command arguments
* @param executeCallback session specific execute callback function
*/
public FFprobeSession(final String[] arguments, final ExecuteCallback executeCallback) {
this(arguments, executeCallback, null);
} }
@Override /**
public Queue<Statistics> getAllStatistics() { * Builds a new FFprobe session.
return new LinkedList<>(); *
} * @param arguments command arguments
* @param executeCallback session specific execute callback function
@Override * @param logCallback session specific log callback function
public Queue<Statistics> getStatistics() { */
return new LinkedList<>(); FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback) {
this(arguments, executeCallback, logCallback, FFmpegKitConfig.getLogRedirectionStrategy());
} }
@Override /**
public void addStatistics(final Statistics statistics) { * Builds a new FFprobe session.
/* *
* ffprobe does not support statistics. * @param arguments command arguments
* So, this method should never have been called. * @param executeCallback session specific execute callback function
*/ * @param logCallback session specific log callback function
android.util.Log.w(FFmpegKitConfig.TAG, MessageFormat.format("FFprobe execute session {0} received statistics.", sessionId)); * @param logRedirectionStrategy session specific log redirection strategy
*/
FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
super(arguments, executeCallback, logCallback, logRedirectionStrategy);
} }
@Override @Override

@ -26,7 +26,7 @@ public enum Level {
/** /**
* This log level is defined by FFmpegKit. It is used to specify logs printed to stderr by * This log level is defined by FFmpegKit. It is used to specify logs printed to stderr by
* ffmpeg. Logs that has this level are not filtered and always redirected. * FFmpeg. Logs that has this level are not filtered and always redirected.
*/ */
AV_LOG_STDERR(-16), AV_LOG_STDERR(-16),
@ -82,7 +82,7 @@ public enum Level {
private final int value; private final int value;
/** /**
* <p>Returns enumeration defined by value. * <p>Returns the enumeration defined by provided value.
* *
* @param value level value * @param value level value
* @return enumeration defined by value * @return enumeration defined by value
@ -121,7 +121,7 @@ public enum Level {
} }
/** /**
* Creates new enum. * Creates a new enum.
* *
* @param value level value * @param value level value
*/ */

@ -20,7 +20,7 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
/** /**
* <p>Log entry for an execute session. * <p>Log entry for an <code>FFmpegKit</code> session.
*/ */
public class Log { public class Log {
private final long sessionId; private final long sessionId;

@ -20,7 +20,7 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
/** /**
* <p>Callback function to receive logs for executions. * <p>Callback function that receives logs generated for <code>FFmpegKit</code> sessions.
*/ */
@FunctionalInterface @FunctionalInterface
public interface LogCallback { public interface LogCallback {

@ -30,16 +30,16 @@ import org.json.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
/** /**
* Parser for {@link MediaInformation}. * A parser that constructs {@link MediaInformation} from FFprobe's json output.
*/ */
public class MediaInformationParser { public class MediaInformationJsonParser {
/** /**
* Extracts <code>MediaInformation</code> from the given ffprobe json output. Note that this * Extracts <code>MediaInformation</code> from the given FFprobe json output. Note that this
* method does not throw {@link JSONException} as {@link #fromWithError(String)} does and * method does not throw {@link JSONException} as {@link #fromWithError(String)} does and
* handles errors internally. * handles errors internally.
* *
* @param ffprobeJsonOutput ffprobe json output * @param ffprobeJsonOutput FFprobe json output
* @return created {@link MediaInformation} instance of null if a parsing error occurs * @return created {@link MediaInformation} instance of null if a parsing error occurs
*/ */
public static MediaInformation from(final String ffprobeJsonOutput) { public static MediaInformation from(final String ffprobeJsonOutput) {
@ -52,7 +52,7 @@ public class MediaInformationParser {
} }
/** /**
* Extracts MediaInformation from the given ffprobe json output. * Extracts MediaInformation from the given FFprobe json output.
* *
* @param ffprobeJsonOutput ffprobe json output * @param ffprobeJsonOutput ffprobe json output
* @return created {@link MediaInformation} instance * @return created {@link MediaInformation} instance

@ -20,24 +20,62 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
/** /**
* <p>A custom FFprobe execute session, which produces a <code>MediaInformation</code> object * <p>A custom FFprobe session, which produces a <code>MediaInformation</code> object using the
* using the output of the execution. * FFprobe output.
*/ */
public class MediaInformationSession extends FFprobeSession implements Session { public class MediaInformationSession extends FFprobeSession implements Session {
/**
* Media information extracted in the session.
*/
private MediaInformation mediaInformation; private MediaInformation mediaInformation;
public MediaInformationSession(final String[] arguments, /**
final ExecuteCallback executeCallback, * Creates a new media information session.
final LogCallback logCallback, *
final StatisticsCallback statisticsCallback) { * @param arguments command arguments
super(arguments, executeCallback, logCallback, statisticsCallback, LogRedirectionStrategy.NEVER_PRINT_LOGS); */
public MediaInformationSession(final String[] arguments) {
this(arguments, null);
}
/**
* Creates a new media information session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
*/
public MediaInformationSession(final String[] arguments, final ExecuteCallback executeCallback) {
this(arguments, executeCallback, null);
}
/**
* Creates a new media information session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param logCallback session specific log callback function
*/
public MediaInformationSession(final String[] arguments, final ExecuteCallback executeCallback, final LogCallback logCallback) {
super(arguments, executeCallback, logCallback, LogRedirectionStrategy.NEVER_PRINT_LOGS);
} }
/**
* Returns the media information extracted in this session.
*
* @return media information extracted or null if the command failed or the output can not be
* parsed
*/
public MediaInformation getMediaInformation() { public MediaInformation getMediaInformation() {
return mediaInformation; return mediaInformation;
} }
public void setMediaInformation(MediaInformation mediaInformation) { /**
* Sets the media information extracted in this session.
*
* @param mediaInformation media information extracted
*/
public void setMediaInformation(final MediaInformation mediaInformation) {
this.mediaInformation = mediaInformation; this.mediaInformation = mediaInformation;
} }

@ -0,0 +1,183 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit;
import android.os.Build;
import com.arthenica.smartexception.java.Exceptions;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* <p>Responsible of loading native libraries.
*/
public class NativeLoader {
static final String[] FFMPEG_LIBRARIES = {"avutil", "swscale", "swresample", "avcodec", "avformat", "avfilter", "avdevice"};
static boolean isTestModeDisabled() {
return (System.getProperty("enable.ffmpeg.kit.test.mode") == null);
}
private static void loadLibrary(final String libraryName) {
if (isTestModeDisabled()) {
System.loadLibrary(libraryName);
}
}
private static List<String> loadExternalLibraries() {
if (isTestModeDisabled()) {
return Packages.getExternalLibraries();
} else {
return Collections.emptyList();
}
}
private static String loadNativeAbi() {
if (isTestModeDisabled()) {
return AbiDetect.getNativeAbi();
} else {
return Abi.ABI_X86_64.getName();
}
}
static String loadAbi() {
if (isTestModeDisabled()) {
return AbiDetect.getAbi();
} else {
return Abi.ABI_X86_64.getName();
}
}
static String loadPackageName() {
if (isTestModeDisabled()) {
return Packages.getPackageName();
} else {
return "test";
}
}
static String loadVersion() {
final String version = "4.4";
if (isTestModeDisabled()) {
return FFmpegKitConfig.getVersion();
} else if (loadIsLTSBuild()) {
return String.format("%s-lts", version);
} else {
return version;
}
}
static boolean loadIsLTSBuild() {
if (isTestModeDisabled()) {
return AbiDetect.isNativeLTSBuild();
} else {
return true;
}
}
static int loadLogLevel() {
if (isTestModeDisabled()) {
return FFmpegKitConfig.getNativeLogLevel();
} else {
return Level.AV_LOG_DEBUG.getValue();
}
}
static String loadBuildDate() {
if (isTestModeDisabled()) {
return FFmpegKitConfig.getBuildDate();
} else {
return new SimpleDateFormat("yyyyMMdd").format(new Date());
}
}
static void enableRedirection() {
if (isTestModeDisabled()) {
FFmpegKitConfig.enableRedirection();
}
}
static void loadFFmpegKitAbiDetect() {
loadLibrary("ffmpegkit_abidetect");
}
static boolean loadFFmpeg() {
boolean nativeFFmpegLoaded = false;
boolean nativeFFmpegTriedAndFailed = false;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
/* LOADING LINKED LIBRARIES MANUALLY ON API < 21 */
final List<String> externalLibrariesEnabled = loadExternalLibraries();
if (externalLibrariesEnabled.contains("tesseract") || externalLibrariesEnabled.contains("x265") || externalLibrariesEnabled.contains("snappy") || externalLibrariesEnabled.contains("openh264") || externalLibrariesEnabled.contains("rubberband")) {
loadLibrary("c++_shared");
}
if (AbiDetect.ARM_V7A.equals(loadNativeAbi())) {
try {
for (String ffmpegLibrary : FFMPEG_LIBRARIES) {
loadLibrary(ffmpegLibrary + "_neon");
}
nativeFFmpegLoaded = true;
} catch (final UnsatisfiedLinkError e) {
android.util.Log.i(FFmpegKitConfig.TAG, String.format("NEON supported armeabi-v7a ffmpeg library not found. Loading default armeabi-v7a library.%s", Exceptions.getStackTraceString(e)));
nativeFFmpegTriedAndFailed = true;
}
}
if (!nativeFFmpegLoaded) {
for (String ffmpegLibrary : FFMPEG_LIBRARIES) {
loadLibrary(ffmpegLibrary);
}
}
}
return nativeFFmpegTriedAndFailed;
}
static void loadFFmpegKit(final boolean nativeFFmpegTriedAndFailed) {
boolean nativeFFmpegKitLoaded = false;
if (!nativeFFmpegTriedAndFailed && AbiDetect.ARM_V7A.equals(loadNativeAbi())) {
try {
/*
* THE TRY TO LOAD ARM-V7A-NEON FIRST. IF NOT LOAD DEFAULT ARM-V7A
*/
loadLibrary("ffmpegkit_armv7a_neon");
nativeFFmpegKitLoaded = true;
AbiDetect.setArmV7aNeonLoaded();
} catch (final UnsatisfiedLinkError e) {
android.util.Log.i(FFmpegKitConfig.TAG, String.format("NEON supported armeabi-v7a ffmpegkit library not found. Loading default armeabi-v7a library.%s", Exceptions.getStackTraceString(e)));
}
}
if (!nativeFFmpegKitLoaded) {
loadLibrary("ffmpegkit");
}
}
}

@ -66,32 +66,11 @@ class Packages {
} }
/** /**
* Returns enabled external libraries by FFmpeg. * Returns the FFmpegKit binary package name.
*
* @return enabled external libraries
*/
static List<String> getExternalLibraries() {
final String buildConfiguration = AbiDetect.getNativeBuildConf();
final List<String> enabledLibraryList = new ArrayList<>();
for (String supportedExternalLibrary : supportedExternalLibraries) {
if (buildConfiguration.contains("enable-" + supportedExternalLibrary) ||
buildConfiguration.contains("enable-lib" + supportedExternalLibrary)) {
enabledLibraryList.add(supportedExternalLibrary);
}
}
Collections.sort(enabledLibraryList);
return enabledLibraryList;
}
/**
* Returns FFmpegKit binary package name.
* *
* @return guessed FFmpegKit binary package name * @return predicted FFmpegKit binary package name
*/ */
static String getPackageName() { public static String getPackageName() {
final List<String> externalLibraryList = getExternalLibraries(); final List<String> externalLibraryList = getExternalLibraries();
final boolean speex = externalLibraryList.contains("speex"); final boolean speex = externalLibraryList.contains("speex");
final boolean fribidi = externalLibraryList.contains("fribidi"); final boolean fribidi = externalLibraryList.contains("fribidi");
@ -266,4 +245,25 @@ class Packages {
} }
} }
/**
* Returns enabled external libraries by FFmpeg.
*
* @return enabled external libraries
*/
public static List<String> getExternalLibraries() {
final String buildConfiguration = AbiDetect.getNativeBuildConf();
final List<String> enabledLibraryList = new ArrayList<>();
for (String supportedExternalLibrary : supportedExternalLibraries) {
if (buildConfiguration.contains("enable-" + supportedExternalLibrary) ||
buildConfiguration.contains("enable-lib" + supportedExternalLibrary)) {
enabledLibraryList.add(supportedExternalLibrary);
}
}
Collections.sort(enabledLibraryList);
return enabledLibraryList;
}
} }

@ -21,22 +21,35 @@ package com.arthenica.ffmpegkit;
public class ReturnCode { public class ReturnCode {
public static int NOT_SET = -999;
public static int SUCCESS = 0; public static int SUCCESS = 0;
public static int CANCEL = 255; public static int CANCEL = 255;
public static boolean isSuccess(final int returnCode) { private final int value;
return (returnCode == SUCCESS);
public ReturnCode(final int value) {
this.value = value;
}
public int getValue() {
return value;
}
public boolean isSuccess() {
return (value == SUCCESS);
}
public boolean isError() {
return ((value != SUCCESS) && (value != CANCEL));
} }
public static boolean isFailure(final int returnCode) { public boolean isCancel() {
return (returnCode != NOT_SET) && (returnCode != SUCCESS) && (returnCode != CANCEL); return (value == CANCEL);
} }
public static boolean isCancel(final int returnCode) { @Override
return (returnCode == CANCEL); public String toString() {
return String.valueOf(value);
} }
} }

@ -20,80 +20,213 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
import java.util.Date; import java.util.Date;
import java.util.Queue; import java.util.List;
import java.util.concurrent.Future; import java.util.concurrent.Future;
/** /**
* <p>Interface for ffmpeg and ffprobe execute sessions. * <p>Common interface for all <code>FFmpegKit</code> sessions.
*/ */
public interface Session { public interface Session {
/**
* Returns the session specific execute callback function.
*
* @return session specific execute callback function
*/
ExecuteCallback getExecuteCallback(); ExecuteCallback getExecuteCallback();
/**
* Returns the session specific log callback function.
*
* @return session specific log callback function
*/
LogCallback getLogCallback(); LogCallback getLogCallback();
StatisticsCallback getStatisticsCallback(); /**
* Returns the session identifier.
*
* @return session identifier
*/
long getSessionId(); long getSessionId();
/**
* Returns session create time.
*
* @return session create time
*/
Date getCreateTime(); Date getCreateTime();
/**
* Returns session start time.
*
* @return session start time
*/
Date getStartTime(); Date getStartTime();
/**
* Returns session end time.
*
* @return session end time
*/
Date getEndTime(); Date getEndTime();
/**
* Returns the time taken to execute this session.
*
* @return time taken to execute this session in milliseconds or zero (0) if the session is
* not over yet
*/
long getDuration(); long getDuration();
/**
* Returns command arguments as an array.
*
* @return command arguments as an array
*/
String[] getArguments(); String[] getArguments();
/**
* Returns command arguments as a concatenated string.
*
* @return command arguments as a concatenated string
*/
String getCommand(); String getCommand();
Queue<Log> getAllLogs(final int waitTimeout); /**
* Returns all log entries generated for this session. If there are asynchronous
Queue<Log> getAllLogs(); * messages that are not delivered yet, this method waits for them until the given timeout.
*
Queue<Log> getLogs(); * @param waitTimeout wait timeout for asynchronous messages in milliseconds
* @return list of log entries generated for this session
*/
List<Log> getAllLogs(final int waitTimeout);
/**
* Returns all log entries generated for this session. If there are asynchronous
* messages that are not delivered yet, this method waits for them.
*
* @return list of log entries generated for this session
*/
List<Log> getAllLogs();
/**
* Returns all log entries delivered for this session. Note that if there are asynchronous log
* messages that are not delivered yet, this method will not wait for them and will return
* immediately.
*
* @return list of log entries received for this session
*/
List<Log> getLogs();
/**
* Returns all log entries generated for this session as a concatenated string. If there are
* asynchronous messages that are not delivered yet, this method waits for them until
* the given timeout.
*
* @param waitTimeout wait timeout for asynchronous messages in milliseconds
* @return all log entries generated for this session as a concatenated string
*/
String getAllLogsAsString(final int waitTimeout); String getAllLogsAsString(final int waitTimeout);
/**
* Returns all log entries generated for this session as a concatenated string. If there are
* asynchronous messages that are not delivered yet, this method waits for them.
*
* @return all log entries generated for this session as a concatenated string
*/
String getAllLogsAsString(); String getAllLogsAsString();
/**
* Returns all log entries delivered for this session as a concatenated string. Note that if
* there are asynchronous log messages that are not delivered yet, this method will not wait
* for them and will return immediately.
*
* @return list of log entries received for this session
*/
String getLogsAsString(); String getLogsAsString();
Queue<Statistics> getAllStatistics(final int waitTimeout); /**
* Returns the log output generated while running the session.
Queue<Statistics> getAllStatistics(); *
* @return log output generated
Queue<Statistics> getStatistics(); */
String getOutput();
/**
* Returns the state of the session.
*
* @return state of the session
*/
SessionState getState(); SessionState getState();
int getReturnCode(); /**
* Returns the return code for this session. Note that return code is only set for sessions
* that end with COMPLETED state. If a session is not started, still running or failed then
* this method returns null.
*
* @return the return code for this session if the session is COMPLETED, null if session is
* not started, still running or failed
*/
ReturnCode getReturnCode();
/**
* Returns the stack trace of the exception received while executing this session.
* <p>
* The stack trace is only set for sessions that end with FAILED state. For sessions that has
* COMPLETED state this method returns null.
*
* @return stack trace of the exception received while executing this session, null if session
* is not started, still running or completed
*/
String getFailStackTrace(); String getFailStackTrace();
/**
* Returns session specific log redirection strategy.
*
* @return session specific log redirection strategy
*/
LogRedirectionStrategy getLogRedirectionStrategy(); LogRedirectionStrategy getLogRedirectionStrategy();
boolean thereAreCallbackMessagesInTransmit(); /**
* Returns whether there are still asynchronous messages being transmitted for this
* session or not.
*
* @return true if there are still asynchronous messages being transmitted, false
* otherwise
*/
boolean thereAreAsynchronousMessagesInTransmit();
/**
* Adds a new log entry for this session.
*
* @param log log entry
*/
void addLog(final Log log); void addLog(final Log log);
void addStatistics(final Statistics statistics); /**
* Returns the future created for this session, if it is executed asynchronously.
*
* @return future that runs this session asynchronously
*/
Future<?> getFuture(); Future<?> getFuture();
void setFuture(final Future<?> future); /**
* Returns whether it is an <code>FFmpeg</code> session or not.
void startRunning(); *
* @return true if it is an <code>FFmpeg</code> session, false otherwise
void complete(final int returnCode); */
void fail(final Exception exception);
boolean isFFmpeg(); boolean isFFmpeg();
/**
* Returns whether it is an <code>FFprobe</code> session or not.
*
* @return true if it is an <code>FFprobe</code> session, false otherwise
*/
boolean isFFprobe(); boolean isFFprobe();
/**
* Cancels running the session.
*/
void cancel(); void cancel();
} }

@ -32,17 +32,6 @@ public class Statistics {
private double bitrate; private double bitrate;
private double speed; private double speed;
public Statistics() {
sessionId = 0;
videoFrameNumber = 0;
videoFps = 0;
videoQuality = 0;
size = 0;
time = 0;
bitrate = 0;
speed = 0;
}
public Statistics(final long sessionId, final int videoFrameNumber, final float videoFps, final float videoQuality, final long size, final int time, final double bitrate, final double speed) { public Statistics(final long sessionId, final int videoFrameNumber, final float videoFps, final float videoQuality, final long size, final int time, final double bitrate, final double speed) {
this.sessionId = sessionId; this.sessionId = sessionId;
this.videoFrameNumber = videoFrameNumber; this.videoFrameNumber = videoFrameNumber;

@ -20,7 +20,7 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
/** /**
* <p>Callback function to receive statistics for executions. * <p>Callback function that receives statistics generated for <code>FFmpegKit</code> sessions.
*/ */
@FunctionalInterface @FunctionalInterface
public interface StatisticsCallback { public interface StatisticsCallback {

@ -27,24 +27,24 @@ import org.json.JSONObject;
public class StreamInformation { public class StreamInformation {
/* COMMON KEYS */ /* COMMON KEYS */
private static final String KEY_INDEX = "index"; public static final String KEY_INDEX = "index";
private static final String KEY_TYPE = "codec_type"; public static final String KEY_TYPE = "codec_type";
private static final String KEY_CODEC = "codec_name"; public static final String KEY_CODEC = "codec_name";
private static final String KEY_CODEC_LONG = "codec_long_name"; public static final String KEY_CODEC_LONG = "codec_long_name";
private static final String KEY_FORMAT = "pix_fmt"; public static final String KEY_FORMAT = "pix_fmt";
private static final String KEY_WIDTH = "width"; public static final String KEY_WIDTH = "width";
private static final String KEY_HEIGHT = "height"; public static final String KEY_HEIGHT = "height";
private static final String KEY_BIT_RATE = "bit_rate"; public static final String KEY_BIT_RATE = "bit_rate";
private static final String KEY_SAMPLE_RATE = "sample_rate"; public static final String KEY_SAMPLE_RATE = "sample_rate";
private static final String KEY_SAMPLE_FORMAT = "sample_fmt"; public static final String KEY_SAMPLE_FORMAT = "sample_fmt";
private static final String KEY_CHANNEL_LAYOUT = "channel_layout"; public static final String KEY_CHANNEL_LAYOUT = "channel_layout";
private static final String KEY_SAMPLE_ASPECT_RATIO = "sample_aspect_ratio"; public static final String KEY_SAMPLE_ASPECT_RATIO = "sample_aspect_ratio";
private static final String KEY_DISPLAY_ASPECT_RATIO = "display_aspect_ratio"; public static final String KEY_DISPLAY_ASPECT_RATIO = "display_aspect_ratio";
private static final String KEY_AVERAGE_FRAME_RATE = "avg_frame_rate"; public static final String KEY_AVERAGE_FRAME_RATE = "avg_frame_rate";
private static final String KEY_REAL_FRAME_RATE = "r_frame_rate"; public static final String KEY_REAL_FRAME_RATE = "r_frame_rate";
private static final String KEY_TIME_BASE = "time_base"; public static final String KEY_TIME_BASE = "time_base";
private static final String KEY_CODEC_TIME_BASE = "codec_time_base"; public static final String KEY_CODEC_TIME_BASE = "codec_time_base";
private static final String KEY_TAGS = "tags"; public static final String KEY_TAGS = "tags";
/** /**
* Stores all properties. * Stores all properties.

@ -1,44 +0,0 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit;
import org.junit.Assert;
import org.junit.Test;
public class AbstractSessionTest {
private static final String[] TEST_ARGUMENTS = new String[]{"argument1", "argument2"};
@Test
public void getLogsAsStringTest() {
final FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS, null, null, null, LogRedirectionStrategy.ALWAYS_PRINT_LOGS);
String logMessage1 = "i am log one";
String logMessage2 = "i am log two";
ffprobeSession.addLog(new Log(ffprobeSession.getSessionId(), Level.AV_LOG_DEBUG, logMessage1));
ffprobeSession.addLog(new Log(ffprobeSession.getSessionId(), Level.AV_LOG_DEBUG, logMessage2));
String logsAsString = ffprobeSession.getLogsAsString();
Assert.assertEquals(logMessage1 + logMessage2, logsAsString);
}
}

@ -445,7 +445,7 @@ public class FFmpegKitTest {
@Test @Test
public void mediaInformationMp3() { public void mediaInformationMp3() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_MP3); MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_MP3);
Assert.assertNotNull(mediaInformation); Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "mp3", "sample.mp3"); assertMediaInput(mediaInformation, "mp3", "sample.mp3");
@ -463,7 +463,7 @@ public class FFmpegKitTest {
@Test @Test
public void mediaInformationJpg() { public void mediaInformationJpg() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_JPG); MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_JPG);
Assert.assertNotNull(mediaInformation); Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "image2", "sample.jpg"); assertMediaInput(mediaInformation, "image2", "sample.jpg");
@ -475,7 +475,7 @@ public class FFmpegKitTest {
@Test @Test
public void mediaInformationGif() { public void mediaInformationGif() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_GIF); MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_GIF);
Assert.assertNotNull(mediaInformation); Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "gif", "sample.gif"); assertMediaInput(mediaInformation, "gif", "sample.gif");
@ -487,7 +487,7 @@ public class FFmpegKitTest {
@Test @Test
public void mediaInformationMp4() { public void mediaInformationMp4() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_MP4); MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_MP4);
Assert.assertNotNull(mediaInformation); Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "mov,mp4,m4a,3gp,3g2,mj2", "sample.mp4"); assertMediaInput(mediaInformation, "mov,mp4,m4a,3gp,3g2,mj2", "sample.mp4");
@ -508,7 +508,7 @@ public class FFmpegKitTest {
@Test @Test
public void mediaInformationPng() { public void mediaInformationPng() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_PNG); MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_PNG);
Assert.assertNotNull(mediaInformation); Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "png_pipe", "sample.png"); assertMediaInput(mediaInformation, "png_pipe", "sample.png");
@ -520,7 +520,7 @@ public class FFmpegKitTest {
@Test @Test
public void mediaInformationOgg() { public void mediaInformationOgg() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_OGG); MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_OGG);
Assert.assertNotNull(mediaInformation); Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "ogg", "sample.ogg"); assertMediaInput(mediaInformation, "ogg", "sample.ogg");

@ -0,0 +1,350 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit;
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
public class FFmpegSessionTest {
static {
System.setProperty("enable.ffmpeg.kit.test.mode", "true");
}
private static final String[] TEST_ARGUMENTS = new String[]{"argument1", "argument2"};
@Test
public void constructorTest() {
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS);
// 1. getExecuteCallback
Assert.assertNull(ffmpegSession.getExecuteCallback());
// 2. getLogCallback
Assert.assertNull(ffmpegSession.getLogCallback());
// 3. getStatisticsCallback
Assert.assertNull(ffmpegSession.getStatisticsCallback());
// 4. getSessionId
Assert.assertTrue(ffmpegSession.getSessionId() > 0);
// 5. getCreateTime
Assert.assertTrue(ffmpegSession.getCreateTime().getTime() <= System.currentTimeMillis());
// 6. getStartTime
Assert.assertNull(ffmpegSession.getStartTime());
// 7. getEndTime
Assert.assertNull(ffmpegSession.getEndTime());
// 8. getDuration
Assert.assertEquals(0, ffmpegSession.getDuration());
// 9. getArguments
Assert.assertArrayEquals(TEST_ARGUMENTS, ffmpegSession.getArguments());
// 10. getCommand
StringBuilder commandBuilder = new StringBuilder();
for (int i = 0; i < TEST_ARGUMENTS.length; i++) {
if (i > 0) {
commandBuilder.append(" ");
}
commandBuilder.append(TEST_ARGUMENTS[i]);
}
Assert.assertEquals(commandBuilder.toString(), ffmpegSession.getCommand());
// 11. getLogs
Assert.assertEquals(0, ffmpegSession.getLogs().size());
// 12. getLogsAsString
Assert.assertEquals("", ffmpegSession.getLogsAsString());
// 13. getState
Assert.assertEquals(SessionState.CREATED, ffmpegSession.getState());
// 14. getState
Assert.assertNull(ffmpegSession.getReturnCode());
// 15. getFailStackTrace
Assert.assertNull(ffmpegSession.getFailStackTrace());
// 16. getLogRedirectionStrategy
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffmpegSession.getLogRedirectionStrategy());
// 17. getFuture
Assert.assertNull(ffmpegSession.getFuture());
}
@Test
public void constructorTest2() {
ExecuteCallback executeCallback = new ExecuteCallback() {
@Override
public void apply(Session session) {
}
};
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS, executeCallback);
// 1. getExecuteCallback
Assert.assertEquals(ffmpegSession.getExecuteCallback(), executeCallback);
// 2. getLogCallback
Assert.assertNull(ffmpegSession.getLogCallback());
// 3. getStatisticsCallback
Assert.assertNull(ffmpegSession.getStatisticsCallback());
// 4. getSessionId
Assert.assertTrue(ffmpegSession.getSessionId() > 0);
// 5. getCreateTime
Assert.assertTrue(ffmpegSession.getCreateTime().getTime() <= System.currentTimeMillis());
// 6. getStartTime
Assert.assertNull(ffmpegSession.getStartTime());
// 7. getEndTime
Assert.assertNull(ffmpegSession.getEndTime());
// 8. getDuration
Assert.assertEquals(0, ffmpegSession.getDuration());
// 9. getArguments
Assert.assertArrayEquals(TEST_ARGUMENTS, ffmpegSession.getArguments());
// 10. getCommand
StringBuilder commandBuilder = new StringBuilder();
for (int i = 0; i < TEST_ARGUMENTS.length; i++) {
if (i > 0) {
commandBuilder.append(" ");
}
commandBuilder.append(TEST_ARGUMENTS[i]);
}
Assert.assertEquals(commandBuilder.toString(), ffmpegSession.getCommand());
// 11. getLogs
Assert.assertEquals(0, ffmpegSession.getLogs().size());
// 12. getLogsAsString
Assert.assertEquals("", ffmpegSession.getLogsAsString());
// 13. getState
Assert.assertEquals(SessionState.CREATED, ffmpegSession.getState());
// 14. getState
Assert.assertNull(ffmpegSession.getReturnCode());
// 15. getFailStackTrace
Assert.assertNull(ffmpegSession.getFailStackTrace());
// 16. getLogRedirectionStrategy
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffmpegSession.getLogRedirectionStrategy());
// 17. getFuture
Assert.assertNull(ffmpegSession.getFuture());
}
@Test
public void constructorTest3() {
ExecuteCallback executeCallback = new ExecuteCallback() {
@Override
public void apply(Session session) {
}
};
LogCallback logCallback = new LogCallback() {
@Override
public void apply(Log log) {
}
};
StatisticsCallback statisticsCallback = new StatisticsCallback() {
@Override
public void apply(Statistics statistics) {
}
};
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS, executeCallback, logCallback, statisticsCallback);
// 1. getExecuteCallback
Assert.assertEquals(ffmpegSession.getExecuteCallback(), executeCallback);
// 2. getLogCallback
Assert.assertEquals(ffmpegSession.getLogCallback(), logCallback);
// 3. getStatisticsCallback
Assert.assertEquals(ffmpegSession.getStatisticsCallback(), statisticsCallback);
// 4. getSessionId
Assert.assertTrue(ffmpegSession.getSessionId() > 0);
// 5. getCreateTime
Assert.assertTrue(ffmpegSession.getCreateTime().getTime() <= System.currentTimeMillis());
// 6. getStartTime
Assert.assertNull(ffmpegSession.getStartTime());
// 7. getEndTime
Assert.assertNull(ffmpegSession.getEndTime());
// 8. getDuration
Assert.assertEquals(0, ffmpegSession.getDuration());
// 9. getArguments
Assert.assertArrayEquals(TEST_ARGUMENTS, ffmpegSession.getArguments());
// 10. getCommand
StringBuilder commandBuilder = new StringBuilder();
for (int i = 0; i < TEST_ARGUMENTS.length; i++) {
if (i > 0) {
commandBuilder.append(" ");
}
commandBuilder.append(TEST_ARGUMENTS[i]);
}
Assert.assertEquals(commandBuilder.toString(), ffmpegSession.getCommand());
// 11. getLogs
Assert.assertEquals(0, ffmpegSession.getLogs().size());
// 12. getLogsAsString
Assert.assertEquals("", ffmpegSession.getLogsAsString());
// 13. getState
Assert.assertEquals(SessionState.CREATED, ffmpegSession.getState());
// 14. getState
Assert.assertNull(ffmpegSession.getReturnCode());
// 15. getFailStackTrace
Assert.assertNull(ffmpegSession.getFailStackTrace());
// 16. getLogRedirectionStrategy
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffmpegSession.getLogRedirectionStrategy());
// 17. getFuture
Assert.assertNull(ffmpegSession.getFuture());
}
@Test
public void getSessionIdTest() {
FFmpegSession ffmpegSession1 = new FFmpegSession(TEST_ARGUMENTS);
FFmpegSession ffmpegSession2 = new FFmpegSession(TEST_ARGUMENTS);
FFmpegSession ffmpegSession3 = new FFmpegSession(TEST_ARGUMENTS);
Assert.assertTrue(ffmpegSession3.getSessionId() > ffmpegSession2.getSessionId());
Assert.assertTrue(ffmpegSession3.getSessionId() > ffmpegSession1.getSessionId());
Assert.assertTrue(ffmpegSession2.getSessionId() > ffmpegSession1.getSessionId());
Assert.assertTrue(ffmpegSession1.getSessionId() > 0);
Assert.assertTrue(ffmpegSession2.getSessionId() > 0);
Assert.assertTrue(ffmpegSession3.getSessionId() > 0);
}
@Test
public void getLogs() {
final FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS);
String logMessage1 = "i am log one";
String logMessage2 = "i am log two";
String logMessage3 = "i am log three";
ffmpegSession.addLog(new Log(ffmpegSession.getSessionId(), Level.AV_LOG_INFO, logMessage1));
ffmpegSession.addLog(new Log(ffmpegSession.getSessionId(), Level.AV_LOG_DEBUG, logMessage2));
ffmpegSession.addLog(new Log(ffmpegSession.getSessionId(), Level.AV_LOG_TRACE, logMessage3));
List<Log> logs = ffmpegSession.getLogs();
Assert.assertEquals(3, logs.size());
}
@Test
public void getLogsAsStringTest() {
final FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS);
String logMessage1 = "i am log one";
String logMessage2 = "i am log two";
ffmpegSession.addLog(new Log(ffmpegSession.getSessionId(), Level.AV_LOG_DEBUG, logMessage1));
ffmpegSession.addLog(new Log(ffmpegSession.getSessionId(), Level.AV_LOG_DEBUG, logMessage2));
String logsAsString = ffmpegSession.getLogsAsString();
Assert.assertEquals(logMessage1 + logMessage2, logsAsString);
}
@Test
public void getLogRedirectionStrategy() {
FFmpegKitConfig.setLogRedirectionStrategy(LogRedirectionStrategy.NEVER_PRINT_LOGS);
final FFmpegSession ffmpegSession1 = new FFmpegSession(TEST_ARGUMENTS);
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffmpegSession1.getLogRedirectionStrategy());
FFmpegKitConfig.setLogRedirectionStrategy(LogRedirectionStrategy.PRINT_LOGS_WHEN_SESSION_CALLBACK_NOT_DEFINED);
final FFmpegSession ffmpegSession2 = new FFmpegSession(TEST_ARGUMENTS);
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffmpegSession2.getLogRedirectionStrategy());
}
@Test
public void startRunningTest() {
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS);
ffmpegSession.startRunning();
Assert.assertEquals(SessionState.RUNNING, ffmpegSession.getState());
Assert.assertTrue(ffmpegSession.getStartTime().getTime() <= System.currentTimeMillis());
Assert.assertTrue(ffmpegSession.getCreateTime().getTime() <= ffmpegSession.getStartTime().getTime());
}
@Test
public void completeTest() {
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS);
ffmpegSession.startRunning();
ffmpegSession.complete(new ReturnCode(100));
Assert.assertEquals(SessionState.COMPLETED, ffmpegSession.getState());
Assert.assertEquals(100, ffmpegSession.getReturnCode().getValue());
Assert.assertTrue(ffmpegSession.getStartTime().getTime() <= ffmpegSession.getEndTime().getTime());
Assert.assertTrue(ffmpegSession.getDuration() >= 0);
}
@Test
public void failTest() {
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS);
ffmpegSession.startRunning();
ffmpegSession.fail(new Exception(""));
Assert.assertEquals(SessionState.FAILED, ffmpegSession.getState());
Assert.assertNull(ffmpegSession.getReturnCode());
Assert.assertTrue(ffmpegSession.getStartTime().getTime() <= ffmpegSession.getEndTime().getTime());
Assert.assertTrue(ffmpegSession.getDuration() >= 0);
Assert.assertNotNull(ffmpegSession.getFailStackTrace());
}
}

@ -0,0 +1,334 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.ffmpegkit;
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
public class FFprobeSessionTest {
static {
System.setProperty("enable.ffmpeg.kit.test.mode", "true");
}
private static final String[] TEST_ARGUMENTS = new String[]{"argument1", "argument2"};
@Test
public void constructorTest() {
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS);
// 1. getExecuteCallback
Assert.assertNull(ffprobeSession.getExecuteCallback());
// 2. getLogCallback
Assert.assertNull(ffprobeSession.getLogCallback());
// 3. getSessionId
Assert.assertTrue(ffprobeSession.getSessionId() > 0);
// 4. getCreateTime
Assert.assertTrue(ffprobeSession.getCreateTime().getTime() <= System.currentTimeMillis());
// 5. getStartTime
Assert.assertNull(ffprobeSession.getStartTime());
// 6. getEndTime
Assert.assertNull(ffprobeSession.getEndTime());
// 7. getDuration
Assert.assertEquals(0, ffprobeSession.getDuration());
// 8. getArguments
Assert.assertArrayEquals(TEST_ARGUMENTS, ffprobeSession.getArguments());
// 9. getCommand
StringBuilder commandBuilder = new StringBuilder();
for (int i = 0; i < TEST_ARGUMENTS.length; i++) {
if (i > 0) {
commandBuilder.append(" ");
}
commandBuilder.append(TEST_ARGUMENTS[i]);
}
Assert.assertEquals(commandBuilder.toString(), ffprobeSession.getCommand());
// 10. getLogs
Assert.assertEquals(0, ffprobeSession.getLogs().size());
// 11. getLogsAsString
Assert.assertEquals("", ffprobeSession.getLogsAsString());
// 12. getState
Assert.assertEquals(SessionState.CREATED, ffprobeSession.getState());
// 13. getState
Assert.assertNull(ffprobeSession.getReturnCode());
// 14. getFailStackTrace
Assert.assertNull(ffprobeSession.getFailStackTrace());
// 15. getLogRedirectionStrategy
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffprobeSession.getLogRedirectionStrategy());
// 16. getFuture
Assert.assertNull(ffprobeSession.getFuture());
}
@Test
public void constructorTest2() {
ExecuteCallback executeCallback = new ExecuteCallback() {
@Override
public void apply(Session session) {
}
};
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS, executeCallback);
// 1. getExecuteCallback
Assert.assertEquals(ffprobeSession.getExecuteCallback(), executeCallback);
// 2. getLogCallback
Assert.assertNull(ffprobeSession.getLogCallback());
// 3. getSessionId
Assert.assertTrue(ffprobeSession.getSessionId() > 0);
// 4. getCreateTime
Assert.assertTrue(ffprobeSession.getCreateTime().getTime() <= System.currentTimeMillis());
// 5. getStartTime
Assert.assertNull(ffprobeSession.getStartTime());
// 6. getEndTime
Assert.assertNull(ffprobeSession.getEndTime());
// 7. getDuration
Assert.assertEquals(0, ffprobeSession.getDuration());
// 8. getArguments
Assert.assertArrayEquals(TEST_ARGUMENTS, ffprobeSession.getArguments());
// 9. getCommand
StringBuilder commandBuilder = new StringBuilder();
for (int i = 0; i < TEST_ARGUMENTS.length; i++) {
if (i > 0) {
commandBuilder.append(" ");
}
commandBuilder.append(TEST_ARGUMENTS[i]);
}
Assert.assertEquals(commandBuilder.toString(), ffprobeSession.getCommand());
// 10. getLogs
Assert.assertEquals(0, ffprobeSession.getLogs().size());
// 11. getLogsAsString
Assert.assertEquals("", ffprobeSession.getLogsAsString());
// 12. getState
Assert.assertEquals(SessionState.CREATED, ffprobeSession.getState());
// 13. getState
Assert.assertNull(ffprobeSession.getReturnCode());
// 14. getFailStackTrace
Assert.assertNull(ffprobeSession.getFailStackTrace());
// 15. getLogRedirectionStrategy
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffprobeSession.getLogRedirectionStrategy());
// 16. getFuture
Assert.assertNull(ffprobeSession.getFuture());
}
@Test
public void constructorTest3() {
ExecuteCallback executeCallback = new ExecuteCallback() {
@Override
public void apply(Session session) {
}
};
LogCallback logCallback = new LogCallback() {
@Override
public void apply(Log log) {
}
};
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS, executeCallback, logCallback);
// 1. getExecuteCallback
Assert.assertEquals(ffprobeSession.getExecuteCallback(), executeCallback);
// 2. getLogCallback
Assert.assertEquals(ffprobeSession.getLogCallback(), logCallback);
// 3. getSessionId
Assert.assertTrue(ffprobeSession.getSessionId() > 0);
// 4. getCreateTime
Assert.assertTrue(ffprobeSession.getCreateTime().getTime() <= System.currentTimeMillis());
// 5. getStartTime
Assert.assertNull(ffprobeSession.getStartTime());
// 6. getEndTime
Assert.assertNull(ffprobeSession.getEndTime());
// 7. getDuration
Assert.assertEquals(0, ffprobeSession.getDuration());
// 8. getArguments
Assert.assertArrayEquals(TEST_ARGUMENTS, ffprobeSession.getArguments());
// 9. getCommand
StringBuilder commandBuilder = new StringBuilder();
for (int i = 0; i < TEST_ARGUMENTS.length; i++) {
if (i > 0) {
commandBuilder.append(" ");
}
commandBuilder.append(TEST_ARGUMENTS[i]);
}
Assert.assertEquals(commandBuilder.toString(), ffprobeSession.getCommand());
// 10. getLogs
Assert.assertEquals(0, ffprobeSession.getLogs().size());
// 11. getLogsAsString
Assert.assertEquals("", ffprobeSession.getLogsAsString());
// 12. getState
Assert.assertEquals(SessionState.CREATED, ffprobeSession.getState());
// 13. getState
Assert.assertNull(ffprobeSession.getReturnCode());
// 14. getFailStackTrace
Assert.assertNull(ffprobeSession.getFailStackTrace());
// 15. getLogRedirectionStrategy
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffprobeSession.getLogRedirectionStrategy());
// 16. getFuture
Assert.assertNull(ffprobeSession.getFuture());
}
@Test
public void getSessionIdTest() {
FFprobeSession ffprobeSession1 = new FFprobeSession(TEST_ARGUMENTS);
FFprobeSession ffprobeSession2 = new FFprobeSession(TEST_ARGUMENTS);
FFprobeSession ffprobeSession3 = new FFprobeSession(TEST_ARGUMENTS);
Assert.assertTrue(ffprobeSession3.getSessionId() > ffprobeSession2.getSessionId());
Assert.assertTrue(ffprobeSession3.getSessionId() > ffprobeSession1.getSessionId());
Assert.assertTrue(ffprobeSession2.getSessionId() > ffprobeSession1.getSessionId());
Assert.assertTrue(ffprobeSession1.getSessionId() > 0);
Assert.assertTrue(ffprobeSession2.getSessionId() > 0);
Assert.assertTrue(ffprobeSession3.getSessionId() > 0);
}
@Test
public void getLogs() {
final FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS);
String logMessage1 = "i am log one";
String logMessage2 = "i am log two";
String logMessage3 = "i am log three";
ffprobeSession.addLog(new Log(ffprobeSession.getSessionId(), Level.AV_LOG_INFO, logMessage1));
ffprobeSession.addLog(new Log(ffprobeSession.getSessionId(), Level.AV_LOG_DEBUG, logMessage2));
ffprobeSession.addLog(new Log(ffprobeSession.getSessionId(), Level.AV_LOG_TRACE, logMessage3));
List<Log> logs = ffprobeSession.getLogs();
Assert.assertEquals(3, logs.size());
}
@Test
public void getLogsAsStringTest() {
final FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS);
String logMessage1 = "i am log one";
String logMessage2 = "i am log two";
ffprobeSession.addLog(new Log(ffprobeSession.getSessionId(), Level.AV_LOG_DEBUG, logMessage1));
ffprobeSession.addLog(new Log(ffprobeSession.getSessionId(), Level.AV_LOG_DEBUG, logMessage2));
String logsAsString = ffprobeSession.getLogsAsString();
Assert.assertEquals(logMessage1 + logMessage2, logsAsString);
}
@Test
public void getLogRedirectionStrategy() {
FFmpegKitConfig.setLogRedirectionStrategy(LogRedirectionStrategy.NEVER_PRINT_LOGS);
final FFprobeSession ffprobeSession1 = new FFprobeSession(TEST_ARGUMENTS);
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffprobeSession1.getLogRedirectionStrategy());
FFmpegKitConfig.setLogRedirectionStrategy(LogRedirectionStrategy.PRINT_LOGS_WHEN_SESSION_CALLBACK_NOT_DEFINED);
final FFprobeSession ffprobeSession2 = new FFprobeSession(TEST_ARGUMENTS);
Assert.assertEquals(FFmpegKitConfig.getLogRedirectionStrategy(), ffprobeSession2.getLogRedirectionStrategy());
}
@Test
public void startRunningTest() {
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS);
ffprobeSession.startRunning();
Assert.assertEquals(SessionState.RUNNING, ffprobeSession.getState());
Assert.assertTrue(ffprobeSession.getStartTime().getTime() <= System.currentTimeMillis());
Assert.assertTrue(ffprobeSession.getCreateTime().getTime() <= ffprobeSession.getStartTime().getTime());
}
@Test
public void completeTest() {
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS);
ffprobeSession.startRunning();
ffprobeSession.complete(new ReturnCode(100));
Assert.assertEquals(SessionState.COMPLETED, ffprobeSession.getState());
Assert.assertEquals(100, ffprobeSession.getReturnCode().getValue());
Assert.assertTrue(ffprobeSession.getStartTime().getTime() <= ffprobeSession.getEndTime().getTime());
Assert.assertTrue(ffprobeSession.getDuration() >= 0);
}
@Test
public void failTest() {
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS);
ffprobeSession.startRunning();
ffprobeSession.fail(new Exception(""));
Assert.assertEquals(SessionState.FAILED, ffprobeSession.getState());
Assert.assertNull(ffprobeSession.getReturnCode());
Assert.assertTrue(ffprobeSession.getStartTime().getTime() <= ffprobeSession.getEndTime().getTime());
Assert.assertTrue(ffprobeSession.getDuration() >= 0);
Assert.assertNotNull(ffprobeSession.getFailStackTrace());
}
}

@ -1,4 +1,2 @@
include ':ffmpeg-kit-android-lib' include ':ffmpeg-kit-android-lib'
include ':ffmpeg-kit'
project(':ffmpeg-kit').projectDir = new File('..')
rootProject.name = 'ffmpeg-kit-android' rootProject.name = 'ffmpeg-kit-android'

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -198,6 +198,8 @@ am__relativize = \
DIST_ARCHIVES = $(distdir).tar.gz DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best GZIP_ENV = --best
DIST_TARGETS = dist-gzip DIST_TARGETS = dist-gzip
# Exists only to be overridden by the user if desired.
AM_DISTCHECK_DVI_TARGET = dvi
distuninstallcheck_listfiles = find . -type f -print distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@ -623,7 +625,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \ --srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \

13
apple/aclocal.m4 vendored

@ -1,4 +1,4 @@
# generated automatically by aclocal 1.16.2 -*- Autoconf -*- # generated automatically by aclocal 1.16.3 -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc. # Copyright (C) 1996-2020 Free Software Foundation, Inc.
@ -35,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16' [am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.16.2], [], m4_if([$1], [1.16.3], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
]) ])
@ -51,7 +51,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.2])dnl [AM_AUTOMAKE_VERSION([1.16.3])dnl
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@ -799,12 +799,7 @@ AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then if test x"${MISSING+set}" != xset; then
case $am_aux_dir in MISSING="\${SHELL} '$am_aux_dir/missing'"
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi fi
# Use eval to expand $SHELL # Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then if eval "$MISSING --is-lightweight"; then

221
apple/config.guess vendored

@ -2,7 +2,7 @@
# Attempt to guess a canonical system name. # Attempt to guess a canonical system name.
# Copyright 1992-2020 Free Software Foundation, Inc. # Copyright 1992-2020 Free Software Foundation, Inc.
timestamp='2020-11-19' timestamp='2020-08-17'
# This file is free software; you can redistribute it and/or modify it # This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by # under the terms of the GNU General Public License as published by
@ -27,12 +27,12 @@ timestamp='2020-11-19'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
# #
# You can get the latest version of this script from: # You can get the latest version of this script from:
# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
# #
# Please send patches to <config-patches@gnu.org>. # Please send patches to <config-patches@gnu.org>.
me=$(echo "$0" | sed -e 's,.*/,,') me=`echo "$0" | sed -e 's,.*/,,'`
usage="\ usage="\
Usage: $0 [OPTION] Usage: $0 [OPTION]
@ -103,7 +103,7 @@ set_cc_for_build() {
test "$tmp" && return 0 test "$tmp" && return 0
: "${TMPDIR=/tmp}" : "${TMPDIR=/tmp}"
# shellcheck disable=SC2039 # shellcheck disable=SC2039
{ tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } || { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
@ -131,14 +131,16 @@ if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH PATH=$PATH:/.attbin ; export PATH
fi fi
UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "$UNAME_SYSTEM" in case "$UNAME_SYSTEM" in
Linux|GNU|GNU/*) Linux|GNU|GNU/*)
LIBC=unknown # If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
set_cc_for_build set_cc_for_build
cat <<-EOF > "$dummy.c" cat <<-EOF > "$dummy.c"
@ -147,29 +149,17 @@ Linux|GNU|GNU/*)
LIBC=uclibc LIBC=uclibc
#elif defined(__dietlibc__) #elif defined(__dietlibc__)
LIBC=dietlibc LIBC=dietlibc
#elif defined(__GLIBC__)
LIBC=gnu
#else #else
#include <stdarg.h> LIBC=gnu
/* First heuristic to detect musl libc. */
#ifdef __DEFINED_va_list
LIBC=musl
#endif
#endif #endif
EOF EOF
eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')" eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
# Second heuristic to detect musl libc. # If ldd exists, use it to detect musl libc.
if [ "$LIBC" = unknown ] && if command -v ldd >/dev/null && \
command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl
ldd --version 2>&1 | grep -q ^musl; then then
LIBC=musl LIBC=musl
fi
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
if [ "$LIBC" = unknown ]; then
LIBC=gnu
fi fi
;; ;;
esac esac
@ -189,20 +179,19 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# Note: NetBSD doesn't particularly care about the vendor # Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown". # portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch" sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
"/sbin/$sysctl" 2>/dev/null || \ "/sbin/$sysctl" 2>/dev/null || \
"/usr/sbin/$sysctl" 2>/dev/null || \ "/usr/sbin/$sysctl" 2>/dev/null || \
echo unknown)) echo unknown)`
case "$UNAME_MACHINE_ARCH" in case "$UNAME_MACHINE_ARCH" in
aarch64eb) machine=aarch64_be-unknown ;;
armeb) machine=armeb-unknown ;; armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;; arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;; sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;; sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;; sh5el) machine=sh5le-unknown ;;
earmv*) earmv*)
arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,') arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p') endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
machine="${arch}${endian}"-unknown machine="${arch}${endian}"-unknown
;; ;;
*) machine="$UNAME_MACHINE_ARCH"-unknown ;; *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
@ -233,7 +222,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
case "$UNAME_MACHINE_ARCH" in case "$UNAME_MACHINE_ARCH" in
earm*) earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//' expr='s/^earmv[0-9]/-eabi/;s/eb$//'
abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr") abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
;; ;;
esac esac
# The OS release # The OS release
@ -246,7 +235,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
release='-gnu' release='-gnu'
;; ;;
*) *)
release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2) release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
;; ;;
esac esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
@ -255,15 +244,15 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
echo "$machine-${os}${release}${abi-}" echo "$machine-${os}${release}${abi-}"
exit ;; exit ;;
*:Bitrig:*:*) *:Bitrig:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//') UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
exit ;; exit ;;
*:OpenBSD:*:*) *:OpenBSD:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//') UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
exit ;; exit ;;
*:LibertyBSD:*:*) *:LibertyBSD:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//') UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
exit ;; exit ;;
*:MidnightBSD:*:*) *:MidnightBSD:*:*)
@ -299,17 +288,17 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
alpha:OSF1:*:*) alpha:OSF1:*:*)
case $UNAME_RELEASE in case $UNAME_RELEASE in
*4.0) *4.0)
UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}') UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;; ;;
*5.*) *5.*)
UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}') UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;; ;;
esac esac
# According to Compaq, /usr/sbin/psrinfo has been available on # According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that # OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU # covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0. # types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1) ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in case "$ALPHA_CPU_TYPE" in
"EV4 (21064)") "EV4 (21064)")
UNAME_MACHINE=alpha ;; UNAME_MACHINE=alpha ;;
@ -347,7 +336,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# A Tn.n version is a released field test version. # A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel. # A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r. # 1.2 uses "1.2" for uname -r.
echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)" echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
# Reset EXIT trap before exiting to avoid spurious non-zero exit code. # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$? exitcode=$?
trap '' 0 trap '' 0
@ -381,7 +370,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
exit ;; exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "$( (/bin/universe) 2>/dev/null)" = att ; then if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3 echo pyramid-pyramid-sysv3
else else
echo pyramid-pyramid-bsd echo pyramid-pyramid-bsd
@ -394,17 +383,17 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
echo sparc-icl-nx6 echo sparc-icl-nx6
exit ;; exit ;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case $(/usr/bin/uname -p) in case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;; sparc) echo sparc-icl-nx7; exit ;;
esac ;; esac ;;
s390x:SunOS:*:*) s390x:SunOS:*:*)
echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
exit ;; exit ;;
sun4H:SunOS:5.*:*) sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;; exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
exit ;; exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux"$UNAME_RELEASE" echo i386-pc-auroraux"$UNAME_RELEASE"
@ -423,30 +412,30 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
SUN_ARCH=x86_64 SUN_ARCH=x86_64
fi fi
fi fi
echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;; exit ;;
sun4*:SunOS:6*:*) sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize # According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but # SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4. # it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;; exit ;;
sun4*:SunOS:*:*) sun4*:SunOS:*:*)
case "$(/usr/bin/arch -k)" in case "`/usr/bin/arch -k`" in
Series*|S4*) Series*|S4*)
UNAME_RELEASE=$(uname -v) UNAME_RELEASE=`uname -v`
;; ;;
esac esac
# Japanese Language versions have a version number like `4.1.3-JL'. # Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')" echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
exit ;; exit ;;
sun3*:SunOS:*:*) sun3*:SunOS:*:*)
echo m68k-sun-sunos"$UNAME_RELEASE" echo m68k-sun-sunos"$UNAME_RELEASE"
exit ;; exit ;;
sun*:*:4.2BSD:*) sun*:*:4.2BSD:*)
UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
case "$(/bin/arch)" in case "`/bin/arch`" in
sun3) sun3)
echo m68k-sun-sunos"$UNAME_RELEASE" echo m68k-sun-sunos"$UNAME_RELEASE"
;; ;;
@ -526,8 +515,8 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
} }
EOF EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" && $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') && dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=$("$dummy" "$dummyarg") && SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; } { echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos"$UNAME_RELEASE" echo mips-mips-riscos"$UNAME_RELEASE"
exit ;; exit ;;
@ -554,7 +543,7 @@ EOF
exit ;; exit ;;
AViiON:dgux:*:*) AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures # DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=$(/usr/bin/uname -p) UNAME_PROCESSOR=`/usr/bin/uname -p`
if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
then then
if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
@ -582,17 +571,17 @@ EOF
echo m68k-tektronix-bsd echo m68k-tektronix-bsd
exit ;; exit ;;
*:IRIX*:*:*) *:IRIX*:*:*)
echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')" echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
exit ;; exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX ' exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*) i*86:AIX:*:*)
echo i386-ibm-aix echo i386-ibm-aix
exit ;; exit ;;
ia64:AIX:*:*) ia64:AIX:*:*)
if test -x /usr/bin/oslevel ; then if test -x /usr/bin/oslevel ; then
IBM_REV=$(/usr/bin/oslevel) IBM_REV=`/usr/bin/oslevel`
else else
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi fi
@ -612,7 +601,7 @@ EOF
exit(0); exit(0);
} }
EOF EOF
if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then then
echo "$SYSTEM_NAME" echo "$SYSTEM_NAME"
else else
@ -625,15 +614,15 @@ EOF
fi fi
exit ;; exit ;;
*:AIX:*:[4567]) *:AIX:*:[4567])
IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }') IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000 IBM_ARCH=rs6000
else else
IBM_ARCH=powerpc IBM_ARCH=powerpc
fi fi
if test -x /usr/bin/lslpp ; then if test -x /usr/bin/lslpp ; then
IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc | IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/) awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else else
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi fi
@ -661,14 +650,14 @@ EOF
echo m68k-hp-bsd4.4 echo m68k-hp-bsd4.4
exit ;; exit ;;
9000/[34678]??:HP-UX:*:*) 9000/[34678]??:HP-UX:*:*)
HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
case "$UNAME_MACHINE" in case "$UNAME_MACHINE" in
9000/31?) HP_ARCH=m68000 ;; 9000/31?) HP_ARCH=m68000 ;;
9000/[34]??) HP_ARCH=m68k ;; 9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9]) 9000/[678][0-9][0-9])
if test -x /usr/bin/getconf; then if test -x /usr/bin/getconf; then
sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null) sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null) sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "$sc_cpu_version" in case "$sc_cpu_version" in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
@ -715,7 +704,7 @@ EOF
exit (0); exit (0);
} }
EOF EOF
(CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy") (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
test -z "$HP_ARCH" && HP_ARCH=hppa test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;; fi ;;
esac esac
@ -743,7 +732,7 @@ EOF
echo "$HP_ARCH"-hp-hpux"$HPUX_REV" echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
exit ;; exit ;;
ia64:HP-UX:*:*) ia64:HP-UX:*:*)
HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux"$HPUX_REV" echo ia64-hp-hpux"$HPUX_REV"
exit ;; exit ;;
3050*:HI-UX:*:*) 3050*:HI-UX:*:*)
@ -773,7 +762,7 @@ EOF
exit (0); exit (0);
} }
EOF EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") && $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; } { echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2 echo unknown-hitachi-hiuxwe2
exit ;; exit ;;
@ -842,14 +831,14 @@ EOF
echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;; exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/') FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;; exit ;;
5000:UNIX_System_V:4.*:*) 5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/') FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;; exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
@ -862,25 +851,25 @@ EOF
echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
exit ;; exit ;;
arm:FreeBSD:*:*) arm:FreeBSD:*:*)
UNAME_PROCESSOR=$(uname -p) UNAME_PROCESSOR=`uname -p`
set_cc_for_build set_cc_for_build
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP | grep -q __ARM_PCS_VFP
then then
echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi
else else
echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf
fi fi
exit ;; exit ;;
*:FreeBSD:*:*) *:FreeBSD:*:*)
UNAME_PROCESSOR=$(/usr/bin/uname -p) UNAME_PROCESSOR=`/usr/bin/uname -p`
case "$UNAME_PROCESSOR" in case "$UNAME_PROCESSOR" in
amd64) amd64)
UNAME_PROCESSOR=x86_64 ;; UNAME_PROCESSOR=x86_64 ;;
i386) i386)
UNAME_PROCESSOR=i586 ;; UNAME_PROCESSOR=i586 ;;
esac esac
echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
exit ;; exit ;;
i*:CYGWIN*:*) i*:CYGWIN*:*)
echo "$UNAME_MACHINE"-pc-cygwin echo "$UNAME_MACHINE"-pc-cygwin
@ -916,15 +905,15 @@ EOF
echo x86_64-pc-cygwin echo x86_64-pc-cygwin
exit ;; exit ;;
prep*:SunOS:5.*:*) prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;; exit ;;
*:GNU:*:*) *:GNU:*:*)
# the GNU system # the GNU system
echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')" echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
exit ;; exit ;;
*:GNU/*:*:*) *:GNU/*:*:*)
# other systems with GNU libc and userland # other systems with GNU libc and userland
echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC" echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
exit ;; exit ;;
*:Minix:*:*) *:Minix:*:*)
echo "$UNAME_MACHINE"-unknown-minix echo "$UNAME_MACHINE"-unknown-minix
@ -937,7 +926,7 @@ EOF
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;; exit ;;
alpha:Linux:*:*) alpha:Linux:*:*)
case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;; EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;; EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;; PCA56) UNAME_MACHINE=alphapca56 ;;
@ -1046,7 +1035,7 @@ EOF
#endif #endif
#endif #endif
EOF EOF
eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')" eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`"
test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
;; ;;
mips64el:Linux:*:*) mips64el:Linux:*:*)
@ -1066,7 +1055,7 @@ EOF
exit ;; exit ;;
parisc:Linux:*:* | hppa:Linux:*:*) parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level # Look for CPU level
case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
*) echo hppa-unknown-linux-"$LIBC" ;; *) echo hppa-unknown-linux-"$LIBC" ;;
@ -1156,7 +1145,7 @@ EOF
echo "$UNAME_MACHINE"-pc-msdosdjgpp echo "$UNAME_MACHINE"-pc-msdosdjgpp
exit ;; exit ;;
i*86:*:4.*:*) i*86:*:4.*:*)
UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//') UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
else else
@ -1165,7 +1154,7 @@ EOF
exit ;; exit ;;
i*86:*:5:[678]*) i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6. # UnixWare 7.x, OpenUNIX and OpenServer 6.
case $(/bin/uname -X | grep "^Machine") in case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;; *486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;; *Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
@ -1174,10 +1163,10 @@ EOF
exit ;; exit ;;
i*86:*:3.2:*) i*86:*:3.2:*)
if test -f /usr/options/cb.name; then if test -f /usr/options/cb.name; then
UNAME_REL=$(sed -n 's/.*Version //p' </usr/options/cb.name) UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL" echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
elif /bin/uname -X 2>/dev/null >/dev/null ; then elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //')) UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586 && UNAME_MACHINE=i586
@ -1227,7 +1216,7 @@ EOF
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL='' OS_REL=''
test -r /etc/.relid \ test -r /etc/.relid \
&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; } && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
@ -1238,7 +1227,7 @@ EOF
NCR*:*:4.2:* | MPRAS*:*:4.2:*) NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3' OS_REL='.3'
test -r /etc/.relid \ test -r /etc/.relid \
&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; } && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
@ -1271,7 +1260,7 @@ EOF
exit ;; exit ;;
*:SINIX-*:*:*) *:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=$( (uname -p) 2>/dev/null) UNAME_MACHINE=`(uname -p) 2>/dev/null`
echo "$UNAME_MACHINE"-sni-sysv4 echo "$UNAME_MACHINE"-sni-sysv4
else else
echo ns32k-sni-sysv echo ns32k-sni-sysv
@ -1357,7 +1346,7 @@ EOF
echo aarch64-apple-darwin"$UNAME_RELEASE" echo aarch64-apple-darwin"$UNAME_RELEASE"
exit ;; exit ;;
*:Darwin:*:*) *:Darwin:*:*)
UNAME_PROCESSOR=$(uname -p) UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;; unknown) UNAME_PROCESSOR=powerpc ;;
esac esac
@ -1394,7 +1383,7 @@ EOF
echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
exit ;; exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*) *:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=$(uname -p) UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = x86; then if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386 UNAME_PROCESSOR=i386
UNAME_MACHINE=pc UNAME_MACHINE=pc
@ -1462,10 +1451,10 @@ EOF
echo mips-sei-seiux"$UNAME_RELEASE" echo mips-sei-seiux"$UNAME_RELEASE"
exit ;; exit ;;
*:DragonFly:*:*) *:DragonFly:*:*)
echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
exit ;; exit ;;
*:*VMS:*:*) *:*VMS:*:*)
UNAME_MACHINE=$( (uname -p) 2>/dev/null) UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "$UNAME_MACHINE" in case "$UNAME_MACHINE" in
A*) echo alpha-dec-vms ; exit ;; A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;;
@ -1475,7 +1464,7 @@ EOF
echo i386-pc-xenix echo i386-pc-xenix
exit ;; exit ;;
i*86:skyos:*:*) i*86:skyos:*:*)
echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')" echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
exit ;; exit ;;
i*86:rdos:*:*) i*86:rdos:*:*)
echo "$UNAME_MACHINE"-pc-rdos echo "$UNAME_MACHINE"-pc-rdos
@ -1533,7 +1522,7 @@ main ()
#define __ARCHITECTURE__ "m68k" #define __ARCHITECTURE__ "m68k"
#endif #endif
int version; int version;
version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null); version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
if (version < 4) if (version < 4)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else else
@ -1625,7 +1614,7 @@ main ()
} }
EOF EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) && $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` &&
{ echo "$SYSTEM_NAME"; exit; } { echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment. # Apollos put the system type in the environment.
@ -1650,14 +1639,14 @@ This script (version $timestamp), has failed to recognize the
operating system you are using. If your script is old, overwrite *all* operating system you are using. If your script is old, overwrite *all*
copies of config.guess and config.sub with the latest versions from: copies of config.guess and config.sub with the latest versions from:
https://git.savannah.gnu.org/cgit/config.git/plain/config.guess https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and and
https://git.savannah.gnu.org/cgit/config.git/plain/config.sub https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
EOF EOF
year=$(echo $timestamp | sed 's,-.*,,') year=`echo $timestamp | sed 's,-.*,,'`
# shellcheck disable=SC2003 # shellcheck disable=SC2003
if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then if test "`expr "\`date +%Y\`" - "$year"`" -lt 3 ; then
cat >&2 <<EOF cat >&2 <<EOF
If $0 has already been updated, send the following data and any If $0 has already been updated, send the following data and any
@ -1666,20 +1655,20 @@ provide the necessary information to handle your system.
config.guess timestamp = $timestamp config.guess timestamp = $timestamp
uname -m = $( (uname -m) 2>/dev/null || echo unknown) uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = $( (uname -r) 2>/dev/null || echo unknown) uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = $( (uname -s) 2>/dev/null || echo unknown) uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = $( (uname -v) 2>/dev/null || echo unknown) uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null) /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
/bin/uname -X = $( (/bin/uname -X) 2>/dev/null) /bin/uname -X = `(/bin/uname -X) 2>/dev/null`
hostinfo = $( (hostinfo) 2>/dev/null) hostinfo = `(hostinfo) 2>/dev/null`
/bin/universe = $( (/bin/universe) 2>/dev/null) /bin/universe = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null) /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch = $( (/bin/arch) 2>/dev/null) /bin/arch = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null) /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null) /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
UNAME_MACHINE = "$UNAME_MACHINE" UNAME_MACHINE = "$UNAME_MACHINE"
UNAME_RELEASE = "$UNAME_RELEASE" UNAME_RELEASE = "$UNAME_RELEASE"

59
apple/config.sub vendored

@ -2,7 +2,7 @@
# Configuration validation subroutine script. # Configuration validation subroutine script.
# Copyright 1992-2020 Free Software Foundation, Inc. # Copyright 1992-2020 Free Software Foundation, Inc.
timestamp='2020-12-02' timestamp='2020-08-17'
# This file is free software; you can redistribute it and/or modify it # This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by # under the terms of the GNU General Public License as published by
@ -33,7 +33,7 @@ timestamp='2020-12-02'
# Otherwise, we print the canonical config type on stdout and succeed. # Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from: # You can get the latest version of this script from:
# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages # This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases # and recognize all the CPU types, system types and aliases
@ -50,7 +50,7 @@ timestamp='2020-12-02'
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification. # It is wrong to echo any other type of specification.
me=$(echo "$0" | sed -e 's,.*/,,') me=`echo "$0" | sed -e 's,.*/,,'`
usage="\ usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
@ -769,22 +769,22 @@ case $basic_machine in
vendor=hp vendor=hp
;; ;;
i*86v32) i*86v32)
cpu=$(echo "$1" | sed -e 's/86.*/86/') cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc vendor=pc
basic_os=sysv32 basic_os=sysv32
;; ;;
i*86v4*) i*86v4*)
cpu=$(echo "$1" | sed -e 's/86.*/86/') cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc vendor=pc
basic_os=sysv4 basic_os=sysv4
;; ;;
i*86v) i*86v)
cpu=$(echo "$1" | sed -e 's/86.*/86/') cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc vendor=pc
basic_os=sysv basic_os=sysv
;; ;;
i*86sol2) i*86sol2)
cpu=$(echo "$1" | sed -e 's/86.*/86/') cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc vendor=pc
basic_os=solaris2 basic_os=solaris2
;; ;;
@ -917,7 +917,7 @@ case $basic_machine in
;; ;;
leon-*|leon[3-9]-*) leon-*|leon[3-9]-*)
cpu=sparc cpu=sparc
vendor=$(echo "$basic_machine" | sed 's/-.*//') vendor=`echo "$basic_machine" | sed 's/-.*//'`
;; ;;
*-*) *-*)
@ -1084,7 +1084,7 @@ case $cpu-$vendor in
cpu=mipsisa64sb1el cpu=mipsisa64sb1el
;; ;;
sh5e[lb]-*) sh5e[lb]-*)
cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/') cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
;; ;;
spur-*) spur-*)
cpu=spur cpu=spur
@ -1102,7 +1102,7 @@ case $cpu-$vendor in
cpu=x86_64 cpu=x86_64
;; ;;
xscale-* | xscalee[bl]-*) xscale-* | xscalee[bl]-*)
cpu=$(echo "$cpu" | sed 's/^xscale/arm/') cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;; ;;
arm64-*) arm64-*)
cpu=aarch64 cpu=aarch64
@ -1241,7 +1241,6 @@ case $cpu-$vendor in
| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
| spu \ | spu \
| tahoe \ | tahoe \
| thumbv7* \
| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
| tron \ | tron \
| ubicom32 \ | ubicom32 \
@ -1287,15 +1286,11 @@ then
case $basic_os in case $basic_os in
gnu/linux*) gnu/linux*)
kernel=linux kernel=linux
os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|') os=`echo $basic_os | sed -e 's|gnu/linux|gnu|'`
;;
os2-emx)
kernel=os2
os=$(echo $basic_os | sed -e 's|os2-emx|emx|')
;; ;;
nto-qnx*) nto-qnx*)
kernel=nto kernel=nto
os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|') os=`echo $basic_os | sed -e 's|nto-qnx|qnx|'`
;; ;;
*-*) *-*)
# shellcheck disable=SC2162 # shellcheck disable=SC2162
@ -1306,11 +1301,11 @@ EOF
# Default OS when just kernel was specified # Default OS when just kernel was specified
nto*) nto*)
kernel=nto kernel=nto
os=$(echo $basic_os | sed -e 's|nto|qnx|') os=`echo $basic_os | sed -e 's|nto|qnx|'`
;; ;;
linux*) linux*)
kernel=linux kernel=linux
os=$(echo $basic_os | sed -e 's|linux|gnu|') os=`echo $basic_os | sed -e 's|linux|gnu|'`
;; ;;
*) *)
kernel= kernel=
@ -1331,7 +1326,7 @@ case $os in
os=cnk os=cnk
;; ;;
solaris1 | solaris1.*) solaris1 | solaris1.*)
os=$(echo $os | sed -e 's|solaris1|sunos4|') os=`echo $os | sed -e 's|solaris1|sunos4|'`
;; ;;
solaris) solaris)
os=solaris2 os=solaris2
@ -1360,7 +1355,7 @@ case $os in
os=sco3.2v4 os=sco3.2v4
;; ;;
sco3.2.[4-9]*) sco3.2.[4-9]*)
os=$(echo $os | sed -e 's/sco3.2./sco3.2v/') os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
;; ;;
sco*v* | scout) sco*v* | scout)
# Don't match below # Don't match below
@ -1372,7 +1367,13 @@ case $os in
os=psos os=psos
;; ;;
qnx*) qnx*)
os=qnx case $cpu in
x86 | i*86)
;;
*)
os=nto-$os
;;
esac
;; ;;
hiux*) hiux*)
os=hiuxwe2 os=hiuxwe2
@ -1390,7 +1391,7 @@ case $os in
os=lynxos os=lynxos
;; ;;
mac[0-9]*) mac[0-9]*)
os=$(echo "$os" | sed -e 's|mac|macos|') os=`echo "$os" | sed -e 's|mac|macos|'`
;; ;;
opened*) opened*)
os=openedition os=openedition
@ -1399,10 +1400,10 @@ case $os in
os=os400 os=os400
;; ;;
sunos5*) sunos5*)
os=$(echo "$os" | sed -e 's|sunos5|solaris2|') os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;; ;;
sunos6*) sunos6*)
os=$(echo "$os" | sed -e 's|sunos6|solaris3|') os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;; ;;
wince*) wince*)
os=wince os=wince
@ -1436,7 +1437,7 @@ case $os in
;; ;;
# Preserve the version number of sinix5. # Preserve the version number of sinix5.
sinix5.*) sinix5.*)
os=$(echo $os | sed -e 's|sinix|sysv|') os=`echo $os | sed -e 's|sinix|sysv|'`
;; ;;
sinix*) sinix*)
os=sysv4 os=sysv4
@ -1721,7 +1722,7 @@ case $os in
| skyos* | haiku* | rdos* | toppers* | drops* | es* \ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*) | nsk* | powerunix* | genode* | zvmoe* )
;; ;;
# This one is extra strict with allowed versions # This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*) sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@ -1740,8 +1741,6 @@ esac
case $kernel-$os in case $kernel-$os in
linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
;; ;;
uclinux-uclibc* )
;;
-dietlibc* | -newlib* | -musl* | -uclibc* ) -dietlibc* | -newlib* | -musl* | -uclibc* )
# These are just libc implementations, not actual OSes, and thus # These are just libc implementations, not actual OSes, and thus
# require a kernel. # require a kernel.
@ -1752,8 +1751,6 @@ case $kernel-$os in
;; ;;
nto-qnx*) nto-qnx*)
;; ;;
os2-emx)
;;
*-eabi* | *-gnueabi*) *-eabi* | *-gnueabi*)
;; ;;
-*) -*)

7
apple/configure vendored

@ -2663,12 +2663,7 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
am_aux_dir=`cd "$ac_aux_dir" && pwd` am_aux_dir=`cd "$ac_aux_dir" && pwd`
if test x"${MISSING+set}" != xset; then if test x"${MISSING+set}" != xset; then
case $am_aux_dir in MISSING="\${SHELL} '$am_aux_dir/missing'"
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi fi
# Use eval to expand $SHELL # Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then if eval "$MISSING --is-lightweight"; then

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# install - install a program, script, or datafile # install - install a program, script, or datafile
scriptversion=2018-03-11.20; # UTC scriptversion=2020-11-14.01; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was # This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the # later released in X11R6 (xc/config/util/install.sh) with the
@ -69,6 +69,11 @@ posix_mkdir=
# Desired mode of installed file. # Desired mode of installed file.
mode=0755 mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd= chgrpcmd=
chmodcmd=$chmodprog chmodcmd=$chmodprog
chowncmd= chowncmd=
@ -99,18 +104,28 @@ Options:
--version display version info and exit. --version display version info and exit.
-c (ignored) -c (ignored)
-C install only if different (preserve the last data modification time) -C install only if different (preserve data modification time)
-d create directories instead of installing files. -d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP. -g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE. -m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER. -o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files. -s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY. -t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory. -T report an error if DSTFILE is a directory.
Environment variables override the default commands: Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Email bug reports to bug-automake@gnu.org.
Automake home page: https://www.gnu.org/software/automake/
" "
while test $# -ne 0; do while test $# -ne 0; do
@ -137,8 +152,13 @@ while test $# -ne 0; do
-o) chowncmd="$chownprog $2" -o) chowncmd="$chownprog $2"
shift;; shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;; -s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t) -t)
is_target_a_directory=always is_target_a_directory=always
dst_arg=$2 dst_arg=$2
@ -255,6 +275,10 @@ do
dstdir=$dst dstdir=$dst
test -d "$dstdir" test -d "$dstdir"
dstdir_status=$? dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
@ -301,22 +325,6 @@ do
if test $dstdir_status != 0; then if test $dstdir_status != 0; then
case $posix_mkdir in case $posix_mkdir in
'') '')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode. # With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask. # Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then if test -n "$dir_arg"; then
@ -326,52 +334,49 @@ do
fi fi
posix_mkdir=false posix_mkdir=false
case $umask in # The $RANDOM variable is not portable (e.g., dash). Use it
*[123567][0-7][0-7]) # here however when possible just to lower collision chance.
# POSIX mkdir -p sets u+wx bits regardless of umask, which tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;; trap '
*) ret=$?
# Note that $RANDOM variable is not portable (e.g. dash); Use it rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
# here however when possible just to lower collision chance. exit $ret
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ ' 0
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# Because "mkdir -p" follows existing symlinks and we likely work # directory is successfully created first before we actually test
# directly in world-writeable /tmp, make sure that the '$tmpdir' # 'mkdir -p'.
# directory is successfully created first before we actually test if (umask $mkdir_umask &&
# 'mkdir -p' feature. $mkdirprog $mkdir_mode "$tmpdir" &&
if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
$mkdirprog $mkdir_mode "$tmpdir" && then
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 if test -z "$dir_arg" || {
then # Check for POSIX incompatibilities with -m.
if test -z "$dir_arg" || { # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# Check for POSIX incompatibilities with -m. # other-writable bit of parent directory when it shouldn't.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
# other-writable bit of parent directory when it shouldn't. test_tmpdir="$tmpdir/a"
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
test_tmpdir="$tmpdir/a" case $ls_ld_tmpdir in
ls_ld_tmpdir=`ls -ld "$test_tmpdir"` d????-?r-*) different_mode=700;;
case $ls_ld_tmpdir in d????-?--*) different_mode=755;;
d????-?r-*) different_mode=700;; *) false;;
d????-?--*) different_mode=755;; esac &&
*) false;; $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
esac && ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && { test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` }
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" }
} then posix_mkdir=:
} fi
then posix_mkdir=: rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
fi else
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" # Remove any dirs left behind by ancient mkdir implementations.
else rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
# Remove any dirs left behind by ancient mkdir implementations. fi
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null trap '' 0;;
fi
trap '' 0;;
esac;;
esac esac
if if
@ -382,7 +387,7 @@ do
then : then :
else else
# The umask is ridiculous, or mkdir does not conform to POSIX, # mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the # or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go. # directory the slow way, step by step, checking for races as we go.
@ -411,7 +416,7 @@ do
prefixes= prefixes=
else else
if $posix_mkdir; then if $posix_mkdir; then
(umask=$mkdir_umask && (umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently. # Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1 test -d "$prefix" || exit 1
@ -488,6 +493,13 @@ do
then then
rm -f "$dsttmp" rm -f "$dsttmp"
else else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Rename the file to the real destination. # Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
@ -502,9 +514,9 @@ do
# file should still install successfully. # file should still install successfully.
{ {
test ! -f "$dst" || test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null || $doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} || } ||
{ echo "$0: cannot unlink or rename $dst" >&2 { echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1 (exit 1); exit 1

@ -0,0 +1,56 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_ABSTRACT_SESSION_H
#define FFMPEG_KIT_ABSTRACT_SESSION_H
#import <Foundation/Foundation.h>
#import "Session.h"
/**
* Defines how long default "getAll" methods wait, in milliseconds.
*/
extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
/**
* Abstract session implementation which includes common features shared by <code>FFmpeg</code>
* and <code>FFprobe</code> sessions.
*/
@interface AbstractSession : NSObject<Session>
/**
* Creates a new abstract session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
* @param logDelegate session specific log delegate
* @param logRedirectionStrategy session specific log redirection strategy
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
/**
* Waits for all asynchronous messages to be transmitted until the given timeout.
*
* @param timeout wait timeout in milliseconds
*/
- (void)waitForAsynchronousMessagesInTransmit:(int)timeout;
@end
#endif // FFMPEG_KIT_ABSTRACT_SESSION_H

@ -0,0 +1,235 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "AbstractSession.h"
#import "AtomicLong.h"
#import "ExecuteDelegate.h"
#import "FFmpegKit.h"
#import "FFmpegKitConfig.h"
#import "LogDelegate.h"
#import "ReturnCode.h"
int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit = 5000;
static AtomicLong *sessionIdGenerator = nil;
@implementation AbstractSession {
long _sessionId;
id<ExecuteDelegate> _executeDelegate;
id<LogDelegate> _logDelegate;
NSDate* _createTime;
NSDate* _startTime;
NSDate* _endTime;
NSArray* _arguments;
NSMutableArray* _logs;
NSRecursiveLock* _logsLock;
SessionState _state;
ReturnCode* _returnCode;
NSString* _failStackTrace;
LogRedirectionStrategy _logRedirectionStrategy;
}
+ (void)initialize {
sessionIdGenerator = [[AtomicLong alloc] initWithValue:1];
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
self = [super init];
if (self) {
_sessionId = [sessionIdGenerator incrementAndGet];
_executeDelegate = executeDelegate;
_logDelegate = logDelegate;
_createTime = [NSDate date];
_startTime = nil;
_endTime = nil;
_arguments = arguments;
_logs = [[NSMutableArray alloc] init];
_logsLock = [[NSRecursiveLock alloc] init];
_state = SessionStateCreated;
_returnCode = nil;
_failStackTrace = nil;
_logRedirectionStrategy = logRedirectionStrategy;
}
return self;
}
- (id<ExecuteDelegate>)getExecuteDelegate {
return _executeDelegate;
}
- (id<LogDelegate>)getLogDelegate {
return _logDelegate;
}
- (long)getSessionId {
return _sessionId;
}
- (NSDate*)getCreateTime {
return _createTime;
}
- (NSDate*)getStartTime {
return _startTime;
}
- (NSDate*)getEndTime {
return _endTime;
}
- (long)getDuration {
NSDate* startTime = _startTime;
NSDate* endTime = _endTime;
if (startTime != nil && endTime != nil) {
return [[NSNumber numberWithDouble:([endTime timeIntervalSinceDate:startTime]*1000)] longValue];
}
return 0;
}
- (NSArray*)getArguments {
return _arguments;
}
- (NSString*)getCommand {
return [FFmpegKit argumentsToString:_arguments];
}
- (void)waitForAsynchronousMessagesInTransmit:(int)timeout {
NSDate* expireDate = [[NSDate date] dateByAddingTimeInterval:((double)timeout)/1000];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
while ([self thereAreAsynchronousMessagesInTransmit] && ([[NSDate date] timeIntervalSinceDate:expireDate] < 0)) {
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 100 * NSEC_PER_MSEC));
}
}
- (NSArray*)getAllLogsWithTimeout:(int)waitTimeout {
[self waitForAsynchronousMessagesInTransmit:waitTimeout];
if ([self thereAreAsynchronousMessagesInTransmit]) {
NSLog(@"getAllLogsWithTimeout was called to return all logs but there are still logs being transmitted for session id %ld.", _sessionId);
}
return [self getLogs];
}
- (NSArray*)getAllLogs {
return [self getAllLogsWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
}
- (NSArray*)getLogs {
[_logsLock lock];
NSArray* logsCopy = [_logs copy];
[_logsLock unlock];
return logsCopy;
}
- (NSString*)getAllLogsAsStringWithTimeout:(int)waitTimeout {
[self waitForAsynchronousMessagesInTransmit:waitTimeout];
if ([self thereAreAsynchronousMessagesInTransmit]) {
NSLog(@"getAllLogsAsStringWithTimeout was called to return all logs but there are still logs being transmitted for session id %ld.", _sessionId);
}
return [self getAllLogsAsString];
}
- (NSString*)getAllLogsAsString {
return [self getAllLogsAsStringWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
}
- (NSString*)getLogsAsString {
NSMutableString* concatenatedString = [[NSMutableString alloc] init];
[_logsLock lock];
for (int i=0; i < [_logs count]; i++) {
[concatenatedString appendString:[[_logs objectAtIndex:i] getMessage]];
}
[_logsLock unlock];
return concatenatedString;
}
- (NSString*)getOutput {
return [self getAllLogsAsString];
}
- (SessionState)getState {
return _state;
}
- (ReturnCode*)getReturnCode {
return _returnCode;
}
- (NSString*)getFailStackTrace {
return _failStackTrace;
}
- (LogRedirectionStrategy)getLogRedirectionStrategy {
return _logRedirectionStrategy;
}
- (BOOL)thereAreAsynchronousMessagesInTransmit {
return ([FFmpegKitConfig messagesInTransmit:_sessionId] != 0);
}
- (void)addLog:(Log*)log {
[_logsLock lock];
[_logs addObject:log];
[_logsLock unlock];
}
- (void)startRunning {
_state = SessionStateRunning;
_startTime = [NSDate date];
}
- (void)complete:(ReturnCode*)returnCode {
_returnCode = returnCode;
_state = SessionStateCompleted;
_endTime = [NSDate date];
}
- (void)fail:(NSException*)exception {
_failStackTrace = [NSString stringWithFormat:@"%@", [exception callStackSymbols]];
_state = SessionStateFailed;
_endTime = [NSDate date];
}
- (BOOL)isFFmpeg {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (BOOL)isFFprobe {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (void)cancel {
if (_state == SessionStateRunning) {
[FFmpegKit cancel:_sessionId];
}
}
@end

@ -17,35 +17,30 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <sys/types.h> #ifndef FFMPEG_KIT_ARCH_DETECT_H
#include <sys/sysctl.h> #define FFMPEG_KIT_ARCH_DETECT_H
#include <mach/machine.h>
#include <Foundation/Foundation.h> #import <Foundation/Foundation.h>
/** /**
* This class is used to detect running architecture. * Detects the running architecture.
*/ */
@interface ArchDetect : NSObject @interface ArchDetect : NSObject
/** /**
* Returns running cpu architecture name. * Returns architecture name of the cpu running.
* *
* @return running cpu architecture name as NSString * @return architecture name of the cpu running
*/ */
+ (NSString*)getCpuArch; + (NSString*)getCpuArch;
/** /**
* Returns loaded architecture name. * Returns architecture name loaded.
* *
* @return loaded architecture name as NSString * @return architecture name loaded
*/ */
+ (NSString*)getArch; + (NSString*)getArch;
/**
* Returns whether FFmpegKit release is a long term release or not.
*
* @return yes=1 or no=0
*/
+ (int)isLTSBuild;
@end @end
#endif // FFMPEG_KIT_ARCH_DETECT_H

@ -17,32 +17,32 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "ArchDetect.h" #import <sys/types.h>
#include "FFmpegKitConfig.h" #import <sys/sysctl.h>
#include "FFmpegKit.h" #import <mach/machine.h>
#import "ArchDetect.h"
#import "FFmpegKitConfig.h"
#import "FFmpegKit.h"
#import "FFprobeKit.h"
@implementation ArchDetect @implementation ArchDetect
+ (void)initialize { + (void)initialize {
[FFmpegKitConfig class];
[FFmpegKit class]; [FFmpegKit class];
[FFmpegKitConfig class];
[FFprobeKit class];
} }
/**
* Returns running cpu architecture name.
*
* @return running cpu architecture name as NSString
*/
+ (NSString*)getCpuArch { + (NSString*)getCpuArch {
NSMutableString *cpu = [[NSMutableString alloc] init]; NSMutableString* cpu = [[NSMutableString alloc] init];
size_t size; size_t size;
cpu_type_t type; cpu_type_t type;
cpu_subtype_t subtype; cpu_subtype_t subtype;
size = sizeof(type); size = sizeof(type);
sysctlbyname("hw.cputype", &type, &size, NULL, 0); sysctlbyname("hw.cputype", &type, &size, nil, 0);
size = sizeof(subtype); size = sizeof(subtype);
sysctlbyname("hw.cpusubtype", &subtype, &size, NULL, 0); sysctlbyname("hw.cpusubtype", &subtype, &size, nil, 0);
if (type == CPU_TYPE_X86_64) { if (type == CPU_TYPE_X86_64) {
[cpu appendString:@"x86_64"]; [cpu appendString:@"x86_64"];
@ -118,9 +118,11 @@
case CPU_SUBTYPE_ARM_V7S: case CPU_SUBTYPE_ARM_V7S:
[cpu appendString:@"v7s"]; [cpu appendString:@"v7s"];
break; break;
#ifndef FFMPEG_KIT_LTS
case CPU_SUBTYPE_ARM_V8: case CPU_SUBTYPE_ARM_V8:
[cpu appendString:@"v8"]; [cpu appendString:@"v8"];
break; break;
#endif
} }
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120100 #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120100
@ -141,11 +143,6 @@
return cpu; return cpu;
} }
/**
* Returns loaded architecture name.
*
* @return loaded architecture name as NSString
*/
+ (NSString*)getArch { + (NSString*)getArch {
NSMutableString *arch = [[NSMutableString alloc] init]; NSMutableString *arch = [[NSMutableString alloc] init];
@ -155,6 +152,10 @@
[arch appendString:@"armv7s"]; [arch appendString:@"armv7s"];
#elif FFMPEG_KIT_ARM64 #elif FFMPEG_KIT_ARM64
[arch appendString:@"arm64"]; [arch appendString:@"arm64"];
#elif FFMPEG_KIT_ARM64_MAC_CATALYST
[arch appendString:@"arm64_mac_catalyst"];
#elif FFMPEG_KIT_ARM64_SIMULATOR
[arch appendString:@"arm64_simulator"];
#elif FFMPEG_KIT_ARM64E #elif FFMPEG_KIT_ARM64E
[arch appendString:@"arm64e"]; [arch appendString:@"arm64e"];
#elif FFMPEG_KIT_I386 #elif FFMPEG_KIT_I386
@ -168,17 +169,4 @@
return arch; return arch;
} }
/**
* Returns whether FFmpegKit release is a long term release or not.
*
* @return yes=1 or no=0
*/
+ (int)isLTSBuild {
#if defined(FFMPEG_KIT_LTS)
return 1;
#else
return 0;
#endif
}
@end @end

@ -17,15 +17,22 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <Foundation/Foundation.h> #ifndef FFMPEG_KIT_ATOMIC_LONG_H
#define FFMPEG_KIT_ATOMIC_LONG_H
#import <Foundation/Foundation.h>
/** /**
* Represents an atomic long data type. * Represents an atomic long data type.
*/ */
@interface AtomicLong : NSObject @interface AtomicLong : NSObject
- (instancetype)initWithInitialValue:(long)initialValue; - (instancetype)initWithValue:(long)value;
- (long)incrementAndGet; - (long)incrementAndGet;
- (long)getAndIncrement;
@end @end
#endif // FFMPEG_KIT_ATOMIC_LONG_H

@ -17,17 +17,23 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "AtomicLong.h" #import "AtomicLong.h"
@interface AtomicLong()
@property (strong) NSRecursiveLock* lock;
@end
@implementation AtomicLong { @implementation AtomicLong {
NSRecursiveLock *lock; long _value;
long value;
} }
- (instancetype)initWithInitialValue:(long)initialValue { - (instancetype)initWithValue:(long)value {
self = [super init]; self = [super init];
if (self) { if (self) {
value = initialValue; _value = value;
_lock = [[NSRecursiveLock alloc] init];
} }
return self; return self;
@ -36,10 +42,21 @@
- (long)incrementAndGet { - (long)incrementAndGet {
long returnValue; long returnValue;
[lock lock]; [self.lock lock];
value += 1; _value += 1;
returnValue = value; returnValue = _value;
[lock unlock]; [self.lock unlock];
return returnValue;
}
- (long)getAndIncrement {
long returnValue;
[self.lock lock];
returnValue = _value;
_value += 1;
[self.lock unlock];
return returnValue; return returnValue;
} }

@ -17,10 +17,43 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FFMPEG_KIT_EXECUTE_DELEGATE_H
#define FFMPEG_KIT_EXECUTE_DELEGATE_H
#import <Foundation/Foundation.h>
#import "Session.h"
@protocol Session;
/** /**
* Use this delegate to receive an asynchronous execution result. * <p>Delegate invoked when an asynchronous session ends running.
* <p>Session has either SessionStateCompleted or SessionStateFailed state when
* the delegate is invoked.
* <p>If it has SessionStateCompleted state, <code>ReturnCode</code> should be checked to
* see the execution result.
* <p>If <code>getState</code> returns SessionStateFailed then
* <code>getFailStackTrace</code> should be used to get the failure reason.
* <pre>
* switch ([session getState]) {
* case SessionStateCompleted:
* ReturnCode *returnCode = [session getReturnCode];
* break;
* case SessionStateFailed:
* NSString *failStackTrace = [session getFailStackTrace];
* break;
* }
* </pre>
*/ */
@protocol ExecuteDelegate<NSObject> @protocol ExecuteDelegate<NSObject>
@required @required
- (void)executeCallback:(long)executionId :(int)returnCode;
/**
* Called when an execution is completed.
*
* @param session session of the completed execution
*/
- (void)executeCallback:(id<Session>)session;
@end @end
#endif // FFMPEG_KIT_EXECUTE_DELEGATE_H

@ -1,35 +0,0 @@
/*
* Copyright (c) 2020-2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Foundation/Foundation.h>
/**
* Represents an ongoing FFmpeg execution.
*/
@interface FFmpegExecution : NSObject
- (instancetype)initWithExecutionId:(long)newExecutionId andArguments:(NSArray*)arguments;
- (NSDate*)getStartTime;
- (long)getExecutionId;
- (NSString*)getCommand;
@end

@ -1,52 +0,0 @@
/*
* Copyright (c) 2020-2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FFmpegExecution.h"
#include "FFmpegKit.h"
@implementation FFmpegExecution {
NSDate* startTime;
long executionId;
NSString* command;
}
- (instancetype)initWithExecutionId:(long)newExecutionId andArguments:(NSArray*)arguments {
self = [super init];
if (self) {
startTime = [NSDate date];
executionId = newExecutionId;
command = [FFmpegKit argumentsToString:arguments];
}
return self;
}
- (NSDate*)getStartTime {
return startTime;
}
- (long)getExecutionId {
return executionId;
}
- (NSString*)getCommand {
return command;
}
@end

@ -17,102 +17,168 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h> #ifndef FFMPEG_KIT_H
#include <stdlib.h> #define FFMPEG_KIT_H
#include <Foundation/Foundation.h>
#include "ExecuteDelegate.h"
/** Global library version */ #import <string.h>
extern NSString *const FFMPEG_KIT_VERSION; #import <stdlib.h>
#import <Foundation/Foundation.h>
#import "ExecuteDelegate.h"
#import "LogDelegate.h"
#import "FFmpegSession.h"
#import "StatisticsDelegate.h"
/** /**
* Main class for FFmpeg operations. * <p>Main class to run <code>FFmpeg</code> commands. Supports executing commands both
* synchronously and asynchronously.
* <pre>
* FFmpegSession *session = [FFmpegKit execute:@"-i file1.mp4 -c:v libxvid file1.avi"];
*
* FFmpegSession *asyncSession = [FFmpegKit executeAsync:@"-i file1.mp4 -c:v libxvid file1.avi" withExecuteDelegate:executeDelegate];
* </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific delegates.
* <pre>
* FFmpegSession *asyncSession = [FFmpegKit executeAsync:@"-i file1.mp4 -c:v libxvid file1.avi" withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
* </pre>
*/ */
@interface FFmpegKit : NSObject @interface FFmpegKit : NSObject
/** /**
* Synchronously executes FFmpeg with arguments provided. * <p>Synchronously executes FFmpeg with arguments provided.
* *
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @return zero on successful execution, 255 on user cancel and non-zero on error * @return FFmpeg session created for this execution
*/ */
+ (int)executeWithArguments:(NSArray*)arguments; + (FFmpegSession*)executeWithArguments:(NSArray*)arguments;
/** /**
* Asynchronously executes FFmpeg with arguments provided. Space character is used to split command into arguments. * <p>Asynchronously executes FFmpeg with arguments provided.
* *
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @param delegate delegate that will be notified when execution is completed * @param executeDelegate delegate that will be called when the execution is completed
* @return returns a unique id that represents this execution * @return FFmpeg session created for this execution
*/ */
+ (int)executeWithArgumentsAsync:(NSArray*)arguments withCallback:(id<ExecuteDelegate>)delegate; + (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/** /**
* Asynchronously executes FFmpeg with arguments provided. Space character is used to split command into arguments. * <p>Asynchronously executes FFmpeg with arguments provided.
* *
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @param delegate delegate that will be notified when execution is completed * @param executeDelegate delegate that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation * @param logDelegate delegate that will receive logs
* @return returns a unique id that represents this execution * @param statisticsDelegate delegate that will receive statistics
* @return FFmpeg session created for this execution
*/ */
+ (int)executeWithArgumentsAsync:(NSArray*)arguments withCallback:(id<ExecuteDelegate>)delegate andDispatchQueue:(dispatch_queue_t)queue; + (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate;
/** /**
* Synchronously executes FFmpeg command provided. Space character is used to split command into arguments. * <p>Asynchronously executes FFmpeg with arguments provided.
* *
* @param command FFmpeg command * @param arguments FFmpeg command options/arguments as string array
* @return zero on successful execution, 255 on user cancel and non-zero on error * @param executeDelegate delegate that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/ */
+ (int)execute:(NSString*)command; + (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue;
/** /**
* Asynchronously executes FFmpeg command provided. Space character is used to split command into arguments. * <p>Asynchronously executes FFmpeg with arguments provided.
* *
* @param command FFmpeg command * @param arguments FFmpeg command options/arguments as string array
* @param delegate delegate that will be notified when execution is completed * @param executeDelegate delegate that will be called when the execution is completed
* @return returns a unique id that represents this execution * @param logDelegate delegate that will receive logs
* @param statisticsDelegate delegate that will receive statistics
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/ */
+ (int)executeAsync:(NSString*)command withCallback:(id<ExecuteDelegate>)delegate; + (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate onDispatchQueue:(dispatch_queue_t)queue;
/** /**
* Asynchronously executes FFmpeg command provided. Space character is used to split command into arguments. * <p>Synchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* @param command FFmpeg command * @param command FFmpeg command
* @param delegate delegate that will be notified when execution is completed * @return FFmpeg session created for this execution
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return returns a unique id that represents this execution
*/ */
+ (int)executeAsync:(NSString*)command withCallback:(id<ExecuteDelegate>)delegate andDispatchQueue:(dispatch_queue_t)queue; + (FFmpegSession*)execute:(NSString*)command;
/** /**
* Synchronously executes FFmpeg command provided. Delimiter parameter is used to split command into arguments. * <p>Asynchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* @param command FFmpeg command * @param command FFmpeg command
* @param delimiter arguments delimiter * @param executeDelegate delegate that will be called when the execution is completed
* @deprecated argument splitting mechanism used in this method is pretty simple and prone to errors. Consider * @return FFmpeg session created for this execution
* using a more advanced method like execute or executeWithArguments */
* @return zero on successful execution, 255 on user cancel and non-zero on error + (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* <p>Asynchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
*
* @param command FFmpeg command
* @param executeDelegate delegate that will be called when the execution is completed
* @param logDelegate delegate that will receive logs
* @param statisticsDelegate delegate that will receive statistics
* @return FFmpeg session created for this execution
*/
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate;
/**
* <p>Asynchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
*
* @param command FFmpeg command
* @param executeDelegate delegate that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Asynchronously executes FFmpeg command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
*
* @param command FFmpeg command
* @param executeDelegate delegate that will be called when the execution is completed
* @param logDelegate delegate that will receive logs
* @param statisticsDelegate delegate that will receive statistics
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/ */
+ (int)execute:(NSString*)command delimiter:(NSString*)delimiter __attribute__((deprecated)); + (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate onDispatchQueue:(dispatch_queue_t)queue;
/** /**
* Cancels an ongoing operation. * <p>Cancels all running sessions.
* *
* This function does not wait for termination to complete and returns immediately. * <p>This function does not wait for termination to complete and returns immediately.
*/ */
+ (void)cancel; + (void)cancel;
/** /**
* Cancels an ongoing operation. * <p>Cancels the session specified with <code>sessionId</code>.
* *
* This function does not wait for termination to complete and returns immediately. * <p>This function does not wait for termination to complete and returns immediately.
* *
* @param executionId execution id * @param sessionId id of the session that will be cancelled
*/ */
+ (void)cancel:(long)executionId; + (void)cancel:(long)sessionId;
/** /**
* Parses the given command into arguments. * <p>Lists all FFmpeg sessions in the session history.
*
* @return all FFmpeg sessions in the session history
*/
+ (NSArray*)listSessions;
/**
* <p>Parses the given command into arguments. Uses space character to split the arguments.
* Supports single and double quote characters.
* *
* @param command string command * @param command string command
* @return array of arguments * @return array of arguments
@ -120,18 +186,13 @@ extern NSString *const FFMPEG_KIT_VERSION;
+ (NSArray*)parseArguments:(NSString*)command; + (NSArray*)parseArguments:(NSString*)command;
/** /**
* <p>Combines arguments into a string. * <p>Concatenates arguments into a string adding a space character between two arguments.
* *
* @param arguments arguments * @param arguments arguments
* @return string containing all arguments * @return concatenated string containing all arguments
*/ */
+ (NSString*)argumentsToString:(NSArray*)arguments; + (NSString*)argumentsToString:(NSArray*)arguments;
/** @end
* <p>Lists ongoing executions.
*
* @return list of ongoing executions
*/
+ (NSArray*)listExecutions;
@end #endif // FFMPEG_KIT_H

@ -17,210 +17,98 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "fftools_ffmpeg.h" #import "fftools_ffmpeg.h"
#import "ArchDetect.h"
#include "FFmpegKit.h" #import "AtomicLong.h"
#include "ArchDetect.h" #import "FFmpegKit.h"
#include "AtomicLong.h" #import "FFmpegKitConfig.h"
#include "FFmpegExecution.h" #import "Packages.h"
#include "FFmpegKitConfig.h"
/** Forward declaration for function defined in fftools_ffmpeg.c */
int ffmpeg_execute(int argc, char **argv);
@implementation FFmpegKit @implementation FFmpegKit
/** Global library version */
NSString *const FFMPEG_KIT_VERSION = @"4.4";
extern int lastReturnCode;
extern NSMutableString *lastCommandOutput;
long const DEFAULT_EXECUTION_ID = 0;
AtomicLong *executionIdCounter;
extern __thread volatile long executionId;
int cancelRequested(long executionId);
void addExecution(long executionId);
void removeExecution(long executionId);
NSMutableArray *executions;
NSLock *executionsLock;
extern int configuredLogLevel;
+ (void)initialize { + (void)initialize {
[FFmpegKitConfig class]; [FFmpegKitConfig class];
executionIdCounter = [[AtomicLong alloc] initWithInitialValue:3000]; NSLog(@"Loaded ffmpeg-kit-%@-%@-%@-%@\n", [Packages getPackageName], [ArchDetect getArch], [FFmpegKitConfig getVersion], [FFmpegKitConfig getBuildDate]);
executions = [[NSMutableArray alloc] init];
executionsLock = [[NSLock alloc] init];
NSLog(@"Loaded ffmpeg-kit-%@-%@-%@-%@\n", [FFmpegKitConfig getPackageName], [ArchDetect getArch], [FFmpegKitConfig getVersion], [FFmpegKitConfig getBuildDate]);
} }
+ (int)executeWithId:(long)newExecutionId andArguments:(NSArray*)arguments { + (FFmpegSession*)executeWithArguments:(NSArray*)arguments {
lastCommandOutput = [[NSMutableString alloc] init]; FFmpegSession* session = [[FFmpegSession alloc] init:arguments];
[FFmpegKitConfig ffmpegExecute:session];
// SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW EXECUTION return session;
av_log_set_level(configuredLogLevel); }
FFmpegExecution* currentFFmpegExecution = [[FFmpegExecution alloc] initWithExecutionId:newExecutionId andArguments:arguments];
[executionsLock lock];
[executions addObject: currentFFmpegExecution];
[executionsLock unlock];
char **commandCharPArray = (char **)av_malloc(sizeof(char*) * ([arguments count] + 1));
/* PRESERVING CALLING FORMAT
*
* ffmpeg <arguments>
*/
commandCharPArray[0] = (char *)av_malloc(sizeof(char) * ([LIB_NAME length] + 1));
strcpy(commandCharPArray[0], [LIB_NAME UTF8String]);
for (int i=0; i < [arguments count]; i++) {
NSString *argument = [arguments objectAtIndex:i];
commandCharPArray[i + 1] = (char *) [argument UTF8String];
}
// REGISTER THE ID BEFORE STARTING EXECUTION
executionId = newExecutionId;
addExecution(newExecutionId);
// RUN
lastReturnCode = ffmpeg_execute(([arguments count] + 1), commandCharPArray);
// ALWAYS REMOVE THE ID FROM THE MAP
removeExecution(newExecutionId);
// CLEANUP
av_free(commandCharPArray[0]);
av_free(commandCharPArray);
[executionsLock lock];
[executions removeObject: currentFFmpegExecution];
[executionsLock unlock];
return lastReturnCode; + (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
} }
/** + (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate {
* Synchronously executes FFmpeg with arguments provided. FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
* [FFmpegKitConfig asyncFFmpegExecute:session];
* @param arguments FFmpeg command options/arguments as string array return session;
* @return zero on successful execution, 255 on user cancel and non-zero on error
*/
+ (int)executeWithArguments:(NSArray*)arguments {
return [self executeWithId:DEFAULT_EXECUTION_ID andArguments:arguments];
} }
/** + (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue {
* Asynchronously executes FFmpeg with arguments provided. Space character is used to split command into arguments. FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteDelegate:executeDelegate];
* [FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
* @param arguments FFmpeg command options/arguments as string array return session;
* @param delegate delegate that will be notified when execution is completed
* @return a unique id that represents this execution
*/
+ (int)executeWithArgumentsAsync:(NSArray*)arguments withCallback:(id<ExecuteDelegate>)delegate {
return [self executeWithArgumentsAsync:arguments withCallback:delegate andDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
} }
/** + (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate onDispatchQueue:(dispatch_queue_t)queue {
* Asynchronously executes FFmpeg with arguments provided. Space character is used to split command into arguments. FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
* [FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
* @param arguments FFmpeg command options/arguments as string array return session;
* @param delegate delegate that will be notified when execution is completed }
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return a unique id that represents this execution
*/
+ (int)executeWithArgumentsAsync:(NSArray*)arguments withCallback:(id<ExecuteDelegate>)delegate andDispatchQueue:(dispatch_queue_t)queue {
const long newExecutionId = [executionIdCounter incrementAndGet];
dispatch_async(queue, ^{ + (FFmpegSession*)execute:(NSString*)command {
const int returnCode = [self executeWithId:newExecutionId andArguments:arguments]; FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command]];
if (delegate != nil) { [FFmpegKitConfig ffmpegExecute:session];
[delegate executeCallback:executionId:returnCode]; return session;
} }
});
return newExecutionId; + (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
} }
/** + (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate {
* Synchronously executes FFmpeg command provided. Space character is used to split command into arguments. FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
* [FFmpegKitConfig asyncFFmpegExecute:session];
* @param command FFmpeg command return session;
* @return zero on successful execution, 255 on user cancel and non-zero on error
*/
+ (int)execute:(NSString*)command {
return [self executeWithArguments: [self parseArguments: command]];
} }
/** + (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue {
* Asynchronously executes FFmpeg command provided. Space character is used to split command into arguments. FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate];
* [FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
* @param command FFmpeg command return session;
* @param delegate delegate that will be notified when execution is completed
* @return a unique id that represents this execution
*/
+ (int)executeAsync:(NSString*)command withCallback:(id<ExecuteDelegate>)delegate {
return [self executeAsync:command withCallback:delegate andDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
} }
/** + (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate onDispatchQueue:(dispatch_queue_t)queue {
* Asynchronously executes FFmpeg command provided. Space character is used to split command into arguments. FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
* [FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
* @param command FFmpeg command return session;
* @param delegate delegate that will be notified when execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return a unique id that represents this execution
*/
+ (int)executeAsync:(NSString*)command withCallback:(id<ExecuteDelegate>)delegate andDispatchQueue:(dispatch_queue_t)queue {
return [self executeWithArgumentsAsync:[self parseArguments:command] withCallback:delegate andDispatchQueue:queue];
} }
/** + (void)cancel {
* Synchronously executes FFmpeg command provided. Delimiter parameter is used to split command into arguments.
*
* @param command FFmpeg command
* @param delimiter arguments delimiter
* @return zero on successful execution, 255 on user cancel and non-zero on error
*/
+ (int)execute:(NSString*)command delimiter:(NSString*)delimiter {
// SPLITTING ARGUMENTS /*
NSArray* argumentArray = [command componentsSeparatedByString:(delimiter == nil ? @" ": delimiter)]; * ZERO (0) IS A SPECIAL SESSION ID
return [self executeWithArguments:argumentArray]; * WHEN IT IS PASSED TO THIS METHOD, A SIGINT IS GENERATED WHICH CANCELS ALL ONGOING SESSIONS
*/
cancel_operation(0);
} }
/** + (void)cancel:(long)sessionId {
* Cancels an ongoing operation. cancel_operation(sessionId);
*
* This function does not wait for termination to complete and returns immediately.
*/
+ (void)cancel {
cancel_operation(DEFAULT_EXECUTION_ID);
} }
/** + (NSArray*)listSessions {
* Cancels an ongoing operation. return [FFmpegKitConfig getFFmpegSessions];
*
* This function does not wait for termination to complete and returns immediately.
*
* @param executionId execution id
*/
+ (void)cancel:(long)executionId {
cancel_operation(executionId);
} }
/**
* Parses the given command into arguments.
*
* @param command string command
* @return array of arguments
*/
+ (NSArray*)parseArguments:(NSString*)command { + (NSArray*)parseArguments:(NSString*)command {
NSMutableArray *argumentArray = [[NSMutableArray alloc] init]; NSMutableArray *argumentArray = [[NSMutableArray alloc] init];
NSMutableString *currentArgument = [[NSMutableString alloc] init]; NSMutableString *currentArgument = [[NSMutableString alloc] init];
@ -272,15 +160,9 @@ extern int configuredLogLevel;
return argumentArray; return argumentArray;
} }
/**
* <p>Combines arguments into a string.
*
* @param arguments arguments
* @return string containing all arguments
*/
+ (NSString*)argumentsToString:(NSArray*)arguments { + (NSString*)argumentsToString:(NSArray*)arguments {
if (arguments == nil) { if (arguments == nil) {
return @"null"; return @"nil";
} }
NSMutableString *string = [NSMutableString stringWithString:@""]; NSMutableString *string = [NSMutableString stringWithString:@""];
@ -295,16 +177,4 @@ extern int configuredLogLevel;
return string; return string;
} }
/**
* <p>Lists ongoing executions.
*
* @return list of ongoing executions
*/
+ (NSArray*)listExecutions {
[executionsLock lock];
NSArray *array = [NSArray arrayWithArray:executions];
[executionsLock unlock];
return array;
}
@end @end

@ -17,250 +17,362 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdio.h> #ifndef FFMPEG_KIT_CONFIG_H
#include <pthread.h> #define FFMPEG_KIT_CONFIG_H
#include <unistd.h>
#include <Foundation/Foundation.h> #import <stdio.h>
#include "LogDelegate.h" #import <pthread.h>
#include "StatisticsDelegate.h" #import <unistd.h>
#import <Foundation/Foundation.h>
#import "ExecuteDelegate.h"
#import "FFmpegSession.h"
#import "FFprobeSession.h"
#import "LogDelegate.h"
#import "MediaInformationSession.h"
#import "StatisticsDelegate.h"
/** Global library version */
extern NSString* const FFmpegKitVersion;
typedef NS_ENUM(NSUInteger, Signal) {
SignalInt = 2,
SignalQuit = 3,
SignalPipe = 13,
SignalTerm = 15,
SignalXcpu = 24
};
/** Common return code values */ /**
extern int const RETURN_CODE_SUCCESS; * <p>Configuration class of <code>FFmpegKit</code> library. Allows customizing the global library
extern int const RETURN_CODE_CANCEL; * options. Provides helper methods to support additional resources.
*/
@interface FFmpegKitConfig : NSObject
/** Identifier used for IOS logging. */ /**
extern NSString *const LIB_NAME; * <p>Enables log and statistics redirection.
*
* <p>When redirection is enabled FFmpeg/FFprobe logs are redirected to NSLog and sessions
* collect log and statistics entries for the executions. It is possible to define global or
* session specific log/statistics delegates as well.
*
* <p>Note that redirection is enabled by default. If you do not want to use its functionality
* please use disableRedirection method to disable it.
*/
+ (void)enableRedirection;
/** /**
* Print no output. * <p>Disables log and statistics redirection.
*
* <p>When redirection is disabled logs are printed to stderr, all logs and statistics
* delegates are disabled and <code>FFprobe</code>'s <code>getMediaInformation</code> methods
* do not work.
*/ */
#define AV_LOG_QUIET -8 + (void)disableRedirection;
/** /**
* Something went really wrong and we will crash now. * <p>Sets and overrides <code>fontconfig</code> configuration directory.
*
* @param path directory that contains fontconfig configuration (fonts.conf)
* @return zero on success, non-zero on error
*/ */
#define AV_LOG_PANIC 0 + (int)setFontconfigConfigurationPath:(NSString*)path;
/** /**
* Something went wrong and recovery is not possible. * <p>Registers the fonts inside the given path, so they become available to use in FFmpeg
* For example, no header was found for a format which depends * filters.
* on headers or an illegal combination of parameters is used. *
* <p>Note that you need to build <code>FFmpegKit</code> with <code>fontconfig</code>
* enabled or use a prebuilt package with <code>fontconfig</code> inside to be able to use
* fonts in <code>FFmpeg</code>.
*
* @param fontDirectoryPath directory that contains fonts (.ttf and .otf files)
* @param fontNameMapping custom font name mappings, useful to access your fonts with more
* friendly names
*/ */
#define AV_LOG_FATAL 8 + (void)setFontDirectory:(NSString*)fontDirectoryPath with:(NSDictionary*)fontNameMapping;
/** /**
* Something went wrong and cannot losslessly be recovered. * <p>Registers the fonts inside the given array of font directories, so they become available
* However, not all future data is affected. * to use in FFmpeg filters.
*
* <p>Note that you need to build <code>FFmpegKit</code> with <code>fontconfig</code>
* enabled or use a prebuilt package with <code>fontconfig</code> inside to be able to use
* fonts in <code>FFmpeg</code>.
*
* @param fontDirectoryList array of directories that contain fonts (.ttf and .otf files)
* @param fontNameMapping custom font name mappings, useful to access your fonts with more
* friendly names
*/ */
#define AV_LOG_ERROR 16 + (void)setFontDirectoryList:(NSArray*)fontDirectoryList with:(NSDictionary*)fontNameMapping;
/** /**
* Something somehow does not look correct. This may or may not * <p>Creates a new named pipe to use in <code>FFmpeg</code> operations.
* lead to problems. An example would be the use of '-vstrict -2'. *
* <p>Please note that creator is responsible of closing created pipes.
*
* @return the full path of the named pipe
*/ */
#define AV_LOG_WARNING 24 + (NSString*)registerNewFFmpegPipe;
/** /**
* Standard information. * <p>Closes a previously created <code>FFmpeg</code> pipe.
*
* @param ffmpegPipePath full path of the FFmpeg pipe
*/ */
#define AV_LOG_INFO 32 + (void)closeFFmpegPipe:(NSString*)ffmpegPipePath;
/** /**
* Detailed information. * <p>Returns the version of FFmpeg bundled within <code>FFmpegKit</code> library.
*
* @return the version of FFmpeg
*/ */
#define AV_LOG_VERBOSE 40 + (NSString*)getFFmpegVersion;
/** /**
* Stuff which is only useful for libav* developers. * Returns FFmpegKit library version.
*
* @return FFmpegKit version
*/ */
#define AV_LOG_DEBUG 48 + (NSString*)getVersion;
/** /**
* This class is used to configure FFmpegKit library utilities/tools. * <p>Returns whether FFmpegKit release is a Long Term Release or not.
* *
* 1. LogDelegate: This class redirects FFmpeg/FFprobe output to NSLog by default. As * @return true/yes or false/no
* an alternative, it is possible not to print messages to NSLog and pass them to a */
* LogDelegate function. This function can decide whether to print these logs, show them + (int)isLTSBuild;
* inside another container or ignore them.
/**
* Returns FFmpegKit library build date.
* *
* 2. setLogLevel:/getLogLevel: Use this methods to set/get * @return FFmpegKit library build date
* FFmpeg/FFprobe log severity. */
+ (NSString*)getBuildDate;
/**
* <p>Sets an environment variable.
* *
* 3. StatsDelegate: It is possible to receive statistics about ongoing * @param variableName environment variable name
* operation by defining a StatsDelegate or by calling * @param variableValue environment variable value
* getLastReceivedStats method. * @return zero on success, non-zero on error
*/
+ (int)setEnvironmentVariable:(NSString*)variableName value:(NSString*)variableValue;
/**
* <p>Registers a new ignored signal. Ignored signals are not handled by <code>FFmpegKit</code>
* library.
* *
* 4. Font configuration: It is possible to register custom fonts with * @param signal signal to be ignored
* setFontconfigConfigurationPath: and */
* setFontDirectory:with: methods. + (void)ignoreSignal:(Signal)signal;
/**
* <p>Synchronously executes the FFmpeg session provided.
* *
* @param ffmpegSession FFmpeg session which includes command options/arguments
*/ */
@interface FFmpegKitConfig : NSObject + (void)ffmpegExecute:(FFmpegSession*)ffmpegSession;
/** /**
* Enables log and statistics redirection. * <p>Synchronously executes the FFprobe session provided.
* When redirection is not enabled FFmpeg/FFprobe logs are printed to stderr. By enabling *
* redirection, they are routed to NSLog and can be routed further to a log delegate. * @param ffprobeSession FFprobe session which includes command options/arguments
* Statistics redirection behaviour is similar. Statistics are not printed at all if
* redirection is not enabled. If it is enabled then it is possible to define a statistics
* delegate but if you don't, they are not printed anywhere and only saved as
* 'lastReceivedStatistics' data which can be polled with
* '{@link #'getLastReceivedStatistics()'.
* Note that redirection is enabled by default. If you do not want to use its functionality
* please use 'disableRedirection()' to disable it.
*/ */
+ (void)enableRedirection; + (void)ffprobeExecute:(FFprobeSession*)ffprobeSession;
/** /**
* Disables log and statistics redirection. * <p>Synchronously executes the media information session provided.
*
* @param mediaInformationSession media information session which includes command options/arguments
* @param waitTimeout max time to wait until media information is transmitted
*/ */
+ (void)disableRedirection; + (void)getMediaInformationExecute:(MediaInformationSession*)mediaInformationSession withTimeout:(int)waitTimeout;
/** /**
* Returns log level. * <p>Asynchronously executes the FFmpeg session provided.
* *
* @return log level * @param ffmpegSession FFmpeg session which includes command options/arguments
*/ */
+ (int)getLogLevel; + (void)asyncFFmpegExecute:(FFmpegSession*)ffmpegSession;
/** /**
* Sets log level. * <p>Asynchronously executes the FFmpeg session provided.
* *
* @param level log level * @param ffmpegSession FFmpeg session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation
*/ */
+ (void)setLogLevel:(int)level; + (void)asyncFFmpegExecute:(FFmpegSession*)ffmpegSession onDispatchQueue:(dispatch_queue_t)queue;
/** /**
* Converts int log level to string. * <p>Asynchronously executes the FFprobe session provided.
* *
* @param level value * @param ffprobeSession FFprobe session which includes command options/arguments
* @return string value
*/ */
+ (NSString*)logLevelToString:(int)level; + (void)asyncFFprobeExecute:(FFprobeSession*)ffprobeSession;
/** /**
* Sets a LogDelegate. logCallback method inside LogDelegate is used to redirect logs. * <p>Asynchronously executes the FFprobe session provided.
* *
* @param newLogDelegate log delegate or nil to disable a previously defined delegate * @param ffprobeSession FFprobe session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation
*/ */
+ (void)setLogDelegate:(id<LogDelegate>)newLogDelegate; + (void)asyncFFprobeExecute:(FFprobeSession*)ffprobeSession onDispatchQueue:(dispatch_queue_t)queue;
/** /**
* Sets a StatisticsDelegate. statisticsCallback method inside StatisticsDelegate is used to redirect statistics. * <p>Asynchronously executes the media information session provided.
* *
* @param newStatisticsDelegate statistics delegate or nil to disable a previously defined delegate * @param mediaInformationSession media information session which includes command options/arguments
* @param waitTimeout max time to wait until media information is transmitted
*/ */
+ (void)setStatisticsDelegate:(id<StatisticsDelegate>)newStatisticsDelegate; + (void)asyncGetMediaInformationExecute:(MediaInformationSession*)mediaInformationSession withTimeout:(int)waitTimeout;
/** /**
* Returns the last received statistics data. It is recommended to call it before starting a new execution. * <p>Asynchronously executes the media information session provided.
* *
* @return last received statistics data * @param mediaInformationSession media information session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation
* @param waitTimeout max time to wait until media information is transmitted
*/ */
+ (Statistics*)getLastReceivedStatistics; + (void)asyncGetMediaInformationExecute:(MediaInformationSession*)mediaInformationSession onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout;
/** /**
* Resets last received statistics. * <p>Sets a global log delegate to redirect FFmpeg/FFprobe logs.
*
* @param logDelegate log delegate or nil to disable a previously defined log delegate
*/ */
+ (void)resetStatistics; + (void)enableLogDelegate:(id<LogDelegate>)logDelegate;
/** /**
* Sets and overrides fontconfig configuration directory. * <p>Sets a global statistics delegate to redirect FFmpeg statistics.
* *
* @param path directory which contains fontconfig configuration (fonts.conf) * @param statisticsDelegate statistics delegate or nil to disable a previously defined statistics delegate
*/ */
+ (void)setFontconfigConfigurationPath:(NSString*)path; + (void)enableStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate;
/** /**
* Registers fonts inside the given path, so they are available to use in FFmpeg filters. * <p>Sets a global execute delegate to receive execution results.
* *
* Note that you need to build FFmpegKit with fontconfig * @param executeDelegate execute delegate or nil to disable a previously execute delegate
* enabled or use a prebuilt package with fontconfig inside to use this feature. */
+ (void)enableExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* <p>Returns the global execute delegate.
* *
* @param fontDirectoryPath directory which contains fonts (.ttf and .otf files) * @return global execute delegate
* @param fontNameMapping custom font name mappings, useful to access your fonts with more friendly names
*/ */
+ (void)setFontDirectory:(NSString*)fontDirectoryPath with:(NSDictionary*)fontNameMapping; + (id<ExecuteDelegate>)getExecuteDelegate;
/** /**
* Returns package name. * Returns the current log level.
* *
* @return guessed package name according to supported external libraries * @return current log level
*/ */
+ (NSString*)getPackageName; + (int)getLogLevel;
/** /**
* Returns supported external libraries. * Sets the log level.
* *
* @return array of supported external libraries * @param level new log level
*/ */
+ (NSArray*)getExternalLibraries; + (void)setLogLevel:(int)level;
/** /**
* Creates a new named pipe to use in FFmpeg operations. * Converts int log level to string.
* *
* Please note that creator is responsible of closing created pipes. * @param level value
* @return string value
*/
+ (NSString*)logLevelToString:(int)level;
/**
* Returns the session history size.
* *
* @return the full path of named pipe * @return session history size
*/ */
+ (NSString*)registerNewFFmpegPipe; + (int)getSessionHistorySize;
/** /**
* Closes a previously created FFmpeg pipe. * Sets the session history size.
* *
* @param ffmpegPipePath full path of ffmpeg pipe * @param sessionHistorySize session history size, should be smaller than 1000
*/ */
+ (void)closeFFmpegPipe:(NSString*)ffmpegPipePath; + (void)setSessionHistorySize:(int)sessionHistorySize;
/** /**
* Returns FFmpeg version bundled within the library. * Returns the session specified with <code>sessionId</code> from the session history.
* *
* @return FFmpeg version * @param sessionId session identifier
* @return session specified with sessionId or nil if it is not found in the history
*/ */
+ (NSString*)getFFmpegVersion; + (id<Session>)getSession:(long)sessionId;
/** /**
* Returns FFmpegKit library version. * Returns the last session created from the session history.
* *
* @return FFmpegKit version * @return the last session created or nil if session history is empty
*/ */
+ (NSString*)getVersion; + (id<Session>)getLastSession;
/** /**
* Returns FFmpegKit library build date. * Returns the last session completed from the session history.
* *
* @return FFmpegKit library build date * @return the last session completed. If there are no completed sessions in the history this
* method will return nil
*/ */
+ (NSString*)getBuildDate; + (id<Session>)getLastCompletedSession;
/**
* <p>Returns all sessions in the session history.
*
* @return all sessions in the session history
*/
+ (NSArray*)getSessions;
/** /**
* Returns return code of last executed command. * <p>Returns all FFmpeg sessions in the session history.
* *
* @return return code of last executed command * @return all FFmpeg sessions in the session history
*/ */
+ (int)getLastReturnCode; + (NSArray*)getFFmpegSessions;
/** /**
* Returns log output of last executed single FFmpeg/FFprobe command. * <p>Returns all FFprobe sessions in the session history.
* *
* This method does not support executing multiple concurrent commands. If you execute * @return all FFprobe sessions in the session history
* multiple commands at the same time, this method will return output from all executions. */
+ (NSArray*)getFFprobeSessions;
/**
* <p>Returns sessions that have the given state.
* *
* Please note that disabling redirection using FFmpegKitConfig.disableRedirection() method * @return sessions that have the given state from the session history
* also disables this functionality. */
+ (NSArray*)getSessionsByState:(SessionState)state;
/**
* Returns the active log redirection strategy.
* *
* @return output of last executed command * @return log redirection strategy
*/ */
+ (NSString*)getLastCommandOutput; + (LogRedirectionStrategy)getLogRedirectionStrategy;
/** /**
* Registers a new ignored signal. Ignored signals are not handled by the library. * <p>Sets the log redirection strategy
* *
* By default, the following 5 signals are handled: SIGINT, SIGQUIT, SIGPIPE, SIGTERM and SIGXCPU. Any of them can be * @param logRedirectionStrategy log redirection strategy
* ignored. */
+ (void)setLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
/**
* <p>Returns the number of async messages that are not transmitted to the delegates for
* this session.
* *
* @param signum signal number to ignore * @param sessionId id of the session
* @return number of async messages that are not transmitted to the delegates for this session
*/ */
+ (void)ignoreSignal:(int)signum; + (int)messagesInTransmit:(long)sessionId;
@end @end
#endif // FFMPEG_KIT_CONFIG_H

File diff suppressed because it is too large Load Diff

@ -0,0 +1,119 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_FFMPEG_SESSION_H
#define FFMPEG_KIT_FFMPEG_SESSION_H
#import <Foundation/Foundation.h>
#import "AbstractSession.h"
#import "StatisticsDelegate.h"
/**
* <p>An FFmpeg session.
*/
@interface FFmpegSession : AbstractSession
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
*/
- (instancetype)init:(NSArray*)arguments;
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
* @param logDelegate session specific log delegate
* @param statisticsDelegate session specific statistics delegate
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate;
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
* @param logDelegate session specific log delegate
* @param statisticsDelegate session specific statistics delegate
* @param logRedirectionStrategy session specific log redirection strategy
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
/**
* Returns the session specific statistics delegate.
*
* @return session specific statistics delegate
*/
- (id<StatisticsDelegate>)getStatisticsDelegate;
/**
* Returns all statistics entries generated for this session. If there are asynchronous
* messages that are not delivered yet, this method waits for them until the given timeout.
*
* @param waitTimeout wait timeout for asynchronous messages in milliseconds
* @return list of statistics entries generated for this session
*/
- (NSArray*)getAllStatisticsWithTimeout:(int)waitTimeout;
/**
* Returns all statistics entries generated for this session. If there are asynchronous
* messages that are not delivered yet, this method waits for them until
* AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit expires.
*
* @return list of statistics entries generated for this session
*/
- (NSArray*)getAllStatistics;
/**
* Returns all statistics entries delivered for this session. Note that if there are
* asynchronous messages that are not delivered yet, this method will not wait for
* them and will return immediately.
*
* @return list of statistics entries received for this session
*/
- (NSArray*)getStatistics;
/**
* Returns the last received statistics entry.
*
* @return the last received statistics entry or nil if there are not any statistics entries
* received
*/
- (Statistics*)getLastReceivedStatistics;
/**
* Adds a new statistics entry for this session.
*
* @param statistics statistics entry
*/
- (void)addStatistics:(Statistics*)statistics;
@end
#endif // FFMPEG_KIT_FFMPEG_SESSION_H

@ -0,0 +1,137 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ExecuteDelegate.h"
#import "FFmpegSession.h"
#import "FFmpegKitConfig.h"
#import "LogDelegate.h"
#import "StatisticsDelegate.h"
@implementation FFmpegSession {
id<StatisticsDelegate> _statisticsDelegate;
NSMutableArray* _statistics;
NSRecursiveLock* _statisticsLock;
}
- (instancetype)init:(NSArray*)arguments {
self = [super init:arguments withExecuteDelegate:nil withLogDelegate:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_statisticsDelegate = nil;
_statistics = [[NSMutableArray alloc] init];
_statisticsLock = [[NSRecursiveLock alloc] init];
}
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
self = [super init:arguments withExecuteDelegate:executeDelegate withLogDelegate:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_statisticsDelegate = nil;
_statistics = [[NSMutableArray alloc] init];
_statisticsLock = [[NSRecursiveLock alloc] init];
}
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate {
self = [super init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_statisticsDelegate = statisticsDelegate;
_statistics = [[NSMutableArray alloc] init];
_statisticsLock = [[NSRecursiveLock alloc] init];
}
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
self = [super init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withLogRedirectionStrategy:logRedirectionStrategy];
if (self) {
_statisticsDelegate = statisticsDelegate;
_statistics = [[NSMutableArray alloc] init];
_statisticsLock = [[NSRecursiveLock alloc] init];
}
return self;
}
- (id<StatisticsDelegate>)getStatisticsDelegate {
return _statisticsDelegate;
}
- (NSArray*)getAllStatisticsWithTimeout:(int)waitTimeout {
[self waitForAsynchronousMessagesInTransmit:waitTimeout];
if ([self thereAreAsynchronousMessagesInTransmit]) {
NSLog(@"getAllStatisticsWithTimeout was called to return all statistics but there are still statistics being transmitted for session id %ld.", [self getSessionId]);
}
return [self getStatistics];
}
- (NSArray*)getAllStatistics {
return [self getAllStatisticsWithTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
}
- (NSArray*)getStatistics {
[_statisticsLock lock];
NSArray* statisticsCopy = [_statistics copy];
[_statisticsLock unlock];
return statisticsCopy;
}
- (Statistics*)getLastReceivedStatistics {
Statistics* lastStatistics = nil;
[_statisticsLock lock];
if ([_statistics count] > 0) {
lastStatistics = [_statistics objectAtIndex:0];
}
[_statisticsLock unlock];
return lastStatistics;
}
- (void)addStatistics:(Statistics*)statistics {
[_statisticsLock lock];
[_statistics addObject:statistics];
[_statisticsLock unlock];
}
- (BOOL)isFFmpeg {
return true;
}
- (BOOL)isFFprobe {
return false;
}
@end

@ -17,71 +17,225 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h> #ifndef FFPROBE_KIT_H
#include <stdlib.h> #define FFPROBE_KIT_H
#include <Foundation/Foundation.h>
#include "MediaInformationParser.h" #import <string.h>
#import <stdlib.h>
#import <Foundation/Foundation.h>
#import "FFprobeSession.h"
#import "MediaInformationJsonParser.h"
/** /**
* Main class for FFprobe operations. * <p>Main class to run <code>FFprobe</code> commands. Supports executing commands both
* synchronously and asynchronously.
* <pre>
* FFprobeSession *session = [FFprobeKit execute:@"-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4"];
*
* FFprobeSession *asyncSession = [FFprobeKit executeAsync:@"-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4" withExecuteDelegate:executeDelegate];
* </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific delegates.
* <pre>
* FFprobeSession *session = [FFprobeKit executeAsync:@"-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4" withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
* </pre>
* <p>It can extract media information for a file or a url, using getMediaInformation method.
* <pre>
* MediaInformationSession *session = [FFprobeKit getMediaInformation:@"file1.mp4"];
* </pre>
*/ */
@interface FFprobeKit : NSObject @interface FFprobeKit : NSObject
/** /**
* Synchronously executes FFprobe with arguments provided. * <p>Synchronously executes FFprobe with arguments provided.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe command options/arguments as string array
* @return zero on successful execution, 255 on user cancel and non-zero on error * @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeWithArguments:(NSArray*)arguments;
/**
* <p>Asynchronously executes FFprobe with arguments provided.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeDelegate delegate that will be called when the execution is completed
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* <p>Asynchronously executes FFprobe with arguments provided.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeDelegate delegate that will be notified when execution is completed
* @param logDelegate delegate that will receive logs
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate;
/**
* <p>Asynchronously executes FFprobe with arguments provided.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeDelegate delegate that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Asynchronously executes FFprobe with arguments provided.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeDelegate delegate that will be notified when execution is completed
* @param logDelegate delegate that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution
*/ */
+ (int)executeWithArguments:(NSArray*)arguments; + (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue;
/** /**
* Synchronously executes FFprobe command provided. Space character is used to split command * <p>Synchronously executes FFprobe command provided. Space character is used to split command
* into arguments. * into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* @param command FFprobe command * @param command FFprobe command
* @return zero on successful execution, 255 on user cancel and non-zero on error * @return FFprobe session created for this execution
*/ */
+ (int)execute:(NSString*)command; + (FFprobeSession*)execute:(NSString*)command;
/** /**
* Returns media information for the given file. * <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* This method does not support executing multiple concurrent operations. If you execute * @param command FFprobe command
* multiple operations (execute or getMediaInformation) at the same time, the response of this * @param executeDelegate delegate that will be called when the execution is completed
* method is not predictable. * @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* @param path or uri of media file * @param command FFprobe command
* @return media information * @param executeDelegate delegate that will be notified when execution is completed
* @param logDelegate delegate that will receive logs
* @return FFprobe session created for this execution
*/ */
+ (MediaInformation*)getMediaInformation:(NSString*)path; + (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate;
/** /**
* Returns media information for the given command. * <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* This method does not support executing multiple concurrent operations. If you execute * @param command FFprobe command
* multiple operations (execute or getMediaInformation) at the same time, the response of this * @param executeDelegate delegate that will be called when the execution is completed
* method is not predictable. * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Asynchronously executes FFprobe command provided. Space character is used to split command
* into arguments. You can use single or double quote characters to specify arguments inside
* your command.
* *
* @param command ffprobe command * @param command FFprobe command
* @return media information * @param executeDelegate delegate that will be called when the execution is completed
* @param logDelegate delegate that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution
*/ */
+ (MediaInformation*)getMediaInformationFromCommand:(NSString*)command; + (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue;
/** /**
* Returns media information for given file. * <p>Extracts media information for the file specified with path.
* *
* This method does not support executing multiple concurrent operations. If you execute * @param path path or uri of a media file
* multiple operations (execute or getMediaInformation) at the same time, the response of this * @return media information session created for this execution
* method is not predictable. */
+ (MediaInformationSession*)getMediaInformation:(NSString*)path;
/**
* <p>Extracts media information for the file specified with path.
* *
* @param path path or uri of media file * @param path path or uri of a media file
* @param timeout complete timeout * @param waitTimeout max time to wait until media information is transmitted
* @deprecated this method is deprecated since v4.3.1. You can still use this method but * @return media information session created for this execution
* timeout parameter is not effective anymore.
* @return media information
*/ */
+ (MediaInformation*)getMediaInformation:(NSString*)path timeout:(long)timeout __attribute__((deprecated)); + (MediaInformationSession*)getMediaInformation:(NSString*)path withTimeout:(int)waitTimeout;
/**
* <p>Extracts media information for the file specified with path asynchronously.
*
* @param path path or uri of a media file
* @param executeDelegate delegate that will be called when the execution is completed
* @return media information session created for this execution
*/
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* <p>Extracts media information for the file specified with path asynchronously.
*
* @param path path or uri of a media file
* @param executeDelegate delegate that will be notified when execution is completed
* @param logDelegate delegate that will receive logs
* @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution
*/
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withTimeout:(int)waitTimeout;
/**
* <p>Extracts media information for the file specified with path asynchronously.
*
* @param path path or uri of a media file
* @param executeDelegate delegate that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return media information session created for this execution
*/
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Extracts media information for the file specified with path asynchronously.
*
* @param path path or uri of a media file
* @param executeDelegate delegate that will be notified when execution is completed
* @param logDelegate delegate that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation
* @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution
*/
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout;
/**
* <p>Extracts media information using the command provided asynchronously.
*
* @param command FFprobe command that prints media information for a file in JSON format
* @return media information session created for this execution
*/
+ (MediaInformationSession*)getMediaInformationFromCommand:(NSString*)command;
/**
* <p>Extracts media information using the command provided asynchronously.
*
* @param command FFprobe command that prints media information for a file in JSON format
* @param executeDelegate delegate that will be notified when execution is completed
* @param logDelegate delegate that will receive logs
* @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution
*/
+ (MediaInformationSession*)getMediaInformationFromCommandAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout;
/**
* <p>Lists all FFprobe sessions in the session history.
*
* @return all FFprobe sessions in the session history
*/
+ (NSArray*)listSessions;
@end
@end #endif // FFPROBE_KIT_H

@ -17,131 +17,133 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "libavutil/ffversion.h" #import "fftools_ffmpeg.h"
#include "fftools_ffmpeg.h" #import "FFmpegKit.h"
#import "FFmpegKitConfig.h"
#include "FFmpegKit.h" #import "FFprobeKit.h"
#include "FFmpegKitConfig.h"
#include "FFprobeKit.h"
/** Forward declaration for function defined in fftools_ffprobe.c */
int ffprobe_execute(int argc, char **argv);
@implementation FFprobeKit @implementation FFprobeKit
extern int lastReturnCode;
extern NSMutableString *lastCommandOutput;
extern int configuredLogLevel;
+ (void)initialize { + (void)initialize {
[FFmpegKitConfig class]; [FFmpegKitConfig class];
} }
/** + (FFprobeSession*)executeWithArguments:(NSArray*)arguments {
* Synchronously executes FFprobe with arguments provided. FFprobeSession* session = [[FFprobeSession alloc] init:arguments];
* [FFmpegKitConfig ffprobeExecute:session];
* @param arguments FFprobe command options/arguments as string array return session;
* @return zero on successful execution, 255 on user cancel and non-zero on error }
*/
+ (int)executeWithArguments:(NSArray*)arguments {
lastCommandOutput = [[NSMutableString alloc] init];
// SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW EXECUTION + (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
av_log_set_level(configuredLogLevel); FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncFFprobeExecute:session];
return session;
}
char **commandCharPArray = (char **)av_malloc(sizeof(char*) * ([arguments count] + 1)); + (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
[FFmpegKitConfig asyncFFprobeExecute:session];
return session;
}
/* PRESERVING CALLING FORMAT + (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue {
* FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteDelegate:executeDelegate];
* ffprobe <arguments> [FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
*/ return session;
commandCharPArray[0] = (char *)av_malloc(sizeof(char) * ([LIB_NAME length] + 1)); }
strcpy(commandCharPArray[0], [LIB_NAME UTF8String]);
for (int i=0; i < [arguments count]; i++) { + (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue {
NSString *argument = [arguments objectAtIndex:i]; FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
commandCharPArray[i + 1] = (char *) [argument UTF8String]; [FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
} return session;
}
// RUN + (FFprobeSession*)execute:(NSString*)command {
lastReturnCode = ffprobe_execute(([arguments count] + 1), commandCharPArray); FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command]];
[FFmpegKitConfig ffprobeExecute:session];
return session;
}
// CLEANUP + (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
av_free(commandCharPArray[0]); FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate];
av_free(commandCharPArray); [FFmpegKitConfig asyncFFprobeExecute:session];
return session;
}
return lastReturnCode; + (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
[FFmpegKitConfig asyncFFprobeExecute:session];
return session;
} }
/** + (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue {
* Synchronously executes FFprobe command provided. Space character is used to split command FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate];
* into arguments. [FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
* return session;
* @param command FFprobe command
* @return zero on successful execution, 255 on user cancel and non-zero on error
*/
+ (int)execute:(NSString*)command {
return [FFprobeKit executeWithArguments: [FFmpegKit parseArguments: command]];
} }
/** + (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue {
* Returns media information for the given file. FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
* [FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
* This method does not support executing multiple concurrent operations. If you execute return session;
* multiple operations (execute or getMediaInformation) at the same time, the response of this
* method is not predictable.
*
* @param path or uri of media file
* @return media information
*/
+ (MediaInformation*)getMediaInformation:(NSString*)path {
return [FFprobeKit getMediaInformationFromCommandArguments:[[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-i", path, nil]];
} }
/** + (MediaInformationSession*)getMediaInformation:(NSString*)path {
* Returns media information for the given command. NSArray* arguments = [[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-i", path, nil];
* MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments];
* This method does not support executing multiple concurrent operations. If you execute [FFmpegKitConfig getMediaInformationExecute:session withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
* multiple operations (execute or getMediaInformation) at the same time, the response of this return session;
* method is not predictable.
*
* @param command
* @return media information
*/
+ (MediaInformation*)getMediaInformationFromCommand:(NSString*)command {
return [FFprobeKit getMediaInformationFromCommandArguments:[FFmpegKit parseArguments: command]];
} }
/** + (MediaInformationSession*)getMediaInformation:(NSString*)path withTimeout:(int)waitTimeout {
* Returns media information for given file. NSArray* arguments = [[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-i", path, nil];
* MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments];
* This method does not support executing multiple concurrent operations. If you execute [FFmpegKitConfig getMediaInformationExecute:session withTimeout:waitTimeout];
* multiple operations (execute or getMediaInformation) at the same time, the response of this return session;
* method is not predictable. }
*
* @param path path or uri of media file + (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
* @param timeout complete timeout NSArray* arguments = [[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-i", path, nil];
* @deprecated this method is deprecated since v4.3.1. You can still use this method but MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteDelegate:executeDelegate];
* timeout parameter is not effective anymore. [FFmpegKitConfig asyncGetMediaInformationExecute:session withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
* @return media information return session;
*/
+ (MediaInformation*)getMediaInformation:(NSString*)path timeout:(long)timeout {
return [FFprobeKit getMediaInformation:path];
} }
+ (MediaInformation*)getMediaInformationFromCommandArguments:(NSArray*)arguments { + (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withTimeout:(int)waitTimeout {
int rc = [FFprobeKit executeWithArguments:arguments]; NSArray* arguments = [[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-i", path, nil];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
[FFmpegKitConfig asyncGetMediaInformationExecute:session withTimeout:waitTimeout];
return session;
}
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue {
NSArray* arguments = [[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-i", path, nil];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncGetMediaInformationExecute:session onDispatchQueue:queue withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
return session;
}
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
NSArray* arguments = [[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-i", path, nil];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncGetMediaInformationExecute:session onDispatchQueue:queue withTimeout:waitTimeout];
return session;
}
+ (MediaInformationSession*)getMediaInformationFromCommand:(NSString*)command {
MediaInformationSession* session = [[MediaInformationSession alloc] init:[FFmpegKit parseArguments:command]];
[FFmpegKitConfig getMediaInformationExecute:session withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
return session;
}
if (rc == 0) { + (MediaInformationSession*)getMediaInformationFromCommandAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
return [MediaInformationParser from:[FFmpegKitConfig getLastCommandOutput]]; MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
} else { [FFmpegKitConfig asyncGetMediaInformationExecute:session onDispatchQueue:queue withTimeout:waitTimeout];
int activeLogLevel = av_log_get_level(); return session;
if ((activeLogLevel != AV_LOG_QUIET) && (AV_LOG_WARNING <= activeLogLevel)) { }
NSLog(@"%@", [FFmpegKitConfig getLastCommandOutput]);
}
return nil; + (NSArray*)listSessions {
} return [FFmpegKitConfig getFFprobeSessions];
} }
@end @end

@ -0,0 +1,67 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_FFPROBE_SESSION_H
#define FFMPEG_KIT_FFPROBE_SESSION_H
#import <Foundation/Foundation.h>
#import "AbstractSession.h"
/**
* <p>An FFprobe session.
*/
@interface FFprobeSession : AbstractSession
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
*/
- (instancetype)init:(NSArray*)arguments;
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
* @param logDelegate session specific log delegate
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate;
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
* @param logDelegate session specific log delegate
* @param logRedirectionStrategy session specific log redirection strategy
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
@end
#endif // FFMPEG_KIT_FFPROBE_SESSION_H

@ -0,0 +1,64 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ExecuteDelegate.h"
#import "FFprobeSession.h"
#import "FFmpegKitConfig.h"
#import "LogDelegate.h"
@implementation FFprobeSession
- (instancetype)init:(NSArray*)arguments {
self = [super init:arguments withExecuteDelegate:nil withLogDelegate:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
self = [super init:arguments withExecuteDelegate:executeDelegate withLogDelegate:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate {
self = [super init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
self = [super init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withLogRedirectionStrategy:logRedirectionStrategy];
return self;
}
- (BOOL)isFFmpeg {
return false;
}
- (BOOL)isFFprobe {
return true;
}
@end

@ -0,0 +1,85 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_LEVEL_H
#define FFMPEG_KIT_LEVEL_H
/**
* <p>Enumeration type for log levels.
*/
typedef NS_ENUM(NSUInteger, Level) {
/**
* This log level is defined by FFmpegKit. It is used to specify logs printed to stderr by
* FFmpeg. Logs that has this level are not filtered and always redirected.
*/
LevelAVLogStdErr = -16,
/**
* Print no output.
*/
LevelAVLogQuiet = -8,
/**
* Something went really wrong and we will crash now.
*/
LevelAVLogPanic = 0,
/**
* Something went wrong and recovery is not possible.
* For example, no header was found for a format which depends
* on headers or an illegal combination of parameters is used.
*/
LevelAVLogFatal = 8,
/**
* Something went wrong and cannot losslessly be recovered.
* However, not all future data is affected.
*/
LevelAVLogError = 16,
/**
* Something somehow does not look correct. This may or may not
* lead to problems. An example would be the use of '-vstrict -2'.
*/
LevelAVLogWarning = 24,
/**
* Standard information.
*/
LevelAVLogInfo = 32,
/**
* Detailed information.
*/
LevelAVLogVerbose = 40,
/**
* Stuff which is only useful for libav* developers.
*/
LevelAVLogDebug = 48,
/**
* Extremely verbose debugging, useful for libav* development.
*/
LevelAVLogTrace = 56
};
#endif // FFMPEG_KIT_LEVEL_H

@ -0,0 +1,40 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_LOG_H
#define FFMPEG_KIT_LOG_H
#import <Foundation/Foundation.h>
/**
* <p>Log entry for an <code>FFmpegKit</code> session.
*/
@interface Log : NSObject
- (instancetype)init:(long)sessionId :(int)level :(NSString*)message;
- (long)getSessionId;
- (int)getLevel;
- (NSString*)getMessage;
@end
#endif // FFMPEG_KIT_LOG_H

@ -0,0 +1,51 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "Log.h"
@implementation Log {
long _sessionId;
int _level;
NSString *_message;
}
- (instancetype)init:(long)sessionId :(int)level :(NSString*)message {
self = [super init];
if (self) {
_sessionId = sessionId;
_level = level;
_message = message;
}
return self;
}
- (long)getSessionId {
return _sessionId;
}
- (int)getLevel {
return _level;
}
- (NSString*)getMessage {
return _message;
}
@end

@ -17,10 +17,25 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FFMPEG_KIT_LOG_DELEGATE_H
#define FFMPEG_KIT_LOG_DELEGATE_H
#import <Foundation/Foundation.h>
#import "Log.h"
/** /**
* Use this delegate to receive logs from running executions. * <p>Delegate that receives logs generated for <code>FFmpegKit</code> sessions.
*/ */
@protocol LogDelegate<NSObject> @protocol LogDelegate<NSObject>
@required @required
- (void)logCallback:(long)executionId :(int)level :(NSString*)message;
/**
* <p>Called when a log entry is received.
*
* @param log log entry
*/
- (void)logCallback:(Log*)log;
@end @end
#endif // FFMPEG_KIT_LOG_DELEGATE_H

@ -0,0 +1,31 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_LOG_REDIRECTION_STRATEGY_H
#define FFMPEG_KIT_LOG_REDIRECTION_STRATEGY_H
typedef NS_ENUM(NSUInteger, LogRedirectionStrategy) {
LogRedirectionStrategyAlwaysPrintLogs,
LogRedirectionStrategyPrintLogsWhenNoDelegatesDefined,
LogRedirectionStrategyPrintLogsWhenGlobalDelegateNotDefined,
LogRedirectionStrategyPrintLogsWhenSessionDelegateNotDefined,
LogRedirectionStrategyNeverPrintLogs
};
#endif // FFMPEG_KIT_LOG_REDIRECTION_STRATEGY_H

@ -3,45 +3,61 @@ lib_LTLIBRARIES = libffmpegkit.la
libffmpegkit_la_LIBADD = @FFMPEG_LIBS@ libffmpegkit_la_LIBADD = @FFMPEG_LIBS@
libffmpegkit_la_SOURCES = \ libffmpegkit_la_SOURCES = \
AbstractSession.m \
ArchDetect.m \ ArchDetect.m \
AtomicLong.m \ AtomicLong.m \
FFmpegExecution.m \
FFmpegKit.m \ FFmpegKit.m \
ffmpegkit_exception.m \
FFmpegKitConfig.m \ FFmpegKitConfig.m \
FFmpegSession.m \
FFprobeKit.m \ FFprobeKit.m \
FFprobeSession.m \
Log.m \
MediaInformation.m \
MediaInformationJsonParser.m \
MediaInformationSession.m \
Packages.m \
ReturnCode.m \
Statistics.m \
StreamInformation.m \
ffmpegkit_exception.m \
fftools_cmdutils.c \ fftools_cmdutils.c \
fftools_ffmpeg.c \ fftools_ffmpeg.c \
fftools_ffmpeg_filter.c \ fftools_ffmpeg_filter.c \
fftools_ffmpeg_hw.c \ fftools_ffmpeg_hw.c \
fftools_ffmpeg_opt.c \ fftools_ffmpeg_opt.c \
fftools_ffprobe.c \ fftools_ffprobe.c
MediaInformation.m \
MediaInformationParser.m \
Statistics.m \
StreamInformation.m
if FFMPEGKIT_VIDEOTOOLBOX if FFMPEGKIT_VIDEOTOOLBOX
libffmpegkit_la_SOURCES += fftools_ffmpeg_videotoolbox.c libffmpegkit_la_SOURCES += fftools_ffmpeg_videotoolbox.c
endif endif
include_HEADERS = \ include_HEADERS = \
AbstractSession.h \
ArchDetect.h \ ArchDetect.h \
AtomicLong.h \ AtomicLong.h \
ExecuteDelegate.h \ ExecuteDelegate.h \
FFmpegExecution.h \
FFmpegKit.h \ FFmpegKit.h \
ffmpegkit_exception.h \
FFmpegKitConfig.h \ FFmpegKitConfig.h \
FFmpegSession.h \
FFprobeKit.h \ FFprobeKit.h \
fftools_cmdutils.h \ FFprobeSession.h \
fftools_ffmpeg.h \ Level.h \
Log.h \
LogDelegate.h \ LogDelegate.h \
LogRedirectionStrategy.h \
MediaInformation.h \ MediaInformation.h \
MediaInformationParser.h \ MediaInformationJsonParser.h \
MediaInformationSession.h \
Packages.h \
ReturnCode.h \
Session.h \
SessionState.h \
Statistics.h \ Statistics.h \
StatisticsDelegate.h \ StatisticsDelegate.h \
StreamInformation.h StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
fftools_ffmpeg.h
libffmpegkit_la_CFLAGS = $(CFLAGS) libffmpegkit_la_CFLAGS = $(CFLAGS)
libffmpegkit_la_OBJCFLAGS = $(CFLAGS) libffmpegkit_la_OBJCFLAGS = $(CFLAGS)

@ -1,4 +1,4 @@
# Makefile.in generated by automake 1.16.2 from Makefile.am. # Makefile.in generated by automake 1.16.3 from Makefile.am.
# @configure_input@ # @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc. # Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -133,31 +133,35 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES) LTLIBRARIES = $(lib_LTLIBRARIES)
libffmpegkit_la_DEPENDENCIES = libffmpegkit_la_DEPENDENCIES =
am__libffmpegkit_la_SOURCES_DIST = ArchDetect.m AtomicLong.m \ am__libffmpegkit_la_SOURCES_DIST = AbstractSession.m ArchDetect.m \
fftools_cmdutils.c fftools_ffmpeg.c fftools_ffmpeg_filter.c \ AtomicLong.m FFmpegKit.m FFmpegKitConfig.m FFmpegSession.m \
fftools_ffmpeg_hw.c fftools_ffmpeg_opt.c fftools_ffprobe.c \ FFprobeKit.m FFprobeSession.m Log.m MediaInformation.m \
FFmpegExecution.m MediaInformation.m MediaInformationParser.m \ MediaInformationJsonParser.m MediaInformationSession.m \
FFmpegKit.m FFmpegKitConfig.m ffmpegkit_exception.m \ Packages.m ReturnCode.m Statistics.m StreamInformation.m \
FFprobeKit.m Statistics.m StreamInformation.m \ ffmpegkit_exception.m fftools_cmdutils.c fftools_ffmpeg.c \
fftools_ffmpeg_filter.c fftools_ffmpeg_hw.c \
fftools_ffmpeg_opt.c fftools_ffprobe.c \
fftools_ffmpeg_videotoolbox.c fftools_ffmpeg_videotoolbox.c
@FFMPEGKIT_VIDEOTOOLBOX_TRUE@am__objects_1 = libffmpegkit_la-fftools_ffmpeg_videotoolbox.lo @FFMPEGKIT_VIDEOTOOLBOX_TRUE@am__objects_1 = libffmpegkit_la-fftools_ffmpeg_videotoolbox.lo
am_libffmpegkit_la_OBJECTS = libffmpegkit_la-ArchDetect.lo \ am_libffmpegkit_la_OBJECTS = libffmpegkit_la-AbstractSession.lo \
libffmpegkit_la-AtomicLong.lo \ libffmpegkit_la-ArchDetect.lo libffmpegkit_la-AtomicLong.lo \
libffmpegkit_la-FFmpegKit.lo \
libffmpegkit_la-FFmpegKitConfig.lo \
libffmpegkit_la-FFmpegSession.lo libffmpegkit_la-FFprobeKit.lo \
libffmpegkit_la-FFprobeSession.lo libffmpegkit_la-Log.lo \
libffmpegkit_la-MediaInformation.lo \
libffmpegkit_la-MediaInformationJsonParser.lo \
libffmpegkit_la-MediaInformationSession.lo \
libffmpegkit_la-Packages.lo libffmpegkit_la-ReturnCode.lo \
libffmpegkit_la-Statistics.lo \
libffmpegkit_la-StreamInformation.lo \
libffmpegkit_la-ffmpegkit_exception.lo \
libffmpegkit_la-fftools_cmdutils.lo \ libffmpegkit_la-fftools_cmdutils.lo \
libffmpegkit_la-fftools_ffmpeg.lo \ libffmpegkit_la-fftools_ffmpeg.lo \
libffmpegkit_la-fftools_ffmpeg_filter.lo \ libffmpegkit_la-fftools_ffmpeg_filter.lo \
libffmpegkit_la-fftools_ffmpeg_hw.lo \ libffmpegkit_la-fftools_ffmpeg_hw.lo \
libffmpegkit_la-fftools_ffmpeg_opt.lo \ libffmpegkit_la-fftools_ffmpeg_opt.lo \
libffmpegkit_la-fftools_ffprobe.lo \ libffmpegkit_la-fftools_ffprobe.lo $(am__objects_1)
libffmpegkit_la-FFmpegExecution.lo \
libffmpegkit_la-MediaInformation.lo \
libffmpegkit_la-MediaInformationParser.lo \
libffmpegkit_la-FFmpegKit.lo \
libffmpegkit_la-FFmpegKitConfig.lo \
libffmpegkit_la-ffmpegkit_exception.lo \
libffmpegkit_la-FFprobeKit.lo \
libffmpegkit_la-Statistics.lo \
libffmpegkit_la-StreamInformation.lo $(am__objects_1)
libffmpegkit_la_OBJECTS = $(am_libffmpegkit_la_OBJECTS) libffmpegkit_la_OBJECTS = $(am_libffmpegkit_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@) AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -182,24 +186,30 @@ am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo \ am__depfiles_remade = ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo \
./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo \
./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo \ ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegExecution.Plo \
./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo \
./$(DEPDIR)/libffmpegkit_la-MediaInformationParser.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo \ ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo \ ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo \
./$(DEPDIR)/libffmpegkit_la-FFprobeKit.Plo \ ./$(DEPDIR)/libffmpegkit_la-FFprobeKit.Plo \
./$(DEPDIR)/libffmpegkit_la-FFprobeSession.Plo \
./$(DEPDIR)/libffmpegkit_la-Log.Plo \
./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo \
./$(DEPDIR)/libffmpegkit_la-MediaInformationJsonParser.Plo \
./$(DEPDIR)/libffmpegkit_la-MediaInformationSession.Plo \
./$(DEPDIR)/libffmpegkit_la-Packages.Plo \
./$(DEPDIR)/libffmpegkit_la-ReturnCode.Plo \
./$(DEPDIR)/libffmpegkit_la-Statistics.Plo \ ./$(DEPDIR)/libffmpegkit_la-Statistics.Plo \
./$(DEPDIR)/libffmpegkit_la-StreamInformation.Plo \ ./$(DEPDIR)/libffmpegkit_la-StreamInformation.Plo \
./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo \ ./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo \ ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo \ ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_hw.Plo \ ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_hw.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo \ ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo \ ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo \ ./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo
./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
am__mv = mv -f am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@ -389,30 +399,41 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
lib_LTLIBRARIES = libffmpegkit.la lib_LTLIBRARIES = libffmpegkit.la
libffmpegkit_la_LIBADD = @FFMPEG_LIBS@ libffmpegkit_la_LIBADD = @FFMPEG_LIBS@
libffmpegkit_la_SOURCES = ArchDetect.m AtomicLong.m \ libffmpegkit_la_SOURCES = AbstractSession.m ArchDetect.m AtomicLong.m \
fftools_cmdutils.c fftools_ffmpeg.c fftools_ffmpeg_filter.c \ FFmpegKit.m FFmpegKitConfig.m FFmpegSession.m FFprobeKit.m \
fftools_ffmpeg_hw.c fftools_ffmpeg_opt.c fftools_ffprobe.c \ FFprobeSession.m Log.m MediaInformation.m \
FFmpegExecution.m MediaInformation.m MediaInformationParser.m \ MediaInformationJsonParser.m MediaInformationSession.m \
FFmpegKit.m FFmpegKitConfig.m ffmpegkit_exception.m \ Packages.m ReturnCode.m Statistics.m StreamInformation.m \
FFprobeKit.m Statistics.m StreamInformation.m \ ffmpegkit_exception.m fftools_cmdutils.c fftools_ffmpeg.c \
$(am__append_1) fftools_ffmpeg_filter.c fftools_ffmpeg_hw.c \
fftools_ffmpeg_opt.c fftools_ffprobe.c $(am__append_1)
include_HEADERS = \ include_HEADERS = \
AbstractSession.h \
ArchDetect.h \ ArchDetect.h \
AtomicLong.h \ AtomicLong.h \
ExecuteDelegate.h \ ExecuteDelegate.h \
FFmpegExecution.h \
fftools_cmdutils.h \
fftools_ffmpeg.h \
LogDelegate.h \
MediaInformation.h \
MediaInformationParser.h \
FFmpegKit.h \ FFmpegKit.h \
FFmpegKitConfig.h \ FFmpegKitConfig.h \
ffmpegkit_exception.h \ FFmpegSession.h \
FFprobeKit.h \ FFprobeKit.h \
FFprobeSession.h \
Level.h \
Log.h \
LogDelegate.h \
LogRedirectionStrategy.h \
MediaInformation.h \
MediaInformationJsonParser.h \
MediaInformationSession.h \
Packages.h \
ReturnCode.h \
Session.h \
SessionState.h \
Statistics.h \ Statistics.h \
StatisticsDelegate.h \ StatisticsDelegate.h \
StreamInformation.h StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
fftools_ffmpeg.h
libffmpegkit_la_CFLAGS = $(CFLAGS) libffmpegkit_la_CFLAGS = $(CFLAGS)
libffmpegkit_la_OBJCFLAGS = $(CFLAGS) libffmpegkit_la_OBJCFLAGS = $(CFLAGS)
@ -487,7 +508,7 @@ clean-libLTLIBRARIES:
rm -f $${locs}; \ rm -f $${locs}; \
} }
libffmpegkit.la: $(libffmpegkit_la_OBJECTS) $(libffmpegkit_la_DEPENDENCIES) $(EXTRA_libffmpegkit_la_DEPENDENCIES) libffmpegkit.la: $(libffmpegkit_la_OBJECTS) $(libffmpegkit_la_DEPENDENCIES) $(EXTRA_libffmpegkit_la_DEPENDENCIES)
$(AM_V_OBJCLD)$(libffmpegkit_la_LINK) -rpath $(libdir) $(libffmpegkit_la_OBJECTS) $(libffmpegkit_la_LIBADD) $(LIBS) $(AM_V_OBJCLD)$(libffmpegkit_la_LINK) -rpath $(libdir) $(libffmpegkit_la_OBJECTS) $(libffmpegkit_la_LIBADD) $(LIBS)
mostlyclean-compile: mostlyclean-compile:
@ -496,16 +517,23 @@ mostlyclean-compile:
distclean-compile: distclean-compile:
-rm -f *.tab.c -rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegExecution.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-MediaInformationParser.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFprobeKit.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFprobeKit.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFprobeSession.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-Log.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-MediaInformationJsonParser.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-MediaInformationSession.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-Packages.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-ReturnCode.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-Statistics.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-Statistics.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-StreamInformation.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-StreamInformation.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo@am__quote@ # am--include-marker
@ -513,7 +541,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo@am__quote@ # am--include-marker
$(am__depfiles_remade): $(am__depfiles_remade):
@$(MKDIR_P) $(@D) @$(MKDIR_P) $(@D)
@ -618,6 +645,13 @@ libffmpegkit_la-fftools_ffmpeg_videotoolbox.lo: fftools_ffmpeg_videotoolbox.c
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LTOBJCCOMPILE) -c -o $@ $< @am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LTOBJCCOMPILE) -c -o $@ $<
libffmpegkit_la-AbstractSession.lo: AbstractSession.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-AbstractSession.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-AbstractSession.Tpo -c -o libffmpegkit_la-AbstractSession.lo `test -f 'AbstractSession.m' || echo '$(srcdir)/'`AbstractSession.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-AbstractSession.Tpo $(DEPDIR)/libffmpegkit_la-AbstractSession.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='AbstractSession.m' object='libffmpegkit_la-AbstractSession.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-AbstractSession.lo `test -f 'AbstractSession.m' || echo '$(srcdir)/'`AbstractSession.m
libffmpegkit_la-ArchDetect.lo: ArchDetect.m libffmpegkit_la-ArchDetect.lo: ArchDetect.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-ArchDetect.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-ArchDetect.Tpo -c -o libffmpegkit_la-ArchDetect.lo `test -f 'ArchDetect.m' || echo '$(srcdir)/'`ArchDetect.m @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-ArchDetect.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-ArchDetect.Tpo -c -o libffmpegkit_la-ArchDetect.lo `test -f 'ArchDetect.m' || echo '$(srcdir)/'`ArchDetect.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-ArchDetect.Tpo $(DEPDIR)/libffmpegkit_la-ArchDetect.Plo @am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-ArchDetect.Tpo $(DEPDIR)/libffmpegkit_la-ArchDetect.Plo
@ -632,27 +666,6 @@ libffmpegkit_la-AtomicLong.lo: AtomicLong.m
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-AtomicLong.lo `test -f 'AtomicLong.m' || echo '$(srcdir)/'`AtomicLong.m @am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-AtomicLong.lo `test -f 'AtomicLong.m' || echo '$(srcdir)/'`AtomicLong.m
libffmpegkit_la-FFmpegExecution.lo: FFmpegExecution.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFmpegExecution.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFmpegExecution.Tpo -c -o libffmpegkit_la-FFmpegExecution.lo `test -f 'FFmpegExecution.m' || echo '$(srcdir)/'`FFmpegExecution.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-FFmpegExecution.Tpo $(DEPDIR)/libffmpegkit_la-FFmpegExecution.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='FFmpegExecution.m' object='libffmpegkit_la-FFmpegExecution.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-FFmpegExecution.lo `test -f 'FFmpegExecution.m' || echo '$(srcdir)/'`FFmpegExecution.m
libffmpegkit_la-MediaInformation.lo: MediaInformation.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-MediaInformation.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-MediaInformation.Tpo -c -o libffmpegkit_la-MediaInformation.lo `test -f 'MediaInformation.m' || echo '$(srcdir)/'`MediaInformation.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-MediaInformation.Tpo $(DEPDIR)/libffmpegkit_la-MediaInformation.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='MediaInformation.m' object='libffmpegkit_la-MediaInformation.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-MediaInformation.lo `test -f 'MediaInformation.m' || echo '$(srcdir)/'`MediaInformation.m
libffmpegkit_la-MediaInformationParser.lo: MediaInformationParser.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-MediaInformationParser.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-MediaInformationParser.Tpo -c -o libffmpegkit_la-MediaInformationParser.lo `test -f 'MediaInformationParser.m' || echo '$(srcdir)/'`MediaInformationParser.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-MediaInformationParser.Tpo $(DEPDIR)/libffmpegkit_la-MediaInformationParser.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='MediaInformationParser.m' object='libffmpegkit_la-MediaInformationParser.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-MediaInformationParser.lo `test -f 'MediaInformationParser.m' || echo '$(srcdir)/'`MediaInformationParser.m
libffmpegkit_la-FFmpegKit.lo: FFmpegKit.m libffmpegkit_la-FFmpegKit.lo: FFmpegKit.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFmpegKit.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFmpegKit.Tpo -c -o libffmpegkit_la-FFmpegKit.lo `test -f 'FFmpegKit.m' || echo '$(srcdir)/'`FFmpegKit.m @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFmpegKit.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFmpegKit.Tpo -c -o libffmpegkit_la-FFmpegKit.lo `test -f 'FFmpegKit.m' || echo '$(srcdir)/'`FFmpegKit.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-FFmpegKit.Tpo $(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo @am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-FFmpegKit.Tpo $(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo
@ -667,12 +680,12 @@ libffmpegkit_la-FFmpegKitConfig.lo: FFmpegKitConfig.m
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-FFmpegKitConfig.lo `test -f 'FFmpegKitConfig.m' || echo '$(srcdir)/'`FFmpegKitConfig.m @am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-FFmpegKitConfig.lo `test -f 'FFmpegKitConfig.m' || echo '$(srcdir)/'`FFmpegKitConfig.m
libffmpegkit_la-ffmpegkit_exception.lo: ffmpegkit_exception.m libffmpegkit_la-FFmpegSession.lo: FFmpegSession.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-ffmpegkit_exception.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Tpo -c -o libffmpegkit_la-ffmpegkit_exception.lo `test -f 'ffmpegkit_exception.m' || echo '$(srcdir)/'`ffmpegkit_exception.m @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFmpegSession.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFmpegSession.Tpo -c -o libffmpegkit_la-FFmpegSession.lo `test -f 'FFmpegSession.m' || echo '$(srcdir)/'`FFmpegSession.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Tpo $(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo @am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-FFmpegSession.Tpo $(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='ffmpegkit_exception.m' object='libffmpegkit_la-ffmpegkit_exception.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='FFmpegSession.m' object='libffmpegkit_la-FFmpegSession.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-ffmpegkit_exception.lo `test -f 'ffmpegkit_exception.m' || echo '$(srcdir)/'`ffmpegkit_exception.m @am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-FFmpegSession.lo `test -f 'FFmpegSession.m' || echo '$(srcdir)/'`FFmpegSession.m
libffmpegkit_la-FFprobeKit.lo: FFprobeKit.m libffmpegkit_la-FFprobeKit.lo: FFprobeKit.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFprobeKit.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFprobeKit.Tpo -c -o libffmpegkit_la-FFprobeKit.lo `test -f 'FFprobeKit.m' || echo '$(srcdir)/'`FFprobeKit.m @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFprobeKit.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFprobeKit.Tpo -c -o libffmpegkit_la-FFprobeKit.lo `test -f 'FFprobeKit.m' || echo '$(srcdir)/'`FFprobeKit.m
@ -681,6 +694,55 @@ libffmpegkit_la-FFprobeKit.lo: FFprobeKit.m
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-FFprobeKit.lo `test -f 'FFprobeKit.m' || echo '$(srcdir)/'`FFprobeKit.m @am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-FFprobeKit.lo `test -f 'FFprobeKit.m' || echo '$(srcdir)/'`FFprobeKit.m
libffmpegkit_la-FFprobeSession.lo: FFprobeSession.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFprobeSession.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFprobeSession.Tpo -c -o libffmpegkit_la-FFprobeSession.lo `test -f 'FFprobeSession.m' || echo '$(srcdir)/'`FFprobeSession.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-FFprobeSession.Tpo $(DEPDIR)/libffmpegkit_la-FFprobeSession.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='FFprobeSession.m' object='libffmpegkit_la-FFprobeSession.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-FFprobeSession.lo `test -f 'FFprobeSession.m' || echo '$(srcdir)/'`FFprobeSession.m
libffmpegkit_la-Log.lo: Log.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-Log.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-Log.Tpo -c -o libffmpegkit_la-Log.lo `test -f 'Log.m' || echo '$(srcdir)/'`Log.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-Log.Tpo $(DEPDIR)/libffmpegkit_la-Log.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='Log.m' object='libffmpegkit_la-Log.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-Log.lo `test -f 'Log.m' || echo '$(srcdir)/'`Log.m
libffmpegkit_la-MediaInformation.lo: MediaInformation.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-MediaInformation.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-MediaInformation.Tpo -c -o libffmpegkit_la-MediaInformation.lo `test -f 'MediaInformation.m' || echo '$(srcdir)/'`MediaInformation.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-MediaInformation.Tpo $(DEPDIR)/libffmpegkit_la-MediaInformation.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='MediaInformation.m' object='libffmpegkit_la-MediaInformation.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-MediaInformation.lo `test -f 'MediaInformation.m' || echo '$(srcdir)/'`MediaInformation.m
libffmpegkit_la-MediaInformationJsonParser.lo: MediaInformationJsonParser.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-MediaInformationJsonParser.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-MediaInformationJsonParser.Tpo -c -o libffmpegkit_la-MediaInformationJsonParser.lo `test -f 'MediaInformationJsonParser.m' || echo '$(srcdir)/'`MediaInformationJsonParser.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-MediaInformationJsonParser.Tpo $(DEPDIR)/libffmpegkit_la-MediaInformationJsonParser.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='MediaInformationJsonParser.m' object='libffmpegkit_la-MediaInformationJsonParser.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-MediaInformationJsonParser.lo `test -f 'MediaInformationJsonParser.m' || echo '$(srcdir)/'`MediaInformationJsonParser.m
libffmpegkit_la-MediaInformationSession.lo: MediaInformationSession.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-MediaInformationSession.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-MediaInformationSession.Tpo -c -o libffmpegkit_la-MediaInformationSession.lo `test -f 'MediaInformationSession.m' || echo '$(srcdir)/'`MediaInformationSession.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-MediaInformationSession.Tpo $(DEPDIR)/libffmpegkit_la-MediaInformationSession.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='MediaInformationSession.m' object='libffmpegkit_la-MediaInformationSession.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-MediaInformationSession.lo `test -f 'MediaInformationSession.m' || echo '$(srcdir)/'`MediaInformationSession.m
libffmpegkit_la-Packages.lo: Packages.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-Packages.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-Packages.Tpo -c -o libffmpegkit_la-Packages.lo `test -f 'Packages.m' || echo '$(srcdir)/'`Packages.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-Packages.Tpo $(DEPDIR)/libffmpegkit_la-Packages.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='Packages.m' object='libffmpegkit_la-Packages.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-Packages.lo `test -f 'Packages.m' || echo '$(srcdir)/'`Packages.m
libffmpegkit_la-ReturnCode.lo: ReturnCode.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-ReturnCode.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-ReturnCode.Tpo -c -o libffmpegkit_la-ReturnCode.lo `test -f 'ReturnCode.m' || echo '$(srcdir)/'`ReturnCode.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-ReturnCode.Tpo $(DEPDIR)/libffmpegkit_la-ReturnCode.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='ReturnCode.m' object='libffmpegkit_la-ReturnCode.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-ReturnCode.lo `test -f 'ReturnCode.m' || echo '$(srcdir)/'`ReturnCode.m
libffmpegkit_la-Statistics.lo: Statistics.m libffmpegkit_la-Statistics.lo: Statistics.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-Statistics.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-Statistics.Tpo -c -o libffmpegkit_la-Statistics.lo `test -f 'Statistics.m' || echo '$(srcdir)/'`Statistics.m @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-Statistics.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-Statistics.Tpo -c -o libffmpegkit_la-Statistics.lo `test -f 'Statistics.m' || echo '$(srcdir)/'`Statistics.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-Statistics.Tpo $(DEPDIR)/libffmpegkit_la-Statistics.Plo @am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-Statistics.Tpo $(DEPDIR)/libffmpegkit_la-Statistics.Plo
@ -695,6 +757,13 @@ libffmpegkit_la-StreamInformation.lo: StreamInformation.m
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-StreamInformation.lo `test -f 'StreamInformation.m' || echo '$(srcdir)/'`StreamInformation.m @am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-StreamInformation.lo `test -f 'StreamInformation.m' || echo '$(srcdir)/'`StreamInformation.m
libffmpegkit_la-ffmpegkit_exception.lo: ffmpegkit_exception.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-ffmpegkit_exception.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Tpo -c -o libffmpegkit_la-ffmpegkit_exception.lo `test -f 'ffmpegkit_exception.m' || echo '$(srcdir)/'`ffmpegkit_exception.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Tpo $(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='ffmpegkit_exception.m' object='libffmpegkit_la-ffmpegkit_exception.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-ffmpegkit_exception.lo `test -f 'ffmpegkit_exception.m' || echo '$(srcdir)/'`ffmpegkit_exception.m
mostlyclean-libtool: mostlyclean-libtool:
-rm -f *.lo -rm -f *.lo
@ -850,16 +919,23 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
mostlyclean-am mostlyclean-am
distclean: distclean-am distclean: distclean-am
-rm -f ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegExecution.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformationParser.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFprobeKit.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFprobeKit.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFprobeSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-Log.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformationJsonParser.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformationSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-Packages.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ReturnCode.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-Statistics.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-Statistics.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-StreamInformation.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-StreamInformation.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo
@ -867,7 +943,6 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
-rm -f Makefile -rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \ distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags distclean-tags
@ -913,16 +988,23 @@ install-ps-am:
installcheck-am: installcheck-am:
maintainer-clean: maintainer-clean-am maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegExecution.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformationParser.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFprobeKit.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFprobeKit.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFprobeSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-Log.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformationJsonParser.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-MediaInformationSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-Packages.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ReturnCode.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-Statistics.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-Statistics.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-StreamInformation.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-StreamInformation.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo
@ -930,7 +1012,6 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
-rm -f Makefile -rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic maintainer-clean-am: distclean-am maintainer-clean-generic

@ -17,8 +17,21 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <Foundation/Foundation.h> #ifndef FFMPEG_KIT_MEDIA_INFORMATION_H
#include "StreamInformation.h" #define FFMPEG_KIT_MEDIA_INFORMATION_H
#import <Foundation/Foundation.h>
#import "StreamInformation.h"
extern NSString* const MediaKeyMediaProperties;
extern NSString* const MediaKeyFilename;
extern NSString* const MediaKeyFormat;
extern NSString* const MediaKeyFormatLong;
extern NSString* const MediaKeyStartTime;
extern NSString* const MediaKeyDuration;
extern NSString* const MediaKeySize;
extern NSString* const MediaKeyBitRate;
extern NSString* const MediaKeyTags;
/** /**
* Media information class. * Media information class.
@ -126,3 +139,5 @@
- (NSDictionary*)getAllProperties; - (NSDictionary*)getAllProperties;
@end @end
#endif // FFMPEG_KIT_MEDIA_INFORMATION_H

@ -17,17 +17,17 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "MediaInformation.h" #import "MediaInformation.h"
#define KEY_MEDIA_PROPERTIES @"format" NSString* const MediaKeyMediaProperties = @"format";
#define KEY_FILENAME @"filename" NSString* const MediaKeyFilename = @"filename";
#define KEY_FORMAT @"format_name" NSString* const MediaKeyFormat = @"format_name";
#define KEY_FORMAT_LONG @"format_long_name" NSString* const MediaKeyFormatLong = @"format_long_name";
#define KEY_START_TIME @"start_time" NSString* const MediaKeyStartTime = @"start_time";
#define KEY_DURATION @"duration" NSString* const MediaKeyDuration = @"duration";
#define KEY_SIZE @"size" NSString* const MediaKeySize = @"size";
#define KEY_BIT_RATE @"bit_rate" NSString* const MediaKeyBitRate = @"bit_rate";
#define KEY_TAGS @"tags" NSString* const MediaKeyTags = @"tags";
@implementation MediaInformation { @implementation MediaInformation {
@ -54,35 +54,35 @@
} }
- (NSString*)getFilename { - (NSString*)getFilename {
return [self getStringProperty:KEY_FILENAME]; return [self getStringProperty:MediaKeyFilename];
} }
- (NSString*)getFormat { - (NSString*)getFormat {
return [self getStringProperty:KEY_FORMAT]; return [self getStringProperty:MediaKeyFormat];
} }
- (NSString*)getLongFormat { - (NSString*)getLongFormat {
return [self getStringProperty:KEY_FORMAT_LONG]; return [self getStringProperty:MediaKeyFormatLong];
} }
- (NSString*)getStartTime { - (NSString*)getStartTime {
return [self getStringProperty:KEY_START_TIME]; return [self getStringProperty:MediaKeyStartTime];
} }
- (NSString*)getDuration { - (NSString*)getDuration {
return [self getStringProperty:KEY_DURATION]; return [self getStringProperty:MediaKeyDuration];
} }
- (NSString*)getSize { - (NSString*)getSize {
return [self getStringProperty:KEY_SIZE]; return [self getStringProperty:MediaKeySize];
} }
- (NSString*)getBitrate { - (NSString*)getBitrate {
return [self getStringProperty:KEY_BIT_RATE]; return [self getStringProperty:MediaKeyBitRate];
} }
- (NSDictionary*)getTags { - (NSDictionary*)getTags {
return [self getProperties:KEY_TAGS]; return [self getProperties:MediaKeyTags];
} }
- (NSArray*)getStreams { - (NSArray*)getStreams {
@ -117,7 +117,7 @@
} }
- (NSDictionary*)getMediaProperties { - (NSDictionary*)getMediaProperties {
return dictionary[KEY_MEDIA_PROPERTIES]; return dictionary[MediaKeyMediaProperties];
} }
- (NSDictionary*)getAllProperties { - (NSDictionary*)getAllProperties {

@ -17,19 +17,34 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <Foundation/Foundation.h> #ifndef FFMPEG_KIT_MEDIA_INFORMATION_PARSER_H
#include "MediaInformation.h" #define FFMPEG_KIT_MEDIA_INFORMATION_PARSER_H
@interface MediaInformationParser : NSObject #import <Foundation/Foundation.h>
#import "MediaInformation.h"
/** /**
* Extracts MediaInformation from the given ffprobe json output. * A parser that constructs MediaInformation from FFprobe's json output.
*/
@interface MediaInformationJsonParser : NSObject
/**
* Extracts <code>MediaInformation</code> from the given FFprobe json output.
*
* @param ffprobeJsonOutput FFprobe json output
* @return created MediaInformation instance of nil if a parsing error occurs
*/ */
+ (MediaInformation*)from:(NSString*)ffprobeJsonOutput; + (MediaInformation*)from:(NSString*)ffprobeJsonOutput;
/** /**
* Extracts MediaInformation from the given ffprobe json output and saves parsing errors in error parameter. * Extracts <code>MediaInformation</code> from the given FFprobe json output.
*
* @param ffprobeJsonOutput FFprobe json output
* @param error error to save the parsing error if a parsing error occurs
* @return created MediaInformation instance
*/ */
+ (MediaInformation*)from:(NSString*)ffprobeJsonOutput with:(NSError*)error; + (MediaInformation*)from:(NSString*)ffprobeJsonOutput with:(NSError*)error;
@end @end
#endif // FFMPEG_KIT_MEDIA_INFORMATION_PARSER_H

@ -17,9 +17,9 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "MediaInformationParser.h" #import "MediaInformationJsonParser.h"
@implementation MediaInformationParser @implementation MediaInformationJsonParser
+ (MediaInformation*)from:(NSString*)ffprobeJsonOutput { + (MediaInformation*)from:(NSString*)ffprobeJsonOutput {
NSError *error; NSError *error;

@ -0,0 +1,74 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_MEDIA_INFORMATION_SESSION_H
#define FFMPEG_KIT_MEDIA_INFORMATION_SESSION_H
#import <Foundation/Foundation.h>
#import "FFprobeSession.h"
#import "MediaInformation.h"
/**
* <p>A custom FFprobe session, which produces a <code>MediaInformation</code> object using the
* FFprobe output.
*/
@interface MediaInformationSession : FFprobeSession
/**
* Creates a new media information session.
*
* @param arguments command arguments
*/
- (instancetype)init:(NSArray*)arguments;
/**
* Creates a new media information session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* Creates a new media information session.
*
* @param arguments command arguments
* @param executeDelegate session specific execute delegate
* @param logDelegate session specific log delegate
*/
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate;
/**
* Returns the media information extracted in this session.
*
* @return media information extracted or nil if the command failed or the output can not be
* parsed
*/
- (MediaInformation*)getMediaInformation;
/**
* Sets the media information extracted in this session.
*
* @param mediaInformation media information extracted
*/
- (void)setMediaInformation:(MediaInformation*)mediaInformation;
@end
#endif // FFMPEG_KIT_MEDIA_INFORMATION_SESSION_H

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ExecuteDelegate.h"
#import "LogDelegate.h"
#import "MediaInformation.h"
#import "MediaInformationSession.h"
@implementation MediaInformationSession {
MediaInformation* _mediaInformation;
}
- (instancetype)init:(NSArray*)arguments {
self = [super init:arguments withExecuteDelegate:nil withLogDelegate:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
self = [super init:arguments withExecuteDelegate:executeDelegate withLogDelegate:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate {
self = [super init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
return self;
}
- (MediaInformation*)getMediaInformation {
return _mediaInformation;
}
- (void)setMediaInformation:(MediaInformation*)mediaInformation {
_mediaInformation = mediaInformation;
}
@end

@ -0,0 +1,46 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_PACKAGES_H
#define FFMPEG_KIT_PACKAGES_H
#import <Foundation/Foundation.h>
/**
* <p>Helper class to extract binary package information.
*/
@interface Packages : NSObject
/**
* Returns the FFmpegKit binary package name.
*
* @return predicted FFmpegKit binary package name
*/
+ (NSString*)getPackageName;
/**
* Returns enabled external libraries by FFmpeg.
*
* @return enabled external libraries
*/
+ (NSArray*)getExternalLibraries;
@end
#endif // FFMPEG_KIT_PACKAGES_H

@ -0,0 +1,263 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "config.h"
#import "libavutil/ffversion.h"
#import "FFmpegKitConfig.h"
#import "Packages.h"
static NSMutableArray *supportedExternalLibraries;
@implementation Packages
+ (void)initialize {
supportedExternalLibraries = [[NSMutableArray alloc] init];
[supportedExternalLibraries addObject:@"dav1d"];
[supportedExternalLibraries addObject:@"fontconfig"];
[supportedExternalLibraries addObject:@"freetype"];
[supportedExternalLibraries addObject:@"fribidi"];
[supportedExternalLibraries addObject:@"gmp"];
[supportedExternalLibraries addObject:@"gnutls"];
[supportedExternalLibraries addObject:@"kvazaar"];
[supportedExternalLibraries addObject:@"mp3lame"];
[supportedExternalLibraries addObject:@"libaom"];
[supportedExternalLibraries addObject:@"libass"];
[supportedExternalLibraries addObject:@"iconv"];
[supportedExternalLibraries addObject:@"libilbc"];
[supportedExternalLibraries addObject:@"libtheora"];
[supportedExternalLibraries addObject:@"libvidstab"];
[supportedExternalLibraries addObject:@"libvorbis"];
[supportedExternalLibraries addObject:@"libvpx"];
[supportedExternalLibraries addObject:@"libwebp"];
[supportedExternalLibraries addObject:@"libxml2"];
[supportedExternalLibraries addObject:@"opencore-amr"];
[supportedExternalLibraries addObject:@"openh264"];
[supportedExternalLibraries addObject:@"opus"];
[supportedExternalLibraries addObject:@"rubberband"];
[supportedExternalLibraries addObject:@"sdl2"];
[supportedExternalLibraries addObject:@"shine"];
[supportedExternalLibraries addObject:@"snappy"];
[supportedExternalLibraries addObject:@"soxr"];
[supportedExternalLibraries addObject:@"speex"];
[supportedExternalLibraries addObject:@"tesseract"];
[supportedExternalLibraries addObject:@"twolame"];
[supportedExternalLibraries addObject:@"x264"];
[supportedExternalLibraries addObject:@"x265"];
[supportedExternalLibraries addObject:@"xvid"];
}
+ (NSString*)getBuildConf {
return [NSString stringWithUTF8String:FFMPEG_CONFIGURATION];
}
+ (NSString*)getPackageName {
NSArray *enabledLibraryArray = [Packages getExternalLibraries];
Boolean speex = [enabledLibraryArray containsObject:@"speex"];
Boolean fribidi = [enabledLibraryArray containsObject:@"fribidi"];
Boolean gnutls = [enabledLibraryArray containsObject:@"gnutls"];
Boolean xvid = [enabledLibraryArray containsObject:@"xvid"];
Boolean min = false;
Boolean minGpl = false;
Boolean https = false;
Boolean httpsGpl = false;
Boolean audio = false;
Boolean video = false;
Boolean full = false;
Boolean fullGpl = false;
if (speex && fribidi) {
if (xvid) {
fullGpl = true;
} else {
full = true;
}
} else if (speex) {
audio = true;
} else if (fribidi) {
video = true;
} else if (xvid) {
if (gnutls) {
httpsGpl = true;
} else {
minGpl = true;
}
} else {
if (gnutls) {
https = true;
} else {
min = true;
}
}
if (fullGpl) {
if ([enabledLibraryArray containsObject:@"dav1d"] &&
[enabledLibraryArray containsObject:@"fontconfig"] &&
[enabledLibraryArray containsObject:@"freetype"] &&
[enabledLibraryArray containsObject:@"fribidi"] &&
[enabledLibraryArray containsObject:@"gmp"] &&
[enabledLibraryArray containsObject:@"gnutls"] &&
[enabledLibraryArray containsObject:@"kvazaar"] &&
[enabledLibraryArray containsObject:@"mp3lame"] &&
[enabledLibraryArray containsObject:@"libass"] &&
[enabledLibraryArray containsObject:@"iconv"] &&
[enabledLibraryArray containsObject:@"libilbc"] &&
[enabledLibraryArray containsObject:@"libtheora"] &&
[enabledLibraryArray containsObject:@"libvidstab"] &&
[enabledLibraryArray containsObject:@"libvorbis"] &&
[enabledLibraryArray containsObject:@"libvpx"] &&
[enabledLibraryArray containsObject:@"libwebp"] &&
[enabledLibraryArray containsObject:@"libxml2"] &&
[enabledLibraryArray containsObject:@"opencore-amr"] &&
[enabledLibraryArray containsObject:@"opus"] &&
[enabledLibraryArray containsObject:@"shine"] &&
[enabledLibraryArray containsObject:@"snappy"] &&
[enabledLibraryArray containsObject:@"soxr"] &&
[enabledLibraryArray containsObject:@"speex"] &&
[enabledLibraryArray containsObject:@"twolame"] &&
[enabledLibraryArray containsObject:@"x264"] &&
[enabledLibraryArray containsObject:@"x265"] &&
[enabledLibraryArray containsObject:@"xvid"]) {
return @"full-gpl";
} else {
return @"custom";
}
}
if (full) {
if ([enabledLibraryArray containsObject:@"dav1d"] &&
[enabledLibraryArray containsObject:@"fontconfig"] &&
[enabledLibraryArray containsObject:@"freetype"] &&
[enabledLibraryArray containsObject:@"fribidi"] &&
[enabledLibraryArray containsObject:@"gmp"] &&
[enabledLibraryArray containsObject:@"gnutls"] &&
[enabledLibraryArray containsObject:@"kvazaar"] &&
[enabledLibraryArray containsObject:@"mp3lame"] &&
[enabledLibraryArray containsObject:@"libass"] &&
[enabledLibraryArray containsObject:@"iconv"] &&
[enabledLibraryArray containsObject:@"libilbc"] &&
[enabledLibraryArray containsObject:@"libtheora"] &&
[enabledLibraryArray containsObject:@"libvorbis"] &&
[enabledLibraryArray containsObject:@"libvpx"] &&
[enabledLibraryArray containsObject:@"libwebp"] &&
[enabledLibraryArray containsObject:@"libxml2"] &&
[enabledLibraryArray containsObject:@"opencore-amr"] &&
[enabledLibraryArray containsObject:@"opus"] &&
[enabledLibraryArray containsObject:@"shine"] &&
[enabledLibraryArray containsObject:@"snappy"] &&
[enabledLibraryArray containsObject:@"soxr"] &&
[enabledLibraryArray containsObject:@"speex"] &&
[enabledLibraryArray containsObject:@"twolame"]) {
return @"full";
} else {
return @"custom";
}
}
if (video) {
if ([enabledLibraryArray containsObject:@"dav1d"] &&
[enabledLibraryArray containsObject:@"fontconfig"] &&
[enabledLibraryArray containsObject:@"freetype"] &&
[enabledLibraryArray containsObject:@"fribidi"] &&
[enabledLibraryArray containsObject:@"kvazaar"] &&
[enabledLibraryArray containsObject:@"libass"] &&
[enabledLibraryArray containsObject:@"iconv"] &&
[enabledLibraryArray containsObject:@"libtheora"] &&
[enabledLibraryArray containsObject:@"libvpx"] &&
[enabledLibraryArray containsObject:@"libwebp"] &&
[enabledLibraryArray containsObject:@"snappy"]) {
return @"video";
} else {
return @"custom";
}
}
if (audio) {
if ([enabledLibraryArray containsObject:@"mp3lame"] &&
[enabledLibraryArray containsObject:@"libilbc"] &&
[enabledLibraryArray containsObject:@"libvorbis"] &&
[enabledLibraryArray containsObject:@"opencore-amr"] &&
[enabledLibraryArray containsObject:@"opus"] &&
[enabledLibraryArray containsObject:@"shine"] &&
[enabledLibraryArray containsObject:@"soxr"] &&
[enabledLibraryArray containsObject:@"speex"] &&
[enabledLibraryArray containsObject:@"twolame"]) {
return @"audio";
} else {
return @"custom";
}
}
if (httpsGpl) {
if ([enabledLibraryArray containsObject:@"gmp"] &&
[enabledLibraryArray containsObject:@"gnutls"] &&
[enabledLibraryArray containsObject:@"libvidstab"] &&
[enabledLibraryArray containsObject:@"x264"] &&
[enabledLibraryArray containsObject:@"x265"] &&
[enabledLibraryArray containsObject:@"xvid"]) {
return @"https-gpl";
} else {
return @"custom";
}
}
if (https) {
if ([enabledLibraryArray containsObject:@"gmp"] &&
[enabledLibraryArray containsObject:@"gnutls"]) {
return @"https";
} else {
return @"custom";
}
}
if (minGpl) {
if ([enabledLibraryArray containsObject:@"libvidstab"] &&
[enabledLibraryArray containsObject:@"x264"] &&
[enabledLibraryArray containsObject:@"x265"] &&
[enabledLibraryArray containsObject:@"xvid"]) {
return @"min-gpl";
} else {
return @"custom";
}
}
return @"min";
}
+ (NSArray*)getExternalLibraries {
NSString *buildConfiguration = [Packages getBuildConf];
NSMutableArray *enabledLibraryArray = [[NSMutableArray alloc] init];
for (int i=0; i < [supportedExternalLibraries count]; i++) {
NSString *supportedExternalLibrary = [supportedExternalLibraries objectAtIndex:i];
NSString *libraryName1 = [NSString stringWithFormat:@"enable-%@", supportedExternalLibrary];
NSString *libraryName2 = [NSString stringWithFormat:@"enable-lib%@", supportedExternalLibrary];
if ([buildConfiguration rangeOfString:libraryName1].location != NSNotFound || [buildConfiguration rangeOfString:libraryName2].location != NSNotFound) {
[enabledLibraryArray addObject:supportedExternalLibrary];
}
}
[enabledLibraryArray sortUsingSelector:@selector(compare:)];
return enabledLibraryArray;
}
@end

@ -0,0 +1,44 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_RETURN_CODE_H
#define FFMPEG_KIT_RETURN_CODE_H
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, ReturnCodeEnum) {
ReturnCodeSuccess = 0,
ReturnCodeCancel = 255
};
@interface ReturnCode : NSObject
- (instancetype)init:(int)value;
- (int)getValue;
- (BOOL)isSuccess;
- (BOOL)isError;
- (BOOL)isCancel;
@end
#endif // FFMPEG_KIT_RETURN_CODE_H

@ -0,0 +1,51 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ReturnCode.h"
@implementation ReturnCode {
int _value;
}
- (instancetype)init:(int)value {
self = [super init];
if (self) {
_value = value;
}
return self;
}
- (int)getValue {
return _value;
}
- (BOOL)isSuccess {
return (_value == ReturnCodeSuccess);
}
- (BOOL)isError {
return ((_value != ReturnCodeSuccess) && (_value != ReturnCodeCancel));
}
- (BOOL)isCancel {
return (_value == ReturnCodeCancel);
}
@end

@ -0,0 +1,255 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_SESSION_H
#define FFMPEG_KIT_SESSION_H
#import <Foundation/Foundation.h>
#import "ExecuteDelegate.h"
#import "Log.h"
#import "LogDelegate.h"
#import "LogRedirectionStrategy.h"
#import "ReturnCode.h"
#import "SessionState.h"
@protocol ExecuteDelegate;
/**
* <p>Common interface for all <code>FFmpegKit</code> sessions.
*/
@protocol Session
@required
/**
* Returns the session specific execute delegate.
*
* @return session specific execute delegate
*/
- (id<ExecuteDelegate>)getExecuteDelegate;
/**
* Returns the session specific log delegate.
*
* @return session specific log delegate
*/
- (id<LogDelegate>)getLogDelegate;
/**
* Returns the session identifier.
*
* @return session identifier
*/
- (long)getSessionId;
/**
* Returns session create time.
*
* @return session create time
*/
- (NSDate*)getCreateTime;
/**
* Returns session start time.
*
* @return session start time
*/
- (NSDate*)getStartTime;
/**
* Returns session end time.
*
* @return session end time
*/
- (NSDate*)getEndTime;
/**
* Returns the time taken to execute this session.
*
* @return time taken to execute this session in milliseconds or zero (0) if the session is
* not over yet
*/
- (long)getDuration;
/**
* Returns command arguments as an array.
*
* @return command arguments as an array
*/
- (NSArray*)getArguments;
/**
* Returns command arguments as a concatenated string.
*
* @return command arguments as a concatenated string
*/
- (NSString*)getCommand;
/**
* Returns all log entries generated for this session. If there are asynchronous
* messages that are not delivered yet, this method waits for them until the given timeout.
*
* @param waitTimeout wait timeout for asynchronous messages in milliseconds
* @return list of log entries generated for this session
*/
- (NSArray*)getAllLogsWithTimeout:(int)waitTimeout;
/**
* Returns all log entries generated for this session. If there are asynchronous
* messages that are not delivered yet, this method waits for them.
*
* @return list of log entries generated for this session
*/
- (NSArray*)getAllLogs;
/**
* Returns all log entries delivered for this session. Note that if there are asynchronous
* messages that are not delivered yet, this method will not wait for them and will return
* immediately.
*
* @return list of log entries received for this session
*/
- (NSArray*)getLogs;
/**
* Returns all log entries generated for this session as a concatenated string. If there are
* asynchronous messages that are not delivered yet, this method waits for them until
* the given timeout.
*
* @param waitTimeout wait timeout for asynchronous messages in milliseconds
* @return all log entries generated for this session as a concatenated string
*/
- (NSString*)getAllLogsAsStringWithTimeout:(int)waitTimeout;
/**
* Returns all log entries generated for this session as a concatenated string. If there are
* asynchronous messages that are not delivered yet, this method waits for them.
*
* @return all log entries generated for this session as a concatenated string
*/
- (NSString*)getAllLogsAsString;
/**
* Returns all log entries delivered for this session as a concatenated string. Note that if
* there are asynchronous messages that are not delivered yet, this method will not wait
* for them and will return immediately.
*
* @return list of log entries received for this session
*/
- (NSString*)getLogsAsString;
/**
* Returns the log output generated while running the session.
*
* @return log output generated
*/
- (NSString*)getOutput;
/**
* Returns the state of the session.
*
* @return state of the session
*/
- (SessionState)getState;
/**
* Returns the return code for this session. Note that return code is only set for sessions
* that end with SessionStateCompleted state. If a session is not started, still running or failed then
* this method returns nil.
*
* @return the return code for this session if the session is completed, nil if session is
* not started, still running or failed
*/
- (ReturnCode*)getReturnCode;
/**
* Returns the stack trace of the exception received while executing this session.
* <p>
* The stack trace is only set for sessions that end with SessionStateFailed state. For sessions that has
* SessionStateCompleted state this method returns nil.
*
* @return stack trace of the exception received while executing this session, nil if session
* is not started, still running or completed
*/
- (NSString*)getFailStackTrace;
/**
* Returns session specific log redirection strategy.
*
* @return session specific log redirection strategy
*/
- (LogRedirectionStrategy)getLogRedirectionStrategy;
/**
* Returns whether there are still asynchronous messages being transmitted for this
* session or not.
*
* @return true if there are still asynchronous messages being transmitted, false
* otherwise
*/
- (BOOL)thereAreAsynchronousMessagesInTransmit;
/**
* Adds a new log entry for this session.
*
* @param log log entry
*/
- (void)addLog:(Log*)log;
/**
* Starts running the session.
*/
- (void)startRunning;
/**
* Completes running the session with the provided return code.
*
* @param returnCode return code of the execution
*/
- (void)complete:(ReturnCode*)returnCode;
/**
* Ends running the session with a failure.
*
* @param exception execution received
*/
- (void)fail:(NSException*)exception;
/**
* Returns whether it is an <code>FFmpeg</code> session or not.
*
* @return true if it is an <code>FFmpeg</code> session, false otherwise
*/
- (BOOL)isFFmpeg;
/**
* Returns whether it is an <code>FFprobe</code> session or not.
*
* @return true if it is an <code>FFprobe</code> session, false otherwise
*/
- (BOOL)isFFprobe;
/**
* Cancels running the session.
*/
- (void)cancel;
@end
#endif // FFMPEG_KIT_SESSION_H

@ -0,0 +1,30 @@
/*
* Copyright (c) 2021 Taner Sener
*
* This file is part of FFmpegKit.
*
* FFmpegKit is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FFmpegKit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General License for more details.
*
* You should have received a copy of the GNU Lesser General License
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_SESSION_STATE_H
#define FFMPEG_KIT_SESSION_STATE_H
typedef NS_ENUM(NSUInteger, SessionState) {
SessionStateCreated,
SessionStateRunning,
SessionStateFailed,
SessionStateCompleted
};
#endif // FFMPEG_KIT_SESSION_STATE_H

@ -17,20 +17,19 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <Foundation/Foundation.h> #ifndef FFMPEG_KIT_STATISTICS_H
#define FFMPEG_KIT_STATISTICS_H
#import <Foundation/Foundation.h>
/** /**
* Statistics for running executions. * Statistics entry for an FFmpeg execute session.
*/ */
@interface Statistics : NSObject @interface Statistics : NSObject
- (instancetype)init; - (instancetype)init:(long)sessionId videoFrameNumber:(int)videoFrameNumber videoFps:(float)videoFps videoQuality:(float)videoQuality size:(int64_t)size time:(int)time bitrate:(double)bitrate speed:(double)speed;
- (instancetype)initWithId:(long)currentExecutionId videoFrameNumber:(int)newVideoFrameNumber fps:(float)newVideoFps quality:(float)newVideoQuality size:(int64_t)newSize time:(int)newTime bitrate:(double)newBitrate speed:(double)newSpeed;
- (void)update:(Statistics*)statistics; - (long)getSessionId;
- (long)getExecutionId;
- (int)getVideoFrameNumber; - (int)getVideoFrameNumber;
@ -47,3 +46,5 @@
- (double)getSpeed; - (double)getSpeed;
@end @end
#endif // FFMPEG_KIT_STATISTICS_H

@ -17,108 +17,65 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "Statistics.h" #import "Statistics.h"
@implementation Statistics { @implementation Statistics {
long executionId; long _sessionId;
int videoFrameNumber; int _videoFrameNumber;
float videoFps; float _videoFps;
float videoQuality; float _videoQuality;
long size; long _size;
int time; int _time;
double bitrate; double _bitrate;
double speed; double _speed;
} }
- (instancetype)init { - (instancetype)init:(long)sessionId videoFrameNumber:(int)videoFrameNumber videoFps:(float)videoFps videoQuality:(float)videoQuality size:(int64_t)size time:(int)time bitrate:(double)bitrate speed:(double)speed {
self = [super init]; self = [super init];
if (self) { if (self) {
executionId = 0; _sessionId = sessionId;
videoFrameNumber = 0; _videoFrameNumber = videoFrameNumber;
videoFps = 0; _videoFps = videoFps;
videoQuality = 0; _videoQuality = videoQuality;
size = 0; _size = size;
time = 0; _time = time;
bitrate = 0; _bitrate = bitrate;
speed = 0; _speed = speed;
} }
return self; return self;
} }
- (instancetype)initWithId:(long)currentExecutionId videoFrameNumber:(int)newVideoFrameNumber fps:(float)newVideoFps quality:(float)newVideoQuality size:(int64_t)newSize time:(int)newTime bitrate:(double)newBitrate speed:(double)newSpeed { - (long)getSessionId {
self = [super init]; return _sessionId;
if (self) {
executionId = currentExecutionId;
videoFrameNumber = newVideoFrameNumber;
videoFps = newVideoFps;
videoQuality = newVideoQuality;
size = newSize;
time = newTime;
bitrate = newBitrate;
speed = newSpeed;
}
return self;
}
- (void)update:(Statistics*)statistics {
if (statistics != nil) {
executionId = [statistics getExecutionId];
if ([statistics getVideoFrameNumber] > 0) {
videoFrameNumber = [statistics getVideoFrameNumber];
}
if ([statistics getVideoFps] > 0) {
videoFps = [statistics getVideoFps];
}
if ([statistics getVideoQuality] > 0) {
videoQuality = [statistics getVideoQuality];
}
if ([statistics getSize] > 0) {
size = [statistics getSize];
}
if ([statistics getTime] > 0) {
time = [statistics getTime];
}
if ([statistics getBitrate] > 0) {
bitrate = [statistics getBitrate];
}
if ([statistics getSpeed] > 0) {
speed = [statistics getSpeed];
}
}
}
- (long)getExecutionId {
return executionId;
} }
- (int)getVideoFrameNumber { - (int)getVideoFrameNumber {
return videoFrameNumber; return _videoFrameNumber;
} }
- (float)getVideoFps { - (float)getVideoFps {
return videoFps; return _videoFps;
} }
- (float)getVideoQuality { - (float)getVideoQuality {
return videoQuality; return _videoQuality;
} }
- (long)getSize { - (long)getSize {
return size; return _size;
} }
- (int)getTime { - (int)getTime {
return time; return _time;
} }
- (double)getBitrate { - (double)getBitrate {
return bitrate; return _bitrate;
} }
- (double)getSpeed { - (double)getSpeed {
return speed; return _speed;
} }
@end @end

@ -17,12 +17,25 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "Statistics.h" #ifndef FFMPEG_KIT_STATISTICS_DELEGATE_H
#define FFMPEG_KIT_STATISTICS_DELEGATE_H
#import <Foundation/Foundation.h>
#import "Statistics.h"
/** /**
* Use this delegate to receive statistics from running executions. * <p>Delegate that receives statistics generated for <code>FFmpegKit</code> sessions.
*/ */
@protocol StatisticsDelegate<NSObject> @protocol StatisticsDelegate<NSObject>
@required @required
/**
* <p>Called when a statistics entry is received.
*
* @param statistics statistics entry
*/
- (void)statisticsCallback:(Statistics*)statistics; - (void)statisticsCallback:(Statistics*)statistics;
@end @end
#endif // FFMPEG_KIT_STATISTICS_DELEGATE_H

@ -17,7 +17,29 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <Foundation/Foundation.h> #ifndef FFMPEG_KIT_STREAM_INFORMATION_H
#define FFMPEG_KIT_STREAM_INFORMATION_H
#import <Foundation/Foundation.h>
extern NSString* const StreamKeyIndex;
extern NSString* const StreamKeyType;
extern NSString* const StreamKeyCodec;
extern NSString* const StreamKeyCodecLong;
extern NSString* const StreamKeyFormat;
extern NSString* const StreamKeyWidth;
extern NSString* const StreamKeyHeight;
extern NSString* const StreamKeyBitRate;
extern NSString* const StreamKeySampleRate;
extern NSString* const StreamKeySampleFormat;
extern NSString* const StreamKeyChannelLayout;
extern NSString* const StreamKeySampleAspectRatio;
extern NSString* const StreamKeyDisplayAspectRatio;
extern NSString* const StreamKeyAverageFrameRate;
extern NSString* const StreamKeyRealFrameRate;
extern NSString* const StreamKeyTimeBase;
extern NSString* const StreamKeyCodecTimeBase;
extern NSString* const StreamKeyTags;
/** /**
* Stream information class. * Stream information class.
@ -181,3 +203,5 @@
- (NSDictionary*)getAllProperties; - (NSDictionary*)getAllProperties;
@end @end
#endif // FFMPEG_KIT_STREAM_INFORMATION_H

@ -17,26 +17,26 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "StreamInformation.h" #import "StreamInformation.h"
#define KEY_INDEX @"index" NSString* const StreamKeyIndex = @"index";
#define KEY_TYPE @"codec_type" NSString* const StreamKeyType = @"codec_type";
#define KEY_CODEC @"codec_name" NSString* const StreamKeyCodec = @"codec_name";
#define KEY_CODEC_LONG @"codec_long_name" NSString* const StreamKeyCodecLong = @"codec_long_name";
#define KEY_FORMAT @"pix_fmt" NSString* const StreamKeyFormat = @"pix_fmt";
#define KEY_WIDTH @"width" NSString* const StreamKeyWidth = @"width";
#define KEY_HEIGHT @"height" NSString* const StreamKeyHeight = @"height";
#define KEY_BIT_RATE @"bit_rate" NSString* const StreamKeyBitRate = @"bit_rate";
#define KEY_SAMPLE_RATE @"sample_rate" NSString* const StreamKeySampleRate = @"sample_rate";
#define KEY_SAMPLE_FORMAT @"sample_fmt" NSString* const StreamKeySampleFormat = @"sample_fmt";
#define KEY_CHANNEL_LAYOUT @"channel_layout" NSString* const StreamKeyChannelLayout = @"channel_layout";
#define KEY_SAMPLE_ASPECT_RATIO @"sample_aspect_ratio" NSString* const StreamKeySampleAspectRatio = @"sample_aspect_ratio";
#define KEY_DISPLAY_ASPECT_RATIO @"display_aspect_ratio" NSString* const StreamKeyDisplayAspectRatio = @"display_aspect_ratio";
#define KEY_AVERAGE_FRAME_RATE @"avg_frame_rate" NSString* const StreamKeyAverageFrameRate = @"avg_frame_rate";
#define KEY_REAL_FRAME_RATE @"r_frame_rate" NSString* const StreamKeyRealFrameRate = @"r_frame_rate";
#define KEY_TIME_BASE @"time_base" NSString* const StreamKeyTimeBase = @"time_base";
#define KEY_CODEC_TIME_BASE @"codec_time_base" NSString* const StreamKeyCodecTimeBase = @"codec_time_base";
#define KEY_TAGS @"tags" NSString* const StreamKeyTags = @"tags";
@implementation StreamInformation { @implementation StreamInformation {
@ -57,75 +57,75 @@
} }
- (NSNumber*)getIndex { - (NSNumber*)getIndex {
return [self getNumberProperty:KEY_INDEX]; return [self getNumberProperty:StreamKeyIndex];
} }
- (NSString*)getType { - (NSString*)getType {
return [self getStringProperty:KEY_TYPE]; return [self getStringProperty:StreamKeyType];
} }
- (NSString*)getCodec { - (NSString*)getCodec {
return [self getStringProperty:KEY_CODEC]; return [self getStringProperty:StreamKeyCodec];
} }
- (NSString*)getFullCodec { - (NSString*)getFullCodec {
return [self getStringProperty:KEY_CODEC_LONG]; return [self getStringProperty:StreamKeyCodecLong];
} }
- (NSString*)getFormat { - (NSString*)getFormat {
return [self getStringProperty:KEY_FORMAT]; return [self getStringProperty:StreamKeyFormat];
} }
- (NSNumber*)getWidth { - (NSNumber*)getWidth {
return [self getNumberProperty:KEY_WIDTH]; return [self getNumberProperty:StreamKeyWidth];
} }
- (NSNumber*)getHeight { - (NSNumber*)getHeight {
return [self getNumberProperty:KEY_HEIGHT]; return [self getNumberProperty:StreamKeyHeight];
} }
- (NSString*)getBitrate { - (NSString*)getBitrate {
return [self getStringProperty:KEY_BIT_RATE]; return [self getStringProperty:StreamKeyBitRate];
} }
- (NSString*)getSampleRate { - (NSString*)getSampleRate {
return [self getStringProperty:KEY_SAMPLE_RATE]; return [self getStringProperty:StreamKeySampleRate];
} }
- (NSString*)getSampleFormat { - (NSString*)getSampleFormat {
return [self getStringProperty:KEY_SAMPLE_FORMAT]; return [self getStringProperty:StreamKeySampleFormat];
} }
- (NSString*)getChannelLayout { - (NSString*)getChannelLayout {
return [self getStringProperty:KEY_CHANNEL_LAYOUT]; return [self getStringProperty:StreamKeyChannelLayout];
} }
- (NSString*)getSampleAspectRatio { - (NSString*)getSampleAspectRatio {
return [self getStringProperty:KEY_SAMPLE_ASPECT_RATIO]; return [self getStringProperty:StreamKeySampleAspectRatio];
} }
- (NSString*)getDisplayAspectRatio { - (NSString*)getDisplayAspectRatio {
return [self getStringProperty:KEY_DISPLAY_ASPECT_RATIO]; return [self getStringProperty:StreamKeyDisplayAspectRatio];
} }
- (NSString*)getAverageFrameRate { - (NSString*)getAverageFrameRate {
return [self getStringProperty:KEY_AVERAGE_FRAME_RATE]; return [self getStringProperty:StreamKeyAverageFrameRate];
} }
- (NSString*)getRealFrameRate { - (NSString*)getRealFrameRate {
return [self getStringProperty:KEY_REAL_FRAME_RATE]; return [self getStringProperty:StreamKeyRealFrameRate];
} }
- (NSString*)getTimeBase { - (NSString*)getTimeBase {
return [self getStringProperty:KEY_TIME_BASE]; return [self getStringProperty:StreamKeyTimeBase];
} }
- (NSString*)getCodecTimeBase { - (NSString*)getCodecTimeBase {
return [self getStringProperty:KEY_CODEC_TIME_BASE]; return [self getStringProperty:StreamKeyCodecTimeBase];
} }
- (NSDictionary*)getTags { - (NSDictionary*)getTags {
return [self getProperties:KEY_TAGS]; return [self getProperties:StreamKeyTags];
} }
- (NSString*)getStringProperty:(NSString*)key { - (NSString*)getStringProperty:(NSString*)key {

@ -257,9 +257,9 @@ extern volatile int handleSIGTERM;
extern volatile int handleSIGXCPU; extern volatile int handleSIGXCPU;
extern volatile int handleSIGPIPE; extern volatile int handleSIGPIPE;
extern __thread volatile long executionId; extern __thread volatile long _sessionId;
extern int cancelRequested(long executionId); extern void cancelSession(long sessionId);
extern void removeExecution(long executionId); extern int cancelRequested(long sessionId);
/* sub2video hack: /* sub2video hack:
Convert subtitles to video with alpha to insert them in filter graphs. Convert subtitles to video with alpha to insert them in filter graphs.
@ -768,7 +768,7 @@ static void ffmpeg_cleanup(int ret)
if (received_sigterm) { if (received_sigterm) {
av_log(NULL, AV_LOG_INFO, "Exiting normally, received signal %d.\n", av_log(NULL, AV_LOG_INFO, "Exiting normally, received signal %d.\n",
(int) received_sigterm); (int) received_sigterm);
} else if (cancelRequested(executionId)) { } else if (cancelRequested(_sessionId)) {
av_log(NULL, AV_LOG_INFO, "Exiting normally, received cancel request.\n"); av_log(NULL, AV_LOG_INFO, "Exiting normally, received cancel request.\n");
} else if (ret && atomic_load(&transcode_init_done)) { } else if (ret && atomic_load(&transcode_init_done)) {
av_log(NULL, AV_LOG_INFO, "Conversion failed!\n"); av_log(NULL, AV_LOG_INFO, "Conversion failed!\n");
@ -2431,7 +2431,7 @@ static int ifilter_send_eof(InputFilter *ifilter, int64_t pts)
if (ifilter->filter) { if (ifilter->filter) {
/* THIS VALIDATION IS REQUIRED TO COMPLETE CANCELLATION */ /* THIS VALIDATION IS REQUIRED TO COMPLETE CANCELLATION */
if (!received_sigterm && !cancelRequested(executionId)) { if (!received_sigterm && !cancelRequested(_sessionId)) {
ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH); ret = av_buffersrc_close(ifilter->filter, pts, AV_BUFFERSRC_FLAG_PUSH);
} }
if (ret < 0) if (ret < 0)
@ -4934,7 +4934,7 @@ static int transcode(void)
goto fail; goto fail;
#endif #endif
while (!received_sigterm && !cancelRequested(executionId)) { while (!received_sigterm && !cancelRequested(_sessionId)) {
int64_t cur_time= av_gettime_relative(); int64_t cur_time= av_gettime_relative();
/* if 'q' pressed, exits */ /* if 'q' pressed, exits */
@ -5148,7 +5148,7 @@ void cancel_operation(long id)
if (id == 0) { if (id == 0) {
sigterm_handler(SIGINT); sigterm_handler(SIGINT);
} else { } else {
removeExecution(id); cancelSession(id);
} }
} }
@ -5672,10 +5672,10 @@ int ffmpeg_execute(int argc, char **argv)
if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1]) if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1])
exit_program(69); exit_program(69);
exit_program((received_nb_signals || cancelRequested(executionId))? 255 : main_ffmpeg_return_code); exit_program((received_nb_signals || cancelRequested(_sessionId))? 255 : main_ffmpeg_return_code);
} else { } else {
main_ffmpeg_return_code = (received_nb_signals || cancelRequested(executionId)) ? 255 : longjmp_value; main_ffmpeg_return_code = (received_nb_signals || cancelRequested(_sessionId)) ? 255 : longjmp_value;
} }
return main_ffmpeg_return_code; return main_ffmpeg_return_code;

@ -22,14 +22,14 @@ enable_default_ios_architectures
enable_main_build enable_main_build
# SELECT XCODE VERSION USED FOR BUILDING # SELECT XCODE VERSION USED FOR BUILDING
XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh) XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh 2>>"${BASEDIR}"/build.log)
if [[ -f ${XCODE_FOR_FFMPEG_KIT} ]]; then if [[ -f ${XCODE_FOR_FFMPEG_KIT} ]]; then
source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1 source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1
fi fi
# DETECT IOS SDK VERSION # DETECT IOS SDK VERSION
DETECTED_IOS_SDK_VERSION="$(xcrun --sdk iphoneos --show-sdk-version)" DETECTED_IOS_SDK_VERSION="$(xcrun --sdk iphoneos --show-sdk-version)"
echo -e "INFO: Using SDK ${DETECTED_IOS_SDK_VERSION} by Xcode provided at $(xcode-select -p)\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "\nINFO: Using SDK ${DETECTED_IOS_SDK_VERSION} by Xcode provided at $(xcode-select -p)\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "INFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "INFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1
# SET DEFAULT BUILD OPTIONS # SET DEFAULT BUILD OPTIONS

@ -22,14 +22,14 @@ enable_default_macos_architectures
enable_main_build enable_main_build
# SELECT XCODE VERSION USED FOR BUILDING # SELECT XCODE VERSION USED FOR BUILDING
XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh) XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh 2>>"${BASEDIR}"/build.log)
if [[ -f ${XCODE_FOR_FFMPEG_KIT} ]]; then if [[ -f ${XCODE_FOR_FFMPEG_KIT} ]]; then
source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1 source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1
fi fi
# DETECT MACOS SDK VERSION # DETECT MACOS SDK VERSION
DETECTED_MACOS_SDK_VERSION="$(xcrun --sdk macosx --show-sdk-version)" DETECTED_MACOS_SDK_VERSION="$(xcrun --sdk macosx --show-sdk-version)"
echo -e "INFO: Using SDK ${DETECTED_MACOS_SDK_VERSION} by Xcode provided at $(xcode-select -p)\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "\nINFO: Using SDK ${DETECTED_MACOS_SDK_VERSION} by Xcode provided at $(xcode-select -p)\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "\nINFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "\nINFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1
# SET DEFAULT BUILD OPTIONS # SET DEFAULT BUILD OPTIONS

@ -22,14 +22,14 @@ enable_default_tvos_architectures
enable_main_build enable_main_build
# SELECT XCODE VERSION USED FOR BUILDING # SELECT XCODE VERSION USED FOR BUILDING
XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh) XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh 2>>"${BASEDIR}"/build.log)
if [[ -f ${XCODE_FOR_FFMPEG_KIT} ]]; then if [[ -f ${XCODE_FOR_FFMPEG_KIT} ]]; then
source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1 source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1
fi fi
# DETECT TVOS SDK VERSION # DETECT TVOS SDK VERSION
DETECTED_TVOS_SDK_VERSION="$(xcrun --sdk appletvos --show-sdk-version)" DETECTED_TVOS_SDK_VERSION="$(xcrun --sdk appletvos --show-sdk-version)"
echo -e "INFO: Using SDK ${DETECTED_TVOS_SDK_VERSION} by Xcode provided at $(xcode-select -p)\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "\nINFO: Using SDK ${DETECTED_TVOS_SDK_VERSION} by Xcode provided at $(xcode-select -p)\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "\nINFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "\nINFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1
# SET DEFAULT BUILD OPTIONS # SET DEFAULT BUILD OPTIONS

Loading…
Cancel
Save