iOS 运用 ffmpeg 实现视频直播 (DZB item)

iOS 如何运用 ffmpeg 实现直播技术.

    说明,本文主要介绍如何运用 ffmpeg

视频直播的大概流程:

1.直播设备端(推流):从摄像头获取视频流,然后使用 rtmp 服务提交到服务器.

2.服务器端:接收直播人提交的 rtmp 视频流,并为观看者提供 rtmp 源.

3.观看者(拉流):用播放器播放 rtmp 的视频源.

 ps:RTMP(Real Time Messaging Protocol) 实时消息传输协议.该协议基于 TCP, 是一个协议族

前期准备:

新建一个项目,将所有需要引入的 ffmpeg 的静态库以及其他相关库引入到工程中,配置头文件搜索路径. ffmpeg 最新版本的应该是2.1的,历史版本详见http://www.ffmpeg.org/releases/,在这个网站上我们可以下到所有历史版本的库. ffmpeg 是一个跨平台的用 C 语言写成的库,包含了编码,解码,色彩空间装换等库.编译需要用到命令行,对于我们这些没搞过后台或者 Linux 开发的脚本知识欠缺的人来说的确是一个挑战.大家就各种百度 Google, 可以看下这个脚本, https://gist.github.com/m1entus/6983547 是一个老外写的,运行这个脚本需要依赖一个库 Perl 写的脚本,搜了一下网上目前编译 FFmpeg 库的帖子基本都会提到这个脚本,地址如下:https://github.com/mansr/gas-preprocessor

下载完这两个脚本后,编译 ffmpeg 库的准备工作就基本完成了,接着依次执行下面几步:

1.拷贝gas-preprocessor.pl文件到 /usr/bin目录下。(不能拷贝的把权限打开)

2.修gas-preprocessor.pl文件的权限 要有读写的操作

3.切换build-ffmpeg.sh脚本的目录下,使用命令sh build-ffmpeg.sh 运行该脚本即可。

注意: 1) build-ffmpeg.sh脚本的父目录的名字不能包括空格,否则可能导致构建失败。

     2) build-ffmpeg.sh脚本中可以配置编译的FFMpeg版本,以及使用iOS SDK的版本

该脚本中默认采用的FFmpeg是2.0版本的.使用 iOS7.0的 SDK 编译, C语言编译器采用clang, 应用中可以根据时间项目需要选中不同的 FFmpeg 和 iOS SDK 版本

根据上面的步骤来看,编译工作也没有什么复杂的.

编译完成后,为了后期的使用,需要将这些 C 文件添加到项目:

 

cmdutils_common_opts.h

 

cmdutils.h及cmdutils.c

 

config.h在scratch目录下取个对应平台的

 

ffmpeg_filter.c

 

ffmpeg_opt.c

 

ffmpeg_videotoolbox.c

 

ffmpeg.h及ffmpeg.c

 

除了config.h文件外,别的文件均在ffmpeg-3.0源码目录中

注意:1.此时编译的话会报错,因为 ffmpeg.c 文件中包含 main 函数,将该函数重民命为 ffmpeg_main 并在 ffmpeg.h 中添加 ffmpeg_main 函数的声明

 

         2.ffmpeg 任务完成后会结束进程,而 iOS 设备都是单进程多线程任务,所以需要将 cmdutils.c 文件中的 exit_program 方法中的 exit(ret).改为结束线程,需要引入#include  pthread_exit(null)

直播端:用 FFmepg 库抓取直播人设备的摄像头信息

使用 libavdevice 库可以代开获取摄像头的输入流,在 ffmpeg 中获取摄像头的输入流跟打开文件输入流很类似,示例代码如下:

//打开一个文件夹

 

AVFormatContext*pFormatCtx =avformat_alloc_context();

 

avformat_open_input(&pFormatCtx,"test.h264",NULL,NULL);

//获取摄像头输入

AVFormatContext*pFormatCtx =avformat_alloc_context();

//查找输入设备

AVInputFormat*ifmt=av_find_input_format("vfwcap");

//选取 vfwcap类型的第一个输入设备作为输入流

avformat_open_input(&pFormatCtx,0, ifmt,NULL);

如何使用 RTMP 上传视频流

使用 ffmpeg.c 中的 ffmpeg_main 方法直接运行该指令即可,示例代码: NSString*command =@"ffmpeg -re -i temp.h264 -vcodec copy -f flv rtmp://xxx/xxx/livestream";

//根据空格将指令分割为指令数组

NSArray*argv_array=[command_strcomponentsSeparatedByString:(@" ")];

//将 OC 对象转换为对应的 C 对象

intargc=(int)argv_array.count;

char** argv=(char**)malloc(sizeof(char*)*argc);

for(inti=0;i

{

argv[i]=(char*)malloc(sizeof(char)*1024);

strcpy(argv[i],[[argv_arrayobjectAtIndex:i]UTF8String]);

}

//传入指令数及指令数组

ffmpeg_main

//线程杀死,下面的代码不会执行

ffmpeg -re -itemp.h264 -vcodec copy -f flvrtmp://xxx/xxx/livestream   这行代码 -re 参数是按照帧率发送,否则ffmpeg会按最高速率发送,那么视频速率会忽快忽慢   -itemp.h264是需要上传的裸 h264流

服务端:这个需要后台的技术,原谅我前台不懂,大概就是采集视频后进行编码,再返回到服务器.

播放端:播放端实际上就是一个播放器,很多直播软件播放端和客户端都是同一个软件,所以使用项目中的 ffmpeg 进行播放简单粗暴又省事.

在 Github 上有个基于 ffmpeg 的第三方播放器Kxmovie,直接用就好. 地址:GitHub - kolyvan/kxmovie: movie player for iOS using ffmpeg.用法看它的 Readme.

 

posted @ 2016-06-23 14:12  Julius-Caesar  阅读(877)  评论(0)    收藏  举报