【ARM-Linux开发】gstreamer教程及在DM3730上的应用
感谢原文作者:goalie高义http://blog.csdn.net/goalietech/article/details/24887955
1 Gstreamer基本概念
GStreamer 是一个开源的多媒体用的框架,采用了基于插件(plugin)和管道(pipeline)的体系结构,框架中的所有的功能模块都被实现成可以插拔的组件, 并且在需要的时候能够很方便地安装到任意一个管道上,由于所有插件都通过管道机制进行统一的数据交换,因此很容易利用已有的各种插件“组装”出一个功能完善的多媒体应用程序。
2Gstreamer基本组成
Gstreamer组成有四个基本单位,它们分别为元件(element)、衬垫(Pads)、箱柜(Bins)、管道(pipelines)。
A:元件(element):元件是Gstreamer中最重要的概念,它是组成整个gstreamer应用程序的基本单位,可以将多个相关功能的元件链接到一起组成一个管道,这样就可以实现一个简单的多媒体软件了。常见的元件有音频编解码、视频编解码、文件读取、网络传输等。
B:衬垫(Pads):用于元件之间的链接,可以理解为元件的插座或端口,衬垫分为两种类型:src为输出,sink为输入。一个元件可以既有src又有sink衬垫,也可以多个src或sink衬垫。例如:音频编码元件的输入或输出端、音频播放元件的输入端都属于衬垫。
C: 箱柜(Bins)、管道(pipelines):箱柜是一个可以装载元件的容器,将多个元件链接起来放入箱柜中实现一个高级功能的单元。例如:将音频解码元件和音频输出元件链接起来可以组成一个音频解码播放模块装载到箱柜中。管道是最高等级的箱柜,是由多个元件或箱柜组成的一个完整的功能单元。例如:一个音视频文件的播放通道。
如下图所示,一个简单的ogg格式的播放器用gstreamer的方式去实现,就是将各相关功能的元件通过衬垫连接到一起组成一个管道,这样就可以实现一个基本的ogg播放器了。
简单的ogg播放器Gstreamer实现
3 Gstreamer应用及实现功能
Gstreamer功能框架图
GStreamer核心库函数是一个处理插件、数据流和媒体操作的框架,gstremer的插件机制是其核心,所有的元件的都是以插件的形式绑定在管道中用来实现媒体处理的功能的。Gstreamer目前包含的插件已经超过了250个,包含音视频的各种方式输入输出、编解码、存储、网络传输、传输协议、音视频编辑、格式转换等方面的插件。
4 基于gstreamer框架的软件及功能
l Rhythmbox是一个综合的音乐管理软件,属于建筑于网络之上的播放器。可以直接下载歌曲,支持网络电台和播客。
Rhythmbox
l Sound juicer是一种在Linux及其它Unix-Like等操作系统平台上可将CD音轨转档的软件,能透过GStreamer的插件来进行各种音效编码。可转换包括mp3、Ogg、FLAC、及PCM等不同格式。
Sound juicer
l Monkey Bubble 是一个很有趣又很酷的GNOME下的一个游戏软件,它通过GStreamer播放音乐产生惊悚的或甜美的音响效果。
Monkey Bubble
l AviSynth是一个功能强大的视频文件后期处理工具,提供了许多编辑和处理视频文件的方法。能够提供各种方式来合并和滤镜处理影像文件。最独特的就是AviSynth并不是一个孤立的影像处理程序,而是在影像文件和应用程序之间担任“中间人”的角色。
AviSynth
l Thoggen 是一个高效的 DVD 备份软件,它基于GStreamer,拥有一个漂亮的 GTK+ 界面,功能强大且容易使用。
l GNOME Media 是用GStreamer 来进行声音控制、音频录制和CD播放。
5 DM3730平台及环境搭建
DM3730是TI公司生产一款ARM+DSP双核的处理器,该处理器集成了高达 1GHz的ARM Cortex™-A8内核及高达800MHz的具有高级数字信号处理的DSP核,并提供了丰富的外设接口。主要应用于便携式数据终端、导航、自动化资讯娱乐、医疗设备、工业控制等产品中。
搭建DVSDK开发环境
DVSDK(DaVinci Software Development Kit)是TI公司为了方便用户开发和测试而提供的一系列的工具包。开发者可以利用DVSDK提供的工具测试DM3730的软硬件性能,能够评估ARM
Linux的开发环境并且体验到硬件多媒体编解码的性能。
1、首先下载一个DM3730对应的DVSDK安装包,我们这里下载的是DVSDK4.03的版本。
2、DVSDK安装推荐使用Ubuntu 10.04的版本,然后安装DVSDK到ubuntu系统。
3、修改根目录下的Rules.make文件,主要是修改对应的平台、内核、编译工具链等选项。
4、执行根目录下的setup.sh脚本,主要是安装tftp工具,创建文件系统目录、配置串口和uboot环境参数。
5、执行make clean、make all和 make install进行完全编译。make help 可参看make帮助信息。
6、编译成功后就会生成目标文件系统targetfs,在targetfs/usr/share/ti文件夹里面会有调试软硬的各种工具。
CMEM和DSPLink
DM3730为ARM+DSP双核机制的CPU,所以ARM和DSP之间的通信就显得尤为重要。CMEM和DSPLink对于DM3730来说是俩个非常重要的驱动,它们的主要功能就是为了实现ARM和DSP之间的通信和数据交换。
CMEM:主要用于分配大片连续共享内存和数据交互。
DSPLink:双核通信的基础软件,为开发人员提供通用的API,用于ARM 与DSP之间通信。
内存分配
由于ARM和DSP共享内存,为了避免内存使用混乱,需要重新分配内存的使用范围,下图是DM3730的内存分配情况:
DM3730内存分配
从上图可以看到Linux的内存被分配成了2个部分0x80000000-0x83700000,0x88000000-0xA0000000。所以uboot的启动参数bootargs应该传递给linux内核内存的分配情况(mem=55M@0x80000000 mem=384M@0x88000000)。
系统启动后需要安装cmemk.ko和dsplinkk.ko。
- > insmod cmemk.ko phys_start=0x83700000 phys_end=0x85900000 allowOverlap=1 useHeapIfPoolUnavailable=1
- > insmod dsplinkk.ko
6 移植Gstreamer
DVSDK中的文件系统已经做好了对gstreamer的支持,当你编译完dvsdk后,make install会将文件系统生成到Rules.make文件中EXEC_DIR变量所对应的目录里。然后你会在文件系统的usr/lib/gstreamer-0.10/看到gstreamer的库文件。该版本的gstreamer使用过程中可能会出现库的版本名称不对或则丢失软连接等问题,这些问题需要大家重命名或则手动创建软连接即可解决。
7 media-ctl移植
media-ctl是一个通过调用linux系统的MediaController API来实现对多媒体设备(DM3730默认为/dev/media0)进行控制的指令,是一个开源的工具。它可以枚举出系统各多媒体设备实体及实体的衬垫(pads),并可以将不同实体的衬垫连接到一起组成一个通道,从而控制视频在前端采集时的流向。
由上图可以看到,视频采集过来的原始数据最终到达DM3730的ARM核,也就是可以被我们的程序得到是有很多条路径可以选择的。
Sensor->CCDC->Memory- (C)
Sensor->CCDC->Preview->Memory- (1), (4)
Sensor->CCDC->Preview->Resizer->Memory- (1), (2), (3)
此处参考网页《CM-T3730: Linux: Camera》
通过media-ctl –help可以看到该工具的使用方法,media-ctl –p可以列出各实体的参数和衬垫及连接状态。如下所示:
- Openingmedia device /dev/media0
- Enumeratingentities
- Found16 entities
- Enumeratingpads and links
- Devicetopology
- -entity 1: OMAP3 ISP CCP2 (2 pads, 2 links)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev0
- pad0: Input [SGRBG10 4096x4096]
- <- 'OMAP3 ISP CCP2input':pad0 []
- pad1: Output [SGRBG10 4096x4096]
- -> 'OMAP3 ISP CCDC':pad0 []
- -entity 2: OMAP3 ISP CCP2 input (1 pad, 1 link)
- type Node subtype V4L
- device node name /dev/video0
- pad0: Output
- -> 'OMAP3 ISP CCP2':pad0 []
- -entity 3: OMAP3 ISP CSI2a (2 pads, 2 links)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev1
- pad0: Input [SGRBG10 4096x4096]
- pad1: Output [SGRBG10 4096x4096]
- -> 'OMAP3 ISP CSI2aoutput':pad0 []
- -> 'OMAP3 ISP CCDC':pad0 []
- -entity 4: OMAP3 ISP CSI2a output (1 pad, 1 link)
- type Node subtype V4L
- device node name /dev/video1
- pad0: Input
- <- 'OMAP3 ISP CSI2a':pad1 []
- -entity 5: OMAP3 ISP CCDC (3 pads, 9 links)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev2
- pad0: Input [SGRBG10 4096x4096]
- <- 'OMAP3 ISP CCP2':pad1 []
- <- 'OMAP3 ISP CSI2a':pad1 []
- <- 'ov5640 2-003c':pad0 []
- pad1: Output [SGRBG10 4096x4096]
- -> 'OMAP3 ISP CCDC output':pad0[]
- -> 'OMAP3 ISP resizer':pad0[]
- pad2: Output [SGRBG10 4096x4095]
- -> 'OMAP3 ISP preview':pad0[]
- -> 'OMAP3 ISP AEWB':pad0[IMMUTABLE,ACTIVE]
- -> 'OMAP3 ISP AF':pad0[IMMUTABLE,ACTIVE]
- -> 'OMAP3 ISPhistogram':pad0 [IMMUTABLE,ACTIVE]
- -entity 6: OMAP3 ISP CCDC output (1 pad, 1 link)
- type Node subtype V4L
- device node name /dev/video2
- pad0: Input
- <- 'OMAP3 ISP CCDC':pad1 []
- -entity 7: OMAP3 ISP preview (2 pads, 4 links)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev3
- pad0: Input [SGRBG10 4096x4096]
- <- 'OMAP3 ISP CCDC':pad2 []
- <- 'OMAP3 ISP previewinput':pad0 []
- pad1: Output [YUYV 4082x4088]
- -> 'OMAP3 ISP previewoutput':pad0 []
- -> 'OMAP3 ISP resizer':pad0[]
- -entity 8: OMAP3 ISP preview input (1 pad, 1 link)
- type Node subtype V4L
- device node name /dev/video3
- pad0: Output
- -> 'OMAP3 ISP preview':pad0[]
- -entity 9: OMAP3 ISP preview output (1 pad, 1 link)
- type Node subtype V4L
- device node name /dev/video4
- pad0: Input
- <- 'OMAP3 ISP preview':pad1[]
- -entity 10: OMAP3 ISP resizer (2 pads, 4 links)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev4
- pad0: Input [YUYV 4095x4095(0,0)/4086x4082]
- <- 'OMAP3 ISP CCDC':pad1 []
- <- 'OMAP3 ISP preview':pad1[]
- <- 'OMAP3 ISP resizerinput':pad0 []
- pad1: Output [YUYV 4096x4095]
- -> 'OMAP3 ISP resizeroutput':pad0 []
- -entity 11: OMAP3 ISP resizer input (1 pad, 1 link)
- type Node subtype V4L
- device node name /dev/video5
- pad0: Output
- -> 'OMAP3 ISP resizer':pad0[]
- -entity 12: OMAP3 ISP resizer output (1 pad, 1 link)
- type Node subtype V4L
- device node name /dev/video6
- pad0: Input
- <- 'OMAP3 ISP resizer':pad1[]
- -entity 13: OMAP3 ISP AEWB (1 pad, 1 link)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev5
- pad0: Input
- <- 'OMAP3 ISP CCDC':pad2[IMMUTABLE,ACTIVE]
- -entity 14: OMAP3 ISP AF (1 pad, 1 link)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev6
- pad0: Input
- <- 'OMAP3 ISP CCDC':pad2[IMMUTABLE,ACTIVE]
- -entity 15: OMAP3 ISP histogram (1 pad, 1 link)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev7
- pad0: Input
- <- 'OMAP3 ISP CCDC':pad2[IMMUTABLE,ACTIVE]
- -entity 17: ov5640 2-003c (1 pad, 1 link)
- type V4L2 subdev subtype Unknown
- device node name /dev/v4l-subdev8
- pad0: Output [unknown 640x480(0,0)/640x480]
- -> 'OMAP3 ISP CCDC':pad0 []
从上面列表从可以看到entity17对应ov5640也就是视频输入源,输出可以选择OMAP3 ISP CCDC,我们要建立一个ov5640--> ISP CCDC-->memory的通道实现视频采集功能,通过帮助我知道应该使用media-ctl –l来实现通道连接功能。
可以直接使用entity和pad的数字来进行连接,这样上述通道可以表示为:
- media-ctl -l '17:0->5:0[1]', '5:1->6:0[1]'
“:”前面的数字代表entity的值,后面的数字为该entity的pad值,“[]”里面的数字代表状态0为不激活,1为激活。
但是还是建议使用名称来进行连接,这样更加直观一些,如下:
- media-ctl -l '"ov56402-003c":0->"OMAP3 ISP CCDC":0[1], "OMAP3 ISPCCDC":1->"OMAP3 ISP CCDC output":0[1]'
除此之外还要对各pad的分辨率进行配置,使用media-ctl -v --set-format指令,这里ov5640默认使用640x480的分辨率,设置如下:
- media-ctl -v --set-format '"ov56402-003c":0 [UYVY 640x480]'
- media-ctl -v --set-format '"OMAP3 ISPCCDC":0 [UYVY 640x480]'
- media-ctl -v --set-format '"OMAP3 ISPCCDC":1 [UYVY 640x480]'
这样可以看到ISP CCDC的输出节点为/dev/video2,以后程序就可以使用该节点获取视频数据和控制了。
如果你使用的TVP5150这样AD芯片,其实实现方式也是相同的,只是名字和分辨率换换而已,如下所示:
- media-ctl -r -l '"tvp51503-005d":0->"OMAP3 ISP CCDC":0[1], "OMAP3 ISPCCDC":1->"OMAP3 ISP CCDC output":0[1]'
- media-ctl -v --set-format '"tvp51503-005d":0 [UYVY 720x576]'
- media-ctl -v --set-format '"OMAP3 ISPCCDC":0 [UYVY 720x576]'
- media-ctl -v --set-format '"OMAP3 ISPCCDC":1 [UYVY 720x576]'
另外。Media-ctl有好多版本,费很大劲才找到适合DM3730使用的,但还是有一个小bug,现在将我修改后使用的media-ctl源码上传上来了,需要的话可以去下载。当然如果通过MediaController API自己编程实现上述功能也是可以的。
调试过程中发现一个问题,文件系统存放在SD启动时会生成/dev/media0设备,但是烧写到NandFlash之后/dev/media0没有了。后来发现原来是mdev的问题,于是将mdev替换为udev后,问题就解决了,时间太长了具体原因忘记了,知道的朋友帮忙留一下言吧。
Media-ctl.tar.gz
8 DM3730音视频gstreamer处理流程
DVSDK软件包中提供了gstreamer的代码并集成了针对于DM3730芯片的插件TI GStreamer Plugin,如下图所示:
DM3730软件系统框架图
上图绿色部分为TI基于gstreamer框架实现的插件,里面包含了基于DM3730的DSP音视频编解码算法、视频显示、DMA控制等插件。
我们想做一个类似于IPcamera的测试功能,通过采集音视频并编码打包,然后通过网络传输出去,通过客户端可以接收到数据并分别解包后显示出来。具体实现方式将用到gstreamer内部提供的元件和TI提供的视频编码的插件。
DM3730音视频处理的具体功能框图如下图所示:
元件功能介绍:
l v4l2src:从video4linux2设备(ov5640、tvp5150)中读取视频帧。支持rgb、yuv、jpeg、dv、mpegts等常见视频格式。
l alsasrc:通过ALSA接口声卡设备中读取音频数据,支持8、16、24、32位的音频数据。
l ffmpegcolorspace:将视频数据从一种颜色空间转换成另一种。
l audioconvert:音频格式转换。
l TIVidenc1:TI提供的视频编码器插件。
l alawenc:A率音频编码器。
l mpegtsmux:混合多媒体到MPEG2-TS传输流(一种传输和存储包含音效、图像与通信协议各种数据的标准格式,用于数字电视广播系统),主要实现音视频的同步处理。
l rtpmp2tpay:将有效的负载编码MPEG2-TS传输流打包成RTP协议包,适合实时流媒体传输。
l udpsink:通过以太网传输udp的数据。
gst-launch是gstreamer提供的快速建立多媒体处理管道的软件,它可以通过指令来验证整个软件的实现的可能性。上述的功能我们可以通过该工具很方便的实现出来,具体指令如下所示:
- gst-launch-v v4l2src device=/dev/video2 \
- !ffmpegcolorspace \
- !video/x-raw-yuv,format=fourccUYVY,width=720, height=576 \
- !TIVidenc1 codecName=h264enc engineName=codecServer \
- !queue ! mux. \
- alsasrc! audioconvert \
- !'audio/x-raw-int,rate=44100,channels=1' ! faac \
- !mux.mpegtsmux name=mux ! queue ! rtpmp2tpay ! udpsink port=8877 host=192.168.2.100
如果正常的话通过客户端软件就可以直接看到带有伴音的图像了,而且应该是音视频同步的图像。当然客户端也可以通过gst-launch来进行实现,可以在电脑上安装好gstreamer的环境,现在windows和linux均有支持,我没有去研究如何用gst-launch来进行解码显示,因为有更方便的工具可以实现这个功能,那就是VLC播放器,打开VLC选择“文件”-->“打开网络串流”在UDP/RTP输入正确的端口号,点击确定就可以正常播放网络传输的音视频了。
当然你如果仅仅想传输视频也是可以的,通过如下指令即可实现视频单独传输:
- gst-launch-v v4l2src device=/dev/video2 !\
- ffmpegcolorspace! videoscale! videorate ! \
- video/x-raw-yuv,format=fourccUYVY,width=720, height=576, framerate=30/1!\
- TIVidenc1rateControlPreset=3 codecName=h264enc engineName=codecServer !\
- rtph264paypt=96 ! udpsink host=192.168.2.100 port=8877 sync=false async=false
客户端解码可以通过gst-launch实现,指令如下(windows下的指令,linux下未测试):
- gst-launch udpsrc port=8877caps="application/x-rtp, media=(string)video, clock-rate=(int)90000 ,encoding-name=(string)H264, payload=(int)96" ! gstrtpjitterbuffer !rtph264depay ! ffdec_h264 ! ffmpegcolorspace ! videoscale !"video/x-raw-yuv" ! autovideosink
或则也可以通过VLC进行播放,需要先编写一个.sdp的文件,如下:
- v=0
- m=video 8877 RTP/AVP 96
- c=IN IP4 192.168.2.200
- a=rtpmap:96 H264/9000
将上面内容保存为rtph264.sdp文件,然后通过VLC打开即可接收并播放网络传输的视频流。
上面的参数大家可以自行研究,这里就不赘述了。
上面的指令通过应用程序也是很方便实现的,前提是你掌握了gstreamer的编程方法。
这里上传一个非常有用的gstreamerAPI手册,CHM格式的,是本人自己制作的,还是很实用的,而且查找函数和使用方法非常的方便,大家可以选择下载。
GStreamer 1.0 Core Reference Manual
- <pre code_snippet_id="324143" snippet_file_name="blog_20140503_10_3411737"></pre>
- <pre></pre>
- <pre></pre>
【ARM-Linux开发】gstreamer教程及在DM3730上的应用的更多相关文章
- 《嵌入式Linux开发实用教程》
<嵌入式Linux开发实用教程> 基本信息 作者: 朱兆祺 李强 袁晋蓉 出版社:人民邮电出版社 ISBN:9787115334831 上架时间:2014-2-13 出版日期: ...
- go 语言开发中 GOPATH问题 与 go语言linux 开发环境 教程
https://github.com/rubyhan1314/Golang-100-Days/blob/master/Day01-15(Go%E8%AF%AD%E8%A8%80%E5%9F%BA%E7 ...
- 在Ubuntu上建立Arm Linux 开发环境
我使用的是友善2410的板子,以前都是用Fedora,现在家里的电脑被我转为Linux专用的了,装的是Ubuntu.但是嵌入式还是要玩的,在装载过程中也遇到一些小麻烦.在此记录一下,一来自己比较健忘, ...
- Linux开发工具教程
今天把上个星期写的Linux开发工具相关的教程整理一下,方便阅读: 1.第一课 GCC入门: 2.第二课 GCC入门之静态库以及共享库: 3.第三课 Makefile文件的制作(上) : 4.第四课 ...
- CTF必备技能丨Linux Pwn入门教程——ROP技术(上)
Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...
- 成功移植SQLite3到ARM Linux开发板
SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了 ...
- minigui移植到arm linux开发板上无法执行
要保证目录下有该文件 /etc/MiniGUI.cfg 复制过程使用cp –af 强制复制
- CTF必备技能丨Linux Pwn入门教程——调整栈帧的技巧
Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...
- CTF必备技能丨Linux Pwn入门教程——ROP技术(下)
Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...
随机推荐
- 前端面试题-HTML+CSS
引用GitHub 上 ltadpoles的前端面试 https://github.com/ltadpoles HTML部分 1. Doctype作用,HTML5 为什么只需要写<!DOCTYPE ...
- CF46F Hercule Poirot Problem
题意: 有n个房间和m扇门,每扇门有且仅有一把钥匙 有k个人度过了两天,在第一天开始的时候所有的门都是关闭的,在第二天结束的时候,所有的门也都是关闭的 在这两天内,每个人可以执行如下操作若干次: 关上 ...
- Java进阶知识19 Struts2和Spring整合在一起
1.概述 1.Spring负责对象创建 2.Struts2负责用Action处理请求 3.整合的关键点:让Struts2框架Action对象的创建交给Spring完成. 2.整合实例 需要用到的 ...
- php使用ZipArchive提示Fatal error: Class ZipArchive not found in的解决方法
使用压缩包函数必须要安装zip扩展,否则会报错 $ apt install php-zip
- HTTP header 介绍 转载
这篇文章为大家介绍了HTTP头部信息,中英文对比分析,还是比较全面的,若大家在使用过程中遇到不了解的,可以适当参考下 HTTP 头部解释 1. Accept:告诉WEB服务器自己接受什么介质类型,*/ ...
- 2016"百度之星" - 初赛(Astar Round2A)1005 BD String(HDU5694)——找规律、字符串对称、分治
分析:按照题目所给的意思每次处理得到的新的字符串都是具有高度对称性的,举个例子,如题目所给的第三个字符串,最中间的是B然后两边分散开去,一边是B的话另外一边关于这个中心对称的那个位置一定是D,反过来同 ...
- docker部署nginx+vue项目
1.vue项目打包 npm run build 会在项目生成dist文件夹,这个文件夹可以使用nginx或tomcat来发布服务 2.查找nginx基础镜像 可以通过以下网站找到符合自己的基础镜像,我 ...
- Windows Server 2008 R2 服务器内存使用率过高几乎耗光
系统环境: Windows Server 2008 R2 Enterprise 搭建有 web服务器(iis) 和 文件服务 问题描述: Windows Server 2008 R2系统内存耗光 ...
- PHP学习之文件上传类
<?php $up = new Upload(); $newPath = $up->uploadFile('fm'); if ($newPath === false) { var_dump ...
- https://uwsgi-docs.readthedocs.io/en/latest/Async.html
Beware! Async modes will not speed up your app, they are aimed at improving concurrency. Do not expe ...