Compare commits

..

12 Commits

Author SHA1 Message Date
Taner Şener 3327609fde Merge pull request #690 from alexcohn/bugfix/#634_fdsan
fixing #634
2021-03-07 11:53:53 +00:00
alexcohn bd5dfc1241 fixing #634
attempted to close file descriptor XX, expected to be unowned, actually owned by ParcelFileDescriptor XXX
2021-03-06 22:49:04 +02:00
Taner Sener 6064b7dd02 update android release script 2021-02-07 00:54:51 +00:00
Juha Heinanen 9d1aefd1ea Added --no-archive option to android.sh 2021-01-23 19:49:48 +00:00
Taner Sener 729ef3e496 fix android async example 2020-11-03 22:22:59 +00:00
Taner Sener ce3a906b4e update ios manual test application 2020-10-22 20:48:02 +01:00
Taner Sener dc4feaceb4 update android test app 2020-09-26 16:20:04 +01:00
Taner Sener 035ad8cd39 support iOS 14, fixes #553 2020-09-26 15:29:08 +01:00
Alex Cohn b898574b53 Support Android scoped storage (#440)
* introducing saf_wrapper - a transparent API to use the file descriptor via custom AVIO for saf: Url

* demonstrate how use to use SAF with some demo tabs

SAF is enabled for API 19 or higher
SAF pickers are used for FFprobe on CommandTabFragment and for video output on PipeTabFragment

* Revert "demonstrate how use to use SAF with some demo tabs"

This reverts commit 97b25815

* add SAF tab with two buttons

* change the getSafParameter handles filenames with spaces

see https://github.com/alexcohn/mobile-ffmpeg/pull/1#issuecomment-688643836

* take advantage of Cursor being Closeable

* provide NBSP in hexa, to make sure that git and editor don't destroy it

* Avoid "rw" because it may not be supported (e.g. Google Drive).

Also, some code cleanup in SafTabFragment.

* don't run FFprobe after video playback

* ACTION_GET_CONTENT is better than ACTION_OPEN_DOCUMENT: it gives us more options to choose.

* add closeParcelFileDescriptor to fix working with Google Drive

keep the temp files open, we must keep the ParcelFileDecriptor until the fd is closed
2020-09-21 22:29:22 +01:00
Pete ef39b78068 Update arch-common.sh (#534)
* Update arch-common.sh

x265 download on Bitbucket no longer works. Use GitHub link instead
2020-08-24 13:48:38 +01:00
Taner Sener 3490446b1b fix monitorWait method for android, fixes #520 2020-08-10 23:41:56 +01:00
Taner Sener 0f911a26ed reorganise android.mk for cpu-features 2020-08-06 23:51:56 +01:00
32 changed files with 933 additions and 340 deletions
+3 -3
View File
@@ -155,12 +155,12 @@ Please remember that some parts of `FFmpeg` are licensed under the `GPL` and onl
@Override
public void apply(final long executionId, final int returnCode) {
if (rc == RETURN_CODE_SUCCESS) {
if (returnCode == RETURN_CODE_SUCCESS) {
Log.i(Config.TAG, "Async command execution completed successfully.");
} else if (rc == RETURN_CODE_CANCEL) {
} else if (returnCode == RETURN_CODE_CANCEL) {
Log.i(Config.TAG, "Async command execution cancelled by user.");
} else {
Log.i(Config.TAG, String.format("Async command execution failed with rc=%d.", rc));
Log.i(Config.TAG, String.format("Async command execution failed with returnCode=%d.", returnCode));
}
}
});
+5 -1
View File
@@ -159,6 +159,7 @@ When compilation ends an Android Archive (AAR) file is created under the prebuil
echo -e " --reconf-LIBRARY\t\trun autoreconf before building LIBRARY [no]"
echo -e " --redownload-LIBRARY\t\tdownload LIBRARY even it is detected as already downloaded [no]"
echo -e " --rebuild-LIBRARY\t\tbuild LIBRARY even it is detected as already built [no]\n"
echo -e " --no-archive\t\tdo not build Android archive [no]\n"
}
display_version() {
@@ -702,6 +703,9 @@ while [ ! $# -eq 0 ]; do
redownload_library ${DOWNLOAD_LIBRARY}
;;
--no-archive)
NO_ARCHIVE="1"
;;
--full)
BUILD_FULL="1"
;;
@@ -844,7 +848,7 @@ if [[ ${ENABLED_ARCHITECTURES[4]} -eq 1 ]]; then
ANDROID_ARCHITECTURES+="$(get_android_arch 4) "
fi
if [[ ! -z ${ANDROID_ARCHITECTURES} ]]; then
if [[ ! -z ${ANDROID_ARCHITECTURES} ]] && [ -z ${NO_ARCHIVE} ]; then
echo -n -e "\nmobile-ffmpeg: "
+4 -7
View File
@@ -31,14 +31,11 @@ android {
}
}
task javadoc(type: Javadoc) {
title = 'MobileFFmpeg'
destinationDir = file("${projectDir}/../../docs/android/javadoc")
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
source = android.sourceSets.main.java.srcDirs
}
dependencies {
testImplementation "androidx.test.ext:junit:1.1.1"
testImplementation "org.json:json:20190722"
}
if (System.properties.containsKey('releaseMobileFFmpeg')) {
apply from: "${rootProject.projectDir}/../tools/release/android/release.template.gradle"
}
+1
View File
@@ -9,6 +9,7 @@
native <methods>;
void log(long, int, byte[]);
void statistics(long, int, float, float, long , int, double, double);
void closeParcelFileDescriptor(int);
}
-keep class com.arthenica.mobileffmpeg.AbiDetect {
@@ -51,6 +51,8 @@
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "saf_wrapper.h"
#ifdef _WIN32
#undef main /* We don't want SDL to override our main() */
#endif
+21 -1
View File
@@ -79,6 +79,9 @@ static jmethodID logMethod;
/** Global reference of statistics redirection method in Java */
static jmethodID statisticsMethod;
/** Global reference of closeParcelFileDescriptor method in Java */
static jmethodID closeParcelFileDescriptorMethod;
/** Global reference of String class in Java */
static jclass stringClass;
@@ -306,6 +309,8 @@ void monitorWait(int milliSeconds) {
ts.tv_nsec = tp.tv_usec * 1000;
ts.tv_sec += milliSeconds / 1000;
ts.tv_nsec += (milliSeconds % 1000)*1000000;
ts.tv_sec += ts.tv_nsec / 1000000000L;
ts.tv_nsec = ts.tv_nsec % 1000000000L;
pthread_mutex_lock(&monitorMutex);
pthread_cond_timedwait(&monitorCondition, &monitorMutex, &ts);
@@ -653,6 +658,12 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
return JNI_FALSE;
}
closeParcelFileDescriptorMethod = (*env)->GetStaticMethodID(env, localConfigClass, "closeParcelFileDescriptor", "(I)V");
if (logMethod == NULL) {
LOGE("OnLoad thread failed to GetStaticMethodID for %s.\n", "closeParcelFileDescriptor");
return JNI_FALSE;
}
stringConstructor = (*env)->GetMethodID(env, localStringClass, "<init>", "([BLjava/lang/String;)V");
if (stringConstructor == NULL) {
LOGE("OnLoad thread failed to GetMethodID for %s.\n", "<init>");
@@ -688,7 +699,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
* @param object reference to the class on which this method is invoked
* @param level log level
*/
JNIEXPORT void JNICALL Java_com_arthenica_mobileffmpeg_Config_setNativeLogLevel(JNIEnv *env, jclass object, jint level) {
JNIEXPORT void JNICALL Java_com_arthenica_mobileffmpeg_Config_setNativeLogLevel(JNIEnv *env, jclass object, jint level) {
configuredLogLevel = level;
}
@@ -941,3 +952,12 @@ JNIEXPORT void JNICALL Java_com_arthenica_mobileffmpeg_Config_ignoreNativeSignal
handleSIGPIPE = 0;
}
}
/**
* used by saf_wrapper; is expected to be called from a Java thread, therefore we don't need attach/detach
*/
void closeParcelFileDescriptor(int fd) {
JNIEnv *env = NULL;
(*globalVm)->GetEnv(globalVm, (void**) &env, JNI_VERSION_1_6);
(*env)->CallStaticVoidMethod(env, configClass, closeParcelFileDescriptorMethod, fd);
}
+134
View File
@@ -0,0 +1,134 @@
/*
* Copyright (c) 2020 Taner Sener
*
* This file is part of MobileFFmpeg.
*
* MobileFFmpeg is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MobileFFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include "config.h"
#include "libavformat/avformat.h"
#include "libavutil/avstring.h"
#include "saf_wrapper.h"
/** JNI wrapper in mobileffmpeg.c */
void closeParcelFileDescriptor(int fd);
// in these wrappers, we call the original functions, so we remove the shadow defines
#undef avio_closep
#undef avformat_close_input
#undef avio_open
#undef avio_open2
#undef avformat_open_input
static int fd_read_packet(void* opaque, uint8_t* buf, int buf_size) {
int fd = (int)opaque;
return read(fd, buf, buf_size);
}
static int fd_write_packet(void* opaque, uint8_t* buf, int buf_size) {
int fd = (int)opaque;
return write(fd, buf, buf_size);
}
static int64_t fd_seek(void *opaque, int64_t offset, int whence) {
int fd = (int)opaque;
if (fd < 0) {
return AVERROR(EINVAL);
}
int64_t ret;
if (whence == AVSEEK_SIZE) {
struct stat st;
ret = fstat(fd, &st);
return ret < 0 ? AVERROR(errno) : (S_ISFIFO(st.st_mode) ? 0 : st.st_size);
}
ret = lseek(fd, offset, whence);
return ret < 0 ? AVERROR(errno) : ret;
}
/*
* returns NULL if the filename is not of expected format (e.g. 'saf:72/video.md4')
*/
static AVIOContext *create_fd_avio_context(const char *filename, int flags) {
union {int fd; void* opaque;} fdunion;
fdunion.fd = -1;
const char *fd_ptr = NULL;
if (av_strstart(filename, "saf:", &fd_ptr)) {
char *final;
fdunion.fd = strtol(fd_ptr, &final, 10);
if (fd_ptr == final) { /* No digits found */
fdunion.fd = -1;
}
}
if (fdunion.fd >= 0) {
int write_flag = flags & AVIO_FLAG_WRITE ? 1 : 0;
return avio_alloc_context(av_malloc(4096), 4096, write_flag, fdunion.opaque, fd_read_packet, write_flag ? fd_write_packet : NULL, fd_seek);
}
return NULL;
}
static void close_fd_avio_context(AVIOContext *ctx) {
if (fd_seek(ctx->opaque, 0, AVSEEK_SIZE) >= 0) {
int fd = (int)ctx->opaque;
closeParcelFileDescriptor(fd);
}
ctx->opaque = NULL;
}
int android_avformat_open_input(AVFormatContext **ps, const char *filename,
ff_const59 AVInputFormat *fmt, AVDictionary **options) {
if (!(*ps) && !(*ps = avformat_alloc_context()))
return AVERROR(ENOMEM);
(*ps)->pb = create_fd_avio_context(filename, AVIO_FLAG_READ);
return avformat_open_input(ps, filename, fmt, options);
}
int android_avio_open2(AVIOContext **s, const char *filename, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options) {
AVIOContext *fd_context = create_fd_avio_context(filename, flags);
if (fd_context) {
*s = fd_context;
return 0;
}
return avio_open2(s, filename, flags, int_cb, options);
}
int android_avio_open(AVIOContext **s, const char *url, int flags) {
return android_avio_open2(s, url, flags, NULL, NULL);
}
int android_avio_closep(AVIOContext **s) {
close_fd_avio_context(*s);
return avio_closep(s);
}
void android_avformat_close_input(AVFormatContext **ps) {
if (*ps && (*ps)->pb) {
close_fd_avio_context((*ps)->pb);
}
avformat_close_input(ps);
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2020 Taner Sener
*
* This file is part of MobileFFmpeg.
*
* MobileFFmpeg is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MobileFFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MOBILE_FFMPEG_SAF_WRAPPER_H
#define MOBILE_FFMPEG_SAF_WRAPPER_H
/*
* These wrappers are intended to be used instead of the ffmpeg apis.
* You don't even need to change the source to call them.
* Instead, we redefine the public api names so that the wrapper be used.
*/
int android_avio_closep(AVIOContext **s);
#define avio_closep android_avio_closep
void android_avformat_close_input(AVFormatContext **s);
#define avformat_close_input android_avformat_close_input
int android_avio_open(AVIOContext **s, const char *url, int flags);
#define avio_open android_avio_open
int android_avio_open2(AVIOContext **s, const char *url, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options);
#define avio_open2 android_avio_open2
int android_avformat_open_input(AVFormatContext **ps, const char *filename,
ff_const59 AVInputFormat *fmt, AVDictionary **options);
#define avformat_open_input android_avformat_open_input
#endif //MOBILE_FFMPEG_SAF_WRAPPER_H
@@ -20,8 +20,13 @@
package com.arthenica.mobileffmpeg;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract;
import android.util.Log;
import android.util.SparseArray;
import java.io.File;
import java.io.FileOutputStream;
@@ -80,6 +85,7 @@ public class Config {
private static int lastCreatedPipeIndex;
private static final List<FFmpegExecution> executions;
private static SparseArray<ParcelFileDescriptor> pfdmap = new SparseArray<>();
static {
@@ -769,4 +775,58 @@ public class Config {
*/
private native static void ignoreNativeSignal(final int signum);
/**
* <p>Convert Structured Access Framework Uri (<code></code>"content:…"</code>) for MobileFfmpeg.
*
* @return String can be passed to FFmpeg or FFprobe
*/
private static String getSafParameter(Context context, Uri uri, String openMode) {
String displayName = "unknown";
try (Cursor cursor = context.getContentResolver().query(uri, null, null, null, null)) {
if (cursor != null && cursor.moveToFirst()) {
displayName = cursor.getString(cursor.getColumnIndex(DocumentsContract.Document.COLUMN_DISPLAY_NAME));
}
} catch (Throwable ex) {
Log.e(TAG, "failed to get column", ex);
}
int fd = -1;
try {
ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(uri, openMode);
fd = parcelFileDescriptor.getFd();
pfdmap.put(fd, parcelFileDescriptor);
} catch (Throwable e) {
Log.e(TAG, "obtaining " + openMode + " ParcelFileDescriptor for " + uri, e);
}
// workaround for https://issuetracker.google.com/issues/162440528: ANDROID_CREATE_DOCUMENT generating file names like "transcode.mp3 (2)"
if (displayName.lastIndexOf('.') > 0 && displayName.lastIndexOf(' ') > displayName.lastIndexOf('.')) {
String extension = displayName.substring(displayName.lastIndexOf('.'), displayName.lastIndexOf(' '));
displayName += extension;
}
// spaces can break argument list parsing, see https://github.com/alexcohn/mobile-ffmpeg/pull/1#issuecomment-688643836
final char NBSP = (char)0xa0;
return "saf:" + fd + "/" + displayName.replace(' ', NBSP);
}
public static String getSafParameterForRead(Context context, Uri uri) {
return getSafParameter(context, uri, "r");
}
public static String getSafParameterForWrite(Context context, Uri uri) {
return getSafParameter(context, uri, "w");
}
private static void closeParcelFileDescriptor(int fd) {
try {
ParcelFileDescriptor pfd = pfdmap.get(fd);
if (pfd != null) {
pfd.close();
pfdmap.delete(fd);
}
} catch (Throwable e) {
Log.e(TAG, "closeParcelFileDescriptor " + fd, e);
}
}
}
+3 -2
View File
@@ -13,10 +13,8 @@ ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
endif
ifeq ($(MY_ARMV7_NEON), true)
FFMPEG_INCLUDES := $(MY_LOCAL_PATH)/../../prebuilt/android-$(TARGET_ARCH)/neon/ffmpeg/include
$(call import-module, cpu-features/neon)
else
FFMPEG_INCLUDES := $(MY_LOCAL_PATH)/../../prebuilt/android-$(TARGET_ARCH)/ffmpeg/include
$(call import-module, cpu-features)
endif
MY_ARM_MODE := arm
@@ -50,6 +48,8 @@ LOCAL_STATIC_LIBRARIES := cpu-features
LOCAL_ARM_NEON := ${MY_ARM_NEON}
include $(BUILD_SHARED_LIBRARY)
$(call import-module, cpu-features)
ifeq ($(TARGET_PLATFORM),android-16)
MY_SRC_FILES := mobileffmpeg.c mobileffprobe.c android_lts_support.c mobileffmpeg_exception.c fftools_cmdutils.c fftools_ffmpeg.c fftools_ffprobe.c fftools_ffmpeg_opt.c fftools_ffmpeg_hw.c fftools_ffmpeg_filter.c
else ifeq ($(TARGET_PLATFORM),android-17)
@@ -57,6 +57,7 @@ else ifeq ($(TARGET_PLATFORM),android-17)
else
MY_SRC_FILES := mobileffmpeg.c mobileffprobe.c mobileffmpeg_exception.c fftools_cmdutils.c fftools_ffmpeg.c fftools_ffprobe.c fftools_ffmpeg_opt.c fftools_ffmpeg_hw.c fftools_ffmpeg_filter.c
endif
MY_SRC_FILES += saf_wrapper.c
MY_CFLAGS := -Wall -Werror -Wno-unused-parameter -Wno-switch -Wno-sign-compare
MY_LDLIBS := -llog -lz -landroid
+5 -1
View File
@@ -1,4 +1,8 @@
LOCAL_PATH := $(call my-dir)/../../../prebuilt/android-$(TARGET_ARCH)/cpu-features/lib
ifeq ($(MY_ARMV7_NEON), true)
LOCAL_PATH := $(call my-dir)/../../../prebuilt/android-$(TARGET_ARCH)/neon/cpu-features/lib
else
LOCAL_PATH := $(call my-dir)/../../../prebuilt/android-$(TARGET_ARCH)/cpu-features/lib
endif
include $(CLEAR_VARS)
LOCAL_ARM_MODE := $(MY_ARM_MODE)
-8
View File
@@ -1,8 +0,0 @@
LOCAL_PATH := $(call my-dir)/../../../../prebuilt/android-$(TARGET_ARCH)/neon/cpu-features/lib
include $(CLEAR_VARS)
LOCAL_ARM_MODE := $(MY_ARM_MODE)
LOCAL_MODULE := cpu-features
LOCAL_SRC_FILES := libndk_compat.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../include/ndk_compat
include $(PREBUILT_STATIC_LIBRARY)
+2 -2
View File
@@ -51,8 +51,8 @@ android.applicationVariants.all { variant ->
}
dependencies {
// implementation project(':app')
implementation 'com.arthenica:mobile-ffmpeg-full:4.4.LTS'
implementation project(':app')
// implementation 'com.arthenica:mobile-ffmpeg-full:4.4.LTS'
implementation 'com.arthenica:smart-exception-java:0.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
@@ -198,7 +198,7 @@ public class AudioTabFragment extends Fragment implements AdapterView.OnItemSele
String ffmpegCommand = String.format("-hide_banner -y -f lavfi -i sine=frequency=1000:duration=5 -c:a pcm_s16le %s", audioSampleFile.getAbsolutePath());
android.util.Log.d(TAG, String.format("Sample file is created with '%s'.", ffmpegCommand));
android.util.Log.d(TAG, String.format("Creating audio sample with '%s'.", ffmpegCommand));
int result = FFmpeg.execute(ffmpegCommand);
if (result == 0) {
@@ -64,7 +64,7 @@ public class HttpsTabFragment extends Fragment {
@Override
public void onClick(View v) {
getInfo();
runGetMediaInformation();
}
});
@@ -99,7 +99,7 @@ public class HttpsTabFragment extends Fragment {
});
}
public void getInfo() {
public void runGetMediaInformation() {
clearLog();
String testUrl = urlText.getText().toString();
@@ -26,7 +26,7 @@ import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
public class PagerAdapter extends FragmentPagerAdapter {
private static final int NUMBER_OF_TABS = 8;
private static final int NUMBER_OF_TABS = 9;
private final Context context;
@@ -62,6 +62,9 @@ public class PagerAdapter extends FragmentPagerAdapter {
case 7: {
return ConcurrentExecutionTabFragment.newInstance();
}
case 8: {
return SafTabFragment.newInstance();
}
default: {
return null;
}
@@ -100,6 +103,9 @@ public class PagerAdapter extends FragmentPagerAdapter {
case 7: {
return context.getString(R.string.concurrent_tab);
}
case 8: {
return context.getString(R.string.saf_tab);
}
default: {
return null;
}
@@ -0,0 +1,420 @@
/*
* Copyright (c) 2018 Taner Sener
*
* This file is part of MobileFFmpeg.
*
* MobileFFmpeg is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MobileFFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MobileFFmpeg. If not, see <http://www.gnu.org/licenses/>.
*/
package com.arthenica.mobileffmpeg.test;
import android.app.AlertDialog;
import android.content.Intent;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.AndroidRuntimeException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.TextView;
import android.widget.VideoView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.arthenica.mobileffmpeg.Config;
import com.arthenica.mobileffmpeg.ExecuteCallback;
import com.arthenica.mobileffmpeg.FFmpeg;
import com.arthenica.mobileffmpeg.FFprobe;
import com.arthenica.mobileffmpeg.LogCallback;
import com.arthenica.mobileffmpeg.LogMessage;
import com.arthenica.mobileffmpeg.Statistics;
import com.arthenica.mobileffmpeg.StatisticsCallback;
import com.arthenica.mobileffmpeg.util.DialogUtil;
import com.arthenica.mobileffmpeg.util.ResourcesUtil;
import com.arthenica.smartexception.java.Exceptions;
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.mobileffmpeg.Config.RETURN_CODE_SUCCESS;
import static com.arthenica.mobileffmpeg.test.MainActivity.TAG;
public class SafTabFragment extends Fragment {
private TextView outputText;
private Uri inUri;
private Uri outUri;
private static final int REQUEST_SAF_FFPROBE = 11;
private static final int REQUEST_SAF_FFMPEG = 12;
private boolean backFromIntent = false;
private VideoView videoView;
private AlertDialog progressDialog;
private Statistics statistics;
private Button runFFmpegButton;
private Button runFFprobeButton;
public SafTabFragment() {
super(R.layout.fragment_saf_tab);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
runFFmpegButton = view.findViewById(R.id.runFFmpegButton);
runFFmpegButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT)
.setType("video/*")
.putExtra(Intent.EXTRA_TITLE, "video.mp4")
.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, REQUEST_SAF_FFMPEG);
}
});
runFFprobeButton = view.findViewById(R.id.runFFprobeButton);
runFFprobeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT)
.setType("*/*")
.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/*", "video/*", "audio/*"})
.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, REQUEST_SAF_FFPROBE);
}
});
outputText = view.findViewById(R.id.outputText);
outputText.setMovementMethod(new ScrollingMovementMethod());
videoView = view.findViewById(R.id.videoPlayerFrame);
progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding video");
}
@Override
public void onResume() {
super.onResume();
setActive();
}
static SafTabFragment newInstance() {
return new SafTabFragment();
}
private void enableLogCallback() {
Config.enableLogCallback(new LogCallback() {
@Override
public void apply(final LogMessage message) {
MainActivity.addUIAction(new Callable() {
@Override
public Object call() {
appendLog(message.getText());
return null;
}
});
}
});
}
private void runFFprobe() {
videoView.setVisibility(View.GONE);
outputText.setVisibility(View.VISIBLE);
clearLog();
final String ffprobeCommand = "-hide_banner -print_format json -show_format -show_streams " + Config.getSafParameterForRead(getContext(), inUri);
Log.d(TAG, "Testing FFprobe COMMAND synchronously.");
Log.d(TAG, String.format("FFprobe process started with arguments\n\'%s\'", ffprobeCommand));
int result = FFprobe.execute(ffprobeCommand);
Log.d(TAG, String.format("FFprobe process exited with rc %d", result));
if (result != 0) {
Popup.show(requireContext(), "Command failed. Please check output for the details.");
}
inUri = null;
}
private void setActive() {
if (backFromIntent) {
backFromIntent = false;
return;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
Popup.show(requireContext(), "SAF is only available for Android 4.4 and above.");
runFFprobeButton.setEnabled(false);
runFFmpegButton.setEnabled(false);
outputText.setEnabled(false);
Log.i(TAG, "SAF Tab Dectivated");
return;
}
Log.i(TAG, "SAF Tab Activated");
enableLogCallback();
enableStatisticsCallback();
Popup.show(requireContext(), getString(R.string.saf_test_tooltip_text));
}
private void appendLog(final String logMessage) {
outputText.append(logMessage);
}
private void clearLog() {
outputText.setText("");
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
backFromIntent = true;
if (requestCode == REQUEST_SAF_FFPROBE && resultCode == RESULT_OK && data != null) {
inUri = data.getData();
MainActivity.handler.post(new Runnable() {
@Override
public void run() {
runFFprobe();
}
});
} else if (requestCode == REQUEST_SAF_FFMPEG && resultCode == MainActivity.RESULT_OK && data != null) {
outUri = data.getData();
MainActivity.handler.post(new Runnable() {
@Override
public void run() {
encodeVideo();
}
});
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private String getCodec(String videoPath) {
String extension = "mp4";
int pos = videoPath.lastIndexOf('.');
if (pos >= 0)
extension = videoPath.substring(pos+1);
switch (extension) {
case "webm":
return "vp8";
case "mkv":
return "aom";
case "ogv":
return "theora";
case "mov":
return "hap";
case "mp4":
default:
return "mpeg4";
}
}
private String getCustomOptions(String videoCodec) {
switch (videoCodec) {
case "x265":
return "-crf 28 -preset fast ";
case "vp8":
return "-b:v 1M -crf 10 ";
case "vp9":
return "-b:v 2M ";
case "aom":
return "-crf 30 -strict experimental ";
case "theora":
return "-qscale:v 7 ";
case "hap":
return "-format hap_q ";
default:
// kvazaar, mpeg4, x264, xvid
return "";
}
}
private void enableStatisticsCallback() {
Config.enableStatisticsCallback(new StatisticsCallback() {
@Override
public void apply(final Statistics newStatistics) {
MainActivity.addUIAction(new Callable<Object>() {
@Override
public Object call() {
statistics = newStatistics;
updateProgressDialog();
return null;
}
});
throw new AndroidRuntimeException("I am test exception thrown by test application");
}
});
}
private void encodeVideo() {
final File image1File = new File(requireContext().getCacheDir(), "colosseum.jpg");
final File image2File = new File(requireContext().getCacheDir(), "pyramid.jpg");
final File image3File = new File(requireContext().getCacheDir(), "tajmahal.jpg");
final String videoPath = Config.getSafParameterForWrite(requireContext(), outUri);
try {
// IF VIDEO IS PLAYING STOP PLAYBACK
videoView.stopPlayback();
videoView.setVisibility(View.GONE);
outputText.setVisibility(View.VISIBLE);
String selectedCodec = getCodec(videoPath);
Log.d(TAG, String.format("Testing VIDEO encoding with '%s' codec", selectedCodec));
showProgressDialog();
ResourcesUtil.resourceToFile(getResources(), R.drawable.colosseum, image1File);
ResourcesUtil.resourceToFile(getResources(), R.drawable.pyramid, image2File);
ResourcesUtil.resourceToFile(getResources(), R.drawable.tajmahal, image3File);
final String ffmpegCommand = Video.generateEncodeVideoScript(image1File.getAbsolutePath(), image2File.getAbsolutePath(), image3File.getAbsolutePath(), videoPath, selectedCodec, getCustomOptions(selectedCodec));
Log.d(TAG, String.format("FFmpeg process started with arguments\n'%s'.", ffmpegCommand));
long executionId = FFmpeg.executeAsync(ffmpegCommand, new ExecuteCallback() {
@Override
public void apply(final long executionId, final int returnCode) {
Log.d(TAG, String.format("FFmpeg process exited with rc %d.", returnCode));
Log.d(TAG, "FFmpeg process output:");
Config.printLastCommandOutput(Log.INFO);
hideProgressDialog();
MainActivity.addUIAction(new Callable<Object>() {
@Override
public Object call() {
if (returnCode == RETURN_CODE_SUCCESS) {
Log.d(TAG, "Encode completed successfully; playing video.");
playVideo(outUri, new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
videoView.setVisibility(View.GONE);
outputText.setVisibility(View.VISIBLE);
}
});
} else {
Popup.show(requireContext(), "Encode failed. Please check log for the details.");
Log.d(TAG, String.format("Encode failed with rc=%d.", returnCode));
}
return null;
}
});
}
});
Log.d(TAG, String.format("Async FFmpeg process started with executionId %d.", executionId));
} catch (IOException e) {
Log.e(TAG, String.format("Encode video failed %s.", Exceptions.getStackTraceString(e)));
Popup.show(requireContext(), "Encode video failed");
}
}
private void playVideo(Uri videoUri, MediaPlayer.OnCompletionListener onCompletionListener) {
videoView.setVisibility(View.VISIBLE);
outputText.setVisibility(View.GONE);
MediaController mediaController = new MediaController(requireContext());
mediaController.setAnchorView(videoView);
videoView.setVideoURI(videoUri);
videoView.setMediaController(mediaController);
videoView.requestFocus();
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
videoView.setBackgroundColor(0x00000000);
}
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
videoView.stopPlayback();
return false;
}
});
videoView.setOnCompletionListener(onCompletionListener);
videoView.start();
}
private void showProgressDialog() {
// CLEAN STATISTICS
statistics = null;
Config.resetStatistics();
progressDialog.show();
}
private void updateProgressDialog() {
if (statistics == null) {
return;
}
int timeInMilliseconds = this.statistics.getTime();
if (timeInMilliseconds > 0) {
int totalVideoDuration = 9000;
String completePercentage = new BigDecimal(timeInMilliseconds).multiply(new BigDecimal(100)).divide(new BigDecimal(totalVideoDuration), 0, BigDecimal.ROUND_HALF_UP).toString();
TextView textView = progressDialog.findViewById(R.id.progressDialogText);
if (textView != null) {
textView.setText(String.format("Encoding video: %% %s.", completePercentage));
}
}
}
private void hideProgressDialog() {
progressDialog.dismiss();
MainActivity.addUIAction(new Callable<Object>() {
@Override
public Object call() {
progressDialog = DialogUtil.createProgressDialog(requireContext(), "Encoding video");
return null;
}
});
}
}
@@ -224,7 +224,7 @@ public class SubtitleTabFragment extends Fragment {
}
});
Log.d(TAG, String.format("FFmpeg started execution id: %d.", executionId));
Log.d(TAG, String.format("Async FFmpeg process started with executionId %d.", executionId));
} catch (IOException e) {
Log.e(TAG, String.format("Burn subtitles failed %s.", Exceptions.getStackTraceString(e)));
@@ -261,8 +261,6 @@ public class VideoTabFragment extends Fragment implements AdapterView.OnItemSele
}
public String getSelectedVideoCodec() {
// NOTE THAT MPEG4 CODEC IS ASSIGNED HERE
String videoCodec = selectedCodec;
// VIDEO CODEC SPINNER HAS BASIC NAMES, FFMPEG NEEDS LONGER AND EXACT CODEC NAMES.
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".SafTabFragment">
<Button
android:id="@+id/runFFmpegButton"
android:layout_width="140dp"
android:layout_height="36dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:background="@drawable/rounded_button"
android:fontFamily="sans-serif"
android:gravity="center"
android:text="@string/command_run_ffmpeg_button_text"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="16sp"
android:textStyle="bold"
tools:targetApi="jelly_bean" />
<Button
android:id="@+id/runFFprobeButton"
android:layout_width="140dp"
android:layout_height="36dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:background="@drawable/rounded_button"
android:fontFamily="sans-serif"
android:gravity="center"
android:text="@string/command_run_ffprobe_button_text"
android:textAlignment="center"
android:textColor="@android:color/white"
android:textSize="16sp"
android:textStyle="bold"
tools:targetApi="jelly_bean" />
<TextView
android:id="@+id/outputText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="6dp"
android:layout_marginBottom="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:background="@drawable/rounded_output_frame"
android:fontFamily="sans-serif"
android:gravity="bottom"
android:overScrollMode="ifContentScrolls"
android:scrollbars="vertical"
android:textColor="@android:color/black"
android:textSize="14sp"
android:typeface="sans"
tools:targetApi="jelly_bean" />
<VideoView
android:visibility="gone"
android:id="@+id/videoPlayerFrame"
android:layout_width="wrap_content"
android:background="@drawable/rounded_video_frame"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:layout_margin="20dp"
android:layout_weight="1" />
</LinearLayout>
@@ -8,6 +8,7 @@
<string name="vidstab_tab">VID.STAB</string>
<string name="pipe_tab">PIPE</string>
<string name="concurrent_tab">CONCURRENT</string>
<string name="saf_tab">SAF</string>
<string name="command_text_input_placeholder">Enter command</string>
<string name="command_run_ffmpeg_button_text">RUN FFMPEG</string>
<string name="command_run_ffprobe_button_text">RUN FFPROBE</string>
@@ -7,4 +7,5 @@
<string name="vidstab_test_tooltip_text">Click the button to stabilize video. Original video will play above and stabilized video will play below</string>
<string name="pipe_test_tooltip_text">Click the button to create a video using pipe redirection. Created video will play inside the frame below</string>
<string name="concurrent_execution_test_tooltip_text">Use ENCODE and CANCEL buttons to start/stop multiple execution</string>
<string name="saf_test_tooltip_text">Use system file picker to test scoped storage extension</string>
</resources>
+2 -2
View File
@@ -263,9 +263,9 @@ download_gpl_library_source() {
GPL_LIB_ORIG_DIR="x264-cde9a93319bea766a92e306d69059c76de970190"
;;
x265)
GPL_LIB_URL="https://bitbucket.org/multicoreware/x265/downloads/x265_3.4.tar.gz"
GPL_LIB_URL="https://github.com/videolan/x265/archive/3.4.tar.gz"
GPL_LIB_FILE="x265_3.4.tar.gz"
GPL_LIB_ORIG_DIR="x265_3.4"
GPL_LIB_ORIG_DIR="x265-3.4"
;;
xvidcore)
GPL_LIB_URL="https://downloads.xvid.com/downloads/xvidcore-1.3.7.tar.gz"
+3
View File
@@ -56,6 +56,9 @@ if [[ ${RECONF_nettle} -eq 1 ]]; then
autoreconf_library ${LIB_NAME}
fi
${SED_INLINE} 's/exit(0)/return 0/g' ${BASEDIR}/src/${LIB_NAME}/configure
${SED_INLINE} 's/exit (0)/return 0/g' ${BASEDIR}/src/${LIB_NAME}/configure
./configure \
--prefix=${BASEDIR}/prebuilt/$(get_target_build_directory)/${LIB_NAME} \
--enable-pic \
+2 -2
View File
@@ -986,7 +986,7 @@ if [[ -n ${MOBILE_FFMPEG_LTS_BUILD} ]] && [[ "${DETECTED_IOS_SDK_VERSION}" != "$
fi
# DISABLE 32-bit architectures on newer IOS versions
if [[ ${DETECTED_IOS_SDK_VERSION} == 11* ]] || [[ ${DETECTED_IOS_SDK_VERSION} == 12* ]] || [[ ${DETECTED_IOS_SDK_VERSION} == 13* ]]; then
if [[ ${DETECTED_IOS_SDK_VERSION} == 11* ]] || [[ ${DETECTED_IOS_SDK_VERSION} == 12* ]] || [[ ${DETECTED_IOS_SDK_VERSION} == 13* ]] || [[ ${DETECTED_IOS_SDK_VERSION} == 14* ]]; then
if [[ -z ${BUILD_FORCE} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_ARMV7}]} -eq 1 ]]; then
echo -e "INFO: Disabled armv7 architecture which is not supported on SDK ${DETECTED_IOS_SDK_VERSION}\n" 1>>"${BASEDIR}/build.log" 2>&1
disable_arch "armv7"
@@ -1009,7 +1009,7 @@ elif [[ ${DETECTED_IOS_SDK_VERSION} != 10* ]]; then
fi
# DISABLE x86-64-mac-catalyst architecture on IOS versions lower than 13
if [[ ${DETECTED_IOS_SDK_VERSION} != 13* ]] && [[ -z ${BUILD_FORCE} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_X86_64_MAC_CATALYST}]} -eq 1 ]]; then
if [[ ${DETECTED_IOS_SDK_VERSION} != 13* || ${DETECTED_IOS_SDK_VERSION} != 14* ]] && [[ -z ${BUILD_FORCE} ]] && [[ ${ENABLED_ARCHITECTURES[${ARCH_X86_64_MAC_CATALYST}]} -eq 1 ]]; then
echo -e "INFO: Disabled x86-64-mac-catalyst architecture which is not supported on SDK ${DETECTED_IOS_SDK_VERSION}\n" 1>>"${BASEDIR}/build.log" 2>&1
disable_arch "x86-64-mac-catalyst"
fi
@@ -9,14 +9,6 @@
/* 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 */; };
341D1E8223CA8F3E00B24203 /* libswscale.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1E4923CA8F3C00B24203 /* libswscale.framework */; };
341D1E8523CA8F3E00B24203 /* libavdevice.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1E4C23CA8F3C00B24203 /* libavdevice.framework */; };
341D1E8F23CA8F3F00B24203 /* libavfilter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1E5623CA8F3C00B24203 /* libavfilter.framework */; };
341D1E9423CA8F3F00B24203 /* libavformat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1E5B23CA8F3D00B24203 /* libavformat.framework */; };
341D1E9B23CA8F3F00B24203 /* libavcodec.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1E6223CA8F3D00B24203 /* libavcodec.framework */; };
341D1E9C23CA8F3F00B24203 /* libavutil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1E6323CA8F3D00B24203 /* libavutil.framework */; };
341D1EA123CA8F3F00B24203 /* mobileffmpeg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1E6823CA8F3D00B24203 /* mobileffmpeg.framework */; };
341D1EAA23CA8F3F00B24203 /* libswresample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1E7123CA8F3E00B24203 /* libswresample.framework */; };
341D1EB723CA8F8400B24203 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 341D1EB623CA8F8400B24203 /* libiconv.tbd */; };
342900D422DE3AAB0071B2E4 /* MediaInformationParserTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 342900D322DE3AAB0071B2E4 /* MediaInformationParserTest.h */; };
342900D722DE3AB30071B2E4 /* MobileFFmpegTest.h in Headers */ = {isa = PBXBuildFile; fileRef = 342900D522DE3AB30071B2E4 /* MobileFFmpegTest.h */; };
@@ -51,7 +43,6 @@
34DC789E21215B5800C3486C /* sil_open_font_license.txt in Resources */ = {isa = PBXBuildFile; fileRef = 34DC789A21215B5800C3486C /* sil_open_font_license.txt */; };
34E313FC24A533040004B1D7 /* ConcurrentExecutionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 34E313FA24A533040004B1D7 /* ConcurrentExecutionViewController.h */; };
34E313FD24A533040004B1D7 /* ConcurrentExecutionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34E313FB24A533040004B1D7 /* ConcurrentExecutionViewController.m */; };
34F2036B24C31F61003C6973 /* openh264.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F2036A24C31F61003C6973 /* openh264.framework */; };
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 */; };
@@ -77,14 +68,6 @@
/* Begin PBXFileReference section */
340FABBC2115A17600B33CE7 /* VidStabViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VidStabViewController.h; sourceTree = "<group>"; };
340FABBD2115A17600B33CE7 /* VidStabViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VidStabViewController.m; sourceTree = "<group>"; };
341D1E4923CA8F3C00B24203 /* libswscale.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libswscale.framework; sourceTree = "<group>"; };
341D1E4C23CA8F3C00B24203 /* libavdevice.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavdevice.framework; sourceTree = "<group>"; };
341D1E5623CA8F3C00B24203 /* libavfilter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavfilter.framework; sourceTree = "<group>"; };
341D1E5B23CA8F3D00B24203 /* libavformat.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavformat.framework; sourceTree = "<group>"; };
341D1E6223CA8F3D00B24203 /* libavcodec.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavcodec.framework; sourceTree = "<group>"; };
341D1E6323CA8F3D00B24203 /* libavutil.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libavutil.framework; sourceTree = "<group>"; };
341D1E6823CA8F3D00B24203 /* mobileffmpeg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = mobileffmpeg.framework; sourceTree = "<group>"; };
341D1E7123CA8F3E00B24203 /* libswresample.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = libswresample.framework; sourceTree = "<group>"; };
341D1EB623CA8F8400B24203 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; };
342900D322DE3AAB0071B2E4 /* MediaInformationParserTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaInformationParserTest.h; sourceTree = "<group>"; };
342900D522DE3AB30071B2E4 /* MobileFFmpegTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MobileFFmpegTest.h; sourceTree = "<group>"; };
@@ -119,7 +102,6 @@
34DC789A21215B5800C3486C /* sil_open_font_license.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = sil_open_font_license.txt; sourceTree = "<group>"; };
34E313FA24A533040004B1D7 /* ConcurrentExecutionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcurrentExecutionViewController.h; sourceTree = "<group>"; };
34E313FB24A533040004B1D7 /* ConcurrentExecutionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConcurrentExecutionViewController.m; sourceTree = "<group>"; };
34F2036A24C31F61003C6973 /* openh264.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = openh264.framework; sourceTree = "<group>"; };
34FAE210209F7DDD005CE2AE /* MobileFFmpegTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MobileFFmpegTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
34FAE213209F7DDD005CE2AE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
34FAE214209F7DDD005CE2AE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -141,18 +123,9 @@
files = (
341D1EB723CA8F8400B24203 /* libiconv.tbd in Frameworks */,
34AE897122AE5A4600742D95 /* GameController.framework in Frameworks */,
341D1EAA23CA8F3F00B24203 /* libswresample.framework in Frameworks */,
34AE897022AE5A3500742D95 /* VideoToolbox.framework in Frameworks */,
34F2036B24C31F61003C6973 /* openh264.framework in Frameworks */,
341D1E8523CA8F3E00B24203 /* libavdevice.framework in Frameworks */,
341D1EA123CA8F3F00B24203 /* mobileffmpeg.framework in Frameworks */,
34AE896F22AE5A2E00742D95 /* CoreMotion.framework in Frameworks */,
341D1E9C23CA8F3F00B24203 /* libavutil.framework in Frameworks */,
341D1E9B23CA8F3F00B24203 /* libavcodec.framework in Frameworks */,
343165D121D136FC001A7185 /* libz.tbd in Frameworks */,
341D1E8F23CA8F3F00B24203 /* libavfilter.framework in Frameworks */,
341D1E8223CA8F3E00B24203 /* libswscale.framework in Frameworks */,
341D1E9423CA8F3F00B24203 /* libavformat.framework in Frameworks */,
3431662B21D13B0A001A7185 /* libc++.tbd in Frameworks */,
343165D321D13704001A7185 /* libbz2.tbd in Frameworks */,
);
@@ -179,21 +152,12 @@
isa = PBXGroup;
children = (
341D1EB623CA8F8400B24203 /* libiconv.tbd */,
341D1E6223CA8F3D00B24203 /* libavcodec.framework */,
341D1E4C23CA8F3C00B24203 /* libavdevice.framework */,
341D1E5623CA8F3C00B24203 /* libavfilter.framework */,
341D1E5B23CA8F3D00B24203 /* libavformat.framework */,
341D1E6323CA8F3D00B24203 /* libavutil.framework */,
341D1E7123CA8F3E00B24203 /* libswresample.framework */,
341D1E4923CA8F3C00B24203 /* libswscale.framework */,
341D1E6823CA8F3D00B24203 /* mobileffmpeg.framework */,
3431662E21D13C58001A7185 /* CoreMotion.framework */,
3431662D21D13C4A001A7185 /* GameController.framework */,
3431662C21D13C3D001A7185 /* VideoToolbox.framework */,
3431662A21D13B0A001A7185 /* libc++.tbd */,
343165D221D13704001A7185 /* libbz2.tbd */,
343165D021D136FC001A7185 /* libz.tbd */,
34F2036A24C31F61003C6973 /* openh264.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -521,7 +485,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 44;
CURRENT_PROJECT_VERSION = 45;
DEVELOPMENT_TEAM = 98GD5J4999;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -548,7 +512,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 44;
CURRENT_PROJECT_VERSION = 45;
DEVELOPMENT_TEAM = 98GD5J4999;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
+22 -49
View File
@@ -1,5 +1,5 @@
#!/bin/bash
#
#
# Creates a new android release from current branch
#
@@ -10,110 +10,83 @@ export GPL_PACKAGES="--enable-gpl --enable-libvidstab --enable-x264 --enable-x26
export FULL_PACKAGES="--enable-fontconfig --enable-freetype --enable-fribidi --enable-gmp --enable-gnutls --enable-kvazaar --enable-lame --enable-libaom --enable-libass --enable-libiconv --enable-libilbc --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libxml2 --enable-opencore-amr --enable-opus --enable-shine --enable-snappy --enable-soxr --enable-speex --enable-twolame --enable-vo-amrwbenc --enable-wavpack"
create_package() {
local NEW_PACKAGE="${PACKAGE_DIRECTORY}/mobile-ffmpeg-$1-$2.LTS.aar"
local NEW_PACKAGE="${PACKAGE_DIRECTORY}/mobile-ffmpeg-$1-$2.LTS.aar"
local CURRENT_PACKAGE="${PACKAGE_DIRECTORY}/mobile-ffmpeg.aar"
rm -f ${NEW_PACKAGE}
local CURRENT_PACKAGE="${PACKAGE_DIRECTORY}/mobile-ffmpeg.aar"
rm -f ${NEW_PACKAGE}
mv ${CURRENT_PACKAGE} ${NEW_PACKAGE} || exit 1
}
enable_gradle_build() {
rm -f ${BASEDIR}/../../android/app/build.gradle || exit 1
cp ${BASEDIR}/android/build.gradle ${BASEDIR}/../../android/app/build.gradle || exit 1
}
enable_gradle_release() {
rm -f ${BASEDIR}/../../android/app/build.gradle || exit 1
cp ${BASEDIR}/android/release.template.gradle ${BASEDIR}/../../android/app/build.gradle || exit 1
mv ${CURRENT_PACKAGE} ${NEW_PACKAGE} || exit 1
}
if [ $# -ne 2 ]; then
echo "Usage: android.sh <version code> <version name>"
exit 1
echo "Usage: android.sh <version code> <version name>"
exit 1
fi
# VALIDATE VERSIONS
MOBILE_FFMPEG_VERSION=$(grep '#define MOBILE_FFMPEG_VERSION' ${BASEDIR}/../../android/app/src/main/cpp/mobileffmpeg.h | grep -Eo '\".*\"' | sed -e 's/\"//g')
if [[ "${MOBILE_FFMPEG_VERSION}" != "$2" ]]; then
echo "Error: version mismatch. v$2 requested but v${MOBILE_FFMPEG_VERSION} found. Please perform the following updates and try again."
echo "1. Update docs"
echo "2. Update android/app/build.gradle file versions"
echo "3. Update tools/release scripts' descriptions"
echo "4. Update mobileffmpeg.h versions for both android and ios"
echo "5. Update versions in Doxyfile"
exit 1
echo "Error: version mismatch. v$2 requested but v${MOBILE_FFMPEG_VERSION} found. Please perform the following updates and try again."
echo "1. Update docs"
echo "2. Update android/app/build.gradle file versions"
echo "3. Update tools/release scripts' descriptions"
echo "4. Update mobileffmpeg.h versions for both android and ios"
echo "5. Update versions in Doxyfile"
exit 1
fi
# MIN RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-min -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 without any external libraries enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-min -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 without any external libraries enabled.' uploadArchives || exit 1
create_package "min" "$2" || exit 1
# MIN-GPL RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} ${GPL_PACKAGES} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-min-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with libvid.stab v1.1.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-min-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with libvid.stab v1.1.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 uploadArchives || exit 1
create_package "min-gpl" "$2" || exit 1
# HTTPS RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} --enable-gnutls --enable-gmp || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-https -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with gmp v6.2.0 and gnutls v3.6.13 library enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-https -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with gmp v6.2.0 and gnutls v3.6.13 library enabled.' uploadArchives || exit 1
create_package "https" "$2" || exit 1
# HTTPS-GPL RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} --enable-gnutls --enable-gmp ${GPL_PACKAGES} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-https-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with gmp v6.2.0, gnutls v3.6.13, libvid.stab v1.1.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-https-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with gmp v6.2.0, gnutls v3.6.13, libvid.stab v1.1.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 uploadArchives || exit 1
create_package "https-gpl" "$2" || exit 1
# AUDIO RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} --enable-lame --enable-libilbc --enable-libvorbis --enable-opencore-amr --enable-opus --enable-shine --enable-soxr --enable-speex --enable-twolame --enable-vo-amrwbenc --enable-wavpack || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-audio -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with lame v3.100, libilbc v2.0.2, libvorbis v1.3.7, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3 and wavpack v5.3.0 libraries enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-audio -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with lame v3.100, libilbc v2.0.2, libvorbis v1.3.7, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3 and wavpack v5.3.0 libraries enabled.' uploadArchives || exit 1
create_package "audio" "$2" || exit 1
# VIDEO RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} --enable-fontconfig --enable-freetype --enable-fribidi --enable-kvazaar --enable-libaom --enable-libass --enable-libiconv --enable-libtheora --enable-libvpx --enable-snappy --enable-libwebp || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-video -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, kvazaar v2.0.0, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libtheora v1.1.1, libvpx v1.8.2, snappy v1.1.8 and libwebp v1.1.0 libraries enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-video -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, kvazaar v2.0.0, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libtheora v1.1.1, libvpx v1.8.2, snappy v1.1.8 and libwebp v1.1.0 libraries enabled.' uploadArchives || exit 1
create_package "video" "$2" || exit 1
# FULL RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} ${FULL_PACKAGES} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-full -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, gmp v6.2.0, gnutls v3.6.13, kvazaar v2.0.0, lame v3.100, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libilbc v2.0.2, libtheora v1.1.1, libvorbis v1.3.7, libvpx v1.8.2, libwebp v1.1.0, libxml2 v2.9.10, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, snappy v1.1.8, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3 and wavpack v5.3.0 libraries enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-full -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, gmp v6.2.0, gnutls v3.6.13, kvazaar v2.0.0, lame v3.100, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libilbc v2.0.2, libtheora v1.1.1, libvorbis v1.3.7, libvpx v1.8.2, libwebp v1.1.0, libxml2 v2.9.10, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, snappy v1.1.8, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3 and wavpack v5.3.0 libraries enabled.' uploadArchives || exit 1
create_package "full" "$2" || exit 1
# FULL-GPL RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} ${FULL_PACKAGES} ${GPL_PACKAGES} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-full-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, gmp v6.2.0, gnutls v3.6.13, kvazaar v2.0.0, lame v3.100, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libilbc v2.0.2, libtheora v1.1.1, libvid.stab v1.1.0, libvorbis v1.3.7, libvpx v1.8.2, libwebp v1.1.0, libxml2 v2.9.10, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, snappy v1.1.8, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3, wavpack v5.3.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2.LTS -PreleaseMinSdk=16 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-full-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, gmp v6.2.0, gnutls v3.6.13, kvazaar v2.0.0, lame v3.100, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libilbc v2.0.2, libtheora v1.1.1, libvid.stab v1.1.0, libvorbis v1.3.7, libvpx v1.8.2, libwebp v1.1.0, libxml2 v2.9.10, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, snappy v1.1.8, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3, wavpack v5.3.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 uploadArchives || exit 1
create_package "full-gpl" "$2" || exit 1
enable_gradle_build
+23 -49
View File
@@ -1,5 +1,5 @@
#!/bin/bash
#
#
# Creates a new android release from current branch
#
@@ -10,110 +10,84 @@ export GPL_PACKAGES="--enable-gpl --enable-libvidstab --enable-x264 --enable-x26
export FULL_PACKAGES="--enable-fontconfig --enable-freetype --enable-fribidi --enable-gmp --enable-gnutls --enable-kvazaar --enable-lame --enable-libaom --enable-libass --enable-libiconv --enable-libilbc --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libxml2 --enable-opencore-amr --enable-opus --enable-shine --enable-snappy --enable-soxr --enable-speex --enable-twolame --enable-vo-amrwbenc --enable-wavpack"
create_package() {
local NEW_PACKAGE="${PACKAGE_DIRECTORY}/mobile-ffmpeg-$1-$2.aar"
local NEW_PACKAGE="${PACKAGE_DIRECTORY}/mobile-ffmpeg-$1-$2.aar"
local CURRENT_PACKAGE="${PACKAGE_DIRECTORY}/mobile-ffmpeg.aar"
rm -f ${NEW_PACKAGE}
local CURRENT_PACKAGE="${PACKAGE_DIRECTORY}/mobile-ffmpeg.aar"
rm -f ${NEW_PACKAGE}
mv ${CURRENT_PACKAGE} ${NEW_PACKAGE} || exit 1
}
enable_gradle_build() {
rm -f ${BASEDIR}/../../android/app/build.gradle || exit 1
cp ${BASEDIR}/android/build.gradle ${BASEDIR}/../../android/app/build.gradle || exit 1
}
enable_gradle_release() {
rm -f ${BASEDIR}/../../android/app/build.gradle || exit 1
cp ${BASEDIR}/android/release.template.gradle ${BASEDIR}/../../android/app/build.gradle || exit 1
mv ${CURRENT_PACKAGE} ${NEW_PACKAGE} || exit 1
}
if [ $# -ne 2 ]; then
echo "Usage: android.sh <version code> <version name>"
exit 1
echo "Usage: android.sh <version code> <version name>"
exit 1
fi
# VALIDATE VERSIONS
MOBILE_FFMPEG_VERSION=$(grep '#define MOBILE_FFMPEG_VERSION' ${BASEDIR}/../../android/app/src/main/cpp/mobileffmpeg.h | grep -Eo '\".*\"' | sed -e 's/\"//g')
if [[ "${MOBILE_FFMPEG_VERSION}" != "$2" ]]; then
echo "Error: version mismatch. v$2 requested but v${MOBILE_FFMPEG_VERSION} found. Please perform the following updates and try again."
echo "1. Update docs"
echo "2. Update android/app/build.gradle file versions"
echo "3. Update tools/release scripts' descriptions"
echo "4. Update mobileffmpeg.h versions for both android and ios"
echo "5. Update versions in Doxyfile"
exit 1
echo "Error: version mismatch. v$2 requested but v${MOBILE_FFMPEG_VERSION} found. Please perform the following updates and try again."
echo "1. Update docs"
echo "2. Update android/app/build.gradle file versions"
echo "3. Update tools/release scripts' descriptions"
echo "4. Update mobileffmpeg.h versions for both android and ios"
echo "5. Update versions in Doxyfile"
exit 1
fi
# MIN RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-min -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 without any external libraries enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-min -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 without any external libraries enabled.' uploadArchives || exit 1
create_package "min" "$2" || exit 1
# MIN-GPL RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} ${GPL_PACKAGES} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-min-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with libvid.stab v1.1.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-min-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with libvid.stab v1.1.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 uploadArchives || exit 1
create_package "min-gpl" "$2" || exit 1
# HTTPS RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} --enable-gnutls --enable-gmp || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-https -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with gmp v6.2.0 and gnutls v3.6.13 library enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-https -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with gmp v6.2.0 and gnutls v3.6.13 library enabled.' uploadArchives || exit 1
create_package "https" "$2" || exit 1
# HTTPS-GPL RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} --enable-gnutls --enable-gmp ${GPL_PACKAGES} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-https-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with gmp v6.2.0, gnutls v3.6.13, libvid.stab v1.1.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-https-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with gmp v6.2.0, gnutls v3.6.13, libvid.stab v1.1.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 uploadArchives || exit 1
create_package "https-gpl" "$2" || exit 1
# AUDIO RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} --enable-lame --enable-libilbc --enable-libvorbis --enable-opencore-amr --enable-opus --enable-shine --enable-soxr --enable-speex --enable-twolame --enable-vo-amrwbenc --enable-wavpack || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-audio -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with lame v3.100, libilbc v2.0.2, libvorbis v1.3.7, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3 and wavpack v5.3.0 libraries enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-audio -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with lame v3.100, libilbc v2.0.2, libvorbis v1.3.7, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3 and wavpack v5.3.0 libraries enabled.' uploadArchives || exit 1
create_package "audio" "$2" || exit 1
# VIDEO RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} --enable-fontconfig --enable-freetype --enable-fribidi --enable-kvazaar --enable-libaom --enable-libass --enable-libiconv --enable-libtheora --enable-libvpx --enable-snappy --enable-libwebp || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-video -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, kvazaar v2.0.0, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libtheora v1.1.1, libvpx v1.8.2, snappy v1.1.8 and libwebp v1.1.0 libraries enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-video -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, kvazaar v2.0.0, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libtheora v1.1.1, libvpx v1.8.2, snappy v1.1.8 and libwebp v1.1.0 libraries enabled.' uploadArchives || exit 1
create_package "video" "$2" || exit 1
# FULL RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} ${FULL_PACKAGES} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-full -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, gmp v6.2.0, gnutls v3.6.13, kvazaar v2.0.0, lame v3.100, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libilbc v2.0.2, libtheora v1.1.1, libvorbis v1.3.7, libvpx v1.8.2, libwebp v1.1.0, libxml2 v2.9.10, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, snappy v1.1.8, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3 and wavpack v5.3.0 libraries enabled.' clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-full -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, gmp v6.2.0, gnutls v3.6.13, kvazaar v2.0.0, lame v3.100, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libilbc v2.0.2, libtheora v1.1.1, libvorbis v1.3.7, libvpx v1.8.2, libwebp v1.1.0, libxml2 v2.9.10, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, snappy v1.1.8, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3 and wavpack v5.3.0 libraries enabled.' uploadArchives || exit 1
create_package "full" "$2" || exit 1
# FULL-GPL RELEASE
enable_gradle_build
cd ${BASEDIR}/../.. || exit 1
./android.sh ${CUSTOM_OPTIONS} ${FULL_PACKAGES} ${GPL_PACKAGES} || exit 1
cd ${BASEDIR}/../../android/app || exit 1
enable_gradle_release
gradle -p ${BASEDIR}/../../android/app -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-full-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, gmp v6.2.0, gnutls v3.6.13, kvazaar v2.0.0, lame v3.100, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libilbc v2.0.2, libtheora v1.1.1, libvid.stab v1.1.0, libvorbis v1.3.7, libvpx v1.8.2, libwebp v1.1.0, libxml2 v2.9.10, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, snappy v1.1.8, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3, wavpack v5.3.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 clean install bintrayUpload || exit 1
gradle -p ${BASEDIR}/../../android/app -DreleaseMobileFFmpeg=true -PreleaseVersionCode=$1 -PreleaseVersionName=$2 -PreleaseMinSdk=24 -PreleaseTargetSdk=30 -PreleaseProject=mobile-ffmpeg-full-gpl -PreleaseProjectDescription='Includes FFmpeg v4.4-dev-416 with fontconfig v2.13.92, freetype v2.10.2, fribidi v1.0.9, gmp v6.2.0, gnutls v3.6.13, kvazaar v2.0.0, lame v3.100, libaom v1.0.0-errata1-avif-110, libass v0.14.0, libiconv v1.16, libilbc v2.0.2, libtheora v1.1.1, libvid.stab v1.1.0, libvorbis v1.3.7, libvpx v1.8.2, libwebp v1.1.0, libxml2 v2.9.10, opencore-amr v0.1.5, opus v1.3.1, shine v3.1.1, snappy v1.1.8, soxr v0.1.3, speex v1.2.0, twolame v0.4, vo-amrwbenc v0.1.3, wavpack v5.3.0, x264 v20200630-stable, x265 v3.4 and xvidcore v1.3.7 libraries enabled.' -PreleaseGPL=1 uploadArchives || exit 1
create_package "full-gpl" "$2" || exit 1
enable_gradle_build
+4 -7
View File
@@ -31,14 +31,11 @@ android {
}
}
task javadoc(type: Javadoc) {
title = 'MobileFFmpeg'
destinationDir = file("${projectDir}/../../docs/android/javadoc")
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
source = android.sourceSets.main.java.srcDirs
}
dependencies {
testImplementation "androidx.test.ext:junit:1.1.1"
testImplementation "org.json:json:20190722"
}
if (System.properties.containsKey('releaseMobileFFmpeg')) {
apply from: "${rootProject.projectDir}/../tools/release/android/release.template.gradle"
}
+4 -7
View File
@@ -31,14 +31,11 @@ android {
}
}
task javadoc(type: Javadoc) {
title = 'MobileFFmpeg'
destinationDir = file("${projectDir}/../../docs/android/javadoc")
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
source = android.sourceSets.main.java.srcDirs
}
dependencies {
testImplementation "androidx.test.ext:junit:1.1.1"
testImplementation "org.json:json:20190722"
}
if (System.properties.containsKey('releaseMobileFFmpeg')) {
apply from: "${rootProject.projectDir}/../tools/release/android/release.template.gradle"
}
+81 -154
View File
@@ -1,149 +1,3 @@
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
}
}
android {
compileSdkVersion Integer.parseInt(releaseTargetSdk)
ndkVersion "21.3.6528147"
defaultConfig {
minSdkVersion Integer.parseInt(releaseMinSdk)
targetSdkVersion Integer.parseInt(releaseTargetSdk)
versionCode Integer.parseInt(releaseVersionCode)
versionName releaseVersionName
project.archivesBaseName = releaseProject
consumerProguardFiles 'proguard-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ["../libs"]
}
}
testOptions {
unitTests.returnDefaultValues = true
}
libraryVariants.all { variant ->
variant.outputs.all {
outputFileName = "${archivesBaseName}-${android.defaultConfig.versionName}.aar"
}
}
}
ext {
bintrayRepo = 'maven'
bintrayName = releaseProject
publishedGroupId = 'com.arthenica'
libraryName = releaseProject
artifact = releaseProject
libraryDescription = releaseProjectDescription
siteUrl = 'https://github.com/tanersener/mobile-ffmpeg'
issueTrackerUrl = 'https://github.com/tanersener/mobile-ffmpeg/issues'
gitUrl = 'https://github.com/tanersener/mobile-ffmpeg.git'
libraryVersion = releaseVersionName
developerId = 'tanersener'
developerName = 'Taner Sener'
developerEmail = 'tanersener@gmail.com'
if (Project.hasProperty('releaseGPL')) {
licenseName = 'GNU General Public License version 3'
licenseUrl = 'https://www.gnu.org/licenses/gpl-3.0.txt'
allLicenses = ["GPL-3.0"]
} else {
licenseName = 'GNU Lesser General Public License, Version 3'
licenseUrl = 'https://www.gnu.org/licenses/lgpl-3.0.txt'
allLicenses = ["LGPL-3.0"]
}
}
group = publishedGroupId
version = libraryVersion
install {
repositories.mavenInstaller {
pom.project {
packaging 'aar'
groupId publishedGroupId
artifactId artifact
name libraryName
description libraryDescription
url siteUrl
licenses {
license {
name licenseName
url licenseUrl
}
}
developers {
developer {
id developerId
name developerName
email developerEmail
}
}
scm {
connection gitUrl
developerConnection gitUrl
url siteUrl
}
}
}
}
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")
configurations = ['archives']
pkg {
repo = bintrayRepo
name = bintrayName
desc = libraryDescription
websiteUrl = siteUrl
vcsUrl = gitUrl
issueTrackerUrl = issueTrackerUrl
licenses = allLicenses
dryRun = true
publish = false
override = false
publicDownloadNumbers = false
version {
desc = libraryDescription
}
}
}
task sourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
@@ -165,14 +19,87 @@ artifacts {
archives sourcesJar
}
dependencies {
testImplementation "androidx.test.ext:junit:1.1.1"
testImplementation "org.json:json:20190722"
}
apply plugin: 'maven'
apply plugin: 'signing'
allprojects {
repositories {
google()
jcenter()
group = 'com.arthenica'
archivesBaseName = releaseProject
version = releaseVersionName
File propertiesFile = project.rootProject.file('local.properties')
if (propertiesFile.exists()) {
Properties properties = new Properties()
properties.load(new FileInputStream(propertiesFile))
properties.each { name, value ->
ext[name] = value
}
}
ext {
publishedGroupId = group
artifact = releaseProject
libraryName = releaseProject
libraryVersion = version
libraryDescription = releaseProjectDescription
siteUrl = 'https://github.com/tanersener/mobile-ffmpeg'
gitUrl = 'https://github.com/tanersener/mobile-ffmpeg.git'
developerId = 'tanersener'
developerName = 'Taner Sener'
developerEmail = 'tanersener@gmail.com'
if (Project.hasProperty('releaseGPL')) {
licenseName = 'GNU General Public License version 3'
licenseUrl = 'https://www.gnu.org/licenses/gpl-3.0.txt'
} else {
licenseName = 'GNU Lesser General Public License, Version 3'
licenseUrl = 'https://www.gnu.org/licenses/lgpl-3.0.txt'
}
}
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
authentication(userName: ossrhUsername, password: ossrhPassword)
}
snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
authentication(userName: ossrhUsername, password: ossrhPassword)
}
pom.project {
packaging 'aar'
name = libraryName
description = libraryDescription
url = siteUrl
licenses {
license {
name = licenseName
url = licenseUrl
}
}
developers {
developer {
id developerId
name developerName
email developerEmail
}
}
scm {
connection gitUrl
developerConnection gitUrl
url siteUrl
}
}
}
}
}
signing {
sign configurations.archives
}