Merge branch 'main' into development-react-native

pull/294/head
Taner Sener 4 years ago
commit 70ad8a8caa
  1. 3
      .github/FUNDING.yml
  2. 8
      .github/workflows/android-build-scripts.yml
  3. 46
      README.md
  4. 56
      android.sh
  5. 1
      android/.gitignore
  6. 42
      android/README.md
  7. 2
      android/ffmpeg-kit-android-lib/Doxyfile
  8. 10
      android/ffmpeg-kit-android-lib/build.gradle
  9. 3
      android/ffmpeg-kit-android-lib/proguard-rules.pro
  10. 36
      android/ffmpeg-kit-android-lib/src/main/cpp/ffmpegkit.c
  11. 2
      android/ffmpeg-kit-android-lib/src/main/cpp/ffmpegkit.h
  12. 21
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AbstractSession.java
  13. 26
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AsyncFFmpegExecuteTask.java
  14. 26
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AsyncFFprobeExecuteTask.java
  15. 26
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/AsyncGetMediaInformationTask.java
  16. 131
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Chapter.java
  17. 51
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/ExecuteCallback.java
  18. 160
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFmpegKit.java
  19. 320
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFmpegKitConfig.java
  20. 57
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFmpegSession.java
  21. 35
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFmpegSessionCompleteCallback.java
  22. 338
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFprobeKit.java
  23. 47
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFprobeSession.java
  24. 35
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/FFprobeSessionCompleteCallback.java
  25. 17
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/MediaInformation.java
  26. 22
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/MediaInformationJsonParser.java
  27. 51
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/MediaInformationSession.java
  28. 36
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/MediaInformationSessionCompleteCallback.java
  29. 14
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/NativeLoader.java
  30. 12
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Packages.java
  31. 6
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/ReturnCode.java
  32. 21
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/Session.java
  33. 2
      android/ffmpeg-kit-android-lib/src/main/java/com/arthenica/ffmpegkit/StreamInformation.java
  34. 98
      android/ffmpeg-kit-android-lib/src/test/java/com/arthenica/ffmpegkit/FFmpegKitTest.java
  35. 24
      android/ffmpeg-kit-android-lib/src/test/java/com/arthenica/ffmpegkit/FFmpegSessionTest.java
  36. 24
      android/ffmpeg-kit-android-lib/src/test/java/com/arthenica/ffmpegkit/FFprobeSessionTest.java
  37. 128
      apple.sh
  38. 2
      apple/.gitignore
  39. 2
      apple/Doxyfile
  40. 19
      apple/Makefile.in
  41. 53
      apple/README.md
  42. 72
      apple/aclocal.m4
  43. 2
      apple/ar-lib
  44. 2
      apple/compile
  45. 1143
      apple/config.guess
  46. 91
      apple/config.sub
  47. 6347
      apple/configure
  48. 13
      apple/configure.ac
  49. 2
      apple/depcomp
  50. 64
      apple/libtool
  51. 2
      apple/missing
  52. 7
      apple/src/AbstractSession.h
  53. 14
      apple/src/AbstractSession.m
  54. 84
      apple/src/Chapter.h
  55. 107
      apple/src/Chapter.m
  56. 105
      apple/src/FFmpegKit.h
  57. 32
      apple/src/FFmpegKit.m
  58. 73
      apple/src/FFmpegKitConfig.h
  59. 264
      apple/src/FFmpegKitConfig.m
  60. 39
      apple/src/FFmpegSession.h
  61. 28
      apple/src/FFmpegSession.m
  62. 14
      apple/src/FFmpegSessionCompleteCallback.h
  63. 176
      apple/src/FFprobeKit.h
  64. 80
      apple/src/FFprobeKit.m
  65. 32
      apple/src/FFprobeSession.h
  66. 49
      apple/src/FFprobeSession.m
  67. 50
      apple/src/FFprobeSessionCompleteCallback.h
  68. 44
      apple/src/Makefile.am
  69. 86
      apple/src/Makefile.in
  70. 10
      apple/src/MediaInformation.h
  71. 12
      apple/src/MediaInformation.m
  72. 20
      apple/src/MediaInformationJsonParser.m
  73. 26
      apple/src/MediaInformationSession.h
  74. 42
      apple/src/MediaInformationSession.m
  75. 51
      apple/src/MediaInformationSessionCompleteCallback.h
  76. 6
      apple/src/ReturnCode.h
  77. 6
      apple/src/ReturnCode.m
  78. 20
      apple/src/Session.h
  79. 76
      ios.sh
  80. 38
      macos.sh
  81. 7
      scripts/android/chromaprint.sh
  82. 2
      scripts/android/expat.sh
  83. 89
      scripts/android/ffmpeg.sh
  84. 11
      scripts/android/fontconfig.sh
  85. 2
      scripts/android/freetype.sh
  86. 2
      scripts/android/fribidi.sh
  87. 2
      scripts/android/giflib.sh
  88. 2
      scripts/android/gmp.sh
  89. 2
      scripts/android/kvazaar.sh
  90. 2
      scripts/android/lame.sh
  91. 2
      scripts/android/leptonica.sh
  92. 2
      scripts/android/libaom.sh
  93. 2
      scripts/android/libass.sh
  94. 2
      scripts/android/libiconv.sh
  95. 2
      scripts/android/libilbc.sh
  96. 2
      scripts/android/libogg.sh
  97. 2
      scripts/android/libpng.sh
  98. 2
      scripts/android/libsamplerate.sh
  99. 2
      scripts/android/libsndfile.sh
  100. 2
      scripts/android/libuuid.sh
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,2 +1,3 @@
patreon: tanersener
custom: [ 'https://www.patreon.com/tanersener','https://opencollective.com/ffmpeg-kit','https://buymeacoff.ee/tanersener','https://paypal.me/teodosiyminchev' ]
open_collective: ffmpeg-kit
custom: [ 'https://buymeacoff.ee/tanersener' ]

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
ndk-version: [ 'r21e-linux-x86_64', 'r22b-linux-x86_64', 'r23-linux' ]
ndk-version: [ 'r22b-linux-x86_64', 'r23b-linux' ]
defaults:
run:
shell: bash
@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
ndk-version: [ 'r21e-linux-x86_64', 'r22b-linux-x86_64', 'r23-linux' ]
ndk-version: [ 'r22b-linux-x86_64', 'r23b-linux' ]
defaults:
run:
shell: bash
@ -73,7 +73,7 @@ jobs:
runs-on: macos-10.15
strategy:
matrix:
ndk-version: [ 'r21e-darwin-x86_64', 'r22b-darwin-x86_64', 'r23-darwin' ]
ndk-version: [ 'r22b-darwin-x86_64', 'r23b-darwin' ]
defaults:
run:
shell: bash
@ -102,7 +102,7 @@ jobs:
runs-on: macos-10.15
strategy:
matrix:
ndk-version: [ 'r21e-darwin-x86_64', 'r22b-darwin-x86_64', 'r23-darwin' ]
ndk-version: [ 'r22b-darwin-x86_64', 'r23b-darwin' ]
defaults:
run:
shell: bash

@ -1,4 +1,4 @@
# FFmpegKit ![GitHub release](https://img.shields.io/badge/release-v4.5-blue.svg) ![Maven Central](https://img.shields.io/maven-central/v/com.arthenica/ffmpeg-kit-min) ![CocoaPods](https://img.shields.io/cocoapods/v/ffmpeg-kit-ios-min) ![pub](https://img.shields.io/pub/v/ffmpeg_kit_flutter.svg) ![npm](https://img.shields.io/npm/v/ffmpeg-kit-react-native.svg)
# FFmpegKit ![GitHub release](https://img.shields.io/badge/release-v4.5.1-blue.svg) ![Maven Central](https://img.shields.io/maven-central/v/com.arthenica/ffmpeg-kit-min) ![CocoaPods](https://img.shields.io/cocoapods/v/ffmpeg-kit-ios-min) ![pub](https://img.shields.io/pub/v/ffmpeg_kit_flutter.svg) ![npm](https://img.shields.io/npm/v/ffmpeg-kit-react-native.svg)
<img src="https://github.com/tanersener/ffmpeg-kit/blob/main/docs/assets/ffmpeg-kit-icon-v9.png" width="240">
@ -83,9 +83,9 @@ include them.
<td align="center"><sup>gmp</sup><br><sup>gnutls</sup></td>
<td align="center"><sup>gmp</sup><br><sup>gnutls</sup><br><sup>vid.stab</sup><br><sup>x264</sup><br><sup>x265</sup><br><sup>xvidcore</sup></td>
<td align="center"><sup>lame</sup><br><sup>libilbc</sup><br><sup>libvorbis</sup><br><sup>opencore-amr</sup><br><sup>opus</sup><br><sup>shine</sup><br><sup>soxr</sup><br><sup>speex</sup><br><sup>twolame</sup><br><sup>vo-amrwbenc</sup></td>
<td align="center"><sup>dav1d</sup><br><sup>fontconfig</sup><br><sup>freetype</sup><br><sup>fribidi</sup><br><sup>kvazaar</sup><br><sup>libass</sup><br><sup>libiconv</sup><br><sup>libtheora</sup><br><sup>libvpx</sup><br><sup>libwebp</sup><br><sup>snappy</sup></td>
<td align="center"><sup>dav1d</sup><br><sup>fontconfig</sup><br><sup>freetype</sup><br><sup>fribidi</sup><br><sup>gmp</sup><br><sup>gnutls</sup><br><sup>kvazaar</sup><br><sup>lame</sup><br><sup>libass</sup><br><sup>libiconv</sup><br><sup>libilbc</sup><br><sup>libtheora</sup><br><sup>libvorbis</sup><br><sup>libvpx</sup><br><sup>libwebp</sup><br><sup>libxml2</sup><br><sup>opencore-amr</sup><br><sup>opus</sup><br><sup>shine</sup><br><sup>snappy</sup><br><sup>soxr</sup><br><sup>speex</sup><br><sup>twolame</sup><br><sup>vo-amrwbenc</sup></td>
<td align="center"><sup>dav1d</sup><br><sup>fontconfig</sup><br><sup>freetype</sup><br><sup>fribidi</sup><br><sup>gmp</sup><br><sup>gnutls</sup><br><sup>kvazaar</sup><br><sup>lame</sup><br><sup>libass</sup><br><sup>libiconv</sup><br><sup>libilbc</sup><br><sup>libtheora</sup><br><sup>libvorbis</sup><br><sup>libvpx</sup><br><sup>libwebp</sup><br><sup>libxml2</sup><br><sup>opencore-amr</sup><br><sup>opus</sup><br><sup>shine</sup><br><sup>snappy</sup><br><sup>soxr</sup><br><sup>speex</sup><br><sup>twolame</sup><br><sup>vid.stab</sup><br><sup>vo-amrwbenc</sup><br><sup>x264</sup><br><sup>x265</sup><br><sup>xvidcore</sup></td>
<td align="center"><sup>dav1d</sup><br><sup>fontconfig</sup><br><sup>freetype</sup><br><sup>fribidi</sup><br><sup>kvazaar</sup><br><sup>libass</sup><br><sup>libiconv</sup><br><sup>libtheora</sup><br><sup>libvpx</sup><br><sup>libwebp</sup><br><sup>snappy</sup><br><sup>zimg</sup></td>
<td align="center"><sup>dav1d</sup><br><sup>fontconfig</sup><br><sup>freetype</sup><br><sup>fribidi</sup><br><sup>gmp</sup><br><sup>gnutls</sup><br><sup>kvazaar</sup><br><sup>lame</sup><br><sup>libass</sup><br><sup>libiconv</sup><br><sup>libilbc</sup><br><sup>libtheora</sup><br><sup>libvorbis</sup><br><sup>libvpx</sup><br><sup>libwebp</sup><br><sup>libxml2</sup><br><sup>opencore-amr</sup><br><sup>opus</sup><br><sup>shine</sup><br><sup>snappy</sup><br><sup>soxr</sup><br><sup>speex</sup><br><sup>twolame</sup><br><sup>vo-amrwbenc</sup><br><sup>zimg</sup></td>
<td align="center"><sup>dav1d</sup><br><sup>fontconfig</sup><br><sup>freetype</sup><br><sup>fribidi</sup><br><sup>gmp</sup><br><sup>gnutls</sup><br><sup>kvazaar</sup><br><sup>lame</sup><br><sup>libass</sup><br><sup>libiconv</sup><br><sup>libilbc</sup><br><sup>libtheora</sup><br><sup>libvorbis</sup><br><sup>libvpx</sup><br><sup>libwebp</sup><br><sup>libxml2</sup><br><sup>opencore-amr</sup><br><sup>opus</sup><br><sup>shine</sup><br><sup>snappy</sup><br><sup>soxr</sup><br><sup>speex</sup><br><sup>twolame</sup><br><sup>vid.stab</sup><br><sup>vo-amrwbenc</sup><br><sup>x264</sup><br><sup>x265</sup><br><sup>xvidcore</sup><br><sup>zimg</sup></td>
</tr>
<tr>
<td align="center"><sup>android system libraries</sup></td>
@ -109,6 +109,7 @@ include them.
- `AVFoundation` is not available on `tvOS`
- `VideoToolbox` is not available on LTS releases of `iOS` and `tvOS`
- `zimg` is supported since `v4.5.1`
### 9. Versions
@ -137,24 +138,25 @@ indicates that `FFmpeg` source code is cloned from the `FFmpeg` `master` branch.
This table shows the differences between two variants.
| | Main Release | LTS Release |
| :----: | :----: | :----: |
| Android API Level | 24 | 16 |
| Android Camera Access | Yes | - |
| | Main Release | LTS Release |
| :----: | :----: |:---------------------------------------------------------:|
| Android API Level | 24 | 16 |
| Android Camera Access | Yes | - |
| Android Architectures | arm-v7a-neon<br/>arm64-v8a<br/>x86<br/>x86-64 | arm-v7a<br/>arm-v7a-neon<br/>arm64-v8a<br/>x86<br/>x86-64 |
| iOS Min SDK | 12.1 | 9.3 |
| iOS VideoToolbox | Yes | - |
| iOS AVFoundation | Yes | - |
| iOS Architectures | arm64<br/>arm64-simulator<br/>arm64-mac-catalyst<br/>x86-64<br/>x86-64-mac-catalyst | armv7<br/>arm64<br/>i386<br/>x86-64 |
| iOS Bundle Format | XCFrameworks | Frameworks |
| macOS Min SDK | 10.15 | 10.11 |
| macOS AVFoundation | Yes | - |
| macOS Architectures | arm64<br/>x86-64 | x86-64 |
| macOS Bundle Format | XCFrameworks | Frameworks |
| tvOS Min SDK | 11.0 | 9.2 |
| tvOS VideoToolbox | Yes | - |
| tvOS Architectures | arm64<br/>x86-64<br/>arm64-simulator | arm64<br/>x86-64 |
| tvOS Bundle Format | XCFrameworks | Frameworks |
| iOS Min SDK | 12.1 | 10 |
| iOS VideoToolbox | Yes | - |
| iOS AVFoundation | Yes | - |
| iOS Architectures | arm64<br/>arm64-simulator<br/>arm64-mac-catalyst<br/>x86-64<br/>x86-64-mac-catalyst | armv7<br/>arm64<br/>i386<br/>x86-64 |
| iOS Bundle Format | XCFrameworks | Frameworks |
| Mac Catalyst Min Version | 14.0 | - |
| macOS Min SDK | 10.15 | 10.12 |
| macOS AVFoundation | Yes | - |
| macOS Architectures | arm64<br/>x86-64 | x86-64 |
| macOS Bundle Format | XCFrameworks | Frameworks |
| tvOS Min SDK | 11.0 | 10.0 |
| tvOS VideoToolbox | Yes | - |
| tvOS Architectures | arm64<br/>x86-64<br/>arm64-simulator | arm64<br/>x86-64 |
| tvOS Bundle Format | XCFrameworks | Frameworks |
### 11. Documentation
@ -173,6 +175,8 @@ burning subtitles, video stabilisation, pipe operations and concurrent command e
`FFmpegKit` is licensed under the `LGPL v3.0`. However, if source code is built using the optional `--enable-gpl` flag
or prebuilt binaries with `-gpl` postfix are used, then `FFmpegKit` is subject to the `GPL v3.0` license.
See the [License](https://github.com/tanersener/ffmpeg-kit/wiki/License) wiki page for the details.
### 14. Patents
It is not clearly explained in their documentation, but it is believed that `FFmpeg`, `kvazaar`, `x264` and `x265`

@ -15,6 +15,7 @@ export BASEDIR="$(pwd)"
export FFMPEG_KIT_BUILD_TYPE="android"
source "${BASEDIR}"/scripts/variable.sh
source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh
disabled_libraries=()
# SET DEFAULTS SETTINGS
enable_default_android_architectures
@ -106,11 +107,24 @@ while [ ! $# -eq 0 ]; do
--enable-gpl)
GPL_ENABLED="yes"
;;
--enable-custom-library-*)
CUSTOM_LIBRARY_OPTION_KEY=$(echo $1 | sed -e 's/^--enable-custom-//g;s/=.*$//g')
CUSTOM_LIBRARY_OPTION_VALUE=$(echo $1 | sed -e 's/^--enable-custom-.*=//g')
echo -e "INFO: Custom library options detected: ${CUSTOM_LIBRARY_OPTION_KEY} ${CUSTOM_LIBRARY_OPTION_VALUE}\n" 1>>"${BASEDIR}"/build.log 2>&1
generate_custom_library_environment_variables "${CUSTOM_LIBRARY_OPTION_KEY}" "${CUSTOM_LIBRARY_OPTION_VALUE}"
;;
--enable-*)
ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
enable_library "${ENABLED_LIBRARY}"
;;
--disable-lib-*)
DISABLED_LIB=$(echo $1 | sed -e 's/^--[A-Za-z]*-[A-Za-z]*-//g')
disabled_libraries+=("${DISABLED_LIB}")
;;
--disable-*)
DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
@ -138,7 +152,7 @@ fi
# PROCESS FULL OPTION AS LAST OPTION
if [[ -n ${BUILD_FULL} ]]; then
for library in {0..58}; do
for library in {0..61}; do
if [ ${GPL_ENABLED} == "yes" ]; then
enable_library "$(get_library_name $library)" 1
else
@ -149,12 +163,21 @@ if [[ -n ${BUILD_FULL} ]]; then
done
fi
# DISABLE SPECIFIED LIBRARIES
for disabled_library in ${disabled_libraries[@]}; do
set_library "${disabled_library}" 0
done
# IF HELP DISPLAYED EXIT
if [[ -n ${DISPLAY_HELP} ]]; then
display_help
exit 0
fi
# SET API LEVEL IN build.gradle
${SED_INLINE} "s/minSdkVersion .*/minSdkVersion ${API}/g" "${BASEDIR}"/android/ffmpeg-kit-android-lib/build.gradle 1>>"${BASEDIR}"/build.log 2>&1
${SED_INLINE} "s/versionCode ..0/versionCode ${API}0/g" "${BASEDIR}"/android/ffmpeg-kit-android-lib/build.gradle 1>>"${BASEDIR}"/build.log 2>&1
echo -e "\nBuilding ffmpeg-kit ${BUILD_TYPE_ID}library for Android\n"
echo -e -n "INFO: Building ffmpeg-kit ${BUILD_VERSION} ${BUILD_TYPE_ID}library for Android: " 1>>"${BASEDIR}"/build.log 2>&1
echo -e "$(date)\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -165,6 +188,7 @@ print_enabled_libraries
print_reconfigure_requested_libraries
print_rebuild_requested_libraries
print_redownload_requested_libraries
print_custom_libraries
# VALIDATE GPL FLAGS
for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVIDSTAB,$LIBRARY_RUBBERBAND}; do
@ -180,13 +204,13 @@ for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVI
done
echo -n -e "\nDownloading sources: "
echo -e "INFO: Downloading source code of ffmpeg and enabled external libraries.\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "INFO: Downloading the source code of ffmpeg and external libraries.\n" 1>>"${BASEDIR}"/build.log 2>&1
# DOWNLOAD GNU CONFIG
download_gnu_config
# DOWNLOAD LIBRARY SOURCES
downloaded_enabled_library_sources "${ENABLED_LIBRARIES[@]}"
downloaded_library_sources "${ENABLED_LIBRARIES[@]}"
# SAVE ORIGINAL API LEVEL = NECESSARY TO BUILD 64bit ARCHITECTURES
export ORIGINAL_API=${API}
@ -210,7 +234,7 @@ for run_arch in {0..12}; do
. "${BASEDIR}"/scripts/main-android.sh "${ENABLED_LIBRARIES[@]}" || exit 1
# CLEAR FLAGS
for library in {0..58}; do
for library in {0..61}; do
library_name=$(get_library_name ${library})
unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")"
unset "$(echo "DEPENDENCY_REBUILT_${library_name}" | sed "s/\-/\_/g")"
@ -265,10 +289,10 @@ if [[ -n ${ANDROID_ARCHITECTURES} ]]; then
cd "${BASEDIR}"/android 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
# COPY LICENSES
# COPY LIBRARY LICENSES
LICENSE_BASEDIR="${BASEDIR}"/android/ffmpeg-kit-android-lib/src/main/res/raw
rm -f "${LICENSE_BASEDIR}"/*.txt 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
for library in {0..46}; do
for library in {0..49}; do
if [[ ${ENABLED_LIBRARIES[$library]} -eq 1 ]]; then
ENABLED_LIBRARY=$(get_library_name ${library} | sed 's/-/_/g')
LICENSE_FILE="${LICENSE_BASEDIR}/license_${ENABLED_LIBRARY}.txt"
@ -285,6 +309,26 @@ if [[ -n ${ANDROID_ARCHITECTURES} ]]; then
fi
done
# COPY CUSTOM LIBRARY LICENSES
for custom_library_index in "${CUSTOM_LIBRARIES[@]}"; do
library_name="CUSTOM_LIBRARY_${custom_library_index}_NAME"
relative_license_path="CUSTOM_LIBRARY_${custom_library_index}_LICENSE_FILE"
destination_license_path="${LICENSE_BASEDIR}/license_${!library_name}.txt"
cp "${BASEDIR}/src/${!library_name}/${!relative_license_path}" "${destination_license_path}" 1>>"${BASEDIR}"/build.log 2>&1
RC=$?
if [[ ${RC} -ne 0 ]]; then
echo -e "DEBUG: Failed to copy the license file of custom library ${!library_name}\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "failed\n\nSee build.log for details\n"
exit 1
fi
echo -e "DEBUG: Copied the license file of custom library ${!library_name} successfully\n" 1>>"${BASEDIR}"/build.log 2>&1
done
# COPY LIBRARY LICENSES
if [[ ${GPL_ENABLED} == "yes" ]]; then
cp "${BASEDIR}"/LICENSE.GPLv3 "${LICENSE_BASEDIR}"/license.txt 1>>"${BASEDIR}"/build.log 2>&1

@ -5,3 +5,4 @@
/libs/
/obj/
/ffmpeg-kit-android-lib/build/
*.tmp

@ -22,7 +22,7 @@ external libraries enabled.
##### 2.1.1 Android Tools
- Android SDK Build Tools
- Android NDK r21e or later with LLDB and CMake
- Android NDK r22b or later with LLDB and CMake
##### 2.1.2 Packages
@ -77,7 +77,7 @@ All libraries created by `android.sh` can be found under the `prebuilt` director
}
dependencies {
implementation 'com.arthenica:ffmpeg-kit-full:4.5'
implementation 'com.arthenica:ffmpeg-kit-full:4.5.1'
}
```
@ -144,10 +144,10 @@ All libraries created by `android.sh` can be found under the `prebuilt` director
4. Execute asynchronous `FFmpeg` commands by providing session specific `execute`/`log`/`session` callbacks.
```java
FFmpegKit.executeAsync("-i file1.mp4 -c:v mpeg4 file2.mp4", new ExecuteCallback() {
FFmpegKit.executeAsync("-i file1.mp4 -c:v mpeg4 file2.mp4", new FFmpegSessionCompleteCallback() {
@Override
public void apply(Session session) {
public void apply(FFmpegSession session) {
SessionState state = session.getState();
ReturnCode returnCode = session.getReturnCode();
@ -189,10 +189,10 @@ All libraries created by `android.sh` can be found under the `prebuilt` director
- Asynchronous
```java
FFprobeKit.executeAsync(ffprobeCommand, new ExecuteCallback() {
FFprobeKit.executeAsync(ffprobeCommand, new FFprobeSessionCompleteCallback() {
@Override
public void apply(Session session) {
public void apply(FFprobeSession session) {
CALLED WHEN SESSION IS EXECUTED
@ -235,6 +235,14 @@ All libraries created by `android.sh` can be found under the `prebuilt` director
FFmpegKit.execute("-i file1.mp4 -c:v mpeg4 " + outputVideoPath);
```
- Writing to a file in a custom mode.
```java
Uri safUri = intent.getData();
String path = FFmpegKitConfig.getSafParameter(requireContext(), safUri, "rw");
FFmpegKit.execute("-i file1.mp4 -c:v mpeg4 " + path);
```
9. Get previous `FFmpeg` and `FFprobe` sessions from session history.
```java
@ -253,13 +261,29 @@ All libraries created by `android.sh` can be found under the `prebuilt` director
10. Enable global callbacks.
- Execute Callback, called when an async execution is ended
- Session type specific Complete Callbacks, called when an async session has been completed
```java
FFmpegKitConfig.enableExecuteCallback(new ExecuteCallback() {
FFmpegKitConfig.enableFFmpegSessionCompleteCallback(new FFmpegSessionCompleteCallback() {
@Override
public void apply(FFmpegSession session) {
}
});
FFmpegKitConfig.enableFFprobeSessionCompleteCallback(new FFprobeSessionCompleteCallback() {
@Override
public void apply(FFprobeSession session) {
}
});
FFmpegKitConfig.enableMediaInformationSessionCompleteCallback(new MediaInformationSessionCompleteCallback() {
@Override
public void apply(Session session) {
public void apply(MediaInformationSession session) {
}
});

@ -38,7 +38,7 @@ PROJECT_NAME = "FFmpegKit Android API"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.5
PROJECT_NUMBER = 4.5.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

@ -2,13 +2,13 @@ apply plugin: 'com.android.library'
android {
compileSdkVersion 30
ndkVersion "23.0.7599858"
ndkVersion "23.1.7779620"
defaultConfig {
minSdkVersion 24
targetSdkVersion 30
versionCode 240450
versionName "4.5"
versionCode 240451
versionName "4.5.1"
project.archivesBaseName = "ffmpeg-kit"
consumerProguardFiles 'proguard-rules.pro'
}
@ -44,8 +44,8 @@ task javadoc(type: Javadoc) {
}
dependencies {
implementation 'com.arthenica:smart-exception-java:0.1.0'
testImplementation "androidx.test.ext:junit:1.1.2"
implementation 'com.arthenica:smart-exception-java:0.1.1'
testImplementation "androidx.test.ext:junit:1.1.3"
testImplementation "org.json:json:20201115"
}

@ -9,7 +9,8 @@
native <methods>;
void log(long, int, byte[]);
void statistics(long, int, float, float, long , int, double, double);
void closeParcelFileDescriptor(int);
int safOpen(int);
int safClose(int);
}
-keep class com.arthenica.ffmpegkit.AbiDetect {

@ -80,8 +80,11 @@ static jmethodID logMethod;
/** Global reference of statistics redirection method in Java */
static jmethodID statisticsMethod;
/** Global reference of closeParcelFileDescriptor method in Java */
static jmethodID closeParcelFileDescriptorMethod;
/** Global reference of safOpen method in Java */
static jmethodID safOpenMethod;
/** Global reference of safClose method in Java */
static jmethodID safCloseMethod;
/** Global reference of String class in Java */
static jclass stringClass;
@ -561,13 +564,21 @@ void *callbackThreadFunction() {
}
/**
* Used by fd and saf protocols; is expected to be called from a Java thread, therefore we don't need attach/detach
* Used by saf protocol; is expected to be called from a Java thread, therefore we don't need attach/detach
*/
int close_parcel_file_descriptor(int fd) {
int saf_open(int safId) {
JNIEnv *env = NULL;
(*globalVm)->GetEnv(globalVm, (void**) &env, JNI_VERSION_1_6);
(*env)->CallStaticVoidMethod(env, configClass, closeParcelFileDescriptorMethod, fd);
return 0;
return (*env)->CallStaticIntMethod(env, configClass, safOpenMethod, safId);
}
/**
* Used by saf protocol; is expected to be called from a Java thread, therefore we don't need attach/detach
*/
int saf_close(int fd) {
JNIEnv *env = NULL;
(*globalVm)->GetEnv(globalVm, (void**) &env, JNI_VERSION_1_6);
return (*env)->CallStaticIntMethod(env, configClass, safCloseMethod, fd);
}
/**
@ -615,9 +626,15 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
return JNI_FALSE;
}
closeParcelFileDescriptorMethod = (*env)->GetStaticMethodID(env, localConfigClass, "closeParcelFileDescriptor", "(I)V");
safOpenMethod = (*env)->GetStaticMethodID(env, localConfigClass, "safOpen", "(I)I");
if (logMethod == NULL) {
LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "safOpen");
return JNI_FALSE;
}
safCloseMethod = (*env)->GetStaticMethodID(env, localConfigClass, "safClose", "(I)I");
if (logMethod == NULL) {
LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "closeParcelFileDescriptor");
LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "safClose");
return JNI_FALSE;
}
@ -645,7 +662,8 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
redirectionEnabled = 0;
av_set_fd_close(close_parcel_file_descriptor);
av_set_saf_open(saf_open);
av_set_saf_close(saf_close);
return JNI_VERSION_1_6;
}

@ -27,7 +27,7 @@
#include "libavutil/ffversion.h"
/** Library version string */
#define FFMPEG_KIT_VERSION "4.5"
#define FFMPEG_KIT_VERSION "4.5.1"
/** Defines tag used for Android logging. */
#define LIB_NAME "ffmpeg-kit"

@ -28,8 +28,8 @@ 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.
* Abstract session implementation which includes common features shared by <code>FFmpeg</code>,
* <code>FFprobe</code> and <code>MediaInformation</code> sessions.
*/
public abstract class AbstractSession implements Session {
@ -49,12 +49,7 @@ public abstract class AbstractSession implements Session {
protected final long sessionId;
/**
* Session specific execute callback function.
*/
protected final ExecuteCallback executeCallback;
/**
* Session specific log callback function.
* Session specific log callback.
*/
protected final LogCallback logCallback;
@ -117,16 +112,13 @@ public abstract class AbstractSession implements Session {
* Creates a new abstract session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param logCallback session specific log callback function
* @param logCallback session specific log callback
* @param logRedirectionStrategy session specific log redirection strategy
*/
public AbstractSession(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
this.sessionId = sessionIdGenerator.getAndIncrement();
this.executeCallback = executeCallback;
this.logCallback = logCallback;
this.createTime = new Date();
this.startTime = null;
@ -143,11 +135,6 @@ public abstract class AbstractSession implements Session {
FFmpegKitConfig.addSession(this);
}
@Override
public ExecuteCallback getExecuteCallback() {
return executeCallback;
}
@Override
public LogCallback getLogCallback() {
return logCallback;

@ -19,29 +19,41 @@
package com.arthenica.ffmpegkit;
import com.arthenica.smartexception.java.Exceptions;
/**
* <p>Executes an FFmpeg session asynchronously.
*/
public class AsyncFFmpegExecuteTask implements Runnable {
private final FFmpegSession ffmpegSession;
private final ExecuteCallback executeCallback;
private final FFmpegSessionCompleteCallback completeCallback;
public AsyncFFmpegExecuteTask(final FFmpegSession ffmpegSession) {
this.ffmpegSession = ffmpegSession;
this.executeCallback = ffmpegSession.getExecuteCallback();
this.completeCallback = ffmpegSession.getCompleteCallback();
}
@Override
public void run() {
FFmpegKitConfig.ffmpegExecute(ffmpegSession);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback();
if (globalExecuteCallbackFunction != null) {
globalExecuteCallbackFunction.apply(ffmpegSession);
if (completeCallback != null) {
try {
// NOTIFY SESSION CALLBACK DEFINED
completeCallback.apply(ffmpegSession);
} catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session complete callback.%s", Exceptions.getStackTraceString(e)));
}
}
if (executeCallback != null) {
executeCallback.apply(ffmpegSession);
final FFmpegSessionCompleteCallback globalFFmpegSessionCompleteCallback = FFmpegKitConfig.getFFmpegSessionCompleteCallback();
if (globalFFmpegSessionCompleteCallback != null) {
try {
// NOTIFY GLOBAL CALLBACK DEFINED
globalFFmpegSessionCompleteCallback.apply(ffmpegSession);
} catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global complete callback.%s", Exceptions.getStackTraceString(e)));
}
}
}
}

@ -19,29 +19,41 @@
package com.arthenica.ffmpegkit;
import com.arthenica.smartexception.java.Exceptions;
/**
* <p>Executes an FFprobe session asynchronously.
*/
public class AsyncFFprobeExecuteTask implements Runnable {
private final FFprobeSession ffprobeSession;
private final ExecuteCallback executeCallback;
private final FFprobeSessionCompleteCallback completeCallback;
public AsyncFFprobeExecuteTask(final FFprobeSession ffprobeSession) {
this.ffprobeSession = ffprobeSession;
this.executeCallback = ffprobeSession.getExecuteCallback();
this.completeCallback = ffprobeSession.getCompleteCallback();
}
@Override
public void run() {
FFmpegKitConfig.ffprobeExecute(ffprobeSession);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback();
if (globalExecuteCallbackFunction != null) {
globalExecuteCallbackFunction.apply(ffprobeSession);
if (completeCallback != null) {
try {
// NOTIFY SESSION CALLBACK DEFINED
completeCallback.apply(ffprobeSession);
} catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session complete callback.%s", Exceptions.getStackTraceString(e)));
}
}
if (executeCallback != null) {
executeCallback.apply(ffprobeSession);
final FFprobeSessionCompleteCallback globalFFprobeSessionCompleteCallback = FFmpegKitConfig.getFFprobeSessionCompleteCallback();
if (globalFFprobeSessionCompleteCallback != null) {
try {
// NOTIFY GLOBAL CALLBACK DEFINED
globalFFprobeSessionCompleteCallback.apply(ffprobeSession);
} catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global complete callback.%s", Exceptions.getStackTraceString(e)));
}
}
}

@ -19,12 +19,14 @@
package com.arthenica.ffmpegkit;
import com.arthenica.smartexception.java.Exceptions;
/**
* <p>Executes a MediaInformation session asynchronously.
*/
public class AsyncGetMediaInformationTask implements Runnable {
private final MediaInformationSession mediaInformationSession;
private final ExecuteCallback executeCallback;
private final MediaInformationSessionCompleteCallback completeCallback;
private final Integer waitTimeout;
public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession) {
@ -33,7 +35,7 @@ public class AsyncGetMediaInformationTask implements Runnable {
public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession, final Integer waitTimeout) {
this.mediaInformationSession = mediaInformationSession;
this.executeCallback = mediaInformationSession.getExecuteCallback();
this.completeCallback = mediaInformationSession.getCompleteCallback();
this.waitTimeout = waitTimeout;
}
@ -41,13 +43,23 @@ public class AsyncGetMediaInformationTask implements Runnable {
public void run() {
FFmpegKitConfig.getMediaInformationExecute(mediaInformationSession, waitTimeout);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback();
if (globalExecuteCallbackFunction != null) {
globalExecuteCallbackFunction.apply(mediaInformationSession);
if (completeCallback != null) {
try {
// NOTIFY SESSION CALLBACK DEFINED
completeCallback.apply(mediaInformationSession);
} catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session complete callback.%s", Exceptions.getStackTraceString(e)));
}
}
if (executeCallback != null) {
executeCallback.apply(mediaInformationSession);
final MediaInformationSessionCompleteCallback globalMediaInformationSessionCompleteCallback = FFmpegKitConfig.getMediaInformationSessionCompleteCallback();
if (globalMediaInformationSessionCompleteCallback != null) {
try {
// NOTIFY GLOBAL CALLBACK DEFINEDs
globalMediaInformationSessionCompleteCallback.apply(mediaInformationSession);
} catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global complete callback.%s", Exceptions.getStackTraceString(e)));
}
}
}

@ -0,0 +1,131 @@
/*
* 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.json.JSONObject;
public class Chapter {
/* KEYS */
public static final String KEY_ID = "id";
public static final String KEY_TIME_BASE = "time_base";
public static final String KEY_START = "start";
public static final String KEY_START_TIME = "start_time";
public static final String KEY_END = "end";
public static final String KEY_END_TIME = "end_time";
public static final String KEY_TAGS = "tags";
private final JSONObject jsonObject;
public Chapter(JSONObject jsonObject) {
this.jsonObject = jsonObject;
}
public Long getId() {
return getNumberProperty(KEY_ID);
}
public String getTimeBase() {
return getStringProperty(KEY_TIME_BASE);
}
public Long getStart() {
return getNumberProperty(KEY_START);
}
public String getStartTime() {
return getStringProperty(KEY_START_TIME);
}
public Long getEnd() {
return getNumberProperty(KEY_END);
}
public String getEndTime() {
return getStringProperty(KEY_END_TIME);
}
public JSONObject getTags() {
return getProperties(KEY_TAGS);
}
/**
* Returns the chapter property associated with the key.
*
* @param key property key
* @return chapter property as string or null if the key is not found
*/
public String getStringProperty(final String key) {
JSONObject chapterProperties = getAllProperties();
if (chapterProperties == null) {
return null;
}
if (chapterProperties.has(key)) {
return chapterProperties.optString(key);
} else {
return null;
}
}
/**
* Returns the chapter property associated with the key.
*
* @param key property key
* @return chapter property as Long or null if the key is not found
*/
public Long getNumberProperty(String key) {
JSONObject chapterProperties = getAllProperties();
if (chapterProperties == null) {
return null;
}
if (chapterProperties.has(key)) {
return chapterProperties.optLong(key);
} else {
return null;
}
}
/**
* Returns the chapter properties associated with the key.
*
* @param key properties key
* @return chapter properties as a JSONObject or null if the key is not found
*/
public JSONObject getProperties(String key) {
JSONObject chapterProperties = getAllProperties();
if (chapterProperties == null) {
return null;
}
return chapterProperties.optJSONObject(key);
}
/**
* Returns all chapter properties defined.
*
* @return all chapter properties as a JSONObject or null if no properties are defined
*/
public JSONObject getAllProperties() {
return jsonObject;
}
}

@ -1,51 +0,0 @@
/*
* Copyright (c) 2018-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;
/**
* <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 asynchronous session ends running.
*
* @param session session
*/
void apply(final Session session);
}

@ -19,21 +19,20 @@
package com.arthenica.ffmpegkit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
/**
* <p>Main class to run <code>FFmpeg</code> commands. Supports executing commands both synchronously and
* asynchronously.
* <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", executeCallback);
* FFmpegSession asyncSession = FFmpegKit.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", completeCallback);
* </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre>
* FFmpegSession asyncSession = FFmpegKit.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", executeCallback, logCallback, statisticsCallback);
* FFmpegSession asyncSession = FFmpegKit.executeAsync("-i file1.mp4 -c:v libxvid file1.avi", completeCallback, logCallback, statisticsCallback);
* </pre>
*/
public class FFmpegKit {
@ -55,7 +54,7 @@ public class FFmpegKit {
* @param arguments FFmpeg command options/arguments as string array
* @return FFmpeg session created for this execution
*/
public static FFmpegSession execute(final String[] arguments) {
public static FFmpegSession executeWithArguments(final String[] arguments) {
final FFmpegSession session = new FFmpegSession(arguments);
FFmpegKitConfig.ffmpegExecute(session);
@ -66,16 +65,17 @@ public class FFmpegKit {
/**
* <p>Starts an asynchronous FFmpeg execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param arguments FFmpeg command options/arguments as string array
* @param completeCallback callback that will be called when the execution has 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);
public static FFmpegSession executeWithArgumentsAsync(final String[] arguments,
final FFmpegSessionCompleteCallback completeCallback) {
final FFmpegSession session = new FFmpegSession(arguments, completeCallback);
FFmpegKitConfig.asyncFFmpegExecute(session);
@ -85,20 +85,21 @@ public class FFmpegKit {
/**
* <p>Starts an asynchronous FFmpeg execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, logCallback, statisticsCallback);
public static FFmpegSession executeWithArgumentsAsync(final String[] arguments,
final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback) {
final FFmpegSession session = new FFmpegSession(arguments, completeCallback, logCallback, statisticsCallback);
FFmpegKitConfig.asyncFFmpegExecute(session);
@ -108,18 +109,19 @@ public class FFmpegKit {
/**
* <p>Starts an asynchronous FFmpeg execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param arguments FFmpeg 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
* @param arguments FFmpeg command options/arguments as string array
* @param completeCallback callback that will be called when the execution has 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 ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback);
public static FFmpegSession executeWithArgumentsAsync(final String[] arguments,
final FFmpegSessionCompleteCallback completeCallback,
final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, completeCallback);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
@ -129,22 +131,24 @@ public class FFmpegKit {
/**
* <p>Starts an asynchronous FFmpeg execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics
* @param executorService executor service that will be used to run this asynchronous operation
* @param 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 ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, logCallback, statisticsCallback);
public static FFmpegSession executeWithArgumentsAsync(final String[] arguments,
final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, completeCallback, logCallback, statisticsCallback);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
@ -160,61 +164,67 @@ public class FFmpegKit {
* @return FFmpeg session created for this execution
*/
public static FFmpegSession execute(final String command) {
return execute(FFmpegKitConfig.parseArguments(command));
return executeWithArguments(FFmpegKitConfig.parseArguments(command));
}
/**
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to
* split the command into arguments. You can use single or double quote characters to specify
* arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param command FFmpeg command
* @param executeCallback callback that will be called when the execution is completed
* @param command FFmpeg command
* @param completeCallback callback that will be called when the execution has completed
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback) {
return executeAsync(FFmpegKitConfig.parseArguments(command), executeCallback);
final FFmpegSessionCompleteCallback completeCallback) {
return executeWithArgumentsAsync(FFmpegKitConfig.parseArguments(command), completeCallback);
}
/**
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to
* split the command into arguments. You can use single or double quote characters to specify
* arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param command FFmpeg command
* @param executeCallback callback that will be called when the execution is completed
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback,
final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback) {
return executeAsync(FFmpegKitConfig.parseArguments(command), executeCallback, logCallback, statisticsCallback);
return executeWithArgumentsAsync(FFmpegKitConfig.parseArguments(command), completeCallback, logCallback, statisticsCallback);
}
/**
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to
* split the command into arguments. You can use single or double quote characters to specify
* arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param command FFmpeg 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
* @param command FFmpeg command
* @param completeCallback callback that will be called when the execution has 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 FFmpegSessionCompleteCallback completeCallback,
final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(FFmpegKitConfig.parseArguments(command), executeCallback);
final FFmpegSession session = new FFmpegSession(FFmpegKitConfig.parseArguments(command), completeCallback);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
@ -222,25 +232,27 @@ public class FFmpegKit {
}
/**
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to
* split the command into arguments. You can use single or double quote characters to specify
* arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param command FFmpeg command
* @param executeCallback callback that will be called when the execution is completed
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics
* @param executorService executor service that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/
public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback,
final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(FFmpegKitConfig.parseArguments(command), executeCallback, logCallback, statisticsCallback);
final FFmpegSession session = new FFmpegSession(FFmpegKitConfig.parseArguments(command), completeCallback, logCallback, statisticsCallback);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
@ -250,7 +262,7 @@ public class FFmpegKit {
/**
* <p>Cancels all running sessions.
*
* <p>This function does not wait for termination to complete and returns immediately.
* <p>This method does not wait for termination to complete and returns immediately.
*/
public static void cancel() {
@ -265,7 +277,7 @@ public class FFmpegKit {
/**
* <p>Cancels the session specified with <code>sessionId</code>.
*
* <p>This function does not wait for termination to complete and returns immediately.
* <p>This method does not wait for termination to complete and returns immediately.
*
* @param sessionId id of the session that will be cancelled
*/

@ -19,6 +19,8 @@
package com.arthenica.ffmpegkit;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
@ -44,7 +46,7 @@ import java.util.StringTokenizer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
/**
@ -52,6 +54,45 @@ import java.util.concurrent.atomic.AtomicReference;
*/
public class FFmpegKitConfig {
static class SAFProtocolUrl {
private final Integer safId;
private final Uri uri;
private final String openMode;
private final ContentResolver contentResolver;
private ParcelFileDescriptor parcelFileDescriptor;
public SAFProtocolUrl(final Integer safId, final Uri uri, final String openMode, final ContentResolver contentResolver) {
this.safId = safId;
this.uri = uri;
this.openMode = openMode;
this.contentResolver = contentResolver;
}
public Integer getSafId() {
return safId;
}
public Uri getUri() {
return uri;
}
public String getOpenMode() {
return openMode;
}
public ContentResolver getContentResolver() {
return contentResolver;
}
public void setParcelFileDescriptor(final ParcelFileDescriptor parcelFileDescriptor) {
this.parcelFileDescriptor = parcelFileDescriptor;
}
public ParcelFileDescriptor getParcelFileDescriptor() {
return parcelFileDescriptor;
}
}
/**
* The tag used for logging.
*/
@ -63,9 +104,9 @@ public class FFmpegKitConfig {
static final String FFMPEG_KIT_NAMED_PIPE_PREFIX = "fk_pipe_";
/**
* Generates ids for named ffmpeg kit pipes.
* Generates ids for named ffmpeg kit pipes and saf protocol urls.
*/
private static final AtomicLong pipeIndexGenerator;
private static final AtomicInteger uniqueIdGenerator;
private static Level activeLogLevel;
@ -79,10 +120,13 @@ public class FFmpegKitConfig {
private static ExecutorService asyncExecutorService;
/* Global callbacks */
private static LogCallback globalLogCallbackFunction;
private static StatisticsCallback globalStatisticsCallbackFunction;
private static ExecuteCallback globalExecuteCallbackFunction;
private static final SparseArray<ParcelFileDescriptor> pfdMap;
private static LogCallback globalLogCallback;
private static StatisticsCallback globalStatisticsCallback;
private static FFmpegSessionCompleteCallback globalFFmpegSessionCompleteCallback;
private static FFprobeSessionCompleteCallback globalFFprobeSessionCompleteCallback;
private static MediaInformationSessionCompleteCallback globalMediaInformationSessionCompleteCallback;
private static final SparseArray<SAFProtocolUrl> safIdMap;
private static final SparseArray<SAFProtocolUrl> safFileDescriptorMap;
private static LogRedirectionStrategy globalLogRedirectionStrategy;
static {
@ -102,7 +146,7 @@ public class FFmpegKitConfig {
android.util.Log.i(FFmpegKitConfig.TAG, String.format("Loaded ffmpeg-kit-%s-%s-%s-%s.", NativeLoader.loadPackageName(), NativeLoader.loadAbi(), NativeLoader.loadVersion(), NativeLoader.loadBuildDate()));
pipeIndexGenerator = new AtomicLong(1);
uniqueIdGenerator = new AtomicInteger(1);
/* NATIVE LOG LEVEL IS RECEIVED ONLY ON STARTUP */
activeLogLevel = Level.from(NativeLoader.loadLogLevel());
@ -121,11 +165,14 @@ public class FFmpegKitConfig {
sessionHistoryList = new LinkedList<>();
sessionHistoryLock = new Object();
globalLogCallbackFunction = null;
globalStatisticsCallbackFunction = null;
globalExecuteCallbackFunction = null;
globalLogCallback = null;
globalStatisticsCallback = null;
globalFFmpegSessionCompleteCallback = null;
globalFFprobeSessionCompleteCallback = null;
globalMediaInformationSessionCompleteCallback = null;
pfdMap = new SparseArray<>();
safIdMap = new SparseArray<>();
safFileDescriptorMap = new SparseArray<>();
globalLogRedirectionStrategy = LogRedirectionStrategy.PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED;
NativeLoader.enableRedirection();
@ -196,12 +243,12 @@ public class FFmpegKitConfig {
// 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)));
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session log callback.%s", Exceptions.getStackTraceString(e)));
}
}
}
final LogCallback globalLogCallbackFunction = FFmpegKitConfig.globalLogCallbackFunction;
final LogCallback globalLogCallbackFunction = FFmpegKitConfig.globalLogCallback;
if (globalLogCallbackFunction != null) {
globalCallbackDefined = true;
@ -209,7 +256,7 @@ public class FFmpegKitConfig {
// 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)));
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global log callback.%s", Exceptions.getStackTraceString(e)));
}
}
@ -229,13 +276,16 @@ public class FFmpegKitConfig {
return;
}
}
break;
case PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED: {
if (globalCallbackDefined || sessionCallbackDefined) {
return;
}
}
break;
case ALWAYS_PRINT_LOGS: {
}
break;
}
// PRINT LOGS
@ -299,18 +349,18 @@ public class FFmpegKitConfig {
// NOTIFY SESSION CALLBACK IF DEFINED
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)));
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session statistics callback.%s", Exceptions.getStackTraceString(e)));
}
}
}
final StatisticsCallback globalStatisticsCallbackFunction = FFmpegKitConfig.globalStatisticsCallbackFunction;
final StatisticsCallback globalStatisticsCallbackFunction = FFmpegKitConfig.globalStatisticsCallback;
if (globalStatisticsCallbackFunction != null) {
try {
// NOTIFY GLOBAL CALLBACK IF DEFINED
globalStatisticsCallbackFunction.apply(statistics);
} catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global StatisticsCallback block.%s", Exceptions.getStackTraceString(e)));
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global statistics callback.%s", Exceptions.getStackTraceString(e)));
}
}
}
@ -458,7 +508,7 @@ public class FFmpegKitConfig {
}
}
final String newFFmpegPipePath = MessageFormat.format("{0}{1}{2}{3}", pipesDir, File.separator, FFMPEG_KIT_NAMED_PIPE_PREFIX, pipeIndexGenerator.getAndIncrement());
final String newFFmpegPipePath = MessageFormat.format("{0}{1}{2}{3}", pipesDir, File.separator, FFMPEG_KIT_NAMED_PIPE_PREFIX, uniqueIdGenerator.getAndIncrement());
// FIRST CLOSE OLD PIPES WITH THE SAME NAME
closeFFmpegPipe(newFFmpegPipePath);
@ -645,7 +695,7 @@ public class FFmpegKitConfig {
final int returnCodeValue = nativeFFprobeExecute(mediaInformationSession.getSessionId(), mediaInformationSession.getArguments());
final ReturnCode returnCode = new ReturnCode(returnCodeValue);
mediaInformationSession.complete(returnCode);
if (returnCode.isSuccess()) {
if (returnCode.isValueSuccess()) {
MediaInformation mediaInformation = MediaInformationJsonParser.fromWithError(mediaInformationSession.getAllLogsAsString(waitTimeout));
mediaInformationSession.setMediaInformation(mediaInformation);
}
@ -658,8 +708,9 @@ public class FFmpegKitConfig {
/**
* <p>Starts an asynchronous FFmpeg execution for the given session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param ffmpegSession FFmpeg session which includes command options/arguments
*/
@ -672,8 +723,9 @@ public class FFmpegKitConfig {
/**
* <p>Starts an asynchronous FFmpeg execution for the given session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param ffmpegSession FFmpeg session which includes command options/arguments
* @param executorService executor service that will be used to run this asynchronous operation
@ -687,8 +739,9 @@ public class FFmpegKitConfig {
/**
* <p>Starts an asynchronous FFprobe execution for the given session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param ffprobeSession FFprobe session which includes command options/arguments
*/
@ -701,8 +754,9 @@ public class FFmpegKitConfig {
/**
* <p>Starts an asynchronous FFprobe execution for the given session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param ffprobeSession FFprobe session which includes command options/arguments
* @param executorService executor service that will be used to run this asynchronous operation
@ -716,10 +770,12 @@ public class FFmpegKitConfig {
/**
* <p>Starts an asynchronous FFprobe execution for the given media information session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use a {@link MediaInformationSessionCompleteCallback} if you want to be notified
* about the result.
*
* @param mediaInformationSession media information session which includes command options/arguments
* @param mediaInformationSession media information session which includes command
* options/arguments
* @param waitTimeout max time to wait until media information is transmitted
*/
public static void asyncGetMediaInformationExecute(final MediaInformationSession mediaInformationSession, final int waitTimeout) {
@ -731,11 +787,14 @@ public class FFmpegKitConfig {
/**
* <p>Starts an asynchronous FFprobe execution for the given media information session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use a {@link MediaInformationSessionCompleteCallback} if you want to be notified
* about the result.
*
* @param mediaInformationSession media information session which includes command options/arguments
* @param executorService executor service that will be used to run this asynchronous operation
* @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) {
@ -776,42 +835,82 @@ public class FFmpegKitConfig {
}
/**
* <p>Sets a global callback function to redirect FFmpeg/FFprobe logs.
* <p>Sets a global callback to redirect FFmpeg/FFprobe logs.
*
* @param logCallback log callback function or null to disable a previously defined
* callback
* @param logCallback log callback or null to disable a previously defined callback
*/
public static void enableLogCallback(final LogCallback logCallback) {
globalLogCallbackFunction = logCallback;
globalLogCallback = logCallback;
}
/**
* <p>Sets a global callback function to redirect FFmpeg statistics.
* <p>Sets a global callback to redirect FFmpeg statistics.
*
* @param statisticsCallback statistics callback function or null to disable a previously
* @param statisticsCallback statistics callback or null to disable a previously
* defined callback
*/
public static void enableStatisticsCallback(final StatisticsCallback statisticsCallback) {
globalStatisticsCallbackFunction = statisticsCallback;
globalStatisticsCallback = statisticsCallback;
}
/**
* <p>Sets a global callback function to receive execution results.
* <p>Sets a global FFmpegSessionCompleteCallback to receive execution results for FFmpeg
* sessions.
*
* @param executeCallback execute callback function or null to disable a previously
* defined callback
* @param ffmpegSessionCompleteCallback complete callback or null to disable a
* previously defined callback
*/
public static void enableExecuteCallback(final ExecuteCallback executeCallback) {
globalExecuteCallbackFunction = executeCallback;
public static void enableFFmpegSessionCompleteCallback(final FFmpegSessionCompleteCallback ffmpegSessionCompleteCallback) {
globalFFmpegSessionCompleteCallback = ffmpegSessionCompleteCallback;
}
/**
* <p>Returns the global execute callback function.
* <p>Returns the global FFmpegSessionCompleteCallback set.
*
* @return global execute callback function
* @return global FFmpegSessionCompleteCallback or null if it is not set
*/
static ExecuteCallback getExecuteCallback() {
return globalExecuteCallbackFunction;
public static FFmpegSessionCompleteCallback getFFmpegSessionCompleteCallback() {
return globalFFmpegSessionCompleteCallback;
}
/**
* <p>Sets a global FFprobeSessionCompleteCallback to receive execution results for FFprobe
* sessions.
*
* @param ffprobeSessionCompleteCallback complete callback or null to disable a
* previously defined callback
*/
public static void enableFFprobeSessionCompleteCallback(final FFprobeSessionCompleteCallback ffprobeSessionCompleteCallback) {
globalFFprobeSessionCompleteCallback = ffprobeSessionCompleteCallback;
}
/**
* <p>Returns the global FFprobeSessionCompleteCallback set.
*
* @return global FFprobeSessionCompleteCallback or null if it is not set
*/
public static FFprobeSessionCompleteCallback getFFprobeSessionCompleteCallback() {
return globalFFprobeSessionCompleteCallback;
}
/**
* <p>Sets a global MediaInformationSessionCompleteCallback to receive execution results for
* MediaInformation sessions.
*
* @param mediaInformationSessionCompleteCallback complete callback or null to disable
* a previously defined callback
*/
public static void enableMediaInformationSessionCompleteCallback(final MediaInformationSessionCompleteCallback mediaInformationSessionCompleteCallback) {
globalMediaInformationSessionCompleteCallback = mediaInformationSessionCompleteCallback;
}
/**
* <p>Returns the global MediaInformationSessionCompleteCallback set.
*
* @return global MediaInformationSessionCompleteCallback or null if it is not set
*/
public static MediaInformationSessionCompleteCallback getMediaInformationSessionCompleteCallback() {
return globalMediaInformationSessionCompleteCallback;
}
/**
@ -851,13 +950,16 @@ public class FFmpegKitConfig {
/**
* <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an
* input/output url that can be used in FFmpeg and FFprobe commands.
* SAF protocol url that can be used in FFmpeg and FFprobe commands.
*
* <p>Requires API Level >= 19. On older API levels it returns an empty url.
* <p>Requires API Level 19+. On older API levels it returns an empty url.
*
* @param context application context
* @param uri SAF uri
* @param openMode file mode to use as defined in {@link ContentProvider#openFile ContentProvider.openFile}
* @return input/output url that can be passed to FFmpegKit or FFprobeKit
*/
private static String getSafParameter(final Context context, final Uri uri, final String openMode) {
public static String getSafParameter(final Context context, final Uri uri, final String openMode) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
android.util.Log.i(TAG, String.format("getSafParameter is not supported on API Level %d", Build.VERSION.SDK_INT));
return "";
@ -870,28 +972,23 @@ public class FFmpegKitConfig {
}
} catch (final Throwable t) {
android.util.Log.e(TAG, String.format("Failed to get %s column for %s.%s", DocumentsContract.Document.COLUMN_DISPLAY_NAME, uri.toString(), Exceptions.getStackTraceString(t)));
throw t;
}
int fd = -1;
try {
ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(uri, openMode);
fd = parcelFileDescriptor.getFd();
pfdMap.put(fd, parcelFileDescriptor);
} catch (final Throwable t) {
android.util.Log.e(TAG, String.format("Failed to obtain %s parcelFileDescriptor for %s.%s", openMode, uri.toString(), Exceptions.getStackTraceString(t)));
}
final int safId = uniqueIdGenerator.getAndIncrement();
safIdMap.put(safId, new SAFProtocolUrl(safId, uri, openMode, context.getContentResolver()));
return "saf:" + fd + "." + FFmpegKitConfig.extractExtensionFromSafDisplayName(displayName);
return "saf:" + safId + "." + FFmpegKitConfig.extractExtensionFromSafDisplayName(displayName);
}
/**
* <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an
* input url that can be used in FFmpeg and FFprobe commands.
* SAF protocol url that can be used in FFmpeg and FFprobe commands.
*
* <p>Requires API Level &ge; 19. On older API levels it returns an empty url.
*
* @param context application context
* @param uri saf uri
* @param uri SAF uri
* @return input url that can be passed to FFmpegKit or FFprobeKit
*/
public static String getSafParameterForRead(final Context context, final Uri uri) {
@ -900,12 +997,12 @@ public class FFmpegKitConfig {
/**
* <p>Converts the given Structured Access Framework Uri (<code>"content:…"</code>) into an
* output url that can be used in FFmpeg and FFprobe commands.
* SAF protocol url that can be used in FFmpeg and FFprobe commands.
*
* <p>Requires API Level &ge; 19. On older API levels it returns an empty url.
*
* @param context application context
* @param uri saf uri
* @param uri SAF uri
* @return output url that can be passed to FFmpegKit or FFprobeKit
*/
public static String getSafParameterForWrite(final Context context, final Uri uri) {
@ -913,20 +1010,57 @@ public class FFmpegKitConfig {
}
/**
* Called by saf_wrapper from native library to close a parcel file descriptor.
* Called from native library to open an SAF protocol url.
*
* @param fd parcel file descriptor created for a saf uri
* @param safId SAF id part of an SAF protocol url
* @return file descriptor created for this SAF id or 0 if an error occurs
*/
private static void closeParcelFileDescriptor(final int fd) {
private static int safOpen(final int safId) {
try {
ParcelFileDescriptor pfd = pfdMap.get(fd);
if (pfd != null) {
pfd.close();
pfdMap.delete(fd);
SAFProtocolUrl safUrl = safIdMap.get(safId);
if (safUrl != null) {
final ParcelFileDescriptor parcelFileDescriptor = safUrl.getContentResolver().openFileDescriptor(safUrl.getUri(), safUrl.getOpenMode());
safUrl.setParcelFileDescriptor(parcelFileDescriptor);
final int fd = parcelFileDescriptor.getFd();
safFileDescriptorMap.put(fd, safUrl);
return fd;
} else {
android.util.Log.e(TAG, String.format("SAF id %d not found.", safId));
}
} catch (final Throwable t) {
android.util.Log.e(TAG, String.format("Failed to close file descriptor: %d.%s", fd, Exceptions.getStackTraceString(t)));
android.util.Log.e(TAG, String.format("Failed to open SAF id: %d.%s", safId, Exceptions.getStackTraceString(t)));
}
return 0;
}
/**
* Called from native library to close a file descriptor created for a SAF protocol url.
*
* @param fileDescriptor file descriptor that belongs to a SAF protocol url
* @return 1 if the given file descriptor is closed successfully, 0 if an error occurs
*/
private static int safClose(final int fileDescriptor) {
try {
final SAFProtocolUrl safProtocolUrl = safFileDescriptorMap.get(fileDescriptor);
if (safProtocolUrl != null) {
ParcelFileDescriptor parcelFileDescriptor = safProtocolUrl.getParcelFileDescriptor();
if (parcelFileDescriptor != null) {
safFileDescriptorMap.delete(fileDescriptor);
safIdMap.delete(safProtocolUrl.getSafId());
parcelFileDescriptor.close();
return 1;
} else {
android.util.Log.e(TAG, String.format("ParcelFileDescriptor for SAF fd %d not found.", fileDescriptor));
}
} else {
android.util.Log.e(TAG, String.format("SAF fd %d not found.", fileDescriptor));
}
} catch (final Throwable t) {
android.util.Log.e(TAG, String.format("Failed to close SAF fd: %d.%s", fileDescriptor, Exceptions.getStackTraceString(t)));
}
return 0;
}
/**
@ -1045,6 +1179,7 @@ public class FFmpegKitConfig {
public static void clearSessions() {
synchronized (sessionHistoryLock) {
sessionHistoryList.clear();
sessionHistoryMap.clear();
}
}
@ -1053,7 +1188,7 @@ public class FFmpegKitConfig {
*
* @return all FFmpeg sessions in the session history
*/
static List<FFmpegSession> getFFmpegSessions() {
public static List<FFmpegSession> getFFmpegSessions() {
final LinkedList<FFmpegSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) {
@ -1072,7 +1207,7 @@ public class FFmpegKitConfig {
*
* @return all FFprobe sessions in the session history
*/
static List<FFprobeSession> getFFprobeSessions() {
public static List<FFprobeSession> getFFprobeSessions() {
final LinkedList<FFprobeSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) {
@ -1086,6 +1221,25 @@ public class FFmpegKitConfig {
return list;
}
/**
* <p>Returns all MediaInformation sessions in the session history.
*
* @return all MediaInformation sessions in the session history
*/
public static List<MediaInformationSession> getMediaInformationSessions() {
final LinkedList<MediaInformationSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) {
for (Session session : sessionHistoryList) {
if (session.isMediaInformation()) {
list.add((MediaInformationSession) session);
}
}
}
return list;
}
/**
* <p>Returns sessions that have the given state.
*
@ -1124,6 +1278,16 @@ public class FFmpegKitConfig {
FFmpegKitConfig.globalLogRedirectionStrategy = logRedirectionStrategy;
}
/**
* Converts session state to string.
*
* @param state session state
* @return string value
*/
public static String sessionStateToString(final SessionState state) {
return state.toString();
}
/**
* <p>Parses the given command into arguments. Uses space character to split the arguments.
* Supports single and double quote characters.
@ -1265,7 +1429,7 @@ public class FFmpegKitConfig {
native static int nativeFFprobeExecute(final long sessionId, final String[] arguments);
/**
* <p>Cancels an ongoing FFmpeg operation natively. This function does not wait for termination
* <p>Cancels an ongoing FFmpeg operation natively. This method does not wait for termination
* to complete and returns immediately.
*
* @param sessionId id of the session

@ -28,10 +28,15 @@ import java.util.List;
public class FFmpegSession extends AbstractSession implements Session {
/**
* Session specific statistics callback function.
* Session specific statistics callback.
*/
private final StatisticsCallback statisticsCallback;
/**
* Session specific complete callback.
*/
private final FFmpegSessionCompleteCallback completeCallback;
/**
* Statistics entries received for this session.
*/
@ -54,44 +59,45 @@ public class FFmpegSession extends AbstractSession implements Session {
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param arguments command arguments
* @param completeCallback session specific complete callback
*/
public FFmpegSession(final String[] arguments, final ExecuteCallback executeCallback) {
this(arguments, executeCallback, null, null);
public FFmpegSession(final String[] arguments, final FFmpegSessionCompleteCallback completeCallback) {
this(arguments, completeCallback, 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
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback
*/
public FFmpegSession(final String[] arguments,
final ExecuteCallback executeCallback,
final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback) {
this(arguments, executeCallback, logCallback, statisticsCallback, FFmpegKitConfig.getLogRedirectionStrategy());
this(arguments, completeCallback, 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 completeCallback session specific complete callback
* @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback
* @param logRedirectionStrategy session specific log redirection strategy
*/
public FFmpegSession(final String[] arguments,
final ExecuteCallback executeCallback,
final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final StatisticsCallback statisticsCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
super(arguments, executeCallback, logCallback, logRedirectionStrategy);
super(arguments, logCallback, logRedirectionStrategy);
this.completeCallback = completeCallback;
this.statisticsCallback = statisticsCallback;
this.statistics = new LinkedList<>();
@ -99,14 +105,23 @@ public class FFmpegSession extends AbstractSession implements Session {
}
/**
* Returns the session specific statistics callback function.
* Returns the session specific statistics callback.
*
* @return session specific statistics callback function
* @return session specific statistics callback
*/
public StatisticsCallback getStatisticsCallback() {
return statisticsCallback;
}
/**
* Returns the session specific complete callback.
*
* @return session specific complete callback
*/
public FFmpegSessionCompleteCallback getCompleteCallback() {
return completeCallback;
}
/**
* 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.
@ -165,7 +180,8 @@ public class FFmpegSession extends AbstractSession implements Session {
}
/**
* Adds a new statistics entry for this session.
* Adds a new statistics entry for this session. It is invoked internally by
* <code>FFmpegKit</code> library methods. Must not be used by user applications.
*
* @param statistics statistics entry
*/
@ -185,6 +201,11 @@ public class FFmpegSession extends AbstractSession implements Session {
return false;
}
@Override
public boolean isMediaInformation() {
return false;
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();

@ -0,0 +1,35 @@
/*
* Copyright (c) 2018-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;
/**
* <p>Callback function that is invoked when an asynchronous <code>FFmpeg</code> session has ended.
*/
@FunctionalInterface
public interface FFmpegSessionCompleteCallback {
/**
* <p>Called when an FFmpeg session has ended.
*
* @param session FFmpeg session
*/
void apply(final FFmpegSession session);
}

@ -23,16 +23,16 @@ import java.util.List;
import java.util.concurrent.ExecutorService;
/**
* <p>Main class to run <code>FFprobe</code> commands. Supports executing commands both synchronously and
* asynchronously.
* <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", executeCallback);
* FFprobeSession asyncSession = FFprobeKit.executeAsync("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4", completeCallback);
* </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);
* FFprobeSession session = FFprobeKit.executeAsync("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4", completeCallback, logCallback);
* </pre>
* <p>It can extract media information for a file or a url, using {@link #getMediaInformation(String)} method.
* <pre>
@ -52,13 +52,23 @@ public class FFprobeKit {
private FFprobeKit() {
}
/**
* <p>Builds the default command used to get media information for a file.
*
* @param path file path to use in the command
* @return default command arguments to get media information
*/
private static String[] defaultGetMediaInformationCommandArguments(final String path) {
return new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-show_chapters", "-i", path};
}
/**
* <p>Synchronously executes FFprobe with arguments provided.
*
* @param arguments FFprobe command options/arguments as string array
* @return FFprobe session created for this execution
*/
public static FFprobeSession execute(final String[] arguments) {
public static FFprobeSession executeWithArguments(final String[] arguments) {
final FFprobeSession session = new FFprobeSession(arguments);
FFmpegKitConfig.ffprobeExecute(session);
@ -69,16 +79,17 @@ public class FFprobeKit {
/**
* <p>Starts an asynchronous FFprobe execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param arguments FFprobe command options/arguments as string array
* @param completeCallback callback that will be called when the execution has completed
* @return FFprobe session created for this execution
*/
public static FFprobeSession executeAsync(final String[] arguments,
final ExecuteCallback executeCallback) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback);
public static FFprobeSession executeWithArgumentsAsync(final String[] arguments,
final FFprobeSessionCompleteCallback completeCallback) {
final FFprobeSession session = new FFprobeSession(arguments, completeCallback);
FFmpegKitConfig.asyncFFprobeExecute(session);
@ -88,18 +99,19 @@ public class FFprobeKit {
/**
* <p>Starts an asynchronous FFprobe execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @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 arguments FFprobe command options/arguments as string array
* @param completeCallback callback that will be notified when execution has 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 LogCallback logCallback) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback);
public static FFprobeSession executeWithArgumentsAsync(final String[] arguments,
final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback) {
final FFprobeSession session = new FFprobeSession(arguments, completeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session);
@ -109,18 +121,19 @@ public class FFprobeKit {
/**
* <p>Starts an asynchronous FFprobe execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @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
* @param arguments FFprobe command options/arguments as string array
* @param completeCallback callback that will be called when the execution has 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,
final ExecuteCallback executeCallback,
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback);
public static FFprobeSession executeWithArgumentsAsync(final String[] arguments,
final FFprobeSessionCompleteCallback completeCallback,
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, completeCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
@ -130,20 +143,21 @@ public class FFprobeKit {
/**
* <p>Starts an asynchronous FFprobe execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @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
* @param arguments FFprobe command options/arguments as string array
* @param completeCallback callback that will be notified when execution has 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 ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback);
public static FFprobeSession executeWithArgumentsAsync(final String[] arguments,
final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, completeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
@ -159,59 +173,65 @@ public class FFprobeKit {
* @return FFprobe session created for this execution
*/
public static FFprobeSession execute(final String command) {
return execute(FFmpegKitConfig.parseArguments(command));
return executeWithArguments(FFmpegKitConfig.parseArguments(command));
}
/**
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used
* to split the command into arguments. You can use single or double quote characters to
* specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param command FFprobe command
* @param executeCallback callback that will be called when the execution is completed
* @param command FFprobe command
* @param completeCallback callback that will be called when the execution has completed
* @return FFprobe session created for this execution
*/
public static FFprobeSession executeAsync(final String command,
final ExecuteCallback executeCallback) {
return executeAsync(FFmpegKitConfig.parseArguments(command), executeCallback);
final FFprobeSessionCompleteCallback completeCallback) {
return executeWithArgumentsAsync(FFmpegKitConfig.parseArguments(command), completeCallback);
}
/**
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used
* to split the command into arguments. You can use single or double quote characters to
* specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param command FFprobe command
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive logs
* @param command FFprobe command
* @param completeCallback callback that will be notified when execution has 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 FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback) {
return executeAsync(FFmpegKitConfig.parseArguments(command), executeCallback, logCallback);
return executeWithArgumentsAsync(FFmpegKitConfig.parseArguments(command), completeCallback, logCallback);
}
/**
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used
* to split the command into arguments. You can use single or double quote characters to
* specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @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
* @param command FFprobe command
* @param completeCallback callback that will be called when the execution has 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,
final ExecuteCallback executeCallback,
final FFprobeSessionCompleteCallback completeCallback,
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(FFmpegKitConfig.parseArguments(command), executeCallback);
final FFprobeSession session = new FFprobeSession(FFmpegKitConfig.parseArguments(command), completeCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
@ -219,23 +239,25 @@ public class FFprobeKit {
}
/**
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
*
* @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
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used
* to split the command into arguments. You can use single or double quote characters to
* specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
*
* @param command FFprobe command
* @param completeCallback callback that will be called when the execution has 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 command,
final ExecuteCallback executeCallback,
final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(FFmpegKitConfig.parseArguments(command), executeCallback, logCallback);
final FFprobeSession session = new FFprobeSession(FFmpegKitConfig.parseArguments(command), completeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
@ -249,7 +271,7 @@ public class FFprobeKit {
* @return media information session created for this execution
*/
public static MediaInformationSession getMediaInformation(final String path) {
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path});
final MediaInformationSession session = new MediaInformationSession(defaultGetMediaInformationCommandArguments(path));
FFmpegKitConfig.getMediaInformationExecute(session, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
@ -265,7 +287,7 @@ public class FFprobeKit {
*/
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});
final MediaInformationSession session = new MediaInformationSession(defaultGetMediaInformationCommandArguments(path));
FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout);
@ -273,18 +295,20 @@ public class FFprobeKit {
}
/**
* <p>Starts an asynchronous FFprobe execution to extract the media information for the specified file.
* <p>Starts an asynchronous FFprobe execution to extract the media information for the
* specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use a {@link MediaInformationSessionCompleteCallback} if you want to be notified
* about the result.
*
* @param path path or uri of a media file
* @param executeCallback callback that will be called when the execution is completed
* @param path path or uri of a media file
* @param completeCallback callback that will be called when the execution has 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);
final MediaInformationSessionCompleteCallback completeCallback) {
final MediaInformationSession session = new MediaInformationSession(defaultGetMediaInformationCommandArguments(path), completeCallback);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
@ -292,22 +316,24 @@ public class FFprobeKit {
}
/**
* <p>Starts an asynchronous FFprobe execution to extract the media information for the specified file.
* <p>Starts an asynchronous FFprobe execution to extract the media information for the
* specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use a {@link MediaInformationSessionCompleteCallback} if you want to be notified
* about the result.
*
* @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
* @param path path or uri of a media file
* @param completeCallback callback that will be notified when execution has 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 MediaInformationSessionCompleteCallback completeCallback,
final LogCallback logCallback,
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);
final MediaInformationSession session = new MediaInformationSession(defaultGetMediaInformationCommandArguments(path), completeCallback, logCallback);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, waitTimeout);
@ -315,20 +341,22 @@ public class FFprobeKit {
}
/**
* <p>Starts an asynchronous FFprobe execution to extract the media information for the specified file.
* <p>Starts an asynchronous FFprobe execution to extract the media information for the
* specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use a {@link MediaInformationSessionCompleteCallback} if you want to be notified
* about the result.
*
* @param path path or uri of a media file
* @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
* @param path path or uri of a media file
* @param completeCallback callback that will be called when the execution has 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 MediaInformationSessionCompleteCallback completeCallback,
final ExecutorService executorService) {
final MediaInformationSession session = new MediaInformationSession(new String[]{"-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path}, executeCallback);
final MediaInformationSession session = new MediaInformationSession(defaultGetMediaInformationCommandArguments(path), completeCallback);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, executorService, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
@ -336,24 +364,26 @@ public class FFprobeKit {
}
/**
* <p>Starts an asynchronous FFprobe execution to extract the media information for the specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
*
* @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
* <p>Starts an asynchronous FFprobe execution to extract the media information for the
* specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use a {@link MediaInformationSessionCompleteCallback} if you want to be notified
* about the result.
*
* @param path path or uri of a media file
* @param completeCallback callback that will be notified when execution has 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 MediaInformationSessionCompleteCallback completeCallback,
final LogCallback logCallback,
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);
final MediaInformationSession session = new MediaInformationSession(defaultGetMediaInformationCommandArguments(path), completeCallback, logCallback);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, executorService, waitTimeout);
@ -361,7 +391,7 @@ public class FFprobeKit {
}
/**
* <p>Extracts media information using the command provided asynchronously.
* <p>Extracts media information using the command provided.
*
* @param command FFprobe command that prints media information for a file in JSON format
* @return media information session created for this execution
@ -369,52 +399,57 @@ public class FFprobeKit {
public static MediaInformationSession getMediaInformationFromCommand(final String command) {
final MediaInformationSession session = new MediaInformationSession(FFmpegKitConfig.parseArguments(command));
FFmpegKitConfig.asyncGetMediaInformationExecute(session, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
FFmpegKitConfig.getMediaInformationExecute(session, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT);
return session;
}
/**
* <p>Starts an asynchronous FFprobe execution to extract media information using a command. The command passed to
* this method must generate the output in JSON format in order to successfully extract media information from it.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
*
* @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
* <p>Starts an asynchronous FFprobe execution to extract media information using a command.
* The command passed to this method must generate the output in JSON format in order to
* successfully extract media information from it.
*
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use a {@link MediaInformationSessionCompleteCallback} if you want to be notified
* about the result.
*
* @param command FFprobe command that prints media information for a file in JSON
* format
* @param completeCallback callback that will be notified when execution has 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 getMediaInformationFromCommandAsync(final String command,
final ExecuteCallback executeCallback,
final MediaInformationSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final int waitTimeout) {
return getMediaInformationFromCommandArgumentsAsync(FFmpegKitConfig.parseArguments(command), executeCallback, logCallback, waitTimeout);
return getMediaInformationFromCommandArgumentsAsync(FFmpegKitConfig.parseArguments(command), completeCallback, logCallback, waitTimeout);
}
/**
* <p>Starts an asynchronous FFprobe execution to extract media information using command arguments. The command
* passed to this method must generate the output in JSON format in order to successfully extract media information
* from it.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* {@jlink ExecuteCallback} if you want to be notified about the result.
*
* @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
* <p>Starts an asynchronous FFprobe execution to extract media information using command
* arguments. The command passed to this method must generate the output in JSON format in
* order to successfully extract media information from it.
*
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use a {@link MediaInformationSessionCompleteCallback} if you want to be notified
* about the result.
*
* @param arguments FFprobe command arguments that print media information for a file in
* JSON format
* @param completeCallback callback that will be notified when execution has 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 MediaInformationSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final int waitTimeout) {
final MediaInformationSession session = new MediaInformationSession(arguments, executeCallback, logCallback);
final MediaInformationSession session = new MediaInformationSession(arguments, completeCallback, logCallback);
FFmpegKitConfig.getMediaInformationExecute(session, waitTimeout);
FFmpegKitConfig.asyncGetMediaInformationExecute(session, waitTimeout);
return session;
}
@ -424,8 +459,17 @@ public class FFprobeKit {
*
* @return all FFprobe sessions in the session history
*/
public static List<FFprobeSession> listSessions() {
public static List<FFprobeSession> listFFprobeSessions() {
return FFmpegKitConfig.getFFprobeSessions();
}
/**
* <p>Lists all MediaInformation sessions in the session history.
*
* @return all MediaInformation sessions in the session history
*/
public static List<MediaInformationSession> listMediaInformationSessions() {
return FFmpegKitConfig.getMediaInformationSessions();
}
}

@ -24,6 +24,11 @@ package com.arthenica.ffmpegkit;
*/
public class FFprobeSession extends AbstractSession implements Session {
/**
* Session specific complete callback.
*/
private final FFprobeSessionCompleteCallback completeCallback;
/**
* Builds a new FFprobe session.
*
@ -36,39 +41,50 @@ public class FFprobeSession extends AbstractSession implements Session {
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param arguments command arguments
* @param completeCallback session specific complete callback
*/
public FFprobeSession(final String[] arguments, final ExecuteCallback executeCallback) {
this(arguments, executeCallback, null);
public FFprobeSession(final String[] arguments, final FFprobeSessionCompleteCallback completeCallback) {
this(arguments, completeCallback, null);
}
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param logCallback session specific log callback function
* @param arguments command arguments
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
*/
public FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback) {
this(arguments, executeCallback, logCallback, FFmpegKitConfig.getLogRedirectionStrategy());
this(arguments, completeCallback, logCallback, FFmpegKitConfig.getLogRedirectionStrategy());
}
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param logCallback session specific log callback function
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
* @param logRedirectionStrategy session specific log redirection strategy
*/
public FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback,
final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback,
final LogRedirectionStrategy logRedirectionStrategy) {
super(arguments, executeCallback, logCallback, logRedirectionStrategy);
super(arguments, logCallback, logRedirectionStrategy);
this.completeCallback = completeCallback;
}
/**
* Returns the session specific complete callback.
*
* @return session specific complete callback
*/
public FFprobeSessionCompleteCallback getCompleteCallback() {
return completeCallback;
}
@Override
@ -81,6 +97,11 @@ public class FFprobeSession extends AbstractSession implements Session {
return true;
}
@Override
public boolean isMediaInformation() {
return false;
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();

@ -0,0 +1,35 @@
/*
* Copyright (c) 2018-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;
/**
* <p>Callback function that is invoked when an asynchronous <code>FFprobe</code> session has ended.
*/
@FunctionalInterface
public interface FFprobeSessionCompleteCallback {
/**
* <p>Called when an FFprobe session has ended.
*
* @param session FFprobe session
*/
void apply(final FFprobeSession session);
}

@ -49,9 +49,15 @@ public class MediaInformation {
*/
private final List<StreamInformation> streams;
public MediaInformation(final JSONObject jsonObject, final List<StreamInformation> streams) {
/**
* Stores chapters.
*/
private final List<Chapter> chapters;
public MediaInformation(final JSONObject jsonObject, final List<StreamInformation> streams, final List<Chapter> chapters) {
this.jsonObject = jsonObject;
this.streams = streams;
this.chapters = chapters;
}
/**
@ -135,6 +141,15 @@ public class MediaInformation {
return streams;
}
/**
* Returns all chapters.
*
* @return list of chapters
*/
public List<Chapter> getChapters() {
return chapters;
}
/**
* Returns the media property associated with the key.
*

@ -34,6 +34,9 @@ import java.util.ArrayList;
*/
public class MediaInformationJsonParser {
public static final String KEY_STREAMS = "streams";
public static final String KEY_CHAPTERS = "chapters";
/**
* 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
@ -59,18 +62,27 @@ public class MediaInformationJsonParser {
* @throws JSONException if a parsing error occurs
*/
public static MediaInformation fromWithError(final String ffprobeJsonOutput) throws JSONException {
JSONObject jsonObject = new JSONObject(ffprobeJsonOutput);
JSONArray streamArray = jsonObject.optJSONArray("streams");
final JSONObject jsonObject = new JSONObject(ffprobeJsonOutput);
final JSONArray streamArray = jsonObject.optJSONArray(KEY_STREAMS);
final JSONArray chapterArray = jsonObject.optJSONArray(KEY_CHAPTERS);
ArrayList<StreamInformation> arrayList = new ArrayList<>();
ArrayList<StreamInformation> streamList = new ArrayList<>();
for (int i = 0; streamArray != null && i < streamArray.length(); i++) {
JSONObject streamObject = streamArray.optJSONObject(i);
if (streamObject != null) {
arrayList.add(new StreamInformation(streamObject));
streamList.add(new StreamInformation(streamObject));
}
}
ArrayList<Chapter> chapterList = new ArrayList<>();
for (int i = 0; chapterArray != null && i < chapterArray.length(); i++) {
JSONObject chapterObject = chapterArray.optJSONObject(i);
if (chapterObject != null) {
chapterList.add(new Chapter(chapterObject));
}
}
return new MediaInformation(jsonObject, arrayList);
return new MediaInformation(jsonObject, streamList, chapterList);
}
}

@ -23,13 +23,18 @@ package com.arthenica.ffmpegkit;
* <p>A custom FFprobe session, which produces a <code>MediaInformation</code> object using the
* FFprobe output.
*/
public class MediaInformationSession extends FFprobeSession implements Session {
public class MediaInformationSession extends AbstractSession implements Session {
/**
* Media information extracted in the session.
*/
private MediaInformation mediaInformation;
/**
* Session specific complete callback.
*/
private final MediaInformationSessionCompleteCallback completeCallback;
/**
* Creates a new media information session.
*
@ -42,22 +47,24 @@ public class MediaInformationSession extends FFprobeSession implements Session {
/**
* Creates a new media information session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback function
* @param arguments command arguments
* @param completeCallback session specific complete callback
*/
public MediaInformationSession(final String[] arguments, final ExecuteCallback executeCallback) {
this(arguments, executeCallback, null);
public MediaInformationSession(final String[] arguments, final MediaInformationSessionCompleteCallback completeCallback) {
this(arguments, completeCallback, 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
* @param arguments command arguments
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
*/
public MediaInformationSession(final String[] arguments, final ExecuteCallback executeCallback, final LogCallback logCallback) {
super(arguments, executeCallback, logCallback, LogRedirectionStrategy.NEVER_PRINT_LOGS);
public MediaInformationSession(final String[] arguments, final MediaInformationSessionCompleteCallback completeCallback, final LogCallback logCallback) {
super(arguments, logCallback, LogRedirectionStrategy.NEVER_PRINT_LOGS);
this.completeCallback = completeCallback;
}
/**
@ -79,6 +86,30 @@ public class MediaInformationSession extends FFprobeSession implements Session {
this.mediaInformation = mediaInformation;
}
/**
* Returns the session specific complete callback.
*
* @return session specific complete callback
*/
public MediaInformationSessionCompleteCallback getCompleteCallback() {
return completeCallback;
}
@Override
public boolean isFFmpeg() {
return false;
}
@Override
public boolean isFFprobe() {
return false;
}
@Override
public boolean isMediaInformation() {
return true;
}
@Override
public String toString() {
final StringBuilder stringBuilder = new StringBuilder();

@ -0,0 +1,36 @@
/*
* Copyright (c) 2018-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;
/**
* <p>Callback function that is invoked when an asynchronous <code>MediaInformation</code> session
* has ended.
*/
@FunctionalInterface
public interface MediaInformationSessionCompleteCallback {
/**
* <p>Called when a media information session has ended.
*
* @param session media information session
*/
void apply(final MediaInformationSession session);
}

@ -27,6 +27,7 @@ import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* <p>Responsible of loading native libraries.
@ -35,6 +36,8 @@ public class NativeLoader {
static final String[] FFMPEG_LIBRARIES = {"avutil", "swscale", "swresample", "avcodec", "avformat", "avfilter", "avdevice"};
static final String[] LIBRARIES_LINKED_WITH_CXX = {"openh264", "rubberband", "snappy", "srt", "tesseract", "x265", "zimg"};
static boolean isTestModeDisabled() {
return (System.getProperty("enable.ffmpeg.kit.test.mode") == null);
}
@ -82,7 +85,7 @@ public class NativeLoader {
}
static String loadVersion() {
final String version = "4.5";
final String version = "4.5.1";
if (isTestModeDisabled()) {
return FFmpegKitConfig.getVersion();
@ -113,7 +116,7 @@ public class NativeLoader {
if (isTestModeDisabled()) {
return FFmpegKitConfig.getBuildDate();
} else {
return new SimpleDateFormat("yyyyMMdd").format(new Date());
return new SimpleDateFormat("yyyyMMdd", Locale.getDefault()).format(new Date());
}
}
@ -135,8 +138,11 @@ public class NativeLoader {
/* 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");
for (String dependantLibrary : LIBRARIES_LINKED_WITH_CXX) {
if (externalLibrariesEnabled.contains(dependantLibrary)) {
loadLibrary("c++_shared");
break;
}
}
if (AbiDetect.ARM_V7A.equals(loadNativeAbi())) {

@ -51,6 +51,7 @@ public class Packages {
supportedExternalLibraries.add("libxml2");
supportedExternalLibraries.add("opencore-amr");
supportedExternalLibraries.add("openh264");
supportedExternalLibraries.add("openssl");
supportedExternalLibraries.add("opus");
supportedExternalLibraries.add("rubberband");
supportedExternalLibraries.add("sdl2");
@ -58,11 +59,13 @@ public class Packages {
supportedExternalLibraries.add("snappy");
supportedExternalLibraries.add("soxr");
supportedExternalLibraries.add("speex");
supportedExternalLibraries.add("srt");
supportedExternalLibraries.add("tesseract");
supportedExternalLibraries.add("twolame");
supportedExternalLibraries.add("x264");
supportedExternalLibraries.add("x265");
supportedExternalLibraries.add("xvid");
supportedExternalLibraries.add("zimg");
}
/**
@ -134,7 +137,8 @@ public class Packages {
externalLibraryList.contains("twolame") &&
externalLibraryList.contains("x264") &&
externalLibraryList.contains("x265") &&
externalLibraryList.contains("xvid")) {
externalLibraryList.contains("xvid") &&
externalLibraryList.contains("zimg")) {
return "full-gpl";
} else {
return "custom";
@ -164,7 +168,8 @@ public class Packages {
externalLibraryList.contains("snappy") &&
externalLibraryList.contains("soxr") &&
externalLibraryList.contains("speex") &&
externalLibraryList.contains("twolame")) {
externalLibraryList.contains("twolame") &&
externalLibraryList.contains("zimg")) {
return "full";
} else {
return "custom";
@ -182,7 +187,8 @@ public class Packages {
externalLibraryList.contains("libtheora") &&
externalLibraryList.contains("libvpx") &&
externalLibraryList.contains("libwebp") &&
externalLibraryList.contains("snappy")) {
externalLibraryList.contains("snappy") &&
externalLibraryList.contains("zimg")) {
return "video";
} else {
return "custom";

@ -43,15 +43,15 @@ public class ReturnCode {
return value;
}
public boolean isSuccess() {
public boolean isValueSuccess() {
return (value == SUCCESS);
}
public boolean isError() {
public boolean isValueError() {
return ((value != SUCCESS) && (value != CANCEL));
}
public boolean isCancel() {
public boolean isValueCancel() {
return (value == CANCEL);
}

@ -29,16 +29,9 @@ import java.util.concurrent.Future;
public interface Session {
/**
* Returns the session specific execute callback function.
* Returns the session specific log callback.
*
* @return session specific execute callback function
*/
ExecuteCallback getExecuteCallback();
/**
* Returns the session specific log callback function.
*
* @return session specific log callback function
* @return session specific log callback
*/
LogCallback getLogCallback();
@ -198,6 +191,9 @@ public interface Session {
/**
* Adds a new log entry for this session.
* <p>
* It is invoked internally by <code>FFmpegKit</code> library methods. Must not be used by user
* applications.
*
* @param log log entry
*/
@ -224,6 +220,13 @@ public interface Session {
*/
boolean isFFprobe();
/**
* Returns whether it is a <code>MediaInformation</code> session or not.
*
* @return true if it is a <code>MediaInformation</code> session, false otherwise
*/
boolean isMediaInformation();
/**
* Cancels running the session.
*/

@ -211,7 +211,7 @@ public class StreamInformation {
/**
* Returns all tags.
*
* @return tags dictionary
* @return tags object
*/
public JSONObject getTags() {
return getProperties(KEY_TAGS);

@ -72,6 +72,85 @@ public class FFmpegKitTest {
" }\n" +
" }\n" +
" ],\n" +
" \"chapters\": [\n" +
" {\n" +
" \"id\": 0,\n" +
" \"time_base\": \"1/22050\",\n" +
" \"start\": 0,\n" +
" \"start_time\": \"0.000000\",\n" +
" \"end\": 11158238,\n" +
" \"end_time\": \"506.042540\",\n" +
" \"tags\": {\n" +
" \"title\": \"1 Laying Plans - 2 Waging War\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"id\": 1,\n" +
" \"time_base\": \"1/22050\",\n" +
" \"start\": 11158238,\n" +
" \"start_time\": \"506.042540\",\n" +
" \"end\": 21433051,\n" +
" \"end_time\": \"972.020454\",\n" +
" \"tags\": {\n" +
" \"title\": \"3 Attack By Stratagem - 4 Tactical Dispositions\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"id\": 2,\n" +
" \"time_base\": \"1/22050\",\n" +
" \"start\": 21433051,\n" +
" \"start_time\": \"972.020454\",\n" +
" \"end\": 35478685,\n" +
" \"end_time\": \"1609.010658\",\n" +
" \"tags\": {\n" +
" \"title\": \"5 Energy - 6 Weak Points and Strong\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"id\": 3,\n" +
" \"time_base\": \"1/22050\",\n" +
" \"start\": 35478685,\n" +
" \"start_time\": \"1609.010658\",\n" +
" \"end\": 47187043,\n" +
" \"end_time\": \"2140.001950\",\n" +
" \"tags\": {\n" +
" \"title\": \"7 Maneuvering - 8 Variation in Tactics\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"id\": 4,\n" +
" \"time_base\": \"1/22050\",\n" +
" \"start\": 47187043,\n" +
" \"start_time\": \"2140.001950\",\n" +
" \"end\": 66635594,\n" +
" \"end_time\": \"3022.022404\",\n" +
" \"tags\": {\n" +
" \"title\": \"9 The Army on the March - 10 Terrain\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"id\": 5,\n" +
" \"time_base\": \"1/22050\",\n" +
" \"start\": 66635594,\n" +
" \"start_time\": \"3022.022404\",\n" +
" \"end\": 83768105,\n" +
" \"end_time\": \"3799.007029\",\n" +
" \"tags\": {\n" +
" \"title\": \"11 The Nine Situations\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"id\": 6,\n" +
" \"time_base\": \"1/22050\",\n" +
" \"start\": 83768105,\n" +
" \"start_time\": \"3799.007029\",\n" +
" \"end\": 95659008,\n" +
" \"end_time\": \"4338.277007\",\n" +
" \"tags\": {\n" +
" \"title\": \"12 The Attack By Fire - 13 The Use of Spies\"\n" +
" }\n" +
" }\n" +
" ],\n" +
" \"format\": {\n" +
" \"filename\": \"sample.mp3\",\n" +
" \"nb_streams\": 1,\n" +
@ -459,6 +538,11 @@ public class FFmpegKitTest {
Assert.assertNotNull(mediaInformation.getStreams());
Assert.assertEquals(1, mediaInformation.getStreams().size());
assertAudioStream(mediaInformation.getStreams().get(0), 0L, "mp3", "MP3 (MPEG audio layer 3)", "44100", "stereo", "fltp", "320000");
Assert.assertNotNull(mediaInformation.getChapters());
Assert.assertEquals(7, mediaInformation.getChapters().size());
assertChapter(mediaInformation.getChapters().get(0), 0L, "1/22050", 0L, "0.000000", 11158238L, "506.042540");
assertChapter(mediaInformation.getChapters().get(1), 1L, "1/22050", 11158238L, "506.042540", 21433051L, "972.020454");
}
@Test
@ -743,4 +827,18 @@ public class FFmpegKitTest {
Assert.assertEquals(codecTimeBase, streamInformation.getCodecTimeBase());
}
private void assertChapter(Chapter chapter, Long id, String timeBase, Long start, String startTime, Long end, String endTime) {
Assert.assertEquals(id, chapter.getId());
Assert.assertEquals(timeBase, chapter.getTimeBase());
Assert.assertEquals(start, chapter.getStart());
Assert.assertEquals(startTime, chapter.getStartTime());
Assert.assertEquals(end, chapter.getEnd());
Assert.assertEquals(endTime, chapter.getEndTime());
Assert.assertNotNull(chapter.getTags());
Assert.assertEquals(1, chapter.getTags().length());
}
}

@ -32,8 +32,8 @@ public class FFmpegSessionTest {
public void constructorTest() {
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS);
// 1. getExecuteCallback
Assert.assertNull(ffmpegSession.getExecuteCallback());
// 1. getCompleteCallback
Assert.assertNull(ffmpegSession.getCompleteCallback());
// 2. getLogCallback
Assert.assertNull(ffmpegSession.getLogCallback());
@ -93,17 +93,17 @@ public class FFmpegSessionTest {
@Test
public void constructorTest2() {
ExecuteCallback executeCallback = new ExecuteCallback() {
FFmpegSessionCompleteCallback completeCallback = new FFmpegSessionCompleteCallback() {
@Override
public void apply(Session session) {
public void apply(FFmpegSession session) {
}
};
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS, executeCallback);
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS, completeCallback);
// 1. getExecuteCallback
Assert.assertEquals(ffmpegSession.getExecuteCallback(), executeCallback);
// 1. getCompleteCallback
Assert.assertEquals(ffmpegSession.getCompleteCallback(), completeCallback);
// 2. getLogCallback
Assert.assertNull(ffmpegSession.getLogCallback());
@ -163,10 +163,10 @@ public class FFmpegSessionTest {
@Test
public void constructorTest3() {
ExecuteCallback executeCallback = new ExecuteCallback() {
FFmpegSessionCompleteCallback completeCallback = new FFmpegSessionCompleteCallback() {
@Override
public void apply(Session session) {
public void apply(FFmpegSession session) {
}
};
@ -184,10 +184,10 @@ public class FFmpegSessionTest {
}
};
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS, executeCallback, logCallback, statisticsCallback);
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS, completeCallback, logCallback, statisticsCallback);
// 1. getExecuteCallback
Assert.assertEquals(ffmpegSession.getExecuteCallback(), executeCallback);
// 1. getCompleteCallback
Assert.assertEquals(ffmpegSession.getCompleteCallback(), completeCallback);
// 2. getLogCallback
Assert.assertEquals(ffmpegSession.getLogCallback(), logCallback);

@ -32,8 +32,8 @@ public class FFprobeSessionTest {
public void constructorTest() {
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS);
// 1. getExecuteCallback
Assert.assertNull(ffprobeSession.getExecuteCallback());
// 1. getCompleteCallback
Assert.assertNull(ffprobeSession.getCompleteCallback());
// 2. getLogCallback
Assert.assertNull(ffprobeSession.getLogCallback());
@ -90,17 +90,17 @@ public class FFprobeSessionTest {
@Test
public void constructorTest2() {
ExecuteCallback executeCallback = new ExecuteCallback() {
FFprobeSessionCompleteCallback completeCallback = new FFprobeSessionCompleteCallback() {
@Override
public void apply(Session session) {
public void apply(FFprobeSession session) {
}
};
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS, executeCallback);
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS, completeCallback);
// 1. getExecuteCallback
Assert.assertEquals(ffprobeSession.getExecuteCallback(), executeCallback);
// 1. getCompleteCallback
Assert.assertEquals(ffprobeSession.getCompleteCallback(), completeCallback);
// 2. getLogCallback
Assert.assertNull(ffprobeSession.getLogCallback());
@ -157,10 +157,10 @@ public class FFprobeSessionTest {
@Test
public void constructorTest3() {
ExecuteCallback executeCallback = new ExecuteCallback() {
FFprobeSessionCompleteCallback completeCallback = new FFprobeSessionCompleteCallback() {
@Override
public void apply(Session session) {
public void apply(FFprobeSession session) {
}
};
@ -171,10 +171,10 @@ public class FFprobeSessionTest {
}
};
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS, executeCallback, logCallback);
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS, completeCallback, logCallback);
// 1. getExecuteCallback
Assert.assertEquals(ffprobeSession.getExecuteCallback(), executeCallback);
// 1. getCompleteCallback
Assert.assertEquals(ffprobeSession.getCompleteCallback(), completeCallback);
// 2. getLogCallback
Assert.assertEquals(ffprobeSession.getLogCallback(), logCallback);

@ -12,14 +12,11 @@ enable_default_architecture_variants() {
display_help() {
COMMAND=$(echo "$0" | sed -e 's/\.\///g')
echo -e "\n'$COMMAND' combines FFmpegKit frameworks created for apple architecture variants in an xcframework. \
echo -e "\n'$COMMAND' combines FFmpegKit frameworks created for Apple architecture variants in an xcframework. \
It uses frameworks created under the prebuilt folder for iOS, tvOS and macOS architecture variants (iphoneos, \
iphonesimulator, mac-catalyst, appletvos, appletvsimulator, macosx) as input and builds an umbrella xcframework under \
the prebuilt folder.\n\n\
Additional options can be specified to disable architectures or to build xcframeworks for external libraries as well.\
\n\nPlease note that this script is only responsible of packaging existing frameworks, created by 'ios.sh', 'tvos.sh' \
and 'macos.sh'. Running it will not compile any of these libraries again. Enabling an external library means building \
an xcframework for that library. It does not guarantee that ffmpeg has support for it. Top level build scripts \
the prebuilt folder.\n\nPlease note that this script is only responsible of packaging existing frameworks, created by \
'ios.sh', 'tvos.sh' and 'macos.sh'. Running it will not compile any of these libraries again. Top level build scripts \
('ios.sh', 'tvos.sh', 'macos.sh') must be used to build ffmpeg with support for a specific external library first. \
After that this script should be used to create an umbrella xcframework.\n"
echo -e "Usage: ./$COMMAND [OPTION]...\n"
@ -29,10 +26,7 @@ After that this script should be used to create an umbrella xcframework.\n"
echo -e " -h, --help\t\t\tdisplay this help and exit"
echo -e " -v, --version\t\t\tdisplay version information and exit"
echo -e " -f, --force\t\t\tignore warnings"
echo -e " -l, --lts\t\t\tinclude lts packages to support iOS 9.3+, tvOS 9.2+, macOS 10.11+ devices\n"
echo -e "Licensing options:"
echo -e " --enable-gpl\t\t\tallow building umbrella xcframeworks for GPL libraries[no]\n"
echo -e " -l, --lts\t\t\tinclude lts packages to support iOS 10+, tvOS 10+, macOS 10.12+ devices\n"
echo -e "Architectures:"
echo -e " --disable-iphoneos\t\tdo not include iphoneos architecture variant [yes]"
@ -41,44 +35,6 @@ After that this script should be used to create an umbrella xcframework.\n"
echo -e " --disable-appletvos\t\tdo not include appletvos architecture variant [yes]"
echo -e " --disable-appletvsimulator\tdo not include appletvsimulator architecture variant [yes]"
echo -e " --disable-macosx\t\tdo not include macosx architecture variant [yes]\n"
echo -e "Libraries:"
echo -e " --full\t\t\tbuilds umbrella xcframeworks all non-GPL external libraries"
echo -e " --enable-chromaprint\t\tbuild umbrella xcframework for chromaprint [no]"
echo -e " --enable-dav1d\t\tbuild umbrella xcframework for dav1d [no]"
echo -e " --enable-fontconfig\t\tbuild umbrella xcframework for fontconfig [no]"
echo -e " --enable-freetype\t\tbuild umbrella xcframework for freetype [no]"
echo -e " --enable-fribidi\t\tbuild umbrella xcframework for fribidi [no]"
echo -e " --enable-gmp\t\t\tbuild umbrella xcframework for gmp [no]"
echo -e " --enable-gnutls\t\tbuild umbrella xcframework for gnutls [no]"
echo -e " --enable-kvazaar\t\tbuild umbrella xcframework for kvazaar [no]"
echo -e " --enable-lame\t\t\tbuild umbrella xcframework for lame [no]"
echo -e " --enable-libaom\t\tbuild umbrella xcframework for libaom [no]"
echo -e " --enable-libass\t\tbuild umbrella xcframework for libass [no]"
echo -e " --enable-libilbc\t\tbuild umbrella xcframework for libilbc [no]"
echo -e " --enable-libtheora\t\tbuild umbrella xcframework for libtheora [no]"
echo -e " --enable-libvorbis\t\tbuild umbrella xcframework for libvorbis [no]"
echo -e " --enable-libvpx\t\tbuild umbrella xcframework for libvpx [no]"
echo -e " --enable-libwebp\t\tbuild umbrella xcframework for libwebp [no]"
echo -e " --enable-libxml2\t\tbuild umbrella xcframework for libxml2 [no]"
echo -e " --enable-opencore-amr\t\tbuild umbrella xcframework for opencore-amr [no]"
echo -e " --enable-openh264\t\tbuild umbrella xcframework for openh264 [no]"
echo -e " --enable-opus\t\t\tbuild umbrella xcframework for opus [no]"
echo -e " --enable-sdl\t\t\tbuild umbrella xcframework for sdl [no]"
echo -e " --enable-shine\t\tbuild umbrella xcframework for shine [no]"
echo -e " --enable-snappy\t\tbuild umbrella xcframework for snappy [no]"
echo -e " --enable-soxr\t\t\tbuild umbrella xcframework for soxr [no]"
echo -e " --enable-speex\t\tbuild umbrella xcframework for speex [no]"
echo -e " --enable-tesseract\t\tbuild umbrella xcframework for tesseract [no]"
echo -e " --enable-twolame\t\tbuild umbrella xcframework for twolame [no]"
echo -e " --enable-vo-amrwbenc\t\tbuild umbrella xcframework for vo-amrwbenc [no]\n"
echo -e "GPL libraries:"
echo -e " --enable-libvidstab\t\tbuild umbrella xcframework for libvidstab [no]"
echo -e " --enable-rubberband\t\tbuild umbrella xcframework for rubber band [no]"
echo -e " --enable-x264\t\t\tbuild umbrella xcframework for x264 [no]"
echo -e " --enable-x265\t\t\tbuild umbrella xcframework for x265 [no]"
echo -e " --enable-xvidcore\t\tbuild umbrella xcframework for xvidcore [no]\n"
}
initialize_prebuilt_umbrella_xcframework_folders() {
@ -219,17 +175,6 @@ while [ ! $# -eq 0 ]; do
-f | --force)
export BUILD_FORCE="1"
;;
--full)
BUILD_FULL="1"
;;
--enable-gpl)
GPL_ENABLED="yes"
;;
--enable-*)
ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
enable_library "${ENABLED_LIBRARY}"
;;
--disable-*)
DISABLED_ARCH_VARIANT=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
@ -242,19 +187,6 @@ while [ ! $# -eq 0 ]; do
shift
done
# PROCESS FULL OPTION AS LAST OPTION
if [[ -n ${BUILD_FULL} ]]; then
for library in {0..58}; do
if [ ${GPL_ENABLED} == "yes" ]; then
set_library "$(get_library_name "$library")" 1
else
if [[ $(is_gpl_licensed "$library") -eq 1 ]]; then
set_library "$(get_library_name "$library")" 1
fi
fi
done
fi
# IF HELP DISPLAYED EXIT
if [[ -n ${DISPLAY_HELP} ]]; then
display_help
@ -271,19 +203,6 @@ print_enabled_xcframeworks
echo ""
# VALIDATE GPL FLAGS
for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVIDSTAB,$LIBRARY_RUBBERBAND}; do
if [[ ${ENABLED_LIBRARIES[$gpl_library]} -eq 1 ]]; then
library_name=$(get_library_name "${gpl_library}")
if [ ${GPL_ENABLED} != "yes" ]; then
echo -e "\n(*) Invalid configuration detected. GPL library ${library_name} enabled without --enable-gpl flag.\n"
echo -e "\n(*) Invalid configuration detected. GPL library ${library_name} enabled without --enable-gpl flag.\n" 1>>"${BASEDIR}"/build.log 2>&1
exit 1
fi
fi
done
# THIS WILL SAVE ARCHITECTURE VARIANTS TO BE INCLUDED
TARGET_ARCHITECTURE_VARIANT_INDEX_ARRAY=()
@ -309,45 +228,6 @@ if [[ -n ${TARGET_ARCHITECTURE_VARIANT_INDEX_ARRAY[0]} ]]; then
# INITIALIZE TARGET FOLDERS
initialize_prebuilt_umbrella_xcframework_folders
# BUILD XCFRAMEWORKS FOR ENABLED LIBRARIES ON ENABLED ARCHITECTURE VARIANTS
for library in {0..46}; do
if [[ ${ENABLED_LIBRARIES[${library}]} -eq 1 ]]; then
if [[ ${LIBRARY_LIBTHEORA} == "${library}" ]]; then
create_umbrella_xcframework "libtheora"
create_umbrella_xcframework "libtheoraenc"
create_umbrella_xcframework "libtheoradec"
elif [[ ${LIBRARY_LIBVORBIS} == "${library}" ]]; then
create_umbrella_xcframework "libvorbisfile"
create_umbrella_xcframework "libvorbisenc"
create_umbrella_xcframework "libvorbis"
elif [[ ${LIBRARY_LIBWEBP} == "${library}" ]]; then
create_umbrella_xcframework "libwebpmux"
create_umbrella_xcframework "libwebpdemux"
create_umbrella_xcframework "libwebp"
elif [[ ${LIBRARY_OPENCOREAMR} == "${library}" ]]; then
create_umbrella_xcframework "libopencore-amrnb"
elif [[ ${LIBRARY_NETTLE} == "${library}" ]]; then
create_umbrella_xcframework "libnettle"
create_umbrella_xcframework "libhogweed"
else
create_umbrella_xcframework "$(get_static_archive_name "${library}")"
fi
fi
done
for FFMPEG_LIB in "${FFMPEG_LIBS[@]}"; do
create_umbrella_xcframework "${FFMPEG_LIB}"
done

2
apple/.gitignore vendored

@ -2,9 +2,11 @@
/Makefile
/config.status
/configure.tmp
/configure~
/.deps/
/.libs/
*.trs
/unittests
/test-driver
/config.log
/*.tmp

@ -38,7 +38,7 @@ PROJECT_NAME = "FFmpegKit iOS / macOS / tvOS API"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 4.5
PROJECT_NUMBER = 4.5.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -154,12 +154,9 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in ar-lib compile config.guess \
config.sub install-sh ltmain.sh missing
am__DIST_COMMON = $(srcdir)/Makefile.in README.md ar-lib compile \
config.guess config.sub install-sh ltmain.sh missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
@ -215,8 +212,9 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@ -227,8 +225,9 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FFMPEG_LIBS = @FFMPEG_LIBS@
FFMPEG_FRAMEWORKS = @FFMPEG_FRAMEWORKS@
FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
@ -317,6 +316,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@ -478,7 +478,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am

@ -2,36 +2,36 @@
### 1. Features
#### 1.1 iOS
- Supports `iOS SDK 12.1+` on Main releases and `iOS SDK 9.3+` on LTS releases
- Supports `iOS SDK 12.1+` on Main releases and `iOS SDK 10+` on LTS releases
- Includes `armv7`, `armv7s`, `arm64`, `arm64-simulator`, `arm64e`, `i386`, `x86_64`, `x86_64-mac-catalyst` and
`arm64-mac-catalyst` architectures
- Objective-C API
- Camera access
- `ARC` enabled library
- Built with `-fembed-bitcode` flag
- Creates static `frameworks`, static `xcframeworks` and static `universal (fat)` libraries (.a)
- Creates shared `frameworks` and `xcframeworks`
#### 1.2 macOS
- Supports `macOS SDK 10.15+` on Main releases and `macOS SDK 10.11+` on LTS releases
- Supports `macOS SDK 10.15+` on Main releases and `macOS SDK 10.12+` on LTS releases
- Includes `arm64` and `x86_64` architectures
- Objective-C API
- Camera access
- `ARC` enabled library
- Built with `-fembed-bitcode` flag
- Creates static `frameworks`, static `xcframeworks` and static `universal (fat)` libraries (.a)
- Creates shared `frameworks` and `xcframeworks`
#### 1.3 tvOS
- Supports `tvOS SDK 10.2+` on Main releases and `tvOS SDK 9.2+` on LTS releases
- Supports `tvOS SDK 11.0+` on Main releases and `tvOS SDK 10.0+` on LTS releases
- Includes `arm64`, `arm64-simulator` and `x86_64` architectures
- Objective-C API
- `ARC` enabled library
- Built with `-fembed-bitcode` flag
- Creates static `frameworks`, static `xcframeworks` and static `universal (fat)` libraries (.a)
- Creates shared `frameworks` and `xcframeworks`
### 2. Building
Run `ios.sh`/`macos.sh`/`tvos.sh` at project root directory to build `ffmpeg-kit` and `ffmpeg` static libraries for a
platform.
Run `ios.sh`/`macos.sh`/`tvos.sh` inside the project root to build `ffmpeg-kit` and `ffmpeg` shared libraries
for a platform.
Optionally, use `apple.sh` to combine bundles created by these three scripts in a single bundle.
@ -45,20 +45,20 @@ Please note that `FFmpegKit` project repository includes the source code of `FFm
##### 2.1.1 iOS
- **Xcode 7.3.1** or later
- **iOS SDK 9.3** or later
- **Xcode 8.0** or later
- **iOS SDK 10** or later
- **Command Line Tools**
##### 2.1.2 macOS
- **Xcode 7.3.1** or later
- **macOS SDK 10.11** or later
- **Xcode 8.0** or later
- **macOS SDK 10.12** or later
- **Command Line Tools**
##### 2.1.3 tvOS
- **Xcode 7.3.1** or later
- **tvOS SDK 9.2** or later
- **Xcode 8.0** or later
- **tvOS SDK 10.0** or later
- **Command Line Tools**
##### 2.1.4 Packages
@ -97,13 +97,10 @@ All libraries created can be found under the `prebuilt` directory.
- `tvOS` `xcframeworks` for `Main` builds are located under the `bundle-apple-xcframework-tvos` folder.
- `iOS` `frameworks` for `Main` builds are located under the `bundle-apple-framework-ios` folder.
- `iOS` `frameworks` for `LTS` builds are located under the `bundle-apple-framework-ios-lts` folder.
- `iOS` `universal (fat) libraries (.a)` for `LTS` builds are located under the `bundle-apple-universal-ios-lts` folder.
- `macOS` `frameworks` for `Main` builds are located under the `bundle-apple-framework-macos` folder.
- `macOS` `frameworks` for `LTS` builds are located under the `bundle-apple-framework-macos-lts` folder.
- `macOS` `universal (fat) libraries (.a)` for `LTS` builds are located under the `bundle-apple-universal-macos-lts` folder.
- `tvOS` `frameworks` for `Main` builds are located under the `bundle-apple-framework-tvos` folder.
- `tvOS` `frameworks` for `LTS` builds are located under the `bundle-apple-framework-tvos-lts` folder.
- `tvOS` `universal (fat) libraries (.a)` for `LTS` builds are located under the `bundle-apple-universal-tvos-lts` folder.
### 3. Using
@ -114,17 +111,17 @@ All libraries created can be found under the `prebuilt` directory.
- iOS
```yaml
pod 'ffmpeg-kit-ios-full', '~> 4.5'
pod 'ffmpeg-kit-ios-full', '~> 4.5.1'
```
- macOS
```yaml
pod 'ffmpeg-kit-macos-full', '~> 4.5'
pod 'ffmpeg-kit-macos-full', '~> 4.5.1'
```
- tvOS
```yaml
pod 'ffmpeg-kit-tvos-full', '~> 4.5'
pod 'ffmpeg-kit-tvos-full', '~> 4.5.1'
```
2. Execute synchronous `FFmpeg` commands.
@ -191,7 +188,7 @@ All libraries created can be found under the `prebuilt` directory.
4. Execute asynchronous `FFmpeg` commands by providing session specific `execute`/`log`/`session` callbacks.
```objectivec
id<Session> session = [FFmpegKit executeAsync:@"-i file1.mp4 -c:v mpeg4 file2.mp4" withExecuteCallback:^(id<Session> session){
FFmpegSession* session = [FFmpegKit executeAsync:@"-i file1.mp4 -c:v mpeg4 file2.mp4" withCompleteCallback:^(FFmpegSession* session){
SessionState state = [session getState];
ReturnCode *returnCode = [session getReturnCode];
@ -225,7 +222,7 @@ All libraries created can be found under the `prebuilt` directory.
- Asynchronous
```objectivec
[FFprobeKit executeAsync:ffmpegCommand withExecuteCallback:^(id<Session> session) {
[FFprobeKit executeAsync:ffmpegCommand withCompleteCallback:^(FFprobeSession* session) {
CALLED WHEN SESSION IS EXECUTED
@ -268,10 +265,18 @@ All libraries created can be found under the `prebuilt` directory.
9. Enable global callbacks.
- Execute Callback, called when an async execution is ended
- Session type specific Complete Callbacks, called when an async session has been completed
```objectivec
[FFmpegKitConfig enableExecuteCallback:^(id<Session> session) {
[FFmpegKitConfig enableFFmpegSessionCompleteCallback:^(FFmpegSession* session) {
...
}];
[FFmpegKitConfig enableFFprobeSessionCompleteCallback:^(FFprobeSession* session) {
...
}];
[FFmpegKitConfig enableMediaInformationSessionCompleteCallback:^(MediaInformationSession* session) {
...
}];
```

72
apple/aclocal.m4 vendored

@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.3 -*- Autoconf -*-
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -14,13 +14,13 @@
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
[m4_warning([this file was generated for autoconf 2.69.
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
[m4_warning([this file was generated for autoconf 2.71.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically 'autoreconf'.])])
# Copyright (C) 2002-2020 Free Software Foundation, Inc.
# Copyright (C) 2002-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -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.3], [],
m4_if([$1], [1.16.5], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@ -51,12 +51,12 @@ 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.3])dnl
[AM_AUTOMAKE_VERSION([1.16.5])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# Copyright (C) 2011-2020 Free Software Foundation, Inc.
# Copyright (C) 2011-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -118,7 +118,7 @@ AC_SUBST([AR])dnl
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -170,7 +170,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2020 Free Software Foundation, Inc.
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -201,7 +201,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -392,7 +392,7 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -460,7 +460,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -488,6 +488,10 @@ m4_defn([AC_PROG_CC])
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.65])dnl
m4_ifdef([_$0_ALREADY_INIT],
[m4_fatal([$0 expanded multiple times
]m4_defn([_$0_ALREADY_INIT]))],
[m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
@ -524,7 +528,7 @@ m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(
m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
[ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
@ -576,6 +580,20 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
])
# Variables for tags utilities; see am/tags.am
if test -z "$CTAGS"; then
CTAGS=ctags
fi
AC_SUBST([CTAGS])
if test -z "$ETAGS"; then
ETAGS=etags
fi
AC_SUBST([ETAGS])
if test -z "$CSCOPE"; then
CSCOPE=cscope
fi
AC_SUBST([CSCOPE])
AC_REQUIRE([AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
@ -657,7 +675,7 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -678,7 +696,7 @@ if test x"${install_sh+set}" != xset; then
fi
AC_SUBST([install_sh])])
# Copyright (C) 2003-2020 Free Software Foundation, Inc.
# Copyright (C) 2003-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -700,7 +718,7 @@ AC_SUBST([am__leading_dot])])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -735,7 +753,7 @@ AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -778,7 +796,7 @@ AC_SUBST([am__quote])])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997-2020 Free Software Foundation, Inc.
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -812,7 +830,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -841,7 +859,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -888,7 +906,7 @@ AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -907,7 +925,7 @@ AC_DEFUN([AM_RUN_LOG],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -988,7 +1006,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file
])
# Copyright (C) 2009-2020 Free Software Foundation, Inc.
# Copyright (C) 2009-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1048,7 +1066,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
# Copyright (C) 2001-2020 Free Software Foundation, Inc.
# Copyright (C) 2001-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1076,7 +1094,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006-2020 Free Software Foundation, Inc.
# Copyright (C) 2006-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -1095,7 +1113,7 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004-2020 Free Software Foundation, Inc.
# Copyright (C) 2004-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,

@ -4,7 +4,7 @@
me=ar-lib
scriptversion=2019-07-04.01; # UTC
# Copyright (C) 2010-2020 Free Software Foundation, Inc.
# Copyright (C) 2010-2021 Free Software Foundation, Inc.
# Written by Peter Rosin <peda@lysator.liu.se>.
#
# This program is free software; you can redistribute it and/or modify

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify

1143
apple/config.guess vendored

File diff suppressed because it is too large Load Diff

91
apple/config.sub vendored

@ -1,8 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2020 Free Software Foundation, Inc.
# Copyright 1992-2021 Free Software Foundation, Inc.
timestamp='2020-08-17'
# shellcheck disable=SC2006,SC2268 # see below for rationale
timestamp='2021-08-14'
# 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 +35,7 @@ timestamp='2020-08-17'
# 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/gitweb/?p=config.git;a=blob_plain;f=config.sub
# https://git.savannah.gnu.org/cgit/config.git/plain/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,6 +52,13 @@ timestamp='2020-08-17'
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
# The "shellcheck disable" line above the timestamp inhibits complaints
# about features and limitations of the classic Bourne shell that were
# superseded or lifted in POSIX. However, this script identifies a wide
# variety of pre-POSIX systems that do not have POSIX shells at all, and
# even some reasonably current systems (Solaris 10 as case-in-point) still
# have a pre-POSIX /bin/sh.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
@ -67,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2020 Free Software Foundation, Inc.
Copyright 1992-2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -112,9 +121,11 @@ esac
# Split fields of configuration type
# shellcheck disable=SC2162
saved_IFS=$IFS
IFS="-" read field1 field2 field3 field4 <<EOF
$1
EOF
IFS=$saved_IFS
# Separate into logical components for further validation
case $1 in
@ -163,6 +174,10 @@ case $1 in
basic_machine=$field1
basic_os=$field2
;;
zephyr*)
basic_machine=$field1-unknown
basic_os=$field2
;;
# Manufacturers
dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
@ -922,9 +937,11 @@ case $basic_machine in
*-*)
# shellcheck disable=SC2162
saved_IFS=$IFS
IFS="-" read cpu vendor <<EOF
$basic_machine
EOF
IFS=$saved_IFS
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
@ -1165,7 +1182,7 @@ case $cpu-$vendor in
| alphapca5[67] | alpha64pca5[67] \
| am33_2.0 \
| amdgcn \
| arc | arceb \
| arc | arceb | arc32 | arc64 \
| arm | arm[lb]e | arme[lb] | armv* \
| avr | avr32 \
| asmjs \
@ -1185,6 +1202,7 @@ case $cpu-$vendor in
| k1om \
| le32 | le64 \
| lm32 \
| loongarch32 | loongarch64 | loongarchx32 \
| m32c | m32r | m32rle \
| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
@ -1203,9 +1221,13 @@ case $cpu-$vendor in
| mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa32r3 | mipsisa32r3el \
| mipsisa32r5 | mipsisa32r5el \
| mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \
| mipsisa64r3 | mipsisa64r3el \
| mipsisa64r5 | mipsisa64r5el \
| mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
@ -1229,7 +1251,7 @@ case $cpu-$vendor in
| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
| pru \
| pyramid \
| riscv | riscv32 | riscv64 \
| riscv | riscv32 | riscv32be | riscv64 | riscv64be \
| rl78 | romp | rs6000 | rx \
| s390 | s390x \
| score \
@ -1241,6 +1263,7 @@ case $cpu-$vendor in
| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
| spu \
| tahoe \
| thumbv7* \
| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
| tron \
| ubicom32 \
@ -1286,26 +1309,32 @@ then
case $basic_os in
gnu/linux*)
kernel=linux
os=`echo $basic_os | sed -e 's|gnu/linux|gnu|'`
os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
;;
os2-emx)
kernel=os2
os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
;;
nto-qnx*)
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
saved_IFS=$IFS
IFS="-" read kernel os <<EOF
$basic_os
EOF
IFS=$saved_IFS
;;
# 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=
@ -1326,7 +1355,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
@ -1355,7 +1384,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
@ -1367,13 +1396,7 @@ case $os in
os=psos
;;
qnx*)
case $cpu in
x86 | i*86)
;;
*)
os=nto-$os
;;
esac
os=qnx
;;
hiux*)
os=hiuxwe2
@ -1437,7 +1460,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
@ -1683,11 +1706,14 @@ fi
# Now, validate our (potentially fixed-up) OS.
case $os in
# Sometimes we do "kernel-abi", so those need to count as OSes.
musl* | newlib* | uclibc*)
# Sometimes we do "kernel-libc", so those need to count as OSes.
musl* | newlib* | relibc* | uclibc*)
;;
# Likewise for "kernel-abi"
eabi* | gnueabi*)
;;
# Likewise for "kernel-libc"
eabi | eabihf | gnueabi | gnueabihf)
# VxWorks passes extra cpu info in the 4th filed.
simlinux | simwindows | spe)
;;
# Now accept the basic system types.
# The portable systems comes first.
@ -1704,12 +1730,12 @@ case $os in
| nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
| clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
| mirbsd* | netbsd* | dicos* | openedition* | ose* \
| bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
| bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
| ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
| bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
| ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
| udi* | lites* | ieee* | go32* | aux* | hcos* \
| chorusrdb* | cegcc* | glidix* \
| chorusrdb* | cegcc* | glidix* | serenity* \
| cygwin* | msys* | pe* | moss* | proelf* | rtems* \
| midipix* | mingw32* | mingw64* | mint* \
| uxpv* | beos* | mpeix* | udk* | moxiebox* \
@ -1722,7 +1748,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* )
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*)
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@ -1739,9 +1765,12 @@ esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
case $kernel-$os in
linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
| linux-musl* | linux-relibc* | linux-uclibc* )
;;
-dietlibc* | -newlib* | -musl* | -uclibc* )
uclinux-uclibc* )
;;
-dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
@ -1749,8 +1778,12 @@ case $kernel-$os in
;;
kfreebsd*-gnu* | kopensolaris*-gnu*)
;;
vxworks-simlinux | vxworks-simwindows | vxworks-spe)
;;
nto-qnx*)
;;
os2-emx)
;;
*-eabi* | *-gnueabi*)
;;
-*)

6347
apple/configure vendored

File diff suppressed because it is too large Load Diff

@ -1,8 +1,8 @@
# ffmpeg-kit 4.4 configure.ac
# ffmpeg-kit 4.5.1 configure.ac
AC_INIT([ffmpeg-kit], [4.4], [https://github.com/tanersener/ffmpeg-kit/issues/new])
AC_CONFIG_SRCDIR([src/FFmpegKit.m])
AC_INIT([ffmpeg-kit], [4.5.1], [https://github.com/tanersener/ffmpeg-kit/issues/new])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([src/FFmpegKit.m])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AM_MAINTAINER_MODE
@ -24,8 +24,8 @@ AM_PROG_AR
AC_PROG_OBJC
CFLAGS="$cflags_bckup"
FFMPEG_LIBS="-lavcodec -lavfilter -lavformat -lavutil -lswscale -lswresample"
AC_SUBST(FFMPEG_LIBS)
FFMPEG_FRAMEWORKS="-framework libavcodec -framework libavfilter -framework libavformat -framework libavutil -framework libswscale -framework libswresample"
AC_SUBST(FFMPEG_FRAMEWORKS)
LT_INIT
@ -58,7 +58,6 @@ AC_TYPE_UINT8_T
# Checks for library functions.
AC_CHECK_FUNCS([dup2 floor memmove memset select strchr strcspn strerror strrchr strstr strtol malloc strcpy strlen vsnprintf])
AC_CONFIG_FILES([Makefile
src/Makefile])
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1999-2020 Free Software Foundation, Inc.
# Copyright (C) 1999-2021 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by

@ -1,6 +1,6 @@
#! /bin/sh
# Generated automatically by config.status (ffmpeg-kit) 4.4
# Libtool was configured on host mera.local:
# Generated automatically by config.status (ffmpeg-kit) 4.5
# Libtool was configured on host MiRA.local:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
@ -42,10 +42,10 @@ macro_version=2.4.6
macro_revision=2.4.6
# Whether or not to build shared libraries.
build_libtool_libs=no
build_libtool_libs=yes
# Whether or not to build static libraries.
build_old_libs=yes
build_old_libs=no
# What type of objects to build.
pic_mode=yes
@ -66,14 +66,14 @@ ECHO="printf %s\\n"
PATH_SEPARATOR=":"
# The host system.
host_alias=x86_64-ios-darwin
host=x86_64-ios-darwin
host_alias=arm64-ios-darwin
host=aarch64-ios-darwin
host_os=darwin
# The build system.
build_alias=
build=x86_64-apple-darwin18.5.0
build_os=darwin18.5.0
build=aarch64-apple-darwin20.6.0
build_os=darwin20.6.0
# A sed program that does not truncate output.
SED="/usr/bin/sed"
@ -91,13 +91,13 @@ EGREP="/usr/bin/grep -E"
FGREP="/usr/bin/grep -F"
# A BSD- or MS-compatible name lister.
NM="nm"
NM="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/nm"
# Whether we need soft or hard links.
LN_S="ln -s"
# What is the maximum length of a command?
max_cmd_len=196608
max_cmd_len=786432
# Object file suffix (normally "o").
objext=o
@ -136,25 +136,25 @@ file_magic_glob=""
want_nocaseglob="no"
# DLL creation program.
DLLTOOL="dlltool"
DLLTOOL="false"
# Command to associate shared and link libraries.
sharedlib_from_linklib_cmd="printf %s\\n"
# The archiver.
AR="ar"
AR="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar"
# Flags to create an archive.
AR_FLAGS="cru"
# How to feed a file listing to the archiver.
archiver_list_spec="@"
archiver_list_spec=""
# A symbol stripping program.
STRIP="strip"
STRIP="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip"
# Commands used to install an old-style archive.
RANLIB="ranlib"
RANLIB="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib"
old_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$tool_oldlib"
old_postuninstall_cmds=""
@ -165,22 +165,22 @@ lock_old_archive_extraction=yes
LTCC="clang"
# LTCC compiler flags.
LTCFLAGS="-arch x86_64 -target x86_64-ios-darwin -march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel -DFFMPEG_KIT_X86_64 -std=c99 -Wno-unused-function -Wall -Wno-deprecated-declarations -Wno-pointer-sign -Wno-switch -Wno-unused-result -Wno-unused-variable -DPIC -fobjc-arc -fstrict-aliasing -DIOS -DFFMPEG_KIT_BUILD_DATE=20190403 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.2.sdk -O2 -Wno-ignored-optimization-argument -mios-simulator-version-min=12.1 -I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.2.sdk/usr/include -I/Users/taner/Projects/ffmpeg-kit/prebuilt/ios-x86_64-ios-darwin/ffmpeg/include"
LTCFLAGS="-arch arm64 -target arm64-apple-ios12.1 -march=armv8-a+crc+crypto -mcpu=generic -DFFMPEG_KIT_ARM64 -std=c99 -Wno-unused-function -Wall -Wno-deprecated-declarations -Wno-pointer-sign -Wno-switch -Wno-unused-result -Wno-unused-variable -DPIC -fobjc-arc -fstrict-aliasing -fembed-bitcode -DIOS -DFFMPEG_KIT_BUILD_DATE=20211024 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.0.sdk -Oz -Wno-ignored-optimization-argument -miphoneos-version-min=12.1 -I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.0.sdk/usr/include -I/Users/taner/Projects/ffmpeg-kit/prebuilt/apple-ios-arm64/ffmpeg/include"
# Take the output of nm and produce a listing of raw symbols and C names.
global_symbol_pipe="sed -n -e 's/^.*[ ]\\([ABCDGIRSTW][ABCDGIRSTW]*\\)[ ][ ]*_\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 _\\2 \\2/p' | sed '/ __gnu_lto/d'"
global_symbol_pipe="sed -n -e 's/^.*[ ]\\([BCDEGRST][BCDEGRST]*\\)[ ][ ]*_\\([_A-Za-z][_A-Za-z0-9]*\\)\$/\\1 _\\2 \\2/p' | sed '/ __gnu_lto/d'"
# Transform the output of nm in a proper C declaration.
global_symbol_to_cdecl="sed -n -e 's/^T .* \\(.*\\)\$/extern int \\1();/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/extern char \\1;/p'"
global_symbol_to_cdecl="sed -n -e 's/^T .* \\(.*\\)\$/extern int \\1();/p' -e 's/^[BCDEGRST][BCDEGRST]* .* \\(.*\\)\$/extern char \\1;/p'"
# Transform the output of nm into a list of symbols to manually relocate.
global_symbol_to_import=""
# Transform the output of nm in a C name address pair.
global_symbol_to_c_name_address="sed -n -e 's/^: \\(.*\\) .*\$/ {\"\\1\", (void *) 0},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/ {\"\\1\", (void *) \\&\\1},/p'"
global_symbol_to_c_name_address="sed -n -e 's/^: \\(.*\\) .*\$/ {\"\\1\", (void *) 0},/p' -e 's/^[BCDEGRST][BCDEGRST]* .* \\(.*\\)\$/ {\"\\1\", (void *) \\&\\1},/p'"
# Transform the output of nm in a C name address pair when lib prefix is needed.
global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \\(.*\\) .*\$/ {\"\\1\", (void *) 0},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(lib.*\\)\$/ {\"\\1\", (void *) \\&\\1},/p' -e 's/^[ABCDGIRSTW][ABCDGIRSTW]* .* \\(.*\\)\$/ {\"lib\\1\", (void *) \\&\\1},/p'"
global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \\(.*\\) .*\$/ {\"\\1\", (void *) 0},/p' -e 's/^[BCDEGRST][BCDEGRST]* .* \\(lib.*\\)\$/ {\"\\1\", (void *) \\&\\1},/p' -e 's/^[BCDEGRST][BCDEGRST]* .* \\(.*\\)\$/ {\"lib\\1\", (void *) \\&\\1},/p'"
# The name lister interface.
nm_interface="BSD nm"
@ -189,7 +189,7 @@ nm_interface="BSD nm"
nm_file_list_spec="@"
# The root where to search for dependent libraries,and where our libraries should be installed.
lt_sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.2.sdk
lt_sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS15.0.sdk
# Command to truncate a binary pipe.
lt_truncate_bin="/bin/dd bs=4096 count=1"
@ -213,7 +213,7 @@ DSYMUTIL="dsymutil"
NMEDIT="nmedit"
# Tool to manipulate fat objects and archives on Mac OS X.
LIPO="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo"
LIPO="lipo"
# ldd/readelf like tool for Mach-O binaries on Mac OS X.
OTOOL="otool"
@ -282,7 +282,7 @@ finish_eval=""
hardcode_into_libs=no
# Compile-time system search path for libraries.
sys_lib_search_path_spec="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.1 /usr/local/lib"
sys_lib_search_path_spec="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0 /usr/local/lib"
# Detected run-time system search path for libraries.
sys_lib_dlsearch_path_spec="/usr/local/lib /lib /usr/lib"
@ -300,12 +300,12 @@ dlopen_self=unknown
dlopen_self_static=unknown
# Commands to strip libraries.
old_striplib="strip --strip-debug"
striplib="strip --strip-unneeded"
old_striplib="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip -S"
striplib="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip -x"
# The linker used to build libraries.
LD="ld"
LD="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld"
# How to create reloadable object files.
reload_flag=" -r"
@ -345,7 +345,7 @@ allow_libtool_libs_with_static_runtimes=no
export_dynamic_flag_spec=""
# Compiler flag to generate shared objects directly from archives.
whole_archive_flag_spec=""
whole_archive_flag_spec="\`for conv in \$convenience\\\"\\\"; do test -n \\\"\$conv\\\" && new_convenience=\\\"\$new_convenience \$wl-force_load,\$conv\\\"; done; func_echo_all \\\"\$new_convenience\\\"\`"
# Whether the compiler copes with passing no objects directly.
compiler_needs_object="no"
@ -357,19 +357,19 @@ old_archive_from_new_cmds=""
old_archive_from_expsyms_cmds=""
# Commands used to build a shared archive.
archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring \$single_module~\$DSYMUTIL \$lib || :"
archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring \$single_module \$wl-exported_symbols_list,\$output_objdir/\$libname-symbols.expsym~\$DSYMUTIL \$lib || :"
archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring \$single_module"
archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring \$single_module \$wl-exported_symbols_list,\$output_objdir/\$libname-symbols.expsym"
# Commands used to build a loadable module if different from building
# a shared archive.
module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags~\$DSYMUTIL \$lib || :"
module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags \$wl-exported_symbols_list,\$output_objdir/\$libname-symbols.expsym~\$DSYMUTIL \$lib || :"
module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags"
module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags \$wl-exported_symbols_list,\$output_objdir/\$libname-symbols.expsym"
# Whether we are building with GNU ld or not.
with_gnu_ld="no"
# Flag that allows shared libraries with undefined symbols to be built.
allow_undefined_flag=""
allow_undefined_flag="\$wl-undefined \${wl}dynamic_lookup"
# Flag that enforces no undefined symbols.
no_undefined_flag=""

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify

@ -29,8 +29,8 @@
extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
/**
* Abstract session implementation which includes common features shared by <code>FFmpeg</code>
* and <code>FFprobe</code> sessions.
* Abstract session implementation which includes common features shared by <code>FFmpeg</code>,
* <code>FFprobe</code> and <code>MediaInformation</code> sessions.
*/
@interface AbstractSession : NSObject<Session>
@ -38,11 +38,10 @@ extern int const AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit;
* Creates a new abstract session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param logCallback session specific log callback
* @param logRedirectionStrategy session specific log redirection strategy
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
- (instancetype)init:(NSArray*)arguments withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
/**
* Waits for all asynchronous messages to be transmitted until the given timeout.

@ -19,7 +19,6 @@
#import "AbstractSession.h"
#import "AtomicLong.h"
#import "ExecuteCallback.h"
#import "FFmpegKit.h"
#import "FFmpegKitConfig.h"
#import "LogCallback.h"
@ -33,7 +32,6 @@ extern void addSessionToSessionHistory(id<Session> session);
@implementation AbstractSession {
long _sessionId;
ExecuteCallback _executeCallback;
LogCallback _logCallback;
NSDate* _createTime;
NSDate* _startTime;
@ -51,11 +49,10 @@ extern void addSessionToSessionHistory(id<Session> session);
sessionIdGenerator = [[AtomicLong alloc] initWithValue:1];
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
- (instancetype)init:(NSArray*)arguments withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
self = [super init];
if (self) {
_sessionId = [sessionIdGenerator getAndIncrement];
_executeCallback = executeCallback;
_logCallback = logCallback;
_createTime = [NSDate date];
_startTime = nil;
@ -74,10 +71,6 @@ extern void addSessionToSessionHistory(id<Session> session);
return self;
}
- (ExecuteCallback)getExecuteCallback {
return _executeCallback;
}
- (LogCallback)getLogCallback {
return _logCallback;
}
@ -230,6 +223,11 @@ extern void addSessionToSessionHistory(id<Session> session);
return false;
}
- (BOOL)isMediaInformation {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (void)cancel {
if (_state == SessionStateRunning) {
[FFmpegKit cancel:_sessionId];

@ -0,0 +1,84 @@
/*
* 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/>.
*/
#ifndef FFMPEG_KIT_CHAPTER_H
#define FFMPEG_KIT_CHAPTER_H
#import <Foundation/Foundation.h>
extern NSString* const ChapterKeyId;
extern NSString* const ChapterKeyTimeBase;
extern NSString* const ChapterKeyStart;
extern NSString* const ChapterKeyStartTime;
extern NSString* const ChapterKeyEnd;
extern NSString* const ChapterKeyEndTime;
extern NSString* const ChapterKeyTags;
/**
* Chapter class.
*/
@interface Chapter : NSObject
- (instancetype)init:(NSDictionary*)chapterDictionary;
- (NSNumber*)getId;
- (NSString*)getTimeBase;
- (NSNumber*)getStart;
- (NSString*)getStartTime;
- (NSNumber*)getEnd;
- (NSString*)getEndTime;
- (NSDictionary*)getTags;
/**
* Returns the chapter property associated with the key.
*
* @return chapter property as string or nil if the key is not found
*/
- (NSString*)getStringProperty:(NSString*)key;
/**
* Returns the chapter property associated with the key.
*
* @return chapter property as number or nil if the key is not found
*/
- (NSNumber*)getNumberProperty:(NSString*)key;
/**
* Returns the chapter properties associated with the key.
*
* @return chapter properties in a dictionary or nil if the key is not found
*/
- (NSDictionary*)getProperties:(NSString*)key;
/**
* Returns all chapter properties defined.
*
* @return all chapter properties in a dictionary or nil if no properties are defined
*/
- (NSDictionary*)getAllProperties;
@end
#endif // FFMPEG_KIT_CHAPTER_H

@ -0,0 +1,107 @@
/*
* 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/>.
*/
#import "Chapter.h"
NSString* const ChapterKeyId = @"id";
NSString* const ChapterKeyTimeBase = @"time_base";
NSString* const ChapterKeyStart = @"start";
NSString* const ChapterKeyStartTime = @"start_time";
NSString* const ChapterKeyEnd = @"end";
NSString* const ChapterKeyEndTime = @"end_time";
NSString* const ChapterKeyTags = @"tags";
@implementation Chapter {
/**
* Stores all properties.
*/
NSDictionary *dictionary;
}
- (instancetype)init:(NSDictionary*)chapterDictionary {
self = [super init];
if (self) {
dictionary = chapterDictionary;
}
return self;
}
- (NSNumber*)getId {
return [self getNumberProperty:ChapterKeyId];
}
- (NSString*)getTimeBase {
return [self getStringProperty:ChapterKeyTimeBase];
}
- (NSNumber*)getStart {
return [self getNumberProperty:ChapterKeyStart];
}
- (NSString*)getStartTime {
return [self getStringProperty:ChapterKeyStartTime];
}
- (NSNumber*)getEnd {
return [self getNumberProperty:ChapterKeyEnd];
}
- (NSString*)getEndTime {
return [self getStringProperty:ChapterKeyEndTime];
}
- (NSDictionary*)getTags {
return [self getProperties:ChapterKeyTags];
}
- (NSString*)getStringProperty:(NSString*)key {
NSDictionary* allProperties = [self getAllProperties];
if (allProperties == nil) {
return nil;
}
return allProperties[key];
}
- (NSNumber*)getNumberProperty:(NSString*)key {
NSDictionary* mediaProperties = [self getAllProperties];
if (mediaProperties == nil) {
return nil;
}
return mediaProperties[key];
}
- (NSDictionary*)getProperties:(NSString*)key {
NSDictionary* allProperties = [self getAllProperties];
if (allProperties == nil) {
return nil;
}
return allProperties[key];
}
- (NSDictionary*)getAllProperties {
return dictionary;
}
@end

@ -23,7 +23,6 @@
#import <string.h>
#import <stdlib.h>
#import <Foundation/Foundation.h>
#import "ExecuteCallback.h"
#import "LogCallback.h"
#import "FFmpegSession.h"
#import "StatisticsCallback.h"
@ -34,11 +33,11 @@
* <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" withExecuteCallback:executeCallback];
* FFmpegSession *asyncSession = [FFmpegKit executeAsync:@"-i file1.mp4 -c:v libxvid file1.avi" withCompleteCallback:completeCallback];
* </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre>
* FFmpegSession *asyncSession = [FFmpegKit executeAsync:@"-i file1.mp4 -c:v libxvid file1.avi" withExecuteCallback:executeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
* FFmpegSession *asyncSession = [FFmpegKit executeAsync:@"-i file1.mp4 -c:v libxvid file1.avi" withCompleteCallback:completeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
* </pre>
*/
@interface FFmpegKit : NSObject
@ -54,56 +53,56 @@
/**
* <p>Starts an asynchronous FFmpeg execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param arguments FFmpeg command options/arguments as string array
* @param completeCallback callback that will be called when the execution has completed
* @return FFmpeg session created for this execution
*/
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback;
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback;
/**
* <p>Starts an asynchronous FFmpeg execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param arguments FFmpeg command options/arguments as string array
* @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 arguments FFmpeg command options/arguments as string array
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics
* @return FFmpeg session created for this execution
*/
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback;
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback;
/**
* <p>Starts an asynchronous FFmpeg execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param arguments FFmpeg command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @param arguments FFmpeg command options/arguments as string array
* @param completeCallback callback that will be called when the execution has completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Starts an asynchronous FFmpeg execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param arguments FFmpeg command options/arguments as string array
* @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 queue dispatch queue that will be used to run this asynchronous operation
* @param arguments FFmpeg command options/arguments as string array
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback 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*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Synchronously executes FFmpeg command provided. Space character is used to split command
@ -120,70 +119,70 @@
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFmpeg command
* @param executeCallback callback that will be called when the execution is completed
* @param command FFmpeg command
* @param completeCallback callback that will be called when the execution has completed
* @return FFmpeg session created for this execution
*/
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback;
+ (FFmpegSession*)executeAsync:(NSString*)command withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback;
/**
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFmpeg command
* @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 command FFmpeg command
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics
* @return FFmpeg session created for this execution
*/
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback;
+ (FFmpegSession*)executeAsync:(NSString*)command withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback;
/**
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFmpeg command
* @param executeCallback callback that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @param command FFmpeg command
* @param completeCallback callback that will be called when the execution has completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution
*/
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (FFmpegSession*)executeAsync:(NSString*)command withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFmpeg command
* @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 queue dispatch queue that will be used to run this asynchronous operation
* @param command FFmpeg command
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param statisticsCallback callback 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 withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (FFmpegSession*)executeAsync:(NSString*)command withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Cancels all running sessions.
*
* <p>This function does not wait for termination to complete and returns immediately.
* <p>This method does not wait for termination to complete and returns immediately.
*/
+ (void)cancel;
/**
* <p>Cancels the session specified with <code>sessionId</code>.
*
* <p>This function does not wait for termination to complete and returns immediately.
* <p>This method does not wait for termination to complete and returns immediately.
*
* @param sessionId id of the session that will be cancelled
*/

@ -40,26 +40,26 @@
return session;
}
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteCallback:executeCallback];
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
}
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:completeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
}
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteCallback:executeCallback];
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
return session;
}
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
+ (FFmpegSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:arguments withCompleteCallback:completeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
[FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
return session;
}
@ -70,26 +70,26 @@
return session;
}
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKitConfig parseArguments:command] withExecuteCallback:executeCallback];
+ (FFmpegSession*)executeAsync:(NSString*)command withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
}
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKitConfig parseArguments:command] withExecuteCallback:executeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
+ (FFmpegSession*)executeAsync:(NSString*)command withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
[FFmpegKitConfig asyncFFmpegExecute:session];
return session;
}
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKitConfig parseArguments:command] withExecuteCallback:executeCallback];
+ (FFmpegSession*)executeAsync:(NSString*)command withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
return session;
}
+ (FFmpegSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKitConfig parseArguments:command] withExecuteCallback:executeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
+ (FFmpegSession*)executeAsync:(NSString*)command withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback onDispatchQueue:(dispatch_queue_t)queue {
FFmpegSession* session = [[FFmpegSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback withLogCallback:logCallback withStatisticsCallback:statisticsCallback];
[FFmpegKitConfig asyncFFmpegExecute:session onDispatchQueue:queue];
return session;
}

@ -24,7 +24,6 @@
#import <pthread.h>
#import <unistd.h>
#import <Foundation/Foundation.h>
#import "ExecuteCallback.h"
#import "FFmpegSession.h"
#import "FFprobeSession.h"
#import "LogCallback.h"
@ -191,8 +190,8 @@ typedef NS_ENUM(NSUInteger, Signal) {
/**
* <p>Starts an asynchronous FFmpeg execution for the given session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param ffmpegSession FFmpeg session which includes command options/arguments
*/
@ -201,8 +200,8 @@ typedef NS_ENUM(NSUInteger, Signal) {
/**
* <p>Starts an asynchronous FFmpeg execution for the given session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
*
* @param ffmpegSession FFmpeg session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation
@ -212,8 +211,8 @@ typedef NS_ENUM(NSUInteger, Signal) {
/**
* <p>Starts an asynchronous FFprobe execution for the given session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @param ffprobeSession FFprobe session which includes command options/arguments
*/
@ -222,8 +221,8 @@ typedef NS_ENUM(NSUInteger, Signal) {
/**
* <p>Starts an asynchronous FFprobe execution for the given session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @param ffprobeSession FFprobe session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation
@ -233,8 +232,8 @@ typedef NS_ENUM(NSUInteger, Signal) {
/**
* <p>Starts an asynchronous FFprobe execution for the given media information session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an MediaInformationSessionCompleteCallback if you want to be notified about the result.
*
* @param mediaInformationSession media information session which includes command options/arguments
* @param waitTimeout max time to wait until media information is transmitted
@ -244,8 +243,8 @@ typedef NS_ENUM(NSUInteger, Signal) {
/**
* <p>Starts an asynchronous FFprobe execution for the given media information session.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an MediaInformationSessionCompleteCallback if you want to be notified about the result.
*
* @param mediaInformationSession media information session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation
@ -268,18 +267,47 @@ typedef NS_ENUM(NSUInteger, Signal) {
+ (void)enableStatisticsCallback:(StatisticsCallback)statisticsCallback;
/**
* <p>Sets a global execute callback to receive execution results.
* <p>Sets a global FFmpegSessionCompleteCallback to receive execution results for FFmpeg sessions.
*
* @param executeCallback execute callback or nil to disable a previously execute callback
* @param ffmpegSessionCompleteCallback complete callback or nil to disable a previously defined callback
*/
+ (void)enableExecuteCallback:(ExecuteCallback)executeCallback;
+ (void)enableFFmpegSessionCompleteCallback:(FFmpegSessionCompleteCallback)ffmpegSessionCompleteCallback;
/**
* <p>Returns the global execute callback.
* <p>Returns the global FFmpegSessionCompleteCallback set.
*
* @return global execute callback
* @return global FFmpegSessionCompleteCallback or nil if it is not set
*/
+ (ExecuteCallback)getExecuteCallback;
+ (FFmpegSessionCompleteCallback)getFFmpegSessionCompleteCallback;
/**
* <p>Sets a global FFprobeSessionCompleteCallback to receive execution results for FFprobe sessions.
*
* @param ffprobeSessionCompleteCallback complete callback or nil to disable a previously defined callback
*/
+ (void)enableFFprobeSessionCompleteCallback:(FFprobeSessionCompleteCallback)ffprobeSessionCompleteCallback;
/**
* <p>Returns the global FFprobeSessionCompleteCallback set.
*
* @return global FFprobeSessionCompleteCallback or nil if it is not set
*/
+ (FFprobeSessionCompleteCallback)getFFprobeSessionCompleteCallback;
/**
* <p>Sets a global MediaInformationSessionCompleteCallback to receive execution results for MediaInformation sessions.
*
* @param mediaInformationSessionCompleteCallback complete callback or nil to disable a previously defined
* callback
*/
+ (void)enableMediaInformationSessionCompleteCallback:(MediaInformationSessionCompleteCallback)mediaInformationSessionCompleteCallback;
/**
* <p>Returns the global MediaInformationSessionCompleteCallback set.
*
* @return global MediaInformationSessionCompleteCallback or nil if it is not set
*/
+ (MediaInformationSessionCompleteCallback)getMediaInformationSessionCompleteCallback;
/**
* Returns the current log level.
@ -367,6 +395,13 @@ typedef NS_ENUM(NSUInteger, Signal) {
*/
+ (NSArray*)getFFprobeSessions;
/**
* <p>Returns all MediaInformation sessions in the session history.
*
* @return all MediaInformation sessions in the session history
*/
+ (NSArray*)getMediaInformationSessions;
/**
* <p>Returns sessions that have the given state.
*

@ -21,6 +21,7 @@
#import <sys/types.h>
#import <sys/stat.h>
#import "libavutil/ffversion.h"
#import "libavutil/bprint.h"
#import "fftools_ffmpeg.h"
#import "ArchDetect.h"
#import "AtomicLong.h"
@ -35,7 +36,7 @@
#import "SessionState.h"
/** Global library version */
NSString* const FFmpegKitVersion = @"4.5";
NSString* const FFmpegKitVersion = @"4.5.1";
/**
* Prefix of named pipes created by ffmpeg-kit.
@ -66,8 +67,10 @@ static LogCallback logCallback;
/** Holds callback defined to redirect statistics */
static StatisticsCallback statisticsCallback;
/** Holds callback defined to redirect asynchronous execution results */
static ExecuteCallback executeCallback;
/** Holds complete callbacks defined to redirect asynchronous execution results */
static FFmpegSessionCompleteCallback ffmpegSessionCompleteCallback;
static FFprobeSessionCompleteCallback ffprobeSessionCompleteCallback;
static MediaInformationSessionCompleteCallback mediaInformationSessionCompleteCallback;
static LogRedirectionStrategy globalLogRedirectionStrategy;
@ -138,7 +141,7 @@ void addSessionToSessionHistory(id<Session> session) {
long _sessionId; // session id
int _logLevel; // log level
NSString* _logData; // log data
AVBPrint _logData; // log data
int _statisticsFrameNumber; // statistics frame number
float _statisticsFps; // statistics fps
@ -149,13 +152,14 @@ void addSessionToSessionHistory(id<Session> session) {
double _statisticsSpeed; // statistics speed
}
- (instancetype)init:(long)sessionId logLevel:(int)logLevel data:(NSString*)logData {
- (instancetype)init:(long)sessionId logLevel:(int)logLevel data:(AVBPrint*)data {
self = [super init];
if (self) {
_type = LogType;
_sessionId = sessionId;
_logLevel = logLevel;
_logData = logData;
av_bprint_init(&_logData, 0, AV_BPRINT_SIZE_UNLIMITED);
av_bprintf(&_logData, "%s", data->str);
}
return self;
@ -197,8 +201,8 @@ void addSessionToSessionHistory(id<Session> session) {
return _logLevel;
}
- (NSString*)getLogData {
return _logData;
- (AVBPrint*)getLogData {
return &_logData;
}
- (int)getStatisticsFrameNumber {
@ -247,15 +251,80 @@ void callbackNotify() {
dispatch_semaphore_signal(semaphore);
}
static const char *avutil_log_get_level_str(int level) {
switch (level) {
case AV_LOG_STDERR:
return "stderr";
case AV_LOG_QUIET:
return "quiet";
case AV_LOG_DEBUG:
return "debug";
case AV_LOG_VERBOSE:
return "verbose";
case AV_LOG_INFO:
return "info";
case AV_LOG_WARNING:
return "warning";
case AV_LOG_ERROR:
return "error";
case AV_LOG_FATAL:
return "fatal";
case AV_LOG_PANIC:
return "panic";
default:
return "";
}
}
static void avutil_log_format_line(void *avcl, int level, const char *fmt, va_list vl, AVBPrint part[4], int *print_prefix) {
int flags = av_log_get_flags();
AVClass* avc = avcl ? *(AVClass **) avcl : NULL;
av_bprint_init(part+0, 0, 1);
av_bprint_init(part+1, 0, 1);
av_bprint_init(part+2, 0, 1);
av_bprint_init(part+3, 0, 65536);
if (*print_prefix && avc) {
if (avc->parent_log_context_offset) {
AVClass** parent = *(AVClass ***) (((uint8_t *) avcl) +
avc->parent_log_context_offset);
if (parent && *parent) {
av_bprintf(part+0, "[%s @ %p] ",
(*parent)->item_name(parent), parent);
}
}
av_bprintf(part+1, "[%s @ %p] ",
avc->item_name(avcl), avcl);
}
if (*print_prefix && (level > AV_LOG_QUIET) && (flags & AV_LOG_PRINT_LEVEL))
av_bprintf(part+2, "[%s] ", avutil_log_get_level_str(level));
av_vbprintf(part+3, fmt, vl);
if(*part[0].str || *part[1].str || *part[2].str || *part[3].str) {
char lastc = part[3].len && part[3].len <= part[3].size ? part[3].str[part[3].len - 1] : 0;
*print_prefix = lastc == '\n' || lastc == '\r';
}
}
static void avutil_log_sanitize(uint8_t *line) {
while(*line){
if(*line < 0x08 || (*line > 0x0D && *line < 0x20))
*line='?';
line++;
}
}
/**
* Adds log data to the end of callback data list.
*
* @param level log level
* @param logData log data
* @param data log data
*/
void logCallbackDataAdd(int level, NSString *logData) {
CallbackData* callbackData = [[CallbackData alloc] init:globalSessionId logLevel:level data:logData];
void logCallbackDataAdd(int level, AVBPrint *data) {
CallbackData* callbackData = [[CallbackData alloc] init:globalSessionId logLevel:level data:data];
[lock lock];
[callbackDataArray addObject:callbackData];
[lock unlock];
@ -361,6 +430,9 @@ void resetMessagesInTransmit(long sessionId) {
* @param vargs arguments
*/
void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, va_list vargs) {
AVBPrint fullLine;
AVBPrint part[4];
int print_prefix = 1;
// DO NOT PROCESS UNWANTED LOGS
if (level >= 0) {
@ -373,11 +445,26 @@ void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, v
return;
}
NSString *logData = [[NSString alloc] initWithFormat:[NSString stringWithCString:format encoding:NSUTF8StringEncoding] arguments:vargs];
av_bprint_init(&fullLine, 0, AV_BPRINT_SIZE_UNLIMITED);
avutil_log_format_line(ptr, level, format, vargs, part, &print_prefix);
avutil_log_sanitize(part[0].str);
avutil_log_sanitize(part[1].str);
avutil_log_sanitize(part[2].str);
avutil_log_sanitize(part[3].str);
// COMBINE ALL 4 LOG PARTS
av_bprintf(&fullLine, "%s%s%s%s", part[0].str, part[1].str, part[2].str, part[3].str);
if (logData.length > 0) {
logCallbackDataAdd(level, logData);
if (fullLine.len > 0) {
logCallbackDataAdd(level, &fullLine);
}
av_bprint_finalize(part, NULL);
av_bprint_finalize(part+1, NULL);
av_bprint_finalize(part+2, NULL);
av_bprint_finalize(part+3, NULL);
av_bprint_finalize(&fullLine, NULL);
}
/**
@ -395,9 +482,9 @@ void ffmpegkit_statistics_callback_function(int frameNumber, float fps, float qu
statisticsCallbackDataAdd(frameNumber, fps, quality, size, time, bitrate, speed);
}
void process_log(long sessionId, int levelValue, NSString* logMessage) {
void process_log(long sessionId, int levelValue, AVBPrint* logMessage) {
int activeLogLevel = av_log_get_level();
Log* log = [[Log alloc] init:sessionId:levelValue:logMessage];
Log* log = [[Log alloc] init:sessionId:levelValue:[NSString stringWithCString:logMessage->str encoding:NSUTF8StringEncoding]];
BOOL globalCallbackDefined = false;
BOOL sessionCallbackDefined = false;
LogRedirectionStrategy activeLogRedirectionStrategy = globalLogRedirectionStrategy;
@ -422,7 +509,7 @@ void process_log(long sessionId, int levelValue, NSString* logMessage) {
sessionLogCallback(log);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside session LogCallback block. %@", [exception callStackSymbols]);
NSLog(@"Exception thrown inside session log callback. %@", [exception callStackSymbols]);
}
}
}
@ -436,7 +523,7 @@ void process_log(long sessionId, int levelValue, NSString* logMessage) {
globalLogCallback(log);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside global LogCallback block. %@", [exception callStackSymbols]);
NSLog(@"Exception thrown inside global log callback. %@", [exception callStackSymbols]);
}
}
@ -456,13 +543,16 @@ void process_log(long sessionId, int levelValue, NSString* logMessage) {
return;
}
}
break;
case LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined: {
if (globalCallbackDefined || sessionCallbackDefined) {
return;
}
}
break;
case LogRedirectionStrategyAlwaysPrintLogs: {
}
break;
}
// PRINT LOGS
@ -472,7 +562,7 @@ void process_log(long sessionId, int levelValue, NSString* logMessage) {
break;
default:
// WRITE TO NSLOG
NSLog(@"%@: %@", [FFmpegKitConfig logLevelToString:levelValue], logMessage);
NSLog(@"%@: %@", [FFmpegKitConfig logLevelToString:levelValue], [NSString stringWithCString:logMessage->str encoding:NSUTF8StringEncoding]);
break;
}
}
@ -492,7 +582,7 @@ void process_statistics(long sessionId, int videoFrameNumber, float videoFps, fl
sessionStatisticsCallback(statistics);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside session StatisticsCallback block. %@", [exception callStackSymbols]);
NSLog(@"Exception thrown inside session statistics callback. %@", [exception callStackSymbols]);
}
}
}
@ -503,7 +593,7 @@ void process_statistics(long sessionId, int videoFrameNumber, float videoFps, fl
globalStatisticsCallback(statistics);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside global StatisticsCallback block. %@", [exception callStackSymbols]);
NSLog(@"Exception thrown inside global statistics callback. %@", [exception callStackSymbols]);
}
}
}
@ -526,6 +616,7 @@ void callbackBlockFunction() {
if ([callbackData getType] == LogType) {
process_log([callbackData getSessionId], [callbackData getLogLevel], [callbackData getLogData]);
av_bprint_finalize([callbackData getLogData], NULL);
} else {
process_statistics([callbackData getSessionId],
[callbackData getStatisticsFrameNumber],
@ -662,7 +753,9 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
logCallback = nil;
statisticsCallback = nil;
executeCallback = nil;
ffmpegSessionCompleteCallback = nil;
ffprobeSessionCompleteCallback = nil;
mediaInformationSessionCompleteCallback = nil;
globalLogRedirectionStrategy = LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined;
@ -901,7 +994,7 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
int returnCodeValue = executeFFprobe([mediaInformationSession getSessionId], [mediaInformationSession getArguments]);
ReturnCode* returnCode = [[ReturnCode alloc] init:returnCodeValue];
[mediaInformationSession complete:returnCode];
if ([returnCode isSuccess]) {
if ([returnCode isValueSuccess]) {
MediaInformation* mediaInformation = [MediaInformationJsonParser from:[mediaInformationSession getAllLogsAsStringWithTimeout:waitTimeout]];
[mediaInformationSession setMediaInformation:mediaInformation];
}
@ -918,14 +1011,27 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
+ (void)asyncFFmpegExecute:(FFmpegSession*)ffmpegSession onDispatchQueue:(dispatch_queue_t)queue {
dispatch_async(queue, ^{
[FFmpegKitConfig ffmpegExecute:ffmpegSession];
ExecuteCallback globalExecuteCallback = [FFmpegKitConfig getExecuteCallback];
if (globalExecuteCallback != nil) {
globalExecuteCallback(ffmpegSession);
FFmpegSessionCompleteCallback completeCallback = [ffmpegSession getCompleteCallback];
if (completeCallback != nil) {
@try {
// NOTIFY SESSION CALLBACK DEFINED
completeCallback(ffmpegSession);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside session complete callback. %@", [exception callStackSymbols]);
}
}
ExecuteCallback sessionExecuteCallback = [ffmpegSession getExecuteCallback];
if (sessionExecuteCallback != nil) {
sessionExecuteCallback(ffmpegSession);
FFmpegSessionCompleteCallback globalFFmpegSessionCompleteCallback = [FFmpegKitConfig getFFmpegSessionCompleteCallback];
if (globalFFmpegSessionCompleteCallback != nil) {
@try {
// NOTIFY SESSION CALLBACK DEFINED
globalFFmpegSessionCompleteCallback(ffmpegSession);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside global complete callback. %@", [exception callStackSymbols]);
}
}
});
}
@ -937,14 +1043,27 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
+ (void)asyncFFprobeExecute:(FFprobeSession*)ffprobeSession onDispatchQueue:(dispatch_queue_t)queue {
dispatch_async(queue, ^{
[FFmpegKitConfig ffprobeExecute:ffprobeSession];
ExecuteCallback globalExecuteCallback = [FFmpegKitConfig getExecuteCallback];
if (globalExecuteCallback != nil) {
globalExecuteCallback(ffprobeSession);
FFprobeSessionCompleteCallback completeCallback = [ffprobeSession getCompleteCallback];
if (completeCallback != nil) {
@try {
// NOTIFY SESSION CALLBACK DEFINED
completeCallback(ffprobeSession);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside session complete callback. %@", [exception callStackSymbols]);
}
}
ExecuteCallback sessionExecuteCallback = [ffprobeSession getExecuteCallback];
if (sessionExecuteCallback != nil) {
sessionExecuteCallback(ffprobeSession);
FFprobeSessionCompleteCallback globalFFprobeSessionCompleteCallback = [FFmpegKitConfig getFFprobeSessionCompleteCallback];
if (globalFFprobeSessionCompleteCallback != nil) {
@try {
// NOTIFY SESSION CALLBACK DEFINED
globalFFprobeSessionCompleteCallback(ffprobeSession);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside global complete callback. %@", [exception callStackSymbols]);
}
}
});
}
@ -956,14 +1075,27 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
+ (void)asyncGetMediaInformationExecute:(MediaInformationSession*)mediaInformationSession onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
dispatch_async(queue, ^{
[FFmpegKitConfig getMediaInformationExecute:mediaInformationSession withTimeout:waitTimeout];
ExecuteCallback globalExecuteCallback = [FFmpegKitConfig getExecuteCallback];
if (globalExecuteCallback != nil) {
globalExecuteCallback(mediaInformationSession);
MediaInformationSessionCompleteCallback completeCallback = [mediaInformationSession getCompleteCallback];
if (completeCallback != nil) {
@try {
// NOTIFY SESSION CALLBACK DEFINED
completeCallback(mediaInformationSession);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside session complete callback. %@", [exception callStackSymbols]);
}
}
ExecuteCallback sessionExecuteCallback = [mediaInformationSession getExecuteCallback];
if (sessionExecuteCallback != nil) {
sessionExecuteCallback(mediaInformationSession);
MediaInformationSessionCompleteCallback globalMediaInformationSessionCompleteCallback = [FFmpegKitConfig getMediaInformationSessionCompleteCallback];
if (globalMediaInformationSessionCompleteCallback != nil) {
@try {
// NOTIFY SESSION CALLBACK DEFINED
globalMediaInformationSessionCompleteCallback(mediaInformationSession);
}
@catch(NSException* exception) {
NSLog(@"Exception thrown inside global complete callback. %@", [exception callStackSymbols]);
}
}
});
}
@ -976,12 +1108,28 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
statisticsCallback = callback;
}
+ (void)enableExecuteCallback:(ExecuteCallback)callback {
executeCallback = callback;
+ (void)enableFFmpegSessionCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback {
ffmpegSessionCompleteCallback = completeCallback;
}
+ (ExecuteCallback)getExecuteCallback {
return executeCallback;
+ (FFmpegSessionCompleteCallback)getFFmpegSessionCompleteCallback {
return ffmpegSessionCompleteCallback;
}
+ (void)enableFFprobeSessionCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback {
ffprobeSessionCompleteCallback = completeCallback;
}
+ (FFprobeSessionCompleteCallback)getFFprobeSessionCompleteCallback {
return ffprobeSessionCompleteCallback;
}
+ (void)enableMediaInformationSessionCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback {
mediaInformationSessionCompleteCallback = completeCallback;
}
+ (MediaInformationSessionCompleteCallback)getMediaInformationSessionCompleteCallback {
return mediaInformationSessionCompleteCallback;
}
+ (int)getLogLevel {
@ -1076,6 +1224,7 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
[sessionHistoryLock lock];
[sessionHistoryList removeAllObjects];
[sessionHistoryMap removeAllObjects];
[sessionHistoryLock unlock];
}
@ -1114,6 +1263,23 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
return ffprobeSessions;
}
+ (NSArray*)getMediaInformationSessions {
NSMutableArray* mediaInformationSessions = [[NSMutableArray alloc] init];
[sessionHistoryLock lock];
for(int i = 0; i < [sessionHistoryList count]; i++) {
id<Session> session = [sessionHistoryList objectAtIndex:i];
if ([session isMediaInformation]) {
[mediaInformationSessions addObject:session];
}
}
[sessionHistoryLock unlock];
return mediaInformationSessions;
}
+ (NSArray*)getSessionsByState:(SessionState)state {
NSMutableArray* sessions = [[NSMutableArray alloc] init];

@ -23,6 +23,7 @@
#import <Foundation/Foundation.h>
#import "AbstractSession.h"
#import "StatisticsCallback.h"
#import "FFmpegSessionCompleteCallback.h"
/**
* <p>An FFmpeg session.
@ -39,31 +40,31 @@
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param arguments command arguments
* @param completeCallback session specific complete callback
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback;
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback;
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback
* @param arguments command arguments
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback;
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback;
/**
* Builds a new FFmpeg session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback
* @param logRedirectionStrategy session specific log redirection strategy
* @param arguments command arguments
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback
* @param logRedirectionStrategy session specific log redirection strategy
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
/**
* Returns the session specific statistics callback.
@ -72,6 +73,13 @@
*/
- (StatisticsCallback)getStatisticsCallback;
/**
* Returns the session specific complete callback.
*
* @return session specific complete callback
*/
- (FFmpegSessionCompleteCallback)getCompleteCallback;
/**
* 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.
@ -108,7 +116,8 @@
- (Statistics*)getLastReceivedStatistics;
/**
* Adds a new statistics entry for this session.
* Adds a new statistics entry for this session. It is invoked internally by <code>FFmpegKit</code> library methods.
* Must not be used by user applications.
*
* @param statistics statistics entry
*/

@ -17,7 +17,6 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ExecuteCallback.h"
#import "FFmpegSession.h"
#import "FFmpegKitConfig.h"
#import "LogCallback.h"
@ -25,6 +24,7 @@
@implementation FFmpegSession {
StatisticsCallback _statisticsCallback;
FFmpegSessionCompleteCallback _completeCallback;
NSMutableArray* _statistics;
NSRecursiveLock* _statisticsLock;
}
@ -35,10 +35,11 @@
- (instancetype)init:(NSArray*)arguments {
self = [super init:arguments withExecuteCallback:nil withLogCallback:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
self = [super init:arguments withLogCallback:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_statisticsCallback = nil;
_completeCallback = nil;
_statistics = [[NSMutableArray alloc] init];
_statisticsLock = [[NSRecursiveLock alloc] init];
}
@ -46,12 +47,13 @@
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback {
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback {
self = [super init:arguments withExecuteCallback:executeCallback withLogCallback:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
self = [super init:arguments withLogCallback:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_statisticsCallback = nil;
_completeCallback = completeCallback;
_statistics = [[NSMutableArray alloc] init];
_statisticsLock = [[NSRecursiveLock alloc] init];
}
@ -59,12 +61,13 @@
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback {
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback {
self = [super init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
self = [super init:arguments withLogCallback:logCallback withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_statisticsCallback = statisticsCallback;
_completeCallback = completeCallback;
_statistics = [[NSMutableArray alloc] init];
_statisticsLock = [[NSRecursiveLock alloc] init];
}
@ -72,12 +75,13 @@
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withStatisticsCallback:(StatisticsCallback)statisticsCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
self = [super init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback withLogRedirectionStrategy:logRedirectionStrategy];
self = [super init:arguments withLogCallback:logCallback withLogRedirectionStrategy:logRedirectionStrategy];
if (self) {
_statisticsCallback = statisticsCallback;
_completeCallback = completeCallback;
_statistics = [[NSMutableArray alloc] init];
_statisticsLock = [[NSRecursiveLock alloc] init];
}
@ -89,6 +93,10 @@
return _statisticsCallback;
}
- (FFmpegSessionCompleteCallback)getCompleteCallback {
return _completeCallback;
}
- (NSArray*)getAllStatisticsWithTimeout:(int)waitTimeout {
[self waitForAsynchronousMessagesInTransmit:waitTimeout];
@ -137,5 +145,9 @@
return false;
}
- (BOOL)isMediaInformation {
return false;
}
@end

@ -17,13 +17,13 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FFMPEG_KIT_EXECUTE_CALLBACK_H
#define FFMPEG_KIT_EXECUTE_CALLBACK_H
#ifndef FFMPEG_KIT_FFMPEG_SESSION_COMPLETE_CALLBACK_H
#define FFMPEG_KIT_FFMPEG_SESSION_COMPLETE_CALLBACK_H
@protocol Session;
@class FFmpegSession;
/**
* <p>Callback invoked when an asynchronous session ends running.
* <p>Callback function that is invoked when an asynchronous <code>FFmpeg</code> session has ended.
* <p>Session has either SessionStateCompleted or SessionStateFailed state when
* the callback is invoked.
* <p>If it has SessionStateCompleted state, <code>ReturnCode</code> should be checked to
@ -43,8 +43,8 @@
*
* @param session session of the completed execution
*/
typedef void (^ExecuteCallback)(id<Session> session);
typedef void (^FFmpegSessionCompleteCallback)(FFmpegSession* session);
#import "Session.h"
#import "FFmpegSession.h"
#endif // FFMPEG_KIT_EXECUTE_CALLBACK_H
#endif // FFMPEG_KIT_FFMPEG_SESSION_COMPLETE_CALLBACK_H

@ -32,11 +32,11 @@
* <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" withExecuteCallback:executeCallback];
* FFprobeSession *asyncSession = [FFprobeKit executeAsync:@"-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4" withCompleteCallback:completeCallback];
* </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" withExecuteCallback:executeCallback withLogCallback:logCallback];
* FFprobeSession *session = [FFprobeKit executeAsync:@"-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4" withCompleteCallback:completeCallback withLogCallback:logCallback];
* </pre>
* <p>It can extract media information for a file or a url, using getMediaInformation method.
* <pre>
@ -56,54 +56,54 @@
/**
* <p>Starts an asynchronous FFprobe execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param arguments FFprobe command options/arguments as string array
* @param completeCallback callback that will be called when the execution has completed
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback;
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback;
/**
* <p>Starts an asynchronous FFprobe execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @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 arguments FFprobe command options/arguments as string array
* @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback;
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback;
/**
* <p>Starts an asynchronous FFprobe execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @param arguments FFprobe command options/arguments as string array
* @param completeCallback callback that will be called when the execution has 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 withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Starts an asynchronous FFprobe execution with arguments provided.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* <p>Note that this method returns immediately and does not wait the execution to complete.
* You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @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 queue dispatch queue that will be used to run this asynchronous operation
* @param arguments FFprobe command options/arguments as string array
* @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Synchronously executes FFprobe command provided. Space character is used to split command
@ -120,56 +120,56 @@
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFprobe command
* @param executeCallback callback that will be called when the execution is completed
* @param command FFprobe command
* @param completeCallback callback that will be called when the execution has completed
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback;
+ (FFprobeSession*)executeAsync:(NSString*)command withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback;
/**
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFprobe command
* @param executeCallback callback that will be notified when execution is completed
* @param logCallback callback that will receive logs
* @param command FFprobe command
* @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback;
+ (FFprobeSession*)executeAsync:(NSString*)command withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback;
/**
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFprobe command
* @param executeCallback callback that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @param command FFprobe command
* @param completeCallback callback that will be called when the execution has 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 withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (FFprobeSession*)executeAsync:(NSString*)command withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command
* into arguments. You can use single or double quote characters to specify arguments inside your command.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* FFprobeSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFprobe command
* @param executeCallback callback that will be called when the execution is completed
* @param logCallback callback that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation
* @param command FFprobe command
* @param completeCallback callback that will be called when the execution has completed
* @param logCallback callback that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution
*/
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (FFprobeSession*)executeAsync:(NSString*)command withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Extracts media information for the file specified with path.
@ -192,55 +192,55 @@
* <p>Starts an asynchronous FFprobe execution to extract the media information for the specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* MediaInformationSessionCompleteCallback if you want to be notified about the result.
*
* @param path path or uri of a media file
* @param executeCallback callback that will be called when the execution is completed
* @param path path or uri of a media file
* @param completeCallback callback that will be called when the execution has completed
* @return media information session created for this execution
*/
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteCallback:(ExecuteCallback)executeCallback;
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback;
/**
* <p>Starts an asynchronous FFprobe execution to extract the media information for the specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* MediaInformationSessionCompleteCallback if you want to be notified about the result.
*
* @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
* @param path path or uri of a media file
* @param completeCallback callback that will be notified when execution has 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
*/
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withTimeout:(int)waitTimeout;
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withTimeout:(int)waitTimeout;
/**
* <p>Starts an asynchronous FFprobe execution to extract the media information for the specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* MediaInformationSessionCompleteCallback if you want to be notified about the result.
*
* @param path path or uri of a media file
* @param executeCallback callback that will be called when the execution is completed
* @param queue dispatch queue that will be used to run this asynchronous operation
* @param path path or uri of a media file
* @param completeCallback callback that will be called when the execution has 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 withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue;
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue;
/**
* <p>Starts an asynchronous FFprobe execution to extract the media information for the specified file.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* MediaInformationSessionCompleteCallback if you want to be notified about the result.
*
* @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 queue dispatch queue 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 completeCallback callback that will be notified when execution has completed
* @param logCallback callback 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 withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout;
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout;
/**
* <p>Extracts media information using the command provided asynchronously.
@ -255,23 +255,47 @@
* this method must generate the output in JSON format in order to successfully extract media information from it.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* ExecuteCallback if you want to be notified about the result.
* MediaInformationSessionCompleteCallback if you want to be notified about the result.
*
* @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 queue dispatch queue that will be used to run this asynchronous operation
* @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 completeCallback callback that will be notified when execution has completed
* @param logCallback callback 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*)getMediaInformationFromCommandAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout;
+ (MediaInformationSession*)getMediaInformationFromCommandAsync:(NSString*)command withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout;
/**
* <p>Starts an asynchronous FFprobe execution to extract media information using command arguments. The command
* passed to this method must generate the output in JSON format in order to successfully extract media information
* from it.
*
* <p>Note that this method returns immediately and does not wait the execution to complete. You must use an
* MediaInformationSessionCompleteCallback if you want to be notified about the result.
*
* @param command FFprobe command that prints media information for a file in JSON format
* @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback 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*)getMediaInformationFromCommandArgumentsAsync:(NSArray*)arguments withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback 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;
+ (NSArray*)listFFprobeSessions;
/**
* <p>Lists all MediaInformation sessions in the session history.
*
* @return all MediaInformation sessions in the session history
*/
+ (NSArray*)listMediaInformationSessions;
@end

@ -28,32 +28,36 @@
[FFmpegKitConfig class];
}
+ (NSArray*)defaultGetMediaInformationCommandArguments:(NSString*)path {
return [[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-show_chapters", @"-i", path, nil];
}
+ (FFprobeSession*)executeWithArguments:(NSArray*)arguments {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments];
[FFmpegKitConfig ffprobeExecute:session];
return session;
}
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteCallback:executeCallback];
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncFFprobeExecute:session];
return session;
}
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback];
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:completeCallback withLogCallback:logCallback];
[FFmpegKitConfig asyncFFprobeExecute:session];
return session;
}
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteCallback:executeCallback];
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
return session;
}
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback];
+ (FFprobeSession*)executeWithArgumentsAsync:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:arguments withCompleteCallback:completeCallback withLogCallback:logCallback];
[FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
return session;
}
@ -64,68 +68,68 @@
return session;
}
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:command] withExecuteCallback:executeCallback];
+ (FFprobeSession*)executeAsync:(NSString*)command withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncFFprobeExecute:session];
return session;
}
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:command] withExecuteCallback:executeCallback withLogCallback:logCallback];
+ (FFprobeSession*)executeAsync:(NSString*)command withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback withLogCallback:logCallback];
[FFmpegKitConfig asyncFFprobeExecute:session];
return session;
}
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:command] withExecuteCallback:executeCallback];
+ (FFprobeSession*)executeAsync:(NSString*)command withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
return session;
}
+ (FFprobeSession*)executeAsync:(NSString*)command withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:command] withExecuteCallback:executeCallback withLogCallback:logCallback];
+ (FFprobeSession*)executeAsync:(NSString*)command withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue {
FFprobeSession* session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback withLogCallback:logCallback];
[FFmpegKitConfig asyncFFprobeExecute:session onDispatchQueue:queue];
return session;
}
+ (MediaInformationSession*)getMediaInformation:(NSString*)path {
NSArray* arguments = [[NSArray alloc] initWithObjects:@"-v", @"error", @"-hide_banner", @"-print_format", @"json", @"-show_format", @"-show_streams", @"-i", path, nil];
NSArray* arguments = [FFprobeKit defaultGetMediaInformationCommandArguments:path];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments];
[FFmpegKitConfig getMediaInformationExecute:session withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
return session;
}
+ (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];
NSArray* arguments = [FFprobeKit defaultGetMediaInformationCommandArguments:path];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments];
[FFmpegKitConfig getMediaInformationExecute:session withTimeout:waitTimeout];
return session;
}
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteCallback:(ExecuteCallback)executeCallback {
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 withExecuteCallback:executeCallback];
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback {
NSArray* arguments = [FFprobeKit defaultGetMediaInformationCommandArguments:path];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncGetMediaInformationExecute:session withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
return session;
}
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback 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 withExecuteCallback:executeCallback withLogCallback:logCallback];
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withTimeout:(int)waitTimeout {
NSArray* arguments = [FFprobeKit defaultGetMediaInformationCommandArguments:path];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:completeCallback withLogCallback:logCallback];
[FFmpegKitConfig asyncGetMediaInformationExecute:session withTimeout:waitTimeout];
return session;
}
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteCallback:(ExecuteCallback)executeCallback 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 withExecuteCallback:executeCallback];
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback onDispatchQueue:(dispatch_queue_t)queue {
NSArray* arguments = [FFprobeKit defaultGetMediaInformationCommandArguments:path];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncGetMediaInformationExecute:session onDispatchQueue:queue withTimeout:AbstractSessionDefaultTimeoutForAsynchronousMessagesInTransmit];
return session;
}
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback 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 withExecuteCallback:executeCallback];
+ (MediaInformationSession*)getMediaInformationAsync:(NSString*)path withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
NSArray* arguments = [FFprobeKit defaultGetMediaInformationCommandArguments:path];
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:completeCallback];
[FFmpegKitConfig asyncGetMediaInformationExecute:session onDispatchQueue:queue withTimeout:waitTimeout];
return session;
}
@ -136,14 +140,24 @@
return session;
}
+ (MediaInformationSession*)getMediaInformationFromCommandAsync:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback];
+ (MediaInformationSession*)getMediaInformationFromCommandAsync:(NSString*)command withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
MediaInformationSession* session = [[MediaInformationSession alloc] init:[FFmpegKitConfig parseArguments:command] withCompleteCallback:completeCallback withLogCallback:logCallback];
[FFmpegKitConfig asyncGetMediaInformationExecute:session onDispatchQueue:queue withTimeout:waitTimeout];
return session;
}
+ (MediaInformationSession*)getMediaInformationFromCommandArgumentsAsync:(NSArray*)arguments withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
MediaInformationSession* session = [[MediaInformationSession alloc] init:arguments withCompleteCallback:completeCallback withLogCallback:logCallback];
[FFmpegKitConfig asyncGetMediaInformationExecute:session onDispatchQueue:queue withTimeout:waitTimeout];
return session;
}
+ (NSArray*)listSessions {
+ (NSArray*)listFFprobeSessions {
return [FFmpegKitConfig getFFprobeSessions];
}
+ (NSArray*)listMediaInformationSessions {
return [FFmpegKitConfig getMediaInformationSessions];
}
@end

@ -22,6 +22,7 @@
#import <Foundation/Foundation.h>
#import "AbstractSession.h"
#import "FFprobeSessionCompleteCallback.h"
/**
* <p>An FFprobe session.
@ -38,29 +39,36 @@
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param arguments command arguments
* @param completeCallback session specific complete callback
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback;
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback;
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param logCallback session specific log callback
* @param arguments command arguments
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback;
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback;
/**
* Builds a new FFprobe session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param logCallback session specific log callback
* @param logRedirectionStrategy session specific log redirection strategy
* @param arguments command arguments
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
* @param logRedirectionStrategy session specific log redirection strategy
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy;
/**
* Returns the session specific complete callback.
*
* @return session specific complete callback
*/
- (FFprobeSessionCompleteCallback)getCompleteCallback;
@end

@ -17,45 +17,66 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ExecuteCallback.h"
#import "FFprobeSession.h"
#import "FFmpegKitConfig.h"
#import "LogCallback.h"
@implementation FFprobeSession
@implementation FFprobeSession {
FFprobeSessionCompleteCallback _completeCallback;
}
+ (void)initialize {
// EMPTY INITIALIZE
}
- (instancetype)init:(NSArray*)arguments {
self = [super init:arguments withExecuteCallback:nil withLogCallback:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
self = [super init:arguments withLogCallback:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_completeCallback = nil;
}
return self;
}
+ (void)initialize {
// EMPTY INITIALIZE
}
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback {
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback {
self = [super init:arguments withLogCallback:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
self = [super init:arguments withExecuteCallback:executeCallback withLogCallback:nil withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_completeCallback = completeCallback;
}
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback {
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback {
self = [super init:arguments withLogCallback:logCallback withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
self = [super init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback withLogRedirectionStrategy:[FFmpegKitConfig getLogRedirectionStrategy]];
if (self) {
_completeCallback = completeCallback;
}
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback withLogRedirectionStrategy:(LogRedirectionStrategy)logRedirectionStrategy {
self = [super init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback withLogRedirectionStrategy:logRedirectionStrategy];
self = [super init:arguments withLogCallback:logCallback withLogRedirectionStrategy:logRedirectionStrategy];
if (self) {
_completeCallback = completeCallback;
}
return self;
}
- (FFprobeSessionCompleteCallback)getCompleteCallback {
return _completeCallback;
}
- (BOOL)isFFmpeg {
return false;
}
@ -64,5 +85,9 @@
return true;
}
- (BOOL)isMediaInformation {
return false;
}
@end

@ -0,0 +1,50 @@
/*
* 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/>.
*/
#ifndef FFMPEG_KIT_FFPROBE_SESSION_COMPLETE_CALLBACK_H
#define FFMPEG_KIT_FFPROBE_SESSION_COMPLETE_CALLBACK_H
@class FFprobeSession;
/**
* <p>Callback function that is invoked when an asynchronous <code>FFprobe</code> session has ended.
* <p>Session has either SessionStateCompleted or SessionStateFailed state when
* the callback 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>
*
* @param session session of the completed execution
*/
typedef void (^FFprobeSessionCompleteCallback)(FFprobeSession* session);
#import "FFprobeSession.h"
#endif // FFMPEG_KIT_FFPROBE_SESSION_COMPLETE_CALLBACK_H

@ -1,11 +1,12 @@
lib_LTLIBRARIES = libffmpegkit.la
libffmpegkit_la_LIBADD = @FFMPEG_LIBS@
libffmpegkit_la_LIBADD = @FFMPEG_FRAMEWORKS@
libffmpegkit_la_SOURCES = \
AbstractSession.m \
ArchDetect.m \
AtomicLong.m \
Chapter.m \
FFmpegKit.m \
FFmpegKitConfig.m \
FFmpegSession.m \
@ -35,28 +36,31 @@ include_HEADERS = \
AbstractSession.h \
ArchDetect.h \
AtomicLong.h \
ExecuteCallback.h \
Chapter.h \
FFmpegKit.h \
FFmpegKitConfig.h \
FFmpegSession.h \
FFprobeKit.h \
FFprobeSession.h \
Level.h \
Log.h \
LogCallback.h \
LogRedirectionStrategy.h \
MediaInformation.h \
MediaInformationJsonParser.h \
MediaInformationSession.h \
Packages.h \
ReturnCode.h \
Session.h \
SessionState.h \
Statistics.h \
StatisticsCallback.h \
StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
FFmpegSessionCompleteCallback.h \
FFprobeKit.h \
FFprobeSession.h \
FFprobeSessionCompleteCallback.h \
Level.h \
Log.h \
LogCallback.h \
LogRedirectionStrategy.h \
MediaInformation.h \
MediaInformationJsonParser.h \
MediaInformationSession.h \
MediaInformationSessionCompleteCallback.h \
Packages.h \
ReturnCode.h \
Session.h \
SessionState.h \
Statistics.h \
StatisticsCallback.h \
StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
fftools_ffmpeg.h
libffmpegkit_la_CFLAGS = $(CFLAGS)

@ -1,7 +1,7 @@
# Makefile.in generated by automake 1.16.3 from Makefile.am.
# Makefile.in generated by automake 1.16.5 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
# Copyright (C) 1994-2021 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@ -134,18 +134,18 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
libffmpegkit_la_DEPENDENCIES =
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 \
AtomicLong.m Chapter.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-AbstractSession.lo \
libffmpegkit_la-ArchDetect.lo libffmpegkit_la-AtomicLong.lo \
libffmpegkit_la-FFmpegKit.lo \
libffmpegkit_la-Chapter.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 \
@ -189,6 +189,7 @@ am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo \
./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo \
./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo \
./$(DEPDIR)/libffmpegkit_la-Chapter.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo \
@ -272,8 +273,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
@ -287,8 +286,9 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@ -299,8 +299,9 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
FFMPEG_LIBS = @FFMPEG_LIBS@
FFMPEG_FRAMEWORKS = @FFMPEG_FRAMEWORKS@
FGREP = @FGREP@
GREP = @GREP@
INSTALL = @INSTALL@
@ -389,6 +390,7 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@ -398,10 +400,10 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
lib_LTLIBRARIES = libffmpegkit.la
libffmpegkit_la_LIBADD = @FFMPEG_LIBS@
libffmpegkit_la_LIBADD = @FFMPEG_FRAMEWORKS@
libffmpegkit_la_SOURCES = AbstractSession.m ArchDetect.m AtomicLong.m \
FFmpegKit.m FFmpegKitConfig.m FFmpegSession.m FFprobeKit.m \
FFprobeSession.m Log.m MediaInformation.m \
Chapter.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 \
@ -411,28 +413,31 @@ include_HEADERS = \
AbstractSession.h \
ArchDetect.h \
AtomicLong.h \
ExecuteCallback.h \
Chapter.h \
FFmpegKit.h \
FFmpegKitConfig.h \
FFmpegSession.h \
FFprobeKit.h \
FFprobeSession.h \
Level.h \
Log.h \
LogCallback.h \
LogRedirectionStrategy.h \
MediaInformation.h \
MediaInformationJsonParser.h \
MediaInformationSession.h \
Packages.h \
ReturnCode.h \
Session.h \
SessionState.h \
Statistics.h \
StatisticsCallback.h \
StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
FFmpegSessionCompleteCallback.h \
FFprobeKit.h \
FFprobeSession.h \
FFprobeSessionCompleteCallback.h \
Level.h \
Log.h \
LogCallback.h \
LogRedirectionStrategy.h \
MediaInformation.h \
MediaInformationJsonParser.h \
MediaInformationSession.h \
MediaInformationSessionCompleteCallback.h \
Packages.h \
ReturnCode.h \
Session.h \
SessionState.h \
Statistics.h \
StatisticsCallback.h \
StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
fftools_ffmpeg.h
libffmpegkit_la_CFLAGS = $(CFLAGS)
@ -520,6 +525,7 @@ distclean-compile:
@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-Chapter.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
@ -666,6 +672,13 @@ 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-Chapter.lo: Chapter.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-Chapter.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-Chapter.Tpo -c -o libffmpegkit_la-Chapter.lo `test -f 'Chapter.m' || echo '$(srcdir)/'`Chapter.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-Chapter.Tpo $(DEPDIR)/libffmpegkit_la-Chapter.Plo
@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='Chapter.m' object='libffmpegkit_la-Chapter.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-Chapter.lo `test -f 'Chapter.m' || echo '$(srcdir)/'`Chapter.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
@ -842,7 +855,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
@ -922,6 +934,7 @@ distclean: distclean-am
-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-Chapter.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo
@ -991,6 +1004,7 @@ maintainer-clean: maintainer-clean-am
-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-Chapter.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo

@ -21,6 +21,7 @@
#define FFMPEG_KIT_MEDIA_INFORMATION_H
#import <Foundation/Foundation.h>
#import "Chapter.h"
#import "StreamInformation.h"
extern NSString* const MediaKeyMediaProperties;
@ -38,7 +39,7 @@ extern NSString* const MediaKeyTags;
*/
@interface MediaInformation : NSObject
- (instancetype)init:(NSDictionary*)mediaDictionary withStreams:(NSArray*)streams;
- (instancetype)init:(NSDictionary*)mediaDictionary withStreams:(NSArray*)streams withChapters:(NSArray*)chapters;
/**
* Returns file name.
@ -103,6 +104,13 @@ extern NSString* const MediaKeyTags;
*/
- (NSArray*)getStreams;
/**
* Returns all chapters.
*
* @return chapters array
*/
- (NSArray*)getChapters;
/**
* Returns the media property associated with the key.
*

@ -41,13 +41,19 @@ NSString* const MediaKeyTags = @"tags";
*/
NSArray *streamArray;
/**
* Stores chapters.
*/
NSArray *chapterArray;
}
- (instancetype)init:(NSDictionary*)mediaDictionary withStreams:(NSArray*)streams{
- (instancetype)init:(NSDictionary*)mediaDictionary withStreams:(NSArray*)streams withChapters:(NSArray*)chapters{
self = [super init];
if (self) {
dictionary = mediaDictionary;
streamArray = streams;
chapterArray = chapters;
}
return self;
@ -89,6 +95,10 @@ NSString* const MediaKeyTags = @"tags";
return streamArray;
}
- (NSArray*)getChapters {
return chapterArray;
}
- (NSString*)getStringProperty:(NSString*)key {
NSDictionary* mediaProperties = [self getMediaProperties];
if (mediaProperties == nil) {

@ -19,6 +19,9 @@
#import "MediaInformationJsonParser.h"
NSString* const MediaInformationJsonParserKeyStreams = @"streams";
NSString* const MediaInformationJsonParserKeyChapters = @"chapters";
@implementation MediaInformationJsonParser
+ (MediaInformation*)from:(NSString*)ffprobeJsonOutput {
@ -40,14 +43,21 @@
return nil;
}
NSArray* array = [jsonDictionary objectForKey:@"streams"];
NSArray* jsonStreamArray = [jsonDictionary objectForKey:MediaInformationJsonParserKeyStreams];
NSMutableArray *streamArray = [[NSMutableArray alloc] init];
for(int i = 0; i<array.count; i++) {
NSDictionary *streamDictionary = [array objectAtIndex:i];
[streamArray addObject:[[StreamInformation alloc] init: streamDictionary]];
for(int i = 0; i<jsonStreamArray.count; i++) {
NSDictionary *streamDictionary = [jsonStreamArray objectAtIndex:i];
[streamArray addObject:[[StreamInformation alloc] init:streamDictionary]];
}
NSArray* jsonChapterArray = [jsonDictionary objectForKey:MediaInformationJsonParserKeyChapters];
NSMutableArray *chapterArray = [[NSMutableArray alloc] init];
for(int i = 0; i<jsonChapterArray.count; i++) {
NSDictionary *chapterDictionary = [jsonChapterArray objectAtIndex:i];
[chapterArray addObject:[[Chapter alloc] init:chapterDictionary]];
}
return [[MediaInformation alloc] init:jsonDictionary withStreams:streamArray];
return [[MediaInformation alloc] init:jsonDictionary withStreams:streamArray withChapters:chapterArray];
}
@end

@ -21,14 +21,15 @@
#define FFMPEG_KIT_MEDIA_INFORMATION_SESSION_H
#import <Foundation/Foundation.h>
#import "FFprobeSession.h"
#import "AbstractSession.h"
#import "MediaInformation.h"
#import "MediaInformationSessionCompleteCallback.h"
/**
* <p>A custom FFprobe session, which produces a <code>MediaInformation</code> object using the
* FFprobe output.
*/
@interface MediaInformationSession : FFprobeSession
@interface MediaInformationSession : AbstractSession
/**
* Creates a new media information session.
@ -40,19 +41,19 @@
/**
* Creates a new media information session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param arguments command arguments
* @param completeCallback session specific complete callback
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback;
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback;
/**
* Creates a new media information session.
*
* @param arguments command arguments
* @param executeCallback session specific execute callback
* @param logCallback session specific log callback
* @param arguments command arguments
* @param completeCallback session specific complete callback
* @param logCallback session specific log callback
*/
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback;
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback;
/**
* Returns the media information extracted in this session.
@ -69,6 +70,13 @@
*/
- (void)setMediaInformation:(MediaInformation*)mediaInformation;
/**
* Returns the session specific complete callback.
*
* @return session specific complete callback
*/
- (MediaInformationSessionCompleteCallback)getCompleteCallback;
@end
#endif // FFMPEG_KIT_MEDIA_INFORMATION_SESSION_H

@ -17,13 +17,13 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/
#import "ExecuteCallback.h"
#import "MediaInformationSession.h"
#import "LogCallback.h"
#import "MediaInformation.h"
#import "MediaInformationSession.h"
@implementation MediaInformationSession {
MediaInformation* _mediaInformation;
MediaInformationSessionCompleteCallback _completeCallback;
}
+ (void)initialize {
@ -32,21 +32,33 @@
- (instancetype)init:(NSArray*)arguments {
self = [super init:arguments withExecuteCallback:nil withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
self = [super init:arguments withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
if (self) {
_completeCallback = nil;
}
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback {
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback {
self = [super init:arguments withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
self = [super init:arguments withExecuteCallback:executeCallback withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
if (self) {
_completeCallback = completeCallback;
}
return self;
}
- (instancetype)init:(NSArray*)arguments withExecuteCallback:(ExecuteCallback)executeCallback withLogCallback:(LogCallback)logCallback {
- (instancetype)init:(NSArray*)arguments withCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback withLogCallback:(LogCallback)logCallback {
self = [super init:arguments withExecuteCallback:executeCallback withLogCallback:logCallback withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
self = [super init:arguments withLogCallback:logCallback withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs];
if (self) {
_completeCallback = completeCallback;
}
return self;
}
@ -59,5 +71,21 @@
_mediaInformation = mediaInformation;
}
- (MediaInformationSessionCompleteCallback)getCompleteCallback {
return _completeCallback;
}
- (BOOL)isFFmpeg {
return false;
}
- (BOOL)isFFprobe {
return false;
}
- (BOOL)isMediaInformation {
return true;
}
@end

@ -0,0 +1,51 @@
/*
* 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/>.
*/
#ifndef FFMPEG_KIT_MEDIA_INFORMATION_SESSION_COMPLETE_CALLBACK_H
#define FFMPEG_KIT_MEDIA_INFORMATION_SESSION_COMPLETE_CALLBACK_H
@class MediaInformationSession;
/**
* <p>Callback function that is invoked when an asynchronous <code>MediaInformation</code> session
* has ended.
* <p>Session has either SessionStateCompleted or SessionStateFailed state when
* the callback 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>
*
* @param session session of the completed execution
*/
typedef void (^MediaInformationSessionCompleteCallback)(MediaInformationSession* session);
#import "MediaInformationSession.h"
#endif // FFMPEG_KIT_MEDIA_INFORMATION_SESSION_COMPLETE_CALLBACK_H

@ -37,11 +37,11 @@ typedef NS_ENUM(NSUInteger, ReturnCodeEnum) {
- (int)getValue;
- (BOOL)isSuccess;
- (BOOL)isValueSuccess;
- (BOOL)isError;
- (BOOL)isValueError;
- (BOOL)isCancel;
- (BOOL)isValueCancel;
@end

@ -44,15 +44,15 @@
return _value;
}
- (BOOL)isSuccess {
- (BOOL)isValueSuccess {
return (_value == ReturnCodeSuccess);
}
- (BOOL)isError {
- (BOOL)isValueError {
return ((_value != ReturnCodeSuccess) && (_value != ReturnCodeCancel));
}
- (BOOL)isCancel {
- (BOOL)isValueCancel {
return (_value == ReturnCodeCancel);
}

@ -21,7 +21,6 @@
#define FFMPEG_KIT_SESSION_H
#import <Foundation/Foundation.h>
#import "ExecuteCallback.h"
#import "Log.h"
#import "LogCallback.h"
#import "LogRedirectionStrategy.h"
@ -35,13 +34,6 @@
@required
/**
* Returns the session specific execute callback.
*
* @return session specific execute callback
*/
- (ExecuteCallback)getExecuteCallback;
/**
* Returns the session specific log callback.
*
@ -171,7 +163,7 @@
* 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
* @return the return code for this session if the session has completed, nil if session is
* not started, still running or failed
*/
- (ReturnCode*)getReturnCode;
@ -206,6 +198,9 @@
/**
* Adds a new log entry for this session.
*
* It is invoked internally by <code>FFmpegKit</code> library methods. Must not be used by user
* applications.
*
* @param log log entry
*/
- (void)addLog:(Log*)log;
@ -243,6 +238,13 @@
*/
- (BOOL)isFFprobe;
/**
* Returns whether it is a <code>MediaInformation</code> session or not.
*
* @return true if it is a <code>MediaInformation</code> session, false otherwise
*/
- (BOOL)isMediaInformation;
/**
* Cancels running the session.
*/

@ -16,10 +16,10 @@ export BASEDIR="$(pwd)"
export FFMPEG_KIT_BUILD_TYPE="ios"
source "${BASEDIR}"/scripts/variable.sh
source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh
disabled_libraries=()
# SET DEFAULTS SETTINGS
enable_default_ios_architectures
enable_main_build
# SELECT XCODE VERSION USED FOR BUILDING
XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh 2>>"${BASEDIR}"/build.log)
@ -28,7 +28,7 @@ if [[ -f ${XCODE_FOR_FFMPEG_KIT} ]]; then
fi
# DETECT IOS SDK VERSION
DETECTED_IOS_SDK_VERSION="$(xcrun --sdk iphoneos --show-sdk-version 2>>${BASEDIR}/build.log)"
export DETECTED_IOS_SDK_VERSION="$(xcrun --sdk iphoneos --show-sdk-version 2>>${BASEDIR}/build.log)"
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
@ -45,6 +45,9 @@ if [[ -z ${BUILD_VERSION} ]]; then
exit 1
fi
# MAIN BUILDS ENABLED BY DEFAULT
enable_main_build
# PROCESS LTS BUILD OPTION FIRST AND SET BUILD TYPE: MAIN OR LTS
for argument in "$@"; do
if [[ "$argument" == "-l" ]] || [[ "$argument" == "--lts" ]]; then
@ -113,11 +116,24 @@ while [ ! $# -eq 0 ]; do
--enable-gpl)
GPL_ENABLED="yes"
;;
--enable-custom-library-*)
CUSTOM_LIBRARY_OPTION_KEY=$(echo $1 | sed -e 's/^--enable-custom-//g;s/=.*$//g')
CUSTOM_LIBRARY_OPTION_VALUE=$(echo $1 | sed -e 's/^--enable-custom-.*=//g')
echo -e "INFO: Custom library options detected: ${CUSTOM_LIBRARY_OPTION_KEY} ${CUSTOM_LIBRARY_OPTION_VALUE}\n" 1>>"${BASEDIR}"/build.log 2>&1
generate_custom_library_environment_variables "${CUSTOM_LIBRARY_OPTION_KEY}" "${CUSTOM_LIBRARY_OPTION_VALUE}"
;;
--enable-*)
ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
enable_library "${ENABLED_LIBRARY}"
;;
--disable-lib-*)
DISABLED_LIB=$(echo $1 | sed -e 's/^--[A-Za-z]*-[A-Za-z]*-//g')
disabled_libraries+=("${DISABLED_LIB}")
;;
--disable-*)
DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
@ -142,7 +158,7 @@ done
# PROCESS FULL OPTION AS LAST OPTION
if [[ -n ${BUILD_FULL} ]]; then
for library in {0..58}; do
for library in {0..61}; do
if [ ${GPL_ENABLED} == "yes" ]; then
enable_library "$(get_library_name "$library")" 1
else
@ -153,6 +169,11 @@ if [[ -n ${BUILD_FULL} ]]; then
done
fi
# DISABLE SPECIFIED LIBRARIES
for disabled_library in ${disabled_libraries[@]}; do
set_library "${disabled_library}" 0
done
# IF HELP DISPLAYED EXIT
if [[ -n ${DISPLAY_HELP} ]]; then
display_help
@ -160,41 +181,35 @@ if [[ -n ${DISPLAY_HELP} ]]; then
fi
# DISABLE NOT SUPPORTED ARCHITECTURES
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARMV7}" "${DETECTED_IOS_SDK_VERSION}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARMV7S}" "${DETECTED_IOS_SDK_VERSION}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_I386}" "${DETECTED_IOS_SDK_VERSION}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARM64E}" "${DETECTED_IOS_SDK_VERSION}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_X86_64_MAC_CATALYST}" "${DETECTED_IOS_SDK_VERSION}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARM64_MAC_CATALYST}" "${DETECTED_IOS_SDK_VERSION}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARM64_SIMULATOR}" "${DETECTED_IOS_SDK_VERSION}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARMV7}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARMV7S}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_I386}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARM64E}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_X86_64_MAC_CATALYST}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARM64_MAC_CATALYST}"
disable_ios_architecture_not_supported_on_detected_sdk_version "${ARCH_ARM64_SIMULATOR}"
# CHECK SOME RULES FOR .framework BUNDLES
# 1. DISABLE arm64-mac-catalyst WHEN arm64 IS ENABLED IN framework BUNDLES
if [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64}]} -eq 1 ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64_MAC_CATALYST}]} -eq 1 ]]; then
echo -e "INFO: Disabled arm64-mac-catalyst architecture which can not co-exist with arm64 in the same framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1
# 1. DISABLE arm64-mac-catalyst IN framework BUNDLES
if [[ ${NO_FRAMEWORK} -ne 1 ]] && [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64_MAC_CATALYST}]} -eq 1 ]]; then
echo -e "INFO: Disabled arm64-mac-catalyst architecture which cannot exist in a framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1
disable_arch "arm64-mac-catalyst"
fi
# 2. DISABLE arm64-simulator WHEN arm64 IS ENABLED IN framework BUNDLES
if [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64}]} -eq 1 ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64_SIMULATOR}]} -eq 1 ]]; then
echo -e "INFO: Disabled arm64-simulator architecture which can not co-exist with arm64 in the same framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1
disable_arch "arm64-simulator"
# 2. DISABLE x86-64-mac-catalyst IN framework BUNDLES
if [[ ${NO_FRAMEWORK} -ne 1 ]] && [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_X86_64_MAC_CATALYST}]} -eq 1 ]]; then
echo -e "INFO: Disabled x86-64-mac-catalyst architecture which cannot exist in a framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1
disable_arch "x86-64-mac-catalyst"
fi
# 3. DISABLE arm64-simulator WHEN arm64-mac-catalyst IS ENABLED IN framework BUNDLES
if [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64_MAC_CATALYST}]} -eq 1 ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64_SIMULATOR}]} -eq 1 ]]; then
echo -e "INFO: Disabled arm64-simulator architecture which can not co-exist with arm64-mac-catalyst in the same framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1
# 3. DISABLE arm64-simulator WHEN arm64 IS ENABLED IN framework BUNDLES
if [[ ${NO_FRAMEWORK} -ne 1 ]] && [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64}]} -eq 1 ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64_SIMULATOR}]} -eq 1 ]]; then
echo -e "INFO: Disabled arm64-simulator architecture which cannot co-exist with arm64 in the same framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1
disable_arch "arm64-simulator"
fi
# 4. DISABLE x86-64-mac-catalyst WHEN x86-64 IS ENABLED IN framework BUNDLES
if [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_X86_64}]} -eq 1 ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_X86_64_MAC_CATALYST}]} -eq 1 ]]; then
echo -e "INFO: Disabled x86-64-mac-catalyst architecture which can not co-exist with x86-64 in the same framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1
disable_arch "x86-64-mac-catalyst"
fi
echo -e "\nBuilding ffmpeg-kit ${BUILD_TYPE_ID}static library for iOS\n"
echo -e "\nBuilding ffmpeg-kit ${BUILD_TYPE_ID}shared library for iOS\n"
echo -e -n "INFO: Building ffmpeg-kit ${BUILD_VERSION} ${BUILD_TYPE_ID}for iOS: " 1>>"${BASEDIR}"/build.log 2>&1
echo -e "$(date)\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -204,6 +219,7 @@ print_enabled_libraries
print_reconfigure_requested_libraries
print_rebuild_requested_libraries
print_redownload_requested_libraries
print_custom_libraries
# VALIDATE GPL FLAGS
for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVIDSTAB,$LIBRARY_RUBBERBAND}; do
@ -219,13 +235,13 @@ for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVI
done
echo -n -e "\nDownloading sources: "
echo -e "INFO: Downloading source code of ffmpeg and enabled external libraries.\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "INFO: Downloading the source code of ffmpeg and external libraries.\n" 1>>"${BASEDIR}"/build.log 2>&1
# DOWNLOAD GNU CONFIG
download_gnu_config
# DOWNLOAD LIBRARY SOURCES
downloaded_enabled_library_sources "${ENABLED_LIBRARIES[@]}"
downloaded_library_sources "${ENABLED_LIBRARIES[@]}"
# THIS WILL SAVE ARCHITECTURES TO BUILD
TARGET_ARCH_LIST=()
@ -244,7 +260,7 @@ for run_arch in {0..12}; do
TARGET_ARCH_LIST+=("${FULL_ARCH}")
# CLEAR FLAGS
for library in {0..58}; do
for library in {0..61}; do
library_name=$(get_library_name "${library}")
unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")"
unset "$(echo "DEPENDENCY_REBUILT_${library_name}" | sed "s/\-/\_/g")"

@ -16,10 +16,10 @@ export BASEDIR="$(pwd)"
export FFMPEG_KIT_BUILD_TYPE="macos"
source "${BASEDIR}"/scripts/variable.sh
source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh
disabled_libraries=()
# SET DEFAULTS SETTINGS
enable_default_macos_architectures
enable_main_build
# SELECT XCODE VERSION USED FOR BUILDING
XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh 2>>"${BASEDIR}"/build.log)
@ -28,7 +28,7 @@ if [[ -f ${XCODE_FOR_FFMPEG_KIT} ]]; then
fi
# DETECT MACOS SDK VERSION
DETECTED_MACOS_SDK_VERSION="$(xcrun --sdk macosx --show-sdk-version 2>>${BASEDIR}/build.log)"
export DETECTED_MACOS_SDK_VERSION="$(xcrun --sdk macosx --show-sdk-version 2>>${BASEDIR}/build.log)"
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
@ -45,6 +45,9 @@ if [[ -z ${BUILD_VERSION} ]]; then
exit 1
fi
# MAIN BUILDS ENABLED BY DEFAULT
enable_main_build
# PROCESS LTS BUILD OPTION FIRST AND SET BUILD TYPE: MAIN OR LTS
for argument in "$@"; do
if [[ "$argument" == "-l" ]] || [[ "$argument" == "--lts" ]]; then
@ -113,11 +116,24 @@ while [ ! $# -eq 0 ]; do
--enable-gpl)
GPL_ENABLED="yes"
;;
--enable-custom-library-*)
CUSTOM_LIBRARY_OPTION_KEY=$(echo $1 | sed -e 's/^--enable-custom-//g;s/=.*$//g')
CUSTOM_LIBRARY_OPTION_VALUE=$(echo $1 | sed -e 's/^--enable-custom-.*=//g')
echo -e "INFO: Custom library options detected: ${CUSTOM_LIBRARY_OPTION_KEY} ${CUSTOM_LIBRARY_OPTION_VALUE}\n" 1>>"${BASEDIR}"/build.log 2>&1
generate_custom_library_environment_variables "${CUSTOM_LIBRARY_OPTION_KEY}" "${CUSTOM_LIBRARY_OPTION_VALUE}"
;;
--enable-*)
ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
enable_library "${ENABLED_LIBRARY}"
;;
--disable-lib-*)
DISABLED_LIB=$(echo $1 | sed -e 's/^--[A-Za-z]*-[A-Za-z]*-//g')
disabled_libraries+=("${DISABLED_LIB}")
;;
--disable-*)
DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
@ -137,7 +153,7 @@ done
# PROCESS FULL OPTION AS LAST OPTION
if [[ -n ${BUILD_FULL} ]]; then
for library in {0..58}; do
for library in {0..61}; do
if [ ${GPL_ENABLED} == "yes" ]; then
enable_library "$(get_library_name "$library")" 1
else
@ -148,6 +164,11 @@ if [[ -n ${BUILD_FULL} ]]; then
done
fi
# DISABLE SPECIFIED LIBRARIES
for disabled_library in ${disabled_libraries[@]}; do
set_library "${disabled_library}" 0
done
# IF HELP DISPLAYED EXIT
if [[ -n ${DISPLAY_HELP} ]]; then
display_help
@ -155,9 +176,9 @@ if [[ -n ${DISPLAY_HELP} ]]; then
fi
# DISABLE NOT SUPPORTED ARCHITECTURES
disable_macos_architecture_not_supported_on_detected_sdk_version "${ARCH_ARM64}" "${DETECTED_MACOS_SDK_VERSION}"
disable_macos_architecture_not_supported_on_detected_sdk_version "${ARCH_ARM64}"
echo -e "\nBuilding ffmpeg-kit ${BUILD_TYPE_ID}static library for macOS\n"
echo -e "\nBuilding ffmpeg-kit ${BUILD_TYPE_ID}shared library for macOS\n"
echo -e -n "INFO: Building ffmpeg-kit ${BUILD_VERSION} ${BUILD_TYPE_ID}for macOS: " 1>>"${BASEDIR}"/build.log 2>&1
echo -e "$(date)\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -167,6 +188,7 @@ print_enabled_libraries
print_reconfigure_requested_libraries
print_rebuild_requested_libraries
print_redownload_requested_libraries
print_custom_libraries
# VALIDATE GPL FLAGS
for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVIDSTAB,$LIBRARY_RUBBERBAND}; do
@ -182,13 +204,13 @@ for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVI
done
echo -n -e "\nDownloading sources: "
echo -e "INFO: Downloading source code of ffmpeg and enabled external libraries.\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "INFO: Downloading the source code of ffmpeg and external libraries.\n" 1>>"${BASEDIR}"/build.log 2>&1
# DOWNLOAD GNU CONFIG
download_gnu_config
# DOWNLOAD LIBRARY SOURCES
downloaded_enabled_library_sources "${ENABLED_LIBRARIES[@]}"
downloaded_library_sources "${ENABLED_LIBRARIES[@]}"
# THIS WILL SAVE ARCHITECTURES TO BUILD
TARGET_ARCH_LIST=()
@ -207,7 +229,7 @@ for run_arch in {0..12}; do
TARGET_ARCH_LIST+=("${FULL_ARCH}")
# CLEAR FLAGS
for library in {0..58}; do
for library in {0..61}; do
library_name=$(get_library_name "${library}")
unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")"
unset "$(echo "DEPENDENCY_REBUILT_${library_name}" | sed "s/\-/\_/g")"

@ -14,17 +14,20 @@ cmake -Wno-dev \
-DCMAKE_INSTALL_PREFIX="${LIB_INSTALL_PREFIX}" \
-DCMAKE_SYSTEM_NAME=Generic \
-DCMAKE_C_COMPILER="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$CC" \
-DCMAKE_CXX_COMPILER="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$CXX" \
-DCMAKE_LINKER="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$LD" \
-DCMAKE_AR="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$AR" \
-DCMAKE_AS="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$AS" \
-DCMAKE_SYSTEM_PROCESSOR=$(get_cmake_system_processor) \
-DCMAKE_POSITION_INDEPENDENT_CODE=1 \
-DFFT_LIB=kissfft \
-DBUILD_SHARED_LIBS=0 "${BASEDIR}"/src/"${LIB_NAME}" || return 1
-DKISSFFT_SOURCE_DIR="${BASEDIR}"/src/"${LIB_NAME}"/src/3rdparty/kissfft \
-DBUILD_SHARED_LIBS=0 \
-DBUILD_TESTS=0 "${BASEDIR}"/src/"${LIB_NAME}" || return 1
make -j$(get_cpu_count) || return 1
make install || return 1
# CREATE PACKAGE CONFIG MANUALLY
create_chromaprint_package_config "1.5.0" || return 1
create_chromaprint_package_config "1.5.1" || return 1

@ -7,7 +7,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/"${LIB_NAME}"/configure ]] || [[ ${RECONF_expat} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -6,9 +6,6 @@ if [ -z "${HOST_PKG_CONFIG_PATH}" ]; then
exit 1
fi
# ENABLE COMMON FUNCTIONS
source "${BASEDIR}"/scripts/function-"${FFMPEG_KIT_BUILD_TYPE}".sh 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
LIB_NAME="ffmpeg"
echo -e "----------------------------------------------------------------" 1>>"${BASEDIR}"/build.log 2>&1
@ -32,7 +29,7 @@ export CXXFLAGS=$(get_cxxflags "${LIB_NAME}")
export LDFLAGS=$(get_ldflags "${LIB_NAME}")
export PKG_CONFIG_LIBDIR="${INSTALL_PKG_CONFIG_DIR}"
cd "${BASEDIR}"/src/"${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
cd "${BASEDIR}"/src/"${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
# SET BUILD OPTIONS
TARGET_CPU=""
@ -72,9 +69,9 @@ CONFIGURE_POSTFIX=""
HIGH_PRIORITY_INCLUDES=""
# SET CONFIGURE OPTIONS
for library in {1..58}; do
if [[ ${!library} -eq 1 ]]; then
ENABLED_LIBRARY=$(get_library_name $((library - 1)))
for library in {0..61}; do
if [[ ${ENABLED_LIBRARIES[$library]} -eq 1 ]]; then
ENABLED_LIBRARY=$(get_library_name ${library})
echo -e "INFO: Enabling library ${ENABLED_LIBRARY}\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -161,7 +158,7 @@ for library in {1..58}; do
libvidstab)
CFLAGS+=" $(pkg-config --cflags vidstab 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static vidstab 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libvidstab --enable-gpl"
CONFIGURE_POSTFIX+=" --enable-libvidstab"
;;
libvorbis)
CFLAGS+=" $(pkg-config --cflags vorbis 2>>"${BASEDIR}"/build.log)"
@ -194,6 +191,11 @@ for library in {1..58}; do
LDFLAGS+=" $(pkg-config --libs --static openh264 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libopenh264"
;;
openssl)
CFLAGS+=" $(pkg-config --cflags openssl 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static openssl 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-openssl"
;;
opus)
CFLAGS+=" $(pkg-config --cflags opus 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static opus 2>>"${BASEDIR}"/build.log)"
@ -202,7 +204,7 @@ for library in {1..58}; do
rubberband)
CFLAGS+=" $(pkg-config --cflags rubberband 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static rubberband 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-librubberband --enable-gpl"
CONFIGURE_POSTFIX+=" --enable-librubberband"
;;
sdl)
CFLAGS+=" $(pkg-config --cflags sdl2 2>>"${BASEDIR}"/build.log)"
@ -229,6 +231,11 @@ for library in {1..58}; do
LDFLAGS+=" $(pkg-config --libs --static speex 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libspeex"
;;
srt)
CFLAGS+=" $(pkg-config --cflags srt 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static srt 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libsrt"
;;
tesseract)
CFLAGS+=" $(pkg-config --cflags tesseract 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static tesseract 2>>"${BASEDIR}"/build.log)"
@ -249,17 +256,22 @@ for library in {1..58}; do
x264)
CFLAGS+=" $(pkg-config --cflags x264 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static x264 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libx264 --enable-gpl"
CONFIGURE_POSTFIX+=" --enable-libx264"
;;
x265)
CFLAGS+=" $(pkg-config --cflags x265 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static x265 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libx265 --enable-gpl"
CONFIGURE_POSTFIX+=" --enable-libx265"
;;
xvidcore)
CFLAGS+=" $(pkg-config --cflags xvidcore 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static xvidcore 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libxvid --enable-gpl"
CONFIGURE_POSTFIX+=" --enable-libxvid"
;;
zimg)
CFLAGS+=" $(pkg-config --cflags zimg 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static zimg 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libzimg"
;;
expat)
CFLAGS+=" $(pkg-config --cflags expat 2>>"${BASEDIR}"/build.log)"
@ -296,16 +308,36 @@ for library in {1..58}; do
# THE FOLLOWING LIBRARIES SHOULD BE EXPLICITLY DISABLED TO PREVENT AUTODETECT
# NOTE THAT IDS MUST BE +1 OF THE INDEX VALUE
if [[ ${library} -eq $((LIBRARY_SDL + 1)) ]]; then
if [[ ${library} -eq ${LIBRARY_SDL} ]]; then
CONFIGURE_POSTFIX+=" --disable-sdl2"
elif [[ ${library} -eq $((LIBRARY_ANDROID_ZLIB + 1)) ]]; then
elif [[ ${library} -eq ${LIBRARY_ANDROID_ZLIB} ]]; then
CONFIGURE_POSTFIX+=" --disable-zlib"
elif [[ ${library} -eq $((LIBRARY_ANDROID_MEDIA_CODEC + 1)) ]]; then
elif [[ ${library} -eq ${LIBRARY_ANDROID_MEDIA_CODEC} ]]; then
CONFIGURE_POSTFIX+=" --disable-mediacodec"
elif [[ ${library} -eq ${LIBRARY_OPENSSL} ]]; then
CONFIGURE_POSTFIX+=" --disable-openssl"
fi
fi
done
# SET CONFIGURE OPTIONS FOR CUSTOM LIBRARIES
for custom_library_index in "${CUSTOM_LIBRARIES[@]}"; do
library_name="CUSTOM_LIBRARY_${custom_library_index}_NAME"
pc_file_name="CUSTOM_LIBRARY_${custom_library_index}_PACKAGE_CONFIG_FILE_NAME"
ffmpeg_flag_name="CUSTOM_LIBRARY_${custom_library_index}_FFMPEG_ENABLE_FLAG"
echo -e "INFO: Enabling custom library ${!library_name}\n" 1>>"${BASEDIR}"/build.log 2>&1
CFLAGS+=" $(pkg-config --cflags ${!pc_file_name} 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static ${!pc_file_name} 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-${!ffmpeg_flag_name}"
done
# SET ENABLE GPL FLAG WHEN REQUESTED
if [ "$GPL_ENABLED" == "yes" ]; then
CONFIGURE_POSTFIX+=" --enable-gpl"
fi
export LDFLAGS+=" -L${ANDROID_NDK_ROOT}/platforms/android-${API}/arch-${TOOLCHAIN_ARCH}/usr/lib"
# LINKING WITH ANDROID LTS SUPPORT LIBRARY IS NECESSARY FOR API < 18
@ -341,6 +373,13 @@ echo -n -e "\n${LIB_NAME}: "
if [[ -z ${NO_WORKSPACE_CLEANUP_ffmpeg} ]]; then
echo -e "INFO: Cleaning workspace for ${LIB_NAME}\n" 1>>"${BASEDIR}"/build.log 2>&1
make distclean 2>/dev/null 1>/dev/null
# WORKAROUND TO MANUALLY DELETE UNCLEANED FILES
rm -f "${BASEDIR}"/src/"${LIB_NAME}"/libavfilter/opencl/*.o 1>>"${BASEDIR}"/build.log 2>&1
rm -f "${BASEDIR}"/src/"${LIB_NAME}"/libavcodec/neon/*.o 1>>"${BASEDIR}"/build.log 2>&1
# DELETE SHARED FRAMEWORK WORKAROUNDS
git checkout "${BASEDIR}/src/ffmpeg/ffbuild" 1>>"${BASEDIR}"/build.log 2>&1
fi
# UPDATE BUILD FLAGS
@ -350,19 +389,19 @@ export CFLAGS="${HIGH_PRIORITY_INCLUDES} ${CFLAGS}"
ulimit -n 2048 1>>"${BASEDIR}"/build.log 2>&1
########################### CUSTOMIZATIONS #######################
cd "${BASEDIR}" 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
cd "${BASEDIR}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
git checkout android/ffmpeg-kit-android-lib/src/main/cpp/ffmpegkit.c 1>>"${BASEDIR}"/build.log 2>&1
cd "${BASEDIR}"/src/"${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
cd "${BASEDIR}"/src/"${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
git checkout libavformat/file.c 1>>"${BASEDIR}"/build.log 2>&1
git checkout libavformat/protocols.c 1>>"${BASEDIR}"/build.log 2>&1
git checkout libavutil 1>>"${BASEDIR}"/build.log 2>&1
# 1. Use thread local log levels
${SED_INLINE} 's/static int av_log_level/__thread int av_log_level/g' "${BASEDIR}"/src/"${LIB_NAME}"/libavutil/log.c 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
${SED_INLINE} 's/static int av_log_level/__thread int av_log_level/g' "${BASEDIR}"/src/"${LIB_NAME}"/libavutil/log.c 1>>"${BASEDIR}"/build.log 2>&1 || return 1
# 2. Set friendly ffmpeg version
FFMPEG_VERSION="v$(get_user_friendly_ffmpeg_version)"
${SED_INLINE} "s/\$version/$FFMPEG_VERSION/g" "${BASEDIR}"/src/"${LIB_NAME}"/ffbuild/version.sh 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
${SED_INLINE} "s/\$version/$FFMPEG_VERSION/g" "${BASEDIR}"/src/"${LIB_NAME}"/ffbuild/version.sh 1>>"${BASEDIR}"/build.log 2>&1 || return 1
# 3. Enable ffmpeg-kit protocols
if [[ ${NO_FFMPEG_KIT_PROTOCOLS} == "1" ]]; then
@ -373,7 +412,7 @@ else
cat ../../tools/protocols/libavutil_file.h >> libavutil/file.h
cat ../../tools/protocols/libavutil_file.c >> libavutil/file.c
awk '{gsub(/ff_file_protocol;/,"ff_file_protocol;\nextern const URLProtocol ff_saf_protocol;")}1' libavformat/protocols.c > libavformat/protocols.c.tmp
awk '{gsub(/ff_file_protocol;/,"ff_file_protocol;\nextern const URLProtocol ff_fd_protocol;")}1' libavformat/protocols.c.tmp > libavformat/protocols.c
cat libavformat/protocols.c.tmp > libavformat/protocols.c
echo -e "\nINFO: Enabled custom ffmpeg-kit protocols\n" 1>>"${BASEDIR}"/build.log 2>&1
fi
@ -387,25 +426,27 @@ fi
--enable-version3 \
--arch="${TARGET_ARCH}" \
--cpu="${TARGET_CPU}" \
--target-os=android \
${ASM_OPTIONS} \
--ar="${AR}" \
--cc="${CC}" \
--cxx="${CXX}" \
--ranlib="${RANLIB}" \
--strip="${STRIP}" \
--nm="${NM}" \
--extra-libs="$(pkg-config --libs --static cpu-features)" \
--target-os=android \
${ASM_OPTIONS} \
--disable-autodetect \
--enable-cross-compile \
--enable-pic \
--enable-jni \
--enable-optimizations \
--enable-swscale \
${BUILD_LIBRARY_OPTIONS} \
--enable-pthreads \
--enable-v4l2-m2m \
--disable-outdev=fbdev \
--disable-indev=fbdev \
${SIZE_OPTIONS} \
--disable-openssl \
--disable-xmm-clobber-test \
${DEBUG_OPTIONS} \
--disable-neon-clobber-test \
@ -462,7 +503,7 @@ fi
# DELETE THE PREVIOUS BUILD OF THE LIBRARY BEFORE INSTALLING
if [ -d "${FFMPEG_LIBRARY_PATH}" ]; then
rm -rf "${FFMPEG_LIBRARY_PATH}" 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
rm -rf "${FFMPEG_LIBRARY_PATH}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
make install 1>>"${BASEDIR}"/build.log 2>&1

@ -3,16 +3,19 @@
# ALWAYS CLEAN THE PREVIOUS BUILD
make distclean 2>/dev/null 1>/dev/null
# WORKAROUND FOR "bad flag in substitute command"
${SED_INLINE} "s|in \"\$default_fonts\"|in \$default_fonts|g" "${BASEDIR}"/src/"${LIB_NAME}"/configure.ac 1>>"${BASEDIR}"/build.log 2>&1
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_fontconfig} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
# WORKAROUND TO FIX NOT-APPLIED HAVE_POSIX_FADVISE define ON MACOS
if [[ -n ${FFMPEG_KIT_LTS_BUILD} ]]; then
${SED_INLINE} "s/(HAVE_POSIX_FADVISE)/(NO_HAVE_POSIX_FADVISE)/g" "${BASEDIR}"/src/"${LIB_NAME}"/src/fccache.c 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
${SED_INLINE} "s/(HAVE_POSIX_FADVISE)/(NO_HAVE_POSIX_FADVISE)/g" "${BASEDIR}"/src/"${LIB_NAME}"/src/fccache.c 1>>"${BASEDIR}"/build.log 2>&1 || return 1
else
${SED_INLINE} "s/NO_HAVE_POSIX_FADVISE/HAVE_POSIX_FADVISE/g" "${BASEDIR}"/src/"${LIB_NAME}"/src/fccache.c 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
${SED_INLINE} "s/NO_HAVE_POSIX_FADVISE/HAVE_POSIX_FADVISE/g" "${BASEDIR}"/src/"${LIB_NAME}"/src/fccache.c 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \
@ -34,4 +37,4 @@ make -j$(get_cpu_count) || return 1
make install || return 1
# CREATE PACKAGE CONFIG MANUALLY
create_fontconfig_package_config "2.13.93" || return 1
create_fontconfig_package_config "2.13.94" || return 1

@ -37,4 +37,4 @@ make -j$(get_cpu_count) || return 1
make install || return 1
# CREATE PACKAGE CONFIG MANUALLY
create_freetype_package_config "24.0.18" || return 1
create_freetype_package_config "24.1.18" || return 1

@ -5,7 +5,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_fribidi} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -8,7 +8,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_giflib} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -5,7 +5,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_gmp} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -5,7 +5,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_kvazaar} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
# UPDATE BUILD FLAGS

@ -7,7 +7,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_lame} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -23,7 +23,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_leptonica} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -56,4 +56,4 @@ make -j$(get_cpu_count) || return 1
make install || return 1
# CREATE PACKAGE CONFIG MANUALLY
create_libaom_package_config "3.1.2" || return 1
create_libaom_package_config "3.2.0" || return 1

@ -19,7 +19,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libass} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -8,7 +8,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libiconv} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -5,7 +5,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libilbc} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -5,7 +5,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libogg} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -22,7 +22,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libpng} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -5,7 +5,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libsamplerate} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -5,7 +5,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libsndfile} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

@ -5,7 +5,7 @@ make distclean 2>/dev/null 1>/dev/null
# REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libuuid} -eq 1 ]]; then
autoreconf_library "${LIB_NAME}"
autoreconf_library "${LIB_NAME}" 1>>"${BASEDIR}"/build.log 2>&1 || return 1
fi
./configure \

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save