移植ffmpeg到android_1
.移植ffmpeg到android
-----------------------另一个方法
FFMPEG移植到Android(ubuntu环境下)
搞左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
- android create project -n vPlayer -t 8 -p vPlayer -kme.abitno.vplayer -a PlayerView
复制代码
然后在vPlayer目录里
- mkdir jni && cd jni
- wget http://ffmpeg.org/releases/ffmpeg-0.6.tar.bz2
- tar xf ffmpeg-0.6.tar.bz2 && mvffmpeg-0.6 ffmpeg && cd ffmpeg
复制代码
在ffmpeg下新建一个config.sh,内容如下,注意把PREBUILT和PLATFORM设置正确。另外里面有些参数你也可以自行调整,我主要是为了配置一个播放器而这样设置的。
- #!/bin/bash
- PREBUILT=/home/abitno/Android/android-ndk-r4/build/prebuilt/linux-x86/arm-eabi-4.4.0
- PLATFORM=/home/abitno/Android/android-ndk-r4/build/platforms/android-8/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"
复制代码
运行config.sh开始configure
- chmod +x config.sh
- ./config.sh
复制代码
configure完成后,编辑刚刚生成的config.h,找到这句
- #define restrict restrict
复制代码
Android的GCC不支持restrict关键字,于是修改成下面这样
- #define restrict
复制代码
编辑libavutil/libm.h,把其中的static方法都删除。
分别修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和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)
- JNIEXPORT void JNICALL Java_com_chnic_jni_SayHellotoCPP_sayHello
- (JNIEnv *, jobject, jstring);
仔细观察一下这个方法,在注释上标注类名、方法名、签名(Signature),至于这个签名是做什么用的,我们以后再说。在这里最重要的是Java_com_chnic_jni_SayHellotoCPP_sayHello这个方法签名。在Java端我们执行sayHello(Stringname)这个方法之后,JVM就会帮我们唤醒在DLL里的Java_com_chnic_jni_SayHellotoCPP_sayHello这个方法。因此我们新建一个C++ source file来实现这个方法。
- #include <iostream.h>
- #include "com_chnic_jni_SayHellotoCPP.h"
- JNIEXPORT void JNICALL Java_com_chnic_jni_SayHellotoCPP_sayHello
- (JNIEnv* env, jobject obj, jstring name)
- {
- const char* pname = env->GetStringUTFChars(name, NULL);
- cout << "Hello, " << pname << endl;
- }
因为我们生成的那个头文件是在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环境变量下面。有两种方法可以做到:
- 把这个DLL放到windows下面的sysytem32文件夹下面,这个是windows默认的path
- 复制你工程的Debug目录,我这里是C:\Program Files\Microsoft VisualStudio\MyProjects\HelloEnd\Debug这个目录,把这个目录配置到Uservariable的Path下面。重启eclipse,让eclipse在启动的时候重新读取这个path变量。
比较起来,第二种方法比较灵活,在开发的时候不用来回copydll文件了,节省了很多工作量,所以在开发的时候推荐用第二种方法。在这里我们使用的也是第二种,eclipse重启之后打开SayHellotoCPP这个类。其实我们上面做的那些是不是是让JVM能找到那些DLL文件,接下来我们要让我们自己的java代码“认识”这个动态链接库。加入System.loadLibrary("HelloEnd");这句到静态初始化块里。
- package com.chnic.jni;
- public class SayHellotoCPP {
- static{
- System.loadLibrary("HelloEnd");
- }
- public SayHellotoCPP(){
- }
- public native void sayHello(String name);
- }
这样我们的代码就能认识并加载这个动态链接库文件了。万事俱备,只欠测试代码了,接下来编写测试代码。
- SayHellotoCPP shp = new SayHellotoCPP();
- shp.sayHello("World");
我们不让他直接Hello,World。我们把World传进去,执行代码。发现控制台打印出来Hello,World这句话。就此一个最简单的JNI程序已经开发完成。也许有朋友会对CPP代码里的
- const char* pname = env->GetStringUTFChars(name, NULL);
这句有疑问,这个GetStringUTFChars就是JNI给developer提供的API,我们以后再讲。在这里不得不多句嘴。
- 因为JNI有一个Native这个特点,一点有项目用了JNI,也就说明这个项目基本不能跨平台了。
- JNI调用是相当慢的,在实际使用的之前一定要先想明白是否有这个必要。
- 因为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类。
- package com.chnic.service;
- import com.chnic.bean.Order;
- public class Business {
- static{
- System.loadLibrary("FruitFactory");
- }
- public Business(){
- }
- public native double getPrice(String name);
- public native Order getOrder(String name, int amount);
- public native Order getRamdomOrder();
- public native void analyzeOrder(Order order);
- public void notification(){
- System.out.println("Got a notification.");
- }
- public static void notificationByStatic(){
- System.out.println("Got a notification in a static method.");
- }
- }
这个类里面包含4个本地方法,一个静态初始化块加载将要生成的dll文件。剩下的方法都是很普通的java方法,等会在backend中回调这些方法。这个类需要一个名为Order的JavaBean。
- package com.chnic.bean;
- public class Order {
- private String name = "Fruit";
- private double price;
- private int amount = 30;
- public Order(){
- }
- public int getAmount() {
- return amount;
- }
- public void setAmount(int amount) {
- this.amount = amount;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public double getPrice() {
- return price;
- }
- public void setPrice(double price) {
- this.price = price;
- }
- }
JavaBean中,我们为两个私有属性赋值,方便后面的例子演示。到此为止除了测试代码之外的Java端的代码就全部高调了,接下来进行生成.h头文件、建立C++工程的工作,在这里就一笔带过,不熟悉的朋友请回头看第一篇。在工程里我们新建一个名为Foctory的C++source file 文件,去实现那些native方法。具体的代码如下。
- #include <iostream.h>
- #include <string.h>
- #include "com_chnic_service_Business.h"
- jobject getInstance(JNIEnv* env, jclass obj_class);
- JNIEXPORT jdouble JNICALL Java_com_chnic_service_Business_getPrice(JNIEnv* env,
- jobject obj,
- jstring name)
- {
- const char* pname = env->GetStringUTFChars(name, NULL);
- cout << "Before release: " << pname << endl;
- if (strcmp(pname, "Apple") == 0)
- {
- env->ReleaseStringUTFChars(name, pname);
- cout << "After release: " << pname << endl;
- return 1.2;
- }
- else
- {
- env->ReleaseStringUTFChars(name, pname);
- cout << "After release: " << pname << endl;
- return 2.1;
- }
- }
- JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getOrder(JNIEnv* env,
- jobject obj,
- jstring name,
- jint amount)
- {
- jclass order_class = env->FindClass("com/chnic/bean/Order");
- jobject order = getInstance(env, order_class);
- jmethodID setName_method = env->GetMethodID(order_class, "setName", "(Ljava/lang/String;)V");
- env->CallVoidMethod(order, setName_method, name);
- jmethodID setAmount_method = env->GetMethodID(order_class, "setAmount", "(I)V");
- env->CallVoidMethod(order, setAmount_method, amount);
- return order;
- }
- JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getRamdomOrder(JNIEnv* env,
- jobject obj)
- {
- jclass business_class = env->GetObjectClass(obj);
- jobject business_obj = getInstance(env, business_class);
- jmethodID notification_method = env->GetMethodID(business_class, "notification", "()V");
- env->CallVoidMethod(obj, notification_method);
- jclass order_class = env->FindClass("com/chnic/bean/Order");
- jobject order = getInstance(env, order_class);
- jfieldID amount_field = env->GetFieldID(order_class, "amount", "I");
- jint amount = env->GetIntField(order, amount_field);
- cout << "amount: " << amount << endl;
- return order;
- }
- JNIEXPORT void JNICALL Java_com_chnic_service_Business_analyzeOrder (JNIEnv* env,
- jclass cls,
- jobject obj)
- {
- jclass order_class = env->GetObjectClass(obj);
- jmethodID getName_method = env->GetMethodID(order_class, "getName", "()Ljava/lang/String;");
- jstring name_str = static_cast<jstring>(env->CallObjectMethod(obj, getName_method));
- const char* pname = env->GetStringUTFChars(name_str, NULL);
- cout << "Name in Java_com_chnic_service_Business_analyzeOrder: " << pname << endl;
- jmethodID notification_method_static = env->GetStaticMethodID(cls, "notificationByStatic", "()V");
- env->CallStaticVoidMethod(cls, notification_method_static);
- }
- jobject getInstance(JNIEnv* env, jclass obj_class)
- {
- jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V");
- jobject obj = env->NewObject(obj_class, construction_id);
- return obj;
- }
可以看到,在我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之后,我们编写测试代码。
- Business b = new Business();
- 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相关推荐
- 移植ffmpeg到VC环境心得
所有想学习ffmpeg的网友有福了,大名鼎鼎的ffmpeg,移植到Windows的VC6版本全部开源,编译环境为VC6+SP5+VCPP5.别忘记了顶贴哦. 移植ffmpeg到windows,主要的修 ...
- 【转载】移植FFMpeg到VC环境心得
原文地址:http://www.cnblogs.com/mcodec/articles/1659671.html 移植ffmpeg到windows,主要修改的是ffmpeg中VC6不支持的C99语法, ...
- 交叉编译移植 FFMPEG X264 XVID 到 hi3531
2.移植 xvid a. 到如下链接下载 xvidcore-1.3.3.tar.gz http://ftp.br.debian.org/debian-multimedia/pool/main ...
- android平台移植ffmpeg 播放器
引用:http://blog.csdn.net/ouyangtianhan/article/details/7943543 IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是 ...
- android.mk 添加v7_在Android上以命令行方式移植FFmpeg
最近要做视频I帧提取和摘要生成的项目,在Android平台上的应用,经过调研,发现ffmpeg有很多相关功能的轮子,因此考虑将ffmpeg移植到Android平台.为了更好解耦和以及更多的文档参考,选 ...
- 解决Android平台移植ffmpeg的一揽子问题
原文地址: http://blog.csdn.net/moruite/article/details/6305944 IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是基于h ...
- 解决Android平台移植ffmpeg的一些问题
转自 http://blog.csdn.net/moruite/article/details/6305944 IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是基于havl ...
- 【Android】解决Android平台移植ffmpeg的一揽子问题
IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是基于havlenapetr移植的ffmpeg基础上做了些改进,他做的主要贡献有: 1. 移植了ffmpeg并将与媒体相关的结 ...
- Android平台移植FFmpeg和x264
音视频实践学习 android全平台编译ffmpeg以及x264与fdk-aac实践 ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器 android全平台编译ffm ...
- linux之x86裁剪移植---ffmpeg的H264解码显示(420、422)
在虚拟机上yuv420可以正常显示 ,而945(D525)模块上却无法显示 ,后来验证了directdraw的yuv420也无法显示 ,由此怀疑显卡不支持 ,后把420转换为422显示. 420显示如 ...
最新文章
- Eclipse创建一个普通maven项目详细步骤
- Three-way Partition
- wordvba编程代码大全_面向对象、设计原则、设计模式、编程规范、重构
- Android开发之SDK开发获取资源id报错的问题
- Fragment销毁时replace和add两个方法的区别
- 新来的大神用策略模式把if else给优化了,技术总监说:能不能想好了再改?...
- Arduino 各种模块篇 DHT11 温度湿度 数字模块 单总线
- Does taro support react hook?
- Android实现滑块拼图验证码功能
- matlab 符号函数 计算,MATLAB符号计算函数用法总结
- fatal: couldn‘t find remote ref develop-XXXX fatal: the remote end hung up unexpectedly
- Linux应用基础——串口应用编程
- 【四二学堂】jquery方式ajax获取数据并渲染页面
- 数据库应用程序开发基础篇—— .NET中SQL Server数据库的操作C#篇之一
- GB2312、GB18030、GBK、UNICODE、BIG5之间兼容关系如何?
- 看互联网将如何颠覆这17个传统行业
- 财务管理都学什么计算机课程,财务管理都学什么课程
- Android游戏: 连连看
- javascript 倒计时
- 30岁转行学Python晚吗?在这个年龄我为什么会焦虑?
热门文章
- jupyter notebook更换浏览器一直不成功
- 下拉框输入模糊查询_高考英语听力考试查询、网上填报志愿时间、诈骗陷阱提防!全在这里了...
- h5 富文本输入框_富文本输入框
- AXI总线学习-------从零开始详细学-------------连载(7)读写处理架构,burst介绍,burst细节定义(burst type burst address)
- 不是python中文件操作的相关函数是_以下选项中,不是Python中文件操作的相关函数是:...
- 天地劫一直说服务器在维护,天地劫手游网络连接错误怎么办 天地劫幽城再临网络异常解决方法...
- PT100热敏电阻原理解析
- Unity UnityWebRequest从网页加载图片并永久保存在本地
- 显示upnp服务器 sonos,蒲公英的上层设备如何开启UPnP及其优点
- 大风车音乐计算机,大风车歌曲