refactor api

pull/7/head
Taner Sener 5 years ago
parent 2fceb5f5ed
commit 4680721cef
  1. 131
      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. 1328
      apple/src/FFmpegKitConfig.m
  54. 119
      apple/src/FFmpegSession.h
  55. 137
      apple/src/FFmpegSession.m
  56. 226
      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. 241
      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. 97
      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 <stdatomic.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -28,6 +29,9 @@
#include "ffmpegkit.h"
#include "ffprobekit.h"
# define LogType 1
# define StatisticsType 2
/** Callback data structure */
struct CallbackData {
int type; // 1 (log callback) or 2 (statistics callback)
@ -47,11 +51,10 @@ struct CallbackData {
struct CallbackData *next;
};
/** Session map variables */
/** Session control variables */
const int SESSION_MAP_SIZE = 1000;
static volatile int sessionMap[SESSION_MAP_SIZE];
static volatile int sessionInTransitMessageCountMap[SESSION_MAP_SIZE];
static pthread_mutex_t sessionMapMutex;
static atomic_short sessionMap[SESSION_MAP_SIZE];
static atomic_int sessionInTransitMessageCountMap[SESSION_MAP_SIZE];
/** Redirection control variables */
static pthread_mutex_t lockMutex;
@ -215,15 +218,6 @@ void monitorInit() {
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() {
pthread_mutex_destroy(&lockMutex);
}
@ -233,26 +227,14 @@ void monitorUnInit() {
pthread_cond_destroy(&monitorCondition);
}
void sessionMapLockUnInit() {
pthread_mutex_destroy(&sessionMapMutex);
}
void mutexLock() {
pthread_mutex_lock(&lockMutex);
}
void sessionMapLock() {
pthread_mutex_lock(&sessionMapMutex);
}
void mutexUnlock() {
pthread_mutex_unlock(&lockMutex);
}
void sessionMapUnlock() {
pthread_mutex_unlock(&sessionMapMutex);
}
void monitorWait(int milliSeconds) {
struct timeval tp;
struct timespec ts;
@ -291,7 +273,7 @@ void logCallbackDataAdd(int level, AVBPrint *data) {
// CREATE DATA STRUCT FIRST
struct CallbackData *newData = (struct CallbackData*)av_malloc(sizeof(struct CallbackData));
newData->type = 1;
newData->type = LogType;
newData->sessionId = sessionId;
newData->logLevel = level;
av_bprint_init(&newData->logData, 0, AV_BPRINT_SIZE_UNLIMITED);
@ -316,12 +298,11 @@ void logCallbackDataAdd(int level, AVBPrint *data) {
callbackDataTail = newData;
}
int key = sessionId % SESSION_MAP_SIZE;
sessionInTransitMessageCountMap[key] += 1;
mutexUnlock();
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
struct CallbackData *newData = (struct CallbackData*)av_malloc(sizeof(struct CallbackData));
newData->type = 2;
newData->type = StatisticsType;
newData->sessionId = sessionId;
newData->statisticsFrameNumber = frameNumber;
newData->statisticsFps = fps;
@ -361,12 +342,11 @@ void statisticsCallbackDataAdd(int frameNumber, float fps, float quality, int64_
callbackDataTail = newData;
}
int key = sessionId % SESSION_MAP_SIZE;
sessionInTransitMessageCountMap[key] += 1;
mutexUnlock();
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
*/
void addSession(long id) {
sessionMapLock();
int key = id % SESSION_MAP_SIZE;
sessionMap[key] = 1;
sessionMapUnlock();
atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 1);
}
/**
@ -421,12 +396,7 @@ struct CallbackData *callbackDataRemove() {
* @param id session id
*/
void removeSession(long id) {
sessionMapLock();
int key = id % SESSION_MAP_SIZE;
sessionMap[key] = 0;
sessionMapUnlock();
atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 0);
}
/**
@ -435,12 +405,7 @@ void removeSession(long id) {
* @param id session id
*/
void cancelSession(long id) {
sessionMapLock();
int key = id % SESSION_MAP_SIZE;
sessionMap[key] = 2;
sessionMapUnlock();
atomic_store(&sessionMap[id % SESSION_MAP_SIZE], 2);
}
/**
@ -450,18 +415,11 @@ void cancelSession(long id) {
* @return 1 if exists, false otherwise
*/
int cancelRequested(long id) {
int found = 0;
sessionMapLock();
int key = id % SESSION_MAP_SIZE;
if (sessionMap[key] == 2) {
found = 1;
if (atomic_load(&sessionMap[id % SESSION_MAP_SIZE]) == 2) {
return 1;
} else {
return 0;
}
sessionMapUnlock();
return found;
}
/**
@ -470,12 +428,7 @@ int cancelRequested(long id) {
* @param id session id
*/
void resetMessagesInTransmit(long id) {
mutexLock();
int key = id % SESSION_MAP_SIZE;
sessionInTransitMessageCountMap[key] = 0;
mutexUnlock();
atomic_store(&sessionInTransitMessageCountMap[id % SESSION_MAP_SIZE], 0);
}
/**
@ -556,13 +509,13 @@ void *callbackThreadFunction() {
}
}
LOGD("Callback thread started.\n");
LOGD("Async callback block started.\n");
while(redirectionEnabled) {
struct CallbackData *callbackData = callbackDataRemove();
if (callbackData != NULL) {
if (callbackData->type == 1) {
if (callbackData->type == LogType) {
// LOG CALLBACK
@ -588,8 +541,7 @@ void *callbackThreadFunction() {
}
int key = callbackData->sessionId % SESSION_MAP_SIZE;
sessionInTransitMessageCountMap[key] -= 1;
atomic_fetch_sub(&sessionInTransitMessageCountMap[callbackData->sessionId % SESSION_MAP_SIZE], 1);
// CLEAN STRUCT
callbackData->next = NULL;
@ -602,7 +554,7 @@ void *callbackThreadFunction() {
(*globalVm)->DetachCurrentThread(globalVm);
LOGD("Callback thread stopped.\n");
LOGD("Async callback block stopped.\n");
return NULL;
}
@ -678,18 +630,18 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
configClass = (jclass) ((*env)->NewGlobalRef(env, localConfigClass));
stringClass = (jclass) ((*env)->NewGlobalRef(env, localStringClass));
redirectionEnabled = 0;
callbackDataHead = NULL;
callbackDataTail = NULL;
for(int i = 0; i<SESSION_MAP_SIZE; i++) {
sessionMap[i] = 0;
atomic_init(&sessionMap[i], 0);
atomic_init(&sessionInTransitMessageCountMap[i], 0);
}
mutexInit();
monitorInit();
sessionMapLockInit();
redirectionEnabled = 0;
return JNI_VERSION_1_6;
}
@ -802,10 +754,10 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFmpeg
int argumentCount = 1;
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);
if (stringArray != NULL) {
if (stringArray) {
int programArgumentCount = (*env)->GetArrayLength(env, stringArray);
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));
strcpy(argv[0], LIB_NAME);
// PREPARE
if (stringArray != NULL) {
// PREPARE ARRAY ELEMENTS
if (stringArray) {
for (int i = 0; i < (argumentCount - 1); i++) {
tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
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;
addSession((long) id);
resetMessagesInTransmit(sessionId);
// RUN
int retCode = ffmpeg_execute(argumentCount, argv);
int returnCode = ffmpeg_execute(argumentCount, argv);
// ALWAYS REMOVE THE ID FROM THE MAP
removeSession((long) id);
// CLEANUP
if (tempArray != NULL) {
if (tempArray) {
for (int i = 0; i < (argumentCount - 1); i++) {
(*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);
return retCode;
return returnCode;
}
/**
@ -944,12 +896,5 @@ JNIEXPORT void JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_ignoreNative
* @param id session id
*/
JNIEXPORT int JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_messagesInTransmit(JNIEnv *env, jclass object, jlong id) {
mutexLock();
int key = id % SESSION_MAP_SIZE;
int count = sessionInTransitMessageCountMap[key];
mutexUnlock();
return count;
return atomic_load(&sessionInTransitMessageCountMap[id % SESSION_MAP_SIZE]);
}

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

@ -49,10 +49,10 @@ JNIEXPORT jint JNICALL Java_com_arthenica_ffmpegkit_FFmpegKitConfig_nativeFFprob
int argumentCount = 1;
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);
if (stringArray != NULL) {
if (stringArray) {
int programArgumentCount = (*env)->GetArrayLength(env, stringArray);
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));
strcpy(argv[0], LIB_NAME);
// PREPARE
if (stringArray != NULL) {
// PREPARE ARRAY ELEMENTS
if (stringArray) {
for (int i = 0; i < (argumentCount - 1); i++) {
tempArray[i] = (jstring) (*env)->GetObjectArrayElement(env, stringArray, i);
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;
addSession((long) id);
resetMessagesInTransmit(sessionId);
// RUN
int retCode = ffprobe_execute(argumentCount, argv);
int returnCode = ffprobe_execute(argumentCount, argv);
// ALWAYS REMOVE THE ID FROM THE MAP
removeSession((long) id);
// CLEANUP
if (tempArray != NULL) {
if (tempArray) {
for (int i = 0; i < (argumentCount - 1); i++) {
(*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);
return retCode;
return returnCode;
}

@ -38,13 +38,11 @@ void closeParcelFileDescriptor(int fd);
#undef avformat_open_input
static int fd_read_packet(void* opaque, uint8_t* buf, int buf_size) {
int *fd = opaque;
return read(*fd, buf, buf_size);
return read(*(int*)opaque, buf, buf_size);
}
static int fd_write_packet(void* opaque, uint8_t* buf, int buf_size) {
int *fd = opaque;
return write(*fd, buf, buf_size);
return write(*(int*)opaque, buf, buf_size);
}
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')
*/
static AVIOContext *create_fd_avio_context(const char *filename, int flags) {
int *fd = av_mallocz(sizeof(int));
*fd = -1;
const char *fd_ptr = NULL;
int fd = -1;
const char* fd_ptr = NULL;
if (av_strstart(filename, "saf:", &fd_ptr)) {
char *final;
*fd = strtol(fd_ptr, &final, 10);
fd = strtol(fd_ptr, &final, 10);
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;
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;
}
static void close_fd_avio_context(AVIOContext *ctx) {
if (fd_seek(ctx->opaque, 0, AVSEEK_SIZE) >= 0) {
int *fd = ctx->opaque;
closeParcelFileDescriptor(*fd);
av_freep(&fd);
if (ctx) {
if (fd_seek(ctx->opaque, 0, AVSEEK_SIZE) >= 0) {
int *fd = ctx->opaque;
closeParcelFileDescriptor(*fd);
av_freep(&fd);
}
ctx->opaque = NULL;
}
ctx->opaque = NULL;
}
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;
return 0;
}
return avio_open2(s, filename, flags, int_cb, options);
}

@ -20,9 +20,7 @@
package com.arthenica.ffmpegkit;
/**
* <p>Enumeration type for Android ABIs.
*
* @author Taner Sener
* <p>Enumeration for Android ABIs.
*/
public enum Abi {
@ -64,10 +62,10 @@ public enum Abi {
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
* @return enumeration defined by ABI name
* @return enumeration defined for the ABI name
*/
public static Abi from(final String abiName) {
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() {
return name;

@ -20,18 +20,19 @@
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 {
static {
armV7aNeonLoaded = false;
System.loadLibrary("ffmpegkit_abidetect");
NativeLoader.loadFFmpegKitAbiDetect();
/* ALL LIBRARIES LOADED AT STARTUP */
FFmpegKitConfig.class.getName();
FFmpegKit.class.getName();
FFmpegKitConfig.class.getName();
FFprobeKit.class.getName();
}
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() {
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
*/
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
*/

@ -22,54 +22,121 @@ package com.arthenica.ffmpegkit;
import com.arthenica.smartexception.java.Exceptions;
import java.util.Date;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Future;
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 {
/**
* Generates ids for execute sessions.
* Generates unique ids for sessions.
*/
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;
/**
* Session specific log callback function.
*/
protected final LogCallback logCallback;
protected final StatisticsCallback statisticsCallback;
protected final long sessionId;
/**
* Date and time the session was created.
*/
protected final Date createTime;
/**
* Date and time the session was started.
*/
protected Date startTime;
/**
* Date and time the session has ended.
*/
protected Date endTime;
/**
* Command arguments as an array.
*/
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;
/**
* State of the session.
*/
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;
/**
* Session specific log redirection strategy.
*/
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,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
this.sessionId = sessionIdGenerator.getAndIncrement();
this.executeCallback = executeCallback;
this.logCallback = logCallback;
this.createTime = new Date();
this.startTime = null;
this.endTime = null;
this.arguments = arguments;
this.executeCallback = executeCallback;
this.logCallback = logCallback;
this.statisticsCallback = statisticsCallback;
this.logs = new ConcurrentLinkedQueue<>();
this.logs = new LinkedList<>();
this.logsLock = new Object();
this.future = null;
this.state = SessionState.CREATED;
this.returnCode = ReturnCode.NOT_SET;
this.returnCode = null;
this.failStackTrace = null;
this.logRedirectionStrategy = logRedirectionStrategy;
}
@ -84,11 +151,6 @@ public abstract class AbstractSession implements Session {
return logCallback;
}
@Override
public StatisticsCallback getStatisticsCallback() {
return statisticsCallback;
}
@Override
public long getSessionId() {
return sessionId;
@ -117,7 +179,7 @@ public abstract class AbstractSession implements Session {
return (endTime.getTime() - startTime.getTime());
}
return -1;
return 0;
}
@Override
@ -130,77 +192,84 @@ public abstract class AbstractSession implements Session {
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
public Queue<Log> getAllLogs(final int waitTimeout) {
waitForCallbackMessagesInTransmit(waitTimeout);
public List<Log> getAllLogs(final int waitTimeout) {
waitForAsynchronousMessagesInTransmit(waitTimeout);
if (thereAreCallbackMessagesInTransmit()) {
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));
if (thereAreAsynchronousMessagesInTransmit()) {
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
public Queue<Log> getAllLogs() {
return getAllLogs(DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT);
public List<Log> getAllLogs() {
return getAllLogs(DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
}
@Override
public Queue<Log> getLogs() {
return logs;
public List<Log> getLogs() {
synchronized (logsLock) {
return new LinkedList<>(logs);
}
}
@Override
public String getAllLogsAsString(final int waitTimeout) {
waitForCallbackMessagesInTransmit(waitTimeout);
waitForAsynchronousMessagesInTransmit(waitTimeout);
if (thereAreCallbackMessagesInTransmit()) {
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));
if (thereAreAsynchronousMessagesInTransmit()) {
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();
}
/**
* 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
public String getAllLogsAsString() {
return getAllLogsAsString(DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT);
return getAllLogsAsString(DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
}
@Override
public String getLogsAsString() {
final StringBuilder concatenatedString = new StringBuilder();
for (Log log : logs) {
concatenatedString.append(log.getMessage());
synchronized (logsLock) {
for (Log log : logs) {
concatenatedString.append(log.getMessage());
}
}
return concatenatedString.toString();
}
@Override
public String getOutput() {
return getAllLogsAsString();
}
@Override
public SessionState getState() {
return state;
}
@Override
public int getReturnCode() {
public ReturnCode getReturnCode() {
return returnCode;
}
@ -215,13 +284,15 @@ public abstract class AbstractSession implements Session {
}
@Override
public boolean thereAreCallbackMessagesInTransmit() {
public boolean thereAreAsynchronousMessagesInTransmit() {
return (FFmpegKitConfig.messagesInTransmit(sessionId) != 0);
}
@Override
public void addLog(final Log log) {
this.logs.add(log);
synchronized (logsLock) {
this.logs.add(log);
}
}
@Override
@ -230,35 +301,67 @@ public abstract class AbstractSession implements Session {
}
@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;
}
@Override
public void startRunning() {
/**
* Starts running the session.
*/
void startRunning() {
this.state = SessionState.RUNNING;
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.state = SessionState.COMPLETED;
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.state = SessionState.FAILED;
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() {
FFmpegKitConfig.ffmpegExecute(ffmpegSession);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getGlobalExecuteCallbackFunction();
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback();
if (globalExecuteCallbackFunction != null) {
globalExecuteCallbackFunction.apply(ffmpegSession);
}

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

@ -28,7 +28,7 @@ public class AsyncGetMediaInformationTask implements Runnable {
private final Integer waitTimeout;
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) {
@ -41,7 +41,7 @@ public class AsyncGetMediaInformationTask implements Runnable {
public void run() {
FFmpegKitConfig.getMediaInformationExecute(mediaInformationSession, waitTimeout);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getGlobalExecuteCallbackFunction();
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback();
if (globalExecuteCallbackFunction != null) {
globalExecuteCallbackFunction.apply(mediaInformationSession);
}

@ -34,17 +34,17 @@ import static android.content.Context.CAMERA_SERVICE;
import static com.arthenica.ffmpegkit.FFmpegKitConfig.TAG;
/**
* <p>Helper class to find camera devices supported.
* <p>Note that camera devices can only be detected on Android API Level 24+. On older API levels
* an empty list will be returned.
* <p>Helper class to detect camera devices that can be used in
* <code>FFmpeg</code>/<code>FFprobe</code> commands.
*/
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
* @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) {
final List<String> detectedCameraIdList = new ArrayList<>();

@ -20,15 +20,31 @@
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
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);

@ -21,18 +21,19 @@ package com.arthenica.ffmpegkit;
import java.util.ArrayList;
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
* asynchronous {@link #executeAsync(String, ExecuteCallback)} methods to execute FFmpeg commands.
* <p>Main class to run <code>FFmpeg</code> commands. Supports executing commands both
* synchronously and asynchronously.
* <pre>
* FFmpegSession session = FFmpeg.execute("-i file1.mp4 -c:v libxvid file1.avi");
* Log.i(Config.TAG, String.format("Command execution completed with %d.", session.getReturnCode());
* FFmpegSession session = FFmpegKit.execute("-i file1.mp4 -c:v libxvid file1.avi");
*
* FFmpegSession asyncSession = FFmpegKit.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", executeCallback);
* </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre>
* FFmpegSession session = FFmpeg.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", executeCallback);
* Log.i(Config.TAG, String.format("Asynchronous session %d started.", session.getSessionId()));
* FFmpegSession asyncSession = FFmpegKit.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", executeCallback, logCallback, statisticsCallback);
* </pre>
*/
public class FFmpegKit {
@ -52,10 +53,10 @@ public class FFmpegKit {
* <p>Synchronously executes FFmpeg with arguments provided.
*
* @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) {
final FFmpegSession session = new FFmpegSession(arguments, null, null, null);
final FFmpegSession session = new FFmpegSession(arguments);
FFmpegKitConfig.ffmpegExecute(session);
@ -66,12 +67,12 @@ public class FFmpegKit {
* <p>Asynchronously executes FFmpeg with arguments provided.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be notified when the execution is completed
* @return ffmpeg session created for this execution
* @param executeCallback callback that will be called when the execution is completed
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, null, null);
final FFmpegSession session = new FFmpegSession(arguments, executeCallback);
FFmpegKitConfig.asyncFFmpegExecute(session);
@ -82,10 +83,10 @@ public class FFmpegKit {
* <p>Asynchronously executes FFmpeg with arguments provided.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive logs
* @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,
final ExecuteCallback executeCallback,
@ -102,17 +103,16 @@ public class FFmpegKit {
* <p>Asynchronously executes FFmpeg with arguments provided.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed
* @param executor executor that will be used to run this asynchronous operation
* @return ffmpeg session created for this execution
* @param executeCallback callback that will be called when the execution is completed
* @param executorService executor service that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback,
final Executor executor) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, null, null);
final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback);
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(session);
executor.execute(asyncFFmpegExecuteTask);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
return session;
}
@ -121,32 +121,31 @@ public class FFmpegKit {
* <p>Asynchronously executes FFmpeg with arguments provided.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics
* @param executor executor that will be used to run this asynchronous operation
* @return ffmpeg session created for this execution
* @param executorService executor service that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final Executor executor) {
final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, logCallback, statisticsCallback);
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(session);
executor.execute(asyncFFmpegExecuteTask);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
return session;
}
/**
* <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.
*
* @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) {
return execute(parseArguments(command));
@ -154,12 +153,12 @@ public class FFmpegKit {
/**
* <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.
*
* @param command FFmpeg command
* @param executeCallback callback that will be notified when execution is completed
* @return ffmpeg session created for this execution
* @param executeCallback callback that will be called when the execution is completed
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback) {
@ -168,14 +167,14 @@ public class FFmpegKit {
/**
* <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.
*
* @param command FFmpeg command
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive logs
* @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,
final ExecuteCallback executeCallback,
@ -186,52 +185,50 @@ public class FFmpegKit {
/**
* <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.
*
* @param command FFmpeg command
* @param executeCallback callback that will be notified when execution is completed
* @param executor executor that will be used to run this asynchronous operation
* @return ffmpeg session created for this execution
* @param executeCallback callback that will be called when the execution is completed
* @param executorService executor service that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback,
final Executor executor) {
final FFmpegSession session = new FFmpegSession(parseArguments(command), executeCallback, null, null);
final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(parseArguments(command), executeCallback);
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(session);
executor.execute(asyncFFmpegExecuteTask);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
return session;
}
/**
* <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.
*
* @param command FFmpeg command
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics
* @param executor executor that will be used to run this asynchronous operation
* @return ffmpeg session created for this execution
* @param executorService executor service that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final Executor executor) {
final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(parseArguments(command), executeCallback, logCallback, statisticsCallback);
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(session);
executor.execute(asyncFFmpegExecuteTask);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
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.
*/
@ -240,13 +237,13 @@ public class FFmpegKit {
/*
* ZERO (0) IS A SPECIAL SESSION ID
* WHEN IT IS PASSED TO THIS METHOD, A SIGINT IS GENERATED WHICH CANCELS ALL ONGOING
* EXECUTIONS
* SESSIONS
*/
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.
*
@ -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
*/
@ -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
* @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
* @return string containing all arguments
* @return concatenated string containing all arguments
*/
static String argumentsToString(final String[] arguments) {
if (arguments == null) {

@ -40,7 +40,6 @@ import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@ -48,58 +47,43 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
/**
* <p>This class is used to configure FFmpegKit library and tools coming with it.
*
* <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.
* <p>Configuration class of <code>FFmpegKit</code> library. Allows customizing the global library
* options. Provides helper methods to support additional resources.
*/
public class FFmpegKitConfig {
/**
* 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.
*/
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.
*/
private static final AtomicLong pipeIndexGenerator;
/* SESSION HISTORY VARIABLES */
private static Level activeLogLevel;
/* Session history variables */
private static int sessionHistorySize;
private static final Map<Long, Session> sessionHistoryMap;
private static final Queue<Session> sessionHistoryQueue;
private static final List<Session> sessionHistoryList;
private static final Object sessionHistoryLock;
/**
* Executor service for async executions.
*/
private static int asyncConcurrencyLimit;
private static ExecutorService asyncExecutorService;
/* Global callbacks */
private static LogCallback globalLogCallbackFunction;
private static StatisticsCallback globalStatisticsCallbackFunction;
private static ExecuteCallback globalExecuteCallbackFunction;
private static Level activeLogLevel;
private static int asyncConcurrencyLimit;
private static final SparseArray<ParcelFileDescriptor> pfdMap;
private static LogRedirectionStrategy logRedirectionStrategy;
private static LogRedirectionStrategy globalLogRedirectionStrategy;
static {
@ -107,92 +91,44 @@ public class FFmpegKitConfig {
android.util.Log.i(FFmpegKitConfig.TAG, "Loading ffmpeg-kit.");
boolean nativeFFmpegLoaded = false;
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");
}
}
final boolean nativeFFmpegTriedAndFailed = NativeLoader.loadFFmpeg();
/* ALL FFMPEG-KIT LIBRARIES LOADED AT STARTUP */
Abi.class.getName();
FFmpegKit.class.getName();
FFprobeKit.class.getName();
boolean nativeFFmpegKitLoaded = false;
if (!nativeFFmpegTriedAndFailed && AbiDetect.ARM_V7A.equals(AbiDetect.getNativeAbi())) {
try {
/*
* THE TRY TO LOAD ARM-V7A-NEON FIRST. IF NOT LOAD DEFAULT ARM-V7A
*/
NativeLoader.loadFFmpegKit(nativeFFmpegTriedAndFailed);
System.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)));
}
}
android.util.Log.i(FFmpegKitConfig.TAG, String.format("Loaded ffmpeg-kit-%s-%s-%s-%s.", NativeLoader.loadPackageName(), NativeLoader.loadAbi(), NativeLoader.loadVersion(), NativeLoader.loadBuildDate()));
if (!nativeFFmpegKitLoaded) {
System.loadLibrary("ffmpegkit");
}
pipeIndexGenerator = new AtomicLong(1);
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;
asyncExecutorService = Executors.newFixedThreadPool(asyncConcurrencyLimit);
/* NATIVE LOG LEVEL IS RECEIVED ONLY ON STARTUP */
activeLogLevel = Level.from(getNativeLogLevel());
sessionHistorySize = 10;
sessionHistoryMap = Collections.synchronizedMap(new LinkedHashMap<Long, Session>() {
sessionHistoryMap = new LinkedHashMap<Long, Session>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Long, Session> eldest) {
return (this.size() > sessionHistorySize);
}
});
sessionHistoryQueue = new LinkedList<>();
};
sessionHistoryList = new LinkedList<>();
sessionHistoryLock = new Object();
globalLogCallbackFunction = null;
globalStatisticsCallbackFunction = null;
globalExecuteCallbackFunction = null;
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>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>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
* 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>When redirection is enabled FFmpeg/FFprobe logs are redirected to Logcat and sessions
* collect log and statistics entries for the executions. It is possible to define global or
* session specific log/statistics callbacks as well.
*
* <p>Note that redirection is enabled by default. If you do not want to use its functionality
* please use {@link #disableRedirection()} to disable it.
*/
@ -219,17 +153,22 @@ public class FFmpegKitConfig {
/**
* <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() {
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 logMessage redirected log message
* @param logMessage redirected log message data
*/
private static void log(final long sessionId, final int levelValue, final byte[] logMessage) {
final Level level = Level.from(levelValue);
@ -237,7 +176,7 @@ public class FFmpegKitConfig {
final Log log = new Log(sessionId, level, text);
boolean globalCallbackDefined = false;
boolean sessionCallbackDefined = false;
LogRedirectionStrategy activeLogRedirectionStrategy = FFmpegKitConfig.logRedirectionStrategy;
LogRedirectionStrategy activeLogRedirectionStrategy = globalLogRedirectionStrategy;
// AV_LOG_STDERR logs are always redirected
if ((activeLogLevel == Level.AV_LOG_QUIET && levelValue != Level.AV_LOG_STDERR.getValue()) || levelValue > activeLogLevel.getValue()) {
@ -254,7 +193,7 @@ public class FFmpegKitConfig {
sessionCallbackDefined = true;
try {
// NOTIFY SESSION CALLBACK IF DEFINED
// NOTIFY SESSION CALLBACK DEFINED
session.getLogCallback().apply(log);
} catch (final Exception 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;
try {
// NOTIFY GLOBAL CALLBACK IF DEFINED
// NOTIFY GLOBAL CALLBACK DEFINED
globalLogCallbackFunction.apply(log);
} catch (final Exception 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;
}
}
case ALWAYS_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 videoFrameNumber last processed frame number for videos
* @param videoFps frames processed per second for videos
* @param videoFrameNumber frame number for videos
* @param videoFps frames per second value for videos
* @param videoQuality quality of the video stream
* @param size size in bytes
* @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 Session session = getSession(sessionId);
if (session != null) {
session.addStatistics(statistics);
if (session != null && session.isFFmpeg()) {
FFmpegSession ffmpegSession = (FFmpegSession) session;
ffmpegSession.addStatistics(statistics);
if (session.getStatisticsCallback() != null) {
if (ffmpegSession.getStatisticsCallback() != null) {
try {
// NOTIFY SESSION CALLBACK IF DEFINED
session.getStatisticsCallback().apply(statistics);
ffmpegSession.getStatisticsCallback().apply(statistics);
} catch (final Exception 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.
*
* @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
*/
public static int setFontconfigConfigurationPath(final String path) {
@ -402,10 +330,11 @@ public class FFmpegKitConfig {
* 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 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 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
* friendly names
*/
@ -418,10 +347,11 @@ public class FFmpegKitConfig {
* 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 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 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
* 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.
*
@ -563,7 +475,7 @@ public class FFmpegKitConfig {
/**
* <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) {
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
* list.
*
* @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) {
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() {
return getNativeFFmpegVersion();
@ -632,41 +545,8 @@ public class FFmpegKitConfig {
}
/**
* <p>Returns the return code of the last completed execution.
*
* @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.
* <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.
*
* @param logPriority one of {@link android.util.Log#VERBOSE},
* {@link android.util.Log#DEBUG},
@ -674,26 +554,27 @@ public class FFmpegKitConfig {
* {@link android.util.Log#WARN},
* {@link android.util.Log#ERROR},
* {@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;
String buffer = getLastCommandOutput();
String remainingString = string;
do {
if (buffer.length() <= LOGGER_ENTRY_MAX_LEN) {
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, buffer);
buffer = "";
if (remainingString.length() <= LOGGER_ENTRY_MAX_LEN) {
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, remainingString);
remainingString = "";
} 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) {
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, buffer.substring(0, LOGGER_ENTRY_MAX_LEN));
buffer = buffer.substring(LOGGER_ENTRY_MAX_LEN);
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, remainingString.substring(0, LOGGER_ENTRY_MAX_LEN));
remainingString = remainingString.substring(LOGGER_ENTRY_MAX_LEN);
} else {
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, buffer.substring(0, index));
buffer = buffer.substring(index);
android.util.Log.println(logPriority, FFmpegKitConfig.TAG, remainingString.substring(0, 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) {
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
*/
static void ffmpegExecute(final FFmpegSession ffmpegSession) {
public static void ffmpegExecute(final FFmpegSession ffmpegSession) {
addSession(ffmpegSession);
ffmpegSession.startRunning();
try {
final int returnCode = nativeFFmpegExecute(ffmpegSession.getSessionId(), ffmpegSession.getArguments());
ffmpegSession.complete(returnCode);
ffmpegSession.complete(new ReturnCode(returnCode));
} catch (final Exception e) {
ffmpegSession.fail(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
*/
static void ffprobeExecute(final FFprobeSession ffprobeSession) {
public static void ffprobeExecute(final FFprobeSession ffprobeSession) {
addSession(ffprobeSession);
ffprobeSession.startRunning();
try {
final int returnCode = nativeFFprobeExecute(ffprobeSession.getSessionId(), ffprobeSession.getArguments());
ffprobeSession.complete(returnCode);
ffprobeSession.complete(new ReturnCode(returnCode));
} catch (final Exception e) {
ffprobeSession.fail(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 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);
mediaInformationSession.startRunning();
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);
if (returnCode == ReturnCode.SUCCESS) {
MediaInformation mediaInformation = MediaInformationParser.fromWithError(mediaInformationSession.getAllLogsAsString(waitTimeout));
if (returnCode.isSuccess()) {
MediaInformation mediaInformation = MediaInformationJsonParser.fromWithError(mediaInformationSession.getAllLogsAsString(waitTimeout));
mediaInformationSession.setMediaInformation(mediaInformation);
}
} 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
*/
static void asyncFFmpegExecute(final FFmpegSession ffmpegSession) {
public static void asyncFFmpegExecute(final FFmpegSession ffmpegSession) {
AsyncFFmpegExecuteTask asyncFFmpegExecuteTask = new AsyncFFmpegExecuteTask(ffmpegSession);
Future<?> future = asyncExecutorService.submit(asyncFFmpegExecuteTask);
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
*/
static void asyncFFprobeExecute(final FFprobeSession ffprobeSession) {
public static void asyncFFprobeExecute(final FFprobeSession ffprobeSession) {
AsyncFFprobeExecuteTask asyncFFmpegExecuteTask = new AsyncFFprobeExecuteTask(ffprobeSession);
Future<?> future = asyncExecutorService.submit(asyncFFmpegExecuteTask);
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.
*
* @param mediaInformationSession media information session which includes command options/arguments
* @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);
Future<?> future = asyncExecutorService.submit(asyncGetMediaInformationTask);
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() {
return asyncConcurrencyLimit;
}
/**
* Sets the maximum number of async operations that will be executed in parallel. If more
* operations are submitted those will be queued.
* Sets the maximum number of async sessions that will be executed in parallel. If more
* sessions are submitted those will be queued.
*
* @param asyncConcurrencyLimit new async concurrency limit
*/
@ -843,17 +763,17 @@ public class FFmpegKitConfig {
/**
* <p>Sets a global callback function to redirect FFmpeg/FFprobe logs.
*
* @param newLogCallback new log callback function or null to disable a previously defined
* callback
* @param logCallback log callback function or null to disable a previously defined
* callback
*/
public static void enableLogCallback(final LogCallback newLogCallback) {
globalLogCallbackFunction = newLogCallback;
public static void enableLogCallback(final LogCallback logCallback) {
globalLogCallbackFunction = logCallback;
}
/**
* <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
*/
public static void enableStatisticsCallback(final StatisticsCallback statisticsCallback) {
@ -863,7 +783,7 @@ public class FFmpegKitConfig {
/**
* <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
*/
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
*/
static ExecuteCallback getGlobalExecuteCallbackFunction() {
static ExecuteCallback getExecuteCallback() {
return globalExecuteCallbackFunction;
}
@ -902,7 +822,7 @@ public class FFmpegKitConfig {
/**
* <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.
*
@ -944,7 +864,7 @@ public class FFmpegKitConfig {
/**
* <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.
*
@ -956,7 +876,7 @@ public class FFmpegKitConfig {
/**
* <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.
*
@ -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
*/
@ -995,7 +915,7 @@ public class FFmpegKitConfig {
/**
* 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) {
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
*/
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) {
synchronized (sessionHistoryLock) {
sessionHistoryMap.put(session.getSessionId(), session);
sessionHistoryQueue.offer(session);
if (sessionHistoryQueue.size() > sessionHistorySize) {
final Session oldestElement = sessionHistoryQueue.poll();
if (oldestElement != null) {
sessionHistoryMap.remove(oldestElement.getSessionId());
sessionHistoryList.add(session);
if (sessionHistoryList.size() > sessionHistorySize) {
try {
sessionHistoryList.remove(0);
} catch (final IndexOutOfBoundsException ignored) {
}
}
}
}
/**
* 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
* @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() {
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() {
synchronized (sessionHistoryLock) {
return new LinkedList<>(sessionHistoryQueue);
return new LinkedList<>(sessionHistoryList);
}
}
@ -1070,7 +1013,7 @@ public class FFmpegKitConfig {
final LinkedList<FFmpegSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) {
for (Session session : sessionHistoryQueue) {
for (Session session : sessionHistoryList) {
if (session.isFFmpeg()) {
list.add((FFmpegSession) session);
}
@ -1089,7 +1032,7 @@ public class FFmpegKitConfig {
final LinkedList<FFprobeSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) {
for (Session session : sessionHistoryQueue) {
for (Session session : sessionHistoryList) {
if (session.isFFprobe()) {
list.add((FFprobeSession) session);
}
@ -1108,7 +1051,7 @@ public class FFmpegKitConfig {
final LinkedList<Session> list = new LinkedList<>();
synchronized (sessionHistoryLock) {
for (Session session : sessionHistoryQueue) {
for (Session session : sessionHistoryList) {
if (session.getState() == state) {
list.add(session);
}
@ -1124,25 +1067,25 @@ public class FFmpegKitConfig {
* @return log redirection strategy
*/
public static LogRedirectionStrategy getLogRedirectionStrategy() {
return logRedirectionStrategy;
return globalLogRedirectionStrategy;
}
/**
* <p>Sets the log redirection strategy
*
* @param logRedirectionStrategy new log redirection strategy
* @param logRedirectionStrategy log redirection strategy
*/
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();
/**
* <p>Disables native redirection
* <p>Disables redirection natively.
*/
private static native void disableNativeRedirection();
@ -1151,7 +1094,7 @@ public class FFmpegKitConfig {
*
* @return log level
*/
private static native int getNativeLogLevel();
static native int getNativeLogLevel();
/**
* Sets native log level
@ -1185,14 +1128,6 @@ public class FFmpegKitConfig {
*/
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.
*
@ -1205,14 +1140,22 @@ public class FFmpegKitConfig {
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.
*
* @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
*/
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.
@ -1241,7 +1184,8 @@ public class FFmpegKitConfig {
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
*/

@ -19,48 +19,160 @@
package com.arthenica.ffmpegkit;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.LinkedList;
import java.util.List;
/**
* <p>An FFmpeg execute session.
* <p>An FFmpeg 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,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
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) {
waitForCallbackMessagesInTransmit(waitTimeout);
/**
* Returns the session specific statistics callback function.
*
* @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();
}
@Override
public Queue<Statistics> getAllStatistics() {
return getAllStatistics(DEFAULT_TIMEOUT_FOR_CALLBACK_MESSAGES_IN_TRANSMIT);
/**
* Returns all statistics 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 statistics entries generated for this session
*/
public List<Statistics> getAllStatistics() {
return getAllStatistics(DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
}
@Override
public Queue<Statistics> getStatistics() {
return statistics;
/**
* 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
*/
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) {
this.statistics.add(statistics);
synchronized (statisticsLock) {
this.statistics.add(statistics);
}
}
@Override

@ -20,19 +20,23 @@
package com.arthenica.ffmpegkit;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
/**
* <p>Main class for FFprobe operations.
* <p>Supports running FFprobe commands using {@link #execute(String...)} method.
* <p>Main class to run <code>FFprobe</code> commands. Supports executing commands both
* synchronously and asynchronously.
* <pre>
* FFprobeSession session = FFprobe.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 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", 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>
* <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>
* MediaInformationSession session = FFprobe.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()));
* MediaInformationSession session = FFprobeKit.getMediaInformation("file1.mp4");
* </pre>
*/
public class FFprobeKit {
@ -52,10 +56,10 @@ public class FFprobeKit {
* <p>Synchronously executes FFprobe with arguments provided.
*
* @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) {
final FFprobeSession session = new FFprobeSession(arguments, null, null, null);
final FFprobeSession session = new FFprobeSession(arguments);
FFmpegKitConfig.ffprobeExecute(session);
@ -63,41 +67,33 @@ public class FFprobeKit {
}
/**
* <p>Synchronously 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
* @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.
* <p>Asynchronously executes FFprobe with arguments provided.
*
* @param command FFprobe command
* @param executeCallback callback that will be notified when the execution is completed
* @return ffprobe session created for this execution
* @param arguments FFprobe command options/arguments as string array
* @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,
public static FFprobeSession executeAsync(final String[] arguments,
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.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when the execution is completed
* @return ffprobe session created for this execution
* @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[] arguments,
final ExecuteCallback executeCallback) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, null, null);
final ExecuteCallback executeCallback,
final LogCallback logCallback) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session);
@ -105,147 +101,187 @@ public class FFprobeKit {
}
/**
* <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.
* <p>Asynchronously executes FFprobe with arguments provided.
*
* @param command FFprobe command
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param statisticsCallback callback that will receive statistics
* @return ffprobe session created for this execution
* @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param executorService executor service that will be used to run this asynchronous operation
* @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 LogCallback logCallback,
final StatisticsCallback statisticsCallback) {
return executeAsync(FFmpegKit.parseArguments(command), executeCallback, logCallback, statisticsCallback);
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
return session;
}
/**
* <p>Asynchronously executes FFprobe with arguments provided.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param statisticsCallback callback that will receive statistics
* @return ffprobe session created for this execution
* @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when 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 FFprobeSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback, statisticsCallback);
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
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 executeCallback callback that will be notified when the execution is completed
* @param executor executor that will be used to run this asynchronous operation
* @return ffprobe session created for this execution
* @param command FFprobe command
* @return FFprobe session created for this execution
*/
public static FFprobeSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback,
final Executor executor) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, null, null);
public static FFprobeSession execute(final String command) {
return execute(FFmpegKit.parseArguments(command));
}
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 executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param statisticsCallback callback that will receive statistics
* @param executor executor that will be used to run this asynchronous operation
* @return ffprobe session created for this execution
* @param command FFprobe command
* @param executeCallback callback that will be called when the execution is completed
* @param executorService executor service 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 LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final Executor executor) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback, statisticsCallback);
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(FFmpegKit.parseArguments(command), executeCallback);
AsyncFFprobeExecuteTask asyncFFprobeExecuteTask = new AsyncFFprobeExecuteTask(session);
executor.execute(asyncFFprobeExecuteTask);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
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() {
return FFmpegKitConfig.getFFprobeSessions();
public static FFprobeSession executeAsync(final String command,
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
* @return media information session created for this execution
*/
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 waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution
*/
public static MediaInformationSession getMediaInformation(final String path, final Integer waitTimeout) {
return getMediaInformationFromCommandArguments(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, null, null, null, waitTimeout);
public static MediaInformationSession getMediaInformation(final String path,
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 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
*/
public static MediaInformationSession getMediaInformationAsync(final String path,
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;
}
/**
* <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 executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param statisticsCallback callback that will receive statistics
* @param waitTimeout max time to wait until media information is transmitted
* @param path path or uri of a media file
* @param executeCallback callback that will be notified when execution is completed
* @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
*/
public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
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, statisticsCallback);
final int waitTimeout) {
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, logCallback);
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 executeCallback callback that will be notified when the execution is completed
* @param executor executor that will be used to run this asynchronous operation
* @param executeCallback callback that will be called when the execution is completed
* @param executorService executor service that will be used to run this asynchronous operation
* @return media information session created for this execution
*/
public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback,
final Executor executor) {
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, null, null);
final ExecutorService executorService) {
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);
executor.execute(asyncGetMediaInformationTask);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, executorService, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
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 executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param statisticsCallback callback that will receive statistics
* @param executor executor that will be used to run this asynchronous operation
* @param waitTimeout max time to wait until media information is transmitted
* @param path path or uri of a media file
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive logs
* @param executorService executor service 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
*/
public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final Executor executor,
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, statisticsCallback);
final ExecutorService executorService,
final int waitTimeout) {
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback, logCallback);
AsyncGetMediaInformationTask asyncGetMediaInformationTask = new AsyncGetMediaInformationTask(session, waitTimeout);
executor.execute(asyncGetMediaInformationTask);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, executorService, waitTimeout);
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
*/
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 executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive log entries
* @param statisticsCallback callback that will receive statistics
* @param waitTimeout max time to wait until media information is transmitted
* @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 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
*/
public static MediaInformationSession getMediaInformationFromCommand(final String command,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final Integer waitTimeout) {
return getMediaInformationFromCommandArguments(FFmpegKit.parseArguments(command), executeCallback, logCallback, statisticsCallback, waitTimeout);
public static MediaInformationSession getMediaInformationFromCommandAsync(final String command,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final int waitTimeout) {
return getMediaInformationFromCommandArgumentsAsync(FFmpegKit.parseArguments(command), executeCallback, logCallback, waitTimeout);
}
private static MediaInformationSession getMediaInformationFromCommandArguments(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final Integer waitTimeout) {
final MediaInformationSession session = new MediaInformationSession(arguments, executeCallback, logCallback, statisticsCallback);
/**
* Extracts media information using the command arguments provided asynchronously.
*
* @param arguments FFprobe command arguments that print media information for a file in JSON format
* @param executeCallback callback that will be notified when execution is completed
* @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);
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;
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 FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback) {
this(arguments, executeCallback, logCallback, statisticsCallback, FFmpegKitConfig.getLogRedirectionStrategy());
}
FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
super(arguments, executeCallback, logCallback, statisticsCallback, logRedirectionStrategy);
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
*/
public FFprobeSession(final String[] arguments) {
this(arguments, null);
}
@Override
public Queue<Statistics> getAllStatistics(final int waitTimeout) {
return new LinkedList<>();
/**
* Builds a new FFprobe session.
*
* @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() {
return new LinkedList<>();
}
@Override
public Queue<Statistics> getStatistics() {
return new LinkedList<>();
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param logCallback session specific log callback function
*/
FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback) {
this(arguments, executeCallback, logCallback, FFmpegKitConfig.getLogRedirectionStrategy());
}
@Override
public void addStatistics(final Statistics statistics) {
/*
* ffprobe does not support statistics.
* So, this method should never have been called.
*/
android.util.Log.w(FFmpegKitConfig.TAG, MessageFormat.format("FFprobe execute session {0} received statistics.", sessionId));
/**
* Builds a new FFprobe 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
*/
FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
super(arguments, executeCallback, logCallback, logRedirectionStrategy);
}
@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
* 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),
@ -82,7 +82,7 @@ public enum Level {
private final int value;
/**
* <p>Returns enumeration defined by value.
* <p>Returns the enumeration defined by provided value.
*
* @param value level value
* @return enumeration defined by value
@ -121,7 +121,7 @@ public enum Level {
}
/**
* Creates new enum.
* Creates a new enum.
*
* @param value level value
*/

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

@ -20,7 +20,7 @@
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
public interface LogCallback {

@ -30,16 +30,16 @@ import org.json.JSONObject;
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
* 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
*/
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
* @return created {@link MediaInformation} instance

@ -20,24 +20,62 @@
package com.arthenica.ffmpegkit;
/**
* <p>A custom FFprobe execute session, which produces a <code>MediaInformation</code> object
* using the output of the execution.
* <p>A custom FFprobe session, which produces a <code>MediaInformation</code> object using the
* FFprobe output.
*/
public class MediaInformationSession extends FFprobeSession implements Session {
/**
* Media information extracted in the session.
*/
private MediaInformation mediaInformation;
public MediaInformationSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback) {
super(arguments, executeCallback, logCallback, statisticsCallback, LogRedirectionStrategy.NEVER_PRINT_LOGS);
/**
* Creates a new media information session.
*
* @param arguments command arguments
*/
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() {
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;
}

@ -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.
*
* @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.
* Returns the 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 boolean speex = externalLibraryList.contains("speex");
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 static int NOT_SET = -999;
public static int SUCCESS = 0;
public static int CANCEL = 255;
public static boolean isSuccess(final int returnCode) {
return (returnCode == SUCCESS);
private final int value;
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) {
return (returnCode != NOT_SET) && (returnCode != SUCCESS) && (returnCode != CANCEL);
public boolean isCancel() {
return (value == CANCEL);
}
public static boolean isCancel(final int returnCode) {
return (returnCode == CANCEL);
@Override
public String toString() {
return String.valueOf(value);
}
}

@ -20,80 +20,213 @@
package com.arthenica.ffmpegkit;
import java.util.Date;
import java.util.Queue;
import java.util.List;
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 {
/**
* Returns the session specific execute callback function.
*
* @return session specific execute callback function
*/
ExecuteCallback getExecuteCallback();
/**
* Returns the session specific log callback function.
*
* @return session specific log callback function
*/
LogCallback getLogCallback();
StatisticsCallback getStatisticsCallback();
/**
* Returns the session identifier.
*
* @return session identifier
*/
long getSessionId();
/**
* Returns session create time.
*
* @return session create time
*/
Date getCreateTime();
/**
* Returns session start time.
*
* @return session start time
*/
Date getStartTime();
/**
* Returns session end time.
*
* @return session end time
*/
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();
/**
* Returns command arguments as an array.
*
* @return command arguments as an array
*/
String[] getArguments();
/**
* Returns command arguments as a concatenated string.
*
* @return command arguments as a concatenated string
*/
String getCommand();
Queue<Log> getAllLogs(final int waitTimeout);
Queue<Log> getAllLogs();
Queue<Log> 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 the given timeout.
*
* @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);
/**
* 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();
/**
* 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();
Queue<Statistics> getAllStatistics(final int waitTimeout);
Queue<Statistics> getAllStatistics();
Queue<Statistics> getStatistics();
/**
* Returns the log output generated while running the session.
*
* @return log output generated
*/
String getOutput();
/**
* Returns the state of the session.
*
* @return state of the session
*/
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();
/**
* Returns session specific log redirection strategy.
*
* @return session specific log redirection strategy
*/
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 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();
void setFuture(final Future<?> future);
void startRunning();
void complete(final int returnCode);
void fail(final Exception exception);
/**
* Returns whether it is an <code>FFmpeg</code> session or not.
*
* @return true if it is an <code>FFmpeg</code> session, false otherwise
*/
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();
/**
* Cancels running the session.
*/
void cancel();
}

@ -32,17 +32,6 @@ public class Statistics {
private double bitrate;
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) {
this.sessionId = sessionId;
this.videoFrameNumber = videoFrameNumber;

@ -20,7 +20,7 @@
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
public interface StatisticsCallback {

@ -27,24 +27,24 @@ import org.json.JSONObject;
public class StreamInformation {
/* COMMON KEYS */
private static final String KEY_INDEX = "index";
private static final String KEY_TYPE = "codec_type";
private static final String KEY_CODEC = "codec_name";
private static final String KEY_CODEC_LONG = "codec_long_name";
private static final String KEY_FORMAT = "pix_fmt";
private static final String KEY_WIDTH = "width";
private static final String KEY_HEIGHT = "height";
private static final String KEY_BIT_RATE = "bit_rate";
private static final String KEY_SAMPLE_RATE = "sample_rate";
private static final String KEY_SAMPLE_FORMAT = "sample_fmt";
private static final String KEY_CHANNEL_LAYOUT = "channel_layout";
private static final String KEY_SAMPLE_ASPECT_RATIO = "sample_aspect_ratio";
private static final String KEY_DISPLAY_ASPECT_RATIO = "display_aspect_ratio";
private static final String KEY_AVERAGE_FRAME_RATE = "avg_frame_rate";
private static final String KEY_REAL_FRAME_RATE = "r_frame_rate";
private static final String KEY_TIME_BASE = "time_base";
private static final String KEY_CODEC_TIME_BASE = "codec_time_base";
private static final String KEY_TAGS = "tags";
public static final String KEY_INDEX = "index";
public static final String KEY_TYPE = "codec_type";
public static final String KEY_CODEC = "codec_name";
public static final String KEY_CODEC_LONG = "codec_long_name";
public static final String KEY_FORMAT = "pix_fmt";
public static final String KEY_WIDTH = "width";
public static final String KEY_HEIGHT = "height";
public static final String KEY_BIT_RATE = "bit_rate";
public static final String KEY_SAMPLE_RATE = "sample_rate";
public static final String KEY_SAMPLE_FORMAT = "sample_fmt";
public static final String KEY_CHANNEL_LAYOUT = "channel_layout";
public static final String KEY_SAMPLE_ASPECT_RATIO = "sample_aspect_ratio";
public static final String KEY_DISPLAY_ASPECT_RATIO = "display_aspect_ratio";
public static final String KEY_AVERAGE_FRAME_RATE = "avg_frame_rate";
public static final String KEY_REAL_FRAME_RATE = "r_frame_rate";
public static final String KEY_TIME_BASE = "time_base";
public static final String KEY_CODEC_TIME_BASE = "codec_time_base";
public static final String KEY_TAGS = "tags";
/**
* 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
public void mediaInformationMp3() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_MP3);
MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_MP3);
Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "mp3", "sample.mp3");
@ -463,7 +463,7 @@ public class FFmpegKitTest {
@Test
public void mediaInformationJpg() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_JPG);
MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_JPG);
Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "image2", "sample.jpg");
@ -475,7 +475,7 @@ public class FFmpegKitTest {
@Test
public void mediaInformationGif() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_GIF);
MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_GIF);
Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "gif", "sample.gif");
@ -487,7 +487,7 @@ public class FFmpegKitTest {
@Test
public void mediaInformationMp4() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_MP4);
MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_MP4);
Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "mov,mp4,m4a,3gp,3g2,mj2", "sample.mp4");
@ -508,7 +508,7 @@ public class FFmpegKitTest {
@Test
public void mediaInformationPng() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_PNG);
MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_PNG);
Assert.assertNotNull(mediaInformation);
assertMediaInput(mediaInformation, "png_pipe", "sample.png");
@ -520,7 +520,7 @@ public class FFmpegKitTest {
@Test
public void mediaInformationOgg() {
MediaInformation mediaInformation = MediaInformationParser.from(MEDIA_INFORMATION_OGG);
MediaInformation mediaInformation = MediaInformationJsonParser.from(MEDIA_INFORMATION_OGG);
Assert.assertNotNull(mediaInformation);
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'
project(':ffmpeg-kit').projectDir = new File('..')
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@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -198,6 +198,8 @@ am__relativize = \
DIST_ARCHIVES = $(distdir).tar.gz
GZIP_ENV = --best
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
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
@ -623,7 +625,7 @@ distcheck: dist
$(DISTCHECK_CONFIGURE_FLAGS) \
--srcdir=../.. --prefix="$$dc_install_base" \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(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.
@ -35,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16'
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.
m4_if([$1], [1.16.2], [],
m4_if([$1], [1.16.3], [],
[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.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
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_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_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_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then

221
apple/config.guess vendored

@ -2,7 +2,7 @@
# Attempt to guess a canonical system name.
# 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
# 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.
#
# 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>.
me=$(echo "$0" | sed -e 's,.*/,,')
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
@ -103,7 +103,7 @@ set_cc_for_build() {
test "$tmp" && return 0
: "${TMPDIR=/tmp}"
# 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) ; } ||
{ 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 ; }
@ -131,14 +131,16 @@ if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown
UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown
UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown
UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "$UNAME_SYSTEM" in
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
cat <<-EOF > "$dummy.c"
@ -147,29 +149,17 @@ Linux|GNU|GNU/*)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#elif defined(__GLIBC__)
LIBC=gnu
#else
#include <stdarg.h>
/* First heuristic to detect musl libc. */
#ifdef __DEFINED_va_list
LIBC=musl
#endif
LIBC=gnu
#endif
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 [ "$LIBC" = unknown ] &&
command -v ldd >/dev/null &&
ldd --version 2>&1 | grep -q ^musl; then
LIBC=musl
fi
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
if [ "$LIBC" = unknown ]; then
LIBC=gnu
# If ldd exists, use it to detect musl libc.
if command -v ldd >/dev/null && \
ldd --version 2>&1 | grep -q ^musl
then
LIBC=musl
fi
;;
esac
@ -189,20 +179,19 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
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 || \
"/usr/sbin/$sysctl" 2>/dev/null || \
echo unknown))
echo unknown)`
case "$UNAME_MACHINE_ARCH" in
aarch64eb) machine=aarch64_be-unknown ;;
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,')
endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p')
arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
machine="${arch}${endian}"-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
earm*)
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
# The OS release
@ -246,7 +235,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
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
# 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-}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
exit ;;
*:LibertyBSD:*:*)
UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//')
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
exit ;;
*:MidnightBSD:*:*)
@ -299,17 +288,17 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}')
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}')
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# 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
"EV4 (21064)")
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 Xn.n version is an unreleased experimental baselevel.
# 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.
exitcode=$?
trap '' 0
@ -381,7 +370,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# 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
else
echo pyramid-pyramid-bsd
@ -394,17 +383,17 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
echo sparc-icl-nx6
exit ;;
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 ;;
esac ;;
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 ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
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 ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux"$UNAME_RELEASE"
@ -423,30 +412,30 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
SUN_ARCH=x86_64
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 ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# 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 ;;
sun4*:SunOS:*:*)
case "$(/usr/bin/arch -k)" in
case "`/usr/bin/arch -k`" in
Series*|S4*)
UNAME_RELEASE=$(uname -v)
UNAME_RELEASE=`uname -v`
;;
esac
# 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 ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos"$UNAME_RELEASE"
exit ;;
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
case "$(/bin/arch)" in
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos"$UNAME_RELEASE"
;;
@ -526,8 +515,8 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') &&
SYSTEM_NAME=$("$dummy" "$dummyarg") &&
dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos"$UNAME_RELEASE"
exit ;;
@ -554,7 +543,7 @@ EOF
exit ;;
AViiON:dgux:*:*)
# 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
then
if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
@ -582,17 +571,17 @@ EOF
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')"
echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
exit ;;
????????: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
exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX '
exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
exit ;;
ia64:AIX:*:*)
if test -x /usr/bin/oslevel ; then
IBM_REV=$(/usr/bin/oslevel)
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi
@ -612,7 +601,7 @@ EOF
exit(0);
}
EOF
if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy")
if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then
echo "$SYSTEM_NAME"
else
@ -625,15 +614,15 @@ EOF
fi
exit ;;
*: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
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if test -x /usr/bin/lslpp ; then
IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi
@ -661,14 +650,14 @@ EOF
echo m68k-hp-bsd4.4
exit ;;
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
9000/31?) HP_ARCH=m68000 ;;
9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if test -x /usr/bin/getconf; then
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_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "$sc_cpu_version" in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
@ -715,7 +704,7 @@ EOF
exit (0);
}
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
fi ;;
esac
@ -743,7 +732,7 @@ EOF
echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
exit ;;
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"
exit ;;
3050*:HI-UX:*:*)
@ -773,7 +762,7 @@ EOF
exit (0);
}
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 unknown-hitachi-hiuxwe2
exit ;;
@ -842,14 +831,14 @@ EOF
echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)
FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/')
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
FUJITSU_REL=$(echo "$UNAME_RELEASE" | 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/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
@ -862,25 +851,25 @@ EOF
echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
exit ;;
arm:FreeBSD:*:*)
UNAME_PROCESSOR=$(uname -p)
UNAME_PROCESSOR=`uname -p`
set_cc_for_build
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
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
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
exit ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=$(/usr/bin/uname -p)
UNAME_PROCESSOR=`/usr/bin/uname -p`
case "$UNAME_PROCESSOR" in
amd64)
UNAME_PROCESSOR=x86_64 ;;
i386)
UNAME_PROCESSOR=i586 ;;
esac
echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
exit ;;
i*:CYGWIN*:*)
echo "$UNAME_MACHINE"-pc-cygwin
@ -916,15 +905,15 @@ EOF
echo x86_64-pc-cygwin
exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
*:GNU:*:*)
# 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 ;;
*:GNU/*:*:*)
# 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 ;;
*:Minix:*:*)
echo "$UNAME_MACHINE"-unknown-minix
@ -937,7 +926,7 @@ EOF
echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
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 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
@ -1046,7 +1035,7 @@ EOF
#endif
#endif
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; }
;;
mips64el:Linux:*:*)
@ -1066,7 +1055,7 @@ EOF
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# 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" ;;
PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
*) echo hppa-unknown-linux-"$LIBC" ;;
@ -1156,7 +1145,7 @@ EOF
echo "$UNAME_MACHINE"-pc-msdosdjgpp
exit ;;
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
echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
else
@ -1165,7 +1154,7 @@ EOF
exit ;;
i*86:*:5:[678]*)
# 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 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
@ -1174,10 +1163,10 @@ EOF
exit ;;
i*86:*:3.2:*)
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"
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 '^Machine.*Pentium' >/dev/null) \
&& 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)
OS_REL=''
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 \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
@ -1238,7 +1227,7 @@ EOF
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
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 \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
@ -1271,7 +1260,7 @@ EOF
exit ;;
*:SINIX-*:*:*)
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
else
echo ns32k-sni-sysv
@ -1357,7 +1346,7 @@ EOF
echo aarch64-apple-darwin"$UNAME_RELEASE"
exit ;;
*:Darwin:*:*)
UNAME_PROCESSOR=$(uname -p)
UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
@ -1394,7 +1383,7 @@ EOF
echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=$(uname -p)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
@ -1462,10 +1451,10 @@ EOF
echo mips-sei-seiux"$UNAME_RELEASE"
exit ;;
*:DragonFly:*:*)
echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=$( (uname -p) 2>/dev/null)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "$UNAME_MACHINE" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
@ -1475,7 +1464,7 @@ EOF
echo i386-pc-xenix
exit ;;
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 ;;
i*86:rdos:*:*)
echo "$UNAME_MACHINE"-pc-rdos
@ -1533,7 +1522,7 @@ main ()
#define __ARCHITECTURE__ "m68k"
#endif
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)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else
@ -1625,7 +1614,7 @@ main ()
}
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; }
# 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*
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
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
year=$(echo $timestamp | sed 's,-.*,,')
year=`echo $timestamp | sed 's,-.*,,'`
# shellcheck disable=SC2003
if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then
if test "`expr "\`date +%Y\`" - "$year"`" -lt 3 ; then
cat >&2 <<EOF
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
uname -m = $( (uname -m) 2>/dev/null || echo unknown)
uname -r = $( (uname -r) 2>/dev/null || echo unknown)
uname -s = $( (uname -s) 2>/dev/null || echo unknown)
uname -v = $( (uname -v) 2>/dev/null || echo unknown)
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 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)
/bin/uname -X = $( (/bin/uname -X) 2>/dev/null)
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
hostinfo = $( (hostinfo) 2>/dev/null)
/bin/universe = $( (/bin/universe) 2>/dev/null)
/usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null)
/bin/arch = $( (/bin/arch) 2>/dev/null)
/usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null)
/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null)
hostinfo = `(hostinfo) 2>/dev/null`
/bin/universe = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
UNAME_MACHINE = "$UNAME_MACHINE"
UNAME_RELEASE = "$UNAME_RELEASE"

59
apple/config.sub vendored

@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# 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
# 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.
# 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
# and recognize all the CPU types, system types and aliases
@ -50,7 +50,7 @@ timestamp='2020-12-02'
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
me=$(echo "$0" | sed -e 's,.*/,,')
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
@ -769,22 +769,22 @@ case $basic_machine in
vendor=hp
;;
i*86v32)
cpu=$(echo "$1" | sed -e 's/86.*/86/')
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv32
;;
i*86v4*)
cpu=$(echo "$1" | sed -e 's/86.*/86/')
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv4
;;
i*86v)
cpu=$(echo "$1" | sed -e 's/86.*/86/')
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv
;;
i*86sol2)
cpu=$(echo "$1" | sed -e 's/86.*/86/')
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=solaris2
;;
@ -917,7 +917,7 @@ case $basic_machine in
;;
leon-*|leon[3-9]-*)
cpu=sparc
vendor=$(echo "$basic_machine" | sed 's/-.*//')
vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
*-*)
@ -1084,7 +1084,7 @@ case $cpu-$vendor in
cpu=mipsisa64sb1el
;;
sh5e[lb]-*)
cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/')
cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
;;
spur-*)
cpu=spur
@ -1102,7 +1102,7 @@ case $cpu-$vendor in
cpu=x86_64
;;
xscale-* | xscalee[bl]-*)
cpu=$(echo "$cpu" | sed 's/^xscale/arm/')
cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
arm64-*)
cpu=aarch64
@ -1241,7 +1241,6 @@ case $cpu-$vendor in
| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
| spu \
| tahoe \
| thumbv7* \
| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
| tron \
| ubicom32 \
@ -1287,15 +1286,11 @@ then
case $basic_os in
gnu/linux*)
kernel=linux
os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|')
;;
os2-emx)
kernel=os2
os=$(echo $basic_os | sed -e 's|os2-emx|emx|')
os=`echo $basic_os | sed -e 's|gnu/linux|gnu|'`
;;
nto-qnx*)
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
@ -1306,11 +1301,11 @@ EOF
# Default OS when just kernel was specified
nto*)
kernel=nto
os=$(echo $basic_os | sed -e 's|nto|qnx|')
os=`echo $basic_os | sed -e 's|nto|qnx|'`
;;
linux*)
kernel=linux
os=$(echo $basic_os | sed -e 's|linux|gnu|')
os=`echo $basic_os | sed -e 's|linux|gnu|'`
;;
*)
kernel=
@ -1331,7 +1326,7 @@ case $os in
os=cnk
;;
solaris1 | solaris1.*)
os=$(echo $os | sed -e 's|solaris1|sunos4|')
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
solaris)
os=solaris2
@ -1360,7 +1355,7 @@ case $os in
os=sco3.2v4
;;
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)
# Don't match below
@ -1372,7 +1367,13 @@ case $os in
os=psos
;;
qnx*)
os=qnx
case $cpu in
x86 | i*86)
;;
*)
os=nto-$os
;;
esac
;;
hiux*)
os=hiuxwe2
@ -1390,7 +1391,7 @@ case $os in
os=lynxos
;;
mac[0-9]*)
os=$(echo "$os" | sed -e 's|mac|macos|')
os=`echo "$os" | sed -e 's|mac|macos|'`
;;
opened*)
os=openedition
@ -1399,10 +1400,10 @@ case $os in
os=os400
;;
sunos5*)
os=$(echo "$os" | sed -e 's|sunos5|solaris2|')
os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
sunos6*)
os=$(echo "$os" | sed -e 's|sunos6|solaris3|')
os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
wince*)
os=wince
@ -1436,7 +1437,7 @@ case $os in
;;
# Preserve the version number of sinix5.
sinix5.*)
os=$(echo $os | sed -e 's|sinix|sysv|')
os=`echo $os | sed -e 's|sinix|sysv|'`
;;
sinix*)
os=sysv4
@ -1721,7 +1722,7 @@ case $os in
| skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*)
| nsk* | powerunix* | genode* | zvmoe* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@ -1740,8 +1741,6 @@ esac
case $kernel-$os in
linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
;;
uclinux-uclibc* )
;;
-dietlibc* | -newlib* | -musl* | -uclibc* )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
@ -1752,8 +1751,6 @@ case $kernel-$os in
;;
nto-qnx*)
;;
os2-emx)
;;
*-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`
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
MISSING="\${SHELL} '$am_aux_dir/missing'"
fi
# Use eval to expand $SHELL
if eval "$MISSING --is-lightweight"; then

@ -1,7 +1,7 @@
#!/bin/sh
# 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
# later released in X11R6 (xc/config/util/install.sh) with the
@ -69,6 +69,11 @@ posix_mkdir=
# Desired mode of installed file.
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=
chmodcmd=$chmodprog
chowncmd=
@ -99,18 +104,28 @@ Options:
--version display version info and exit.
-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.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
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
@ -137,8 +152,13 @@ while test $# -ne 0; do
-o) chowncmd="$chownprog $2"
shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
@ -255,6 +275,10 @@ do
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
@ -301,22 +325,6 @@ do
if test $dstdir_status != 0; then
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.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
@ -326,52 +334,49 @@ do
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
# Note that $RANDOM variable is not portable (e.g. dash); Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
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'
# directory is successfully created first before we actually test
# 'mkdir -p' feature.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac;;
# The $RANDOM variable is not portable (e.g., dash). Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
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'
# directory is successfully created first before we actually test
# 'mkdir -p'.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac
if
@ -382,7 +387,7 @@ do
then :
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
# directory the slow way, step by step, checking for races as we go.
@ -411,7 +416,7 @@ do
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
(umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
@ -488,6 +493,13 @@ do
then
rm -f "$dsttmp"
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.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
@ -502,9 +514,9 @@ do
# file should still install successfully.
{
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 $rmcmd -f "$rmtmp" 2>/dev/null; :; }
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(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/>.
*/
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/machine.h>
#include <Foundation/Foundation.h>
#ifndef FFMPEG_KIT_ARCH_DETECT_H
#define FFMPEG_KIT_ARCH_DETECT_H
#import <Foundation/Foundation.h>
/**
* This class is used to detect running architecture.
* Detects the running architecture.
*/
@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;
/**
* Returns loaded architecture name.
* Returns architecture name loaded.
*
* @return loaded architecture name as NSString
* @return architecture name loaded
*/
+ (NSString*)getArch;
/**
* Returns whether FFmpegKit release is a long term release or not.
*
* @return yes=1 or no=0
*/
+ (int)isLTSBuild;
@end
#endif // FFMPEG_KIT_ARCH_DETECT_H

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

@ -17,15 +17,22 @@
* 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.
*/
@interface AtomicLong : NSObject
- (instancetype)initWithInitialValue:(long)initialValue;
- (instancetype)initWithValue:(long)value;
- (long)incrementAndGet;
- (long)getAndIncrement;
@end
#endif // FFMPEG_KIT_ATOMIC_LONG_H

@ -17,17 +17,23 @@
* 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 {
NSRecursiveLock *lock;
long value;
long _value;
}
- (instancetype)initWithInitialValue:(long)initialValue {
- (instancetype)initWithValue:(long)value {
self = [super init];
if (self) {
value = initialValue;
_value = value;
_lock = [[NSRecursiveLock alloc] init];
}
return self;
@ -36,10 +42,21 @@
- (long)incrementAndGet {
long returnValue;
[lock lock];
value += 1;
returnValue = value;
[lock unlock];
[self.lock lock];
_value += 1;
returnValue = _value;
[self.lock unlock];
return returnValue;
}
- (long)getAndIncrement {
long returnValue;
[self.lock lock];
returnValue = _value;
_value += 1;
[self.lock unlock];
return returnValue;
}

@ -17,10 +17,43 @@
* 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>
@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
#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/>.
*/
#include <string.h>
#include <stdlib.h>
#include <Foundation/Foundation.h>
#include "ExecuteDelegate.h"
#ifndef FFMPEG_KIT_H
#define FFMPEG_KIT_H
/** Global library version */
extern NSString *const FFMPEG_KIT_VERSION;
#import <string.h>
#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
/**
* Synchronously executes FFmpeg with arguments provided.
* <p>Synchronously executes FFmpeg with arguments provided.
*
* @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 delegate delegate that will be notified when execution is completed
* @return returns a unique id that represents this execution
* @param arguments FFmpeg command options/arguments as string array
* @param executeDelegate delegate that will be called when the execution is completed
* @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 delegate delegate that will be notified when execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return returns a unique id that represents this execution
* @param arguments FFmpeg command options/arguments as string array
* @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
*/
+ (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
* @return zero on successful execution, 255 on user cancel and non-zero on error
* @param arguments FFmpeg 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 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.
*
* @param command FFmpeg command
* @param delegate delegate that will be notified when execution is completed
* @return returns a unique id that represents this execution
* <p>Asynchronously executes FFmpeg with arguments provided.
*
* @param arguments FFmpeg command options/arguments as string array
* @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)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 delegate delegate that will be notified when execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return returns a unique id that represents this execution
* @return FFmpeg session created for 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 delimiter arguments delimiter
* @deprecated argument splitting mechanism used in this method is pretty simple and prone to errors. Consider
* using a more advanced method like execute or executeWithArguments
* @return zero on successful execution, 255 on user cancel and non-zero on error
* @param command FFmpeg command
* @param executeDelegate delegate that will be called when the execution is completed
* @return FFmpeg session created for this execution
*/
+ (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
*/
+ (int)execute:(NSString*)command delimiter:(NSString*)delimiter __attribute__((deprecated));
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue;
/**
* Cancels an ongoing operation.
* <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
*/
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate onDispatchQueue:(dispatch_queue_t)queue;
/**
* <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;
/**
* 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 sessionId id of the session that will be cancelled
*/
+ (void)cancel:(long)sessionId;
/**
* <p>Lists all FFmpeg sessions in the session history.
*
* @param executionId execution id
* @return all FFmpeg sessions in the session history
*/
+ (void)cancel:(long)executionId;
+ (NSArray*)listSessions;
/**
* 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
* @return array of arguments
@ -120,18 +186,13 @@ extern NSString *const FFMPEG_KIT_VERSION;
+ (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
* @return string containing all arguments
* @return concatenated string containing all arguments
*/
+ (NSString*)argumentsToString:(NSArray*)arguments;
/**
* <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/>.
*/
#include "fftools_ffmpeg.h"
#include "FFmpegKit.h"
#include "ArchDetect.h"
#include "AtomicLong.h"
#include "FFmpegExecution.h"
#include "FFmpegKitConfig.h"
/** Forward declaration for function defined in fftools_ffmpeg.c */
int ffmpeg_execute(int argc, char **argv);
#import "fftools_ffmpeg.h"
#import "ArchDetect.h"
#import "AtomicLong.h"
#import "FFmpegKit.h"
#import "FFmpegKitConfig.h"
#import "Packages.h"
@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 {
[FFmpegKitConfig class];
executionIdCounter = [[AtomicLong alloc] initWithInitialValue:3000];
executions = [[NSMutableArray alloc] init];
executionsLock = [[NSLock alloc] init];
NSLog(@"Loaded ffmpeg-kit-%@-%@-%@-%@\n", [FFmpegKitConfig getPackageName], [ArchDetect getArch], [FFmpegKitConfig getVersion], [FFmpegKitConfig getBuildDate]);
NSLog(@"Loaded ffmpeg-kit-%@-%@-%@-%@\n", [Packages getPackageName], [ArchDetect getArch], [FFmpegKitConfig getVersion], [FFmpegKitConfig getBuildDate]);
}
+ (int)executeWithId:(long)newExecutionId andArguments:(NSArray*)arguments {
lastCommandOutput = [[NSMutableString alloc] init];
// SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW EXECUTION
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];
+ (FFmpegSession*)executeWithArguments:(NSArray*)arguments {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments];
[FFmpegKitConfig ffmpegExecute:session];
return session;
}
return lastReturnCode;
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
}
/**
* Synchronously executes FFmpeg with arguments provided.
*
* @param arguments FFmpeg command options/arguments as string array
* @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 withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
}
/**
* Asynchronously executes FFmpeg with arguments provided. Space character is used to split command into arguments.
*
* @param arguments FFmpeg command options/arguments as string array
* @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 onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
return session;
}
/**
* Asynchronously executes FFmpeg with arguments provided. Space character is used to split command into arguments.
*
* @param arguments FFmpeg command options/arguments as string array
* @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];
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
return session;
}
dispatch_async(queue, ^{
const int returnCode = [self executeWithId:newExecutionId andArguments:arguments];
if (delegate != nil) {
[delegate executeCallback:executionId:returnCode];
}
});
+ (FFmpegSession*)execute:(NSString*)command {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command]];
[FFmpegKitConfig ffmpegExecute:session];
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;
}
/**
* Synchronously executes FFmpeg command provided. Space character is used to split command into arguments.
*
* @param command FFmpeg command
* @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 withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
}
/**
* Asynchronously executes FFmpeg command provided. Space character is used to split command into arguments.
*
* @param command FFmpeg command
* @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 onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
return session;
}
/**
* Asynchronously executes FFmpeg command provided. Space character is used to split command into arguments.
*
* @param command FFmpeg command
* @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];
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate withStatisticsDelegate:(id<StatisticsDelegate>)statisticsDelegate onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate withLogDelegate:logDelegate withStatisticsDelegate:statisticsDelegate];
[FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
return session;
}
/**
* 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 {
+ (void)cancel {
// SPLITTING ARGUMENTS
NSArray* argumentArray = [command componentsSeparatedByString:(delimiter == nil ? @" ": delimiter)];
return [self executeWithArguments:argumentArray];
/*
* ZERO (0) IS A SPECIAL SESSION ID
* WHEN IT IS PASSED TO THIS METHOD, A SIGINT IS GENERATED WHICH CANCELS ALL ONGOING SESSIONS
*/
cancel_operation(0);
}
/**
* Cancels an ongoing operation.
*
* This function does not wait for termination to complete and returns immediately.
*/
+ (void)cancel {
cancel_operation(DEFAULT_EXECUTION_ID);
+ (void)cancel:(long)sessionId {
cancel_operation(sessionId);
}
/**
* Cancels an ongoing operation.
*
* This function does not wait for termination to complete and returns immediately.
*
* @param executionId execution id
*/
+ (void)cancel:(long)executionId {
cancel_operation(executionId);
+ (NSArray*)listSessions {
return [FFmpegKitConfig getFFmpegSessions];
}
/**
* Parses the given command into arguments.
*
* @param command string command
* @return array of arguments
*/
+ (NSArray*)parseArguments:(NSString*)command {
NSMutableArray *argumentArray = [[NSMutableArray alloc] init];
NSMutableString *currentArgument = [[NSMutableString alloc] init];
@ -272,15 +160,9 @@ extern int configuredLogLevel;
return argumentArray;
}
/**
* <p>Combines arguments into a string.
*
* @param arguments arguments
* @return string containing all arguments
*/
+ (NSString*)argumentsToString:(NSArray*)arguments {
if (arguments == nil) {
return @"null";
return @"nil";
}
NSMutableString *string = [NSMutableString stringWithString:@""];
@ -295,16 +177,4 @@ extern int configuredLogLevel;
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

@ -17,250 +17,362 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <Foundation/Foundation.h>
#include "LogDelegate.h"
#include "StatisticsDelegate.h"
#ifndef FFMPEG_KIT_CONFIG_H
#define FFMPEG_KIT_CONFIG_H
#import <stdio.h>
#import <pthread.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;
extern int const RETURN_CODE_CANCEL;
/**
* <p>Configuration class of <code>FFmpegKit</code> library. Allows customizing the global library
* 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.
* For example, no header was found for a format which depends
* on headers or an illegal combination of parameters is used.
* <p>Registers the fonts inside the given path, so they become available 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 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.
* However, not all future data is affected.
* <p>Registers the fonts inside the given array of font directories, so they become available
* 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
* lead to problems. An example would be the use of '-vstrict -2'.
* <p>Creates a new named pipe to use in <code>FFmpeg</code> operations.
*
* <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
* 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
* inside another container or ignore them.
* @return true/yes or false/no
*/
+ (int)isLTSBuild;
/**
* Returns FFmpegKit library build date.
*
* 2. setLogLevel:/getLogLevel: Use this methods to set/get
* FFmpeg/FFprobe log severity.
* @return FFmpegKit library build date
*/
+ (NSString*)getBuildDate;
/**
* <p>Sets an environment variable.
*
* 3. StatsDelegate: It is possible to receive statistics about ongoing
* operation by defining a StatsDelegate or by calling
* getLastReceivedStats method.
* @param variableName environment variable name
* @param variableValue environment variable value
* @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
* setFontconfigConfigurationPath: and
* setFontDirectory:with: methods.
* @param signal signal to be ignored
*/
+ (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.
* 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.
* 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.
* <p>Synchronously executes the FFprobe session provided.
*
* @param ffprobeSession FFprobe session which includes command options/arguments
*/
+ (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
* @return string value
* @param ffprobeSession FFprobe session which includes command options/arguments
*/
+ (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
* enabled or use a prebuilt package with fontconfig inside to use this feature.
* @param executeDelegate execute delegate or nil to disable a previously execute delegate
*/
+ (void)enableExecuteDelegate:(id<ExecuteDelegate>)executeDelegate;
/**
* <p>Returns the global execute delegate.
*
* @param fontDirectoryPath directory which contains fonts (.ttf and .otf files)
* @param fontNameMapping custom font name mappings, useful to access your fonts with more friendly names
* @return global execute delegate
*/
+ (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
* multiple commands at the same time, this method will return output from all executions.
* @return all FFprobe sessions in the session history
*/
+ (NSArray*)getFFprobeSessions;
/**
* <p>Returns sessions that have the given state.
*
* Please note that disabling redirection using FFmpegKitConfig.disableRedirection() method
* also disables this functionality.
* @return sessions that have the given state from the session history
*/
+ (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
* ignored.
* @param logRedirectionStrategy log redirection strategy
*/
+ (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
#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/>.
*/
#include <string.h>
#include <stdlib.h>
#include <Foundation/Foundation.h>
#ifndef FFPROBE_KIT_H
#define FFPROBE_KIT_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
/**
* Synchronously executes FFprobe with arguments provided.
* <p>Synchronously executes FFprobe with arguments provided.
*
* @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
* into arguments.
* <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 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
* multiple operations (execute or getMediaInformation) at the same time, the response of this
* method is not predictable.
* @param command FFprobe command
* @param executeDelegate delegate that will be called when the execution is completed
* @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
* @return media information
* @param command FFprobe command
* @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
* multiple operations (execute or getMediaInformation) at the same time, the response of this
* method is not predictable.
* @param command FFprobe 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 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
* @return media information
* @param command FFprobe command
* @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
* multiple operations (execute or getMediaInformation) at the same time, the response of this
* method is not predictable.
* @param path path or uri of a media file
* @return media information session created for this execution
*/
+ (MediaInformationSession*)getMediaInformation:(NSString*)path;
/**
* <p>Extracts media information for the file specified with path.
*
* @param path path or uri of media file
* @param timeout complete timeout
* @deprecated this method is deprecated since v4.3.1. You can still use this method but
* timeout parameter is not effective anymore.
* @return media information
* @param path path or uri of a media file
* @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution
*/
+ (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
#endif // FFPROBE_KIT_H

@ -17,131 +17,133 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libavutil/ffversion.h"
#include "fftools_ffmpeg.h"
#include "FFmpegKit.h"
#include "FFmpegKitConfig.h"
#include "FFprobeKit.h"
/** Forward declaration for function defined in fftools_ffprobe.c */
int ffprobe_execute(int argc, char **argv);
#import "fftools_ffmpeg.h"
#import "FFmpegKit.h"
#import "FFmpegKitConfig.h"
#import "FFprobeKit.h"
@implementation FFprobeKit
extern int lastReturnCode;
extern NSMutableString *lastCommandOutput;
extern int configuredLogLevel;
+ (void)initialize {
[FFmpegKitConfig class];
}
/**
* Synchronously executes FFprobe with arguments provided.
*
* @param arguments FFprobe command options/arguments as string array
* @return zero on successful execution, 255 on user cancel and non-zero on error
*/
+ (int)executeWithArguments:(NSArray*)arguments {
lastCommandOutput = [[NSMutableString alloc] init];
+ (FFprobeSession*)executeWithArguments:(NSArray*)arguments {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments];
[FFmpegKitConfig ffprobeExecute:session];
return session;
}
// SETS DEFAULT LOG LEVEL BEFORE STARTING A NEW EXECUTION
av_log_set_level(configuredLogLevel);
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
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
*
* ffprobe <arguments>
*/
commandCharPArray[0] = (char *)av_malloc(sizeof(char) * ([LIB_NAME length] + 1));
strcpy(commandCharPArray[0], [LIB_NAME UTF8String]);
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
return session;
}
for (int i=0; i < [arguments count]; i++) {
NSString *argument = [arguments objectAtIndex:i];
commandCharPArray[i + 1] = (char *) [argument UTF8String];
}
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
[FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
return session;
}
// RUN
lastReturnCode = ffprobe_execute(([arguments count] + 1), commandCharPArray);
+ (FFprobeSession*)execute:(NSString*)command {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command]];
[FFmpegKitConfig ffprobeExecute:session];
return session;
}
// CLEANUP
av_free(commandCharPArray[0]);
av_free(commandCharPArray);
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate];
[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;
}
/**
* Synchronously executes FFprobe command provided. Space character is used to split command
* into arguments.
*
* @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 onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate];
[FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
return session;
}
/**
* Returns media information for the given file.
*
* This method does not support executing multiple concurrent operations. If you execute
* 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]];
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKit parseArguments:command] withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
[FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
return session;
}
/**
* Returns media information for the given command.
*
* This method does not support executing multiple concurrent operations. If you execute
* multiple operations (execute or getMediaInformation) at the same time, the response of this
* method is not predictable.
*
* @param command
* @return media information
*/
+ (MediaInformation*)getMediaInformationFromCommand:(NSString*)command {
return [FFprobeKit getMediaInformationFromCommandArguments:[FFmpegKit parseArguments: command]];
+ (MediaInformationSession*)getMediaInformation:(NSString*)path {
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];
[FFmpegKitConfig getMediaInformationExecute:session withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
return session;
}
/**
* Returns media information for given file.
*
* This method does not support executing multiple concurrent operations. If you execute
* multiple operations (execute or getMediaInformation) at the same time, the response of this
* method is not predictable.
*
* @param path path or uri of media file
* @param timeout complete timeout
* @deprecated this method is deprecated since v4.3.1. You can still use this method but
* timeout parameter is not effective anymore.
* @return media information
*/
+ (MediaInformation*)getMediaInformation:(NSString*)path timeout:(long)timeout {
return [FFprobeKit getMediaInformation:path];
+ (MediaInformationSession*)getMediaInformation:(NSString*)path 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];
[FFmpegKitConfig getMediaInformationExecute:session withTimeout:waitTimeout];
return session;
}
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate {
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 withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
return session;
}
+ (MediaInformation*)getMediaInformationFromCommandArguments:(NSArray*)arguments {
int rc = [FFprobeKit executeWithArguments:arguments];
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate 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 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) {
return [MediaInformationParser from:[FFmpegKitConfig getLastCommandOutput]];
} else {
int activeLogLevel = av_log_get_level();
if ((activeLogLevel != AV_LOG_QUIET) && (AV_LOG_WARNING <= activeLogLevel)) {
NSLog(@"%@", [FFmpegKitConfig getLastCommandOutput]);
}
+ (MediaInformationSession*)getMediaInformationFromCommandAsync:(NSArray*)arguments withExecuteDelegate:(id<ExecuteDelegate>)executeDelegate withLogDelegate:(id<LogDelegate>)logDelegate onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteDelegate:executeDelegate withLogDelegate:logDelegate];
[FFmpegKitConfig asyncGetMediaInformationExecute:session onDispatchQueue:queue withTimeout:waitTimeout];
return session;
}
return nil;
}
+ (NSArray*)listSessions {
return [FFmpegKitConfig getFFprobeSessions];
}
@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/>.
*/
#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>
@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
#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_SOURCES = \
AbstractSession.m \
ArchDetect.m \
AtomicLong.m \
FFmpegExecution.m \
FFmpegKit.m \
ffmpegkit_exception.m \
FFmpegKitConfig.m \
FFmpegSession.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_ffmpeg.c \
fftools_ffmpeg_filter.c \
fftools_ffmpeg_hw.c \
fftools_ffmpeg_opt.c \
fftools_ffprobe.c \
MediaInformation.m \
MediaInformationParser.m \
Statistics.m \
StreamInformation.m
fftools_ffprobe.c
if FFMPEGKIT_VIDEOTOOLBOX
libffmpegkit_la_SOURCES += fftools_ffmpeg_videotoolbox.c
endif
include_HEADERS = \
AbstractSession.h \
ArchDetect.h \
AtomicLong.h \
ExecuteDelegate.h \
FFmpegExecution.h \
FFmpegKit.h \
ffmpegkit_exception.h \
FFmpegKitConfig.h \
FFmpegSession.h \
FFprobeKit.h \
fftools_cmdutils.h \
fftools_ffmpeg.h \
FFprobeSession.h \
Level.h \
Log.h \
LogDelegate.h \
LogRedirectionStrategy.h \
MediaInformation.h \
MediaInformationParser.h \
MediaInformationJsonParser.h \
MediaInformationSession.h \
Packages.h \
ReturnCode.h \
Session.h \
SessionState.h \
Statistics.h \
StatisticsDelegate.h \
StreamInformation.h
StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
fftools_ffmpeg.h
libffmpegkit_la_CFLAGS = $(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@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
@ -133,31 +133,35 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libffmpegkit_la_DEPENDENCIES =
am__libffmpegkit_la_SOURCES_DIST = ArchDetect.m AtomicLong.m \
fftools_cmdutils.c fftools_ffmpeg.c fftools_ffmpeg_filter.c \
fftools_ffmpeg_hw.c fftools_ffmpeg_opt.c fftools_ffprobe.c \
FFmpegExecution.m MediaInformation.m MediaInformationParser.m \
FFmpegKit.m FFmpegKitConfig.m ffmpegkit_exception.m \
FFprobeKit.m Statistics.m StreamInformation.m \
am__libffmpegkit_la_SOURCES_DIST = AbstractSession.m ArchDetect.m \
AtomicLong.m FFmpegKit.m FFmpegKitConfig.m FFmpegSession.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_ffmpeg.c \
fftools_ffmpeg_filter.c fftools_ffmpeg_hw.c \
fftools_ffmpeg_opt.c fftools_ffprobe.c \
fftools_ffmpeg_videotoolbox.c
@FFMPEGKIT_VIDEOTOOLBOX_TRUE@am__objects_1 = libffmpegkit_la-fftools_ffmpeg_videotoolbox.lo
am_libffmpegkit_la_OBJECTS = libffmpegkit_la-ArchDetect.lo \
libffmpegkit_la-AtomicLong.lo \
am_libffmpegkit_la_OBJECTS = libffmpegkit_la-AbstractSession.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_ffmpeg.lo \
libffmpegkit_la-fftools_ffmpeg_filter.lo \
libffmpegkit_la-fftools_ffmpeg_hw.lo \
libffmpegkit_la-fftools_ffmpeg_opt.lo \
libffmpegkit_la-fftools_ffprobe.lo \
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-fftools_ffprobe.lo $(am__objects_1)
libffmpegkit_la_OBJECTS = $(am_libffmpegkit_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -182,24 +186,30 @@ am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
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-FFmpegExecution.Plo \
./$(DEPDIR)/libffmpegkit_la-MediaInformation.Plo \
./$(DEPDIR)/libffmpegkit_la-MediaInformationParser.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegSession.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-StreamInformation.Plo \
./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_filter.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_hw.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_opt.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg_videotoolbox.Plo \
./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo \
./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@ -389,30 +399,41 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
lib_LTLIBRARIES = libffmpegkit.la
libffmpegkit_la_LIBADD = @FFMPEG_LIBS@
libffmpegkit_la_SOURCES = ArchDetect.m AtomicLong.m \
fftools_cmdutils.c fftools_ffmpeg.c fftools_ffmpeg_filter.c \
fftools_ffmpeg_hw.c fftools_ffmpeg_opt.c fftools_ffprobe.c \
FFmpegExecution.m MediaInformation.m MediaInformationParser.m \
FFmpegKit.m FFmpegKitConfig.m ffmpegkit_exception.m \
FFprobeKit.m Statistics.m StreamInformation.m \
$(am__append_1)
libffmpegkit_la_SOURCES = AbstractSession.m ArchDetect.m AtomicLong.m \
FFmpegKit.m FFmpegKitConfig.m FFmpegSession.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_ffmpeg.c \
fftools_ffmpeg_filter.c fftools_ffmpeg_hw.c \
fftools_ffmpeg_opt.c fftools_ffprobe.c $(am__append_1)
include_HEADERS = \
AbstractSession.h \
ArchDetect.h \
AtomicLong.h \
ExecuteDelegate.h \
FFmpegExecution.h \
fftools_cmdutils.h \
fftools_ffmpeg.h \
LogDelegate.h \
MediaInformation.h \
MediaInformationParser.h \
FFmpegKit.h \
FFmpegKitConfig.h \
ffmpegkit_exception.h \
FFmpegSession.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 \
StatisticsDelegate.h \
StreamInformation.h
StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
fftools_ffmpeg.h
libffmpegkit_la_CFLAGS = $(CFLAGS)
libffmpegkit_la_OBJCFLAGS = $(CFLAGS)
@ -496,16 +517,23 @@ mostlyclean-compile:
distclean-compile:
-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-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-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-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-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_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
@ -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_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-ffmpegkit_exception.Plo@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(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@
@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
@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
@ -632,27 +666,6 @@ libffmpegkit_la-AtomicLong.lo: AtomicLong.m
@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
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
@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
@ -667,12 +680,12 @@ libffmpegkit_la-FFmpegKitConfig.lo: FFmpegKitConfig.m
@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
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@
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-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-FFmpegSession.Tpo $(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo
@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@
@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
@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@
@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
@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
@ -695,6 +757,13 @@ libffmpegkit_la-StreamInformation.lo: StreamInformation.m
@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
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:
-rm -f *.lo
@ -850,16 +919,23 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
mostlyclean-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-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-FFmpegKitConfig.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.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-StreamInformation.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.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_videotoolbox.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@ -913,16 +988,23 @@ install-ps-am:
installcheck-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-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-FFmpegKitConfig.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.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-StreamInformation.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_cmdutils.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffmpeg.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_videotoolbox.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-fftools_ffprobe.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ffmpegkit_exception.Plo
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

@ -17,8 +17,21 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Foundation/Foundation.h>
#include "StreamInformation.h"
#ifndef FFMPEG_KIT_MEDIA_INFORMATION_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.
@ -126,3 +139,5 @@
- (NSDictionary*)getAllProperties;
@end
#endif // FFMPEG_KIT_MEDIA_INFORMATION_H

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

@ -17,19 +17,34 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Foundation/Foundation.h>
#include "MediaInformation.h"
#ifndef FFMPEG_KIT_MEDIA_INFORMATION_PARSER_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;
/**
* 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;
@end
#endif // FFMPEG_KIT_MEDIA_INFORMATION_PARSER_H

@ -17,9 +17,9 @@
* 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 {
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/>.
*/
#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
- (instancetype)init;
- (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;
- (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;
- (void)update:(Statistics*)statistics;
- (long)getExecutionId;
- (long)getSessionId;
- (int)getVideoFrameNumber;
@ -47,3 +46,5 @@
- (double)getSpeed;
@end
#endif // FFMPEG_KIT_STATISTICS_H

@ -17,108 +17,65 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Statistics.h"
#import "Statistics.h"
@implementation Statistics {
long executionId;
int videoFrameNumber;
float videoFps;
float videoQuality;
long size;
int time;
double bitrate;
double speed;
long _sessionId;
int _videoFrameNumber;
float _videoFps;
float _videoQuality;
long _size;
int _time;
double _bitrate;
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];
if (self) {
executionId = 0;
videoFrameNumber = 0;
videoFps = 0;
videoQuality = 0;
size = 0;
time = 0;
bitrate = 0;
speed = 0;
_sessionId = sessionId;
_videoFrameNumber = videoFrameNumber;
_videoFps = videoFps;
_videoQuality = videoQuality;
_size = size;
_time = time;
_bitrate = bitrate;
_speed = speed;
}
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 {
self = [super init];
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;
- (long)getSessionId {
return _sessionId;
}
- (int)getVideoFrameNumber {
return videoFrameNumber;
return _videoFrameNumber;
}
- (float)getVideoFps {
return videoFps;
return _videoFps;
}
- (float)getVideoQuality {
return videoQuality;
return _videoQuality;
}
- (long)getSize {
return size;
return _size;
}
- (int)getTime {
return time;
return _time;
}
- (double)getBitrate {
return bitrate;
return _bitrate;
}
- (double)getSpeed {
return speed;
return _speed;
}
@end

@ -17,12 +17,25 @@
* 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>
@required
/**
* <p>Called when a statistics entry is received.
*
* @param statistics statistics entry
*/
- (void)statisticsCallback:(Statistics*)statistics;
@end
#endif // FFMPEG_KIT_STATISTICS_DELEGATE_H

@ -17,7 +17,29 @@
* 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.
@ -181,3 +203,5 @@
- (NSDictionary*)getAllProperties;
@end
#endif // FFMPEG_KIT_STREAM_INFORMATION_H

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

@ -257,9 +257,9 @@ extern volatile int handleSIGTERM;
extern volatile int handleSIGXCPU;
extern volatile int handleSIGPIPE;
extern __thread volatile long executionId;
extern int cancelRequested(long executionId);
extern void removeExecution(long executionId);
extern __thread volatile long _sessionId;
extern void cancelSession(long sessionId);
extern int cancelRequested(long sessionId);
/* sub2video hack:
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) {
av_log(NULL, AV_LOG_INFO, "Exiting normally, received signal %d.\n",
(int) received_sigterm);
} else if (cancelRequested(executionId)) {
} else if (cancelRequested(_sessionId)) {
av_log(NULL, AV_LOG_INFO, "Exiting normally, received cancel request.\n");
} else if (ret && atomic_load(&transcode_init_done)) {
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) {
/* 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);
}
if (ret < 0)
@ -4934,7 +4934,7 @@ static int transcode(void)
goto fail;
#endif
while (!received_sigterm && !cancelRequested(executionId)) {
while (!received_sigterm && !cancelRequested(_sessionId)) {
int64_t cur_time= av_gettime_relative();
/* if 'q' pressed, exits */
@ -5148,7 +5148,7 @@ void cancel_operation(long id)
if (id == 0) {
sigterm_handler(SIGINT);
} 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])
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 {
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;

@ -22,14 +22,14 @@ enable_default_ios_architectures
enable_main_build
# 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
source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1
fi
# DETECT IOS 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
# SET DEFAULT BUILD OPTIONS

@ -22,14 +22,14 @@ enable_default_macos_architectures
enable_main_build
# 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
source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1
fi
# DETECT MACOS 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
# SET DEFAULT BUILD OPTIONS

@ -22,14 +22,14 @@ enable_default_tvos_architectures
enable_main_build
# 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
source "${XCODE_FOR_FFMPEG_KIT}" 1>>"${BASEDIR}"/build.log 2>&1
fi
# DETECT TVOS 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
# SET DEFAULT BUILD OPTIONS

Loading…
Cancel
Save