IjkMediaPlayer:入口类
https://blog.csdn.net/wangxiuwen12/article/details/84556860
结构为:
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; //面定义了很多种播放状态,比如,MP_STATE_IDLE ,MP_STATE_INITIALIZED,MP_STATE_ASYNC_PREPARING。ijkmp_change_state_l 函数专门用来改变mp_state 状态值
char*data_source; //存储应用层传入的播放url
void*weak_thiz;
int restart;
int restart_from_beginning;
int seek_req; //记录是否调用了ijkplayer.c里的ijkmp_seek_to
long seek_msec;//记录ijkmp_seek_to 要拖动到第几毫秒值
};
创建时机为:
IJKFFMoviePlayerController->initWithContentURLString:withOptions:{
IJKWeakHolder *weakHolder = [IJKWeakHolder new]; //保存了IJKFFMoviePlayerController的weak指针
weakHolder.object= self;
ijkmp_set_weak_thiz(_mediaPlayer, (__bridge_retained void*) self);//将IJKFFMoviePlayerController对象赋值给_mediaPlayer的weak_thiz属性
ijkmp_set_inject_opaque(_mediaPlayer, (__bridge_retained void*) weakHolder); //将weakHolder赋值给_mediaPlayer->ffplayer的inject_opaque属性
ijkmp_set_ijkio_inject_opaque(_mediaPlayer, (__bridge _retained void*)weakHolder); //将weakHolder赋值给_mediaPlayer->ffplayer的ijkio_inject_opaque属性,这个函数会调用ijkio_manager_create创建_mediaPlayer->ffplayer的(IjkIOManagerContext *)ijkio_manager_ctx属性,ijkio_manager_create内部会创建ijkio_manager_ctx的(IjkIOApplicationContext *)ijkio_app_ctx属性
}
ffmplay:属于IjkMediaPlayer对象,ijkplayer实际上是基于ffplay.c实现的
typedef struct FFPlayer {
/* ffplay context */
VideoState *is;
void *inject_opaque;
void *ijkio_inject_opaque;
IjkIOManagerContext*ijkio_manager_ctx;
}
//VideoState也就代表着视频当前的状态,包括帧,数据,解码器等等
typedefs truct VideoState {
SDL_Thread*read_tid; //视频读取数据线程
SDL_Thread _read_tid;
FrameQueue pictq;//解码后队列-视频
FrameQueue sampq;//解码后队列-音频
PacketQueue audioq;//解码前队列-视频
PacketQueue videoq;//解码前队列-音频
SDL_Thread*video_refresh_tid; //视频刷新线程,负责显示
SDL_Thread _video_refresh_tid;
}
SDL_Vout:属于ffmplay对象,图像渲染对象
IJKFF_Pipeline:属于ffmplay对象,包括视频解码以及音频输出部分
播放流程:
当外部调用prepareToPlay启动播放后,ijkplayer内部最终会调用到ffplay.c中的
int ffp_prepare_async_l(FFPlayer *ffp,const char*file_name)
该方法是启动播放器的入口函数,在此会设置player选项,打开audio output,最重要的是调用stream_open方法。
stream_open主要做了以下几件事情:
创建存放video/audio解码前数据的videoq/audioq
创建存放video/audio解码后数据的pictq/sampq
创建读数据线程read_thread
创建视频渲染线程video_refresh_thread
说明:subtitle是与video、audio平行的一个stream,ffplay中也支持对它的处理,即创建存放解码前后数据的两个queue,并且当文件中存在subtitle时,还会启动subtitle的解码线程
ffplay.c中主要的代码调用流程:
调用流程
显示过程:
IJKSDLGLView:核心显示类,包含CAEAGLLayer和framebuffer
- (void)display: (SDL_VoutOverlay*) overlay :每帧绘制
IJKSDLGLView属性:IJK_GLES2_Renderer盛放了opengl属性,在renderer文件内根据overlay->format创建
rgb565-用16位,2个字节表示rgb;rgb888-用24位,3个字节表示rgb;
avformat_open_input:
探测协议类型,如果是网络文件则创建网络链接等
假如url是:ijkio:cache:ffio:http://cdnup.huoying666.com/video/20190530/3411e912ba3ed1173070ad212899b560/3411e.mp4
ijkio是注册到ffmpge系统的私有协议,avformat_open_input方法会调用到ijkio的ijkio_open(URLContext *h)方法,h的prot属性是ijkio结构体
Context *c = h->priv_data;//取出Context
IjkIOManagerContext *manager_ctx = (IjkIOManagerContext *)(c->io_manager_ctx);//取出io_manager_ctx
IjkURLContext *inner = NULL;
ijkio_alloc_url(&inner, url); //alloc inner,inner的protprot是ijkio_cache_protocol,inner的priv_data是IjkIOCacheContext,IjkIOCacheContext也有一个IjkURLContext属性它的protrot是ijkffio,可以以此类推ijkioffio
ijk_map_put(h->ijk_ctx_map, (int64_t)(intptr_t)h->cur_ffmpeg_ctx, inner);//h为上面取出的io_manager_ctx,将io_manager_ctx的cur_ffmpeg_ctx和inner关联,
会调用到ijkio_open这个方法,而cache:ffio:http://cdnup.huoying666.com/video/20190530/3411e912ba3ed1173070ad212899b560/3411e.mp4是ijk自己的协议IjkURLProtocol,最终会调用ijkio_alloc_url(),这个方法又会根据自己的协议来进行调用









网友评论