从本文开始打算记录一系列FFmpeg在Android/IOS开发的示例程序。前面几篇文章记录FFmpeg安卓端开发的例子,后面几篇文章记录FFmpeg IOS端开发的例子。这些例子中FFmpeg相关的代码源自于《FFmpeg示例合集》中的程序。本文记录第一个程序:安卓平台下基于FFmpeg的HelloWorld程序。
Android应用程序使用FFmpeg类库的流程图如下所示。
上图中的流程可以分为“编译FFmpeg类库”、“编写Java端代码”、“编写C语言端代码”三个步骤。
下载NDK之后直接解压缩就可以使用了。在Windows下使用的时候需要用到Cygwin。在这里我自己使用Linux编译类库。
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)‘
按照configure、make、make install的步骤就可以得到FFmpeg的头文件和类库文件了。其中configure的配置脚本在网上比较多。下面列举几个脚本。
FFmpeg类库完整功能脚本cd ffmpeg
make clean
export NDK=/home/leixiaohua1020/cdtworkspace/android-ndk-r9d
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt
export PLATFORM=$NDK/platforms/android-8/arch-arm
export PREFIX=../simplefflib
build_one(){
./configure --target-os=linux --prefix=$PREFIX --enable-cross-compile --enable-runtime-cpudetect --disable-asm --arch=arm --cc=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-gcc --cross-prefix=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi- --disable-stripping --nm=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-nm --sysroot=$PLATFORM --enable-gpl --enable-shared --disable-static --enable-small --disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-ffserver --disable-debug --extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a"
}
build_one
make
make install
cd ..
该脚本中前面几个变量“NDK”、“PREBUILT”、“PLATFORM”根据NDK路径的不同需要做相应的修改。另外需要注意64位NDK和32位NDK中某些文件夹名称也有一些区别:例如32位NDK中文件夹名称为“linux-x86”而64位NDK中文件夹名称为“linux-x86_64”。
将上述脚本拷贝至ffmpeg源代码外面,成功执行之后,会将类库和头文件生成到脚本所在目录下的“simplefflib”文件夹中。FFmpeg类库裁剪功能后包含libx264和libfaac支持脚本
下面这个脚本可以生成一个裁剪功能后,包含libx264和libfaac支持的类库。export NDK=/home/leixiaohua1020/cdtworkspace/android-ndk-r9d
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt
export PLATFORM=$NDK/platforms/android-8/arch-arm
export PREFIX=../264fflib
build_one(){
./configure --target-os=linux --prefix=$PREFIX --enable-cross-compile --enable-runtime-cpudetect --disable-asm --arch=arm --cc=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-gcc --cross-prefix=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi- --disable-stripping --nm=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-nm --sysroot=$PLATFORM --enable-gpl --enable-shared --disable-static --enable-nonfree --enable-version3 --enable-small --disable-vda --disable-iconv --disable-encoders --enable-libx264 --enable-libfaac --enable-encoder=libx264 --enable-encoder=libfaac --disable-muxers --enable-muxer=mov --enable-muxer=ipod --enable-muxer=psp --enable-muxer=mp4 --enable-muxer=avi --disable-decoders --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=h264 --enable-decoder=mpeg4 --disable-demuxers --enable-demuxer=h264 --enable-demuxer=avi --enable-demuxer=mpc --enable-demuxer=mov --disable-parsers --enable-parser=aac --enable-parser=ac3 --enable-parser=h264 --disable-protocols --enable-protocol=file --disable-bsfs --enable-bsf=aac_adtstoasc --enable-bsf=h264_mp4toannexb --disable-indevs --enable-zlib --disable-outdevs --disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-ffserver --disable-debug --extra-cflags="-I ../android-lib/include -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" --extra-ldflags="-L ../android-lib/lib"
}
build_one
make
make install
cd ..
cd x264 export NDK=/home/leixiaohua1020/cdtworkspace/android-ndk-r9d export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt export PLATFORM=$NDK/platforms/android-8/arch-arm export PREFIX=../android-lib ./configure --prefix=$PREFIX --enable-static --enable-pic --disable-asm --disable-cli --host=arm-linux --cross-prefix=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi- --sysroot=$PLATFORM cd ..
cd faac
export NDK=/home/leixiaohua1020/cdtworkspace/android-ndk-r9d
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt
export PLATFORM=$NDK/platforms/android-9/arch-arm
CFLAGS="-fpic -DANDROID -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_7__ -Wno-psabi -march=armv7 -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -DANDROID -Wa,--noexecstack -MMD -MP "
#CFLAGS="-fpic -DANDROID -fpic -mthumb-interwork -D__ARM_ARCH_7__ -Wno-psabi -march=armv7-a -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -DANDROID -Wa, -MMD -MP "
CROSS_COMPILE=$PREBUILT/linux-x86_64/bin/arm-linux-androideabi-
export CPPFLAGS="$CFLAGS"
export CFLAGS="$CFLAGS"
export CXXFLAGS="$CFLAGS"
export CXX="${CROSS_COMPILE}g++ --sysroot=${PLATFORM}"
export LDFLAGS="$LDFLAGS"
export CC="${CROSS_COMPILE}gcc --sysroot=${PLATFORM}"
export NM="${CROSS_COMPILE}nm"
export STRIP="${CROSS_COMPILE}strip"
export RANLIB="${CROSS_COMPILE}ranlib"
export AR="${CROSS_COMPILE}ar"
./configure --without-mp4v2 --host=arm-linux --enable-static
make
make install
cp -rf /usr/local/include/faac.h ../android-lib/include
cp -rf /usr/local/include/faaccfg.h ../android-lib/include
cp -rf /usr/local/lib/libfaac.a ../android-lib/lib
cd ..
libavformat-56.so
libavcodec-56.so
libavfilter-5.so
libavdevice-56.so
libavutil-54.so
libpostproc-53.so
libswresample-1.so
libswscale-3.so
package com.example.hellojni;
import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
public class HelloJni extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
/* Create a TextView and set its content.
* the text is retrieved by calling a native
* function.
*/
TextView tv = new TextView(this);
tv.setText( stringFromJNI() );
setContentView(tv);
}
/* A native method that is implemented by the
* ‘hello-jni‘ native library, which is packaged
* with this application.
*/
public native String stringFromJNI();
/* This is another native method declaration that is *not*
* implemented by ‘hello-jni‘. This is simply to show that
* you can declare as many native methods in your Java code
* as you want, their implementation is searched in the
* currently loaded native libraries only the first time
* you call them.
*
* Trying to call this function will result in a
* java.lang.UnsatisfiedLinkError exception !
*/
public native String unimplementedStringFromJNI();
/* this is used to load the ‘hello-jni‘ library on application
* startup. The library has already been unpacked into
* /data/data/com.example.hellojni/lib/libhello-jni.so at
* installation time by the package manager.
*/
static {
System.loadLibrary("hello-jni");
}
}
static {
System.loadLibrary("avutil-54");
System.loadLibrary("avcodec-56");
System.loadLibrary("avformat-56");
System.loadLibrary("avdevice-56");
System.loadLibrary("swresample-1");
System.loadLibrary("swscale-3");
System.loadLibrary("postproc-53");
System.loadLibrary("avfilter-5");
System.loadLibrary("hello-jni");
}javah com.example.hellojni.HelloJni就可以在当前目录下生成一个头文件“com_example_hellojni_HelloJni.h”,该头文件内容如下所示。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_hellojni_HelloJni */
#ifndef _Included_com_example_hellojni_HelloJni
#define _Included_com_example_hellojni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_hellojni_HelloJni
* Method: stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI
(JNIEnv *, jobject);
/*
* Class: com_example_hellojni_HelloJni
* Method: unimplementedStringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_unimplementedStringFromJNI
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
从源代码可以看出,JNI调用的C语言函数是有固定格式的,即:
Java_{包名}_{包名}…_{类名}(JNIEnv *,…)
对于HelloJni类中的stringFromJNI方法,其C语言版本的函数声明为:JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI (JNIEnv *, jobject)PS:这个头文件只是一个参考,对于JNI来说并不是必须的。也可以根据命名规则直接编写C语言函数。
#include <string.h>
#include <jni.h>
/* This is a trivial JNI example where we use a native method
* to return a new VM String. See the corresponding Java source
* file located at:
*
* apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java
*/
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
#if defined(__arm__)
#if defined(__ARM_ARCH_7A__)
#if defined(__ARM_NEON__)
#define ABI "armeabi-v7a/NEON"
#else
#define ABI "armeabi-v7a"
#endif
#else
#define ABI "armeabi"
#endif
#elif defined(__i386__)
#define ABI "x86"
#elif defined(__mips__)
#define ABI "mips"
#else
#define ABI "unknown"
#endif
return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");
}
#include <string.h>
#include <jni.h>
#include "libavcodec/avcodec.h"
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
char info[10000] = { 0 };
sprintf(info, "%s\n", avcodec_configuration());
return (*env)->NewStringUTF(env, info);
}
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir) # FFmpeg library include $(CLEAR_VARS) LOCAL_MODULE := avcodec LOCAL_SRC_FILES := libavcodec-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avdevice LOCAL_SRC_FILES := libavdevice-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avfilter LOCAL_SRC_FILES := libavfilter-5.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avformat LOCAL_SRC_FILES := libavformat-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avutil LOCAL_SRC_FILES := libavutil-54.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := postproc LOCAL_SRC_FILES := libpostproc-53.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := swresample LOCAL_SRC_FILES := libswresample-1.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := swscale LOCAL_SRC_FILES := libswscale-3.so include $(PREBUILT_SHARED_LIBRARY) # Program include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c LOCAL_C_INCLUDES += $(LOCAL_PATH)/include LOCAL_LDLIBS := -llog -lz LOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale include $(BUILD_SHARED_LIBRARY)
Application.mk中的APP_ABI设定了编译后库文件支持的指令集,默认使用“armeabi”。在hello-jni例子中,APP_ABI取值为“all”。由于我们编译的FFmpeg并不在像x86这样的平台下运行,所以不需要“all”,把它修改为“armeabi”或者删除就可以了(对于hello-jni这个例子,不做这一步的话会在编译x86平台类库的时候报错,但并不影响后面的测试运行)。
libavformat-56.so
libavcodec-56.so
libavfilter-5.so
libavdevice-56.so
libavutil-54.so
libpostproc-53.so
libswresample-1.so
libswscale-3.so
libhello-jni.so
接下来就可以在Android手机或者虚拟机上对整个Android工程进行测试了。
Protocol: FFmpeg类库支持的协议
AVFormat: FFmpeg类库支持的封装格式
AVCodec: FFmpeg类库支持的编解码器
AVFilter: FFmpeg类库支持的滤镜
Configure: FFmpeg类库的配置信息
Android程序Java端代码位于src\com\leixiaohua1020\sffmpegandroidhelloworld\MainActivity.java,如下所示。
/**
* 最简单的基于FFmpeg的Helloworld例子-安卓
* Simplest FFmpeg Android Helloworld
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
*
* 本程序是移植FFmpeg到安卓平台的最简单程序。它可以打印出FFmpeg类库的下列信息:
* Protocol: FFmpeg类库支持的协议
* AVFormat: FFmpeg类库支持的封装格式
* AVCodec: FFmpeg类库支持的编解码器
* AVFilter: FFmpeg类库支持的滤镜
* Configure: FFmpeg类库的配置信息
*
* This is the simplest program based on FFmpeg in Android. It can show following
* informations about FFmpeg library:
* Protocol: Protocols supported by FFmpeg.
* AVFormat: Container format supported by FFmpeg.
* AVCodec: Encoder/Decoder supported by FFmpeg.
* AVFilter: Filters supported by FFmpeg.
* Configure: configure information of FFmpeg.
*
*/
package com.leixiaohua1020.sffmpegandroidhelloworld;
import android.os.Bundle;
import android.app.Activity;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView libinfoText = (TextView) findViewById(R.id.text_libinfo);
libinfoText.setMovementMethod(ScrollingMovementMethod.getInstance());
libinfoText.setText(configurationinfo());
Button configurationButton = (Button) this.findViewById(R.id.button_configuration);
Button urlprotocolButton = (Button) this.findViewById(R.id.button_urlprotocol);
Button avformatButton = (Button) this.findViewById(R.id.button_avformat);
Button avcodecButton = (Button) this.findViewById(R.id.button_avcodec);
Button avfilterButton = (Button) this.findViewById(R.id.button_avfilter);
urlprotocolButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0){
libinfoText.setText(urlprotocolinfo());
}
});
avformatButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0){
libinfoText.setText(avformatinfo());
}
});
avcodecButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0){
libinfoText.setText(avcodecinfo());
}
});
avfilterButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0){
libinfoText.setText(avfilterinfo());
}
});
configurationButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0){
libinfoText.setText(configurationinfo());
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
//JNI
public native String urlprotocolinfo();
public native String avformatinfo();
public native String avcodecinfo();
public native String avfilterinfo();
public native String configurationinfo();
static{
System.loadLibrary("avutil-54");
System.loadLibrary("swresample-1");
System.loadLibrary("avcodec-56");
System.loadLibrary("avformat-56");
System.loadLibrary("swscale-3");
System.loadLibrary("postproc-53");
System.loadLibrary("avfilter-5");
System.loadLibrary("avdevice-56");
System.loadLibrary("sffhelloworld");
}
}
/**
* 最简单的基于FFmpeg的Helloworld例子-安卓
* Simplest FFmpeg Android Helloworld
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
*
* 本程序是移植FFmpeg到安卓平台的最简单程序。它可以打印出FFmpeg类库的下列信息:
* Protocol: FFmpeg类库支持的协议
* AVFormat: FFmpeg类库支持的封装格式
* AVCodec: FFmpeg类库支持的编解码器
* AVFilter: FFmpeg类库支持的滤镜
* Configure: FFmpeg类库的配置信息
*
* This is the simplest program based on FFmpeg in Android. It can show following
* informations about FFmpeg library:
* Protocol: Protocols supported by FFmpeg.
* AVFormat: Container format supported by FFmpeg.
* AVCodec: Encoder/Decoder supported by FFmpeg.
* AVFilter: Filters supported by FFmpeg.
* Configure: configure information of FFmpeg.
*/
#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
//Log
#ifdef ANDROID
#include <jni.h>
#include <android/log.h>
#define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)
#else
#define LOGE(format, ...) printf("(>_<) " format "\n", ##__VA_ARGS__)
#endif
//FIX
struct URLProtocol;
/**
* com.leixiaohua1020.sffmpegandroidhelloworld.MainActivity.urlprotocolinfo()
* Protocol Support Information
*/
JNIEXPORT jstring Java_com_leixiaohua1020_sffmpegandroidhelloworld_MainActivity_urlprotocolinfo(JNIEnv *env, jobject obj){
char info[40000]={0};
av_register_all();
struct URLProtocol *pup = NULL;
//Input
struct URLProtocol **p_temp = &pup;
avio_enum_protocols((void **)p_temp, 0);
while ((*p_temp) != NULL){
sprintf(info, "%s[In ][%10s]\n", info, avio_enum_protocols((void **)p_temp, 0));
}
pup = NULL;
//Output
avio_enum_protocols((void **)p_temp, 1);
while ((*p_temp) != NULL){
sprintf(info, "%s[Out][%10s]\n", info, avio_enum_protocols((void **)p_temp, 1));
}
//LOGE("%s", info);
return (*env)->NewStringUTF(env, info);
}
/**
* com.leixiaohua1020.sffmpegandroidhelloworld.MainActivity.avformatinfo()
* AVFormat Support Information
*/
JNIEXPORT jstring Java_com_leixiaohua1020_sffmpegandroidhelloworld_MainActivity_avformatinfo(JNIEnv *env, jobject obj){
char info[40000] = { 0 };
av_register_all();
AVInputFormat *if_temp = av_iformat_next(NULL);
AVOutputFormat *of_temp = av_oformat_next(NULL);
//Input
while(if_temp!=NULL){
sprintf(info, "%s[In ][%10s]\n", info, if_temp->name);
if_temp=if_temp->next;
}
//Output
while (of_temp != NULL){
sprintf(info, "%s[Out][%10s]\n", info, of_temp->name);
of_temp = of_temp->next;
}
//LOGE("%s", info);
return (*env)->NewStringUTF(env, info);
}
/**
* com.leixiaohua1020.sffmpegandroidhelloworld.MainActivity.avcodecinfo()
* AVCodec Support Information
*/
JNIEXPORT jstring Java_com_leixiaohua1020_sffmpegandroidhelloworld_MainActivity_avcodecinfo(JNIEnv *env, jobject obj)
{
char info[40000] = { 0 };
av_register_all();
AVCodec *c_temp = av_codec_next(NULL);
while(c_temp!=NULL){
if (c_temp->decode!=NULL){
sprintf(info, "%s[Dec]", info);
}
else{
sprintf(info, "%s[Enc]", info);
}
switch (c_temp->type){
case AVMEDIA_TYPE_VIDEO:
sprintf(info, "%s[Video]", info);
break;
case AVMEDIA_TYPE_AUDIO:
sprintf(info, "%s[Audio]", info);
break;
default:
sprintf(info, "%s[Other]", info);
break;
}
sprintf(info, "%s[%10s]\n", info, c_temp->name);
c_temp=c_temp->next;
}
//LOGE("%s", info);
return (*env)->NewStringUTF(env, info);
}
/**
* com.leixiaohua1020.sffmpegandroidhelloworld.MainActivity.avfilterinfo()
* AVFilter Support Information
*/
JNIEXPORT jstring Java_com_leixiaohua1020_sffmpegandroidhelloworld_MainActivity_avfilterinfo(JNIEnv *env, jobject obj)
{
char info[40000] = { 0 };
av_register_all();
AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
while (f_temp != NULL){
sprintf(info, "%s[%10s]\n", info, f_temp->name);
}
//LOGE("%s", info);
return (*env)->NewStringUTF(env, info);
}
/**
* com.leixiaohua1020.sffmpegandroidhelloworld.MainActivity.urlprotocolinfo()
* Protocol Support Information
*/
JNIEXPORT jstring Java_com_leixiaohua1020_sffmpegandroidhelloworld_MainActivity_configurationinfo(JNIEnv *env, jobject obj)
{
char info[10000] = { 0 };
av_register_all();
sprintf(info, "%s\n", avcodec_configuration());
//LOGE("%s", info);
return (*env)->NewStringUTF(env, info);
}
# Android.mk for FFmpeg # # Lei Xiaohua 雷霄骅 # leixiaohua1020@126.com # http://blog.csdn.net/leixiaohua1020 # LOCAL_PATH := $(call my-dir) # FFmpeg library include $(CLEAR_VARS) LOCAL_MODULE := avcodec LOCAL_SRC_FILES := libavcodec-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avdevice LOCAL_SRC_FILES := libavdevice-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avfilter LOCAL_SRC_FILES := libavfilter-5.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avformat LOCAL_SRC_FILES := libavformat-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avutil LOCAL_SRC_FILES := libavutil-54.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := postproc LOCAL_SRC_FILES := libpostproc-53.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := swresample LOCAL_SRC_FILES := libswresample-1.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := swscale LOCAL_SRC_FILES := libswscale-3.so include $(PREBUILT_SHARED_LIBRARY) # Program include $(CLEAR_VARS) LOCAL_MODULE := sffhelloworld LOCAL_SRC_FILES :=simplest_ffmpeg_helloworld.c LOCAL_C_INCLUDES += $(LOCAL_PATH)/include LOCAL_LDLIBS := -llog -lz LOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale include $(BUILD_SHARED_LIBRARY)
Github:https://github.com/leixiaohua1020/simplest_ffmpeg_mobile
开源中国:https://git.oschina.net/leixiaohua1020/simplest_ffmpeg_mobile
CSDN工程下载地址:http://download.csdn.net/detail/leixiaohua1020/8924391
本解决方案包含了使用FFmpeg在移动端处理多媒体的各种例子:
[Android]
simplest_android_player: 基于安卓接口的视频播放器
simplest_ffmpeg_android_helloworld: 安卓平台下基于FFmpeg的HelloWorld程序
simplest_ffmpeg_android_decoder: 安卓平台下最简单的基于FFmpeg的视频解码器
simplest_ffmpeg_android_decoder_onelib: 安卓平台下最简单的基于FFmpeg的视频解码器-单库版
simplest_ffmpeg_android_streamer: 安卓平台下最简单的基于FFmpeg的推流器
simplest_ffmpeg_android_transcoder: 安卓平台下移植的FFmpeg命令行工具
simplest_sdl_android_helloworld: 移植SDL到安卓平台的最简单程序
[IOS]
simplest_ios_player: 基于IOS接口的视频播放器
simplest_ffmpeg_ios_helloworld: IOS平台下基于FFmpeg的HelloWorld程序
simplest_ffmpeg_ios_decoder: IOS平台下最简单的基于FFmpeg的视频解码器
simplest_ffmpeg_ios_streamer: IOS平台下最简单的基于FFmpeg的推流器
simplest_ffmpeg_ios_transcoder: IOS平台下移植的ffmpeg.c命令行工具
simplest_sdl_ios_helloworld: 移植SDL到IOS平台的最简单程序
版权声明:本文为博主原创文章,未经博主允许不得转载。
最简单的基于FFmpeg的移动端例子:Android HelloWorld
原文地址:http://blog.csdn.net/leixiaohua1020/article/details/47008825