欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ijkplayer源码---setDataSource

程序员文章站 2022-07-01 20:32:46
...

我们要让ijk能够进行播放,必须设置播放路径。可以是本地的也可以是网络的。

我们在

IMediaPlayer

 接口中可以看到下面的接口

@TargetApi(14)
void setDataSource(Context var1, Uri var2, Map<String, String> var3) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;

void setDataSource(FileDescriptor var1) throws IOException, IllegalArgumentException, IllegalStateException;

void setDataSource(String var1) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;

我们分析setDataSource,

setDataSource的实现在

public final class IjkMediaPlayer extends AbstractMediaPlayer 
private String mDataSource;
public void setDataSource(String path) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
    this.mDataSource = path;
    this._setDataSource(path, (String[])null, (String[])null);
}
private native void _setDataSource(String var1, String[] var2, String[] var3) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
}

 

可以看到,调用后先对播放的路径进行了下保存,然后又调用了_setDataSource的native方法。

我们接下来看下_setDataSource的实现

#define JNI_CLASS_IJKPLAYER     "tv/danmaku/ijk/media/player/IjkMediaPlayer"
static JNINativeMethod g_methods[] = {
    {
        "_setDataSource",
        "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
        (void *) IjkMediaPlayer_setDataSourceAndHeaders
    },
    }
    
    JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
    JNIEnv* env = NULL;
 
 
    g_jvm = vm;
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);
 
 
    pthread_mutex_init(&g_clazz.mutex, NULL );
 
 
    // FindClass returns LocalReference
    IJK_FIND_JAVA_CLASS(env, g_clazz.clazz, JNI_CLASS_IJKPLAYER);
    (*env)->RegisterNatives(env, g_clazz.clazz, g_methods, NELEM(g_methods) );
 
 
    ijkmp_global_init();
    ijkmp_global_set_inject_callback(inject_callback);
 
 
    FFmpegApi_global_init(env);
 
 
    return JNI_VERSION_1_4;
}

通过上面的代码我们可以知道_setDataSource对应的函数是IjkMediaPlayer_setDataSourceAndHeaders

我们下面分析下这个函数

static void
IjkMediaPlayer_setDataSourceAndHeaders(
    JNIEnv *env, jobject thiz, jstring path,
    jobjectArray keys, jobjectArray values)
{
    MPTRACE("%s\n", __func__);
    int retval = 0;
    const char *c_path = NULL;
    //获得IjkMediaPlayer
    IjkMediaPlayer *mp = jni_get_media_player(env, thiz);
    JNI_CHECK_GOTO(path, env, "java/lang/IllegalArgumentException", "mpjni: setDataSource: null path", LABEL_RETURN);
    JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException", "mpjni: setDataSource: null mp", LABEL_RETURN);


    //转化成char*类型
    c_path = (*env)->GetStringUTFChars(env, path, NULL );
    JNI_CHECK_GOTO(c_path, env, "java/lang/OutOfMemoryError", "mpjni: setDataSource: path.string oom", LABEL_RETURN);


    ALOGV("setDataSource: path %s", c_path);
    //将path设置禁mp当中
    retval = ijkmp_set_data_source(mp, c_path);
    (*env)->ReleaseStringUTFChars(env, path, c_path);


    IJK_CHECK_MPRET_GOTO(retval, env, LABEL_RETURN);


LABEL_RETURN:
    ijkmp_dec_ref_p(&mp);
}

我们接下来看

int ijkmp_set_data_source(IjkMediaPlayer *mp, const char *url)
{
    assert(mp);
    assert(url);
    MPTRACE("ijkmp_set_data_source(url=\"%s\")\n", url);
    pthread_mutex_lock(&mp->mutex);
    int retval = ijkmp_set_data_source_l(mp, url);
    pthread_mutex_unlock(&mp->mutex);
    MPTRACE("ijkmp_set_data_source(url=\"%s\")=%d\n", url, retval);
    return retval;
}

static int ijkmp_set_data_source_l(IjkMediaPlayer *mp, const char *url)
{
    assert(mp);
    assert(url);


    // MPST_RET_IF_EQ(mp->mp_state, MP_STATE_IDLE);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_INITIALIZED);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_ASYNC_PREPARING);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_PREPARED);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_STARTED);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_PAUSED);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_COMPLETED);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_STOPPED);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_ERROR);
    MPST_RET_IF_EQ(mp->mp_state, MP_STATE_END);


    freep((void**)&mp->data_source);
    mp->data_source = strdup(url);
    if (!mp->data_source)
        return EIJK_OUT_OF_MEMORY;


    ijkmp_change_state_l(mp, MP_STATE_INITIALIZED);
    return 0;
}

mp->data_source = strdup(url);

struct IjkMediaPlayer {
    volatile int ref_count;
    pthread_mutex_t mutex;
    FFPlayer *ffplayer;
 
 
    int (*msg_loop)(void*);
    SDL_Thread *msg_thread;
    SDL_Thread _msg_thread;
 
 
    int mp_state;
    char *data_source;
    void *weak_thiz;
 
 
    int restart;
    int restart_from_beginning;
    int seek_req;
    long seek_msec;
};

IjkMediaPlayer设置了源地址data_source