HEXA娱乐开发日志技术点004——一步到位的推流

HEXA开发日志目录
上一篇 HEXA娱乐开发日志技术点003——下位机成功推流


颠覆

本篇的成果是,实现了基于raw data的推流。
前一篇是基于flv文件的推流,flv文件的内容是对raw data进行压缩编码的产物,而我们从mind SDK获得的是raw data,是不能用RTMPDUMP直接推流的,所以才有了本篇内容,并对前一篇的内容进行了颠覆,这个颠覆要从下图说起。

技术需求与技术点

这张图相对于之前的版本有些变化,左边技术需求多了个压缩编码,右边技术点中的RTMPDUMPffmpeg取代了,右边这个变化就是本篇所指的颠覆了。

需求的变化

当初对RTMPDUMP不了解,不清楚它要的是压缩编码后的数据,所以没考虑到压缩编码这个必要的数据转换步骤。

技术点的颠覆

前一篇的部分成果被颠覆的原因是,我只知道ffmpeg可以压缩编码,但不知道它还可以直接推流,当我看到雷前辈的例子时,我惊呆了,因为里面没有一点RTMPDUMP的影子,却说它可以推流。
在验证了雷前辈的例子之后,我当时认为,大概是ffmpeg使用了RTMPDUMP的库吧,因为它们的git地址都出现了ffmpeg.org,既然它们是整整齐齐的一家人,那至少应该是相互有关联的一群人做出来的吧。对于rtmp推流的功能不会单独做出两份相同功能的东西吧。因为我的系统里装了RTMPDUMP的库,所以还侥幸地认为多半ffmpegRTMPDUMP之间有依赖关系,直到我把skill中的RTMPDUMP库删除,并确认机器人身体里确实没有了这个库,还依旧能正常推流之后,我才放弃了侥幸。
这彻底宣告了,我对RTMPDUMP的相关研究,对于目标来说是无用功。

这就是积极前进的人生的常态吧,在对昨天的自己的嘲笑中前进,明知道今天的自己也会被明天的自己嘲笑,但若不做今天的无用功,也无法获得明天嘲笑今天的资格。

干货

回顾了昨天的无用功,再来看看今天又搞出了什么幺蛾子。
首先明确一下本篇目标,就是把从raw data到推流这条路打通,这里的raw data还不是从mind SDK获得的,只是用官方的算法制造的。步骤还是经典三板斧,即研究、上位机demo、移植到下位机

研究ffmpeg

其实算不上什么研究,主要是搞清楚上位机demo的步骤,在考虑如何入手之前,先列一下已知条件:

  • ffmpeg有官方例子可以参考
  • 我在之前的工作中研究并改造过一个官方例子
  • 雷前辈有例子可以参考

下面对已知逐一分析:

  1. 首先,先看一下我研究过的那个例子,这个例子只能编码视频,没有音频,我并不能拿来用。只是在这个例子的研究中,我知道了如何用新ffmpeg接口替换掉过时的接口。
  2. 然后,我确定了我需要参考的官方例子,这个例子把raw data压成了flv文件,而前一篇正好是以flv文件作为输入的,我当时想,一定可以在这两者之间建立数据连接,而不必生成flv文件,这样输入是raw data,输出是推流,本篇的目标就达到了。这时的产出是61dd400e0323bd242e5242ec01608c594373cde0。在这个修改中,我把这个例子的过时接口都换成了新的,并且编译OK了,然后待用。
  3. 最后,我看到了雷前辈的例子,从这个例子可以看出,我根本不用考虑如何与RTMPDUMP建立数据连接,只要对例子改一下输出方式,就可以直接推流啦。

至此,第一板斧砍完。

上位机demo

这个阶段就三步,先验证例子的有效性,再验证改造的例子的推流功能的有效性,最后用GO语言调用测试。
第一步很顺利,没有单独提交。
第二步,即C语言部分的提交是f51f070eeb2b3a0a7827519d58d6a3c27bb7ce23,可以看到修改很简单,如果真去嫁接RTMPDUMP,工作量得比这个大得多得多得多。。。
第三步,加入GO语言部分的提交是cf0d3e304a5a824c6912a8e3b2b13975c990e8c8,其中的demo_ffmpeg.c是基于test.c修改的,主要是把生产raw data的函数改成了call back,这样就可以在GO语言里实现raw data的生成,至少从C部分来看,整个流程就和最后实际的使用方式完全一样了。而对于GO语言部分,后面再把生产raw data的方法改成从摄像头和话筒获取就行了,当然这是后话了。

至此,第二板斧砍完。

移植到下位机

移植也是之前的套路,先编译C依赖库,然后GO程序与mind SDK对接。

ffmpeg的交叉编译

这里先感谢某位哥们儿的帮助,把他以一般Ubuntu为目标平台的编译方法提供给我做参考。
可惜的是,后面还是有东西要探索,最关键的就是交叉编译所带来的麻烦,最后的configure命令长这样:

./configure --prefix="/go/src/skill/FFmpeg" \
--extra-cflags="-I/go/src/skill/FFmpeg/include" \
--extra-ldflags="-L/go/src/skill/FFmpeg/lib" \
--bindir="/go/src/skill/FFmpeg/bin" \
--enable-cross-compile \
--cross-prefix=arm-linux-gnueabihf- \
--cc=arm-linux-gnueabihf-gcc \
--disable-x86asm --arch=armv4 --target-os=linux \
--disable-static --enable-shared \
--disable-ffmpeg --disable-ffplay --disable-ffprobe
make
make install
  • 带有cross字样的都与交叉编译有关,还有cc指定了交叉编译器
  • 要生成动态库,--enable-shared是要加的,我不需要静态库就加了--disable-static
  • -disable-ffmpeg -disable-ffprobe -disable-ffplay是说不需要生成这些可执行程序,因为我只需要依赖库

相对于对接mind SDK,编译ffmpeg还是麻烦一点,以为它的编译选项比较复杂,有些选项好不好用、该不该用,都变成了很随缘的事情,这些选项也是我慢慢摸索出来的。

GO程序对接mind SDK

关于对接mind SDK,修改是ca44359aebc9d2729cd9213f6c126a9be1722c34,虽然文件多,但是并不复杂。

  • 增加ffmpeg的头文件(DanmuDriveMe/robot/deps/include下面多个文件)
  • 增加ffmpeg的库文件(DanmuDriveMe/robot/deps/lib下面多个文件)
  • 删除RTMPDUMP相关的文件,包括头文件、库文件和GO文件
  • ffmpeg demo对接mind SDK,这些是核心修改,只有5个文件

逻辑和上位机demo大同小异,关于对接mind SDK不做详细解释了,只说一个GO与C混合编程的小坑,一个坑了我若干小时的小坑,具体看下面注释吧。

func stream_start(url string) {
    //这个cc是C语言部分的buffer
    cc := C.CString(url)
    //defer是说在即将退出这个函数时执行后面语句,即在退出stream_start函数之前会把cc free掉
    defer C.free(unsafe.Pointer(cc))
    if stream_control(true) {
        log.Debug.Println("url:["+url+"]")
        //setup是C函数,里面会使用cc
        go C.setup(cc)
        //go语句是非阻塞的,如果没有这个sleep,stream_start函数就会很快返回,这意味着cc很快会free
        // avoid to free cc too early
        time.Sleep(time.Second)
    }
}

要注意上面代码中的2件事的顺序,即cc的释放和使用的顺序,我被坑的原因就是,cc先被释放了,然后才被使用,并且我还不知道怎么才能看到C部分的log,对C部分的debug手段很笨拙,所以花很长时间才怀疑到这。
cc被释放的原因是stream_start函数很快返回了,那么基于defer语句的机制,cc就很快被释放了,而go语句是非阻塞的,从cc传入setup到被使用,需要一段时间,所以函数最后要加一个sleep,保证在这段时间内,函数不会返回,cc也就不会在使用前被释放。
当然,还应该有其他解决方法,比如不在GO这边释放cc,在C部分释放也许也能行。

至此,第三板斧砍完。

总结

  • ffmpeg替代了RTMPDUMP,一步到位地完成了压缩编码和推流
  • 下位机推流还有点问题,可以在播放端看到,似乎是推流的速度不够,出现了视频网站那种放一会儿就要缓冲一下的现象,具体原因有待分析
  • 下面计划是对机器人采集的音视频raw data进行推流,以及用OpenCV处理图像
  • 这些事情的草还没发芽,包括弹幕命令集、机器人命名等

下一篇 HEXA娱乐开发日志技术点005——死而复生之Gstreamer推流

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容