一、MediaPlayer状态
Android官网上赫然挂着这张MediaPlayer状态图,熟悉这张图,对了解MediaPlayer的工作原理有很大的帮助;
下图中,单箭头表示同步调用,双箭头表示异步调用;
mediaplayer_state_diagram.gif
- MediaPlayer 创建实例或者在调用reset方法之后,播放器处于Idle状态;
- MediaPlayer 有prepare 和 prepareAysnc两种方法,prepare 针对本地音视频,是同步的;prepareAsync针对网络音视频,异步的;
- MediaPlayer在播放中调用pause函数,Started ---> Paused 状态切换是瞬间的;但是再次调用 MediaPlayer.start函数,Paused ---> Started 状态切换需要一些耗时;即时是本地音视频,也是需要一些耗时的;
- MediaPlayer 进入onPrepared状态,才可以设置一些属性,例如 音量、 screenOnWhilePlaying looping;第一次调start函数有效,后续调用无效;
- MediaPlayer.stop ---> 播放器进入Stopped状态,这事想要重新激活,可以重新调用prepare / prepareAsync 函数
二、MediaPlayer 调用流程剖析
MediaPlayer 从启动,初始化,setDataSource,到 setSurface 步骤的操作过程;
MediaPlayer.png MediaPlayer 类关系
本章讲解涉及到的源码路径:
/frameworks/base/media/java/android/media/MediaPlayer.java
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
/frameworks/av/media/libmedia/mediaplayer.cpp
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
/frameworks/av/include/media/MediaPlayerInterface.h
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
/frameworks/av/media/libmedia/mediaplayer.cpp
下面从源码的角度分析一下重要的执行流程:
/frameworks/av/media/libmedia/mediaplayer.cpp
175status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
176{
177 ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
178 status_t err = UNKNOWN_ERROR;
179 const sp<IMediaPlayerService> service(getMediaPlayerService());
180 if (service != 0) {
181 sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
182 if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
183 (NO_ERROR != player->setDataSource(fd, offset, length))) {
184 player.clear();
185 }
186 err = attachNewPlayer(player);
187 }
188 return err;
189}
执行了:
sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
313sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
314 audio_session_t audioSessionId)
315{
316 pid_t pid = IPCThreadState::self()->getCallingPid();
317 int32_t connId = android_atomic_inc(&mNextConnId);
318
319 sp<Client> c = new Client(
320 this, pid, connId, client, audioSessionId,
321 IPCThreadState::self()->getCallingUid());
322
323 ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
324 IPCThreadState::self()->getCallingUid());
325
326 wp<Client> w = c;
327 {
328 Mutex::Autolock lock(mLock);
329 mClients.add(w);
330 }
331 return c;
332}
调用到MediaPlayerService::Client 类中:
795status_t MediaPlayerService::Client::setDataSource(
796 const sp<IMediaHTTPService> &httpService,
797 const char *url,
798 const KeyedVector<String8, String8> *headers)
799{
800 ALOGV("setDataSource(%s)", url);
801 if (url == NULL)
802 return UNKNOWN_ERROR;
803
804 if ((strncmp(url, "http://", 7) == 0) ||
805 (strncmp(url, "https://", 8) == 0) ||
806 (strncmp(url, "rtsp://", 7) == 0)) {
807 if (!checkPermission("android.permission.INTERNET")) {
808 return PERMISSION_DENIED;
809 }
810 }
811
812 if (strncmp(url, "content://", 10) == 0) {
813 // get a filedescriptor for the content Uri and
814 // pass it to the setDataSource(fd) method
815
816 String16 url16(url);
817 int fd = android::openContentProviderFile(url16);
818 if (fd < 0)
819 {
820 ALOGE("Couldn't open fd for %s", url);
821 return UNKNOWN_ERROR;
822 }
823 status_t status = setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
824 close(fd);
825 return mStatus = status;
826 } else {
827 player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
828 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
829 if (p == NULL) {
830 return NO_INIT;
831 }
832
833 return mStatus =
834 setDataSource_post(
835 p, p->setDataSource(httpService, url, headers));
836 }
837}
重点关注这个代码片段的执行流程:
827 player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
828 sp<MediaPlayerBase> p = setDataSource_pre(playerType);
829 if (p == NULL) {
830 return NO_INIT;
831 }
832
833 return mStatus =
834 setDataSource_post(
835 p, p->setDataSource(httpService, url, headers));
这儿会执行两个函数:
setDataSource_pre
setDataSource_post
从字面上可以理解,一个是setDataSource 执行前,一个是setDataSource执行后;
724sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
725 player_type playerType)
726{
727 ALOGV("player type = %d", playerType);
728
729 // create the right type of player
730 sp<MediaPlayerBase> p = createPlayer(playerType);
731 if (p == NULL) {
732 return p;
733 }
734
735 sp<IServiceManager> sm = defaultServiceManager();
736 sp<IBinder> binder = sm->getService(String16("media.extractor"));
737 if (binder == NULL) {
738 ALOGE("extractor service not available");
739 return NULL;
740 }
741 sp<ServiceDeathNotifier> extractorDeathListener =
742 new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
743 binder->linkToDeath(extractorDeathListener);
744
745 sp<IOmx> omx = IOmx::getService();
746 if (omx == nullptr) {
747 ALOGE("IOmx service is not available");
748 return NULL;
749 }
750 sp<ServiceDeathNotifier> codecDeathListener =
751 new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
752 omx->linkToDeath(codecDeathListener, 0);
753
754 Mutex::Autolock lock(mLock);
755
756 clearDeathNotifiers_l();
757 mExtractorDeathListener = extractorDeathListener;
758 mCodecDeathListener = codecDeathListener;
759 mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
760
761 if (!p->hardwareOutput()) {
762 mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
763 mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
764 static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
765 }
766
767 return p;
768}
- 获取 media.extractor 服务;
- 获取omx服务;
这两个服务在视频解析和解码的流程中非常重要;
其中在mediaplayer.cpp 中有调用 getMediaPlayerService()函数,具体是在
/frameworks/av/media/libmedia/IMediaDeathNotifier.cpp
// establish binder interface to MediaPlayerService
/*static*/const sp<IMediaPlayerService>
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
ALOGW("Media player service not published, waiting...");
usleep(500000); // 0.5 s
} while (true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
调用的是初始化定义的media.player服务,就实现从Client到Server端之间的调用;
/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
241void MediaPlayerFactory::registerBuiltinFactories() {
242 Mutex::Autolock lock_(&sLock);
243
244 if (sInitComplete)
245 return;
246
247 IFactory* factory = new NuPlayerFactory();
248 if (registerFactory_l(factory, NU_PLAYER) != OK)
249 delete factory;
250 factory = new TestPlayerFactory();
251 if (registerFactory_l(factory, TEST_PLAYER) != OK)
252 delete factory;
253
254 sInitComplete = true;
255}
MediaPlayerFactory.cpp是管理播放器的一个工厂类,从源码中可以看出来,目前只有一个NuPlayerFactory 管理类了,TestPlayerFactory 是测试使用的,可以忽略;
NuPlayerFactory工厂类源码如下:
164/*****************************************************************************
165 * *
166 * Built-In Factory Implementations *
167 * *
168 *****************************************************************************/
169
170class NuPlayerFactory : public MediaPlayerFactory::IFactory {
171 public:
172 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
173 const char* url,
174 float curScore) {
175 static const float kOurScore = 0.8;
176
177 if (kOurScore <= curScore)
178 return 0.0;
179
180 if (!strncasecmp("http://", url, 7)
181 || !strncasecmp("https://", url, 8)
182 || !strncasecmp("file://", url, 7)) {
183 size_t len = strlen(url);
184 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
185 return kOurScore;
186 }
187
188 if (strstr(url,"m3u8")) {
189 return kOurScore;
190 }
191
192 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
193 return kOurScore;
194 }
195 }
196
197 if (!strncasecmp("rtsp://", url, 7)) {
198 return kOurScore;
199 }
200
201 return 0.0;
202 }
203
204 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
205 const sp<IStreamSource>& /*source*/,
206 float /*curScore*/) {
207 return 1.0;
208 }
209
210 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
211 const sp<DataSource>& /*source*/,
212 float /*curScore*/) {
213 // Only NuPlayer supports setting a DataSource source directly.
214 return 1.0;
215 }
216
217 virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
218 ALOGV(" create NuPlayer");
219 return new NuPlayerDriver(pid);
220 }
221};
最终createPlayer中是实例化一个NuPlayerDriver对象;
这儿判断是否是m3u8视频类型简直是简单粗暴啊;
- url的后缀名是不是.m3u8;
- url中是否包含 m3u8 字符串;
184 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
185 return kOurScore;
186 }
187
188 if (strstr(url,"m3u8")) {
189 return kOurScore;
190 }
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
71NuPlayerDriver::NuPlayerDriver(pid_t pid)
72 : mState(STATE_IDLE),
73 mIsAsyncPrepare(false),
74 mAsyncResult(UNKNOWN_ERROR),
75 mSetSurfaceInProgress(false),
76 mDurationUs(-1),
77 mPositionUs(-1),
78 mSeekInProgress(false),
79 mPlayingTimeUs(0),
80 mRebufferingTimeUs(0),
81 mRebufferingEvents(0),
82 mRebufferingAtExit(false),
83 mLooper(new ALooper),
84 mMediaClock(new MediaClock),
85 mPlayer(new NuPlayer(pid, mMediaClock)),
86 mPlayerFlags(0),
87 mAnalyticsItem(NULL),
88 mClientUid(-1),
89 mAtEOS(false),
90 mLooping(false),
91 mAutoLoop(false) {
92 ALOGD("NuPlayerDriver(%p) created, clientPid(%d)", this, pid);
93 mLooper->setName("NuPlayerDriver Looper");
94
95 mMediaClock->init();
96
97 // set up an analytics record
98 mAnalyticsItem = new MediaAnalyticsItem(kKeyPlayer);
99
100 mLooper->start(
101 false, /* runOnCallingThread */
102 true, /* canCallJava */
103 PRIORITY_AUDIO);
104
105 mLooper->registerHandler(mPlayer);
106
107 mPlayer->init(this);
108}
mPlayer(new NuPlayer(pid, mMediaClock)),
setDataSource 会执行到NuPlayer.cpp 中:
257void NuPlayer::setDataSourceAsync(
258 const sp<IMediaHTTPService> &httpService,
259 const char *url,
260 const KeyedVector<String8, String8> *headers) {
261
262 sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
263 size_t len = strlen(url);
264
265 sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
266
267 sp<Source> source;
268 if (IsHTTPLiveURL(url)) {
269 source = new HTTPLiveSource(notify, httpService, url, headers);
270 ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
271 mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
272 } else if (!strncasecmp(url, "rtsp://", 7)) {
273 source = new RTSPSource(
274 notify, httpService, url, headers, mUIDValid, mUID);
275 ALOGV("setDataSourceAsync RTSPSource %s", url);
276 mDataSourceType = DATA_SOURCE_TYPE_RTSP;
277 } else if ((!strncasecmp(url, "http://", 7)
278 || !strncasecmp(url, "https://", 8))
279 && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
280 || strstr(url, ".sdp?"))) {
281 source = new RTSPSource(
282 notify, httpService, url, headers, mUIDValid, mUID, true);
283 ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
284 mDataSourceType = DATA_SOURCE_TYPE_RTSP;
285 } else {
286 ALOGV("setDataSourceAsync GenericSource %s", url);
287
288 sp<GenericSource> genericSource =
289 new GenericSource(notify, mUIDValid, mUID, mMediaClock);
290
291 status_t err = genericSource->setDataSource(httpService, url, headers);
292
293 if (err == OK) {
294 source = genericSource;
295 } else {
296 ALOGE("Failed to set data source!");
297 }
298
299 // regardless of success/failure
300 mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
301 }
302 msg->setObject("source", source);
303 msg->post();
304}
通过NuPlayer.cpp 内部定义的AMessage 消息来控制:
548void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
549 switch (msg->what()) {
550 case kWhatSetDataSource:
551 {
552 ALOGV("kWhatSetDataSource");
553
554 CHECK(mSource == NULL);
555
556 status_t err = OK;
557 sp<RefBase> obj;
558 CHECK(msg->findObject("source", &obj));
559 if (obj != NULL) {
560 Mutex::Autolock autoLock(mSourceLock);
561 mSource = static_cast<Source *>(obj.get());
562 } else {
563 err = UNKNOWN_ERROR;
564 }
565
566 CHECK(mDriver != NULL);
567 sp<NuPlayerDriver> driver = mDriver.promote();
568 if (driver != NULL) {
569 driver->notifySetDataSourceCompleted(err);
570 }
571 break;
572 }
接收到消息,将传入的source赋给mSource对象;
根据url来封装source:
267 sp<Source> source;
268 if (IsHTTPLiveURL(url)) {
269 source = new HTTPLiveSource(notify, httpService, url, headers);
270 ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
271 mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
272 } else if (!strncasecmp(url, "rtsp://", 7)) {
273 source = new RTSPSource(
274 notify, httpService, url, headers, mUIDValid, mUID);
275 ALOGV("setDataSourceAsync RTSPSource %s", url);
276 mDataSourceType = DATA_SOURCE_TYPE_RTSP;
277 } else if ((!strncasecmp(url, "http://", 7)
278 || !strncasecmp(url, "https://", 8))
279 && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
280 || strstr(url, ".sdp?"))) {
281 source = new RTSPSource(
282 notify, httpService, url, headers, mUIDValid, mUID, true);
283 ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
284 mDataSourceType = DATA_SOURCE_TYPE_RTSP;
285 } else {
286 ALOGV("setDataSourceAsync GenericSource %s", url);
287
288 sp<GenericSource> genericSource =
289 new GenericSource(notify, mUIDValid, mUID, mMediaClock);
290
291 status_t err = genericSource->setDataSource(httpService, url, headers);
292
293 if (err == OK) {
294 source = genericSource;
295 } else {
296 ALOGE("Failed to set data source!");
297 }
298
299 // regardless of success/failure
300 mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
301 }
/frameworks/av/include/media/stagefright/foundation/AHandler.h
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
/frameworks/av/media/libmediaplayerservice/nuplayer/StreamingSource.h
/frameworks/av/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
/frameworks/av/media/libmediaplayerservice/nuplayer/GenericSource.h
/frameworks/av/media/libmediaplayerservice/nuplayer/RTSPSource.h
MediaPlayer Source 类关系HTTPLiveSource:针对m3u8 视频,实际上直播不止m3u8一种类型,MediaPlayer 支持有限;
RTSPSource:这是针对RTSP的流,MediaPlayer专门针对RTSP的流做了优化;
GenericSource:通用的source,一些http https file:///协议的url都是走这儿的;
240static bool IsHTTPLiveURL(const char *url) {
241 if (!strncasecmp("http://", url, 7)
242 || !strncasecmp("https://", url, 8)
243 || !strncasecmp("file://", url, 7)) {
244 size_t len = strlen(url);
245 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
246 return true;
247 }
248
249 if (strstr(url,"m3u8")) {
250 return true;
251 }
252 }
253
254 return false;
255}
setVideoSurfaceTexture 执行到 MediaPlayerService.cpp:
916status_t MediaPlayerService::Client::setVideoSurfaceTexture(
917 const sp<IGraphicBufferProducer>& bufferProducer)
918{
919 ALOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, bufferProducer.get());
920 sp<MediaPlayerBase> p = getPlayer();
921 if (p == 0) return UNKNOWN_ERROR;
922
923 sp<IBinder> binder(IInterface::asBinder(bufferProducer));
924 if (mConnectedWindowBinder == binder) {
925 return OK;
926 }
927
928 sp<ANativeWindow> anw;
929 if (bufferProducer != NULL) {
930 anw = new Surface(bufferProducer, true /* controlledByApp */);
931 status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture");
932
933 if (err != OK) {
934 ALOGE("setVideoSurfaceTexture failed: %d", err);
935 // Note that we must do the reset before disconnecting from the ANW.
936 // Otherwise queue/dequeue calls could be made on the disconnected
937 // ANW, which may result in errors.
938 reset();
939
940 Mutex::Autolock lock(mLock);
941 disconnectNativeWindow_l();
942
943 return err;
944 }
945 }
946
947 // Note that we must set the player's new GraphicBufferProducer before
948 // disconnecting the old one. Otherwise queue/dequeue calls could be made
949 // on the disconnected ANW, which may result in errors.
950 status_t err = p->setVideoSurfaceTexture(bufferProducer);
951
952 mLock.lock();
953 disconnectNativeWindow_l();
954
955 if (err == OK) {
956 mConnectedWindow = anw;
957 mConnectedWindowBinder = binder;
958 mLock.unlock();
959 } else {
960 mLock.unlock();
961 status_t err = nativeWindowDisconnect(
962 anw.get(), "disconnectNativeWindow");
963
964 if (err != OK) {
965 ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
966 strerror(-err), err);
967 }
968 }
969
970 return err;
971}
创建一个Surface对象:
930 anw = new Surface(bufferProducer, true /* controlledByApp */);
931 status_t err = nativeWindowConnect(anw.get(), "setVideoSurfaceTexture");
950 status_t err = p->setVideoSurfaceTexture(bufferProducer);
这个p 对象就是 MediaPlayerFactory 中定义的 NuPlayer对象;
上面也说过了NuPlayer 是在NuPlayerDriver中定义的;
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
377void NuPlayer::setVideoSurfaceTextureAsync(
378 const sp<IGraphicBufferProducer> &bufferProducer) {
379 sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
380
381 if (bufferProducer == NULL) {
382 msg->setObject("surface", NULL);
383 } else {
384 msg->setObject("surface", new Surface(bufferProducer, true /* controlledByApp */));
385 }
386
387 msg->post();
388}
发送一个异步消息通知设置Surface成功了;
Surface设置成功了,setDataSource 也设置成功了,接下来开始发起请求了,MediaPlayer发起请求的函数是prepare 或者 prepareAsync 函数,一个是同步请求,一个是异步请求,建议还是使用异步请求,毕竟网络请求有时候比较慢;
下面主要分析MediaPlayer->prepareAsync 执行流程:
MediaPlayer->prepareAsync调用流程
/frameworks/av/media/libmedia/mediaplayer.cpp
中持有的mPlayer 对象就是 MediaPlayerService::Client 对象;
273status_t MediaPlayer::prepareAsync_l()
274{
275 if ( (mPlayer != 0) && ( mCurrentState & (MEDIA_PLAYER_INITIALIZED | MEDIA_PLAYER_STOPPED) ) ) {
276 if (mAudioAttributesParcel != NULL) {
277 mPlayer->setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, *mAudioAttributesParcel);
278 } else {
279 mPlayer->setAudioStreamType(mStreamType);
280 }
281 mCurrentState = MEDIA_PLAYER_PREPARING;
282 return mPlayer->prepareAsync();
283 }
284 ALOGE("prepareAsync called in state %d, mPlayer(%p)", mCurrentState, mPlayer.get());
285 return INVALID_OPERATION;
286}
上面两个都是设置一些播放过程中的基本参数,主要是mPlayer->prepareAsync()
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
306status_t NuPlayerDriver::prepareAsync() {
307 ALOGV("prepareAsync(%p)", this);
308 Mutex::Autolock autoLock(mLock);
309
310 switch (mState) {
311 case STATE_UNPREPARED:
312 mState = STATE_PREPARING;
313 mIsAsyncPrepare = true;
314 mPlayer->prepareAsync();
315 return OK;
316 case STATE_STOPPED:
317 // this is really just paused. handle as seek to start
318 mAtEOS = false;
319 mState = STATE_STOPPED_AND_PREPARING;
320 mIsAsyncPrepare = true;
321 mPlayer->seekToAsync(0, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */,
322 true /* needNotify */);
323 return OK;
324 default:
325 return INVALID_OPERATION;
326 };
327}
源码中看出这儿执行prepareAsync 也是需要看播放器当前的播放状态的,STATE_UNPREPARED 的时候说明播放器之前从没有执行过prepare ;STATE_STOPPED 说明播放器执行了 stop 函数;
其他状态的情况下prepareAsync 可以直接忽略;
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
371void NuPlayer::prepareAsync() {
372 ALOGV("prepareAsync");
373
374 (new AMessage(kWhatPrepare, this))->post();
375}
NuPlayer 中定义了一个 Handler message处理机制:
548void NuPlayer::onMessageReceived(const sp<AMessage> &msg)
执行到NuPlayer-->prepareAsync(...)中的函数,需要发送一个 :
(new AMessage(kWhatPrepare, this))->post()
消息;
616 case kWhatPrepare:
617 {
618 ALOGV("onMessageReceived kWhatPrepare");
619
620 mSource->prepareAsync();
621 break;
622 }
从上面源码可以看出,这个mSource是 执行setDataSource的时候设置进去的,有3种Source,我们以GenericSource 为例;
/frameworks/av/media/libmediaplayerservice/nuplayer/GenericSource.cpp
342void NuPlayer::GenericSource::prepareAsync() {
343 Mutex::Autolock _l(mLock);
344 ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
345
346 if (mLooper == NULL) {
347 mLooper = new ALooper;
348 mLooper->setName("generic");
349 mLooper->start();
350
351 mLooper->registerHandler(this);
352 }
353
354 sp<AMessage> msg = new AMessage(kWhatPrepareAsync, this);
355 msg->post();
356}
583void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
584 Mutex::Autolock _l(mLock);
585 switch (msg->what()) {
586 case kWhatPrepareAsync:
587 {
588 onPrepareAsync();
589 break;
590 }
这个函数中是执行视频资源网络请求的核心函数;
358void NuPlayer::GenericSource::onPrepareAsync() {
359 ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
360
361 // delayed data source creation
362 if (mDataSource == NULL) {
363 // set to false first, if the extractor
364 // comes back as secure, set it to true then.
365 mIsSecure = false;
366
367 if (!mUri.empty()) {
368 const char* uri = mUri.c_str();
369 String8 contentType;
370
371 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
372 mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
373 if (mHttpSource == NULL) {
374 ALOGE("Failed to create http source!");
375 notifyPreparedAndCleanup(UNKNOWN_ERROR);
376 return;
377 }
378 }
379
380 mLock.unlock();
381 // This might take long time if connection has some issue.
382 sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
383 mHTTPService, uri, &mUriHeaders, &contentType,
384 static_cast<HTTPBase *>(mHttpSource.get()));
385 mLock.lock();
386 if (!mDisconnected) {
387 mDataSource = dataSource;
388 }
389 } else {
390 if (property_get_bool("media.stagefright.extractremote", true) &&
391 !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
392 sp<IBinder> binder =
393 defaultServiceManager()->getService(String16("media.extractor"));
394 if (binder != nullptr) {
395 ALOGD("FileSource remote");
396 sp<IMediaExtractorService> mediaExService(
397 interface_cast<IMediaExtractorService>(binder));
398 sp<IDataSource> source =
399 mediaExService->makeIDataSource(mFd, mOffset, mLength);
400 ALOGV("IDataSource(FileSource): %p %d %lld %lld",
401 source.get(), mFd, (long long)mOffset, (long long)mLength);
402 if (source.get() != nullptr) {
403 mDataSource = CreateDataSourceFromIDataSource(source);
404 if (mDataSource != nullptr) {
405 // Close the local file descriptor as it is not needed anymore.
406 close(mFd);
407 mFd = -1;
408 }
409 } else {
410 ALOGW("extractor service cannot make data source");
411 }
412 } else {
413 ALOGW("extractor service not running");
414 }
415 }
416 if (mDataSource == nullptr) {
417 ALOGD("FileSource local");
418 mDataSource = new FileSource(mFd, mOffset, mLength);
419 }
420 // TODO: close should always be done on mFd, see the lines following
421 // CreateDataSourceFromIDataSource above,
422 // and the FileSource constructor should dup the mFd argument as needed.
423 mFd = -1;
424 }
425
426 if (mDataSource == NULL) {
427 ALOGE("Failed to create data source!");
428 notifyPreparedAndCleanup(UNKNOWN_ERROR);
429 return;
430 }
431 }
432
433 if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
434 mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
435 }
436
437 // For cached streaming cases, we need to wait for enough
438 // buffering before reporting prepared.
439 mIsStreaming = (mCachedSource != NULL);
440
441 // init extractor from data source
442 status_t err = initFromDataSource();
443
444 if (err != OK) {
445 ALOGE("Failed to init from data source!");
446 notifyPreparedAndCleanup(err);
447 return;
448 }
449
450 if (mVideoTrack.mSource != NULL) {
451 sp<MetaData> meta = getFormatMeta_l(false /* audio */);
452 sp<AMessage> msg = new AMessage;
453 err = convertMetaDataToMessage(meta, &msg);
454 if(err != OK) {
455 notifyPreparedAndCleanup(err);
456 return;
457 }
458 notifyVideoSizeChanged(msg);
459 }
460
461 notifyFlagsChanged(
462 // FLAG_SECURE will be known if/when prepareDrm is called by the app
463 // FLAG_PROTECTED will be known if/when prepareDrm is called by the app
464 FLAG_CAN_PAUSE |
465 FLAG_CAN_SEEK_BACKWARD |
466 FLAG_CAN_SEEK_FORWARD |
467 FLAG_CAN_SEEK);
468
469 finishPrepareAsync();
470
471 ALOGV("onPrepareAsync: Done");
472}
关键的执行片段是:
371 if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
372 mHttpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
373 if (mHttpSource == NULL) {
374 ALOGE("Failed to create http source!");
375 notifyPreparedAndCleanup(UNKNOWN_ERROR);
376 return;
377 }
378 }
379
380 mLock.unlock();
381 // This might take long time if connection has some issue.
382 sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
383 mHTTPService, uri, &mUriHeaders, &contentType,
384 static_cast<HTTPBase *>(mHttpSource.get()));
385 mLock.lock();
386 if (!mDisconnected) {
387 mDataSource = dataSource;
388 }
开始onPrepared 和 onVideoSizeChanged 回调:
450 if (mVideoTrack.mSource != NULL) {
451 sp<MetaData> meta = getFormatMeta_l(false /* audio */);
452 sp<AMessage> msg = new AMessage;
453 err = convertMetaDataToMessage(meta, &msg);
454 if(err != OK) {
455 notifyPreparedAndCleanup(err);
456 return;
457 }
458 notifyVideoSizeChanged(msg);
459 }
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
2487 case Source::kWhatPrepared:
2488 {
2489 ALOGV("NuPlayer::onSourceNotify Source::kWhatPrepared source: %p", mSource.get());
2490 if (mSource == NULL) {
2491 // This is a stale notification from a source that was
2492 // asynchronously preparing when the client called reset().
2493 // We handled the reset, the source is gone.
2494 break;
2495 }
2496
2497 int32_t err;
2498 CHECK(msg->findInt32("err", &err));
2499
2500 if (err != OK) {
2501 // shut down potential secure codecs in case client never calls reset
2502 mDeferredActions.push_back(
2503 new FlushDecoderAction(FLUSH_CMD_SHUTDOWN /* audio */,
2504 FLUSH_CMD_SHUTDOWN /* video */));
2505 processDeferredActions();
2506 } else {
2507 mPrepared = true;
2508 }
2509
2510 sp<NuPlayerDriver> driver = mDriver.promote();
2511 if (driver != NULL) {
2512 // notify duration first, so that it's definitely set when
2513 // the app received the "prepare complete" callback.
2514 int64_t durationUs;
2515 if (mSource->getDuration(&durationUs) == OK) {
2516 driver->notifyDuration(durationUs);
2517 }
2518 driver->notifyPrepareCompleted(err);
2519 }
2520
2521 break;
2522 }
2510 sp<NuPlayerDriver> driver = mDriver.promote();
2511 if (driver != NULL) {
2512 // notify duration first, so that it's definitely set when
2513 // the app received the "prepare complete" callback.
2514 int64_t durationUs;
2515 if (mSource->getDuration(&durationUs) == OK) {
2516 driver->notifyDuration(durationUs);
2517 }
2518 driver->notifyPrepareCompleted(err);
2519 }
回调了notifyPrepareCompleted 和 notifyDuration
其中/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
继承了
/frameworks/av/media/libmediaplayerservice/include/MediaPlayerInterface.h
所有底层NuPlayer的回调会通过NuPlayerDriver.h 中的sendEvent 到MediaPlayerInterface.h:
282 void sendEvent(int msg, int ext1=0, int ext2=0,
283 const Parcel *obj=NULL) {
284 sp<Listener> listener;
285 {
286 Mutex::Autolock autoLock(mNotifyLock);
287 listener = mListener;
288 }
289
290 if (listener != NULL) {
291 listener->notify(msg, ext1, ext2, obj);
292 }
293 }
这个listener 是MediaPlayerService.cpp中设置进来的,所有还会回调到MediaPlayerService.cpp
1424void MediaPlayerService::Client::notify(
1425 int msg, int ext1, int ext2, const Parcel *obj)
1426{
1427 sp<IMediaPlayerClient> c;
1428 sp<Client> nextClient;
1429 status_t errStartNext = NO_ERROR;
1430 {
1431 Mutex::Autolock l(mLock);
1432 c = mClient;
1433 if (msg == MEDIA_PLAYBACK_COMPLETE && mNextClient != NULL) {
1434 nextClient = mNextClient;
1435
1436 if (mAudioOutput != NULL)
1437 mAudioOutput->switchToNextOutput();
1438
1439 errStartNext = nextClient->start();
1440 }
1441 }
1442
1443 if (nextClient != NULL) {
1444 sp<IMediaPlayerClient> nc;
1445 {
1446 Mutex::Autolock l(nextClient->mLock);
1447 nc = nextClient->mClient;
1448 }
1449 if (nc != NULL) {
1450 if (errStartNext == NO_ERROR) {
1451 nc->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
1452 } else {
1453 nc->notify(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN , 0, obj);
1454 ALOGE("gapless:start playback for next track failed, err(%d)", errStartNext);
1455 }
1456 }
1457 }
1458
1459 if (MEDIA_INFO == msg &&
1460 MEDIA_INFO_METADATA_UPDATE == ext1) {
1461 const media::Metadata::Type metadata_type = ext2;
1462
1463 if(shouldDropMetadata(metadata_type)) {
1464 return;
1465 }
1466
1467 // Update the list of metadata that have changed. getMetadata
1468 // also access mMetadataUpdated and clears it.
1469 addNewMetadataUpdate(metadata_type);
1470 }
1471
1472 if (c != NULL) {
1473 ALOGV("[%d] notify (%d, %d, %d)", mConnId, msg, ext1, ext2);
1474 c->notify(msg, ext1, ext2, obj);
1475 }
1476}
/frameworks/av/media/libmedia/mediaplayer.cpp
继承
/frameworks/av/media/libmedia/IMediaPlayerClient.cpp
上层MediaPlayer 所有的回调都会集中在
/frameworks/av/media/libmedia/mediaplayer.cpp
中的notify 函数回调:
848void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
849{
850 ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
851 bool send = true;
852 bool locked = false;
853
854 // TODO: In the future, we might be on the same thread if the app is
855 // running in the same process as the media server. In that case,
856 // this will deadlock.
857 //
858 // The threadId hack below works around this for the care of prepare,
859 // seekTo, start, and reset within the same process.
860 // FIXME: Remember, this is a hack, it's not even a hack that is applied
861 // consistently for all use-cases, this needs to be revisited.
862 if (mLockThreadId != getThreadId()) {
863 mLock.lock();
864 locked = true;
865 }
866
867 // Allows calls from JNI in idle state to notify errors
868 if (!(msg == MEDIA_ERROR && mCurrentState == MEDIA_PLAYER_IDLE) && mPlayer == 0) {
869 ALOGV("notify(%d, %d, %d) callback on disconnected mediaplayer", msg, ext1, ext2);
870 if (locked) mLock.unlock(); // release the lock when done.
871 return;
872 }
873
874 switch (msg) {
875 case MEDIA_NOP: // interface test message
876 break;
877 case MEDIA_PREPARED:
878 ALOGV("MediaPlayer::notify() prepared");
879 mCurrentState = MEDIA_PLAYER_PREPARED;
880 if (mPrepareSync) {
881 ALOGV("signal application thread");
882 mPrepareSync = false;
883 mPrepareStatus = NO_ERROR;
884 mSignal.signal();
885 }
886 break;
887 case MEDIA_DRM_INFO:
888 ALOGV("MediaPlayer::notify() MEDIA_DRM_INFO(%d, %d, %d, %p)", msg, ext1, ext2, obj);
889 break;
890 case MEDIA_PLAYBACK_COMPLETE:
891 ALOGV("playback complete");
892 if (mCurrentState == MEDIA_PLAYER_IDLE) {
893 ALOGE("playback complete in idle state");
894 }
895 if (!mLoop) {
896 mCurrentState = MEDIA_PLAYER_PLAYBACK_COMPLETE;
897 }
898 break;
899 case MEDIA_ERROR:
900 // Always log errors.
901 // ext1: Media framework error code.
902 // ext2: Implementation dependant error code.
903 ALOGE("error (%d, %d)", ext1, ext2);
904 mCurrentState = MEDIA_PLAYER_STATE_ERROR;
905 if (mPrepareSync)
906 {
907 ALOGV("signal application thread");
908 mPrepareSync = false;
909 mPrepareStatus = ext1;
910 mSignal.signal();
911 send = false;
912 }
913 break;
914 case MEDIA_INFO:
915 // ext1: Media framework error code.
916 // ext2: Implementation dependant error code.
917 if (ext1 != MEDIA_INFO_VIDEO_TRACK_LAGGING) {
918 ALOGW("info/warning (%d, %d)", ext1, ext2);
919 }
920 break;
921 case MEDIA_SEEK_COMPLETE:
922 ALOGV("Received seek complete");
923 if (mSeekPosition != mCurrentPosition || (mSeekMode != mCurrentSeekMode)) {
924 ALOGV("Executing queued seekTo(%d, %d)", mCurrentPosition, mCurrentSeekMode);
925 mSeekPosition = -1;
926 mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
927 seekTo_l(mCurrentPosition, mCurrentSeekMode);
928 }
929 else {
930 ALOGV("All seeks complete - return to regularly scheduled program");
931 mCurrentPosition = mSeekPosition = -1;
932 mCurrentSeekMode = mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
933 }
934 break;
935 case MEDIA_BUFFERING_UPDATE:
936 ALOGV("buffering %d", ext1);
937 break;
938 case MEDIA_SET_VIDEO_SIZE:
939 ALOGV("New video size %d x %d", ext1, ext2);
940 mVideoWidth = ext1;
941 mVideoHeight = ext2;
942 break;
943 case MEDIA_NOTIFY_TIME:
944 ALOGV("Received notify time message");
945 break;
946 case MEDIA_TIMED_TEXT:
947 ALOGV("Received timed text message");
948 break;
949 case MEDIA_SUBTITLE_DATA:
950 ALOGV("Received subtitle data message");
951 break;
952 case MEDIA_META_DATA:
953 ALOGV("Received timed metadata message");
954 break;
955 default:
956 ALOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
957 break;
958 }
959
960 sp<MediaPlayerListener> listener = mListener;
961 if (locked) mLock.unlock();
962
963 // this prevents re-entrant calls into client code
964 if ((listener != 0) && send) {
965 Mutex::Autolock _l(mNotifyLock);
966 ALOGV("callback application");
967 listener->notify(msg, ext1, ext2, obj);
968 ALOGV("back from callback");
969 }
970}
以onPrepared 回调为例:
877 case MEDIA_PREPARED:
878 ALOGV("MediaPlayer::notify() prepared");
879 mCurrentState = MEDIA_PLAYER_PREPARED;
880 if (mPrepareSync) {
881 ALOGV("signal application thread");
882 mPrepareSync = false;
883 mPrepareStatus = NO_ERROR;
884 mSignal.signal();
885 }
886 break;
......
......
......
960 sp<MediaPlayerListener> listener = mListener;
961 if (locked) mLock.unlock();
962
963 // this prevents re-entrant calls into client code
964 if ((listener != 0) && send) {
965 Mutex::Autolock _l(mNotifyLock);
966 ALOGV("callback application");
967 listener->notify(msg, ext1, ext2, obj);
968 ALOGV("back from callback");
969 }
从上面分析MediaPlayer->setDataSource 和 MediaPlayer->prepareAsync 两个调用流程来看,我们简单总结一下主要调用的类;
/frameworks/base/media/java/android/media/MediaPlayer.java
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
/frameworks/av/media/libmedia/mediaplayer.cpp
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
/frameworks/av/media/libmediaplayerservice/include/MediaPlayerInterface.h
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
将上面的类图再完善一下:
MediaPlayer 类关系
网友评论