-
Notifications
You must be signed in to change notification settings - Fork 15
Building from source
Download the .zip file for your operating system from the official site
Unzip the downloaded ndk archive. For the remainder of the tutorial, we’ll assume the path to the unzipped directory (android-ndk-, eg. android-ndk-r12b) to be /path/to/android-ndk
Get the latest ffmpeg source. The remainder of this tutorial assumes that the ffmpeg directory resides at /path/to/ffmpeg
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd /path/to/ffmpeg
Modify the configure script.
Open the file /path/to/ffmpeg/configure and find & replace the following lines
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
with
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
Create a file here called build_ffmpeg.sh (/path/to/ffmpeg/build_ffmpeg.sh) with the following contents :
#!/bin/bash
NDK=/path/to/android-ndk/
SYSROOT=$NDK/platforms/android-14/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--enable-protocol=concat \
--enable-protocol=file \
--enable-muxer=mp4 \
--enable-demuxer=mpegts \
--enable-memalign-hack \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make -j3
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one
Make sure you change the ndk paths in the script appropriately
After you have saved the contents of build_ffmpeg.sh run the script.
chmod a+x build_ffmpeg.sh
./build_ffmpeg.sh
On successful completion you should see the android/ directory in the /path/to/ffmpeg directory. The android/ directory should contain arm/include and arm/lib
Copy the following files from /path/to/ffmpeg to the jni/ directory
cmdutils.c
cmdutils.h
ffmpeg.c
ffmpeg.h
ffmpeg_filter.c
ffmpeg_opt.c
ffmpeg_opt.h
logjam.h
In the same jni directory, create a ffmpeg_controller.c with the following contents
#include <android/log.h>
#include "com_example_Controller.h"
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, char **argv);
JavaVM *sVm = NULL;
jint JNI_OnLoad( JavaVM* vm, void* reserved )
{
sVm = vm;
return JNI_VERSION_1_6;
}
JNIEXPORT void JNICALL Java_com_example_Controller_run(JNIEnv *env, jobject obj, jobjectArray args)
{
int i = 0;
int argc = 0;
char **argv = NULL;
jstring *strr = NULL;
if (args != NULL) {
argc = (*env)->GetArrayLength(env, args);
argv = (char **) malloc(sizeof(char *) * argc);
strr = (jstring *) malloc(sizeof(jstring) * argc);
for(i=0;i<argc;i++) { strr[i] = (jstring)(*env)->GetObjectArrayElement(env, args, i);
argv[i] = (char *)(*env)->GetStringUTFChars(env, strr[i], 0);
}
}
main(argc, argv);
for(i=0;i<argc;i++) { (*env)->ReleaseStringUTFChars(env, strr[i], argv[i]);
}
free(argv);
free(strr);
}
and also create a header file in the same directory com_example_Controller.h
#include <jni.h>
#ifndef _Included_com_example_Controller
#define _Included_com_example_Controller
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_Controller
* Method: run
* Signature: ([Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_example_Controller_run
(JNIEnv *, jobject, jobjectArray);
#ifdef __cplusplus
}
#endif
#endif
Note there are 2 Android.mk
Create a file Android.mk in the jni directory with the following content :
LOCAL_PATH := $(call my-dir)
#$(warning $(LOCAL_PATH))
include $(CLEAR_VARS)
LOCAL_MODULE := libffmpeg
LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid
LOCAL_CFLAGS := -Wdeprecated-declarations
ANDROID_LIB := -landroid
LOCAL_C_INCLUDES:=/path/to/ffmpeg
LOCAL_SRC_FILES := ffmpeg_controller.c ffmpeg.c ffmpeg_filter.c ffmpeg_opt.c cmdutils.c
LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil libswresample libavfilter libavdevice
include $(BUILD_SHARED_LIBRARY)
$(call import-module,/path/to/ffmpeg/android/arm)
LOCAL_PATH:= $(call my-dir)
Note replace /path/to with the appropriate path to the ffmpeg’s parent dir.
And create another Android.mk at /path/to/ffmpeg/android/arm/ with the following contents.
include $(CLEAR_VARS)
LOCAL_MODULE:= libavdevice
LOCAL_SRC_FILES:= lib/libavdevice-56.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec-56.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= lib/libavformat-56.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= lib/libswscale-3.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= lib/libavutil-54.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= lib/libavfilter-5.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libswresample
LOCAL_SRC_FILES:= lib/libswresample-1.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
cd /path/to/app/jni
/path/to/ndk/ndk-build
Create a file com.example.Controller java file with the following content
package com.example;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
public class Controller {
static {
System.loadLibrary("ffmpeg");
}
public static native void run(String[] argv);
public static void testFFMPEG(){
//ffmpeg -y -start_number 1 -i /sdcard/test_%d.jpg -vcodec mpeg4 /sdcard/test.mp4
run(new String[]{
"-y",
"-start_number",
"1",
"-i",
"/sdcard/test_%d.jpg",
"-vcodec",
"mpeg4",
"/sdcard/test.mp4"
});
}
}
You can call the function testFFMPEG as
Controller.testFFMPEG();
Modify the testFFMPEG directory to appropriately suit your requirements.
If you want to run the command "ffmpeg a b c d e", your argument to the run function will be {"a","b","c","d","e"}