ijkplayer是一款跨平台的播放器,支持Android与iOS端,核心部分基于ffmpeg,支持Android的mediacodec硬解与iOS的videotoolbox硬解,视频图像采用OpenGL进行渲染。许多主流播放器都使用ijkplayer作为播放方案。接下来我们从核心播放流程、内核架构、时序图、状态机、播放器整体架构进行详细分析。
目录
1、核心播放流程
2、播放内核架构
3、播放时序图
4、播放状态机
5、播放器整体架构
1、核心播放流程
ijkplayer的核心处理在ff_ffplay.c,从ffp_prepare_sync_l方法开始,调用stream_open方法分别创建video、audio、subtitle三个packet队列和三个frame队列,启动video_refresh_thread与read_thread线程。
其中read_thread为解封装线程,调用avformat_open_input打开本地文件/网络流,而stream_component_open方法负责初始化解码器、创建解码线程,接着是for循环读取媒体数据包存入packet队列。解码线程负责从packet队列取出数据包进行解码,然后存入frame队列。视频渲染线程默认10ms轮训一次,从frame队列取出图像进行渲染;iOS的音频播放采用AudioQueue,内部创建工作线程定时读取pcm数据进行播放:
2、播放内核架构解封装、解码、播放分为三个线程,使用packet_queue队列连接解封装与解码,使用frame_queue连接解码与播放。其中解封装协议包括:http、https、hls、file、private自定义私有协议等,iOS视频硬解码用videotoolbox,Android视频硬解码用mediacodec,iOS的音频播放用AudioQueue,Android音频播放用AudioTrack或OpenSL。如同如下图所示:
3、播放时序图以iOS移动端的播放时序为例,从IJKMoviePlayerViewController.m,到IJKFFMoviePlayerController.m,中间层是ijkplayer_ios.m,再到ijkplayer.c,最后是ff_ffplay.c。具体时序如下图所示:
4、播放状态机ijkplayer的状态包括:idle、initialized、async_preparing、prepared、started、paused、stopped、completed、error、end共10种state。整体的状态机state machine如下:
每个状态名、状态值、状态描述,如下图所示:
5、播放器整体架构
播放器的整体架构分为内核层、抽象层、控制层、业务层。
内核层负责核心播放功能,Android端可以用ExoPlayer、IjkPlayer、MediaPlayer,而iOS端可以用IjkPlayer、AVPlayer,也可以自研播放器。
抽象层负责对内核进行封装、内核切换,提供PlayerFactory来创建对应播放器。
控制层分为基本 *** 作、界面控制、播放状态。基本 *** 作包括play、pause、seek等,界面控制包括volume、brightness等,播放状态包括prepared、complete、error等。
业务层分为业务场景、特色功能、延伸能力。业务场景包括悬浮窗播放、边下边播、转音频播放、列表播放等,特色功能包括截图、视频剪裁、视频转GIF图、音频均衡器等,延伸能力包括投屏播放、技术埋点、插屏广告等。
我们先从ijkplayer的核心播放流程进行分析,然后到内核播放架构、播放时序图、播放状态机,最后拓展到通用的播放器整体架构。希望能让大家对播放器有更深刻的认识。
学习音视频可以到GitHub:https://github.com/xufuji456/FFmpegAndroid
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)