热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ffmpeg不同版本的NDK编译

0.版本确定:最近需要以NativeC方式编译OpenCV2.0.其中用到ffmpeg.(OpenCV目录树下,有interfacesffopencv)
0. 版本确定:

最近需要以NativeC方式编译OpenCV2.0.  其中用到ffmpeg. (OpenCV 目录树下,有interfaces/ffopencv). 但ffmpeg版本一直在升级,在不同的版本中,接口也有所变化,如何判断OpenCV2.0使用的哪个版本的ffmpeg是个关键。




首先观察interfaces/ffopencv/ffopencv.cpp. 其中包含:

#ifdef WIN32
 #include   //ffmpeg_/avformat.h
 #include  //ffmpeg_/avcodec.h
 #include  //ffmpeg_/imgconvert.h
#else


说明Windows编译时使用这几个ffmpeg头文件。




打开:3rdparty/include/ffmpeg_/avcodec.h

有如下代码:

#define LIBAVCODEC_VERSION_MAJOR 52
#define LIBAVCODEC_VERSION_MINOR 20
#define LIBAVCODEC_VERSION_MICRO  0





所以,确认应该找对应的ffmpeg 版本。




在ffmpeg官网(http://ffmpeg.org/) 分别下载了:

ffmpeg-2.2.4.tar.gz(当前最新版本)

ffmpeg-1.0.9.tar.gz,ffmpeg-0.6.7.tar.gz,ffmpeg-0.5.13.tar.gz

分别打开其avcodec.h,结果0.5.13最为接近:

#define LIBAVCODEC_VERSION_MAJOR 52
#define LIBAVCODEC_VERSION_MINOR 20
#define LIBAVCODEC_VERSION_MICRO  1





所以说明:OpenCV2.0所使用的FFMpeg库是0.5.13.













1. 开始编译ffMpeg-0.5.13:

以下编译方法,是借鉴网络上已有的ffmpeg NDK编译之方法。只是针对各个特定ffmpeg版本做了一点微调。在此感谢分享这些编译经历的朋友。




1.1:目录建立:

创建jni目录。将ffmpeg-0.5.13.tar.gz copy到其中并解压缩。

最终目录结构如下:

jni/ffmpeg-0.5.13




1.2: 建立config_android.sh并生成config.h文件:

在编译X86 Linux环境下ffmpeg, 是通过configure来创建config.h 和config.mk.

决定编译哪些模块,以及程序中用到的一些宏定义(关系到程序向哪方向走)。




我们也需要一个config.h.  所以要利用configure来生成它。




在jni/ffmpeg-0.5.13/目录内,创建config_android.sh

内容如下:

NDK_ROOT=/opt/android-ndk-r9d
PREBUILT=${NDK_ROOT}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
PLATFORM=${NDK_ROOT}/platforms/android-8/arch-arm
./configure --target-os=linux \
--arch=arm \
--enable-small \
--enable-static \
--disable-yasm \
--enable-armv5te \
--enable-cross-compile \
--disable-stripping \
--disable-ffplay \
--disable-ffserver \
--disable-devices \
--disable-devices \
--enable-swscale \
--cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
--nm=$PREBUILT/bin/arm-linux-androideabi-nm \
--extra-cflags="-fPIC -DANDROID" \
--extra-ldflags='-L$PLATFORM/usr/lib -nostdlib' \


echo "#undef restrict" >> config.h
echo "#define restrict __restrict__" >> config.h
echo "#undef HAVE_LRINT" >> config.h
echo "#define HAVE_LRINT 1" >> config.h
echo "#undef HAVE_LRINTF" >> config.h
echo "#define HAVE_LRINTF 1" >> config.h
echo "#undef HAVE_ROUND" >> config.h
echo "#define HAVE_ROUND 1" >> config.h
echo "#undef HAVE_ROUNDF" >> config.h
echo "#define HAVE_ROUNDF 1" >> config.h
echo "#undef HAVE_TRUNCF" >> config.h
echo "#define HAVE_TRUNCF 1" >> config.h





注意:NDK_ROOT,PREBUILT 要按照本机实际地址配置。




之后修改其权限:

chmod 777 config_android.sh




运行:

./config_android.sh




生成了config.h




1.3: 微调config.h和几个文件:

1.3.1: config.h微调:

在config.h中,找到:

#define restrict restrict

#define restrict  __restrict__




修改为:

#define restrict

#define restrict




因为restrict关键字是C99才引入的。




1.3.2:libavutil/internal.h微调:

#if 0
static av_always_inline av_const long long llrint(double x)
{
   return rint(x);
}
#endif


如果不去掉,llrint会重定义。(llrint是C函数)




1.3.3:libavcodec/utils.c微调:

fd = open(*filename, O_RDWR | O_BINARY | O_CREAT, 0444);

修改为:

fd = open(*filename, O_RDWR | O_CREAT, 0444);




1.3.4: libavformat/rtsp.c微调:

增加:

#include    // sys/time.h
#include   // sys/types.h
#include      // unistd.h








1.4: 修改Makefile:

分别修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale下的Makefile,把每个Makefile中的下面两句删除或注释掉
include $(SUBDIR)../config.mak
include $(SRC_PATH)/subdir.mak








1.5:增加av.mk文件:

在jni/ffmpeg-0.5.13中增加av.mk文件,内容如下:




# LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale

#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)/*.S)
ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))

ifneq ($(ALL_S_FILES),)
ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))
C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))
S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))
else
C_OBJS := $(OBJS)
S_OBJS :=
endif

C_FILES := $(patsubst %.o,%.c,$(C_OBJS))
S_FILES := $(patsubst %.o,%.S,$(S_OBJS))

FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))








1.6:在目标目录内添加Android.mk , Application.mk

1.6.1: 先添加Android.mk




jni/Android.mk 内容如下:

include $(all-subdir-makefiles)




jni/ffmpeg-0.5.13/Android.mk 内容如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))

注意:为了编译一个测试程序:ffmpeg. 可以将这个Android.mk修改为如下版本:
LOCAL_PATH := $(call my-dir)
L_PATH := $(PWD)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))


LOCAL_PATH := $(L_PATH)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T -I../ -I./
LOCAL_MODULE := ffmpeg_g
LOCAL_SRC_FILES := ffmpeg.c cmdutils.c
LOCAL_LDLIBS := -llog -L../../obj/local/armeabi-v7a/ -lavformat -lavcodec -lavutil -lswscale -lpostproc -lffmpeg
include $(BUILD_EXECUTABLE)











jni/ffmpeg-0.5.13/libavcodec/Android.mk内容如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

ARCH=arm
ARCH_ARM=yes

include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=        \
   $(LOCAL_PATH)        \
   $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS) -Wa,-mimplicit-it=thumb
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)





请注意:一定要添加:-Wa, -mimplicit-it=thumb

否则会报错:

/tmp/ccYZnT0I.s: Assembler messages:
/tmp/ccYZnT0I.s:3268: Error: thumb conditional instruction should be in IT block -- `movgt fp,r3'
/tmp/ccYZnT0I.s:3269: Error: thumb conditional instruction should be in IT block -- `movgt r3,sl'
/tmp/ccYZnT0I.s:3271: Error: thumb conditional instruction should be in IT block -- `movle r3,lr'
/tmp/ccYZnT0I.s:3273: Error: thumb conditional instruction should be in IT block -- `movgt fp,r3'


jni/ffmpeg-0.5.13/libavformat/Android.mk 内容如下:
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_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)



libavfilter、libavutil、libpostproc和libswscale下的Android.mk内容如下:


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_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)











1.6.2: 添加Application.mk

所有对应的Application.mk可以自定义,Sam常用的是:

# Build both ARMv5TE and ARMv7-A machine code.
APP_PLATFORM = android-8

APP_ABI := armeabi-v7a
#APP_ABI := $(ARM_ARCH)

#Sam modify it to release
APP_OPTIM := release
#APP_OPTIM := debug
#APP_OPTIM = $(MY_OPTIM)

APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -frtti

#sam modify it from gnustl_static to gnustl_shared
#APP_STL := gnustl_static
#APP_STL        := gnustl_shared
APP_STL := gnustl_shared

#APP_CPPFLAGS += -fno-rtti


#
APP_CPPFLAGS += -Dlinux -fsigned-char
APP_CFLAGS += -fsigned-char
#APP_CPPFLAGS += $(MY_CPPFLAGS) -Dlinux
#STLPORT_FORCE_REBUILD := true











1.7: 编译:

在jni目录:

ndk-build -B V=1




编译结果可以在jni同级目录obj下看到编译出的结果:

obj/local/armeabi-v7a




1.8: 编译ffmpeg 应用程序:

如果上面在jni/ffmpeg-0.5.13目录下的Android.mk用的是第二项。则可以生成一个ffmpeg测试程序。

则在jni/ffmpeg-0.5.13/下,

运行:ndk-build -B V=1

则在jni/ffmpeg-0.5.13/下生成ffmpeg应用程序。




中间会需要version.h

可以创建之:内容如下:

#define FFMPEG_VERSION "0.5.13"













1.9: 测试:

将一段视频源转换为DVD格式:




./ffmpeg -i command_6.wmv -target pal-dvd -ps 2000000000 -aspect 16:9 a.mpeg




转换后一切正常,可以播放之。证明此版本ffmpeg交叉编译通过。










因为之前在寻找对应OpenCV2.0的ffmpeg时,下载了多份FFMpeg。

包括:

ffmpeg-2.2.4.tar.gz(当前最新版本)
ffmpeg-1.0.9.tar.gz,ffmpeg-0.6.7.tar.gz,ffmpeg-0.5.13.tar.gz


所以,干脆把他们都给编译了吧。







2. 编译ffmpeg-0.6.7

2.1:目录建立:
创建jni目录。将ffmpeg-0.5.13.tar.gz copy到其中并解压缩。
最终目录结构如下:
jni/ffmpeg-0.6.7








2.2: 建立config_android.sh并生成config.h文件:
在jni/ffmpeg-0.6.7/目录内,创建config_android.sh
内容如下:





NDK_ROOT=/opt/android-ndk-r9d
PREBUILT=${NDK_ROOT}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
PLATFORM=${NDK_ROOT}/platforms/android-8/arch-arm
./configure --target-os=linux \
--arch=arm \
--enable-small \
--enable-static \
--disable-yasm \
--enable-armv5te \
--enable-cross-compile \
--disable-stripping \
--disable-ffplay \
--disable-devices \
--disable-devices \
--enable-swscale \
--disable-asm \
--cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
--nm=$PREBUILT/bin/arm-linux-androideabi-nm \
--extra-cflags="-fPIC -DANDROID" \
--extra-ldflags='-L$PLATFORM/usr/lib -nostdlib' \


echo "#undef restrict" >> config.h
echo "#define restrict __restrict__" >> config.h
echo "#undef HAVE_LRINT" >> config.h
echo "#define HAVE_LRINT 1" >> config.h
echo "#undef HAVE_LRINTF" >> config.h
echo "#define HAVE_LRINTF 1" >> config.h
echo "#undef HAVE_ROUND" >> config.h
echo "#define HAVE_ROUND 1" >> config.h
echo "#undef HAVE_ROUNDF" >> config.h
echo "#define HAVE_ROUNDF 1" >> config.h
echo "#undef HAVE_TRUNCF" >> config.h
echo "#define HAVE_TRUNCF 1" >> config.h











2.3: 微调config.h和几个文件:
2.3.1: config.h微调:
在config.h中,找到:
#define restrict restrict
#define restrict  __restrict__

修改为:
#define restrict
#define restrict

2.3.2:libavcodec/utils.c微调:
fd = open(*filename, O_RDWR | O_BINARY | O_CREAT, 0444);
修改为:
fd = open(*filename, O_RDWR | O_CREAT, 0444);











2.4: 修改Makefile:
分别修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale下的Makefile,把每个Makefile中的下面两句删除或注释掉
include $(SUBDIR)../config.mak
include $(SRC_PATH)/subdir.mak








2.5:增加av.mk文件:
在jni/ffmpeg-0.5.13中增加av.mk文件,内容如下:

# LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale

#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)/*.S)
ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))

ifneq ($(ALL_S_FILES),)
ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))
C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))
S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))
else
C_OBJS := $(OBJS)
S_OBJS :=
endif

C_FILES := $(patsubst %.o,%.c,$(C_OBJS))
S_FILES := $(patsubst %.o,%.S,$(S_OBJS))

FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))











2.6:在目标目录内添加Android.mk , Application.mk
2.6.1: 先添加Android.mk

jni/Android.mk 内容如下:
include $(all-subdir-makefiles)

jni/ffmpeg-0.6.7/Android.mk 内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))

注意:为了编译一个测试程序:ffmpeg. 可以将这个Android.mk修改为如下版本:
LOCAL_PATH := $(call my-dir)
L_PATH := $(PWD)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))


LOCAL_PATH := $(L_PATH)
include $(CLEAR_VARS)
LOCAL_ARM_MODE := arm
LOCAL_CXXFLAGS := -D_GLIBCXX_USE_WCHAR_T -I../ -I./
LOCAL_MODULE := ffmpeg_g
LOCAL_SRC_FILES := ffmpeg.c cmdutils.c
LOCAL_LDLIBS := -llog -L../../obj/local/armeabi-v7a/ -lavformat -lavcodec -lavutil -lswscale -lpostproc -lffmpeg
include $(BUILD_EXECUTABLE)





jni/ffmpeg-0.6.7/libavcodec/Android.mk内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

ARCH=arm
ARCH_ARM=yes

include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=        \
   $(LOCAL_PATH)        \
   $(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS) 
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)




jni/ffmpeg-0.6.7/libavformat/Android.mk 内容如下:
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_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)



libavfilter、libavutil、libpostproc和libswscale下的Android.mk内容如下:
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_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)



2.6.2: 添加Application.mk
所有对应的Application.mk可以自定义,Sam常用的是:
# Build both ARMv5TE and ARMv7-A machine code.
APP_PLATFORM = android-8

APP_ABI := armeabi-v7a
#APP_ABI := $(ARM_ARCH)

#Sam modify it to release
APP_OPTIM := release
#APP_OPTIM := debug
#APP_OPTIM = $(MY_OPTIM)

APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -frtti

#sam modify it from gnustl_static to gnustl_shared
#APP_STL := gnustl_static
#APP_STL        := gnustl_shared
APP_STL := gnustl_shared

#APP_CPPFLAGS += -fno-rtti


#
APP_CPPFLAGS += -Dlinux -fsigned-char
APP_CFLAGS += -fsigned-char
#APP_CPPFLAGS += $(MY_CPPFLAGS) -Dlinux
#STLPORT_FORCE_REBUILD := true



2.7: 编译:
在jni目录:
ndk-build -B V=1

cmdutils.c 中有几处要屏蔽.
编译结果可以在jni同级目录obj下看到编译出的结果:
obj/local/armeabi-v7a

2.8: 编译ffmpeg 应用程序:
如果上面在jni/ffmpeg-0.5.13目录下的Android.mk用的是第二项。则可以生成一个ffmpeg测试程序。
则在jni/ffmpeg-0.6.7/下,
运行:ndk-build -B V=1
则在jni/ffmpeg-0.6.7/下生成ffmpeg应用程序。

中间会需要version.h
可以创建之:内容如下:
#define FFMPEG_VERSION "0.6.7"

2.9: 测试:
将一段视频源转换为DVD格式:

./ffmpeg -i command_6.wmv -target pal-dvd -ps 2000000000 -aspect 16:9 a.mpeg

转换后一切正常,可以播放之。证明此版本ffmpeg交叉编译通过。




其它版本大同小异,就不再继续抄录了.

记录:
OpenCV-2.4.10的FFMPEG版本是:ffmpeg-2.0.7
#define LIBAVCODEC_VERSION_MAJOR 55
#define LIBAVCODEC_VERSION_MINOR  18
#define LIBAVCODEC_VERSION_MICRO 102



附录:
出错信息1:
/opt/android-ndk-r9/build/core/build-binary.mk:109: *** target file `clean' has both : and :: entries.  Stop.

通常是在Makefile中,有clean段,请将clean 段注释掉。
libavfilter/Makefile 中就有。

出错信息2:
jni/ffmpeg-2.0.7/libavcodec/../libavutil/libm.h:52:32: error: static declaration of 'cbrt' follows non-static declaration
去掉libm.h中的static 


推荐阅读
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 如何去除Win7快捷方式的箭头
    本文介绍了如何去除Win7快捷方式的箭头的方法,通过生成一个透明的ico图标并将其命名为Empty.ico,将图标复制到windows目录下,并导入注册表,即可去除箭头。这样做可以改善默认快捷方式的外观,提升桌面整洁度。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
author-avatar
手机用户2602886967
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有