音视频开发面试宝典:OpenGL、编解码与直播技术全解析

音视频开发工程师必备面试题解析 #

本人是主要从事音视频相关的开发工作,但发现网上关于音视频的学习资料都比较零散,而且也没有一套比较全面的面经,所以我把自己这几年整理的相关资料都掏出来给大家。(获取完整版pdf文档可添加我微信cpp-father领取)

咳咳:这篇文章我本来都想开付费阅读了,因为真的耗费了我极大精力。后来想想还是算了,也不差这点钱,支持的就多去看看我公众号文章吧。

废话不多数,直接上干货,内容都是自己整理的(请别抄袭了),有些地方难免有错误,大家见谅哈。

音频处理需要理解的概念有哪些? #

  • 采样率:每秒采集声音的数量HZ,一般为44100HZ
  • 采样精度:每次采样的精度位数,位数越多,能记录的范围就越大,一般为16bit。
  • 通道:单声道,双声道,四声道等。
  • 比特率:也叫码率,比特率 = 采样率 x 采样精度 x 通道数
  • 采样率44100,采样精度16,通道2的比特率为44100*16*2bps
  • wav格式:前44字节(有可能比44字节多)记录采样率通道等信息,后面就是pcm裸数据。http://soundfile.sapp.org/doc/WaveFormat/
  • aac格式:一般packet为adts头+编码数据;如果是将aac封装到mp4容器中,则不需要为每个aac packet添加adts,音频信息和偏移量可以存储到moov中,然后直接存储aac packet即可。
  • https://zhuanlan.zhihu.com/p/34295106
  • https://blog.csdn.net/yuhengyue/article/details/91443191

PCM音频数据是如何组织的? #

img

pcm数据经过AAC编码器编码后,直接写文件会怎么样? #

将AAC封装到mp4容器中,是否需要为每个AAC packet添加ADTS? #

AAC(Advance Audio Coding)封装有哪些规格,ADTS帧头包含哪些字段和含义 #

  • ADIF格式,头信息只在文件头部,解码必须从头部开始,获取头信息后,剩下全是音频数据,但是这种格式的解码必须在开头位置进行。
  • ADTS格式,每个packet都有个header,可以从任何位置开始。
  • 如图 https://zhuanlan.zhihu.com/p/162998699

img

WAV格式,WAV的数据头的最小大小和作用 #

  • 上面介绍过,前44字节(有可能比44字节多)记录采样率通道等信息,后面就是pcm裸数据。

介绍信号的时域和频域? #

  • 时域:信号在时间轴随时间变化的总体概括,时间和振幅的关系【横轴是时间,纵轴是信号的变化幅度】
  • 频域:频谱图,频率和振幅的关系【横轴是频率,纵轴是信号的变化幅度】
  • https://www.zhihu.com/question/21040374

RTP数据包格式 #

简述H264格式 #

  • 目标:高的视频压缩比、良好的网络亲和性,适用于各种传输网络
  • 分层:目的是?
    • 视频编码层VCL:VCL数据是编码处理的输出,表示被压缩编码后的视频数据序列。【编码/压缩、切分】
    • 网络提取层NAL:VCL数据传输和存储之前,这些VCL数据,会被封装进NAL单元中。【打包】

NALU结构 #

img

  • Header有一个字节,8个比特位(1,2,5)
    • 1(forbidden_zero_bit):正常为0,当前NALU存在错误时才为1
    • 2(nal_ref_idc):NALU的重要性,0-3,值越大越重要,0表示非参考帧(其他帧解码时不需要参考该帧),如果NALU是参考帧或SPS、PPS重要数据时会大于0。
    • 5(nal_unit_type):当前NALU的类型,具体类型如下图:

img

  • NALU Body,如图:

img

  • NALU = header + EBSP = header + 0x03 + RBSP = header + 0x03 + SODB + 补齐字节

  • 一个NALU可以代表一个完整的帧吗?

    • 不可以,看nal_unit_type,5代表完整帧,1-4不一定是完整帧。
  • 多个NAL单元组成一个Access Unit,多个Access Unit再组成一个视频编码序列(即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列)。

  • nal_unit_type的第9位才表示是不是一个完整帧结束。

  • SPS:序列参数集,保存编码序列的全局参数,主要是profile(baseline、main、extended profile)

  • PPS:图像参数集,保存整体图像相关的参数,每一帧可能有不同的设置信息,初始QP,分块信息等。

  • IDR:后面的帧不会参考IDR之前的帧,可以刷新缓冲队列。

  • Slice:主要就是表示IBP帧。

  • SEI:补充增强帧,可以增加图像参数、用户信息等。

img

主流格式:两者的差别很小,就是视频数据单元分割方式不同 #

  • Annexb:即以start code来分割NALU,打包方式如下:[startCode]–[NALU]–[startCode]–[NALU]…
  • avcc的格式:不使用startCode,而使用[size]–[NAL]–[size]–[NAL],mp4的h264就是这种格式。
  • https://www.cnblogs.com/linuxAndMcu/p/14533228.html

IBP帧和GOP #

  • I:帧内编码图像帧,不参考其他帧,只利用本帧的信息进行编码,压缩比最低。
  • P:利用之前的I帧和P帧,采用运动预测的方式进行帧间编码,压缩比略高。
  • B:既利用前面的帧,也参考后面的帧,进行帧间双向预测编码,压缩比最高。
  • GOP:两个I帧之间的间隔。GOP越大,PB帧就越多。
  • https://zhuanlan.zhihu.com/p/112635240

如何通过SPS内部的 pic_width_in_mbs_minus1和pic_height_in_map_units_minus1 计算宽高 #

  • 假设pic_width_in_mbs_minus1=21pic_height_in_map_units_minus1=17,则宽为(21+1)*16=352,高为(17+1)*16=288

列举几种profile #

  • baseline profile:基本画质,支持I/P帧
  • main profile:主流画质,支持I/B/P帧
  • extended profile:进阶画质,支持I/B/P/SP/SI帧

IDR帧与I帧的理解 #

  • IDR帧一定是I帧,但I帧不一定是IDR帧。一个序列中可以有很多I帧,但是I帧后的图像也可以引用I帧前的图像做参考。如果是IDR帧,则可以将参考帧队列清空,后面的图像一定不会参考IDR帧之前的图像。

编码I P B帧存储和显示顺序问题 #

无法复制加载中的内容

H264 over rtp 如何实现? #

  • 就是h264的另一种形式,size-nal-size-nal格式

mp4封装 #

img

音视频同步的做法 #

img

AudioTrack与MediaPlayer的对比 #

  • 都用于播放声音,都有Android Java API,AudioTrack的实现原理?
  • AudioTrack只能播放已经解码的PCM裸流
  • MediaPlayer可以播放多种格式的音频,比如mp3、aac、wav、midi等,它会在framework层创建对应的解码器,解码成pcm后再利用AudioTrack播放
  • MediaPlayer会创建AudioTrack,把解码后的pcm给AudioTrack,AudioTrack再给AudioFlinger进行混音,然后给硬件播放。
  • 还有个SoundPool
    • MediaPlayer适合在后台长时间播放本地音乐文件或在线的流式资源
    • SoundPool适合播放比较短的音频片段,比如游戏声音、按键声、铃声片段等,可以同时播放多个音频
    • AudioTrack更接近底层,支持低延迟播放,适合流媒体和语音通话场景
    • Native层用的opensl或oboe
  • AudioFlinger
    • AudioFlinger和AudioPolicyService是Android音频系统的两大基本服务。AudioPolicyService是音频系统策略大制定者,负责音频设备切换的策略抉择、音量调节策略等;AudioFlinger是音频系统策略的执行者,负责音频流设备的管理及音频流数据的处理传输,包括重采样、混音、音量调节、音效处理、start、stop、pause等,所以 AudioFlinger 也被认为是 Android 音频系统的引擎。
  • https://blog.csdn.net/zyuanyun/article/details/60890534

MediaRecorder和AudioRecord的对比 #

  • 都用于录制音频
  • AudioRecord录制的是PCM裸数据,需要AudioTrack播放
  • MediaRecorder录制的音频是经过压缩后的,需要设置编码器,录制的音频文件可以直接播放
  • MediaRecorder录制音频时会先创建AudioRecord进行录制,然后再使用编码器编码

MediaCodec #

  • 用途:音视频编解码
  • 原理如图:Codec模块不停的从输入缓冲区拿数据做处理,处理完毕后把数据吐到输出缓冲区。

img

  • 状态图

img

  • 流程
    • 创建MediaCodec对象
    • 配置MediaCodec
    • 不停的循环
      • 如果输入缓冲区就绪,拿到一块输入缓冲区,把数据送到输入缓冲区中
      • 如果输出缓冲区就绪,拿到输出缓冲区,把数据从输出缓冲区中拷贝出来
    • 释放MediaCodec对象
  • Q&A
    • 6.0以上基本可以解码4路,以下有2路有1路的
    • 最多能解码几路?怎么优化?快速seek。
    • SE以上4路,以下2路
    • 视频用硬解,音频软解
    • 快速seek
      • 提前做缓存,前M后N张纹理
      • 判断seek频率,如果较快时,直接调用seek到I帧,只解码IDR帧
    • 如果同一文件,只起一路解码器?
  • https://www.cnblogs.com/renhui/p/7478527.html
  • https://www.jianshu.com/p/7cdf5b495ada

声音或者视频慢的解决办法 #

  • 声音慢:让视频帧再多显示一会
  • 视频慢:丢视频帧

介绍Opengl渲染管线流程和各个步骤的工作 #

纹理 #

  • 可以理解为纹理就是一张贴纸画布,这个纹理可以用来存储大量的数据,可以将数据发送到着色器上。
  • 什么是纹理
  • Texture中环绕方式有几种可选,都是什么效果
    • 纹理环绕方式(当纹理坐标超出默认范围时,每个选项都有不同的视觉效果输出)
    • GL_REPEAT 默认行为,重复纹理图像
    • GL_MIRRORED_REPEAT 和REPEAT一样,但每次重复都是镜像放置
    • GL_CLAMP_TO_EDGE 纹理坐标会约束在0-1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果
    • GL_CLAMP_TO_BORDER 超出的坐标为用户指定的边缘颜色

img

  • 纹理过滤方式
    • 纹理过滤(纹理坐标不依赖于分辨率,OpenGL需要知道怎样将纹理像素映射到纹理坐标。当一个很大的物体但是纹理的分辨率很低,过滤方式很重要)
    • GL_NEAREST(邻近过滤)选择中心点最接近纹理坐标的那个像素
    • GL_LINEAR(线性过滤)基于纹理坐标附近的纹理像素,计算出一个插值,近似出这些像素之间的颜色

img

几个概念 #

  • 光栅化:也叫栅格化或像素化,就是把矢量图形转化成像素点的过程。
  • 渲染管线:渲染过程中从几何体到最终渲染图像、数据传输处理的过程。实际上指的是一堆原始图形数据途经一个输送管道,期间经过各种变化处理最终出现在屏幕的过程)管理的。图形渲染管线可以被划分为两个主要部分:第一部分把你的3D坐标转换为2D坐标,第二部分是把2D坐标转变为实际的有颜色的像素。
  • https://positiveczp.github.io/%E7%BB%86%E8%AF%B4%E5%9B%BE%E5%BD%A2%E5%AD%A6%E6%B8%B2%E6%9F%93%E7%AE%A1%E7%BA%BF.html

那什么是光栅化呢?首先我们需要明白一个概念,就是计算机只能处理离散的数据,而我们现实世界都是连续的,所以如何将我们输入的连续数据进行离散化呢?答案就是光栅化!
其实光栅化就是个离散化的过程,现在一般都是硬件来处理的,效率很高!我们通过光栅化得到了离散的片段或像素后,那到底该像素显示什么颜色呢?
答案就是用着色器来控制像素的颜色!着色器可以理解为上色,好比你画画,你需要给画图上各种颜色,着色器道理也是一样的!只不过它可以用来控制GPU的着色效果,实现屏幕上各种酷炫的效果!

img

img

着色器:先打线稿,再上色 #

  • 顶点着色器:如何打线稿,如何处理顶点等数据
  • 片元着色器:如何上色,如何处理光、阴影、遮挡、环境等对物体表面的影响,最终生成一幅图像。

img

说出FrameBuffer的用处,如何渲染到纹理 #

  • FrameBuffer Object,称为FBO,通常用作离屏渲染。
  • 可将FBO和texture绑定,fbo像画板,texture像画纸,在上面画东西后,texture上自然就有了数据。
  • FBO 本身不能用于渲染,只有添加了纹理或者渲染缓冲区之后才能作为渲染目标,它仅且提供了 3 个附着(Attachment),分别是颜色附着、深度附着和模板附着。

说出几个GLSL中常用类型和限定符 #

  • GLSL,在我们普通人理解就是一个用于写shader的语言,称为着色器语言。
  • 数据类型:int、float、double、uint、bool、vector、matrix
  • 输入和输出:in和out关键字
// vertex shader
#version 330 core
layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为0
out vec4 vertexColor; // 为片段着色器指定一个颜色输出

void main() {
    gl_Position = vec4(aPos, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数
    vertexColor = vec4(0.5, 0.0, 0.0, 1.0); // 把输出变量设置为暗红色
}

// fragment shader
#version 330 core
out vec4 FragColor;
in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)

void main() {
    FragColor = vertexColor;
}
  • uniform:一种从CPU向GPU传递数据的方式,uniform是全局的,如果fragment里有个uniform变量,不需要通过vertexshader作为中介,直接就可以传递数据。存储着色器需要等各种数据,如变换矩阵、光参数和颜色等。uniform 变量存储在常量存储区,因此限制了 uniform 变量的个数,OpenGL ES 2.0 也规定了所有实现应该支持的最大顶点着色器 uniform 变量个数不能少于 128 个,最大的片元着色器 uniform 变量个数不能少于 16 个。
  • samplers:一种特殊的uniform,用于呈现纹理,可用于顶点着色器和片元着色器。
  • const:编译时常量
  • attribute:只用于顶点着色器中,存储每个顶点的信息,比如坐标、法向量、纹理坐标和颜色等。
  • varying:由顶点着色器传递给片段着色器中的插值数据。两个shader拥有相同的varying字段。
  • 精度限定符:highp、mediump、lowp
  • https://colin1994.github.io/2017/11/11/OpenGLES-Lesson04/

GLContext是否可以进行共享?如何实现 #

  • 可以共享,直接创建sharedcontext就行,创建第二个GLContext时,把第一个GLContext传入进去。

VAO、VBO、EBO、FBO、PBO、TBO、UBO都是啥 #

  • VBO:Vertex Buffer Object,顶点缓冲区对象
  • EBO:Element Buffer Object,图元索引缓冲区对象
  • 这两个其实都是Buffer,都是通过glGenBuffers生成的,只是按照用途的不同称呼
  • 2.0中,用于绘制的顶点数组首先保存在CPU内存中,glDrawArrays时需要将数据从CPU传到GPU中,没必要每次绘制的时候都去拷贝,可以提前在GPU中缓存这块数据。
  • 3.0中,引入了VBO、EBO,用于提前在GPU中开辟一块内存,来缓存顶点数据或者图元索引数据,减少CPU和GPU间的数据拷贝。
  • VAO:Vertex Array Object,顶点数组对象,用于管理VBO或EBO,减少glBindBufferglEnableVertexAttribArray等操作
// 是不是精简了很多?
glUseProgram(m_ProgramObj);
glBindVertexArray(m_VaoId);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);

img

  • UBO:Uniform Buffer Object,装载Uniform变量数据的缓冲区对象。
  • FBO:Frame Buffer Object,帧缓冲区对象。FBO 本身不能用于渲染,只有添加了纹理或者渲染缓冲区之后才能作为渲染目标,它仅且提供了 3 个附着(Attachment),分别是颜色附着、深度附着和模板附着。
  • RBO:Render Buffer Object,渲染缓冲区对象,2D图像缓冲区,可用作FBO中的颜色、深度、模版附着。
  • TBO:Texture Buffer Object,Android API >= 24,纹理缓冲区对象。
  • PBO:Pixel Buffer Object,像素缓冲区对象,主要用于异步像素传输操作,用于像素传输,不连接到纹理,与FBO无关。可用于GPU的缓存间快速传递像素数据,不影响CPU时钟周期。
  • https://juejin.cn/post/6915341825515454478

glDrawElements和glDrawArrays区别 #

  • glDrawArrays指定的数据是最终的真实数据,绘制时效能更好。
  • glDrawElements指定的是真实数据的索引,如果很多顶点被重复使用,可以采用索引的方式,避免重复。
  • 如果画的图形较少或图形虽多但很多相同,可采用glDrawArrays更节省数据占用的空间;如果图形多,而且形状大不相同的时候,可以优先考虑采用glDrawElements函数。
  • https://blog.csdn.net/leon_zeng0/article/details/89291860

如何render to texture #

  • 拿到一个FBO,FBO绑定一个texture,然后把src 纹理画上去,就完成了RTT的需求。
  • texture和framebuffer,是否必须要一一对应
    • 不需要一一对应,是绑定的关系,可以将某一texture绑定到某一framebuffer上。

绘制模式 #

  • GL_LINES
  • GL_LINE_LOOP
  • GL_LINE_STRIP
  • GL_POINTS
  • GL_TRIANGLES
  • GL_TRIANGLE_STRIP
  • GL_TRIANGLE_FAN

坐标系统 #

  • 局部空间:对象所在的坐标空间。
  • 世界空间:世界空间的坐标是指顶点相对于世界的坐标。物体变换到的最终空间就是世界坐标系,将世界中的物体分散开来。
  • 观察空间:也称为摄像机空间,将对象的世界空间的坐标转换为观察者视野前面的坐标。
  • 裁剪空间:opengl的坐标会落在一个范围内,超过这个范围的点都会被裁剪掉,将顶点坐标从观察空间转换到裁剪空间,需要Projection Matrix。
  • 屏幕空间:换个坐标系。
  • 都可使用glm
  • https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/08%20Coordinate%20Systems/

img

简单实现灰度效果的 frament shader #

  • float luminance = 0.2125*col.r + 0.7154*col.g + 0.0721*col.b;
  • 然后rgb分量都变成luminance,出来都就是灰度图

三分屏效果 frament shader 实现 #

GLContext是什么 #

  • opengl的上下文,存储此opengl关联的所有状态。glcontext是线程局部变量,每个进程有多个线程,每个线程都有自己独立的上下文。

不同上下文在多个线程中进行渲染,需要注意什么 #

  • 它们需要是shared context,只有这样,才可以共享纹理等。
  • 某个fbo创建和销毁都要在同一个线程,跨线程会有gl内存泄漏。

opengl是?egl是? #

  • opengl是个操作GPU的API,它通过驱动向GPU发送相关指令,控制图形渲染管线状态机的运行状态,但当涉及到与本地窗口系统交互时,需要一个中间层,这个中间层就是EGL,作为OpenGL和窗口系统之间的桥梁。【Android是EGL,iOS是EAGL】

EGL可以 #

  • 与设备原生窗口通信
  • 查询绘制surface的可用类型和配置
  • 创建绘制surface
  • 渲染
  • 管理纹理等渲染资源

为什么要有YUV这种数据出来?(YUV相比RGB来说的优点) #

  • 相比于rgb,能够节省内存空间
  • 解决与黑白电视机等兼容问题,使黑白电视机也能接受彩色电视信号,Y和UV分离,Y是亮度,UV是色度。
  • https://zhuanlan.zhihu.com/p/75735751

说一下ffmpeg? #

  • 开源程序,主要功能有音视频采集、转码、滤镜、编解码、裁剪、播放等等。

img

H264/H265有什么区别? #

  • 都是编码协议,h265是h264的升级版。
  • h264每个宏块是固定的16x16像素,h265从8x8到64x64都有。
  • 帧内预测模式h264支持8种,h265支持33种,提供了更好的运动补偿处理和矢量预测方法。
  • 相同图像质量下,h265视频大小较h264的大小减少大于39%-44%。

平常的视频格式? #

  • mp4、mov、wmv、flv、avi

视频或者音频传输,你会选择TCP协议还是UDP协议?为什么? #

何为直播?何为点播? #

  • 直播:实时。
  • 点播:提前录制好的,可随时观看。

简述推流、拉流的工作流程? #

img

直播推流中推I帧与推非I帧区别是什么? #

常见的直播协议有哪些?之间有什么区别? #

点播中常见的数据传输协议主要有哪些? #

简述RTMP协议,如何封装RTMP包? #

m3u8构成是?直播中m3u8、ts如何实时更新? #

何为音视频同步,音视频同步是什么标准? #

  • 就是视频和音频要对应的上,比如电视剧声音和嘴形需要匹配(排除演员念123456的情况)
  • 标准:以视频为主、以音频为主(主流方案)、以外部时钟为主

播放器暂停、快进快退、seek、逐帧、变速怎么实现? #

  • 说说你平时在播放过程中做的优化工作?

视频编码标准两大系统是什么? #

  • ITU-T:国际电信联盟,h.264,h.265等
  • ISO:国际标准化组织,MPEG-1,MPEG-2,MPEG-4等

img

什么是音视频编码格式?什么是音视频封装格式? #

  • h264、mp3、aac就是编码格式
  • mp4、rmvb、flv就是封装格式

平时说的软解和硬解,具体是什么? #

  • 软解:CPU解码
  • 硬解:GPU解码

openGL渲染模式 #

  • 立即渲染模式:使用简单,但是效率低
  • 核心模式:使用困难,效率高,灵活性高,对开发者的要求也高,需要更深入的理解图形编程。

纹理的大小可以动态改变吗 #

  • MediaCodec连环炮:MediaCodec报错,只有错误码,没有任何其它信息,如何解决?使用MediaCodec遇到了哪些问题?同步使用和异步使用有什么区别?
  • 如何计算音频帧,一帧音频帧有多大
    • 音频帧其实概念没那么清晰,音频帧可以理解为采样了一次,帧大小是指每帧的采样数
    • 每帧的持续时间 frametime = samplesize / samplerate * 1000
    • 采样数1152,采样率为44100HZ的音频长度为 1152 / 44100 * 1000 = 26ms

Surface和SurfaceTexture区别 #

SurfaceView和TextureView区别 #

  • SurfaceView:可以在子线程中更新UI的View,且不影响主线程。但和常规View不同,它没有动画或者变形等特效。
  • GLSurfaceView:比SurfaceView多了个GL环境,无需自己swapBuffer。
  • SurfaceTexture:相机中得到的数据可以画到SurfaceTexture中的外部纹理上,方便对外部纹理进行二次处理。
  • TextureView:可以进行平移缩放等操作,必须开启硬件加速,但是没法自己拿纹理进行自定义绘制。

OpenGL ES相关问题,MVP矩阵左乘和右乘有什么区别,什么是外部纹理,为什么叫外部。 #

  • Android的MediaPlayer和Camera数据能转纹理显示,这就需要OES纹理。OES可以跨越GL环境传递纹理数据,通过OES纹理可以创建SurfaceTexture。
  • OpenGL如何渲染一个View
    • 通过EGL。
  • blend
    • 可以通过blend开启混合效果,完成一定透明度的混合。
  • 帧内预测,帧间预测
    • 帧内预测:解决的是空域数据冗余问题,一幅图中有很多肉眼很难察觉的数据,可以认为这些是冗余数据,直接压缩掉。
    • 帧间预测:解决的是时域数据冗余问题,一段时间内捕捉的数据没有较大的变化,可以针对这一时间内相同的数据做压缩,叫时域数据压缩。
  • glUseProgram和glBindFramebuffer这玩意有顺序要求吗?
    • 貌似没啥顺序,glUseProgram是在更新uniform等之前调用,因为它是在当前激活等着色器程序中设置的。如果当前没有program的情况下调用glUniform之类的函数,会报错。

其他(上面的链接里都介绍过) #

  • FLV封装
  • FLV的组成
  • FLV怎么获取sps,pps
  • 如何获取onMetaData,并解析metadata
  • TS封装
  • TS封装的第一个字节是什么,一个TS数据是多少?
  • TS的组成?
  • TS的内容通过什么标识的?
  • HLS HTTP Live Streaming
  • HLS是依靠什么工作的?
  • HLS点播和直播的区别?
  • m3u8有哪些字段和含义?
  • udp质量控制
  • 如何控制udp的传输质量
  • RTSP Real Time Streaming Protocol
  • rtsp包含哪些方法,rtsp的流程
  • RTMP Real Time Messaging Protocol
  • rtmp是可靠的传输协议吗?
  • rtmp一般采用那种封装格式?
  • rtmp的握手流程

资料推荐 #

声明 #

本文由我整理,相关文章和图片均来自网络,已经标明来源,如有侵权,请联系我删除。