Android MediaPlayer框架分析

来源:互联网 发布:铁塔基础设计软件 编辑:程序博客网 时间:2024/05/17 01:23

应用层:从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 voidandroid_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 voidandroid_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 voidandroid_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;}
阅读全文
0 0
原创粉丝点击