NDK_Day11_Shell 脚本、FFmpeg 交叉编译

一、Shell 脚本

Sheell:是一个用 C 语言编写的程序
脚本:Script
后缀:.sh

Shell 脚本很多情况下就是一段命令的集合,用于完成一系列的操作,解决了每次都需要手动执行繁杂操作步骤的问题

举个栗子
写个 HelloWorld
① 创建 helloworld.sh

vim helloworld.sh

添加如下内容

#!/bin/bash
echo "Hello World"

第一行:指定脚本用到的解释器,目前应用最广的是 bash 解释器
第二行:使用 echo 输出内容

② 设置可执行权限

// Linux 中新创建的文件默认没有可执行权限,需要增加可执行权限
chmod +x helloworld.sh

③ 执行

./helloworld.sh

二、编译 Android 可用的 FFmpeg

2.1 准备

1.下载
打开 FFmpeg 官网,点击 Download 按钮
打开官网,点击 Download 按钮
右键 Download
右键 Download
右键复制下载链接
右键复制下载链接
到虚拟机中粘贴下载链接,使用 wget 命令下载(测试的话,下载最新的就行)

wget https://ffmpeg.org/releases/ffmpeg-4.1.3.tar.bz2

到虚拟机中粘贴下载链接,使用 wget 命令下载

2.解压

// x:解压
// v:显示解压过程
// f:file 文件
tar -xvf ffmpeg-4.1.3.tar.bz2

解压
看下 ffmpeg 目录下都有啥(含组件源码、文档、配置脚本等)
查看 ffmpeg 目录
看下绿色的 configure 文件都有什么内容(是一个 Shell 脚本)
查看 configure 文件
configure 文件(Shell 脚本)作用:生成 makefile 脚本
makefile:定义了一系列的规则来完成编译和链接,即使编译自动化,可以使用 make 指令执行 makefile 脚本,可以生成 makefile 脚本对应的静、动态库或可执行文件

2.2 常见参数简介

avformat:用于音视频封装格式的生成与解析,平时需要解析音视频时可使用
avcodec:音视频编解码
avutil:工具类,一般都需要
scale:视频缩放、色彩映射转换
avdevice:操作摄像头,但是不支持操作 Android 上的摄像头(不支持 Android 采集和播放设备),可以关闭此功能
swresample:对音频重采样,如对视频中双声道和单声道间转换
postproc:后期处理
avfilter:加字幕加水印时可用
encoders:编码,只播放可关闭此功能
muxers:混合封装,将图像和声音封装成音视频,不需封装可关闭此功能
cross-compile:交叉编译

cross-prefix:交叉编译工具前缀,就是路径

D:/android_studisdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-

sysroot:编译时查找头文件、库文件的目录

D:/android_studio/sdk/ndk-bundle/platforms/android-21/arch-arm

isystem:编译时查找头文件目录

D:\android_studio\sdk\ndk-bundle\sysroot\usr\include\arm-linux-androideabi

2.3 配置 FFmpeg Shell 脚本

使用到的 NDK 版本要在 16 往上,15 可能会有问题,最后测试 17 没问题

配置 NDK 环境变量
下载 NDK

  1. 官网下载 Linux 环境下的 NDK:https://developer.android.google.cn/ndk/downloads/
  2. 下载到指定目录(我们这里下载到 /home/lql 目录下),下载完成后,解压即可

打开环境变量配置文件

vim /etc/profile

在末尾添加如下内容

export ANDROID_NDK=/home/lql/android-ndk-r17c
export PATH=$ANDROID_NDK:$PATH

使配置马上生效

source /etc/profile

编写 build.sh

#!/bin/bash

# NDK_ROOT=/root/linux/ndk/android-ndk-r17c
CPU=arm-linux-androideabi
TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64

# FLAGS 除了 -isystem、-D__ANDROID_API__=21,其它都是默认的,其实网上有的并没有这么多参数,只有 -isystem、-D__ANDROID_API__=21-fPIC 等简单的几个参数
FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=21 -g  -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fPIC"
INCLUDES="-isystem $NDK_ROOT/sources/android/support/include"

# 指定最终编译生成的文件的存放路径,随便制定一个目录也行
# 这里指定为在当前目录(pwd)下的 android/armeabi-v7a7 目录,其中 android 和 armeabi-v7a7(叫 armeabi-v7aJQK 也米问题)只是为了标识库文件是 android 平台下 armeabi-v7a 架构的库文件而已
PREFIX=`pwd`/android/armabi-v7a7

./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-postproc \
--disable-encoders \
--disable-muxers \
--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/$CPU- \
--sysroot=$NDK_ROOT/platforms/android-21/arch-arm \
--extra-cflags="$FLAGS $INCLUDES" \
--extra-cflags="-isysroot $NDK_ROOT/sysroot" \
--arch=arm \
--target-os=android

# 清理一下
make clean
# 编译 makefile
make
# 执行 makefile
make install

运行脚本

./build.sh

可以忽略下图的警告,不影响编译
可以忽略一些警告,不影响编译

等着吧…

如下图,不出意外的话,脚本运行完毕,生成了一个 android 文件夹,即编译成功
生成了一个 android 文件夹,即编译成功

进入 android/armabi-v7a7,查看生成的文件
进入 android/armabi-v7a7,查看生成的文件

进入 lib 目录(内含生成的 .a 静态库文件)
lib 目录中含生成的 .a 静态库文件

打包 .a 静态库为 .so 动态库

$ANDROID_NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=$ANDROID_NDK/platforms/android-21/arch-arm -shared -o libffmpeg.so -Wl,--whole-archive libavcodec.a libavformat.a libavutil.a libswresample.a libswscale.a libavfilter.a -Wl,--no-whole-archive

2.4 在 Android 中使用编译好的 FFmpeg 静态库

这里我们使用静态库,拿到 AndroidStudio 中使用
① 使用 AndroidStudio 创建 NDK 项目
② 在 src 目录下创建 jniLibs 目录
② 引入头文件
将 include 文件夹复制到 jniLibs 目录下
将 include 文件夹复制到 jniLibs 目录下
③ 引入库文件
-1 在 jniLibs 目录下创建 libs/armeabi-v7a 目录
-2 将生成的静态库放在 libs/armeabi-v7a 目录下
引入库文件
④ 配置 CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)

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)

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)

include_directories(${CMAKE_SOURCE_DIR}/../jniLibs/include)
# 因为有 5 个静态库文件,所以这里直接使用 set() 方式链接,当然也可以用 add_library()set_target_properties() 去链接,5 个静态库文件配置 5set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/libs/${ANDROID_ABI}")

target_link_libraries( # Specifies the target library.
        native-lib avcodec avfilter avformat avutil swresample swscale

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

⑤ 配置 app 下的 build.gradle

apply plugin: 'com.android.application'

android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters "armeabi-v7a"
            }
        }
    }
    ...
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    ...
}

⑥ 使用 ffmpeg 函数

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

// extern "C":在 C++ 中使用 C 的代码
extern "C" {
#include <libavcodec/avcodec.h>
}

extern "C" JNIEXPORT jstring JNICALL
Java_com_lql_dn_ndk_day11_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    const char *version = av_version_info(); // 使用 ffmpeg 的一个函数
    return env->NewStringUTF(version);
}

⑦ 运行
运行
o**k,模拟器显示内容和我们下载的 ffmpeg 的版本 4.1.3 一致
模拟器显示内容和我们下载的 ffmpeg 的版本 4.1.3 一致

三、音视频

视频:一段声音 + 一段视频,以一定格式组合起来,就是视频文件

播放视频时,图像是三原色 rgb,声音是 pcm

编码:图像声音原始数据过大,需要对其进行编码(编码压缩,对原始数据进行压缩的过程),编码后的数据就是音视频数据,然后再进行封装,封装到容器(mp4、avi、flv)里面,就形成了视频文件
解码:把容器(音频+视频+字幕+…),需要解封装,抽离出音频、视频(压缩后的数据)等,然后再进行解码(解压缩),解出来图像声音的原始模型 RGB、亮度模型 YUV,拿到这些原始数据后,才能显示到屏幕上

未完待续…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值