Mac 平台 Android FFmpeg 编译与集成实践

2023-05-16

文章目录

  • FFmpeg 是什么
  • 为什么要学 FFmpeg 开发
  • FFmpeg 编译
    • 1. 编译环境准备
    • 2. FFmpeg 环境配置
    • 3. 完整的脚本
    • 4. FQA
  • 编译小结
  • 在Android Studio 中的集成
  • 集成问题记录
  • 写在最后

FFmpeg 是什么

FFmpeg 既是一款音视频编解码工具,同时也是一组音视频编解码开发套件,作为编解码开发套件,他为开发者提供了丰富的音视频处理的调用接口。

​ FFmpeg 提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种色彩格式转换、多种采样率转换、多种码率转换等; FFmpeg 框架提供了多种丰富的插件模块,包含封装与解封转的插件、编码与解码的插件等。

官方地址:https://www.ffmpeg.org/

为什么要学 FFmpeg 开发

FFmpeg 是一款知名的开源音视频处理软件,它提供了丰富而友好的接口支持开发者进行二次开发。

FFmpeg 读作 “ef ef em peg” ,其中的 “FF” 指的是 “Fast Forward”,“mpeg” 则是 “Moving Picture Experts Group” (动态图像专家组)。

FFmpeg 项目功能复杂而庞大,基本上支持所有常见的音视频处理操作,如封装格式转换、音视频转码、音视频播放和剪辑、视频添加水印滤镜等。

尽管 FFmpeg 功能强大,但是由于其采用的是带有传染性的 LGPL/GPL 开源协议,所以一些大厂基本上都是自己独立开发类似的音视频处理库,甚至在接口和组织模块上模仿 FFmpeg 。

因此,学习 FFmpeg 不仅能够帮助你掌握音视频开发的相关知识脉络,还能让你快速适应不同的音视频处理框架。

FFmpeg 编译

FFmpeg 有六个常用的功能模块:

  • libavformat:多媒体文件或协议的封装和解封装库,如 Mp4、Flv 等文件封装格式,RTMP、RTSP 等网络协议封装格式;
  • libavcodec:音视频编解码库;
  • libavfilter:音视频、字幕滤镜库;
  • libswscale:图像格式转换库;
  • libswresample:音频重采样库;
  • libavutil:工具库;

本文主要是帮助初学者快速上手 FFmpeg 的编译。

1. 编译环境准备

  • MAC系统版本:

image-20220912161223454

  • NDK版本:

    NDK 从 Android Studio 中配置中直接下载

    版本号为:25.1.8937393

  • ffmpeg-5.0.1

编译前准备:

mac 环境

//1. 下载 ffmpeg-5.0.1
wget https://ffmpeg.org/releases/ffmpeg-5.0.1.tar.bz2

//2. 解压 FFmpeg  也可以直接解压
tar -jxvf ffmpeg-5.0.1.tar.bz2

遇到的问题:

在官网的链接中下载的 ndk 格式为 dmg 的 如何安装呢?(暂时没有解决,换成了其他方式下载)

https://developer.android.google.cn/ndk/downloads?hl=zh_cn

image-20220912135245701

image-20220912135043727

此种方式没有用,不能解压成功,如果大家能处理成功,求指导。

于是根据官方文档的提示 在Android studio中去下载

image-20220912135146463

最后找到NDK的路径,后面的脚本需要用:

image-20220912161946847

注意这里的路径:

image-20220912162201368

刚开始我用的是 :~/Libraray/…… 这里的缩写路径,在文件夹右健进入 iterm 后出现的。不能用,需要用 pwd来找到绝对的路径。

以我的为例:

/Users/yangjun/Library/Android/sdk/ndk/25.1.8937393

2. FFmpeg 环境配置

image-20220912162957090

使用 Android studio 打开configure文件,

  • 搜索CMDLINE_SET,新增cross_prefix_clang

image-20220912163145572

  • 修改编译工具路径设置
    image-20220912163417600

  • 新建编译脚本build_android_so.sh

3. 完整的脚本

#!/bin/bash

#配置NDK路径 需要以你的为准
export NDK=/Users/xiaoyangzishuo/Library/Android/sdk/ndk/21.4.7075529
#配置toolchain路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
#配置交叉编译环境的根路径
SYSROOT=$TOOLCHAIN/sysroot

#arm64-v8a
API=30
ARCH=arm64
CPU=armv8-a
CROSS_PREFIX="$TOOLCHAIN/bin/aarch64-linux-android"
CROSS_PREFIX_CLANG="$TOOLCHAIN/bin/aarch64-linux-android$API"

#armeabi-v7a
#API=30
#ARCH=arm
#CPU=armv7-a
#CROSS_PREFIX="$TOOLCHAIN/bin/arm-linux-androideabi"
#CROSS_PREFIX_CLANG="$TOOLCHAIN/bin/armv7a-linux-androideabi$API"

OPTIMIZE_CFLAGS="-march=$CPU"
#配置so输出路径
OUTPUT=/Users/xiaoyangzishuo/Documents/android/FFmpeg/ffmpeg-5.0.1/out/android/$CPU

fun build
{
    ./configure \
    --prefix=$OUTPUT \
    --target-os=android \
    --arch=$ARCH \
    --cpu=$CPU \
    --enable-neon \
    --enable-cross-compile \
    --enable-shared \
    --enable-jni \
    --disable-static \
    --disable-asm \
    --disable-doc \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-symver \
    --disable-ffmpeg \
    --disable-avdevice \
    --disable-debug \
    --disable-postproc \
    --sysroot=$SYSROOT \
    --cross-prefix=$CROSS_PREFIX- \
    --cross_prefix_clang=$CROSS_PREFIX_CLANG- \
    --extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS"
    
    make clean all
    make -j8
    make install
}

echo '编译开始...'
build
echo '编译结束...'

最后执行脚本即可

chmod +x build_android_so.sh (如果没有权限,先添加权限,之后不再需要)

./build_android_so.sh

image-20220912165300904脚本已经执行成功,这里有个提示。先忽略。

大概 5-10 分钟后,得到了 6个 so 库 编译成功。

image-20220912163809215

后面可以将此 so 放到 Android Stuido中集成。

4. FQA

后面完善。

编译小结

上面编译 ffmpeg 脚本流程:shell -> configure -> make
首先我们编写 build_android_so.sh 脚本,调用 configure 配置参数,最后调用 make 命令生成动态库。

其中的 make 就是调用 makefile,makefile 是一种构建工具,类似于Gradle(构建.apk)、Maven(构建.war)
遇到最大的问题,是环境的路径的配置,脚本很简单,也有一些莫名奇妙的小问题,不过不影响编译成功。

在Android Studio 中的集成

  1. 先建立C++的项目

image-20220913225536812

按上图所示例一步一步运行,配置好ndk环境。目的在于接下来的操作的文件先准备好。

  1. 将 so库及头文件 copy到项目中来

    image-20220913225757384

  2. 设置 CMakeLists.txt

    # For more information about using CMake with Android Studio, read the
    # documentation: https://d.android.com/studio/projects/add-native-code.html
    
    # Sets the minimum version of CMake required to build the native library.
    
    cmake_minimum_required(VERSION 3.18.1)
    
    # 支持gnu++11
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
    
    # 1. 定义so库和头文件所在目录,方面后面使用
    set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
    set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR})
    
    
    # 2. 添加头文件目录
    include_directories(${ffmpeg_head_dir}/include)
    
    # 3. 添加ffmpeg相关的so库
    add_library( avutil
            SHARED
            IMPORTED )
    set_target_properties( avutil
            PROPERTIES IMPORTED_LOCATION
            ${ffmpeg_lib_dir}/libavutil.so )
    
    add_library(
            # 生成的库的名字
            swresample
            # 动态库
            SHARED
            # 源文件
            IMPORTED )
    set_target_properties( swresample
            PROPERTIES IMPORTED_LOCATION
            ${ffmpeg_lib_dir}/libswresample.so )
    
    add_library(
            avcodec
            SHARED
            IMPORTED )
    set_target_properties(
            avcodec
            PROPERTIES IMPORTED_LOCATION
            ${ffmpeg_lib_dir}/libavcodec.so )
    
    add_library(
            avfilter
            SHARED
            IMPORTED)
    set_target_properties(
            avfilter
            PROPERTIES IMPORTED_LOCATION
            ${ffmpeg_lib_dir}/libavfilter.so )
    
    add_library(
            swscale
            SHARED
            IMPORTED)
    set_target_properties(
            swscale
            PROPERTIES IMPORTED_LOCATION
            ${ffmpeg_lib_dir}/libswscale.so )
    
    add_library(
            avformat
            SHARED
            IMPORTED)
    set_target_properties(
            avformat
            PROPERTIES IMPORTED_LOCATION
            ${ffmpeg_lib_dir}/libavformat.so )
    
    # 查找代码中使用到的系统库
    find_library( # Sets the name of the path variable.
            log-lib
    
            # Specifies the name of the NDK library that
            # you want CMake to locate.
            log )
    
    # 配置目标so库编译信息
    add_library( # Sets the name of the library.
            native-lib
    
            # Sets the library as a shared library.
            SHARED
    
            # Provides a relative path to your source file(s).
            native-lib.cpp
            )
    
    # 指定编译目标库时,cmake要链接的库
    target_link_libraries(
            # 指定目标库,native-lib 是在上面 add_library 中配置的目标库
            native-lib
    
            # 4. 连接 FFmpeg 相关的库
            avutil
            swresample
            avcodec
            avfilter
            swscale
            avformat
            #        avdevice
    
            # Links the target library to the log library
            # included in the NDK.
            ${log-lib} )
    
  3. 设置 native-lib.cpp

#include <jni.h>
#include <string>

extern "C" {
#include "include/libavutil/avutil.h"
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_juneyang_cdemo_MainActivity_ffmpegInfo(JNIEnv *env, jobject thiz) {
// 返回 ffmpeg 配置信息
return env->NewStringUTF(avutil_configuration());
}
  1. 最后设置build.gradle
plugins {
  id 'com.android.application'
  id 'org.jetbrains.kotlin.android'
}

android {
  compileSdk 32

  defaultConfig {
    applicationId "com.juneyang.cdemo"
    minSdk 26
    targetSdk 32
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    externalNativeBuild {
      cmake {
        cppFlags '-std=c++17'
      }
      // abiFilters
      ndk {
        abiFilters "arm64-v8a"
      }
    }
  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
  kotlinOptions {
    jvmTarget = '1.8'
  }
  externalNativeBuild {
    cmake {
      path file('src/main/cpp/CMakeLists.txt')
      version '3.18.1'
    }
  }
  buildFeatures {
    viewBinding true
  }
  sourceSets {
    main {
      //将依赖库打进apk,否则可能出现找不到库
      jniLibs.srcDirs = ['libs']
    }
  }
}

dependencies {
  implementation fileTree(dir: 'libs', include: ['*.jar'])
  implementation 'androidx.core:core-ktx:1.7.0'
  implementation 'androidx.appcompat:appcompat:1.3.0'
  implementation 'com.google.android.material:material:1.4.0'
  implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
  testImplementation 'junit:junit:4.13.2'
  androidTestImplementation 'androidx.test.ext:junit:1.1.3'
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

最后运行成功。

image-20220913230323299

代码已上传到 GitHub

集成问题记录

目前出现一个问题,明明 NDK中有该文件,编译时却找不到。

NDK中有文件如图所示:

image-20220912232031736

编译时出错。

image-20220912231720563

image-20220912232302708

CMakeLists.txt 配置如下:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.18.1)

# 支持gnu++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

# 1. 定义so库和头文件所在目录,方面后面使用
set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR})

# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir}/include)

# 3. 添加ffmpeg相关的so库
add_library( avutil
        SHARED
        IMPORTED )
set_target_properties( avutil
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavutil.so )

add_library(
        # 生成的库的名字
        swresample
        # 动态库
        SHARED
        # 源文件
        IMPORTED )
set_target_properties( swresample
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libswresample.so )

add_library(
        avcodec
        SHARED
        IMPORTED )
set_target_properties(
        avcodec
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavcodec.so )

add_library(
        avfilter
        SHARED
        IMPORTED)
set_target_properties(
        avfilter
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavfilter.so )

add_library(
        swscale
        SHARED
        IMPORTED)
set_target_properties(
        swscale
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libswscale.so )

add_library(
        avformat
        SHARED
        IMPORTED)
set_target_properties(
        avformat
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavformat.so )

#add_library(
#        avdevice
#        SHARED
#        IMPORTED)

#set_target_properties( avdevice
#        PROPERTIES IMPORTED_LOCATION
#        ${ffmpeg_lib_dir}/libavdevice.so )

# 查找代码中使用到的系统库
find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log )

# 配置目标so库编译信息
add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp
        )

# 指定编译目标库时,cmake要链接的库
target_link_libraries(
        # 指定目标库,native-lib 是在上面 add_library 中配置的目标库
        native-lib

        # 4. 连接 FFmpeg 相关的库
        avutil
        swresample
        avcodec
        avfilter
        swscale
        avformat
#        avdevice

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib} )

native-lib.cpp 如下:

#include <jni.h>
#include <unistd.h>
#include <cstdint>
#include <string>
extern "C" {
#include "include/libavcodec/avcodec.h"
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_juneyang_cdemo_MainActivity_ffmpegInfo(JNIEnv *env, jobject thiz) {
  // 返回ffmpeg配置信息
  return env->NewStringUTF(avcodec_configuration());
}

编译时出错,最后在在 avcodec_configuration引用时选择了几个不同的头文件,并检查了 CmakeLists.txt中的头文件路径,几次尝试后解决了,这里有点困惑。

写在最后

折腾了两个晚上,记录了整个编译流程和集成的问题,如有问题,欢迎指正。

参考资料:

https://zhuanlan.zhihu.com/p/498073893

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mac 平台 Android FFmpeg 编译与集成实践 的相关文章

  • 关于电脑出厂时间查询工具的构思

    在做一个单位的计算机盘点 管理的时候 xff0c 很容易遇见需要知道电脑的采购时间 xff0c 或者出厂时间 这个信息能够帮助管理人员决定电脑是否该按定期报废制度进行报废或更换 目前为止 xff0c 作者接触过的各类电脑 xff0c 没有看
  • Outlook频繁崩溃解决方法

    这几天新换了笔记本 xff0c IT部门帮忙进行了配置 xff0c 拿到手上却屡屡发现邮件系统这出问题那出问题 xff0c 好生烦躁 经过几天的修修补补 xff0c 今天总算完全OK了 xff0c 又恢复到正常的轨道上来了 由于被折磨得够呛
  • Manifest文件详解

    一 关于AndroidManifest xml AndroidManifest xml 是每个android程序中必须的文件 它位于整个项目的根目录 xff0c 描述了package中暴露的组件 xff08 activities servi
  • Android蓝牙完全学习手册

    1 前言 市面上关于Android的技术书籍很多 xff0c 几乎每本书也都会涉及到蓝牙开发 xff0c 但均是上层应用级别的 xff0c 而且篇幅也普遍短小 对于手机行业的开发者 xff0c 要进行蓝牙模块的维护 xff0c 就必须从An
  • 【高级】深入理解Word里的字号、行距、段距、间距、样式

    昨天领导交给我一份文档 xff0c 让我帮忙修改一下 改完后最后一页只有单独的一行 xff0c 打印出来不够美观 因此 xff0c 我缩小了行距 xff0c 把默认的单倍行距改为了固定值28磅 结果是 xff0c 整个文档的确少了一页 xf
  • 笔记本插上耳机后仍在外放Realtek Audio Console不支持此机器

    大年初七 xff0c 开工第一天 下午办公室新来的同事请教的如题问题 他用的华硕笔记本 xff0c 飞行堡垒FX86FE 插上华为耳机 xff0c 耳机始终播放不出来声音 显示已经检测到耳机插入了耳机孔 xff0c 点击弹窗会显示 Real
  • git Filename too long

    全局 git config global core longpaths true 当前仓库 git config core longpaths true 转载于 https www cnblogs com EasonJim p 108038
  • VxWorks入门级开发环境学习

    由于实习需要 xff0c 最近在学习VxWorks xff0c 久闻该操作系统大名 xff0c 一直被其深厚的内力震撼着从未敢去了解 xff0c 直到最近 操作系统Vxworks本身的优点特点等详细信息不多说了 xff0c 这里讲讲几天来我
  • 树莓派 Retropie 4.4中文版使用说明 含roms资源

    漫步云端服务器 http chdong top bbs http www chdong top 相关名词 Retropie Retropie可以将你的树莓派或者PC变成一台复古游戏机 Retropie基于完整的操作系统之上 xff0c 你可
  • selenium 中 css-寻找元素

    等同于 tag名 不改变 elements 61 wd find elements by css selector 39 div 39 elements 61 wd find elements by tag name 39 div 39 i
  • 解决 The following packages have unmet dependencies: 问题

    The following packages have unmet dependencies libvtk5 dev Depends libfreetype6 dev but it is not going to be installed
  • 2.1Ubuntu20.4安装QT5.14.2

    QT简介 xff1a Qt是一个跨平台的C 43 43 图形用户界面库 xff0c 我们平时所说所使用的Qt xff0c 准确的来说是它的GUI编程部分 Qt提供给应用程序开发者建立图形用户界面所需要的功能 xff0c 并且Qt很容易扩展
  • 美国出台最严技术出口管制!14项前沿科技面临封锁

    关注ITValue xff0c 查看企业级市场最新鲜 最具价值的报道 xff01 xff08 本文转载自量子位公众号 xff0c ID xff1a QbitAI xff0c 作者 xff1a 乾明 夏乙 问耕 xff09 美国又打出一套七伤
  • sftp文件上传详解

    JSch是Java Secure Channel的缩写 JSch是一个SSH2的纯Java实现 它允许你连接到一个SSH服务器 xff0c 并且可以使用端口转发 xff0c X11转发 xff0c 文件传输等 xff0c 当然你也可以集成它
  • 数据库设计 ER图

    一 E R图构成要素 E R图也称实体 联系图 Entity Relationship Diagram xff0c 提供了表示实体类型 属性和联系的方法 xff0c 用来描述现实世界的概念模型 它是描述现实世界关系概念模型的有效方法 是表示
  • ssh-keygen -t rsa详解

    ssh keygen q 安静模式 b bits 位数 t dsa ecdsa ed25519 rsa rsa1 加密算法 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 6
  • samba源码编译安装(版本4.13.0)

    目录 前言编译安装samba下载三个包安装依赖共需要安装samba gnutls nettle1 进入解压后的samba目录执行 xff1a 2 进入解压后的gnutls目录执行3 进入解压后的nettle目录执行3 1 卸载已存在nett
  • mybatis+postgresql10插入返回主键ID

    MyBatis如果使用useGeneratedKeys去生成自增列会造成不成功 xff0c 因为官方提供只支持这些数据库 xff1a mybatis generatedkeys xff0c 那么如果要用在oracle和postgresql上
  • Mac 环境下使用 homebrew 安装和彻底卸载 MySQL5.7

    一 安装 MySQL5 7 在终端执行下列命令 xff1a brew install mysql 64 5 7 使用 brew 安装好 MySQL 5 7 版本后 xff0c 此时 MySQL root 用户的密码是空的 我们需要修改一下
  • python 爬取网站首页并获取资源文件

    一 使用requests模块 xff0c 如果没有安装请使用如下命令 xff0c 安装requests模块 pip install requests 二 打开PyCharm xff0c 创建一个新的py文件 1 请求网站 xff0c 获取网

随机推荐

  • github pages部署静态网页

    github pages部署静态网页 如果你的项目只是一个静态网站 xff0c 就没有必要再去整什么服务器 xff0c github pages 提供了搭建静态网站的功能 xff1b 为什么使用Github Pages 1 搭建简单而且免费
  • 使用 @PostConstruct、@Bean(initMethod=“”)注解指定初始化方法 、及实现InitializingBean接口 在 Spring Bean 完成初始化后进行一些响应的操作

    如果需要在 某个特定的bean 被初始化后 xff0c 执行一些代码逻辑 xff0c 可以使用 64 PostConstruct 64 Bean xff08 initMethod 61 xff09 注解指定初始化方法 及实现Initiali
  • RK3399环境搭建----glibc2.29编译

    硬件 xff1a firefly RK3399 JD4 软件 xff1a ubuntu18 04 需求 xff1a 在RK3399开发板上进行在线调试 调试需要用到GDB xff0c 之前拿到的gdb运行的时候报错 xff1a 提示libm
  • Sql Server索引

    1 创建索引时遵循一般原则 在需要经常搜索的列上面创建索引 在主键上创建索引 在外键上创建索引 在经常用于Where子句的列上创建索引 在经常需要排序的列上创建索引 对于数据类型为text xff0c image xff0c bit的列不应
  • 迅雷下载提示:应版权方要求/包含违规内容, 文件无法下载

    问题 在使用迅雷下载资源时 xff0c 可能会提示应版权方要求 xff0c 无法下载或包含违规内容 xff0c 无法下载 xff0c 如下图 很多人可能此时已经放弃了 xff0c 不过 xff0c 迅雷可以配合Free Download M
  • 有趣的教程:在PyCharm2019.2版本中集成Jupyter Notebooks!

    PyCharm是一种Python IDE xff0c 其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具 此外 xff0c 该IDE提供了一些高级功能 xff0c 以用于Django框架下的专业Web开发 嗨 xff0c
  • 分享文件的另一种选择--Firefox Send

    提起 Firefox xff0c 大家熟知的应该就是 Firefox Browser xff0c 即 火狐浏览器 xff0c 但是今天要说的是火狐旗下的文件分享产品 Firefox Send xff0c 可以让你安全地进行文件分享 适用场景
  • 消除if...else的十种方法

    前言 if else 是所有高级编程语言都有的必备功能 但现实中的代码往往存在着过多的 if else 虽然 if else 是必须的 xff0c 但滥用 if else 会对代码的可读性 可维护性造成很大伤害 xff0c 进而危害到整个软
  • Qt学习笔记(三)运行库依赖

    正常应该写release版本的依赖库 xff0c 不过都差不多 xff0c 自行转化就对了 自己使用qt版本 Qt5 15 2 xff0c 因为我只编译了debug版本程序 xff0c 暂时只能拿debug说事了 直接查找依赖可以找到依赖有
  • 宽带测速网站收集

    国际通用 xff1a https www speedtest net http www speedtest cn xff08 国产 xff0c 主要服务器节点多 xff09 电信 xff1a https 10000 gd cn 移动 xff
  • 使用Git为每个项目配置独立的用户名和邮箱

    使用Git为每个项目配置独立的用户名和邮箱 平时在开发的过程中 xff0c 用到git时 xff0c 要做一些特殊的配置 xff0c 例如自己公司内网https的SSL证书未经过第三方机构签署 xff0c 直接操作Git就会报错 xff0c
  • 电脑重装系统后文件还能恢复吗?2个方法助你还原文件

    电脑重装系统后文件还能恢复吗 xff1f 此时可能你面临一个难题 xff1a 已经重装了电脑 xff0c 但是发现丢失的问题 实际上 xff0c 一般当电脑出现运行缓慢 xff0c 或者是电脑系统出现故障无法修复的时候 xff0c 大家都会
  • C盘重装还能恢复以前文件嘛,重装C盘数据备份清单

    重装系统主要是对C盘的重装 xff0c 也就是对C盘的格式化 xff0c 电脑安装系统的位置是C盘 xff0c 常见的重装方法只影响C盘而不会丢失其他盘的数据 那么C盘重装还能恢复以前的文件嘛 xff1f 重装C盘时什么文件必须备份呢 xf
  • HTML Parsing Error:Unable to modify the parent container element before the child element is closed

    一 又涨见识了 IE8报下面错误 xff0c 而且是我的机器不报 xff0c 同事的机器报 xff0c 试了4台 xff0c 两个报 xff0c 两个不报 xff0c IE版本都一样 xff0c 没想明白 解决 xff1a 1 查看是否有未
  • 架构师必须学会的几种 UML图

    文章目录 一 UML 是什么定义作用 二 UML 画图的工具推荐三 UML 类图中的关系1 泛化 继承 2 实现 xff08 Realization xff09 3 关联 xff08 Association 4 聚合 xff08 Aggre
  • 算法:如何实现两个大数相加

    文章目录 问题要求思路代码实现 问题 实现两个很大很大的数相加 xff0c 求出它们的和 要求 1 是整数 xff1b 2 两个数无限大 xff0c long 都装不下 xff1b 3 不能用 BigInteger xff1b 4 不能用任
  • 关于Android 未来开发的方向探讨

    文章目录 背景Anroid 应用开发工程师技能参考Android 基础设施建设技能参考Android 逆向开发工程师技能参考Android Framework工程师技能参考 xff08 车载系统 系统开发方向 xff09 Android 性
  • Git Commit Message 规范实践

    文章目录 背景示例FeatureBugRefactorDocsTestStyleChore 每个Merge Request只有一个Commit小结附录 背景 本文总结了项目实践中的 Commit Message 规范 任何一笔提交都是有原因
  • github push 报错的问题记录

    文章目录 背景解决办法示例 背景 当 git 执行 git push xff08 origin origin master xff09 后出现错误提示 xff1a git push origin origin master Password
  • Mac 平台 Android FFmpeg 编译与集成实践

    文章目录 FFmpeg 是什么为什么要学 FFmpeg 开发FFmpeg 编译1 编译环境准备2 FFmpeg 环境配置3 完整的脚本4 FQA 编译小结在Android Studio 中的集成集成问题记录写在最后 FFmpeg 是什么 F