您当前位置: 首页 »

音视频_图像相关

分类目录归档: 音视频_图像相关

实践正当时(二)

继上次的更新 实践正当时(一)

上次的版本已经支持了:

1. 支持264
2. 简单解析nalu
3. 解码出码流
4. 拿到运动适量
5. mv ui绘制(用了ffmpeg的codecview来绘制运动适量)

这次新增有:

  1. 当前帧poc
  2. decode/disp顺序计算(在外部进行计算的,实际上可以通过vui里面的信息来计算,还没开始完全看decoder的代码,对vui也不熟悉,所以暂时实现功能先)
  3. 增加fp/bp的mv显示功能
  4. 基本播放、调试功能
  5. 能够获取当前预览帧中的具体某个16*16快的mv信息并显示出来(mv方向、位置信息)
  6. 块信息:块类型(例如,intra 8*8 L0L1),delta_qp
  7. 帧信息:avg_qp, delta_qp(这个应该还有问题,一直都是-2,看上去是从pps获取的估计哪里不对,需要继续了解一下vui语法和解码器内部*)

下一个版本准备新增:

  1. slice_type(一个硬骨头,其他参数获取会更麻烦点,因为需要看明白代码,parser组帧完成后就需要关联到picture上)
  2. 修改codecview filter,增加16*16 block绘制
  3. vui信息获取
  4. 参考信息关联(也是个硬骨头,比slice_type麻烦些*)

未来需求:

  1. 性能优化(优先级最低,除非出现不可忍受的情况)
  2. 残差图
  3. 频域图
  4. 支持265
  5. 自动化诊断码流问题(等其他功能差不多再说,这个需要大量实践经验,还需要了解vui)

实践正当时(一)

之前给自己定过一个3年左右的计划,原因很简单,不管什么上天还是入地的公司,对我来说无非就是一个打工的地方而已;随时也要做好被公司用完就丢的准备。

既然到了所谓就业歧视年龄线,那就应该拿出一定的所谓能力来,不是技术上有一些自己可以落地的时间,就是管理上有很强的的软实力。

目前来说,进入管理通道之前,该有的技术实践还是需要跟上,后续想走资源受限场景下的卡顿、画质方向的优化,所以对网络和编解码相关有一个感性到浅层的了解时必须的。

为了了解编解码,为了不受到一些所谓的技术专家和算法专家的歧视,业余时间自己倒腾一个码流分析工具,同时也是为了自己可以用。

目前是ffmpeg + duilib来做的,首先我想当排斥做界面,一方面我自己不感兴趣,另一方面这东西要做深门槛很高,奈何这玩意入门门槛太低,庄家太多受不了这种乌烟瘴气的环境。

用ffmpeg来做码流处理,主要是因为解码器开源,可以看到代码也能试着去按照自己的需求改,另一个确实什么更快又更好的选择。

目前完成的功能有:

  1. 支持264
  2. 简单解析nalu
  3. 解码出码流
  4. 拿到运动适量
  5. fuck ui绘制(用了ffmpeg的codecview来绘制运动适量)

接下来要做的功能:

  1. 拿到qp
  2. 拿到参考信息,帧级,块级
  3. vui信息解析

后续需要完成的功能:

  1. 性能优化(优先级最低,除非出现不可忍受的情况)
  2. 残差图
  3. 频域图
  4. 支持265
  5. 自动化诊断码流(等其他功能差不多再说,这个需要大量实践经验,还需要了解vui)

ffmpeg + vs2017 编译(持续更新)

前言

2022的计划,就是开始做个小工具,拿来分析es流,主要通过解码器解码es流,来获取编码中一些过程,比如预测方向,slice qp等等。当然也包括最基本的parser,虽然这块会有很多bug(只要是字节流相关的代码都很容易出现解析和打包问题)

所以现在最先需要解决的是ffmpeg的编译,然后再找一个稳定简易的界面库来先基本完成264的码流解析和解码工作。

脚手架选择

windows terminal

msys2

vs 2017

安装

略过

编译

配置

windows terminal

msys2

这里需要说明的是,msys2现在支持ucrt和mingw64两种链接方式,区别在于前者使用系统自带的crt链接到编译出来的库中,后者使用msvs的。目前还是继续使用mingw64的版本

#先更新一下
pacman -Syu

#库管理工具
pacman -S pkgconf diffutils


pacman -S make

#sdl2必须品
pacman -S mingw-w64-x86_64-nasm mingw-w64-x86_64-gcc mingw-w64-x86_64-toolchain

vs 2017

其他

关于ffplay的编译

由于msys2自带的sdl2包和本地vs编译环境可能存在一些不兼容的情况,所以有两种办法。所以需要单独下载sdl2编译后,再创建ffplay的vs工程来做。

2022-01-08 | | 爱捣腾的小玩具, 码流学习, 编码技巧, 音视频_图像相关, 音视频编解码

ffmpeg + vs2017 编译(持续更新)已关闭评论

2022计划定一下

虽然我一直都是将自身技能分为软技能和硬技能,并且按照一定规则来进行计划,不过还是有必要重新考虑一下侧重点,这么几年下年,折腾来折腾去,东搞搞西弄弄,一直没有很好的执行一个系统性或者专业化的自身知识技能体系。但维度有一点很明确的是,自身工作方向一定要和自己的目标知识建设是存在较大关联或重合的,这方面做的还是不错,所以大部分时间都没有跑题跑的太偏了。

硬技能

  • 学历、院校、就职单位
    • 可遇不可求,有些事情已经定型了不行了。
  • 性格
    • 江山难改本性难移,只能说尽量保持克制和改善。不忘初心也很重要
  • 为人处世
    • 最讨厌乌烟瘴气、帮派和小圈子,除非有必要,小圈子是一个不错的选择,但是小圈子很容易会和前两者有很强的关联性。还是需要一定程度上的假装合群
    • 站队,不站队远比站队还严重。一直以来都不站队,或者抗拒站队,在一个比较强调控制的团队或组织里面,很容易被弄,最后过得也很惨,不过也从侧面反映了,这种团队和组织没必要长待,长久不了;事实却是证明了,不管多少年过去,这种组织或机构要么都死掉了,要么勉强维持着现状。
    • 有时候少一点有意而为,很多时候明知道这样做的结果会如何。但自己偏偏不信邪,并且带着好奇心的故意做一些事情,反过来观察大家的反应,尽管确实很有效果,也相对客观准确的能观察到信息,但实际上不太理想,容易变成掘地自焚。
  • 管理 & 洞察
    • 尽管不喜欢也不想做管理岗位,也不愿意去做。主要还是不愿意和人打交道,不想去搞那些麻烦的人和事,也不想承当责任。
    • 但事与愿违,年纪上去了,就该适当的考虑扩宽自身的路子。所以管理岗的一些同事,他们的行为风格是一个较好的学习习惯,和观察机会。透过他们可以间接学习一些成与败的经验。
    • 从小到大洞察能力是不需要做任何评价的,这一个点是先天有优势,但还需要注意一下,不能让自身主观兴趣过多的去主导洞察的目标和信息的获取。先收集信息,后整理和分类。然后适当的对洞察结果做出相应,稳优先,切莫太急躁,因为现在认为干扰信息也挺多的。

软技能

  • 知识深度
    • 这里需要明确,这里提到的知识深度不同于公司层面,因为公司层面更多是通过所谓的知识深度来淘汰人的一个借口罢了。
    • 这里更多是结合现阶段自身岗位情况,和未来目标可达岗位情况去指定的知识深度学习计划
      • 编解码
        • 目标:<了解>编码原理,能够通过码流的一些现象来判断大致的问题
        • 知识范围(粗略,待二次细化):
          • <了解> x264预处理过程
          • <了解> x264图像分割的过程(预测、宏块划分)
          • <了解> x264熵编码特点(非了解算法内部)
          • <选择了解> x264 码控等相关模块
        • check point(2-3年完成):
          • 产出工具或matlab脚本,演示预处理过程
          • 产出工具,可视化预测、宏块信息(先帧内,后帧间)
  • 知识广度
    • 这里需要明确,这里提到的知识深度不同于公司层面,因为公司层面更多是通过所谓的知识广度来淘汰人的一个借口罢了。
    • 这里更多是结合现阶段自身岗位情况,和未来目标可达岗位情况去指定的知识广度学习计划
      • 策略器
      • 目标:搞清楚现有的一些策略器,对媒体“流畅”和“质量”的影响有哪些,如何做到的。
      • 知识范围:
        • <了解> 采集 <-> 前处理 策略通路
        • <了解> 前处理 <-> 编码 策略通路
        • <了解> 编码 <-> 编码 策略通路
        • <了解> 编码 <-> 网络 策略通路
        • <了解> 总控 <-> 各子控 策略通路
      • check point(1-2年把大致流程搞清楚):
        • 产出详细图(正在做)

留意几类人

  • 没自知之明,自以为是;关系不便搞僵,不过距离要保持住
  • 自私的人,这些人靠利益维系
  • 小圈子,小帮派。凡是”小“这个东西就很成问题
  • 虚的人
  • 看似很好打交道,其实很难的人

【英伟达】nvenc/nvdec/sm关系猜测

因为不是做cuda相关开发,临时被拿来做调试一些相关代码。看到官方的一些介绍并不是很清晰,并没有完全说明cuda计算单元和nvenc/nvdec关系。仅仅提到nvenc和nvdec是两个编解码引擎。

并且还对特定显卡做了nvdec和nvenc的限制,对于一些老卡上,并没有nvdec和nvenc引擎。

官方给出的定义是nvdec、nvenc是独立于cuda核心,并不是很理解。或许nvdec和nvenc是相对于cuda核心的单纯的计算功能而划分出来给视频编解码使用的一个特定模块。

上网查了一下,以前的GPU加速编解码,实际上是利用cuda计算单元做一些数学计算,加快编解码速度。而nvenc和nvdec可以直接未编码数据或已编码数据进行处理。

那么这里就很好奇了,nvenc是一个单独的物理模块,还是一个逻辑模块。

通过对比实验发现还是稍有区别:

  • 第一个实验,仅使用nvdec、nvenc,以及ffmpeg的混流滤镜。得到的数据如下:
  • 第二个实验,通过外部加载一个推理模型。将解码好的数据丢给推理模型进行推理后,再返回解码,所有的过程均在显存中进行。

通过nvidia-smi dmon,可以发现除了流处理使用率有所增长,在程序初始化初期,从数据是上来看,可以推测nvenc和nvdec实际上还是利用到了部分流处理器,至于把这些流处理器拿来做什么就不得而知,也许只是作为解码初始化的一些树的加速计算,也许仅仅是被划分到nvenc、nvdec中参与编解码工作。

后续还需要一些相应深入和系统性的了解才好做判断。

2020-10-27 | | GPU相关, unix编程环境学习, 音视频_图像相关, 音视频编解码

【英伟达】nvenc/nvdec/sm关系猜测已关闭评论

编译freeswitch踩的那点坑

由于虚拟机里面装了ubunutu 18,本来想直接装freeswitch的deb报,进行方案快速验证和freeswitch学习。结果,按照官方的步骤去执行,发现源有问题。

接着就进入了苦逼的编译过程,说实话,对freeswitch的官方文档表示迷惑,不是很习惯文档中描述的内容跳来跳去的样子。后来找来找去,就零零散散的参考按照了以下几个文档进行下去,基本采取默认配置,并没有作为其他配置修改

https://freeswitch.org/confluence/display/FREESWITCH/Installation
https://freeswitch.org/confluence/display/FREESWITCH/Ubuntu#Ubuntu-InstallfromRepo
https://freeswitch.org/confluence/display/FREESWITCH/Linux+Quick+Install+Guide#LinuxQuickInstallGuide-GenerateInstallationandConfigurationFiles

首先先说一下步骤:

安装依赖

apt-get install git-core subversion build-essential autoconf automake libtool libncurses5 libncurses5-dev make libjpeg-dev liblua5.3-dev

apt-get install libcurl4-openssl-dev libexpat1-dev libopus-dev libgnutls-dev libtiff4-dev libx11-dev unixodbc-dev libssl-dev python2.6-dev zlib1g-dev libzrtpcpp-dev libasound2-dev libogg-dev libvorbis-dev libperl-dev libgdbm-dev libdb-dev python-dev uuid-dev libpq-dev libsndfile-dev

sudo apt-get install gawk

update-alternatives --set awk /usr/bin/gawk

下载freeswitch代码

FSfile=$(curl -s https://files.freeswitch.org/releases/freeswitch/ | grep -oE “freeswitch-[0-9].[0-9].[0-9]*.-release.tar.bz2″ | tail -n 1) && echo Downloading $FSfile && curl https://files.freeswitch.org/freeswitch-releases/$FSfile | tar -xj && mv ${FSfile/.tar.bz2//} freeswitch

编译x264

这是为了启动mod_av模块的时候,而进行的准备工作,以下命令行为:

./configure --enable-static --prefix=/usr --enable-pic

 make ; make install 

编译ffmpeg

如果不编译ffmpeg,或不安装libavformat-dev就进行执行./configure,又刚好开启了freeswitchmod_av,那就会出现You must install libavformat-dev to build mod_av. Stop错误。

在网上查一同,会发现需要编译libav,事实上却被大坑了一把。这主要还是由于ffmpeg与libav的关系有关。

libav是从ffmpeg拉出的一个分支,网上对libav说法很多,又说libav是从早期版本拉出来,也有说后来libav已经和ffmpeg的master保持同步等等。

但真实去编译的时候,发现了一个巨坑,也就是freeswitch报错AVFormatContext中不存在url成员。到ffmpeg和libav官网上一查。发现最新版本的libav确实没有这个变量,而ffmpeg 4.x的文档里有。果断改成编译ffmpeg。

另外还要喷一下libav的官方文档,各种详细说明藏的非常深。。。

下好ffmpeg 4.x的源代码后,开始编译

./configure --enable-shared --enable-gpl  --enable-libx264 --enable-pic

make &amp;&amp; make install

编译libk

 git clone https://github.com/signalwire/libks.git  

 cd libk  

 cmake . 

 make ; make install 

编译signalwire-c

git clone https://github.com/signalwire/signalwire-c.git

 cd signalwire-c 

 cmake . 

 make ; make install 

mod_lua编译不过

尽管安装了lua的开发库,但还是会出现找不到lua头文件的情况,找到

/src/mod/languages/mod_lua/Makefile

并找到如下行

DEFAULT_INCLUDES = -I. -I$(top_builddir)/src/include -I$(top_builddir)/libs/esl/src/include -I$(top_builddir)/libs/xmlrpc-c

修改成

 DEFAULT_INCLUDES = -I. -I$(top_builddir)/src/include -I$(top_builddir)/libs/esl/src/include -I$(top_builddir)/libs/xmlrpc-c -I/usr/include/lua5.3 

并到/usr/lib/x86_64-linux-gnu下

对liblua.so做个软连,即

ln -sf liblua5.3.so liblua.so

出现implicit declaration of function ‘ks_json_get_object_cstr’; did you mean ‘ks_json_get_object

由于版本不一致引起的,freeswitch、signalwire-c和libks版本不要一致,需要换版本。由于我用的freeswitch是1.10版,所以直接用9月份附近的这两个库就没问题了。

切换libks与signalwire-c版本后cmake不过的问题

直接从github上下载release的1.3.0版本,出现了cmake不过的情况:

— cotire 1.7.10 loaded.
Platform is linux
Build type: Debug CXX Flags:
Install prefix: /usr
LibKS Version 1.3
CMake Error at CMakeLists.txt:291 (string):
string sub-command REPLACE requires at least four arguments.
Found UUID setup target at imported location: /usr/lib/x86_64-linux-gnu/libuuid.so

看了一下cmake的配置文件,报错的位置主要是为了生成一个changlog文本,直接注释掉这行即可

#string(REPLACE "\"" "" CHANGELOG ${CHANGELOG})

阿斯顿

注意点

由于configure在执行的时候,会检查大部分依赖是否存在,但仅对关键依赖进行报错,且输出的检查内容太多以至于没有那么多耐心去看。

因此在出现configure不报错,make期间有某个mod编译失败的话,那就必须要用排错后,再次执行configure在进行make,反正就是各种复杂和扯淡。

编译完成后的运行

由于freeswitch会加载相应的mod,还有配置文件,所以需要执行一下make isntall;假设在configure阶段没有指定具体的prefix,就会默认安装到/urs/local/下。如果不需要这样,可以明确指定perfix位置。

运行freeswitch,执行 ./freeswitch即可

2020-01-20 | | VOIP, 音视频_图像相关

编译freeswitch踩的那点坑已关闭评论

srs-bench代码整理及理解

废话不多说,直接上图,以下是对srs-bench主要模块的一个梳理:

srs-bench支持对srs进行压测,其支持的范围有:

rtmp推流

rtmp拉流

hls拉流

http请求

hls拉流:

hls的拉流是,先产生一个http请求并拉去m3u8文件,解析后并顺序请求ts文件,当请求完毕后,下载任务挂起,一般挂起时长为当前模拟播放的ts文件的duration大小。

等挂起被唤醒后,再次请求m3u8文件,并更新未下载的ts文件列表后,开始请求ts文件。若本次更新的m3u8没有发生变化,那么将进行再次挂起,挂起时长不大于当前模拟播放的ts的duration。

http请求:

首先对某个url进行请求,请求之后将会产生挂起,挂起时长主要有进程启动时的入参决定。

rtmp推流:

rtmp推流进程启动时,首先会和srs在rtmp协议上进行协商,协商完成后,会读取入参时指定的flv文件。并按照当前flv tag和下一个flv tag的时间差挂起数据发送任务。

但这里需要注意的是,如果rtmp推流的压测里指定了2个以上的并发,但又由于srs-bench只支持一个flv文件输入,那么文件打开的次数会很多次,并且读取的flv数据在协程中未共享的,因此在该测试中,这一块可以改经一下,毕竟单线程的任务来说,不存在加锁问题,因此也就可以考虑是否做到一次性将数据读到内存里,所有协程共享数据发送;以此来提高测试程序的执行效率。

毕竟协程在io上不是强项。

rtmp拉流(非fast):

对于非fast的rtmp拉流,其整个协议过程是完整的rtmp client。只不过对拉下来的流不做解码等处理,仅仅是针对协议上做一些校验和处理而已。

rtmp拉流(fast):

类似非fast的流程来说,只是收到的数据不再做rtmp协议的校验了。

2019-12-12 | | SRS, 音视频_图像相关

srs-bench代码整理及理解已关闭评论

Why We Created SRT and the Difference Between SRT and UDT

Article Form :
https://www.haivision.com/blog/broadcast-video/created-srt-difference-srt-udt/

Editor’s Note: This post originally appeared on the GitHub Wiki for SRT. It has been slightly modified for formatting. 

Some people have asked us why we’re using the UDT library within our SRT protocol. Actually, some people claimed that SRT is just a slightly modified version of UDT and that UDT is known to be useless for live video transmission. Guess what, the latter is true. UDT has been designed for high throughput file transmission over public networks. However, SRT is far from being a slightly modified version of UDT. I’ll get into the details, but will start with a little bit of history.

Haivision has always been known for lowest latency video transmission across IP based networks — typically MPEG-TS unicast or multicast streams over the UDP protocol. This solution is perfect for protected networks and if packet lossbecame a problem, enabling forward error correction (FEC) fixed it. At some point we were getting questioned as to whether it would be possible to achieve the same latency between customer sites in different locations, between different cities, countries or even continents.

Of course it’s possible with satellite links or dedicated MPLS networks, but those are quite expensive solutions, so people wanted to use their public internet connectivity instead. While it’s possible to go with FEC in some cases, that’s not a reliable solution, as the amount of recoverable packet loss is limited, unless you accept a significant amount of bandwidth overhead.

After evaluating the pros and cons of different third party solutions, we found that none satisfied all our requirements. The lack of insight into the underlying technology drove us to the the decision to develop our own solution, which we then could deeply integrate into products. That way, it would become the “glue” that enables us to transmit streams between all our different products, locally or across far distances, while maintaining our low latency proposition.

There were a few of possible choices to consider:

  • The TCP based approach. Problem for live streaming: Network congestion, too slow packet loss recovery.
  • The UDP based Approach. General problem: Packet lossjitter, packet re-ordering, delay
  • Reliable UDP. Adds framing and selective retransmit.

Having had a history with UDT for data transmission, I remembered its packet loss recovery abilities and just started playing with it. Though not designed for live streaming at all, it kind of worked when using really big buffers. I handed it over to one of our extremely talented networking guys in the embedded software team (thanks, Jean!) and asked him whether he’d be able to make this a low latency live streaming solution. I didn’t hear anything back for quite a while and had almost lost my hope, when he contacted me to tell me he had to rewrite the whole packet retransmissionfunctionality in order to be able to react to packet loss immediately when it happens and that he added an encryption protocol, which he had specified and implemented for other use cases before. Nice 🙂

We started testing sending low latency live streams back and forth between Germany and Montreal and it worked! However, we didn’t get the latency down to a level we had hoped to achieve. The problem we faced turned out to be timing related (as it often is in media).

Bad Signal

What happened was this: 

The characteristics of the original stream on the source network got completely changed by the transmission over the public internet. The reasons are delay, jitterpacket loss and its recovery on the dirty network. The signal on the receiver side had completely different characteristics, which led to problems with decoding, as the audio and video decoders didn’t get the packets at the expected times. This can be handled by buffering, but that’s not what you want in low latency setups.

The solution was to come up with a mechanism that recreates the signal characteristics on the receiver side. That way we were able to dramatically reduce the buffering. This functionality is part of the SRT protocol itself, so once the data comes out of the SRT protocol on the receiver side, the stream characteristics have been properly recovered.

The result is a happy decoder: 

Good Signal

We publicly showed SRT (Secure Reliable Transport) for the first time at IBC 2013, where we were the only ones to show an HEVC encoded live stream, camera to glass, from a hotel suite outside the exhibition directly onto the show floor, using the network provided by the RAI. Everybody who has been at a show like this knows how bad these networks can get. And the network was bad. So bad that we expected the whole demo to fall apart, having pulled the first trial version of SRT directly from the labs. The excitement was huge, when we realized that the transmission still worked fine!

Since then, we added SRT to all our products, enabling us to send high quality, low latency video from and to any endpoint, including our mobile applications. Of course there were improvements to be made and the protocol matured on the way. Until NAB 2017, where we announced that SRT is now Open Source.

You can learn more about SRT at the SRT Alliance website here.

To view the SRT on GitHub and start contributing to this open-source movement, click here!

2019-06-10 | | udt, 网络协议, 音视频_图像相关

Why We Created SRT and the Difference Between SRT and UDT已关闭评论

【webrtc、gclient】cpid更新失败代理新的配置方案

首先按照原先的配置方案如下:

1. 设置http_proxy和https_proxy环境变量

2. 设置winhttp代理

3. 配置git代理

但在执行gclient自身更新时,总是发现cipd更新失败。简单跟踪了一下cpid,发现cpid的更新有两种,第一种是cpid自身自动更新,另一种是通过执行bootstrap来更新cpid。
cpid是使用go写的,虽然网上一堆教程说配置了http_proxy之后就可以等等,但这其中cpid存在一个问题,即在进行https请求时,会对证书做校验,若https_proxy配置的代理是一个https真实代理服务器,那么cpid做校验时会失败,具体未看代码,估计webdav执行过程中需要用到https中的证书做登录校验。

至于对cipd的更新处理方式为:

因此将https_proxy有意配置成http服务器,即可破。这会让cipd自更新时强制通过ensure方式进行更新

同时在其他一些脚本执行时,似乎用到了类似原先的csript,因此最好在ie代理时也配上相应的代理服务器地址。这样就可以正常更新gclient了。

2019-01-15 | | shell, windows-shell, 音视频_图像相关

【webrtc、gclient】cpid更新失败代理新的配置方案已关闭评论

【ios、x264】将静态库打包成动态库,链接时的text relocations错误

最近在ios上出现将多个sdk放到一个app时,有各种开源静态库冲突的问题;于是考虑将自己用到的库进行打包成动态库版本,以此解决冲突问题。

在进行打包成动态库时,发现x264问题最大。打包出来的库在链接期出现text relocations错误,网上找了以后发现基本都是进行忽略这个错误,事实上这个错误忽略了没用,app启动时还是会出现相应的crash。

换了几个版本的xcode进行测试,发现x264编译会出现不同情况的告警和错误,根据底部罗列的参考文章,估计xcode的编译器可能也有一些bug。

后来模仿android上的编译方式,在x264里加入了–enable-pic和–disable-asm顺利编译通过,但由于osx和xcode版本的因素,模拟器上的并没有编译出来,仅仅编译了armv7和arm64。

 

参考文章:

MacOSX下编译linphone(text-relocation错误说明)

libxxx.so- text relocations问题的终极解决方案(android)

Linker error when using incremental builds on iPhone

Android Gradle编译so库或运行时出现 text relocations 崩溃的正确解决方法

2018-06-15 | | [linux总结], unix编程环境学习, 编码技巧, 音视频_图像相关, 音视频编解码

【ios、x264】将静态库打包成动态库,链接时的text relocations错误已关闭评论

【h264、baseline、flv】使用baseline做双向强交互直播不利的几点因素

再说baseline做强交互不利因素之前,先说说现在直播的场景情况。

 

场景如上图,推流段不是移动平台,就是PC机。当然最近几年也出现专门用来推流的定制盒子,本质不是一个嵌入式windows,就是一个android设备(android设备较多)。

  • 而对于PC机作为推流端来说其实问题并不大,只要在保证带宽足够理想的情况下,采用264的任何一种profile都能尽可能的做到最大延时接近编码器固有延时的效果。同样对于使用何种容器来说问题都不大。

 

  • 但对于移动设备来说,需要匹配的情景就很多了,主要是由于移动设备的电池续航能力、操作系统小类别太多、整体性能表现。在使用264编解码时,一般尽量采用硬编解码,对于实在没有办法的情况下才使用软编解码。就仅仅一个硬编解码上就存在诸多差异,例如有些profile硬件不支持,或者rom上存在一些问题导致本该支持的profile,支持的不好或者根本不支持。

 

  • 除了上述提到的问题以外,其实还有一个隐形问题,那就是用户使用习惯问题。现在的用户越来越偏向于使用web方式展现的产品,一方面对于开发者来说,界面改动较为简单灵活,另一方面对于用户来说,只需要打开浏览器即可,简化使用步骤。

然而上述提到的这些问题,就造就了可能大家会想到flash、h5和native应用,对于native应用来说还好,开发起来虽然周期长,但可塑性比较强。对于flash和h5来说可选择余地就非常小了。

暂时不说flash和h5本身在做双向强交互直播是否可行,先说一说两者采用的协议类型。对于flash来说:

  • 通讯协议为rtmp系列协议(包括rtmpt等),协议本身并不是太复杂,但涉及当初并不是用来做双向强交互的直播协议,因此协议本身就没有在双向强交互上做太多的考虑。

 

  • 由于协议本身所承载的流媒体容器格式为flv或f4v,现在大部分直播平台基本采用的是flv作为容器,同时flv也是一种较为简单易用的容器

 

  • 但由于flv容器格式的限制,在adobe官方手册中就已经说明,flv容器支持的264的profile范围中,目前仅对baseline、extended、main、high、high10、high4:2:2、high4:4:4,在经过简单测试之后,如果不考虑flash端推流的情况下,用户电脑(移动端一般用h5,不用flash)性能具备一定保证的情况下,再根据官方手册并测试(as3手册),没有实际去测试过high10,不过脑补得知high10也是可以的,但延时太大,也有可能会引起其他flash异常。因此往往最佳的选择就在baseline、main、high中选择,因为他们的颜色编码是8bit的。从解码效率和广泛性来说,这三种都可以。

 

  • 但由于是双向直播,因此,在这时就需要考虑编解码器的时延问题。这时,大家一贯的做法就是关闭B帧编码,这样即可极大的提高编解码延时。当关闭了B帧编码之后,剩下几种profile互相比拼的就是在给定的一个平均分辨率、gop的情况下,编解码固有时延和数据码率,以及支持的广泛性。实测之后发现high其实在不同浏览器的flash上表现存在一定差异,主要情形为编解码速度、性能开销等等。因此在flash上使用high这种方式时,还需要综合考虑。

 

接下来说一说h5方式的直播:

  • h5方式的直播一般是通过websocket进行通讯,协议是hls,容器格式为ts、ps。然而我对hls和ts、ps都不是很了解。

 

  • h5支持还有待进一步推广,目前在较新的chrome系浏览器和较新的firefox浏览器上均支持较好。IE系暂时较弱(我把edge理解成IE系)。

 

  • 就目前来说,从开发手机端开发难度,和各手机厂商的支持力度上,无论是webview app还是native app来说,hls+ps/ts也是较优选择。

 

  • 通过看了苹果官方的FAQ得知,hls协议似乎仅仅支持baseline、main、high三种,不清楚是由于ts、ps容器特性导致的,还是hls协议特点。因此在决定使用哪一种profile时,又回到了和flash一样的情况下。

 

通过以上可以得知,实际上在使用x264编码时,最终在profile的选择上基本就限制在了baseline、main、high三种。从算法复杂度上来上讲,baseline是最为简单,而high是较为最为复杂(主要是预测模型比前两者多不少)。

不过在实际工程应用中,我们还是做了一个比较脑残又没有办法的决定,那就是使用baseline。原因有二:

  1. 我们使用的编码库是openh264,早期版本的openh264宏块分割方式较小,也仅仅支持baseline,对main也只是仅限于试验阶段。
  2. 在同样的profile级别下,参数大致相同的情况下,openh264的编码时延比x264的utral模式下略高,但码率略低(未做定量测试,简单定性测试得到的结论)。编码完的数据解码出来的视觉感受差别不大,反正都是渣画质。

考虑到使用场景和当时网络的大环境,确实选择openh264,即是无奈的选择,也是一个极其脑残的选择。说无奈主要是现实,说脑残是因为压根就没有做过定性分析。。。。。。

然后接下来就开始“数落数落”baseline不适合做双向强交互直播的原因。在看x264的代码时,偶然对编码中的预测做了少许的了解。

—- 我是装逼的分割线 1号 —-

传统上对一副图像的处理,一般的理论是基于“分割”,由于图像一般情况下具有前景和后景之分,也就是说,前景和背景之间存在着大量的局部图像细节,对于图像压缩中的思路往往是,尽量将相似的区域用差别不大的统一一个区域去表达,对于差异较大的区域,尽量在用较多的数据量去存储以此保留图像的局部细节。

那么就会存在如何分割图像的问题。如果是一副简单单值图,例如大学时代我做的非矢量图压缩(理论基础差不多),那么只需要根据图像分辨率,做相应的最佳分割快大小计算,并做简单切割即可。将区域内的有色的点和无色的点进行记录,并按做纵向或横向切割成色带,记录色带中有色点或者无色点的坐标值即可。整个思路转换成代码思维,类似于多级联映射表。当然这个做法的关键还在于公式如何设计,即如何动态计算切割区域的大小。由于是做印章方面,所以图像不会太大,因此公式也非常简单。

最终压缩可以理解成单值图的无损压缩,实测试之后,和转换成矢量图之后的文件大小相比,应该两者都会比现在主流的大部分图像编码小非常多。

接着通过类似7z、rar工具里面的二进制压缩算法进行再次压缩,文件最大还能缩小60%左右。一个500k的位图最终生成文件在3k左右。

—- 我是装逼的分割线 2号 —-

由于有上面的实践基础,因此在理解264的压缩时,我也能够理解到“分割”时的重要性。

首先,在baseline模式下,x264的预测模型相对于其他high来说,非常简单。这样的情况就决定了,在局部的细节切块相比high来说有着很多不足,对二进制数据进行压缩前就已经输在起跑线了。即细节丢失比high多。

其次在编码算法上(或者说压缩算法上),baseline仅仅使用cavlc,而对其他两者来说他们既可以使用cavlc也可以使用cabac。没有做过定性或者定考量分析,但通过网上资料获知,cavlc的效率似乎没有cabac高,具体在哪些指标有所体现目前暂时并不清楚。

因此,可以得知。baseline除了在实时性上满足了双向强交互直播对时间的要求,对于相同质量下的压缩比并不是很好。但又由于baseline相对其他profile的简单特点,其实广泛性还是比较不错的。

手里有台android 2.3时代的三星手机,对baseline的视频进行解码,手机基本可以应付(不清楚是硬解还是软解,因为当时的arm好像还有没有对264硬解做太多优化),但相同视频长度的main和high的话,那就有点头疼了。看来baseline对老旧手机还是比较“良好”的。

2017-11-22 | | matlab, 数据结构 & 算法, 音视频_图像相关, 音视频编解码

【h264、baseline、flv】使用baseline做双向强交互直播不利的几点因素已关闭评论

【x264、宏块、邻居】x264中对宏块预测方向与邻居类型的定义

在x264中,由于单一宏块预测方向与264规范定义实际上是一直的,即预测方向只有:左(left)、上(top)、左上(left-top)、右上(right-top)。

没有其他的另外四个方向,估计可能是zig-zag的数据排列有关,或只是由于对称关系,不需要做重复预测。

有上述4中预测方向,x264中定义了几种邻居关系(下面拿I帧4×4的宏块距离说明):

  • 垂直方向,即I_PRED_4x4_V、I_PRED_4x4_DC_TOP,实际上是向上方向预测(top)
  • 水平方向,即I_PRED_4x4_H、I_PRED_4x4_HU、I_PRED_4x4_DC_LEFT,实际上是向左方向预测(left)
  • 左边和向上方向,即I_PRED_4x4_DC
  • 向上旋转到右上方向,即I_PRED_4x4_DDL、I_PRED_4x4_VL
  • 左边旋转到向上方向,即I_PRED_4x4_DDR、I_PRED_4x4_VR、I_PRED_4x4_HD
  • 左边旋转到向上方向,即I_PRED_4x4_VL
  • I_PRED_4x4_DC_128代表自身?
2017-11-21 | | 数据结构 & 算法, 音视频_图像相关, 音视频编解码

【x264、宏块、邻居】x264中对宏块预测方向与邻居类型的定义已关闭评论

【x264、视频、编码、宏块】编码成不同帧时,宏块参数的变化情况

出于好奇最近在看x264的源代码。

对于不管是263、264还265编码来说,图像的压缩大题思路实际上是没有太大变化的。

对图像的压缩和编码,分为相关和非相关部分。又由于263、264、265并没有定义一定是无损压缩,所以在压缩和编码上与音频的编码和压缩也有着相似的处理方式;即,按照人的视觉特性进行编码(人眼分辨画面细节的能力是有限的)。

相关性压缩(和编码)又分为帧内相关和帧间相关,即编码出来的I帧就是我们所说帧内相关,B、P帧则是帧间相关。

对于非相关编码部分,大部分都集中在图像的前期处理上,例如归一化、白平衡、色度调节等。步骤大致如下:

  • 在图像预处理完成后(归一化、降噪等),接下来就是x264较多需要做的事情图像编码与压缩(虽然x264自身也会做一些降噪、再降噪、色度调节等)。
  • 先说编码部分,x264里面先将一副raw数据(可能是yuv420,可能是yv12等等),进行切块(即宏块分割,图像简单预测)。
  • 将分割好的图像在做块内再分割(细节预测,找出图像细节部分,对细节部分在切割,变成小块)
  • 接着又对每一个块做相邻之间的差异化计算(其实就是求出差异),这个过程是最复杂的一个。

 

下面是对于不同类型帧切块分类的说明其他具体的解释会在后续说:

 


 

其中对于不同类型的输出帧,宏块的大小如下:

I帧:

16*16、8*8、4*4


P帧:

L0、8*8、SKIP


B帧:

DIRECT、L0L0、L0L1、L0BI、L1L0、L1L1、L1BI、BIL0、BIL1、BIBI、8*8、SKIP

 


 

 

2017-11-20 | | 音视频_图像相关, 音视频编解码

【x264、视频、编码、宏块】编码成不同帧时,宏块参数的变化情况已关闭评论

【webrtc、ios sdk 11、 xcode9】webrtc在xcode 9下的uuid_t编译错误

最近osx环境无意间升级了所有的包,并把xcode升级到了9。按部就班的继续编译之前可以正常编译的webrtc,后来不料,除了这么一个错误:

error: nullability specifier ‘_Nullable’ cannot be applied to non-pointer type ‘uuid_t’ (aka ‘unsigned char [16]’)

 

东查西查。最后就查到了之前的猜测,这里有解释:

https://forums.xamarin.com/discussion/103773/will-there-be-support-for-ios-11-sdk

因为xcode自带的是ios sdk 11的。就目前来说,这一点比较坑人,因为ios sdk 11的库和ios sdk 10的库在部分函数上的定义上有所区别。

而webrtc和相应的depot_tools也是今年年初的,因此使用的第三方clang编译器也相对xcode 9的步调来说老了一些。

为了不想增加麻烦,也就不打算用gclient了,因为当时不是我去拿的webrtc代码,也不知道会不会有坑。就果断把xcode降级为xcode 8。

xcode 8的下载地址:

https://developer.apple.com/download/more/

降级的方法:

http://osxdaily.com/2012/02/20/uninstall-xcode/

 

看来用第三方编译器也是让人比较头疼的一件事情。有时候ios上遇到的坑不比android少。。。

 

2017-11-01 | | [奇葩类]求上进系列, iOS, 移动开发, 编码技巧, 音视频_图像相关

【webrtc、ios sdk 11、 xcode9】webrtc在xcode 9下的uuid_t编译错误已关闭评论

【编译、ffmpeg、msvc】windows下编译ffmpeg

由于最近使用的ffmpeg及其相关的库太过于老旧,所以需要进行更新。

对于视频方面的编码主要用到h264,音频则用到mp3、aac、speex。

其中最为坑的,还是mp3和aac。因为mp3中的分支太多,为了简化问题,最后还是选用lamemp3作为编码器。在ffmpeg 3.0开始,ffmpeg就停止了aacplus的使用,改为使用fdk aac。并且ffmpeg还自带了一个aac编码器。

在编译过程中由于没有注意到这个问题,因此使用了内置编码器,导致he aac编码出来的数据缺少sbr段。因此需要外部加入fdk aac来完成。

 

  • 先说一说需要提前做的一些准备:

1、lamemp3源代码

2、speex源代码

3、fdk_aac源代码

4、x264源代码

5、ffmpeg源代码

6、安装msys2极其相应的工具(如果在windows上编译)

7、vs2015(如果在windows上编译)

 

lamemp3编译步骤:

直接代开源代码下vc_solution目录,使用vs2015编译即可

 

speex编译步骤:

打开win32目录下的vs2008直接用vs2015编译即可

 

fdk_aac编译步骤:

fdk_aac编译比较坑,不能在msys2中编译,需要用nmake(vs工具链)直接编译就好……

 

x264编译步骤:

在msys2中直接编译即可

 

ffmpeg编译步骤:

1,将speex、mp3、aac中include的部分代码拷贝到ffmpeg根目录下

2,在将相应的lib文件拷贝到根目录下的某个文件,这里用3rdparty来代表目录

3,执行编译命令

./configure –prefix=/c/work/github/ffmpeg_src_3.2/out –toolchain=msvc –enable-libx264 –enable-libmp3lame –enable-libfdk-aac –enable-nonfree –enable-libspeex –enable-gpl –extra-cflags=-IC:\\work\\github\\ffmpeg_src_3.2 –enable-shared –extra-ldflags=-LIBPATH:C:\\work\\github\\ffmpeg_src_3.2\\3rdparty\\lib

4,执行make和 make install之后即可

 

2017-08-31 | | win, 编码技巧, 音视频_图像相关, 音视频编解码

【编译、ffmpeg、msvc】windows下编译ffmpeg已关闭评论