当前位置:网站首页>【学习】从零开始的音视频开发(9)——NuPlayer
【学习】从零开始的音视频开发(9)——NuPlayer
2022-04-23 07:16:00 【Panic Lin】
NuPlayer基于StagefrightPlayer的基础类构建,利用了底层的ALooper/AHandler
机制来进行异步解码播放,Alooper轮循队列中的消息,把消息推送到AHandler处理,最后通过handleMessage函数回调,做相应的逻辑处理
NuPlayer整体结构
MediaPlayerFactory通过工厂模式创建NuPlayerFactory
,然后通过NuPlayerFactory创建NuPlayerDriver
,接着通过NuPlayerDriver构建一个NuPlayer
,NuPlayer作为播放器,其中设计数据解析、解码、渲染等过程
NuPlayer的构建过程
在上层调用setDataSource函数后,开始到达MediaPlayerService的setDataSource函数,通过getPlayerType
函数获取播放器类型
播放器类型枚举如下
这时再回到MediaPlayerFactory中看看getPlayerType函数
接下来进入一个宏函数,宏的主要作用是替换,提高代码的执行效率,因为其省去了分配和释放栈帧、传参、传返回值等一系列工作
这个宏函数的标示遍历map中存放的播放器工厂类,调用scoreFactory
可以得到播放器的播放能力,如果是NuPlayer,默认有一个0.8的值,返回的ret就是NuPlayerFactory对象,如果得到的值为0.0,就进入getDefaultPlayerType
函数
默认也是NuPlayerFactory
针对NuPlayerFactory不会直接创建NuPlayer,而是在NuPlayerDriver的构造函数中创建一个NuPlayerDriver
在NuPlayerDriver的构造函数中,创建了一个NuPlayer,NuPlayerDriver是对NuPlayer的封装,继承MediaPlayerInterface
接口。通过NuPlayer可以实现播放功能,主要用于通知上面的流程
NuPlayer继承自AHandler
,并且引入了AMessage,通过ALooper来处理消息,比如它的prepareAsync
函数
实际就是发送一个kWhatPrepare
消息。在onMessageReceived
函数中,收到消息并进行处理(该函数太长,仅摘取kWhatPrepare部分分析)
NuPlayer的数据解析模块
解析的模块主要是NuPlayerSource
以及继承它的几个类,如HTTPLiveSource、RTSPSource、GenericSource等
在NuPlayer中调用setDataSourceAsync
函数后
这里会根据不同协议选择不同的Source对象,有了这个Source对象后,发送kWhatSetDataSource
消息(下图同样只是该函数部分截图)
通过具体的Source解析完数据,再把Source强制转换成mSource
给Decoder使用,这时里面就包含了数据相关信息,其中的一个HTTPLiveSource
,主要用于解析HLS协议
当调用HTTPLiveSource的prepareAsync函数时
内部主要构建了一个LiveSession
对象,通过LiveSession内部的connectAsync
函数,创建一个会话
查看onConnect函数
网络请求,开始取播放列表,在取到播放列表后进行回调(下图是回调函数)
上面的代码主要是根据URL返回的M3U文件,获取对应的BandwidthItem
,如果熟悉M3U文件,可以知道M3U文件有一级索引和二级索引,下图是一些举例
其主要作用是动态码率适应,BANDWIDTH
越大,分辨率越高。BINDWIDTH实际上就是带宽
若想获得某个Track的信息,得到视频、音频、字幕相关信息,可以通过LiveSession的getTrackInfo
函数
到此数据解析模块完成,视频源的主要作用都是得到音视频数据信息,最终通过mSource
变量传递给解码器
NuPlayer的解码模块
它引入了NuPlayerDecoderBase
,这是一个基类,真正的解码器逻辑在NuPlayerDecoder.cpp中,它继承了这个基类,下面先查看实例化解码器
上面的代码构造了Decoder
对象,且进行了初始化和构建解码器
由于NuPlayerDecoder继承自NuPlayerDecoderBase
类,所以Configure函数会执行NuPlayerDecoder的Configure
函数,最终回调onConfigure
函数,其位于NuPlayerDecoder.cpp中
从onConfigure函数可以看到,NuPlayerDecoder引入了MediaCodec
作为解码器。通过CreateByType/CreateByComponentName
创建了Codec
对象。
NuPlayer的渲染模块
主要功能
1.将音视频原始数据缓存到队列
2.音频数据消耗播放
3.视频数据消耗显示
4.音视频同步
5.播放器控制
将音视频原始数据缓存到队列,在NuPlayerRenderer.h中,存在一个QueueEntry结构体和两个队列
数据在onQueueBuffer
函数中进行添加
而音频的播放在NuPlayerRenderer
中,会先调用openAudioSink
函数
发送一个kWhatOpenAudioSink
消息,收到消息后进行如下处理
调用onOpenAudioSink
函数
这里打开了AudioSink(音频后端)
。当将音频数据放入音频队列时,会接着调用postDrainAudioQueue_l
函数
上图代码发送了一个kWhatDrainAudioQueue
主要是有一个进行判断的onDrainAudioQueue
函数,判断是否需要重新向AudioSink写入数据
到这里,这个音频播放流程如下:先打开音频后端,然后当向音频队列中发送数据,音频队列同时向音频后端写入数据,以供播放音频
视频显示的话,同样是在视频原始数据进入视频队列后,开始执行postDrainVideoQueue
函数
这里先发送一个kWhatDrainVideoQueue
的消息,然后进行音视频同步,发送消息后会出发调用onDrainVideoQueue
NuPlayer::Renderer
使用的是以视频为基准的同步机制,解码后的音频数据时间戳如果大于视频数据时间戳,直接丢弃音频包,然后直接渲染视频。同步机制主要位于视频缓冲区处理部分的onDrainVideoQueue
和音频缓冲区处理部分的onDrainVideoQueue
中。音视频的渲染都采用类似定时器的机制,只不过视频显示需要依赖于实际解码器,音频播放需要依赖于AudioSink接口
版权声明
本文为[Panic Lin]所创,转载请带上原文链接,感谢
https://blog.csdn.net/PanicLin/article/details/124356518
边栏推荐
- 网赚APP资源下载类网站源码
- Brief description of CPU
- [go]常见的并发模型[泛型版]
- Transformer-XL: Attentive Language ModelsBeyond a Fixed-Length Context 论文总结
- clang 如何产生汇编文件
- 常用正则表达式
- ApplicationReadyEvent的使用
- Find the largest of 3 strings (no more than 20 characters per string).
- Discussion on ES6 tail tune optimization
- 2022.4.11-4.17 AI行业周刊(第93期):AI行业的困局
猜你喜欢
青苹果影视系统源码 影视聚合 影视导航 影视点播网站源码
谈谈那些基础但不简单的股票数据
简述存储器的分级策略
Why are there 1px problems? How?
几种智能机器人室内定位方法对比
Principle of sentinel integrating Nacos to update data dynamically
LeetCode中等题之旋转函数
dried food! Point based: differentiable Poisson solver
2022.4.11-4.17 AI行业周刊(第93期):AI行业的困局
Somme numérique de la chaîne de calcul pour un problème simple de leetcode
随机推荐
社区团购小程序源码+界面diy+附近团长+供应商+拼团+菜谱+秒杀+预售+配送+直播
The whole house intelligence bet by the giant is driving the "self revolution" of Hisense, Huawei and Xiaomi
Online yaml to XML tool
2022.4.11-4.17 AI industry weekly (issue 93): the dilemma of AI industry
LeetCode15. Sum of three
Mobile web (Font Icon, plane conversion, color gradient)
英语课小记(四)
Mobile terminal layout (3D conversion, animation)
Compiling principle questions - with answers
User manual of Chinese version of solidity ide Remix
Compiler des questions de principe - avec des réponses
3C装配中的机械臂运动规划
Canvas learning Chapter 1
Anti shake and throttling
Implementation of promise all
WordPress爱导航主题 1.1.3 简约大气网站导航源码网址导航源码
Hump naming object
Jetson Xavier NX (3) bazel mediapipe installation
How does feign integrate hystrix
Positioning and decoration style