Merge pull request #289 from tanersener/development

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

@ -1,2 +1,3 @@
patreon: tanersener 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' ]

@ -1,6 +1,13 @@
name: android build scripts name: android build scripts
on: [ push, pull_request ] on:
push:
branches:
- development
- main
pull_request:
branches:
- main
jobs: jobs:
build-main-on-linux: build-main-on-linux:
@ -8,7 +15,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
ndk-version: [ 'r21e-linux-x86_64', 'r22b-linux-x86_64', 'r23-linux' ] ndk-version: [ 'r22b-linux-x86_64', 'r23b-linux' ]
defaults: defaults:
run: run:
shell: bash shell: bash
@ -37,7 +44,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
strategy: strategy:
matrix: matrix:
ndk-version: [ 'r21e-linux-x86_64', 'r22b-linux-x86_64', 'r23-linux' ] ndk-version: [ 'r22b-linux-x86_64', 'r23b-linux' ]
defaults: defaults:
run: run:
shell: bash shell: bash
@ -66,7 +73,7 @@ jobs:
runs-on: macos-10.15 runs-on: macos-10.15
strategy: strategy:
matrix: matrix:
ndk-version: [ 'r21e-darwin-x86_64', 'r22b-darwin-x86_64', 'r23-darwin' ] ndk-version: [ 'r22b-darwin-x86_64', 'r23b-darwin' ]
defaults: defaults:
run: run:
shell: bash shell: bash
@ -95,7 +102,7 @@ jobs:
runs-on: macos-10.15 runs-on: macos-10.15
strategy: strategy:
matrix: matrix:
ndk-version: [ 'r21e-darwin-x86_64', 'r22b-darwin-x86_64', 'r23-darwin' ] ndk-version: [ 'r22b-darwin-x86_64', 'r23b-darwin' ]
defaults: defaults:
run: run:
shell: bash shell: bash

@ -1,6 +1,13 @@
name: ios build scripts name: ios build scripts
on: [ push, pull_request ] on:
push:
branches:
- development
- main
pull_request:
branches:
- main
jobs: jobs:
build-main-on-macos-bigsur: build-main-on-macos-bigsur:

@ -1,6 +1,13 @@
name: macos build scripts name: macos build scripts
on: [ push, pull_request ] on:
push:
branches:
- development
- main
pull_request:
branches:
- main
jobs: jobs:
build-main-on-macos-bigsur: build-main-on-macos-bigsur:

@ -1,6 +1,13 @@
name: tvos build scripts name: tvos build scripts
on: [ push, pull_request ] on:
push:
branches:
- development
- main
pull_request:
branches:
- main
jobs: jobs:
build-main-on-macos-bigsur: build-main-on-macos-bigsur:

@ -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"> <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></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>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>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>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></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></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>
<tr> <tr>
<td align="center"><sup>android system libraries</sup></td> <td align="center"><sup>android system libraries</sup></td>
@ -109,6 +109,7 @@ include them.
- `AVFoundation` is not available on `tvOS` - `AVFoundation` is not available on `tvOS`
- `VideoToolbox` is not available on LTS releases of `iOS` and `tvOS` - `VideoToolbox` is not available on LTS releases of `iOS` and `tvOS`
- `zimg` is supported since `v4.5.1`
### 9. Versions ### 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. This table shows the differences between two variants.
| | Main Release | LTS Release | | | Main Release | LTS Release |
| :----: | :----: | :----: | | :----: | :----: |:---------------------------------------------------------:|
| Android API Level | 24 | 16 | | Android API Level | 24 | 16 |
| Android Camera Access | Yes | - | | 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 | | 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 Min SDK | 12.1 | 10 |
| iOS VideoToolbox | Yes | - | | iOS VideoToolbox | Yes | - |
| iOS AVFoundation | 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 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 | | iOS Bundle Format | XCFrameworks | Frameworks |
| macOS Min SDK | 10.15 | 10.11 | | Mac Catalyst Min Version | 14.0 | - |
| macOS AVFoundation | Yes | - | | macOS Min SDK | 10.15 | 10.12 |
| macOS Architectures | arm64<br/>x86-64 | x86-64 | | macOS AVFoundation | Yes | - |
| macOS Bundle Format | XCFrameworks | Frameworks | | macOS Architectures | arm64<br/>x86-64 | x86-64 |
| tvOS Min SDK | 11.0 | 9.2 | | macOS Bundle Format | XCFrameworks | Frameworks |
| tvOS VideoToolbox | Yes | - | | tvOS Min SDK | 11.0 | 10.0 |
| tvOS Architectures | arm64<br/>x86-64<br/>arm64-simulator | arm64<br/>x86-64 | | tvOS VideoToolbox | Yes | - |
| tvOS Bundle Format | XCFrameworks | Frameworks | | tvOS Architectures | arm64<br/>x86-64<br/>arm64-simulator | arm64<br/>x86-64 |
| tvOS Bundle Format | XCFrameworks | Frameworks |
### 11. Documentation ### 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 `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. 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 ### 14. Patents
It is not clearly explained in their documentation, but it is believed that `FFmpeg`, `kvazaar`, `x264` and `x265` 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" export FFMPEG_KIT_BUILD_TYPE="android"
source "${BASEDIR}"/scripts/variable.sh source "${BASEDIR}"/scripts/variable.sh
source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh
disabled_libraries=()
# SET DEFAULTS SETTINGS # SET DEFAULTS SETTINGS
enable_default_android_architectures enable_default_android_architectures
@ -106,11 +107,24 @@ while [ ! $# -eq 0 ]; do
--enable-gpl) --enable-gpl)
GPL_ENABLED="yes" 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-*) --enable-*)
ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g') ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
enable_library "${ENABLED_LIBRARY}" 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-*) --disable-*)
DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g') DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
@ -138,7 +152,7 @@ fi
# PROCESS FULL OPTION AS LAST OPTION # PROCESS FULL OPTION AS LAST OPTION
if [[ -n ${BUILD_FULL} ]]; then if [[ -n ${BUILD_FULL} ]]; then
for library in {0..58}; do for library in {0..61}; do
if [ ${GPL_ENABLED} == "yes" ]; then if [ ${GPL_ENABLED} == "yes" ]; then
enable_library "$(get_library_name $library)" 1 enable_library "$(get_library_name $library)" 1
else else
@ -149,12 +163,21 @@ if [[ -n ${BUILD_FULL} ]]; then
done done
fi fi
# DISABLE SPECIFIED LIBRARIES
for disabled_library in ${disabled_libraries[@]}; do
set_library "${disabled_library}" 0
done
# IF HELP DISPLAYED EXIT # IF HELP DISPLAYED EXIT
if [[ -n ${DISPLAY_HELP} ]]; then if [[ -n ${DISPLAY_HELP} ]]; then
display_help display_help
exit 0 exit 0
fi 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 "\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 -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 echo -e "$(date)\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -165,6 +188,7 @@ print_enabled_libraries
print_reconfigure_requested_libraries print_reconfigure_requested_libraries
print_rebuild_requested_libraries print_rebuild_requested_libraries
print_redownload_requested_libraries print_redownload_requested_libraries
print_custom_libraries
# VALIDATE GPL FLAGS # VALIDATE GPL FLAGS
for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVIDSTAB,$LIBRARY_RUBBERBAND}; do 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 done
echo -n -e "\nDownloading sources: " 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_gnu_config download_gnu_config
# DOWNLOAD LIBRARY SOURCES # DOWNLOAD LIBRARY SOURCES
downloaded_enabled_library_sources "${ENABLED_LIBRARIES[@]}" downloaded_library_sources "${ENABLED_LIBRARIES[@]}"
# SAVE ORIGINAL API LEVEL = NECESSARY TO BUILD 64bit ARCHITECTURES # SAVE ORIGINAL API LEVEL = NECESSARY TO BUILD 64bit ARCHITECTURES
export ORIGINAL_API=${API} export ORIGINAL_API=${API}
@ -210,7 +234,7 @@ for run_arch in {0..12}; do
. "${BASEDIR}"/scripts/main-android.sh "${ENABLED_LIBRARIES[@]}" || exit 1 . "${BASEDIR}"/scripts/main-android.sh "${ENABLED_LIBRARIES[@]}" || exit 1
# CLEAR FLAGS # CLEAR FLAGS
for library in {0..58}; do for library in {0..61}; do
library_name=$(get_library_name ${library}) library_name=$(get_library_name ${library})
unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")" unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")"
unset "$(echo "DEPENDENCY_REBUILT_${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 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 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 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 if [[ ${ENABLED_LIBRARIES[$library]} -eq 1 ]]; then
ENABLED_LIBRARY=$(get_library_name ${library} | sed 's/-/_/g') ENABLED_LIBRARY=$(get_library_name ${library} | sed 's/-/_/g')
LICENSE_FILE="${LICENSE_BASEDIR}/license_${ENABLED_LIBRARY}.txt" LICENSE_FILE="${LICENSE_BASEDIR}/license_${ENABLED_LIBRARY}.txt"
@ -285,6 +309,26 @@ if [[ -n ${ANDROID_ARCHITECTURES} ]]; then
fi fi
done 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 # COPY LIBRARY LICENSES
if [[ ${GPL_ENABLED} == "yes" ]]; then if [[ ${GPL_ENABLED} == "yes" ]]; then
cp "${BASEDIR}"/LICENSE.GPLv3 "${LICENSE_BASEDIR}"/license.txt 1>>"${BASEDIR}"/build.log 2>&1 cp "${BASEDIR}"/LICENSE.GPLv3 "${LICENSE_BASEDIR}"/license.txt 1>>"${BASEDIR}"/build.log 2>&1

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

@ -22,7 +22,7 @@ external libraries enabled.
##### 2.1.1 Android Tools ##### 2.1.1 Android Tools
- Android SDK Build 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 ##### 2.1.2 Packages
@ -77,7 +77,7 @@ All libraries created by `android.sh` can be found under the `prebuilt` director
} }
dependencies { 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. 4. Execute asynchronous `FFmpeg` commands by providing session specific `execute`/`log`/`session` callbacks.
```java ```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 @Override
public void apply(Session session) { public void apply(FFmpegSession session) {
SessionState state = session.getState(); SessionState state = session.getState();
ReturnCode returnCode = session.getReturnCode(); ReturnCode returnCode = session.getReturnCode();
@ -189,10 +189,10 @@ All libraries created by `android.sh` can be found under the `prebuilt` director
- Asynchronous - Asynchronous
```java ```java
FFprobeKit.executeAsync(ffprobeCommand, new ExecuteCallback() { FFprobeKit.executeAsync(ffprobeCommand, new FFprobeSessionCompleteCallback() {
@Override @Override
public void apply(Session session) { public void apply(FFprobeSession session) {
CALLED WHEN SESSION IS EXECUTED 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); 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. 9. Get previous `FFmpeg` and `FFprobe` sessions from session history.
```java ```java
@ -253,13 +261,29 @@ All libraries created by `android.sh` can be found under the `prebuilt` director
10. Enable global callbacks. 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 ```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 @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 # could be handy for archiving the generated documentation or if some version
# control system is used. # 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 # 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 # 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 { android {
compileSdkVersion 30 compileSdkVersion 30
ndkVersion "23.0.7599858" ndkVersion "23.1.7779620"
defaultConfig { defaultConfig {
minSdkVersion 24 minSdkVersion 24
targetSdkVersion 30 targetSdkVersion 30
versionCode 240450 versionCode 240451
versionName "4.5" versionName "4.5.1"
project.archivesBaseName = "ffmpeg-kit" project.archivesBaseName = "ffmpeg-kit"
consumerProguardFiles 'proguard-rules.pro' consumerProguardFiles 'proguard-rules.pro'
} }
@ -44,8 +44,8 @@ task javadoc(type: Javadoc) {
} }
dependencies { dependencies {
implementation 'com.arthenica:smart-exception-java:0.1.0' implementation 'com.arthenica:smart-exception-java:0.1.1'
testImplementation "androidx.test.ext:junit:1.1.2" testImplementation "androidx.test.ext:junit:1.1.3"
testImplementation "org.json:json:20201115" testImplementation "org.json:json:20201115"
} }

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

@ -80,8 +80,11 @@ static jmethodID logMethod;
/** Global reference of statistics redirection method in Java */ /** Global reference of statistics redirection method in Java */
static jmethodID statisticsMethod; static jmethodID statisticsMethod;
/** Global reference of closeParcelFileDescriptor method in Java */ /** Global reference of safOpen method in Java */
static jmethodID closeParcelFileDescriptorMethod; static jmethodID safOpenMethod;
/** Global reference of safClose method in Java */
static jmethodID safCloseMethod;
/** Global reference of String class in Java */ /** Global reference of String class in Java */
static jclass stringClass; 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; JNIEnv *env = NULL;
(*globalVm)->GetEnv(globalVm, (void**) &env, JNI_VERSION_1_6); (*globalVm)->GetEnv(globalVm, (void**) &env, JNI_VERSION_1_6);
(*env)->CallStaticVoidMethod(env, configClass, closeParcelFileDescriptorMethod, fd); return (*env)->CallStaticIntMethod(env, configClass, safOpenMethod, safId);
return 0; }
/**
* 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; 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) { 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; return JNI_FALSE;
} }
@ -645,7 +662,8 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
redirectionEnabled = 0; 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; return JNI_VERSION_1_6;
} }

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

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

@ -19,29 +19,41 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
import com.arthenica.smartexception.java.Exceptions;
/** /**
* <p>Executes an FFmpeg session asynchronously. * <p>Executes an FFmpeg session asynchronously.
*/ */
public class AsyncFFmpegExecuteTask implements Runnable { public class AsyncFFmpegExecuteTask implements Runnable {
private final FFmpegSession ffmpegSession; private final FFmpegSession ffmpegSession;
private final ExecuteCallback executeCallback; private final FFmpegSessionCompleteCallback completeCallback;
public AsyncFFmpegExecuteTask(final FFmpegSession ffmpegSession) { public AsyncFFmpegExecuteTask(final FFmpegSession ffmpegSession) {
this.ffmpegSession = ffmpegSession; this.ffmpegSession = ffmpegSession;
this.executeCallback = ffmpegSession.getExecuteCallback(); this.completeCallback = ffmpegSession.getCompleteCallback();
} }
@Override @Override
public void run() { public void run() {
FFmpegKitConfig.ffmpegExecute(ffmpegSession); FFmpegKitConfig.ffmpegExecute(ffmpegSession);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback(); if (completeCallback != null) {
if (globalExecuteCallbackFunction != null) { try {
globalExecuteCallbackFunction.apply(ffmpegSession); // 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) { final FFmpegSessionCompleteCallback globalFFmpegSessionCompleteCallback = FFmpegKitConfig.getFFmpegSessionCompleteCallback();
executeCallback.apply(ffmpegSession); 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; package com.arthenica.ffmpegkit;
import com.arthenica.smartexception.java.Exceptions;
/** /**
* <p>Executes an FFprobe session asynchronously. * <p>Executes an FFprobe session asynchronously.
*/ */
public class AsyncFFprobeExecuteTask implements Runnable { public class AsyncFFprobeExecuteTask implements Runnable {
private final FFprobeSession ffprobeSession; private final FFprobeSession ffprobeSession;
private final ExecuteCallback executeCallback; private final FFprobeSessionCompleteCallback completeCallback;
public AsyncFFprobeExecuteTask(final FFprobeSession ffprobeSession) { public AsyncFFprobeExecuteTask(final FFprobeSession ffprobeSession) {
this.ffprobeSession = ffprobeSession; this.ffprobeSession = ffprobeSession;
this.executeCallback = ffprobeSession.getExecuteCallback(); this.completeCallback = ffprobeSession.getCompleteCallback();
} }
@Override @Override
public void run() { public void run() {
FFmpegKitConfig.ffprobeExecute(ffprobeSession); FFmpegKitConfig.ffprobeExecute(ffprobeSession);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback(); if (completeCallback != null) {
if (globalExecuteCallbackFunction != null) { try {
globalExecuteCallbackFunction.apply(ffprobeSession); // 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) { final FFprobeSessionCompleteCallback globalFFprobeSessionCompleteCallback = FFmpegKitConfig.getFFprobeSessionCompleteCallback();
executeCallback.apply(ffprobeSession); 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; package com.arthenica.ffmpegkit;
import com.arthenica.smartexception.java.Exceptions;
/** /**
* <p>Executes a MediaInformation session asynchronously. * <p>Executes a MediaInformation session asynchronously.
*/ */
public class AsyncGetMediaInformationTask implements Runnable { public class AsyncGetMediaInformationTask implements Runnable {
private final MediaInformationSession mediaInformationSession; private final MediaInformationSession mediaInformationSession;
private final ExecuteCallback executeCallback; private final MediaInformationSessionCompleteCallback completeCallback;
private final Integer waitTimeout; private final Integer waitTimeout;
public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession) { public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession) {
@ -33,7 +35,7 @@ public class AsyncGetMediaInformationTask implements Runnable {
public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession, final Integer waitTimeout) { public AsyncGetMediaInformationTask(final MediaInformationSession mediaInformationSession, final Integer waitTimeout) {
this.mediaInformationSession = mediaInformationSession; this.mediaInformationSession = mediaInformationSession;
this.executeCallback = mediaInformationSession.getExecuteCallback(); this.completeCallback = mediaInformationSession.getCompleteCallback();
this.waitTimeout = waitTimeout; this.waitTimeout = waitTimeout;
} }
@ -41,13 +43,23 @@ public class AsyncGetMediaInformationTask implements Runnable {
public void run() { public void run() {
FFmpegKitConfig.getMediaInformationExecute(mediaInformationSession, waitTimeout); FFmpegKitConfig.getMediaInformationExecute(mediaInformationSession, waitTimeout);
final ExecuteCallback globalExecuteCallbackFunction = FFmpegKitConfig.getExecuteCallback(); if (completeCallback != null) {
if (globalExecuteCallbackFunction != null) { try {
globalExecuteCallbackFunction.apply(mediaInformationSession); // 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) { final MediaInformationSessionCompleteCallback globalMediaInformationSessionCompleteCallback = FFmpegKitConfig.getMediaInformationSessionCompleteCallback();
executeCallback.apply(mediaInformationSession); 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; package com.arthenica.ffmpegkit;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
/** /**
* <p>Main class to run <code>FFmpeg</code> commands. Supports executing commands both synchronously and * <p>Main class to run <code>FFmpeg</code> commands. Supports executing commands both
* asynchronously. * synchronously and asynchronously.
* <pre> * <pre>
* FFmpegSession session = FFmpegKit.execute("-i file1.mp4 -c:v libxvid file1.avi"); * 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> * </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks. * <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre> * <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> * </pre>
*/ */
public class FFmpegKit { public class FFmpegKit {
@ -55,7 +54,7 @@ public class FFmpegKit {
* @param arguments FFmpeg command options/arguments as string array * @param arguments FFmpeg command options/arguments as string array
* @return FFmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession execute(final String[] arguments) { public static FFmpegSession executeWithArguments(final String[] arguments) {
final FFmpegSession session = new FFmpegSession(arguments); final FFmpegSession session = new FFmpegSession(arguments);
FFmpegKitConfig.ffmpegExecute(session); FFmpegKitConfig.ffmpegExecute(session);
@ -66,16 +65,17 @@ public class FFmpegKit {
/** /**
* <p>Starts an asynchronous FFmpeg execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 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
* @return FFmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String[] arguments, public static FFmpegSession executeWithArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback) { final FFmpegSessionCompleteCallback completeCallback) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback); final FFmpegSession session = new FFmpegSession(arguments, completeCallback);
FFmpegKitConfig.asyncFFmpegExecute(session); FFmpegKitConfig.asyncFFmpegExecute(session);
@ -85,20 +85,21 @@ public class FFmpegKit {
/** /**
* <p>Starts an asynchronous FFmpeg execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 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 logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @return FFmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String[] arguments, public static FFmpegSession executeWithArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback, final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback) { final StatisticsCallback statisticsCallback) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, logCallback, statisticsCallback); final FFmpegSession session = new FFmpegSession(arguments, completeCallback, logCallback, statisticsCallback);
FFmpegKitConfig.asyncFFmpegExecute(session); FFmpegKitConfig.asyncFFmpegExecute(session);
@ -108,18 +109,19 @@ public class FFmpegKit {
/** /**
* <p>Starts an asynchronous FFmpeg execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 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 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 * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String[] arguments, public static FFmpegSession executeWithArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback, final FFmpegSessionCompleteCallback completeCallback,
final ExecutorService executorService) { final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback); final FFmpegSession session = new FFmpegSession(arguments, completeCallback);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService); FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
@ -129,22 +131,24 @@ public class FFmpegKit {
/** /**
* <p>Starts an asynchronous FFmpeg execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 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 logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @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 * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String[] arguments, public static FFmpegSession executeWithArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback, final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback, final StatisticsCallback statisticsCallback,
final ExecutorService executorService) { final ExecutorService executorService) {
final FFmpegSession session = new FFmpegSession(arguments, executeCallback, logCallback, statisticsCallback); final FFmpegSession session = new FFmpegSession(arguments, completeCallback, logCallback, statisticsCallback);
FFmpegKitConfig.asyncFFmpegExecute(session, executorService); FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
@ -160,61 +164,67 @@ public class FFmpegKit {
* @return FFmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession execute(final String command) { public static FFmpegSession execute(final String command) {
return execute(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 * <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to
* into arguments. You can use single or double quote characters to specify arguments inside your command. * 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
* *
* @param command FFmpeg command * @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
* @return FFmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String command, public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback) { final FFmpegSessionCompleteCallback completeCallback) {
return executeAsync(FFmpegKitConfig.parseArguments(command), executeCallback); return executeWithArgumentsAsync(FFmpegKitConfig.parseArguments(command), completeCallback);
} }
/** /**
* <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to split the command * <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to
* into arguments. You can use single or double quote characters to specify arguments inside your command. * 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
* *
* @param command FFmpeg command * @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 logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @return FFmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String command, public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback, final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback) { 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 * <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to
* into arguments. You can use single or double quote characters to specify arguments inside your command. * 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
* *
* @param command FFmpeg command * @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 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 * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String command, public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback, final FFmpegSessionCompleteCallback completeCallback,
final ExecutorService executorService) { 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); 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 * <p>Starts an asynchronous FFmpeg execution for the given command. Space character is used to
* into arguments. You can use single or double quote characters to specify arguments inside your command. * 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * You must use an {@link FFmpegSessionCompleteCallback} if you want to be notified about the
* result.
* *
* @param command FFmpeg command * @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 logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @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 * @return FFmpeg session created for this execution
*/ */
public static FFmpegSession executeAsync(final String command, public static FFmpegSession executeAsync(final String command,
final ExecuteCallback executeCallback, final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback, final StatisticsCallback statisticsCallback,
final ExecutorService executorService) { 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); FFmpegKitConfig.asyncFFmpegExecute(session, executorService);
@ -250,7 +262,7 @@ public class FFmpegKit {
/** /**
* <p>Cancels all running sessions. * <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() { public static void cancel() {
@ -265,7 +277,7 @@ public class FFmpegKit {
/** /**
* <p>Cancels the session specified with <code>sessionId</code>. * <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 * @param sessionId id of the session that will be cancelled
*/ */

@ -19,6 +19,8 @@
package com.arthenica.ffmpegkit; package com.arthenica.ffmpegkit;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
@ -44,7 +46,7 @@ import java.util.StringTokenizer;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
/** /**
@ -52,6 +54,45 @@ import java.util.concurrent.atomic.AtomicReference;
*/ */
public class FFmpegKitConfig { 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. * The tag used for logging.
*/ */
@ -63,9 +104,9 @@ public class FFmpegKitConfig {
static final String FFMPEG_KIT_NAMED_PIPE_PREFIX = "fk_pipe_"; static final String FFMPEG_KIT_NAMED_PIPE_PREFIX = "fk_pipe_";
/** /**
* Generates ids for named ffmpeg kit pipes. * Generates ids for named ffmpeg kit pipes and saf protocol urls.
*/ */
private static final AtomicLong pipeIndexGenerator; private static final AtomicInteger uniqueIdGenerator;
private static Level activeLogLevel; private static Level activeLogLevel;
@ -79,10 +120,13 @@ public class FFmpegKitConfig {
private static ExecutorService asyncExecutorService; private static ExecutorService asyncExecutorService;
/* Global callbacks */ /* Global callbacks */
private static LogCallback globalLogCallbackFunction; private static LogCallback globalLogCallback;
private static StatisticsCallback globalStatisticsCallbackFunction; private static StatisticsCallback globalStatisticsCallback;
private static ExecuteCallback globalExecuteCallbackFunction; private static FFmpegSessionCompleteCallback globalFFmpegSessionCompleteCallback;
private static final SparseArray<ParcelFileDescriptor> pfdMap; private static FFprobeSessionCompleteCallback globalFFprobeSessionCompleteCallback;
private static MediaInformationSessionCompleteCallback globalMediaInformationSessionCompleteCallback;
private static final SparseArray<SAFProtocolUrl> safIdMap;
private static final SparseArray<SAFProtocolUrl> safFileDescriptorMap;
private static LogRedirectionStrategy globalLogRedirectionStrategy; private static LogRedirectionStrategy globalLogRedirectionStrategy;
static { 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())); 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 */ /* NATIVE LOG LEVEL IS RECEIVED ONLY ON STARTUP */
activeLogLevel = Level.from(NativeLoader.loadLogLevel()); activeLogLevel = Level.from(NativeLoader.loadLogLevel());
@ -121,11 +165,14 @@ public class FFmpegKitConfig {
sessionHistoryList = new LinkedList<>(); sessionHistoryList = new LinkedList<>();
sessionHistoryLock = new Object(); sessionHistoryLock = new Object();
globalLogCallbackFunction = null; globalLogCallback = null;
globalStatisticsCallbackFunction = null; globalStatisticsCallback = null;
globalExecuteCallbackFunction = null; globalFFmpegSessionCompleteCallback = null;
globalFFprobeSessionCompleteCallback = null;
globalMediaInformationSessionCompleteCallback = null;
pfdMap = new SparseArray<>(); safIdMap = new SparseArray<>();
safFileDescriptorMap = new SparseArray<>();
globalLogRedirectionStrategy = LogRedirectionStrategy.PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED; globalLogRedirectionStrategy = LogRedirectionStrategy.PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED;
NativeLoader.enableRedirection(); NativeLoader.enableRedirection();
@ -196,12 +243,12 @@ public class FFmpegKitConfig {
// NOTIFY SESSION CALLBACK DEFINED // NOTIFY SESSION CALLBACK DEFINED
session.getLogCallback().apply(log); session.getLogCallback().apply(log);
} catch (final Exception e) { } catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session LogCallback block.%s", Exceptions.getStackTraceString(e))); android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session log callback.%s", Exceptions.getStackTraceString(e)));
} }
} }
} }
final LogCallback globalLogCallbackFunction = FFmpegKitConfig.globalLogCallbackFunction; final LogCallback globalLogCallbackFunction = FFmpegKitConfig.globalLogCallback;
if (globalLogCallbackFunction != null) { if (globalLogCallbackFunction != null) {
globalCallbackDefined = true; globalCallbackDefined = true;
@ -209,7 +256,7 @@ public class FFmpegKitConfig {
// NOTIFY GLOBAL CALLBACK DEFINED // NOTIFY GLOBAL CALLBACK DEFINED
globalLogCallbackFunction.apply(log); globalLogCallbackFunction.apply(log);
} catch (final Exception e) { } catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global LogCallback block.%s", Exceptions.getStackTraceString(e))); android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside global log callback.%s", Exceptions.getStackTraceString(e)));
} }
} }
@ -229,13 +276,16 @@ public class FFmpegKitConfig {
return; return;
} }
} }
break;
case PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED: { case PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED: {
if (globalCallbackDefined || sessionCallbackDefined) { if (globalCallbackDefined || sessionCallbackDefined) {
return; return;
} }
} }
break;
case ALWAYS_PRINT_LOGS: { case ALWAYS_PRINT_LOGS: {
} }
break;
} }
// PRINT LOGS // PRINT LOGS
@ -299,18 +349,18 @@ public class FFmpegKitConfig {
// NOTIFY SESSION CALLBACK IF DEFINED // NOTIFY SESSION CALLBACK IF DEFINED
ffmpegSession.getStatisticsCallback().apply(statistics); ffmpegSession.getStatisticsCallback().apply(statistics);
} catch (final Exception e) { } catch (final Exception e) {
android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session StatisticsCallback block.%s", Exceptions.getStackTraceString(e))); android.util.Log.e(FFmpegKitConfig.TAG, String.format("Exception thrown inside session statistics callback.%s", Exceptions.getStackTraceString(e)));
} }
} }
} }
final StatisticsCallback globalStatisticsCallbackFunction = FFmpegKitConfig.globalStatisticsCallbackFunction; final StatisticsCallback globalStatisticsCallbackFunction = FFmpegKitConfig.globalStatisticsCallback;
if (globalStatisticsCallbackFunction != null) { if (globalStatisticsCallbackFunction != null) {
try { try {
// NOTIFY GLOBAL CALLBACK IF DEFINED // NOTIFY GLOBAL CALLBACK IF DEFINED
globalStatisticsCallbackFunction.apply(statistics); globalStatisticsCallbackFunction.apply(statistics);
} catch (final Exception e) { } 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 // FIRST CLOSE OLD PIPES WITH THE SAME NAME
closeFFmpegPipe(newFFmpegPipePath); closeFFmpegPipe(newFFmpegPipePath);
@ -645,7 +695,7 @@ public class FFmpegKitConfig {
final int returnCodeValue = nativeFFprobeExecute(mediaInformationSession.getSessionId(), mediaInformationSession.getArguments()); final int returnCodeValue = nativeFFprobeExecute(mediaInformationSession.getSessionId(), mediaInformationSession.getArguments());
final ReturnCode returnCode = new ReturnCode(returnCodeValue); final ReturnCode returnCode = new ReturnCode(returnCodeValue);
mediaInformationSession.complete(returnCode); mediaInformationSession.complete(returnCode);
if (returnCode.isSuccess()) { if (returnCode.isValueSuccess()) {
MediaInformation mediaInformation = MediaInformationJsonParser.fromWithError(mediaInformationSession.getAllLogsAsString(waitTimeout)); MediaInformation mediaInformation = MediaInformationJsonParser.fromWithError(mediaInformationSession.getAllLogsAsString(waitTimeout));
mediaInformationSession.setMediaInformation(mediaInformation); mediaInformationSession.setMediaInformation(mediaInformation);
} }
@ -658,8 +708,9 @@ public class FFmpegKitConfig {
/** /**
* <p>Starts an asynchronous FFmpeg execution for the given session. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 ffmpegSession FFmpeg session which includes command options/arguments
* @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
@ -687,8 +739,9 @@ public class FFmpegKitConfig {
/** /**
* <p>Starts an asynchronous FFprobe execution for the given session. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 ffprobeSession FFprobe session which includes command options/arguments
* @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
@ -716,10 +770,12 @@ public class FFmpegKitConfig {
/** /**
* <p>Starts an asynchronous FFprobe execution for the given media information session. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 * @param waitTimeout max time to wait until media information is transmitted
*/ */
public static void asyncGetMediaInformationExecute(final MediaInformationSession mediaInformationSession, final int waitTimeout) { 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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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
* @param executorService executor service that will be used to run this asynchronous operation * 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 * @param waitTimeout max time to wait until media information is transmitted
*/ */
public static void asyncGetMediaInformationExecute(final MediaInformationSession mediaInformationSession, final ExecutorService executorService, final int waitTimeout) { 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 * @param logCallback log callback or null to disable a previously defined callback
* callback
*/ */
public static void enableLogCallback(final LogCallback logCallback) { 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 * defined callback
*/ */
public static void enableStatisticsCallback(final StatisticsCallback statisticsCallback) { 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 * @param ffmpegSessionCompleteCallback complete callback or null to disable a
* defined callback * previously defined callback
*/ */
public static void enableExecuteCallback(final ExecuteCallback executeCallback) { public static void enableFFmpegSessionCompleteCallback(final FFmpegSessionCompleteCallback ffmpegSessionCompleteCallback) {
globalExecuteCallbackFunction = executeCallback; 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() { public static FFmpegSessionCompleteCallback getFFmpegSessionCompleteCallback() {
return globalExecuteCallbackFunction; 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 * <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 * @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) { 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)); android.util.Log.i(TAG, String.format("getSafParameter is not supported on API Level %d", Build.VERSION.SDK_INT));
return ""; return "";
@ -870,28 +972,23 @@ public class FFmpegKitConfig {
} }
} catch (final Throwable t) { } 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))); 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; final int safId = uniqueIdGenerator.getAndIncrement();
try { safIdMap.put(safId, new SAFProtocolUrl(safId, uri, openMode, context.getContentResolver()));
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)));
}
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 * <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. * <p>Requires API Level &ge; 19. On older API levels it returns an empty url.
* *
* @param context application context * @param context application context
* @param uri saf uri * @param uri SAF uri
* @return input url that can be passed to FFmpegKit or FFprobeKit * @return input url that can be passed to FFmpegKit or FFprobeKit
*/ */
public static String getSafParameterForRead(final Context context, final Uri uri) { 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 * <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. * <p>Requires API Level &ge; 19. On older API levels it returns an empty url.
* *
* @param context application context * @param context application context
* @param uri saf uri * @param uri SAF uri
* @return output url that can be passed to FFmpegKit or FFprobeKit * @return output url that can be passed to FFmpegKit or FFprobeKit
*/ */
public static String getSafParameterForWrite(final Context context, final Uri uri) { 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 { try {
ParcelFileDescriptor pfd = pfdMap.get(fd); SAFProtocolUrl safUrl = safIdMap.get(safId);
if (pfd != null) { if (safUrl != null) {
pfd.close(); final ParcelFileDescriptor parcelFileDescriptor = safUrl.getContentResolver().openFileDescriptor(safUrl.getUri(), safUrl.getOpenMode());
pfdMap.delete(fd); 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) { } 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() { public static void clearSessions() {
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
sessionHistoryList.clear(); sessionHistoryList.clear();
sessionHistoryMap.clear();
} }
} }
@ -1053,7 +1188,7 @@ public class FFmpegKitConfig {
* *
* @return all FFmpeg sessions in the session history * @return all FFmpeg sessions in the session history
*/ */
static List<FFmpegSession> getFFmpegSessions() { public static List<FFmpegSession> getFFmpegSessions() {
final LinkedList<FFmpegSession> list = new LinkedList<>(); final LinkedList<FFmpegSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
@ -1072,7 +1207,7 @@ public class FFmpegKitConfig {
* *
* @return all FFprobe sessions in the session history * @return all FFprobe sessions in the session history
*/ */
static List<FFprobeSession> getFFprobeSessions() { public static List<FFprobeSession> getFFprobeSessions() {
final LinkedList<FFprobeSession> list = new LinkedList<>(); final LinkedList<FFprobeSession> list = new LinkedList<>();
synchronized (sessionHistoryLock) { synchronized (sessionHistoryLock) {
@ -1086,6 +1221,25 @@ public class FFmpegKitConfig {
return list; 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. * <p>Returns sessions that have the given state.
* *
@ -1124,6 +1278,16 @@ public class FFmpegKitConfig {
FFmpegKitConfig.globalLogRedirectionStrategy = logRedirectionStrategy; 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. * <p>Parses the given command into arguments. Uses space character to split the arguments.
* Supports single and double quote characters. * Supports single and double quote characters.
@ -1265,7 +1429,7 @@ public class FFmpegKitConfig {
native static int nativeFFprobeExecute(final long sessionId, final String[] arguments); 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. * to complete and returns immediately.
* *
* @param sessionId id of the session * @param sessionId id of the session

@ -28,10 +28,15 @@ import java.util.List;
public class FFmpegSession extends AbstractSession implements Session { public class FFmpegSession extends AbstractSession implements Session {
/** /**
* Session specific statistics callback function. * Session specific statistics callback.
*/ */
private final StatisticsCallback statisticsCallback; private final StatisticsCallback statisticsCallback;
/**
* Session specific complete callback.
*/
private final FFmpegSessionCompleteCallback completeCallback;
/** /**
* Statistics entries received for this session. * Statistics entries received for this session.
*/ */
@ -54,44 +59,45 @@ public class FFmpegSession extends AbstractSession implements Session {
/** /**
* Builds a new FFmpeg session. * Builds a new FFmpeg session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback function * @param completeCallback session specific complete callback
*/ */
public FFmpegSession(final String[] arguments, final ExecuteCallback executeCallback) { public FFmpegSession(final String[] arguments, final FFmpegSessionCompleteCallback completeCallback) {
this(arguments, executeCallback, null, null); this(arguments, completeCallback, null, null);
} }
/** /**
* Builds a new FFmpeg session. * Builds a new FFmpeg session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback function * @param completeCallback session specific complete callback
* @param logCallback session specific log callback function * @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback function * @param statisticsCallback session specific statistics callback
*/ */
public FFmpegSession(final String[] arguments, public FFmpegSession(final String[] arguments,
final ExecuteCallback executeCallback, final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback) { final StatisticsCallback statisticsCallback) {
this(arguments, executeCallback, logCallback, statisticsCallback, FFmpegKitConfig.getLogRedirectionStrategy()); this(arguments, completeCallback, logCallback, statisticsCallback, FFmpegKitConfig.getLogRedirectionStrategy());
} }
/** /**
* Builds a new FFmpeg session. * Builds a new FFmpeg session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback function * @param completeCallback session specific complete callback
* @param logCallback session specific log callback function * @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback function * @param statisticsCallback session specific statistics callback
* @param logRedirectionStrategy session specific log redirection strategy * @param logRedirectionStrategy session specific log redirection strategy
*/ */
public FFmpegSession(final String[] arguments, public FFmpegSession(final String[] arguments,
final ExecuteCallback executeCallback, final FFmpegSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final StatisticsCallback statisticsCallback, final StatisticsCallback statisticsCallback,
final LogRedirectionStrategy logRedirectionStrategy) { final LogRedirectionStrategy logRedirectionStrategy) {
super(arguments, executeCallback, logCallback, logRedirectionStrategy); super(arguments, logCallback, logRedirectionStrategy);
this.completeCallback = completeCallback;
this.statisticsCallback = statisticsCallback; this.statisticsCallback = statisticsCallback;
this.statistics = new LinkedList<>(); 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() { public StatisticsCallback getStatisticsCallback() {
return statisticsCallback; 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 * 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. * 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 * @param statistics statistics entry
*/ */
@ -185,6 +201,11 @@ public class FFmpegSession extends AbstractSession implements Session {
return false; return false;
} }
@Override
public boolean isMediaInformation() {
return false;
}
@Override @Override
public String toString() { public String toString() {
final StringBuilder stringBuilder = new StringBuilder(); 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; import java.util.concurrent.ExecutorService;
/** /**
* <p>Main class to run <code>FFprobe</code> commands. Supports executing commands both synchronously and * <p>Main class to run <code>FFprobe</code> commands. Supports executing commands both
* asynchronously. * synchronously and asynchronously.
* <pre> * <pre>
* FFprobeSession session = FFprobeKit.execute("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4"); * FFprobeSession session = FFprobeKit.execute("-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4");
* *
* 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> * </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks. * <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre> * <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> * </pre>
* <p>It can extract media information for a file or a url, using {@link #getMediaInformation(String)} method. * <p>It can extract media information for a file or a url, using {@link #getMediaInformation(String)} method.
* <pre> * <pre>
@ -52,13 +52,23 @@ public class FFprobeKit {
private 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. * <p>Synchronously executes FFprobe with arguments provided.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe command options/arguments as string array
* @return FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession execute(final String[] arguments) { public static FFprobeSession executeWithArguments(final String[] arguments) {
final FFprobeSession session = new FFprobeSession(arguments); final FFprobeSession session = new FFprobeSession(arguments);
FFmpegKitConfig.ffprobeExecute(session); FFmpegKitConfig.ffprobeExecute(session);
@ -69,16 +79,17 @@ public class FFprobeKit {
/** /**
* <p>Starts an asynchronous FFprobe execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 arguments FFprobe 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
* @return FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String[] arguments, public static FFprobeSession executeWithArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback) { final FFprobeSessionCompleteCallback completeCallback) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback); final FFprobeSession session = new FFprobeSession(arguments, completeCallback);
FFmpegKitConfig.asyncFFprobeExecute(session); FFmpegKitConfig.asyncFFprobeExecute(session);
@ -88,18 +99,19 @@ public class FFprobeKit {
/** /**
* <p>Starts an asynchronous FFprobe execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @return FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String[] arguments, public static FFprobeSession executeWithArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback, final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback) { final LogCallback logCallback) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback); final FFprobeSession session = new FFprobeSession(arguments, completeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session); FFmpegKitConfig.asyncFFprobeExecute(session);
@ -109,18 +121,19 @@ public class FFprobeKit {
/** /**
* <p>Starts an asynchronous FFprobe execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 arguments FFprobe 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 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 FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String[] arguments, public static FFprobeSession executeWithArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback, final FFprobeSessionCompleteCallback completeCallback,
final ExecutorService executorService) { final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback); final FFprobeSession session = new FFprobeSession(arguments, completeCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService); FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
@ -130,20 +143,21 @@ public class FFprobeKit {
/** /**
* <p>Starts an asynchronous FFprobe execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @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 FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String[] arguments, public static FFprobeSession executeWithArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback, final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final ExecutorService executorService) { final ExecutorService executorService) {
final FFprobeSession session = new FFprobeSession(arguments, executeCallback, logCallback); final FFprobeSession session = new FFprobeSession(arguments, completeCallback, logCallback);
FFmpegKitConfig.asyncFFprobeExecute(session, executorService); FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
@ -159,59 +173,65 @@ public class FFprobeKit {
* @return FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession execute(final String command) { 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 * <p>Starts an asynchronous FFprobe execution for the given command. Space character is used
* into arguments. You can use single or double quote characters to specify arguments inside your command. * 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
* *
* @param command FFprobe command * @param command FFprobe 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
* @return FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String command, public static FFprobeSession executeAsync(final String command,
final ExecuteCallback executeCallback) { final FFprobeSessionCompleteCallback completeCallback) {
return executeAsync(FFmpegKitConfig.parseArguments(command), executeCallback); return executeWithArgumentsAsync(FFmpegKitConfig.parseArguments(command), completeCallback);
} }
/** /**
* <p>Starts an asynchronous FFprobe execution for the given command. Space character is used to split the command * <p>Starts an asynchronous FFprobe execution for the given command. Space character is used
* into arguments. You can use single or double quote characters to specify arguments inside your command. * 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
* *
* @param command FFprobe command * @param command FFprobe command
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @return FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String command, public static FFprobeSession executeAsync(final String command,
final ExecuteCallback executeCallback, final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback) { 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 * <p>Starts an asynchronous FFprobe execution for the given command. Space character is used
* into arguments. You can use single or double quote characters to specify arguments inside your command. * 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * You must use an {@link FFprobeSessionCompleteCallback} if you want to be notified about the
* result.
* *
* @param command FFprobe command * @param command FFprobe 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 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 FFprobe session created for this execution * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String command, public static FFprobeSession executeAsync(final String command,
final ExecuteCallback executeCallback, final FFprobeSessionCompleteCallback completeCallback,
final ExecutorService executorService) { 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); 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 * <p>Starts an asynchronous FFprobe execution for the given command. Space character is used
* into arguments. You can use single or double quote characters to specify arguments inside your command. * 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
* @param command FFprobe command * result.
* @param executeCallback callback that will be called when the execution is completed *
* @param logCallback callback that will receive logs * @param command FFprobe command
* @param executorService executor service that will be used to run this asynchronous operation * @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 * @return FFprobe session created for this execution
*/ */
public static FFprobeSession executeAsync(final String command, public static FFprobeSession executeAsync(final String command,
final ExecuteCallback executeCallback, final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final ExecutorService executorService) { 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); FFmpegKitConfig.asyncFFprobeExecute(session, executorService);
@ -249,7 +271,7 @@ public class FFprobeKit {
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformation(final String path) { public static MediaInformationSession getMediaInformation(final String path) {
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); 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, public static MediaInformationSession getMediaInformation(final String path,
final int waitTimeout) { 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); 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 path path or uri of a media file
* @param executeCallback callback that will be called when the execution is completed * @param completeCallback callback that will be called when the execution has completed
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationAsync(final String path, public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback) { final MediaInformationSessionCompleteCallback completeCallback) {
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, AbstractSession.DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT); 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 path path or uri of a media file
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @param waitTimeout max time to wait until media information is transmitted * @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationAsync(final String path, public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback, final MediaInformationSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final int waitTimeout) { 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); 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 path path or uri of a media file
* @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 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 media information session created for this execution * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationAsync(final String path, public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback, final MediaInformationSessionCompleteCallback completeCallback,
final ExecutorService executorService) { 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); 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>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
* @param path path or uri of a media file * about the result.
* @param executeCallback callback that will be notified when execution is completed *
* @param logCallback callback that will receive logs * @param path path or uri of a media file
* @param executorService executor service that will be used to run this asynchronous operation * @param completeCallback callback that will be notified when execution has completed
* @param waitTimeout max time to wait until media information is transmitted * @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 * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationAsync(final String path, public static MediaInformationSession getMediaInformationAsync(final String path,
final ExecuteCallback executeCallback, final MediaInformationSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final ExecutorService executorService, final ExecutorService executorService,
final int waitTimeout) { 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); 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 * @param command FFprobe command that prints media information for a file in JSON format
* @return media information session created for this execution * @return media information session created for this execution
@ -369,52 +399,57 @@ public class FFprobeKit {
public static MediaInformationSession getMediaInformationFromCommand(final String command) { public static MediaInformationSession getMediaInformationFromCommand(final String command) {
final MediaInformationSession session = new MediaInformationSession(FFmpegKitConfig.parseArguments(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; return session;
} }
/** /**
* <p>Starts an asynchronous FFprobe execution to extract media information using a command. The command passed to * <p>Starts an asynchronous FFprobe execution to extract media information using a command.
* this method must generate the output in JSON format in order to successfully extract media information from it. * 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. * <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
* @param command FFprobe command that prints media information for a file in JSON format * about the result.
* @param executeCallback callback that will be notified when execution is completed *
* @param logCallback callback that will receive logs * @param command FFprobe command that prints media information for a file in JSON
* @param waitTimeout max time to wait until media information is transmitted * 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 * @return media information session created for this execution
*/ */
public static MediaInformationSession getMediaInformationFromCommandAsync(final String command, public static MediaInformationSession getMediaInformationFromCommandAsync(final String command,
final ExecuteCallback executeCallback, final MediaInformationSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final int waitTimeout) { 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 * <p>Starts an asynchronous FFprobe execution to extract media information using command
* passed to this method must generate the output in JSON format in order to successfully extract media information * arguments. The command passed to this method must generate the output in JSON format in
* from it. * 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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* {@jlink ExecuteCallback} if you want to be notified about the result. * 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 executeCallback callback that will be notified when execution is completed * @param arguments FFprobe command arguments that print media information for a file in
* @param logCallback callback that will receive logs * JSON format
* @param waitTimeout max time to wait until media information is transmitted * @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 * @return media information session created for this execution
*/ */
private static MediaInformationSession getMediaInformationFromCommandArgumentsAsync(final String[] arguments, private static MediaInformationSession getMediaInformationFromCommandArgumentsAsync(final String[] arguments,
final ExecuteCallback executeCallback, final MediaInformationSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final int waitTimeout) { 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; return session;
} }
@ -424,8 +459,17 @@ public class FFprobeKit {
* *
* @return all FFprobe sessions in the session history * @return all FFprobe sessions in the session history
*/ */
public static List<FFprobeSession> listSessions() { public static List<FFprobeSession> listFFprobeSessions() {
return FFmpegKitConfig.getFFprobeSessions(); 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 { public class FFprobeSession extends AbstractSession implements Session {
/**
* Session specific complete callback.
*/
private final FFprobeSessionCompleteCallback completeCallback;
/** /**
* Builds a new FFprobe session. * Builds a new FFprobe session.
* *
@ -36,39 +41,50 @@ public class FFprobeSession extends AbstractSession implements Session {
/** /**
* Builds a new FFprobe session. * Builds a new FFprobe session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback function * @param completeCallback session specific complete callback
*/ */
public FFprobeSession(final String[] arguments, final ExecuteCallback executeCallback) { public FFprobeSession(final String[] arguments, final FFprobeSessionCompleteCallback completeCallback) {
this(arguments, executeCallback, null); this(arguments, completeCallback, null);
} }
/** /**
* Builds a new FFprobe session. * Builds a new FFprobe session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback function * @param completeCallback session specific complete callback
* @param logCallback session specific log callback function * @param logCallback session specific log callback
*/ */
public FFprobeSession(final String[] arguments, public FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback, final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback) { final LogCallback logCallback) {
this(arguments, executeCallback, logCallback, FFmpegKitConfig.getLogRedirectionStrategy()); this(arguments, completeCallback, logCallback, FFmpegKitConfig.getLogRedirectionStrategy());
} }
/** /**
* Builds a new FFprobe session. * Builds a new FFprobe session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback function * @param completeCallback session specific complete callback
* @param logCallback session specific log callback function * @param logCallback session specific log callback
* @param logRedirectionStrategy session specific log redirection strategy * @param logRedirectionStrategy session specific log redirection strategy
*/ */
public FFprobeSession(final String[] arguments, public FFprobeSession(final String[] arguments,
final ExecuteCallback executeCallback, final FFprobeSessionCompleteCallback completeCallback,
final LogCallback logCallback, final LogCallback logCallback,
final LogRedirectionStrategy logRedirectionStrategy) { 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 @Override
@ -81,6 +97,11 @@ public class FFprobeSession extends AbstractSession implements Session {
return true; return true;
} }
@Override
public boolean isMediaInformation() {
return false;
}
@Override @Override
public String toString() { public String toString() {
final StringBuilder stringBuilder = new StringBuilder(); 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; 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.jsonObject = jsonObject;
this.streams = streams; this.streams = streams;
this.chapters = chapters;
} }
/** /**
@ -135,6 +141,15 @@ public class MediaInformation {
return streams; return streams;
} }
/**
* Returns all chapters.
*
* @return list of chapters
*/
public List<Chapter> getChapters() {
return chapters;
}
/** /**
* Returns the media property associated with the key. * Returns the media property associated with the key.
* *

@ -34,6 +34,9 @@ import java.util.ArrayList;
*/ */
public class MediaInformationJsonParser { 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 * Extracts <code>MediaInformation</code> from the given FFprobe json output. Note that this
* method does not throw {@link JSONException} as {@link #fromWithError(String)} does and * method does not throw {@link JSONException} as {@link #fromWithError(String)} does and
@ -59,18 +62,27 @@ public class MediaInformationJsonParser {
* @throws JSONException if a parsing error occurs * @throws JSONException if a parsing error occurs
*/ */
public static MediaInformation fromWithError(final String ffprobeJsonOutput) throws JSONException { public static MediaInformation fromWithError(final String ffprobeJsonOutput) throws JSONException {
JSONObject jsonObject = new JSONObject(ffprobeJsonOutput); final JSONObject jsonObject = new JSONObject(ffprobeJsonOutput);
JSONArray streamArray = jsonObject.optJSONArray("streams"); 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++) { for (int i = 0; streamArray != null && i < streamArray.length(); i++) {
JSONObject streamObject = streamArray.optJSONObject(i); JSONObject streamObject = streamArray.optJSONObject(i);
if (streamObject != null) { 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 * <p>A custom FFprobe session, which produces a <code>MediaInformation</code> object using the
* FFprobe output. * FFprobe output.
*/ */
public class MediaInformationSession extends FFprobeSession implements Session { public class MediaInformationSession extends AbstractSession implements Session {
/** /**
* Media information extracted in the session. * Media information extracted in the session.
*/ */
private MediaInformation mediaInformation; private MediaInformation mediaInformation;
/**
* Session specific complete callback.
*/
private final MediaInformationSessionCompleteCallback completeCallback;
/** /**
* Creates a new media information session. * Creates a new media information session.
* *
@ -42,22 +47,24 @@ public class MediaInformationSession extends FFprobeSession implements Session {
/** /**
* Creates a new media information session. * Creates a new media information session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback function * @param completeCallback session specific complete callback
*/ */
public MediaInformationSession(final String[] arguments, final ExecuteCallback executeCallback) { public MediaInformationSession(final String[] arguments, final MediaInformationSessionCompleteCallback completeCallback) {
this(arguments, executeCallback, null); this(arguments, completeCallback, null);
} }
/** /**
* Creates a new media information session. * Creates a new media information session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback function * @param completeCallback session specific complete callback
* @param logCallback session specific log callback function * @param logCallback session specific log callback
*/ */
public MediaInformationSession(final String[] arguments, final ExecuteCallback executeCallback, final LogCallback logCallback) { public MediaInformationSession(final String[] arguments, final MediaInformationSessionCompleteCallback completeCallback, final LogCallback logCallback) {
super(arguments, executeCallback, logCallback, LogRedirectionStrategy.NEVER_PRINT_LOGS); super(arguments, logCallback, LogRedirectionStrategy.NEVER_PRINT_LOGS);
this.completeCallback = completeCallback;
} }
/** /**
@ -79,6 +86,30 @@ public class MediaInformationSession extends FFprobeSession implements Session {
this.mediaInformation = mediaInformation; 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 @Override
public String toString() { public String toString() {
final StringBuilder stringBuilder = new StringBuilder(); 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.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale;
/** /**
* <p>Responsible of loading native libraries. * <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[] 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() { static boolean isTestModeDisabled() {
return (System.getProperty("enable.ffmpeg.kit.test.mode") == null); return (System.getProperty("enable.ffmpeg.kit.test.mode") == null);
} }
@ -82,7 +85,7 @@ public class NativeLoader {
} }
static String loadVersion() { static String loadVersion() {
final String version = "4.5"; final String version = "4.5.1";
if (isTestModeDisabled()) { if (isTestModeDisabled()) {
return FFmpegKitConfig.getVersion(); return FFmpegKitConfig.getVersion();
@ -113,7 +116,7 @@ public class NativeLoader {
if (isTestModeDisabled()) { if (isTestModeDisabled()) {
return FFmpegKitConfig.getBuildDate(); return FFmpegKitConfig.getBuildDate();
} else { } 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 */ /* LOADING LINKED LIBRARIES MANUALLY ON API < 21 */
final List<String> externalLibrariesEnabled = loadExternalLibraries(); final List<String> externalLibrariesEnabled = loadExternalLibraries();
if (externalLibrariesEnabled.contains("tesseract") || externalLibrariesEnabled.contains("x265") || externalLibrariesEnabled.contains("snappy") || externalLibrariesEnabled.contains("openh264") || externalLibrariesEnabled.contains("rubberband")) { for (String dependantLibrary : LIBRARIES_LINKED_WITH_CXX) {
loadLibrary("c++_shared"); if (externalLibrariesEnabled.contains(dependantLibrary)) {
loadLibrary("c++_shared");
break;
}
} }
if (AbiDetect.ARM_V7A.equals(loadNativeAbi())) { if (AbiDetect.ARM_V7A.equals(loadNativeAbi())) {

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

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

@ -29,16 +29,9 @@ import java.util.concurrent.Future;
public interface Session { public interface Session {
/** /**
* Returns the session specific execute callback function. * Returns the session specific log callback.
* *
* @return session specific execute callback function * @return session specific log callback
*/
ExecuteCallback getExecuteCallback();
/**
* Returns the session specific log callback function.
*
* @return session specific log callback function
*/ */
LogCallback getLogCallback(); LogCallback getLogCallback();
@ -198,6 +191,9 @@ public interface Session {
/** /**
* Adds a new log entry for this 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 * @param log log entry
*/ */
@ -224,6 +220,13 @@ public interface Session {
*/ */
boolean isFFprobe(); 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. * Cancels running the session.
*/ */

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

@ -72,6 +72,85 @@ public class FFmpegKitTest {
" }\n" + " }\n" +
" }\n" + " }\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" + " \"format\": {\n" +
" \"filename\": \"sample.mp3\",\n" + " \"filename\": \"sample.mp3\",\n" +
" \"nb_streams\": 1,\n" + " \"nb_streams\": 1,\n" +
@ -459,6 +538,11 @@ public class FFmpegKitTest {
Assert.assertNotNull(mediaInformation.getStreams()); Assert.assertNotNull(mediaInformation.getStreams());
Assert.assertEquals(1, mediaInformation.getStreams().size()); Assert.assertEquals(1, mediaInformation.getStreams().size());
assertAudioStream(mediaInformation.getStreams().get(0), 0L, "mp3", "MP3 (MPEG audio layer 3)", "44100", "stereo", "fltp", "320000"); 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 @Test
@ -743,4 +827,18 @@ public class FFmpegKitTest {
Assert.assertEquals(codecTimeBase, streamInformation.getCodecTimeBase()); 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() { public void constructorTest() {
FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS); FFmpegSession ffmpegSession = new FFmpegSession(TEST_ARGUMENTS);
// 1. getExecuteCallback // 1. getCompleteCallback
Assert.assertNull(ffmpegSession.getExecuteCallback()); Assert.assertNull(ffmpegSession.getCompleteCallback());
// 2. getLogCallback // 2. getLogCallback
Assert.assertNull(ffmpegSession.getLogCallback()); Assert.assertNull(ffmpegSession.getLogCallback());
@ -93,17 +93,17 @@ public class FFmpegSessionTest {
@Test @Test
public void constructorTest2() { public void constructorTest2() {
ExecuteCallback executeCallback = new ExecuteCallback() { FFmpegSessionCompleteCallback completeCallback = new FFmpegSessionCompleteCallback() {
@Override @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 // 1. getCompleteCallback
Assert.assertEquals(ffmpegSession.getExecuteCallback(), executeCallback); Assert.assertEquals(ffmpegSession.getCompleteCallback(), completeCallback);
// 2. getLogCallback // 2. getLogCallback
Assert.assertNull(ffmpegSession.getLogCallback()); Assert.assertNull(ffmpegSession.getLogCallback());
@ -163,10 +163,10 @@ public class FFmpegSessionTest {
@Test @Test
public void constructorTest3() { public void constructorTest3() {
ExecuteCallback executeCallback = new ExecuteCallback() { FFmpegSessionCompleteCallback completeCallback = new FFmpegSessionCompleteCallback() {
@Override @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 // 1. getCompleteCallback
Assert.assertEquals(ffmpegSession.getExecuteCallback(), executeCallback); Assert.assertEquals(ffmpegSession.getCompleteCallback(), completeCallback);
// 2. getLogCallback // 2. getLogCallback
Assert.assertEquals(ffmpegSession.getLogCallback(), logCallback); Assert.assertEquals(ffmpegSession.getLogCallback(), logCallback);

@ -32,8 +32,8 @@ public class FFprobeSessionTest {
public void constructorTest() { public void constructorTest() {
FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS); FFprobeSession ffprobeSession = new FFprobeSession(TEST_ARGUMENTS);
// 1. getExecuteCallback // 1. getCompleteCallback
Assert.assertNull(ffprobeSession.getExecuteCallback()); Assert.assertNull(ffprobeSession.getCompleteCallback());
// 2. getLogCallback // 2. getLogCallback
Assert.assertNull(ffprobeSession.getLogCallback()); Assert.assertNull(ffprobeSession.getLogCallback());
@ -90,17 +90,17 @@ public class FFprobeSessionTest {
@Test @Test
public void constructorTest2() { public void constructorTest2() {
ExecuteCallback executeCallback = new ExecuteCallback() { FFprobeSessionCompleteCallback completeCallback = new FFprobeSessionCompleteCallback() {
@Override @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 // 1. getCompleteCallback
Assert.assertEquals(ffprobeSession.getExecuteCallback(), executeCallback); Assert.assertEquals(ffprobeSession.getCompleteCallback(), completeCallback);
// 2. getLogCallback // 2. getLogCallback
Assert.assertNull(ffprobeSession.getLogCallback()); Assert.assertNull(ffprobeSession.getLogCallback());
@ -157,10 +157,10 @@ public class FFprobeSessionTest {
@Test @Test
public void constructorTest3() { public void constructorTest3() {
ExecuteCallback executeCallback = new ExecuteCallback() { FFprobeSessionCompleteCallback completeCallback = new FFprobeSessionCompleteCallback() {
@Override @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 // 1. getCompleteCallback
Assert.assertEquals(ffprobeSession.getExecuteCallback(), executeCallback); Assert.assertEquals(ffprobeSession.getCompleteCallback(), completeCallback);
// 2. getLogCallback // 2. getLogCallback
Assert.assertEquals(ffprobeSession.getLogCallback(), logCallback); Assert.assertEquals(ffprobeSession.getLogCallback(), logCallback);

@ -12,14 +12,11 @@ enable_default_architecture_variants() {
display_help() { display_help() {
COMMAND=$(echo "$0" | sed -e 's/\.\///g') 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, \ 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 \ iphonesimulator, mac-catalyst, appletvos, appletvsimulator, macosx) as input and builds an umbrella xcframework under \
the prebuilt folder.\n\n\ the prebuilt folder.\n\nPlease note that this script is only responsible of packaging existing frameworks, created by \
Additional options can be specified to disable architectures or to build xcframeworks for external libraries as well.\ 'ios.sh', 'tvos.sh' and 'macos.sh'. Running it will not compile any of these libraries again. Top level build scripts \
\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 \
('ios.sh', 'tvos.sh', 'macos.sh') must be used to build ffmpeg with support for a specific external library first. \ ('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" After that this script should be used to create an umbrella xcframework.\n"
echo -e "Usage: ./$COMMAND [OPTION]...\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 " -h, --help\t\t\tdisplay this help and exit"
echo -e " -v, --version\t\t\tdisplay version information and exit" echo -e " -v, --version\t\t\tdisplay version information and exit"
echo -e " -f, --force\t\t\tignore warnings" 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 " -l, --lts\t\t\tinclude lts packages to support iOS 10+, tvOS 10+, macOS 10.12+ devices\n"
echo -e "Licensing options:"
echo -e " --enable-gpl\t\t\tallow building umbrella xcframeworks for GPL libraries[no]\n"
echo -e "Architectures:" echo -e "Architectures:"
echo -e " --disable-iphoneos\t\tdo not include iphoneos architecture variant [yes]" 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-appletvos\t\tdo not include appletvos architecture variant [yes]"
echo -e " --disable-appletvsimulator\tdo not include appletvsimulator 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 " --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() { initialize_prebuilt_umbrella_xcframework_folders() {
@ -219,17 +175,6 @@ while [ ! $# -eq 0 ]; do
-f | --force) -f | --force)
export BUILD_FORCE="1" 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-*) --disable-*)
DISABLED_ARCH_VARIANT=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g') DISABLED_ARCH_VARIANT=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
@ -242,19 +187,6 @@ while [ ! $# -eq 0 ]; do
shift shift
done 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 HELP DISPLAYED EXIT
if [[ -n ${DISPLAY_HELP} ]]; then if [[ -n ${DISPLAY_HELP} ]]; then
display_help display_help
@ -271,19 +203,6 @@ print_enabled_xcframeworks
echo "" 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 # THIS WILL SAVE ARCHITECTURE VARIANTS TO BE INCLUDED
TARGET_ARCHITECTURE_VARIANT_INDEX_ARRAY=() TARGET_ARCHITECTURE_VARIANT_INDEX_ARRAY=()
@ -309,45 +228,6 @@ if [[ -n ${TARGET_ARCHITECTURE_VARIANT_INDEX_ARRAY[0]} ]]; then
# INITIALIZE TARGET FOLDERS # INITIALIZE TARGET FOLDERS
initialize_prebuilt_umbrella_xcframework_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 for FFMPEG_LIB in "${FFMPEG_LIBS[@]}"; do
create_umbrella_xcframework "${FFMPEG_LIB}" create_umbrella_xcframework "${FFMPEG_LIB}"
done done

2
apple/.gitignore vendored

@ -2,9 +2,11 @@
/Makefile /Makefile
/config.status /config.status
/configure.tmp /configure.tmp
/configure~
/.deps/ /.deps/
/.libs/ /.libs/
*.trs *.trs
/unittests /unittests
/test-driver /test-driver
/config.log /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 # could be handy for archiving the generated documentation or if some version
# control system is used. # 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 # 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 # 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@ # @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 # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -154,12 +154,9 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \ unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
CSCOPE = cscope
DIST_SUBDIRS = $(SUBDIRS) DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in ar-lib compile config.guess \ am__DIST_COMMON = $(srcdir)/Makefile.in README.md ar-lib compile \
config.sub install-sh ltmain.sh missing config.guess config.sub install-sh ltmain.sh missing
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION) distdir = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir) top_distdir = $(distdir)
@ -215,8 +212,9 @@ AWK = @AWK@
CC = @CC@ CC = @CC@
CCDEPMODE = @CCDEPMODE@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -227,8 +225,9 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FFMPEG_LIBS = @FFMPEG_LIBS@ FFMPEG_FRAMEWORKS = @FFMPEG_FRAMEWORKS@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
@ -317,6 +316,7 @@ pdfdir = @pdfdir@
prefix = @prefix@ prefix = @prefix@
program_transform_name = @program_transform_name@ program_transform_name = @program_transform_name@
psdir = @psdir@ psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@ srcdir = @srcdir@
@ -478,7 +478,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags: distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-rm -f cscope.out cscope.in.out cscope.po.out cscope.files -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am

@ -2,36 +2,36 @@
### 1. Features ### 1. Features
#### 1.1 iOS #### 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 - Includes `armv7`, `armv7s`, `arm64`, `arm64-simulator`, `arm64e`, `i386`, `x86_64`, `x86_64-mac-catalyst` and
`arm64-mac-catalyst` architectures `arm64-mac-catalyst` architectures
- Objective-C API - Objective-C API
- Camera access - Camera access
- `ARC` enabled library - `ARC` enabled library
- Built with `-fembed-bitcode` flag - Built with `-fembed-bitcode` flag
- Creates static `frameworks`, static `xcframeworks` and static `universal (fat)` libraries (.a) - Creates shared `frameworks` and `xcframeworks`
#### 1.2 macOS #### 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 - Includes `arm64` and `x86_64` architectures
- Objective-C API - Objective-C API
- Camera access - Camera access
- `ARC` enabled library - `ARC` enabled library
- Built with `-fembed-bitcode` flag - Built with `-fembed-bitcode` flag
- Creates static `frameworks`, static `xcframeworks` and static `universal (fat)` libraries (.a) - Creates shared `frameworks` and `xcframeworks`
#### 1.3 tvOS #### 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 - Includes `arm64`, `arm64-simulator` and `x86_64` architectures
- Objective-C API - Objective-C API
- `ARC` enabled library - `ARC` enabled library
- Built with `-fembed-bitcode` flag - Built with `-fembed-bitcode` flag
- Creates static `frameworks`, static `xcframeworks` and static `universal (fat)` libraries (.a) - Creates shared `frameworks` and `xcframeworks`
### 2. Building ### 2. Building
Run `ios.sh`/`macos.sh`/`tvos.sh` at project root directory to build `ffmpeg-kit` and `ffmpeg` static libraries for a Run `ios.sh`/`macos.sh`/`tvos.sh` inside the project root to build `ffmpeg-kit` and `ffmpeg` shared libraries
platform. for a platform.
Optionally, use `apple.sh` to combine bundles created by these three scripts in a single bundle. 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 ##### 2.1.1 iOS
- **Xcode 7.3.1** or later - **Xcode 8.0** or later
- **iOS SDK 9.3** or later - **iOS SDK 10** or later
- **Command Line Tools** - **Command Line Tools**
##### 2.1.2 macOS ##### 2.1.2 macOS
- **Xcode 7.3.1** or later - **Xcode 8.0** or later
- **macOS SDK 10.11** or later - **macOS SDK 10.12** or later
- **Command Line Tools** - **Command Line Tools**
##### 2.1.3 tvOS ##### 2.1.3 tvOS
- **Xcode 7.3.1** or later - **Xcode 8.0** or later
- **tvOS SDK 9.2** or later - **tvOS SDK 10.0** or later
- **Command Line Tools** - **Command Line Tools**
##### 2.1.4 Packages ##### 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. - `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 `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` `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 `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` `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 `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` `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 ### 3. Using
@ -114,17 +111,17 @@ All libraries created can be found under the `prebuilt` directory.
- iOS - iOS
```yaml ```yaml
pod 'ffmpeg-kit-ios-full', '~> 4.5' pod 'ffmpeg-kit-ios-full', '~> 4.5.1'
``` ```
- macOS - macOS
```yaml ```yaml
pod 'ffmpeg-kit-macos-full', '~> 4.5' pod 'ffmpeg-kit-macos-full', '~> 4.5.1'
``` ```
- tvOS - tvOS
```yaml ```yaml
pod 'ffmpeg-kit-tvos-full', '~> 4.5' pod 'ffmpeg-kit-tvos-full', '~> 4.5.1'
``` ```
2. Execute synchronous `FFmpeg` commands. 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. 4. Execute asynchronous `FFmpeg` commands by providing session specific `execute`/`log`/`session` callbacks.
```objectivec ```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]; SessionState state = [session getState];
ReturnCode *returnCode = [session getReturnCode]; ReturnCode *returnCode = [session getReturnCode];
@ -225,7 +222,7 @@ All libraries created can be found under the `prebuilt` directory.
- Asynchronous - Asynchronous
```objectivec ```objectivec
[FFprobeKit executeAsync:ffmpegCommand withExecuteCallback:^(id<Session> session) { [FFprobeKit executeAsync:ffmpegCommand withCompleteCallback:^(FFprobeSession* session) {
CALLED WHEN SESSION IS EXECUTED CALLED WHEN SESSION IS EXECUTED
@ -268,10 +265,18 @@ All libraries created can be found under the `prebuilt` directory.
9. Enable global callbacks. 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 ```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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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_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_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
[m4_warning([this file was generated for autoconf 2.69. [m4_warning([this file was generated for autoconf 2.71.
You have another version of autoconf. It may work, but is not guaranteed to. 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. 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'.])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -35,7 +35,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.16' [am__api_version='1.16'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro. dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.16.3], [], m4_if([$1], [1.16.5], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
]) ])
@ -51,12 +51,12 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.16.3])dnl [AM_AUTOMAKE_VERSION([1.16.5])dnl
m4_ifndef([AC_AUTOCONF_VERSION], m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -118,7 +118,7 @@ AC_SUBST([AR])dnl
# AM_AUX_DIR_EXPAND -*- Autoconf -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -170,7 +170,7 @@ am_aux_dir=`cd "$ac_aux_dir" && pwd`
# AM_CONDITIONAL -*- Autoconf -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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.]]) Usually this means the macro was only invoked conditionally.]])
fi])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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. # release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE], AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.65])dnl [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 Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about. dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl 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 [_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if( 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],, [ok:ok],,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
@ -576,6 +580,20 @@ AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
[m4_define([AC_PROG_OBJCXX], [m4_define([AC_PROG_OBJCXX],
m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl 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 AC_REQUIRE([AM_SILENT_RULES])dnl
dnl The testsuite driver may need to know about EXEEXT, so add the dnl The testsuite driver may need to know about EXEEXT, so add the
dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
@ -657,7 +675,7 @@ for _am_header in $config_headers :; do
done done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -678,7 +696,7 @@ if test x"${install_sh+set}" != xset; then
fi fi
AC_SUBST([install_sh])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -812,7 +830,7 @@ fi
# Helper functions for option handling. -*- Autoconf -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -841,7 +859,7 @@ AC_DEFUN([_AM_SET_OPTIONS],
AC_DEFUN([_AM_IF_OPTION], AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) [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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -888,7 +906,7 @@ AC_LANG_POP([C])])
# For backward compatibility. # For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -988,7 +1006,7 @@ AC_CONFIG_COMMANDS_PRE(
rm -f conftest.file 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1048,7 +1066,7 @@ AC_SUBST([AM_BACKSLASH])dnl
_AM_SUBST_NOTMAKE([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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -1076,7 +1094,7 @@ fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])]) 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # 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 -*- # 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 # This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,

@ -4,7 +4,7 @@
me=ar-lib me=ar-lib
scriptversion=2019-07-04.01; # UTC 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>. # Written by Peter Rosin <peda@lysator.liu.se>.
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC 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>. # Written by Tom Tromey <tromey@cygnus.com>.
# #
# This program is free software; you can redistribute it and/or modify # 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 #! /bin/sh
# Configuration validation subroutine script. # 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 # This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by # under the terms of the GNU General Public License as published by
@ -33,7 +35,7 @@ timestamp='2020-08-17'
# Otherwise, we print the canonical config type on stdout and succeed. # Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from: # You can get the latest version of this script from:
# https://git.savannah.gnu.org/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 # This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases # and recognize all the CPU types, system types and aliases
@ -50,6 +52,13 @@ timestamp='2020-08-17'
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification. # It is wrong to echo any other type of specification.
# 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,.*/,,'` me=`echo "$0" | sed -e 's,.*/,,'`
usage="\ usage="\
@ -67,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\ version="\
GNU config.sub ($timestamp) 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 This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@ -112,9 +121,11 @@ esac
# Split fields of configuration type # Split fields of configuration type
# shellcheck disable=SC2162 # shellcheck disable=SC2162
saved_IFS=$IFS
IFS="-" read field1 field2 field3 field4 <<EOF IFS="-" read field1 field2 field3 field4 <<EOF
$1 $1
EOF EOF
IFS=$saved_IFS
# Separate into logical components for further validation # Separate into logical components for further validation
case $1 in case $1 in
@ -163,6 +174,10 @@ case $1 in
basic_machine=$field1 basic_machine=$field1
basic_os=$field2 basic_os=$field2
;; ;;
zephyr*)
basic_machine=$field1-unknown
basic_os=$field2
;;
# Manufacturers # Manufacturers
dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
@ -922,9 +937,11 @@ case $basic_machine in
*-*) *-*)
# shellcheck disable=SC2162 # shellcheck disable=SC2162
saved_IFS=$IFS
IFS="-" read cpu vendor <<EOF IFS="-" read cpu vendor <<EOF
$basic_machine $basic_machine
EOF EOF
IFS=$saved_IFS
;; ;;
# We use `pc' rather than `unknown' # We use `pc' rather than `unknown'
# because (1) that's what they normally are, and # because (1) that's what they normally are, and
@ -1165,7 +1182,7 @@ case $cpu-$vendor in
| alphapca5[67] | alpha64pca5[67] \ | alphapca5[67] | alpha64pca5[67] \
| am33_2.0 \ | am33_2.0 \
| amdgcn \ | amdgcn \
| arc | arceb \ | arc | arceb | arc32 | arc64 \
| arm | arm[lb]e | arme[lb] | armv* \ | arm | arm[lb]e | arme[lb] | armv* \
| avr | avr32 \ | avr | avr32 \
| asmjs \ | asmjs \
@ -1185,6 +1202,7 @@ case $cpu-$vendor in
| k1om \ | k1om \
| le32 | le64 \ | le32 | le64 \
| lm32 \ | lm32 \
| loongarch32 | loongarch64 | loongarchx32 \
| m32c | m32r | m32rle \ | m32c | m32r | m32rle \
| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
@ -1203,9 +1221,13 @@ case $cpu-$vendor in
| mips64vr5900 | mips64vr5900el \ | mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \ | mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \ | mipsisa32r2 | mipsisa32r2el \
| mipsisa32r3 | mipsisa32r3el \
| mipsisa32r5 | mipsisa32r5el \
| mipsisa32r6 | mipsisa32r6el \ | mipsisa32r6 | mipsisa32r6el \
| mipsisa64 | mipsisa64el \ | mipsisa64 | mipsisa64el \
| mipsisa64r2 | mipsisa64r2el \ | mipsisa64r2 | mipsisa64r2el \
| mipsisa64r3 | mipsisa64r3el \
| mipsisa64r5 | mipsisa64r5el \
| mipsisa64r6 | mipsisa64r6el \ | mipsisa64r6 | mipsisa64r6el \
| mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \ | mipsisa64sr71k | mipsisa64sr71kel \
@ -1229,7 +1251,7 @@ case $cpu-$vendor in
| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
| pru \ | pru \
| pyramid \ | pyramid \
| riscv | riscv32 | riscv64 \ | riscv | riscv32 | riscv32be | riscv64 | riscv64be \
| rl78 | romp | rs6000 | rx \ | rl78 | romp | rs6000 | rx \
| s390 | s390x \ | s390 | s390x \
| score \ | score \
@ -1241,6 +1263,7 @@ case $cpu-$vendor in
| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
| spu \ | spu \
| tahoe \ | tahoe \
| thumbv7* \
| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
| tron \ | tron \
| ubicom32 \ | ubicom32 \
@ -1286,26 +1309,32 @@ then
case $basic_os in case $basic_os in
gnu/linux*) gnu/linux*)
kernel=linux kernel=linux
os=`echo $basic_os | sed -e 's|gnu/linux|gnu|'` os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
;;
os2-emx)
kernel=os2
os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
;; ;;
nto-qnx*) nto-qnx*)
kernel=nto kernel=nto
os=`echo $basic_os | sed -e 's|nto-qnx|qnx|'` os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
;; ;;
*-*) *-*)
# shellcheck disable=SC2162 # shellcheck disable=SC2162
saved_IFS=$IFS
IFS="-" read kernel os <<EOF IFS="-" read kernel os <<EOF
$basic_os $basic_os
EOF EOF
IFS=$saved_IFS
;; ;;
# Default OS when just kernel was specified # Default OS when just kernel was specified
nto*) nto*)
kernel=nto kernel=nto
os=`echo $basic_os | sed -e 's|nto|qnx|'` os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
;; ;;
linux*) linux*)
kernel=linux kernel=linux
os=`echo $basic_os | sed -e 's|linux|gnu|'` os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
;; ;;
*) *)
kernel= kernel=
@ -1326,7 +1355,7 @@ case $os in
os=cnk os=cnk
;; ;;
solaris1 | solaris1.*) solaris1 | solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'` os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
;; ;;
solaris) solaris)
os=solaris2 os=solaris2
@ -1355,7 +1384,7 @@ case $os in
os=sco3.2v4 os=sco3.2v4
;; ;;
sco3.2.[4-9]*) sco3.2.[4-9]*)
os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
;; ;;
sco*v* | scout) sco*v* | scout)
# Don't match below # Don't match below
@ -1367,13 +1396,7 @@ case $os in
os=psos os=psos
;; ;;
qnx*) qnx*)
case $cpu in os=qnx
x86 | i*86)
;;
*)
os=nto-$os
;;
esac
;; ;;
hiux*) hiux*)
os=hiuxwe2 os=hiuxwe2
@ -1437,7 +1460,7 @@ case $os in
;; ;;
# Preserve the version number of sinix5. # Preserve the version number of sinix5.
sinix5.*) sinix5.*)
os=`echo $os | sed -e 's|sinix|sysv|'` os=`echo "$os" | sed -e 's|sinix|sysv|'`
;; ;;
sinix*) sinix*)
os=sysv4 os=sysv4
@ -1683,11 +1706,14 @@ fi
# Now, validate our (potentially fixed-up) OS. # Now, validate our (potentially fixed-up) OS.
case $os in case $os in
# Sometimes we do "kernel-abi", so those need to count as OSes. # Sometimes we do "kernel-libc", so those need to count as OSes.
musl* | newlib* | uclibc*) musl* | newlib* | relibc* | uclibc*)
;;
# Likewise for "kernel-abi"
eabi* | gnueabi*)
;; ;;
# Likewise for "kernel-libc" # VxWorks passes extra cpu info in the 4th filed.
eabi | eabihf | gnueabi | gnueabihf) simlinux | simwindows | spe)
;; ;;
# Now accept the basic system types. # Now accept the basic system types.
# The portable systems comes first. # The portable systems comes first.
@ -1704,12 +1730,12 @@ case $os in
| nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
| clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
| mirbsd* | netbsd* | dicos* | openedition* | ose* \ | mirbsd* | netbsd* | dicos* | openedition* | ose* \
| bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
| ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
| bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
| ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
| udi* | lites* | ieee* | go32* | aux* | hcos* \ | udi* | lites* | ieee* | go32* | aux* | hcos* \
| chorusrdb* | cegcc* | glidix* \ | chorusrdb* | cegcc* | glidix* | serenity* \
| cygwin* | msys* | pe* | moss* | proelf* | rtems* \ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
| midipix* | mingw32* | mingw64* | mint* \ | midipix* | mingw32* | mingw64* | mint* \
| uxpv* | beos* | mpeix* | udk* | moxiebox* \ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
@ -1722,7 +1748,7 @@ case $os in
| skyos* | haiku* | rdos* | toppers* | drops* | es* \ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* ) | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*)
;; ;;
# This one is extra strict with allowed versions # This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*) sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
@ -1739,9 +1765,12 @@ esac
# As a final step for OS-related things, validate the OS-kernel combination # As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel. # (given a valid OS), if there is a kernel.
case $kernel-$os in case $kernel-$os in
linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
| linux-musl* | linux-relibc* | linux-uclibc* )
;; ;;
-dietlibc* | -newlib* | -musl* | -uclibc* ) uclinux-uclibc* )
;;
-dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
# These are just libc implementations, not actual OSes, and thus # These are just libc implementations, not actual OSes, and thus
# require a kernel. # require a kernel.
echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
@ -1749,8 +1778,12 @@ case $kernel-$os in
;; ;;
kfreebsd*-gnu* | kopensolaris*-gnu*) kfreebsd*-gnu* | kopensolaris*-gnu*)
;; ;;
vxworks-simlinux | vxworks-simwindows | vxworks-spe)
;;
nto-qnx*) nto-qnx*)
;; ;;
os2-emx)
;;
*-eabi* | *-gnueabi*) *-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_INIT([ffmpeg-kit], [4.5.1], [https://github.com/tanersener/ffmpeg-kit/issues/new])
AC_CONFIG_SRCDIR([src/FFmpegKit.m])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([src/FFmpegKit.m])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
@ -24,8 +24,8 @@ AM_PROG_AR
AC_PROG_OBJC AC_PROG_OBJC
CFLAGS="$cflags_bckup" CFLAGS="$cflags_bckup"
FFMPEG_LIBS="-lavcodec -lavfilter -lavformat -lavutil -lswscale -lswresample" FFMPEG_FRAMEWORKS="-framework libavcodec -framework libavfilter -framework libavformat -framework libavutil -framework libswscale -framework libswresample"
AC_SUBST(FFMPEG_LIBS) AC_SUBST(FFMPEG_FRAMEWORKS)
LT_INIT LT_INIT
@ -58,7 +58,6 @@ AC_TYPE_UINT8_T
# Checks for library functions. # Checks for library functions.
AC_CHECK_FUNCS([dup2 floor memmove memset select strchr strcspn strerror strrchr strstr strtol malloc strcpy strlen vsnprintf]) AC_CHECK_FUNCS([dup2 floor memmove memset select strchr strcspn strerror strrchr strstr strtol malloc strcpy strlen vsnprintf])
AC_CONFIG_FILES([Makefile AC_CONFIG_FILES([Makefile src/Makefile])
src/Makefile])
AC_OUTPUT AC_OUTPUT

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC 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 # 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 # it under the terms of the GNU General Public License as published by

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Generated automatically by config.status (ffmpeg-kit) 4.4 # Generated automatically by config.status (ffmpeg-kit) 4.5
# Libtool was configured on host mera.local: # Libtool was configured on host MiRA.local:
# NOTE: Changes made to this file will be lost: look at ltmain.sh. # NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services. # Provide generalized library-building support services.
@ -42,10 +42,10 @@ macro_version=2.4.6
macro_revision=2.4.6 macro_revision=2.4.6
# Whether or not to build shared libraries. # Whether or not to build shared libraries.
build_libtool_libs=no build_libtool_libs=yes
# Whether or not to build static libraries. # Whether or not to build static libraries.
build_old_libs=yes build_old_libs=no
# What type of objects to build. # What type of objects to build.
pic_mode=yes pic_mode=yes
@ -66,14 +66,14 @@ ECHO="printf %s\\n"
PATH_SEPARATOR=":" PATH_SEPARATOR=":"
# The host system. # The host system.
host_alias=x86_64-ios-darwin host_alias=arm64-ios-darwin
host=x86_64-ios-darwin host=aarch64-ios-darwin
host_os=darwin host_os=darwin
# The build system. # The build system.
build_alias= build_alias=
build=x86_64-apple-darwin18.5.0 build=aarch64-apple-darwin20.6.0
build_os=darwin18.5.0 build_os=darwin20.6.0
# A sed program that does not truncate output. # A sed program that does not truncate output.
SED="/usr/bin/sed" SED="/usr/bin/sed"
@ -91,13 +91,13 @@ EGREP="/usr/bin/grep -E"
FGREP="/usr/bin/grep -F" FGREP="/usr/bin/grep -F"
# A BSD- or MS-compatible name lister. # 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. # Whether we need soft or hard links.
LN_S="ln -s" LN_S="ln -s"
# What is the maximum length of a command? # What is the maximum length of a command?
max_cmd_len=196608 max_cmd_len=786432
# Object file suffix (normally "o"). # Object file suffix (normally "o").
objext=o objext=o
@ -136,25 +136,25 @@ file_magic_glob=""
want_nocaseglob="no" want_nocaseglob="no"
# DLL creation program. # DLL creation program.
DLLTOOL="dlltool" DLLTOOL="false"
# Command to associate shared and link libraries. # Command to associate shared and link libraries.
sharedlib_from_linklib_cmd="printf %s\\n" sharedlib_from_linklib_cmd="printf %s\\n"
# The archiver. # The archiver.
AR="ar" AR="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar"
# Flags to create an archive. # Flags to create an archive.
AR_FLAGS="cru" AR_FLAGS="cru"
# How to feed a file listing to the archiver. # How to feed a file listing to the archiver.
archiver_list_spec="@" archiver_list_spec=""
# A symbol stripping program. # 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. # 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_postinstall_cmds="chmod 644 \$oldlib~\$RANLIB \$tool_oldlib"
old_postuninstall_cmds="" old_postuninstall_cmds=""
@ -165,22 +165,22 @@ lock_old_archive_extraction=yes
LTCC="clang" LTCC="clang"
# LTCC compiler flags. # 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. # 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. # 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. # Transform the output of nm into a list of symbols to manually relocate.
global_symbol_to_import="" global_symbol_to_import=""
# Transform the output of nm in a C name address pair. # 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. # 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. # The name lister interface.
nm_interface="BSD nm" nm_interface="BSD nm"
@ -189,7 +189,7 @@ nm_interface="BSD nm"
nm_file_list_spec="@" nm_file_list_spec="@"
# The root where to search for dependent libraries,and where our libraries should be installed. # 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. # Command to truncate a binary pipe.
lt_truncate_bin="/bin/dd bs=4096 count=1" lt_truncate_bin="/bin/dd bs=4096 count=1"
@ -213,7 +213,7 @@ DSYMUTIL="dsymutil"
NMEDIT="nmedit" NMEDIT="nmedit"
# Tool to manipulate fat objects and archives on Mac OS X. # 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. # ldd/readelf like tool for Mach-O binaries on Mac OS X.
OTOOL="otool" OTOOL="otool"
@ -282,7 +282,7 @@ finish_eval=""
hardcode_into_libs=no hardcode_into_libs=no
# Compile-time system search path for libraries. # 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. # Detected run-time system search path for libraries.
sys_lib_dlsearch_path_spec="/usr/local/lib /lib /usr/lib" sys_lib_dlsearch_path_spec="/usr/local/lib /lib /usr/lib"
@ -300,12 +300,12 @@ dlopen_self=unknown
dlopen_self_static=unknown dlopen_self_static=unknown
# Commands to strip libraries. # Commands to strip libraries.
old_striplib="strip --strip-debug" old_striplib="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip -S"
striplib="strip --strip-unneeded" striplib="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip -x"
# The linker used to build libraries. # 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. # How to create reloadable object files.
reload_flag=" -r" reload_flag=" -r"
@ -345,7 +345,7 @@ allow_libtool_libs_with_static_runtimes=no
export_dynamic_flag_spec="" export_dynamic_flag_spec=""
# Compiler flag to generate shared objects directly from archives. # 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. # Whether the compiler copes with passing no objects directly.
compiler_needs_object="no" compiler_needs_object="no"
@ -357,19 +357,19 @@ old_archive_from_new_cmds=""
old_archive_from_expsyms_cmds="" old_archive_from_expsyms_cmds=""
# Commands used to build a shared archive. # 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_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~\$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"
# Commands used to build a loadable module if different from building # Commands used to build a loadable module if different from building
# a shared archive. # a shared archive.
module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags~\$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~\$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"
# Whether we are building with GNU ld or not. # Whether we are building with GNU ld or not.
with_gnu_ld="no" with_gnu_ld="no"
# Flag that allows shared libraries with undefined symbols to be built. # 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. # Flag that enforces no undefined symbols.
no_undefined_flag="" no_undefined_flag=""

@ -3,7 +3,7 @@
scriptversion=2018-03-07.03; # UTC 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. # Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify

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

@ -19,7 +19,6 @@
#import "AbstractSession.h" #import "AbstractSession.h"
#import "AtomicLong.h" #import "AtomicLong.h"
#import "ExecuteCallback.h"
#import "FFmpegKit.h" #import "FFmpegKit.h"
#import "FFmpegKitConfig.h" #import "FFmpegKitConfig.h"
#import "LogCallback.h" #import "LogCallback.h"
@ -33,7 +32,6 @@ extern void addSessionToSessionHistory(id<Session> session);
@implementation AbstractSession { @implementation AbstractSession {
long _sessionId; long _sessionId;
ExecuteCallback _executeCallback;
LogCallback _logCallback; LogCallback _logCallback;
NSDate* _createTime; NSDate* _createTime;
NSDate* _startTime; NSDate* _startTime;
@ -51,11 +49,10 @@ extern void addSessionToSessionHistory(id<Session> session);
sessionIdGenerator = [[AtomicLong alloc] initWithValue:1]; 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]; self = [super init];
if (self) { if (self) {
_sessionId = [sessionIdGenerator getAndIncrement]; _sessionId = [sessionIdGenerator getAndIncrement];
_executeCallback = executeCallback;
_logCallback = logCallback; _logCallback = logCallback;
_createTime = [NSDate date]; _createTime = [NSDate date];
_startTime = nil; _startTime = nil;
@ -74,10 +71,6 @@ extern void addSessionToSessionHistory(id<Session> session);
return self; return self;
} }
- (ExecuteCallback)getExecuteCallback {
return _executeCallback;
}
- (LogCallback)getLogCallback { - (LogCallback)getLogCallback {
return _logCallback; return _logCallback;
} }
@ -230,6 +223,11 @@ extern void addSessionToSessionHistory(id<Session> session);
return false; return false;
} }
- (BOOL)isMediaInformation {
// IMPLEMENTED IN SUBCLASSES
return false;
}
- (void)cancel { - (void)cancel {
if (_state == SessionStateRunning) { if (_state == SessionStateRunning) {
[FFmpegKit cancel:_sessionId]; [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 <string.h>
#import <stdlib.h> #import <stdlib.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "ExecuteCallback.h"
#import "LogCallback.h" #import "LogCallback.h"
#import "FFmpegSession.h" #import "FFmpegSession.h"
#import "StatisticsCallback.h" #import "StatisticsCallback.h"
@ -34,11 +33,11 @@
* <pre> * <pre>
* FFmpegSession *session = [FFmpegKit execute:@"-i file1.mp4 -c:v libxvid file1.avi"]; * 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> * </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks. * <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre> * <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> * </pre>
*/ */
@interface FFmpegKit : NSObject @interface FFmpegKit : NSObject
@ -54,56 +53,56 @@
/** /**
* <p>Starts an asynchronous FFmpeg execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
* *
* @param arguments FFmpeg command options/arguments as string array * @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
* @return FFmpeg session created for this execution * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
* *
* @param arguments FFmpeg command options/arguments as string array * @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 logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @return FFmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
+ (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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
* *
* @param arguments FFmpeg command options/arguments as string array * @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 queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
* *
* @param arguments FFmpeg command options/arguments as string array * @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 logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @param queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution * @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 * <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. * 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 * <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 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
* @return FFmpeg session created for this execution * @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 * <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. * 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 * <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 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 logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @return FFmpeg session created for this execution * @return FFmpeg session created for this execution
*/ */
+ (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 * <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. * 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 * <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 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 queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution * @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 * <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. * 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 * <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 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 logCallback callback that will receive logs
* @param statisticsCallback callback that will receive statistics * @param statisticsCallback callback that will receive statistics
* @param queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFmpeg session created for this execution * @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>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; + (void)cancel;
/** /**
* <p>Cancels the session specified with <code>sessionId</code>. * <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 * @param sessionId id of the session that will be cancelled
*/ */

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

@ -24,7 +24,6 @@
#import <pthread.h> #import <pthread.h>
#import <unistd.h> #import <unistd.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "ExecuteCallback.h"
#import "FFmpegSession.h" #import "FFmpegSession.h"
#import "FFprobeSession.h" #import "FFprobeSession.h"
#import "LogCallback.h" #import "LogCallback.h"
@ -191,8 +190,8 @@ typedef NS_ENUM(NSUInteger, Signal) {
/** /**
* <p>Starts an asynchronous FFmpeg execution for the given session. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
* *
* @param ffmpegSession FFmpeg session which includes command options/arguments * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFmpegSessionCompleteCallback if you want to be notified about the result.
* *
* @param ffmpegSession FFmpeg session which includes command options/arguments * @param ffmpegSession FFmpeg session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
* *
* @param ffprobeSession FFprobe session which includes command options/arguments * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
* *
* @param ffprobeSession FFprobe session which includes command options/arguments * @param ffprobeSession FFprobe session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * 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 mediaInformationSession media information session which includes command options/arguments
* @param waitTimeout max time to wait until media information is transmitted * @param waitTimeout max time to wait until media information is transmitted
@ -244,8 +243,8 @@ typedef NS_ENUM(NSUInteger, Signal) {
/** /**
* <p>Starts an asynchronous FFprobe execution for the given media information session. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * 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 mediaInformationSession media information session which includes command options/arguments
* @param queue dispatch queue that will be used to run this asynchronous operation * @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; + (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. * Returns the current log level.
@ -367,6 +395,13 @@ typedef NS_ENUM(NSUInteger, Signal) {
*/ */
+ (NSArray*)getFFprobeSessions; + (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. * <p>Returns sessions that have the given state.
* *

@ -21,6 +21,7 @@
#import <sys/types.h> #import <sys/types.h>
#import <sys/stat.h> #import <sys/stat.h>
#import "libavutil/ffversion.h" #import "libavutil/ffversion.h"
#import "libavutil/bprint.h"
#import "fftools_ffmpeg.h" #import "fftools_ffmpeg.h"
#import "ArchDetect.h" #import "ArchDetect.h"
#import "AtomicLong.h" #import "AtomicLong.h"
@ -35,7 +36,7 @@
#import "SessionState.h" #import "SessionState.h"
/** Global library version */ /** Global library version */
NSString* const FFmpegKitVersion = @"4.5"; NSString* const FFmpegKitVersion = @"4.5.1";
/** /**
* Prefix of named pipes created by ffmpeg-kit. * Prefix of named pipes created by ffmpeg-kit.
@ -66,8 +67,10 @@ static LogCallback logCallback;
/** Holds callback defined to redirect statistics */ /** Holds callback defined to redirect statistics */
static StatisticsCallback statisticsCallback; static StatisticsCallback statisticsCallback;
/** Holds callback defined to redirect asynchronous execution results */ /** Holds complete callbacks defined to redirect asynchronous execution results */
static ExecuteCallback executeCallback; static FFmpegSessionCompleteCallback ffmpegSessionCompleteCallback;
static FFprobeSessionCompleteCallback ffprobeSessionCompleteCallback;
static MediaInformationSessionCompleteCallback mediaInformationSessionCompleteCallback;
static LogRedirectionStrategy globalLogRedirectionStrategy; static LogRedirectionStrategy globalLogRedirectionStrategy;
@ -138,7 +141,7 @@ void addSessionToSessionHistory(id<Session> session) {
long _sessionId; // session id long _sessionId; // session id
int _logLevel; // log level int _logLevel; // log level
NSString* _logData; // log data AVBPrint _logData; // log data
int _statisticsFrameNumber; // statistics frame number int _statisticsFrameNumber; // statistics frame number
float _statisticsFps; // statistics fps float _statisticsFps; // statistics fps
@ -149,13 +152,14 @@ void addSessionToSessionHistory(id<Session> session) {
double _statisticsSpeed; // statistics speed 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]; self = [super init];
if (self) { if (self) {
_type = LogType; _type = LogType;
_sessionId = sessionId; _sessionId = sessionId;
_logLevel = logLevel; _logLevel = logLevel;
_logData = logData; av_bprint_init(&_logData, 0, AV_BPRINT_SIZE_UNLIMITED);
av_bprintf(&_logData, "%s", data->str);
} }
return self; return self;
@ -197,8 +201,8 @@ void addSessionToSessionHistory(id<Session> session) {
return _logLevel; return _logLevel;
} }
- (NSString*)getLogData { - (AVBPrint*)getLogData {
return _logData; return &_logData;
} }
- (int)getStatisticsFrameNumber { - (int)getStatisticsFrameNumber {
@ -247,15 +251,80 @@ void callbackNotify() {
dispatch_semaphore_signal(semaphore); 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. * Adds log data to the end of callback data list.
* *
* @param level log level * @param level log level
* @param logData log data * @param data log data
*/ */
void logCallbackDataAdd(int level, NSString *logData) { void logCallbackDataAdd(int level, AVBPrint *data) {
CallbackData* callbackData = [[CallbackData alloc] init:globalSessionId logLevel:level data:logData]; CallbackData* callbackData = [[CallbackData alloc] init:globalSessionId logLevel:level data:data];
[lock lock]; [lock lock];
[callbackDataArray addObject:callbackData]; [callbackDataArray addObject:callbackData];
[lock unlock]; [lock unlock];
@ -361,6 +430,9 @@ void resetMessagesInTransmit(long sessionId) {
* @param vargs arguments * @param vargs arguments
*/ */
void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, va_list vargs) { 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 // DO NOT PROCESS UNWANTED LOGS
if (level >= 0) { if (level >= 0) {
@ -373,11 +445,26 @@ void ffmpegkit_log_callback_function(void *ptr, int level, const char* format, v
return; 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) { if (fullLine.len > 0) {
logCallbackDataAdd(level, logData); 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); 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(); 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 globalCallbackDefined = false;
BOOL sessionCallbackDefined = false; BOOL sessionCallbackDefined = false;
LogRedirectionStrategy activeLogRedirectionStrategy = globalLogRedirectionStrategy; LogRedirectionStrategy activeLogRedirectionStrategy = globalLogRedirectionStrategy;
@ -422,7 +509,7 @@ void process_log(long sessionId, int levelValue, NSString* logMessage) {
sessionLogCallback(log); sessionLogCallback(log);
} }
@catch(NSException* exception) { @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); globalLogCallback(log);
} }
@catch(NSException* exception) { @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; return;
} }
} }
break;
case LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined: { case LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined: {
if (globalCallbackDefined || sessionCallbackDefined) { if (globalCallbackDefined || sessionCallbackDefined) {
return; return;
} }
} }
break;
case LogRedirectionStrategyAlwaysPrintLogs: { case LogRedirectionStrategyAlwaysPrintLogs: {
} }
break;
} }
// PRINT LOGS // PRINT LOGS
@ -472,7 +562,7 @@ void process_log(long sessionId, int levelValue, NSString* logMessage) {
break; break;
default: default:
// WRITE TO NSLOG // WRITE TO NSLOG
NSLog(@"%@: %@", [FFmpegKitConfig logLevelToString:levelValue], logMessage); NSLog(@"%@: %@", [FFmpegKitConfig logLevelToString:levelValue], [NSString stringWithCString:logMessage->str encoding:NSUTF8StringEncoding]);
break; break;
} }
} }
@ -492,7 +582,7 @@ void process_statistics(long sessionId, int videoFrameNumber, float videoFps, fl
sessionStatisticsCallback(statistics); sessionStatisticsCallback(statistics);
} }
@catch(NSException* exception) { @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); globalStatisticsCallback(statistics);
} }
@catch(NSException* exception) { @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) { if ([callbackData getType] == LogType) {
process_log([callbackData getSessionId], [callbackData getLogLevel], [callbackData getLogData]); process_log([callbackData getSessionId], [callbackData getLogLevel], [callbackData getLogData]);
av_bprint_finalize([callbackData getLogData], NULL);
} else { } else {
process_statistics([callbackData getSessionId], process_statistics([callbackData getSessionId],
[callbackData getStatisticsFrameNumber], [callbackData getStatisticsFrameNumber],
@ -662,7 +753,9 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
logCallback = nil; logCallback = nil;
statisticsCallback = nil; statisticsCallback = nil;
executeCallback = nil; ffmpegSessionCompleteCallback = nil;
ffprobeSessionCompleteCallback = nil;
mediaInformationSessionCompleteCallback = nil;
globalLogRedirectionStrategy = LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined; globalLogRedirectionStrategy = LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined;
@ -901,7 +994,7 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
int returnCodeValue = executeFFprobe([mediaInformationSession getSessionId], [mediaInformationSession getArguments]); int returnCodeValue = executeFFprobe([mediaInformationSession getSessionId], [mediaInformationSession getArguments]);
ReturnCode* returnCode = [[ReturnCode alloc] init:returnCodeValue]; ReturnCode* returnCode = [[ReturnCode alloc] init:returnCodeValue];
[mediaInformationSession complete:returnCode]; [mediaInformationSession complete:returnCode];
if ([returnCode isSuccess]) { if ([returnCode isValueSuccess]) {
MediaInformation* mediaInformation = [MediaInformationJsonParser from:[mediaInformationSession getAllLogsAsStringWithTimeout:waitTimeout]]; MediaInformation* mediaInformation = [MediaInformationJsonParser from:[mediaInformationSession getAllLogsAsStringWithTimeout:waitTimeout]];
[mediaInformationSession setMediaInformation:mediaInformation]; [mediaInformationSession setMediaInformation:mediaInformation];
} }
@ -918,14 +1011,27 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
+ (void)asyncFFmpegExecute:(FFmpegSession*)ffmpegSession onDispatchQueue:(dispatch_queue_t)queue { + (void)asyncFFmpegExecute:(FFmpegSession*)ffmpegSession onDispatchQueue:(dispatch_queue_t)queue {
dispatch_async(queue, ^{ dispatch_async(queue, ^{
[FFmpegKitConfig ffmpegExecute:ffmpegSession]; [FFmpegKitConfig ffmpegExecute:ffmpegSession];
ExecuteCallback globalExecuteCallback = [FFmpegKitConfig getExecuteCallback];
if (globalExecuteCallback != nil) { FFmpegSessionCompleteCallback completeCallback = [ffmpegSession getCompleteCallback];
globalExecuteCallback(ffmpegSession); 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]; FFmpegSessionCompleteCallback globalFFmpegSessionCompleteCallback = [FFmpegKitConfig getFFmpegSessionCompleteCallback];
if (sessionExecuteCallback != nil) { if (globalFFmpegSessionCompleteCallback != nil) {
sessionExecuteCallback(ffmpegSession); @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 { + (void)asyncFFprobeExecute:(FFprobeSession*)ffprobeSession onDispatchQueue:(dispatch_queue_t)queue {
dispatch_async(queue, ^{ dispatch_async(queue, ^{
[FFmpegKitConfig ffprobeExecute:ffprobeSession]; [FFmpegKitConfig ffprobeExecute:ffprobeSession];
ExecuteCallback globalExecuteCallback = [FFmpegKitConfig getExecuteCallback];
if (globalExecuteCallback != nil) { FFprobeSessionCompleteCallback completeCallback = [ffprobeSession getCompleteCallback];
globalExecuteCallback(ffprobeSession); 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]; FFprobeSessionCompleteCallback globalFFprobeSessionCompleteCallback = [FFmpegKitConfig getFFprobeSessionCompleteCallback];
if (sessionExecuteCallback != nil) { if (globalFFprobeSessionCompleteCallback != nil) {
sessionExecuteCallback(ffprobeSession); @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 { + (void)asyncGetMediaInformationExecute:(MediaInformationSession*)mediaInformationSession onDispatchQueue:(dispatch_queue_t)queue withTimeout:(int)waitTimeout {
dispatch_async(queue, ^{ dispatch_async(queue, ^{
[FFmpegKitConfig getMediaInformationExecute:mediaInformationSession withTimeout:waitTimeout]; [FFmpegKitConfig getMediaInformationExecute:mediaInformationSession withTimeout:waitTimeout];
ExecuteCallback globalExecuteCallback = [FFmpegKitConfig getExecuteCallback];
if (globalExecuteCallback != nil) { MediaInformationSessionCompleteCallback completeCallback = [mediaInformationSession getCompleteCallback];
globalExecuteCallback(mediaInformationSession); 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]; MediaInformationSessionCompleteCallback globalMediaInformationSessionCompleteCallback = [FFmpegKitConfig getMediaInformationSessionCompleteCallback];
if (sessionExecuteCallback != nil) { if (globalMediaInformationSessionCompleteCallback != nil) {
sessionExecuteCallback(mediaInformationSession); @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; statisticsCallback = callback;
} }
+ (void)enableExecuteCallback:(ExecuteCallback)callback { + (void)enableFFmpegSessionCompleteCallback:(FFmpegSessionCompleteCallback)completeCallback {
executeCallback = callback; ffmpegSessionCompleteCallback = completeCallback;
} }
+ (ExecuteCallback)getExecuteCallback { + (FFmpegSessionCompleteCallback)getFFmpegSessionCompleteCallback {
return executeCallback; return ffmpegSessionCompleteCallback;
}
+ (void)enableFFprobeSessionCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback {
ffprobeSessionCompleteCallback = completeCallback;
}
+ (FFprobeSessionCompleteCallback)getFFprobeSessionCompleteCallback {
return ffprobeSessionCompleteCallback;
}
+ (void)enableMediaInformationSessionCompleteCallback:(MediaInformationSessionCompleteCallback)completeCallback {
mediaInformationSessionCompleteCallback = completeCallback;
}
+ (MediaInformationSessionCompleteCallback)getMediaInformationSessionCompleteCallback {
return mediaInformationSessionCompleteCallback;
} }
+ (int)getLogLevel { + (int)getLogLevel {
@ -1076,6 +1224,7 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
[sessionHistoryLock lock]; [sessionHistoryLock lock];
[sessionHistoryList removeAllObjects]; [sessionHistoryList removeAllObjects];
[sessionHistoryMap removeAllObjects];
[sessionHistoryLock unlock]; [sessionHistoryLock unlock];
} }
@ -1114,6 +1263,23 @@ int executeFFprobe(long sessionId, NSArray* arguments) {
return ffprobeSessions; 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 { + (NSArray*)getSessionsByState:(SessionState)state {
NSMutableArray* sessions = [[NSMutableArray alloc] init]; NSMutableArray* sessions = [[NSMutableArray alloc] init];

@ -23,6 +23,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "AbstractSession.h" #import "AbstractSession.h"
#import "StatisticsCallback.h" #import "StatisticsCallback.h"
#import "FFmpegSessionCompleteCallback.h"
/** /**
* <p>An FFmpeg session. * <p>An FFmpeg session.
@ -39,31 +40,31 @@
/** /**
* Builds a new FFmpeg session. * Builds a new FFmpeg session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback * @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. * Builds a new FFmpeg session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback * @param completeCallback session specific complete callback
* @param logCallback session specific log callback * @param logCallback session specific log callback
* @param statisticsCallback session specific statistics 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. * Builds a new FFmpeg session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback * @param completeCallback session specific complete callback
* @param logCallback session specific log callback * @param logCallback session specific log callback
* @param statisticsCallback session specific statistics callback * @param statisticsCallback session specific statistics callback
* @param logRedirectionStrategy session specific log redirection strategy * @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. * Returns the session specific statistics callback.
@ -72,6 +73,13 @@
*/ */
- (StatisticsCallback)getStatisticsCallback; - (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 * 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. * messages that are not delivered yet, this method waits for them until the given timeout.
@ -108,7 +116,8 @@
- (Statistics*)getLastReceivedStatistics; - (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 * @param statistics statistics entry
*/ */

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

@ -17,13 +17,13 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef FFMPEG_KIT_EXECUTE_CALLBACK_H #ifndef FFMPEG_KIT_FFMPEG_SESSION_COMPLETE_CALLBACK_H
#define FFMPEG_KIT_EXECUTE_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 * <p>Session has either SessionStateCompleted or SessionStateFailed state when
* the callback is invoked. * the callback is invoked.
* <p>If it has SessionStateCompleted state, <code>ReturnCode</code> should be checked to * <p>If it has SessionStateCompleted state, <code>ReturnCode</code> should be checked to
@ -43,8 +43,8 @@
* *
* @param session session of the completed execution * @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> * <pre>
* FFprobeSession *session = [FFprobeKit execute:@"-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4"]; * FFprobeSession *session = [FFprobeKit execute:@"-hide_banner -v error -show_entries format=size -of default=noprint_wrappers=1 file1.mp4"];
* *
* 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> * </pre>
* <p>Provides overloaded <code>execute</code> methods to define session specific callbacks. * <p>Provides overloaded <code>execute</code> methods to define session specific callbacks.
* <pre> * <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> * </pre>
* <p>It can extract media information for a file or a url, using getMediaInformation method. * <p>It can extract media information for a file or a url, using getMediaInformation method.
* <pre> * <pre>
@ -56,54 +56,54 @@
/** /**
* <p>Starts an asynchronous FFprobe execution with arguments provided. * <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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe 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
* @return FFprobe session created for this execution * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @return FFprobe session created for this execution * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe 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 queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution * @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>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 * <p>Note that this method returns immediately and does not wait the execution to complete.
* ExecuteCallback if you want to be notified about the result. * You must use an FFprobeSessionCompleteCallback if you want to be notified about the result.
* *
* @param arguments FFprobe command options/arguments as string array * @param arguments FFprobe command options/arguments as string array
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution * @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 * <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. * 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 * <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 command FFprobe 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
* @return FFprobe session created for this execution * @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 * <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. * 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 * <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 command FFprobe command
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @return FFprobe session created for this execution * @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 * <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. * 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 * <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 command FFprobe 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 queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution * @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 * <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. * 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 * <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 command FFprobe 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 logCallback callback that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return FFprobe session created for this execution * @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. * <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>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 * <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 path path or uri of a media file
* @param executeCallback callback that will be called when the execution is completed * @param completeCallback callback that will be called when the execution has completed
* @return media information session created for this execution * @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>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 * <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 path path or uri of a media file
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @param waitTimeout max time to wait until media information is transmitted * @param waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution * @return media information session created for this execution
*/ */
+ (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>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 * <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 path path or uri of a media file
* @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 queue dispatch queue that will be used to run this asynchronous operation * @param queue dispatch queue that will be used to run this asynchronous operation
* @return media information session created for this execution * @return media information session created for this execution
*/ */
+ (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>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 * <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 path path or uri of a media file
* @param executeCallback callback that will be notified when execution is completed * @param completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation * @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 waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution * @return media information session created for this execution
*/ */
+ (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. * <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. * 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 * <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 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 completeCallback callback that will be notified when execution has completed
* @param logCallback callback that will receive logs * @param logCallback callback that will receive logs
* @param queue dispatch queue that will be used to run this asynchronous operation * @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 waitTimeout max time to wait until media information is transmitted
* @return media information session created for this execution * @return media information session created for this execution
*/ */
+ (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. * <p>Lists all FFprobe sessions in the session history.
* *
* @return 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 @end

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

@ -22,6 +22,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "AbstractSession.h" #import "AbstractSession.h"
#import "FFprobeSessionCompleteCallback.h"
/** /**
* <p>An FFprobe session. * <p>An FFprobe session.
@ -38,29 +39,36 @@
/** /**
* Builds a new FFprobe session. * Builds a new FFprobe session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback * @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. * Builds a new FFprobe session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback * @param completeCallback session specific complete callback
* @param logCallback session specific log 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. * Builds a new FFprobe session.
* *
* @param arguments command arguments * @param arguments command arguments
* @param executeCallback session specific execute callback * @param completeCallback session specific complete callback
* @param logCallback session specific log callback * @param logCallback session specific log callback
* @param logRedirectionStrategy session specific log redirection strategy * @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 @end

@ -17,45 +17,66 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#import "ExecuteCallback.h"
#import "FFprobeSession.h" #import "FFprobeSession.h"
#import "FFmpegKitConfig.h" #import "FFmpegKitConfig.h"
#import "LogCallback.h" #import "LogCallback.h"
@implementation FFprobeSession @implementation FFprobeSession {
FFprobeSessionCompleteCallback _completeCallback;
}
+ (void)initialize {
// EMPTY INITIALIZE
}
- (instancetype)init:(NSArray*)arguments { - (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; return self;
} }
+ (void)initialize { - (instancetype)init:(NSArray*)arguments withCompleteCallback:(FFprobeSessionCompleteCallback)completeCallback {
// EMPTY INITIALIZE
}
- (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; 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; 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; return self;
} }
- (FFprobeSessionCompleteCallback)getCompleteCallback {
return _completeCallback;
}
- (BOOL)isFFmpeg { - (BOOL)isFFmpeg {
return false; return false;
} }
@ -64,5 +85,9 @@
return true; return true;
} }
- (BOOL)isMediaInformation {
return false;
}
@end @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 lib_LTLIBRARIES = libffmpegkit.la
libffmpegkit_la_LIBADD = @FFMPEG_LIBS@ libffmpegkit_la_LIBADD = @FFMPEG_FRAMEWORKS@
libffmpegkit_la_SOURCES = \ libffmpegkit_la_SOURCES = \
AbstractSession.m \ AbstractSession.m \
ArchDetect.m \ ArchDetect.m \
AtomicLong.m \ AtomicLong.m \
Chapter.m \
FFmpegKit.m \ FFmpegKit.m \
FFmpegKitConfig.m \ FFmpegKitConfig.m \
FFmpegSession.m \ FFmpegSession.m \
@ -35,28 +36,31 @@ include_HEADERS = \
AbstractSession.h \ AbstractSession.h \
ArchDetect.h \ ArchDetect.h \
AtomicLong.h \ AtomicLong.h \
ExecuteCallback.h \ Chapter.h \
FFmpegKit.h \ FFmpegKit.h \
FFmpegKitConfig.h \ FFmpegKitConfig.h \
FFmpegSession.h \ FFmpegSession.h \
FFprobeKit.h \ FFmpegSessionCompleteCallback.h \
FFprobeSession.h \ FFprobeKit.h \
Level.h \ FFprobeSession.h \
Log.h \ FFprobeSessionCompleteCallback.h \
LogCallback.h \ Level.h \
LogRedirectionStrategy.h \ Log.h \
MediaInformation.h \ LogCallback.h \
MediaInformationJsonParser.h \ LogRedirectionStrategy.h \
MediaInformationSession.h \ MediaInformation.h \
Packages.h \ MediaInformationJsonParser.h \
ReturnCode.h \ MediaInformationSession.h \
Session.h \ MediaInformationSessionCompleteCallback.h \
SessionState.h \ Packages.h \
Statistics.h \ ReturnCode.h \
StatisticsCallback.h \ Session.h \
StreamInformation.h \ SessionState.h \
ffmpegkit_exception.h \ Statistics.h \
fftools_cmdutils.h \ StatisticsCallback.h \
StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
fftools_ffmpeg.h fftools_ffmpeg.h
libffmpegkit_la_CFLAGS = $(CFLAGS) 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@ # @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 # This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it, # gives unlimited permission to copy and/or distribute it,
@ -134,18 +134,18 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES) LTLIBRARIES = $(lib_LTLIBRARIES)
libffmpegkit_la_DEPENDENCIES = libffmpegkit_la_DEPENDENCIES =
am__libffmpegkit_la_SOURCES_DIST = AbstractSession.m ArchDetect.m \ am__libffmpegkit_la_SOURCES_DIST = AbstractSession.m ArchDetect.m \
AtomicLong.m FFmpegKit.m FFmpegKitConfig.m FFmpegSession.m \ AtomicLong.m Chapter.m FFmpegKit.m FFmpegKitConfig.m \
FFprobeKit.m FFprobeSession.m Log.m MediaInformation.m \ FFmpegSession.m FFprobeKit.m FFprobeSession.m Log.m \
MediaInformationJsonParser.m MediaInformationSession.m \ MediaInformation.m MediaInformationJsonParser.m \
Packages.m ReturnCode.m Statistics.m StreamInformation.m \ MediaInformationSession.m Packages.m ReturnCode.m Statistics.m \
ffmpegkit_exception.m fftools_cmdutils.c fftools_ffmpeg.c \ StreamInformation.m ffmpegkit_exception.m fftools_cmdutils.c \
fftools_ffmpeg_filter.c fftools_ffmpeg_hw.c \ fftools_ffmpeg.c fftools_ffmpeg_filter.c fftools_ffmpeg_hw.c \
fftools_ffmpeg_opt.c fftools_ffprobe.c \ fftools_ffmpeg_opt.c fftools_ffprobe.c \
fftools_ffmpeg_videotoolbox.c fftools_ffmpeg_videotoolbox.c
@FFMPEGKIT_VIDEOTOOLBOX_TRUE@am__objects_1 = libffmpegkit_la-fftools_ffmpeg_videotoolbox.lo @FFMPEGKIT_VIDEOTOOLBOX_TRUE@am__objects_1 = libffmpegkit_la-fftools_ffmpeg_videotoolbox.lo
am_libffmpegkit_la_OBJECTS = libffmpegkit_la-AbstractSession.lo \ am_libffmpegkit_la_OBJECTS = libffmpegkit_la-AbstractSession.lo \
libffmpegkit_la-ArchDetect.lo libffmpegkit_la-AtomicLong.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-FFmpegKitConfig.lo \
libffmpegkit_la-FFmpegSession.lo libffmpegkit_la-FFprobeKit.lo \ libffmpegkit_la-FFmpegSession.lo libffmpegkit_la-FFprobeKit.lo \
libffmpegkit_la-FFprobeSession.lo libffmpegkit_la-Log.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 \ am__depfiles_remade = ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo \
./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo \ ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo \
./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo \ ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo \
./$(DEPDIR)/libffmpegkit_la-Chapter.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo \ ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo \ ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo \
./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo \ ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo \
@ -272,8 +273,6 @@ am__define_uniq_tagged_files = \
unique=`for i in $$list; do \ unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)` done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@ ACLOCAL = @ACLOCAL@
@ -287,8 +286,9 @@ AWK = @AWK@
CC = @CC@ CC = @CC@
CCDEPMODE = @CCDEPMODE@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@ CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@ CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@ DEFS = @DEFS@
DEPDIR = @DEPDIR@ DEPDIR = @DEPDIR@
@ -299,8 +299,9 @@ ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@ ECHO_T = @ECHO_T@
EGREP = @EGREP@ EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@ EXEEXT = @EXEEXT@
FFMPEG_LIBS = @FFMPEG_LIBS@ FFMPEG_FRAMEWORKS = @FFMPEG_FRAMEWORKS@
FGREP = @FGREP@ FGREP = @FGREP@
GREP = @GREP@ GREP = @GREP@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
@ -389,6 +390,7 @@ pdfdir = @pdfdir@
prefix = @prefix@ prefix = @prefix@
program_transform_name = @program_transform_name@ program_transform_name = @program_transform_name@
psdir = @psdir@ psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@ sharedstatedir = @sharedstatedir@
srcdir = @srcdir@ srcdir = @srcdir@
@ -398,10 +400,10 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
lib_LTLIBRARIES = libffmpegkit.la lib_LTLIBRARIES = libffmpegkit.la
libffmpegkit_la_LIBADD = @FFMPEG_LIBS@ libffmpegkit_la_LIBADD = @FFMPEG_FRAMEWORKS@
libffmpegkit_la_SOURCES = AbstractSession.m ArchDetect.m AtomicLong.m \ libffmpegkit_la_SOURCES = AbstractSession.m ArchDetect.m AtomicLong.m \
FFmpegKit.m FFmpegKitConfig.m FFmpegSession.m FFprobeKit.m \ Chapter.m FFmpegKit.m FFmpegKitConfig.m FFmpegSession.m \
FFprobeSession.m Log.m MediaInformation.m \ FFprobeKit.m FFprobeSession.m Log.m MediaInformation.m \
MediaInformationJsonParser.m MediaInformationSession.m \ MediaInformationJsonParser.m MediaInformationSession.m \
Packages.m ReturnCode.m Statistics.m StreamInformation.m \ Packages.m ReturnCode.m Statistics.m StreamInformation.m \
ffmpegkit_exception.m fftools_cmdutils.c fftools_ffmpeg.c \ ffmpegkit_exception.m fftools_cmdutils.c fftools_ffmpeg.c \
@ -411,28 +413,31 @@ include_HEADERS = \
AbstractSession.h \ AbstractSession.h \
ArchDetect.h \ ArchDetect.h \
AtomicLong.h \ AtomicLong.h \
ExecuteCallback.h \ Chapter.h \
FFmpegKit.h \ FFmpegKit.h \
FFmpegKitConfig.h \ FFmpegKitConfig.h \
FFmpegSession.h \ FFmpegSession.h \
FFprobeKit.h \ FFmpegSessionCompleteCallback.h \
FFprobeSession.h \ FFprobeKit.h \
Level.h \ FFprobeSession.h \
Log.h \ FFprobeSessionCompleteCallback.h \
LogCallback.h \ Level.h \
LogRedirectionStrategy.h \ Log.h \
MediaInformation.h \ LogCallback.h \
MediaInformationJsonParser.h \ LogRedirectionStrategy.h \
MediaInformationSession.h \ MediaInformation.h \
Packages.h \ MediaInformationJsonParser.h \
ReturnCode.h \ MediaInformationSession.h \
Session.h \ MediaInformationSessionCompleteCallback.h \
SessionState.h \ Packages.h \
Statistics.h \ ReturnCode.h \
StatisticsCallback.h \ Session.h \
StreamInformation.h \ SessionState.h \
ffmpegkit_exception.h \ Statistics.h \
fftools_cmdutils.h \ StatisticsCallback.h \
StreamInformation.h \
ffmpegkit_exception.h \
fftools_cmdutils.h \
fftools_ffmpeg.h fftools_ffmpeg.h
libffmpegkit_la_CFLAGS = $(CFLAGS) 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-AbstractSession.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-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-FFmpegKit.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libffmpegkit_la-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@ @AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-AtomicLong.lo `test -f 'AtomicLong.m' || echo '$(srcdir)/'`AtomicLong.m @am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -c -o libffmpegkit_la-AtomicLong.lo `test -f 'AtomicLong.m' || echo '$(srcdir)/'`AtomicLong.m
libffmpegkit_la-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 libffmpegkit_la-FFmpegKit.lo: FFmpegKit.m
@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFmpegKit.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFmpegKit.Tpo -c -o libffmpegkit_la-FFmpegKit.lo `test -f 'FFmpegKit.m' || echo '$(srcdir)/'`FFmpegKit.m @am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libffmpegkit_la_OBJCFLAGS) $(OBJCFLAGS) -MT libffmpegkit_la-FFmpegKit.lo -MD -MP -MF $(DEPDIR)/libffmpegkit_la-FFmpegKit.Tpo -c -o libffmpegkit_la-FFmpegKit.lo `test -f 'FFmpegKit.m' || echo '$(srcdir)/'`FFmpegKit.m
@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-FFmpegKit.Tpo $(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo @am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libffmpegkit_la-FFmpegKit.Tpo $(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo
@ -842,7 +855,6 @@ cscopelist-am: $(am__tagged_files)
distclean-tags: distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES) distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am $(MAKE) $(AM_MAKEFLAGS) distdir-am
@ -922,6 +934,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-Chapter.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo
@ -991,6 +1004,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-AbstractSession.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-ArchDetect.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-AtomicLong.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-Chapter.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKit.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegKitConfig.Plo
-rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo -rm -f ./$(DEPDIR)/libffmpegkit_la-FFmpegSession.Plo

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

@ -41,13 +41,19 @@ NSString* const MediaKeyTags = @"tags";
*/ */
NSArray *streamArray; 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]; self = [super init];
if (self) { if (self) {
dictionary = mediaDictionary; dictionary = mediaDictionary;
streamArray = streams; streamArray = streams;
chapterArray = chapters;
} }
return self; return self;
@ -89,6 +95,10 @@ NSString* const MediaKeyTags = @"tags";
return streamArray; return streamArray;
} }
- (NSArray*)getChapters {
return chapterArray;
}
- (NSString*)getStringProperty:(NSString*)key { - (NSString*)getStringProperty:(NSString*)key {
NSDictionary* mediaProperties = [self getMediaProperties]; NSDictionary* mediaProperties = [self getMediaProperties];
if (mediaProperties == nil) { if (mediaProperties == nil) {

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

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

@ -17,13 +17,13 @@
* along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>. * along with FFmpegKit. If not, see <http://www.gnu.org/licenses/>.
*/ */
#import "ExecuteCallback.h" #import "MediaInformationSession.h"
#import "LogCallback.h" #import "LogCallback.h"
#import "MediaInformation.h" #import "MediaInformation.h"
#import "MediaInformationSession.h"
@implementation MediaInformationSession { @implementation MediaInformationSession {
MediaInformation* _mediaInformation; MediaInformation* _mediaInformation;
MediaInformationSessionCompleteCallback _completeCallback;
} }
+ (void)initialize { + (void)initialize {
@ -32,21 +32,33 @@
- (instancetype)init:(NSArray*)arguments { - (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; 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; 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; return self;
} }
@ -59,5 +71,21 @@
_mediaInformation = mediaInformation; _mediaInformation = mediaInformation;
} }
- (MediaInformationSessionCompleteCallback)getCompleteCallback {
return _completeCallback;
}
- (BOOL)isFFmpeg {
return false;
}
- (BOOL)isFFprobe {
return false;
}
- (BOOL)isMediaInformation {
return true;
}
@end @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; - (int)getValue;
- (BOOL)isSuccess; - (BOOL)isValueSuccess;
- (BOOL)isError; - (BOOL)isValueError;
- (BOOL)isCancel; - (BOOL)isValueCancel;
@end @end

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

@ -21,7 +21,6 @@
#define FFMPEG_KIT_SESSION_H #define FFMPEG_KIT_SESSION_H
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "ExecuteCallback.h"
#import "Log.h" #import "Log.h"
#import "LogCallback.h" #import "LogCallback.h"
#import "LogRedirectionStrategy.h" #import "LogRedirectionStrategy.h"
@ -35,13 +34,6 @@
@required @required
/**
* Returns the session specific execute callback.
*
* @return session specific execute callback
*/
- (ExecuteCallback)getExecuteCallback;
/** /**
* Returns the session specific log callback. * 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 * that end with SessionStateCompleted state. If a session is not started, still running or failed then
* this method returns nil. * 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 * not started, still running or failed
*/ */
- (ReturnCode*)getReturnCode; - (ReturnCode*)getReturnCode;
@ -206,6 +198,9 @@
/** /**
* Adds a new log entry for this session. * 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 * @param log log entry
*/ */
- (void)addLog:(Log*)log; - (void)addLog:(Log*)log;
@ -243,6 +238,13 @@
*/ */
- (BOOL)isFFprobe; - (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. * Cancels running the session.
*/ */

@ -16,10 +16,10 @@ export BASEDIR="$(pwd)"
export FFMPEG_KIT_BUILD_TYPE="ios" export FFMPEG_KIT_BUILD_TYPE="ios"
source "${BASEDIR}"/scripts/variable.sh source "${BASEDIR}"/scripts/variable.sh
source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh
disabled_libraries=()
# SET DEFAULTS SETTINGS # SET DEFAULTS SETTINGS
enable_default_ios_architectures enable_default_ios_architectures
enable_main_build
# SELECT XCODE VERSION USED FOR BUILDING # SELECT XCODE VERSION USED FOR BUILDING
XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh 2>>"${BASEDIR}"/build.log) 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 fi
# DETECT IOS SDK VERSION # 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 "\nINFO: Using SDK ${DETECTED_IOS_SDK_VERSION} by Xcode provided at $(xcode-select -p)\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "INFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "INFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -45,6 +45,9 @@ if [[ -z ${BUILD_VERSION} ]]; then
exit 1 exit 1
fi fi
# MAIN BUILDS ENABLED BY DEFAULT
enable_main_build
# PROCESS LTS BUILD OPTION FIRST AND SET BUILD TYPE: MAIN OR LTS # PROCESS LTS BUILD OPTION FIRST AND SET BUILD TYPE: MAIN OR LTS
for argument in "$@"; do for argument in "$@"; do
if [[ "$argument" == "-l" ]] || [[ "$argument" == "--lts" ]]; then if [[ "$argument" == "-l" ]] || [[ "$argument" == "--lts" ]]; then
@ -113,11 +116,24 @@ while [ ! $# -eq 0 ]; do
--enable-gpl) --enable-gpl)
GPL_ENABLED="yes" 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-*) --enable-*)
ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g') ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
enable_library "${ENABLED_LIBRARY}" 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-*) --disable-*)
DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g') DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
@ -142,7 +158,7 @@ done
# PROCESS FULL OPTION AS LAST OPTION # PROCESS FULL OPTION AS LAST OPTION
if [[ -n ${BUILD_FULL} ]]; then if [[ -n ${BUILD_FULL} ]]; then
for library in {0..58}; do for library in {0..61}; do
if [ ${GPL_ENABLED} == "yes" ]; then if [ ${GPL_ENABLED} == "yes" ]; then
enable_library "$(get_library_name "$library")" 1 enable_library "$(get_library_name "$library")" 1
else else
@ -153,6 +169,11 @@ if [[ -n ${BUILD_FULL} ]]; then
done done
fi fi
# DISABLE SPECIFIED LIBRARIES
for disabled_library in ${disabled_libraries[@]}; do
set_library "${disabled_library}" 0
done
# IF HELP DISPLAYED EXIT # IF HELP DISPLAYED EXIT
if [[ -n ${DISPLAY_HELP} ]]; then if [[ -n ${DISPLAY_HELP} ]]; then
display_help display_help
@ -160,41 +181,35 @@ if [[ -n ${DISPLAY_HELP} ]]; then
fi fi
# DISABLE NOT SUPPORTED ARCHITECTURES # 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_ARMV7}"
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_ARMV7S}"
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_I386}"
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_ARM64E}"
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_X86_64_MAC_CATALYST}"
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_MAC_CATALYST}"
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_ARM64_SIMULATOR}"
# CHECK SOME RULES FOR .framework BUNDLES # CHECK SOME RULES FOR .framework BUNDLES
# 1. DISABLE arm64-mac-catalyst WHEN arm64 IS ENABLED IN framework BUNDLES # 1. DISABLE arm64-mac-catalyst IN framework BUNDLES
if [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64}]} -eq 1 ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64_MAC_CATALYST}]} -eq 1 ]]; then 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 can not co-exist with arm64 in the same framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1 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" disable_arch "arm64-mac-catalyst"
fi fi
# 2. DISABLE arm64-simulator WHEN arm64 IS ENABLED IN framework BUNDLES # 2. DISABLE x86-64-mac-catalyst IN framework BUNDLES
if [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64}]} -eq 1 ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARM64_SIMULATOR}]} -eq 1 ]]; then if [[ ${NO_FRAMEWORK} -ne 1 ]] && [[ -z ${FFMPEG_KIT_XCF_BUILD} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_X86_64_MAC_CATALYST}]} -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 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 "arm64-simulator" disable_arch "x86-64-mac-catalyst"
fi fi
# 3. DISABLE arm64-simulator WHEN arm64-mac-catalyst IS ENABLED IN framework BUNDLES # 3. DISABLE arm64-simulator WHEN arm64 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 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 can not co-exist with arm64-mac-catalyst in the same framework bundle.\n" 1>>"${BASEDIR}"/build.log 2>&1 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" disable_arch "arm64-simulator"
fi fi
# 4. DISABLE x86-64-mac-catalyst WHEN x86-64 IS ENABLED IN framework BUNDLES echo -e "\nBuilding ffmpeg-kit ${BUILD_TYPE_ID}shared library for iOS\n"
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 -n "INFO: Building ffmpeg-kit ${BUILD_VERSION} ${BUILD_TYPE_ID}for iOS: " 1>>"${BASEDIR}"/build.log 2>&1 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 echo -e "$(date)\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -204,6 +219,7 @@ print_enabled_libraries
print_reconfigure_requested_libraries print_reconfigure_requested_libraries
print_rebuild_requested_libraries print_rebuild_requested_libraries
print_redownload_requested_libraries print_redownload_requested_libraries
print_custom_libraries
# VALIDATE GPL FLAGS # VALIDATE GPL FLAGS
for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVIDSTAB,$LIBRARY_RUBBERBAND}; do 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 done
echo -n -e "\nDownloading sources: " 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_gnu_config download_gnu_config
# DOWNLOAD LIBRARY SOURCES # DOWNLOAD LIBRARY SOURCES
downloaded_enabled_library_sources "${ENABLED_LIBRARIES[@]}" downloaded_library_sources "${ENABLED_LIBRARIES[@]}"
# THIS WILL SAVE ARCHITECTURES TO BUILD # THIS WILL SAVE ARCHITECTURES TO BUILD
TARGET_ARCH_LIST=() TARGET_ARCH_LIST=()
@ -244,7 +260,7 @@ for run_arch in {0..12}; do
TARGET_ARCH_LIST+=("${FULL_ARCH}") TARGET_ARCH_LIST+=("${FULL_ARCH}")
# CLEAR FLAGS # CLEAR FLAGS
for library in {0..58}; do for library in {0..61}; do
library_name=$(get_library_name "${library}") library_name=$(get_library_name "${library}")
unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")" unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")"
unset "$(echo "DEPENDENCY_REBUILT_${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" export FFMPEG_KIT_BUILD_TYPE="macos"
source "${BASEDIR}"/scripts/variable.sh source "${BASEDIR}"/scripts/variable.sh
source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh source "${BASEDIR}"/scripts/function-${FFMPEG_KIT_BUILD_TYPE}.sh
disabled_libraries=()
# SET DEFAULTS SETTINGS # SET DEFAULTS SETTINGS
enable_default_macos_architectures enable_default_macos_architectures
enable_main_build
# SELECT XCODE VERSION USED FOR BUILDING # SELECT XCODE VERSION USED FOR BUILDING
XCODE_FOR_FFMPEG_KIT=$(ls ~/.xcode.for.ffmpeg.kit.sh 2>>"${BASEDIR}"/build.log) 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 fi
# DETECT MACOS SDK VERSION # 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: Using SDK ${DETECTED_MACOS_SDK_VERSION} by Xcode provided at $(xcode-select -p)\n" 1>>"${BASEDIR}"/build.log 2>&1
echo -e "\nINFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "\nINFO: Build options: $*\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -45,6 +45,9 @@ if [[ -z ${BUILD_VERSION} ]]; then
exit 1 exit 1
fi fi
# MAIN BUILDS ENABLED BY DEFAULT
enable_main_build
# PROCESS LTS BUILD OPTION FIRST AND SET BUILD TYPE: MAIN OR LTS # PROCESS LTS BUILD OPTION FIRST AND SET BUILD TYPE: MAIN OR LTS
for argument in "$@"; do for argument in "$@"; do
if [[ "$argument" == "-l" ]] || [[ "$argument" == "--lts" ]]; then if [[ "$argument" == "-l" ]] || [[ "$argument" == "--lts" ]]; then
@ -113,11 +116,24 @@ while [ ! $# -eq 0 ]; do
--enable-gpl) --enable-gpl)
GPL_ENABLED="yes" 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-*) --enable-*)
ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g') ENABLED_LIBRARY=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
enable_library "${ENABLED_LIBRARY}" 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-*) --disable-*)
DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g') DISABLED_ARCH=$(echo $1 | sed -e 's/^--[A-Za-z]*-//g')
@ -137,7 +153,7 @@ done
# PROCESS FULL OPTION AS LAST OPTION # PROCESS FULL OPTION AS LAST OPTION
if [[ -n ${BUILD_FULL} ]]; then if [[ -n ${BUILD_FULL} ]]; then
for library in {0..58}; do for library in {0..61}; do
if [ ${GPL_ENABLED} == "yes" ]; then if [ ${GPL_ENABLED} == "yes" ]; then
enable_library "$(get_library_name "$library")" 1 enable_library "$(get_library_name "$library")" 1
else else
@ -148,6 +164,11 @@ if [[ -n ${BUILD_FULL} ]]; then
done done
fi fi
# DISABLE SPECIFIED LIBRARIES
for disabled_library in ${disabled_libraries[@]}; do
set_library "${disabled_library}" 0
done
# IF HELP DISPLAYED EXIT # IF HELP DISPLAYED EXIT
if [[ -n ${DISPLAY_HELP} ]]; then if [[ -n ${DISPLAY_HELP} ]]; then
display_help display_help
@ -155,9 +176,9 @@ if [[ -n ${DISPLAY_HELP} ]]; then
fi fi
# DISABLE NOT SUPPORTED ARCHITECTURES # 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 -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 echo -e "$(date)\n" 1>>"${BASEDIR}"/build.log 2>&1
@ -167,6 +188,7 @@ print_enabled_libraries
print_reconfigure_requested_libraries print_reconfigure_requested_libraries
print_rebuild_requested_libraries print_rebuild_requested_libraries
print_redownload_requested_libraries print_redownload_requested_libraries
print_custom_libraries
# VALIDATE GPL FLAGS # VALIDATE GPL FLAGS
for gpl_library in {$LIBRARY_X264,$LIBRARY_XVIDCORE,$LIBRARY_X265,$LIBRARY_LIBVIDSTAB,$LIBRARY_RUBBERBAND}; do 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 done
echo -n -e "\nDownloading sources: " 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_gnu_config download_gnu_config
# DOWNLOAD LIBRARY SOURCES # DOWNLOAD LIBRARY SOURCES
downloaded_enabled_library_sources "${ENABLED_LIBRARIES[@]}" downloaded_library_sources "${ENABLED_LIBRARIES[@]}"
# THIS WILL SAVE ARCHITECTURES TO BUILD # THIS WILL SAVE ARCHITECTURES TO BUILD
TARGET_ARCH_LIST=() TARGET_ARCH_LIST=()
@ -207,7 +229,7 @@ for run_arch in {0..12}; do
TARGET_ARCH_LIST+=("${FULL_ARCH}") TARGET_ARCH_LIST+=("${FULL_ARCH}")
# CLEAR FLAGS # CLEAR FLAGS
for library in {0..58}; do for library in {0..61}; do
library_name=$(get_library_name "${library}") library_name=$(get_library_name "${library}")
unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")" unset "$(echo "OK_${library_name}" | sed "s/\-/\_/g")"
unset "$(echo "DEPENDENCY_REBUILT_${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_INSTALL_PREFIX="${LIB_INSTALL_PREFIX}" \
-DCMAKE_SYSTEM_NAME=Generic \ -DCMAKE_SYSTEM_NAME=Generic \
-DCMAKE_C_COMPILER="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$CC" \ -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_LINKER="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$LD" \
-DCMAKE_AR="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$AR" \ -DCMAKE_AR="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$AR" \
-DCMAKE_AS="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$AS" \ -DCMAKE_AS="${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/${TOOLCHAIN}/bin/$AS" \
-DCMAKE_SYSTEM_PROCESSOR=$(get_cmake_system_processor) \ -DCMAKE_SYSTEM_PROCESSOR=$(get_cmake_system_processor) \
-DCMAKE_POSITION_INDEPENDENT_CODE=1 \ -DCMAKE_POSITION_INDEPENDENT_CODE=1 \
-DFFT_LIB=kissfft \ -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 -j$(get_cpu_count) || return 1
make install || return 1 make install || return 1
# CREATE PACKAGE CONFIG MANUALLY # 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 # REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/"${LIB_NAME}"/configure ]] || [[ ${RECONF_expat} -eq 1 ]]; then 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 fi
./configure \ ./configure \

@ -6,9 +6,6 @@ if [ -z "${HOST_PKG_CONFIG_PATH}" ]; then
exit 1 exit 1
fi fi
# ENABLE COMMON FUNCTIONS
source "${BASEDIR}"/scripts/function-"${FFMPEG_KIT_BUILD_TYPE}".sh 1>>"${BASEDIR}"/build.log 2>&1 || exit 1
LIB_NAME="ffmpeg" LIB_NAME="ffmpeg"
echo -e "----------------------------------------------------------------" 1>>"${BASEDIR}"/build.log 2>&1 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 LDFLAGS=$(get_ldflags "${LIB_NAME}")
export PKG_CONFIG_LIBDIR="${INSTALL_PKG_CONFIG_DIR}" 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 # SET BUILD OPTIONS
TARGET_CPU="" TARGET_CPU=""
@ -72,9 +69,9 @@ CONFIGURE_POSTFIX=""
HIGH_PRIORITY_INCLUDES="" HIGH_PRIORITY_INCLUDES=""
# SET CONFIGURE OPTIONS # SET CONFIGURE OPTIONS
for library in {1..58}; do for library in {0..61}; do
if [[ ${!library} -eq 1 ]]; then if [[ ${ENABLED_LIBRARIES[$library]} -eq 1 ]]; then
ENABLED_LIBRARY=$(get_library_name $((library - 1))) ENABLED_LIBRARY=$(get_library_name ${library})
echo -e "INFO: Enabling library ${ENABLED_LIBRARY}\n" 1>>"${BASEDIR}"/build.log 2>&1 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) libvidstab)
CFLAGS+=" $(pkg-config --cflags vidstab 2>>"${BASEDIR}"/build.log)" CFLAGS+=" $(pkg-config --cflags vidstab 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static 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) libvorbis)
CFLAGS+=" $(pkg-config --cflags vorbis 2>>"${BASEDIR}"/build.log)" 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)" LDFLAGS+=" $(pkg-config --libs --static openh264 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libopenh264" 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) opus)
CFLAGS+=" $(pkg-config --cflags opus 2>>"${BASEDIR}"/build.log)" CFLAGS+=" $(pkg-config --cflags opus 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static 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) rubberband)
CFLAGS+=" $(pkg-config --cflags rubberband 2>>"${BASEDIR}"/build.log)" CFLAGS+=" $(pkg-config --cflags rubberband 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static 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) sdl)
CFLAGS+=" $(pkg-config --cflags sdl2 2>>"${BASEDIR}"/build.log)" 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)" LDFLAGS+=" $(pkg-config --libs --static speex 2>>"${BASEDIR}"/build.log)"
CONFIGURE_POSTFIX+=" --enable-libspeex" 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) tesseract)
CFLAGS+=" $(pkg-config --cflags tesseract 2>>"${BASEDIR}"/build.log)" CFLAGS+=" $(pkg-config --cflags tesseract 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static 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) x264)
CFLAGS+=" $(pkg-config --cflags x264 2>>"${BASEDIR}"/build.log)" CFLAGS+=" $(pkg-config --cflags x264 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static 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) x265)
CFLAGS+=" $(pkg-config --cflags x265 2>>"${BASEDIR}"/build.log)" CFLAGS+=" $(pkg-config --cflags x265 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static 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) xvidcore)
CFLAGS+=" $(pkg-config --cflags xvidcore 2>>"${BASEDIR}"/build.log)" CFLAGS+=" $(pkg-config --cflags xvidcore 2>>"${BASEDIR}"/build.log)"
LDFLAGS+=" $(pkg-config --libs --static 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) expat)
CFLAGS+=" $(pkg-config --cflags expat 2>>"${BASEDIR}"/build.log)" 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 # THE FOLLOWING LIBRARIES SHOULD BE EXPLICITLY DISABLED TO PREVENT AUTODETECT
# NOTE THAT IDS MUST BE +1 OF THE INDEX VALUE # 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" CONFIGURE_POSTFIX+=" --disable-sdl2"
elif [[ ${library} -eq $((LIBRARY_ANDROID_ZLIB + 1)) ]]; then elif [[ ${library} -eq ${LIBRARY_ANDROID_ZLIB} ]]; then
CONFIGURE_POSTFIX+=" --disable-zlib" 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" CONFIGURE_POSTFIX+=" --disable-mediacodec"
elif [[ ${library} -eq ${LIBRARY_OPENSSL} ]]; then
CONFIGURE_POSTFIX+=" --disable-openssl"
fi fi
fi fi
done 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" 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 # 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 if [[ -z ${NO_WORKSPACE_CLEANUP_ffmpeg} ]]; then
echo -e "INFO: Cleaning workspace for ${LIB_NAME}\n" 1>>"${BASEDIR}"/build.log 2>&1 echo -e "INFO: Cleaning workspace for ${LIB_NAME}\n" 1>>"${BASEDIR}"/build.log 2>&1
make distclean 2>/dev/null 1>/dev/null 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 fi
# UPDATE BUILD FLAGS # UPDATE BUILD FLAGS
@ -350,19 +389,19 @@ export CFLAGS="${HIGH_PRIORITY_INCLUDES} ${CFLAGS}"
ulimit -n 2048 1>>"${BASEDIR}"/build.log 2>&1 ulimit -n 2048 1>>"${BASEDIR}"/build.log 2>&1
########################### CUSTOMIZATIONS ####################### ########################### 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 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/file.c 1>>"${BASEDIR}"/build.log 2>&1
git checkout libavformat/protocols.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 git checkout libavutil 1>>"${BASEDIR}"/build.log 2>&1
# 1. Use thread local log levels # 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 # 2. Set friendly ffmpeg version
FFMPEG_VERSION="v$(get_user_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 # 3. Enable ffmpeg-kit protocols
if [[ ${NO_FFMPEG_KIT_PROTOCOLS} == "1" ]]; then 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.h >> libavutil/file.h
cat ../../tools/protocols/libavutil_file.c >> libavutil/file.c 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_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 echo -e "\nINFO: Enabled custom ffmpeg-kit protocols\n" 1>>"${BASEDIR}"/build.log 2>&1
fi fi
@ -387,25 +426,27 @@ fi
--enable-version3 \ --enable-version3 \
--arch="${TARGET_ARCH}" \ --arch="${TARGET_ARCH}" \
--cpu="${TARGET_CPU}" \ --cpu="${TARGET_CPU}" \
--target-os=android \
${ASM_OPTIONS} \
--ar="${AR}" \
--cc="${CC}" \ --cc="${CC}" \
--cxx="${CXX}" \ --cxx="${CXX}" \
--ranlib="${RANLIB}" \ --ranlib="${RANLIB}" \
--strip="${STRIP}" \ --strip="${STRIP}" \
--nm="${NM}" \ --nm="${NM}" \
--extra-libs="$(pkg-config --libs --static cpu-features)" \ --extra-libs="$(pkg-config --libs --static cpu-features)" \
--target-os=android \ --disable-autodetect \
${ASM_OPTIONS} \
--enable-cross-compile \ --enable-cross-compile \
--enable-pic \ --enable-pic \
--enable-jni \ --enable-jni \
--enable-optimizations \ --enable-optimizations \
--enable-swscale \ --enable-swscale \
${BUILD_LIBRARY_OPTIONS} \ ${BUILD_LIBRARY_OPTIONS} \
--enable-pthreads \
--enable-v4l2-m2m \ --enable-v4l2-m2m \
--disable-outdev=fbdev \ --disable-outdev=fbdev \
--disable-indev=fbdev \ --disable-indev=fbdev \
${SIZE_OPTIONS} \ ${SIZE_OPTIONS} \
--disable-openssl \
--disable-xmm-clobber-test \ --disable-xmm-clobber-test \
${DEBUG_OPTIONS} \ ${DEBUG_OPTIONS} \
--disable-neon-clobber-test \ --disable-neon-clobber-test \
@ -462,7 +503,7 @@ fi
# DELETE THE PREVIOUS BUILD OF THE LIBRARY BEFORE INSTALLING # DELETE THE PREVIOUS BUILD OF THE LIBRARY BEFORE INSTALLING
if [ -d "${FFMPEG_LIBRARY_PATH}" ]; then 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 fi
make install 1>>"${BASEDIR}"/build.log 2>&1 make install 1>>"${BASEDIR}"/build.log 2>&1

@ -3,16 +3,19 @@
# ALWAYS CLEAN THE PREVIOUS BUILD # ALWAYS CLEAN THE PREVIOUS BUILD
make distclean 2>/dev/null 1>/dev/null 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 # REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_fontconfig} -eq 1 ]]; then 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 fi
# WORKAROUND TO FIX NOT-APPLIED HAVE_POSIX_FADVISE define ON MACOS # WORKAROUND TO FIX NOT-APPLIED HAVE_POSIX_FADVISE define ON MACOS
if [[ -n ${FFMPEG_KIT_LTS_BUILD} ]]; then 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 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 fi
./configure \ ./configure \
@ -34,4 +37,4 @@ make -j$(get_cpu_count) || return 1
make install || return 1 make install || return 1
# CREATE PACKAGE CONFIG MANUALLY # 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 make install || return 1
# CREATE PACKAGE CONFIG MANUALLY # 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 # REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_fribidi} -eq 1 ]]; then 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 fi
./configure \ ./configure \

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

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

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

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

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

@ -56,4 +56,4 @@ make -j$(get_cpu_count) || return 1
make install || return 1 make install || return 1
# CREATE PACKAGE CONFIG MANUALLY # 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 # REGENERATE BUILD FILES IF NECESSARY OR REQUESTED
if [[ ! -f "${BASEDIR}"/src/"${LIB_NAME}"/configure ]] || [[ ${RECONF_libass} -eq 1 ]]; then 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 fi
./configure \ ./configure \

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

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

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

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

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

Loading…
Cancel
Save