当前位置:网站首页>Overview of demoplayer program framework design of ijkplayer

Overview of demoplayer program framework design of ijkplayer

2022-06-13 06:27:00 That's right

First step Read this source code for a walk , The following preparations are needed

JNI Methods and java How does the method correspond to ?
Android JNI Principle analysis
http://gityuan.com/2016/05/28/android-jni/

JNI Development :
Android The use of notes CMake Conduct JNI Development (Android Studio)
https://anacz.blog.csdn.net/article/details/84202451

JNI Learning notes
Android JNI Study ( 3、 ... and )——Java And Native Mutual invocation
https://www.jianshu.com/p/b71aeb4ed13d

ijkplayer A brief analysis of the framework – From construction to onPrepared
http://yydcdut.com/2019/03/16/ijkplayer-from-constructor-to-prepare/

The following articles can be used as advanced materials .
H264 Detailed explanation of codec protocol
https://blog.csdn.net/qq_19923217/article/details/83348095
https://www.jianshu.com/p/0c296b05ef2a

Support h265 Hard solution and soft solution of Consider the compatibility of hard solutions
Android NDK MediaCodec stay ijkplayer Practice in
https://www.cnblogs.com/jukan/p/9845673.html

The second step DemoPlayer Source code

Source code github Address : https://github.com/YBill/IjkPlayerProject_2.git

The third step Source code walkthrough is the framework description

  • 1> Program entry
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import com.bill.ijkplayerproject_2.util.PageJumpUtil;

public class MainActivity extends AppCompatActivity {
    

   @Override
   protected void onCreate(Bundle savedInstanceState) {
    
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);         ///>  There are two on the interface botton
   }

   public void handleAudioTest(View view) {
                ///> onClick()  Event activation  handleAudioTest
       PageJumpUtil.gotoAudioTestActivity(this);
   }

   public void handleVideoTest(View view) {
                ///> onClick()  Event activation  handleVideoTest
       //PageJumpUtil.gotoVideoSettingActivity(this);
       PageJumpUtil.gotoVideoTestActivity(this);
   }

}
  • 2> Intermediate activation Intent The process
public class PageJumpUtil {
    

   public static void gotoAudioTestActivity(Activity activity) {
    
       Intent intent = new Intent(activity, AudioTestActivity.class);   ///>  Audio test Activity
       activity.startActivity(intent);
   }

   public static void gotoVideoTestActivity(Activity activity) {
    
       Intent intent = new Intent(activity, VideoTestActivity.class);  ///>  Video test Activity
       activity.startActivity(intent);
   }

   public static void gotoVideoSettingActivity(Activity activity) {
    
       Intent intent = new Intent(activity, VideoSettingActivity.class);
       activity.startActivity(intent);
   }
}
  • 3> Video startup process
///> VideoTestActivity.java  in app start-up 
public class VideoTestActivity extends AppCompatActivity {
    

    private boolean mBackPressed;
    private IjkVideoView mVideoView;						///>  be based on  ijkPlayer-java  Medium  IMediaPlayer interface  Encapsulate the implementation of  IjkVideoView  class 
    private AndroidMediaController mMediaController;        ///>  be based on Androidsdk Of  MediaController  Realization  Demo The interface applied in ,  Interface content IMediaController in .

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_test);
        mVideoView = findViewById(R.id.ijk_video_view);
        mMediaController = new AndroidMediaController(this, true);
        mVideoView.setMediaController(mMediaController);
        mMediaController.setPrevNextListeners(new View.OnClickListener() {
    
            @Override
            public void onClick(View v) {
    
                Toast.makeText(VideoTestActivity.this, " next ", Toast.LENGTH_SHORT).show();
            }
        }, new View.OnClickListener() {
    
            @Override
            public void onClick(View v) {
    
                Toast.makeText(VideoTestActivity.this, " the previous ", Toast.LENGTH_SHORT).show();
            }
        });

        IjkMediaPlayer.loadLibrariesOnce(null);																	///> 1>.  Use  ijkplayer-java  Player class methods encapsulated in 
        IjkMediaPlayer.native_profileBegin("libijkplayer.so");													///> 2>.  load ijkplayer.so  The library files 
        mVideoView.setVideoPath("https://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f30.mp4"); ///> 3>.  Create player 、 And put the player in the ready playing state 
// mVideoView.setVideoPath("https://wdl.wallstreetcn.com/41aae4d2-390a-48ff-9230-ee865552e72d");
// mVideoView.setVideoPath("http://o6wf52jln.bkt.clouddn.com/ actor .mp3");
        mVideoView.start();																						///> 4>.  start-up  VideoView  Components , Start the player to play 
    }

    @Override
    public void onBackPressed() {
    
        mBackPressed = true;
        super.onBackPressed();
    }

    @Override
    protected void onStop() {
    
        super.onStop();
        if (mBackPressed || !mVideoView.isBackgroundPlayEnabled()) {
    
            mVideoView.stopPlayback();
            mVideoView.release(true);
            mVideoView.stopBackgroundPlay();
        } else {
    
            mVideoView.enterBackground();
        }
        IjkMediaPlayer.native_profileEnd();
    }

}
///> mVideoView.setVideoPath(Uri *) In the method , The final call ijkVideoView.java  The implementation is as follows 
 private void setVideoURI(Uri uri, Map<String, String> headers) {
    
        mUri = uri;
        mHeaders = headers;
        mSeekWhenPrepared = 0;
        openVideo();																///>  This method creates a player 、 And configure the control callback 
        requestLayout();
        invalidate();
    }

///>  Open video method , Create... In this method  ijkplayer  player 、 And set the callback of the relevant user control program 
     @TargetApi(Build.VERSION_CODES.M)
    private void openVideo() {
    
    	try {
    
            mMediaPlayer = createPlayer(PlayerConfig.getInstance().getPlayer());    ///> 1. Create player , This method configures the parameters to select the player type ExoPlayer、AndroidPlayer or ijkPlayer
                       // a context for the subtitle renderers
            final Context context = getContext();
            // REMOVED: SubtitleController

            // REMOVED: mAudioSession
            /** The video is ready to play */
            mMediaPlayer.setOnPreparedListener(mPreparedListener);
            /** Video interface size change monitoring */
            mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
            /** Video playback completed listening */
            mMediaPlayer.setOnCompletionListener(mCompletionListener);
            /** Video error monitoring */
            mMediaPlayer.setOnErrorListener(mErrorListener);
            /** Video and other information monitoring */
            mMediaPlayer.setOnInfoListener(mInfoListener);
            /** Video buffer monitor */
            mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
            mMediaPlayer.setOnSeekCompleteListener(mSeekCompleteListener);
            mMediaPlayer.setOnTimedTextListener(mOnTimedTextListener);
            mCurrentBufferPercentage = 0;
            String scheme = mUri.getScheme();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                    PlayerConfig.getInstance().getUsingMediaDataSource() &&
                    (TextUtils.isEmpty(scheme) || scheme.equalsIgnoreCase("file"))) {
    
                IMediaDataSource dataSource = new FileMediaDataSource(new File(mUri.toString()));
                mMediaPlayer.setDataSource(dataSource);
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    
                mMediaPlayer.setDataSource(mAppContext, mUri, mHeaders);
            } else {
    
                mMediaPlayer.setDataSource(mUri.toString());
            }
            bindSurfaceHolder(mMediaPlayer, mSurfaceHolder);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setScreenOnWhilePlaying(true);
            mPrepareStartTime = System.currentTimeMillis();
            mMediaPlayer.prepareAsync();

            // REMOVED: mPendingSubtitleTracks

            // we don't set the target state here either, but preserve the
            // target state that was there before.
            mCurrentState = STATE_PREPARING;                                         ///> 2.  Set the player status to   Preparation stage 
            attachMediaController();

        } catch (IOException ex) {
    
            Log.w(TAG, "Unable to open content: " + mUri, ex);
            mCurrentState = STATE_ERROR;
            mTargetState = STATE_ERROR;
            mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
        } catch (IllegalArgumentException ex) {
    
            Log.w(TAG, "Unable to open content: " + mUri, ex);
            mCurrentState = STATE_ERROR;
            mTargetState = STATE_ERROR;
            mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
        } finally {
    
            // REMOVED: mPendingSubtitleTracks.clear();
        }
    }
///> ijkVideoView.java  Medium VideoView Method 
 public void start() {
    																
        if (isInPlaybackState()) {
    
            mMediaPlayer.start();													///> 3.  Start the player to play  
            mCurrentState = STATE_PLAYING;											///> 4.  Set the status to play 
        }
        mTargetState = STATE_PLAYING;
    }

  • 4> Player packaging method
    this Demo Used in the program IjkMediaPlayer The class evolution route is as follows .
    This is ijkplayer The source code provides ijkplayer-java In file Demo Program , This program encapsulates IjkMediaPlayer class .
public interface IMediaPlayer {
    }
————————————————————————————————
			||
			\/
public abstract class AbstractMediaPlayer implements IMediaPlayer {
    }
____________________________________________________________________
            ||
            \/
public final class IjkMediaPlayer extends AbstractMediaPlayer {
    }
_________________________________________________________________

The implementation logic of the class is as follows , What we care about now is Java How the program relates to ijkplayer In the source code C Language programs are associated with ?
The first part In the materials prepared for you , It has been mentioned , We combine this Demo Smooth out the interrelationship .

  • 4.1> Let's look at it first IjkMediaPlayer in Start the player implementation method .
public final class IjkMediaPlayer extends AbstractMediaPlayer {
    

	@Override
    public void start() throws IllegalStateException {
    				
        stayAwake(true);
        _start();													///>  This method calls  native _start()  function 
    }

    private native void _start() throws IllegalStateException;      ///>  Statement here  native void _start()  function , Function implementation ?

    @Override
    public void stop() throws IllegalStateException {
    
        stayAwake(false);
        _stop();
    }

    private native void _stop() throws IllegalStateException;

    @Override
    public void pause() throws IllegalStateException {
    
        stayAwake(false);
        _pause();
    }

    private native void _pause() throws IllegalStateException;


}
  • 4.2> jni Dynamic registration of interface methods
    This part needs to see ijkplayer Source program file ijkplayer\ijkplayer_jni.c file , Yes JNI Method
    The contents of the registration function are as follows :
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) );                     ///>  Dynamic registration  jni  Interface method 

    ijkmp_global_init();
    ijkmp_global_set_inject_callback(inject_callback);

    FFmpegApi_global_init(env);

    return JNI_VERSION_1_4;
}

///> ijkplayer  Registered jni The method is as follows :

static JNINativeMethod g_methods[] = {
    
    {
       "_setDataSource",
        "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
        (void *) IjkMediaPlayer_setDataSourceAndHeaders},											///> IjkMediaPlayer_setDataSourceAndHeaders(JNIEnv *env, jobject thiz, 
        																												jstring path,jobjectArray keys, jobjectArray values);
    {
     "_setDataSourceFd",       "(I)V",     (void *) IjkMediaPlayer_setDataSourceFd },				///> _setDataSourceFd(), Set the local file as the playback source  JNI  Interface 
    {
     "_setDataSource",         
      "(Ltv/danmaku/ijk/media/player/misc/IMediaDataSource;)V", 
      (void *) IjkMediaPlayer_setDataSourceCallback },                                              ///> _setDataSource(),  Set the network file playback source  JNI  Interface 

    {
     "_setVideoSurface",       "(Landroid/view/Surface;)V", (void *) IjkMediaPlayer_setVideoSurface },
    {
     "_prepareAsync",          "()V",      (void *) IjkMediaPlayer_prepareAsync },
    {
     "_start",                 "()V",      (void *) IjkMediaPlayer_start },                        ///> _start()  Start player method , C The implementation of the language is analyzed next .
    {
     "_stop",                  "()V",      (void *) IjkMediaPlayer_stop },
    {
     "seekTo",                 "(J)V",     (void *) IjkMediaPlayer_seekTo },
    {
     "_pause",                 "()V",      (void *) IjkMediaPlayer_pause },
    {
     "isPlaying",              "()Z",      (void *) IjkMediaPlayer_isPlaying },
    {
     "getCurrentPosition",     "()J",      (void *) IjkMediaPlayer_getCurrentPosition },
    {
     "getDuration",            "()J",      (void *) IjkMediaPlayer_getDuration },
    {
     "_release",               "()V",      (void *) IjkMediaPlayer_release },
    {
     "_reset",                 "()V",      (void *) IjkMediaPlayer_reset },
    {
     "setVolume",              "(FF)V",    (void *) IjkMediaPlayer_setVolume },
    {
     "getAudioSessionId",      "()I",      (void *) IjkMediaPlayer_getAudioSessionId },
    {
     "native_init",            "()V",      (void *) IjkMediaPlayer_native_init },
    {
     "native_setup",           "(Ljava/lang/Object;)V", (void *) IjkMediaPlayer_native_setup },
    {
     "native_finalize",        "()V",      (void *) IjkMediaPlayer_native_finalize },

    {
     "_setOption",             "(ILjava/lang/String;Ljava/lang/String;)V", (void *) IjkMediaPlayer_setOption },
    {
     "_setOption",             "(ILjava/lang/String;J)V",                  (void *) IjkMediaPlayer_setOptionLong },

    {
     "_getColorFormatName",    "(I)Ljava/lang/String;",    (void *) IjkMediaPlayer_getColorFormatName },
    {
     "_getVideoCodecInfo",     "()Ljava/lang/String;",     (void *) IjkMediaPlayer_getVideoCodecInfo },
    {
     "_getAudioCodecInfo",     "()Ljava/lang/String;",     (void *) IjkMediaPlayer_getAudioCodecInfo },
    {
     "_getMediaMeta",          "()Landroid/os/Bundle;",    (void *) IjkMediaPlayer_getMediaMeta },
    {
     "_setLoopCount",          "(I)V",                     (void *) IjkMediaPlayer_setLoopCount },
    {
     "_getLoopCount",          "()I",                      (void *) IjkMediaPlayer_getLoopCount },
    {
     "_getPropertyFloat",      "(IF)F",                    (void *) ijkMediaPlayer_getPropertyFloat },
    {
     "_setPropertyFloat",      "(IF)V",                    (void *) ijkMediaPlayer_setPropertyFloat },
    {
     "_getPropertyLong",       "(IJ)J",                    (void *) ijkMediaPlayer_getPropertyLong },
    {
     "_setPropertyLong",       "(IJ)V",                    (void *) ijkMediaPlayer_setPropertyLong },
    {
     "_setStreamSelected",     "(IZ)V",                    (void *) ijkMediaPlayer_setStreamSelected },

    {
     "native_profileBegin",    "(Ljava/lang/String;)V",    (void *) IjkMediaPlayer_native_profileBegin },
    {
     "native_profileEnd",      "()V",                      (void *) IjkMediaPlayer_native_profileEnd },

    {
     "native_setLogLevel",     "(I)V",                     (void *) IjkMediaPlayer_native_setLogLevel },
};

///> ijkplayer_jni.c  Your player starts 
static void
IjkMediaPlayer_start(JNIEnv *env, jobject thiz)
{
    
    MPTRACE("%s\n", __func__);
    IjkMediaPlayer *mp = jni_get_media_player(env, thiz);
    JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException", "mpjni: start: null mp", LABEL_RETURN);

    ijkmp_start(mp);

LABEL_RETURN:
    ijkmp_dec_ref_p(&mp);
}

///> ijkplayer.c  File to start the 
int ijkmp_start(IjkMediaPlayer *mp)
{
    
    assert(mp);
    MPTRACE("ijkmp_start()\n");
    pthread_mutex_lock(&mp->mutex);
    int retval = ijkmp_start_l(mp);
    pthread_mutex_unlock(&mp->mutex);
    MPTRACE("ijkmp_start()=%d\n", retval);
    return retval;
}
static int ijkmp_start_l(IjkMediaPlayer *mp)
{
    
    assert(mp);

    MP_RET_IF_FAILED(ikjmp_chkst_start_l(mp->mp_state));

    ffp_remove_msg(mp->ffplayer, FFP_REQ_START);
    ffp_remove_msg(mp->ffplayer, FFP_REQ_PAUSE);
    ffp_notify_msg1(mp->ffplayer, FFP_REQ_START);     ///>  Through the event mode of message queue 、 Notify the player .
    return 0;
}

this _start() So many interfaces are analyzed , The main point of this article is _setDataSource() Interface implementation , Because I need to tidy up ijkplayer This part of the code .

Step four Go to school _setDataSource() Interface implementation code

4.1>. The next step is from java Code entry starts , How users use this _setDataSource() Interface .


    public void setVideoPath(String path) {
    
        setVideoURI(Uri.parse(path));        ///>  structure  Uri 
    }

    public void setVideoURI(Uri uri) {
    
        setVideoURI(uri, null);              ///> Map<String, String> headers  This parameter is set to null 
    }
    private void setVideoURI(Uri uri, Map<String, String> headers) {
    
        mUri = uri;
        mHeaders = headers;
        mSeekWhenPrepared = 0;
        openVideo();
        requestLayout();
        invalidate();
    }

From this process, we can see that setting up the data source is only uri Assign values to the private Uri mUri in ; Next let's look at openVideo() How to use mUri Variable .

4.2>. Open the video

    @TargetApi(Build.VERSION_CODES.M)
    private void openVideo() {
    
        if (mUri == null || mSurfaceHolder == null) {
    
            // not ready for playback just yet, will try again later
            return;
        }

        String scheme = mUri.getScheme();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                    PlayerConfig.getInstance().getUsingMediaDataSource() &&
                    (TextUtils.isEmpty(scheme) || scheme.equalsIgnoreCase("file"))) {
    
                IMediaDataSource dataSource = new FileMediaDataSource(new File(mUri.toString()));  
                mMediaPlayer.setDataSource(dataSource);												///> IMediaDataSource  type 
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    
                mMediaPlayer.setDataSource(mAppContext, mUri, mHeaders);                           ///> Context  type 
            } else {
    
                mMediaPlayer.setDataSource(mUri.toString());                                       ///> String  type 
            }        
    }

///>  The three corresponding methods for setting data sources , stay  IjkMediaPlayer.java  Implemented in , as follows .
public final class IjkMediaPlayer extends AbstractMediaPlayer {
        
    
     
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @Override
    public void setDataSource(Context context, Uri uri, Map<String, String> headers)
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
    

        final String scheme = uri.getScheme();
        if (ContentResolver.SCHEME_FILE.equals(scheme)) {
    
            setDataSource(uri.getPath());
            return;
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
                && Settings.AUTHORITY.equals(uri.getAuthority())) {
    
            // Redirect ringtones to go directly to underlying provider
            uri = RingtoneManager.getActualDefaultRingtoneUri(context,
                    RingtoneManager.getDefaultType(uri));
            if (uri == null) {
    
                throw new FileNotFoundException("Failed to resolve default ringtone");
            }
        }

        AssetFileDescriptor fd = null;
        try {
       ///>  file type 
            ContentResolver resolver = context.getContentResolver();
            fd = resolver.openAssetFileDescriptor(uri, "r");
            if (fd == null) {
    
                return;
            }
            // Note: using getDeclaredLength so that our behavior is the same
            // as previous versions when the content provider is returning
            // a full file.
            if (fd.getDeclaredLength() < 0) {
    
                setDataSource(fd.getFileDescriptor());
            } else {
    
                setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
            }
            return;
        } catch (SecurityException ignored) {
    
        } catch (IOException ignored) {
    
        } finally {
    
            if (fd != null) {
    
                fd.close();
            }
        }

        Log.d(TAG, "Couldn't open file on client side, trying server side");

        setDataSource(uri.toString(), headers);
    }

    public void setDataSource(String path, Map<String, String> headers)
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException
    {
    
        if (headers != null && !headers.isEmpty()) {
    
            StringBuilder sb = new StringBuilder();
            for(Map.Entry<String, String> entry: headers.entrySet()) {
    
                sb.append(entry.getKey());
                sb.append(":");
                String value = entry.getValue();
                if (!TextUtils.isEmpty(value))
                    sb.append(entry.getValue());
                sb.append("\r\n");
                setOption(OPT_CATEGORY_FORMAT, "headers", sb.toString());
                setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "protocol_whitelist", "async,cache,crypto,file,http,https,ijkhttphook,ijkinject,ijklivehook,ijklongurl,ijksegment,ijktcphook,pipe,rtp,tcp,tls,udp,ijkurlhook,data");
            }
        }
        setDataSource(path);
    }


    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    @Override
    public void setDataSource(FileDescriptor fd)
            throws IOException, IllegalArgumentException, IllegalStateException {
    
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
    
            int native_fd = -1;
            try {
    
                Field f = fd.getClass().getDeclaredField("descriptor"); //NoSuchFieldException
                f.setAccessible(true);
                native_fd = f.getInt(fd); //IllegalAccessException
            } catch (NoSuchFieldException e) {
    
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
    
                throw new RuntimeException(e);
            }
            _setDataSourceFd(native_fd);
        } else {
    
            ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd);
            try {
    
                _setDataSourceFd(pfd.getFd());
            } finally {
    
                pfd.close();
            }
        }
    }

    public void setDataSource(IMediaDataSource mediaDataSource)
            throws IllegalArgumentException, SecurityException, IllegalStateException {
    
        _setDataSource(mediaDataSource);
    }

    private native void _setDataSource(String path, String[] keys, String[] values)
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;

    private native void _setDataSourceFd(int fd)
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;

    private native void _setDataSource(IMediaDataSource mediaDataSource)
            throws IllegalArgumentException, SecurityException, IllegalStateException;

}

This section is for JNI Three interfaces for method registration , I will focus on _setDataSource(String path, String[] keys, String[] values) Network part of C The realization of language .

4.3> go back to ijkplayer_jni.c In file , Find the corresponding C The realization of language

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 *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);

    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);
    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;
}

///> ijkplayer.c  in 
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);                     ///>  Change the data source content 
    if (!mp->data_source)
        return EIJK_OUT_OF_MEMORY;

    ijkmp_change_state_l(mp, MP_STATE_INITIALIZED);   ///>  Change the player state to the initial state 
    return 0;
}

void ijkmp_change_state_l(IjkMediaPlayer *mp, int new_state)
{
    
    mp->mp_state = new_state;										///>  Notification status content 
    ffp_notify_msg1(mp->ffplayer, FFP_MSG_PLAYBACK_STATE_CHANGED);  ///>  Notification player 
}

The above section completes the code reading of the data source setting section .

原网站

版权声明
本文为[That's right]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202270555068615.html