【Android多媒体】NuPlayer for HTTP Live Streaming【2】
2015-08-02 21:01
746 查看
不管是本地播放多媒体,还是流媒体播放,在上层的实现方法都是一样的,总体来说就下面的这些流程。
接下来会以播放流程的步骤去解析NuPayer实现的细节。其中涉及到具体的请求消息构建和处理请参考:AHandler机制。
framework/av/media/libmedia/mediaplayer.cpp
这里主要是通过mediaPlayerService获取BnMediaplayer,然后通过Binder通信调用底层的setDataSource。这里涉及到了Binder通信的知识,以后再做研究。
成功完成之后,意味着mediaPlayer进入了MEDIA_PLAYER_INITIALIZED状态。
(2)
MediaPlayerService.cpp中具体BnMediaPlayer的执行;
这里依据代码URL得出要创建的player类型,这里是NuPlayerDriver(这是个NuPlayer的封装)。
NuPlayer就是一个AHandler,继承自AHandler,构成nuplayer的过程,初始化一些状态,标志位,重要的是起了消息队列、Looper和Handler,也就是AHandler机制。
(3)
这个过程创建了NuPlayer之后,从NuPlayerDriver开始执行底层的setDataSource。
从图上看,setDataSource整个过程,做了三件事情:
1. 创建Message
2. 创建HTTPLiveSource
3. onMessageReceived中处理消息
HTTPLiveSource初始化,基本上没做什么。
上面的步骤进入STATE_SET_DATASOURCE_PENDING状态,NuPlayerDriver的状态:
setDataSource基本上简单地初始化了source就完了。
[code]MediaPlayer mMediaPlayer = new MediaPlayer( ); //创建mediaplayer mMediaPlayer.setDataSource(mContext, mUri); // setDataSoutce mMediaPlayer.setDisplay(mSurfaceHolder); // setDisplay mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mMediaPlayer.prepareAsync(); // Prepare mMediaPlayer.start(); // start ... // Pause, stop
接下来会以播放流程的步骤去解析NuPayer实现的细节。其中涉及到具体的请求消息构建和处理请参考:AHandler机制。
1. setDataSource
(1)framework/av/media/libmedia/mediaplayer.cpp
[code]status_t MediaPlayer::setDataSource( const sp<IMediaHTTPService> &httpService, const char *url, const KeyedVector<String8, String8> *headers) { ALOGV("setDataSource(%s)", url); status_t err = BAD_VALUE; if (url != NULL) { const sp<IMediaPlayerService>& service(getMediaPlayerService()); if (service != 0) { sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); if ((NO_ERROR != doSetRetransmitEndpoint(player)) || (NO_ERROR != player->setDataSource(httpService, url, headers))) { player.clear(); } err = attachNewPlayer(player); } } return err; }
这里主要是通过mediaPlayerService获取BnMediaplayer,然后通过Binder通信调用底层的setDataSource。这里涉及到了Binder通信的知识,以后再做研究。
成功完成之后,意味着mediaPlayer进入了MEDIA_PLAYER_INITIALIZED状态。
[code]enum media_player_states { MEDIA_PLAYER_STATE_ERROR = 0, MEDIA_PLAYER_IDLE = 1 << 0, MEDIA_PLAYER_INITIALIZED = 1 << 1, MEDIA_PLAYER_PREPARING = 1 << 2, MEDIA_PLAYER_PREPARED = 1 << 3, MEDIA_PLAYER_STARTED = 1 << 4, MEDIA_PLAYER_PAUSED = 1 << 5, MEDIA_PLAYER_STOPPED = 1 << 6, MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7 };
(2)
MediaPlayerService.cpp中具体BnMediaPlayer的执行;
[code]status_t MediaPlayerService::Client::setDataSource( const sp<IMediaHTTPService> &httpService, const char *url, const KeyedVector<String8, String8> *headers) { ALOGV("setDataSource(%s)", url); ... } else { player_type playerType = MediaPlayerFactory::getPlayerType(this, url); sp<MediaPlayerBase> p = setDataSource_pre(playerType); if (p == NULL) { return NO_INIT; } setDataSource_post(p, p->setDataSource(httpService, url, headers)); return mStatus; } }
这里依据代码URL得出要创建的player类型,这里是NuPlayerDriver(这是个NuPlayer的封装)。
[code]class NuPlayerFactory : public MediaPlayerFactory::IFactory { ... virtual sp<MediaPlayerBase> createPlayer() { ALOGV(" create NuPlayer"); return new NuPlayerDriver; } };
[code]NuPlayerDriver::NuPlayerDriver() : mState(STATE_IDLE), mIsAsyncPrepare(false), mAsyncResult(UNKNOWN_ERROR), mSetSurfaceInProgress(false), mDurationUs(-1), mPositionUs(-1), mSeekInProgress(false), mLooper(new ALooper), mPlayerFlags(0), mAtEOS(false), mLooping(false), mAutoLoop(false), mStartupSeekTimeUs(-1) { ALOGV("NuPlayerDriver(%p)", this); mLooper->setName("NuPlayerDriver Looper"); mLooper->start( false, /* runOnCallingThread */ true, /* canCallJava */ PRIORITY_AUDIO); mPlayer = new NuPlayer; mLooper->registerHandler(mPlayer); mPlayer->setDriver(this); }
NuPlayer就是一个AHandler,继承自AHandler,构成nuplayer的过程,初始化一些状态,标志位,重要的是起了消息队列、Looper和Handler,也就是AHandler机制。
(3)
这个过程创建了NuPlayer之后,从NuPlayerDriver开始执行底层的setDataSource。
从图上看,setDataSource整个过程,做了三件事情:
1. 创建Message
2. 创建HTTPLiveSource
3. onMessageReceived中处理消息
[code]void NuPlayer::setDataSourceAsync( const sp<IMediaHTTPService> &httpService, const char *url, const KeyedVector<String8, String8> *headers) { sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); // 1 创建消息 size_t len = strlen(url); sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); // 创建返回通知消息 sp<Source> source; if (IsHTTPLiveURL(url)) { source = new HTTPLiveSource(notify, httpService, url, headers); // 2 对于HLS 创建HTTPLiveSource } else if (!strncasecmp(url, "rtsp://", 7)) { source = new RTSPSource( notify, httpService, url, headers, mUIDValid, mUID); // 对于RTSP 创建RTSPSource } else if ((!strncasecmp(url, "http://", 7) || !strncasecmp(url, "https://", 8)) && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?"))) { source = new RTSPSource( notify, httpService, url, headers, mUIDValid, mUID, true); } else { sp<GenericSource> genericSource = new GenericSource(notify, mUIDValid, mUID); // Don't set FLAG_SECURE on mSourceFlags here for widevine. // The correct flags will be updated in Source::kWhatFlagsChanged // handler when GenericSource is prepared. status_t err = genericSource->setDataSource(httpService, url, headers); if (err == OK) { source = genericSource; } else { ALOGE("Failed to set data source!"); } } msg->setObject("source", source); msg->post(); // Post消息队列等待处理 }
[code]void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatSetDataSource: { ALOGV("kWhatSetDataSource"); CHECK(mSource == NULL); status_t err = OK; sp<RefBase> obj; CHECK(msg->findObject("source", &obj)); if (obj != NULL) { mSource = static_cast<Source *>(obj.get()); // 这个就是上面创建的HTTPLiveSource } else { err = UNKNOWN_ERROR; } CHECK(mDriver != NULL); sp<NuPlayerDriver> driver = mDriver.promote(); if (driver != NULL) { driver->notifySetDataSourceCompleted(err); } break; } case kWhatSourceNotify: { onSourceNotify(msg); break; } } } void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) { Mutex::Autolock autoLock(mLock); CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING); mAsyncResult = err; mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE; mCondition.broadcast(); } // 这个函数如同回调函数一样进入HTTPLiveSource,随时能通知到NuPlayer void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { int32_t what; CHECK(msg->findInt32("what", &what)); ... }
HTTPLiveSource初始化,基本上没做什么。
[code]NuPlayer::HTTPLiveSource::HTTPLiveSource( const sp<AMessage> ¬ify, const sp<IMediaHTTPService> &httpService, const char *url, const KeyedVector<String8, String8> *headers) : Source(notify), mHTTPService(httpService), mURL(url), mFlags(0), mFinalResult(OK), mOffset(0), mFetchSubtitleDataGeneration(0) { if (headers) { mExtraHeaders = *headers; ssize_t index = mExtraHeaders.indexOfKey(String8("x-hide-urls-from-log")); if (index >= 0) { mFlags |= kFlagIncognito; mExtraHeaders.removeItemsAt(index); } } }
上面的步骤进入STATE_SET_DATASOURCE_PENDING状态,NuPlayerDriver的状态:
[code] enum State { STATE_IDLE, STATE_SET_DATASOURCE_PENDING, STATE_UNPREPARED, STATE_PREPARING, STATE_PREPARED, STATE_RUNNING, STATE_PAUSED, STATE_RESET_IN_PROGRESS, STATE_STOPPED, // equivalent to PAUSED STATE_STOPPED_AND_PREPARING, // equivalent to PAUSED, but seeking STATE_STOPPED_AND_PREPARED, // equivalent to PAUSED, but seek complete };
setDataSource基本上简单地初始化了source就完了。
相关文章推荐
- 08-02 文件IO流 网络通信(TCP) 集合 泛型
- 20150802-网络连接-TCP
- java基础第七讲——集合、泛型、枚举、网络
- python 网络编程——客户端
- 无线网络覆盖
- 网络编程学习日志
- linux网络编程-内存管理
- 网络分析与图简介
- 用httpPost对JSON发送和接收的例子
- 【转】win7“您可能没有权限使用网络资源”的解决办法
- TCP/IP、Http、Socket的区别
- Android之通过网络播放一首简单的音乐
- java 实现socket基于TCP的多线程多机交互
- TCP/IP 端口号大全
- 网络上常见的攻击方式以及防御系统
- http://www.blogjava.net/crespochen/archive/2011/04/22/348819.html
- TCP建立连接和释放的过程,及TCP状态变迁图
- 第十二天 网络连接
- 读书笔记 TCP滑动窗口
- 利用http协议发布博客园博文评论