Android MediaPlayer接口及状态迁移
[时间:2016-09] [状态:Open]
[关键词:android,mediaplayer,播放接口,播放状态图]
引言
本文内容相对简单,作为后续处理的起点,简要整理了Android MediaPlayer的接口层,并且这里只会涉及c层的实现,至于上层的JNI/跨进程调用逻辑,建议参考其他资料。
整理本文的目的仅供个人后续参考使用。
MediaPlayer Interface
我们可以在Android源码中找到MediaPlayerInterface的定义如下:(这里只列出接口信息,详细内容建议参考源码)
// from frameworks/av/include/media/MediaPlayerInterface.h
// abstract base class - use MediaPlayerInterface
class MediaPlayerBase : public RefBase
{
public:
// AudioSink: abstraction layer for audio output
class AudioSink : public RefBase {...};
MediaPlayerBase() : mCookie(0), mNotify(0) {}
virtual ~MediaPlayerBase() {}
virtual status_t initCheck() = 0;
virtual bool hardwareOutput() = 0;
virtual status_t setUID(uid_t /* uid */);
virtual status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers = NULL) = 0;
virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0;
virtual status_t setDataSource(const sp<IStreamSource>& /* source */);
virtual status_t setDataSource(const sp<DataSource>& /* source */);
// pass the buffered IGraphicBufferProducer to the media player service
virtual status_t setVideoSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) = 0;
virtual status_t prepare() = 0;
virtual status_t prepareAsync() = 0;
virtual status_t start() = 0;
virtual status_t stop() = 0;
virtual status_t pause() = 0;
virtual bool isPlaying() = 0;
virtual status_t setPlaybackSettings(const AudioPlaybackRate& rate);
virtual status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
virtual status_t setSyncSettings(const AVSyncSettings& sync, float /* videoFps */);
virtual status_t getSyncSettings(AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */);
virtual status_t seekTo(int msec) = 0;
virtual status_t getCurrentPosition(int *msec) = 0;
virtual status_t getDuration(int *msec) = 0;
virtual status_t reset() = 0;
virtual status_t setLooping(int loop) = 0;
virtual player_type playerType() = 0;
virtual status_t setParameter(int key, const Parcel &request) = 0;
virtual status_t getParameter(int key, Parcel *reply) = 0;
// default no-op implementation of optional extensions
virtual status_t setRetransmitEndpoint(const struct sockaddr_in* /* endpoint */);
virtual status_t getRetransmitEndpoint(struct sockaddr_in* /* endpoint */);
virtual status_t setNextPlayer(const sp<MediaPlayerBase>& /* next */);
virtual status_t invoke(const Parcel& request, Parcel *reply) = 0;
virtual status_t getMetadata(const media::Metadata::Filter& /* ids */, Parcel* /* records */);
void setNotifyCallback(void* cookie, notify_callback_f notifyFunc);
void sendEvent(int msg, int ext1=0, int ext2=0, const Parcel *obj=NULL);
virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const;
private:
friend class MediaPlayerService;
Mutex mNotifyLock;
void* mCookie;
notify_callback_f mNotify;
};
// Implement this class for media players that use the AudioFlinger software mixer
class MediaPlayerInterface : public MediaPlayerBase
{
public:
virtual ~MediaPlayerInterface() { }
virtual bool hardwareOutput() { return false; }
virtual void setAudioSink(const sp<AudioSink>& audioSink) { mAudioSink = audioSink; }
protected:
sp<AudioSink> mAudioSink;
};
// Implement this class for media players that output audio directly to hardware
class MediaPlayerHWInterface : public MediaPlayerBase
{
public:
virtual ~MediaPlayerHWInterface() {}
virtual bool hardwareOutput() { return true; }
virtual status_t setVolume(float leftVolume, float rightVolume) = 0;
virtual status_t setAudioStreamType(audio_stream_type_t streamType) = 0;
};
通常我们的调用逻辑是,构造函数->setDataSource->SetVideoSurfaceTexture->prepare/prepareAsync->start->stop->reset->析构函数,按照实际需求还会调用pause、isPlaying、getDuration、getCurrentPosition、setLooping、seekTo等。
各个接口具体含义参考下表:
| 方法 | 说明 |
|---|---|
| setDataSource | 设置多媒体数据来源(位置) |
| setVideoSurfaceTexture | 设置用SurfaceHolder来显示多媒体 |
| prepare | 准备(同步) |
| prepareAsync | 准备(异步) |
| start | 开始播放 |
| stop | 停止播放 |
| reset | 重置MediaPlayer对象为刚刚创建的状态 |
| getCurrentPosition | 得到当前播放位置 |
| getDuration | 得到文件的时间 |
| isPlaying | 是否正在播放 |
| pause | 暂停 |
| seekTo | 指定播放的位置(以毫秒为单位的时间) |
| setLooping | 设置是否循环播放 |
MediaPlayer状态图
MediaPlayer的状态图如下:

这个状态图对应的java层的MediaPlayer。不过可以参考,在实际的源码实现时,不会完全参考这个状态图,可能有更多的内部状态和简化状态。
比如,你可以不调用prepare,直接调用start。
图中各个状态的迁移,建议参考MediaPlayer的官方文档。
参考资料
Android MediaPlayer接口及状态迁移的更多相关文章
- android MediaPlayer API大全已经方法详解(转载)
通过这张图,我们可以知道一个MediaPlayer对象有以下的状态: 1)当一个MediaPlayer对象被刚刚用new操作符创建或是调用了reset()方法后,它就处于Idle状态.当调用了rele ...
- Android MediaPlayer状态机
对播放音频/视频文件和流的控制是通过一个状态机来管理的.下图显示一个MediaPlayer对象被支持的播放控制操作驱动的生命周期和状态.椭圆代表MediaPlayer对象可能驻留的状态.弧线表示驱动M ...
- 学习Android MediaPlayer
Android Media Playback 原文 The Android multimedia framework includes support for playing variety of c ...
- 翻译的很好的一篇android mediaplayer
MediaPlayer类可用于控制音频/视频文件或流的播放.关于如何使用这个类的方法还可以阅读VideoView类的文档. 1.状态图对播放音频/视频文件和流的控制是通过一个状态机来管理的.下图显示一 ...
- Android MediaPlayer和VideoView的使用
MediaPlayer MediaPlayer类是Androd多媒体框架中的一个重要组件,通过该类,我们可以以最小的步骤来获取,解码和播放音视频.它支持三种不同的媒体来源: 本地资源 内部 ...
- [转]Android MediaPlayer状态机
翻译Android Reference Manual的MediaPlayer的状态机 对播放音频/视频文件和流的控制是通过一个状态机来管理的.下图显示一个MediaPlayer对象被支持的播放控制操作 ...
- Android MediaPlayer 在 6.0 以上版本使用倍速播放功能说明
Android MediaPlayer 在API 23即6.0版本开始支持倍速播放,下面我们来介绍一下如何使用MediaPlayer进行倍速播放. 一.核心接口 MediaPlayer.setPlay ...
- Android MediaPlayer的生命周期
MediaPlayer的状态转换图也表征了它的生命周期,如下: 这张状态转换图清晰的描述了MediaPlayer的各个状态,也列举了主要的方法的调用时序,每种方法只能在一些特定的状态下使用,如果使用时 ...
- Android MediaPlayer Error/Info Code
1. 常见错误 error(-38, 0) 我觉得-38表示在当前的MediaPlayer状态下,不能运行你的操作. 详细怎样做请參考:Android MediaPlayer 另外我在其它资料中.发现 ...
随机推荐
- UCP规模估算方法介绍 基于UCP方法的软件项目成本估计及其应用方法,软件,项目,UCP方法,应用,项目估算及软件及应用,软件估算,项目成本,软件项目
基于UCP方法的软件项目成本估计及其应用 UCP说明: UCP = 交易的UCP数 + Actor的UCP数,1.交易/Actor在估算时按复杂度分为简单.普通.复杂.主观类别,权重分别对应1.2.3 ...
- Tomcat 6 部署工程总结,使用JNDI数据源配置
工程需要用JNDI数据源方式部署到tomcat,参考网上文章后,经过配置测试,摸索出来了. 环境说明: 数据库:Oracle9i Web服务器:tomcat-6.0.33 tomcat启动方式 ...
- 淘宝JAVA中间件Diamond详解之简介&快速使用 管理持久配置的系统
http://my.oschina.net/u/435621/blog/270483?p=1 淘宝JAVA中间件Diamond详解(一)---简介&快速使用 大家好,今天开始为大家带来我们通用 ...
- shell脚本中解决SCP命令需要输入密码的问题
使用密钥文件. 这里假设主机A(192.168.100.3)用来获到主机B(192.168.100.4)的文件. 在主机A上执行如下命令来生成配对密钥: ssh-keygen -t r ...
- OpenCV 学习笔记03 findContours函数
opencv-python 4.0.1 1 函数释义 词义:发现轮廓! 从二进制图像中查找轮廓(Finds contours in a binary image):轮廓是形状分析和物体检测和识别的 ...
- React Native工程修改Android包名
默认初始化的React Native工程,生成Android工程的时候,包名默认是React Native工程的名字,跟一般Android工程com.company.xxx不一样. 这时候就需要手动修 ...
- MVC摘记
2013年9月23日18:04:06 直接cshtml页面的js中使用 var customerId = @(ViewBag.Oppotunity as OppotunityDto==null ...
- easyui刷新指定tab页里面的数据
主页Home/Index中使用tab管理,在主页中设置一个刷新的方法. /** * 刷新指定的tab里面的数据 * @param title 选项卡标题 * @param refreshTabFunc ...
- HANA初印象
今天手懒,看了一些SAP HANA 的一些外文介绍,不翻译了,直接剽窃过来,供参考. 1. HANA 是什么东西? “HANA doesn't actually mean anything, but ...
- python中数组与多维数组用法介绍
增加时a.append( 'a ')就可以了.只要按顺序加,就没有问题 . 使用时,完全可以使用下标: 代码如下 复制代码 a[0] a[1] 但出果引用不存在的下标,则会引发异常.这时,你需要先添加 ...