Mac OS Detailed tutorial on compiling the FFmpeg decoding library for Android Studio

  • 2020-12-16 06:05:56
  • OfStack

NDK part
Download ndk
There's only one.

2. Unzip ndk
Do not unzip, file permissions will error. When executed, mv is automatically unzipped and placed where you want it. I in the "/ usr/local/bin/android - ndk - r10d" (use $NDK_DIR refer to after this directory).

3. Download Ffmpeg
I clicked on version 2.5.3.

4. Unzip Ffmpeg
Unzip Ffmpeg to $NDK_DIR/sources/ffmpeg-2.5.3.

5. Modify Ffmpeg compilation configuration
Drop these lines from the configure file in the ES36en-2.5.3 directory to remove the version number of the last "55" of the default-generated library name libavcodec.so.55.


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 should be configured correctly on 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 saving


sudo chmod +x build_android.sh
./build_android.sh

It will take a while to compile.

7, view the compilation results

After compiling $NDK_DIR/sources/ ffmpeg-2.5.3, there will be one more 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

Among them, libavcodec.so, libavfilter.so, libavformat.so, libavutil.so, libswresample.so, libswscale.so are soft chains, which are useless and can be deleted.

8. Write ES85en. mk to the Ffmpeg library to make it available
Create $NDK_DIR/sources/ffmpeg - 2.5.3 android/arm/Android mk files, content is as follows:
Note that the number before so should be changed to the number compiled by your version of ffmpeg.


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)

At this point, ndk is configured, followed by the parts that configure Android Studio.

Android Studio part
Android Studio is not exactly the same as Eclipse, it has a fixed ability to automatically generate ES113en.ES114en and automatically fix JNI.
The Ffmpeg library is not yet ready to be used.
So the idea was to disable the Android Studio automatic ndk-ES122en and compile our C code manually.

First, of course, create a new Android Studio project.
We use $ROOT_DIR to refer to the project root directory.

1. Android Studio configure ndk path
$ROOT_DIR/ ES139en.properties was originally configured with sdk only.


sdk.dir=/usr/local/bin/android-sdk-macosx

Add 1 line to its ndk configuration


sdk.dir=/usr/local/bin/android-sdk-macosx
ndk.dir=/usr/local/bin/android-ndk-r10d

2. Configuration of build.gradle
There are two build.gradle in the project, one in the root directory and one under $ROOT_DIR/app/src, which we want to modify.
A > Add this paragraph to disable automatic ndk-build.


sourceSets.main.jni.srcDirs = []

B > Add this section to let it know that you're using the library


SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
0

The revised ES171en. gradle looks like this.


SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
1

3. Generate header files
Execute the command, and note that the path changes according to your situation.


javah -d jni -classpath ..\..\build\intermediates\classes\debug com.example.nativeapp.app.MainActivity

Generates the file $ROOT_DIR/app/src/main/jni/com_example_chengang_myapplication_MainActivity h

4. Compile C files
$ROOT_DIR/app/src/main/jni/ovsplayer c content is as follows:



SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
2

5. Compile Java file
$ROOT_DIR/app src/main java/com/example/chengang/myapplication/MainActivity java content is as follows.
The getStringFromNative() method is implemented by us, printing out the version number of the Ffmpeg library (this one I compiled is 3673444) and the information of 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 will
  // automatically handle clicks on the Home/Up button, so long
  // as you 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");
 }
}

The attached layout file looks like this.


SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
4

6. Project Android.mk
Android. mk in $ROOT_DIR/app/build/intermediates/ndk debug /.
Pay attention to the absolute path "/ Users/chengang/Code Android/MyApplication4" are our $ROOT_DIR.


SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
5

Briefly, the difference between LOCAL_LDLIBS and LOCAL_SHARED_LIBRARIES is that the former links to the system library, while the latter links to the third library.
You can't switch.

7. Compile C code
Execute this command from the terminal to compile the C code.


/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. Run the project
Back to Android Studio Ctrl+R to run the project.
You'll see the version number of the Ffmpeg library printed out on the phone (the one I compiled was 3673444) and the video file information.
The Ffmpeg library is ready to be invoked, and you can just continue to write your own logic.

9, in addition
Here are two more errors you may encounter in the C code:
A > If you use the standard library to get the file size, you write the wrong file name. On Android, executing fseek on a handle that does not exist 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 forgot to call av_register_all(), and the other is that you did not compile Ffmpeg or specified ES306en-ES307en.


Related articles: