ffmpeg不同版本的NDK编译

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 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值