new IjkMediaPlayer();
IjkMediaPlayer.java中初始化方法:
public IjkMediaPlayer() {
this(sLocalLibLoader);
}
调用
public IjkMediaPlayer(IjkLibLoader libLoader) {
//初始化player
initPlayer(libLoader);
}
private void initPlayer(IjkLibLoader libLoader) {
loadLibrariesOnce(libLoader);//加载native库,注册静态方法
initNativeOnce();
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;
}
native_setup(new WeakReference<IjkMediaPlayer>(this));//弱引用给到native层用
}
加载native库
public static void loadLibrariesOnce(IjkLibLoader libLoader) {
synchronized (IjkMediaPlayer.class) {
if (!mIsLibLoaded) {
if (libLoader ==null)
libLoader =sLocalLibLoader;
libLoader.loadLibrary("ijkffmpeg");
libLoader.loadLibrary("ijksdl");
libLoader.loadLibrary("ijkplayer");
mIsLibLoaded =true;
}
}
}
ijkplayer_jni.c:
当去加载native库时,会调用JNI_OnLoad方法:
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);//注册base64编码方法
return JNI_VERSION_1_4;
}
ijkplayer.c: ijkmp_global_init():
void ijkmp_global_init()
{
ffp_global_init();
}
ff_ffplayer.c : ffp_global_init():
void ffp_global_init(){
if (g_ffmpeg_global_inited)//如果初始过了,返回
return;
ALOGD("ijkmediaplayer version : %s", ijkmp_version());
/* register all codecs, demux and protocols */
avcodec_register_all();//注册编解码器
#if CONFIG_AVDEVICE
avdevice_register_all();//注册设备
#endif
#if CONFIG_AVFILTER
avfilter_register_all();//注册滤镜,用于图像处理,音频重采样处理等
#endif
av_register_all();//注册,包括编解码器以及网络其他等
ijkav_register_all();//注册网络协议
avformat_network_init();
av_lockmgr_register(lockmgr);
av_log_set_callback(ffp_log_callback_brief);
av_init_packet(&flush_pkt);
flush_pkt.data = (uint8_t *)&flush_pkt;
g_ffmpeg_global_inited =true;
}
native_setup(new WeakReference<IjkMediaPlayer>(this));
ijkplayer_jni.c:IjkMediaPlayer_native_setup();
static void IjkMediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
MPTRACE("%s\n", __func__);
IjkMediaPlayer *mp = ijkmp_android_create(message_loop);//创建IjkMediaPlayer指针
JNI_CHECK_GOTO(mp, env, "java/lang/OutOfMemoryError", "mpjni: native_setup: ijkmp_create() failed", LABEL_RETURN);
jni_set_media_player(env, thiz, mp);//把旧的player释放掉,设置新的player
ijkmp_set_weak_thiz(mp, (*env)->NewGlobalRef(env, weak_this));//设置全局弱引用player
ijkmp_set_inject_opaque(mp, ijkmp_get_weak_thiz(mp));//设置AVApplication
ijkmp_set_ijkio_inject_opaque(mp, ijkmp_get_weak_thiz(mp));//设置io
ijkmp_android_set_mediacodec_select_callback(mp, mediacodec_select_callback, ijkmp_get_weak_thiz(mp));//设置编码回调
LABEL_RETURN:
ijkmp_dec_ref_p(&mp);
}
IjkMediaPlayer *mp = ijkmp_android_create(message_loop)
ijkplayer_android.c:
IjkMediaPlayer *ijkmp_android_create(int(*msg_loop)(void*))
{
//创建播放器
IjkMediaPlayer *mp = ijkmp_create(msg_loop);
if (!mp)
goto fail;
//创建渲染输出对象
mp->ffplayer->vout = SDL_VoutAndroid_CreateForAndroidSurface();
if (!mp->ffplayer->vout)
goto fail;
//创建pipeline,视频编解码器,音频输出
mp->ffplayer->pipeline = ffpipeline_create_from_android(mp->ffplayer);
if (!mp->ffplayer->pipeline)
goto fail;
ffpipeline_set_vout(mp->ffplayer->pipeline, mp->ffplayer->vout);
return mp;
fail:
ijkmp_dec_ref_p(&mp);
return NULL;
}
IjkMediaPlayer *mp = ijkmp_create(msg_loop);
ijkplayer.c
IjkMediaPlayer *ijkmp_create(int (*msg_loop)(void*))
{
IjkMediaPlayer *mp = (IjkMediaPlayer *) mallocz(sizeof(IjkMediaPlayer));
if (!mp)
goto fail;
mp->ffplayer = ffp_create();
if (!mp->ffplayer)
goto fail;
mp->msg_loop = msg_loop;
ijkmp_inc_ref(mp);
pthread_mutex_init(&mp->mutex, NULL);
return mp;
fail:
ijkmp_destroy_p(&mp);
return NULL;
}
mp->ffplayer = ffp_create();
ff_ffplay.c:
FFPlayer *ffp_create()
{
av_log(NULL, AV_LOG_INFO, "av_version_info: %s\n", av_version_info());
av_log(NULL, AV_LOG_INFO, "ijk_version_info: %s\n", ijk_version_info());
FFPlayer* ffp = (FFPlayer*) av_mallocz(sizeof(FFPlayer));
if (!ffp)
return NULL;
msg_queue_init(&ffp->msg_queue);
ffp->af_mutex = SDL_CreateMutex();
ffp->vf_mutex = SDL_CreateMutex();
ffp_reset_internal(ffp);
ffp->av_class = &ffp_context_class;
ffp->meta = ijkmeta_create();
av_opt_set_defaults(ffp);
return ffp;
}
涉及到到结构体:
IjkMediaPlayer,在ijkplayer_internal.h中:
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;
};
FFPlayer结构体,在ff_ffplay_def.h中:
typedef struct FFPlayer {
const AVClass *av_class;
/* ffplay context */
VideoState *is;
/* format/codec options */
AVDictionary *format_opts;
AVDictionary *codec_opts;
AVDictionary *sws_dict;
AVDictionary *player_opts;
AVDictionary *swr_opts;
AVDictionary *swr_preset_opts;
/* ffplay options specified by the user */
#ifdef FFP_MERGE
AVInputFormat *file_iformat;
#endif
char *input_filename;
#ifdef FFP_MERGE
const char *window_title;
int fs_screen_width;
int fs_screen_height;
int default_width;
int default_height;
int screen_width;
int screen_height;
#endif
int audio_disable;
int video_disable;
int subtitle_disable;
const char* wanted_stream_spec[AVMEDIA_TYPE_NB];
int seek_by_bytes;
int display_disable;
int show_status;
int av_sync_type;
int64_t start_time;
int64_t duration;
int fast;
int genpts;
int lowres;
int decoder_reorder_pts;
int autoexit;
#ifdef FFP_MERGE
int exit_on_keydown;
int exit_on_mousedown;
#endif
int loop;
int framedrop;
int64_t seek_at_start;
int subtitle;
int infinite_buffer;
enum ShowMode show_mode;
char *audio_codec_name;
char *subtitle_codec_name;
char *video_codec_name;
double rdftspeed;
#ifdef FFP_MERGE
int64_t cursor_last_shown;
int cursor_hidden;
#endif
#if CONFIG_AVFILTER
const char **vfilters_list;
int nb_vfilters;
char *afilters;
char *vfilter0;
#endif
int autorotate;
int find_stream_info;
unsigned sws_flags;
/* current context */
#ifdef FFP_MERGE
int is_full_screen;
#endif
int64_t audio_callback_time;
#ifdef FFP_MERGE
SDL_Surface *screen;
#endif
/* extra fields */
SDL_Aout *aout;
SDL_Vout *vout;
struct IJKFF_Pipeline *pipeline;
struct IJKFF_Pipenode *node_vdec;
int sar_num;
int sar_den;
char *video_codec_info;
char *audio_codec_info;
char *subtitle_codec_info;
Uint32 overlay_format;
int last_error;
int prepared;
int auto_resume;
int error;
int error_count;
int start_on_prepared;
int first_video_frame_rendered;
int first_audio_frame_rendered;
int sync_av_start;
MessageQueue msg_queue;
int64_t playable_duration_ms;
int packet_buffering;
int pictq_size;
int max_fps;
int startup_volume;
int videotoolbox;
int vtb_max_frame_width;
int vtb_async;
int vtb_wait_async;
int vtb_handle_resolution_change;
int mediacodec_all_videos;
int mediacodec_avc;
int mediacodec_hevc;
int mediacodec_mpeg2;
int mediacodec_mpeg4;
int mediacodec_handle_resolution_change;
int mediacodec_auto_rotate;
int opensles;
int soundtouch_enable;
char *iformat_name;
int no_time_adjust;
double preset_5_1_center_mix_level;
struct IjkMediaMeta *meta;
SDL_SpeedSampler vfps_sampler;
SDL_SpeedSampler vdps_sampler;
/* filters */
SDL_mutex *vf_mutex;
SDL_mutex *af_mutex;
int vf_changed;
int af_changed;
float pf_playback_rate;
int pf_playback_rate_changed;
float pf_playback_volume;
int pf_playback_volume_changed;
void *inject_opaque;
void *ijkio_inject_opaque;
FFStatistic stat;
FFDemuxCacheControl dcc;
AVApplicationContext *app_ctx;
IjkIOManagerContext *ijkio_manager_ctx;
int enable_accurate_seek;
int accurate_seek_timeout;
int mediacodec_sync;
int skip_calc_frame_rate;
int get_frame_mode;
GetImgInfo *get_img_info;
int async_init_decoder;
char *video_mime_type;
char *mediacodec_default_name;
int ijkmeta_delay_init;
int render_wait_start;
}
网友评论