15AH, San Francisco

California, United States.

Send Your Mail At:

tianyingkejishe@sina.cn

Working Hours

Mon-Sat: 9.30am To 7.00pm

作者标题

Autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et dolore feugait.

Author Archive by stormwind

【摄像头】MT7628wifi摄像头使用说明

一、简介

wifi摄像头采用Linux系统,使用更灵活,功能更强大,采用ov5693传感器500万像素,高清自动聚焦。

二、接口定义

1、电源管脚

管脚1:DC5V 正极

管脚2:DC5V 正极

管脚3:GND 负极

2、串口管脚

管脚4:uart-rx

管脚5:uart-tx

管脚6:GND

3、网口管脚

管脚7:rx0-p

管脚8:rx0-n

管脚9:tx0-p

管脚10:tx0-n

三、应用软件

1、打开极光摄像头APP

2、点击“连接设备”

3、连接“RecologyPower”摄像头热点,返回主界面

4、点击镜头按键,观看视频

【Ubuntu】word转pdf

一、使用Unoconv工具

Unoconv是一个开源工具,用于将各种文档格式转换为PDF格式。可以使用以下命令安装:

$ sudo apt-get install unoconv

转换文件的命令如下:

$ unoconv -f pdf filename.doc

其中,filename.doc为待转换的Word文件名

使用Unoconv工具的优点是非常简单易用,但需要注意的是,该工具需要依赖OpenOffice或LibreOffice来实现转换,所以在使用前需要确保已经安装了相应的软件。

二、使用LibreOffice命令行工具

与Unoconv类似,LibreOffice也提供了一个命令行工具soffice,可以用于将各种文档格式转换为PDF格式。可以使用以下命令安装LibreOffice:

$ sudo apt-get install libreoffice

转换文件的命令如下:

$ soffice --convert-to pdf filename.doc

其中,filename.doc为待转换的Word文件名。

使用LibreOffice命令行工具的优点是它不依赖于其他软件,并且支持各种Office文档格式。但是转换速度可能会比其他工具慢一些。

三、使用Pandoc工具

Pandoc也是一个开源工具,可以将各种文档格式转换为PDF格式。可以使用以下命令安装Pandoc:

$ sudo apt-get install pandoc

转换文件的命令如下:

$ pandoc -s filename.doc -o filename.pdf

其中,filename.doc为待转换的Word文件名。

使用Pandoc工具的优点是它支持各种文档格式,并且可以自定义文档样式,转换后的PDF文件也会自动添加书签,方便查阅。但是需要注意的是,Pandoc工具并不是专门用于文档转换的,所以在转换复杂文档时可能会出现格式错误。

四、使用Liberation字体

在Word文件转换为PDF格式时,由于Linux和Windows系统的字体库不一样,可能导致PDF文档出现乱码或格式错误。为了解决这个问题,我们可以在Linux系统中安装Microsoft Office的字体Liberation字体,实现Linux和Windows字体的兼容。

安装Liberation字体的命令如下:

$ sudo apt-get install fonts-liberation

安装完毕后,我们就可以在Word文件转换成PDF文件时使用Liberation字体了。

五、小结

以上就是在Linux下实现Word文件转PDF的方法,我们可以根据需要选择不同的工具来实现转换,以满足我们的工作需求。同时,为了避免字体的兼容性问题,我们也可以安装Liberation字体来保证转换后的PDF文件格式正确。

linux 获取OS盘符的方法

在服务器测试中,对硬盘的测试有很多,有些测试用例需要我们写一下自动化的脚本,比如给服务器所有的盘施加压力,这个就需要我们把除了OS盘的所有盘遍历出来,下面介绍几种方法来筛选OS盘
我们知道,判断os 盘的方法一般是看其有没有boot分区,通常用两个指令来获取:lsblk和df -h 下面一次介绍一下这两种方法的写法

1、 lsblk 如图所示 带有boot 分区的就是OS盘

系统盘是sda

系统盘是nvme0n1

shell命令行:

lsblk -l  |grep -i boot -B 1 |grep -i disk |awk '{print $1}'

筛选除了OS外所有的盘符

lsblk -l  |grep -vw sda |grep -i disk |awk '{print $1}'
lsblk -l  |grep -vw nvme0n1 |grep -i disk |awk '{print $1}'

2、 df -h

系统盘是sda

shell命令行

df -h | awk '{print $1}' | grep -iE "/dev/sd" | sed 's/[0-9]//g' |sort -u |awk -F "/" {'print $NF'}

系统盘是nvme0n1

shell 命令行

 df -h | awk '{print $1}' | grep -iE "/dev/nvme" | sed 's/p[0-9]//g' |sort -u |awk -F "/" {'print $NF'}

对此可以写成一个小脚本来判断OS,代码如下:

#!/bin/bash
bootdisk=`df -h |grep -i boot | awk '{print $1}' | grep -iE "/dev/sd" | sed 's/[0-9]//g' |sort -u|awk -F "/" '{print $NF}'`
if  test -z "$bootdisk"
then
        bootdisk=`df -h |grep -i boot| awk '{print $1}' | grep -iE "/dev/nvme" | sed 's/p[0-9]*//g' |sort -u|awk -F "/" '{print $NF}'`
        echo "os disk os $bootdisk"
else
        echo "os disk is $bootdisk"
fi

运行结果如下图:

【ubuntu】sudo: error in /etc/sudo.conf, line 0 while loading plugin `sudoers_policy’ 解决方法

报错:

sudo: error in /etc/sudo.conf, line 0 while loading plugin ‘sudoers_policy’
sudo: /usr/lib/sudo/sudoers.so must only be writable by owner
sudo: fatal error, unable to load plugins

导致的原因

用ll查看了一下sudoer.so和sudo的用户权限,发现owner都是非root用户,所以才导致当前用户没有权限执行sudo命令,修改权限后,即可解决此问题。

解决方法:

chmod 644 /usr/lib/sudo/sudoers.so
su 输入密码进入su
chown -R root /usr/lib/sudo

【Android Studio】安装app报错Installation did not succeed. The application could not be installed: INSTALL

问题描述
安装app demo报错;app安装不上
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_INSUFFICIENT_STORAGE
The device needs more free storage to install the application (extra space is needed in addition to APK size).

原因分析:
程序或手机内存空间不足

解决方案:
清理程序内存:Build -> Clean Project

清理手机内存:清理多余程序或空间
File -> Rest重启再运行

app安装成功

【Altium Designer】AD四层板设计

前言

1、用 Altium Designer 软件绘制电路时,通常2层板能实现设计需求。遇到板框固定,元器件密集的情况下,2 层板无法实现预期功能,考虑设计多层板;
2、本文主要介绍AD四层板的设计流程,其中PCB的叠层设计、内缩设计及DRC设计规则是关键。
3、软件版本:Altium Designer 19.0.4

一、正片层和负片层介绍

1、正片层(Signal)
正片就是平常用在走线的信号层,即走线的地方是铜线,用Polygon Pour进行大块敷铜填充。

2、负片层(Plane)
负片正好相反,即默认敷铜,走线的地方是分割线,也就是生成一个负片之后整一层就已经被敷铜了,要做的事情就是分割敷铜,再设置分割后的敷铜网络。

3、内电层的分割实现
AD中直接用Line,快捷键P+L,来分割,分割线不宜太细,用15mil及以上。
要分割敷铜时,只要用Line画一个封闭的多边形框,在双击框内敷铜设置网络即可。

正负片都可以用于内电层,正片也可通过走线和敷铜实现。
负片的好处:默认大块敷铜填充,在添加过孔,改变敷铜大小等等操作都不需要Rebuild,这样省去了PROTEL重新敷铜计算的时间。中间层用于电源层和GND层时候,层面上大多是大块敷铜,这样用负片的优势就很明显。

建议信号层采取“正片”的方式处理,电源层和GND层采取“负片”的方式处理,可以很大程度上减小文件数据量的大小和提高设计的速度。

二、PCB板的叠层设计

  • 叠层设计遵从以下规定:
  • ① 每个走线层都必须有一个邻近的参考层(电源或地层);
  • ② 邻近的主电源层和地层要保持最小间距,以提供较大的耦合电容。

1.两层板的叠层
对于两层板来说,由于板层数量少,已经不存在叠层的问题。控制EMI辐射主要从布线和布局来考虑;

单层板和双层板的电磁兼容问题越来越突出。造成这种现象的主要原因就是因是信号回路面积过大,不仅产生了较强的电磁辐射,而且使电路对外界干扰敏感。

要改善线路的电磁兼容性,最简单的方法是减小关键信号的回路面积。

关键信号:从电磁兼容的角度考虑,关键信号主要指产生较强辐射的信号和对外界敏感的信号。能够产生较强辐射的信号一般是周期性信号,如时钟或地址的低位信号。对干扰敏感的信号是指那些电平较低的模拟信号。

单、双层板通常使用在低于10KHz的低频模拟设计中:

① 在同一层的电源走线以辐射状走线,并最小化线的长度总和;
②走电源、地线时,相互靠近;在关键信号线边上布一条地线,这条地线应尽量靠近信号线。这样就形成了较小的回路面积,减小差模辐射对外界干扰的敏感度。当信号线的旁边加一条地线后,就形成了一个面积最小的回路,信号电流肯定会取道这个回路,而不是其它地线路径。
③ 如果是双层线路板,可以在线路板的另一面,紧靠近信号线的下面,沿着信号线布一条地线,地线尽量宽些。这样形成的回路面积等于线路板的厚度乘以信号线的长度。

2.四层板的叠层
(1)PCB层介绍

AD19默认的Layer(层)有13个,层介绍如下表:

四层板,顾名思义就是有四层的电路板,它通常由顶层信号层、中间层(内电层)Power层、中间层GND层和底层信号层组成。顶层信号层Top Layer和底层信号层Bottom Layer已经存在,中间层的两层需要添加。

(2)四层板的层叠顺序:SIG-GND-PWR -SIG

这种层叠顺序通常应用于板上芯片较多的情况。此方案可得到较好的SI性能,但对于EMI性能来说并不是很好,主要通过走线及其他细节来控制。
注意:地层放在信号最密集的信号层的相连层,有利于吸收和抑制辐射;增大板面积,体现20H规则。
(3)层叠设计步骤:

步骤1:快捷键D+K,打开层叠管理器

注意:Dielectric 是电介质,介于Top Layer与Bottom Layer之间的绝缘材料,不用进行操作。四层板设计需要在Top Layer与Bottom Layer之间添加两层中间层。

步骤2:如下图所示,创建第一个负片层,①选择Top Layer所在行 → ②右键选择Insert layer below → ③选择Plane

中间层选择类型,见下表:

注意:通常,四层板的GND层选择负片层,POWER层选择负片层或信号层。

  • 步骤3:重复步骤2,创建第二个负片层,选中Top Layer双击,重命名,重命名结果如下图。

步骤4:设置GND层和POWER层的内缩值,GND层内缩20mil,POWER层内缩60mil;
GND层内缩设置:
① 选择GND层 → ② 单击Panels → ③ 选择Properties → ④ 取消勾选Stack Symmetry → ⑤ 设置Pullback distance值为20mil。

同理,POWER层内缩:

步骤5:四层板布线
① 与两层板布线方式相同,在Top层和Bottom层布线,而GND层和POWER层禁止布线,需要连接对应的地和电源网络;
② 层与层之间的连接是通过过孔/焊盘实现的,多层板同样如此。放置元器件的Top Layer或Bottom Layer先把电源和GND(或其他的走线)通过过孔引出;
③ 通过过孔/焊盘引出的电源和地网络,在Top和Bottom不需要走线,此处不需要走线的电源和地,指的是POWER层网络和GND层网络连接的电源和地。

三、规则设计

  • 画好的四层板外发打板时,规则设计可参考嘉立创4层板的板层及板厚设计:
  • ① 通常四层板板厚设置为1.6mm或2mm;
  • ② 板材设置为FR-4;
  • ③ 层压顺序选择“按原单处理”;
  • ④ 层压结构参考下图:

⑤ 其余选项参照两层板打板选项设置。

【ffmpeg】五、android使用ffmpeg.so

前言:经过前几篇的介绍,我们已经掌握在linux下编译ffmpeg.so。我们编译出so,目的是为了能够使用so达到使用ffmpeg相关功能的目的。本篇介绍如何在android上使用ffmpeg的so库的基础功能。本文要求读者有一定的jni基础。

本文开发环境:

ffmpeg版本:ffmpeg4.2.2

androidStudio:2022.1.1 Patch 1;gradle版本:7.4.1;ndk21(必须要有ndk环境)

一、androidStudio新建jni(C++)项目

二、导入linux生成的ffmepg的7个so文件和头文件

1、在libs目录下新建文件夹arm64-v8a(本文只引入arm64-v8a版本,读者可以参照自行引入armeabi-v7a版本),在其中复制进来ffmepg相关的7个so文件,在cpp目录下导入include的C头文件:

 2、编辑CMakeLists.txt联编脚本

cmake_minimum_required(VERSION 3.22.1)
#自动生成,自己的项目名
project("ffmpegndk")
 
message("start............................................................")
# 1. 定义so库和头文件所在目录相对与脚本的位置的变量,方面后面使用
set(ffmpeg_lib_dir_neway ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/include)
 
# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir})
 
#==========================ffmpeg引入开始====================================
#add_library(配置模块so库编译信息),set_target_properties(为目标配置编译属性),对于三方so,这两个方法要成对出现
add_library( avcodec
        SHARED
        IMPORTED)
set_target_properties(
        avcodec
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir_neway}/libavcodec.so)
 
add_library( avdevice
        SHARED
        IMPORTED)
set_target_properties(
        avdevice
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir_neway}/libavdevice.so)
 
add_library( avfilter
        SHARED
        IMPORTED)
set_target_properties(
        avfilter
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir_neway}/libavfilter.so)
 
add_library( avformat
        SHARED
        IMPORTED)
set_target_properties(
        avformat
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir_neway}/libavformat.so)
 
add_library( avutil
        SHARED
        IMPORTED)
set_target_properties(
        avutil
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir_neway}/libavutil.so)
 
add_library( swresample
        SHARED
        IMPORTED)
set_target_properties(
        swresample
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir_neway}/libswresample.so)
 
add_library( swscale
        SHARED
        IMPORTED)
set_target_properties(
        swscale
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir_neway}/libswscale.so)
#==========================ffmpeg引入结束====================================
 
#对最后一个自己的so(名称可以自定义),不需要再set_target_properties。这个so最终会生成到build中。
add_library(
        ffmpegNdkCustom
        SHARED
        native-lib.cpp)
 
#查找代码中使用到的android系统预留(预构建)库(如log、zlib压缩库等)
find_library(
        log-lib
        log)
 
#指定编译最终目标库时,cmke要链接的库。
#解释:一般形式是:target_link_libraries(your-lib library1 library2 ...)
target_link_libraries(
        #指定目标库
        ffmpegNdkCustom
        #连接 FFmpeg 相关的库
        avcodec
        avdevice
        avfilter
        avformat
        avutil
        swresample
        swscale
        ${log-lib})

 3、编辑native-lib.cpp文件,编写native方法。

下面的 stringFromJNI 是项目默认帮我们生成的默认方法,getConfiguration是我们测试ffmpeg获取版本号的一个方法

#include <jni.h>
#include <string>
extern "C" {
#include "libavcodec/avcodec.h"
}
 
extern "C" JNIEXPORT jstring JNICALL
Java_com_neway_ffmpegndk_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
 
extern "C"
JNIEXPORT jstring JNICALL
Java_com_neway_ffmpegndk_MainActivity_getConfiguration(JNIEnv *env, jobject thiz) {
    return env->NewStringUTF(avcodec_configuration());
}

三、app中使用

1、修改MainActivity方法:

package com.neway.ffmpegndk;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.os.Bundle;
import android.widget.TextView;
 
import com.neway.ffmpegndk.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
    //用于在程序启动时加载cmake编译好的目标库ffmpegNdkCustom.so,注意大小写
    static {
        System.loadLibrary("ffmpegNdkCustom");
    }
 
    private ActivityMainBinding binding;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        TextView tv = binding.sampleText;
        //tv.setText(stringFromJNI());
        tv.setText(getConfiguration());
    }
 
    /**
     * 在 ffmpegNdkCustom.so 库中声明的原生c++的native方法,起连接作用
     */
    public native String stringFromJNI();
    public native String getConfiguration();
}

2、修改app级别的build.gradle文件,用以使app支持arm64-v8a架构:

android {
    namespace 'com.neway.ffmpegndk'
    compileSdk 33
 
    defaultConfig {
        applicationId "com.neway.ffmpegndk"
        minSdk 21
        targetSdk 33
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters 'arm64-v8a'//,'armeabi-v7a'//,'x86','arm64-v8a',
            }
        }
    }
    ...
}

3、运行(因为指定了arm64-v8a架构,故不能在电脑模拟器上运行,需要真机,电脑模拟器需要编译使用x86架构的),即展示了我们的ffmpeg版本号:

4、此时,我们也可以观察下,cmake联编的目标so同时也生成在了我们的build目录下:

后记:

本文使用了ffmpeg未合并的7个so文件方式,当然也可以使用合并so(见系列文章第四篇ffmpeg专辑(四):linux编译ffmpeg.so合并so篇)后的ffmpeg.so文件,此时libs文件夹和cmake联编文件需要变更,其余地方保持不变:

cmake_minimum_required(VERSION 3.22.1)
 
project("ffmpegndk")
 
message("start............................................................")
# 1. 定义so库和头文件所在目录,方面后面使用
set(ffmpeg_lib_dir_neway ${CMAKE_SOURCE_DIR}/../../../libs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/include)
 
# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir})
 
#==========================ffmpeg引入开始====================================
#ffmpegsofile为自定义名称,libffmpeg.so是libs目录下的linux编译出的so文件
add_library( ffmpegsofile
        SHARED
        IMPORTED)
set_target_properties(
        ffmpegsofile
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir_neway}/libffmpeg.so)
#==========================ffmpeg引入结束====================================
 
#对最后一个自己的so,不需要再set_target_properties。这个so最终会生成到build中。
add_library(
        ffmpegNdkCustom
        SHARED
        native-lib.cpp)
 
find_library(
        log-lib
        log)
 
target_link_libraries(
        #指定目标库
        ffmpegNdkCustom
        #连接 FFmpeg 相关的库
        ffmpegsofile
        ${log-lib})

【ffmpeg】四、linux编译ffmpeg.so合并so篇

前言:在前几篇文章已经介绍了,如何进行编译ffmpeg.so的一个完整过程。但是编译出的是7个独立模块的so文件,使用起来较为不便。本文将在上一篇文章的基础上进行so的合并介绍。

一、编写脚本

注意:本文所述依然是双架构编译,但所谓合并so,并不是合并两个架构的so,而是分别在自己的架构下,进行多个ffmpeg的.a静态库合并成动态库so的过程。即本文两个架构来说,这个过程进行了2次。

在前几篇文章中的ffmpeg-4.2.2源码目录下新建一个编译脚本:build_android_v8v7_comileso.sh:

#!/bin/bash
make clean
API=21
NDK=/home/liuzihui/softwaresCus/ndkr21/android-ndk-r21e
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT=$TOOLCHAIN/sysroot
ADDITIONAL_CONFIGURE_FLAG="--enable-avdevice --enable-avcodec --enable-avformat --enable-swresample --enable-swscale --enable-postproc --enable-avfilter"
function build_android {
  echo "===========================1========================"
  ./configure \
  --prefix=$OUTPUT \
  --target-os=android \
  --arch=$ARCH \
  --cpu=$CPU \
  --enable-asm \
  --enable-neon \
  --enable-cross-compile \
  --disable-shared \
  --enable-static \
  --disable-doc \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-symver \
  --disable-ffmpeg \
  --sysroot=$SYSROOT \
  --cross-prefix=$CROSS_PREFIX \
  --cc=$CC \
  --cxx=$CXX \
  --extra-cflags="-fPIC" \
  $ADDITIONAL_CONFIGURE_FLAG
  echo "===========================2====================="
  make clean
  echo "=============================${CC}==============="
  make -j4
  make install
  $COMBILE_TOOLCHAIN_LD \
-rpath-link=$COMBILE_PLATFORM/usr/lib \
-L$COMBILE_PLATFORM/usr/lib \
-L$OUTPUT/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$OUTPUT/libffmpeg.so \
    libavcodec/libavcodec.a \
    libavfilter/libavfilter.a \
    libswresample/libswresample.a \
    libavformat/libavformat.a \
    libavutil/libavutil.a \
    libavdevice/libavdevice.a \
    libswscale/libswscale.a \
    -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
    $COMBILE_TOOLCHAIN_GCC
}
 
#arm64-v8a
ARCH=arm64
CPU=armv8-a
CPU_INSTRUCT_COMMON=aarch64-linux-android
OUTPUT=/home/liuzihui/softwaresCus/ffmpegSource/ffmpeg-4.2.2/android/$CPU
CROSS_PREFIX=$TOOLCHAIN/bin/$CPU_INSTRUCT_COMMON-    #AR AS LD等通用
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang     #CC单独指定,非通用(因为ndk中CC与AR路径不同,后同理)
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++  #CXX单独指定,非通用
COMBILE_PLATFORM=$NDK/platforms/android-$API/arch-arm64 #
COMBILE_TOOLCHAIN_LD=$NDK/toolchains/$CPU_INSTRUCT_COMMON-4.9/prebuilt/linux-x86_64/bin/$CPU_INSTRUCT_COMMON-ld
COMBILE_TOOLCHAIN_GCC=$NDK/toolchains/$CPU_INSTRUCT_COMMON-4.9/prebuilt/linux-x86_64/lib/gcc/$CPU_INSTRUCT_COMMON/4.9.x/libgcc.a
build_android
 
#armeabi-v7a
ARCH=arm
CPU=armv7-a
CPU_INSTRUCT_COMMON=arm-linux-androideabi
OUTPUT=/home/liuzihui/softwaresCus/ffmpegSource/ffmpeg-4.2.2/android/$CPU
CROSS_PREFIX=$TOOLCHAIN/bin/$CPU_INSTRUCT_COMMON-       #AR AS LD等通用
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang     #CC单独指定,非通用
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++  #CXX单独指定,非通用
COMBILE_PLATFORM=$NDK/platforms/android-$API/arch-arm
COMBILE_TOOLCHAIN_LD=$NDK/toolchains/$CPU_INSTRUCT_COMMON-4.9/prebuilt/linux-x86_64/bin/$CPU_INSTRUCT_COMMON-ld
COMBILE_TOOLCHAIN_GCC=$NDK/toolchains/$CPU_INSTRUCT_COMMON-4.9/prebuilt/linux-x86_64/lib/gcc/$CPU_INSTRUCT_COMMON/4.9.x/libgcc.a
build_android
 

说明:

1、思路是用 –disable-shared –enable-static 先生成7个.a(静态库),然后再利用脚本合并成一个so;

2、在合并so方面,我们在 make install后面追加了一些脚本,虽然ndk17以后在编译ffmpeg.so使用clang,但是合并so这块,适用性更强的gcc在这里派上了用场。

3、-L指定了合并so最终生成的地方,演示项目里(对于armv8a架构来说)是:/home/liuzihui/softwaresCus/ffmpegSource/ffmpeg-4.2.2/android/armv8-a/lib

二、执行脚本

在前几篇文章中的ffmpeg-4.2.2源码目录下,终端命令:赋予脚本权限和执行脚本:

chmod +x build_android_v8v7_comileso.sh
./build_android_v8v7_comileso.sh

【ffmpeg】三、linux编译ffmpeg.so多架构编译【f

前言:在前两章已经介绍了,如何进行编译ffmpeg.so的一个完整过程。但是都是基于一个架构编译的,本文介绍一个sh脚本同时编译出双架构的方法,使编译过程更加方便和高效。

目前android端常用的架构有两个:

arm64-v8a:包含32位和64位执行状态

armeabi-v7a:只包含32位执行状态。

一、编写脚本

在前几篇文章中的ffmpeg-4.2.2源码目录下新建一个编译脚本:build_android_v8v7.sh:

#!/bin/bash
make clean
#变量定义,变量前面的export可要可不要,如export API
API=21
NDK=/home/liuzihui/softwaresCus/ndkr21/android-ndk-r21e
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
SYSROOT=$TOOLCHAIN/sysroot
ADDITIONAL_CONFIGURE_FLAG="--enable-avdevice --enable-avcodec --enable-avformat --enable-swresample --enable-swscale --enable-postproc --enable-avfilter"
function build_android {
  echo "===========================1========================"
  ./configure \
  --prefix=$OUTPUT \
  --target-os=android \
  --arch=$ARCH \
  --cpu=$CPU \
  --enable-asm \
  --enable-neon \
  --enable-cross-compile \
  --enable-shared \
  --disable-static \
  --disable-doc \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-symver \
  --disable-ffmpeg \
  --sysroot=$SYSROOT \
  --cross-prefix=$CROSS_PREFIX \
  --cc=$CC \
  --cxx=$CXX \
  --extra-cflags="-fPIC" \
  $ADDITIONAL_CONFIGURE_FLAG
  echo "===========================2====================="
  make clean
  echo "=============================${CC}==============="
  make -j4
  make install
}
 
#arm64-v8a
ARCH=arm64
CPU=armv8-a
OUTPUT=/home/liuzihui/softwaresCus/ffmpegSource/ffmpeg-4.2.2/android/$CPU
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-    #AR AS LD等通用
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang     #CC单独指定,非通用(因为ndk中CC与AR路径不同,后同理)
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++  #CXX单独指定,非通用
build_android
 
#armeabi-v7a
ARCH=arm
CPU=armv7-a
OUTPUT=/home/liuzihui/softwaresCus/ffmpegSource/ffmpeg-4.2.2/android/$CPU
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-       #AR AS LD等通用
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang     #CC单独指定,非通用
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++  #CXX单独指定,非通用
build_android
 

二、执行脚本

在前几篇文章中的ffmpeg-4.2.2源码目录下,终端命令:赋予脚本权限和执行脚本:

chmod +x build_android_v8v7.sh
./build_android_v8v7.sh

等待几分钟,然后会在ffmpeg-4.2.2源码目录下自动生成android目录和里面的内容:

后记:本次编译没有使用so的裁剪(上一篇已经讲过),使用生成默认的全量包(即生成了7个so)的方式编译的,后面的文章将讲述如何合并这7个so文件。

注意:若想自行裁剪,可以参照上一章介绍,修改本次脚本中的自定义变量 ADDITIONAL_CONFIGURE_FLAG 里面的一些enable和disable属性进行功能模块的配置。