一、MediaPlayer介绍
MediaPlayer是Android系统中一个用于播放本地或网络上的音视频文件的类,它可以播放多种音视频格式,例如MP3、MP4、3GP、AVI、MKV、FLV等。MediaPlayer功能非常强大,提供了丰富的属性和方法,可以满足多种音视频播放的需求,其中包括:
-
设置音频文件资源:MediaPlayer可以通过setDataSource()方法设置要播放的音视频文件的资源。
-
控制视频显示:如果正在播放的是视频,MediaPlayer可以通过setDisplay方法来控制视频的显示、可以在指定SurfaceView或Surface中进行显示。
-
控制音视频播放:MediaPlayer可以通过start()、pause()、stop()等方法来控制音视频文件的播放、暂停和停止。
-
监听音视频播放事件:MediaPlayer可以设置监听器,获取音视频播放状态和错误事件等,例如setOnCompletionListener()可以监听视频播放完毕的事件。
MediaPlayerService是Android中提供的一个基于Binder机制的多媒体服务,它实现了IMediaPlayerService接口,用于提供多媒体播放相关服务。MediaPlayerService在Android系统启动后就被创建,它扮演者多个应用程序之间共享音频服务的角色,例如,多个应用程序可以使用同一个MediaPlayerService来播放音频。MediaPlayerService实现了监听不同事件的Listener,如媒体播放完成、媒体出错或者出现没有音频或视频数据等情况。
MediaPlayerService可以支持多个MediaPlayer对象同时运行。MediaPlayerService还用于管理不同mediaplayer实例之间的AudioFocus,调整不同mediaplayer实例的音量,以及处理多媒体数据与AudioSession的相关信息。

二、MediaPlayer的状态图

从图中我们能看到MediaPlayer有下面的一些状态。
Idle状态及End状态
在MediaPlayer创建示例或者调用reset函数后,播放器就被创建了,这时处于Idle(就绪)状态,调用release函数后,就会变成End(结束)状态,在这两种状态之间的就是MediaPlayer的生命周期。
Error状态
在构造一个新的MediaPlayer或者调用reset函数后,上层应用程序调用getCurrentPosition、getVideoHeight、getDuration、getVideoWidth、setAudioStreamType(int)、setLooping(booleam)、setVolume(float,float)、pause、start、stop、seekTo(int)、prepare、prepareAsync这些方法会出差。如果调用reset方法后再调用它们,用户提高的回调函数OnErrorListener.onError将触发MediaPlayer状态到Error状态,所以一旦不再使用MediaPlayer,就需要调用release函数,以便MediaPlayer资源得到合理释放。
当MediaPlayer处于End状态时,它将不能再被使用,这时不能再回到MediaPlayer的其他状态,因为本次生命周期已经终止。
由于支持的音视频格式分辨率过高,输入数据流超时时,或者其它各种各样的原有将导致播放失败。在这种错误的条件下,如果用户事先通过setOnErrorListener注册过OnErrorListener,当player内部调用OnErrorListener.onError回调函数时,将会返回错误信息。一旦有错误,MediaPlayer会进入Error状态,为了重新使用MediaPlayer,调用reset方法,这时将重新恢复到Idle状态,所以需要给MediaPlayer设置错误监听,出错后就可以从播放器内部返回的信息中找到错误原有。
Initialized状态
当调用setDataSource(FileDescriptor)、setDataSource(String)、setDataSource(Context,Uri)、setDataSource(FileDescriptor,long,long)其中一个函数时,将传递MediaPlayer的Idle状态变成Initalized(初始化)状态,如果setDataSource在非Idle状态时调用,会抛出IllegalStateException异常。当重载setDataSource时,需要抛出IllegalArgumentException和IOException这两个异常。
Prepared状态
MedalPlayer有两种途径到达Prepared状态,一种是同步方式,另一种是异步方式。同步方式主要使用本地音视频文件,异步方式主要使用网络数据,需要缓冲数据。调用prepare(同步方法)将传递MediaPlayer的Initialized状态变成Prepared状态,或者调用prepareAsync(异步方法)将传递MediaPlayer的Initialized状态变成Preparing状态,最后到Prepared状态。如果应用层事先注册过setOnPreparedListener,播放器内部将会调用用户设置的OnPrepareListener中的onPrepared回调方法,注意,Preparing是一个瞬间状态。
Started状态
在MediaPlayer进入Prepare状态后,上层应用即可设置一些属性,如音视频的音量、screenOnWhilePlaying、looping等。在播放控制开始之前,必须调用start函数并成功返回,MediaPlayer的状态开始由Prepared状态变成Started状态。当处于Started状态时,如果用户事先注册过setOnBufferingUpdateListener,播放器内部会开始回调OnBufferingUpdateListener.onBufferingUpdate,这个回调方法主要使应用程序保存跟踪音频流的buffering status,如果MediaPlayer已经处于Started状态,再调用start方法是没有任何作用的。
Paused状态
MediaPlayer在播放控制时可以时Paused(暂停)和Stopped(停止)状态的,且当前的播放时进度可以被调整,当调用MediaPlayer.pause函数时,MediaPlayer开始由Started状态变成Paused状态,这个从Started状态到Paused状态的过程是瞬间的,反之在播放器内部是异步过程的。在状态更新并调用isPlaying方法前,将有一些耗时。已经缓冲过的数据流,也要耗费数秒。
当start函数从Paused状态恢复回来时,playback恢复之前暂停时的位置,接着开始播放,这时MediaPlayer的Paused状态又变成Started状态。如果MediaPlayer已经处于Paused状态,这时再调用pause方法是没有任何作用的,将保存Paused状态。
Stopped状态
当调用stop方法时,MediaPlayer无论正处于Started、Paused、Prepared或PlaybackCompleted中的哪种状态,都将进入Stopped状态。一旦处于Stoped状态,playback将不能开始,直到重新调用prepare或prepareAsync函数,且处于Prepared状态时才可以开始。
如果MediaPlayer已经处于Stopped状态了,这时在调用stop方法是没有任何作用的,将保存Stopped状态。
在Seek操作完成后,如果事先在MediaPlayer注册了setOnSeekCompleteListener,播放器内部将回调OnSeekComplete.onSeekComplete方法。当然seekTo方法也可以在其它状态下被调用,如Prepared、Paused及PlaybackCompleted状态。
PlaybackCompleted状态
当前播放的位置可以通过getCurrentPosition方法获取,通过getCurrentPosition方法,可以跟踪播放器的播放进度。
当MediaPlayer播放到数据流的末尾时,一次播放过程完成。在MediaPlayer中事先调用setLooping(boolean)并设置为true,表示循环播放,MediaPlayer依然处于Started状态。如果调用setLooping(boolean)并设置为false(表示不循环播放),并且事先在MediaPlayer上注册过setOnCompletionListener,播放器内部将回调OnCompletion.onCompletion方法,这就表面MeidaPlayer开始进入PlaybackCompleted(播放完成)状态。当处于PlaybackCompleted状态时,调用start哈数,将重启播放器从头开始播放数据。
三、MediaPlayer相关类
如下为MediaPlayer相关类图:

JAVA类
MediaPlayer
MediaPlayer代码位于:
frameworks/base/media/java/android/media/MediaPlayer.java
MediaPlayer的定义:
public class MediaPlayer extends PlayerBase implements SubtitleController.Listener, VolumeAutomation, AudioRouting {
static public class TrackInfo implements Parcelable {}
static class TimeProvider implements MediaPlayer.OnSeekCompleteListener, MediaTimeProvider {}
public final static class MetricsConstants {}
public static final class DrmInfo {}
public static final class NoDrmSchemeException extends MediaDrmException {}
public static final class ProvisioningNetworkErrorException extends MediaDrmException {}
public static final class ProvisioningServerErrorException extends MediaDrmException {}
private class ProvisioningThread extends Thread {}
private class EventHandler extends Handler {}
private class OnDrmInfoHandlerDelegate {}
private class OnDrmPreparedHandlerDelegate {}
public interface OnPreparedListener {}
public interface OnCompletionListener {}
public interface OnBufferingUpdateListener {}
public interface OnSeekCompleteListener {}
public interface OnVideoSizeChangedListener {}
public interface OnTimedTextListener {}
public interface OnSubtitleDataListener {}
public interface OnMediaTimeDiscontinuityListener {}
public interface OnTimedMetaDataAvailableListener {}
public interface OnRtpRxNoticeListener {}
public interface OnErrorListener {}
public interface OnInfoListener {}
public interface OnDrmConfigHelper {}
public interface OnDrmInfoListener {}
public interface OnDrmPreparedListener {}
}
PlayerBase
PlayerBase是一个Android平台的抽象类,是MediaPlayer和AudioTrack等音视频播放器的基类,提供了部分公共的属性和方法。PlayerBase中封装了播放器的状态以及状态转换的方法,同时提供了一个Handler用于处理内部的消息,保证了内部交互的同步性和可靠性。另外,PlayerBase中也提供了一些常用的变量。子类可以继承并实现PlayerBase的抽象方法,然后使用该类提供的状态的变化来实现相应的逻辑。
PlayerBase代码位于:
frameworks/base/media/java/android/media/PlayerBase.java
PlayerBase的定义:
public abstract class PlayerBase {
private static class IPlayerWrapper extends IPlayer.Stub {}
public static class PlayerIdCard implements Parcelable {}
}
C++类
IMediaPlayerService
IMediaPlayerService代码位于:
frameworks/av/media/libmedia/include/media/IMediaPlayerService.h
IMediaPlayerService的定义:
class IMediaPlayerService: public IInterface {}
class BnMediaPlayerService: public BnInterface<IMediaPlayerService> {}
IStreamSource
IStreamSource代码位于:
frameworks/av/media/libmedia/include/media/IStreamSource.h
IStreamSource的定义:
struct IStreamSource : public IInterface {}
struct IStreamListener : public IInterface {}
struct BnStreamSource : public BnInterface<IStreamSource> {}
struct BnStreamListener : public BnInterface<IStreamListener> {}
IMediaPlayer
IMediaPlayer代码位于:
frameworks/av/media/libmedia/IMediaPlayer.cpp
frameworks/av/media/libmedia/IMediaPlayer.h
IMediaPlayer的定义:
class IMediaPlayer: public IInterface {}
class BnMediaPlayer: public BnInterface<IMediaPlayer> {}
class BpMediaPlayer: public BpInterface<IMediaPlayer> {}
IMediaPlayerClient
IMediaPlayerClient代码位于:
frameworks/av/media/libmedia/IMediaPlayerClient.cpp
frameworks/av/media/libmedia/IMediaPlayerClient.h
IMediaPlayerClient的定义:
class IMediaPlayerClient: public IInterface {}
class BnMediaPlayerClient: public BnInterface<IMediaPlayerClient> {}
class BpMediaPlayerClient: public BpInterface<IMediaPlayerClient> {}
IMediaDeathNotifier
IMediaDeathNotifier代码位于:
frameworks/av/media/libmedia/IMediaDeathNotifier.cpp
frameworks/av/media/libmedia/IMediaDeathNotifier.h
IMediaDeathNotifier的定义:
class IMediaDeathNotifier: virtual public RefBase {}
IDataSource
DataSource描述一个数据源头, 一个文件, 一个流等, 通常以IDataSource向外提供数据源的操作接口,实现为DataURISource、FileSource、HTTPBase、NuCachedSource2。
IDataSource代码位于:
frameworks/av/media/libmedia/IDataSource.cpp
frameworks/av/media/libmedia/include/android/IDataSource.h
IDataSource的定义:
class IDataSource : public IInterface {}
class BnDataSource : public BnInterface<IDataSource> {}
IMediaSource
IMediaSource代码位于:
frameworks/av/media/libmedia/IMediaSource.cpp
frameworks/av/media/libmedia/include/media/IMediaSource.h
IMediaSource的定义:
class IMediaSource : public IInterface {}
class RemoteMediaBufferWrapper : public MediaBuffer {}
class BnMediaSource: public BnInterface<IMediaSource> {}
class BpMediaSource : public BpInterface<IMediaSource> {}
MediaPlayer
MediaPlayer代码位于:
frameworks/av/media/libmedia/MediaPlayer.cpp
frameworks/av/media/libmedia/include/media/MediaPlayer.h
MediaPlayer的定义:
class MediaPlayerListener: virtual public RefBase {}
class MediaPlayer : public BnMediaPlayerClient, public virtual IMediaDeathNotifier {}
四、MediaPlayer API
public native int getAudioSessionId():Returns the audio session ID.
public native int getCurrentPosition():Gets the current playback position.
public native int getDuration():Gets the duration of the file.
public native int getVideoWidth():Returns the width of the video.
public native int getVideoHeight():Returns the height of the video.
public TrackInfo[] getTrackInfo() :Returns an array of track information.
public native boolean isPlaying():Checks whether the MediaPlayer is playing.
public native boolean isLooping():Checks whether the MediaPlayer is looping or non-looping.
public static MediaPlayer create(Context context, Uri uri) :Convenience method to create a MediaPlayer for a given Uri.
public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder) :Convenience method to create a MediaPlayer for a given Uri.
public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder, AudioAttributes audioAttributes, int audioSessionId) :Same factory method as {@link #create(Context, Uri, SurfaceHolder)} but that lets you specify the audio attributes and session ID to be used by the new MediaPlayer instance.
public static MediaPlayer create(Context context, int resid):Convenience method to create a MediaPlayer for a given resource id.
public static MediaPlayer create(Context context, int resid, AudioAttributes audioAttributes, int audioSessionId):Same factory method as {@link #create(Context, int)} but that lets you specify the audio attributes and session ID to be used by the new MediaPlayer instance.
public void start():Starts or resumes playback.
public void stop():Stops playback after playback has been started or paused.
public void pause() :Pauses playback. Call start() to resume.
public void prepare():Prepares the player for playback, synchronously.
public void release():Releases resources associated with this MediaPlayer object.
public void reset():Resets the MediaPlayer to its uninitialized state.
public void seekTo(long msec, @SeekMode int mode):Moves the media to specified time position by considering the given mode.
public void setDisplay(SurfaceHolder sh) :Sets the SurfaceHolder to use for displaying the video portion of the media.
public void setSurface(Surface surface) :Sets the Surface to be used as the sink for the video portion of the media.
public void setVideoScalingMode(int mode) :Sets video scaling mode.
public void setDataSource(String path):Sets the data source (file-path or http/rtsp URL) to use.
public void setDataSource(@NonNull Context context, @NonNull Uri uri):Sets the data source as a content Uri.
public void setDataSource(@NonNull Context context, @NonNull Uri uri, @Nullable Map<String, String> headers):Sets the data source as a content Uri.
public void setDataSource(@NonNull Context context, @NonNull Uri uri, @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies):Sets the data source as a content Uri.
public void setDataSource(@NonNull AssetFileDescriptor afd):Sets the data source (AssetFileDescriptor) to use. It is the caller's responsibility to close the file descriptor.
public void setDataSource(FileDescriptor fd):Sets the data source (FileDescriptor) to use. It is the caller's responsibility to close the file descriptor.
public void setDataSource(FileDescriptor fd, long offset, long length):Sets the data source (FileDescriptor) to use.
public void setDataSource(MediaDataSource dataSource):Sets the data source (MediaDataSource) to use.
public void setAudioAttributes(AudioAttributes attributes):Sets the audio attributes for this MediaPlayer.
public void setAudioStreamType(int streamtype):Sets the audio stream type for this MediaPlayer.
public void setAudioSessionId(int sessionId):Sets the audio session ID.
public void setVolume(float leftVolume, float rightVolume) :Sets the volume on this player.
public void setScreenOnWhilePlaying(boolean screenOn):Control whether we should use the attached SurfaceHolder to keep the screen on while video playback is occurring.
public void setWakeMode(Context context, int mode) :Set the low-level power management behavior for this MediaPlayer.
public void addTimedTextSource(FileDescriptor fd, long offset, long length, String mime):Adds an external timed text file (FileDescriptor).
public void selectTrack(int index) :Selects a track.
public void deselectTrack(int index) :Deselect a track.
public native void setLooping(boolean looping):Sets the player to be looping or non-looping.
public native void setPlaybackParams(@NonNull PlaybackParams params):Sets playback rate using {@link PlaybackParams}.
public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener):Register a callback to be invoked when the status of a network stream's buffer has changed.
public void setOnCompletionListener(OnCompletionListener listener):Register a callback to be invoked when the end of a media source has been reached during playback.
public void setOnErrorListener(OnErrorListener listener):Register a callback to be invoked when an error has happened during an asynchronous operation.
public void setOnInfoListener(OnInfoListener listener):Register a callback to be invoked when an info/warning is available.
public void setOnPreparedListener(OnPreparedListener listener):Register a callback to be invoked when the media source is ready for playback.
public void setOnSeekCompleteListener(OnSeekCompleteListener listener):Register a callback to be invoked when a seek operation has been completed.
public void setOnTimedTextListener(OnTimedTextListener listener):Register a callback to be invoked when a timed text is available for display.
public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener):Register a callback to be invoked when the video size is known or updated.
五、MediaPlayer流程分析
MediaPlayer创建流程分析
Android13 MediaPlayer 创建流程分析-CSDN博客
MediaPlayer setDataSource流程分析
(692) MediaPlayer setDataSource流程分析 | 知识管理 - PingCode
MediaPlayer setDisplay流程分析
Android13 MediaPlayer setDisplay流程分析-CSDN博客
MediaPlayer prepare流程分析
Android13 MediaPlayer prepare流程分析-CSDN博客

9333

被折叠的 条评论
为什么被折叠?



