android最新直播框架,NDK--Android Studio中直播推流框架的搭建

上次我们搭建了nginx流媒体服务器,接下来就是研究安卓端是如何直播推流到nginx服务器,之前我们了解到视频流和音频流,那么直播也必然绕不开这两个流,手机端的直播可想而知,视频流使用摄像头获取,音频流使用麦克风获取。然而摄像头和麦克风直接获取的裸数据的体积实在是太大了,如果要想进行网络传输,必须进行压缩,即编码

一、视频编码:使用h264

h264是目前使用最广泛的视频编码,由于高压缩比、高图像质量等优势,使得其在具有高压缩比的同时还拥有高质量流畅的图像,在网络传输过程中所需要的带宽更少,也更加经济

编码规则--h264拥有一套独特的编码

1.I帧 帧内编码帧

可以理解为这一帧画面的完整保留(实际是进行了切片和压缩);解码时只需要本帧数据就可以完成(因为包含完整画面)

I帧特点:

JPEG压缩编码

它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;

解码时仅用I帧的数据就可重构完整图像;

I帧描述了图像背景和运动主体的详情;

I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);

I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧

I帧不需要考虑运动矢量;

I帧所占数据的信息量比较大。

2.P帧 前向预测编码帧

以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量, 取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。

P帧特点:

P帧是I帧后面相隔1~2帧的编码帧;

P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);

解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;

P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;

由于P帧是参考帧,它可能造成解码错误的扩散;

由于是差值传送,P帧的压缩比较高

3.B帧 双向预测内插编码帧

B帧记录的是本帧(I帧或P帧)与前后帧(P帧)的差别(具体比较复杂,有4种情况,要解码B帧,不仅要取得之前的缓存画面(I帧或P帧),还要解码之后的画面(P帧),通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。

B帧特点

B帧是由前面的I或P帧和后面的P帧来进行预测的;

B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;

B帧是双向预测编码帧;

B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;

B帧不是参考帧,不会造成解码错误的扩散

I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。

4.宏块(对一帧画面进行切片后,片中包含的数据)是视频信息的主要承载者,因为它包含着每一个像素的亮度和色度信息。视频解码最主要的工作则是提供高效的方式从码流中获得宏块中的像素阵列。组成部分:一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个 8×8 Cr 彩色像素块组成 。每个图象中,若干宏块被排列成片的形式。

I帧、P帧、B帧的概念比较抽象,可以用下面的列子作为理解

一个苹果在屏幕中间做自由落体运动,在中间时的画面如下:

d462fe87d6ec

这个画面是运动的起始点,可以把它当作I帧。另一个画面是苹果落到屏幕下边缘时,如下图:

d462fe87d6ec

这是苹果运动过程中,我们某个时间点记录的画面,可以把它当作P帧,而I帧和P帧中间过程的画面,我们把它们成为B帧,由于B帧不存在真正的画面,只有以前一画面(I帧或P帧,P帧也有画面信息)和后一画面(P帧)模拟,进行画面的预测,所以B帧所含的数据量很小,但是B帧越多,预测也就越多,会导致运动的不准确性,可以理解为B帧会使得这运动变为匀速运动,很显然上面两张图中间的速度并不是匀速的,所以P帧特点中有一项为:P帧是I帧后面相隔1~2帧的编码帧,即B帧在两个画面帧之间(I帧和P帧之间,P帧和P帧之间)只有1 ~ 2帧或没有。

我们对裸数据进行h264编码需要用到一个工具x264,接下来介绍如何编译它

1.首先下载x264

直接下载下来的文件是bz2文件,需要使用bzip2,执行以下命令安装bzip2

yum -y install bzip2.x86_64

执行解压命令

tar xvfj x264-master.tar.bz2

解压完毕后的文件内容如下

d462fe87d6ec

在该目录下,编写以下shell脚本,需要使用ndk下的编译器编译,ndk的安装可以参考我以前的文章:https://www.jianshu.com/p/5850b1f0e024

#!/bin/bash

#改为自己对应的ndk目录

NDK_ROOT=/lib/ndk/android-ndk-r14b

SYSROOT=$NDK_ROOT/platforms/android-9/arch-arm/

TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64

function build_one

{

./configure \

--prefix=$PREFIX \

--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \

--sysroot=$SYSROOT \

--host=arm-linux \

--enable-pic \

--enable-static \

--disable-asm \

--disable-shared \

--disable-cli

make clean

make

make install

}

CPU=arm

PREFIX=$(pwd)/android/$CPU

build_one

给shell脚本执行权限后,执行该脚本

d462fe87d6ec

等待编译结束

d462fe87d6ec

将include和lib拷贝出来,以备待会放入as工程中

二、音频编码:使用aac

使用FAAC编码工具,同样的要编译它

下载后在Linux中解压

d462fe87d6ec

在该目录下,编写以下shell脚本,同样需要使用ndk中的编译器

#!/bin/sh

CPU=$1

NDK_ROOT=/lib/ndk/android-ndk-r14b

export PLATFORM=$NDK_ROOT/platforms/android-9/arch-arm

export PREBUILT=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin

export PREFIX="$(pwd)/android/arm"

export CROSS_COMPILE=$PREBUILT/arm-linux-androideabi-

export CFLAGS="-DANDROID -fPIC -ffunction-sections -funwind-tables -fstack-protector -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300"

export CPPFLAGS="$CFLAGS"

export CFLAGS="$CFLAGS"

export CXXFLAGS="$CFLAGS"

export CXX="${CROSS_COMPILE}g++ --sysroot=${PLATFORM}"

export LDFLAGS="$LDFLAGS"

export CC="${CROSS_COMPILE}gcc --sysroot=${PLATFORM}"

export NM="${CROSS_COMPILE}nm"

export STRIP="${CROSS_COMPILE}strip"

export RANLIB="${CROSS_COMPILE}ranlib"

export AR="${CROSS_COMPILE}ar"

mkdir -p ./android/arm/include

mkdir -p ./android/arm/lib

./configure --program-prefix=$PREFIX --without-mp4v2 --host=arm-linux

make

cp ./libfaac/.libs/*.a $PREFIX/lib

cp ./libfaac/.libs/*.so $PREFIX/lib

cp ./include/*.h $PREFIX/include

赋予shell脚本执行权限后执行,将生成的include和lib拷贝出来,以备待会放入as工程中

d462fe87d6ec

三、推流:使用rtmpdump

从官网下载下来后解压(不要下windows和android的,android中只有so文件,如果要使用,需要将头文件导入as工程)

d462fe87d6ec

一会我们将该目录下的librtmp文件夹复制到as工程中,使用cmake编译它

四、创建AS工程:集成各个工具

1.创建ndk工程,在manifest中赋予权限

2.将faac和x264中的头文件和静态库复制进工程中:

d462fe87d6ec

在CMakeLists中导入它们

cmake_minimum_required(VERSION 3.4.1)

#将libs的路径设置到变量中

set(lib_dir ${CMAKE_SOURCE_DIR}/../../../libs)

#include头文件

include_directories(${CMAKE_SOURCE_DIR}/../../../libs/include)

#x264

add_library(

x264

STATIC

IMPORTED)

SET_TARGET_PROPERTIES(

x264

PROPERTIES IMPORTED_LOCATION

${lib_dir}/lib/libx264.a)

#faac

add_library(

faac

STATIC

IMPORTED)

SET_TARGET_PROPERTIES(

faac

PROPERTIES IMPORTED_LOCATION

${lib_dir}/lib/libfaac.a)

add_library(

native-lib

SHARED

native-lib.cpp)

find_library(

log-lib

log)

target_link_libraries(

native-lib

x264

faac

${log-lib})

在gradle的defaultConfig中配置只编译armeabi平台,其他平台需要重新使用ndk中的相应编译器编译

ndk {

abiFilters "armeabi"

}

3.复制rtmpdump到工程下:

d462fe87d6ec

在librtmp中创建新的CMakeLists.txt,内容如下:

#编译时关闭openssl

#编译时关闭openssl

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_CRYPTO")

file(GLOB rtmp_source *.c)

add_library(

rtmp

STATIC

${rtmp_source})

在主CMakeLists.txt中导入上面cmake生成的静态库

...

#引入rtmp的静态库

add_subdirectory(${CMAKE_SOURCE_DIR}/librtmp)

...

target_link_libraries(

native-lib

x264

faac

rtmp

${log-lib})

build顺利通过,至此,集成第三方库的准备工作就结束了,下一篇文章就开始编写代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值