IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【学习】从零开始的Android音视频开发(7)——AwesomePlayer的构造、解码过程 -> 正文阅读

[移动开发]【学习】从零开始的Android音视频开发(7)——AwesomePlayer的构造、解码过程

StagefrightPlayer也叫做AwesomePlayer,虽然只是一个已经不再使用的组件

AwesomePlayer构造过程

StagefrightPlayerFactory创建了一个StagefrightPlayer后,就开始进入StagefrightPlayer的构造函数

在这里插入图片描述

StagefrightPlayer.h中有如下声明

在这里插入图片描述

可看出StagefrightPlayer中封装了AwesomePlayer,进而进行播放行为相关操作,接着分析下里面的StagefrightPlayer

在这里插入图片描述

可以看出它继承了MediaPlayerInterface抽象基类,这个抽象基类有很多虚函数

同样以setDataSource为例,通常当我们负责的模块和别人的模块进行交互时,在模块之间相当于一个黑盒,通过返回对应的状态或者数据可以判断已经发生的事件,进而进行下一个环节。StagefrightPlayer只是一层外壳,真正干活的是AwesomePlayer

在调用MediaPlayerService中的setDataSource函数后会到达StagefrightPlayer中的setDataSource函数

在这里插入图片描述

所有执行步骤都会调用mPlayer->setDataSource(xxxx),而通过前面的分析我们知道,这个mPlayer被定义成AwesomePlayer,虽然AwesomePlayer中也有一些网络流处理的代码,但通常执行不到这段逻辑,而是使用NuPlayer,接下来到达AwesomePlayer的setDataSource函数

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总结:AwesomePlayer主要用于本地播放,匹配不同的文件类型,并用数据解析器处理mime表示该资源的媒体类型,当出现常见音视频封装格式的时候,Android播放器如果在Manifest.xml中设置了mime对应的类型,就能被播放器识别

常用的mime类型资源

在这里插入图片描述

AwesomePlayer使用MediaExtractor进行数据解析的过程

MediaExtractor即为数据解析器,查看其源码

在这里插入图片描述

总结:针对文件解析的不同格式创建Extractor解析器并解析,创建好解析器后回到AwesomePlayer::setDataSource_l中,继续执行setDataSource_l(extractor)函数,对新建的解析器做处理,实质是做视频的A(音频)/V(视频)分离,解析器的类型在AwesomePlayer::setDataSource_l中创建的时候就定下来了

在这里插入图片描述
在这里插入图片描述

mVideoTrackmAudioTrack作为创建AwesomePlayer的成员函数,其类型为MPEG4Source,继承自MediaSource
在这里插入图片描述

以上过程完成了音视频数据的分离,也就是demux(解复用),对音频和视频资源分开处理,顺序:MediaPlayerService->StagefrighterPlayer->AwesomePlayer->MPEG4Extractor->MPEG4Source,音频同理

在这里插入图片描述

AudioPlayer为AwesomePlayer的成员,AudioPlayer通过callback来驱动数据的获取,AwesomePlayer则通过videoevent来驱动。数据的获取都抽象成mSource->read来完成,且read内部把parse和decode绑在一起。StageFright A/V同步部分,Audio完全由callback驱动数据流,注意视频部分在onViewEvent里会获取Audio的时间戳,然后、进行音视频时间的比较,计算下一帧间隔多久显示,使时间戳同步

AwesomePlayer的Video主要成员

1.mVideoSource(解码视频)
2.mVideoTrack(从多媒体文件中读取视频数据)
3.mVideoRenderer(对解码好的视频进行格式转换,Android使用的格式为RGB565)
4.mISurface(重绘图层)
5.mQueue(event事件队列)

StageFright运行时的Audio流程

1.设置mUri的路径
2.启动mQueue,创建一个线程来运行threadEntry(命名为TimedEventQueue),这个线程就是event调度器
3.打开mUri所指定文件的头部,根据类型选择不同的分离器,如MPEG4Extractor
4.使用MPEG4Extractor对MP4进行音视频轨道的分离,并返回MPEG4Source类型的视频轨道给mVideoTrack
5.根据mVideoTrack中的编码类型来选择解码器,AVC的编码类型会选择AVCDecoder,返回给mVideoSource,并设置mVideoSource中的mSource为mVideoTrack
6.插入onVideoEvent到Queue中,开始解码播放
7.通过mVideoSource对象读取解析好的视频Buffer

如果解析好的视频Buffer还没到A/V时间戳同步的时刻,则推迟到下一轮操作
1.mVideoRenderer为空,则进行初始化(如果不使用OMX,会将mVideoRenderer设置为AwesomeLocalRenderer)
2.通过mVideoRenderer对象将解析好的视频Buffer转换成RGB565格式,并发给display模块进行图像绘制
3.将onVideoEvent重新插入event调度器来循环

AwesomePlayer解码过程

AwesomePlayer中的prepare过程

在这里插入图片描述

总结:prepare过程调用了prepareAsync_l函数,在其中执行AwesomeEvent构造函数,并将AwesomePlayer调用onPrepareAsyncEvent的引用结果返回AwesomeEvent的构造函数作为参数

然后分析AwesomeEvent的过程。首先启动mQueue,作为EventHandler

在这里插入图片描述

上面的new AwesomeEvent会执行onPrepareAsyncEvent函数

在这里插入图片描述

总结:会将音视频分别处理,于是有了AwesomePlayer::initVideoDecoderAwesomePlayer::initAudioDecoder

先看initVideoDecoder

在这里插入图片描述

AwesomPlayer.h中几个变量的声明

在这里插入图片描述

然后看看初始化音频解码器

在这里插入图片描述

总结:在StageFright调用AwesomePlayer的prepare函数后,AwesomePlayer调用自身的prepareAsync初始化音视频解码器,无论是prepare还是prepareAsync都会触发OMXCode::Create函数,然后使用OMXCodec处理对应的业务逻辑

prepareAsync主要完成3件事
1.Streaming:启动下载数据并缓存
2.初始化并创建音视频解码器
3.通知上层已经处于Prepared状态

使用OMXCodec的解码过程

经过数据流封装得到的是两个MediaSource其实是两个OMXCodec。AwesomePlayer和mAudioPlayer都是从MediaSource中得到数据并进行播放的。AwesomePlayer得到的是最终要渲染的原始视频数据,而AudioPlayer得到的是最终要播放的原始音频数据,也就是说从OMXCOdec中读到的数据已经是原始数据

先看构造函数Create
在这里插入图片描述

总结
1.IOMX &omx指的是一个OMXNodeInstance对象的实例
2.MetaData &meta这个参数由MediaSource.getFormat获取得到,这个对象的主要成员是一个KeyedVector(uint32_t,typed_data)mItems,里面存放了一些代表MediaSource格式信息的键值对
3.bool createEncoder指明这个OMXCodec是编码还是解码
4.MediaSource &source是一个MeidaExtractor(数据解析器)
5.char* matchComponentName指定一种Codec用于生成这个OMXCodec

先使用findMatchingCodecs寻找对应的Codec,找到以后为当前IOMX分配节点并注册事件监听器

在这里插入图片描述

最后把IOMX封装进一个OMXCodec

在这里插入图片描述

这样就得到了OMXCodec

在AwesomePlayer中得到了这个OMXCodec后,我们返回初始化解码器的函数中

在这里插入图片描述

使mAudioSource=mOmxSource,然后调用start进行初始化
在这里插入图片描述

OMXCodec主要做以下两件事
1.向OpenMAX发送开始指令,如mOMX->sendCommand(mNode,OMX_CommandStateSet,OMX_StateIdle),表示状态就绪了,可以进入预解码阶段
2.调用allocateBufers函数分配两个缓冲去,存放在变量mPortBuffers[2]中,分别用于输入输出

然后再initxxxDecoder函数中调用start函数
在这里插入图片描述

触发MediaSource的子类VideoSource及AudioSource调用start函数后,它的内部就会开始从数据源获取数据并解析,等到缓冲区满后便停止。在AwesomePlayer里就可以调用MediaSource的read函数读取解码后的数据

对于mVideoSource来说,将读取的数据(mVideoSource->read(&mVideoBuffer,&options))交给显示模块进行渲染(mVideoRenderer->render(mVideoBuffer))

对于mAudioSource来说,用mAudioPlayer对mAudioSource进行封装,然后由mAudioPlayer负责读取数据控制播放

AwesomePlayer调用OMXCodec读取ES(基本码流,包含音视频或数据的连续码流),并进行解码处理

OMXCodec调用MediaSource的read函数获取音视频数据,调用Android的IOMX接口来实现音视频解码操作

这个过程就是prepare过程,主要用于分离音视频数据,给音视频申请好Buffer空间,做预解码操作

然后当Java层调用start函数时,通过MediaPlayerService进行IPC通信后,再调用StagefrightPlayer中的start函数,引用AwesomePlayer,这样就调用了AwesomePlayer的play函数

在这里插入图片描述

在AwesomePlayer调用play后,通过mVideoSource->read(&mVideoBuffer,&options)读取数据。mVideoSource->read(&mVideoBuffer,&options)具体是通过调用OMXCdodec.read来读取数据的。

而OMXCodec.read通过1.调用drainInputBuffers函数对mPortBuffers[kPortIndexInput]进行填充,这一步完成parse。由OpenMAX从数据源把demux(解复用)后的数据读取到输入缓冲区,作为OpenMAX的输入。2.通过fillOutputBuffers[kPortIndexInput]进行填充,这一步完成解码数据的填充。由OpenMAX对输入缓冲区中的数据进行解码,然后把解码后可以显示的视频数据输出到输出缓冲区

AwesomePlayer通过mVideoRenderer->render(mVideoBuffer)对经过parse和decode处理的数据进行渲染。一个mVideoRenderer其实就是一个包装了IOMXRenderer的AwesomeRemoteRenderer(在很早的版本才有,仅作了解)

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-23 10:58:30  更:2022-04-23 10:58:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 23:58:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码