Android 9.0 MediaPlayer播放流程分析

article/2025/10/2 0:04:51

1.MediaPlayer初始化流程

EventHandler是后面处理数据回调的handler. 在AudioFlinger.cpp中获取nextUniqueId:

audio_unique_id_t AudioFlinger::nextUniqueId(audio_unique_id_use_t use)
{// This is the internal API, so it is OK to assert on bad parameter.LOG_ALWAYS_FATAL_IF((unsigned) use >= (unsigned) AUDIO_UNIQUE_ID_USE_MAX);const int maxRetries = use == AUDIO_UNIQUE_ID_USE_SESSION ? 3 : 1;for (int retry = 0; retry < maxRetries; retry++) {// The cast allows wraparound from max positive to min negative instead of abortuint32_t base = (uint32_t) atomic_fetch_add_explicit(&mNextUniqueIds[use],(uint_fast32_t) AUDIO_UNIQUE_ID_USE_MAX, memory_order_acq_rel);ALOG_ASSERT(audio_unique_id_get_use(base) == AUDIO_UNIQUE_ID_USE_UNSPECIFIED);// allow wrap by skipping 0 and -1 for session idsif (!(base == 0 || base == (~0u & ~AUDIO_UNIQUE_ID_USE_MASK))) {ALOGW_IF(retry != 0, "unique ID overflow for use %d", use);return (audio_unique_id_t) (base | use);}}// We have no way of recovering from wraparoundLOG_ALWAYS_FATAL("unique ID overflow for use %d", use);// TODO Use a floor after wraparound.  This may need a mutex.
}

2. 设置播放视频路径setDataSource 接口分析

<1>. 在MediaPlayerService的setDataSource_pre中有获取IOmx监听服务是否挂掉,创建NuPlayerDriver,监听音频路由变化,创建AudioOutput:

通过上面过程可知sp<MediaPlayerBase> p是NuPlayerDriver类:

 

NuPlayerDriver中的mAudioSink就是AudioOutput类,它的mPlayer是NuPlayer这个类。 

<2>. NuPlayerDriver后面调用到 NuPlayer中去了,下面看下NuPlayer的setDataSourceAsync函数

 

 在这个函数中创建了一个GenericSource对象,并且将fd设置给了它。

3. 设置setSurface

在NuPlayer的setVideoSurfaceTextureAsync函数中,调用了Message的kWhatSetVideoSurface,在这个Message处理中创建了FlushDecoderAction、SetSurfaceAction 、SimpleAction、ResumeDecoderAction这些的对象,并且在processDeferredActions函数中执行了各个Action的execute函数,这块的分析放到了prepare中分析,主要是初始化NuPlayerDecoder.cpp,NuPlayerCCDecoder.cpp,MediaCodec.cpp

4. prepare流程分析流程分析

 <1>. 在jni中android_media_MediaPlayer_prepare函数,会重新设置surface,然后再调用prepare.这个setVideoSurfaceTexture跟setSurface里面的 mp->setVideoSurfaceTexture(new_st);流程是一样的:

<2>.在GenericSource::onPrepareAsync函数中,通过MediaExtractorService的makeIDataSource函数将MP4文件的音频和视频提取出来

 

 

 <3>. 下面再来看下CreateDataSourceFromIDataSource函数,看是如何得到DataSource对象的, CreateDataSourceFromIDataSource的实现是在InterfaceUtils.cpp文件中:

 

<4>.将视频文件放入DataSource中后,接下来是提取视频和音频

 

 

 

 

 

 创建IMediaExtractor的过程到此结束了。

<5>. 提取音频和视频

主要是通过meta->findCString(kKeyMIMEType, &mime)获取mime,然后通过mime来判断:

 后面会把所有的track都存到mSources中: mSources.push(track);

<6>. 通过5的分析可知,MediaExtractorFactory::Create(dataSource, NULL)最后拿到的对象是RemoteMediaExtractor,所以extractor就是RemoteMediaExtractor对象。在来看看sp<IMediaSource> track = extractor->getTrack(i);

 

 所以track(sp<IMediaSource>)实际是RemoteMediaSource,而RemoteMediaSource里面的mSource实际是MediaTrack,如果是MP4实际就是MPEG4Extractor.cpp

<7>. mime获取

extractor->getTrackMetaData(i)

 

 5. start流程分析

6.视频数据填充

视频数据填充回调在视频编解码里面已经介绍了,详情请看android P MediaCodec编解码流程分析_三火哥的博客-CSDN博客_mediacodec解码流程 ,省略部分流程,从ACodecBufferChannel.cpp的mCallback-onInputBufferAvailable开始介绍。

 <1>. 获取MediaCode中的buffer

 <2>获取MPEG4Extractor.cpp中的数据onRequestInputBuffers

<3>. mPendingInputMessages赋值 

 

 <4>.详细看下dequeueAccessUnit,NuPlayerDecoder.cpp中的mSource是GenericSource.cpp 

 

    (1).  postReadBuffer分析

    

在readBuffer中调用IMediaSource.cpp的readMultiple,最后会调用到MPEG4Extractor.cpp的read方法: 

 下面看下IMediaSource的readMultiple:

 

 

 可以看出从MPEG4Extractor.cpp中read的MediaBuffer *buf后面传给了MediaBuffer *transferBuf,reply的强指针就是transferBuf的mMemory(IMemory),BpMediaSource中接收了mMemory转换成了IMemory,然后将该IMemory传到RemoteMediaBufferWrapper对象中,后面将这个buf放到buffers(Vector<MediaBufferBase *>)的数组中:buffers->push_back(buf),到这里就把这个IMemory传出去了。

(2).得到MPEG4Extractor的IMemory后 需要调用mediaBufferToABuffer将MediaBufferBase转换成ABuffer,然后再把ABuffer通过queueAccessUnit函数传到AnotherPacketSource.cpp中,

 

 下面看下AnotherPacketSource.cpp的queueAccessUnit,ABuffer被存到了mBuffer(List<sp<ABuffer> > )中:

 到此IMemory被传到了AnotherPacketSource.cpp中。

(3). 回调NuPlayerDecoder.cpp的doRequestBuffers中,分析onInputBufferFetched函数

可以看出fetchInputData中回调的buffer (reply->setBuffer("buffer", accessUnit);)传给了 sp<ABuffer> buffer,

 

(4). 在GenericSource.cpp中调用了dequeueAccessUnit后里面循环调用postReadBuffer,也就是循环的获取MPEG4Extractor.cpp的数据。再回头看下dequeueAccessUnit函数:

 由上可知,如果hasBufferAvailable有数据,也就是AnotherPacketSource.cpp中的mBuffers不为空,就会调用AnotherPacketSource的dequeueAccessUnit函数,再来看看dequeueAccessUnit函数:

 后面是直接调用AnotherPacketSource的dequeueAccessUnit函数获取的ABuffer。

参考:

1. Android MediaPlayer播放视频详细步骤_APDL_10的博客-CSDN博客_android mediaplayer 

2. MediaCodec原理与流程(重生之我要成为音视频开发大腕)_守住Android最后的光的博客-CSDN博客_mediacodec流程 

3. Android底层音视频播放媒体提取器【MediaExtractor】的解复用模块demuxers模块化加载和注册流程实现源码分析【Part 1】_小白兔LHao的博客-CSDN博客


http://chatgpt.dhexx.cn/article/hjEPoDQI.shtml

相关文章

Android的MediaPlayer架构介绍

本文主要介绍的是Android中很重要也最为复杂的媒体播放器&#xff08;MediaPlayer&#xff09;部分的架构。对于Android这样一个完整又相对复杂的系统&#xff0c;一个MediaPlayer功能的实现不在其具体的功能&#xff0c;而是具体功能如何适应Android系统Android MediaPlayer的…

Android之MediaPlayer详解

文章转自&#xff1a;http://www.cnblogs.com/gansc23/archive/2011/04/08/2009868.html MediaPlayer类可用于控制音频/视频文件或流的播放。关于如何使用这个类的方法还可以阅读VideoView类的文档。 1&#xff0e;状态图 对播放音频/视频文件和流的控制是通过一个状态机来…

Android MediaPlayer播放视频详细步骤

MediaPlayer类是媒体框架最重要的组成部分之一&#xff0c;此类的对象能够获取&#xff0c;解码以及播放音频和视频&#xff0c;而且只需极少量设置&#xff0c;它支持多种不同的媒体源&#xff0c;例如&#xff1a; 本地资源 内部Url&#xff0c;例如您可能从内容解析器获取U…

Android MediaPlayer

最近在做游戏状态的保存时&#xff0c;需要存储背景音乐是否静音了&#xff0c;一直不成功&#xff0c;并且总是报出如下错误&#xff1a; ERROR/MediaPlayer(9974): start called in state 64 ERROR/MediaPlayer(9974): error (-38, 0) ERROR/MediaPlayer(9974): Error (-38…

MediaPlayer类播放音频

一、MediaPlayer类 1、常用方法 方法名称功能setDataSource()设置要播放的音频文件prepare()在开始播放前。调用该方法准备播放start()开始播放或者继续播放音频pause()暂停播放reset()重置MediaPlayer对象seekTo()从指定位置播放stop()停止播放&#xff0c;调用后MediaPlaye…

Android提高第一篇之MediaPlayer

本文来自http://blog.csdn.net/hellogv/ &#xff0c;引用必须注明出处&#xff01; 前面写了十四篇关于界面的入门文章&#xff0c;大家都看完和跟着练习之后&#xff0c;对于常用的Layout和View都会有一定的了解了,接下来的文章就不再强调介绍界面了&#xff0c;而是针对具体…

Android中的MediaPlayer的使用详解

今天本文介绍的是Andriod系统自带的Mediaplayer,和VideoView实现简单的音乐和视频的播放&#xff0c;至于想做出如酷狗音乐这样的APP的话&#xff0c;只要想做&#xff0c;应该也不难&#xff0c;都是基于此实现了功能的扩展。 Android的MediaPlayer包含了Audio和Video的播放功…

MediaPlayer详解和使用

Android多媒体相关的API&#xff0c;网上基本都能找到很多相关的文章&#xff0c;使用起来也很简单&#xff0c;一直在犹豫要不要写这方面的内容&#xff0c;后来决定还是写一写&#xff0c;一方面算是一个归纳总结&#xff0c;另一方面&#xff0c;也方便以后查阅。这一篇就写…

MediaPlayer的使用

MediaPlayer的使用 MediaPlayer的使用&#xff08;2019.07.16&#xff09;1.视频播放器的原理2.Android系统自带的MediaPlay状态机详解&#xff08;MediaPlay的生命周期&#xff09;3.如何使用MediaPlayer播放音频与视频&#xff08;一 &#xff09;播放音频&#xff08;二&…

MediaPlayer使用以及常见问题

前面已经写过一篇类似的文章&#xff0c;但是还不够细致&#xff1a; 采用Android的MediaPlayerSurfaceView设计视频播放器 这里我们重新理一下&#xff0c;并记录一点实际运用时遇到的问题。 MediaPlayer特性 MediaPlayer类用于控制音频文件、视频文件和流的播放。 Media…

Android MediaPlayer类

1. MediaPlayer方法 MediaPlayer创建 可以直接调用构造函数&#xff0c;利用setDataSource()方法设置资源。MediaPlayer mp new MediaPlayer(); // path可以是本地路径&#xff0c;也可以是网络地址 mp.setDataSource(String path);也可以调用create()方法&#xff0c;create…

MediaPlayer状态图及生命周期

MediaPlayer状态图及生命周期 MediaPlayer是Android中的uoge多媒体播放类&#xff0c;我们能通过它控制音视频流或本地音视频资源的播放过程。 这一片博客主要介绍MediaPlayer状态图及生命周期。先看一张官网很经典的MediaPlayer状态机的图片。 其中椭圆代表MediaPlayer驻留…

Android 使用MediaPlayer播放音频详解

目录 一、官方资料 二、简单介绍 三、MediaPlayer使用 1.创建MediaPlayer实例 2.重要API 3.状态图 4.代码 5.常用API 6.辅助效果 总结 一、官方资料 MediaPlayer 概览https://developer.android.google.cn/guide/topics/media/mediaplayer?hlzh_cn MediaPlayer 文…

Android -- 多媒体播放之MediaPlayer基础简介

Android -- MediaPlayer基础简介 MediaPlayer是Android中的一个多媒体播放类&#xff0c;我们能通过它控制音视频流或本地音视频资源的播放过程。 这段时间查阅了Android官方文档对MediaPlayer的介绍&#xff0c;同时也看了一些书籍介绍。现在把MediaPlayer的基础内容在此做一…

网易雷火9.18笔试题

3小时的题 我迟到了1个小时&#xff0c;提前了40分钟润&#xff0c;花了1个小时20分钟&#xff08;中途有点其他事&#xff09;&#xff0c;a了2道&#xff0c;第三题没思路&#xff0c;第4题不想看&#xff0c;就这样吧 #include <iostream> using namespace std; int…

网易笔试题总结

var string string; var number 0; var bool true; console.log(number || string); console.log(number && string); console.log(bool || number); console.log(bool && number); 输出结果 如果换下string和num的位置呢 var string string1; var numbe…

网易2019笔试题

1.苹果分堆 计算累加小组成员数&#xff0c;结合二分查找&#xff0c;复杂度O( min(n, mlogn) ) package wangyi123;import java.util.Scanner;public class groupNum {public static void main(String[] args) {Scanner sc new Scanner(System.in);while (sc.hasNext()) {i…

2022-08-20-网易笔试题

写在前面 题目收集来源自网络&#xff0c;前四题是开发岗的&#xff0c;后四题是算法岗的&#xff0c;因为代码无处提交&#xff0c;不一定正确&#xff0c;就不贴出来了&#xff0c;这里只写一下我的思路吧~欢迎大家一起讨论~~ 1、 思路&#xff1a;因为最大1e9&#xff0c…

网易游戏策划笔试-20190404

1-7题为文案题&#xff08;答题时请勿参考其他作品&#xff09;&#xff0c;8-23题为数值系统题&#xff0c; 两个方向分别计算分数&#xff0c;最终选择分数更高的方向作为最终成绩&#xff0c;建议优先选择自己擅长或感兴趣的方向进行答题。 8、&#xff08;无需过程&#xf…

JESD204接口调试总结——JESD204+In-system-ibert

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 JESD204接口调试总结——JESD204In-system-ibert 前言IP核的设置IP核连线调试jtag界面总结 前言 之前我们在讲serdes的时候讲到了使用in-system-ibert来进行眼图的扫描&…