.移植ffmpeg到android

-----------------------另一个方法

FFMPEG移植到Android(ubuntu环境下)

分类: androidndk+jni 2010-10-28 15:43 1964人阅读 评论(11)收藏 举报

搞左2日,找了好多资料,终于把ffmpeg移植到android上了。其中参考了一篇介绍移植方法的doc文档,里面是用windows+Cygwin+ndk(windows版本)作为编译环境的,我这里直接用ubuntu了,省了很多配置了^_^。感谢前辈的无私奉献。。。

-->环境:

操作系统:Ubuntu 9.10

ffmpeg源码版本:ffmpeg-0.6.1(可以在http://ffmpeg.org/download.html下载源码)

android ndk版本:android-ndk-r4b-linux-x86(可以在http://androidappdocs.appspot.com/sdk/ndk/index.html下载)

-->设置NDK环境变量:

1、用root用户登陆,打开命令窗口,输入cd /root

2、输入ls -a,会显示一个隐藏文件.bashrc

3、输入vi .bashrc,按i进入编辑模式

4、文件底部添加以下两行:
NDK_ROOT=/home/ndk。这里指你ndk的目录路径
export NDK_ROOT
5、按esc退出,再按:wq保存

你可以测试一下有没有安装成功:
$ cd $NDK_ROOT
$ ./ndk-build NDK_PROJECT_PATH=$NDK_ROOT/samples/two-libs

找到生成的文件就代表安装正常了。

1、如果提示某个文件"Permission denied"之类的信息时,执行chmod 777your_filename就行了

2、如果提示找不到'cc1'等信息,执行chmod -R 777 *,就能解决了

-->配置源代码

在/home/ndk/samples/创建一个FFMPEG文件夹,在里面再新建一个jni文件夹,然后把ffmpeg源码放在jni里面,所以最后ffmpeg源码的路径是:
/home/ndk/samples/FFMPEG/jni/ffmpeg

1. 在ffmpeg源文件夹下创建一个config.sh,内容如下:
#!/bin/bash

PREBUILT=/home/ndk/build/prebuilt/linux/arm-eabi-4.4.0
PLATFORM=/home/ndk/build/platforms/android-3/arch-arm

./configure --target-os=linux /
 --arch=arm /
 --enable-version3 /
 --enable-gpl /
 --enable-nonfree /
 --disable-stripping /
 --disable-ffmpeg /
 --disable-ffplay /
 --disable-ffserver /
 --disable-ffprobe /
 --disable-encoders /
 --disable-muxers /
 --disable-devices /
 --disable-protocols /
 --enable-protocol=file /
 --enable-avfilter /
 --disable-network /
 --disable-mpegaudio-hp /
 --disable-avdevice /
 --enable-cross-compile /
 --cc=$PREBUILT/bin/arm-eabi-gcc /
 --cross-prefix=$PREBUILT/bin/arm-eabi- /
 --nm=$PREBUILT/bin/arm-eabi-nm /
 --extra-cflags="-fPIC -DANDROID" /
 --disable-asm /
 --enable-neon /
 --enable-armv5te /
 --extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib$PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o$PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"

记得PREBUILT和PLATFORM要设置正确,它在你的NDK里面,你可以按自己的填写

2. 然后打开命令窗口,cdffmpeg源文件夹下。
$ chmod +xconfig.sh       
$ ./config.sh

如果配置正确的话显示出来的最后两行是这样的:
License: nonfree and unredistributable
Creating config.mak and config.h...

3、Configure完成后接下做NDK编译的条件了。
Android的GCC是不支持restrict关键字的,所以把ffmpeg源码下configure生成的config.h文件中的这一行:
#define restrict restrict   改成#definerestrict   
如果重新Configure的话记得要把这个关键字去掉。

编辑libavutil/libm.h把其中的static的方法都删除(如果找不到libavutil/libm.h,就表明你的ffmpeg版本不是0.6而是0.5的。)

分别把libavutil、libavcodec、libavformat、libavfilter、libpostproct和libswscale下的Makefile文件中下面两行删除掉:
include $(SUBDIR)../subdir.mak
include $(SUBDIR)../config.mak

然后在ffmpeg源文件夹下新建一个av.mk文件,内容如下:(这些不用替换回车)
# LOCAL_PATH is one of libavutil, libavcodec, libavformat, orlibswscale

#include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
include $(LOCAL_PATH)/../config.mak

OBJS :=
OBJS-yes :=
MMX-OBJS-yes :=
include $(LOCAL_PATH)/Makefile

# collect objects
OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)
OBJS += $(OBJS-yes)

FFNAME := lib$(NAME)
FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))
FFCFLAGS  = -DHAVE_AV_CONFIG_H -Wno-sign-compare-Wno-switch -Wno-pointer-sign
FFCFLAGS += -DTARGET_CONFIG=/"config-$(TARGET_ARCH).h/"

ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=  /
 $(LOCAL_PATH)  /
 $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
#LOCAL_SHARED_LIBRARIES :=(这行根据下面蓝色的来填写相应的lib)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_SHARED_LIBRARY)

----------------------------------------

ffmpeg/libavutil:不需要这一行,直接加#屏蔽掉。
ffmpeg/libswscale:LOCAL_SHARED_LIBRARIES :=libavutil
ffmpeg/libavfilter:LOCAL_SHARED_LIBRARIES :=libavutil libswscalelibavcodec
ffmpeg/libpostproc:LOCAL_SHARED_LIBRARIES :=libavutil

可能编译libavdevice也是用上面这个Android.mk,然后根据提示的错误没改变红色这行就OK了。

最后就是运行ndk-build了:
$ cd $NDK_ROOT
$ ./ndk-build NDK_PROJECT_PATH=$NDK_ROOT/samples/FFMPEG

最后生成libavcodec.so、libavutil.so、libavformat.so、libavfilter.so、libswscale.so和libpostproc.so以及libffmpeg.so,你会发现libffmpeg.so只有2K(1599个字节),其实这个文件是没有加载任何东西而编译成的空SO文件,没有任何函数的SO文件。所以不能用,但其它的都可以。估计是没有LOCAL_SRC_FILES的原因。

另外一篇不错的参考文章:http://www.eoeandroid.com/thread-42184-1-1.html,它生成的是静态库

分享到:
  • 上一篇:横竖屏切换测试
  • 下一篇:Ubuntu+旧版androidndk生成so库文件
查看评论
8楼 perfy001 2011-09-22 10:30发表 [回复] [引用] [举报]
遇到不少问题,想向楼主请教啊!可楼主见不着人了!!
7楼 abc526541845 2011-05-06 14:29发表 [回复] [引用] [举报]
关注
最近也要做这方面的工作
6楼 HongMenzhouxiangang 2011-04-1414:28发表 [回复] [引用] [举报]
我也编译成功了。不过不是用root用户。
Re: shenchao8528 2011-04-21 18:37发表 [回复] [引用] [举报]
回复 HongMenzhouxiangang:你编译成功以后,是不是有两个libffmpeg.so?
5楼 hj475955463 2011-03-23 17:34发表 [回复] [引用] [举报]
楼主您好,现在我已经把ffmpeg编译成功了,但是不知道怎么在androidNDK下使用,网上的例子也都没说明白,您能提供一个一个可以使用的例子么?万分感谢,可以发我邮箱hj2060@126.com

用NDK编译FFmpeg  [复制链接]

android内置的编解码器实在太少,于是我们需要FFmpeg。Android提供了NDK,为我们使用FFmpeg这种C语言代码提供了方便。
首先创建一个标准的Android项目vPlayer

  1. android create project -n vPlayer -t 8 -p vPlayer -kme.abitno.vplayer -a PlayerView

复制代码

然后在vPlayer目录里

  1. mkdir jni && cd jni
  2. wget http://ffmpeg.org/releases/ffmpeg-0.6.tar.bz2
  3. tar xf ffmpeg-0.6.tar.bz2 && mvffmpeg-0.6 ffmpeg && cd ffmpeg

复制代码

在ffmpeg下新建一个config.sh,内容如下,注意把PREBUILT和PLATFORM设置正确。另外里面有些参数你也可以自行调整,我主要是为了配置一个播放器而这样设置的。

  1. #!/bin/bash
  2. PREBUILT=/home/abitno/Android/android-ndk-r4/build/prebuilt/linux-x86/arm-eabi-4.4.0
  3. PLATFORM=/home/abitno/Android/android-ndk-r4/build/platforms/android-8/arch-arm
  4. ./configure --target-os=linux \
  5. --arch=arm \
  6. --enable-version3 \
  7. --enable-gpl \
  8. --enable-nonfree \
  9. --disable-stripping \
  10. --disable-ffmpeg \
  11. --disable-ffplay \
  12. --disable-ffserver \
  13. --disable-ffprobe \
  14. --disable-encoders \
  15. --disable-muxers \
  16. --disable-devices \
  17. --disable-protocols \
  18. --enable-protocol=file \
  19. --enable-avfilter \
  20. --disable-network \
  21. --disable-mpegaudio-hp \
  22. --disable-avdevice \
  23. --enable-cross-compile \
  24. --cc=$PREBUILT/bin/arm-eabi-gcc \
  25. --cross-prefix=$PREBUILT/bin/arm-eabi-\
  26. --nm=$PREBUILT/bin/arm-eabi-nm \
  27. --extra-cflags="-fPIC -DANDROID" \
  28. --disable-asm \
  29. --enable-neon \
  30. --enable-armv5te \
  31. --extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib$PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o$PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"

复制代码

运行config.sh开始configure

  1. chmod +x config.sh
  2. ./config.sh

复制代码

configure完成后,编辑刚刚生成的config.h,找到这句

  1. #define restrict restrict

复制代码

Android的GCC不支持restrict关键字,于是修改成下面这样

  1. #define restrict

复制代码

编辑libavutil/libm.h,把其中的static方法都删除。

分别修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale下的Makefile,把下面两句删除

  1. include $(SUBDIR)../subdir.mak
  2. include $(SUBDIR)../config.mak

复制代码

在ffmpeg下添加一个文件av.mk,内容如下

  1. # LOCAL_PATH is one of libavutil, libavcodec, libavformat, orlibswscale
  2. #include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
  3. include $(LOCAL_PATH)/../config.mak
  4. OBJS :=
  5. OBJS-yes :=
  6. MMX-OBJS-yes :=
  7. include $(LOCAL_PATH)/Makefile
  8. # collect objects
  9. OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)
  10. OBJS += $(OBJS-yes)
  11. FFNAME := lib$(NAME)
  12. FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))
  13. FFCFLAGS  =-DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch-Wno-pointer-sign
  14. FFCFLAGS +=-DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\"
  15. ALL_S_FILES := $(wildcard$(LOCAL_PATH)/$(TARGET_ARCH)
  16. JNIEXPORT void JNICALL Java_com_chnic_jni_SayHellotoCPP_sayHello
  17. (JNIEnv *, jobject, jstring);

仔细观察一下这个方法,在注释上标注类名、方法名、签名(Signature),至于这个签名是做什么用的,我们以后再说。在这里最重要的是Java_com_chnic_jni_SayHellotoCPP_sayHello这个方法签名。在Java端我们执行sayHello(Stringname)这个方法之后,JVM就会帮我们唤醒在DLL里的Java_com_chnic_jni_SayHellotoCPP_sayHello这个方法。因此我们新建一个C++ source file来实现这个方法。

Cpp代码
  1. #include <iostream.h>
  2. #include "com_chnic_jni_SayHellotoCPP.h"
  3. JNIEXPORT void JNICALL Java_com_chnic_jni_SayHellotoCPP_sayHello
  4. (JNIEnv* env, jobject obj, jstring name)
  5. {
  6. const char* pname = env->GetStringUTFChars(name, NULL);
  7. cout << "Hello, " << pname << endl;
  8. }

因为我们生成的那个头文件是在C++工程的根目录不是在环境目录,所以我们要把尖括号改成单引号,至于VC++的环境目录可以在Tools->Options->Directories里设置。F7编译工程发现缺少jni.h这个头文件。这个头文件可以在%JAVA_HOME%\include目录下找到。把这个文件拷贝到C++工程目录,继续编译发现还是找不到。原来是因为在我们刚刚生成的那个头文件里,jni.h这个文件是被 #include<jni.h>引用进来的,因此我们把尖括号改成双引号#include"jni.h",继续编译发现少了jni_md.h文件,接着在%JAVA_HOME%\include\win32下面找到那个头文件,放入到工程根目录,F7编译成功。在Debug目录里会发现生成了HelloEnd.dll这个文件。

这个时候后端的C++代码也已经完成,接下来的任务就是怎么把他们连接在一起了,要让前端的java程序“认识并找到”这个动态链接库,就必须把这个DLL放在windowspath环境变量下面。有两种方法可以做到:

  1. 把这个DLL放到windows下面的sysytem32文件夹下面,这个是windows默认的path
  2. 复制你工程的Debug目录,我这里是C:\Program Files\Microsoft VisualStudio\MyProjects\HelloEnd\Debug这个目录,把这个目录配置到Uservariable的Path下面。重启eclipse,让eclipse在启动的时候重新读取这个path变量。

比较起来,第二种方法比较灵活,在开发的时候不用来回copydll文件了,节省了很多工作量,所以在开发的时候推荐用第二种方法。在这里我们使用的也是第二种,eclipse重启之后打开SayHellotoCPP这个类。其实我们上面做的那些是不是是让JVM能找到那些DLL文件,接下来我们要让我们自己的java代码“认识”这个动态链接库。加入System.loadLibrary("HelloEnd");这句到静态初始化块里。

Java代码
  1. package com.chnic.jni;
  2. public class SayHellotoCPP {
  3. static{
  4. System.loadLibrary("HelloEnd");
  5. }
  6. public SayHellotoCPP(){
  7. }
  8. public native void sayHello(String name);
  9. }

这样我们的代码就能认识并加载这个动态链接库文件了。万事俱备,只欠测试代码了,接下来编写测试代码。

Java代码
  1. SayHellotoCPP shp = new SayHellotoCPP();
  2. shp.sayHello("World");

我们不让他直接Hello,World。我们把World传进去,执行代码。发现控制台打印出来Hello,World这句话。就此一个最简单的JNI程序已经开发完成。也许有朋友会对CPP代码里的

Cpp代码
  1. const char* pname = env->GetStringUTFChars(name, NULL);

这句有疑问,这个GetStringUTFChars就是JNI给developer提供的API,我们以后再讲。在这里不得不多句嘴。

  1. 因为JNI有一个Native这个特点,一点有项目用了JNI,也就说明这个项目基本不能跨平台了。
  2. JNI调用是相当慢的,在实际使用的之前一定要先想明白是否有这个必要。
  3. 因为C++和C这样的语言非常灵活,一不小心就容易出错,比如我刚刚的代码就没有写析构字符串释放内存,对于javadeveloper来说因为有了GC垃圾回收机制,所以大多数人没有写析构函数这样的概念。所以JNI也会增加程序中的风险,增大程序的不稳定性。

其实在Java代码中,除了对本地方法标注native关键字和加上要加载动态链接库之外,JNI基本上是对上层coder透明的,上层coder调用那些本地方法的时候并不知道这个方法的方法体究竟是在哪里,这个道理就像我们用JDK所提供的API一样。所以在Java中使用JNI还是很简单的,相比之下在C++中调用java,就比前者要复杂的多了。

现在来介绍下JNI里的数据类型。在C++里,编译器会很据所处的平台来为一些基本的数据类型来分配长度,因此也就造成了平台不一致性,而这个问题在Java中则不存在,因为有JVM的缘故,所以Java中的基本数据类型在所有平台下得到的都是相同的长度,比如int的宽度永远都是32位。基于这方面的原因,java和c++的基本数据类型就需要实现一些mapping,保持一致性。下面的表可以概括:

    Java类型              本地类型               JNI中定义的别名   
int long jint
long _int64 jlong
byte signed char jbyte
boolean unsigned char jboolean
char unsigned short jchar
short short jshort
float float jfloat
double double jdouble
Object _jobject* jobject

上面的表格是我在网上搜的,放上来给大家对比一下。对于每一种映射的数据类型,JNI的设计者其实已经帮我们取好了相应的别名以方便记忆。如果想了解一些更加细致的信息,可以去看一些jni.h这个头文件,各种数据类型的定义以及别名就被定义在这个文件中。

了解了JNI中的数据类型,下面就来看这次的例子。这次我们用Java来实现一个前端的market(以下就用Foreground代替)用CPP来实现一个后端factory(以下用backend代替)。我们首先还是来编写包含本地方法的java类。

Java代码
  1. package com.chnic.service;
  2. import com.chnic.bean.Order;
  3. public class Business {
  4. static{
  5. System.loadLibrary("FruitFactory");
  6. }
  7. public Business(){
  8. }
  9. public native double getPrice(String name);
  10. public native Order getOrder(String name, int amount);
  11. public native Order getRamdomOrder();
  12. public native void analyzeOrder(Order order);
  13. public void notification(){
  14. System.out.println("Got a notification.");
  15. }
  16. public static void notificationByStatic(){
  17. System.out.println("Got a notification in a static method.");
  18. }
  19. }

这个类里面包含4个本地方法,一个静态初始化块加载将要生成的dll文件。剩下的方法都是很普通的java方法,等会在backend中回调这些方法。这个类需要一个名为Order的JavaBean。

Java代码
  1. package com.chnic.bean;
  2. public class Order {
  3. private String name = "Fruit";
  4. private double price;
  5. private int amount = 30;
  6. public Order(){
  7. }
  8. public int getAmount() {
  9. return amount;
  10. }
  11. public void setAmount(int amount) {
  12. this.amount = amount;
  13. }
  14. public String getName() {
  15. return name;
  16. }
  17. public void setName(String name) {
  18. this.name = name;
  19. }
  20. public double getPrice() {
  21. return price;
  22. }
  23. public void setPrice(double price) {
  24. this.price = price;
  25. }
  26. }

JavaBean中,我们为两个私有属性赋值,方便后面的例子演示。到此为止除了测试代码之外的Java端的代码就全部高调了,接下来进行生成.h头文件、建立C++工程的工作,在这里就一笔带过,不熟悉的朋友请回头看第一篇。在工程里我们新建一个名为Foctory的C++source file 文件,去实现那些native方法。具体的代码如下。

Cpp代码
  1. #include <iostream.h>
  2. #include <string.h>
  3. #include "com_chnic_service_Business.h"
  4. jobject getInstance(JNIEnv* env, jclass obj_class);
  5. JNIEXPORT jdouble JNICALL Java_com_chnic_service_Business_getPrice(JNIEnv* env,
  6. jobject obj,
  7. jstring name)
  8. {
  9. const char* pname = env->GetStringUTFChars(name, NULL);
  10. cout << "Before release: "  << pname << endl;
  11. if (strcmp(pname, "Apple") == 0)
  12. {
  13. env->ReleaseStringUTFChars(name, pname);
  14. cout << "After release: " << pname << endl;
  15. return 1.2;
  16. }
  17. else
  18. {
  19. env->ReleaseStringUTFChars(name, pname);
  20. cout << "After release: " << pname << endl;
  21. return 2.1;
  22. }
  23. }
  24. JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getOrder(JNIEnv* env,
  25. jobject obj,
  26. jstring name,
  27. jint amount)
  28. {
  29. jclass order_class = env->FindClass("com/chnic/bean/Order");
  30. jobject order = getInstance(env, order_class);
  31. jmethodID setName_method = env->GetMethodID(order_class, "setName", "(Ljava/lang/String;)V");
  32. env->CallVoidMethod(order, setName_method, name);
  33. jmethodID setAmount_method = env->GetMethodID(order_class, "setAmount", "(I)V");
  34. env->CallVoidMethod(order, setAmount_method, amount);
  35. return order;
  36. }
  37. JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getRamdomOrder(JNIEnv* env,
  38. jobject obj)
  39. {
  40. jclass business_class = env->GetObjectClass(obj);
  41. jobject business_obj = getInstance(env, business_class);
  42. jmethodID notification_method = env->GetMethodID(business_class, "notification", "()V");
  43. env->CallVoidMethod(obj, notification_method);
  44. jclass order_class = env->FindClass("com/chnic/bean/Order");
  45. jobject order = getInstance(env, order_class);
  46. jfieldID amount_field = env->GetFieldID(order_class, "amount", "I");
  47. jint amount = env->GetIntField(order, amount_field);
  48. cout << "amount: " << amount << endl;
  49. return order;
  50. }
  51. JNIEXPORT void JNICALL Java_com_chnic_service_Business_analyzeOrder (JNIEnv* env,
  52. jclass cls,
  53. jobject obj)
  54. {
  55. jclass order_class = env->GetObjectClass(obj);
  56. jmethodID getName_method = env->GetMethodID(order_class, "getName", "()Ljava/lang/String;");
  57. jstring name_str = static_cast<jstring>(env->CallObjectMethod(obj, getName_method));
  58. const char* pname = env->GetStringUTFChars(name_str, NULL);
  59. cout << "Name in Java_com_chnic_service_Business_analyzeOrder: " << pname << endl;
  60. jmethodID notification_method_static = env->GetStaticMethodID(cls, "notificationByStatic", "()V");
  61. env->CallStaticVoidMethod(cls, notification_method_static);
  62. }
  63. jobject getInstance(JNIEnv* env, jclass obj_class)
  64. {
  65. jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V");
  66. jobject obj = env->NewObject(obj_class, construction_id);
  67. return obj;
  68. }

可以看到,在我Java中的四个本地方法在这里全部被实现,接下来针对这四个方法来解释下,一些JNI相关的API的使用方法。先从第一个方法讲起吧:

1.getPrice(String name)

这个方法是从foreground传递一个类型为string的参数到backend,然后backend判断返回相应的价格。在cpp的代码中,我们用GetStringUTFChars这个方法来把传来的jstring变成一个UTF-8编码的char型字符串。因为jstring的实际类型是jobject,所以无法直接比较。

GetStringUTFChars方法包含两个参数,第一参数是你要处理的jstring对象,第二个参数是否需要在内存中生成一个副本对象。将jstring转换成为了一个constchar*了之后,我们用string.h中带strcmp函数来比较这两个字符串,如果传来的字符串是“Apple”的话我们返回1.2。反之返回2.1。在这里还要多说一下ReleaseStringUTFChars这个函数,这个函数从字面上不难理解,就是释放内存用的。有点像cpp里的析构函数,只不过Sun帮我们已经封装好了。由于在JVM中有GC这个东东,所以多数javacoder并没有写析构的习惯,不过在JNI里是必须的了,否则容易造成内存泄露。我们在这里在release之前和之后分别打出这个字符串来看一下效果。

粗略的解释完一些API之后,我们编写测试代码。

Java代码
  1. Business b = new Business();
  2. System.out.println(b.getPrice("Apple"));

运行这段测试代码,控制台上打出

Before release: Apple
After release:

我的更多文章
  • GCC 警告提示的用法 (2011-10-11 16:36:12)
  • BCB (2011-10-09 10:28:36)
  • Uboot对U盘的支持 (2011-10-07 21:57:05)
  • rvds 4.x 总结与延展 (2011-09-23 08:33:59)
  • NFS 挂载文件系统出现 not responding 错误的解决方法 (2011-09-20 15:41:20)
  • 使用 Strace 和 GDB 调试工具 (2011-08-26 19:23:49)

移植ffmpeg到android_1相关推荐

  1. 移植ffmpeg到VC环境心得

    所有想学习ffmpeg的网友有福了,大名鼎鼎的ffmpeg,移植到Windows的VC6版本全部开源,编译环境为VC6+SP5+VCPP5.别忘记了顶贴哦. 移植ffmpeg到windows,主要的修 ...

  2. 【转载】移植FFMpeg到VC环境心得

    原文地址:http://www.cnblogs.com/mcodec/articles/1659671.html 移植ffmpeg到windows,主要修改的是ffmpeg中VC6不支持的C99语法, ...

  3. 交叉编译移植 FFMPEG X264 XVID 到 hi3531

    2.移植 xvid  a. 到如下链接下载     xvidcore-1.3.3.tar.gz http://ftp.br.debian.org/debian-multimedia/pool/main ...

  4. android平台移植ffmpeg 播放器

    引用:http://blog.csdn.net/ouyangtianhan/article/details/7943543 IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是 ...

  5. android.mk 添加v7_在Android上以命令行方式移植FFmpeg

    最近要做视频I帧提取和摘要生成的项目,在Android平台上的应用,经过调研,发现ffmpeg有很多相关功能的轮子,因此考虑将ffmpeg移植到Android平台.为了更好解耦和以及更多的文档参考,选 ...

  6. 解决Android平台移植ffmpeg的一揽子问题

    原文地址: http://blog.csdn.net/moruite/article/details/6305944 IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是基于h ...

  7. 解决Android平台移植ffmpeg的一些问题

    转自 http://blog.csdn.net/moruite/article/details/6305944 IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是基于havl ...

  8. 【Android】解决Android平台移植ffmpeg的一揽子问题

    IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是基于havlenapetr移植的ffmpeg基础上做了些改进,他做的主要贡献有: 1. 移植了ffmpeg并将与媒体相关的结 ...

  9. Android平台移植FFmpeg和x264

    音视频实践学习 android全平台编译ffmpeg以及x264与fdk-aac实践 ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器 android全平台编译ffm ...

  10. linux之x86裁剪移植---ffmpeg的H264解码显示(420、422)

    在虚拟机上yuv420可以正常显示 ,而945(D525)模块上却无法显示 ,后来验证了directdraw的yuv420也无法显示 ,由此怀疑显卡不支持 ,后把420转换为422显示. 420显示如 ...

最新文章

  1. Eclipse创建一个普通maven项目详细步骤
  2. Three-way Partition
  3. wordvba编程代码大全_面向对象、设计原则、设计模式、编程规范、重构
  4. Android开发之SDK开发获取资源id报错的问题
  5. Fragment销毁时replace和add两个方法的区别
  6. 新来的大神用策略模式把if else给优化了,技术总监说:能不能想好了再改?...
  7. Arduino 各种模块篇 DHT11 温度湿度 数字模块 单总线
  8. Does taro support react hook?
  9. Android实现滑块拼图验证码功能
  10. matlab 符号函数 计算,MATLAB符号计算函数用法总结
  11. fatal: couldn‘t find remote ref develop-XXXX fatal: the remote end hung up unexpectedly
  12. Linux应用基础——串口应用编程
  13. 【四二学堂】jquery方式ajax获取数据并渲染页面
  14. 数据库应用程序开发基础篇—— .NET中SQL Server数据库的操作C#篇之一
  15. GB2312、GB18030、GBK、UNICODE、BIG5之间兼容关系如何?
  16. 看互联网将如何颠覆这17个传统行业
  17. 财务管理都学什么计算机课程,财务管理都学什么课程
  18. Android游戏: 连连看
  19. javascript 倒计时
  20. 30岁转行学Python晚吗?在这个年龄我为什么会焦虑?

热门文章

  1. jupyter notebook更换浏览器一直不成功
  2. 下拉框输入模糊查询_高考英语听力考试查询、网上填报志愿时间、诈骗陷阱提防!全在这里了...
  3. h5 富文本输入框_富文本输入框
  4. AXI总线学习-------从零开始详细学-------------连载(7)读写处理架构,burst介绍,burst细节定义(burst type burst address)
  5. 不是python中文件操作的相关函数是_以下选项中,不是Python中文件操作的相关函数是:...
  6. 天地劫一直说服务器在维护,天地劫手游网络连接错误怎么办 天地劫幽城再临网络异常解决方法...
  7. PT100热敏电阻原理解析
  8. Unity UnityWebRequest从网页加载图片并永久保存在本地
  9. 显示upnp服务器 sonos,蒲公英的上层设备如何开启UPnP及其优点
  10. 大风车音乐计算机,大风车歌曲