08|播放器项目实战(二):底层核心模块的实现
解码模块的实现
openInput
- 深入了解
- 翻译
- 解释
- 总结
本文深入介绍了播放器项目实战中底层核心模块的实现过程,包括解码模块、音频播放模块和视频播放模块的具体实现细节。作者首先详细讲解了解码模块的实现,使用FFmpeg开源库完成输入模块的协议解析、封装格式拆分、解码操作等行为。在音频播放模块的实现中,强调了Android和iOS平台的实现差异,并重点放在了接口设计与内部实现上。在视频播放模块的实现中,依赖于平台构建自己的上下文环境以及窗口管理。文章通过具体的代码实现和技术细节,深入浅出地介绍了播放器项目中底层核心模块的实现过程,对于想要深入了解播放器技术实现的读者具有很高的参考价值。在Android平台上,使用OpenGL ES渲染视频画面需要单独开辟一个线程,并为这个线程绑定一个OpenGL ES的上下文。而在iOS平台上,使用OpenGL ES需要继承自UIView的VideoOutput类,并重写父类的layerClass方法,返回CAEAGLLayer类型。整体而言,本文通过具体的代码实现和技术细节,深入浅出地介绍了播放器项目中底层核心模块的实现过程。
《快手 · 移动端音视频开发实战》,新⼈⾸单¥59
全部留言(4)
- 最新
- 精选
- 大土豆demux感觉某种程度上算不上IO密集型操作,如果是网络资源,网络IO这块是IO密集型操作,但这块不包含在demux的范围,网络模块读取数据输入给demux模块,比如socket read读取了1024 * 20字节,输入给demux模块,demux负责解析,比如20个字节是头部啦,先解析出来各种元数据,然后第21-1024字节是一帧数据,解析完存下来,再解析下段,这种还是属于CPU密集型的操作。
作者回复: 你的理解是正确的,我这里没有拆得太细,我把protocol与muxer统一的都叫“demux”了,在这里只是给大家提出要把av_read_frame这个既有Protocol的IO又有demuxer的操作是占用网络IO资源更多,独立出一个线程会更合适;解码部分独立成一个线程,不要把这两个放到一个线程中。
2022-08-13归属地:北京1 - peter请教老师几个问题: Q1:文中第一个图,就是FFmpeg的处理流程图,Packet为Video时,调用的是“avcodec_decode_audio2”吗?从名字看,似乎是和音频有关。 Q2:“视频部分只需要解码一次,就可以得到 AVFrame 的视频裸数据(一般是 YUV 格式)”,从这句话的上下文来看,这句话中的AVFrame应该是AVPacket吧。这里用AVFrame,是笔误?还是说两者等价? Q3:“Android 平台我们选用 OpenSL ES 来渲染音频”。既然引入了FFmpeg,为什么不用FFmpeg的音频渲染方法?后面视频渲染部分,采用OpenGL ES,也没有采用FFmpeg。我的理解是:1 OpenSL ES和FFmpeg都可以完成音频渲染,选用OpenSL ES只是一种选择而已。2 OpenGL ES和FFmpeg都可以完成视频渲染,选用OpenGL ES只是一种选择而已。3 引入FFmpeg主要目的是为了解码,而不是音视频渲染。音视频的处理,采用OpenSL/GL ES就足够了。我的理解是否对? Q4:手机上YUV格式不能用于实际显示,必须转换为RGBA才能显示,对吗? YUV是通用的视频表示格式,在在手机上,这种数据并不能用来在显卡上显示,需要转换为RGBA才能被显卡显示。或者说,手机的显卡不支持YUV。(但也许某些其他设备可以直接支持YUV显示)。 是这样子吗?
作者回复: A1: 这个图片里面的内容,应该是编辑老师写错了,我让老师修改一下; A2:不是笔误,AVPacket是压缩后的数据(简单理解为H264或者AAC),AVFrame是原始数据(简单理解为YUV或者PCM),AVPacket经过解码形成AVFrame; A3:FFmpeg框架不具有渲染音频的能力,FFmpeg是集协议(protocol,比如rtmp、http、file)、封装(muxer/demuxer,比如mp4、flv、m4a)、编解码(Codec,比如H264、AAC、Mp3)为一体的多媒体框架,本身不具备渲染音频以及渲染视频的能力;多说一句,ffmpeg提供了一个命令行叫ffplay,里面渲染音视频使用的是sdl这个库来进行的。 A4:是的,都要转换为RGBA才可以显示。
2022-08-10归属地:北京1 - keepgoing一般在销毁资源的时候,直接让这个函数返回 0,或者为弱网也提供一个超时的读取时间,这个设置是非常有用的,它可以保证你的解码模块不会因为一些阻塞的 IO 调用变得不可用。 老师请教一下,这里应该是“直接让这个函数返回1”吧?直接取消IO阻塞
作者回复: 你说的是对的,返回1代表中断IO操作。
2022-12-10归属地:北京 - geek请教老师没太理解片段shader的代码。 对于yuv420p的数据是如何做成一张纹理的?yuv420p是4个y数据和2个uv数据,这段数据是如何用顶点坐标得到yuv的三个分量?
作者回复: 使用texture2D方法就可以拿出对应的这个像素点,至于是Y还是U还是V,是从对应不同的纹理ID上拿出来的,类似于这样: mediump vec3 yuv; yuv.x = texture2D(inputImageTexture, v_texcoord).r - (16.0 / 255.0); yuv.y = texture2D(s_texture_u, v_texcoord).r - 0.5; yuv.z = texture2D(s_texture_v, v_texcoord).r - 0.5;
2022-08-11归属地:北京3