MediaPlayer 播放本地视频源码流程-setDataSource

Posted 蜘蛛侠不会飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MediaPlayer 播放本地视频源码流程-setDataSource相关的知识,希望对你有一定的参考价值。

1. MediaPlayer 结合 textureView 播放本地视频

xml 文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextureView
        android:id="@+id/textureView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <Button
        android:id="@+id/btn_opt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="开始"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Activity 类

package com.enjoy.mediademo;

import android.hardware.Camera;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import java.io.File;
import java.io.IOException;

public class VideoActivity extends AppCompatActivity implements View.OnClickListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener 
    private TextureView textureView;
    private Button btn_opt;
    private MediaPlayer mediaPlayer;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_record);
        textureView = findViewById(R.id.textureView);
        btn_opt = findViewById(R.id.btn_opt);

        btn_opt.setOnClickListener(this);
    

    @Override
    public void onClick(View v) 
        CharSequence text = btn_opt.getText();
        if (TextUtils.equals(text, "开始")) 
            btn_opt.setText("结束");
            mediaPlayer = new MediaPlayer();
            //设置准备监听
            mediaPlayer.setOnPreparedListener(this);
            //播放完成监听
            mediaPlayer.setOnCompletionListener(this);
            try 
                //指定视频源
                mediaPlayer.setDataSource(new File(getExternalFilesDir(""), "a.mp4").getAbsolutePath());
             catch (IOException e) 
                e.printStackTrace();
            
            //设置画布进行展示
            mediaPlayer.setSurface(new Surface(textureView.getSurfaceTexture()));
            mediaPlayer.prepareAsync();
         else 
            btn_opt.setText("开始");
            mediaPlayer.stop();

            mediaPlayer.release();
        
    

    @Override
    public void onPrepared(MediaPlayer mp) 
        mediaPlayer.start();
    

    @Override
    public void onCompletion(MediaPlayer mp) 
        btn_opt.setText("开始");
        //释放
        mediaPlayer.release();
    

主要涉及到 MediaPlayer 的方法:

mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
//播放完成回调
 mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setDataSource(new File。。。
//设置画布进行展示
mediaPlayer.setSurface(new Surface(textureView.getSurfaceTexture()));
mediaPlayer.prepareAsync();
mediaPlayer.start();

按照实际需求还会调用pause、isPlaying、getDuration、getCurrentPosition、setLooping、seekTo等方法。 

2. MediaPlayer 源码分析:

MediaPlayer 的状态图:

 音视频相关的编解码,解封装,渲染等操作需要大量的运算,所以谷歌将这些方法通过底层C/C++代码来实现

MediaPlayer框架的层次架构图:

1)创建 MediaPlayer 对象

mediaPlayer = new MediaPlayer();

/frameworks/base/media/java/android/media/MediaPlayer.java

    public MediaPlayer() 
        super(new AudioAttributes.Builder().build(),
                AudioPlaybackConfiguration.PLAYER_TYPE_JAM_MEDIAPLAYER);

// EventHandler 是用于native 层发消息给应用层的,作为回调
        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>();

        /* Native setup requires a weak reference to our object.
         * It's easier to create it here than in C++.
         */
// 1. 调用native 层方法
        native_setup(new WeakReference<MediaPlayer>(this),
                getCurrentOpPackageName());

// 2. 父类方法:用于AudioFlinger跟踪当前播放器的状态信息
        baseRegisterPlayer();
    

// 1. 调用native 层方法  native_setup

    private static native final void native_init();

/frameworks/base/media/jni/android_media_MediaPlayer.cpp

static const JNINativeMethod gMethods[] = 

    "native_setup",        "(Ljava/lang/Object;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_native_setup,
static void
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
                                       jstring opPackageName)

    ALOGV("native_setup");
    ScopedUtfChars opPackageNameStr(env, opPackageName);

// native层创建 MediaPlayer对象
    sp<MediaPlayer> mp = new MediaPlayer(opPackageNameStr.c_str());
    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);

// 通过 MediaPlayer设置观察者然后可以通过 JNIMediaPlayerListener 回调给应用层
    mp->setListener(listener);

    // Stow our new C++ MediaPlayer in an opaque field in the Java object.
    setMediaPlayer(env, thiz, mp);

native层创建 MediaPlayer对象

/frameworks/av/media/libmedia/mediaplayer.cpp

MediaPlayer::MediaPlayer(const std::string opPackageName) : mOpPackageName(opPackageName)

    ALOGV("constructor");
    mListener = NULL;
    mCookie = NULL;

// 设置默认的type 是音乐的
    mStreamType = AUDIO_STREAM_MUSIC;
    mAudioAttributesParcel = NULL;
    mCurrentPosition = -1;

 // 默认当前seek模式为seek位置前SYNC同步,默认寻找seek位置前的关键帧数据进行播放
    mCurrentSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
    mSeekPosition = -1;
    mSeekMode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC;
    mCurrentState = MEDIA_PLAYER_IDLE;
    mPrepareSync = false;
    mPrepareStatus = NO_ERROR;
    mLoop = false;
    mLeftVolume = mRightVolume = 1.0;
    mVideoWidth = mVideoHeight = 0;
    mLockThreadId = 0;

// 获取 AudiosessionId
    mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
    AudioSystem::acquireAudioSessionId(mAudioSessionId, (pid_t)-1, (uid_t)-1); // always in client.
    mSendLevel = 0;
    mRetransmitEndpointValid = false;

看一下 EventHandler 的回调事件处理

/frameworks/av/media/libmedia/mediaplayer.cpp

在MediaPlayer 中有去设置 setListener

status_t MediaPlayer::setListener(const sp<MediaPlayerListener>& listener)

    ALOGV("setListener");
    Mutex::Autolock _l(mLock);
    mListener = listener;
    return NO_ERROR;


-------
// 有个 notify 方法可以通知到 对应的观察者

void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)

    ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
    bool send = true;
    bool locked = false;

    switch (msg) 
    case MEDIA_NOP: // interface test message
        break;

// 比如消息为:MEDIA_PREPARED
    case MEDIA_PREPARED:
        ALOGV("MediaPlayer::notify() prepared");
        mCurrentState = MEDIA_PLAYER_PREPARED;
        if (mPrepareSync) 
            ALOGV("signal application thread");
            mPrepareSync = false;
            mPrepareStatus = NO_ERROR;
            mSignal.signal();
        
        break;

// 将观察者赋值给:listener 
    sp<MediaPlayerListener> listener = mListener;
    if (locked) mLock.unlock();

    // this prevents re-entrant calls into client code
    if ((listener != 0) && send) 
        Mutex::Autolock _l(mNotifyLock);
        ALOGV("callback application");

// 调用 notify 函数通知,ext1, ext2 分别是宽和高
        listener->notify(msg, ext1, ext2, obj);
        ALOGV("back from callback");
    

/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());

// 其中,post_event就是ap 层的方法
            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();
    


-------------------
 fields.post_event 在初始化的时候有赋值

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;
    

// 对应的方法是 postEventFromNative
    fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
                                               "(Ljava/lang/Object;IIILjava/lang/Object;)V");

/frameworks/base/media/java/android/media/MediaPlayer.java

    private static void postEventFromNative(Object mediaplayer_ref,
                                            int what, int arg1, int arg2, Object obj)
    
        final MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get();
        if (mp == null) 
            return;
        

        switch (what) 

        case MEDIA_PREPARED:
            // By this time, we've learned about DrmInfo's presence or absence. This is meant
            // mainly for prepareAsync() use case. For prepare(), this still can run to a race
            // condition b/c MediaPlayerNative releases the prepare() lock before calling notify
            // so we also set mDrmInfoResolved in prepare().
            synchronized (mp.mDrmLock) 
                mp.mDrmInfoResolved = true;
            
            break;

        

        if (mp.mEventHandler != null) 
            Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
// EventHandler handler 去处理消息
            mp.mEventHandler.sendMessage(m);
        
    

---------------

    private class EventHandler extends Handler
    
        private MediaPlayer mMediaPlayer;

        public EventHandler(MediaPlayer mp, Looper looper) 
            super(looper);
            mMediaPlayer = mp;
        

        @Override
        public void handleMessage(Message msg) 
            if (mMediaPlayer.mNativeContext == 0) 
                Log.w(TAG, "mediaplayer went away with unhandled events");
                return;
            
            switch(msg.what) 

// 通知到ap 层媒体已经准备好了,可以显示了
            case MEDIA_PREPARED:
                try 
                    scanInternalSubtitleTracks();
                 catch (RuntimeException e) 
                    // send error message instead of crashing;
                    // send error message instead of inlining a call to onError
                    // to avoid code duplication.
                    Message msg2 = obtainMessage(
                            MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
                    sendMessage(msg2);
                

// mOnPreparedListener为ap 层设置的回调:
//  public void setOnPreparedListener(OnPreparedListener listener)
                OnPreparedListener onPreparedListener = mOnPreparedListener;
                if (onPreparedListener != null)

// 回调 onPrepared方法
                    onPreparedListener.onPrepared(mMediaPlayer);
                return;

---- 还有会回调视频大小的方法---
            case MEDIA_SET_VIDEO_SIZE:
                OnVideoSizeChangedListener onVideoSizeChangedListener = mOnVideoSizeChangedListener;
                if (onVideoSizeChangedListener != null) 
                    onVideoSizeChangedListener.onVideoSizeChanged(
                        mMediaPlayer, msg.arg1, msg.arg2);
                
                return;


//播放完成回调为如下:  mediaPlayer.setOnCompletionListener(this);

            case MEDIA_PLAYBACK_COMPLETE:
                
                    mOnCompletionInternalListener.onCompletion(mMediaPlayer);
                    OnCompletionListener onCompletionListener = mOnCompletionListener;
// 回调播放完成
                    if (onCompletionListener != null)
                        onCompletionListener.onCompletion(mMediaPlayer);
                
                stayAwake(false);
                return;

-------
// stayAwake方法是去设置屏幕不常亮,释放锁
    private void stayAwake(boolean awake) 
        if (mWakeLock != null) 
            if (awake && !mWakeLock.isHeld()) 
                mWakeLock.acquire();
             else if (!awake && mWakeLock.isHeld()) 
                mWakeLock.release();
            
        
        mStayAwake = awake;
        updateSurfaceScreenOn();
    

 具体的话可以参考:MediaPlayer 的消息回调机制

2. 设置播放的源数据:mediaPlayer.setDataSource(new File。。。

 

 MediaPlayer框架采用C/S架构,分别处在两个进程上,采用Bindler机制进行进程间通信。我们发现native层的大部分类都是采用IXXX,BpXXX,BnXXX形式的。在MediaPlayer框架层,由IMediaPlayer,IMediaPlayerService,IMediaPlayerClient三大元老组成了基本框架,由IBinder,BBinder(准确来说叫BnBinder比较合适),BpBinder将其粘合。此外,IXXX类里总是一些虚抽象函数,不存在定义,由BpXXX和BnXXX继承它,BpXXX作为Client端的代理类,发起服务的请求,服务的实现则统一放在BnXXX类里。
 

/frameworks/base/media/java/android/media/MediaPlayer.java

    public void setDataSource(String path)
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException 
        setDataSource(path, null, null);
    

-----------
    @UnsupportedAppUsage
    private void setDataSource(String path, Map<String, String> headers, List<HttpCookie> cookies)
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException
    
        String[] keys = null;
        String[] values = null;

        if (headers != null) 
            keys = new String[headers.size()];
            values = new String[headers.size()];

            int i = 0;
            for (Map.Entry<String, String> entry: headers.entrySet()) 
                keys[i] = entry.getKey();
                values[i] = entry.getValue();
                ++i;
            
        
        setDataSource(path, keys, values, cookies);
    

    @UnsupportedAppUsage
    private void setDataSource(String path, String[] keys, String[] values,
            List<HttpCookie> cookies)
            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, cookies),
                path,
                keys,
                values);
            return;
        

// 如果不是播放网络源的视频,则执行下列的方法
        final File file = new File(path);
        try (FileInputStream is = new FileInputStream(file)) 
            setDataSource(is.getFD());
        
    


--------------
    public void setDataSource(@NonNull AssetFileDescriptor afd)
            throws IOException, IllegalArgumentException, IllegalStateException 
        Preconditions.checkNotNull(afd);
        // Note: using getDeclaredLength so that our behavior is the same
        // as previous versions when the content provider is returning
        // a full file.
        if (afd.getDeclaredLength() < 0) 
            setDataSource(afd.getFileDescriptor());
         else 
            setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
        
    

--------------------
    public void setDataSource(FileDescriptor fd, long offset, long length)
            throws IOException, IllegalArgumentException, IllegalStateException 
        _setDataSource(fd, offset, length);
    

// 调用native 层的代码
    private native void _setDataSource(FileDescriptor fd, long offset, long length)
            throws IOException, IllegalArgumentException, IllegalStateException;

/frameworks/base/media/jni/android_media_MediaPlayer.cpp

static const JNINativeMethod gMethods[] = 
    
        "nativeSetDataSource",
        "(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
        "[Ljava/lang/String;)V",
        (void *)android_media_MediaPlayer_setDataSourceAndHeaders
    ,
// 调用 如下的方法
    "_setDataSource",      "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD,
    "_setDataSource",      "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback ,
static void
android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)

// 获取到 MediaPlayer对象
    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
    if (mp == NULL ) 
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return;
    

    if (fileDescriptor == NULL) 
        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
        return;
    
    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
    ALOGV("setDataSourceFD: fd %d", fd);

// 处理是否有异常 
// MediaPlayer的 setDataSource 方法
    process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );

/frameworks/av/media/libmedia/mediaplayer.cpp

status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)

    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
    status_t err = UNKNOWN_ERROR;

// 1. 获取 MediaPlayerService:getMediaPlayerService()
    const sp<IMediaPlayerService> service(getMediaPlayerService());
    if (service != 0) 

// 2. 调用 MediaPlayerService的create 方法返回 IMediaPlayer对象
        sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mOpPackageName));

// 3. player 去设置 setDataSource
        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
            (NO_ERROR != player->setDataSource(fd, offset, length))) 
            player.clear();
        
        err = attachNewPlayer(player);
    
    return err;

// 1. 获取 MediaPlayerService:getMediaPlayerService()

const sp<IMediaPlayerService> service(getMediaPlayerService()) 

获取的对应的 getMediaPlayerService 是 BpMediaplayerService,;创建对象的时候会传入Binder对象,传入的是 MediaPlayerService

先看一下mediaplayer 的头文件:

frameworks/av/media/libmedia/include/media/mediaplayer.h

// 包含了如下的文件
#include <media/IMediaPlayerClient.h>
#include <media/IMediaPlayer.h>
#include <media/IMediaDeathNotifier.h>

// MediaPlayer 继承于 BnMediaPlayerClient 和 IMediaDeathNotifier
class MediaPlayer : public BnMediaPlayerClient,
                    public virtual IMediaDeathNotifier

public:
    explicit MediaPlayer(const android::content::AttributionSourceState& mAttributionSource =
        android::content::AttributionSourceState());

frameworks/av/media/libmedia/IMediaDeathNotifier.cpp

IMediaDeathNotifier 有实现对应的方法

// 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 对象
            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对象,传入的参数是 binder
        sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
    
    ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
    return sMediaPlayerService;

// 获取对应的binder 对象
binder = sm->getService(String16("media.player"));

frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

 其实在 MediaplayerService 初始化的时候,有创建对应的binder 的对象:new MediaPlayerService()

void MediaPlayerService::instantiate() 
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());

// 获取对应的 sMediaPlayerService对象,传入的参数是 binder 为:new MediaPlayerService()
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder)

frameworks/av/media/libmedia/IMediaDeathNotifier.cpp

frameworks/av/media/libmedia/include/media/IMediaDeathNotifier.h

#include <utils/threads.h>

// 头文件中有包含 IMediaPlayerService
#include <media/IMediaPlayerService.h>
#include <utils/SortedVector.h>

namespace android 

class IMediaDeathNotifier: virtual public RefBase


--------------
frameworks/av/media/libmedia/include/media/IMediaPlayerService.h

#include <utils/RefBase.h>
#include <utils/String8.h>

// 这里有包含 IInterface
#include <binder/IInterface.h>

class IMediaPlayerService: public IInterface

public:

// 这里还去使用了 DECLARE_META_INTERFACE
    DECLARE_META_INTERFACE(MediaPlayerService);

frameworks/native/libs/binder/include/binder/IInterface.h

其实是 IMediaPlayerService  的类的一些实现 

// INTERFACE 为 IMediaPlayerService
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)

    return INTERFACE::asInterface(obj);


------------
如上分析有:DECLARE_META_INTERFACE(MediaPlayerService);

// 传入的参数是:MediaPlayerService
#define DECLARE_META_INTERFACE(INTERFACE)                                                         \\
public:                                                                                           \\
    static const ::android::String16 descriptor;                                                  \\
    static ::android::sp<I##INTERFACE> asInterface(const ::android::sp<::android::IBinder>& obj); \\
    virtual const ::android::String16& getInterfaceDescriptor() const;                            \\

// 定义的是 IMediaPlayerService 构造函数
    I##INTERFACE();                                                                               \\
    virtual ~I##INTERFACE();                                                                      \\
    static bool setDefaultImpl(::android::sp<I##INTERFACE> impl);                                 \\
    static const ::android::sp<I##INTERFACE>& getDefaultImpl();                                   \\
                                                                                                  \\
private:                                                                                          \\
    static ::android::sp<I##INTERFACE> default_impl;                                              \\
                                                                                                  \\

 IMPLEMENT_META_INTERFACE 的实现的定义在如下:

frameworks/av/media/libmedia/IMediaPlayerService.cpp

IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");

回到 IIterface

// INTERFACE 是 MediaPlayerService

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \\
    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)    \\

#endif

----------------------
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                        \\
    const ::android::StaticString16 I##INTERFACE##_descriptor_static_str16(                     \\
            __IINTF_CONCAT(u, NAME));                                                           \\
    const ::android::String16 I##INTERFACE::descriptor(I##INTERFACE##_descriptor_static_str16); \\

// 这里有去设置 BpMediaPlayerService
    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(I##INTERFACE, I##INTERFACE, Bp##INTERFACE)

-------------------------------
// 传入的BPTYPE 为:BpMediaPlayerService
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(ITYPE, INAME, BPTYPE)                     \\
    const ::android::String16& ITYPE::getInterfaceDescriptor() const  return ITYPE::descriptor;  \\
    ::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj)         \\
        ::android::sp<ITYPE> intr;                                                                 \\
        if (obj != nullptr)                                                                       \\
            intr = ::android::sp<ITYPE>::cast(obj->queryLocalInterface(ITYPE::descriptor));        \\
            if (intr == nullptr)                                                                  \\

// 创建对象为 BpMediaPlayerService
                intr = ::android::sp<BPTYPE>::make(obj);                                           \\
                                                                                                  \\
                                                                                                  \\
        return intr;                                                                               \\
                                                                                                  \\
    ::android::sp<ITYPE> ITYPE::default_impl;                                                      \\
    bool ITYPE::setDefaultImpl(::android::sp<ITYPE> impl)                                         \\
        /* Only one user of this interface can use this function     */                            \\
        /* at a time. This is a heuristic to detect if two different */                            \\
        /* users in the same process use this function.              */                            \\
        assert(!ITYPE::default_impl);                                                              \\
        if (impl)                                                                                 \\
            ITYPE::default_impl = std::move(impl);                                                 \\
            return true;                                                                           \\
                                                                                                  \\
        return false;                                                                              \\
                                                                                                  \\
    const ::android::sp<ITYPE>& ITYPE::getDefaultImpl()  return ITYPE::default_impl;             \\
// 构造函数 IMediaPlayerService 的空实现
    ITYPE::INAME()                                                                               \\
    ITYPE::~INAME() 

obj 就是传入的对象为:MediaPlayerService

----------------看下BpMediaplayerService------------------

frameworks/av/media/libmedia/IMediaPlayerService.cpp

// 继承了 BpInterface

class BpMediaPlayerService: public BpInterface<IMediaPlayerService>

public:
// 传入的参数是:MediaPlayerService
    explicit BpMediaPlayerService(const sp<IBinder>& impl)
        : BpInterface<IMediaPlayerService>(impl)
    
    

    virtual sp<IMediaMetadataRetriever> createMetadataRetriever()
    
        Parcel data, reply;

// 获取 IMediaPlayerService类的 getInterfaceDescriptor
// 对应的实现在:DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE

        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
        return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
    

看下 BpInterface

frameworks/native/libs/binder/include/binder/IInterface.h

// BpInterface 是多继承的,有继承 IMediaPlayerService和 BpRefBase
// BpInterface  是作为客户端去调用服务器端的方法的
// 其实 remote 也是 MediaPlayerService 

// BpInterface 是多继承的,有继承 IMediaPlayerService和 BpRefBase
// BpInterface  是作为客户端去调用服务器端的方法的
// 其实 remote 也是 MediaPlayerService
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase

public:
    explicit                    BpInterface(const sp<IBinder>& remote);

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
;

下列类就是 服务器端的

template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder

public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
;

// 2. 调用 BpMediaPlayerService的create 方法返回 IMediaPlayer对象

sp<IMediaPlayer> player(service->create(this, mAudioSessionId, mOpPackageName));

frameworks/av/media/libmedia/IMediaPlayerService.cpp

class BpMediaPlayerService: public BpInterface<IMediaPlayerService>

public:
    explicit BpMediaPlayerService(const sp<IBinder>& impl)
        : BpInterface<IMediaPlayerService>(impl)
    
    

    virtual sp<IMediaPlayer> create(
            const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId,
            const AttributionSourceState& attributionSource) 
        Parcel data, reply;
// 写入数据到驱动中
   
// 通过Binder机制分析可知,getInterfaceDescriptor()该方法为宏定义中实现的,
// 其获取的值其实是如下宏定义赋值的字符串即接口描述符【"android.media.IMediaPlayerService"】
// IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(client));
        data.writeInt32(audioSessionId);
        data.writeParcelable(attributionSource);

// 传输调用服务器端方法
// 即服务端在Bn实现端的onTransact()需要根据该请求类型标识,
// 来执行对应的任务,此处为创建MediaPlayer的事务请求事件
        remote()->transact(CREATE, data, &reply);
// 然后返回BpMediaPlayer
        return interface_cast<IMediaPlayer>(reply.readStrongBinder());
    

remote()->transact(CREATE, data, &reply); 的调用过程

status_t BnMediaPlayerService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

    switch (code) 
        case CREATE: 
            CHECK_INTERFACE(IMediaPlayerService, data, reply);

// 创建对象 BpMediaPlayerClient
            sp<IMediaPlayerClient> client =
                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
            audio_session_t audioSessionId = (audio_session_t) data.readInt32();
            AttributionSourceState attributionSource;
            status_t status = data.readParcelable(&attributionSource);
            if (status != NO_ERROR) 
                return status;
            

// 这里去创建 IMediaPlayer对象,调用的是 create方法,BnMediaPlayerService 的子类的方法
// 有传入对象 BpMediaPlayerClient
            sp<IMediaPlayer> player = create(client, audioSessionId, attributionSource);
            reply->writeStrongBinder(IInterface::asBinder(player));
            return NO_ERROR;
         break;

frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
        audio_session_t audioSessionId, const AttributionSourceState& attributionSource)

    int32_t connId = android_atomic_inc(&mNextConnId);
    // TODO b/182392769: use attribution source util
    AttributionSourceState verifiedAttributionSource = attributionSource;
    verifiedAttributionSource.pid = VALUE_OR_FATAL(
        legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
    verifiedAttributionSource.uid = VALUE_OR_FATAL(
        legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid()));

    sp<Client> c = new Client(
            this, verifiedAttributionSource, connId, client, audioSessionId);

    ALOGV("Create new client(%d) from %s, ", connId,
        verifiedAttributionSource.toString().c_str());

// Client为内部的类
    wp<Client> w = c;
    
        Mutex::Autolock lock(mLock);
        mClients.add(w);
    
    return c;

// 3. player【MediaPlayerService的Client内部类】 去设置 setDataSource

首先看下 Client 为什么是 IMediaPlayer

frameworks/av/media/libmediaplayerservice/MediaPlayerService.h

其实具体的实现都是在:Client 内部类去实现的

// 可以看出是继承于 BnMediaPlayer 
    class Client : public BnMediaPlayer 
        // IMediaPlayer interface
        virtual void            disconnect();
        virtual status_t        setVideoSurfaceTexture(
                                        const sp<IGraphicBufferProducer>& bufferProducer);
        virtual status_t        setBufferingSettings(const BufferingSettings& buffering) override;
        virtual status_t        getBufferingSettings(
                                        BufferingSettings* buffering /* nonnull */) override;
        virtual status_t        prepareAsync();
        virtual status_t        start();
        virtual status_t        stop();
        virtual status_t        pause();
        virtual status_t        isPlaying(bool* state);
        virtual status_t        setPlaybackSettings(const AudioPlaybackRate& rate);
        virtual status_t        getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
        virtual status_t        setSyncSettings(const AVSyncSettings& rate, float videoFpsHint);
        virtual status_t        getSyncSettings(AVSyncSettings* rate /* nonnull */,
                                                float* videoFps /* nonnull */);
        virtual status_t        seekTo(
                int msec,
                MediaPlayerSeekMode mode = MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC);

frameworks/av/media/libmedia/include/media/IMediaPlayer.h

BnMediaPlayer 又是继承于 BnInterface

// BnMediaPlayer 又是继承于 BnInterface
class BnMediaPlayer: public BnInterface<IMediaPlayer>

public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
;

; // namespace android

frameworks/native/libs/binder/include/binder/IInterface.h

// 传入的 INTERFACE 就是 IMediaPlayer
// 并且 BnInterface 多重继承了 IMediaPlayer 和 BBinder

所以Client 内部类可以是 IMediaPlayer 类型的

// 传入的 INTERFACE 就是 IMediaPlayer
// 并且 BnInterface 多重继承了 IMediaPlayer 和 BBinder
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder

public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    typedef INTERFACE           BaseInterface;
    virtual IBinder*            onAsBinder();
;

------------------------

setDataSource

frameworks/av/media/libmediaplayerservice/MediaPlayerService.cpp

status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)

    ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
            fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
    struct stat sb;
    int ret = fstat(fd, &sb);
    if (ret != 0) 
        ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
        return UNKNOWN_ERROR;
    

    ALOGV("st_dev  = %llu", static_cast<unsigned long long>(sb.st_dev));
    ALOGV("st_mode = %u", sb.st_mode);
    ALOGV("st_uid  = %lu", static_cast<unsigned long>(sb.st_uid));
    ALOGV("st_gid  = %lu", static_cast<unsigned long>(sb.st_gid));
    ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));

    if (offset >= sb.st_size) 
        ALOGE("offset error");
        return UNKNOWN_ERROR;
    
    if (offset + length > sb.st_size) 
        length = sb.st_size - offset;
        ALOGV("calculated length = %lld", (long long)length);
    

// 1. 通过MediaPlayerFactory::getPlayerType获取播放器类型
    player_type playerType = MediaPlayerFactory::getPlayerType(this,
                                                               fd,
                                                               offset,
                                                               length);

// 2. 调用setDataSource_pre创建播放器
    sp<MediaPlayerBase> p = setDataSource_pre(playerType);
    if (p == NULL) 
        return NO_INIT;
    


// 3. 调用setDataSource_post通过创建的播放器设置setDataSource
    // now set data source
    return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
  1. 通过MediaPlayerFactory::getPlayerType获取播放器类型
  2. 调用setDataSource_pre创建播放器
  3. 调用setDataSource_post通过创建的播放器设置setDataSource

1. 通过MediaPlayerFactory::getPlayerType获取播放器类型

frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp

获取到的播放器类型为:NU_PLAYER 

player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
                                              int fd,
                                              int64_t offset,
                                              int64_t length) 
    GET_PLAYER_TYPE_IMPL(client, fd, offset, length);


-------------
#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;


--------------------
static player_type getDefaultPlayerType() 

/ return NU_PLAYER;

2. 调用setDataSource_pre创建播放器

sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
        player_type playerType)

    ALOGV("player type = %d", playerType);

    // create the right type of player

// 1. 创建播放器为:NuPlayerDriver
    sp<MediaPlayerBase> p = createPlayer(playerType);
    if (p == NULL) 
        return p;
    

    std::vector<DeathNotifier> deathNotifiers;

    // Listen to death of media.extractor service
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("media.extractor"));
    if (binder == NULL) 
        ALOGE("extractor service not available");
        return NULL;
    
    deathNotifiers.emplace_back(
            binder, [l = wp<MediaPlayerBase>(p)]() 
        sp<MediaPlayerBase> l

以上是关于MediaPlayer 播放本地视频源码流程-setDataSource的主要内容,如果未能解决你的问题,请参考以下文章

Android 使用意图播放本地视频

如何在实际完全加载视频之前开始在 MediaPlayer 中播放视频

SurfaceViewVideoList 列表视频(SurfaceView+Mediaplayer实现播放功能 本地)

Android 简易音乐播放器

Android MediaPlayer播放视频详细步骤

使用MediaPlayer播放音频文件