diff --git a/README.md b/README.md index b87faa6..d36adfb 100644 --- a/README.md +++ b/README.md @@ -19,28 +19,37 @@ demonstrate how SAF uris can be used with `FFmpegKit`. Test applications are tagged with `ffmpeg-kit` release they depend on. -| Platform | FFmpegKit Version | Tag| -| :----: | :----: |:----: | -| Flutter | 4.5.0 | [4.5.0](https://github.com/tanersener/ffmpeg-kit-test/tree/flutter.v4.5.0) | -| Flutter | 4.5.0-LTS | [4.5.0-LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/flutter.v4.5.0.lts) | -| React Native | 4.5.0 | [4.5.0](https://github.com/tanersener/ffmpeg-kit-test/tree/react.native.v4.5.0) | -| Android | 4.5 | [4.5](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.5) | -| Android | 4.5.LTS | [4.5.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.5.lts) | -| iOS | 4.5 | [4.5](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.5) | -| iOS | 4.5.LTS | [4.5.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.5.lts) | -| macOS | 4.5 | [4.5](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.5) | -| macOS | 4.5.LTS | [4.5.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.5.lts) | -| tvOS | 4.5 | [4.5](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.5) | -| tvOS | 4.5.LTS | [4.5.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.5.lts) | -| - | - | - | -| Android | 4.4 | [4.4](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.4) | -| Android | 4.4.LTS | [4.4.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.4.lts) | -| iOS | 4.4 | [4.4](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.4) | -| iOS | 4.4.LTS | [4.4.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.4.lts) | -| macOS | 4.4 | [4.4](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.4) | -| macOS | 4.4.LTS | [4.4.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.4.lts) | -| tvOS | 4.4 | [4.4](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.4) | -| tvOS | 4.4.LTS | [4.4.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.4.lts) | +| Platform | FFmpegKit Version | Tag| +| :----: |:-----------------:|:----: | +| Android | 4.5.1 | [4.5.1](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.5.1) | +| Android | 4.5.1.LTS | [4.5.1.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.5.1.lts) | +| iOS | 4.5.1 | [4.5.1](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.5.1) | +| iOS | 4.5.1.LTS | [4.5.1.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.5.1.lts) | +| macOS | 4.5.1 | [4.5.1](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.5.1) | +| macOS | 4.5.1.LTS | [4.5.1.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.5.1.lts) | +| tvOS | 4.5.1 | [4.5.1](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.5.1) | +| tvOS | 4.5.1.LTS | [4.5.1.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.5.1.lts) | +| - | - | - | +| Flutter | 4.5.0 | [4.5.0](https://github.com/tanersener/ffmpeg-kit-test/tree/flutter.v4.5.0) | +| Flutter | 4.5.0-LTS | [4.5.0-LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/flutter.v4.5.0.lts) | +| React Native | 4.5.0 | [4.5.0](https://github.com/tanersener/ffmpeg-kit-test/tree/react.native.v4.5.0) | +| Android | 4.5 | [4.5](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.5) | +| Android | 4.5.LTS | [4.5.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.5.lts) | +| iOS | 4.5 | [4.5](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.5) | +| iOS | 4.5.LTS | [4.5.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.5.lts) | +| macOS | 4.5 | [4.5](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.5) | +| macOS | 4.5.LTS | [4.5.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.5.lts) | +| tvOS | 4.5 | [4.5](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.5) | +| tvOS | 4.5.LTS | [4.5.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.5.lts) | +| - | - | - | +| Android | 4.4 | [4.4](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.4) | +| Android | 4.4.LTS | [4.4.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/android.v4.4.lts) | +| iOS | 4.4 | [4.4](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.4) | +| iOS | 4.4.LTS | [4.4.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/ios.v4.4.lts) | +| macOS | 4.4 | [4.4](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.4) | +| macOS | 4.4.LTS | [4.4.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/macos.v4.4.lts) | +| tvOS | 4.4 | [4.4](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.4) | +| tvOS | 4.4.LTS | [4.4.LTS](https://github.com/tanersener/ffmpeg-kit-test/tree/tvos.v4.4.lts) | ### License diff --git a/android/test-app-local-dependency/build.gradle b/android/test-app-local-dependency/build.gradle index 35963c3..556c649 100644 --- a/android/test-app-local-dependency/build.gradle +++ b/android/test-app-local-dependency/build.gradle @@ -14,8 +14,8 @@ android { applicationId "com.arthenica.ffmpegkit.test" minSdkVersion 24 targetSdkVersion 30 - versionCode 240450 - versionName "4.5" + versionCode 240451 + versionName "4.5.1" } buildTypes { debug { @@ -53,7 +53,7 @@ android.applicationVariants.all { variant -> dependencies { // implementation files('../../../ffmpeg-kit/prebuilt/bundle-android-aar-lts/ffmpeg-kit/ffmpeg-kit.aar') implementation files('../../../ffmpeg-kit/prebuilt/bundle-android-aar/ffmpeg-kit/ffmpeg-kit.aar') - implementation 'com.arthenica:smart-exception-java:0.1.0' + implementation 'com.arthenica:smart-exception-java:0.1.1' implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/AudioTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/AudioTabFragment.java index 1925908..2c7c11f 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/AudioTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/AudioTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.view.View; @@ -36,21 +39,16 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; import com.arthenica.ffmpegkit.util.DialogUtil; import java.io.File; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class AudioTabFragment extends Fragment implements AdapterView.OnItemSelectedListener { private AlertDialog progressDialog; @@ -105,12 +103,11 @@ public void enableLogCallback() { @Override public void apply(final com.arthenica.ffmpegkit.Log log) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(log.getMessage()); - return null; } }); } @@ -153,19 +150,19 @@ public void encodeAudio() { android.util.Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); hideProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(returnCode)) { Popup.show(requireContext(), "Encode completed successfully."); android.util.Log.d(TAG, "Encode completed successfully."); @@ -173,8 +170,6 @@ public Object call() { Popup.show(requireContext(), "Encode failed. Please check logs for the details."); android.util.Log.d(TAG, String.format("Encode failed with state %s and rc %s.%s", state, returnCode, notNull(session.getFailStackTrace(), "\n"))); } - - return null; } }); } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/CommandTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/CommandTabFragment.java index 38592b6..f10dbf7 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/CommandTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/CommandTabFragment.java @@ -22,6 +22,8 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.AndroidRuntimeException; @@ -34,20 +36,17 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.FFprobeSession; +import com.arthenica.ffmpegkit.FFprobeSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.LogRedirectionStrategy; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; - public class CommandTabFragment extends Fragment { private EditText commandText; private TextView outputText; @@ -105,22 +104,21 @@ public void runFFmpeg() { android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process started with arguments:\n'%s'", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); - android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", state, returnCode, notNull(session.getFailStackTrace(), "\n"))); + android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", FFmpegKitConfig.sessionStateToString(state), returnCode, notNull(session.getFailStackTrace(), "\n"))); - if (state == SessionState.FAILED || !returnCode.isSuccess()) { - MainActivity.addUIAction(new Callable() { + if (state == SessionState.FAILED || !returnCode.isValueSuccess()) { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { Popup.show(requireContext(), "Command failed. Please check output for the details."); - return null; } }); } @@ -129,12 +127,11 @@ public Object call() { @Override public void apply(final com.arthenica.ffmpegkit.Log log) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(log.getMessage()); - return null; } }); @@ -152,31 +149,29 @@ public void runFFprobe() { android.util.Log.d(MainActivity.TAG, String.format("FFprobe process started with arguments:\n'%s'", ffprobeCommand)); - FFprobeSession session = new FFprobeSession(FFmpegKitConfig.parseArguments(ffprobeCommand), new ExecuteCallback() { + FFprobeSession session = new FFprobeSession(FFmpegKitConfig.parseArguments(ffprobeCommand), new FFprobeSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFprobeSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(session.getOutput()); - return null; } }); - android.util.Log.d(MainActivity.TAG, String.format("FFprobe process exited with state %s and rc %s.%s", state, returnCode, notNull(session.getFailStackTrace(), "\n"))); + android.util.Log.d(MainActivity.TAG, String.format("FFprobe process exited with state %s and rc %s.%s", FFmpegKitConfig.sessionStateToString(state), returnCode, notNull(session.getFailStackTrace(), "\n"))); - if (state == SessionState.FAILED || !session.getReturnCode().isSuccess()) { - MainActivity.addUIAction(new Callable() { + if (state == SessionState.FAILED || !session.getReturnCode().isValueSuccess()) { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { Popup.show(requireContext(), "Command failed. Please check output for the details."); - return null; } }); } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/ConcurrentExecutionTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/ConcurrentExecutionTabFragment.java index 855c7af..736d4d7 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/ConcurrentExecutionTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/ConcurrentExecutionTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; @@ -32,13 +35,12 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; import com.arthenica.ffmpegkit.util.ResourcesUtil; import com.arthenica.smartexception.java.Exceptions; @@ -46,10 +48,6 @@ import java.io.File; import java.io.IOException; import java.util.Locale; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class ConcurrentExecutionTabFragment extends Fragment { private TextView outputText; @@ -161,12 +159,11 @@ public void enableLogCallback() { @Override public void apply(final com.arthenica.ffmpegkit.Log log) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(String.format(Locale.getDefault(), "%d -> %s", log.getSessionId(), log.getMessage())); - return null; } }); } @@ -191,10 +188,10 @@ public void encodeVideo(final int buttonNumber) { Log.d(TAG, String.format("FFmpeg process starting for button %d with arguments\n'%s'.", buttonNumber, ffmpegCommand)); - final FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + final FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/HttpsTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/HttpsTabFragment.java index a49457e..5854776 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/HttpsTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/HttpsTabFragment.java @@ -22,6 +22,8 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; @@ -33,12 +35,12 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; +import com.arthenica.ffmpegkit.Chapter; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFprobeKit; import com.arthenica.ffmpegkit.MediaInformation; import com.arthenica.ffmpegkit.MediaInformationSession; -import com.arthenica.ffmpegkit.Session; +import com.arthenica.ffmpegkit.MediaInformationSessionCompleteCallback; import com.arthenica.ffmpegkit.StreamInformation; import org.json.JSONObject; @@ -46,8 +48,6 @@ import java.util.Iterator; import java.util.Random; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; - public class HttpsTabFragment extends Fragment { public static final String HTTPS_TEST_DEFAULT_URL = "https://download.blender.org/peach/trailer/trailer_1080p.ogg"; @@ -165,7 +165,7 @@ public void runGetMediaInformation(final int buttonNumber) { } // EXECUTE - FFprobeKit.getMediaInformationAsync(testUrl, createNewExecuteCallback()); + FFprobeKit.getMediaInformationAsync(testUrl, createNewCompleteCallback()); } public void setActive() { @@ -199,15 +199,15 @@ private String getRandomTestUrl() { } } - private ExecuteCallback createNewExecuteCallback() { - return new ExecuteCallback() { + private MediaInformationSessionCompleteCallback createNewCompleteCallback() { + return new MediaInformationSessionCompleteCallback() { @Override - public void apply(Session session) { + public void apply(MediaInformationSession session) { // SYNC THE OUTPUT SO WE CAN IDENTIFY THE FILES synchronized (outputLock) { - final MediaInformation information = ((MediaInformationSession) session).getMediaInformation(); + final MediaInformation information = session.getMediaInformation(); if (information == null) { appendOutput("Get media information failed\n"); appendOutput(String.format("State: %s\n", session.getState())); @@ -232,12 +232,10 @@ public void apply(Session session) { } if (information.getTags() != null) { JSONObject tags = information.getTags(); - if (tags != null) { - Iterator keys = tags.keys(); - while (keys.hasNext()) { - String next = keys.next(); - appendOutput("Tag: " + next + ":" + tags.optString(next) + "\n"); - } + Iterator keys = tags.keys(); + while (keys.hasNext()) { + String next = keys.next(); + appendOutput("Tag: " + next + ":" + tags.optString(next) + "\n"); } } if (information.getStreams() != null) { @@ -299,14 +297,45 @@ public void apply(Session session) { if (stream.getTags() != null) { JSONObject tags = stream.getTags(); + Iterator keys = tags.keys(); + while (keys.hasNext()) { + String next = keys.next(); + appendOutput(String.format("Stream tag: %s:%s\n", next, tags.optString(next))); + } + } + } + } + if (information.getChapters() != null) { + for (Chapter chapter : information.getChapters()) { + if (chapter.getId() != null) { + appendOutput("Chapter id: " + chapter.getId() + "\n"); + } + if (chapter.getTimeBase() != null) { + appendOutput("Chapter time base: " + chapter.getTimeBase() + "\n"); + } + if (chapter.getStart() != null) { + appendOutput("Chapter start: " + chapter.getStart() + "\n"); + } + if (chapter.getStartTime() != null) { + appendOutput("Chapter start time: " + chapter.getStartTime() + "\n"); + } + if (chapter.getEnd() != null) { + appendOutput("Chapter end: " + chapter.getEnd() + "\n"); + } + if (chapter.getEndTime() != null) { + appendOutput("Chapter end time: " + chapter.getEndTime() + "\n"); + } + if (chapter.getTags() != null) { + JSONObject tags = chapter.getTags(); if (tags != null) { Iterator keys = tags.keys(); while (keys.hasNext()) { String next = keys.next(); - appendOutput(String.format("Stream tag: %s:%s\n", next, tags.optString(next))); + appendOutput(String.format("Chapter tag: %s:%s\n", next, tags.optString(next))); } } } + } } } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/MainActivity.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/MainActivity.java index 2ac2593..8fec024 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/MainActivity.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/MainActivity.java @@ -27,6 +27,7 @@ import android.graphics.Color; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.util.Log; import android.view.Gravity; import android.view.View; @@ -53,9 +54,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; -import java.util.Queue; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentLinkedQueue; public class MainActivity extends AppCompatActivity { @@ -71,30 +69,7 @@ public class MainActivity extends AppCompatActivity { Exceptions.registerRootPackage("com.arthenica"); } - protected static final Queue> actionQueue = new ConcurrentLinkedQueue<>(); - - protected static final Handler handler = new Handler(); - - protected static final Runnable runnable = new Runnable() { - - @Override - public void run() { - Callable callable; - - do { - callable = actionQueue.poll(); - if (callable != null) { - try { - callable.call(); - } catch (final Exception e) { - android.util.Log.e(TAG, String.format("Running UI action received error.%s.", Exceptions.getStackTraceString(e))); - } - } - } while (callable != null); - - handler.postDelayed(this, 250); - } - }; + protected static final Handler handler = new Handler(Looper.getMainLooper()); @Override protected void onCreate(final Bundle savedInstanceState) { @@ -127,8 +102,6 @@ protected void onCreate(final Bundle savedInstanceState) { final ViewPager viewPager = findViewById(R.id.pager); viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager(), this)); - waitForUIAction(); - // VERIFY PERMISSIONS int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { @@ -157,13 +130,6 @@ protected void onCreate(final Bundle savedInstanceState) { FFmpegKitConfig.setLogLevel(Level.AV_LOG_INFO); } - @Override - protected void onDestroy() { - super.onDestroy(); - - handler.removeCallbacks(runnable); - } - public static void listFFmpegSessions() { List ffmpegSessions = FFmpegKit.listSessions(); Log.d(TAG, "Listing FFmpeg sessions."); @@ -181,7 +147,7 @@ public static void listFFmpegSessions() { } public static void listFFprobeSessions() { - List ffprobeSessions = FFprobeKit.listSessions(); + List ffprobeSessions = FFprobeKit.listFFprobeSessions(); Log.d(TAG, "Listing FFprobe sessions."); for (int i = 0; i < ffprobeSessions.size(); i++) { FFprobeSession session = ffprobeSessions.get(i); @@ -196,12 +162,8 @@ public static void listFFprobeSessions() { Log.d(TAG, "Listed FFprobe sessions."); } - public static void waitForUIAction() { - handler.postDelayed(runnable, 250); - } - - public static void addUIAction(final Callable callable) { - actionQueue.add(callable); + public static void addUIAction(final Runnable runnable) { + handler.post(runnable); } protected void registerAppFont() throws IOException { diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/OtherTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/OtherTabFragment.java index e68ca48..d8322dc 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/OtherTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/OtherTabFragment.java @@ -39,16 +39,16 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; +import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.util.ResourcesUtil; import com.arthenica.smartexception.java.Exceptions; import java.io.File; import java.io.IOException; -import java.util.concurrent.Callable; public class OtherTabFragment extends Fragment implements AdapterView.OnItemSelectedListener { @@ -119,6 +119,9 @@ public void runTest() { case "webp": testWebp(); break; + case "zscale": + testZscale(); + break; } } @@ -134,10 +137,10 @@ protected void testChromaprint() { android.util.Log.d(TAG, String.format("Creating audio sample with '%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(Session session) { + public void apply(FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); if (ReturnCode.isSuccess(session.getReturnCode())) { @@ -147,14 +150,14 @@ public void apply(Session session) { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", chromaprintCommand)); - FFmpegKit.executeAsync(chromaprintCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(chromaprintCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { - MainActivity.addUIAction(new Callable() { + public void apply(final FFmpegSession session) { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); if (ReturnCode.isSuccess(session.getReturnCode())) { @@ -162,13 +165,11 @@ public Object call() { } else { Popup.show(requireContext(), "Testing chromaprint failed. Please check logs for the details."); } - return null; } }); } }, log -> MainActivity.addUIAction(() -> { appendOutput(log.getMessage()); - return null; }), null); } else { @@ -185,15 +186,14 @@ protected void testDav1d() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); } }, log -> MainActivity.addUIAction(() -> { appendOutput(log.getMessage()); - return null; }), null); } @@ -210,21 +210,22 @@ protected void testWebp() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(Session session) { + public void apply(FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); - if (ReturnCode.isSuccess(session.getReturnCode())) { - Popup.show(requireContext(), "Encode webp completed successfully."); - } else { - Popup.show(requireContext(), "Encode webp failed. Please check logs for the details."); - } + MainActivity.addUIAction(() -> { + if (ReturnCode.isSuccess(session.getReturnCode())) { + Popup.show(requireContext(), "Encode webp completed successfully."); + } else { + Popup.show(requireContext(), "Encode webp failed. Please check logs for the details."); + } + }); } }, log -> MainActivity.addUIAction(() -> { appendOutput(log.getMessage()); - return null; }), null); } catch (IOException e) { @@ -233,6 +234,35 @@ public void apply(Session session) { } } + protected void testZscale() { + final File videoFile = new File(requireContext().getFilesDir(), "video.mp4"); + final File zscaledVideoFile = new File(requireContext().getFilesDir(), "video.zscaled.mp4"); + + Log.d(TAG, "Testing 'zscale' filter with video file created on the Video tab"); + + final String ffmpegCommand = Video.generateZscaleVideoScript(videoFile.getAbsolutePath(), zscaledVideoFile.getAbsolutePath()); + + Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); + + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { + + @Override + public void apply(FFmpegSession session) { + Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); + + MainActivity.addUIAction(() -> { + if (ReturnCode.isSuccess(session.getReturnCode())) { + Popup.show(requireContext(), "zscale completed successfully."); + } else { + Popup.show(requireContext(), "zscale failed. Please check logs for the details."); + } + }); + } + }, log -> MainActivity.addUIAction(() -> { + appendOutput(log.getMessage()); + }), null); + } + public File getChromaprintSampleFile() { return new File(requireContext().getFilesDir(), "audio-sample.wav"); } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/PipeTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/PipeTabFragment.java index 69a57a5..2fd2bea 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/PipeTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/PipeTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.media.MediaPlayer; import android.net.Uri; import android.os.AsyncTask; @@ -37,12 +40,12 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; import com.arthenica.ffmpegkit.Statistics; import com.arthenica.ffmpegkit.StatisticsCallback; @@ -54,10 +57,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class PipeTabFragment extends Fragment { private VideoView videoView; @@ -113,13 +112,12 @@ public void enableStatisticsCallback() { @Override public void apply(final Statistics newStatistics) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { PipeTabFragment.this.statistics = newStatistics; updateProgressDialog(); - return null; } }); } @@ -162,10 +160,10 @@ public void createVideo() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); @@ -178,18 +176,16 @@ public void apply(final Session session) { FFmpegKitConfig.closeFFmpegPipe(pipe2); FFmpegKitConfig.closeFFmpegPipe(pipe3); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(returnCode)) { Log.d(TAG, "Create completed successfully; playing video."); playVideo(); } else { Popup.show(requireContext(), "Create failed. Please check logs for the details."); } - - return null; } }); } @@ -270,12 +266,11 @@ protected void updateProgressDialog() { protected void hideProgressDialog() { progressDialog.dismiss(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { PipeTabFragment.this.progressDialog = DialogUtil.createProgressDialog(requireContext(), "Creating video"); - return null; } }); } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/SafTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/SafTabFragment.java index 25299b4..e7c9dad 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/SafTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/SafTabFragment.java @@ -22,6 +22,10 @@ package com.arthenica.ffmpegkit.test; +import static android.app.Activity.RESULT_OK; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.content.Intent; import android.net.Uri; import android.os.Build; @@ -37,15 +41,14 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.FFprobeKit; import com.arthenica.ffmpegkit.FFprobeSession; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; import com.arthenica.ffmpegkit.Statistics; import com.arthenica.ffmpegkit.StatisticsCallback; @@ -56,11 +59,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.util.concurrent.Callable; - -import static android.app.Activity.RESULT_OK; -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class SafTabFragment extends Fragment { private TextView outputText; @@ -132,12 +130,11 @@ private void enableLogCallback() { @Override public void apply(final com.arthenica.ffmpegkit.Log log) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(log.getMessage()); - return null; } }); } @@ -167,7 +164,7 @@ private void encodeVideo() { final File image1File = new File(requireContext().getCacheDir(), "machupicchu.jpg"); final File image2File = new File(requireContext().getCacheDir(), "pyramid.jpg"); final File image3File = new File(requireContext().getCacheDir(), "stonehenge.jpg"); - final String videoPath = FFmpegKitConfig.getSafParameterForWrite(requireContext(), outUri); + final String videoPath = FFmpegKitConfig.getSafParameter(requireContext(), outUri, "rw"); try { String selectedCodec = getCodec(videoPath); @@ -183,10 +180,10 @@ private void encodeVideo() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); @@ -194,17 +191,15 @@ public void apply(final Session session) { hideProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(session.getReturnCode())) { Log.d(TAG, "Encode completed successfully."); } else { Popup.show(requireContext(), "Encode failed. Please check logs for the details."); } - - return null; } }); } @@ -307,7 +302,7 @@ private String getCustomOptions(String videoCodec) { default: // kvazaar, mpeg4, x264, xvid - return ""; + return "-movflags faststart "; } } @@ -316,13 +311,12 @@ private void enableStatisticsCallback() { @Override public void apply(final Statistics newStatistics) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { statistics = newStatistics; updateProgressDialog(); - return null; } }); } @@ -358,12 +352,11 @@ private void updateProgressDialog() { private void hideProgressDialog() { progressDialog.dismiss(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding video"); - return null; } }); } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/SubtitleTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/SubtitleTabFragment.java index 4dac4f1..fec5879 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/SubtitleTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/SubtitleTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; @@ -36,12 +39,12 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.Statistics; import com.arthenica.ffmpegkit.StatisticsCallback; import com.arthenica.ffmpegkit.util.DialogUtil; @@ -51,10 +54,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class SubtitleTabFragment extends Fragment { @@ -118,13 +117,12 @@ public void enableStatisticsCallback() { @Override public void apply(final Statistics newStatistics) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { SubtitleTabFragment.this.statistics = newStatistics; updateProgressDialog(); - return null; } }); } @@ -158,20 +156,20 @@ public void burnSubtitles() { state = State.CREATING; - sessionId = FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + sessionId = FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); hideCreateProgressDialog(); if (ReturnCode.isSuccess(session.getReturnCode())) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { Log.d(TAG, "Create completed successfully; burning subtitles."); @@ -183,17 +181,17 @@ public Object call() { state = State.BURNING; - FFmpegKit.executeAsync(burnSubtitlesCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(burnSubtitlesCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session secondSession) { + public void apply(final FFmpegSession secondSession) { hideBurnProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(secondSession.getReturnCode())) { Log.d(TAG, "Burn subtitles completed successfully; playing video."); playVideo(); @@ -204,14 +202,10 @@ public Object call() { Popup.show(requireContext(), "Burn subtitles failed. Please check logs for the details."); Log.d(TAG, String.format("Burn subtitles failed with state %s and rc %s.%s", secondSession.getState(), secondSession.getReturnCode(), notNull(secondSession.getFailStackTrace(), "\n"))); } - - return null; } }); } }); - - return null; } }); } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/VidStabTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/VidStabTabFragment.java index f45b69b..21b6e4b 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/VidStabTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/VidStabTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; @@ -35,22 +38,18 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.util.DialogUtil; import com.arthenica.ffmpegkit.util.ResourcesUtil; import com.arthenica.smartexception.java.Exceptions; import java.io.File; import java.io.IOException; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class VidStabTabFragment extends Fragment { private VideoView videoView; @@ -138,18 +137,18 @@ public void stabilizeVideo() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); hideCreateProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(session.getReturnCode())) { Log.d(TAG, "Create completed successfully; stabilizing video."); @@ -160,10 +159,10 @@ public Object call() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", analyzeVideoCommand)); - FFmpegKit.executeAsync(analyzeVideoCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(analyzeVideoCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session secondSession) { + public void apply(final FFmpegSession secondSession) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", secondSession.getState(), secondSession.getReturnCode(), notNull(secondSession.getFailStackTrace(), "\n"))); if (ReturnCode.isSuccess(secondSession.getReturnCode())) { @@ -171,18 +170,18 @@ public void apply(final Session secondSession) { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", stabilizeVideoCommand)); - FFmpegKit.executeAsync(stabilizeVideoCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(stabilizeVideoCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session thirdSession) { + public void apply(final FFmpegSession thirdSession) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", thirdSession.getState(), thirdSession.getReturnCode(), notNull(thirdSession.getFailStackTrace(), "\n"))); hideStabilizeProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(thirdSession.getReturnCode())) { Log.d(TAG, "Stabilize video completed successfully; playing videos."); playVideo(); @@ -190,16 +189,16 @@ public Object call() { } else { Popup.show(requireContext(), "Stabilize video failed. Please check logs for the details."); } - - return null; } }); } }); } else { - hideStabilizeProgressDialog(); - Popup.show(requireContext(), "Stabilize video failed. Please check logs for the details."); + MainActivity.addUIAction(() -> { + hideStabilizeProgressDialog(); + Popup.show(requireContext(), "Stabilize video failed. Please check logs for the details."); + }); } } }); @@ -207,8 +206,6 @@ public Object call() { } else { Popup.show(requireContext(), "Create video failed. Please check logs for the details."); } - - return null; } }); } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/Video.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/Video.java index b3304e1..fe0daf7 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/Video.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/Video.java @@ -53,6 +53,10 @@ static String generateCreateVideoWithPipesScript(final String image1Pipe, final } static String generateEncodeVideoScript(final String image1Path, final String image2Path, final String image3Path, final String videoFilePath, final String videoCodec, final String customOptions) { + return generateEncodeVideoScript(image1Path, image2Path, image3Path, videoFilePath, videoCodec, "yuv420p", customOptions); + } + + static String generateEncodeVideoScript(final String image1Path, final String image2Path, final String image3Path, final String videoFilePath, final String videoCodec, final String pixelFormat, final String customOptions) { return "-hide_banner -y -loop 1 -i \"" + image1Path + "\" " + "-loop 1 -i '" + image2Path + "' " + @@ -69,7 +73,7 @@ static String generateEncodeVideoScript(final String image1Path, final String im "[stream3out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30)[stream3starting];" + "[stream2starting][stream1ending]blend=all_expr=\'if(gte(X,(W/2)*T/1)*lte(X,W-(W/2)*T/1),B,A)\':shortest=1[stream2blended];" + "[stream3starting][stream2ending]blend=all_expr=\'if(gte(X,(W/2)*T/1)*lte(X,W-(W/2)*T/1),B,A)\':shortest=1[stream3blended];" + - "[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\"" + + "[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=" + pixelFormat + "[video]\"" + " -map [video] -vsync 2 -async 1 " + customOptions + "-c:v " + videoCodec.toLowerCase(Locale.ENGLISH) + " -r 30 " + videoFilePath; } @@ -93,4 +97,11 @@ static String generateShakingVideoScript(final String image1Path, final String i " -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 " + videoFilePath; } + static String generateZscaleVideoScript(final String inputVideoFilePath, final String outputVideoFilePath) { + return "-y -i " + + inputVideoFilePath + + " -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p " + + outputVideoFilePath; + } + } diff --git a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/VideoTabFragment.java b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/VideoTabFragment.java index 2246ea1..ab25178 100644 --- a/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/VideoTabFragment.java +++ b/android/test-app-local-dependency/src/main/java/com/arthenica/ffmpegkit/test/VideoTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; @@ -39,13 +42,12 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.Statistics; import com.arthenica.ffmpegkit.StatisticsCallback; import com.arthenica.ffmpegkit.util.DialogUtil; @@ -55,10 +57,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class VideoTabFragment extends Fragment implements AdapterView.OnItemSelectedListener { private VideoView videoView; @@ -144,22 +142,22 @@ public void encodeVideo() { ResourcesUtil.resourceToFile(getResources(), R.drawable.pyramid, image2File); ResourcesUtil.resourceToFile(getResources(), R.drawable.stonehenge, image3File); - final String ffmpegCommand = Video.generateEncodeVideoScript(image1File.getAbsolutePath(), image2File.getAbsolutePath(), image3File.getAbsolutePath(), videoFile.getAbsolutePath(), getSelectedVideoCodec(), getCustomOptions()); + final String ffmpegCommand = Video.generateEncodeVideoScript(image1File.getAbsolutePath(), image2File.getAbsolutePath(), image3File.getAbsolutePath(), videoFile.getAbsolutePath(), getSelectedVideoCodec(), getPixelFormat(), getCustomOptions()); Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - final FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + final FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final ReturnCode returnCode = session.getReturnCode(); hideProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(returnCode)) { Log.d(TAG, String.format("Encode completed successfully in %d milliseconds; playing video.", session.getDuration())); playVideo(); @@ -167,8 +165,6 @@ public Object call() { Popup.show(requireContext(), "Encode failed. Please check logs for the details."); Log.d(TAG, String.format("Encode failed with state %s and rc %s.%s", session.getState(), returnCode, notNull(session.getFailStackTrace(), "\n"))); } - - return null; } }); } @@ -183,7 +179,13 @@ public void apply(com.arthenica.ffmpegkit.Log log) { @Override public void apply(Statistics statistics) { VideoTabFragment.this.statistics = statistics; - updateProgressDialog(); + MainActivity.addUIAction(new Runnable() { + + @Override + public void run() { + updateProgressDialog(); + } + }); } }); @@ -219,6 +221,19 @@ public boolean onError(MediaPlayer mp, int what, int extra) { videoView.start(); } + public String getPixelFormat() { + String videoCodec = selectedCodec; + + final String pixelFormat; + if ("x265".equals(videoCodec)) { + pixelFormat = "yuv420p10le"; + } else { + pixelFormat = "yuv420p"; + } + + return pixelFormat; + } + public String getSelectedVideoCodec() { String videoCodec = selectedCodec; @@ -345,12 +360,11 @@ protected void updateProgressDialog() { protected void hideProgressDialog() { progressDialog.dismiss(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { VideoTabFragment.this.progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding video"); - return null; } }); } diff --git a/android/test-app-local-dependency/src/main/res/values/other_test.xml b/android/test-app-local-dependency/src/main/res/values/other_test.xml index 09a5de9..928830c 100644 --- a/android/test-app-local-dependency/src/main/res/values/other_test.xml +++ b/android/test-app-local-dependency/src/main/res/values/other_test.xml @@ -4,5 +4,6 @@ chromaprint dav1d webp + zscale \ No newline at end of file diff --git a/android/test-app-maven-central/build.gradle b/android/test-app-maven-central/build.gradle index 68f9f4c..42bff0b 100644 --- a/android/test-app-maven-central/build.gradle +++ b/android/test-app-maven-central/build.gradle @@ -14,8 +14,8 @@ android { applicationId "com.arthenica.ffmpegkit.test" minSdkVersion 24 targetSdkVersion 30 - versionCode 240450 - versionName "4.5" + versionCode 240451 + versionName "4.5.1" } buildTypes { debug { @@ -51,7 +51,7 @@ android.applicationVariants.all { variant -> } dependencies { - implementation 'com.arthenica:ffmpeg-kit-full:4.5.LTS' + implementation 'com.arthenica:ffmpeg-kit-full:4.5.1.LTS' implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/AudioTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/AudioTabFragment.java index 1925908..2c7c11f 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/AudioTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/AudioTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.view.View; @@ -36,21 +39,16 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; import com.arthenica.ffmpegkit.util.DialogUtil; import java.io.File; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class AudioTabFragment extends Fragment implements AdapterView.OnItemSelectedListener { private AlertDialog progressDialog; @@ -105,12 +103,11 @@ public void enableLogCallback() { @Override public void apply(final com.arthenica.ffmpegkit.Log log) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(log.getMessage()); - return null; } }); } @@ -153,19 +150,19 @@ public void encodeAudio() { android.util.Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); hideProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(returnCode)) { Popup.show(requireContext(), "Encode completed successfully."); android.util.Log.d(TAG, "Encode completed successfully."); @@ -173,8 +170,6 @@ public Object call() { Popup.show(requireContext(), "Encode failed. Please check logs for the details."); android.util.Log.d(TAG, String.format("Encode failed with state %s and rc %s.%s", state, returnCode, notNull(session.getFailStackTrace(), "\n"))); } - - return null; } }); } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/CommandTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/CommandTabFragment.java index 38592b6..f10dbf7 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/CommandTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/CommandTabFragment.java @@ -22,6 +22,8 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.AndroidRuntimeException; @@ -34,20 +36,17 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.FFprobeSession; +import com.arthenica.ffmpegkit.FFprobeSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.LogRedirectionStrategy; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; - public class CommandTabFragment extends Fragment { private EditText commandText; private TextView outputText; @@ -105,22 +104,21 @@ public void runFFmpeg() { android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process started with arguments:\n'%s'", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); - android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", state, returnCode, notNull(session.getFailStackTrace(), "\n"))); + android.util.Log.d(MainActivity.TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", FFmpegKitConfig.sessionStateToString(state), returnCode, notNull(session.getFailStackTrace(), "\n"))); - if (state == SessionState.FAILED || !returnCode.isSuccess()) { - MainActivity.addUIAction(new Callable() { + if (state == SessionState.FAILED || !returnCode.isValueSuccess()) { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { Popup.show(requireContext(), "Command failed. Please check output for the details."); - return null; } }); } @@ -129,12 +127,11 @@ public Object call() { @Override public void apply(final com.arthenica.ffmpegkit.Log log) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(log.getMessage()); - return null; } }); @@ -152,31 +149,29 @@ public void runFFprobe() { android.util.Log.d(MainActivity.TAG, String.format("FFprobe process started with arguments:\n'%s'", ffprobeCommand)); - FFprobeSession session = new FFprobeSession(FFmpegKitConfig.parseArguments(ffprobeCommand), new ExecuteCallback() { + FFprobeSession session = new FFprobeSession(FFmpegKitConfig.parseArguments(ffprobeCommand), new FFprobeSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFprobeSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(session.getOutput()); - return null; } }); - android.util.Log.d(MainActivity.TAG, String.format("FFprobe process exited with state %s and rc %s.%s", state, returnCode, notNull(session.getFailStackTrace(), "\n"))); + android.util.Log.d(MainActivity.TAG, String.format("FFprobe process exited with state %s and rc %s.%s", FFmpegKitConfig.sessionStateToString(state), returnCode, notNull(session.getFailStackTrace(), "\n"))); - if (state == SessionState.FAILED || !session.getReturnCode().isSuccess()) { - MainActivity.addUIAction(new Callable() { + if (state == SessionState.FAILED || !session.getReturnCode().isValueSuccess()) { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { Popup.show(requireContext(), "Command failed. Please check output for the details."); - return null; } }); } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/ConcurrentExecutionTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/ConcurrentExecutionTabFragment.java index 855c7af..736d4d7 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/ConcurrentExecutionTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/ConcurrentExecutionTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; @@ -32,13 +35,12 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; import com.arthenica.ffmpegkit.util.ResourcesUtil; import com.arthenica.smartexception.java.Exceptions; @@ -46,10 +48,6 @@ import java.io.File; import java.io.IOException; import java.util.Locale; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class ConcurrentExecutionTabFragment extends Fragment { private TextView outputText; @@ -161,12 +159,11 @@ public void enableLogCallback() { @Override public void apply(final com.arthenica.ffmpegkit.Log log) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(String.format(Locale.getDefault(), "%d -> %s", log.getSessionId(), log.getMessage())); - return null; } }); } @@ -191,10 +188,10 @@ public void encodeVideo(final int buttonNumber) { Log.d(TAG, String.format("FFmpeg process starting for button %d with arguments\n'%s'.", buttonNumber, ffmpegCommand)); - final FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + final FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/HttpsTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/HttpsTabFragment.java index a49457e..5854776 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/HttpsTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/HttpsTabFragment.java @@ -22,6 +22,8 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; @@ -33,12 +35,12 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; +import com.arthenica.ffmpegkit.Chapter; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFprobeKit; import com.arthenica.ffmpegkit.MediaInformation; import com.arthenica.ffmpegkit.MediaInformationSession; -import com.arthenica.ffmpegkit.Session; +import com.arthenica.ffmpegkit.MediaInformationSessionCompleteCallback; import com.arthenica.ffmpegkit.StreamInformation; import org.json.JSONObject; @@ -46,8 +48,6 @@ import java.util.Iterator; import java.util.Random; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; - public class HttpsTabFragment extends Fragment { public static final String HTTPS_TEST_DEFAULT_URL = "https://download.blender.org/peach/trailer/trailer_1080p.ogg"; @@ -165,7 +165,7 @@ public void runGetMediaInformation(final int buttonNumber) { } // EXECUTE - FFprobeKit.getMediaInformationAsync(testUrl, createNewExecuteCallback()); + FFprobeKit.getMediaInformationAsync(testUrl, createNewCompleteCallback()); } public void setActive() { @@ -199,15 +199,15 @@ private String getRandomTestUrl() { } } - private ExecuteCallback createNewExecuteCallback() { - return new ExecuteCallback() { + private MediaInformationSessionCompleteCallback createNewCompleteCallback() { + return new MediaInformationSessionCompleteCallback() { @Override - public void apply(Session session) { + public void apply(MediaInformationSession session) { // SYNC THE OUTPUT SO WE CAN IDENTIFY THE FILES synchronized (outputLock) { - final MediaInformation information = ((MediaInformationSession) session).getMediaInformation(); + final MediaInformation information = session.getMediaInformation(); if (information == null) { appendOutput("Get media information failed\n"); appendOutput(String.format("State: %s\n", session.getState())); @@ -232,12 +232,10 @@ public void apply(Session session) { } if (information.getTags() != null) { JSONObject tags = information.getTags(); - if (tags != null) { - Iterator keys = tags.keys(); - while (keys.hasNext()) { - String next = keys.next(); - appendOutput("Tag: " + next + ":" + tags.optString(next) + "\n"); - } + Iterator keys = tags.keys(); + while (keys.hasNext()) { + String next = keys.next(); + appendOutput("Tag: " + next + ":" + tags.optString(next) + "\n"); } } if (information.getStreams() != null) { @@ -299,14 +297,45 @@ public void apply(Session session) { if (stream.getTags() != null) { JSONObject tags = stream.getTags(); + Iterator keys = tags.keys(); + while (keys.hasNext()) { + String next = keys.next(); + appendOutput(String.format("Stream tag: %s:%s\n", next, tags.optString(next))); + } + } + } + } + if (information.getChapters() != null) { + for (Chapter chapter : information.getChapters()) { + if (chapter.getId() != null) { + appendOutput("Chapter id: " + chapter.getId() + "\n"); + } + if (chapter.getTimeBase() != null) { + appendOutput("Chapter time base: " + chapter.getTimeBase() + "\n"); + } + if (chapter.getStart() != null) { + appendOutput("Chapter start: " + chapter.getStart() + "\n"); + } + if (chapter.getStartTime() != null) { + appendOutput("Chapter start time: " + chapter.getStartTime() + "\n"); + } + if (chapter.getEnd() != null) { + appendOutput("Chapter end: " + chapter.getEnd() + "\n"); + } + if (chapter.getEndTime() != null) { + appendOutput("Chapter end time: " + chapter.getEndTime() + "\n"); + } + if (chapter.getTags() != null) { + JSONObject tags = chapter.getTags(); if (tags != null) { Iterator keys = tags.keys(); while (keys.hasNext()) { String next = keys.next(); - appendOutput(String.format("Stream tag: %s:%s\n", next, tags.optString(next))); + appendOutput(String.format("Chapter tag: %s:%s\n", next, tags.optString(next))); } } } + } } } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/MainActivity.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/MainActivity.java index 2ac2593..8fec024 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/MainActivity.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/MainActivity.java @@ -27,6 +27,7 @@ import android.graphics.Color; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.util.Log; import android.view.Gravity; import android.view.View; @@ -53,9 +54,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; -import java.util.Queue; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentLinkedQueue; public class MainActivity extends AppCompatActivity { @@ -71,30 +69,7 @@ public class MainActivity extends AppCompatActivity { Exceptions.registerRootPackage("com.arthenica"); } - protected static final Queue> actionQueue = new ConcurrentLinkedQueue<>(); - - protected static final Handler handler = new Handler(); - - protected static final Runnable runnable = new Runnable() { - - @Override - public void run() { - Callable callable; - - do { - callable = actionQueue.poll(); - if (callable != null) { - try { - callable.call(); - } catch (final Exception e) { - android.util.Log.e(TAG, String.format("Running UI action received error.%s.", Exceptions.getStackTraceString(e))); - } - } - } while (callable != null); - - handler.postDelayed(this, 250); - } - }; + protected static final Handler handler = new Handler(Looper.getMainLooper()); @Override protected void onCreate(final Bundle savedInstanceState) { @@ -127,8 +102,6 @@ protected void onCreate(final Bundle savedInstanceState) { final ViewPager viewPager = findViewById(R.id.pager); viewPager.setAdapter(new PagerAdapter(getSupportFragmentManager(), this)); - waitForUIAction(); - // VERIFY PERMISSIONS int permission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { @@ -157,13 +130,6 @@ protected void onCreate(final Bundle savedInstanceState) { FFmpegKitConfig.setLogLevel(Level.AV_LOG_INFO); } - @Override - protected void onDestroy() { - super.onDestroy(); - - handler.removeCallbacks(runnable); - } - public static void listFFmpegSessions() { List ffmpegSessions = FFmpegKit.listSessions(); Log.d(TAG, "Listing FFmpeg sessions."); @@ -181,7 +147,7 @@ public static void listFFmpegSessions() { } public static void listFFprobeSessions() { - List ffprobeSessions = FFprobeKit.listSessions(); + List ffprobeSessions = FFprobeKit.listFFprobeSessions(); Log.d(TAG, "Listing FFprobe sessions."); for (int i = 0; i < ffprobeSessions.size(); i++) { FFprobeSession session = ffprobeSessions.get(i); @@ -196,12 +162,8 @@ public static void listFFprobeSessions() { Log.d(TAG, "Listed FFprobe sessions."); } - public static void waitForUIAction() { - handler.postDelayed(runnable, 250); - } - - public static void addUIAction(final Callable callable) { - actionQueue.add(callable); + public static void addUIAction(final Runnable runnable) { + handler.post(runnable); } protected void registerAppFont() throws IOException { diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/OtherTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/OtherTabFragment.java index 080da32..d8322dc 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/OtherTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/OtherTabFragment.java @@ -39,16 +39,16 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; +import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.util.ResourcesUtil; import com.arthenica.smartexception.java.Exceptions; import java.io.File; import java.io.IOException; -import java.util.concurrent.Callable; public class OtherTabFragment extends Fragment implements AdapterView.OnItemSelectedListener { @@ -119,6 +119,9 @@ public void runTest() { case "webp": testWebp(); break; + case "zscale": + testZscale(); + break; } } @@ -134,10 +137,10 @@ protected void testChromaprint() { android.util.Log.d(TAG, String.format("Creating audio sample with '%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(Session session) { + public void apply(FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); if (ReturnCode.isSuccess(session.getReturnCode())) { @@ -147,14 +150,14 @@ public void apply(Session session) { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", chromaprintCommand)); - FFmpegKit.executeAsync(chromaprintCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(chromaprintCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { - MainActivity.addUIAction(new Callable() { + public void apply(final FFmpegSession session) { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); if (ReturnCode.isSuccess(session.getReturnCode())) { @@ -162,13 +165,11 @@ public Object call() { } else { Popup.show(requireContext(), "Testing chromaprint failed. Please check logs for the details."); } - return null; } }); } }, log -> MainActivity.addUIAction(() -> { appendOutput(log.getMessage()); - return null; }), null); } else { @@ -185,15 +186,14 @@ protected void testDav1d() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); } }, log -> MainActivity.addUIAction(() -> { appendOutput(log.getMessage()); - return null; }), null); } @@ -210,21 +210,22 @@ protected void testWebp() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(Session session) { + public void apply(FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); - if (ReturnCode.isSuccess(session.getReturnCode())) { - Popup.show(requireContext(), "Encode webp completed successfully."); - } else { - Popup.show(requireContext(), "Encode webp failed. Please check logs for the details."); - } + MainActivity.addUIAction(() -> { + if (ReturnCode.isSuccess(session.getReturnCode())) { + Popup.show(requireContext(), "Encode webp completed successfully."); + } else { + Popup.show(requireContext(), "Encode webp failed. Please check logs for the details."); + } + }); } }, log -> MainActivity.addUIAction(() -> { appendOutput(log.getMessage()); - return null; }), null); } catch (IOException e) { @@ -233,6 +234,35 @@ public void apply(Session session) { } } + protected void testZscale() { + final File videoFile = new File(requireContext().getFilesDir(), "video.mp4"); + final File zscaledVideoFile = new File(requireContext().getFilesDir(), "video.zscaled.mp4"); + + Log.d(TAG, "Testing 'zscale' filter with video file created on the Video tab"); + + final String ffmpegCommand = Video.generateZscaleVideoScript(videoFile.getAbsolutePath(), zscaledVideoFile.getAbsolutePath()); + + Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); + + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { + + @Override + public void apply(FFmpegSession session) { + Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); + + MainActivity.addUIAction(() -> { + if (ReturnCode.isSuccess(session.getReturnCode())) { + Popup.show(requireContext(), "zscale completed successfully."); + } else { + Popup.show(requireContext(), "zscale failed. Please check logs for the details."); + } + }); + } + }, log -> MainActivity.addUIAction(() -> { + appendOutput(log.getMessage()); + }), null); + } + public File getChromaprintSampleFile() { return new File(requireContext().getFilesDir(), "audio-sample.wav"); } @@ -247,6 +277,8 @@ public File getChromaprintOutputFile() { public void setActive() { android.util.Log.i(MainActivity.TAG, "Other Tab Activated"); + FFmpegKitConfig.enableLogCallback(null); + FFmpegKitConfig.enableStatisticsCallback(null); Popup.show(requireContext(), getString(R.string.other_test_tooltip_text)); } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/PipeTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/PipeTabFragment.java index 69a57a5..2fd2bea 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/PipeTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/PipeTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.media.MediaPlayer; import android.net.Uri; import android.os.AsyncTask; @@ -37,12 +40,12 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; import com.arthenica.ffmpegkit.Statistics; import com.arthenica.ffmpegkit.StatisticsCallback; @@ -54,10 +57,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class PipeTabFragment extends Fragment { private VideoView videoView; @@ -113,13 +112,12 @@ public void enableStatisticsCallback() { @Override public void apply(final Statistics newStatistics) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { PipeTabFragment.this.statistics = newStatistics; updateProgressDialog(); - return null; } }); } @@ -162,10 +160,10 @@ public void createVideo() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); @@ -178,18 +176,16 @@ public void apply(final Session session) { FFmpegKitConfig.closeFFmpegPipe(pipe2); FFmpegKitConfig.closeFFmpegPipe(pipe3); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(returnCode)) { Log.d(TAG, "Create completed successfully; playing video."); playVideo(); } else { Popup.show(requireContext(), "Create failed. Please check logs for the details."); } - - return null; } }); } @@ -270,12 +266,11 @@ protected void updateProgressDialog() { protected void hideProgressDialog() { progressDialog.dismiss(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { PipeTabFragment.this.progressDialog = DialogUtil.createProgressDialog(requireContext(), "Creating video"); - return null; } }); } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/SafTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/SafTabFragment.java index 25299b4..e7c9dad 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/SafTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/SafTabFragment.java @@ -22,6 +22,10 @@ package com.arthenica.ffmpegkit.test; +import static android.app.Activity.RESULT_OK; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.content.Intent; import android.net.Uri; import android.os.Build; @@ -37,15 +41,14 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.FFprobeKit; import com.arthenica.ffmpegkit.FFprobeSession; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.SessionState; import com.arthenica.ffmpegkit.Statistics; import com.arthenica.ffmpegkit.StatisticsCallback; @@ -56,11 +59,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.util.concurrent.Callable; - -import static android.app.Activity.RESULT_OK; -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class SafTabFragment extends Fragment { private TextView outputText; @@ -132,12 +130,11 @@ private void enableLogCallback() { @Override public void apply(final com.arthenica.ffmpegkit.Log log) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { appendOutput(log.getMessage()); - return null; } }); } @@ -167,7 +164,7 @@ private void encodeVideo() { final File image1File = new File(requireContext().getCacheDir(), "machupicchu.jpg"); final File image2File = new File(requireContext().getCacheDir(), "pyramid.jpg"); final File image3File = new File(requireContext().getCacheDir(), "stonehenge.jpg"); - final String videoPath = FFmpegKitConfig.getSafParameterForWrite(requireContext(), outUri); + final String videoPath = FFmpegKitConfig.getSafParameter(requireContext(), outUri, "rw"); try { String selectedCodec = getCodec(videoPath); @@ -183,10 +180,10 @@ private void encodeVideo() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final SessionState state = session.getState(); final ReturnCode returnCode = session.getReturnCode(); @@ -194,17 +191,15 @@ public void apply(final Session session) { hideProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(session.getReturnCode())) { Log.d(TAG, "Encode completed successfully."); } else { Popup.show(requireContext(), "Encode failed. Please check logs for the details."); } - - return null; } }); } @@ -307,7 +302,7 @@ private String getCustomOptions(String videoCodec) { default: // kvazaar, mpeg4, x264, xvid - return ""; + return "-movflags faststart "; } } @@ -316,13 +311,12 @@ private void enableStatisticsCallback() { @Override public void apply(final Statistics newStatistics) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { statistics = newStatistics; updateProgressDialog(); - return null; } }); } @@ -358,12 +352,11 @@ private void updateProgressDialog() { private void hideProgressDialog() { progressDialog.dismiss(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding video"); - return null; } }); } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/SubtitleTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/SubtitleTabFragment.java index 4dac4f1..fec5879 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/SubtitleTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/SubtitleTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; @@ -36,12 +39,12 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.Statistics; import com.arthenica.ffmpegkit.StatisticsCallback; import com.arthenica.ffmpegkit.util.DialogUtil; @@ -51,10 +54,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class SubtitleTabFragment extends Fragment { @@ -118,13 +117,12 @@ public void enableStatisticsCallback() { @Override public void apply(final Statistics newStatistics) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { SubtitleTabFragment.this.statistics = newStatistics; updateProgressDialog(); - return null; } }); } @@ -158,20 +156,20 @@ public void burnSubtitles() { state = State.CREATING; - sessionId = FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + sessionId = FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); hideCreateProgressDialog(); if (ReturnCode.isSuccess(session.getReturnCode())) { - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { Log.d(TAG, "Create completed successfully; burning subtitles."); @@ -183,17 +181,17 @@ public Object call() { state = State.BURNING; - FFmpegKit.executeAsync(burnSubtitlesCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(burnSubtitlesCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session secondSession) { + public void apply(final FFmpegSession secondSession) { hideBurnProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(secondSession.getReturnCode())) { Log.d(TAG, "Burn subtitles completed successfully; playing video."); playVideo(); @@ -204,14 +202,10 @@ public Object call() { Popup.show(requireContext(), "Burn subtitles failed. Please check logs for the details."); Log.d(TAG, String.format("Burn subtitles failed with state %s and rc %s.%s", secondSession.getState(), secondSession.getReturnCode(), notNull(secondSession.getFailStackTrace(), "\n"))); } - - return null; } }); } }); - - return null; } }); } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/VidStabTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/VidStabTabFragment.java index f45b69b..21b6e4b 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/VidStabTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/VidStabTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; @@ -35,22 +38,18 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; +import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.util.DialogUtil; import com.arthenica.ffmpegkit.util.ResourcesUtil; import com.arthenica.smartexception.java.Exceptions; import java.io.File; import java.io.IOException; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class VidStabTabFragment extends Fragment { private VideoView videoView; @@ -138,18 +137,18 @@ public void stabilizeVideo() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", session.getState(), session.getReturnCode(), notNull(session.getFailStackTrace(), "\n"))); hideCreateProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(session.getReturnCode())) { Log.d(TAG, "Create completed successfully; stabilizing video."); @@ -160,10 +159,10 @@ public Object call() { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", analyzeVideoCommand)); - FFmpegKit.executeAsync(analyzeVideoCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(analyzeVideoCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session secondSession) { + public void apply(final FFmpegSession secondSession) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", secondSession.getState(), secondSession.getReturnCode(), notNull(secondSession.getFailStackTrace(), "\n"))); if (ReturnCode.isSuccess(secondSession.getReturnCode())) { @@ -171,18 +170,18 @@ public void apply(final Session secondSession) { Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", stabilizeVideoCommand)); - FFmpegKit.executeAsync(stabilizeVideoCommand, new ExecuteCallback() { + FFmpegKit.executeAsync(stabilizeVideoCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session thirdSession) { + public void apply(final FFmpegSession thirdSession) { Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", thirdSession.getState(), thirdSession.getReturnCode(), notNull(thirdSession.getFailStackTrace(), "\n"))); hideStabilizeProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(thirdSession.getReturnCode())) { Log.d(TAG, "Stabilize video completed successfully; playing videos."); playVideo(); @@ -190,16 +189,16 @@ public Object call() { } else { Popup.show(requireContext(), "Stabilize video failed. Please check logs for the details."); } - - return null; } }); } }); } else { - hideStabilizeProgressDialog(); - Popup.show(requireContext(), "Stabilize video failed. Please check logs for the details."); + MainActivity.addUIAction(() -> { + hideStabilizeProgressDialog(); + Popup.show(requireContext(), "Stabilize video failed. Please check logs for the details."); + }); } } }); @@ -207,8 +206,6 @@ public Object call() { } else { Popup.show(requireContext(), "Create video failed. Please check logs for the details."); } - - return null; } }); } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/Video.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/Video.java index b3304e1..fe0daf7 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/Video.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/Video.java @@ -53,6 +53,10 @@ static String generateCreateVideoWithPipesScript(final String image1Pipe, final } static String generateEncodeVideoScript(final String image1Path, final String image2Path, final String image3Path, final String videoFilePath, final String videoCodec, final String customOptions) { + return generateEncodeVideoScript(image1Path, image2Path, image3Path, videoFilePath, videoCodec, "yuv420p", customOptions); + } + + static String generateEncodeVideoScript(final String image1Path, final String image2Path, final String image3Path, final String videoFilePath, final String videoCodec, final String pixelFormat, final String customOptions) { return "-hide_banner -y -loop 1 -i \"" + image1Path + "\" " + "-loop 1 -i '" + image2Path + "' " + @@ -69,7 +73,7 @@ static String generateEncodeVideoScript(final String image1Path, final String im "[stream3out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30)[stream3starting];" + "[stream2starting][stream1ending]blend=all_expr=\'if(gte(X,(W/2)*T/1)*lte(X,W-(W/2)*T/1),B,A)\':shortest=1[stream2blended];" + "[stream3starting][stream2ending]blend=all_expr=\'if(gte(X,(W/2)*T/1)*lte(X,W-(W/2)*T/1),B,A)\':shortest=1[stream3blended];" + - "[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\"" + + "[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=" + pixelFormat + "[video]\"" + " -map [video] -vsync 2 -async 1 " + customOptions + "-c:v " + videoCodec.toLowerCase(Locale.ENGLISH) + " -r 30 " + videoFilePath; } @@ -93,4 +97,11 @@ static String generateShakingVideoScript(final String image1Path, final String i " -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 " + videoFilePath; } + static String generateZscaleVideoScript(final String inputVideoFilePath, final String outputVideoFilePath) { + return "-y -i " + + inputVideoFilePath + + " -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p " + + outputVideoFilePath; + } + } diff --git a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/VideoTabFragment.java b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/VideoTabFragment.java index 2246ea1..ab25178 100644 --- a/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/VideoTabFragment.java +++ b/android/test-app-maven-central/src/main/java/com/arthenica/ffmpegkit/test/VideoTabFragment.java @@ -22,6 +22,9 @@ package com.arthenica.ffmpegkit.test; +import static com.arthenica.ffmpegkit.test.MainActivity.TAG; +import static com.arthenica.ffmpegkit.test.MainActivity.notNull; + import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; @@ -39,13 +42,12 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; -import com.arthenica.ffmpegkit.ExecuteCallback; import com.arthenica.ffmpegkit.FFmpegKit; import com.arthenica.ffmpegkit.FFmpegKitConfig; import com.arthenica.ffmpegkit.FFmpegSession; +import com.arthenica.ffmpegkit.FFmpegSessionCompleteCallback; import com.arthenica.ffmpegkit.LogCallback; import com.arthenica.ffmpegkit.ReturnCode; -import com.arthenica.ffmpegkit.Session; import com.arthenica.ffmpegkit.Statistics; import com.arthenica.ffmpegkit.StatisticsCallback; import com.arthenica.ffmpegkit.util.DialogUtil; @@ -55,10 +57,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.util.concurrent.Callable; - -import static com.arthenica.ffmpegkit.test.MainActivity.TAG; -import static com.arthenica.ffmpegkit.test.MainActivity.notNull; public class VideoTabFragment extends Fragment implements AdapterView.OnItemSelectedListener { private VideoView videoView; @@ -144,22 +142,22 @@ public void encodeVideo() { ResourcesUtil.resourceToFile(getResources(), R.drawable.pyramid, image2File); ResourcesUtil.resourceToFile(getResources(), R.drawable.stonehenge, image3File); - final String ffmpegCommand = Video.generateEncodeVideoScript(image1File.getAbsolutePath(), image2File.getAbsolutePath(), image3File.getAbsolutePath(), videoFile.getAbsolutePath(), getSelectedVideoCodec(), getCustomOptions()); + final String ffmpegCommand = Video.generateEncodeVideoScript(image1File.getAbsolutePath(), image2File.getAbsolutePath(), image3File.getAbsolutePath(), videoFile.getAbsolutePath(), getSelectedVideoCodec(), getPixelFormat(), getCustomOptions()); Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand)); - final FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new ExecuteCallback() { + final FFmpegSession session = FFmpegKit.executeAsync(ffmpegCommand, new FFmpegSessionCompleteCallback() { @Override - public void apply(final Session session) { + public void apply(final FFmpegSession session) { final ReturnCode returnCode = session.getReturnCode(); hideProgressDialog(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { if (ReturnCode.isSuccess(returnCode)) { Log.d(TAG, String.format("Encode completed successfully in %d milliseconds; playing video.", session.getDuration())); playVideo(); @@ -167,8 +165,6 @@ public Object call() { Popup.show(requireContext(), "Encode failed. Please check logs for the details."); Log.d(TAG, String.format("Encode failed with state %s and rc %s.%s", session.getState(), returnCode, notNull(session.getFailStackTrace(), "\n"))); } - - return null; } }); } @@ -183,7 +179,13 @@ public void apply(com.arthenica.ffmpegkit.Log log) { @Override public void apply(Statistics statistics) { VideoTabFragment.this.statistics = statistics; - updateProgressDialog(); + MainActivity.addUIAction(new Runnable() { + + @Override + public void run() { + updateProgressDialog(); + } + }); } }); @@ -219,6 +221,19 @@ public boolean onError(MediaPlayer mp, int what, int extra) { videoView.start(); } + public String getPixelFormat() { + String videoCodec = selectedCodec; + + final String pixelFormat; + if ("x265".equals(videoCodec)) { + pixelFormat = "yuv420p10le"; + } else { + pixelFormat = "yuv420p"; + } + + return pixelFormat; + } + public String getSelectedVideoCodec() { String videoCodec = selectedCodec; @@ -345,12 +360,11 @@ protected void updateProgressDialog() { protected void hideProgressDialog() { progressDialog.dismiss(); - MainActivity.addUIAction(new Callable() { + MainActivity.addUIAction(new Runnable() { @Override - public Object call() { + public void run() { VideoTabFragment.this.progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding video"); - return null; } }); } diff --git a/android/test-app-maven-central/src/main/res/values/other_test.xml b/android/test-app-maven-central/src/main/res/values/other_test.xml index 09a5de9..928830c 100644 --- a/android/test-app-maven-central/src/main/res/values/other_test.xml +++ b/android/test-app-maven-central/src/main/res/values/other_test.xml @@ -4,5 +4,6 @@ chromaprint dav1d webp + zscale \ No newline at end of file diff --git a/ios/test-app-cocoapods/FFmpegKitIOS.xcodeproj/project.pbxproj b/ios/test-app-cocoapods/FFmpegKitIOS.xcodeproj/project.pbxproj index 65aecfa..54df326 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS.xcodeproj/project.pbxproj +++ b/ios/test-app-cocoapods/FFmpegKitIOS.xcodeproj/project.pbxproj @@ -256,6 +256,7 @@ 34FAE20E209F7DDD005CE2AE /* Resources */, 34F9744020A1A200004A1F68 /* Headers */, 3452D8CF20A373640045E6B0 /* Embed Frameworks */, + 0EA381B86EFACCCDB603F8E5 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -321,6 +322,38 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 0EA381B86EFACCCDB603F8E5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FFmpegKitIOS/Pods-FFmpegKitIOS-frameworks.sh", + "${PODS_ROOT}/ffmpeg-kit-ios-full/ffmpegkit.framework", + "${PODS_ROOT}/ffmpeg-kit-ios-full/libavcodec.framework", + "${PODS_ROOT}/ffmpeg-kit-ios-full/libavdevice.framework", + "${PODS_ROOT}/ffmpeg-kit-ios-full/libavfilter.framework", + "${PODS_ROOT}/ffmpeg-kit-ios-full/libavformat.framework", + "${PODS_ROOT}/ffmpeg-kit-ios-full/libavutil.framework", + "${PODS_ROOT}/ffmpeg-kit-ios-full/libswresample.framework", + "${PODS_ROOT}/ffmpeg-kit-ios-full/libswscale.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ffmpegkit.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavcodec.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavdevice.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavfilter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavformat.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavutil.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libswresample.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libswscale.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FFmpegKitIOS/Pods-FFmpegKitIOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 9DA4995DAAB336867DC608F0 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/ios/test-app-cocoapods/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate b/ios/test-app-cocoapods/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate index c7870b1..de3bec2 100644 Binary files a/ios/test-app-cocoapods/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate and b/ios/test-app-cocoapods/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/AppDelegate.m b/ios/test-app-cocoapods/FFmpegKitIOS/AppDelegate.m index 26fc0b8..20b9c4e 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/AppDelegate.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/AppDelegate.m @@ -35,7 +35,7 @@ @interface AppDelegate () @implementation AppDelegate + (void)listFFprobeSessions { - NSArray* ffprobeSessions = [FFprobeKit listSessions]; + NSArray* ffprobeSessions = [FFprobeKit listFFprobeSessions]; NSLog(@"Listing FFprobe sessions.\n"); diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/AudioViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/AudioViewController.m index ad06792..e4d1b5d 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/AudioViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/AudioViewController.m @@ -130,7 +130,7 @@ - (IBAction)encodeAudio:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/CommandViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/CommandViewController.m index 455858e..b82fdb0 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/CommandViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/CommandViewController.m @@ -70,13 +70,13 @@ - (IBAction)runFFmpeg:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self withTitle:@"Error" message:@"Command failed. Please check output for the details." andButtonText:@"OK"]; }); @@ -99,7 +99,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process started with arguments\n'%@'.\n", ffprobeCommand); - FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withExecuteCallback:^(id session) { + FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withCompleteCallback:^(FFprobeSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; @@ -109,7 +109,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self withTitle:@"Error" message:@"Command failed. Please check output for the details." andButtonText:@"OK"]; }); diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/ConcurrentExecutionViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/ConcurrentExecutionViewController.m index 07e0cff..c3f8d80 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/ConcurrentExecutionViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/ConcurrentExecutionViewController.m @@ -121,7 +121,7 @@ - (void)encodeVideo:(int)buttonNumber { NSLog(@"FFmpeg process starting for button %d with arguments\n'%@'.\n", buttonNumber, ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/FFmpegKitIOS.entitlements b/ios/test-app-cocoapods/FFmpegKitIOS/FFmpegKitIOS.entitlements index dc677b9..ee95ab7 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/FFmpegKitIOS.entitlements +++ b/ios/test-app-cocoapods/FFmpegKitIOS/FFmpegKitIOS.entitlements @@ -4,8 +4,6 @@ com.apple.security.app-sandbox - com.apple.security.device.camera - com.apple.security.network.client diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/FFmpegKitTest.m b/ios/test-app-cocoapods/FFmpegKitIOS/FFmpegKitTest.m index 122a499..81b1bd7 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/FFmpegKitTest.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/FFmpegKitTest.m @@ -192,9 +192,9 @@ void testParseDoubleQuotesAndEscapesInCommand() { void getSessionIdTest() { NSArray *TEST_ARGUMENTS = [[NSArray alloc] initWithObjects:@"argument1", @"argument2", nil]; - FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; + FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; assert([sessions3 getSessionId] > [sessions2 getSessionId]); assert([sessions3 getSessionId] > [sessions1 getSessionId]); diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/HttpsViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/HttpsViewController.m index 849c307..0e90afc 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/HttpsViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/HttpsViewController.m @@ -113,7 +113,7 @@ - (void)runGetMediaInformation:(int)buttonNumber { [self clearOutput]; } - [FFprobeKit getMediaInformationAsync:testUrl withExecuteCallback:[self createNewExecuteCallback]]; + [FFprobeKit getMediaInformationAsync:testUrl withCompleteCallback:[self createNewCompleteCallback]]; } - (void)setActive { @@ -146,11 +146,11 @@ - (NSString*)getRandomTestUrl { } } -- (ExecuteCallback)createNewExecuteCallback { - return ^(id session){ +- (MediaInformationSessionCompleteCallback)createNewCompleteCallback { + return ^(MediaInformationSession* session){ addUIAction(^{ @synchronized (self->outputLock) { - MediaInformation *information = [((MediaInformationSession*) session) getMediaInformation]; + MediaInformation *information = [session getMediaInformation]; if (information == nil) { [self appendOutput:@"Get media information failed\n"]; [self appendOutput:[NSString stringWithFormat:@"State: %@\n", [FFmpegKitConfig sessionStateToString:[session getState]]]]; @@ -176,7 +176,7 @@ - (ExecuteCallback)createNewExecuteCallback { if ([information getTags] != nil) { NSDictionary* tags = [information getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@\n", key, [tags objectForKey:key]]]; } } if ([information getStreams] != nil) { @@ -239,7 +239,35 @@ - (ExecuteCallback)createNewExecuteCallback { if ([stream getTags] != nil) { NSDictionary* tags = [stream getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@\n", key, [tags objectForKey:key]]]; + } + } + } + } + if ([information getChapters] != nil) { + for (Chapter* chapter in [information getChapters]) { + if ([chapter getId] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter id: %@\n", [chapter getId]]]; + } + if ([chapter getTimeBase] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter time base: %@\n", [chapter getTimeBase]]]; + } + if ([chapter getStart] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start: %@\n", [chapter getStart]]]; + } + if ([chapter getStartTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start time: %@\n", [chapter getStartTime]]]; + } + if ([chapter getEnd] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end: %@\n", [chapter getEnd]]]; + } + if ([chapter getEndTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end time: %@\n", [chapter getEndTime]]]; + } + if ([chapter getTags] != nil) { + NSDictionary* tags = [chapter getTags]; + for(NSString *key in [tags allKeys]) { + [self appendOutput:[NSString stringWithFormat:@"Chapter tag: %@:%@\n", key, [tags objectForKey:key]]]; } } } diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/MediaInformationParserTest.m b/ios/test-app-cocoapods/FFmpegKitIOS/MediaInformationParserTest.m index f9071f1..2cabe99 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/MediaInformationParserTest.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/MediaInformationParserTest.m @@ -75,6 +75,85 @@ static void initTests() { " }\n" " }\n" " ],\n" + " \"chapters\": [\n" + " {\n" + " \"id\": 0,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"end\": 11158238,\n" + " \"end_time\": \"506.042540\",\n" + " \"tags\": {\n" + " \"title\": \"1 Laying Plans - 2 Waging War\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 1,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 11158238,\n" + " \"start_time\": \"506.042540\",\n" + " \"end\": 21433051,\n" + " \"end_time\": \"972.020454\",\n" + " \"tags\": {\n" + " \"title\": \"3 Attack By Stratagem - 4 Tactical Dispositions\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 2,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 21433051,\n" + " \"start_time\": \"972.020454\",\n" + " \"end\": 35478685,\n" + " \"end_time\": \"1609.010658\",\n" + " \"tags\": {\n" + " \"title\": \"5 Energy - 6 Weak Points and Strong\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 3,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 35478685,\n" + " \"start_time\": \"1609.010658\",\n" + " \"end\": 47187043,\n" + " \"end_time\": \"2140.001950\",\n" + " \"tags\": {\n" + " \"title\": \"7 Maneuvering - 8 Variation in Tactics\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 4,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 47187043,\n" + " \"start_time\": \"2140.001950\",\n" + " \"end\": 66635594,\n" + " \"end_time\": \"3022.022404\",\n" + " \"tags\": {\n" + " \"title\": \"9 The Army on the March - 10 Terrain\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 5,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 66635594,\n" + " \"start_time\": \"3022.022404\",\n" + " \"end\": 83768105,\n" + " \"end_time\": \"3799.007029\",\n" + " \"tags\": {\n" + " \"title\": \"11 The Nine Situations\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 6,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 83768105,\n" + " \"start_time\": \"3799.007029\",\n" + " \"end\": 95659008,\n" + " \"end_time\": \"4338.277007\",\n" + " \"tags\": {\n" + " \"title\": \"12 The Attack By Fire - 13 The Use of Spies\"\n" + " }\n" + " }\n" + " ],\n" " \"format\": {\n" " \"filename\": \"sample.mp3\",\n" " \"nb_streams\": 1,\n" @@ -448,6 +527,10 @@ static void initTests() { } +void assertNotNull(NSObject *object) { + assert(object != nil); +} + void assertNumber(NSNumber *expected, NSNumber *real) { if (expected == nil) { assert(real == nil); @@ -501,8 +584,21 @@ void assertAudioStream(StreamInformation *stream, NSNumber *index, NSString *cod assertString(bitrate, [stream getBitrate]); } -void assertNotNull(NSObject *object) { - assert(object != nil); +void assertChapter(Chapter *chapter, NSNumber *id, NSString *timeBase, NSNumber *start, NSString * startTime, NSNumber *end, NSString *endTime) { + assert(chapter != nil); + assertNumber(id, [chapter getId]); + assertString(timeBase, [chapter getTimeBase]); + + assertNumber(start, [chapter getStart]); + assertString(startTime, [chapter getStartTime]); + + assertNumber(end, [chapter getEnd]); + assertString(endTime, [chapter getEndTime]); + + NSDictionary *tags = [chapter getTags]; + assertNotNull(tags); + + assert(1 == [tags count]); } void assertMediaInput(MediaInformation *mediaInformation, NSString *expectedFormat, NSString *expectedFilename) { @@ -579,6 +675,13 @@ void testMediaInformationMp3() { assert(1 == [streams count]); assertAudioStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mp3", @"MP3 (MPEG audio layer 3)", @"44100", @"stereo", @"fltp", @"320000"); + + NSArray *chapters = [mediaInformation getChapters]; + assertNotNull(chapters); + assert(7 == [chapters count]); + + assertChapter([chapters objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"1/22050", [[NSNumber alloc] initWithInt:0], @"0.000000", [[NSNumber alloc] initWithInt:11158238], @"506.042540"); + assertChapter([chapters objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"1/22050", [[NSNumber alloc] initWithInt:11158238], @"506.042540", [[NSNumber alloc] initWithInt:21433051], @"972.020454"); } void testMediaInformationJpg() { diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/OtherViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/OtherViewController.m index fe4738a..b4eb238 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/OtherViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/OtherViewController.m @@ -23,6 +23,7 @@ #include #include #include "OtherViewController.h" +#include "Video.h" @interface OtherViewController () @@ -42,7 +43,7 @@ - (void)viewDidLoad { [super viewDidLoad]; // OTHER TEST PICKER INIT - testData = @[@"chromaprint", @"dav1d", @"webp"]; + testData = @[@"chromaprint", @"dav1d", @"webp", @"zscale"]; selectedTest = 0; self.otherTestPicker.dataSource = self; @@ -101,6 +102,9 @@ - (IBAction)runTest:(id)sender { case 2: [self testWebp]; break; + case 3: + [self testZscale]; + break; } } @@ -114,7 +118,7 @@ -(void)testChromaprint { NSLog(@"Creating audio sample with '%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -126,7 +130,7 @@ -(void)testChromaprint { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", chromaprintCommand); - [FFmpegKit executeAsync:chromaprintCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:chromaprintCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -146,7 +150,7 @@ -(void)testDav1d { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); } withLogCallback:^(Log *log) { addUIAction(^{ @@ -167,7 +171,29 @@ -(void)testWebp { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { + + NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); + + } withLogCallback:^(Log *log) { + addUIAction(^{ + [self appendOutput: [log getMessage]]; + }); + } withStatisticsCallback:nil]; +} + +-(void)testZscale { + NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + NSString *videoFile = [docFolder stringByAppendingPathComponent: @"video.mp4"]; + NSString *zscaledVideoFile = [docFolder stringByAppendingPathComponent: @"video.zscaled.mp4"]; + + NSLog(@"Testing 'zscale' filter with video file created on the Video tab\n"); + + NSString *ffmpegCommand = [Video generateZscaleVideoScript:videoFile:zscaledVideoFile]; + + NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); + + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/PipeViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/PipeViewController.m index 5b709ae..b368520 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/PipeViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/PipeViewController.m @@ -83,7 +83,7 @@ - (void)didReceiveMemoryWarning { } - (void)enableLogCallback { - [FFmpegKitConfig enableLogCallback:^(Log* log){ + [FFmpegKitConfig enableLogCallback: ^(Log* log){ addUIAction(^{ NSLog(@"%@", [log getMessage]); }); @@ -173,7 +173,7 @@ - (IBAction)createVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/SubtitleViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/SubtitleViewController.m index 6a07566..029bf28 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/SubtitleViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/SubtitleViewController.m @@ -133,7 +133,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = CreatingState; - sessionId = [[FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + sessionId = [[FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -154,7 +154,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = BurningState; - [FFmpegKit executeAsync:burnSubtitlesCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:burnSubtitlesCommand withCompleteCallback:^(id secondSession) { addUIAction(^{ [self hideProgressDialog]; diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/VidStabViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/VidStabViewController.m index d466d50..ecf8d42 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/VidStabViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/VidStabViewController.m @@ -129,7 +129,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); addUIAction(^{ @@ -147,7 +147,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", analyzeVideoCommand); - [FFmpegKit executeAsync:analyzeVideoCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:analyzeVideoCommand withCompleteCallback:^(id secondSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[secondSession getState]], [secondSession getReturnCode], notNull([secondSession getFailStackTrace], @"\n")); @@ -157,7 +157,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", stabilizeVideoCommand); - [FFmpegKit executeAsync:stabilizeVideoCommand withExecuteCallback:^(id thirdSession) { + [FFmpegKit executeAsync:stabilizeVideoCommand withCompleteCallback:^(id thirdSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[thirdSession getState]], [thirdSession getReturnCode], notNull([thirdSession getFailStackTrace], @"\n")); diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/Video.h b/ios/test-app-cocoapods/FFmpegKitIOS/Video.h index 7aa0a6c..977f2ef 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/Video.h +++ b/ios/test-app-cocoapods/FFmpegKitIOS/Video.h @@ -31,8 +31,12 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions; ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions; + + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile; ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath; + @end #endif /* FFMPEG_KIT_TEST_VIDEO */ diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/Video.m b/ios/test-app-cocoapods/FFmpegKitIOS/Video.m index 0778874..f910e28 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/Video.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/Video.m @@ -48,6 +48,10 @@ + (NSString*)generateCreateVideoWithPipesScript:(NSString *)image1 :(NSString *) } + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions { + return [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:videoCodec:@"yuv420p":customOptions]; +} + ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions { return [NSString stringWithFormat: @"-hide_banner -y -loop 1 -i %@ \ -loop 1 -i %@ \ @@ -66,8 +70,8 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :( [stream2ending]fade=t=out:s=0:n=30[stream2fadeout];\ [stream2fadein][stream1fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream2blended];\ [stream3fadein][stream2fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream3blended];\ -[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\" \ --map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, customOptions, videoCodec, videoFile]; +[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=%@[video]\" \ +-map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, pixelFormat, customOptions, videoCodec, videoFile]; } + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile { @@ -90,4 +94,8 @@ + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 : -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 %@", image1, image2, image3, videoFile]; } ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath { + return [NSString stringWithFormat:@"-y -i %@ -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p %@", inputVideoFilePath, outputVideoFilePath]; +} + @end diff --git a/ios/test-app-cocoapods/FFmpegKitIOS/VideoViewController.m b/ios/test-app-cocoapods/FFmpegKitIOS/VideoViewController.m index abca51c..45879a4 100644 --- a/ios/test-app-cocoapods/FFmpegKitIOS/VideoViewController.m +++ b/ios/test-app-cocoapods/FFmpegKitIOS/VideoViewController.m @@ -140,11 +140,11 @@ - (IBAction)encodeVideo:(id)sender { [self showProgressDialog:@"Encoding video\n\n"]; - NSString* ffmpegCommand = [Video generateVideoEncodeScript:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getCustomOptions]]; + NSString* ffmpegCommand = [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getPixelFormat]:[self getCustomOptions]]; NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session){ + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session){ SessionState state = [session getState]; ReturnCode *returnCode = [session getReturnCode]; @@ -195,6 +195,19 @@ - (void)playVideo { [player insertItem:newVideo afterItem:nil]; } +- (NSString*)getPixelFormat { + NSString *videoCodec = codecData[selectedCodec]; + + NSString *pixelFormat; + if ([videoCodec isEqualToString:@"x265"]) { + pixelFormat = @"yuv420p10le"; + } else { + pixelFormat = @"yuv420p"; + } + + return pixelFormat; +} + - (NSString*)getSelectedVideoCodec { NSString *videoCodec = codecData[selectedCodec]; diff --git a/ios/test-app-cocoapods/Podfile b/ios/test-app-cocoapods/Podfile index 97cf48b..bc8a006 100644 --- a/ios/test-app-cocoapods/Podfile +++ b/ios/test-app-cocoapods/Podfile @@ -3,5 +3,5 @@ platform :ios, '12.1' use_frameworks! target "FFmpegKitIOS" do - pod 'ffmpeg-kit-ios-full', '4.5' + pod 'ffmpeg-kit-ios-full', '4.5.1.LTS' end diff --git a/ios/test-app-cocoapods/Podfile.lock b/ios/test-app-cocoapods/Podfile.lock index 7ae3ddc..1305343 100644 --- a/ios/test-app-cocoapods/Podfile.lock +++ b/ios/test-app-cocoapods/Podfile.lock @@ -1,16 +1,16 @@ PODS: - - ffmpeg-kit-ios-full (4.5) + - ffmpeg-kit-ios-full (4.5.1.LTS) DEPENDENCIES: - - ffmpeg-kit-ios-full (= 4.5) + - ffmpeg-kit-ios-full (= 4.5.1.LTS) SPEC REPOS: trunk: - ffmpeg-kit-ios-full SPEC CHECKSUMS: - ffmpeg-kit-ios-full: c4cb480c1ba316d7f578191e39b079ef5691af00 + ffmpeg-kit-ios-full: 341a178eebe25ab54b92e4d040a00231b23b7c30 -PODFILE CHECKSUM: 684199acaec9a4c221e969584959bb69789e2588 +PODFILE CHECKSUM: 1e27b7ec760ba588f3e33ff311974c6936a35500 COCOAPODS: 1.11.2 diff --git a/ios/test-app-local-dependency/FFmpegKitIOS.xcodeproj/project.pbxproj b/ios/test-app-local-dependency/FFmpegKitIOS.xcodeproj/project.pbxproj index 14d0561..f9f89ba 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS.xcodeproj/project.pbxproj +++ b/ios/test-app-local-dependency/FFmpegKitIOS.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 48; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ @@ -11,57 +11,6 @@ 340FABBF2115A17600B33CE7 /* VidStabViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FABBD2115A17600B33CE7 /* VidStabViewController.m */; }; 342900CB22DE2BCF0071B2E4 /* MediaInformationParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 342900C722DE2BCF0071B2E4 /* MediaInformationParserTest.m */; }; 342900CD22DE2BCF0071B2E4 /* MediaInformationParserTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 342900C922DE2BCF0071B2E4 /* MediaInformationParserTest.h */; }; - 34378A1726F78DCC003118B2 /* kvazaar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789E426F78DC9003118B2 /* kvazaar.framework */; }; - 34378A1826F78DCC003118B2 /* fontconfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789E526F78DC9003118B2 /* fontconfig.framework */; }; - 34378A1926F78DCC003118B2 /* libavutil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789E626F78DC9003118B2 /* libavutil.framework */; }; - 34378A1A26F78DCC003118B2 /* speex.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789E726F78DC9003118B2 /* speex.framework */; }; - 34378A1B26F78DCC003118B2 /* libass.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789E826F78DC9003118B2 /* libass.framework */; }; - 34378A1C26F78DCC003118B2 /* libnettle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789E926F78DC9003118B2 /* libnettle.framework */; }; - 34378A1D26F78DCC003118B2 /* libtheora.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789EA26F78DC9003118B2 /* libtheora.framework */; }; - 34378A1E26F78DCC003118B2 /* libavformat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789EB26F78DC9003118B2 /* libavformat.framework */; }; - 34378A1F26F78DCC003118B2 /* x265.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789EC26F78DC9003118B2 /* x265.framework */; }; - 34378A2026F78DCC003118B2 /* opus.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789ED26F78DCA003118B2 /* opus.framework */; }; - 34378A2126F78DCC003118B2 /* libvorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789EE26F78DCA003118B2 /* libvorbis.framework */; }; - 34378A2226F78DCC003118B2 /* libwebpmux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789EF26F78DCA003118B2 /* libwebpmux.framework */; }; - 34378A2326F78DCC003118B2 /* gnutls.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F026F78DCA003118B2 /* gnutls.framework */; }; - 34378A2426F78DCC003118B2 /* soxr.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F126F78DCA003118B2 /* soxr.framework */; }; - 34378A2526F78DCC003118B2 /* expat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F226F78DCA003118B2 /* expat.framework */; }; - 34378A2626F78DCC003118B2 /* libhogweed.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F326F78DCA003118B2 /* libhogweed.framework */; }; - 34378A2726F78DCC003118B2 /* libvidstab.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F426F78DCA003118B2 /* libvidstab.framework */; }; - 34378A2826F78DCD003118B2 /* gmp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F526F78DCA003118B2 /* gmp.framework */; }; - 34378A2926F78DCD003118B2 /* libopencore-amrnb.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F626F78DCA003118B2 /* libopencore-amrnb.framework */; }; - 34378A2A26F78DCD003118B2 /* x264.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F726F78DCA003118B2 /* x264.framework */; }; - 34378A2B26F78DCD003118B2 /* libswscale.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F826F78DCA003118B2 /* libswscale.framework */; }; - 34378A2C26F78DCD003118B2 /* tiff.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789F926F78DCA003118B2 /* tiff.framework */; }; - 34378A2D26F78DCD003118B2 /* snappy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789FA26F78DCA003118B2 /* snappy.framework */; }; - 34378A2E26F78DCD003118B2 /* freetype.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789FB26F78DCA003118B2 /* freetype.framework */; }; - 34378A2F26F78DCD003118B2 /* ffmpegkit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789FC26F78DCA003118B2 /* ffmpegkit.framework */; }; - 34378A3026F78DCD003118B2 /* dav1d.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789FD26F78DCA003118B2 /* dav1d.framework */; }; - 34378A3126F78DCD003118B2 /* libpng.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789FE26F78DCB003118B2 /* libpng.framework */; }; - 34378A3226F78DCD003118B2 /* libsndfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 343789FF26F78DCB003118B2 /* libsndfile.framework */; }; - 34378A3326F78DCD003118B2 /* harfbuzz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0026F78DCB003118B2 /* harfbuzz.framework */; }; - 34378A3426F78DCD003118B2 /* libwebp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0126F78DCB003118B2 /* libwebp.framework */; }; - 34378A3526F78DCD003118B2 /* libavdevice.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0226F78DCB003118B2 /* libavdevice.framework */; }; - 34378A3626F78DCD003118B2 /* libxml2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0326F78DCB003118B2 /* libxml2.framework */; }; - 34378A3726F78DCD003118B2 /* libilbc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0426F78DCB003118B2 /* libilbc.framework */; }; - 34378A3826F78DCD003118B2 /* vo-amrwbenc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0526F78DCB003118B2 /* vo-amrwbenc.framework */; }; - 34378A3926F78DCE003118B2 /* libavcodec.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0626F78DCB003118B2 /* libavcodec.framework */; }; - 34378A3A26F78DCE003118B2 /* libtheoradec.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0726F78DCB003118B2 /* libtheoradec.framework */; }; - 34378A3B26F78DCE003118B2 /* libswresample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0826F78DCB003118B2 /* libswresample.framework */; }; - 34378A3C26F78DCE003118B2 /* jpeg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0926F78DCB003118B2 /* jpeg.framework */; }; - 34378A3D26F78DCE003118B2 /* libwebpdemux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0A26F78DCB003118B2 /* libwebpdemux.framework */; }; - 34378A3E26F78DCE003118B2 /* libvpx.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0B26F78DCB003118B2 /* libvpx.framework */; }; - 34378A3F26F78DCE003118B2 /* lame.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0C26F78DCB003118B2 /* lame.framework */; }; - 34378A4026F78DCE003118B2 /* giflib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0D26F78DCB003118B2 /* giflib.framework */; }; - 34378A4126F78DCE003118B2 /* libvorbisfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0E26F78DCB003118B2 /* libvorbisfile.framework */; }; - 34378A4226F78DCE003118B2 /* shine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A0F26F78DCB003118B2 /* shine.framework */; }; - 34378A4326F78DCF003118B2 /* xvidcore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A1026F78DCC003118B2 /* xvidcore.framework */; }; - 34378A4426F78DCF003118B2 /* libavfilter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A1126F78DCC003118B2 /* libavfilter.framework */; }; - 34378A4526F78DCF003118B2 /* twolame.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A1226F78DCC003118B2 /* twolame.framework */; }; - 34378A4626F78DCF003118B2 /* libtheoraenc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A1326F78DCC003118B2 /* libtheoraenc.framework */; }; - 34378A4726F78DCF003118B2 /* fribidi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A1426F78DCC003118B2 /* fribidi.framework */; }; - 34378A4826F78DCF003118B2 /* libogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A1526F78DCC003118B2 /* libogg.framework */; }; - 34378A4926F78DCF003118B2 /* libvorbisenc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A1626F78DCC003118B2 /* libvorbisenc.framework */; }; 343D714525E10CAD007CB801 /* Video.m in Sources */ = {isa = PBXBuildFile; fileRef = 343D714425E10CAC007CB801 /* Video.m */; }; 343E66B5210784BD00F95E5B /* HttpsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 343E66B3210784BD00F95E5B /* HttpsViewController.h */; }; 343E66B6210784BD00F95E5B /* HttpsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 343E66B4210784BD00F95E5B /* HttpsViewController.m */; }; @@ -81,6 +30,22 @@ 3487ABA6220CEAA300A40E8D /* PipeViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3487ABA4220CEAA200A40E8D /* PipeViewController.h */; }; 34943E6825DB499E002B5C1E /* FFmpegKitTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 34943E6625DB499E002B5C1E /* FFmpegKitTest.h */; }; 34943E6925DB499E002B5C1E /* FFmpegKitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 34943E6725DB499E002B5C1E /* FFmpegKitTest.m */; }; + 34A33A9C273B1C4B0087F971 /* libswresample.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A94273B1C4B0087F971 /* libswresample.xcframework */; }; + 34A33A9D273B1C4B0087F971 /* ffmpegkit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A95273B1C4B0087F971 /* ffmpegkit.xcframework */; }; + 34A33A9E273B1C4B0087F971 /* libswscale.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A96273B1C4B0087F971 /* libswscale.xcframework */; }; + 34A33A9F273B1C4B0087F971 /* libavfilter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A97273B1C4B0087F971 /* libavfilter.xcframework */; }; + 34A33AA0273B1C4B0087F971 /* libavdevice.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A98273B1C4B0087F971 /* libavdevice.xcframework */; }; + 34A33AA1273B1C4B0087F971 /* libavutil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A99273B1C4B0087F971 /* libavutil.xcframework */; }; + 34A33AA2273B1C4B0087F971 /* libavformat.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A9A273B1C4B0087F971 /* libavformat.xcframework */; }; + 34A33AA3273B1C4B0087F971 /* libavcodec.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A9B273B1C4B0087F971 /* libavcodec.xcframework */; }; + 34A33AA4273B1C630087F971 /* ffmpegkit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A95273B1C4B0087F971 /* ffmpegkit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AA5273B1C630087F971 /* libavcodec.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A9B273B1C4B0087F971 /* libavcodec.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AA6273B1C630087F971 /* libavdevice.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A98273B1C4B0087F971 /* libavdevice.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AA7273B1C630087F971 /* libavfilter.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A97273B1C4B0087F971 /* libavfilter.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AA8273B1C630087F971 /* libavformat.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A9A273B1C4B0087F971 /* libavformat.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AA9273B1C630087F971 /* libavutil.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A99273B1C4B0087F971 /* libavutil.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AAA273B1C630087F971 /* libswresample.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A94273B1C4B0087F971 /* libswresample.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AAB273B1C630087F971 /* libswscale.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33A96273B1C4B0087F971 /* libswscale.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 34BB547C2109D44800606B7C /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 34BB547B2109D44800606B7C /* Constants.m */; }; 34CB450C25DDF1E600CF2282 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB450B25DDF1E600CF2282 /* libz.tbd */; }; 34CB450E25DDF1EF00CF2282 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB450D25DDF1EF00CF2282 /* libiconv.tbd */; }; @@ -114,6 +79,14 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( + 34A33AA4273B1C630087F971 /* ffmpegkit.xcframework in Embed Frameworks */, + 34A33AA5273B1C630087F971 /* libavcodec.xcframework in Embed Frameworks */, + 34A33AA6273B1C630087F971 /* libavdevice.xcframework in Embed Frameworks */, + 34A33AA7273B1C630087F971 /* libavfilter.xcframework in Embed Frameworks */, + 34A33AA8273B1C630087F971 /* libavformat.xcframework in Embed Frameworks */, + 34A33AA9273B1C630087F971 /* libavutil.xcframework in Embed Frameworks */, + 34A33AAA273B1C630087F971 /* libswresample.xcframework in Embed Frameworks */, + 34A33AAB273B1C630087F971 /* libswscale.xcframework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -125,57 +98,6 @@ 340FABBD2115A17600B33CE7 /* VidStabViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VidStabViewController.m; sourceTree = ""; }; 342900C722DE2BCF0071B2E4 /* MediaInformationParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MediaInformationParserTest.m; sourceTree = ""; }; 342900C922DE2BCF0071B2E4 /* MediaInformationParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaInformationParserTest.h; sourceTree = ""; }; - 343789E426F78DC9003118B2 /* kvazaar.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = kvazaar.framework; sourceTree = ""; }; - 343789E526F78DC9003118B2 /* fontconfig.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = fontconfig.framework; sourceTree = ""; }; - 343789E626F78DC9003118B2 /* libavutil.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavutil.framework; sourceTree = ""; }; - 343789E726F78DC9003118B2 /* speex.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = speex.framework; sourceTree = ""; }; - 343789E826F78DC9003118B2 /* libass.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libass.framework; sourceTree = ""; }; - 343789E926F78DC9003118B2 /* libnettle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libnettle.framework; sourceTree = ""; }; - 343789EA26F78DC9003118B2 /* libtheora.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libtheora.framework; sourceTree = ""; }; - 343789EB26F78DC9003118B2 /* libavformat.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavformat.framework; sourceTree = ""; }; - 343789EC26F78DC9003118B2 /* x265.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = x265.framework; sourceTree = ""; }; - 343789ED26F78DCA003118B2 /* opus.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = opus.framework; sourceTree = ""; }; - 343789EE26F78DCA003118B2 /* libvorbis.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvorbis.framework; sourceTree = ""; }; - 343789EF26F78DCA003118B2 /* libwebpmux.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libwebpmux.framework; sourceTree = ""; }; - 343789F026F78DCA003118B2 /* gnutls.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = gnutls.framework; sourceTree = ""; }; - 343789F126F78DCA003118B2 /* soxr.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = soxr.framework; sourceTree = ""; }; - 343789F226F78DCA003118B2 /* expat.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = expat.framework; sourceTree = ""; }; - 343789F326F78DCA003118B2 /* libhogweed.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libhogweed.framework; sourceTree = ""; }; - 343789F426F78DCA003118B2 /* libvidstab.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvidstab.framework; sourceTree = ""; }; - 343789F526F78DCA003118B2 /* gmp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = gmp.framework; sourceTree = ""; }; - 343789F626F78DCA003118B2 /* libopencore-amrnb.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = "libopencore-amrnb.framework"; sourceTree = ""; }; - 343789F726F78DCA003118B2 /* x264.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = x264.framework; sourceTree = ""; }; - 343789F826F78DCA003118B2 /* libswscale.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libswscale.framework; sourceTree = ""; }; - 343789F926F78DCA003118B2 /* tiff.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = tiff.framework; sourceTree = ""; }; - 343789FA26F78DCA003118B2 /* snappy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = snappy.framework; sourceTree = ""; }; - 343789FB26F78DCA003118B2 /* freetype.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = freetype.framework; sourceTree = ""; }; - 343789FC26F78DCA003118B2 /* ffmpegkit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ffmpegkit.framework; sourceTree = ""; }; - 343789FD26F78DCA003118B2 /* dav1d.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = dav1d.framework; sourceTree = ""; }; - 343789FE26F78DCB003118B2 /* libpng.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libpng.framework; sourceTree = ""; }; - 343789FF26F78DCB003118B2 /* libsndfile.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libsndfile.framework; sourceTree = ""; }; - 34378A0026F78DCB003118B2 /* harfbuzz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = harfbuzz.framework; sourceTree = ""; }; - 34378A0126F78DCB003118B2 /* libwebp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libwebp.framework; sourceTree = ""; }; - 34378A0226F78DCB003118B2 /* libavdevice.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavdevice.framework; sourceTree = ""; }; - 34378A0326F78DCB003118B2 /* libxml2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libxml2.framework; sourceTree = ""; }; - 34378A0426F78DCB003118B2 /* libilbc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libilbc.framework; sourceTree = ""; }; - 34378A0526F78DCB003118B2 /* vo-amrwbenc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = "vo-amrwbenc.framework"; sourceTree = ""; }; - 34378A0626F78DCB003118B2 /* libavcodec.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavcodec.framework; sourceTree = ""; }; - 34378A0726F78DCB003118B2 /* libtheoradec.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libtheoradec.framework; sourceTree = ""; }; - 34378A0826F78DCB003118B2 /* libswresample.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libswresample.framework; sourceTree = ""; }; - 34378A0926F78DCB003118B2 /* jpeg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = jpeg.framework; sourceTree = ""; }; - 34378A0A26F78DCB003118B2 /* libwebpdemux.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libwebpdemux.framework; sourceTree = ""; }; - 34378A0B26F78DCB003118B2 /* libvpx.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvpx.framework; sourceTree = ""; }; - 34378A0C26F78DCB003118B2 /* lame.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = lame.framework; sourceTree = ""; }; - 34378A0D26F78DCB003118B2 /* giflib.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = giflib.framework; sourceTree = ""; }; - 34378A0E26F78DCB003118B2 /* libvorbisfile.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvorbisfile.framework; sourceTree = ""; }; - 34378A0F26F78DCB003118B2 /* shine.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = shine.framework; sourceTree = ""; }; - 34378A1026F78DCC003118B2 /* xvidcore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = xvidcore.framework; sourceTree = ""; }; - 34378A1126F78DCC003118B2 /* libavfilter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavfilter.framework; sourceTree = ""; }; - 34378A1226F78DCC003118B2 /* twolame.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = twolame.framework; sourceTree = ""; }; - 34378A1326F78DCC003118B2 /* libtheoraenc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libtheoraenc.framework; sourceTree = ""; }; - 34378A1426F78DCC003118B2 /* fribidi.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = fribidi.framework; sourceTree = ""; }; - 34378A1526F78DCC003118B2 /* libogg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libogg.framework; sourceTree = ""; }; - 34378A1626F78DCC003118B2 /* libvorbisenc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvorbisenc.framework; sourceTree = ""; }; 343D714425E10CAC007CB801 /* Video.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Video.m; sourceTree = ""; }; 343D714625E10CBA007CB801 /* Video.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; 343E66B3210784BD00F95E5B /* HttpsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HttpsViewController.h; sourceTree = ""; }; @@ -197,6 +119,14 @@ 3487ABA4220CEAA200A40E8D /* PipeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PipeViewController.h; sourceTree = ""; }; 34943E6625DB499E002B5C1E /* FFmpegKitTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FFmpegKitTest.h; sourceTree = ""; }; 34943E6725DB499E002B5C1E /* FFmpegKitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FFmpegKitTest.m; sourceTree = ""; }; + 34A33A94273B1C4B0087F971 /* libswresample.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libswresample.xcframework; sourceTree = ""; }; + 34A33A95273B1C4B0087F971 /* ffmpegkit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = ffmpegkit.xcframework; sourceTree = ""; }; + 34A33A96273B1C4B0087F971 /* libswscale.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libswscale.xcframework; sourceTree = ""; }; + 34A33A97273B1C4B0087F971 /* libavfilter.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavfilter.xcframework; sourceTree = ""; }; + 34A33A98273B1C4B0087F971 /* libavdevice.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavdevice.xcframework; sourceTree = ""; }; + 34A33A99273B1C4B0087F971 /* libavutil.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavutil.xcframework; sourceTree = ""; }; + 34A33A9A273B1C4B0087F971 /* libavformat.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavformat.xcframework; sourceTree = ""; }; + 34A33A9B273B1C4B0087F971 /* libavcodec.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavcodec.xcframework; sourceTree = ""; }; 34BB547B2109D44800606B7C /* Constants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = ""; }; 34CB450B25DDF1E600CF2282 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; }; 34CB450D25DDF1EF00CF2282 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/usr/lib/libiconv.tbd; sourceTree = DEVELOPER_DIR; }; @@ -233,65 +163,22 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 34378A1A26F78DCC003118B2 /* speex.framework in Frameworks */, + 34A33A9E273B1C4B0087F971 /* libswscale.xcframework in Frameworks */, 34CB451A25DDF26A00CF2282 /* GameController.framework in Frameworks */, - 34378A3426F78DCD003118B2 /* libwebp.framework in Frameworks */, + 34A33A9D273B1C4B0087F971 /* ffmpegkit.xcframework in Frameworks */, + 34A33A9C273B1C4B0087F971 /* libswresample.xcframework in Frameworks */, + 34A33AA2273B1C4B0087F971 /* libavformat.xcframework in Frameworks */, 34CB451825DDF25300CF2282 /* Accelerate.framework in Frameworks */, - 34378A3A26F78DCE003118B2 /* libtheoradec.framework in Frameworks */, - 34378A3526F78DCD003118B2 /* libavdevice.framework in Frameworks */, - 34378A2B26F78DCD003118B2 /* libswscale.framework in Frameworks */, - 34378A1F26F78DCC003118B2 /* x265.framework in Frameworks */, - 34378A2426F78DCC003118B2 /* soxr.framework in Frameworks */, - 34378A2D26F78DCD003118B2 /* snappy.framework in Frameworks */, - 34378A3026F78DCD003118B2 /* dav1d.framework in Frameworks */, 34CB451625DDF24200CF2282 /* CoreMotion.framework in Frameworks */, - 34378A2C26F78DCD003118B2 /* tiff.framework in Frameworks */, - 34378A3326F78DCD003118B2 /* harfbuzz.framework in Frameworks */, - 34378A4826F78DCF003118B2 /* libogg.framework in Frameworks */, - 34378A2A26F78DCD003118B2 /* x264.framework in Frameworks */, - 34378A1B26F78DCC003118B2 /* libass.framework in Frameworks */, - 34378A1926F78DCC003118B2 /* libavutil.framework in Frameworks */, - 34378A4126F78DCE003118B2 /* libvorbisfile.framework in Frameworks */, - 34378A3E26F78DCE003118B2 /* libvpx.framework in Frameworks */, - 34378A3926F78DCE003118B2 /* libavcodec.framework in Frameworks */, - 34378A4026F78DCE003118B2 /* giflib.framework in Frameworks */, - 34378A3B26F78DCE003118B2 /* libswresample.framework in Frameworks */, - 34378A1D26F78DCC003118B2 /* libtheora.framework in Frameworks */, - 34378A1C26F78DCC003118B2 /* libnettle.framework in Frameworks */, - 34378A1E26F78DCC003118B2 /* libavformat.framework in Frameworks */, - 34378A4526F78DCF003118B2 /* twolame.framework in Frameworks */, - 34378A3726F78DCD003118B2 /* libilbc.framework in Frameworks */, - 34378A3826F78DCD003118B2 /* vo-amrwbenc.framework in Frameworks */, + 34A33A9F273B1C4B0087F971 /* libavfilter.xcframework in Frameworks */, 34CB451425DDF22800CF2282 /* VideoToolbox.framework in Frameworks */, - 34378A2526F78DCC003118B2 /* expat.framework in Frameworks */, - 34378A2726F78DCC003118B2 /* libvidstab.framework in Frameworks */, - 34378A2E26F78DCD003118B2 /* freetype.framework in Frameworks */, - 34378A3D26F78DCE003118B2 /* libwebpdemux.framework in Frameworks */, - 34378A3226F78DCD003118B2 /* libsndfile.framework in Frameworks */, - 34378A4626F78DCF003118B2 /* libtheoraenc.framework in Frameworks */, - 34378A2326F78DCC003118B2 /* gnutls.framework in Frameworks */, - 34378A2126F78DCC003118B2 /* libvorbis.framework in Frameworks */, - 34378A2926F78DCD003118B2 /* libopencore-amrnb.framework in Frameworks */, + 34A33AA3273B1C4B0087F971 /* libavcodec.xcframework in Frameworks */, 34CB451225DDF20300CF2282 /* libbz2.tbd in Frameworks */, - 34378A2826F78DCD003118B2 /* gmp.framework in Frameworks */, - 34378A3126F78DCD003118B2 /* libpng.framework in Frameworks */, + 34A33AA0273B1C4B0087F971 /* libavdevice.xcframework in Frameworks */, 34CB451025DDF1F900CF2282 /* libc++.tbd in Frameworks */, 34CB450E25DDF1EF00CF2282 /* libiconv.tbd in Frameworks */, - 34378A3F26F78DCE003118B2 /* lame.framework in Frameworks */, - 34378A2F26F78DCD003118B2 /* ffmpegkit.framework in Frameworks */, - 34378A2626F78DCC003118B2 /* libhogweed.framework in Frameworks */, - 34378A1826F78DCC003118B2 /* fontconfig.framework in Frameworks */, - 34378A4326F78DCF003118B2 /* xvidcore.framework in Frameworks */, - 34378A2026F78DCC003118B2 /* opus.framework in Frameworks */, - 34378A1726F78DCC003118B2 /* kvazaar.framework in Frameworks */, - 34378A4726F78DCF003118B2 /* fribidi.framework in Frameworks */, + 34A33AA1273B1C4B0087F971 /* libavutil.xcframework in Frameworks */, 34CB450C25DDF1E600CF2282 /* libz.tbd in Frameworks */, - 34378A4426F78DCF003118B2 /* libavfilter.framework in Frameworks */, - 34378A2226F78DCC003118B2 /* libwebpmux.framework in Frameworks */, - 34378A3C26F78DCE003118B2 /* jpeg.framework in Frameworks */, - 34378A4226F78DCE003118B2 /* shine.framework in Frameworks */, - 34378A3626F78DCD003118B2 /* libxml2.framework in Frameworks */, - 34378A4926F78DCF003118B2 /* libvorbisenc.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -315,62 +202,19 @@ 3498DC65209F7F1C005F5883 /* Frameworks */ = { isa = PBXGroup; children = ( + 34A33A95273B1C4B0087F971 /* ffmpegkit.xcframework */, + 34A33A9B273B1C4B0087F971 /* libavcodec.xcframework */, + 34A33A98273B1C4B0087F971 /* libavdevice.xcframework */, + 34A33A97273B1C4B0087F971 /* libavfilter.xcframework */, + 34A33A9A273B1C4B0087F971 /* libavformat.xcframework */, + 34A33A99273B1C4B0087F971 /* libavutil.xcframework */, + 34A33A94273B1C4B0087F971 /* libswresample.xcframework */, + 34A33A96273B1C4B0087F971 /* libswscale.xcframework */, 34CB451925DDF26A00CF2282 /* GameController.framework */, 34CB451725DDF25300CF2282 /* Accelerate.framework */, 34CB451525DDF24200CF2282 /* CoreMotion.framework */, 34CB451325DDF22800CF2282 /* VideoToolbox.framework */, 34CB451125DDF20300CF2282 /* libbz2.tbd */, - 343789FD26F78DCA003118B2 /* dav1d.framework */, - 343789F226F78DCA003118B2 /* expat.framework */, - 343789FC26F78DCA003118B2 /* ffmpegkit.framework */, - 343789E526F78DC9003118B2 /* fontconfig.framework */, - 343789FB26F78DCA003118B2 /* freetype.framework */, - 34378A1426F78DCC003118B2 /* fribidi.framework */, - 34378A0D26F78DCB003118B2 /* giflib.framework */, - 343789F526F78DCA003118B2 /* gmp.framework */, - 343789F026F78DCA003118B2 /* gnutls.framework */, - 34378A0026F78DCB003118B2 /* harfbuzz.framework */, - 34378A0926F78DCB003118B2 /* jpeg.framework */, - 343789E426F78DC9003118B2 /* kvazaar.framework */, - 34378A0C26F78DCB003118B2 /* lame.framework */, - 343789E826F78DC9003118B2 /* libass.framework */, - 34378A0626F78DCB003118B2 /* libavcodec.framework */, - 34378A0226F78DCB003118B2 /* libavdevice.framework */, - 34378A1126F78DCC003118B2 /* libavfilter.framework */, - 343789EB26F78DC9003118B2 /* libavformat.framework */, - 343789E626F78DC9003118B2 /* libavutil.framework */, - 343789F326F78DCA003118B2 /* libhogweed.framework */, - 34378A0426F78DCB003118B2 /* libilbc.framework */, - 343789E926F78DC9003118B2 /* libnettle.framework */, - 34378A1526F78DCC003118B2 /* libogg.framework */, - 343789F626F78DCA003118B2 /* libopencore-amrnb.framework */, - 343789FE26F78DCB003118B2 /* libpng.framework */, - 343789FF26F78DCB003118B2 /* libsndfile.framework */, - 34378A0826F78DCB003118B2 /* libswresample.framework */, - 343789F826F78DCA003118B2 /* libswscale.framework */, - 343789EA26F78DC9003118B2 /* libtheora.framework */, - 34378A0726F78DCB003118B2 /* libtheoradec.framework */, - 34378A1326F78DCC003118B2 /* libtheoraenc.framework */, - 343789F426F78DCA003118B2 /* libvidstab.framework */, - 343789EE26F78DCA003118B2 /* libvorbis.framework */, - 34378A1626F78DCC003118B2 /* libvorbisenc.framework */, - 34378A0E26F78DCB003118B2 /* libvorbisfile.framework */, - 34378A0B26F78DCB003118B2 /* libvpx.framework */, - 34378A0126F78DCB003118B2 /* libwebp.framework */, - 34378A0A26F78DCB003118B2 /* libwebpdemux.framework */, - 343789EF26F78DCA003118B2 /* libwebpmux.framework */, - 34378A0326F78DCB003118B2 /* libxml2.framework */, - 343789ED26F78DCA003118B2 /* opus.framework */, - 34378A0F26F78DCB003118B2 /* shine.framework */, - 343789FA26F78DCA003118B2 /* snappy.framework */, - 343789F126F78DCA003118B2 /* soxr.framework */, - 343789E726F78DC9003118B2 /* speex.framework */, - 343789F926F78DCA003118B2 /* tiff.framework */, - 34378A1226F78DCC003118B2 /* twolame.framework */, - 34378A0526F78DCB003118B2 /* vo-amrwbenc.framework */, - 343789F726F78DCA003118B2 /* x264.framework */, - 343789EC26F78DC9003118B2 /* x265.framework */, - 34378A1026F78DCC003118B2 /* xvidcore.framework */, 34CB450F25DDF1F900CF2282 /* libc++.tbd */, 34CB450D25DDF1EF00CF2282 /* libiconv.tbd */, 34CB450B25DDF1E600CF2282 /* libz.tbd */, @@ -475,6 +319,7 @@ 34FAE20E209F7DDD005CE2AE /* Resources */, 34F9744020A1A200004A1F68 /* Headers */, 3452D8CF20A373640045E6B0 /* Embed Frameworks */, + 3448266727328FD400ECED5A /* ShellScript */, ); buildRules = ( ); @@ -539,6 +384,26 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 3448266727328FD400ECED5A /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/ffmpegkit.framework/Resources/strip-frameworks.sh\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 34FAE20C209F7DDD005CE2AE /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -638,7 +503,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_CODE_SIGN_FLAGS = ""; @@ -693,7 +558,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CODE_SIGN_FLAGS = ""; OTHER_LIBTOOLFLAGS = "-liconv"; @@ -711,7 +576,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 46; DEVELOPMENT_TEAM = 98GD5J4999; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -720,12 +585,24 @@ ); HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = FFmpegKitIOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@loader_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = "$(inherited)"; MARKETING_VERSION = 2.0; OTHER_CODE_SIGN_FLAGS = "--deep"; - OTHER_LDFLAGS = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-rpath", + "@loader_path/Frameworks", + "-rpath", + "@executable_path/Frameworks", + "-rpath", + "@executable_path/../Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.FFmpegKitIOS; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -743,7 +620,7 @@ CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 13; + CURRENT_PROJECT_VERSION = 46; DEVELOPMENT_TEAM = 98GD5J4999; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -751,12 +628,24 @@ ); HEADER_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = FFmpegKitIOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + "IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@loader_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = "$(inherited)"; MARKETING_VERSION = 2.0; OTHER_CODE_SIGN_FLAGS = "--deep"; - OTHER_LDFLAGS = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-rpath", + "@loader_path/Frameworks", + "-rpath", + "@executable_path/Frameworks", + "-rpath", + "@executable_path/../Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.FFmpegKitIOS; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/ios/test-app-local-dependency/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate b/ios/test-app-local-dependency/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate index 91360ca..54b9f5b 100644 Binary files a/ios/test-app-local-dependency/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate and b/ios/test-app-local-dependency/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/AppDelegate.m b/ios/test-app-local-dependency/FFmpegKitIOS/AppDelegate.m index 26fc0b8..20b9c4e 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/AppDelegate.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/AppDelegate.m @@ -35,7 +35,7 @@ @interface AppDelegate () @implementation AppDelegate + (void)listFFprobeSessions { - NSArray* ffprobeSessions = [FFprobeKit listSessions]; + NSArray* ffprobeSessions = [FFprobeKit listFFprobeSessions]; NSLog(@"Listing FFprobe sessions.\n"); diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/AudioViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/AudioViewController.m index ad06792..e4d1b5d 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/AudioViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/AudioViewController.m @@ -130,7 +130,7 @@ - (IBAction)encodeAudio:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/CommandViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/CommandViewController.m index 455858e..b82fdb0 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/CommandViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/CommandViewController.m @@ -70,13 +70,13 @@ - (IBAction)runFFmpeg:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self withTitle:@"Error" message:@"Command failed. Please check output for the details." andButtonText:@"OK"]; }); @@ -99,7 +99,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process started with arguments\n'%@'.\n", ffprobeCommand); - FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withExecuteCallback:^(id session) { + FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withCompleteCallback:^(FFprobeSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; @@ -109,7 +109,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self withTitle:@"Error" message:@"Command failed. Please check output for the details." andButtonText:@"OK"]; }); diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/ConcurrentExecutionViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/ConcurrentExecutionViewController.m index 07e0cff..c3f8d80 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/ConcurrentExecutionViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/ConcurrentExecutionViewController.m @@ -121,7 +121,7 @@ - (void)encodeVideo:(int)buttonNumber { NSLog(@"FFmpeg process starting for button %d with arguments\n'%@'.\n", buttonNumber, ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/FFmpegKitTest.m b/ios/test-app-local-dependency/FFmpegKitIOS/FFmpegKitTest.m index 122a499..81b1bd7 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/FFmpegKitTest.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/FFmpegKitTest.m @@ -192,9 +192,9 @@ void testParseDoubleQuotesAndEscapesInCommand() { void getSessionIdTest() { NSArray *TEST_ARGUMENTS = [[NSArray alloc] initWithObjects:@"argument1", @"argument2", nil]; - FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; + FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; assert([sessions3 getSessionId] > [sessions2 getSessionId]); assert([sessions3 getSessionId] > [sessions1 getSessionId]); diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/HttpsViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/HttpsViewController.m index 849c307..0e90afc 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/HttpsViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/HttpsViewController.m @@ -113,7 +113,7 @@ - (void)runGetMediaInformation:(int)buttonNumber { [self clearOutput]; } - [FFprobeKit getMediaInformationAsync:testUrl withExecuteCallback:[self createNewExecuteCallback]]; + [FFprobeKit getMediaInformationAsync:testUrl withCompleteCallback:[self createNewCompleteCallback]]; } - (void)setActive { @@ -146,11 +146,11 @@ - (NSString*)getRandomTestUrl { } } -- (ExecuteCallback)createNewExecuteCallback { - return ^(id session){ +- (MediaInformationSessionCompleteCallback)createNewCompleteCallback { + return ^(MediaInformationSession* session){ addUIAction(^{ @synchronized (self->outputLock) { - MediaInformation *information = [((MediaInformationSession*) session) getMediaInformation]; + MediaInformation *information = [session getMediaInformation]; if (information == nil) { [self appendOutput:@"Get media information failed\n"]; [self appendOutput:[NSString stringWithFormat:@"State: %@\n", [FFmpegKitConfig sessionStateToString:[session getState]]]]; @@ -176,7 +176,7 @@ - (ExecuteCallback)createNewExecuteCallback { if ([information getTags] != nil) { NSDictionary* tags = [information getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@\n", key, [tags objectForKey:key]]]; } } if ([information getStreams] != nil) { @@ -239,7 +239,35 @@ - (ExecuteCallback)createNewExecuteCallback { if ([stream getTags] != nil) { NSDictionary* tags = [stream getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@\n", key, [tags objectForKey:key]]]; + } + } + } + } + if ([information getChapters] != nil) { + for (Chapter* chapter in [information getChapters]) { + if ([chapter getId] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter id: %@\n", [chapter getId]]]; + } + if ([chapter getTimeBase] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter time base: %@\n", [chapter getTimeBase]]]; + } + if ([chapter getStart] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start: %@\n", [chapter getStart]]]; + } + if ([chapter getStartTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start time: %@\n", [chapter getStartTime]]]; + } + if ([chapter getEnd] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end: %@\n", [chapter getEnd]]]; + } + if ([chapter getEndTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end time: %@\n", [chapter getEndTime]]]; + } + if ([chapter getTags] != nil) { + NSDictionary* tags = [chapter getTags]; + for(NSString *key in [tags allKeys]) { + [self appendOutput:[NSString stringWithFormat:@"Chapter tag: %@:%@\n", key, [tags objectForKey:key]]]; } } } diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/MediaInformationParserTest.m b/ios/test-app-local-dependency/FFmpegKitIOS/MediaInformationParserTest.m index f9071f1..2cabe99 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/MediaInformationParserTest.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/MediaInformationParserTest.m @@ -75,6 +75,85 @@ static void initTests() { " }\n" " }\n" " ],\n" + " \"chapters\": [\n" + " {\n" + " \"id\": 0,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"end\": 11158238,\n" + " \"end_time\": \"506.042540\",\n" + " \"tags\": {\n" + " \"title\": \"1 Laying Plans - 2 Waging War\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 1,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 11158238,\n" + " \"start_time\": \"506.042540\",\n" + " \"end\": 21433051,\n" + " \"end_time\": \"972.020454\",\n" + " \"tags\": {\n" + " \"title\": \"3 Attack By Stratagem - 4 Tactical Dispositions\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 2,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 21433051,\n" + " \"start_time\": \"972.020454\",\n" + " \"end\": 35478685,\n" + " \"end_time\": \"1609.010658\",\n" + " \"tags\": {\n" + " \"title\": \"5 Energy - 6 Weak Points and Strong\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 3,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 35478685,\n" + " \"start_time\": \"1609.010658\",\n" + " \"end\": 47187043,\n" + " \"end_time\": \"2140.001950\",\n" + " \"tags\": {\n" + " \"title\": \"7 Maneuvering - 8 Variation in Tactics\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 4,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 47187043,\n" + " \"start_time\": \"2140.001950\",\n" + " \"end\": 66635594,\n" + " \"end_time\": \"3022.022404\",\n" + " \"tags\": {\n" + " \"title\": \"9 The Army on the March - 10 Terrain\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 5,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 66635594,\n" + " \"start_time\": \"3022.022404\",\n" + " \"end\": 83768105,\n" + " \"end_time\": \"3799.007029\",\n" + " \"tags\": {\n" + " \"title\": \"11 The Nine Situations\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 6,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 83768105,\n" + " \"start_time\": \"3799.007029\",\n" + " \"end\": 95659008,\n" + " \"end_time\": \"4338.277007\",\n" + " \"tags\": {\n" + " \"title\": \"12 The Attack By Fire - 13 The Use of Spies\"\n" + " }\n" + " }\n" + " ],\n" " \"format\": {\n" " \"filename\": \"sample.mp3\",\n" " \"nb_streams\": 1,\n" @@ -448,6 +527,10 @@ static void initTests() { } +void assertNotNull(NSObject *object) { + assert(object != nil); +} + void assertNumber(NSNumber *expected, NSNumber *real) { if (expected == nil) { assert(real == nil); @@ -501,8 +584,21 @@ void assertAudioStream(StreamInformation *stream, NSNumber *index, NSString *cod assertString(bitrate, [stream getBitrate]); } -void assertNotNull(NSObject *object) { - assert(object != nil); +void assertChapter(Chapter *chapter, NSNumber *id, NSString *timeBase, NSNumber *start, NSString * startTime, NSNumber *end, NSString *endTime) { + assert(chapter != nil); + assertNumber(id, [chapter getId]); + assertString(timeBase, [chapter getTimeBase]); + + assertNumber(start, [chapter getStart]); + assertString(startTime, [chapter getStartTime]); + + assertNumber(end, [chapter getEnd]); + assertString(endTime, [chapter getEndTime]); + + NSDictionary *tags = [chapter getTags]; + assertNotNull(tags); + + assert(1 == [tags count]); } void assertMediaInput(MediaInformation *mediaInformation, NSString *expectedFormat, NSString *expectedFilename) { @@ -579,6 +675,13 @@ void testMediaInformationMp3() { assert(1 == [streams count]); assertAudioStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mp3", @"MP3 (MPEG audio layer 3)", @"44100", @"stereo", @"fltp", @"320000"); + + NSArray *chapters = [mediaInformation getChapters]; + assertNotNull(chapters); + assert(7 == [chapters count]); + + assertChapter([chapters objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"1/22050", [[NSNumber alloc] initWithInt:0], @"0.000000", [[NSNumber alloc] initWithInt:11158238], @"506.042540"); + assertChapter([chapters objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"1/22050", [[NSNumber alloc] initWithInt:11158238], @"506.042540", [[NSNumber alloc] initWithInt:21433051], @"972.020454"); } void testMediaInformationJpg() { diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/OtherViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/OtherViewController.m index fe4738a..b4eb238 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/OtherViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/OtherViewController.m @@ -23,6 +23,7 @@ #include #include #include "OtherViewController.h" +#include "Video.h" @interface OtherViewController () @@ -42,7 +43,7 @@ - (void)viewDidLoad { [super viewDidLoad]; // OTHER TEST PICKER INIT - testData = @[@"chromaprint", @"dav1d", @"webp"]; + testData = @[@"chromaprint", @"dav1d", @"webp", @"zscale"]; selectedTest = 0; self.otherTestPicker.dataSource = self; @@ -101,6 +102,9 @@ - (IBAction)runTest:(id)sender { case 2: [self testWebp]; break; + case 3: + [self testZscale]; + break; } } @@ -114,7 +118,7 @@ -(void)testChromaprint { NSLog(@"Creating audio sample with '%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -126,7 +130,7 @@ -(void)testChromaprint { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", chromaprintCommand); - [FFmpegKit executeAsync:chromaprintCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:chromaprintCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -146,7 +150,7 @@ -(void)testDav1d { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); } withLogCallback:^(Log *log) { addUIAction(^{ @@ -167,7 +171,29 @@ -(void)testWebp { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { + + NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); + + } withLogCallback:^(Log *log) { + addUIAction(^{ + [self appendOutput: [log getMessage]]; + }); + } withStatisticsCallback:nil]; +} + +-(void)testZscale { + NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + NSString *videoFile = [docFolder stringByAppendingPathComponent: @"video.mp4"]; + NSString *zscaledVideoFile = [docFolder stringByAppendingPathComponent: @"video.zscaled.mp4"]; + + NSLog(@"Testing 'zscale' filter with video file created on the Video tab\n"); + + NSString *ffmpegCommand = [Video generateZscaleVideoScript:videoFile:zscaledVideoFile]; + + NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); + + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/PipeViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/PipeViewController.m index 8bfb5ca..b368520 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/PipeViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/PipeViewController.m @@ -173,7 +173,7 @@ - (IBAction)createVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/SubtitleViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/SubtitleViewController.m index 6a07566..029bf28 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/SubtitleViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/SubtitleViewController.m @@ -133,7 +133,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = CreatingState; - sessionId = [[FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + sessionId = [[FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -154,7 +154,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = BurningState; - [FFmpegKit executeAsync:burnSubtitlesCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:burnSubtitlesCommand withCompleteCallback:^(id secondSession) { addUIAction(^{ [self hideProgressDialog]; diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/VidStabViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/VidStabViewController.m index d466d50..ecf8d42 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/VidStabViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/VidStabViewController.m @@ -129,7 +129,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); addUIAction(^{ @@ -147,7 +147,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", analyzeVideoCommand); - [FFmpegKit executeAsync:analyzeVideoCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:analyzeVideoCommand withCompleteCallback:^(id secondSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[secondSession getState]], [secondSession getReturnCode], notNull([secondSession getFailStackTrace], @"\n")); @@ -157,7 +157,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", stabilizeVideoCommand); - [FFmpegKit executeAsync:stabilizeVideoCommand withExecuteCallback:^(id thirdSession) { + [FFmpegKit executeAsync:stabilizeVideoCommand withCompleteCallback:^(id thirdSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[thirdSession getState]], [thirdSession getReturnCode], notNull([thirdSession getFailStackTrace], @"\n")); diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/Video.h b/ios/test-app-local-dependency/FFmpegKitIOS/Video.h index 7aa0a6c..977f2ef 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/Video.h +++ b/ios/test-app-local-dependency/FFmpegKitIOS/Video.h @@ -31,8 +31,12 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions; ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions; + + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile; ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath; + @end #endif /* FFMPEG_KIT_TEST_VIDEO */ diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/Video.m b/ios/test-app-local-dependency/FFmpegKitIOS/Video.m index 0778874..f910e28 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/Video.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/Video.m @@ -48,6 +48,10 @@ + (NSString*)generateCreateVideoWithPipesScript:(NSString *)image1 :(NSString *) } + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions { + return [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:videoCodec:@"yuv420p":customOptions]; +} + ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions { return [NSString stringWithFormat: @"-hide_banner -y -loop 1 -i %@ \ -loop 1 -i %@ \ @@ -66,8 +70,8 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :( [stream2ending]fade=t=out:s=0:n=30[stream2fadeout];\ [stream2fadein][stream1fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream2blended];\ [stream3fadein][stream2fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream3blended];\ -[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\" \ --map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, customOptions, videoCodec, videoFile]; +[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=%@[video]\" \ +-map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, pixelFormat, customOptions, videoCodec, videoFile]; } + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile { @@ -90,4 +94,8 @@ + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 : -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 %@", image1, image2, image3, videoFile]; } ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath { + return [NSString stringWithFormat:@"-y -i %@ -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p %@", inputVideoFilePath, outputVideoFilePath]; +} + @end diff --git a/ios/test-app-local-dependency/FFmpegKitIOS/VideoViewController.m b/ios/test-app-local-dependency/FFmpegKitIOS/VideoViewController.m index abca51c..45879a4 100644 --- a/ios/test-app-local-dependency/FFmpegKitIOS/VideoViewController.m +++ b/ios/test-app-local-dependency/FFmpegKitIOS/VideoViewController.m @@ -140,11 +140,11 @@ - (IBAction)encodeVideo:(id)sender { [self showProgressDialog:@"Encoding video\n\n"]; - NSString* ffmpegCommand = [Video generateVideoEncodeScript:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getCustomOptions]]; + NSString* ffmpegCommand = [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getPixelFormat]:[self getCustomOptions]]; NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session){ + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session){ SessionState state = [session getState]; ReturnCode *returnCode = [session getReturnCode]; @@ -195,6 +195,19 @@ - (void)playVideo { [player insertItem:newVideo afterItem:nil]; } +- (NSString*)getPixelFormat { + NSString *videoCodec = codecData[selectedCodec]; + + NSString *pixelFormat; + if ([videoCodec isEqualToString:@"x265"]) { + pixelFormat = @"yuv420p10le"; + } else { + pixelFormat = @"yuv420p"; + } + + return pixelFormat; +} + - (NSString*)getSelectedVideoCodec { NSString *videoCodec = codecData[selectedCodec]; diff --git a/ios/test-app-local-universal-library/.gitignore b/ios/test-app-local-universal-library/.gitignore deleted file mode 100644 index 201b510..0000000 --- a/ios/test-app-local-universal-library/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/Pods/ -/*.xcframework/ -/*.framework/ -/*-universal/ - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.pbxproj b/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.pbxproj deleted file mode 100644 index ae3964e..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.pbxproj +++ /dev/null @@ -1,807 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - 340FABBE2115A17600B33CE7 /* VidStabViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 340FABBC2115A17600B33CE7 /* VidStabViewController.h */; }; - 340FABBF2115A17600B33CE7 /* VidStabViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340FABBD2115A17600B33CE7 /* VidStabViewController.m */; }; - 342900CB22DE2BCF0071B2E4 /* MediaInformationParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 342900C722DE2BCF0071B2E4 /* MediaInformationParserTest.m */; }; - 342900CD22DE2BCF0071B2E4 /* MediaInformationParserTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 342900C922DE2BCF0071B2E4 /* MediaInformationParserTest.h */; }; - 34378A7F26F790B4003118B2 /* libopencore-amrnb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A4C26F790B1003118B2 /* libopencore-amrnb.a */; }; - 34378A8026F790B4003118B2 /* libtiff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A4D26F790B1003118B2 /* libtiff.a */; }; - 34378A8126F790B4003118B2 /* libwebpmux.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A4E26F790B1003118B2 /* libwebpmux.a */; }; - 34378A8226F790B4003118B2 /* libogg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A4F26F790B1003118B2 /* libogg.a */; }; - 34378A8326F790B4003118B2 /* libmp3lame.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5026F790B1003118B2 /* libmp3lame.a */; }; - 34378A8426F790B4003118B2 /* libvidstab.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5126F790B1003118B2 /* libvidstab.a */; }; - 34378A8526F790B4003118B2 /* libvorbisenc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5226F790B2003118B2 /* libvorbisenc.a */; }; - 34378A8626F790B4003118B2 /* libswresample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5326F790B2003118B2 /* libswresample.a */; }; - 34378A8726F790B4003118B2 /* libopus.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5426F790B2003118B2 /* libopus.a */; }; - 34378A8826F790B4003118B2 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5526F790B2003118B2 /* libgmp.a */; }; - 34378A8926F790B4003118B2 /* libwebpdemux.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5626F790B2003118B2 /* libwebpdemux.a */; }; - 34378A8A26F790B4003118B2 /* libilbc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5726F790B2003118B2 /* libilbc.a */; }; - 34378A8B26F790B4003118B2 /* libsnappy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5826F790B2003118B2 /* libsnappy.a */; }; - 34378A8C26F790B4003118B2 /* libffmpegkit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5926F790B2003118B2 /* libffmpegkit.a */; }; - 34378A8D26F790B4003118B2 /* libvpx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5A26F790B2003118B2 /* libvpx.a */; }; - 34378A8E26F790B4003118B2 /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5B26F790B2003118B2 /* libjpeg.a */; }; - 34378A8F26F790B4003118B2 /* libnettle.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5C26F790B2003118B2 /* libnettle.a */; }; - 34378A9026F790B4003118B2 /* libtwolame.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5D26F790B2003118B2 /* libtwolame.a */; }; - 34378A9126F790B4003118B2 /* libxvidcore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5E26F790B2003118B2 /* libxvidcore.a */; }; - 34378A9226F790B4003118B2 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A5F26F790B2003118B2 /* libpng.a */; }; - 34378A9326F790B4003118B2 /* libtheoradec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6026F790B2003118B2 /* libtheoradec.a */; }; - 34378A9426F790B4003118B2 /* libdav1d.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6126F790B2003118B2 /* libdav1d.a */; }; - 34378A9526F790B4003118B2 /* libx264.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6226F790B2003118B2 /* libx264.a */; }; - 34378A9626F790B4003118B2 /* libwebp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6326F790B2003118B2 /* libwebp.a */; }; - 34378A9726F790B4003118B2 /* libhogweed.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6426F790B2003118B2 /* libhogweed.a */; }; - 34378A9826F790B4003118B2 /* libsoxr.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6526F790B2003118B2 /* libsoxr.a */; }; - 34378A9926F790B4003118B2 /* libgnutls.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6626F790B2003118B2 /* libgnutls.a */; }; - 34378A9A26F790B4003118B2 /* libfribidi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6726F790B2003118B2 /* libfribidi.a */; }; - 34378A9B26F790B4003118B2 /* libsndfile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6826F790B3003118B2 /* libsndfile.a */; }; - 34378A9C26F790B4003118B2 /* libavformat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6926F790B3003118B2 /* libavformat.a */; }; - 34378A9D26F790B4003118B2 /* libtheoraenc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6A26F790B3003118B2 /* libtheoraenc.a */; }; - 34378A9E26F790B4003118B2 /* libfontconfig.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6B26F790B3003118B2 /* libfontconfig.a */; }; - 34378A9F26F790B4003118B2 /* libvorbis.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6C26F790B3003118B2 /* libvorbis.a */; }; - 34378AA026F790B4003118B2 /* libfreetype.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6D26F790B3003118B2 /* libfreetype.a */; }; - 34378AA126F790B4003118B2 /* libswscale.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6E26F790B3003118B2 /* libswscale.a */; }; - 34378AA226F790B4003118B2 /* libavcodec.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A6F26F790B3003118B2 /* libavcodec.a */; }; - 34378AA326F790B5003118B2 /* libharfbuzz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7026F790B3003118B2 /* libharfbuzz.a */; }; - 34378AA426F790B5003118B2 /* libshine.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7126F790B3003118B2 /* libshine.a */; }; - 34378AA526F790B5003118B2 /* libexpat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7226F790B3003118B2 /* libexpat.a */; }; - 34378AA626F790B5003118B2 /* libspeex.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7326F790B3003118B2 /* libspeex.a */; }; - 34378AA726F790B5003118B2 /* libgif.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7426F790B3003118B2 /* libgif.a */; }; - 34378AA826F790B5003118B2 /* libvo-amrwbenc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7526F790B3003118B2 /* libvo-amrwbenc.a */; }; - 34378AA926F790B5003118B2 /* libavdevice.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7626F790B3003118B2 /* libavdevice.a */; }; - 34378AAA26F790B5003118B2 /* libvorbisfile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7726F790B3003118B2 /* libvorbisfile.a */; }; - 34378AAB26F790B5003118B2 /* libxml2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7826F790B3003118B2 /* libxml2.a */; }; - 34378AAC26F790B5003118B2 /* libtheora.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7926F790B3003118B2 /* libtheora.a */; }; - 34378AAD26F790B5003118B2 /* libkvazaar.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7A26F790B3003118B2 /* libkvazaar.a */; }; - 34378AAE26F790B5003118B2 /* libx265.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7B26F790B3003118B2 /* libx265.a */; }; - 34378AAF26F790B5003118B2 /* libass.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7C26F790B3003118B2 /* libass.a */; }; - 34378AB026F790B5003118B2 /* libavutil.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7D26F790B4003118B2 /* libavutil.a */; }; - 34378AB126F790B5003118B2 /* libavfilter.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34378A7E26F790B4003118B2 /* libavfilter.a */; }; - 343D714525E10CAD007CB801 /* Video.m in Sources */ = {isa = PBXBuildFile; fileRef = 343D714425E10CAC007CB801 /* Video.m */; }; - 343E66B5210784BD00F95E5B /* HttpsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 343E66B3210784BD00F95E5B /* HttpsViewController.h */; }; - 343E66B6210784BD00F95E5B /* HttpsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 343E66B4210784BD00F95E5B /* HttpsViewController.m */; }; - 343E66B9210789DE00F95E5B /* Constants.h in Headers */ = {isa = PBXBuildFile; fileRef = 343E66B7210789DE00F95E5B /* Constants.h */; }; - 343E67052107AD0100F95E5B /* Util.h in Headers */ = {isa = PBXBuildFile; fileRef = 343E67032107AD0100F95E5B /* Util.h */; }; - 343E67062107AD0100F95E5B /* Util.m in Sources */ = {isa = PBXBuildFile; fileRef = 343E67042107AD0100F95E5B /* Util.m */; }; - 343E67092107C27600F95E5B /* TabBarController.h in Headers */ = {isa = PBXBuildFile; fileRef = 343E67072107C27600F95E5B /* TabBarController.h */; }; - 343E670A2107C27600F95E5B /* TabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 343E67082107C27600F95E5B /* TabBarController.m */; }; - 3457454B2113B8AD00059043 /* AudioViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 345745492113B8AD00059043 /* AudioViewController.h */; }; - 3457454C2113B8AD00059043 /* AudioViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3457454A2113B8AD00059043 /* AudioViewController.m */; }; - 3457454F2113B8D300059043 /* SubtitleViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3457454D2113B8D300059043 /* SubtitleViewController.h */; }; - 345745502113B8D300059043 /* SubtitleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3457454E2113B8D300059043 /* SubtitleViewController.m */; }; - 345E16AA24CB93D1007275F0 /* ConcurrentExecutionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 345E16A824CB93D1007275F0 /* ConcurrentExecutionViewController.m */; }; - 345E16AB24CB93D1007275F0 /* ConcurrentExecutionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 345E16A924CB93D1007275F0 /* ConcurrentExecutionViewController.h */; }; - 348439ED20B2EFAF001A3990 /* pyramid.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 348439EA20B2EFAF001A3990 /* pyramid.jpg */; }; - 3484F7B72604269400640DED /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB451925DDF26A00CF2282 /* GameController.framework */; }; - 3484F7B82604269500640DED /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB451725DDF25300CF2282 /* Accelerate.framework */; }; - 3484F7B92604269600640DED /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB451525DDF24200CF2282 /* CoreMotion.framework */; }; - 3484F7BA2604269700640DED /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB451325DDF22800CF2282 /* VideoToolbox.framework */; }; - 3484F7BB2604269800640DED /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB451125DDF20300CF2282 /* libbz2.tbd */; }; - 3484F7BC2604269A00640DED /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB450F25DDF1F900CF2282 /* libc++.tbd */; }; - 3484F7BD2604269A00640DED /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB450D25DDF1EF00CF2282 /* libiconv.tbd */; }; - 3484F7BE2604269C00640DED /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34CB450B25DDF1E600CF2282 /* libz.tbd */; }; - 3487ABA5220CEAA300A40E8D /* PipeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3487ABA3220CEAA200A40E8D /* PipeViewController.m */; }; - 3487ABA6220CEAA300A40E8D /* PipeViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3487ABA4220CEAA200A40E8D /* PipeViewController.h */; }; - 34943E6825DB499E002B5C1E /* FFmpegKitTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 34943E6625DB499E002B5C1E /* FFmpegKitTest.h */; }; - 34943E6925DB499E002B5C1E /* FFmpegKitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 34943E6725DB499E002B5C1E /* FFmpegKitTest.m */; }; - 34BB547C2109D44800606B7C /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 34BB547B2109D44800606B7C /* Constants.m */; }; - 34CB451D25DDF76200CF2282 /* machupicchu.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 34CB451B25DDF76200CF2282 /* machupicchu.jpg */; }; - 34CB451E25DDF76200CF2282 /* stonehenge.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 34CB451C25DDF76200CF2282 /* stonehenge.jpg */; }; - 34D37D0F25DBEA1D00B8914A /* OtherViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D37D0D25DBEA1D00B8914A /* OtherViewController.m */; }; - 34D37D1025DBEA1D00B8914A /* OtherViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 34D37D0E25DBEA1D00B8914A /* OtherViewController.h */; }; - 34DC789B21215B5800C3486C /* truenorg.otf in Resources */ = {isa = PBXBuildFile; fileRef = 34DC789721215B5800C3486C /* truenorg.otf */; }; - 34DC789C21215B5800C3486C /* subtitle.srt in Resources */ = {isa = PBXBuildFile; fileRef = 34DC789821215B5800C3486C /* subtitle.srt */; }; - 34DC789D21215B5800C3486C /* doppioone_regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34DC789921215B5800C3486C /* doppioone_regular.ttf */; }; - 34DC789E21215B5800C3486C /* sil_open_font_license.txt in Resources */ = {isa = PBXBuildFile; fileRef = 34DC789A21215B5800C3486C /* sil_open_font_license.txt */; }; - 34FAE215209F7DDD005CE2AE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FAE214209F7DDD005CE2AE /* AppDelegate.m */; }; - 34FAE218209F7DDD005CE2AE /* CommandViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FAE217209F7DDD005CE2AE /* CommandViewController.m */; }; - 34FAE21B209F7DDD005CE2AE /* VideoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FAE21A209F7DDD005CE2AE /* VideoViewController.m */; }; - 34FAE21E209F7DDD005CE2AE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 34FAE21C209F7DDD005CE2AE /* Main.storyboard */; }; - 34FAE220209F7DDE005CE2AE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 34FAE21F209F7DDE005CE2AE /* Assets.xcassets */; }; - 34FAE223209F7DDE005CE2AE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 34FAE221209F7DDE005CE2AE /* LaunchScreen.storyboard */; }; - 34FAE226209F7DDE005CE2AE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 34FAE225209F7DDE005CE2AE /* main.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 3452D8CF20A373640045E6B0 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 12; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 340FABBC2115A17600B33CE7 /* VidStabViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VidStabViewController.h; sourceTree = ""; }; - 340FABBD2115A17600B33CE7 /* VidStabViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VidStabViewController.m; sourceTree = ""; }; - 342900C722DE2BCF0071B2E4 /* MediaInformationParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MediaInformationParserTest.m; sourceTree = ""; }; - 342900C922DE2BCF0071B2E4 /* MediaInformationParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaInformationParserTest.h; sourceTree = ""; }; - 34378A4C26F790B1003118B2 /* libopencore-amrnb.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libopencore-amrnb.a"; path = "ffmpeg-kit-ios-universal/lib/libopencore-amrnb.a"; sourceTree = ""; }; - 34378A4D26F790B1003118B2 /* libtiff.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtiff.a; path = "ffmpeg-kit-ios-universal/lib/libtiff.a"; sourceTree = ""; }; - 34378A4E26F790B1003118B2 /* libwebpmux.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libwebpmux.a; path = "ffmpeg-kit-ios-universal/lib/libwebpmux.a"; sourceTree = ""; }; - 34378A4F26F790B1003118B2 /* libogg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libogg.a; path = "ffmpeg-kit-ios-universal/lib/libogg.a"; sourceTree = ""; }; - 34378A5026F790B1003118B2 /* libmp3lame.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmp3lame.a; path = "ffmpeg-kit-ios-universal/lib/libmp3lame.a"; sourceTree = ""; }; - 34378A5126F790B1003118B2 /* libvidstab.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvidstab.a; path = "ffmpeg-kit-ios-universal/lib/libvidstab.a"; sourceTree = ""; }; - 34378A5226F790B2003118B2 /* libvorbisenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisenc.a; path = "ffmpeg-kit-ios-universal/lib/libvorbisenc.a"; sourceTree = ""; }; - 34378A5326F790B2003118B2 /* libswresample.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libswresample.a; path = "ffmpeg-kit-ios-universal/lib/libswresample.a"; sourceTree = ""; }; - 34378A5426F790B2003118B2 /* libopus.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libopus.a; path = "ffmpeg-kit-ios-universal/lib/libopus.a"; sourceTree = ""; }; - 34378A5526F790B2003118B2 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgmp.a; path = "ffmpeg-kit-ios-universal/lib/libgmp.a"; sourceTree = ""; }; - 34378A5626F790B2003118B2 /* libwebpdemux.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libwebpdemux.a; path = "ffmpeg-kit-ios-universal/lib/libwebpdemux.a"; sourceTree = ""; }; - 34378A5726F790B2003118B2 /* libilbc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libilbc.a; path = "ffmpeg-kit-ios-universal/lib/libilbc.a"; sourceTree = ""; }; - 34378A5826F790B2003118B2 /* libsnappy.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsnappy.a; path = "ffmpeg-kit-ios-universal/lib/libsnappy.a"; sourceTree = ""; }; - 34378A5926F790B2003118B2 /* libffmpegkit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libffmpegkit.a; path = "ffmpeg-kit-ios-universal/lib/libffmpegkit.a"; sourceTree = ""; }; - 34378A5A26F790B2003118B2 /* libvpx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvpx.a; path = "ffmpeg-kit-ios-universal/lib/libvpx.a"; sourceTree = ""; }; - 34378A5B26F790B2003118B2 /* libjpeg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjpeg.a; path = "ffmpeg-kit-ios-universal/lib/libjpeg.a"; sourceTree = ""; }; - 34378A5C26F790B2003118B2 /* libnettle.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libnettle.a; path = "ffmpeg-kit-ios-universal/lib/libnettle.a"; sourceTree = ""; }; - 34378A5D26F790B2003118B2 /* libtwolame.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtwolame.a; path = "ffmpeg-kit-ios-universal/lib/libtwolame.a"; sourceTree = ""; }; - 34378A5E26F790B2003118B2 /* libxvidcore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libxvidcore.a; path = "ffmpeg-kit-ios-universal/lib/libxvidcore.a"; sourceTree = ""; }; - 34378A5F26F790B2003118B2 /* libpng.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpng.a; path = "ffmpeg-kit-ios-universal/lib/libpng.a"; sourceTree = ""; }; - 34378A6026F790B2003118B2 /* libtheoradec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtheoradec.a; path = "ffmpeg-kit-ios-universal/lib/libtheoradec.a"; sourceTree = ""; }; - 34378A6126F790B2003118B2 /* libdav1d.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdav1d.a; path = "ffmpeg-kit-ios-universal/lib/libdav1d.a"; sourceTree = ""; }; - 34378A6226F790B2003118B2 /* libx264.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libx264.a; path = "ffmpeg-kit-ios-universal/lib/libx264.a"; sourceTree = ""; }; - 34378A6326F790B2003118B2 /* libwebp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libwebp.a; path = "ffmpeg-kit-ios-universal/lib/libwebp.a"; sourceTree = ""; }; - 34378A6426F790B2003118B2 /* libhogweed.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libhogweed.a; path = "ffmpeg-kit-ios-universal/lib/libhogweed.a"; sourceTree = ""; }; - 34378A6526F790B2003118B2 /* libsoxr.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsoxr.a; path = "ffmpeg-kit-ios-universal/lib/libsoxr.a"; sourceTree = ""; }; - 34378A6626F790B2003118B2 /* libgnutls.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgnutls.a; path = "ffmpeg-kit-ios-universal/lib/libgnutls.a"; sourceTree = ""; }; - 34378A6726F790B2003118B2 /* libfribidi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfribidi.a; path = "ffmpeg-kit-ios-universal/lib/libfribidi.a"; sourceTree = ""; }; - 34378A6826F790B3003118B2 /* libsndfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsndfile.a; path = "ffmpeg-kit-ios-universal/lib/libsndfile.a"; sourceTree = ""; }; - 34378A6926F790B3003118B2 /* libavformat.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavformat.a; path = "ffmpeg-kit-ios-universal/lib/libavformat.a"; sourceTree = ""; }; - 34378A6A26F790B3003118B2 /* libtheoraenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtheoraenc.a; path = "ffmpeg-kit-ios-universal/lib/libtheoraenc.a"; sourceTree = ""; }; - 34378A6B26F790B3003118B2 /* libfontconfig.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfontconfig.a; path = "ffmpeg-kit-ios-universal/lib/libfontconfig.a"; sourceTree = ""; }; - 34378A6C26F790B3003118B2 /* libvorbis.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbis.a; path = "ffmpeg-kit-ios-universal/lib/libvorbis.a"; sourceTree = ""; }; - 34378A6D26F790B3003118B2 /* libfreetype.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libfreetype.a; path = "ffmpeg-kit-ios-universal/lib/libfreetype.a"; sourceTree = ""; }; - 34378A6E26F790B3003118B2 /* libswscale.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libswscale.a; path = "ffmpeg-kit-ios-universal/lib/libswscale.a"; sourceTree = ""; }; - 34378A6F26F790B3003118B2 /* libavcodec.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavcodec.a; path = "ffmpeg-kit-ios-universal/lib/libavcodec.a"; sourceTree = ""; }; - 34378A7026F790B3003118B2 /* libharfbuzz.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libharfbuzz.a; path = "ffmpeg-kit-ios-universal/lib/libharfbuzz.a"; sourceTree = ""; }; - 34378A7126F790B3003118B2 /* libshine.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libshine.a; path = "ffmpeg-kit-ios-universal/lib/libshine.a"; sourceTree = ""; }; - 34378A7226F790B3003118B2 /* libexpat.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libexpat.a; path = "ffmpeg-kit-ios-universal/lib/libexpat.a"; sourceTree = ""; }; - 34378A7326F790B3003118B2 /* libspeex.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libspeex.a; path = "ffmpeg-kit-ios-universal/lib/libspeex.a"; sourceTree = ""; }; - 34378A7426F790B3003118B2 /* libgif.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgif.a; path = "ffmpeg-kit-ios-universal/lib/libgif.a"; sourceTree = ""; }; - 34378A7526F790B3003118B2 /* libvo-amrwbenc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libvo-amrwbenc.a"; path = "ffmpeg-kit-ios-universal/lib/libvo-amrwbenc.a"; sourceTree = ""; }; - 34378A7626F790B3003118B2 /* libavdevice.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavdevice.a; path = "ffmpeg-kit-ios-universal/lib/libavdevice.a"; sourceTree = ""; }; - 34378A7726F790B3003118B2 /* libvorbisfile.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvorbisfile.a; path = "ffmpeg-kit-ios-universal/lib/libvorbisfile.a"; sourceTree = ""; }; - 34378A7826F790B3003118B2 /* libxml2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libxml2.a; path = "ffmpeg-kit-ios-universal/lib/libxml2.a"; sourceTree = ""; }; - 34378A7926F790B3003118B2 /* libtheora.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtheora.a; path = "ffmpeg-kit-ios-universal/lib/libtheora.a"; sourceTree = ""; }; - 34378A7A26F790B3003118B2 /* libkvazaar.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libkvazaar.a; path = "ffmpeg-kit-ios-universal/lib/libkvazaar.a"; sourceTree = ""; }; - 34378A7B26F790B3003118B2 /* libx265.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libx265.a; path = "ffmpeg-kit-ios-universal/lib/libx265.a"; sourceTree = ""; }; - 34378A7C26F790B3003118B2 /* libass.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libass.a; path = "ffmpeg-kit-ios-universal/lib/libass.a"; sourceTree = ""; }; - 34378A7D26F790B4003118B2 /* libavutil.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavutil.a; path = "ffmpeg-kit-ios-universal/lib/libavutil.a"; sourceTree = ""; }; - 34378A7E26F790B4003118B2 /* libavfilter.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libavfilter.a; path = "ffmpeg-kit-ios-universal/lib/libavfilter.a"; sourceTree = ""; }; - 343D714425E10CAC007CB801 /* Video.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Video.m; sourceTree = ""; }; - 343D714625E10CBA007CB801 /* Video.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = ""; }; - 343E66B3210784BD00F95E5B /* HttpsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HttpsViewController.h; sourceTree = ""; }; - 343E66B4210784BD00F95E5B /* HttpsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HttpsViewController.m; sourceTree = ""; }; - 343E66B7210789DE00F95E5B /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = ""; }; - 343E67032107AD0100F95E5B /* Util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Util.h; sourceTree = ""; }; - 343E67042107AD0100F95E5B /* Util.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Util.m; sourceTree = ""; }; - 343E67072107C27600F95E5B /* TabBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TabBarController.h; sourceTree = ""; }; - 343E67082107C27600F95E5B /* TabBarController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TabBarController.m; sourceTree = ""; }; - 345745492113B8AD00059043 /* AudioViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioViewController.h; sourceTree = ""; }; - 3457454A2113B8AD00059043 /* AudioViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioViewController.m; sourceTree = ""; }; - 3457454D2113B8D300059043 /* SubtitleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SubtitleViewController.h; sourceTree = ""; }; - 3457454E2113B8D300059043 /* SubtitleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SubtitleViewController.m; sourceTree = ""; }; - 345E16A824CB93D1007275F0 /* ConcurrentExecutionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConcurrentExecutionViewController.m; sourceTree = ""; }; - 345E16A924CB93D1007275F0 /* ConcurrentExecutionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcurrentExecutionViewController.h; sourceTree = ""; }; - 346B8266244878C000971D55 /* FFmpegKitIOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = FFmpegKitIOS.entitlements; sourceTree = ""; }; - 348439EA20B2EFAF001A3990 /* pyramid.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = pyramid.jpg; sourceTree = ""; }; - 3487ABA3220CEAA200A40E8D /* PipeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PipeViewController.m; sourceTree = ""; }; - 3487ABA4220CEAA200A40E8D /* PipeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PipeViewController.h; sourceTree = ""; }; - 34943E6625DB499E002B5C1E /* FFmpegKitTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FFmpegKitTest.h; sourceTree = ""; }; - 34943E6725DB499E002B5C1E /* FFmpegKitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FFmpegKitTest.m; sourceTree = ""; }; - 34BB547B2109D44800606B7C /* Constants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Constants.m; sourceTree = ""; }; - 34CB450B25DDF1E600CF2282 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; }; - 34CB450D25DDF1EF00CF2282 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/usr/lib/libiconv.tbd; sourceTree = DEVELOPER_DIR; }; - 34CB450F25DDF1F900CF2282 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/usr/lib/libc++.tbd"; sourceTree = DEVELOPER_DIR; }; - 34CB451125DDF20300CF2282 /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/usr/lib/libbz2.tbd; sourceTree = DEVELOPER_DIR; }; - 34CB451325DDF22800CF2282 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/VideoToolbox.framework; sourceTree = DEVELOPER_DIR; }; - 34CB451525DDF24200CF2282 /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/CoreMotion.framework; sourceTree = DEVELOPER_DIR; }; - 34CB451725DDF25300CF2282 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = DEVELOPER_DIR; }; - 34CB451925DDF26A00CF2282 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/iOSSupport/System/Library/Frameworks/GameController.framework; sourceTree = DEVELOPER_DIR; }; - 34CB451B25DDF76200CF2282 /* machupicchu.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = machupicchu.jpg; sourceTree = ""; }; - 34CB451C25DDF76200CF2282 /* stonehenge.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = stonehenge.jpg; sourceTree = ""; }; - 34D37D0D25DBEA1D00B8914A /* OtherViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OtherViewController.m; sourceTree = ""; }; - 34D37D0E25DBEA1D00B8914A /* OtherViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OtherViewController.h; sourceTree = ""; }; - 34DC789721215B5800C3486C /* truenorg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = truenorg.otf; sourceTree = ""; }; - 34DC789821215B5800C3486C /* subtitle.srt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = subtitle.srt; sourceTree = ""; }; - 34DC789921215B5800C3486C /* doppioone_regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = doppioone_regular.ttf; sourceTree = ""; }; - 34DC789A21215B5800C3486C /* sil_open_font_license.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = sil_open_font_license.txt; sourceTree = ""; }; - 34FAE210209F7DDD005CE2AE /* FFmpegKitIOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FFmpegKitIOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 34FAE213209F7DDD005CE2AE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 34FAE214209F7DDD005CE2AE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 34FAE216209F7DDD005CE2AE /* CommandViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommandViewController.h; sourceTree = ""; }; - 34FAE217209F7DDD005CE2AE /* CommandViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CommandViewController.m; sourceTree = ""; }; - 34FAE219209F7DDD005CE2AE /* VideoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VideoViewController.h; sourceTree = ""; }; - 34FAE21A209F7DDD005CE2AE /* VideoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VideoViewController.m; sourceTree = ""; }; - 34FAE21D209F7DDD005CE2AE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 34FAE21F209F7DDE005CE2AE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 34FAE222209F7DDE005CE2AE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 34FAE224209F7DDE005CE2AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 34FAE225209F7DDE005CE2AE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 34FAE20D209F7DDD005CE2AE /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3484F7B82604269500640DED /* Accelerate.framework in Frameworks */, - 34378A9B26F790B4003118B2 /* libsndfile.a in Frameworks */, - 34378A9E26F790B4003118B2 /* libfontconfig.a in Frameworks */, - 34378A9826F790B4003118B2 /* libsoxr.a in Frameworks */, - 34378A9C26F790B4003118B2 /* libavformat.a in Frameworks */, - 34378AA126F790B4003118B2 /* libswscale.a in Frameworks */, - 34378A9026F790B4003118B2 /* libtwolame.a in Frameworks */, - 34378A9A26F790B4003118B2 /* libfribidi.a in Frameworks */, - 34378A9326F790B4003118B2 /* libtheoradec.a in Frameworks */, - 34378AA326F790B5003118B2 /* libharfbuzz.a in Frameworks */, - 34378AAB26F790B5003118B2 /* libxml2.a in Frameworks */, - 34378A8A26F790B4003118B2 /* libilbc.a in Frameworks */, - 34378A9526F790B4003118B2 /* libx264.a in Frameworks */, - 3484F7B92604269600640DED /* CoreMotion.framework in Frameworks */, - 34378AA026F790B4003118B2 /* libfreetype.a in Frameworks */, - 34378A8C26F790B4003118B2 /* libffmpegkit.a in Frameworks */, - 34378A9426F790B4003118B2 /* libdav1d.a in Frameworks */, - 34378AA926F790B5003118B2 /* libavdevice.a in Frameworks */, - 34378A8526F790B4003118B2 /* libvorbisenc.a in Frameworks */, - 34378A8E26F790B4003118B2 /* libjpeg.a in Frameworks */, - 34378A8B26F790B4003118B2 /* libsnappy.a in Frameworks */, - 34378AB126F790B5003118B2 /* libavfilter.a in Frameworks */, - 34378A8F26F790B4003118B2 /* libnettle.a in Frameworks */, - 34378AA226F790B4003118B2 /* libavcodec.a in Frameworks */, - 34378A8726F790B4003118B2 /* libopus.a in Frameworks */, - 34378A9926F790B4003118B2 /* libgnutls.a in Frameworks */, - 34378AAF26F790B5003118B2 /* libass.a in Frameworks */, - 3484F7B72604269400640DED /* GameController.framework in Frameworks */, - 3484F7BB2604269800640DED /* libbz2.tbd in Frameworks */, - 34378A8026F790B4003118B2 /* libtiff.a in Frameworks */, - 34378AAC26F790B5003118B2 /* libtheora.a in Frameworks */, - 34378A8326F790B4003118B2 /* libmp3lame.a in Frameworks */, - 34378A7F26F790B4003118B2 /* libopencore-amrnb.a in Frameworks */, - 34378A8626F790B4003118B2 /* libswresample.a in Frameworks */, - 34378AA826F790B5003118B2 /* libvo-amrwbenc.a in Frameworks */, - 34378AA526F790B5003118B2 /* libexpat.a in Frameworks */, - 34378A8926F790B4003118B2 /* libwebpdemux.a in Frameworks */, - 34378A8826F790B4003118B2 /* libgmp.a in Frameworks */, - 34378AAE26F790B5003118B2 /* libx265.a in Frameworks */, - 3484F7BA2604269700640DED /* VideoToolbox.framework in Frameworks */, - 34378A9726F790B4003118B2 /* libhogweed.a in Frameworks */, - 34378AA426F790B5003118B2 /* libshine.a in Frameworks */, - 34378A8226F790B4003118B2 /* libogg.a in Frameworks */, - 34378A8426F790B4003118B2 /* libvidstab.a in Frameworks */, - 34378AA626F790B5003118B2 /* libspeex.a in Frameworks */, - 34378A9126F790B4003118B2 /* libxvidcore.a in Frameworks */, - 34378A8126F790B4003118B2 /* libwebpmux.a in Frameworks */, - 3484F7BD2604269A00640DED /* libiconv.tbd in Frameworks */, - 3484F7BE2604269C00640DED /* libz.tbd in Frameworks */, - 34378AB026F790B5003118B2 /* libavutil.a in Frameworks */, - 3484F7BC2604269A00640DED /* libc++.tbd in Frameworks */, - 34378A9626F790B4003118B2 /* libwebp.a in Frameworks */, - 34378AAD26F790B5003118B2 /* libkvazaar.a in Frameworks */, - 34378AAA26F790B5003118B2 /* libvorbisfile.a in Frameworks */, - 34378A8D26F790B4003118B2 /* libvpx.a in Frameworks */, - 34378AA726F790B5003118B2 /* libgif.a in Frameworks */, - 34378A9226F790B4003118B2 /* libpng.a in Frameworks */, - 34378A9F26F790B4003118B2 /* libvorbis.a in Frameworks */, - 34378A9D26F790B4003118B2 /* libtheoraenc.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 346AA95920B2ED94000623FE /* Resources */ = { - isa = PBXGroup; - children = ( - 34DC789921215B5800C3486C /* doppioone_regular.ttf */, - 34CB451B25DDF76200CF2282 /* machupicchu.jpg */, - 348439EA20B2EFAF001A3990 /* pyramid.jpg */, - 34DC789A21215B5800C3486C /* sil_open_font_license.txt */, - 34CB451C25DDF76200CF2282 /* stonehenge.jpg */, - 34DC789821215B5800C3486C /* subtitle.srt */, - 34DC789721215B5800C3486C /* truenorg.otf */, - ); - path = Resources; - sourceTree = ""; - }; - 3498DC65209F7F1C005F5883 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 34CB451925DDF26A00CF2282 /* GameController.framework */, - 34CB451725DDF25300CF2282 /* Accelerate.framework */, - 34378A7C26F790B3003118B2 /* libass.a */, - 34378A6F26F790B3003118B2 /* libavcodec.a */, - 34378A7626F790B3003118B2 /* libavdevice.a */, - 34378A7E26F790B4003118B2 /* libavfilter.a */, - 34378A6926F790B3003118B2 /* libavformat.a */, - 34378A7D26F790B4003118B2 /* libavutil.a */, - 34378A6126F790B2003118B2 /* libdav1d.a */, - 34378A7226F790B3003118B2 /* libexpat.a */, - 34378A5926F790B2003118B2 /* libffmpegkit.a */, - 34378A6B26F790B3003118B2 /* libfontconfig.a */, - 34378A6D26F790B3003118B2 /* libfreetype.a */, - 34378A6726F790B2003118B2 /* libfribidi.a */, - 34378A7426F790B3003118B2 /* libgif.a */, - 34378A5526F790B2003118B2 /* libgmp.a */, - 34378A6626F790B2003118B2 /* libgnutls.a */, - 34378A7026F790B3003118B2 /* libharfbuzz.a */, - 34378A6426F790B2003118B2 /* libhogweed.a */, - 34378A5726F790B2003118B2 /* libilbc.a */, - 34378A5B26F790B2003118B2 /* libjpeg.a */, - 34378A7A26F790B3003118B2 /* libkvazaar.a */, - 34378A5026F790B1003118B2 /* libmp3lame.a */, - 34378A5C26F790B2003118B2 /* libnettle.a */, - 34378A4F26F790B1003118B2 /* libogg.a */, - 34378A4C26F790B1003118B2 /* libopencore-amrnb.a */, - 34378A5426F790B2003118B2 /* libopus.a */, - 34378A5F26F790B2003118B2 /* libpng.a */, - 34378A7126F790B3003118B2 /* libshine.a */, - 34378A5826F790B2003118B2 /* libsnappy.a */, - 34378A6826F790B3003118B2 /* libsndfile.a */, - 34378A6526F790B2003118B2 /* libsoxr.a */, - 34378A7326F790B3003118B2 /* libspeex.a */, - 34378A5326F790B2003118B2 /* libswresample.a */, - 34378A6E26F790B3003118B2 /* libswscale.a */, - 34378A7926F790B3003118B2 /* libtheora.a */, - 34378A6026F790B2003118B2 /* libtheoradec.a */, - 34378A6A26F790B3003118B2 /* libtheoraenc.a */, - 34378A4D26F790B1003118B2 /* libtiff.a */, - 34378A5D26F790B2003118B2 /* libtwolame.a */, - 34378A5126F790B1003118B2 /* libvidstab.a */, - 34378A7526F790B3003118B2 /* libvo-amrwbenc.a */, - 34378A6C26F790B3003118B2 /* libvorbis.a */, - 34378A5226F790B2003118B2 /* libvorbisenc.a */, - 34378A7726F790B3003118B2 /* libvorbisfile.a */, - 34378A5A26F790B2003118B2 /* libvpx.a */, - 34378A6326F790B2003118B2 /* libwebp.a */, - 34378A5626F790B2003118B2 /* libwebpdemux.a */, - 34378A4E26F790B1003118B2 /* libwebpmux.a */, - 34378A6226F790B2003118B2 /* libx264.a */, - 34378A7B26F790B3003118B2 /* libx265.a */, - 34378A7826F790B3003118B2 /* libxml2.a */, - 34378A5E26F790B2003118B2 /* libxvidcore.a */, - 34CB451525DDF24200CF2282 /* CoreMotion.framework */, - 34CB451325DDF22800CF2282 /* VideoToolbox.framework */, - 34CB451125DDF20300CF2282 /* libbz2.tbd */, - 34CB450F25DDF1F900CF2282 /* libc++.tbd */, - 34CB450D25DDF1EF00CF2282 /* libiconv.tbd */, - 34CB450B25DDF1E600CF2282 /* libz.tbd */, - ); - name = Frameworks; - sourceTree = ""; - }; - 34FAE207209F7DDD005CE2AE = { - isa = PBXGroup; - children = ( - 346AA95920B2ED94000623FE /* Resources */, - 34FAE212209F7DDD005CE2AE /* FFmpegKitIOS */, - 34FAE211209F7DDD005CE2AE /* Products */, - 3498DC65209F7F1C005F5883 /* Frameworks */, - ); - sourceTree = ""; - }; - 34FAE211209F7DDD005CE2AE /* Products */ = { - isa = PBXGroup; - children = ( - 34FAE210209F7DDD005CE2AE /* FFmpegKitIOS.app */, - ); - name = Products; - sourceTree = ""; - }; - 34FAE212209F7DDD005CE2AE /* FFmpegKitIOS */ = { - isa = PBXGroup; - children = ( - 34FAE213209F7DDD005CE2AE /* AppDelegate.h */, - 34FAE214209F7DDD005CE2AE /* AppDelegate.m */, - 34FAE21F209F7DDE005CE2AE /* Assets.xcassets */, - 345745492113B8AD00059043 /* AudioViewController.h */, - 3457454A2113B8AD00059043 /* AudioViewController.m */, - 34FAE216209F7DDD005CE2AE /* CommandViewController.h */, - 34FAE217209F7DDD005CE2AE /* CommandViewController.m */, - 345E16A924CB93D1007275F0 /* ConcurrentExecutionViewController.h */, - 345E16A824CB93D1007275F0 /* ConcurrentExecutionViewController.m */, - 343E66B7210789DE00F95E5B /* Constants.h */, - 34BB547B2109D44800606B7C /* Constants.m */, - 346B8266244878C000971D55 /* FFmpegKitIOS.entitlements */, - 34943E6625DB499E002B5C1E /* FFmpegKitTest.h */, - 34943E6725DB499E002B5C1E /* FFmpegKitTest.m */, - 343E66B3210784BD00F95E5B /* HttpsViewController.h */, - 343E66B4210784BD00F95E5B /* HttpsViewController.m */, - 34FAE224209F7DDE005CE2AE /* Info.plist */, - 34FAE221209F7DDE005CE2AE /* LaunchScreen.storyboard */, - 34FAE225209F7DDE005CE2AE /* main.m */, - 34FAE21C209F7DDD005CE2AE /* Main.storyboard */, - 342900C922DE2BCF0071B2E4 /* MediaInformationParserTest.h */, - 342900C722DE2BCF0071B2E4 /* MediaInformationParserTest.m */, - 34D37D0E25DBEA1D00B8914A /* OtherViewController.h */, - 34D37D0D25DBEA1D00B8914A /* OtherViewController.m */, - 3487ABA4220CEAA200A40E8D /* PipeViewController.h */, - 3487ABA3220CEAA200A40E8D /* PipeViewController.m */, - 3457454D2113B8D300059043 /* SubtitleViewController.h */, - 3457454E2113B8D300059043 /* SubtitleViewController.m */, - 343E67072107C27600F95E5B /* TabBarController.h */, - 343E67082107C27600F95E5B /* TabBarController.m */, - 343E67032107AD0100F95E5B /* Util.h */, - 343E67042107AD0100F95E5B /* Util.m */, - 343D714625E10CBA007CB801 /* Video.h */, - 343D714425E10CAC007CB801 /* Video.m */, - 34FAE219209F7DDD005CE2AE /* VideoViewController.h */, - 34FAE21A209F7DDD005CE2AE /* VideoViewController.m */, - 340FABBC2115A17600B33CE7 /* VidStabViewController.h */, - 340FABBD2115A17600B33CE7 /* VidStabViewController.m */, - ); - path = FFmpegKitIOS; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 34F9744020A1A200004A1F68 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 34D37D1025DBEA1D00B8914A /* OtherViewController.h in Headers */, - 343E67092107C27600F95E5B /* TabBarController.h in Headers */, - 345E16AB24CB93D1007275F0 /* ConcurrentExecutionViewController.h in Headers */, - 3487ABA6220CEAA300A40E8D /* PipeViewController.h in Headers */, - 3457454B2113B8AD00059043 /* AudioViewController.h in Headers */, - 3457454F2113B8D300059043 /* SubtitleViewController.h in Headers */, - 343E66B9210789DE00F95E5B /* Constants.h in Headers */, - 34943E6825DB499E002B5C1E /* FFmpegKitTest.h in Headers */, - 343E67052107AD0100F95E5B /* Util.h in Headers */, - 342900CD22DE2BCF0071B2E4 /* MediaInformationParserTest.h in Headers */, - 343E66B5210784BD00F95E5B /* HttpsViewController.h in Headers */, - 340FABBE2115A17600B33CE7 /* VidStabViewController.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 34FAE20F209F7DDD005CE2AE /* FFmpegKitIOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 34FAE229209F7DDE005CE2AE /* Build configuration list for PBXNativeTarget "FFmpegKitIOS" */; - buildPhases = ( - 34FAE20C209F7DDD005CE2AE /* Sources */, - 34FAE20D209F7DDD005CE2AE /* Frameworks */, - 34FAE20E209F7DDD005CE2AE /* Resources */, - 34F9744020A1A200004A1F68 /* Headers */, - 3452D8CF20A373640045E6B0 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = FFmpegKitIOS; - productName = FFmpegKitIOS; - productReference = 34FAE210209F7DDD005CE2AE /* FFmpegKitIOS.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 34FAE208209F7DDD005CE2AE /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0930; - ORGANIZATIONNAME = ARTHENICA; - TargetAttributes = { - 34FAE20F209F7DDD005CE2AE = { - CreatedOnToolsVersion = 9.3; - DevelopmentTeam = 98GD5J4999; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = 34FAE20B209F7DDD005CE2AE /* Build configuration list for PBXProject "FFmpegKitIOS" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 34FAE207209F7DDD005CE2AE; - productRefGroup = 34FAE211209F7DDD005CE2AE /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 34FAE20F209F7DDD005CE2AE /* FFmpegKitIOS */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 34FAE20E209F7DDD005CE2AE /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 348439ED20B2EFAF001A3990 /* pyramid.jpg in Resources */, - 34DC789D21215B5800C3486C /* doppioone_regular.ttf in Resources */, - 34DC789E21215B5800C3486C /* sil_open_font_license.txt in Resources */, - 34FAE223209F7DDE005CE2AE /* LaunchScreen.storyboard in Resources */, - 34FAE220209F7DDE005CE2AE /* Assets.xcassets in Resources */, - 34CB451E25DDF76200CF2282 /* stonehenge.jpg in Resources */, - 34DC789B21215B5800C3486C /* truenorg.otf in Resources */, - 34CB451D25DDF76200CF2282 /* machupicchu.jpg in Resources */, - 34FAE21E209F7DDD005CE2AE /* Main.storyboard in Resources */, - 34DC789C21215B5800C3486C /* subtitle.srt in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 34FAE20C209F7DDD005CE2AE /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3487ABA5220CEAA300A40E8D /* PipeViewController.m in Sources */, - 34D37D0F25DBEA1D00B8914A /* OtherViewController.m in Sources */, - 343D714525E10CAD007CB801 /* Video.m in Sources */, - 345E16AA24CB93D1007275F0 /* ConcurrentExecutionViewController.m in Sources */, - 34FAE21B209F7DDD005CE2AE /* VideoViewController.m in Sources */, - 34FAE215209F7DDD005CE2AE /* AppDelegate.m in Sources */, - 34FAE226209F7DDE005CE2AE /* main.m in Sources */, - 343E66B6210784BD00F95E5B /* HttpsViewController.m in Sources */, - 340FABBF2115A17600B33CE7 /* VidStabViewController.m in Sources */, - 34943E6925DB499E002B5C1E /* FFmpegKitTest.m in Sources */, - 342900CB22DE2BCF0071B2E4 /* MediaInformationParserTest.m in Sources */, - 34FAE218209F7DDD005CE2AE /* CommandViewController.m in Sources */, - 343E670A2107C27600F95E5B /* TabBarController.m in Sources */, - 345745502113B8D300059043 /* SubtitleViewController.m in Sources */, - 343E67062107AD0100F95E5B /* Util.m in Sources */, - 3457454C2113B8AD00059043 /* AudioViewController.m in Sources */, - 34BB547C2109D44800606B7C /* Constants.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 34FAE21C209F7DDD005CE2AE /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 34FAE21D209F7DDD005CE2AE /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 34FAE221209F7DDE005CE2AE /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 34FAE222209F7DDE005CE2AE /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 34FAE227209F7DDE005CE2AE /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_CODE_SIGN_FLAGS = ""; - OTHER_LIBTOOLFLAGS = "-liconv"; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 34FAE228209F7DDE005CE2AE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_CODE_SIGN_FLAGS = ""; - OTHER_LIBTOOLFLAGS = "-liconv"; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 34FAE22A209F7DDE005CE2AE /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = FFmpegKitIOS/FFmpegKitIOS.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 6; - DEVELOPMENT_TEAM = 98GD5J4999; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/**", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/ffmpeg-kit-ios-universal/include/**", - ); - INFOPLIST_FILE = FFmpegKitIOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/ffmpeg-kit/lib/**", - "$(PROJECT_DIR)/ffmpeg-kit/lib", - "$(PROJECT_DIR)/ffmpeg-kit-ios-universal/lib", - ); - MARKETING_VERSION = 2.0; - OTHER_CODE_SIGN_FLAGS = "--deep"; - OTHER_LDFLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.FFmpegKitIOS; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SUPPORTS_MACCATALYST = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 34FAE22B209F7DDE005CE2AE /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = FFmpegKitIOS/FFmpegKitIOS.entitlements; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 6; - DEVELOPMENT_TEAM = 98GD5J4999; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/ffmpeg-kit-ios-universal/include/**", - ); - INFOPLIST_FILE = FFmpegKitIOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @loader_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/ffmpeg-kit/lib/**", - "$(PROJECT_DIR)/ffmpeg-kit/lib", - "$(PROJECT_DIR)/ffmpeg-kit-ios-universal/lib", - ); - MARKETING_VERSION = 2.0; - OTHER_CODE_SIGN_FLAGS = "--deep"; - OTHER_LDFLAGS = "$(inherited)"; - PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.FFmpegKitIOS; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SUPPORTS_MACCATALYST = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 34FAE20B209F7DDD005CE2AE /* Build configuration list for PBXProject "FFmpegKitIOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 34FAE227209F7DDE005CE2AE /* Debug */, - 34FAE228209F7DDE005CE2AE /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 34FAE229209F7DDE005CE2AE /* Build configuration list for PBXNativeTarget "FFmpegKitIOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 34FAE22A209F7DDE005CE2AE /* Debug */, - 34FAE22B209F7DDE005CE2AE /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 34FAE208209F7DDD005CE2AE /* Project object */; -} diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate b/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index e164650..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/project.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index fe2b454..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcschemes/FFmpegKitIOS.xcscheme b/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcschemes/FFmpegKitIOS.xcscheme deleted file mode 100644 index 3072a13..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcschemes/FFmpegKitIOS.xcscheme +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcschemes/xcschememanagement.plist b/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index b5c4725..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS.xcodeproj/xcuserdata/taner.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - SchemeUserState - - FFmpegKitIOS.xcscheme - - orderHint - 0 - - - SuppressBuildableAutocreation - - 34FAE20F209F7DDD005CE2AE - - primary - - - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/contents.xcworkspacedata b/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 961178e..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate b/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index b6113c5..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/AppDelegate.h b/ios/test-app-local-universal-library/FFmpegKitIOS/AppDelegate.h deleted file mode 100644 index 6e58642..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/AppDelegate.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - -+ (void)listFFmpegSessions; -+ (void)listFFprobeSessions; - -@end - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/AppDelegate.m b/ios/test-app-local-universal-library/FFmpegKitIOS/AppDelegate.m deleted file mode 100644 index 0070a9a..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/AppDelegate.m +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "AppDelegate.h" -#include -#include -#include -#include -#include - -void uncaughtExceptionHandler(NSException *exception) { - NSLog(@"Uncaught exception detected: %@.", exception); - NSLog(@"%@", [exception callStackSymbols]); -} - -@interface AppDelegate () - -@end - -@implementation AppDelegate - -+ (void)listFFprobeSessions { - NSArray* ffprobeSessions = [FFprobeKit listSessions]; - - NSLog(@"Listing FFprobe sessions.\n"); - - for (int i = 0; i < [ffprobeSessions count]; i++) { - FFprobeSession* session = [ffprobeSessions objectAtIndex:i]; - NSLog(@"Session %d = id: %ld, startTime: %@, duration: %ld, state:%@, returnCode:%@.\n", i, [session getSessionId], [session getStartTime], [session getDuration], [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode]); - } - - NSLog(@"Listed FFprobe sessions.\n"); -} - -+ (void)listFFmpegSessions { - NSArray* ffmpegSessions = [FFmpegKit listSessions]; - - NSLog(@"Listing FFmpeg sessions.\n"); - - for (int i = 0; i < [ffmpegSessions count]; i++) { - FFmpegSession* session = [ffmpegSessions objectAtIndex:i]; - NSLog(@"Session %d = id: %ld, startTime: %@, duration: %ld, state:%@, returnCode:%@.\n", i, [session getSessionId], [session getStartTime], [session getDuration], [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode]); - } - - NSLog(@"Listed FFmpeg sessions.\n"); -} - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - - NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); - - // UPDATE TAB BAR STYLE - UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController; - UITabBar *tabBar = tabBarController.tabBar; - UITabBarItem *tabBarItem1 = [tabBar.items objectAtIndex:0]; - UITabBarItem *tabBarItem2 = [tabBar.items objectAtIndex:1]; - UITabBarItem *tabBarItem3 = [tabBar.items objectAtIndex:2]; - UITabBarItem *tabBarItem4 = [tabBar.items objectAtIndex:3]; - UITabBarItem *tabBarItem5 = [tabBar.items objectAtIndex:4]; - UITabBarItem *tabBarItem6 = [tabBar.items objectAtIndex:5]; - UITabBarItem *tabBarItem7 = [tabBar.items objectAtIndex:6]; - UITabBarItem *tabBarItem8 = [tabBar.items objectAtIndex:7]; - UITabBarItem *tabBarItem9 = [tabBar.items objectAtIndex:8]; - tabBarItem1.title = @"COMMAND"; - tabBarItem2.title = @"VIDEO"; - tabBarItem3.title = @"HTTPS"; - tabBarItem4.title = @"AUDIO"; - tabBarItem5.title = @"SUBTITLE"; - tabBarItem6.title = @"VID.STAB"; - tabBarItem7.title = @"PIPE"; - tabBarItem8.title = @"CONCURRENT"; - tabBarItem9.title = @"OTHER"; - - // SELECTED BAR ITEM - [[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys: - [UIColor colorWithRed:244.0/255.0 green:104.0/255.0 blue:66.0/255.0 alpha:1.0], NSForegroundColorAttributeName, - [UIFont boldSystemFontOfSize:14], NSFontAttributeName, - nil] forState:UIControlStateSelected]; - - // NOT SELECTED BAR ITEMS - [[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys: - [UIColor colorWithRed:189.0/255.0 green:195.0/255.0 blue:199.0/255.0 alpha:1.0], NSForegroundColorAttributeName, - [UIFont boldSystemFontOfSize:12], NSFontAttributeName, - nil] forState:UIControlStateNormal]; - - NSString *resourceFolder = [[NSBundle mainBundle] resourcePath]; - NSDictionary *fontNameMapping = @{@"MyFontName" : @"Doppio One"}; - - [FFmpegKitConfig setFontDirectoryList:[[NSArray alloc] initWithObjects:resourceFolder, @"/System/Library/Fonts", nil] with:fontNameMapping]; - - [FFmpegKitConfig ignoreSignal:SIGXCPU]; - [FFmpegKitConfig setLogLevel:LevelAVLogInfo]; - - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. -} - - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. -} - - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 0cc2196..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-40.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-60.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-58.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-87.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-80.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-120.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-121.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-180.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-20.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-41.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-29.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-59.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-42.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-81.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-76.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-152.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-167.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-1024.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-1024.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-1024.png deleted file mode 100644 index 1eb1263..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-1024.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-120.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-120.png deleted file mode 100644 index 44174f6..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-120.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-121.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-121.png deleted file mode 100644 index 44174f6..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-121.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-152.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-152.png deleted file mode 100644 index c2433a2..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-152.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-167.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-167.png deleted file mode 100644 index f1714c5..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-167.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-180.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-180.png deleted file mode 100644 index 5d9ce57..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-180.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-20.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-20.png deleted file mode 100644 index e757044..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-20.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-29.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-29.png deleted file mode 100644 index eb0dd0a..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-29.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-40.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-40.png deleted file mode 100644 index 784e8f6..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-40.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-41.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-41.png deleted file mode 100644 index 784e8f6..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-41.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-42.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-42.png deleted file mode 100644 index 784e8f6..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-42.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-58.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-58.png deleted file mode 100644 index f87c4f7..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-58.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-59.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-59.png deleted file mode 100644 index f87c4f7..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-59.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-60.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-60.png deleted file mode 100644 index 104e427..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-60.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-76.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-76.png deleted file mode 100644 index 23ff54e..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-76.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-80.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-80.png deleted file mode 100644 index 65ae9e3..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-80.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-81.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-81.png deleted file mode 100644 index 65ae9e3..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-81.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-87.png b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-87.png deleted file mode 100644 index 5972ed6..0000000 Binary files a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/AppIcon.appiconset/Icon-87.png and /dev/null differ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/Contents.json b/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/Contents.json deleted file mode 100644 index da4a164..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/AudioViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/AudioViewController.h deleted file mode 100644 index c4e2971..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/AudioViewController.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface AudioViewController : UIViewController - -- (void)setActive; - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/AudioViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/AudioViewController.m deleted file mode 100644 index 70dbd3c..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/AudioViewController.m +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "AudioViewController.h" - -@interface AudioViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (strong, nonatomic) IBOutlet UIPickerView *audioCodecPicker; -@property (strong, nonatomic) IBOutlet UIButton *encodeButton; -@property (strong, nonatomic) IBOutlet UITextView *outputText; - -@end - -@implementation AudioViewController { - - // Video codec data - NSArray *codecData; - NSInteger selectedCodec; - - // Loading view - UIActivityIndicatorView* indicator; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // AUDIO CODEC PICKER INIT - codecData = @[@"aac (audiotoolbox)", @"mp2 (twolame)", @"mp3 (liblame)", @"mp3 (libshine)", @"vorbis", @"opus", @"amr-nb", @"amr-wb", @"ilbc", @"soxr", @"speex", @"wavpack"]; - selectedCodec = 0; - - self.audioCodecPicker.dataSource = self; - self.audioCodecPicker.delegate = self; - - // STYLE UPDATE - [Util applyPickerViewStyle: self.audioCodecPicker]; - [Util applyButtonStyle: self.encodeButton]; - [Util applyOutputTextStyle: self.outputText]; - [Util applyHeaderStyle: self.header]; - - // BUTTON DISABLED UNTIL AUDIO SAMPLE IS CREATED - [self.encodeButton setEnabled:false]; - - [self createAudioSample]; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (void)enableLogCallback { - [FFmpegKitConfig enableLogCallback: ^(Log* log){ - addUIAction(^{ - [self appendOutput:[log getMessage]]; - }); - }]; -} - -- (void)disableLogCallback { - [FFmpegKitConfig enableLogCallback:nil]; -} - -- (void)disableStatisticsCallback { - [FFmpegKitConfig enableStatisticsCallback:nil]; -} - -/** - * The number of columns of data - */ -- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { - return 1; -} - -/** - * The number of rows of data - */ -- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { - return codecData.count; -} - -/** - * The data to return for the row and component (column) that's being passed in - */ -- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { - return codecData[row]; -} - -- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { - selectedCodec = row; -} - -- (IBAction)encodeAudio:(id)sender { - NSString *audioOutputFile = [self getAudioOutputFilePath]; - [[NSFileManager defaultManager] removeItemAtPath:audioOutputFile error:NULL]; - - NSString *audioCodec = codecData[selectedCodec]; - - NSLog(@"Testing AUDIO encoding with '%@' codec\n", audioCodec); - - NSString *ffmpegCommand = [self generateAudioEncodeScript]; - - [self showProgressDialog:@"Encoding audio\n\n"]; - - [self clearOutput]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - SessionState state = [session getState]; - ReturnCode* returnCode = [session getReturnCode]; - - if ([ReturnCode isSuccess:returnCode]) { - NSLog(@"Encode completed successfully.\n"); - addUIAction(^{ - [self hideProgressDialogAndAlert:@"Success" and:@"Encode completed successfully."]; - }); - } else { - NSLog(@"Encode failed with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - addUIAction(^{ - [self hideProgressDialogAndAlert:@"Error" and:@"Encode failed. Please check logs for the details."]; - }); - } - }]; -} - -- (void)createAudioSample { - NSLog(@"Creating AUDIO sample before the test.\n"); - - NSString *audioSampleFile = [self getAudioSamplePath]; - [[NSFileManager defaultManager] removeItemAtPath:audioSampleFile error:NULL]; - - NSString *ffmpegCommand = [NSString stringWithFormat:@"-y -f lavfi -i sine=frequency=1000:duration=5 -c:a pcm_s16le %@", audioSampleFile]; - - NSLog(@"Creating audio sample with '%@'\n", ffmpegCommand); - - FFmpegSession* session = [FFmpegKit execute:ffmpegCommand]; - ReturnCode* returnCode = [session getReturnCode]; - if ([ReturnCode isSuccess:returnCode]) { - [self.encodeButton setEnabled:true]; - NSLog(@"AUDIO sample created\n"); - } else { - NSLog(@"Creating AUDIO sample failed with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], returnCode, notNull([session getFailStackTrace], @"\n")); - addUIAction(^{ - [Util alert:self withTitle:@"Error" message:@"Creating AUDIO sample failed. Please check logs for the details." andButtonText:@"OK"]; - }); - } -} - -- (NSString*)getAudioOutputFilePath { - NSString *audioCodec = codecData[selectedCodec]; - - NSString *extension; - if ([audioCodec isEqualToString:@"aac (audiotoolbox)"]) { - extension = @"m4a"; - } else if ([audioCodec isEqualToString:@"mp2 (twolame)"]) { - extension = @"mpg"; - } else if ([audioCodec isEqualToString:@"mp3 (liblame)"] || [audioCodec isEqualToString:@"mp3 (libshine)"]) { - extension = @"mp3"; - } else if ([audioCodec isEqualToString:@"vorbis"]) { - extension = @"ogg"; - } else if ([audioCodec isEqualToString:@"opus"]) { - extension = @"opus"; - } else if ([audioCodec isEqualToString:@"amr-nb"]) { - extension = @"amr"; - } else if ([audioCodec isEqualToString:@"amr-wb"]) { - extension = @"amr"; - } else if ([audioCodec isEqualToString:@"ilbc"]) { - extension = @"lbc"; - } else if ([audioCodec isEqualToString:@"speex"]) { - extension = @"spx"; - } else if ([audioCodec isEqualToString:@"wavpack"]) { - extension = @"wv"; - } else { - - // soxr - extension = @"wav"; - } - - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [[docFolder stringByAppendingPathComponent: @"audio."] stringByAppendingString: extension]; -} - -- (NSString*)getAudioSamplePath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"audio-sample.wav"]; -} - -- (void)setActive { - NSLog(@"Audio Tab Activated"); - [self disableStatisticsCallback]; - [self disableLogCallback]; - [self createAudioSample]; - [self enableLogCallback]; -} - -- (void)appendOutput:(NSString*) message { - self.outputText.text = [self.outputText.text stringByAppendingString:message]; - - if (self.outputText.text.length > 0 ) { - NSRange bottom = NSMakeRange(self.outputText.text.length - 1, 1); - [self.outputText scrollRangeToVisible:bottom]; - } -} - -- (void)clearOutput { - [[self outputText] setText:@""]; -} - -- (void)showProgressDialog:(NSString*) dialogMessage { - UIAlertController *pending = [UIAlertController alertControllerWithTitle:nil - message:dialogMessage - preferredStyle:UIAlertControllerStyleAlert]; - indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - indicator.color = [UIColor blackColor]; - indicator.translatesAutoresizingMaskIntoConstraints=NO; - [pending.view addSubview:indicator]; - NSDictionary * views = @{@"pending" : pending.view, @"indicator" : indicator}; - - NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[indicator]-(20)-|" options:0 metrics:nil views:views]; - NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[indicator]|" options:0 metrics:nil views:views]; - NSArray * constraints = [constraintsVertical arrayByAddingObjectsFromArray:constraintsHorizontal]; - [pending.view addConstraints:constraints]; - [indicator startAnimating]; - [self presentViewController:pending animated:YES completion:nil]; -} - -- (void)hideProgressDialogAndAlert: (NSString*)title and:(NSString*)message { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:^{ - [Util alert:self withTitle:title message:message andButtonText:@"OK"]; - }]; -} - -- (NSString*)generateAudioEncodeScript { - NSString *audioCodec = codecData[selectedCodec]; - NSString *audioSampleFile = [self getAudioSamplePath]; - NSString *audioOutputFile = [self getAudioOutputFilePath]; - - if ([audioCodec isEqualToString:@"aac (audiotoolbox)"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a aac_at -b:a 192k %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"mp2 (twolame)"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a mp2 -b:a 192k %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"mp3 (liblame)"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a libmp3lame -qscale:a 2 %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"mp3 (libshine)"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a libshine -qscale:a 2 %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"vorbis"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a libvorbis -b:a 64k %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"opus"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a libopus -b:a 64k -vbr on -compression_level 10 %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"amr-nb"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -ar 8000 -ab 12.2k -c:a libopencore_amrnb %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"amr-wb"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -ar 8000 -ab 12.2k -c:a libvo_amrwbenc -strict experimental %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"ilbc"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a ilbc -ar 8000 -b:a 15200 %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"speex"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a libspeex -ar 16000 %@", audioSampleFile, audioOutputFile]; - } else if ([audioCodec isEqualToString:@"wavpack"]) { - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -c:a wavpack -b:a 64k %@", audioSampleFile, audioOutputFile]; - } else { - - // soxr - return [NSString stringWithFormat:@"-hide_banner -y -i %@ -af aresample=resampler=soxr -ar 44100 %@", audioSampleFile, audioOutputFile]; - } -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Base.lproj/LaunchScreen.storyboard b/ios/test-app-local-universal-library/FFmpegKitIOS/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index 030acd9..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Base.lproj/Main.storyboard b/ios/test-app-local-universal-library/FFmpegKitIOS/Base.lproj/Main.storyboard deleted file mode 100644 index 3c4e444..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Base.lproj/Main.storyboard +++ /dev/null @@ -1,993 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/CommandViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/CommandViewController.h deleted file mode 100644 index 936200e..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/CommandViewController.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface CommandViewController : UIViewController - -- (void)setActive; - -@end - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/CommandViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/CommandViewController.m deleted file mode 100644 index 01826cc..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/CommandViewController.m +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include "AppDelegate.h" -#include "CommandViewController.h" - -@interface CommandViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (strong, nonatomic) IBOutlet UITextField *commandText; -@property (strong, nonatomic) IBOutlet UIButton *runFFmpegButton; -@property (strong, nonatomic) IBOutlet UIButton *runFFprobeButton; -@property (strong, nonatomic) IBOutlet UITextView *outputText; - -@end - -@implementation CommandViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - // STYLE UPDATE - [Util applyEditTextStyle: self.commandText]; - [Util applyButtonStyle: self.runFFmpegButton]; - [Util applyButtonStyle: self.runFFprobeButton]; - [Util applyOutputTextStyle: self.outputText]; - [Util applyHeaderStyle: self.header]; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (IBAction)runFFmpeg:(id)sender { - [self clearOutput]; - - [[self commandText] endEditing:TRUE]; - - NSString *ffmpegCommand = [NSString stringWithFormat:@"-hide_banner %@", [[self commandText] text]]; - - NSLog(@"Current log level is %d.\n", [FFmpegKitConfig getLogLevel]); - - NSLog(@"Testing FFmpeg COMMAND asynchronously.\n"); - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - SessionState state = [session getState]; - ReturnCode* returnCode = [session getReturnCode]; - - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - - if (state == SessionStateFailed || !returnCode.isSuccess) { - addUIAction(^{ - [Util alert:self withTitle:@"Error" message:@"Command failed. Please check output for the details." andButtonText:@"OK"]; - }); - } - } withLogCallback:^(Log *log) { - addUIAction(^{ - [self appendOutput: [log getMessage]]; - }); - } withStatisticsCallback:nil]; -} - -- (IBAction)runFFprobe:(id)sender { - [self clearOutput]; - - [[self commandText] endEditing:TRUE]; - - NSString *ffprobeCommand = [NSString stringWithFormat:@"-hide_banner %@", [[self commandText] text]]; - - NSLog(@"Testing FFprobe COMMAND asynchronously.\n"); - - NSLog(@"FFprobe process started with arguments\n'%@'.\n", ffprobeCommand); - - FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withExecuteCallback:^(id session) { - SessionState state = [session getState]; - ReturnCode* returnCode = [session getReturnCode]; - - addUIAction(^{ - [self appendOutput: [session getOutput]]; - }); - - NSLog(@"FFprobe process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - - if (state == SessionStateFailed || !returnCode.isSuccess) { - addUIAction(^{ - [Util alert:self withTitle:@"Error" message:@"Command failed. Please check output for the details." andButtonText:@"OK"]; - }); - } - } withLogCallback:nil withLogRedirectionStrategy:LogRedirectionStrategyNeverPrintLogs]; - - [FFmpegKitConfig asyncFFprobeExecute:session]; - - [AppDelegate listFFprobeSessions]; -} - -- (void)setActive { - NSLog(@"Command Tab Activated"); - [FFmpegKitConfig enableLogCallback:nil]; -} - -- (void)appendOutput:(NSString*) message { - self.outputText.text = [self.outputText.text stringByAppendingString:message]; - - if (self.outputText.text.length > 0 ) { - NSRange bottom = NSMakeRange(self.outputText.text.length - 1, 1); - [self.outputText scrollRangeToVisible:bottom]; - } -} - -- (void)clearOutput { - [[self outputText] setText:@""]; -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/ConcurrentExecutionViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/ConcurrentExecutionViewController.h deleted file mode 100644 index 4752a53..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/ConcurrentExecutionViewController.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2020-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface ConcurrentExecutionViewController : UIViewController - -- (void)setActive; - -@end - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/ConcurrentExecutionViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/ConcurrentExecutionViewController.m deleted file mode 100644 index 5b9e2fa..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/ConcurrentExecutionViewController.m +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2020-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include "AppDelegate.h" -#include "ConcurrentExecutionViewController.h" -#include "Video.h" - -@interface ConcurrentExecutionViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (strong, nonatomic) IBOutlet UIButton *encode1Button; -@property (strong, nonatomic) IBOutlet UIButton *encode2Button; -@property (strong, nonatomic) IBOutlet UIButton *encode3Button; -@property (strong, nonatomic) IBOutlet UIButton *cancel1Button; -@property (strong, nonatomic) IBOutlet UIButton *cancel2Button; -@property (strong, nonatomic) IBOutlet UIButton *cancel3Button; -@property (strong, nonatomic) IBOutlet UIButton *cancelAllButton; -@property (strong, nonatomic) IBOutlet UITextView *outputText; - -@end - -@implementation ConcurrentExecutionViewController { - long sessionId1; - long sessionId2; - long sessionId3; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // STYLE UPDATE - [Util applyButtonStyle: self.encode1Button]; - [Util applyButtonStyle: self.encode2Button]; - [Util applyButtonStyle: self.encode3Button]; - [Util applyButtonStyle: self.cancel1Button]; - [Util applyButtonStyle: self.cancel2Button]; - [Util applyButtonStyle: self.cancel3Button]; - [Util applyButtonStyle: self.cancelAllButton]; - [Util applyOutputTextStyle: self.outputText]; - [Util applyHeaderStyle: self.header]; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (void)enableLogCallback { - [FFmpegKitConfig enableLogCallback: ^(Log* log){ - addUIAction(^{ - [self appendOutput: [NSString stringWithFormat:@"%ld -> %@", [log getSessionId], [log getMessage]]]; - }); - }]; -} - -- (IBAction)encode1Clicked:(id)sender { - [self encodeVideo:1]; -} - -- (IBAction)encode2Clicked:(id)sender { - [self encodeVideo:2]; -} - -- (IBAction)encode3Clicked:(id)sender { - [self encodeVideo:3]; -} - -- (IBAction)cancel1Button:(id)sender { - [self cancel:1]; -} - -- (IBAction)cancel2Button:(id)sender { - [self cancel:2]; -} - -- (IBAction)cancel3Button:(id)sender { - [self cancel:3]; -} - -- (IBAction)cancelAllButton:(id)sender { - [self cancel:0]; -} - -- (void)encodeVideo:(int)buttonNumber { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - NSString *resourceFolder = [[NSBundle mainBundle] resourcePath]; - NSString *image1 = [resourceFolder stringByAppendingPathComponent: @"machupicchu.jpg"]; - NSString *image2 = [resourceFolder stringByAppendingPathComponent: @"pyramid.jpg"]; - NSString *image3 = [resourceFolder stringByAppendingPathComponent: @"stonehenge.jpg"]; - NSString *videoFile = [docFolder stringByAppendingPathComponent: [NSString stringWithFormat:@"video%d.mp4", buttonNumber]]; - - NSLog(@"Testing CONCURRENT EXECUTION for button %d.\n", buttonNumber); - - NSString* ffmpegCommand = [Video generateVideoEncodeScript:image1:image2:image3:videoFile:@"mpeg4":@""]; - - NSLog(@"FFmpeg process starting for button %d with arguments\n'%@'.\n", buttonNumber, ffmpegCommand); - - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - SessionState state = [session getState]; - ReturnCode* returnCode = [session getReturnCode]; - - if ([ReturnCode isCancel:returnCode]) { - NSLog(@"FFmpeg process ended with cancel for button %d with sessionId %ld.", buttonNumber, [session getSessionId]); - } else { - NSLog(@"FFmpeg process ended with state %lu and rc %@ for button %d with sessionId %ld.%@", state, returnCode, buttonNumber, [session getSessionId], notNull([session getFailStackTrace], @"\n")); - } - }]; - - long sessionId = [session getSessionId]; - - NSLog(@"Async FFmpeg process started for button %d with sessionId %ld.\n", buttonNumber, sessionId); - - switch (buttonNumber) { - case 1: { - sessionId1 = sessionId; - } - break; - case 2: { - sessionId2 = sessionId; - } - break; - default: { - sessionId3 = sessionId; - } - } - - [AppDelegate listFFmpegSessions]; -} - -- (void)cancel:(int)buttonNumber { - long sessionId = 0; - - switch (buttonNumber) { - case 1: { - sessionId = sessionId1; - } - break; - case 2: { - sessionId = sessionId2; - } - break; - case 3: { - sessionId = sessionId3; - } - } - - NSLog(@"Cancelling FFmpeg process for button %d with sessionId %ld.\n", buttonNumber, sessionId); - - if (sessionId == 0) { - [FFmpegKit cancel]; - } else { - [FFmpegKit cancel:sessionId]; - } -} - -- (void)setActive { - NSLog(@"Concurrent Execution Tab Activated"); - [self enableLogCallback]; -} - -- (void)appendOutput:(NSString*) message { - self.outputText.text = [self.outputText.text stringByAppendingString:message]; - - if (self.outputText.text.length > 0 ) { - NSRange bottom = NSMakeRange(self.outputText.text.length - 1, 1); - [self.outputText scrollRangeToVisible:bottom]; - } -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Constants.h b/ios/test-app-local-universal-library/FFmpegKitIOS/Constants.h deleted file mode 100644 index 53e337c..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Constants.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef FFMPEG_KIT_TEST_CONSTANTS -#define FFMPEG_KIT_TEST_CONSTANTS - -#include -#include - -// COMMAND TEST -extern NSString *const COMMAND_TEST_TOOLTIP_TEXT; -extern NSTimeInterval const COMMAND_TEST_TOOLTIP_DURATION; - -// VIDEO TEST -extern NSString *const VIDEO_TEST_TOOLTIP_TEXT; -extern NSTimeInterval const VIDEO_TEST_TOOLTIP_DURATION; - -// HTTPS TEST -extern NSString *const HTTPS_TEST_DEFAULT_URL; -extern NSString *const HTTPS_TEST_FAIL_URL; -extern NSString *const HTTPS_TEST_RANDOM_URL_1; -extern NSString *const HTTPS_TEST_RANDOM_URL_2; -extern NSString *const HTTPS_TEST_RANDOM_URL_3; -extern NSString *const HTTPS_TEST_TOOLTIP_TEXT; -extern NSTimeInterval const HTTPS_TEST_TOOLTIP_DURATION; - -// AUDIO TEST -extern NSString *const AUDIO_TEST_TOOLTIP_TEXT; -extern NSTimeInterval const AUDIO_TEST_TOOLTIP_DURATION; - -// SUBTITLE TEST -extern NSString *const SUBTITLE_TEST_TOOLTIP_TEXT; -extern NSTimeInterval const SUBTITLE_TEST_TOOLTIP_DURATION; - -// VID.STAB TEST -extern NSString *const VIDSTAB_TEST_TOOLTIP_TEXT; -extern NSTimeInterval const VIDSTAB_TEST_TOOLTIP_DURATION; - -// PIPE TEST -extern NSString *const PIPE_TEST_TOOLTIP_TEXT; -extern NSTimeInterval const PIPE_TEST_TOOLTIP_DURATION; - -// OTHER TEST -extern NSString *const DAV1D_TEST_DEFAULT_URL; - -#endif /* FFMPEG_KIT_TEST_CONSTANTS */ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Constants.m b/ios/test-app-local-universal-library/FFmpegKitIOS/Constants.m deleted file mode 100644 index 97da478..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Constants.m +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "Constants.h" - -// COMMAND TEST -NSString *const COMMAND_TEST_TOOLTIP_TEXT = @"Enter an FFmpeg command without 'ffmpeg' at the beginning and click one of the RUN buttons"; -NSTimeInterval const COMMAND_TEST_TOOLTIP_DURATION = 4.0; - -// VIDEO TEST -NSString *const VIDEO_TEST_TOOLTIP_TEXT = @"Select a video codec and press ENCODE button"; -NSTimeInterval const VIDEO_TEST_TOOLTIP_DURATION = 4.0; - -// HTTPS TEST -NSString *const HTTPS_TEST_DEFAULT_URL = @"https://download.blender.org/peach/trailer/trailer_1080p.ogg"; -NSString *const HTTPS_TEST_FAIL_URL = @"https://download2.blender.org/peach/trailer/trailer_1080p.ogg"; -NSString *const HTTPS_TEST_RANDOM_URL_1 = @"https://file-examples-com.github.io/uploads/2018/04/file_example_MOV_640_800kB.mov"; -NSString *const HTTPS_TEST_RANDOM_URL_2 = @"https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3"; -NSString *const HTTPS_TEST_RANDOM_URL_3 = @"https://file-examples-com.github.io/uploads/2020/03/file_example_WEBP_50kB.webp"; -NSString *const HTTPS_TEST_TOOLTIP_TEXT = @"Enter the https url of a media file and click the button"; -NSTimeInterval const HTTPS_TEST_TOOLTIP_DURATION = 4.0; - -// AUDIO TEST -NSString *const AUDIO_TEST_TOOLTIP_TEXT = @"Select an audio codec and press ENCODE button"; -NSTimeInterval const AUDIO_TEST_TOOLTIP_DURATION = 4.0; - -// SUBTITLE TEST -NSString *const SUBTITLE_TEST_TOOLTIP_TEXT = @"Click the button to burn subtitles. Created video will play inside the frame below"; -NSTimeInterval const SUBTITLE_TEST_TOOLTIP_DURATION = 4.0; - -// VID.STAB TEST -NSString *const VIDSTAB_TEST_TOOLTIP_TEXT = @"Click the button to stabilize video. Original video will play above and stabilized video will play below"; -NSTimeInterval const VIDSTAB_TEST_TOOLTIP_DURATION = 4.0; - -// PIPE TEST -NSString *const PIPE_TEST_TOOLTIP_TEXT = @"Click the button to create a video using pipe redirection. Created video will play inside the frame below"; -NSTimeInterval const PIPE_TEST_TOOLTIP_DURATION = 4.0; - -// OTHER TEST -NSString *const DAV1D_TEST_DEFAULT_URL = @"http://download.opencontent.netflix.com.s3.amazonaws.com/AV1/Sparks/Sparks-5994fps-AV1-10bit-960x540-film-grain-synthesis-854kbps.obu"; diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitIOS.entitlements b/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitIOS.entitlements deleted file mode 100644 index dc677b9..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitIOS.entitlements +++ /dev/null @@ -1,12 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.device.camera - - com.apple.security.network.client - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitTest.h b/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitTest.h deleted file mode 100644 index 1767a07..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitTest.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2019-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -void testFFmpegKit(void); diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitTest.m b/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitTest.m deleted file mode 100644 index 8f2e6bf..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/FFmpegKitTest.m +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2019-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include "MediaInformationParserTest.h" -#include -#include -#include - -NSArray *parseArguments(NSString *command) { - NSMutableArray *argumentArray = [[NSMutableArray alloc] init]; - NSMutableString *currentArgument = [[NSMutableString alloc] init]; - - bool singleQuoteStarted = false; - bool doubleQuoteStarted = false; - - for (int i = 0; i < command.length; i++) { - unichar previousChar; - if (i > 0) { - previousChar = [command characterAtIndex:(i - 1)]; - } else { - previousChar = 0; - } - char currentChar = [command characterAtIndex:i]; - - if (currentChar == ' ') { - if (singleQuoteStarted || doubleQuoteStarted) { - [currentArgument appendFormat: @"%c", currentChar]; - } else if ([currentArgument length] > 0) { - [argumentArray addObject: currentArgument]; - currentArgument = [[NSMutableString alloc] init]; - } - } else if (currentChar == '\'' && (previousChar == 0 || previousChar != '\\')) { - if (singleQuoteStarted) { - singleQuoteStarted = false; - } else if (doubleQuoteStarted) { - [currentArgument appendFormat: @"%c", currentChar]; - } else { - singleQuoteStarted = true; - } - } else if (currentChar == '\"' && (previousChar == 0 || previousChar != '\\')) { - if (doubleQuoteStarted) { - doubleQuoteStarted = false; - } else if (singleQuoteStarted) { - [currentArgument appendFormat: @"%c", currentChar]; - } else { - doubleQuoteStarted = true; - } - } else { - [currentArgument appendFormat: @"%c", currentChar]; - } - } - - if ([currentArgument length] > 0) { - [argumentArray addObject: currentArgument]; - } - - return argumentArray; -} - -void testParseSimpleCommand() { - NSArray *argumentArray = parseArguments(@"-hide_banner -loop 1 -i file.jpg -filter_complex [0:v]setpts=PTS-STARTPTS[video] -map [video] -vsync 2 -async 1 video.mp4"); - - assert(argumentArray != nil); - assertNumber([[NSNumber alloc] initWithInt:14], [[NSNumber alloc] initWithUnsignedLong: [argumentArray count]]); - - assertString(@"-hide_banner", argumentArray[0]); - assertString(@"-loop", argumentArray[1]); - assertString(@"1", argumentArray[2]); - assertString(@"-i", argumentArray[3]); - assertString(@"file.jpg", argumentArray[4]); - assertString(@"-filter_complex", argumentArray[5]); - assertString(@"[0:v]setpts=PTS-STARTPTS[video]", argumentArray[6]); - assertString(@"-map", argumentArray[7]); - assertString(@"[video]", argumentArray[8]); - assertString(@"-vsync", argumentArray[9]); - assertString(@"2", argumentArray[10]); - assertString(@"-async", argumentArray[11]); - assertString(@"1", argumentArray[12]); - assertString(@"video.mp4", argumentArray[13]); -} - -void testParseSingleQuotesInCommand() { - NSArray *argumentArray = parseArguments(@"-loop 1 'file one.jpg' -filter_complex '[0:v]setpts=PTS-STARTPTS[video]' -map [video] video.mp4 "); - - assert(argumentArray != nil); - assertNumber([[NSNumber alloc] initWithInt:8], [[NSNumber alloc] initWithUnsignedLong: [argumentArray count]]); - - assertString(@"-loop", argumentArray[0]); - assertString(@"1", argumentArray[1]); - assertString(@"file one.jpg", argumentArray[2]); - assertString(@"-filter_complex", argumentArray[3]); - assertString(@"[0:v]setpts=PTS-STARTPTS[video]", argumentArray[4]); - assertString(@"-map", argumentArray[5]); - assertString(@"[video]", argumentArray[6]); - assertString(@"video.mp4", argumentArray[7]); -} - -void testParseDoubleQuotesInCommand() { - NSArray *argumentArray = parseArguments(@"-loop 1 \"file one.jpg\" -filter_complex \"[0:v]setpts=PTS-STARTPTS[video]\" -map [video] video.mp4 "); - - assert(argumentArray != nil); - assertNumber([[NSNumber alloc] initWithInt:8], [[NSNumber alloc] initWithUnsignedLong: [argumentArray count]]); - - assertString(@"-loop", argumentArray[0]); - assertString(@"1", argumentArray[1]); - assertString(@"file one.jpg", argumentArray[2]); - assertString(@"-filter_complex", argumentArray[3]); - assertString(@"[0:v]setpts=PTS-STARTPTS[video]", argumentArray[4]); - assertString(@"-map", argumentArray[5]); - assertString(@"[video]", argumentArray[6]); - assertString(@"video.mp4", argumentArray[7]); - - argumentArray = parseArguments(@" -i file:///tmp/input.mp4 -vcodec libx264 -vf \"scale=1024:1024,pad=width=1024:height=1024:x=0:y=0:color=black\" -acodec copy -q:v 0 -q:a 0 video.mp4"); - - assert(argumentArray != nil); - assertNumber([[NSNumber alloc] initWithInt:13], [[NSNumber alloc] initWithUnsignedLong: [argumentArray count]]); - - assertString(@"-i", argumentArray[0]); - assertString(@"file:///tmp/input.mp4", argumentArray[1]); - assertString(@"-vcodec", argumentArray[2]); - assertString(@"libx264", argumentArray[3]); - assertString(@"-vf", argumentArray[4]); - assertString(@"scale=1024:1024,pad=width=1024:height=1024:x=0:y=0:color=black", argumentArray[5]); - assertString(@"-acodec", argumentArray[6]); - assertString(@"copy", argumentArray[7]); - assertString(@"-q:v", argumentArray[8]); - assertString(@"0", argumentArray[9]); - assertString(@"-q:a", argumentArray[10]); - assertString(@"0", argumentArray[11]); - assertString(@"video.mp4", argumentArray[12]); -} - -void testParseDoubleQuotesAndEscapesInCommand() { - NSArray *argumentArray = parseArguments(@" -i file:///tmp/input.mp4 -vf \"subtitles=file:///tmp/subtitles.srt:force_style=\'FontSize=16,PrimaryColour=&HFFFFFF&\'\" -vcodec libx264 -acodec copy -q:v 0 -q:a 0 video.mp4"); - - assert(argumentArray != nil); - assertNumber([[NSNumber alloc] initWithInt:13], [[NSNumber alloc] initWithUnsignedLong: [argumentArray count]]); - - assertString(@"-i", argumentArray[0]); - assertString(@"file:///tmp/input.mp4", argumentArray[1]); - assertString(@"-vf", argumentArray[2]); - assertString(@"subtitles=file:///tmp/subtitles.srt:force_style='FontSize=16,PrimaryColour=&HFFFFFF&'", argumentArray[3]); - assertString(@"-vcodec", argumentArray[4]); - assertString(@"libx264", argumentArray[5]); - assertString(@"-acodec", argumentArray[6]); - assertString(@"copy", argumentArray[7]); - assertString(@"-q:v", argumentArray[8]); - assertString(@"0", argumentArray[9]); - assertString(@"-q:a", argumentArray[10]); - assertString(@"0", argumentArray[11]); - assertString(@"video.mp4", argumentArray[12]); - - argumentArray = parseArguments(@" -i file:///tmp/input.mp4 -vf \"subtitles=file:///tmp/subtitles.srt:force_style=\\\"FontSize=16,PrimaryColour=&HFFFFFF&\\\"\" -vcodec libx264 -acodec copy -q:v 0 -q:a 0 video.mp4"); - - assert(argumentArray != nil); - assertNumber([[NSNumber alloc] initWithInt:13], [[NSNumber alloc] initWithUnsignedLong: [argumentArray count]]); - - assertString(@"-i", argumentArray[0]); - assertString(@"file:///tmp/input.mp4", argumentArray[1]); - assertString(@"-vf", argumentArray[2]); - assertString(@"subtitles=file:///tmp/subtitles.srt:force_style=\\\"FontSize=16,PrimaryColour=&HFFFFFF&\\\"", argumentArray[3]); - assertString(@"-vcodec", argumentArray[4]); - assertString(@"libx264", argumentArray[5]); - assertString(@"-acodec", argumentArray[6]); - assertString(@"copy", argumentArray[7]); - assertString(@"-q:v", argumentArray[8]); - assertString(@"0", argumentArray[9]); - assertString(@"-q:a", argumentArray[10]); - assertString(@"0", argumentArray[11]); - assertString(@"video.mp4", argumentArray[12]); -} - -void getSessionIdTest() { - NSArray *TEST_ARGUMENTS = [[NSArray alloc] initWithObjects:@"argument1", @"argument2", nil]; - - FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - - assert([sessions3 getSessionId] > [sessions2 getSessionId]); - assert([sessions3 getSessionId] > [sessions1 getSessionId]); - assert([sessions2 getSessionId] > [sessions1 getSessionId]); - - assert([sessions1 getSessionId] > 0); - assert([sessions2 getSessionId] > 0); - assert([sessions3 getSessionId] > 0); -} - -void testFFmpegKit(void) { - testParseSimpleCommand(); - testParseSingleQuotesInCommand(); - testParseDoubleQuotesInCommand(); - testParseDoubleQuotesAndEscapesInCommand(); - getSessionIdTest(); - - NSLog(@"FFmpegKitConfigTest passed."); -} diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/HttpsViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/HttpsViewController.h deleted file mode 100644 index 2161bb9..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/HttpsViewController.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface HttpsViewController : UIViewController - -- (void)setActive; - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/HttpsViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/HttpsViewController.m deleted file mode 100644 index 5f287b9..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/HttpsViewController.m +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include "HttpsViewController.h" - -@interface HttpsViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (strong, nonatomic) IBOutlet UITextField *urlText; -@property (strong, nonatomic) IBOutlet UIButton *getInfoFromUrlButton; -@property (strong, nonatomic) IBOutlet UIButton *getRandomInfoButton1; -@property (strong, nonatomic) IBOutlet UIButton *getRandomInfoButton2; -@property (strong, nonatomic) IBOutlet UIButton *getInfoAndFailButton; -@property (strong, nonatomic) IBOutlet UITextView *outputText; - -@end - -@implementation HttpsViewController { - NSObject *outputLock; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // STYLE UPDATE - [Util applyEditTextStyle: self.urlText]; - [Util applyButtonStyle: self.getInfoFromUrlButton]; - [Util applyButtonStyle: self.getRandomInfoButton1]; - [Util applyButtonStyle: self.getRandomInfoButton2]; - [Util applyButtonStyle: self.getInfoAndFailButton]; - [Util applyOutputTextStyle: self.outputText]; - [Util applyHeaderStyle: self.header]; - - outputLock = [[NSObject alloc] init]; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (IBAction)runGetInfoFromUrl:(id)sender { - [self runGetMediaInformation:1]; -} - -- (IBAction)runGetRandomInfo1:(id)sender { - [self runGetMediaInformation:2]; -} - -- (IBAction)runGetRandomInfo2:(id)sender { - [self runGetMediaInformation:3]; -} - -- (IBAction)runGetInfoAndFail:(id)sender { - [self runGetMediaInformation:4]; -} - -- (void)runGetMediaInformation:(int)buttonNumber { - - // SELECT TEST URL - NSString *testUrl; - switch (buttonNumber) { - case 1: { - testUrl = [self.urlText text]; - if ([testUrl length] == 0) { - testUrl = HTTPS_TEST_DEFAULT_URL; - [self.urlText setText:testUrl]; - } - } - break; - case 2: - case 3: { - testUrl = [self getRandomTestUrl]; - } - break; - case 4: - default: { - testUrl = HTTPS_TEST_FAIL_URL; - [self.urlText setText:testUrl]; - } - } - - NSLog(@"Testing HTTPS with for button %d using url %@.", buttonNumber, testUrl); - - if (buttonNumber == 4) { - - // ONLY THIS BUTTON CLEARS THE TEXT VIEW - [self clearOutput]; - } - - [FFprobeKit getMediaInformationAsync:testUrl withExecuteCallback:[self createNewExecuteCallback]]; -} - -- (void)setActive { - NSLog(@"Https Tab Activated"); - [FFmpegKitConfig enableLogCallback:nil]; - [FFmpegKitConfig enableStatisticsCallback:nil]; -} - -- (void)appendOutput:(NSString*) message { - self.outputText.text = [self.outputText.text stringByAppendingString:message]; - - if (self.outputText.text.length > 0 ) { - NSRange bottom = NSMakeRange(self.outputText.text.length - 1, 1); - [self.outputText scrollRangeToVisible:bottom]; - } -} - -- (void)clearOutput { - [[self outputText] setText:@""]; -} - -- (NSString*)getRandomTestUrl { - switch (arc4random_uniform(3)) { - case 0: - return HTTPS_TEST_RANDOM_URL_1; - case 1: - return HTTPS_TEST_RANDOM_URL_2; - default: - return HTTPS_TEST_RANDOM_URL_3; - } -} - -- (ExecuteCallback)createNewExecuteCallback { - return ^(id session){ - addUIAction(^{ - @synchronized (self->outputLock) { - MediaInformation *information = [((MediaInformationSession*) session) getMediaInformation]; - if (information == nil) { - [self appendOutput:@"Get media information failed\n"]; - [self appendOutput:[NSString stringWithFormat:@"State: %@\n", [FFmpegKitConfig sessionStateToString:[session getState]]]]; - [self appendOutput:[NSString stringWithFormat:@"Duration: %ld\n", [session getDuration]]]; - [self appendOutput:[NSString stringWithFormat:@"Return Code: %@\n", [session getReturnCode]]]; - [self appendOutput:[NSString stringWithFormat:@"Fail stack trace: %@\n", notNull([session getFailStackTrace], @"\n")]]; - [self appendOutput:[NSString stringWithFormat:@"Output: %@\n", [session getOutput]]]; - } else { - [self appendOutput:[NSString stringWithFormat:@"Media information for %@\n", [information getFilename]]]; - - if ([information getFormat] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Format: %@\n", [information getFormat]]]; - } - if ([information getBitrate] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Bitrate: %@\n", [information getBitrate]]]; - } - if ([information getDuration] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Duration: %@\n", [information getDuration]]]; - } - if ([information getStartTime] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Start time: %@\n", [information getStartTime]]]; - } - if ([information getTags] != nil) { - NSDictionary* tags = [information getTags]; - for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@", key, [tags objectForKey:key]]]; - } - } - if ([information getStreams] != nil) { - for (StreamInformation* stream in [information getStreams]) { - if ([stream getIndex] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream index: %@\n", [stream getIndex]]]; - } - if ([stream getType] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream type: %@\n", [stream getType]]]; - } - if ([stream getCodec] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream codec: %@\n", [stream getCodec]]]; - } - if ([stream getCodecLong] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream codec long: %@\n", [stream getCodecLong]]]; - } - if ([stream getFormat] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream format: %@\n", [stream getFormat]]]; - } - - if ([stream getWidth] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream width: %@\n", [stream getWidth]]]; - } - if ([stream getHeight] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream height: %@\n", [stream getHeight]]]; - } - - if ([stream getBitrate] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream bitrate: %@\n", [stream getBitrate]]]; - } - if ([stream getSampleRate] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream sample rate: %@\n", [stream getSampleRate]]]; - } - if ([stream getSampleFormat] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream sample format: %@\n", [stream getSampleFormat]]]; - } - if ([stream getChannelLayout] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream channel layout: %@\n", [stream getChannelLayout]]]; - } - - if ([stream getSampleAspectRatio] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream sample aspect ratio: %@\n", [stream getSampleAspectRatio]]]; - } - if ([stream getDisplayAspectRatio] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream display ascpect ratio: %@\n", [stream getDisplayAspectRatio]]]; - } - if ([stream getAverageFrameRate] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream average frame rate: %@\n", [stream getAverageFrameRate]]]; - } - if ([stream getRealFrameRate] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream real frame rate: %@\n", [stream getRealFrameRate]]]; - } - if ([stream getTimeBase] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream time base: %@\n", [stream getTimeBase]]]; - } - if ([stream getCodecTimeBase] != nil) { - [self appendOutput:[NSString stringWithFormat:@"Stream codec time base: %@\n", [stream getCodecTimeBase]]]; - } - - if ([stream getTags] != nil) { - NSDictionary* tags = [stream getTags]; - for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@", key, [tags objectForKey:key]]]; - } - } - } - } - } - } - }); - }; -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Info.plist b/ios/test-app-local-universal-library/FFmpegKitIOS/Info.plist deleted file mode 100644 index 37661cc..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Info.plist +++ /dev/null @@ -1,59 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - FFmpegKitIOS - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(MARKETING_VERSION) - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - LSApplicationCategoryType - public.app-category.utilities - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarTintParameters - - UINavigationBar - - Style - UIBarStyleDefault - Translucent - - - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/MediaInformationParserTest.h b/ios/test-app-local-universal-library/FFmpegKitIOS/MediaInformationParserTest.h deleted file mode 100644 index 11b878d..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/MediaInformationParserTest.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -void assertNumber(NSNumber *expected, NSNumber *real); -void assertString(NSString *expected, NSString *real); - -/** - * All json parser tests are initiated from this method - */ -void testMediaInformationJsonParser(void); diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/MediaInformationParserTest.m b/ios/test-app-local-universal-library/FFmpegKitIOS/MediaInformationParserTest.m deleted file mode 100644 index 6e0aa7f..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/MediaInformationParserTest.m +++ /dev/null @@ -1,678 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -static NSString *MEDIA_INFORMATION_MP3; -static NSString *MEDIA_INFORMATION_JPG; -static NSString *MEDIA_INFORMATION_GIF; -static NSString *MEDIA_INFORMATION_H264; -static NSString *MEDIA_INFORMATION_PNG; -static NSString *MEDIA_INFORMATION_MP4; -static NSString *MEDIA_INFORMATION_OGG; - -static void initTests() { - MEDIA_INFORMATION_MP3 = [NSString stringWithFormat: - @"{\n" - " \"streams\": [\n" - " {\n" - " \"index\": 0,\n" - " \"codec_name\": \"mp3\",\n" - " \"codec_long_name\": \"MP3 (MPEG audio layer 3)\",\n" - " \"codec_type\": \"audio\",\n" - " \"codec_time_base\": \"1/44100\",\n" - " \"codec_tag_string\": \"[0][0][0][0]\",\n" - " \"codec_tag\": \"0x0000\",\n" - " \"sample_fmt\": \"fltp\",\n" - " \"sample_rate\": \"44100\",\n" - " \"channels\": 2,\n" - " \"channel_layout\": \"stereo\",\n" - " \"bits_per_sample\": 0,\n" - " \"r_frame_rate\": \"0/0\",\n" - " \"avg_frame_rate\": \"0/0\",\n" - " \"time_base\": \"1/14112000\",\n" - " \"start_pts\": 169280,\n" - " \"start_time\": \"0.011995\",\n" - " \"duration_ts\": 4622376960,\n" - " \"duration\": \"327.549388\",\n" - " \"bit_rate\": \"320000\",\n" - " \"disposition\": {\n" - " \"default\": 0,\n" - " \"dub\": 0,\n" - " \"original\": 0,\n" - " \"comment\": 0,\n" - " \"lyrics\": 0,\n" - " \"karaoke\": 0,\n" - " \"forced\": 0,\n" - " \"hearing_impaired\": 0,\n" - " \"visual_impaired\": 0,\n" - " \"clean_effects\": 0,\n" - " \"attached_pic\": 0,\n" - " \"timed_thumbnails\": 0\n" - " },\n" - " \"tags\": {\n" - " \"encoder\": \"Lavf\"\n" - " }\n" - " }\n" - " ],\n" - " \"format\": {\n" - " \"filename\": \"sample.mp3\",\n" - " \"nb_streams\": 1,\n" - " \"nb_programs\": 0,\n" - " \"format_name\": \"mp3\",\n" - " \"format_long_name\": \"MP2/3 (MPEG audio layer 2/3)\",\n" - " \"start_time\": \"0.011995\",\n" - " \"duration\": \"327.549388\",\n" - " \"size\": \"13103064\",\n" - " \"bit_rate\": \"320026\",\n" - " \"probe_score\": 51,\n" - " \"tags\": {\n" - " \"encoder\": \"Lavf58.20.100\",\n" - " \"album\": \"Impact\",\n" - " \"artist\": \"Kevin MacLeod\",\n" - " \"comment\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit finito.\",\n" - " \"genre\": \"Cinematic\",\n" - " \"title\": \"Impact Moderato\"\n" - " }\n" - " }\n" - "}"]; - - MEDIA_INFORMATION_JPG = [NSString stringWithFormat: - @"{\n" - " \"streams\": [\n" - " {\n" - " \"index\": 0,\n" - " \"codec_name\": \"mjpeg\",\n" - " \"codec_long_name\": \"Motion JPEG\",\n" - " \"profile\": \"Baseline\",\n" - " \"codec_type\": \"video\",\n" - " \"codec_time_base\": \"0/1\",\n" - " \"codec_tag_string\": \"[0][0][0][0]\",\n" - " \"codec_tag\": \"0x0000\",\n" - " \"width\": 1496,\n" - " \"height\": 1729,\n" - " \"coded_width\": 1496,\n" - " \"coded_height\": 1729,\n" - " \"has_b_frames\": 0,\n" - " \"sample_aspect_ratio\": \"1:1\",\n" - " \"display_aspect_ratio\": \"1496:1729\",\n" - " \"pix_fmt\": \"yuvj444p\",\n" - " \"level\": -99,\n" - " \"color_range\": \"pc\",\n" - " \"color_space\": \"bt470bg\",\n" - " \"chroma_location\": \"center\",\n" - " \"refs\": 1,\n" - " \"r_frame_rate\": \"25/1\",\n" - " \"avg_frame_rate\": \"0/0\",\n" - " \"time_base\": \"1/25\",\n" - " \"start_pts\": 0,\n" - " \"start_time\": \"0.000000\",\n" - " \"duration_ts\": 1,\n" - " \"duration\": \"0.040000\",\n" - " \"bits_per_raw_sample\": \"8\",\n" - " \"disposition\": {\n" - " \"default\": 0,\n" - " \"dub\": 0,\n" - " \"original\": 0,\n" - " \"comment\": 0,\n" - " \"lyrics\": 0,\n" - " \"karaoke\": 0,\n" - " \"forced\": 0,\n" - " \"hearing_impaired\": 0,\n" - " \"visual_impaired\": 0,\n" - " \"clean_effects\": 0,\n" - " \"attached_pic\": 0,\n" - " \"timed_thumbnails\": 0\n" - " }\n" - " }\n" - " ],\n" - " \"format\": {\n" - " \"filename\": \"sample.jpg\",\n" - " \"nb_streams\": 1,\n" - " \"nb_programs\": 0,\n" - " \"format_name\": \"image2\",\n" - " \"format_long_name\": \"image2 sequence\",\n" - " \"start_time\": \"0.000000\",\n" - " \"duration\": \"0.040000\",\n" - " \"size\": \"1659050\",\n" - " \"bit_rate\": \"331810000\",\n" - " \"probe_score\": 50\n" - " }\n" - "}"]; - - MEDIA_INFORMATION_GIF = [NSString stringWithFormat: - @"{\n" - " \"streams\": [\n" - " {\n" - " \"index\": 0,\n" - " \"codec_name\": \"gif\",\n" - " \"codec_long_name\": \"CompuServe GIF (Graphics Interchange Format)\",\n" - " \"codec_type\": \"video\",\n" - " \"codec_time_base\": \"12/133\",\n" - " \"codec_tag_string\": \"[0][0][0][0]\",\n" - " \"codec_tag\": \"0x0000\",\n" - " \"width\": 400,\n" - " \"height\": 400,\n" - " \"coded_width\": 400,\n" - " \"coded_height\": 400,\n" - " \"has_b_frames\": 0,\n" - " \"pix_fmt\": \"bgra\",\n" - " \"level\": -99,\n" - " \"refs\": 1,\n" - " \"r_frame_rate\": \"100/9\",\n" - " \"avg_frame_rate\": \"133/12\",\n" - " \"time_base\": \"1/100\",\n" - " \"start_pts\": 0,\n" - " \"start_time\": \"0.000000\",\n" - " \"duration_ts\": 396,\n" - " \"duration\": \"3.960000\",\n" - " \"nb_frames\": \"44\",\n" - " \"disposition\": {\n" - " \"default\": 0,\n" - " \"dub\": 0,\n" - " \"original\": 0,\n" - " \"comment\": 0,\n" - " \"lyrics\": 0,\n" - " \"karaoke\": 0,\n" - " \"forced\": 0,\n" - " \"hearing_impaired\": 0,\n" - " \"visual_impaired\": 0,\n" - " \"clean_effects\": 0,\n" - " \"attached_pic\": 0,\n" - " \"timed_thumbnails\": 0\n" - " }\n" - " }\n" - " ],\n" - " \"format\": {\n" - " \"filename\": \"sample.gif\",\n" - " \"nb_streams\": 1,\n" - " \"nb_programs\": 0,\n" - " \"format_name\": \"gif\",\n" - " \"format_long_name\": \"CompuServe Graphics Interchange Format (GIF)\",\n" - " \"start_time\": \"0.000000\",\n" - " \"duration\": \"3.960000\",\n" - " \"size\": \"1001718\",\n" - " \"bit_rate\": \"2023672\",\n" - " \"probe_score\": 100\n" - " }\n" - "}"]; - - MEDIA_INFORMATION_MP4 = [NSString stringWithFormat: - @"{\n" - " \"streams\": [\n" - " {\n" - " \"index\": 0,\n" - " \"codec_name\": \"h264\",\n" - " \"codec_long_name\": \"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10\",\n" - " \"profile\": \"Main\",\n" - " \"codec_type\": \"video\",\n" - " \"codec_time_base\": \"1/60\",\n" - " \"codec_tag_string\": \"avc1\",\n" - " \"codec_tag\": \"0x31637661\",\n" - " \"width\": 1280,\n" - " \"height\": 720,\n" - " \"coded_width\": 1280,\n" - " \"coded_height\": 720,\n" - " \"has_b_frames\": 0,\n" - " \"sample_aspect_ratio\": \"1:1\",\n" - " \"display_aspect_ratio\": \"16:9\",\n" - " \"pix_fmt\": \"yuv420p\",\n" - " \"level\": 42,\n" - " \"chroma_location\": \"left\",\n" - " \"refs\": 1,\n" - " \"is_avc\": \"true\",\n" - " \"nal_length_size\": \"4\",\n" - " \"r_frame_rate\": \"30/1\",\n" - " \"avg_frame_rate\": \"30/1\",\n" - " \"time_base\": \"1/15360\",\n" - " \"start_pts\": 0,\n" - " \"start_time\": \"0.000000\",\n" - " \"duration_ts\": 215040,\n" - " \"duration\": \"14.000000\",\n" - " \"bit_rate\": \"9166570\",\n" - " \"bits_per_raw_sample\": \"8\",\n" - " \"nb_frames\": \"420\",\n" - " \"disposition\": {\n" - " \"default\": 1,\n" - " \"dub\": 0,\n" - " \"original\": 0,\n" - " \"comment\": 0,\n" - " \"lyrics\": 0,\n" - " \"karaoke\": 0,\n" - " \"forced\": 0,\n" - " \"hearing_impaired\": 0,\n" - " \"visual_impaired\": 0,\n" - " \"clean_effects\": 0,\n" - " \"attached_pic\": 0,\n" - " \"timed_thumbnails\": 0\n" - " },\n" - " \"tags\": {\n" - " \"language\": \"und\",\n" - " \"handler_name\": \"VideoHandler\"\n" - " }\n" - " }\n" - " ],\n" - " \"format\": {\n" - " \"filename\": \"sample.mp4\",\n" - " \"nb_streams\": 1,\n" - " \"nb_programs\": 0,\n" - " \"format_name\": \"mov,mp4,m4a,3gp,3g2,mj2\",\n" - " \"format_long_name\": \"QuickTime / MOV\",\n" - " \"start_time\": \"0.000000\",\n" - " \"duration\": \"14.000000\",\n" - " \"size\": \"16044159\",\n" - " \"bit_rate\": \"9168090\",\n" - " \"probe_score\": 100,\n" - " \"tags\": {\n" - " \"major_brand\": \"isom\",\n" - " \"minor_version\": \"512\",\n" - " \"compatible_brands\": \"isomiso2avc1mp41\",\n" - " \"encoder\": \"Lavf58.33.100\"\n" - " }\n" - " }\n" - "}"]; - - MEDIA_INFORMATION_PNG = [NSString stringWithFormat: - @"{\n" - " \"streams\": [\n" - " {\n" - " \"index\": 0,\n" - " \"codec_name\": \"png\",\n" - " \"codec_long_name\": \"PNG (Portable Network Graphics) image\",\n" - " \"codec_type\": \"video\",\n" - " \"codec_time_base\": \"0/1\",\n" - " \"codec_tag_string\": \"[0][0][0][0]\",\n" - " \"codec_tag\": \"0x0000\",\n" - " \"width\": 1198,\n" - " \"height\": 1198,\n" - " \"coded_width\": 1198,\n" - " \"coded_height\": 1198,\n" - " \"has_b_frames\": 0,\n" - " \"sample_aspect_ratio\": \"1:1\",\n" - " \"display_aspect_ratio\": \"1:1\",\n" - " \"pix_fmt\": \"pal8\",\n" - " \"level\": -99,\n" - " \"color_range\": \"pc\",\n" - " \"refs\": 1,\n" - " \"r_frame_rate\": \"25/1\",\n" - " \"avg_frame_rate\": \"0/0\",\n" - " \"time_base\": \"1/25\",\n" - " \"disposition\": {\n" - " \"default\": 0,\n" - " \"dub\": 0,\n" - " \"original\": 0,\n" - " \"comment\": 0,\n" - " \"lyrics\": 0,\n" - " \"karaoke\": 0,\n" - " \"forced\": 0,\n" - " \"hearing_impaired\": 0,\n" - " \"visual_impaired\": 0,\n" - " \"clean_effects\": 0,\n" - " \"attached_pic\": 0,\n" - " \"timed_thumbnails\": 0\n" - " }\n" - " }\n" - " ],\n" - " \"format\": {\n" - " \"filename\": \"sample.png\",\n" - " \"nb_streams\": 1,\n" - " \"nb_programs\": 0,\n" - " \"format_name\": \"png_pipe\",\n" - " \"format_long_name\": \"piped png sequence\",\n" - " \"size\": \"31533\",\n" - " \"probe_score\": 99\n" - " }\n" - "}"]; - - MEDIA_INFORMATION_OGG = [NSString stringWithFormat: - @"{\n" - " \"streams\": [\n" - " {\n" - " \"index\": 0,\n" - " \"codec_name\": \"theora\",\n" - " \"codec_long_name\": \"Theora\",\n" - " \"codec_type\": \"video\",\n" - " \"codec_time_base\": \"1/25\",\n" - " \"codec_tag_string\": \"[0][0][0][0]\",\n" - " \"codec_tag\": \"0x0000\",\n" - " \"width\": 1920,\n" - " \"height\": 1080,\n" - " \"coded_width\": 1920,\n" - " \"coded_height\": 1088,\n" - " \"has_b_frames\": 0,\n" - " \"pix_fmt\": \"yuv420p\",\n" - " \"level\": -99,\n" - " \"color_space\": \"bt470bg\",\n" - " \"color_transfer\": \"bt709\",\n" - " \"color_primaries\": \"bt470bg\",\n" - " \"chroma_location\": \"center\",\n" - " \"refs\": 1,\n" - " \"r_frame_rate\": \"25/1\",\n" - " \"avg_frame_rate\": \"25/1\",\n" - " \"time_base\": \"1/25\",\n" - " \"start_pts\": 0,\n" - " \"start_time\": \"0.000000\",\n" - " \"duration_ts\": 813,\n" - " \"duration\": \"32.520000\",\n" - " \"disposition\": {\n" - " \"default\": 0,\n" - " \"dub\": 0,\n" - " \"original\": 0,\n" - " \"comment\": 0,\n" - " \"lyrics\": 0,\n" - " \"karaoke\": 0,\n" - " \"forced\": 0,\n" - " \"hearing_impaired\": 0,\n" - " \"visual_impaired\": 0,\n" - " \"clean_effects\": 0,\n" - " \"attached_pic\": 0,\n" - " \"timed_thumbnails\": 0\n" - " },\n" - " \"tags\": {\n" - " \"ENCODER\": \"ffmpeg2theora 0.19\"\n" - " }\n" - " },\n" - " {\n" - " \"index\": 1,\n" - " \"codec_name\": \"vorbis\",\n" - " \"codec_long_name\": \"Vorbis\",\n" - " \"codec_type\": \"audio\",\n" - " \"codec_time_base\": \"1/48000\",\n" - " \"codec_tag_string\": \"[0][0][0][0]\",\n" - " \"codec_tag\": \"0x0000\",\n" - " \"sample_fmt\": \"fltp\",\n" - " \"sample_rate\": \"48000\",\n" - " \"channels\": 2,\n" - " \"channel_layout\": \"stereo\",\n" - " \"bits_per_sample\": 0,\n" - " \"r_frame_rate\": \"0/0\",\n" - " \"avg_frame_rate\": \"0/0\",\n" - " \"time_base\": \"1/48000\",\n" - " \"start_pts\": 0,\n" - " \"start_time\": \"0.000000\",\n" - " \"duration_ts\": 1583850,\n" - " \"duration\": \"32.996875\",\n" - " \"bit_rate\": \"80000\",\n" - " \"disposition\": {\n" - " \"default\": 0,\n" - " \"dub\": 0,\n" - " \"original\": 0,\n" - " \"comment\": 0,\n" - " \"lyrics\": 0,\n" - " \"karaoke\": 0,\n" - " \"forced\": 0,\n" - " \"hearing_impaired\": 0,\n" - " \"visual_impaired\": 0,\n" - " \"clean_effects\": 0,\n" - " \"attached_pic\": 0,\n" - " \"timed_thumbnails\": 0\n" - " },\n" - " \"tags\": {\n" - " \"ENCODER\": \"ffmpeg2theora 0.19\"\n" - " }\n" - " }\n" - " ],\n" - " \"format\": {\n" - " \"filename\": \"sample.ogg\",\n" - " \"nb_streams\": 2,\n" - " \"nb_programs\": 0,\n" - " \"format_name\": \"ogg\",\n" - " \"format_long_name\": \"Ogg\",\n" - " \"start_time\": \"0.000000\",\n" - " \"duration\": \"32.996875\",\n" - " \"size\": \"27873937\",\n" - " \"bit_rate\": \"6757958\",\n" - " \"probe_score\": 100\n" - " }\n" - "}"]; - -} - -void assertNumber(NSNumber *expected, NSNumber *real) { - if (expected == nil) { - assert(real == nil); - } else { - assert([expected isEqualToNumber:real]); - } -} - -void assertString(NSString *expected, NSString *real) { - if (expected == nil) { - assert(real == nil); - } else { - assert([expected isEqualToString:real]); - } -} - -void assertVideoStream(StreamInformation *stream, NSNumber *index, NSString *codec, NSString *fullCodec, NSString *format, NSNumber *width, NSNumber *height, NSString *sampleAspectRatio, NSString *displayAspectRatio, NSString *bitrate, NSString *averageFrameRate, NSString *realFrameRate, NSString *timeBase, NSString *codecTimeBase) { - assert(stream != nil); - assertNumber(index, [stream getIndex]); - assertString(@"video", [stream getType]); - - assertString(codec, [stream getCodec]); - assertString(fullCodec, [stream getCodecLong]); - - assertString(format, [stream getFormat]); - - assertNumber(width, [stream getWidth]); - assertNumber(height, [stream getHeight]); - assertString(sampleAspectRatio, [stream getSampleAspectRatio]); - assertString(displayAspectRatio, [stream getDisplayAspectRatio]); - - assertString(bitrate, [stream getBitrate]); - - assertString(averageFrameRate, [stream getAverageFrameRate]); - assertString(realFrameRate, [stream getRealFrameRate]); - assertString(timeBase, [stream getTimeBase]); - assertString(codecTimeBase, [stream getCodecTimeBase]); -} - -void assertAudioStream(StreamInformation *stream, NSNumber *index, NSString *codec, NSString *fullCodec, NSString *sampleRate, NSString *channelLayout, NSString *sampleFormat, NSString *bitrate) { - assert(stream != nil); - assertNumber(index, [stream getIndex]); - assertString(@"audio", [stream getType]); - - assertString(codec, [stream getCodec]); - assertString(fullCodec, [stream getCodecLong]); - - assertString(sampleRate, [stream getSampleRate]); - assertString(channelLayout, [stream getChannelLayout]); - assertString(sampleFormat, [stream getSampleFormat]); - assertString(bitrate, [stream getBitrate]); -} - -void assertNotNull(NSObject *object) { - assert(object != nil); -} - -void assertMediaInput(MediaInformation *mediaInformation, NSString *expectedFormat, NSString *expectedFilename) { - NSString *format = [mediaInformation getFormat]; - NSString *filename = [mediaInformation getFilename]; - if (format == nil) { - assert(expectedFormat == nil); - } else { - assert([format isEqualToString:expectedFormat]); - } - if (filename == nil) { - assert(expectedFilename == nil); - } else { - assert([filename isEqualToString:expectedFilename]); - } -} - -void assertMediaDuration(MediaInformation *mediaInformation, NSString *expectedDuration, NSString *expectedStartTime, NSString *expectedBitrate) { - NSString *duration = [mediaInformation getDuration]; - NSString *startTime = [mediaInformation getStartTime]; - NSString *bitrate = [mediaInformation getBitrate]; - - if (duration == nil) { - assert(expectedDuration == nil); - } else { - assert([duration isEqualToString:expectedDuration]); - } - if (startTime == nil) { - assert(expectedStartTime == nil); - } else { - assert([startTime isEqualToString:expectedStartTime]); - } - if (bitrate == nil) { - assert(expectedBitrate == nil); - } else { - assert([bitrate isEqualToString:expectedBitrate]); - } -} - -void assertTag(MediaInformation *mediaInformation, NSString *expectedKey, NSString *expectedValue) { - NSDictionary *tags = [mediaInformation getTags]; - assertNotNull(tags); - - NSString *value = [tags valueForKey:expectedKey]; - assertNotNull(value); - - assert([value isEqualToString:expectedValue]); -} - -void assertStreamTag(StreamInformation *streamInformation, NSString *expectedKey, NSString *expectedValue) { - NSDictionary *tags = [streamInformation getTags]; - assertNotNull(tags); - - NSString *value = [tags valueForKey:expectedKey]; - assertNotNull(value); - - assert([value isEqualToString:expectedValue]); -} - -void testMediaInformationMp3() { - MediaInformation *mediaInformation = [MediaInformationJsonParser from:MEDIA_INFORMATION_MP3]; - - assertNotNull(mediaInformation); - assertMediaInput(mediaInformation, @"mp3", @"sample.mp3"); - assertMediaDuration(mediaInformation, @"327.549388", @"0.011995", @"320026"); - - assertTag(mediaInformation, @"comment", @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit finito."); - assertTag(mediaInformation, @"album", @"Impact"); - assertTag(mediaInformation, @"title", @"Impact Moderato"); - assertTag(mediaInformation, @"artist", @"Kevin MacLeod"); - - NSArray *streams = [mediaInformation getStreams]; - assertNotNull(streams); - assert(1 == [streams count]); - - assertAudioStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mp3", @"MP3 (MPEG audio layer 3)", @"44100", @"stereo", @"fltp", @"320000"); -} - -void testMediaInformationJpg() { - MediaInformation *mediaInformation = [MediaInformationJsonParser from:MEDIA_INFORMATION_JPG]; - - assertNotNull(mediaInformation); - assertMediaInput(mediaInformation, @"image2", @"sample.jpg"); - assertMediaDuration(mediaInformation, @"0.040000", @"0.000000", @"331810000"); - - NSArray *streams = [mediaInformation getStreams]; - assertNotNull(streams); - assert(1 == [streams count]); - - assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mjpeg", @"Motion JPEG", @"yuvj444p", [[NSNumber alloc] initWithInt:1496], [[NSNumber alloc] initWithInt:1729], @"1:1", @"1496:1729", nil, @"0/0", @"25/1", @"1/25", @"0/1"); -} - -void testMediaInformationGif() { - MediaInformation *mediaInformation = [MediaInformationJsonParser from:MEDIA_INFORMATION_GIF]; - - assertNotNull(mediaInformation); - assertMediaInput(mediaInformation, @"gif", @"sample.gif"); - assertMediaDuration(mediaInformation, @"3.960000", @"0.000000", @"2023672"); - - NSArray *streams = [mediaInformation getStreams]; - assertNotNull(streams); - assert(1 == [streams count]); - - assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"gif", @"CompuServe GIF (Graphics Interchange Format)", @"bgra", [[NSNumber alloc] initWithInt:400], [[NSNumber alloc] initWithInt:400], nil, nil, nil, @"133/12", @"100/9", @"1/100", @"12/133"); -} - -void testMediaInformationMp4() { - MediaInformation *mediaInformation = [MediaInformationJsonParser from:MEDIA_INFORMATION_MP4]; - - assertNotNull(mediaInformation); - assertMediaInput(mediaInformation, @"mov,mp4,m4a,3gp,3g2,mj2", @"sample.mp4"); - assertMediaDuration(mediaInformation, @"14.000000", @"0.000000", @"9168090"); - - assertTag(mediaInformation, @"major_brand", @"isom"); - assertTag(mediaInformation, @"minor_version", @"512"); - assertTag(mediaInformation, @"compatible_brands", @"isomiso2avc1mp41"); - assertTag(mediaInformation, @"encoder", @"Lavf58.33.100"); - - NSArray *streams = [mediaInformation getStreams]; - assertNotNull(streams); - assert(1 == [streams count]); - - assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"h264", @"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10", @"yuv420p", [[NSNumber alloc] initWithInt:1280], [[NSNumber alloc] initWithInt:720], @"1:1", @"16:9", @"9166570", @"30/1", @"30/1", @"1/15360", @"1/60"); - - assertStreamTag([streams objectAtIndex:0], @"language", @"und"); - assertStreamTag([streams objectAtIndex:0], @"handler_name", @"VideoHandler"); -} - -void testMediaInformationPng() { - MediaInformation *mediaInformation = [MediaInformationJsonParser from:MEDIA_INFORMATION_PNG]; - - assertNotNull(mediaInformation); - assertMediaInput(mediaInformation, @"png_pipe", @"sample.png"); - assertMediaDuration(mediaInformation, nil, nil, nil); - - NSArray *streams = [mediaInformation getStreams]; - assertNotNull(streams); - assert(1 == [streams count]); - - assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"png", @"PNG (Portable Network Graphics) image", @"pal8", [[NSNumber alloc] initWithInt:1198], [[NSNumber alloc] initWithInt:1198], @"1:1", @"1:1", nil, @"0/0", @"25/1", @"1/25", @"0/1"); -} - -void testMediaInformationOgg() { - MediaInformation *mediaInformation = [MediaInformationJsonParser from:MEDIA_INFORMATION_OGG]; - - assertNotNull(mediaInformation); - assertMediaInput(mediaInformation, @"ogg", @"sample.ogg"); - assertMediaDuration(mediaInformation, @"32.996875", @"0.000000", @"6757958"); - - NSArray *streams = [mediaInformation getStreams]; - assertNotNull(streams); - assert(2 == [streams count]); - - assertVideoStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"theora", @"Theora", @"yuv420p", [[NSNumber alloc] initWithInt:1920], [[NSNumber alloc] initWithInt:1080], nil, nil, nil, @"25/1", @"25/1", @"1/25", @"1/25"); - assertAudioStream([streams objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"vorbis", @"Vorbis", @"48000", @"stereo", @"fltp", @"80000"); - - assertStreamTag([streams objectAtIndex:0], @"ENCODER", @"ffmpeg2theora 0.19"); - assertStreamTag([streams objectAtIndex:1], @"ENCODER", @"ffmpeg2theora 0.19"); -} - -void testMediaInformationJsonParser(void) { - - initTests(); - - testMediaInformationMp3(); - testMediaInformationJpg(); - testMediaInformationGif(); - testMediaInformationMp4(); - testMediaInformationPng(); - testMediaInformationOgg(); - - NSLog(@"MediaInformationJsonParserTest passed."); -} diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/OtherViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/OtherViewController.h deleted file mode 100644 index 367a4ec..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/OtherViewController.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface OtherViewController : UIViewController - -- (void)setActive; - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/OtherViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/OtherViewController.m deleted file mode 100644 index c1a3046..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/OtherViewController.m +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "OtherViewController.h" - -@interface OtherViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (strong, nonatomic) IBOutlet UIPickerView *otherTestPicker; -@property (strong, nonatomic) IBOutlet UIButton *runButton; -@property (strong, nonatomic) IBOutlet UITextView *outputText; - -@end - -@implementation OtherViewController { - NSArray *testData; - NSInteger selectedTest; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // OTHER TEST PICKER INIT - testData = @[@"chromaprint", @"dav1d", @"webp"]; - selectedTest = 0; - - self.otherTestPicker.dataSource = self; - self.otherTestPicker.delegate = self; - - // STYLE UPDATE - [Util applyPickerViewStyle: self.otherTestPicker]; - [Util applyButtonStyle: self.runButton]; - [Util applyOutputTextStyle: self.outputText]; - [Util applyHeaderStyle: self.header]; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -/** - * The number of columns of data - */ -- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { - return 1; -} - -/** - * The number of rows of data - */ -- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { - return testData.count; -} - -/** - * The data to return for the row and component (column) that's being passed in - */ -- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { - return testData[row]; -} - -- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { - selectedTest = row; -} - -- (IBAction)runTest:(id)sender { - [self clearOutput]; - - switch (selectedTest) { - case 0: - [self testChromaprint]; - break; - case 1: - [self testDav1d]; - break; - case 2: - [self testWebp]; - break; - } -} - --(void)testChromaprint { - NSLog(@"Testing 'chromaprint' mutex\n"); - - NSString *audioSampleFile = [self getChromaprintSamplePath]; - [[NSFileManager defaultManager] removeItemAtPath:audioSampleFile error:NULL]; - - NSString *ffmpegCommand = [NSString stringWithFormat:@"-hide_banner -y -f lavfi -i sine=frequency=1000:duration=5 -c:a pcm_s16le %@", audioSampleFile]; - - NSLog(@"Creating audio sample with '%@'.\n", ffmpegCommand); - - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); - - if ([ReturnCode isSuccess:[session getReturnCode]]) { - - NSLog(@"AUDIO sample created\n"); - - NSString *chromaprintCommand = [NSString stringWithFormat:@"-hide_banner -y -i %@ -f chromaprint -fp_format 2 %@", audioSampleFile, [self getChromaprintOutputPath]]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", chromaprintCommand); - - [FFmpegKit executeAsync:chromaprintCommand withExecuteCallback:^(id session) { - - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); - - } withLogCallback:^(Log *log) { - addUIAction(^{ - [self appendOutput: [log getMessage]]; - }); - } withStatisticsCallback:nil]; - } - }]; -} - --(void)testDav1d { - NSLog(@"Testing decoding 'av1' codec\n"); - - NSString *ffmpegCommand = [NSString stringWithFormat:@"-hide_banner -y -i %@ %@", DAV1D_TEST_DEFAULT_URL, [self getDav1dOutputPath]]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); - } withLogCallback:^(Log *log) { - addUIAction(^{ - [self appendOutput: [log getMessage]]; - }); - } withStatisticsCallback:nil]; -} - --(void)testWebp { - NSString *resourceFolder = [[NSBundle mainBundle] resourcePath]; - NSString *imageFile = [resourceFolder stringByAppendingPathComponent: @"machupicchu.jpg"]; - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - NSString *outputFile = [docFolder stringByAppendingPathComponent: @"video.webp"]; - - NSLog(@"Testing 'webp' codec\n"); - - NSString *ffmpegCommand = [NSString stringWithFormat:@"-hide_banner -y -i %@ %@", imageFile, outputFile]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); - - } withLogCallback:^(Log *log) { - addUIAction(^{ - [self appendOutput: [log getMessage]]; - }); - } withStatisticsCallback:nil]; -} - -- (NSString*)getChromaprintSamplePath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"audio-sample.wav"]; -} - -- (NSString*)getDav1dOutputPath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"video.mp4"]; -} - -- (NSString*)getChromaprintOutputPath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"chromaprint.txt"]; -} - -- (void)setActive { - NSLog(@"Other Tab Activated"); -} - -- (void)appendOutput:(NSString*) message { - self.outputText.text = [self.outputText.text stringByAppendingString:message]; - - if (self.outputText.text.length > 0 ) { - NSRange bottom = NSMakeRange(self.outputText.text.length - 1, 1); - [self.outputText scrollRangeToVisible:bottom]; - } -} - -- (void)clearOutput { - [[self outputText] setText:@""]; -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/PipeViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/PipeViewController.h deleted file mode 100644 index 309f255..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/PipeViewController.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface PipeViewController : UIViewController - -- (void)setActive; - -@end - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/PipeViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/PipeViewController.m deleted file mode 100644 index 85e7a96..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/PipeViewController.m +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (c) 2019-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include "PipeViewController.h" -#include "Video.h" - -@interface PipeViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (weak, nonatomic) IBOutlet UIButton *createButton; -@property (strong, nonatomic) IBOutlet UILabel *videoPlayerFrame; - -@end - -@implementation PipeViewController { - - // Video player references - AVQueuePlayer *player; - AVPlayerLayer *playerLayer; - AVPlayerItem *activeItem; - - // Loading view - UIAlertController *alertController; - UIActivityIndicatorView* indicator; - - Statistics *statistics; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // STYLE UPDATE - [Util applyButtonStyle: self.createButton]; - [Util applyVideoPlayerFrameStyle: self.videoPlayerFrame]; - [Util applyHeaderStyle: self.header]; - - // VIDEO PLAYER INIT - player = [[AVQueuePlayer alloc] init]; - playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; - activeItem = nil; - - CGRect rectangularFrame = self.view.layer.bounds; - rectangularFrame.size.width = self.view.layer.bounds.size.width - 40; - rectangularFrame.origin.x = 20; - rectangularFrame.origin.y = self.createButton.layer.bounds.origin.y + 120; - - playerLayer.frame = rectangularFrame; - [self.view.layer addSublayer:playerLayer]; - - alertController = nil; - statistics = nil; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (void)enableLogCallback { - [FFmpegKitConfig enableLogCallback: ^(Log* log){ - addUIAction(^{ - NSLog(@"%@", [log getMessage]); - }); - }]; -} - -- (void)enableStatisticsCallback { - [FFmpegKitConfig enableStatisticsCallback:^(Statistics* statistics){ - addUIAction(^{ - self->statistics = statistics; - [self updateProgressDialog]; - }); - }]; -} - -+ (void)startAsyncCopyImageProcess: (NSString*)imagePath onPipe:(NSString*)namedPipePath { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - - NSLog(@"Starting copy %@ to pipe %@ operation.\n", imagePath, namedPipePath); - - NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath: imagePath]; - if (fileHandle == nil) { - NSLog(@"Failed to open file %@.\n", imagePath); - return; - } - - NSFileHandle *pipeHandle = [NSFileHandle fileHandleForWritingAtPath: namedPipePath]; - if (pipeHandle == nil) { - NSLog(@"Failed to open pipe %@.\n", namedPipePath); - [fileHandle closeFile]; - return; - } - - int BUFFER_SIZE = 4096; - unsigned long readBytes = 0; - unsigned long totalBytes = 0; - double startTime = CACurrentMediaTime(); - - @try { - [fileHandle seekToFileOffset: 0]; - - do { - NSData *data = [fileHandle readDataOfLength:BUFFER_SIZE]; - readBytes = [data length]; - if (readBytes > 0) { - totalBytes += readBytes; - [pipeHandle writeData:data]; - } - } while (readBytes > 0); - - double endTime = CACurrentMediaTime(); - - NSLog(@"Completed copy %@ to pipe %@ operation. %lu bytes copied in %f seconds.\n", imagePath, namedPipePath, totalBytes, (endTime - startTime)); - - } @catch (NSException *e) { - NSLog(@"Copy failed %@.\n", [e reason]); - } @finally { - [fileHandle closeFile]; - [pipeHandle closeFile]; - } - }); -} - -- (IBAction)createVideo:(id)sender { - NSString *resourceFolder = [[NSBundle mainBundle] resourcePath]; - NSString *image1 = [resourceFolder stringByAppendingPathComponent: @"machupicchu.jpg"]; - NSString *image2 = [resourceFolder stringByAppendingPathComponent: @"pyramid.jpg"]; - NSString *image3 = [resourceFolder stringByAppendingPathComponent: @"stonehenge.jpg"]; - NSString *videoFile = [self getVideoPath]; - - NSString *pipe1 = [FFmpegKitConfig registerNewFFmpegPipe]; - NSString *pipe2 = [FFmpegKitConfig registerNewFFmpegPipe]; - NSString *pipe3 = [FFmpegKitConfig registerNewFFmpegPipe]; - - if (player != nil) { - [player removeAllItems]; - activeItem = nil; - } - - [[NSFileManager defaultManager] removeItemAtPath:videoFile error:NULL]; - - NSLog(@"Testing PIPE with 'mpeg4' codec\n"); - - [self showProgressDialog:@"Creating video\n\n"]; - - NSString* ffmpegCommand = [Video generateCreateVideoWithPipesScript:pipe1:pipe2:pipe3:videoFile]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - SessionState state = [session getState]; - ReturnCode* returnCode = [session getReturnCode]; - - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - - addUIAction(^{ - [self hideProgressDialog]; - }); - - // CLOSE PIPES - [FFmpegKitConfig closeFFmpegPipe:pipe1]; - [FFmpegKitConfig closeFFmpegPipe:pipe2]; - [FFmpegKitConfig closeFFmpegPipe:pipe3]; - - addUIAction(^{ - if ([ReturnCode isSuccess:returnCode]) { - NSLog(@"Create completed successfully; playing video.\n"); - [self playVideo]; - } else { - [self hideProgressDialogAndAlert:@"Create failed. Please check logs for the details."]; - } - }); - }]; - - // START ASYNC PROCESSES AFTER INITIATING FFMPEG COMMAND - [PipeViewController startAsyncCopyImageProcess:image1 onPipe:pipe1]; - [PipeViewController startAsyncCopyImageProcess:image2 onPipe:pipe2]; - [PipeViewController startAsyncCopyImageProcess:image3 onPipe:pipe3]; -} - -- (void)playVideo { - NSString *videoFile = [self getVideoPath]; - NSURL*videoURL=[NSURL fileURLWithPath:videoFile]; - - AVAsset *asset = [AVAsset assetWithURL:videoURL]; - NSArray *assetKeys = @[@"playable", @"hasProtectedContent"]; - - AVPlayerItem *newVideo = [AVPlayerItem playerItemWithAsset:asset - automaticallyLoadedAssetKeys:assetKeys]; - - NSKeyValueObservingOptions options = - NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew; - - activeItem = newVideo; - - [newVideo addObserver:self forKeyPath:@"status" options:options context:nil]; - - [player insertItem:newVideo afterItem:nil]; -} - -- (NSString*)getVideoPath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"video.mp4"]; -} - -- (void)setActive { - NSLog(@"Pipe Tab Activated"); - [self enableLogCallback]; - [self enableStatisticsCallback]; -} - -- (void)showProgressDialog:(NSString*) dialogMessage { - - // CLEAN STATISTICS - statistics = nil; - - alertController = [UIAlertController alertControllerWithTitle:nil - message:dialogMessage - preferredStyle:UIAlertControllerStyleAlert]; - indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - indicator.color = [UIColor blackColor]; - indicator.translatesAutoresizingMaskIntoConstraints=NO; - [alertController.view addSubview:indicator]; - NSDictionary * views = @{@"pending" : alertController.view, @"indicator" : indicator}; - - NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[indicator]-(20)-|" options:0 metrics:nil views:views]; - NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[indicator]|" options:0 metrics:nil views:views]; - NSArray * constraints = [constraintsVertical arrayByAddingObjectsFromArray:constraintsHorizontal]; - [alertController.view addConstraints:constraints]; - [indicator startAnimating]; - [self presentViewController:alertController animated:YES completion:nil]; -} - -- (void)updateProgressDialog { - if (statistics == nil) { - return; - } - - if (alertController != nil) { - int timeInMilliseconds = [statistics getTime]; - if (timeInMilliseconds > 0) { - int totalVideoDuration = 9000; - - int percentage = timeInMilliseconds*100/totalVideoDuration; - - [alertController setMessage:[NSString stringWithFormat:@"Creating video %% %d \n\n", percentage]]; - } - } -} - -- (void)hideProgressDialog { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:nil]; -} - -- (void)hideProgressDialogAndAlert: (NSString*)message { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:^{ - [Util alert:self withTitle:@"Error" message:message andButtonText:@"OK"]; - }]; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - - NSNumber *statusNumber = change[NSKeyValueChangeNewKey]; - NSInteger status = -1; - if ([statusNumber isKindOfClass:[NSNumber class]]) { - status = statusNumber.integerValue; - } - - switch (status) { - case AVPlayerItemStatusReadyToPlay: { - [player play]; - } break; - case AVPlayerItemStatusFailed: { - if (activeItem != nil && activeItem.error != nil) { - - NSString *message = activeItem.error.localizedFailureReason; - if (message == nil) { - message = activeItem.error.localizedDescription; - } - - [Util alert:self withTitle:@"Player Error" message:message andButtonText:@"OK"]; - } - } break; - default: { - NSLog(@"Status %ld received from player.\n", status); - } - } -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/SubtitleViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/SubtitleViewController.h deleted file mode 100644 index 342320d..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/SubtitleViewController.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface SubtitleViewController : UIViewController - -- (void)setActive; - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/SubtitleViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/SubtitleViewController.m deleted file mode 100644 index 6f99b2e..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/SubtitleViewController.m +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include "SubtitleViewController.h" -#include "VideoViewController.h" -#include "Video.h" - -typedef enum { - IdleState = 1, - CreatingState = 2, - BurningState = 3 -} UITestState; - -@interface SubtitleViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (strong, nonatomic) IBOutlet UIButton *burnSubtitlesButton; -@property (strong, nonatomic) IBOutlet UILabel *videoPlayerFrame; - -@end - -@implementation SubtitleViewController { - - // Video player references - AVQueuePlayer *player; - AVPlayerLayer *playerLayer; - - // Loading view - UIAlertController *alertController; - UIActivityIndicatorView* indicator; - - Statistics *statistics; - - UITestState state; - - long sessionId; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // STYLE UPDATE - [Util applyButtonStyle: self.burnSubtitlesButton]; - [Util applyVideoPlayerFrameStyle: self.videoPlayerFrame]; - [Util applyHeaderStyle: self.header]; - - // VIDEO PLAYER INIT - player = [[AVQueuePlayer alloc] init]; - playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; - - CGRect rectangularFrame = self.view.layer.bounds; - rectangularFrame.size.width = self.view.layer.bounds.size.width - 40; - rectangularFrame.origin.x = 20; - rectangularFrame.origin.y = self.burnSubtitlesButton.layer.bounds.origin.y + 80; - - playerLayer.frame = rectangularFrame; - [self.view.layer addSublayer:playerLayer]; - - alertController = nil; - statistics = nil; - - state = IdleState; - - sessionId = 0; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (void)enableLogCallback { - [FFmpegKitConfig enableLogCallback:^(Log* log){ - NSLog(@"%@", [log getMessage]); - }]; -} - -- (void)enableStatisticsCallback { - [FFmpegKitConfig enableStatisticsCallback:^(Statistics *statistics){ - addUIAction(^{ - self->statistics = statistics; - [self updateProgressDialog]; - }); - }]; -} - -- (IBAction)burnSubtitles:(id)sender { - NSString *resourceFolder = [[NSBundle mainBundle] resourcePath]; - NSString *image1 = [resourceFolder stringByAppendingPathComponent: @"machupicchu.jpg"]; - NSString *image2 = [resourceFolder stringByAppendingPathComponent: @"pyramid.jpg"]; - NSString *image3 = [resourceFolder stringByAppendingPathComponent: @"stonehenge.jpg"]; - NSString *subtitle = [self getSubtitlePath]; - NSString *videoFile = [self getVideoPath]; - NSString *videoWithSubtitlesFile = [self getVideoWithSubtitlesPath]; - - if (player != nil) { - [player removeAllItems]; - } - - NSLog(@"Testing SUBTITLE burning\n"); - - [self showProgressDialog:@"Creating video\n\n"]; - - NSString* ffmpegCommand = [Video generateVideoEncodeScript:image1:image2:image3:videoFile:@"mpeg4":@""]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - - self->state = CreatingState; - - sessionId = [[FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); - - addUIAction(^{ - [self hideProgressDialog]; - }); - - if ([ReturnCode isSuccess:[session getReturnCode]]) { - NSLog(@"Create completed successfully; burning subtitles.\n"); - - NSString *burnSubtitlesCommand = [NSString stringWithFormat:@"-hide_banner -y -i %@ -vf subtitles=%@:force_style='FontName=MyFontName' %@", videoFile, subtitle, videoWithSubtitlesFile]; - - addUIAction(^{ - [self showProgressDialog:@"Burning subtitles\n\n"]; - }); - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", burnSubtitlesCommand); - - self->state = BurningState; - - [FFmpegKit executeAsync:burnSubtitlesCommand withExecuteCallback:^(id secondSession) { - - addUIAction(^{ - [self hideProgressDialog]; - - if ([ReturnCode isSuccess:[secondSession getReturnCode]]) { - NSLog(@"Burn subtitles completed successfully; playing video.\n"); - [self playVideo]; - } else if ([ReturnCode isCancel:[secondSession getReturnCode]]) { - NSLog(@"Burn subtitles operation cancelled\n"); - [self->indicator stopAnimating]; - [Util alert:self withTitle:@"Error" message:@"Burn subtitles operation cancelled." andButtonText:@"OK"]; - } else { - NSLog(@"Burn subtitles failed with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[secondSession getState]], [secondSession getReturnCode], notNull([secondSession getFailStackTrace], @"\n")); - - dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1.3 * NSEC_PER_SEC); - dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ - [self hideProgressDialogAndAlert:@"Burn subtitles failed. Please check logs for the details."]; - }); - } - }); - }]; - } - }] getSessionId]; - - NSLog(@"Async FFmpeg process started with sessionId %ld.\n", sessionId); -} - -- (void)playVideo { - NSString *videoWithSubtitlesFile = [self getVideoWithSubtitlesPath]; - NSURL*videoWithSubtitlesURL=[NSURL fileURLWithPath:videoWithSubtitlesFile]; - - AVAsset *asset = [AVAsset assetWithURL:videoWithSubtitlesURL]; - NSArray *assetKeys = @[@"playable", @"hasProtectedContent"]; - - AVPlayerItem *newVideo = [AVPlayerItem playerItemWithAsset:asset - automaticallyLoadedAssetKeys:assetKeys]; - - [player insertItem:newVideo afterItem:nil]; - [player play]; -} - -- (NSString*)getSubtitlePath { - NSString *resourceFolder = [[NSBundle mainBundle] resourcePath]; - return [resourceFolder stringByAppendingPathComponent: @"subtitle.srt"]; -} - -- (NSString*)getVideoPath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"video.mp4"]; -} - -- (NSString*)getVideoWithSubtitlesPath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"video-with-subtitles.mp4"]; -} - -- (void)setActive { - NSLog(@"Subtitle Tab Activated"); - [self enableLogCallback]; - [self enableStatisticsCallback]; -} - -- (void)showProgressDialog:(NSString*) dialogMessage { - - // CLEAN STATISTICS - statistics = nil; - - alertController = [UIAlertController alertControllerWithTitle:nil - message:dialogMessage - preferredStyle:UIAlertControllerStyleAlert]; - indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - indicator.color = [UIColor blackColor]; - indicator.translatesAutoresizingMaskIntoConstraints=NO; - [alertController.view addSubview:indicator]; - NSDictionary * views = @{@"pending" : alertController.view, @"indicator" : indicator}; - - UIAlertAction* cancelAction = [UIAlertAction - actionWithTitle:@"CANCEL" - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - if (self->state == CreatingState) { - if (self->sessionId != 0) { - [FFmpegKit cancel:self->sessionId]; - } - } else if (self->state == BurningState) { - [FFmpegKit cancel]; - } - }]; - [alertController addAction:cancelAction]; - - NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[indicator]-(56)-|" options:0 metrics:nil views:views]; - NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[indicator]|" options:0 metrics:nil views:views]; - NSArray * constraints = [constraintsVertical arrayByAddingObjectsFromArray:constraintsHorizontal]; - [alertController.view addConstraints:constraints]; - [indicator startAnimating]; - [self presentViewController:alertController animated:YES completion:nil]; -} - -- (void)updateProgressDialog { - if (statistics == nil) { - return; - } - - if (alertController != nil) { - int timeInMilliseconds = [statistics getTime]; - if (timeInMilliseconds > 0) { - int totalVideoDuration = 9000; - - int percentage = timeInMilliseconds*100/totalVideoDuration; - - if (state == CreatingState) { - [alertController setMessage:[NSString stringWithFormat:@"Creating video %% %d \n\n", percentage]]; - } else if (state == BurningState) { - [alertController setMessage:[NSString stringWithFormat:@"Burning subtitles %% %d \n\n", percentage]]; - } - } - } -} - -- (void)hideProgressDialog { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:nil]; -} - -- (void)hideProgressDialogAndAlert: (NSString*)message { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:^{ - [Util alert:self withTitle:@"Error" message:message andButtonText:@"OK"]; - }]; -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/TabBarController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/TabBarController.h deleted file mode 100644 index 81669a2..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/TabBarController.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -@interface TabBarController : UITabBarController - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/TabBarController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/TabBarController.m deleted file mode 100644 index fbaea99..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/TabBarController.m +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "TabBarController.h" -#include "CommandViewController.h" -#include "VideoViewController.h" -#include "HttpsViewController.h" -#include "AudioViewController.h" -#include "SubtitleViewController.h" -#include "VidStabViewController.h" -#include "PipeViewController.h" -#include "ConcurrentExecutionViewController.h" -#include "OtherViewController.h" - -@interface TabBarController () - -@end - -@implementation TabBarController - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.delegate = self; -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (void)tabBarController: (UITabBarController *)tabBarController didSelectViewController: (UIViewController *)viewController { - - if ([viewController isKindOfClass:[CommandViewController class]]) { - CommandViewController* commandView = (CommandViewController*)viewController; - [commandView setActive]; - } else if ([viewController isKindOfClass:[VideoViewController class]]) { - VideoViewController* videoView = (VideoViewController*)viewController; - [videoView setActive]; - } else if ([viewController isKindOfClass:[HttpsViewController class]]) { - HttpsViewController* httpsView = (HttpsViewController*)viewController; - [httpsView setActive]; - } else if ([viewController isKindOfClass:[AudioViewController class]]) { - AudioViewController* audioView = (AudioViewController*)viewController; - [audioView setActive]; - } else if ([viewController isKindOfClass:[SubtitleViewController class]]) { - SubtitleViewController* subtitleView = (SubtitleViewController*)viewController; - [subtitleView setActive]; - } else if ([viewController isKindOfClass:[VidStabViewController class]]) { - VidStabViewController* vidStabView = (VidStabViewController*)viewController; - [vidStabView setActive]; - } else if ([viewController isKindOfClass:[PipeViewController class]]) { - PipeViewController* pipeView = (PipeViewController*)viewController; - [pipeView setActive]; - } else if ([viewController isKindOfClass:[ConcurrentExecutionViewController class]]) { - ConcurrentExecutionViewController* concurrentExecutionView = (ConcurrentExecutionViewController*)viewController; - [concurrentExecutionView setActive]; - } else if ([viewController isKindOfClass:[OtherViewController class]]) { - OtherViewController* otherView = (OtherViewController*)viewController; - [otherView setActive]; - } -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Util.h b/ios/test-app-local-universal-library/FFmpegKitIOS/Util.h deleted file mode 100644 index 4d976ff..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Util.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef FFMPEG_KIT_TEST_UTIL -#define FFMPEG_KIT_TEST_UTIL - -#include -#include - -extern NSString* notNull(NSString* string, NSString* valuePrefix); - -typedef void (^AsyncUpdateUIBlock)(void); - -extern void addUIAction(AsyncUpdateUIBlock asyncUpdateUIBlock); - -@interface Util : NSObject - -+ (void)applyButtonStyle: (UIButton*) button; -+ (void)applyEditTextStyle: (UITextField*) textField; -+ (void)applyHeaderStyle: (UILabel*) label; -+ (void)applyOutputTextStyle: (UITextView*) textView; -+ (void)applyPickerViewStyle: (UIPickerView*) pickerView; -+ (void)applyVideoPlayerFrameStyle: (UILabel*) playerFrame; -+ (void)alert: (UIViewController*)controller withTitle:(NSString*)title message:(NSString*)message andButtonText:(NSString*)buttonText; - -@end - -#endif /* FFMPEG_KIT_TEST_UTIL */ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Util.m b/ios/test-app-local-universal-library/FFmpegKitIOS/Util.m deleted file mode 100644 index 53a5c68..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Util.m +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "Util.h" - -NSString* notNull(NSString* string, NSString* valuePrefix) { - return (string == nil) ? @"" : [NSString stringWithFormat:@"%@%@", valuePrefix, string]; -} - -void addUIAction(AsyncUpdateUIBlock asyncUpdateUIBlock) { - dispatch_async(dispatch_get_main_queue(), ^{ - asyncUpdateUIBlock(); - }); -} - -@implementation Util - -+ (void)applyButtonStyle: (UIButton*) button { - button.tintColor = [UIColor whiteColor]; - [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - button.layer.backgroundColor = [UIColor colorWithDisplayP3Red:46.0/256 green:204.0/256 blue:113.0/256 alpha:1.0].CGColor; - button.layer.borderWidth = 1.0f; - button.layer.borderColor = [UIColor colorWithDisplayP3Red:39.0/256 green:174.0/256 blue:96.0/256 alpha:1.0].CGColor; - button.layer.cornerRadius = 5.0f; -} - -+ (void)applyEditTextStyle: (UITextField*) textField { - textField.layer.borderWidth = 1.0f; - textField.layer.borderColor = [UIColor colorWithDisplayP3Red:52.0/256 green:152.0/256 blue:219.0/256 alpha:1.0].CGColor; - textField.layer.cornerRadius = 5.0f; -} - -+ (void)applyHeaderStyle: (UILabel*) label { - label.layer.borderWidth = 1.0f; - label.layer.borderColor = [UIColor colorWithDisplayP3Red:231.0/256 green:76.0/256 blue:60.0/256 alpha:1.0].CGColor; - label.layer.cornerRadius = 5.0f; -} - -+ (void)applyOutputTextStyle: (UITextView*) textView { - textView.layer.backgroundColor = [UIColor colorWithDisplayP3Red:241.0/256 green:196.0/256 blue:15.0/256 alpha:1.0].CGColor; - textView.layer.borderWidth = 1.0f; - textView.layer.borderColor = [UIColor colorWithDisplayP3Red:243.0/256 green:156.0/256 blue:18.0/256 alpha:1.0].CGColor; - textView.layer.cornerRadius = 5.0f; -} - -+ (void)applyPickerViewStyle: (UIPickerView*) pickerView { - pickerView.layer.backgroundColor = [UIColor colorWithDisplayP3Red:155.0/256 green:89.0/256 blue:182.0/256 alpha:1.0].CGColor; - pickerView.layer.borderWidth = 1.0f; - pickerView.layer.borderColor = [UIColor colorWithDisplayP3Red:142.0/256 green:68.0/256 blue:173.0/256 alpha:1.0].CGColor; - pickerView.layer.cornerRadius = 5.0f; -} - -+ (void)applyVideoPlayerFrameStyle: (UILabel*) playerFrame { - playerFrame.layer.backgroundColor = [UIColor colorWithDisplayP3Red:236.0/256 green:240.0/256 blue:241.0/256 alpha:1.0].CGColor; - playerFrame.layer.borderWidth = 1.0f; - playerFrame.layer.borderColor = [UIColor colorWithDisplayP3Red:185.0/256 green:195.0/256 blue:199.0/256 alpha:1.0].CGColor; - playerFrame.layer.cornerRadius = 5.0f; -} - -+ (void)alert: (UIViewController*)controller withTitle:(NSString*)title message:(NSString*)message andButtonText:(NSString*)buttonText { - UIAlertController* alert = [UIAlertController - alertControllerWithTitle:title - message:message - preferredStyle:UIAlertControllerStyleAlert]; - - UIAlertAction* defaultAction = [UIAlertAction - actionWithTitle:buttonText style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) {}]; - - [alert addAction:defaultAction]; - [controller presentViewController:alert animated:YES completion:nil]; -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/VidStabViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/VidStabViewController.h deleted file mode 100644 index 3f24da9..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/VidStabViewController.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface VidStabViewController : UIViewController - -- (void)setActive; - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/VidStabViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/VidStabViewController.m deleted file mode 100644 index 1257e61..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/VidStabViewController.m +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include "VidStabViewController.h" -#include "Video.h" - -@interface VidStabViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (strong, nonatomic) IBOutlet UIButton *stabilizeVideoButton; -@property (strong, nonatomic) IBOutlet UILabel *videoPlayerFrame; -@property (strong, nonatomic) IBOutlet UILabel *stabilizedVideoPlayerFrame; - -@end - -@implementation VidStabViewController { - - // Video player references - AVQueuePlayer *player; - AVPlayerLayer *playerLayer; - AVQueuePlayer *stabilizedVideoPlayer; - AVPlayerLayer *stabilizedVideoPlayerLayer; - - // Loading view - UIActivityIndicatorView* indicator; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // STYLE UPDATE - [Util applyButtonStyle: self.stabilizeVideoButton]; - [Util applyVideoPlayerFrameStyle: self.videoPlayerFrame]; - [Util applyVideoPlayerFrameStyle: self.stabilizedVideoPlayerFrame]; - [Util applyHeaderStyle: self.header]; - - // VIDEO PLAYER INIT - player = [[AVQueuePlayer alloc] init]; - playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; - stabilizedVideoPlayer = [[AVQueuePlayer alloc] init]; - stabilizedVideoPlayerLayer = [AVPlayerLayer playerLayerWithPlayer:stabilizedVideoPlayer]; - - // SETTING VIDEO FRAME POSITIONS, RANDOMLY (?) - [self.stabilizedVideoPlayerFrame setFrame:CGRectMake(20, 20, self.view.bounds.size.width - 40, self.view.bounds.size.height/4)]; - - CGRect upperRectangularFrame = self.view.bounds; - upperRectangularFrame.size.width = self.stabilizedVideoPlayerFrame.bounds.size.width; - upperRectangularFrame.size.height = self.stabilizedVideoPlayerFrame.bounds.size.height - 4; - upperRectangularFrame.origin.x = 0; - upperRectangularFrame.origin.y = self.view.bounds.size.height/100 - 4; - - playerLayer.frame = upperRectangularFrame; - playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; - [self.videoPlayerFrame.layer addSublayer:playerLayer]; - - CGRect lowerRectangularFrame = self.view.bounds; - lowerRectangularFrame.size.width = self.stabilizedVideoPlayerFrame.bounds.size.width; - lowerRectangularFrame.size.height = self.stabilizedVideoPlayerFrame.bounds.size.height + 4; - lowerRectangularFrame.origin.x = 0; - lowerRectangularFrame.origin.y = self.view.bounds.size.height/50 - 4; - - stabilizedVideoPlayerLayer.frame = lowerRectangularFrame; - stabilizedVideoPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect; - [self.stabilizedVideoPlayerFrame.layer addSublayer:stabilizedVideoPlayerLayer]; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -- (void)enableLogCallback { - [FFmpegKitConfig enableLogCallback: ^(Log* log){ - NSLog(@"%@", [log getMessage]); - }]; -} - -- (IBAction)stabilizedVideo:(id)sender { - NSString *resourceFolder = [[NSBundle mainBundle] resourcePath]; - NSString *image1 = [resourceFolder stringByAppendingPathComponent: @"machupicchu.jpg"]; - NSString *image2 = [resourceFolder stringByAppendingPathComponent: @"pyramid.jpg"]; - NSString *image3 = [resourceFolder stringByAppendingPathComponent: @"stonehenge.jpg"]; - NSString *shakeResultsFile = [self getShakeResultsFilePath]; - NSString *videoFile = [self getVideoPath]; - NSString *stabilizedVideoFile = [self getStabilizedVideoPath]; - - if (player != nil) { - [player removeAllItems]; - } - if (stabilizedVideoPlayer != nil) { - [stabilizedVideoPlayer removeAllItems]; - } - - [[NSFileManager defaultManager] removeItemAtPath:shakeResultsFile error:NULL]; - [[NSFileManager defaultManager] removeItemAtPath:videoFile error:NULL]; - [[NSFileManager defaultManager] removeItemAtPath:stabilizedVideoFile error:NULL]; - - NSLog(@"Testing VID.STAB\n"); - - [self showProgressDialog:@"Creating video\n\n"]; - - NSString* ffmpegCommand = [Video generateShakingVideoScript:image1:image2:image3:videoFile]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); - - addUIAction(^{ - [self hideProgressDialog]; - }); - - if ([ReturnCode isSuccess:[session getReturnCode]]) { - NSLog(@"Create completed successfully; stabilizing video.\n"); - - NSString *analyzeVideoCommand = [NSString stringWithFormat:@"-hide_banner -y -i %@ -vf vidstabdetect=shakiness=10:accuracy=15:result=%@ -f null -", videoFile, shakeResultsFile]; - - addUIAction(^{ - [self showProgressDialog:@"Stabilizing video\n\n"]; - }); - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", analyzeVideoCommand); - - [FFmpegKit executeAsync:analyzeVideoCommand withExecuteCallback:^(id secondSession) { - - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[secondSession getState]], [secondSession getReturnCode], notNull([secondSession getFailStackTrace], @"\n")); - - if ([ReturnCode isSuccess:[secondSession getReturnCode]]) { - - NSString *stabilizeVideoCommand = [NSString stringWithFormat:@"-hide_banner -y -i %@ -vf vidstabtransform=smoothing=30:input=%@ %@", videoFile, shakeResultsFile, stabilizedVideoFile]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", stabilizeVideoCommand); - - [FFmpegKit executeAsync:stabilizeVideoCommand withExecuteCallback:^(id thirdSession) { - - NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[thirdSession getState]], [thirdSession getReturnCode], notNull([thirdSession getFailStackTrace], @"\n")); - - addUIAction(^{ - [self hideProgressDialog]; - - if ([ReturnCode isSuccess:[thirdSession getReturnCode]]) { - NSLog(@"Stabilize video completed successfully; playing videos.\n"); - [self playVideo]; - [self playStabilizedVideo]; - } else { - [self hideProgressDialogAndAlert:@"Stabilize video failed. Please check logs for the details."]; - } - }); - }]; - } else { - dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 1.3 * NSEC_PER_SEC); - dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ - [self hideProgressDialogAndAlert:@"Stabilize video failed. Please check logs for the details."]; - }); - } - }]; - } else { - addUIAction(^{ - [self hideProgressDialogAndAlert:@"Create video failed. Please check logs for the details."]; - }); - } - }]; -} - -- (void)playVideo { - NSString *videoFile = [self getVideoPath]; - NSURL*videoURL=[NSURL fileURLWithPath:videoFile]; - AVAsset *asset = [AVAsset assetWithURL:videoURL]; - NSArray *assetKeys = @[@"playable", @"hasProtectedContent"]; - AVPlayerItem *video = [AVPlayerItem playerItemWithAsset:asset - automaticallyLoadedAssetKeys:assetKeys]; - - [player insertItem:video afterItem:nil]; - [player play]; -} - -- (void)playStabilizedVideo { - NSString *stabilizedVideoFile = [self getStabilizedVideoPath]; - NSURL*stabilizedVideoURL=[NSURL fileURLWithPath:stabilizedVideoFile]; - AVAsset *asset = [AVAsset assetWithURL:stabilizedVideoURL]; - NSArray *assetKeys = @[@"playable", @"hasProtectedContent"]; - AVPlayerItem *stabilizedVideo = [AVPlayerItem playerItemWithAsset:asset - automaticallyLoadedAssetKeys:assetKeys]; - - [stabilizedVideoPlayer insertItem:stabilizedVideo afterItem:nil]; - [stabilizedVideoPlayer play]; -} - -- (NSString*)getShakeResultsFilePath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"transforms.trf"]; -} - -- (NSString*)getVideoPath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"video.mp4"]; -} - -- (NSString*)getStabilizedVideoPath { - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [docFolder stringByAppendingPathComponent: @"video-stabilized.mp4"]; -} - -- (void)setActive { - NSLog(@"VidStab Tab Activated"); - [FFmpegKitConfig enableLogCallback:^(Log *log){ - NSLog(@"%@", [log getMessage]); - }]; -} - -- (void)showProgressDialog:(NSString*) dialogMessage { - UIAlertController *pending = [UIAlertController alertControllerWithTitle:nil - message:dialogMessage - preferredStyle:UIAlertControllerStyleAlert]; - indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - indicator.color = [UIColor blackColor]; - indicator.translatesAutoresizingMaskIntoConstraints=NO; - [pending.view addSubview:indicator]; - NSDictionary * views = @{@"pending" : pending.view, @"indicator" : indicator}; - - NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[indicator]-(20)-|" options:0 metrics:nil views:views]; - NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[indicator]|" options:0 metrics:nil views:views]; - NSArray * constraints = [constraintsVertical arrayByAddingObjectsFromArray:constraintsHorizontal]; - [pending.view addConstraints:constraints]; - [indicator startAnimating]; - [self presentViewController:pending animated:YES completion:nil]; -} - -- (void)hideProgressDialog { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:nil]; -} - -- (void)hideProgressDialogAndAlert: (NSString*)message { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:^{ - [Util alert:self withTitle:@"Error" message:message andButtonText:@"OK"]; - }]; -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Video.h b/ios/test-app-local-universal-library/FFmpegKitIOS/Video.h deleted file mode 100644 index 7aa0a6c..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Video.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef FFMPEG_KIT_TEST_VIDEO -#define FFMPEG_KIT_TEST_VIDEO - -#include - -@interface Video : NSObject - -+ (NSString*)generateCreateVideoWithPipesScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile; - -+ (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions; - -+ (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile; - -@end - -#endif /* FFMPEG_KIT_TEST_VIDEO */ diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/Video.m b/ios/test-app-local-universal-library/FFmpegKitIOS/Video.m deleted file mode 100644 index 0778874..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/Video.m +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#import "Video.h" - -@implementation Video - -+ (NSString*)generateCreateVideoWithPipesScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile { - return [NSString stringWithFormat: -@"-hide_banner -y -i %@ \ --i %@ \ --i %@ \ --filter_complex \"\ -[0:v]loop=loop=-1:size=1:start=0,setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,split=2[stream1out1][stream1out2];\ -[1:v]loop=loop=-1:size=1:start=0,setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,split=2[stream2out1][stream2out2];\ -[2:v]loop=loop=-1:size=1:start=0,setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,split=2[stream3out1][stream3out2];\ -[stream1out1]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=3,select=lte(n\\,90)[stream1overlaid];\ -[stream1out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30),fade=t=out:s=0:n=30[stream1fadeout];\ -[stream2out1]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=2,select=lte(n\\,60)[stream2overlaid];\ -[stream2out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30),split=2[stream2starting][stream2ending];\ -[stream3out1]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=2,select=lte(n\\,60)[stream3overlaid];\ -[stream3out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30),fade=t=in:s=0:n=30[stream3fadein];\ -[stream2starting]fade=t=in:s=0:n=30[stream2fadein];\ -[stream2ending]fade=t=out:s=0:n=30[stream2fadeout];\ -[stream2fadein][stream1fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream2blended];\ -[stream3fadein][stream2fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream3blended];\ -[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\" \ --map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 %@", image1, image2, image3, videoFile]; -} - -+ (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions { - return [NSString stringWithFormat: -@"-hide_banner -y -loop 1 -i %@ \ --loop 1 -i %@ \ --loop 1 -i %@ \ --filter_complex \"\ -[0:v]setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,split=2[stream1out1][stream1out2];\ -[1:v]setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,split=2[stream2out1][stream2out2];\ -[2:v]setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1,split=2[stream3out1][stream3out2];\ -[stream1out1]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=3,select=lte(n\\,90)[stream1overlaid];\ -[stream1out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30),fade=t=out:s=0:n=30[stream1fadeout];\ -[stream2out1]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=2,select=lte(n\\,60)[stream2overlaid];\ -[stream2out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30),split=2[stream2starting][stream2ending];\ -[stream3out1]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=2,select=lte(n\\,60)[stream3overlaid];\ -[stream3out2]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=1,select=lte(n\\,30),fade=t=in:s=0:n=30[stream3fadein];\ -[stream2starting]fade=t=in:s=0:n=30[stream2fadein];\ -[stream2ending]fade=t=out:s=0:n=30[stream2fadeout];\ -[stream2fadein][stream1fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream2blended];\ -[stream3fadein][stream2fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream3blended];\ -[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\" \ --map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, customOptions, videoCodec, videoFile]; -} - -+ (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile { - return [NSString stringWithFormat: -@"-hide_banner -y -loop 1 -i %@ \ --loop 1 -i %@ \ --loop 1 -i %@ \ --f lavfi -i color=black:s=640x427 \ --filter_complex \"\ -[0:v]setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1[stream1out];\ -[1:v]setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1[stream2out];\ -[2:v]setpts=PTS-STARTPTS,scale=w=\'if(gte(iw/ih,640/427),min(iw,640),-1)\':h=\'if(gte(iw/ih,640/427),-1,min(ih,427))\',scale=trunc(iw/2)*2:trunc(ih/2)*2,setsar=sar=1/1[stream3out];\ -[stream1out]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=3[stream1overlaid];\ -[stream2out]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=3[stream2overlaid];\ -[stream3out]pad=width=640:height=427:x=(640-iw)/2:y=(427-ih)/2:color=#00000000,trim=duration=3[stream3overlaid];\ -[3:v][stream1overlaid]overlay=x=\'2*mod(n,4)\':y=\'2*mod(n,2)\',trim=duration=3[stream1shaking];\ -[3:v][stream2overlaid]overlay=x=\'2*mod(n,4)\':y=\'2*mod(n,2)\',trim=duration=3[stream2shaking];\ -[3:v][stream3overlaid]overlay=x=\'2*mod(n,4)\':y=\'2*mod(n,2)\',trim=duration=3[stream3shaking];\ -[stream1shaking][stream2shaking][stream3shaking]concat=n=3:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\" \ --map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 %@", image1, image2, image3, videoFile]; -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/VideoViewController.h b/ios/test-app-local-universal-library/FFmpegKitIOS/VideoViewController.h deleted file mode 100644 index d9c59aa..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/VideoViewController.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include "Constants.h" -#include "Util.h" - -@interface VideoViewController : UIViewController - -- (void)setActive; - -@end - diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/VideoViewController.m b/ios/test-app-local-universal-library/FFmpegKitIOS/VideoViewController.m deleted file mode 100644 index 9a30490..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/VideoViewController.m +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include "VideoViewController.h" -#include "Video.h" - -@interface VideoViewController () - -@property (strong, nonatomic) IBOutlet UILabel *header; -@property (strong, nonatomic) IBOutlet UIPickerView *videoCodecPicker; -@property (strong, nonatomic) IBOutlet UIButton *encodeButton; -@property (strong, nonatomic) IBOutlet UILabel *videoPlayerFrame; - -@end - -@implementation VideoViewController { - - // Video codec data - NSArray *codecData; - NSInteger selectedCodec; - - // Video player references - AVQueuePlayer *player; - AVPlayerLayer *playerLayer; - AVPlayerItem *activeItem; - - // Loading view - UIAlertController *alertController; - UIActivityIndicatorView* indicator; - - Statistics *statistics; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - // VIDEO CODEC PICKER INIT - codecData = @[@"mpeg4", @"h264 (x264)", @"h264 (openh264)", @"h264 (videotoolbox)", @"x265", @"xvid", @"vp8", @"vp9", @"aom", @"kvazaar", @"theora", @"hap"]; - selectedCodec = 0; - - self.videoCodecPicker.dataSource = self; - self.videoCodecPicker.delegate = self; - - // STYLE UPDATE - [Util applyButtonStyle: self.encodeButton]; - [Util applyPickerViewStyle: self.videoCodecPicker]; - [Util applyVideoPlayerFrameStyle: self.videoPlayerFrame]; - [Util applyHeaderStyle: self.header]; - - // VIDEO PLAYER INIT - player = [[AVQueuePlayer alloc] init]; - playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; - activeItem = nil; - - CGRect rectangularFrame = self.view.layer.bounds; - rectangularFrame.size.width = self.view.layer.bounds.size.width - 40; - rectangularFrame.origin.x = 20; - rectangularFrame.origin.y = self.encodeButton.layer.bounds.origin.y + 120; - - playerLayer.frame = rectangularFrame; - [self.view.layer addSublayer:playerLayer]; - - alertController = nil; - statistics = nil; - - addUIAction(^{ - [self setActive]; - }); -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -/** - * The number of columns of data - */ -- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { - return 1; -} - -/** - * The number of rows of data - */ -- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { - return codecData.count; -} - -/** - * The data to return for the row and component (column) that's being passed in - */ -- (NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { - return codecData[row]; -} - -- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { - selectedCodec = row; -} - -- (IBAction)encodeVideo:(id)sender { - NSString *resourceFolder = [[NSBundle mainBundle] resourcePath]; - NSString *image1 = [resourceFolder stringByAppendingPathComponent: @"machupicchu.jpg"]; - NSString *image2 = [resourceFolder stringByAppendingPathComponent: @"pyramid.jpg"]; - NSString *image3 = [resourceFolder stringByAppendingPathComponent: @"stonehenge.jpg"]; - NSString *videoFile = [self getVideoPath]; - - if (player != nil) { - [player removeAllItems]; - activeItem = nil; - } - - [[NSFileManager defaultManager] removeItemAtPath:videoFile error:NULL]; - - NSString *videoCodec = codecData[selectedCodec]; - - NSLog(@"Testing VIDEO encoding with '%@' codec\n", videoCodec); - - [self showProgressDialog:@"Encoding video\n\n"]; - - NSString* ffmpegCommand = [Video generateVideoEncodeScript:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getCustomOptions]]; - - NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session){ - SessionState state = [session getState]; - ReturnCode *returnCode = [session getReturnCode]; - - addUIAction(^{ - [self hideProgressDialog]; - }); - - if ([ReturnCode isSuccess:returnCode]) { - NSLog(@"Encode completed successfully in %ld milliseconds; playing video.\n", [session getDuration]); - addUIAction(^{ - [self playVideo]; - }); - } else { - NSLog(@"Encode failed with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - addUIAction(^{ - [self hideProgressDialogAndAlert:@"Encode failed. Please check logs for the details."]; - }); - } - } withLogCallback:^(Log *log) { - NSLog(@"%@", [log getMessage]); - } withStatisticsCallback:^(Statistics *statistics) { - addUIAction(^{ - self->statistics = statistics; - [self updateProgressDialog]; - }); - }]; - - NSLog(@"Async FFmpeg process started with sessionId %ld.\n", [session getSessionId]); -} - -- (void)playVideo { - NSString *videoFile = [self getVideoPath]; - NSURL*videoURL=[NSURL fileURLWithPath:videoFile]; - - AVAsset *asset = [AVAsset assetWithURL:videoURL]; - NSArray *assetKeys = @[@"playable", @"hasProtectedContent"]; - - AVPlayerItem *newVideo = [AVPlayerItem playerItemWithAsset:asset - automaticallyLoadedAssetKeys:assetKeys]; - - NSKeyValueObservingOptions options = - NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew; - - activeItem = newVideo; - - [newVideo addObserver:self forKeyPath:@"status" options:options context:nil]; - - [player insertItem:newVideo afterItem:nil]; -} - -- (NSString*)getSelectedVideoCodec { - NSString *videoCodec = codecData[selectedCodec]; - - // VIDEO CODEC PICKER HAS BASIC NAMES, FFMPEG NEEDS LONGER AND EXACT CODEC NAMES. - // APPLYING NECESSARY TRANSFORMATION HERE - if ([videoCodec isEqualToString:@"h264 (x264)"]) { - videoCodec = @"libx264"; - } else if ([videoCodec isEqualToString:@"h264 (openh264)"]) { - videoCodec = @"libopenh264"; - } else if ([videoCodec isEqualToString:@"h264 (videotoolbox)"]) { - videoCodec = @"h264_videotoolbox"; - } else if ([videoCodec isEqualToString:@"x265"]) { - videoCodec = @"libx265"; - } else if ([videoCodec isEqualToString:@"xvid"]) { - videoCodec = @"libxvid"; - } else if ([videoCodec isEqualToString:@"vp8"]) { - videoCodec = @"libvpx"; - } else if ([videoCodec isEqualToString:@"vp9"]) { - videoCodec = @"libvpx-vp9"; - } else if ([videoCodec isEqualToString:@"aom"]) { - videoCodec = @"libaom-av1"; - } else if ([videoCodec isEqualToString:@"kvazaar"]) { - videoCodec = @"libkvazaar"; - } else if ([videoCodec isEqualToString:@"theora"]) { - videoCodec = @"libtheora"; - } - - return videoCodec; -} - -- (NSString*)getVideoPath { - NSString *videoCodec = codecData[selectedCodec]; - - NSString *extension; - if ([videoCodec isEqualToString:@"vp8"] || [videoCodec isEqualToString:@"vp9"]) { - extension = @"webm"; - } else if ([videoCodec isEqualToString:@"aom"]) { - extension = @"mkv"; - } else if ([videoCodec isEqualToString:@"theora"]) { - extension = @"ogv"; - } else if ([videoCodec isEqualToString:@"hap"]) { - extension = @"mov"; - } else { - - // mpeg4, x264, x265, xvid, kvazaar - extension = @"mp4"; - } - - NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - return [[docFolder stringByAppendingPathComponent: @"video."] stringByAppendingString: extension]; -} - -- (NSString*)getCustomOptions { - NSString *videoCodec = codecData[selectedCodec]; - - if ([videoCodec isEqualToString:@"x265"]) { - return @"-crf 28 -preset fast "; - } else if ([videoCodec isEqualToString:@"vp8"]) { - return @"-b:v 1M -crf 10 "; - } else if ([videoCodec isEqualToString:@"vp9"]) { - return @"-b:v 2M "; - } else if ([videoCodec isEqualToString:@"aom"]) { - return @"-crf 30 -strict experimental "; - } else if ([videoCodec isEqualToString:@"theora"]) { - return @"-qscale:v 7 "; - } else if ([videoCodec isEqualToString:@"hap"]) { - return @"-format hap_q "; - } else { - return @""; - } -} - -- (void)setActive { - NSLog(@"Video Tab Activated"); - [FFmpegKitConfig enableLogCallback:nil]; - [FFmpegKitConfig enableStatisticsCallback:nil]; -} - -- (void)showProgressDialog:(NSString*) dialogMessage { - - // CLEAN STATISTICS - statistics = nil; - - alertController = [UIAlertController alertControllerWithTitle:nil - message:dialogMessage - preferredStyle:UIAlertControllerStyleAlert]; - indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - indicator.color = [UIColor blackColor]; - indicator.translatesAutoresizingMaskIntoConstraints=NO; - [alertController.view addSubview:indicator]; - NSDictionary * views = @{@"pending" : alertController.view, @"indicator" : indicator}; - - NSArray * constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[indicator]-(20)-|" options:0 metrics:nil views:views]; - NSArray * constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[indicator]|" options:0 metrics:nil views:views]; - NSArray * constraints = [constraintsVertical arrayByAddingObjectsFromArray:constraintsHorizontal]; - [alertController.view addConstraints:constraints]; - [indicator startAnimating]; - [self presentViewController:alertController animated:YES completion:nil]; -} - -- (void)updateProgressDialog { - if (statistics == nil) { - return; - } - - if (alertController != nil) { - int timeInMilliseconds = [statistics getTime]; - if (timeInMilliseconds > 0) { - int totalVideoDuration = 9000; - - int percentage = timeInMilliseconds*100/totalVideoDuration; - - [alertController setMessage:[NSString stringWithFormat:@"Encoding video %% %d \n\n", percentage]]; - } - } -} - -- (void)hideProgressDialog { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:nil]; -} - -- (void)hideProgressDialogAndAlert: (NSString*)message { - [indicator stopAnimating]; - [self dismissViewControllerAnimated:TRUE completion:^{ - [Util alert:self withTitle:@"Error" message:message andButtonText:@"OK"]; - }]; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - - NSNumber *statusNumber = change[NSKeyValueChangeNewKey]; - NSInteger status = -1; - if ([statusNumber isKindOfClass:[NSNumber class]]) { - status = statusNumber.integerValue; - } - - switch (status) { - case AVPlayerItemStatusReadyToPlay: { - [player play]; - } break; - case AVPlayerItemStatusFailed: { - if (activeItem != nil && activeItem.error != nil) { - - NSString *message = activeItem.error.localizedFailureReason; - if (message == nil) { - message = activeItem.error.localizedDescription; - } - - [Util alert:self withTitle:@"Player Error" message:message andButtonText:@"OK"]; - } - } break; - default: { - NSLog(@"Status %ld received from player.\n", status); - } - } -} - -@end diff --git a/ios/test-app-local-universal-library/FFmpegKitIOS/main.m b/ios/test-app-local-universal-library/FFmpegKitIOS/main.m deleted file mode 100644 index 48123ad..0000000 --- a/ios/test-app-local-universal-library/FFmpegKitIOS/main.m +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2018-2021 Taner Sener - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include "AppDelegate.h" -#include "MediaInformationParserTest.h" -#include "FFmpegKitTest.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - - // RUN UNIT TESTS BEFORE STARTING THE APPLICATION - testMediaInformationJsonParser(); - testFFmpegKit(); - - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/ios/test-app-local-universal-library/Resources/doppioone_regular.ttf b/ios/test-app-local-universal-library/Resources/doppioone_regular.ttf deleted file mode 100644 index e87361e..0000000 Binary files a/ios/test-app-local-universal-library/Resources/doppioone_regular.ttf and /dev/null differ diff --git a/ios/test-app-local-universal-library/Resources/machupicchu.jpg b/ios/test-app-local-universal-library/Resources/machupicchu.jpg deleted file mode 100644 index f4448e5..0000000 Binary files a/ios/test-app-local-universal-library/Resources/machupicchu.jpg and /dev/null differ diff --git a/ios/test-app-local-universal-library/Resources/pyramid.jpg b/ios/test-app-local-universal-library/Resources/pyramid.jpg deleted file mode 100644 index c25d21d..0000000 Binary files a/ios/test-app-local-universal-library/Resources/pyramid.jpg and /dev/null differ diff --git a/ios/test-app-local-universal-library/Resources/sil_open_font_license.txt b/ios/test-app-local-universal-library/Resources/sil_open_font_license.txt deleted file mode 100644 index 6bbf728..0000000 --- a/ios/test-app-local-universal-library/Resources/sil_open_font_license.txt +++ /dev/null @@ -1,46 +0,0 @@ -Copyright (c) 2011-2012, Julieta Ulanovsky (julieta.ulanovsky@gmail.com), with Reserved Font Names 'Montserrat' -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. - -The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the copyright statement(s). - -"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. - -"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. - -5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/ios/test-app-local-universal-library/Resources/stonehenge.jpg b/ios/test-app-local-universal-library/Resources/stonehenge.jpg deleted file mode 100644 index 9c04861..0000000 Binary files a/ios/test-app-local-universal-library/Resources/stonehenge.jpg and /dev/null differ diff --git a/ios/test-app-local-universal-library/Resources/subtitle.srt b/ios/test-app-local-universal-library/Resources/subtitle.srt deleted file mode 100644 index 262584b..0000000 --- a/ios/test-app-local-universal-library/Resources/subtitle.srt +++ /dev/null @@ -1,11 +0,0 @@ -1 -00:00:00,021 --> 00:00:04,000 -Machu Picchu is a 15th-century Inca citadel, located in the Eastern Cordillera of southern Peru. - -2 -00:00:04,001 --> 00:00:06,927 -大金字塔和哈夫拉金字塔是古埃及最大的金字塔。 - -3 -00:00:06,928 --> 00:00:09,000 -Stonehenge هو نصب ما قبل التاريخ في ويلتشير ، إنجلترا ، على بعد ميلين (3 كم) غرب Amesbury. diff --git a/ios/test-app-local-universal-library/Resources/truenorg.otf b/ios/test-app-local-universal-library/Resources/truenorg.otf deleted file mode 100644 index 82a3952..0000000 Binary files a/ios/test-app-local-universal-library/Resources/truenorg.otf and /dev/null differ diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS.xcodeproj/project.pbxproj b/macos/test-app-cocoapods/FFmpegKitMACOS.xcodeproj/project.pbxproj index ef91d92..fc33d30 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS.xcodeproj/project.pbxproj +++ b/macos/test-app-cocoapods/FFmpegKitMACOS.xcodeproj/project.pbxproj @@ -213,6 +213,7 @@ 34D678B225E2D9BA004564B7 /* Sources */, 34D678B325E2D9BA004564B7 /* Frameworks */, 34D678B425E2D9BA004564B7 /* Resources */, + 5072DE19BD00276A06F8B1AB /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -296,6 +297,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 5072DE19BD00276A06F8B1AB /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FFmpegKitMACOS/Pods-FFmpegKitMACOS-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FFmpegKitMACOS/Pods-FFmpegKitMACOS-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FFmpegKitMACOS/Pods-FFmpegKitMACOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate b/macos/test-app-cocoapods/FFmpegKitMACOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate index 26d0145..2ca87f4 100644 Binary files a/macos/test-app-cocoapods/FFmpegKitMACOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate and b/macos/test-app-cocoapods/FFmpegKitMACOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/AppDelegate.m b/macos/test-app-cocoapods/FFmpegKitMACOS/AppDelegate.m index a350f2e..fbe68c8 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/AppDelegate.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/AppDelegate.m @@ -31,7 +31,7 @@ void uncaughtExceptionHandler(NSException *exception) { @implementation AppDelegate + (void)listFFprobeSessions { - NSArray* ffprobeSessions = [FFprobeKit listSessions]; + NSArray* ffprobeSessions = [FFprobeKit listFFprobeSessions]; NSLog(@"Listing FFprobe sessions.\n"); diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/AudioViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/AudioViewController.m index 4c514f4..0887342 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/AudioViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/AudioViewController.m @@ -128,7 +128,7 @@ - (IBAction)encodeAudio:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/CommandViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/CommandViewController.m index a1110c5..6de1ae6 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/CommandViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/CommandViewController.m @@ -66,13 +66,13 @@ - (IBAction)runFFmpeg:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self.view.window withTitle:@"Error" message:@"Command failed. Please check output for the details." buttonText:@"OK" andHandler:nil]; }); @@ -93,7 +93,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process started with arguments\n'%@'.\n", ffprobeCommand); - FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withExecuteCallback:^(id session) { + FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withCompleteCallback:^(FFprobeSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; @@ -103,7 +103,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self.view.window withTitle:@"Error" message:@"Command failed. Please check output for the details." buttonText:@"OK" andHandler:nil]; }); diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/ConcurrentExecutionViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/ConcurrentExecutionViewController.m index fb9db7e..e758a0c 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/ConcurrentExecutionViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/ConcurrentExecutionViewController.m @@ -115,7 +115,7 @@ - (void)encodeVideo:(int)buttonNumber { NSLog(@"FFmpeg process starting for button %d with arguments\n'%@'.\n", buttonNumber, ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/FFmpegKitTest.m b/macos/test-app-cocoapods/FFmpegKitMACOS/FFmpegKitTest.m index 7531c1f..63e61d0 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/FFmpegKitTest.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/FFmpegKitTest.m @@ -193,9 +193,9 @@ void testParseDoubleQuotesAndEscapesInCommand() { void getSessionIdTest() { NSArray *TEST_ARGUMENTS = [[NSArray alloc] initWithObjects:@"argument1", @"argument2", nil]; - FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; + FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; assert([sessions3 getSessionId] > [sessions2 getSessionId]); assert([sessions3 getSessionId] > [sessions1 getSessionId]); diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/HttpsViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/HttpsViewController.m index 9d85560..8b4ec84 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/HttpsViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/HttpsViewController.m @@ -106,7 +106,7 @@ - (void)runGetMediaInformation:(int)buttonNumber { [self clearOutput]; } - [FFprobeKit getMediaInformationAsync:testUrl withExecuteCallback:[self createNewExecuteCallback]]; + [FFprobeKit getMediaInformationAsync:testUrl withCompleteCallback:[self createNewCompleteCallback]]; } - (void)setActive { @@ -135,11 +135,11 @@ - (NSString*)getRandomTestUrl { } } -- (ExecuteCallback)createNewExecuteCallback { - return ^(id session){ +- (MediaInformationSessionCompleteCallback)createNewCompleteCallback { + return ^(MediaInformationSession* session){ addUIAction(^{ @synchronized (self->outputLock) { - MediaInformation *information = [((MediaInformationSession*) session) getMediaInformation]; + MediaInformation *information = [session getMediaInformation]; if (information == nil) { [self appendOutput:@"Get media information failed\n"]; [self appendOutput:[NSString stringWithFormat:@"State: %@\n", [FFmpegKitConfig sessionStateToString:[session getState]]]]; @@ -165,7 +165,7 @@ - (ExecuteCallback)createNewExecuteCallback { if ([information getTags] != nil) { NSDictionary* tags = [information getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@\n", key, [tags objectForKey:key]]]; } } if ([information getStreams] != nil) { @@ -228,7 +228,35 @@ - (ExecuteCallback)createNewExecuteCallback { if ([stream getTags] != nil) { NSDictionary* tags = [stream getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@\n", key, [tags objectForKey:key]]]; + } + } + } + } + if ([information getChapters] != nil) { + for (Chapter* chapter in [information getChapters]) { + if ([chapter getId] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter id: %@\n", [chapter getId]]]; + } + if ([chapter getTimeBase] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter time base: %@\n", [chapter getTimeBase]]]; + } + if ([chapter getStart] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start: %@\n", [chapter getStart]]]; + } + if ([chapter getStartTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start time: %@\n", [chapter getStartTime]]]; + } + if ([chapter getEnd] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end: %@\n", [chapter getEnd]]]; + } + if ([chapter getEndTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end time: %@\n", [chapter getEndTime]]]; + } + if ([chapter getTags] != nil) { + NSDictionary* tags = [chapter getTags]; + for(NSString *key in [tags allKeys]) { + [self appendOutput:[NSString stringWithFormat:@"Chapter tag: %@:%@\n", key, [tags objectForKey:key]]]; } } } diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/MediaInformationParserTest.m b/macos/test-app-cocoapods/FFmpegKitMACOS/MediaInformationParserTest.m index 27ac684..9282b8a 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/MediaInformationParserTest.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/MediaInformationParserTest.m @@ -75,6 +75,85 @@ static void initTests() { " }\n" " }\n" " ],\n" + " \"chapters\": [\n" + " {\n" + " \"id\": 0,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"end\": 11158238,\n" + " \"end_time\": \"506.042540\",\n" + " \"tags\": {\n" + " \"title\": \"1 Laying Plans - 2 Waging War\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 1,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 11158238,\n" + " \"start_time\": \"506.042540\",\n" + " \"end\": 21433051,\n" + " \"end_time\": \"972.020454\",\n" + " \"tags\": {\n" + " \"title\": \"3 Attack By Stratagem - 4 Tactical Dispositions\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 2,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 21433051,\n" + " \"start_time\": \"972.020454\",\n" + " \"end\": 35478685,\n" + " \"end_time\": \"1609.010658\",\n" + " \"tags\": {\n" + " \"title\": \"5 Energy - 6 Weak Points and Strong\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 3,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 35478685,\n" + " \"start_time\": \"1609.010658\",\n" + " \"end\": 47187043,\n" + " \"end_time\": \"2140.001950\",\n" + " \"tags\": {\n" + " \"title\": \"7 Maneuvering - 8 Variation in Tactics\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 4,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 47187043,\n" + " \"start_time\": \"2140.001950\",\n" + " \"end\": 66635594,\n" + " \"end_time\": \"3022.022404\",\n" + " \"tags\": {\n" + " \"title\": \"9 The Army on the March - 10 Terrain\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 5,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 66635594,\n" + " \"start_time\": \"3022.022404\",\n" + " \"end\": 83768105,\n" + " \"end_time\": \"3799.007029\",\n" + " \"tags\": {\n" + " \"title\": \"11 The Nine Situations\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 6,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 83768105,\n" + " \"start_time\": \"3799.007029\",\n" + " \"end\": 95659008,\n" + " \"end_time\": \"4338.277007\",\n" + " \"tags\": {\n" + " \"title\": \"12 The Attack By Fire - 13 The Use of Spies\"\n" + " }\n" + " }\n" + " ],\n" " \"format\": {\n" " \"filename\": \"sample.mp3\",\n" " \"nb_streams\": 1,\n" @@ -448,6 +527,10 @@ static void initTests() { } +void assertNotNull(NSObject *object) { + assert(object != nil); +} + void assertNumber(NSNumber *expected, NSNumber *real) { if (expected == nil) { assert(real == nil); @@ -501,8 +584,21 @@ void assertAudioStream(StreamInformation *stream, NSNumber *index, NSString *cod assertString(bitrate, [stream getBitrate]); } -void assertNotNull(NSObject *object) { - assert(object != nil); +void assertChapter(Chapter *chapter, NSNumber *id, NSString *timeBase, NSNumber *start, NSString * startTime, NSNumber *end, NSString *endTime) { + assert(chapter != nil); + assertNumber(id, [chapter getId]); + assertString(timeBase, [chapter getTimeBase]); + + assertNumber(start, [chapter getStart]); + assertString(startTime, [chapter getStartTime]); + + assertNumber(end, [chapter getEnd]); + assertString(endTime, [chapter getEndTime]); + + NSDictionary *tags = [chapter getTags]; + assertNotNull(tags); + + assert(1 == [tags count]); } void assertMediaInput(MediaInformation *mediaInformation, NSString *expectedFormat, NSString *expectedFilename) { @@ -579,6 +675,13 @@ void testMediaInformationMp3() { assert(1 == [streams count]); assertAudioStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mp3", @"MP3 (MPEG audio layer 3)", @"44100", @"stereo", @"fltp", @"320000"); + + NSArray *chapters = [mediaInformation getChapters]; + assertNotNull(chapters); + assert(7 == [chapters count]); + + assertChapter([chapters objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"1/22050", [[NSNumber alloc] initWithInt:0], @"0.000000", [[NSNumber alloc] initWithInt:11158238], @"506.042540"); + assertChapter([chapters objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"1/22050", [[NSNumber alloc] initWithInt:11158238], @"506.042540", [[NSNumber alloc] initWithInt:21433051], @"972.020454"); } void testMediaInformationJpg() { diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/OtherViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/OtherViewController.m index 0f21ba0..1e0a993 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/OtherViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/OtherViewController.m @@ -46,7 +46,7 @@ - (void)viewDidLoad { [super viewDidLoad]; // OTHER TEST PICKER INIT - testData = @[@"chromaprint", @"dav1d", @"webp"]; + testData = @[@"chromaprint", @"dav1d", @"webp", @"zscale"]; selectedTest = 0; [self.otherTestComboBox setUsesDataSource:YES]; @@ -102,6 +102,9 @@ - (IBAction)runTest:(id)sender { case 2: [self testWebp]; break; + case 3: + [self testZscale]; + break; } } @@ -115,7 +118,7 @@ -(void)testChromaprint { NSLog(@"Creating audio sample with '%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -127,7 +130,7 @@ -(void)testChromaprint { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", chromaprintCommand); - [FFmpegKit executeAsync:chromaprintCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:chromaprintCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -147,7 +150,7 @@ -(void)testDav1d { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); } withLogCallback:^(Log *log) { addUIAction(^{ @@ -168,7 +171,29 @@ -(void)testWebp { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { + + NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); + + } withLogCallback:^(Log *log) { + addUIAction(^{ + [self appendOutput: [log getMessage]]; + }); + } withStatisticsCallback:nil]; +} + +-(void)testZscale { + NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + NSString *videoFile = [docFolder stringByAppendingPathComponent: @"video.mp4"]; + NSString *zscaledVideoFile = [docFolder stringByAppendingPathComponent: @"video.zscaled.mp4"]; + + NSLog(@"Testing 'zscale' filter with video file created on the Video tab\n"); + + NSString *ffmpegCommand = [Video generateZscaleVideoScript:videoFile:zscaledVideoFile]; + + NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); + + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/PipeViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/PipeViewController.m index cce34e6..1d213ac 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/PipeViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/PipeViewController.m @@ -158,7 +158,7 @@ - (IBAction)createVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/SubtitleViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/SubtitleViewController.m index 112e958..d55092c 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/SubtitleViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/SubtitleViewController.m @@ -115,7 +115,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = CreatingState; - sessionId = [[FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + sessionId = [[FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -136,7 +136,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = BurningState; - [FFmpegKit executeAsync:burnSubtitlesCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:burnSubtitlesCommand withCompleteCallback:^(id secondSession) { addUIAction(^{ [self hideProgressDialog]; diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/VidStabViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/VidStabViewController.m index f319d77..7573e51 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/VidStabViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/VidStabViewController.m @@ -97,7 +97,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); addUIAction(^{ @@ -115,7 +115,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", analyzeVideoCommand); - [FFmpegKit executeAsync:analyzeVideoCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:analyzeVideoCommand withCompleteCallback:^(id secondSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[secondSession getState]], [secondSession getReturnCode], notNull([secondSession getFailStackTrace], @"\n")); @@ -125,7 +125,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", stabilizeVideoCommand); - [FFmpegKit executeAsync:stabilizeVideoCommand withExecuteCallback:^(id thirdSession) { + [FFmpegKit executeAsync:stabilizeVideoCommand withCompleteCallback:^(id thirdSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[thirdSession getState]], [thirdSession getReturnCode], notNull([thirdSession getFailStackTrace], @"\n")); diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/Video.h b/macos/test-app-cocoapods/FFmpegKitMACOS/Video.h index 7aa0a6c..977f2ef 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/Video.h +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/Video.h @@ -31,8 +31,12 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions; ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions; + + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile; ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath; + @end #endif /* FFMPEG_KIT_TEST_VIDEO */ diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/Video.m b/macos/test-app-cocoapods/FFmpegKitMACOS/Video.m index 0778874..f910e28 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/Video.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/Video.m @@ -48,6 +48,10 @@ + (NSString*)generateCreateVideoWithPipesScript:(NSString *)image1 :(NSString *) } + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions { + return [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:videoCodec:@"yuv420p":customOptions]; +} + ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions { return [NSString stringWithFormat: @"-hide_banner -y -loop 1 -i %@ \ -loop 1 -i %@ \ @@ -66,8 +70,8 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :( [stream2ending]fade=t=out:s=0:n=30[stream2fadeout];\ [stream2fadein][stream1fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream2blended];\ [stream3fadein][stream2fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream3blended];\ -[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\" \ --map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, customOptions, videoCodec, videoFile]; +[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=%@[video]\" \ +-map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, pixelFormat, customOptions, videoCodec, videoFile]; } + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile { @@ -90,4 +94,8 @@ + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 : -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 %@", image1, image2, image3, videoFile]; } ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath { + return [NSString stringWithFormat:@"-y -i %@ -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p %@", inputVideoFilePath, outputVideoFilePath]; +} + @end diff --git a/macos/test-app-cocoapods/FFmpegKitMACOS/VideoViewController.m b/macos/test-app-cocoapods/FFmpegKitMACOS/VideoViewController.m index afef16f..df236fe 100644 --- a/macos/test-app-cocoapods/FFmpegKitMACOS/VideoViewController.m +++ b/macos/test-app-cocoapods/FFmpegKitMACOS/VideoViewController.m @@ -126,11 +126,11 @@ - (IBAction)encodeVideo:(id)sender { [self showProgressDialog:@"Encoding video\n\n"]; - NSString* ffmpegCommand = [Video generateVideoEncodeScript:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getCustomOptions]]; + NSString* ffmpegCommand = [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getPixelFormat]:[self getCustomOptions]]; NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session){ + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session){ SessionState state = [session getState]; ReturnCode *returnCode = [session getReturnCode]; @@ -181,6 +181,19 @@ - (void)playVideo { [player insertItem:newVideo afterItem:nil]; } +- (NSString*)getPixelFormat { + NSString *videoCodec = codecData[selectedCodec]; + + NSString *pixelFormat; + if ([videoCodec isEqualToString:@"x265"]) { + pixelFormat = @"yuv420p10le"; + } else { + pixelFormat = @"yuv420p"; + } + + return pixelFormat; +} + - (NSString*)getSelectedVideoCodec { NSString *videoCodec = codecData[selectedCodec]; diff --git a/macos/test-app-cocoapods/Podfile b/macos/test-app-cocoapods/Podfile index 8b43690..663d3c9 100644 --- a/macos/test-app-cocoapods/Podfile +++ b/macos/test-app-cocoapods/Podfile @@ -3,5 +3,5 @@ platform :osx, '10.15' use_frameworks! target "FFmpegKitMACOS" do - pod 'ffmpeg-kit-macos-full', '4.5' + pod 'ffmpeg-kit-macos-full', '4.5.1.LTS' end diff --git a/macos/test-app-cocoapods/Podfile.lock b/macos/test-app-cocoapods/Podfile.lock index 8734890..e1d0d39 100644 --- a/macos/test-app-cocoapods/Podfile.lock +++ b/macos/test-app-cocoapods/Podfile.lock @@ -1,16 +1,16 @@ PODS: - - ffmpeg-kit-macos-full (4.5) + - ffmpeg-kit-macos-full (4.5.1.LTS) DEPENDENCIES: - - ffmpeg-kit-macos-full (= 4.5) + - ffmpeg-kit-macos-full (= 4.5.1.LTS) SPEC REPOS: trunk: - ffmpeg-kit-macos-full SPEC CHECKSUMS: - ffmpeg-kit-macos-full: eeda86a131a618d6291722a0355435d5384868fa + ffmpeg-kit-macos-full: 5db1604b88ada6c73c9da072a6bd09341e97009e -PODFILE CHECKSUM: 903091a1e6e20eff43af71744a5bd86f2086a318 +PODFILE CHECKSUM: f8fc2f038fe6b00cd764172e3d0fcba19e2dd30b COCOAPODS: 1.11.2 diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS.xcodeproj/project.pbxproj b/macos/test-app-local-dependency/FFmpegKitMACOS.xcodeproj/project.pbxproj index ee0af4a..d3277ad 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS.xcodeproj/project.pbxproj +++ b/macos/test-app-local-dependency/FFmpegKitMACOS.xcodeproj/project.pbxproj @@ -3,62 +3,27 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ 340F2ACE25E8597800FAEEFE /* ProgressIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 340F2ACC25E8597800FAEEFE /* ProgressIndicator.m */; }; - 346EB50226F79DA200ECD319 /* libtheoradec.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4CF26F79D9F00ECD319 /* libtheoradec.framework */; }; - 346EB50326F79DA200ECD319 /* libavutil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D026F79D9F00ECD319 /* libavutil.framework */; }; - 346EB50426F79DA200ECD319 /* libswresample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D126F79D9F00ECD319 /* libswresample.framework */; }; - 346EB50526F79DA200ECD319 /* libwebp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D226F79D9F00ECD319 /* libwebp.framework */; }; - 346EB50626F79DA200ECD319 /* twolame.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D326F79D9F00ECD319 /* twolame.framework */; }; - 346EB50726F79DA200ECD319 /* libass.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D426F79D9F00ECD319 /* libass.framework */; }; - 346EB50826F79DA200ECD319 /* libwebpdemux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D526F79D9F00ECD319 /* libwebpdemux.framework */; }; - 346EB50926F79DA200ECD319 /* libavdevice.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D626F79D9F00ECD319 /* libavdevice.framework */; }; - 346EB50A26F79DA200ECD319 /* libswscale.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D726F79DA000ECD319 /* libswscale.framework */; }; - 346EB50B26F79DA200ECD319 /* jpeg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D826F79DA000ECD319 /* jpeg.framework */; }; - 346EB50C26F79DA200ECD319 /* freetype.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4D926F79DA000ECD319 /* freetype.framework */; }; - 346EB50D26F79DA200ECD319 /* libtheora.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4DA26F79DA000ECD319 /* libtheora.framework */; }; - 346EB50E26F79DA200ECD319 /* x264.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4DB26F79DA000ECD319 /* x264.framework */; }; - 346EB50F26F79DA200ECD319 /* fontconfig.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4DC26F79DA000ECD319 /* fontconfig.framework */; }; - 346EB51026F79DA200ECD319 /* gmp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4DD26F79DA000ECD319 /* gmp.framework */; }; - 346EB51126F79DA200ECD319 /* harfbuzz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4DE26F79DA000ECD319 /* harfbuzz.framework */; }; - 346EB51226F79DA200ECD319 /* opus.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4DF26F79DA000ECD319 /* opus.framework */; }; - 346EB51326F79DA200ECD319 /* kvazaar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E026F79DA000ECD319 /* kvazaar.framework */; }; - 346EB51426F79DA200ECD319 /* expat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E126F79DA000ECD319 /* expat.framework */; }; - 346EB51526F79DA200ECD319 /* speex.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E226F79DA000ECD319 /* speex.framework */; }; - 346EB51626F79DA200ECD319 /* libvidstab.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E326F79DA000ECD319 /* libvidstab.framework */; }; - 346EB51726F79DA200ECD319 /* vo-amrwbenc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E426F79DA000ECD319 /* vo-amrwbenc.framework */; }; - 346EB51826F79DA200ECD319 /* xvidcore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E526F79DA000ECD319 /* xvidcore.framework */; }; - 346EB51926F79DA200ECD319 /* libavformat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E626F79DA000ECD319 /* libavformat.framework */; }; - 346EB51A26F79DA200ECD319 /* tiff.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E726F79DA000ECD319 /* tiff.framework */; }; - 346EB51B26F79DA200ECD319 /* libogg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E826F79DA000ECD319 /* libogg.framework */; }; - 346EB51C26F79DA200ECD319 /* shine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4E926F79DA000ECD319 /* shine.framework */; }; - 346EB51D26F79DA200ECD319 /* libtheoraenc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4EA26F79DA000ECD319 /* libtheoraenc.framework */; }; - 346EB51E26F79DA200ECD319 /* soxr.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4EB26F79DA000ECD319 /* soxr.framework */; }; - 346EB51F26F79DA200ECD319 /* gnutls.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4EC26F79DA100ECD319 /* gnutls.framework */; }; - 346EB52026F79DA300ECD319 /* libvorbisfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4ED26F79DA100ECD319 /* libvorbisfile.framework */; }; - 346EB52126F79DA300ECD319 /* libavcodec.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4EE26F79DA100ECD319 /* libavcodec.framework */; }; - 346EB52226F79DA300ECD319 /* giflib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4EF26F79DA100ECD319 /* giflib.framework */; }; - 346EB52326F79DA300ECD319 /* libvorbisenc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F026F79DA100ECD319 /* libvorbisenc.framework */; }; - 346EB52426F79DA300ECD319 /* libhogweed.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F126F79DA100ECD319 /* libhogweed.framework */; }; - 346EB52526F79DA300ECD319 /* x265.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F226F79DA100ECD319 /* x265.framework */; }; - 346EB52626F79DA300ECD319 /* ffmpegkit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F326F79DA100ECD319 /* ffmpegkit.framework */; }; - 346EB52726F79DA300ECD319 /* libsndfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F426F79DA100ECD319 /* libsndfile.framework */; }; - 346EB52826F79DA300ECD319 /* libavfilter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F526F79DA100ECD319 /* libavfilter.framework */; }; - 346EB52926F79DA300ECD319 /* fribidi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F626F79DA100ECD319 /* fribidi.framework */; }; - 346EB52A26F79DA300ECD319 /* libvorbis.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F726F79DA100ECD319 /* libvorbis.framework */; }; - 346EB52B26F79DA300ECD319 /* dav1d.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F826F79DA100ECD319 /* dav1d.framework */; }; - 346EB52C26F79DA300ECD319 /* libvpx.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4F926F79DA100ECD319 /* libvpx.framework */; }; - 346EB52D26F79DA300ECD319 /* libnettle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4FA26F79DA100ECD319 /* libnettle.framework */; }; - 346EB52E26F79DA300ECD319 /* libopencore-amrnb.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4FB26F79DA100ECD319 /* libopencore-amrnb.framework */; }; - 346EB52F26F79DA300ECD319 /* libpng.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4FC26F79DA100ECD319 /* libpng.framework */; }; - 346EB53026F79DA300ECD319 /* lame.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4FD26F79DA100ECD319 /* lame.framework */; }; - 346EB53126F79DA400ECD319 /* libilbc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4FE26F79DA100ECD319 /* libilbc.framework */; }; - 346EB53226F79DA400ECD319 /* libwebpmux.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB4FF26F79DA100ECD319 /* libwebpmux.framework */; }; - 346EB53326F79DA400ECD319 /* snappy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB50026F79DA100ECD319 /* snappy.framework */; }; - 346EB53426F79DA400ECD319 /* libxml2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 346EB50126F79DA100ECD319 /* libxml2.framework */; }; + 342F4C822736C5340092FC45 /* libavutil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7A2736C5340092FC45 /* libavutil.xcframework */; }; + 342F4C832736C5340092FC45 /* libavformat.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7B2736C5340092FC45 /* libavformat.xcframework */; }; + 342F4C842736C5340092FC45 /* libswresample.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7C2736C5340092FC45 /* libswresample.xcframework */; }; + 342F4C852736C5340092FC45 /* libavcodec.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7D2736C5340092FC45 /* libavcodec.xcframework */; }; + 342F4C862736C5340092FC45 /* ffmpegkit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7E2736C5340092FC45 /* ffmpegkit.xcframework */; }; + 342F4C872736C5340092FC45 /* libswscale.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7F2736C5340092FC45 /* libswscale.xcframework */; }; + 342F4C882736C5340092FC45 /* libavfilter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C802736C5340092FC45 /* libavfilter.xcframework */; }; + 342F4C892736C5340092FC45 /* libavdevice.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C812736C5340092FC45 /* libavdevice.xcframework */; }; + 342F4C8A2736C5450092FC45 /* ffmpegkit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7E2736C5340092FC45 /* ffmpegkit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 342F4C8B2736C5450092FC45 /* libavcodec.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7D2736C5340092FC45 /* libavcodec.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 342F4C8C2736C5450092FC45 /* libavdevice.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C812736C5340092FC45 /* libavdevice.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 342F4C8D2736C5450092FC45 /* libavfilter.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C802736C5340092FC45 /* libavfilter.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 342F4C8E2736C5450092FC45 /* libavformat.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7B2736C5340092FC45 /* libavformat.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 342F4C8F2736C5450092FC45 /* libavutil.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7A2736C5340092FC45 /* libavutil.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 342F4C902736C5450092FC45 /* libswresample.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7C2736C5340092FC45 /* libswresample.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 342F4C912736C5450092FC45 /* libswscale.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 342F4C7F2736C5340092FC45 /* libswscale.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 34B244F525E6F4300066DE76 /* stonehenge.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 34B244EE25E6F4300066DE76 /* stonehenge.jpg */; }; 34B244F625E6F4300066DE76 /* doppioone_regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34B244EF25E6F4300066DE76 /* doppioone_regular.ttf */; }; 34B244F725E6F4300066DE76 /* truenorg.otf in Resources */ = {isa = PBXBuildFile; fileRef = 34B244F025E6F4300066DE76 /* truenorg.otf */; }; @@ -100,60 +65,38 @@ 34F9FDDA25EAA07100B4F3D8 /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F9FDD925EAA07100B4F3D8 /* AVKit.framework */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + 34416D262734AD8B00F225A0 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 342F4C8A2736C5450092FC45 /* ffmpegkit.xcframework in Embed Frameworks */, + 342F4C8B2736C5450092FC45 /* libavcodec.xcframework in Embed Frameworks */, + 342F4C8C2736C5450092FC45 /* libavdevice.xcframework in Embed Frameworks */, + 342F4C8D2736C5450092FC45 /* libavfilter.xcframework in Embed Frameworks */, + 342F4C8E2736C5450092FC45 /* libavformat.xcframework in Embed Frameworks */, + 342F4C8F2736C5450092FC45 /* libavutil.xcframework in Embed Frameworks */, + 342F4C902736C5450092FC45 /* libswresample.xcframework in Embed Frameworks */, + 342F4C912736C5450092FC45 /* libswscale.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 340F2ACC25E8597800FAEEFE /* ProgressIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgressIndicator.m; sourceTree = ""; }; 340F2ACD25E8597800FAEEFE /* ProgressIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgressIndicator.h; sourceTree = ""; }; - 346EB4CF26F79D9F00ECD319 /* libtheoradec.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libtheoradec.framework; sourceTree = ""; }; - 346EB4D026F79D9F00ECD319 /* libavutil.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavutil.framework; sourceTree = ""; }; - 346EB4D126F79D9F00ECD319 /* libswresample.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libswresample.framework; sourceTree = ""; }; - 346EB4D226F79D9F00ECD319 /* libwebp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libwebp.framework; sourceTree = ""; }; - 346EB4D326F79D9F00ECD319 /* twolame.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = twolame.framework; sourceTree = ""; }; - 346EB4D426F79D9F00ECD319 /* libass.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libass.framework; sourceTree = ""; }; - 346EB4D526F79D9F00ECD319 /* libwebpdemux.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libwebpdemux.framework; sourceTree = ""; }; - 346EB4D626F79D9F00ECD319 /* libavdevice.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavdevice.framework; sourceTree = ""; }; - 346EB4D726F79DA000ECD319 /* libswscale.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libswscale.framework; sourceTree = ""; }; - 346EB4D826F79DA000ECD319 /* jpeg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = jpeg.framework; sourceTree = ""; }; - 346EB4D926F79DA000ECD319 /* freetype.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = freetype.framework; sourceTree = ""; }; - 346EB4DA26F79DA000ECD319 /* libtheora.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libtheora.framework; sourceTree = ""; }; - 346EB4DB26F79DA000ECD319 /* x264.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = x264.framework; sourceTree = ""; }; - 346EB4DC26F79DA000ECD319 /* fontconfig.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = fontconfig.framework; sourceTree = ""; }; - 346EB4DD26F79DA000ECD319 /* gmp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = gmp.framework; sourceTree = ""; }; - 346EB4DE26F79DA000ECD319 /* harfbuzz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = harfbuzz.framework; sourceTree = ""; }; - 346EB4DF26F79DA000ECD319 /* opus.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = opus.framework; sourceTree = ""; }; - 346EB4E026F79DA000ECD319 /* kvazaar.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = kvazaar.framework; sourceTree = ""; }; - 346EB4E126F79DA000ECD319 /* expat.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = expat.framework; sourceTree = ""; }; - 346EB4E226F79DA000ECD319 /* speex.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = speex.framework; sourceTree = ""; }; - 346EB4E326F79DA000ECD319 /* libvidstab.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvidstab.framework; sourceTree = ""; }; - 346EB4E426F79DA000ECD319 /* vo-amrwbenc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = "vo-amrwbenc.framework"; sourceTree = ""; }; - 346EB4E526F79DA000ECD319 /* xvidcore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = xvidcore.framework; sourceTree = ""; }; - 346EB4E626F79DA000ECD319 /* libavformat.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavformat.framework; sourceTree = ""; }; - 346EB4E726F79DA000ECD319 /* tiff.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = tiff.framework; sourceTree = ""; }; - 346EB4E826F79DA000ECD319 /* libogg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libogg.framework; sourceTree = ""; }; - 346EB4E926F79DA000ECD319 /* shine.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = shine.framework; sourceTree = ""; }; - 346EB4EA26F79DA000ECD319 /* libtheoraenc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libtheoraenc.framework; sourceTree = ""; }; - 346EB4EB26F79DA000ECD319 /* soxr.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = soxr.framework; sourceTree = ""; }; - 346EB4EC26F79DA100ECD319 /* gnutls.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = gnutls.framework; sourceTree = ""; }; - 346EB4ED26F79DA100ECD319 /* libvorbisfile.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvorbisfile.framework; sourceTree = ""; }; - 346EB4EE26F79DA100ECD319 /* libavcodec.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavcodec.framework; sourceTree = ""; }; - 346EB4EF26F79DA100ECD319 /* giflib.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = giflib.framework; sourceTree = ""; }; - 346EB4F026F79DA100ECD319 /* libvorbisenc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvorbisenc.framework; sourceTree = ""; }; - 346EB4F126F79DA100ECD319 /* libhogweed.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libhogweed.framework; sourceTree = ""; }; - 346EB4F226F79DA100ECD319 /* x265.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = x265.framework; sourceTree = ""; }; - 346EB4F326F79DA100ECD319 /* ffmpegkit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ffmpegkit.framework; sourceTree = ""; }; - 346EB4F426F79DA100ECD319 /* libsndfile.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libsndfile.framework; sourceTree = ""; }; - 346EB4F526F79DA100ECD319 /* libavfilter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavfilter.framework; sourceTree = ""; }; - 346EB4F626F79DA100ECD319 /* fribidi.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = fribidi.framework; sourceTree = ""; }; - 346EB4F726F79DA100ECD319 /* libvorbis.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvorbis.framework; sourceTree = ""; }; - 346EB4F826F79DA100ECD319 /* dav1d.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = dav1d.framework; sourceTree = ""; }; - 346EB4F926F79DA100ECD319 /* libvpx.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libvpx.framework; sourceTree = ""; }; - 346EB4FA26F79DA100ECD319 /* libnettle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libnettle.framework; sourceTree = ""; }; - 346EB4FB26F79DA100ECD319 /* libopencore-amrnb.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = "libopencore-amrnb.framework"; sourceTree = ""; }; - 346EB4FC26F79DA100ECD319 /* libpng.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libpng.framework; sourceTree = ""; }; - 346EB4FD26F79DA100ECD319 /* lame.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = lame.framework; sourceTree = ""; }; - 346EB4FE26F79DA100ECD319 /* libilbc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libilbc.framework; sourceTree = ""; }; - 346EB4FF26F79DA100ECD319 /* libwebpmux.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libwebpmux.framework; sourceTree = ""; }; - 346EB50026F79DA100ECD319 /* snappy.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = snappy.framework; sourceTree = ""; }; - 346EB50126F79DA100ECD319 /* libxml2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libxml2.framework; sourceTree = ""; }; + 342F4C7A2736C5340092FC45 /* libavutil.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavutil.xcframework; sourceTree = ""; }; + 342F4C7B2736C5340092FC45 /* libavformat.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavformat.xcframework; sourceTree = ""; }; + 342F4C7C2736C5340092FC45 /* libswresample.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libswresample.xcframework; sourceTree = ""; }; + 342F4C7D2736C5340092FC45 /* libavcodec.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavcodec.xcframework; sourceTree = ""; }; + 342F4C7E2736C5340092FC45 /* ffmpegkit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = ffmpegkit.xcframework; sourceTree = ""; }; + 342F4C7F2736C5340092FC45 /* libswscale.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libswscale.xcframework; sourceTree = ""; }; + 342F4C802736C5340092FC45 /* libavfilter.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavfilter.xcframework; sourceTree = ""; }; + 342F4C812736C5340092FC45 /* libavdevice.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavdevice.xcframework; sourceTree = ""; }; 34B244EE25E6F4300066DE76 /* stonehenge.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = stonehenge.jpg; sourceTree = ""; }; 34B244EF25E6F4300066DE76 /* doppioone_regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = doppioone_regular.ttf; sourceTree = ""; }; 34B244F025E6F4300066DE76 /* truenorg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = truenorg.otf; sourceTree = ""; }; @@ -222,69 +165,26 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 346EB50626F79DA200ECD319 /* twolame.framework in Frameworks */, - 346EB52C26F79DA300ECD319 /* libvpx.framework in Frameworks */, 34F9FDDA25EAA07100B4F3D8 /* AVKit.framework in Frameworks */, - 346EB50826F79DA200ECD319 /* libwebpdemux.framework in Frameworks */, - 346EB51326F79DA200ECD319 /* kvazaar.framework in Frameworks */, + 342F4C872736C5340092FC45 /* libswscale.xcframework in Frameworks */, 34D67B0125E4931E004564B7 /* AVFoundation.framework in Frameworks */, 34D67AFE25E49309004564B7 /* CoreMedia.framework in Frameworks */, - 346EB53426F79DA400ECD319 /* libxml2.framework in Frameworks */, - 346EB50F26F79DA200ECD319 /* fontconfig.framework in Frameworks */, - 346EB52926F79DA300ECD319 /* fribidi.framework in Frameworks */, - 346EB50726F79DA200ECD319 /* libass.framework in Frameworks */, - 346EB52A26F79DA300ECD319 /* libvorbis.framework in Frameworks */, - 346EB53126F79DA400ECD319 /* libilbc.framework in Frameworks */, - 346EB50D26F79DA200ECD319 /* libtheora.framework in Frameworks */, - 346EB52226F79DA300ECD319 /* giflib.framework in Frameworks */, - 346EB53026F79DA300ECD319 /* lame.framework in Frameworks */, - 346EB52526F79DA300ECD319 /* x265.framework in Frameworks */, - 346EB51A26F79DA200ECD319 /* tiff.framework in Frameworks */, - 346EB51526F79DA200ECD319 /* speex.framework in Frameworks */, - 346EB52026F79DA300ECD319 /* libvorbisfile.framework in Frameworks */, 34D67AF725E492D9004564B7 /* OpenCL.framework in Frameworks */, + 342F4C832736C5340092FC45 /* libavformat.xcframework in Frameworks */, 34D67AF225E492B4004564B7 /* Carbon.framework in Frameworks */, - 346EB50326F79DA200ECD319 /* libavutil.framework in Frameworks */, - 346EB51E26F79DA200ECD319 /* soxr.framework in Frameworks */, - 346EB50E26F79DA200ECD319 /* x264.framework in Frameworks */, - 346EB51426F79DA200ECD319 /* expat.framework in Frameworks */, + 342F4C892736C5340092FC45 /* libavdevice.xcframework in Frameworks */, + 342F4C852736C5340092FC45 /* libavcodec.xcframework in Frameworks */, 34D67AE825E49257004564B7 /* Accelerate.framework in Frameworks */, - 346EB50226F79DA200ECD319 /* libtheoradec.framework in Frameworks */, 34D67AE525E4922B004564B7 /* VideoToolbox.framework in Frameworks */, 34D67AA625E33ECA004564B7 /* AudioToolbox.framework in Frameworks */, - 346EB50926F79DA200ECD319 /* libavdevice.framework in Frameworks */, - 346EB51926F79DA200ECD319 /* libavformat.framework in Frameworks */, - 346EB51B26F79DA200ECD319 /* libogg.framework in Frameworks */, - 346EB50526F79DA200ECD319 /* libwebp.framework in Frameworks */, 34D67AA425E33EC1004564B7 /* CoreAudio.framework in Frameworks */, - 346EB51826F79DA200ECD319 /* xvidcore.framework in Frameworks */, - 346EB51626F79DA200ECD319 /* libvidstab.framework in Frameworks */, + 342F4C862736C5340092FC45 /* ffmpegkit.xcframework in Frameworks */, + 342F4C842736C5340092FC45 /* libswresample.xcframework in Frameworks */, 34D6796525E2F1B5004564B7 /* libiconv.tbd in Frameworks */, 34D6796225E2F1B1004564B7 /* libz.tbd in Frameworks */, - 346EB52E26F79DA300ECD319 /* libopencore-amrnb.framework in Frameworks */, - 346EB51226F79DA200ECD319 /* opus.framework in Frameworks */, - 346EB51026F79DA200ECD319 /* gmp.framework in Frameworks */, - 346EB52D26F79DA300ECD319 /* libnettle.framework in Frameworks */, - 346EB52126F79DA300ECD319 /* libavcodec.framework in Frameworks */, - 346EB53326F79DA400ECD319 /* snappy.framework in Frameworks */, - 346EB53226F79DA400ECD319 /* libwebpmux.framework in Frameworks */, - 346EB51726F79DA200ECD319 /* vo-amrwbenc.framework in Frameworks */, - 346EB52826F79DA300ECD319 /* libavfilter.framework in Frameworks */, - 346EB50C26F79DA200ECD319 /* freetype.framework in Frameworks */, - 346EB52626F79DA300ECD319 /* ffmpegkit.framework in Frameworks */, - 346EB51F26F79DA200ECD319 /* gnutls.framework in Frameworks */, - 346EB50426F79DA200ECD319 /* libswresample.framework in Frameworks */, - 346EB51C26F79DA200ECD319 /* shine.framework in Frameworks */, - 346EB50A26F79DA200ECD319 /* libswscale.framework in Frameworks */, - 346EB52326F79DA300ECD319 /* libvorbisenc.framework in Frameworks */, - 346EB52726F79DA300ECD319 /* libsndfile.framework in Frameworks */, - 346EB52B26F79DA300ECD319 /* dav1d.framework in Frameworks */, - 346EB52426F79DA300ECD319 /* libhogweed.framework in Frameworks */, - 346EB51D26F79DA200ECD319 /* libtheoraenc.framework in Frameworks */, 34D6795F25E2F190004564B7 /* libbz2.tbd in Frameworks */, - 346EB50B26F79DA200ECD319 /* jpeg.framework in Frameworks */, - 346EB51126F79DA200ECD319 /* harfbuzz.framework in Frameworks */, - 346EB52F26F79DA300ECD319 /* libpng.framework in Frameworks */, + 342F4C822736C5340092FC45 /* libavutil.xcframework in Frameworks */, + 342F4C882736C5340092FC45 /* libavfilter.xcframework in Frameworks */, 34D6795A25E2F178004564B7 /* libc++.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -373,63 +273,20 @@ 34D678D525E2EB22004564B7 /* Frameworks */ = { isa = PBXGroup; children = ( + 342F4C7E2736C5340092FC45 /* ffmpegkit.xcframework */, + 342F4C7D2736C5340092FC45 /* libavcodec.xcframework */, + 342F4C812736C5340092FC45 /* libavdevice.xcframework */, + 342F4C802736C5340092FC45 /* libavfilter.xcframework */, + 342F4C7B2736C5340092FC45 /* libavformat.xcframework */, + 342F4C7A2736C5340092FC45 /* libavutil.xcframework */, + 342F4C7C2736C5340092FC45 /* libswresample.xcframework */, + 342F4C7F2736C5340092FC45 /* libswscale.xcframework */, 34F9FDD925EAA07100B4F3D8 /* AVKit.framework */, 34D67B0025E4931E004564B7 /* AVFoundation.framework */, 34D67AFD25E49308004564B7 /* CoreMedia.framework */, 34D67AF925E492E4004564B7 /* OpenGL.framework */, 34D67AF625E492D9004564B7 /* OpenCL.framework */, 34D67AED25E4928B004564B7 /* Metal.framework */, - 346EB4F826F79DA100ECD319 /* dav1d.framework */, - 346EB4E126F79DA000ECD319 /* expat.framework */, - 346EB4F326F79DA100ECD319 /* ffmpegkit.framework */, - 346EB4DC26F79DA000ECD319 /* fontconfig.framework */, - 346EB4D926F79DA000ECD319 /* freetype.framework */, - 346EB4F626F79DA100ECD319 /* fribidi.framework */, - 346EB4EF26F79DA100ECD319 /* giflib.framework */, - 346EB4DD26F79DA000ECD319 /* gmp.framework */, - 346EB4EC26F79DA100ECD319 /* gnutls.framework */, - 346EB4DE26F79DA000ECD319 /* harfbuzz.framework */, - 346EB4D826F79DA000ECD319 /* jpeg.framework */, - 346EB4E026F79DA000ECD319 /* kvazaar.framework */, - 346EB4FD26F79DA100ECD319 /* lame.framework */, - 346EB4D426F79D9F00ECD319 /* libass.framework */, - 346EB4EE26F79DA100ECD319 /* libavcodec.framework */, - 346EB4D626F79D9F00ECD319 /* libavdevice.framework */, - 346EB4F526F79DA100ECD319 /* libavfilter.framework */, - 346EB4E626F79DA000ECD319 /* libavformat.framework */, - 346EB4D026F79D9F00ECD319 /* libavutil.framework */, - 346EB4F126F79DA100ECD319 /* libhogweed.framework */, - 346EB4FE26F79DA100ECD319 /* libilbc.framework */, - 346EB4FA26F79DA100ECD319 /* libnettle.framework */, - 346EB4E826F79DA000ECD319 /* libogg.framework */, - 346EB4FB26F79DA100ECD319 /* libopencore-amrnb.framework */, - 346EB4FC26F79DA100ECD319 /* libpng.framework */, - 346EB4F426F79DA100ECD319 /* libsndfile.framework */, - 346EB4D126F79D9F00ECD319 /* libswresample.framework */, - 346EB4D726F79DA000ECD319 /* libswscale.framework */, - 346EB4DA26F79DA000ECD319 /* libtheora.framework */, - 346EB4CF26F79D9F00ECD319 /* libtheoradec.framework */, - 346EB4EA26F79DA000ECD319 /* libtheoraenc.framework */, - 346EB4E326F79DA000ECD319 /* libvidstab.framework */, - 346EB4F726F79DA100ECD319 /* libvorbis.framework */, - 346EB4F026F79DA100ECD319 /* libvorbisenc.framework */, - 346EB4ED26F79DA100ECD319 /* libvorbisfile.framework */, - 346EB4F926F79DA100ECD319 /* libvpx.framework */, - 346EB4D226F79D9F00ECD319 /* libwebp.framework */, - 346EB4D526F79D9F00ECD319 /* libwebpdemux.framework */, - 346EB4FF26F79DA100ECD319 /* libwebpmux.framework */, - 346EB50126F79DA100ECD319 /* libxml2.framework */, - 346EB4DF26F79DA000ECD319 /* opus.framework */, - 346EB4E926F79DA000ECD319 /* shine.framework */, - 346EB50026F79DA100ECD319 /* snappy.framework */, - 346EB4EB26F79DA000ECD319 /* soxr.framework */, - 346EB4E226F79DA000ECD319 /* speex.framework */, - 346EB4E726F79DA000ECD319 /* tiff.framework */, - 346EB4D326F79D9F00ECD319 /* twolame.framework */, - 346EB4E426F79DA000ECD319 /* vo-amrwbenc.framework */, - 346EB4DB26F79DA000ECD319 /* x264.framework */, - 346EB4F226F79DA100ECD319 /* x265.framework */, - 346EB4E526F79DA000ECD319 /* xvidcore.framework */, 34D67AEA25E49278004564B7 /* CoreImage.framework */, 34D67AE725E49257004564B7 /* Accelerate.framework */, 34D67AE425E4922B004564B7 /* VideoToolbox.framework */, @@ -454,6 +311,7 @@ 34D678B225E2D9BA004564B7 /* Sources */, 34D678B325E2D9BA004564B7 /* Frameworks */, 34D678B425E2D9BA004564B7 /* Resources */, + 34416D262734AD8B00F225A0 /* Embed Frameworks */, ); buildRules = ( ); @@ -605,7 +463,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -658,7 +516,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -671,10 +529,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = FFmpegKitMACOS/FFmpegKitMACOS.entitlements; - CODE_SIGN_IDENTITY = "Mac Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 13; DEVELOPMENT_TEAM = 98GD5J4999; ENABLE_HARDENED_RUNTIME = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -686,11 +544,11 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 2.0; PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.FFmpegKitMACOS; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "macos-development-provisioning-profile"; + PROVISIONING_PROFILE_SPECIFIER = ""; }; name = Debug; }; @@ -700,10 +558,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = FFmpegKitMACOS/FFmpegKitMACOS.entitlements; - CODE_SIGN_IDENTITY = "Mac Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 13; DEVELOPMENT_TEAM = 98GD5J4999; ENABLE_HARDENED_RUNTIME = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -715,11 +573,11 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.15; MARKETING_VERSION = 2.0; PRODUCT_BUNDLE_IDENTIFIER = com.arthenica.ffmpegkit.FFmpegKitMACOS; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "macos-development-provisioning-profile"; + PROVISIONING_PROFILE_SPECIFIER = ""; }; name = Release; }; diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate b/macos/test-app-local-dependency/FFmpegKitMACOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate index 7c5b5e8..1f98dbf 100644 Binary files a/macos/test-app-local-dependency/FFmpegKitMACOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate and b/macos/test-app-local-dependency/FFmpegKitMACOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/AppDelegate.m b/macos/test-app-local-dependency/FFmpegKitMACOS/AppDelegate.m index a350f2e..fbe68c8 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/AppDelegate.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/AppDelegate.m @@ -31,7 +31,7 @@ void uncaughtExceptionHandler(NSException *exception) { @implementation AppDelegate + (void)listFFprobeSessions { - NSArray* ffprobeSessions = [FFprobeKit listSessions]; + NSArray* ffprobeSessions = [FFprobeKit listFFprobeSessions]; NSLog(@"Listing FFprobe sessions.\n"); diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/AudioViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/AudioViewController.m index 4c514f4..0887342 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/AudioViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/AudioViewController.m @@ -128,7 +128,7 @@ - (IBAction)encodeAudio:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/CommandViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/CommandViewController.m index a1110c5..6de1ae6 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/CommandViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/CommandViewController.m @@ -66,13 +66,13 @@ - (IBAction)runFFmpeg:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self.view.window withTitle:@"Error" message:@"Command failed. Please check output for the details." buttonText:@"OK" andHandler:nil]; }); @@ -93,7 +93,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process started with arguments\n'%@'.\n", ffprobeCommand); - FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withExecuteCallback:^(id session) { + FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withCompleteCallback:^(FFprobeSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; @@ -103,7 +103,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self.view.window withTitle:@"Error" message:@"Command failed. Please check output for the details." buttonText:@"OK" andHandler:nil]; }); diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/ConcurrentExecutionViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/ConcurrentExecutionViewController.m index fb9db7e..e758a0c 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/ConcurrentExecutionViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/ConcurrentExecutionViewController.m @@ -115,7 +115,7 @@ - (void)encodeVideo:(int)buttonNumber { NSLog(@"FFmpeg process starting for button %d with arguments\n'%@'.\n", buttonNumber, ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/FFmpegKitTest.m b/macos/test-app-local-dependency/FFmpegKitMACOS/FFmpegKitTest.m index 7531c1f..63e61d0 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/FFmpegKitTest.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/FFmpegKitTest.m @@ -193,9 +193,9 @@ void testParseDoubleQuotesAndEscapesInCommand() { void getSessionIdTest() { NSArray *TEST_ARGUMENTS = [[NSArray alloc] initWithObjects:@"argument1", @"argument2", nil]; - FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; + FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; assert([sessions3 getSessionId] > [sessions2 getSessionId]); assert([sessions3 getSessionId] > [sessions1 getSessionId]); diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/HttpsViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/HttpsViewController.m index 9d85560..8b4ec84 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/HttpsViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/HttpsViewController.m @@ -106,7 +106,7 @@ - (void)runGetMediaInformation:(int)buttonNumber { [self clearOutput]; } - [FFprobeKit getMediaInformationAsync:testUrl withExecuteCallback:[self createNewExecuteCallback]]; + [FFprobeKit getMediaInformationAsync:testUrl withCompleteCallback:[self createNewCompleteCallback]]; } - (void)setActive { @@ -135,11 +135,11 @@ - (NSString*)getRandomTestUrl { } } -- (ExecuteCallback)createNewExecuteCallback { - return ^(id session){ +- (MediaInformationSessionCompleteCallback)createNewCompleteCallback { + return ^(MediaInformationSession* session){ addUIAction(^{ @synchronized (self->outputLock) { - MediaInformation *information = [((MediaInformationSession*) session) getMediaInformation]; + MediaInformation *information = [session getMediaInformation]; if (information == nil) { [self appendOutput:@"Get media information failed\n"]; [self appendOutput:[NSString stringWithFormat:@"State: %@\n", [FFmpegKitConfig sessionStateToString:[session getState]]]]; @@ -165,7 +165,7 @@ - (ExecuteCallback)createNewExecuteCallback { if ([information getTags] != nil) { NSDictionary* tags = [information getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@\n", key, [tags objectForKey:key]]]; } } if ([information getStreams] != nil) { @@ -228,7 +228,35 @@ - (ExecuteCallback)createNewExecuteCallback { if ([stream getTags] != nil) { NSDictionary* tags = [stream getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@\n", key, [tags objectForKey:key]]]; + } + } + } + } + if ([information getChapters] != nil) { + for (Chapter* chapter in [information getChapters]) { + if ([chapter getId] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter id: %@\n", [chapter getId]]]; + } + if ([chapter getTimeBase] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter time base: %@\n", [chapter getTimeBase]]]; + } + if ([chapter getStart] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start: %@\n", [chapter getStart]]]; + } + if ([chapter getStartTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start time: %@\n", [chapter getStartTime]]]; + } + if ([chapter getEnd] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end: %@\n", [chapter getEnd]]]; + } + if ([chapter getEndTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end time: %@\n", [chapter getEndTime]]]; + } + if ([chapter getTags] != nil) { + NSDictionary* tags = [chapter getTags]; + for(NSString *key in [tags allKeys]) { + [self appendOutput:[NSString stringWithFormat:@"Chapter tag: %@:%@\n", key, [tags objectForKey:key]]]; } } } diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/Info.plist b/macos/test-app-local-dependency/FFmpegKitMACOS/Info.plist index a3f7a54..a789f47 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/Info.plist +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 1 + $(CURRENT_PROJECT_VERSION) LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/MediaInformationParserTest.m b/macos/test-app-local-dependency/FFmpegKitMACOS/MediaInformationParserTest.m index 27ac684..9282b8a 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/MediaInformationParserTest.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/MediaInformationParserTest.m @@ -75,6 +75,85 @@ static void initTests() { " }\n" " }\n" " ],\n" + " \"chapters\": [\n" + " {\n" + " \"id\": 0,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"end\": 11158238,\n" + " \"end_time\": \"506.042540\",\n" + " \"tags\": {\n" + " \"title\": \"1 Laying Plans - 2 Waging War\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 1,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 11158238,\n" + " \"start_time\": \"506.042540\",\n" + " \"end\": 21433051,\n" + " \"end_time\": \"972.020454\",\n" + " \"tags\": {\n" + " \"title\": \"3 Attack By Stratagem - 4 Tactical Dispositions\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 2,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 21433051,\n" + " \"start_time\": \"972.020454\",\n" + " \"end\": 35478685,\n" + " \"end_time\": \"1609.010658\",\n" + " \"tags\": {\n" + " \"title\": \"5 Energy - 6 Weak Points and Strong\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 3,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 35478685,\n" + " \"start_time\": \"1609.010658\",\n" + " \"end\": 47187043,\n" + " \"end_time\": \"2140.001950\",\n" + " \"tags\": {\n" + " \"title\": \"7 Maneuvering - 8 Variation in Tactics\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 4,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 47187043,\n" + " \"start_time\": \"2140.001950\",\n" + " \"end\": 66635594,\n" + " \"end_time\": \"3022.022404\",\n" + " \"tags\": {\n" + " \"title\": \"9 The Army on the March - 10 Terrain\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 5,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 66635594,\n" + " \"start_time\": \"3022.022404\",\n" + " \"end\": 83768105,\n" + " \"end_time\": \"3799.007029\",\n" + " \"tags\": {\n" + " \"title\": \"11 The Nine Situations\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 6,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 83768105,\n" + " \"start_time\": \"3799.007029\",\n" + " \"end\": 95659008,\n" + " \"end_time\": \"4338.277007\",\n" + " \"tags\": {\n" + " \"title\": \"12 The Attack By Fire - 13 The Use of Spies\"\n" + " }\n" + " }\n" + " ],\n" " \"format\": {\n" " \"filename\": \"sample.mp3\",\n" " \"nb_streams\": 1,\n" @@ -448,6 +527,10 @@ static void initTests() { } +void assertNotNull(NSObject *object) { + assert(object != nil); +} + void assertNumber(NSNumber *expected, NSNumber *real) { if (expected == nil) { assert(real == nil); @@ -501,8 +584,21 @@ void assertAudioStream(StreamInformation *stream, NSNumber *index, NSString *cod assertString(bitrate, [stream getBitrate]); } -void assertNotNull(NSObject *object) { - assert(object != nil); +void assertChapter(Chapter *chapter, NSNumber *id, NSString *timeBase, NSNumber *start, NSString * startTime, NSNumber *end, NSString *endTime) { + assert(chapter != nil); + assertNumber(id, [chapter getId]); + assertString(timeBase, [chapter getTimeBase]); + + assertNumber(start, [chapter getStart]); + assertString(startTime, [chapter getStartTime]); + + assertNumber(end, [chapter getEnd]); + assertString(endTime, [chapter getEndTime]); + + NSDictionary *tags = [chapter getTags]; + assertNotNull(tags); + + assert(1 == [tags count]); } void assertMediaInput(MediaInformation *mediaInformation, NSString *expectedFormat, NSString *expectedFilename) { @@ -579,6 +675,13 @@ void testMediaInformationMp3() { assert(1 == [streams count]); assertAudioStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mp3", @"MP3 (MPEG audio layer 3)", @"44100", @"stereo", @"fltp", @"320000"); + + NSArray *chapters = [mediaInformation getChapters]; + assertNotNull(chapters); + assert(7 == [chapters count]); + + assertChapter([chapters objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"1/22050", [[NSNumber alloc] initWithInt:0], @"0.000000", [[NSNumber alloc] initWithInt:11158238], @"506.042540"); + assertChapter([chapters objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"1/22050", [[NSNumber alloc] initWithInt:11158238], @"506.042540", [[NSNumber alloc] initWithInt:21433051], @"972.020454"); } void testMediaInformationJpg() { diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/OtherViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/OtherViewController.m index 0f21ba0..1e0a993 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/OtherViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/OtherViewController.m @@ -46,7 +46,7 @@ - (void)viewDidLoad { [super viewDidLoad]; // OTHER TEST PICKER INIT - testData = @[@"chromaprint", @"dav1d", @"webp"]; + testData = @[@"chromaprint", @"dav1d", @"webp", @"zscale"]; selectedTest = 0; [self.otherTestComboBox setUsesDataSource:YES]; @@ -102,6 +102,9 @@ - (IBAction)runTest:(id)sender { case 2: [self testWebp]; break; + case 3: + [self testZscale]; + break; } } @@ -115,7 +118,7 @@ -(void)testChromaprint { NSLog(@"Creating audio sample with '%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -127,7 +130,7 @@ -(void)testChromaprint { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", chromaprintCommand); - [FFmpegKit executeAsync:chromaprintCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:chromaprintCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -147,7 +150,7 @@ -(void)testDav1d { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); } withLogCallback:^(Log *log) { addUIAction(^{ @@ -168,7 +171,29 @@ -(void)testWebp { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { + + NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); + + } withLogCallback:^(Log *log) { + addUIAction(^{ + [self appendOutput: [log getMessage]]; + }); + } withStatisticsCallback:nil]; +} + +-(void)testZscale { + NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + NSString *videoFile = [docFolder stringByAppendingPathComponent: @"video.mp4"]; + NSString *zscaledVideoFile = [docFolder stringByAppendingPathComponent: @"video.zscaled.mp4"]; + + NSLog(@"Testing 'zscale' filter with video file created on the Video tab\n"); + + NSString *ffmpegCommand = [Video generateZscaleVideoScript:videoFile:zscaledVideoFile]; + + NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); + + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/PipeViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/PipeViewController.m index cce34e6..1d213ac 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/PipeViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/PipeViewController.m @@ -158,7 +158,7 @@ - (IBAction)createVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/SubtitleViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/SubtitleViewController.m index 112e958..d55092c 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/SubtitleViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/SubtitleViewController.m @@ -115,7 +115,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = CreatingState; - sessionId = [[FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + sessionId = [[FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -136,7 +136,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = BurningState; - [FFmpegKit executeAsync:burnSubtitlesCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:burnSubtitlesCommand withCompleteCallback:^(id secondSession) { addUIAction(^{ [self hideProgressDialog]; diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/VidStabViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/VidStabViewController.m index f319d77..7573e51 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/VidStabViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/VidStabViewController.m @@ -97,7 +97,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); addUIAction(^{ @@ -115,7 +115,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", analyzeVideoCommand); - [FFmpegKit executeAsync:analyzeVideoCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:analyzeVideoCommand withCompleteCallback:^(id secondSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[secondSession getState]], [secondSession getReturnCode], notNull([secondSession getFailStackTrace], @"\n")); @@ -125,7 +125,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", stabilizeVideoCommand); - [FFmpegKit executeAsync:stabilizeVideoCommand withExecuteCallback:^(id thirdSession) { + [FFmpegKit executeAsync:stabilizeVideoCommand withCompleteCallback:^(id thirdSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[thirdSession getState]], [thirdSession getReturnCode], notNull([thirdSession getFailStackTrace], @"\n")); diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/Video.h b/macos/test-app-local-dependency/FFmpegKitMACOS/Video.h index 7aa0a6c..977f2ef 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/Video.h +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/Video.h @@ -31,8 +31,12 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions; ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions; + + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile; ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath; + @end #endif /* FFMPEG_KIT_TEST_VIDEO */ diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/Video.m b/macos/test-app-local-dependency/FFmpegKitMACOS/Video.m index 0778874..f910e28 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/Video.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/Video.m @@ -48,6 +48,10 @@ + (NSString*)generateCreateVideoWithPipesScript:(NSString *)image1 :(NSString *) } + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions { + return [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:videoCodec:@"yuv420p":customOptions]; +} + ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions { return [NSString stringWithFormat: @"-hide_banner -y -loop 1 -i %@ \ -loop 1 -i %@ \ @@ -66,8 +70,8 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :( [stream2ending]fade=t=out:s=0:n=30[stream2fadeout];\ [stream2fadein][stream1fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream2blended];\ [stream3fadein][stream2fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream3blended];\ -[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\" \ --map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, customOptions, videoCodec, videoFile]; +[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=%@[video]\" \ +-map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, pixelFormat, customOptions, videoCodec, videoFile]; } + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile { @@ -90,4 +94,8 @@ + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 : -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 %@", image1, image2, image3, videoFile]; } ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath { + return [NSString stringWithFormat:@"-y -i %@ -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p %@", inputVideoFilePath, outputVideoFilePath]; +} + @end diff --git a/macos/test-app-local-dependency/FFmpegKitMACOS/VideoViewController.m b/macos/test-app-local-dependency/FFmpegKitMACOS/VideoViewController.m index afef16f..df236fe 100644 --- a/macos/test-app-local-dependency/FFmpegKitMACOS/VideoViewController.m +++ b/macos/test-app-local-dependency/FFmpegKitMACOS/VideoViewController.m @@ -126,11 +126,11 @@ - (IBAction)encodeVideo:(id)sender { [self showProgressDialog:@"Encoding video\n\n"]; - NSString* ffmpegCommand = [Video generateVideoEncodeScript:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getCustomOptions]]; + NSString* ffmpegCommand = [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getPixelFormat]:[self getCustomOptions]]; NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session){ + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session){ SessionState state = [session getState]; ReturnCode *returnCode = [session getReturnCode]; @@ -181,6 +181,19 @@ - (void)playVideo { [player insertItem:newVideo afterItem:nil]; } +- (NSString*)getPixelFormat { + NSString *videoCodec = codecData[selectedCodec]; + + NSString *pixelFormat; + if ([videoCodec isEqualToString:@"x265"]) { + pixelFormat = @"yuv420p10le"; + } else { + pixelFormat = @"yuv420p"; + } + + return pixelFormat; +} + - (NSString*)getSelectedVideoCodec { NSString *videoCodec = codecData[selectedCodec]; diff --git a/scripts/update_ios_local_dependency_frameworks.sh b/scripts/update_ios_local_dependency_frameworks.sh new file mode 100755 index 0000000..fcadcc1 --- /dev/null +++ b/scripts/update_ios_local_dependency_frameworks.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +export BASEDIR="$(pwd)" + +cd ${BASEDIR}/../ios/test-app-local-dependency || exit 1 +rm -rf *.framework || exit 1 +rm -rf *.xcframework || exit 1 +find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-framework-ios -name "*.framework" -exec cp -R {} . \; || exit 1 diff --git a/scripts/update_ios_local_dependency_frameworks_lts.sh b/scripts/update_ios_local_dependency_frameworks_lts.sh new file mode 100755 index 0000000..ac9e1e4 --- /dev/null +++ b/scripts/update_ios_local_dependency_frameworks_lts.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +export BASEDIR="$(pwd)" + +cd ${BASEDIR}/../ios/test-app-local-dependency || exit 1 +rm -rf *.framework || exit 1 +rm -rf *.xcframework || exit 1 +find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-framework-ios-lts -name "*.framework" -exec cp -R {} . \; || exit 1 diff --git a/scripts/update_ios_local_dependency_xcframeworks.sh b/scripts/update_ios_local_dependency_xcframeworks.sh index ddabf6b..eb4a60c 100755 --- a/scripts/update_ios_local_dependency_xcframeworks.sh +++ b/scripts/update_ios_local_dependency_xcframeworks.sh @@ -5,4 +5,4 @@ export BASEDIR="$(pwd)" cd ${BASEDIR}/../ios/test-app-local-dependency || exit 1 rm -rf *.framework || exit 1 rm -rf *.xcframework || exit 1 -find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-xcframework-ios -name "*.xcframework" -exec cp -r {} . \; || exit 1 +find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-xcframework-ios -name "*.xcframework" -exec cp -R {} . \; || exit 1 diff --git a/scripts/update_macos_local_dependency_frameworks.sh b/scripts/update_macos_local_dependency_frameworks.sh index e3c0cde..b1a2c3f 100755 --- a/scripts/update_macos_local_dependency_frameworks.sh +++ b/scripts/update_macos_local_dependency_frameworks.sh @@ -5,4 +5,4 @@ export BASEDIR="$(pwd)" cd ${BASEDIR}/../macos/test-app-local-dependency || exit 1 rm -rf *.xcframework || exit 1 rm -rf *.framework || exit 1 -find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-framework-macos -name "*.framework" -exec cp -r {} . \; || exit 1 +find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-framework-macos -name "*.framework" -exec cp -R {} . \; || exit 1 diff --git a/scripts/update_macos_local_dependency_lts_frameworks.sh b/scripts/update_macos_local_dependency_frameworks_lts.sh similarity index 78% rename from scripts/update_macos_local_dependency_lts_frameworks.sh rename to scripts/update_macos_local_dependency_frameworks_lts.sh index 2cf3604..075d3ea 100755 --- a/scripts/update_macos_local_dependency_lts_frameworks.sh +++ b/scripts/update_macos_local_dependency_frameworks_lts.sh @@ -5,4 +5,4 @@ export BASEDIR="$(pwd)" cd ${BASEDIR}/../macos/test-app-local-dependency || exit 1 rm -rf *.xcframework || exit 1 rm -rf *.framework || exit 1 -find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-framework-macos-lts -name "*.framework" -exec cp -r {} . \; || exit 1 +find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-framework-macos-lts -name "*.framework" -exec cp -R {} . \; || exit 1 diff --git a/scripts/update_macos_local_dependency_xcframeworks.sh b/scripts/update_macos_local_dependency_xcframeworks.sh index 964aa12..050454f 100755 --- a/scripts/update_macos_local_dependency_xcframeworks.sh +++ b/scripts/update_macos_local_dependency_xcframeworks.sh @@ -5,4 +5,4 @@ export BASEDIR="$(pwd)" cd ${BASEDIR}/../macos/test-app-local-dependency || exit 1 rm -rf *.xcframework || exit 1 rm -rf *.framework || exit 1 -find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-xcframework-macos -name "*.xcframework" -exec cp -r {} . \; || exit 1 +find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-xcframework-macos -name "*.xcframework" -exec cp -R {} . \; || exit 1 diff --git a/scripts/update_tvos_local_dependency_frameworks_lts.sh b/scripts/update_tvos_local_dependency_frameworks_lts.sh new file mode 100755 index 0000000..dcacc24 --- /dev/null +++ b/scripts/update_tvos_local_dependency_frameworks_lts.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +export BASEDIR="$(pwd)" + +cd ${BASEDIR}/../tvos/test-app-local-dependency || exit 1 +rm -rf *.framework || exit 1 +rm -rf *.xcframework || exit 1 +find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-framework-tvos-lts -name "*.framework" -exec cp -R {} . \; || exit 1 diff --git a/scripts/update_tvos_local_dependency_xcframeworks.sh b/scripts/update_tvos_local_dependency_xcframeworks.sh index 385aa6e..d356832 100755 --- a/scripts/update_tvos_local_dependency_xcframeworks.sh +++ b/scripts/update_tvos_local_dependency_xcframeworks.sh @@ -3,5 +3,6 @@ export BASEDIR="$(pwd)" cd ${BASEDIR}/../tvos/test-app-local-dependency || exit 1 +rm -rf *.framework || exit 1 rm -rf *.xcframework || exit 1 -find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-xcframework-tvos -name "*.xcframework" -exec cp -r {} . \; || exit 1 +find ${BASEDIR}/../../ffmpeg-kit/prebuilt/bundle-apple-xcframework-tvos -name "*.xcframework" -exec cp -R {} . \; || exit 1 diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS.xcodeproj/project.pbxproj b/tvos/test-app-cocoapods/FFmpegKitTVOS.xcodeproj/project.pbxproj index b56a0e0..c7dc0a1 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS.xcodeproj/project.pbxproj +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS.xcodeproj/project.pbxproj @@ -209,6 +209,7 @@ 34695E8222AD292000889D20 /* Sources */, 34695E8322AD292000889D20 /* Frameworks */, 34695E8422AD292000889D20 /* Resources */, + 88D45C54E3099FB6CA581C5D /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -294,6 +295,38 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 88D45C54E3099FB6CA581C5D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-FFmpegKitTVOS/Pods-FFmpegKitTVOS-frameworks.sh", + "${PODS_ROOT}/ffmpeg-kit-tvos-full/ffmpegkit.framework", + "${PODS_ROOT}/ffmpeg-kit-tvos-full/libavcodec.framework", + "${PODS_ROOT}/ffmpeg-kit-tvos-full/libavdevice.framework", + "${PODS_ROOT}/ffmpeg-kit-tvos-full/libavfilter.framework", + "${PODS_ROOT}/ffmpeg-kit-tvos-full/libavformat.framework", + "${PODS_ROOT}/ffmpeg-kit-tvos-full/libavutil.framework", + "${PODS_ROOT}/ffmpeg-kit-tvos-full/libswresample.framework", + "${PODS_ROOT}/ffmpeg-kit-tvos-full/libswscale.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ffmpegkit.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavcodec.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavdevice.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavfilter.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavformat.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libavutil.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libswresample.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libswscale.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FFmpegKitTVOS/Pods-FFmpegKitTVOS-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate b/tvos/test-app-cocoapods/FFmpegKitTVOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate index 260dd4d..5442a71 100644 Binary files a/tvos/test-app-cocoapods/FFmpegKitTVOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate and b/tvos/test-app-cocoapods/FFmpegKitTVOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/AppDelegate.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/AppDelegate.m index 040fa0c..27272d1 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/AppDelegate.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/AppDelegate.m @@ -35,7 +35,7 @@ @interface AppDelegate () @implementation AppDelegate + (void)listFFprobeSessions { - NSArray* ffprobeSessions = [FFprobeKit listSessions]; + NSArray* ffprobeSessions = [FFprobeKit listFFprobeSessions]; NSLog(@"Listing FFprobe sessions.\n"); diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/AudioViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/AudioViewController.m index 3312cd3..4d1960d 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/AudioViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/AudioViewController.m @@ -98,7 +98,7 @@ - (IBAction)encodeAudio:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/CommandViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/CommandViewController.m index ab8a677..17bb8aa 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/CommandViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/CommandViewController.m @@ -71,13 +71,13 @@ - (IBAction)runFFmpeg:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self withTitle:@"Error" message:@"Command failed. Please check output for the details." andButtonText:@"OK"]; }); @@ -100,7 +100,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process started with arguments\n'%@'.\n", ffprobeCommand); - FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withExecuteCallback:^(id session) { + FFprobeSession *session = [[FFprobeSession alloc] init:[FFmpegKitConfig parseArguments:ffprobeCommand] withCompleteCallback:^(FFprobeSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; @@ -110,7 +110,7 @@ - (IBAction)runFFprobe:(id)sender { NSLog(@"FFprobe process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:state], returnCode, notNull([session getFailStackTrace], @"\n")); - if (state == SessionStateFailed || !returnCode.isSuccess) { + if (state == SessionStateFailed || !returnCode.isValueSuccess) { addUIAction(^{ [Util alert:self withTitle:@"Error" message:@"Command failed. Please check output for the details." andButtonText:@"OK"]; }); diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/ConcurrentExecutionViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/ConcurrentExecutionViewController.m index 07e0cff..c3f8d80 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/ConcurrentExecutionViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/ConcurrentExecutionViewController.m @@ -121,7 +121,7 @@ - (void)encodeVideo:(int)buttonNumber { NSLog(@"FFmpeg process starting for button %d with arguments\n'%@'.\n", buttonNumber, ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/FFmpegKitTest.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/FFmpegKitTest.m index 122a499..81b1bd7 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/FFmpegKitTest.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/FFmpegKitTest.m @@ -192,9 +192,9 @@ void testParseDoubleQuotesAndEscapesInCommand() { void getSessionIdTest() { NSArray *TEST_ARGUMENTS = [[NSArray alloc] initWithObjects:@"argument1", @"argument2", nil]; - FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; - MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withExecuteCallback:nil]; + FFmpegSession *sessions1 = [[FFmpegSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + FFprobeSession *sessions2 = [[FFprobeSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; + MediaInformationSession *sessions3 = [[MediaInformationSession alloc] init:TEST_ARGUMENTS withCompleteCallback:nil]; assert([sessions3 getSessionId] > [sessions2 getSessionId]); assert([sessions3 getSessionId] > [sessions1 getSessionId]); diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/HttpsViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/HttpsViewController.m index 849c307..0e90afc 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/HttpsViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/HttpsViewController.m @@ -113,7 +113,7 @@ - (void)runGetMediaInformation:(int)buttonNumber { [self clearOutput]; } - [FFprobeKit getMediaInformationAsync:testUrl withExecuteCallback:[self createNewExecuteCallback]]; + [FFprobeKit getMediaInformationAsync:testUrl withCompleteCallback:[self createNewCompleteCallback]]; } - (void)setActive { @@ -146,11 +146,11 @@ - (NSString*)getRandomTestUrl { } } -- (ExecuteCallback)createNewExecuteCallback { - return ^(id session){ +- (MediaInformationSessionCompleteCallback)createNewCompleteCallback { + return ^(MediaInformationSession* session){ addUIAction(^{ @synchronized (self->outputLock) { - MediaInformation *information = [((MediaInformationSession*) session) getMediaInformation]; + MediaInformation *information = [session getMediaInformation]; if (information == nil) { [self appendOutput:@"Get media information failed\n"]; [self appendOutput:[NSString stringWithFormat:@"State: %@\n", [FFmpegKitConfig sessionStateToString:[session getState]]]]; @@ -176,7 +176,7 @@ - (ExecuteCallback)createNewExecuteCallback { if ([information getTags] != nil) { NSDictionary* tags = [information getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Tag: %@:%@\n", key, [tags objectForKey:key]]]; } } if ([information getStreams] != nil) { @@ -239,7 +239,35 @@ - (ExecuteCallback)createNewExecuteCallback { if ([stream getTags] != nil) { NSDictionary* tags = [stream getTags]; for(NSString *key in [tags allKeys]) { - [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@", key, [tags objectForKey:key]]]; + [self appendOutput:[NSString stringWithFormat:@"Stream tag: %@:%@\n", key, [tags objectForKey:key]]]; + } + } + } + } + if ([information getChapters] != nil) { + for (Chapter* chapter in [information getChapters]) { + if ([chapter getId] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter id: %@\n", [chapter getId]]]; + } + if ([chapter getTimeBase] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter time base: %@\n", [chapter getTimeBase]]]; + } + if ([chapter getStart] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start: %@\n", [chapter getStart]]]; + } + if ([chapter getStartTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter start time: %@\n", [chapter getStartTime]]]; + } + if ([chapter getEnd] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end: %@\n", [chapter getEnd]]]; + } + if ([chapter getEndTime] != nil) { + [self appendOutput:[NSString stringWithFormat:@"Chapter end time: %@\n", [chapter getEndTime]]]; + } + if ([chapter getTags] != nil) { + NSDictionary* tags = [chapter getTags]; + for(NSString *key in [tags allKeys]) { + [self appendOutput:[NSString stringWithFormat:@"Chapter tag: %@:%@\n", key, [tags objectForKey:key]]]; } } } diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/MediaInformationParserTest.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/MediaInformationParserTest.m index f9071f1..2cabe99 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/MediaInformationParserTest.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/MediaInformationParserTest.m @@ -75,6 +75,85 @@ static void initTests() { " }\n" " }\n" " ],\n" + " \"chapters\": [\n" + " {\n" + " \"id\": 0,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 0,\n" + " \"start_time\": \"0.000000\",\n" + " \"end\": 11158238,\n" + " \"end_time\": \"506.042540\",\n" + " \"tags\": {\n" + " \"title\": \"1 Laying Plans - 2 Waging War\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 1,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 11158238,\n" + " \"start_time\": \"506.042540\",\n" + " \"end\": 21433051,\n" + " \"end_time\": \"972.020454\",\n" + " \"tags\": {\n" + " \"title\": \"3 Attack By Stratagem - 4 Tactical Dispositions\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 2,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 21433051,\n" + " \"start_time\": \"972.020454\",\n" + " \"end\": 35478685,\n" + " \"end_time\": \"1609.010658\",\n" + " \"tags\": {\n" + " \"title\": \"5 Energy - 6 Weak Points and Strong\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 3,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 35478685,\n" + " \"start_time\": \"1609.010658\",\n" + " \"end\": 47187043,\n" + " \"end_time\": \"2140.001950\",\n" + " \"tags\": {\n" + " \"title\": \"7 Maneuvering - 8 Variation in Tactics\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 4,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 47187043,\n" + " \"start_time\": \"2140.001950\",\n" + " \"end\": 66635594,\n" + " \"end_time\": \"3022.022404\",\n" + " \"tags\": {\n" + " \"title\": \"9 The Army on the March - 10 Terrain\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 5,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 66635594,\n" + " \"start_time\": \"3022.022404\",\n" + " \"end\": 83768105,\n" + " \"end_time\": \"3799.007029\",\n" + " \"tags\": {\n" + " \"title\": \"11 The Nine Situations\"\n" + " }\n" + " },\n" + " {\n" + " \"id\": 6,\n" + " \"time_base\": \"1/22050\",\n" + " \"start\": 83768105,\n" + " \"start_time\": \"3799.007029\",\n" + " \"end\": 95659008,\n" + " \"end_time\": \"4338.277007\",\n" + " \"tags\": {\n" + " \"title\": \"12 The Attack By Fire - 13 The Use of Spies\"\n" + " }\n" + " }\n" + " ],\n" " \"format\": {\n" " \"filename\": \"sample.mp3\",\n" " \"nb_streams\": 1,\n" @@ -448,6 +527,10 @@ static void initTests() { } +void assertNotNull(NSObject *object) { + assert(object != nil); +} + void assertNumber(NSNumber *expected, NSNumber *real) { if (expected == nil) { assert(real == nil); @@ -501,8 +584,21 @@ void assertAudioStream(StreamInformation *stream, NSNumber *index, NSString *cod assertString(bitrate, [stream getBitrate]); } -void assertNotNull(NSObject *object) { - assert(object != nil); +void assertChapter(Chapter *chapter, NSNumber *id, NSString *timeBase, NSNumber *start, NSString * startTime, NSNumber *end, NSString *endTime) { + assert(chapter != nil); + assertNumber(id, [chapter getId]); + assertString(timeBase, [chapter getTimeBase]); + + assertNumber(start, [chapter getStart]); + assertString(startTime, [chapter getStartTime]); + + assertNumber(end, [chapter getEnd]); + assertString(endTime, [chapter getEndTime]); + + NSDictionary *tags = [chapter getTags]; + assertNotNull(tags); + + assert(1 == [tags count]); } void assertMediaInput(MediaInformation *mediaInformation, NSString *expectedFormat, NSString *expectedFilename) { @@ -579,6 +675,13 @@ void testMediaInformationMp3() { assert(1 == [streams count]); assertAudioStream([streams objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"mp3", @"MP3 (MPEG audio layer 3)", @"44100", @"stereo", @"fltp", @"320000"); + + NSArray *chapters = [mediaInformation getChapters]; + assertNotNull(chapters); + assert(7 == [chapters count]); + + assertChapter([chapters objectAtIndex:0], [[NSNumber alloc] initWithInt:0], @"1/22050", [[NSNumber alloc] initWithInt:0], @"0.000000", [[NSNumber alloc] initWithInt:11158238], @"506.042540"); + assertChapter([chapters objectAtIndex:1], [[NSNumber alloc] initWithInt:1], @"1/22050", [[NSNumber alloc] initWithInt:11158238], @"506.042540", [[NSNumber alloc] initWithInt:21433051], @"972.020454"); } void testMediaInformationJpg() { diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/OtherViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/OtherViewController.m index 06ad0c2..99feea4 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/OtherViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/OtherViewController.m @@ -23,6 +23,7 @@ #include #include #include "OtherViewController.h" +#include "Video.h" @interface OtherViewController () @@ -64,6 +65,8 @@ - (IBAction)runTest:(id)sender { [self testDav1d]; } else if ([selectedTest isEqualToString:@"webp"]) { [self testWebp]; + } else if ([selectedTest isEqualToString:@"zscale"]) { + [self testZscale]; } } @@ -77,7 +80,7 @@ -(void)testChromaprint { NSLog(@"Creating audio sample with '%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -89,7 +92,7 @@ -(void)testChromaprint { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", chromaprintCommand); - [FFmpegKit executeAsync:chromaprintCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:chromaprintCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -109,7 +112,7 @@ -(void)testDav1d { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); } withLogCallback:^(Log *log) { addUIAction(^{ @@ -130,7 +133,29 @@ -(void)testWebp { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { + + NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); + + } withLogCallback:^(Log *log) { + addUIAction(^{ + [self appendOutput: [log getMessage]]; + }); + } withStatisticsCallback:nil]; +} + +-(void)testZscale { + NSString* docFolder = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; + NSString *videoFile = [docFolder stringByAppendingPathComponent: @"video.mp4"]; + NSString *zscaledVideoFile = [docFolder stringByAppendingPathComponent: @"video.zscaled.mp4"]; + + NSLog(@"Testing 'zscale' filter with video file created on the Video tab\n"); + + NSString *ffmpegCommand = [Video generateZscaleVideoScript:videoFile:zscaledVideoFile]; + + NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); + + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/PipeViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/PipeViewController.m index 7960198..ad98527 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/PipeViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/PipeViewController.m @@ -175,7 +175,7 @@ - (IBAction)createVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/SubtitleViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/SubtitleViewController.m index f1f4962..1cc3aa1 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/SubtitleViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/SubtitleViewController.m @@ -135,7 +135,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = CreatingState; - sessionId = [[FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + sessionId = [[FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); @@ -156,7 +156,7 @@ - (IBAction)burnSubtitles:(id)sender { self->state = BurningState; - [FFmpegKit executeAsync:burnSubtitlesCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:burnSubtitlesCommand withCompleteCallback:^(id secondSession) { addUIAction(^{ [self hideProgressDialog]; diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/VidStabViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/VidStabViewController.m index c5b5836..66a6ec3 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/VidStabViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/VidStabViewController.m @@ -125,7 +125,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[session getState]], [session getReturnCode], notNull([session getFailStackTrace], @"\n")); addUIAction(^{ @@ -143,7 +143,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", analyzeVideoCommand); - [FFmpegKit executeAsync:analyzeVideoCommand withExecuteCallback:^(id secondSession) { + [FFmpegKit executeAsync:analyzeVideoCommand withCompleteCallback:^(id secondSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[secondSession getState]], [secondSession getReturnCode], notNull([secondSession getFailStackTrace], @"\n")); @@ -153,7 +153,7 @@ - (IBAction)stabilizedVideo:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", stabilizeVideoCommand); - [FFmpegKit executeAsync:stabilizeVideoCommand withExecuteCallback:^(id thirdSession) { + [FFmpegKit executeAsync:stabilizeVideoCommand withCompleteCallback:^(id thirdSession) { NSLog(@"FFmpeg process exited with state %@ and rc %@.%@", [FFmpegKitConfig sessionStateToString:[thirdSession getState]], [thirdSession getReturnCode], notNull([thirdSession getFailStackTrace], @"\n")); diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/Video.h b/tvos/test-app-cocoapods/FFmpegKitTVOS/Video.h index 7aa0a6c..977f2ef 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/Video.h +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/Video.h @@ -31,8 +31,12 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions; ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions; + + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile; ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath; + @end #endif /* FFMPEG_KIT_TEST_VIDEO */ diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/Video.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/Video.m index 0778874..f910e28 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/Video.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/Video.m @@ -48,6 +48,10 @@ + (NSString*)generateCreateVideoWithPipesScript:(NSString *)image1 :(NSString *) } + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)customOptions { + return [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:videoCodec:@"yuv420p":customOptions]; +} + ++ (NSString*)generateVideoEncodeScriptWithCustomPixelFormat:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile :(NSString *)videoCodec :(NSString *)pixelFormat :(NSString *)customOptions { return [NSString stringWithFormat: @"-hide_banner -y -loop 1 -i %@ \ -loop 1 -i %@ \ @@ -66,8 +70,8 @@ + (NSString*)generateVideoEncodeScript:(NSString *)image1 :(NSString *)image2 :( [stream2ending]fade=t=out:s=0:n=30[stream2fadeout];\ [stream2fadein][stream1fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream2blended];\ [stream3fadein][stream2fadeout]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2,trim=duration=1,select=lte(n\\,30)[stream3blended];\ -[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=yuv420p[video]\" \ --map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, customOptions, videoCodec, videoFile]; +[stream1overlaid][stream2blended][stream2overlaid][stream3blended][stream3overlaid]concat=n=5:v=1:a=0,scale=w=640:h=424,format=%@[video]\" \ +-map [video] -vsync 2 -async 1 %@-c:v %@ -r 30 %@", image1, image2, image3, pixelFormat, customOptions, videoCodec, videoFile]; } + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 :(NSString *)image3 :(NSString *)videoFile { @@ -90,4 +94,8 @@ + (NSString*)generateShakingVideoScript:(NSString *)image1 :(NSString *)image2 : -map [video] -vsync 2 -async 1 -c:v mpeg4 -r 30 %@", image1, image2, image3, videoFile]; } ++ (NSString*)generateZscaleVideoScript:(NSString *)inputVideoFilePath :(NSString *)outputVideoFilePath { + return [NSString stringWithFormat:@"-y -i %@ -vf zscale=tin=smpte2084:min=bt2020nc:pin=bt2020:rin=tv:t=smpte2084:m=bt2020nc:p=bt2020:r=tv,zscale=t=linear,tonemap=tonemap=clip,zscale=t=bt709,format=yuv420p %@", inputVideoFilePath, outputVideoFilePath]; +} + @end diff --git a/tvos/test-app-cocoapods/FFmpegKitTVOS/VideoViewController.m b/tvos/test-app-cocoapods/FFmpegKitTVOS/VideoViewController.m index 7e3b103..31f43fb 100644 --- a/tvos/test-app-cocoapods/FFmpegKitTVOS/VideoViewController.m +++ b/tvos/test-app-cocoapods/FFmpegKitTVOS/VideoViewController.m @@ -109,11 +109,11 @@ - (IBAction)encodeVideo:(id)sender { [self showProgressDialog:@"Encoding video\n\n"]; - NSString* ffmpegCommand = [Video generateVideoEncodeScript:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getCustomOptions]]; + NSString* ffmpegCommand = [Video generateVideoEncodeScriptWithCustomPixelFormat:image1:image2:image3:videoFile:[self getSelectedVideoCodec]:[self getPixelFormat]:[self getCustomOptions]]; NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - id session = [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session){ + FFmpegSession* session = [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session){ SessionState state = [session getState]; ReturnCode *returnCode = [session getReturnCode]; @@ -164,6 +164,19 @@ - (void)playVideo { [player insertItem:newVideo afterItem:nil]; } +- (NSString*)getPixelFormat { + NSString *videoCodec = [self.videoCodecText text]; + + NSString *pixelFormat; + if ([videoCodec isEqualToString:@"x265"]) { + pixelFormat = @"yuv420p10le"; + } else { + pixelFormat = @"yuv420p"; + } + + return pixelFormat; +} + - (NSString*)getSelectedVideoCodec { NSString *videoCodec = [self.videoCodecText text]; diff --git a/tvos/test-app-cocoapods/Podfile b/tvos/test-app-cocoapods/Podfile index c96f4d5..3584caa 100644 --- a/tvos/test-app-cocoapods/Podfile +++ b/tvos/test-app-cocoapods/Podfile @@ -3,5 +3,5 @@ platform :tvos, '10.2' use_frameworks! target "FFmpegKitTVOS" do - pod 'ffmpeg-kit-tvos-full', '4.5' + pod 'ffmpeg-kit-tvos-full', '4.5.1.LTS' end diff --git a/tvos/test-app-cocoapods/Podfile.lock b/tvos/test-app-cocoapods/Podfile.lock index 71cbb9d..3f516c9 100644 --- a/tvos/test-app-cocoapods/Podfile.lock +++ b/tvos/test-app-cocoapods/Podfile.lock @@ -1,16 +1,16 @@ PODS: - - ffmpeg-kit-tvos-full (4.5) + - ffmpeg-kit-tvos-full (4.5.1.LTS) DEPENDENCIES: - - ffmpeg-kit-tvos-full (= 4.5) + - ffmpeg-kit-tvos-full (= 4.5.1.LTS) SPEC REPOS: trunk: - ffmpeg-kit-tvos-full SPEC CHECKSUMS: - ffmpeg-kit-tvos-full: 497f584341421ee3c58a0cdb874f1d516b79c4fe + ffmpeg-kit-tvos-full: 97d802696cbcc29a08c3d6b0dc461eb6eb2fb9e6 -PODFILE CHECKSUM: a4a33809a239849498d8a1bd52857b295cde10f5 +PODFILE CHECKSUM: a6b09ab19b0863fa198b8dc4104ec338c649dd3b COCOAPODS: 1.11.2 diff --git a/tvos/test-app-local-dependency/FFmpegKitTVOS.xcodeproj/project.pbxproj b/tvos/test-app-local-dependency/FFmpegKitTVOS.xcodeproj/project.pbxproj index 1e893ff..a9bec3f 100644 --- a/tvos/test-app-local-dependency/FFmpegKitTVOS.xcodeproj/project.pbxproj +++ b/tvos/test-app-local-dependency/FFmpegKitTVOS.xcodeproj/project.pbxproj @@ -7,57 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 34314A3526F679EC00D16670 /* kvazaar.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0226F679EB00D16670 /* kvazaar.xcframework */; }; - 34314A3626F679EC00D16670 /* libtheora.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0326F679EB00D16670 /* libtheora.xcframework */; }; - 34314A3726F679EC00D16670 /* libtheoraenc.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0426F679EB00D16670 /* libtheoraenc.xcframework */; }; - 34314A3826F679EC00D16670 /* vo-amrwbenc.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0526F679EB00D16670 /* vo-amrwbenc.xcframework */; }; - 34314A3926F679EC00D16670 /* libxml2.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0626F679EB00D16670 /* libxml2.xcframework */; }; - 34314A3A26F679EC00D16670 /* libswresample.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0726F679EB00D16670 /* libswresample.xcframework */; }; - 34314A3B26F679EC00D16670 /* libhogweed.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0826F679EB00D16670 /* libhogweed.xcframework */; }; - 34314A3C26F679EC00D16670 /* libavutil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0926F679EB00D16670 /* libavutil.xcframework */; }; - 34314A3D26F679EC00D16670 /* libavfilter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0A26F679EB00D16670 /* libavfilter.xcframework */; }; - 34314A3E26F679EC00D16670 /* libswscale.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0B26F679EB00D16670 /* libswscale.xcframework */; }; - 34314A3F26F679EC00D16670 /* opus.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0C26F679EB00D16670 /* opus.xcframework */; }; - 34314A4026F679EC00D16670 /* libavcodec.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0D26F679EB00D16670 /* libavcodec.xcframework */; }; - 34314A4126F679EC00D16670 /* libnettle.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0E26F679EB00D16670 /* libnettle.xcframework */; }; - 34314A4226F679EC00D16670 /* libvpx.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A0F26F679EB00D16670 /* libvpx.xcframework */; }; - 34314A4326F679EC00D16670 /* lame.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1026F679EB00D16670 /* lame.xcframework */; }; - 34314A4426F679EC00D16670 /* xvidcore.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1126F679EB00D16670 /* xvidcore.xcframework */; }; - 34314A4526F679EC00D16670 /* libvidstab.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1226F679EB00D16670 /* libvidstab.xcframework */; }; - 34314A4626F679EC00D16670 /* ffmpegkit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1326F679EB00D16670 /* ffmpegkit.xcframework */; }; - 34314A4726F679EC00D16670 /* shine.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1426F679EB00D16670 /* shine.xcframework */; }; - 34314A4826F679EC00D16670 /* x265.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1526F679EB00D16670 /* x265.xcframework */; }; - 34314A4926F679EC00D16670 /* jpeg.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1626F679EB00D16670 /* jpeg.xcframework */; }; - 34314A4A26F679EC00D16670 /* x264.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1726F679EB00D16670 /* x264.xcframework */; }; - 34314A4B26F679EC00D16670 /* libvorbis.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1826F679EB00D16670 /* libvorbis.xcframework */; }; - 34314A4C26F679EC00D16670 /* fribidi.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1926F679EB00D16670 /* fribidi.xcframework */; }; - 34314A4D26F679EC00D16670 /* giflib.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1A26F679EB00D16670 /* giflib.xcframework */; }; - 34314A4E26F679EC00D16670 /* libtheoradec.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1B26F679EB00D16670 /* libtheoradec.xcframework */; }; - 34314A4F26F679EC00D16670 /* dav1d.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1C26F679EB00D16670 /* dav1d.xcframework */; }; - 34314A5026F679EC00D16670 /* libwebpdemux.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1D26F679EB00D16670 /* libwebpdemux.xcframework */; }; - 34314A5126F679EC00D16670 /* libogg.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1E26F679EB00D16670 /* libogg.xcframework */; }; - 34314A5226F679EC00D16670 /* libavdevice.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A1F26F679EB00D16670 /* libavdevice.xcframework */; }; - 34314A5326F679EC00D16670 /* expat.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2026F679EB00D16670 /* expat.xcframework */; }; - 34314A5426F679EC00D16670 /* gmp.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2126F679EB00D16670 /* gmp.xcframework */; }; - 34314A5526F679ED00D16670 /* speex.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2226F679EB00D16670 /* speex.xcframework */; }; - 34314A5626F679ED00D16670 /* libavformat.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2326F679EB00D16670 /* libavformat.xcframework */; }; - 34314A5726F679ED00D16670 /* libilbc.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2426F679EB00D16670 /* libilbc.xcframework */; }; - 34314A5826F679ED00D16670 /* libvorbisfile.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2526F679EB00D16670 /* libvorbisfile.xcframework */; }; - 34314A5926F679ED00D16670 /* snappy.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2626F679EB00D16670 /* snappy.xcframework */; }; - 34314A5A26F679ED00D16670 /* libass.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2726F679EB00D16670 /* libass.xcframework */; }; - 34314A5B26F679ED00D16670 /* tiff.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2826F679EB00D16670 /* tiff.xcframework */; }; - 34314A5C26F679ED00D16670 /* soxr.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2926F679EB00D16670 /* soxr.xcframework */; }; - 34314A5D26F679ED00D16670 /* freetype.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2A26F679EC00D16670 /* freetype.xcframework */; }; - 34314A5E26F679ED00D16670 /* twolame.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2B26F679EC00D16670 /* twolame.xcframework */; }; - 34314A5F26F679ED00D16670 /* fontconfig.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2C26F679EC00D16670 /* fontconfig.xcframework */; }; - 34314A6026F679ED00D16670 /* libpng.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2D26F679EC00D16670 /* libpng.xcframework */; }; - 34314A6126F679ED00D16670 /* libwebp.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2E26F679EC00D16670 /* libwebp.xcframework */; }; - 34314A6226F679ED00D16670 /* gnutls.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A2F26F679EC00D16670 /* gnutls.xcframework */; }; - 34314A6326F679ED00D16670 /* libvorbisenc.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A3026F679EC00D16670 /* libvorbisenc.xcframework */; }; - 34314A6426F679ED00D16670 /* libwebpmux.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A3126F679EC00D16670 /* libwebpmux.xcframework */; }; - 34314A6526F679ED00D16670 /* libopencore-amrnb.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A3226F679EC00D16670 /* libopencore-amrnb.xcframework */; }; - 34314A6626F679ED00D16670 /* libsndfile.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A3326F679EC00D16670 /* libsndfile.xcframework */; }; - 34314A6726F679ED00D16670 /* harfbuzz.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34314A3426F679EC00D16670 /* harfbuzz.xcframework */; }; 344D0ED222DE40F200DC2568 /* MediaInformationParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 344D0ED022DE40F200DC2568 /* MediaInformationParserTest.m */; }; 344D0ED522DE40F800DC2568 /* FFmpegKitTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 344D0ED322DE40F800DC2568 /* FFmpegKitTest.m */; }; 34695E8A22AD292100889D20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 34695E8922AD292100889D20 /* AppDelegate.m */; }; @@ -80,6 +29,22 @@ 3494910825E1980B0017F7CC /* Video.m in Sources */ = {isa = PBXBuildFile; fileRef = 3494910625E1980B0017F7CC /* Video.m */; }; 3494910D25E19B1A0017F7CC /* OtherViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3494910B25E19B1A0017F7CC /* OtherViewController.m */; }; 3494911325E1A2410017F7CC /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3494911225E1A2410017F7CC /* Accelerate.framework */; }; + 34A33AB4273B1D700087F971 /* ffmpegkit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AAC273B1D700087F971 /* ffmpegkit.xcframework */; }; + 34A33AB5273B1D700087F971 /* libavfilter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AAD273B1D700087F971 /* libavfilter.xcframework */; }; + 34A33AB6273B1D700087F971 /* libswresample.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AAE273B1D700087F971 /* libswresample.xcframework */; }; + 34A33AB7273B1D700087F971 /* libavcodec.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AAF273B1D700087F971 /* libavcodec.xcframework */; }; + 34A33AB8273B1D700087F971 /* libswscale.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AB0273B1D700087F971 /* libswscale.xcframework */; }; + 34A33AB9273B1D700087F971 /* libavformat.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AB1273B1D700087F971 /* libavformat.xcframework */; }; + 34A33ABA273B1D700087F971 /* libavdevice.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AB2273B1D700087F971 /* libavdevice.xcframework */; }; + 34A33ABB273B1D700087F971 /* libavutil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AB3273B1D700087F971 /* libavutil.xcframework */; }; + 34A33ABC273B1D790087F971 /* ffmpegkit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AAC273B1D700087F971 /* ffmpegkit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33ABD273B1D790087F971 /* libavcodec.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AAF273B1D700087F971 /* libavcodec.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33ABE273B1D790087F971 /* libavdevice.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AB2273B1D700087F971 /* libavdevice.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33ABF273B1D790087F971 /* libavfilter.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AAD273B1D700087F971 /* libavfilter.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AC0273B1D790087F971 /* libavformat.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AB1273B1D700087F971 /* libavformat.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AC1273B1D790087F971 /* libavutil.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AB3273B1D700087F971 /* libavutil.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AC2273B1D790087F971 /* libswresample.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AAE273B1D700087F971 /* libswresample.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 34A33AC3273B1D790087F971 /* libswscale.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 34A33AB0273B1D700087F971 /* libswscale.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 34C06BF922AD70C40039DF48 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C06BF822AD70C30039DF48 /* VideoToolbox.framework */; }; 34C06BFB22AD70CD0039DF48 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C06BFA22AD70CD0039DF48 /* libc++.tbd */; }; 34C06BFD22AD70D60039DF48 /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C06BFC22AD70D60039DF48 /* libbz2.tbd */; }; @@ -94,58 +59,28 @@ 34E281A624A5686C0048B3EC /* ConcurrentExecutionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E281A524A5686C0048B3EC /* ConcurrentExecutionViewController.m */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + 34416D5D2734B4C800F225A0 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 34A33ABC273B1D790087F971 /* ffmpegkit.xcframework in Embed Frameworks */, + 34A33ABD273B1D790087F971 /* libavcodec.xcframework in Embed Frameworks */, + 34A33ABE273B1D790087F971 /* libavdevice.xcframework in Embed Frameworks */, + 34A33ABF273B1D790087F971 /* libavfilter.xcframework in Embed Frameworks */, + 34A33AC0273B1D790087F971 /* libavformat.xcframework in Embed Frameworks */, + 34A33AC1273B1D790087F971 /* libavutil.xcframework in Embed Frameworks */, + 34A33AC2273B1D790087F971 /* libswresample.xcframework in Embed Frameworks */, + 34A33AC3273B1D790087F971 /* libswscale.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ - 34314A0226F679EB00D16670 /* kvazaar.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = kvazaar.xcframework; sourceTree = ""; }; - 34314A0326F679EB00D16670 /* libtheora.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libtheora.xcframework; sourceTree = ""; }; - 34314A0426F679EB00D16670 /* libtheoraenc.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libtheoraenc.xcframework; sourceTree = ""; }; - 34314A0526F679EB00D16670 /* vo-amrwbenc.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = "vo-amrwbenc.xcframework"; sourceTree = ""; }; - 34314A0626F679EB00D16670 /* libxml2.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libxml2.xcframework; sourceTree = ""; }; - 34314A0726F679EB00D16670 /* libswresample.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libswresample.xcframework; sourceTree = ""; }; - 34314A0826F679EB00D16670 /* libhogweed.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libhogweed.xcframework; sourceTree = ""; }; - 34314A0926F679EB00D16670 /* libavutil.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavutil.xcframework; sourceTree = ""; }; - 34314A0A26F679EB00D16670 /* libavfilter.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavfilter.xcframework; sourceTree = ""; }; - 34314A0B26F679EB00D16670 /* libswscale.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libswscale.xcframework; sourceTree = ""; }; - 34314A0C26F679EB00D16670 /* opus.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = opus.xcframework; sourceTree = ""; }; - 34314A0D26F679EB00D16670 /* libavcodec.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavcodec.xcframework; sourceTree = ""; }; - 34314A0E26F679EB00D16670 /* libnettle.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libnettle.xcframework; sourceTree = ""; }; - 34314A0F26F679EB00D16670 /* libvpx.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libvpx.xcframework; sourceTree = ""; }; - 34314A1026F679EB00D16670 /* lame.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = lame.xcframework; sourceTree = ""; }; - 34314A1126F679EB00D16670 /* xvidcore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = xvidcore.xcframework; sourceTree = ""; }; - 34314A1226F679EB00D16670 /* libvidstab.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libvidstab.xcframework; sourceTree = ""; }; - 34314A1326F679EB00D16670 /* ffmpegkit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = ffmpegkit.xcframework; sourceTree = ""; }; - 34314A1426F679EB00D16670 /* shine.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = shine.xcframework; sourceTree = ""; }; - 34314A1526F679EB00D16670 /* x265.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = x265.xcframework; sourceTree = ""; }; - 34314A1626F679EB00D16670 /* jpeg.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = jpeg.xcframework; sourceTree = ""; }; - 34314A1726F679EB00D16670 /* x264.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = x264.xcframework; sourceTree = ""; }; - 34314A1826F679EB00D16670 /* libvorbis.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libvorbis.xcframework; sourceTree = ""; }; - 34314A1926F679EB00D16670 /* fribidi.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = fribidi.xcframework; sourceTree = ""; }; - 34314A1A26F679EB00D16670 /* giflib.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = giflib.xcframework; sourceTree = ""; }; - 34314A1B26F679EB00D16670 /* libtheoradec.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libtheoradec.xcframework; sourceTree = ""; }; - 34314A1C26F679EB00D16670 /* dav1d.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = dav1d.xcframework; sourceTree = ""; }; - 34314A1D26F679EB00D16670 /* libwebpdemux.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libwebpdemux.xcframework; sourceTree = ""; }; - 34314A1E26F679EB00D16670 /* libogg.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libogg.xcframework; sourceTree = ""; }; - 34314A1F26F679EB00D16670 /* libavdevice.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavdevice.xcframework; sourceTree = ""; }; - 34314A2026F679EB00D16670 /* expat.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = expat.xcframework; sourceTree = ""; }; - 34314A2126F679EB00D16670 /* gmp.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = gmp.xcframework; sourceTree = ""; }; - 34314A2226F679EB00D16670 /* speex.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = speex.xcframework; sourceTree = ""; }; - 34314A2326F679EB00D16670 /* libavformat.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavformat.xcframework; sourceTree = ""; }; - 34314A2426F679EB00D16670 /* libilbc.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libilbc.xcframework; sourceTree = ""; }; - 34314A2526F679EB00D16670 /* libvorbisfile.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libvorbisfile.xcframework; sourceTree = ""; }; - 34314A2626F679EB00D16670 /* snappy.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = snappy.xcframework; sourceTree = ""; }; - 34314A2726F679EB00D16670 /* libass.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libass.xcframework; sourceTree = ""; }; - 34314A2826F679EB00D16670 /* tiff.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = tiff.xcframework; sourceTree = ""; }; - 34314A2926F679EB00D16670 /* soxr.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = soxr.xcframework; sourceTree = ""; }; - 34314A2A26F679EC00D16670 /* freetype.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = freetype.xcframework; sourceTree = ""; }; - 34314A2B26F679EC00D16670 /* twolame.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = twolame.xcframework; sourceTree = ""; }; - 34314A2C26F679EC00D16670 /* fontconfig.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = fontconfig.xcframework; sourceTree = ""; }; - 34314A2D26F679EC00D16670 /* libpng.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libpng.xcframework; sourceTree = ""; }; - 34314A2E26F679EC00D16670 /* libwebp.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libwebp.xcframework; sourceTree = ""; }; - 34314A2F26F679EC00D16670 /* gnutls.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = gnutls.xcframework; sourceTree = ""; }; - 34314A3026F679EC00D16670 /* libvorbisenc.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libvorbisenc.xcframework; sourceTree = ""; }; - 34314A3126F679EC00D16670 /* libwebpmux.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libwebpmux.xcframework; sourceTree = ""; }; - 34314A3226F679EC00D16670 /* libopencore-amrnb.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = "libopencore-amrnb.xcframework"; sourceTree = ""; }; - 34314A3326F679EC00D16670 /* libsndfile.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libsndfile.xcframework; sourceTree = ""; }; - 34314A3426F679EC00D16670 /* harfbuzz.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = harfbuzz.xcframework; sourceTree = ""; }; 344D0ED022DE40F200DC2568 /* MediaInformationParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MediaInformationParserTest.m; sourceTree = ""; }; 344D0ED122DE40F200DC2568 /* MediaInformationParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaInformationParserTest.h; sourceTree = ""; }; 344D0ED322DE40F800DC2568 /* FFmpegKitTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FFmpegKitTest.m; sourceTree = ""; }; @@ -185,6 +120,14 @@ 3494910B25E19B1A0017F7CC /* OtherViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OtherViewController.m; sourceTree = ""; }; 3494910C25E19B1A0017F7CC /* OtherViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OtherViewController.h; sourceTree = ""; }; 3494911225E1A2410017F7CC /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; + 34A33AAC273B1D700087F971 /* ffmpegkit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = ffmpegkit.xcframework; sourceTree = ""; }; + 34A33AAD273B1D700087F971 /* libavfilter.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavfilter.xcframework; sourceTree = ""; }; + 34A33AAE273B1D700087F971 /* libswresample.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libswresample.xcframework; sourceTree = ""; }; + 34A33AAF273B1D700087F971 /* libavcodec.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavcodec.xcframework; sourceTree = ""; }; + 34A33AB0273B1D700087F971 /* libswscale.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libswscale.xcframework; sourceTree = ""; }; + 34A33AB1273B1D700087F971 /* libavformat.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavformat.xcframework; sourceTree = ""; }; + 34A33AB2273B1D700087F971 /* libavdevice.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavdevice.xcframework; sourceTree = ""; }; + 34A33AB3273B1D700087F971 /* libavutil.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = libavutil.xcframework; sourceTree = ""; }; 34C06BF822AD70C30039DF48 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; }; 34C06BFA22AD70CD0039DF48 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; 34C06BFC22AD70D60039DF48 /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; }; @@ -207,64 +150,21 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 34314A5C26F679ED00D16670 /* soxr.xcframework in Frameworks */, - 34314A5B26F679ED00D16670 /* tiff.xcframework in Frameworks */, - 34314A4B26F679EC00D16670 /* libvorbis.xcframework in Frameworks */, - 34314A5026F679EC00D16670 /* libwebpdemux.xcframework in Frameworks */, - 34314A4A26F679EC00D16670 /* x264.xcframework in Frameworks */, - 34314A4E26F679EC00D16670 /* libtheoradec.xcframework in Frameworks */, - 34314A3926F679EC00D16670 /* libxml2.xcframework in Frameworks */, - 34314A5126F679EC00D16670 /* libogg.xcframework in Frameworks */, - 34314A4626F679EC00D16670 /* ffmpegkit.xcframework in Frameworks */, + 34A33ABA273B1D700087F971 /* libavdevice.xcframework in Frameworks */, 3494911325E1A2410017F7CC /* Accelerate.framework in Frameworks */, - 34314A3D26F679EC00D16670 /* libavfilter.xcframework in Frameworks */, - 34314A4126F679EC00D16670 /* libnettle.xcframework in Frameworks */, - 34314A3E26F679EC00D16670 /* libswscale.xcframework in Frameworks */, - 34314A5826F679ED00D16670 /* libvorbisfile.xcframework in Frameworks */, - 34314A5F26F679ED00D16670 /* fontconfig.xcframework in Frameworks */, - 34314A3A26F679EC00D16670 /* libswresample.xcframework in Frameworks */, - 34314A5E26F679ED00D16670 /* twolame.xcframework in Frameworks */, - 34314A4726F679EC00D16670 /* shine.xcframework in Frameworks */, - 34314A5726F679ED00D16670 /* libilbc.xcframework in Frameworks */, - 34314A5226F679EC00D16670 /* libavdevice.xcframework in Frameworks */, - 34314A3B26F679EC00D16670 /* libhogweed.xcframework in Frameworks */, - 34314A4F26F679EC00D16670 /* dav1d.xcframework in Frameworks */, - 34314A4926F679EC00D16670 /* jpeg.xcframework in Frameworks */, - 34314A3C26F679EC00D16670 /* libavutil.xcframework in Frameworks */, - 34314A4326F679EC00D16670 /* lame.xcframework in Frameworks */, - 34314A4526F679EC00D16670 /* libvidstab.xcframework in Frameworks */, - 34314A4C26F679EC00D16670 /* fribidi.xcframework in Frameworks */, - 34314A6526F679ED00D16670 /* libopencore-amrnb.xcframework in Frameworks */, + 34A33AB4273B1D700087F971 /* ffmpegkit.xcframework in Frameworks */, 34C97E8823CB7655004F75D3 /* libiconv.tbd in Frameworks */, - 34314A6026F679ED00D16670 /* libpng.xcframework in Frameworks */, - 34314A5926F679ED00D16670 /* snappy.xcframework in Frameworks */, - 34314A6726F679ED00D16670 /* harfbuzz.xcframework in Frameworks */, - 34314A5626F679ED00D16670 /* libavformat.xcframework in Frameworks */, - 34314A5326F679EC00D16670 /* expat.xcframework in Frameworks */, - 34314A3526F679EC00D16670 /* kvazaar.xcframework in Frameworks */, + 34A33ABB273B1D700087F971 /* libavutil.xcframework in Frameworks */, 34C06C0122AD71090039DF48 /* GameController.framework in Frameworks */, - 34314A6626F679ED00D16670 /* libsndfile.xcframework in Frameworks */, + 34A33AB7273B1D700087F971 /* libavcodec.xcframework in Frameworks */, 34C06BFF22AD70E40039DF48 /* libz.tbd in Frameworks */, - 34314A3726F679EC00D16670 /* libtheoraenc.xcframework in Frameworks */, 34C06BFD22AD70D60039DF48 /* libbz2.tbd in Frameworks */, - 34314A6326F679ED00D16670 /* libvorbisenc.xcframework in Frameworks */, - 34314A5426F679EC00D16670 /* gmp.xcframework in Frameworks */, - 34314A5526F679ED00D16670 /* speex.xcframework in Frameworks */, - 34314A6226F679ED00D16670 /* gnutls.xcframework in Frameworks */, - 34314A4D26F679EC00D16670 /* giflib.xcframework in Frameworks */, - 34314A4226F679EC00D16670 /* libvpx.xcframework in Frameworks */, + 34A33AB6273B1D700087F971 /* libswresample.xcframework in Frameworks */, + 34A33AB5273B1D700087F971 /* libavfilter.xcframework in Frameworks */, + 34A33AB9273B1D700087F971 /* libavformat.xcframework in Frameworks */, 34C06BFB22AD70CD0039DF48 /* libc++.tbd in Frameworks */, - 34314A4826F679EC00D16670 /* x265.xcframework in Frameworks */, - 34314A4026F679EC00D16670 /* libavcodec.xcframework in Frameworks */, - 34314A4426F679EC00D16670 /* xvidcore.xcframework in Frameworks */, - 34314A6426F679ED00D16670 /* libwebpmux.xcframework in Frameworks */, + 34A33AB8273B1D700087F971 /* libswscale.xcframework in Frameworks */, 34C06BF922AD70C40039DF48 /* VideoToolbox.framework in Frameworks */, - 34314A3626F679EC00D16670 /* libtheora.xcframework in Frameworks */, - 34314A6126F679ED00D16670 /* libwebp.xcframework in Frameworks */, - 34314A5A26F679ED00D16670 /* libass.xcframework in Frameworks */, - 34314A3F26F679EC00D16670 /* opus.xcframework in Frameworks */, - 34314A3826F679EC00D16670 /* vo-amrwbenc.xcframework in Frameworks */, - 34314A5D26F679ED00D16670 /* freetype.xcframework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -334,60 +234,17 @@ 3498DC65209F7F1C005F5883 /* Frameworks */ = { isa = PBXGroup; children = ( + 34A33AAC273B1D700087F971 /* ffmpegkit.xcframework */, + 34A33AAF273B1D700087F971 /* libavcodec.xcframework */, + 34A33AB2273B1D700087F971 /* libavdevice.xcframework */, + 34A33AAD273B1D700087F971 /* libavfilter.xcframework */, + 34A33AB1273B1D700087F971 /* libavformat.xcframework */, + 34A33AB3273B1D700087F971 /* libavutil.xcframework */, + 34A33AAE273B1D700087F971 /* libswresample.xcframework */, + 34A33AB0273B1D700087F971 /* libswscale.xcframework */, 3494911225E1A2410017F7CC /* Accelerate.framework */, 34C97E8723CB7655004F75D3 /* libiconv.tbd */, 34C06C0022AD71090039DF48 /* GameController.framework */, - 34314A1C26F679EB00D16670 /* dav1d.xcframework */, - 34314A2026F679EB00D16670 /* expat.xcframework */, - 34314A1326F679EB00D16670 /* ffmpegkit.xcframework */, - 34314A2C26F679EC00D16670 /* fontconfig.xcframework */, - 34314A2A26F679EC00D16670 /* freetype.xcframework */, - 34314A1926F679EB00D16670 /* fribidi.xcframework */, - 34314A1A26F679EB00D16670 /* giflib.xcframework */, - 34314A2126F679EB00D16670 /* gmp.xcframework */, - 34314A2F26F679EC00D16670 /* gnutls.xcframework */, - 34314A3426F679EC00D16670 /* harfbuzz.xcframework */, - 34314A1626F679EB00D16670 /* jpeg.xcframework */, - 34314A0226F679EB00D16670 /* kvazaar.xcframework */, - 34314A1026F679EB00D16670 /* lame.xcframework */, - 34314A2726F679EB00D16670 /* libass.xcframework */, - 34314A0D26F679EB00D16670 /* libavcodec.xcframework */, - 34314A1F26F679EB00D16670 /* libavdevice.xcframework */, - 34314A0A26F679EB00D16670 /* libavfilter.xcframework */, - 34314A2326F679EB00D16670 /* libavformat.xcframework */, - 34314A0926F679EB00D16670 /* libavutil.xcframework */, - 34314A0826F679EB00D16670 /* libhogweed.xcframework */, - 34314A2426F679EB00D16670 /* libilbc.xcframework */, - 34314A0E26F679EB00D16670 /* libnettle.xcframework */, - 34314A1E26F679EB00D16670 /* libogg.xcframework */, - 34314A3226F679EC00D16670 /* libopencore-amrnb.xcframework */, - 34314A2D26F679EC00D16670 /* libpng.xcframework */, - 34314A3326F679EC00D16670 /* libsndfile.xcframework */, - 34314A0726F679EB00D16670 /* libswresample.xcframework */, - 34314A0B26F679EB00D16670 /* libswscale.xcframework */, - 34314A0326F679EB00D16670 /* libtheora.xcframework */, - 34314A1B26F679EB00D16670 /* libtheoradec.xcframework */, - 34314A0426F679EB00D16670 /* libtheoraenc.xcframework */, - 34314A1226F679EB00D16670 /* libvidstab.xcframework */, - 34314A1826F679EB00D16670 /* libvorbis.xcframework */, - 34314A3026F679EC00D16670 /* libvorbisenc.xcframework */, - 34314A2526F679EB00D16670 /* libvorbisfile.xcframework */, - 34314A0F26F679EB00D16670 /* libvpx.xcframework */, - 34314A2E26F679EC00D16670 /* libwebp.xcframework */, - 34314A1D26F679EB00D16670 /* libwebpdemux.xcframework */, - 34314A3126F679EC00D16670 /* libwebpmux.xcframework */, - 34314A0626F679EB00D16670 /* libxml2.xcframework */, - 34314A0C26F679EB00D16670 /* opus.xcframework */, - 34314A1426F679EB00D16670 /* shine.xcframework */, - 34314A2626F679EB00D16670 /* snappy.xcframework */, - 34314A2926F679EB00D16670 /* soxr.xcframework */, - 34314A2226F679EB00D16670 /* speex.xcframework */, - 34314A2826F679EB00D16670 /* tiff.xcframework */, - 34314A2B26F679EC00D16670 /* twolame.xcframework */, - 34314A0526F679EB00D16670 /* vo-amrwbenc.xcframework */, - 34314A1726F679EB00D16670 /* x264.xcframework */, - 34314A1526F679EB00D16670 /* x265.xcframework */, - 34314A1126F679EB00D16670 /* xvidcore.xcframework */, 34C06BFE22AD70E40039DF48 /* libz.tbd */, 34C06BFC22AD70D60039DF48 /* libbz2.tbd */, 34C06BFA22AD70CD0039DF48 /* libc++.tbd */, @@ -424,6 +281,7 @@ 34695E8222AD292000889D20 /* Sources */, 34695E8322AD292000889D20 /* Frameworks */, 34695E8422AD292000889D20 /* Resources */, + 34416D5D2734B4C800F225A0 /* Embed Frameworks */, ); buildRules = ( ); @@ -445,6 +303,7 @@ TargetAttributes = { 34695E8522AD292000889D20 = { CreatedOnToolsVersion = 10.2.1; + ProvisioningStyle = Automatic; }; }; }; @@ -532,7 +391,7 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 12; DEVELOPMENT_TEAM = 98GD5J4999; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -550,7 +409,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 11.3; + TVOS_DEPLOYMENT_TARGET = 9.2; }; name = Debug; }; @@ -561,7 +420,7 @@ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 4; + CURRENT_PROJECT_VERSION = 12; DEVELOPMENT_TEAM = 98GD5J4999; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -578,7 +437,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 11.3; + TVOS_DEPLOYMENT_TARGET = 9.2; }; name = Release; }; diff --git a/tvos/test-app-local-dependency/FFmpegKitTVOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate b/tvos/test-app-local-dependency/FFmpegKitTVOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate index d752b90..40fa5f8 100644 Binary files a/tvos/test-app-local-dependency/FFmpegKitTVOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate and b/tvos/test-app-local-dependency/FFmpegKitTVOS.xcworkspace/xcuserdata/taner.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/tvos/test-app-local-dependency/FFmpegKitTVOS/AppDelegate.m b/tvos/test-app-local-dependency/FFmpegKitTVOS/AppDelegate.m index 040fa0c..27272d1 100644 --- a/tvos/test-app-local-dependency/FFmpegKitTVOS/AppDelegate.m +++ b/tvos/test-app-local-dependency/FFmpegKitTVOS/AppDelegate.m @@ -35,7 +35,7 @@ @interface AppDelegate () @implementation AppDelegate + (void)listFFprobeSessions { - NSArray* ffprobeSessions = [FFprobeKit listSessions]; + NSArray* ffprobeSessions = [FFprobeKit listFFprobeSessions]; NSLog(@"Listing FFprobe sessions.\n"); diff --git a/tvos/test-app-local-dependency/FFmpegKitTVOS/AudioViewController.m b/tvos/test-app-local-dependency/FFmpegKitTVOS/AudioViewController.m index 3312cd3..4d1960d 100644 --- a/tvos/test-app-local-dependency/FFmpegKitTVOS/AudioViewController.m +++ b/tvos/test-app-local-dependency/FFmpegKitTVOS/AudioViewController.m @@ -98,7 +98,7 @@ - (IBAction)encodeAudio:(id)sender { NSLog(@"FFmpeg process started with arguments\n'%@'.\n", ffmpegCommand); - [FFmpegKit executeAsync:ffmpegCommand withExecuteCallback:^(id session) { + [FFmpegKit executeAsync:ffmpegCommand withCompleteCallback:^(FFmpegSession* session) { SessionState state = [session getState]; ReturnCode* returnCode = [session getReturnCode]; diff --git a/tvos/test-app-local-dependency/FFmpegKitTVOS/Base.lproj/Main.storyboard b/tvos/test-app-local-dependency/FFmpegKitTVOS/Base.lproj/Main.storyboard index b898e62..137dcc9 100644 --- a/tvos/test-app-local-dependency/FFmpegKitTVOS/Base.lproj/Main.storyboard +++ b/tvos/test-app-local-dependency/FFmpegKitTVOS/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -307,7 +307,7 @@ - + @@ -720,8 +720,8 @@ - + @@ -741,14 +741,14 @@ - +