应用层:从setDataSource说起
先来看看应用层Mediaplayer的例子:
public class MediaPlayerStudy extends Activity {
private Button bplay,bpause,bstop;
private MediaPlayer mp = new MediaPlayer();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bplay = (Button)findViewById(R.id.play);
bpause = (Button)findViewById(R.id.pause);
bstop = (Button)findViewById(R.id.stop);
bplay.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
try {
mp.setDataSource("/sdcard/test.mp3");
mp.prepare();
mp.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mp.setOnCompletionListener(new OnCompletionListener(){
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
}
});
bpause.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
if(mp != null){
mp.pause();
}
}
});
bstop.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
if(mp != null){
mp.stop();
}
}
});
}
@Override
protected void onDestroy() {
if(mp != null)
mp.release();
super.onDestroy();
}
}
mediaserver的启动
mediaserver在开机时启动,在init.rc文件中有体现:
/system/core/rootdir/init.rc
service media /system/bin/mediaserver
class main
user media
group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
ioprio rt 4
mediaserver的main函数里初始化了AudioFlinger,MediaPlayerService,ResourceManagerService,CameraService,AudioPolicyService,SoundTriggerHwService和
RadioService等service。
/frameworks/av/media/mediaserver/main_mediaserver.cpp
...
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
SoundTriggerHwService::instantiate();
RadioService::instantiate();
...
这里只涉及MediaPlayerService,看看其instantiate函数实现:
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
MediaPlayerService::instantiate()主要作用是向ServiceManager注册服务。
MediaPlayer的启动
MediaPlayer构造函数执行之前加载了libmedia_jni.so,并调用了native函数native_init。
/frameworks/base/media/java/android/media/MediaPlayer.java
static {
System.loadLibrary("media_jni");
native_init();
}
进程执行native_init时会切换到JNI环境,执行JNI_OnLoad函数:
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("ERROR: GetEnv failed\n");
goto bail;
}
assert(env != NULL);
...
if (register_android_media_MediaPlayer(env) < 0) {
ALOGE("ERROR: MediaPlayer native registration failed\n");
goto bail;
}
...
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static int register_android_media_MediaPlayer(JNIEnv *env)
{
return AndroidRuntime::registerNativeMethods(env,
"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}
Java层的函数与JNI层的函数对应关系写在gMethods数组中:
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static JNINativeMethod gMethods[] = {
...
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
...
native层fields是个struct fields_t类型的static变量。
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
struct fields_t {
jfieldID context;
jfieldID surface_texture;
jmethodID post_event;
jmethodID proxyConfigGetHost;
jmethodID proxyConfigGetPort;
jmethodID proxyConfigGetExclusionList;
};
android_media_MediaPlayer_native_init负责将Java层的一些信息保存在JNI层,如Java层的long型(J)的成员mNativeContext保存在fields.context中,函数成员postEventFromNative保存在fields.post_event中( (Ljava/lang/Object;IIILjava/lang/Object;)V”)表示该函数接收五个参数Object,int,int,int,Object,返回值为void )等等。
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_native_init(JNIEnv *env)
{
jclass clazz;
clazz = env->FindClass("android/media/MediaPlayer");
if (clazz == NULL) {
return;
}
fields.context = env->GetFieldID(clazz, "mNativeContext", "J");
if (fields.context == NULL) {
return;
}
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.post_event == NULL) {
return;
}
fields.surface_texture = env->GetFieldID(clazz, "mNativeSurfaceTexture", "J");
if (fields.surface_texture == NULL) {
return;
}
env->DeleteLocalRef(clazz);
clazz = env->FindClass("android/net/ProxyInfo");
if (clazz == NULL) {
return;
}
fields.proxyConfigGetHost =
env->GetMethodID(clazz, "getHost", "()Ljava/lang/String;");
fields.proxyConfigGetPort =
env->GetMethodID(clazz, "getPort", "()I");
fields.proxyConfigGetExclusionList =
env->GetMethodID(clazz, "getExclusionListAsString", "()Ljava/lang/String;");
env->DeleteLocalRef(clazz);
gPlaybackParamsFields.init(env);
gSyncParamsFields.init(env);
}
这样,MediaPlayer.java的静态代码块执行完毕。返回Java层MediaPlayer的构造函数中,开始为MediaPlayer设置了Looper和EventHandler,末尾调用native函数native_setup,并传入该MediaPlayer对象的弱引用。这里传入MediaPlayer对象的弱引用的原因是当这个MediaPlayer在不再被需要时(被置null)能被GC回收。
/frameworks/base/media/java/android/media/MediaPlayer.java
public MediaPlayer() {
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
mTimeProvider = new TimeProvider(this);
mOpenSubtitleSources = new Vector<InputStream>();
IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE);
mAppOps = IAppOpsService.Stub.asInterface(b);
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
native_setup(new WeakReference<MediaPlayer>(this));
}
同理,native_setup最终会调到JNI层的android_media_MediaPlayer_native_setup函数。
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
ALOGV("native_setup");
sp<MediaPlayer> mp = new MediaPlayer();
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
}
// create new listener and give it to MediaPlayer
sp<JNIMediaPlayerListener> listener = new JNIMediaPlayerListener(env, thiz, weak_this);
mp->setListener(listener);
// Stow our new C++ MediaPlayer in an opaque field in the Java object.
setMediaPlayer(env, thiz, mp);
}
android_media_MediaPlayer_native_setup中首先new了一个C++层的MediaPlayer对象。接着new了一个回调用的JNIMediaPlayerListener,weak_thiz传入Java层传下来的MediaPlayer弱引用。GetObjectClass从对象实例thiz中获取class,mclass为android/media/MediaPlayer的全局引用,mObject为MediaPlayer弱引用的全局引用。如果希望创建的对象实例在作用域外也能使用,则需要使用NewGlobalRef接口将其提升为Global Reference——需要注意的是,当Global Reference不再使用后,需要显式的释放,以便通知JVM进行垃圾收集。
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
JNIMediaPlayerListener::JNIMediaPlayerListener(JNIEnv* env, jobject thiz, jobject weak_thiz)
{
// Hold onto the MediaPlayer class for use in calling the static method
// that posts events to the application thread.
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
ALOGE("Can't find android/media/MediaPlayer");
jniThrowException(env, "java/lang/Exception", NULL);
return;
}
mClass = (jclass)env->NewGlobalRef(clazz);
// We use a weak reference so the MediaPlayer object can be garbage collected.
// The reference is only used as a proxy for callbacks.
mObject = env->NewGlobalRef();
}
setListener将JNIMediaPlayerListener(JNIMediaPlayerListener继承自MediaPlayerListener)保存在成员变量mListener中。这样,C++层的MediaPlayer能够回调JNIMediaPlayerListener的唯一的接口实现notify函数。
/frameworks/av/media/libmedia/mediaplayer.cpp
status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)
{
ALOGV("setListener");
Mutex::Autolock _l(mLock);
mListener = listener;
return NO_ERROR;
}
JNIMediaPlayerListener::notify在JNI层调用Java层的方法。fields.post_event存储的是Java层的postEventFromNative函数,mclass为android/media/MediaPlayer这个class的全局引用,mObject为Java层MediaPlayer对象的全局引用。调用Java层的静态方法或访问Java层的静态变量时,CallStaticVoidMethod第一个参数为jclass,否则为jobject,因为静态方法或静态变量为类所有,不为特定对象所有。mObject,msg, ext1, ext2, jParcel作为Java层的函数参数传入。
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
void JNIMediaPlayerListener::notify(int msg, int ext1, int ext2, const Parcel *obj)
{
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (obj && obj->dataSize() > 0) {
jobject jParcel = createJavaParcelObject(env);
if (jParcel != NULL) {
Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
nativeParcel->setData(obj->data(), obj->dataSize());
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
msg, ext1, ext2, jParcel);
env->DeleteLocalRef(jParcel);
}
} else {
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
msg, ext1, ext2, NULL);
}
if (env->ExceptionCheck()) {
ALOGW("An exception occurred while notifying an event.");
LOGW_EX(env);
env->ExceptionClear();
}
}
Java层的postEventFromNative函数中,首先把native_setup传到C++层的MediaPlayer弱引用捞上来,获得对应的MediaPlayer对象。最后,将what, arg1, arg2, obj参数封装成一个Message发送出去。
/frameworks/base/media/java/android/media/MediaPlayer.java
private static void postEventFromNative(Object mediaplayer_ref,
int what, int arg1, int arg2, Object obj)
{
MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get();
if (mp == null) {
return;
}
if (what == MEDIA_INFO && arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
// this acquires the wakelock if needed, and sets the client side state
mp.start();
}
if (mp.mEventHandler != null) {
Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
mp.mEventHandler.sendMessage(m);
}
}
回到android_media_MediaPlayer_native_setup函数中,最后一步是调用setMediaPlayer。GetLongField获取Java层mNativeContext的值,mNativeContext保存的是C++层MediaPlayer的地址。将最新new的MediaPlayer强引用计数加1,将旧的MediaPlaye强引用计数减1,使旧的MediaPlayer自动释放内存。最后,把新的MediaPlayer的地址保存在mNativeContext中。
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static sp<MediaPlayer> setMediaPlayer(JNIEnv* env, jobject thiz, const sp<MediaPlayer>& player)
{
Mutex::Autolock l(sLock);
sp<MediaPlayer> old = (MediaPlayer*)env->GetLongField(thiz, fields.context);
if (player.get()) {
player->incStrong((void*)setMediaPlayer);
}
if (old != 0) {
old->decStrong((void*)setMediaPlayer);
}
env->SetLongField(thiz, fields.context, (jlong)player.get());
return old;
}
至此,MediaPlayer的启动流程介绍完毕。
MediaPlayer和MediaPlayerService的关系
从mp.setDataSource(“/sdcard/test.mp3”)出发,说明MediaPlayer和MediaPlayer的关系。
setDataSource最终会调到native函数android_media_MediaPlayer_setDataSourceAndHeaders。
/frameworks/base/media/java/android/media/MediaPlayer.java
public void setDataSource(String path)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(path, null, null);
}
MediaHTTPService.createHttpServiceBinderIfNecessary的作用是:如果path是网络路径(”http://”,”https://”或”widevine://”),则返回一个BpMediaHTTPService。由于我们是用的是本地路径,所以该函数返回null。
/frameworks/base/media/java/android/media/MediaPlayer.java
private void setDataSource(String path, String[] keys, String[] values)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
final Uri uri = Uri.parse(path);
final String scheme = uri.getScheme();
if ("file".equals(scheme)) {
path = uri.getPath();
} else if (scheme != null) {
// handle non-file sources
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
keys,
values);
return;
}
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static JNINativeMethod gMethods[] = {
{
"nativeSetDataSource",
"(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
"[Ljava/lang/String;)V",
(void *)android_media_MediaPlayer_setDataSourceAndHeaders
},
...
getMediaPlayer返回Java层mNativeContext保存的C++层MediaPlayer的强指针。GetStringUTFChars将Java的字符串转化为C++的字符串。C++层的MediaPlayer实际上是调用setDataSource(null,”/sdcard/test.mp3”,null)。
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static void
android_media_MediaPlayer_setDataSourceAndHeaders(
JNIEnv *env, jobject thiz, jobject httpServiceBinderObj, jstring path,
jobjectArray keys, jobjectArray values) {
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
}
if (path == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return;
}
const char *tmp = env->GetStringUTFChars(path, NULL);
if (tmp == NULL) { // Out of memory
return;
}
ALOGV("setDataSource: path %s", tmp);
String8 pathStr(tmp);
env->ReleaseStringUTFChars(path, tmp);
tmp = NULL;
// We build a KeyedVector out of the key and val arrays
KeyedVector<String8, String8> headersVector;
if (!ConvertKeyValueArraysToKeyedVector(
env, keys, values, &headersVector)) {
return;
}
sp<IMediaHTTPService> httpService;
if (httpServiceBinderObj != NULL) {
sp<IBinder> binder = ibinderForJavaObject(env, httpServiceBinderObj);
httpService = interface_cast<IMediaHTTPService>(binder);
}
status_t opStatus =
mp->setDataSource(
httpService,
pathStr,
headersVector.size() > 0? &headersVector : NULL);
process_media_player_call(
env, thiz, opStatus, "java/io/IOException",
"setDataSource failed." );
}
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz)
{
Mutex::Autolock l(sLock);
MediaPlayer* const p = (MediaPlayer*)env->GetLongField(thiz, fields.context);
return sp<MediaPlayer>(p);
}
MediaPlayer::setDataSource函数中,首先会调用getMediaPlayerService去获得MediaPlayerService的BpMediaPlayerService对象。getMediaPlayerService定义在MediaPlayer父类IMediaDeathNotifier的cpp实现文件中。
/frameworks/base/media/jni/android_media_MediaPlayer.cpp
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;
}
/frameworks/av/media/libmedia/IMediaDeathNotifier.cpp
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;
}
MediaPlayerService::create函数创建了MediaPlayerService::Client的弱引用,并添加到SortedVector< wp >。SortedVector是一个排序Vector,排序方法是按里面元素的数值大小进行排序。MediaPlayerService::Client以进程的PID,connId(每次连上MediaPlayerService该值都会加1),audioSessionId,UID等为标识。MediaPlayerService::create函数返回Client的强引用。MediaPlayerService::Client的作用类似于套接字,MediaPlayer的主要功能函数在MediaPlayerService::Client这端能找到同名函数,MediaPlayer通过Client对象,使调用流程从客户端转移到服务端。
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
int audioSessionId)
{
pid_t pid = IPCThreadState::self()->getCallingPid();
int32_t connId = android_atomic_inc(&mNextConnId);
sp<Client> c = new Client(
this, pid, connId, client, audioSessionId,
IPCThreadState::self()->getCallingUid());
ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
IPCThreadState::self()->getCallingUid());
wp<Client> w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}
于是,player初始化为MediaPlayerService::Client的强引用。然后调用MediaPlayerService::Client::setDataSource函数。如果传入的url开头为”http://”,”https://”或”rtsp://”(网络内容),则需要检查网络权限。如果传入的url是数据库内容,使用openContentProviderFile函数打开。应用层传下来的url是本地路径,属于第三种情况。
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
status_t MediaPlayerService::Client::setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers)
{
ALOGV("setDataSource(%s)", url);
if (url == NULL)
return UNKNOWN_ERROR;
if ((strncmp(url, "http://", 7) == 0) ||
(strncmp(url, "https://", 8) == 0) ||
(strncmp(url, "rtsp://", 7) == 0)) {
if (!checkPermission("android.permission.INTERNET")) {
return PERMISSION_DENIED;
}
}
if (strncmp(url, "content://", 10) == 0) {
// get a filedescriptor for the content Uri and
// pass it to the setDataSource(fd) method
String16 url16(url);
int fd = android::openContentProviderFile(url16);
if (fd < 0)
{
ALOGE("Couldn't open fd for %s", url);
return UNKNOWN_ERROR;
}
setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
close(fd);
return mStatus;
} 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;
}
}
getPlayerType函数根据视频源获取所需要的播放器。
/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
const char* url) {
GET_PLAYER_TYPE_IMPL(client, url);
}
sFactoryMap类型为KeyedVector< player_type,IFactory*>,player_type是枚举类型,列出了播放器的id;IFactory*对应具体的播放器产品接口实现类。每次要添加播放器时,都要添加播放器id和实现类这对键值对到sFactoryMap中来实现注册。
/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
#define GET_PLAYER_TYPE_IMPL(a...) \
Mutex::Autolock lock_(&sLock); \
\
player_type ret = STAGEFRIGHT_PLAYER; \
float bestScore = 0.0; \
\
for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
\
IFactory* v = sFactoryMap.valueAt(i); \
float thisScore; \
CHECK(v != NULL); \
thisScore = v->scoreFactory(a, bestScore); \
if (thisScore > bestScore) { \
ret = sFactoryMap.keyAt(i); \
bestScore = thisScore; \
} \
} \
\
if (0.0 == bestScore) { \
ret = getDefaultPlayerType(); \
} \
\
return ret;
/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
const char* url,
float /*curScore*/) {
if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
return 1.0;
}
return 0.0;
}
/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.h
enum player_type {
STAGEFRIGHT_PLAYER = 3,
NU_PLAYER = 4,
// Test players are available only in the 'test' and 'eng' builds.
// The shared library with the test player is passed passed as an
// argument to the 'test:' url in the setDataSource call.
TEST_PLAYER = 5,
};
MediaPlayerFactory是一个工厂类,MediaPlayerFactory::IFactory是一个抽象基类,同时也是一个接口类。产品接口实现类在MediaPlayerFactory.cpp中,分别是tagefrightPlayerFactory,NuPlayerFactory和TestPlayerFactory。它们均继承自IFactory,并各自实现了scoreFactory和createPlayer方法,scoreFactory定义了规则来帮助选取合适的播放器,createPlayer直接创建播放器的实例。所以,MediaPlayerFactory::getPlayerType是一个工厂方法,只需传入额外的url参数就能选取到合适的播放器。
/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.h
class MediaPlayerFactory {
public:
class IFactory {
public:
virtual ~IFactory() { }
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
const char* /*url*/,
float /*curScore*/) { return 0.0; }
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
int /*fd*/,
int64_t /*offset*/,
int64_t /*length*/,
float /*curScore*/) { return 0.0; }
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
const sp<IStreamSource> &/*source*/,
float /*curScore*/) { return 0.0; }
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
const sp<DataSource> &/*source*/,
float /*curScore*/) { return 0.0; }
virtual sp<MediaPlayerBase> createPlayer(pid_t pid) = 0;
};
...
接着回到MediaPlayerService::Client::setDataSource函数中,createPlayer创建了具体的播放器实例。mp3文件使用的播放器id为STAGEFRIGHT_PLAYER,所以这里直接跳过细节,假设createPlayer(playerType)返回的是StagefrightPlayer对象指针。
/frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp
sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
player_type playerType)
{
ALOGV("player type = %d", playerType);
// create the right type of player
sp<MediaPlayerBase> p = createPlayer(playerType);
if (p == NULL) {
return p;
}
if (!p->hardwareOutput()) {
Mutex::Autolock l(mLock);
mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
mPid, mAudioAttributes);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
return p;
}
MediaPlayerService::Client::setDataSource的最后一步是调用setDataSource_post,p->setDataSource(httpService, url, headers)这步是播放器真正解析数据的过程,setDataSource_post函数还将MediaPlayerService的mPlayer成员设为播放器对象指针。StagefrightPlayer的mPlayer指向一个AwesomePlayer对象,AwesomePlayer::setDataSource将url保存在struct Stats类型的成员变量mStats的mURI成员中,这样便完成了播放器数据源的设置。
/frameworks/av/media/libmediaplayerservice/StagefrightPlayer.cpp
StagefrightPlayer::StagefrightPlayer()
: mPlayer(new AwesomePlayer) {
ALOGV("StagefrightPlayer");
mPlayer->setListener(this);
}
/frameworks/av/media/libmediaplayerservice/StagefrightPlayer.cpp
status_t StagefrightPlayer::setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers) {
return mPlayer->setDataSource(httpService, url, headers);
}
/frameworks/av/media/libstagefright/AwesomePlayer.cpp
status_t AwesomePlayer::setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *uri,
const KeyedVector<String8, String8> *headers) {
Mutex::Autolock autoLock(mLock);
return setDataSource_l(httpService, uri, headers);
}
/frameworks/av/media/libstagefright/AwesomePlayer.cpp
status_t AwesomePlayer::setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *uri,
const KeyedVector<String8, String8> *headers) {
Mutex::Autolock autoLock(mLock);
return setDataSource_l(httpService, uri, headers);
}
status_t AwesomePlayer::setDataSource_l(
const sp<IMediaHTTPService> &httpService,
const char *uri,
const KeyedVector<String8, String8> *headers) {
reset_l();
mHTTPService = httpService;
mUri = uri;
if (headers) {
mUriHeaders = *headers;
ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
if (index >= 0) {
// Browser is in "incognito" mode, suppress logging URLs.
// This isn't something that should be passed to the server.
mUriHeaders.removeItemsAt(index);
modifyFlags(INCOGNITO, SET);
}
}
ALOGI("setDataSource_l(%s)", uriDebugString(mUri, mFlags & INCOGNITO).c_str());
// The actual work will be done during preparation in the call to
// ::finishSetDataSource_l to avoid blocking the calling thread in
// setDataSource for any significant time.
{
Mutex::Autolock autoLock(mStatsLock);
mStats.mFd = -1;
mStats.mURI = mUri;
}
return OK;
}