NDK part
1, download NDK
here's a stroke.
2, Decompression NDK
do not unzip, file permissions will be wrong. execution, will automatically decompression, and then MV to want to put the place. I put it in the "/usr/local/bin/android-ndk-r10d" (this directory is used to refer to $ndk_dir).
3, download FFmpeg
I'm under the 2.5.3 version.
4, decompression FFmpeg
extract FFmpeg to $ndk_dir/sources/ffmpeg-2.5.3.
5. Modify FFmpeg Compilation configuration
in the ffmpeg-2.5.3 directory, put these lines in the Configure file to remove the default generated library name libavcodec.so.55 the last "55″" version number.
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) '
Slibname_with_major= ' $ (slibpref) $ (FULLNAME)-$ (libmajor) $ (Slibsuf) '
lib_install_extra_cmd= ' $$ (ranlib) "$ ( Libdir)/$ (libname) "'
slib_install_name= ' $ (slibname_with_major) '
slib_install_links= ' $ (slibname) '
6, compile FFmpeg
Create the file build_android.sh in the ffmpeg-2.5.3 directory.
Note that the first three lines are configured correctly in their own path.
#!/bin/bash
ndk=/usr/local/android-ndk-r10d
sysroot= $NDK/platforms/android-15/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-avdevice
\-- Disable-doc \
--disable-symver \
--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 make
install
}
cpu=arm
prefix=$ (pwd)/android/$CPU
addi_cflags= "-marm"
Build_one
Execute after Save
sudo chmod +x build_android.sh
./build_android.sh
Compiling will take some time.
7, view the results of the compilation
After compiling, $ndk_dir/sources/ffmpeg-2.5.3 will have an Android directory, which is the compiled library we want.
[cg@local]# ls -R android/
arm
android//arm:
Android.mk include lib
android//arm/include:
libavcodec libavfilter libavformat libavutil libswresample libswscale
android//arm/include/libavcodec:
avcodec.h avfft.h dv_profile.h dxva2.h old_codec_ids.h vaapi.h vda.h vdpau.h version.h vorbis_parser.h xvmc.h
android//arm/include/libavfilter:
asrc_abuffer.h avcodec.h avfilter.h avfiltergraph.h buffersink.h buffersrc.h version.h
android//arm/include/libavformat:
avformat.h avio.h version.h
android//arm/include/libavutil:
adler32.h avstring.h cast5.h downmix_info.h hash.h macros.h opt.h replaygain.h time.h
aes.h avutil.h channel_layout.h error.h hmac.h mathematics.h parseutils.h ripemd.h timecode.h
attributes.h base64.h common.h eval.h imgutils.h md5.h pixdesc.h samplefmt.h timestamp.h
audio_fifo.h blowfish.h cpu.h ffversion.h intfloat.h mem.h pixelutils.h sha.h version.h
audioconvert.h bprint.h crc.h fifo.h intreadwrite.h motion_vector.h pixfmt.h sha512.h xtea.h
avassert.h bswap.h dict.h file.h lfg.h murmur3.h random_seed.h stereo3d.h
avconfig.h buffer.h display.h frame.h log.h old_pix_fmts.h rational.h threadmessage.h
android//arm/include/libswresample:
swresample.h version.h
android//arm/include/libswscale:
swscale.h version.h
android//arm/lib:
libavcodec-56.so libavfilter-5.so libavformat-56.so libavutil-54.so libswresample-1.so libswscale-3.so pkgconfig
libavcodec.so libavfilter.so libavformat.so libavutil.so libswresample.so libswscale.so
android//arm/lib/pkgconfig:
libavcodec.pc libavfilter.pc libavformat.pc libavutil.pc libswresample.pc libswscale.pc
Which libavcodec.so, libavfilter.so, libavformat.so, libavutil.so, libswresample.so, libswscale.so are soft chain, no use, you can delete.
8, to FFmpeg Library write android.mk make it available
Create a $ndk_dir/sources/ffmpeg-2.5.3/android/arm/android.mk file that reads as follows:
Note that the number in front of so should be changed to the number compiled by your ffmpeg version.
LOCAL_PATH:= $(call my-dir)
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)
This NDK configuration is complete, followed by the section configuring Android Studio.
Android Studio Section
Android Studio and Eclipse are not the same, it has a certain ability to automatically generate ANDROID.MK and automatically handle JNI.
But it is not enough for us to use FFmpeg library.
So our idea is to disable the Android Studio automatic Ndk-build function, and manually compile our C code to achieve the goal.
First of all, of course, create a new Android studio project.
We use $root_dir to refer to the project root directory.
1. Android Studio Configuration Ndk Path
$ROOT _dir/local.properties was previously configured with only the SDK.
Sdk.dir=/usr/local/bin/android-sdk-macosx
Add a row of NDK configuration to it
Sdk.dir=/usr/local/bin/android-sdk-macosx
ndk.dir=/usr/local/bin/android-ndk-r10d
2. Configure Build.gradle
There are two build.gradle in the project, one in the root directory and one under $ROOT_DIR/APP/SRC, and we are going to change the latter.
A> Add this section to disable automatic Ndk-build.
SourceSets.main.jni.srcDirs = []
B> Add this section to let it know with the library
NDK {
abifilter "Armeabi"
modulename "Ovsplayer"
ldlibs "log", "Z", "M", "Jnigraphics", "Android"
}
The modified Build.gradle is like this.
Android {
compilesdkversion
buildtoolsversion "21.1.1"
sourceSets.main.jni.srcDirs = []// Disable automatic execution of Ndk-build
defaultconfig {
ApplicationID "com.example.chengang.myapplication"
minsdkversion
targetsdkversion
versioncode 1
versionname "1.0"
ndk {
abifilter
"Armeabi" ModuleName "Ovsplayer"//This is the name of the C file
ldlibs "log", "Z", "M", "Jnigraphics", "Android"
}
}
Buildtypes {release
{
minifyenabled false
proguardfiles getdefaultproguardfile (' Proguard-android.txt '), ' Proguard-rules.pro '}}}
3. Generate header File
execute the command, and note that the path changes according to your circumstances.
Copy Code code as follows:
Javah-d Jni-classpath. \.. \build\intermediates\classes\debug com.example.nativeapp.app.MainActivity
Will generate this file $root_dir/app/src/main/jni/com_example_chengang_myapplication_mainactivity.h
4, the preparation of C documents
the contents of the $ROOT _dir/app/src/main/jni/ovsplayer.c are as follows:
#include <stdio.h>
#include <stdlib.h>
#include "com_example_chengang_myapplication_MainActivity.h"
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
JNIEXPORT jstring JNICALL Java_com_example_chengang_myapplication_MainActivity_getStringFromNative
(JNIEnv * env , jobject obj)
{
const char *url = "/mnt/sdcard/1.mp4";
av_register_all();
AVFormatContext *pFormatCtx = NULL;
int ret = avformat_open_input(&pFormatCtx, url, NULL, NULL);
ret = avformat_find_stream_info(input_context, NULL);
int streamNum = input_context->nb_streams;
char wd[512];
sprintf(wd, "AVCODEC VERSION %u\n, streamNum[%d]"
, avcodec_version()
, streamNum
);
return (*env)->NewStringUTF(env, wd);
}
5, writing a Java file
$ROOT _dir/app/src/main/java/com/example/chengang/myapplication/ Mainactivity.java content is as follows.
where the Getstringfromnative () method is implemented, print out the version number of the FFmpeg library (which I compiled is 3673444) and the video file.
Package com.example.chengang.myapplication;
Import android.support.v7.app.ActionBarActivity;
Import Android.os.Bundle;
Import Android.view.Menu;
Import Android.view.MenuItem;
Import Android.widget.TextView;
public class Mainactivity extends actionbaractivity {@Override protected void onCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
TextView view = (TextView) Findviewbyid (R.id.mytext);
View.settext (This.getstringfromnative ()); @Override public boolean Oncreateoptionsmenu (Menu menu) {//Inflate the menu; This adds items to the action Bar
If it is present.
Getmenuinflater (). Inflate (R.menu.menu_main, menu);
return true; @Override public boolean onoptionsitemselected (MenuItem Item) {//Handle Action Bar item clicks here. The action bar would//automatically handle clicks on the Home/up button, so long//as your specify a parent activity
In Androidmanifest.xml. int id = Item. Getitemid ();
Noinspection simplifiableifstatement if (id = = r.id.action_settings) {return true;
return super.onoptionsitemselected (item);
Public native String getstringfromnative ();
static {system.loadlibrary ("swresample-1");
System.loadlibrary ("avutil-54");
System.loadlibrary ("avformat-56");
System.loadlibrary ("avcodec-56");
System.loadlibrary ("swscale-3");
System.loadlibrary ("Ovsplayer");
}
}
Attached to the layout file is this.
<relativelayout 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: paddingleft= "@dimen/activity_horizontal_margin"
android:paddingright= "@dimen/activity_horizontal_margin"
android:paddingtop= "@dimen/activity_vertical_margin"
android:paddingbottom= "@dimen/activity_vertical_ Margin "tools:context=". Mainactivity ">
<textview
android:id=" @+id/mytext "
android:text=" @string/hello_world "Android: Layout_width= "Wrap_content"
android:layout_height= "wrap_content"/>
</RelativeLayout>
6. Write Project Android.mk
Android.mk put it under the $root_dir/app/build/intermediates/ndk/debug/.
Note the absolute path in which "/users/chengang/code/android/myapplication4″ is our $root_dir."
Local_path: = $ (call My-dir)
include $ (clear_vars)
local_module: = Ovsplayer local_ldlibs
: = \
-lm \
-ljnigraphics \
-landroid \
-llog \
-lz \
local_shared_libraries: = Libavformat libavcodec Libswscale libavutil
local_src_files: = \
/users/chengang/code/android/myapplication4/app/src/main/jni/ OVSPLAYER.C \
local_c_includes + +/users/chengang/code/android/myapplication4/app/src/main/jni
LOCAL_C_ INCLUDES + +/users/chengang/code/android/myapplication4/app/src/debug/jni
include $ (build_shared_library)
$ (call import-module,ffmpeg-2.5.3/android/arm)
The first is the difference between local_ldlibs and Local_shared_libraries, the former linked to the system library, the latter linked to the third party library.
Can not be used in exchange.
7, compile C code
execute this command under the terminal to compile C code.
Copy Code code as follows:
/usr/local/bin/android-ndk-r10d/ndk-build Ndk_project_path=null App_build_script=/users/chengang/code/android/ Myapplication4/app/build/intermediates/ndk/debug/android.mk app_platform=android-21 NDK_OUT=/Users/chengang/Code /android/myapplication4/app/build/intermediates/ndk/debug/obj Ndk_libs_out=/users/chengang/code/android/ Myapplication4/app/build/intermediates/ndk/debug/lib App_abi=armeabi
8. Running the project
Go back to Android studio and Ctrl+r run the project.
You'll see the phone print out the FFmpeg library version number (which I compiled is 3673444) and the video file information.
The FFmpeg library is ready to be invoked, and then continue to write your own logic.
9, and another
to say another error that may be encountered in the two C code:
A> If you want the file size through the standard library, you write the wrong filename. On Android, executing fseek on a handle to a nonexistent file will report the following error: "Could not disable core file generation." ;
B> if Avformat_open_input () returns-1330794744. There are two possibilities, one is that you forget to call Av_register_all (), and the second is to compile ffmpeg when not compiled into the corresponding demuxer or specified disable-everything.