Android音视频开发--FFmpeg

音视频的基础知识

  • 视频

    • 静止的画面叫图像(picture);

    • 连续的图像变化每秒超过24帧(frame)画面以上时,根椐视觉暂留原理,人眼无法辨别每付单独的静态画面,看上去是平滑连续的视觉效果,这样的连续画面叫视频;

    • 当连续图像变化每秒低于24帧画面时,人眼有不连续的感觉叫动画(cartoon)。

  • 流媒体

    指采用流式传输的方式在Internet播放的媒体格式。流媒体的数据流随时传送随时播放,只是在开始时有些延迟 。边下载边播入的流式传输方式不仅使启动延时大幅度地缩短,而且对系统缓存容量的需求也大大降低,极大地减少用户用在等待的时间

  • 分辨率

    • 分辨率是一个表示平面图像精细程度的概念,通常它是以横向和纵向点的数量来衡量的,表示成水平点数垂直点数的形式。

    • 在计算机显示领域,我们也表示成“每英寸像素”(ppi)。

    • 在一个固定的平面内,分辨率越高,意味着可使用的点数越多,图像越细致。

  • 码流

    • 数据传输时单位时间传送的数据位数或数据流量,可以理解其为取样率。

    • 单位时间内取样率越大,精度就越高,处理出来的文件就越接近原始文件,但是文件体积与取样率是成正比的 。

    • 如何用最低的码率达到最少的失真,一般我们用的单位是kbps即千位每秒。

  • 帧率

    • 帧/秒(frames per second)的缩写,也称为帧速率,测量用于保存、显示动态视频的信息数量。

    • 每一帧都是静止的图象,快速连续地显示帧便形成了运动的假象。

    • 每秒钟帧数 (fps)愈多,所显示的动作就会愈流畅,可理解为1秒钟时间里刷新的图片的帧数,也可以理解为图形处理器每秒钟能够刷新几次,也就是指每秒钟能够播放(或者录制)多少格画面。

多媒体的格式分类

  • 封装格式(专业上讲叫容器,通俗的叫文件格式)、视频编解码、音频编解码

  • 常见的封装格式

    • MPEG : 编码采用的容器,具有流的特性。里面又分为 PS,TS 等,PS 主要用于 DVD 存储,TS 主要用于 HDTV.

    • MPEG Audio Layer 3 : 大名鼎鼎的 MP3,已经成为网络音频的主流格式,能在 128kbps 的码率接近 CD 音质

    • MPEG-4(Mp4) : 编码采用的容器,基于 QuickTime MOV 开发,具有许多先进特性。实际上是对Apple公司开发的MOV格式(也称Quicktime格式)的一种改进.

    • MKV: 它能把 Windows Media Video,RealVideo,MPEG-4 等视频音频融为一个文件,而且支持多音轨,支持章节字幕等;开源的容器格式

    • 3GP : 3GP视频采用的格式, 主要用于流媒体传送。3GP其实是MP4格式的一种简化版本,是手机视频格式的绝对主流.

    • MOV : QuickTime 的容器,恐怕也是现今最强大的容器,甚至支持虚拟现实技术,Java等,它的变种 MP4,3GP都没有这么厉害;广泛应用于Mac OS操作系统,在Windows操作系统上也可兼容,但是远比不上AVI格式流行

    • AVI : 最常见的音频视频容器,音频视频交错(Audio Video Interleaved)允许视频和音频交错在一起同步播放.

    • WAV : 一种音频容器,大家常说的 WAV 就是没有压缩的 PCM 编码,其实 WAV 里面还可以包括 MP3 等其他 ACM 压缩编码

流媒体协议(RTP/RTCP/RTSP/RTMP/HLS)

  • RTP (Real-time Transport Protocol)

    • 用于Internet上针对多媒体数据流的一种传输层协议.

    • RTP协议和RTP控制协议RTCP一起使用,而且它是建立在UDP协议上的 。

    • RTP不像http和ftp可完整的下载整个影视文件,它是以固定的数据率在网络上发送数据,客户端也是按照这种速度观看影视文件,当影视画面播放过后,就不可以再重复播放,除非重新向服务器端要求数据。

  • RTCP(Real-time Transport Control Protocol)

    实时传输控制协议,是实时传输协议(RTP)的一个姐妹协议

  • RTSP(Real Time Streaming Protocol)

    • 用来控制声音或影像的多媒体串流协议

    • RTSP提供了一个可扩展框架,使实时数据,如音频与视频的受控、点播成为可能。

    • 数据源包括现场数据与存储在剪辑中的数据。该协议目的在于控制多个数据发送连接,为选择发送通道,如UDP、多播UDP与TCP提供途径,并为选择基于RTP上发送机制提供方法 。

    • 传输时所用的网络通讯协定并不在其定义的范围内,服务器端可以自行选择使用TCP或UDP来传送串流内容,比较能容忍网络延迟。

    • RTSP与RTP最大的区别在于RTSP是一种双向实时数据传输协议,它允许客户端向服务器端发送请求,如回放、快进、倒退等操作。

    • 当然,RTSP可基于RTP来传送数据,还可以选择TCP、UDP、组播UDP等通道来发送数据,具有很好的扩展性。它时一种类似与http协议的网络应用层协议

  • RTMP(Real Time Messaging Protocol(实时消息传输协议))

    Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的开放协议。

  • HLS(HTTP Live Streaming)

    • 苹果公司(Apple Inc.)实现的基于HTTP的流媒体传输协议,可实现流媒体的直播和点播,主要应用在iOS系统,为iOS设备(如iPhone、iPad)提供音视频直播和点播方案。

    • HLS点播,基本上就是常见的分段HTTP点播,不同在于,它的分段非常小。

    • 相对于常见的流媒体直播协议,例如RTMP协议、RTSP协议、MMS协议等,HLS直播最大的不同在于,直播客户端获取到的,并不是一个完整的数据流。

    • HLS协议在服务器端将直播数据流存储为连续的、很短时长的媒体文件(MPEG-TS格式),而客户端则不断的下载并播放这些小文件,

    • 因为服务器端总是会将最新的直播数据生成新的小文件,这样客户端只要不停的按顺序播放从服务器获取到的文件,就实现了直播。

    • 由此可见,基本上可以认为,HLS是以点播的技术方式来实现直播。由于数据通过HTTP协议传输,所以完全不用考虑防火墙或者代理的问题,

    • 而且分段文件的时长很短,客户端可以很快的选择和切换码率,以适应不同带宽条件下的播放。不过HLS的这种技术特点,决定了它的延迟一般总是会高于普通的流媒体直播协议。

Android音视频开发--FFmpeg_第1张图片

android音视频的开发

  • 播放流程: 获取流–>解码–>播放

  • 录制播放路程: 录制音频视频–>剪辑–>编码–>上传服务器–>播放

  • 直播过程 : 录制音视频–>编码–>流媒体传输–>服务器—>流媒体传输到其他app–>解码–>播放

  • 几个重要的环节

    1. 录制音视频– AudioRecord/MediaRecord

    2. 视频剪辑–mp4parser或ffmpeg

    3. 音视频编码–aac&h264

    4. 上传大文件–网络框架、进度监听、断点续传

    5. 流媒体传输–流媒体传输协议rtmp、rtsp、hls

    6. 音视频解码–aac&h264

    7. 渲染播放–MediaPlayer

  • android平台自身支持的音视频解码一般为mp3、MP4、3gp

  • Android音视频播放框架主要为Vitamio、ijkplayer、UniversalMusicPlayer、vlc

关于FFmpeg

FFmpeg是一套非常知名的音视频处理的开源工具,它包含了开发完成的工具软件、封装好的函数库以及源代码供我们按需使用。

FFmpeg提供了非常强大的功能,可以完成音视频的编码、解码、转码、视频采集、后处理(抓图、水印、封装/解封装、格式转换等),还有流媒体服务等诸多功能,可以说涵盖了音视频开发中绝大多数的领域。

原生的FFmpeg是在Linux环境下开发的,但是通过各种方法(比如交叉编译等)可以使它运行在多种平台环境上,具有比较好的可移植性。

FFmpeg组成

构成FFmpeg主要有三个部分

  • 第一部分是四个作用不同的工具软件,分别是:ffmpeg.exe,ffplay.exe,ffserver.exe和ffprobe.exe。

    • ffmpeg.exe:音视频转码、转换器

    • ffplay.exe:简单的音视频播放器

    • ffserver.exe:流媒体服务器

    • ffprobe.exe:简单的多媒体码流分析器

  • 第二部分是可以供开发者使用的SDK,为各个不同平台编译完成的库。如果说上面的四个工具软件都是完整成品形式的玩具,那么这些库就相当于乐高积木一样,我们可以根据自己的需求使用这些库开发自己的应用程序。这些库有:

    • libavcodec:包含音视频编码器和解码器

    • libavutil:包含多媒体应用常用的简化编程的工具,如随机数生成器、数据结构、数学函数等功能

    • libavformat:包含多种多媒体容器格式的封装、解封装工具

    • libavfilter:包含多媒体处理常用的滤镜功能

    • libavdevice:用于音视频数据采集和渲染等功能的设备相关

    • libswscale:用于图像缩放和色彩空间和像素格式转换功能

    • libswresample:用于音频重采样和格式转换等功能

  • 第三部分是整个工程的源代码,无论是编译出来的可执行程序还是SDK,都是由这些源代码编译出来的。FFmpeg的源代码由C语言实现,主要在Linux平台上进行开发。FFmpeg不是一个孤立的工程,它还存在多个依赖的第三方工程来增强它自身的功能。

FFmpeg进行视频编码所需要的结构

  • AVCodec:AVCodec结构保存了一个编解码器的实例,实现实际的编码功能。通常我们在程序中定义一个指向AVCodec结构的指针指向该实例。

  • AVCodecContext:AVCodecContext表示AVCodec所代表的上下文信息,保存了AVCodec所需要的一些参数。对于实现编码功能,我们可以在这个结构中设置我们指定的编码参数。通常也是定义一个指针指向AVCodecContext。

  • AVFrame:AVFrame结构保存编码之前的像素数据,并作为编码器的输入数据。其在程序中也是一个指针的形式。

  • AVPacket:AVPacket表示码流包结构,包含编码之后的码流数据。该结构可以不定义指针,以一个对象的形式定义。

FFmpeg编码的主要步骤

  • 首先解析、处理输入参数,如编码器的参数、图像的参数、输入输出文件;

  • 建立整个FFmpeg编码器的各种组件工具,顺序依次为:avcodec_register_all-> avcodec_find_encoder -> avcodec_alloc_context3 -> avcodec_open2-> av_frame_alloc -> av_image_alloc;

  • 编码循环:av_init_packet ->avcodec_encode_video2(两次) -> av_packet_unref

  • 关闭编码器组件:avcodec_close,av_free,av_freep,av_frame_free

FFmpeg视频解码器所包含的结构

同FFmpeg编码器类似,FFmpeg解码器也需要编码时的各种结构,除此之外,解码器还需要另一个结构——编解码解析器——用于从码流中截取出一帧完整的码流数据单元。

FFmpeg解码的主要步骤

解码器的流程与编码器类似,只是中间需要加入一个解析的过程。整个流程大致为:

  1. 读取码流数据 ->

  2. 解析数据,是否尚未解析出一个包就已经用完?是返回1,否继续 ->

  3. 解析出一个包?是则继续,否则返回上一步继续解析 ->

  4. 调用avcodec_decode_video2进行解码 ->

  5. 是否解码出一帧完整的图像?是则继续,否则返回上一步继续解码 ->

  6. 写出图像数据 ->返回步骤2继续解析。

FFmpeg实现视频水印

视频的水印通常指附加在原始视频上的可见或者不可见的,与原始视频无直接关联的标识。

通常在有线电视画面上电视台的台标以及视频网站上的logo就是典型的视频水印的应用场景。

通常实现视频水印可以通过FFmpeg提供的libavfilter库实现。libavfilter库实际上实现的是视频的滤镜功能,除了水印之外,还可以实现视频帧的灰度化、平滑、翻转、直方图均衡、裁剪等操作。

我们这里实现的视频水印等操作,完全在视频像素域实现,即从一个yuv文件中读取数据到AVFrame结构,对AVFrame结构进行处理后再输出到另一个yuv文件,中间不涉及封装或编码解码等操作。

  1. 解析命令行,获取输入输出文件信息

  2. Video Filter初始化

  3. 初始化输入输出AVFrame并分配内存

  4. Video Filtering循环体

FFmpeg实现视频缩放

视频缩放是视频开发中一项最基本的功能。通过对视频的像素数据进行采样或插值,可以将低分辨率的视频转换到更高的分辨率,或者将高分辨率的视频转换为更低的分辨率。

通过FFmpeg提供了libswscale库,可以轻松实现视频的分辨率转换功能。除此之外,libswscale库还可以实现颜色空间转换等功能。

通常情况下视频缩放的主要思想是对视频进行解码到像素域后,针对像素域的像素值进行采样或差值操作。这种方式需要在解码端消耗一定时间,但是通用性最好,不需要对码流格式作出任何特殊处理。

在FFmpeg中libswscale库也是针对AVFrame结构进行缩放处理。

  1. 解析命令行参数

  2. 创建SwsContext结构

  3. 分配像素缓存

  4. 循环处理输入frame

  5. 收尾工作

    收尾工作除了释放缓存区和关闭输入输出文件之外,就是需要释放SwsContext结构,需调用函数:sws_freeContext。

 

 

你可能感兴趣的:(音视频开发)