上次我们搭建了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帧的概念比较抽象,可以用下面的列子作为理解

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

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

这是苹果运动过程中,我们某个时间点记录的画面,可以把它当作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

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

在该目录下,编写以下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脚本执行权限后,执行该脚本

等待编译结束

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

二、音频编码:使用aac

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

下载后在Linux中解压

在该目录下,编写以下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工程中

三、推流:使用rtmpdump

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

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

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

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

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

在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到工程下:

在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顺利通过,至此,集成第三方库的准备工作就结束了,下一篇文章就开始编写代码

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

  1. android最新能调试吗,android – 不能在同一台设备上安装调试和发布版本

    我已经使用applicationIdSuffix在我的项目中配置了构建版本,以便我可以在我的设备上安装调试版本和发行版本. 这里是我的build.gradle(相关部分): buildTypes { ...

  2. android jni不适用ndk,Android NDK编译之undefined reference to 'JNI_CreateJavaVM'

    利用Android NDK编译动态库,在C文件中调用了两个JNI函数:JNI_GetDefaultJavaVMInitArgs和JNI_CreateJavaVM.编译的时候始终报以下错误: XXX: ...

  3. android 最新写法,详解Android 硬布局item的高级写法

    本文主要介绍了Android 硬布局item的高级写法,分享给大家,具体如下: 效果: 这种布局应该是非常常见了,且写的比较多. 今天简单探讨一下效果图中上下两种布局的写法. 比较 上下效果一致 行数 ...

  4. android最新adt下载地址,Android SDK和最新ADT下载地址

    ADT Android ADT-0.9.6.zip官方下载地址: http://dl.google.com/android/ADT-0.9.6.zip Android ADT-0.9.7.zip官方下 ...

  5. android最新知识点总结,学习android之 知识点总结

    开发andorid程序必备: Eclipse 3.5以上版本 SDK类似于java中的jdk. Adt 是开发Eclipe上的一个插件. 组件使用: TestView: 为文本设置超链接,需设置该属性 ...

  6. android最新主流机型,就要Android 市售主流机型随你挑

    谷歌奇迹--Android已成不二之选 在IT行业里,谷歌一直都是一个非常有特色的企业,也是一个经常招来争议的企业,远的不说,其对于自己老本行--搜索业务的原则之强就能令人叹为观止,其实谁都知道,对于 ...

  7. android 最新微信红包,分享Android微信红包插件

    本文实例为大家分享了Android微信红包插件,供大家参考,具体内容如下 效果图: 具体代码 @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private vo ...

  8. Android:最新基于adt-bundle-windows-x86的android开发环境搭建

    1.下载jdk:http://www.oracle.com/technetwork/java/javase/downloads/index.html 安装jdk,我的安装目录是C:\Java\jdk1 ...

  9. android zip格式的ndk,Android 使用NDK (JNI)容易解压7z压缩文件

    C语言使用LZMA SDK解压非加密7z文件介绍:http://hzy3774.iteye.com/blog/2104510 github项目地址:https://github.com/hzy3774 ...

最新文章

  1. DataBase 之 拉链表结构设计
  2. Java基础学习总结(21)——数组
  3. python opencv图片编码为h264文件
  4. 使用 Eigen 库写第一个程序
  5. win10家庭版远程桌面连接出现身份验证错误
  6. RTX51 Tiny中容易混淆的问题
  7. 课堂练习之谁是水王(一)
  8. Cocos2d-x 中 CCProgressTimer
  9. 从C#到TypeScript - Generator
  10. 调车遇到的问题及解决办法
  11. 基于Spring Security的认证授权_认证原理_授权流程_Spring Security OAuth2.0认证授权---springcloud工作笔记126
  12. 使用 golang-plugins 时要避免的事情
  13. 例解List<Map<String, Object>>存放的对象问题
  14. jquey控制元素滚动条,外层div滚动,内层顶部div固定不动
  15. kali更新sqlmap命令以及更新后无法使用的解决方法
  16. java三角形边长_java三角形怎么求边?
  17. U3D性能优化之MeshBaker(不带光照)
  18. C# 将错误日志写到txt文件
  19. 苹果MacBook电脑应用优化利器CleanMyMac X
  20. matplotlib.pyplot.colormaps色彩图cmap

热门文章

  1. XPosed及插件安装(解决下载http://dl.xposed.info/repo/full.xml.gz时出错的问题)
  2. python -u xxx.py
  3. 写在35岁,过去现在和未来
  4. 第一部份1:JMF基础原理与相关术语介绍 。。。。快速了解JMF有什么相关内容
  5. 聚蓝bluetech便携式移动滤水壶 家用净水壶,值得拥有
  6. 网页录屏(帧记录)调研总结
  7. Excel PivotTable 使用心得手顺分享(二)
  8. ios开发App的图标背景色不能是透明
  9. 股票K线指标算法整理(Java封装工具类)
  10. epub文件打开乱码_什么是EPUB文件(以及如何打开一个文件)?