整个IJK播放器框架相较于原始ffplay.c播放器,在三处进行了抽象,分别是:
(1)解码器配置初始化操作,对应的数据结构是:
struct IJKFF_Pipeline {SDL_Class *opaque_class;IJKFF_Pipeline_Opaque *opaque;void (*func_destroy) (IJKFF_Pipeline *pipeline);IJKFF_Pipenode *(*func_open_video_decoder) (IJKFF_Pipeline *pipeline, FFPlayer *ffp);SDL_Aout *(*func_open_audio_output) (IJKFF_Pipeline *pipeline, FFPlayer *ffp);IJKFF_Pipenode *(*func_init_video_decoder) (IJKFF_Pipeline *pipeline, FFPlayer *ffp);int (*func_config_video_decoder) (IJKFF_Pipeline *pipeline, FFPlayer *ffp);
};
在该抽象里针对视频,完成了mediacodec方式解码和软解码的统一接入,对音频实现了opensles的渲染方式和audiotrack方式渲染,这很自然,因为视频的重点是解码,而音频的重点是渲染,当然,不是说视频的渲染不重要,于是有了第二个抽象SDL_Vout。
对于android平台,该数据结构实际上就是通过接口ffpipeline_create_from_android创建为平台专有的,具体流程是:
(2)视频渲染,对应的数据结构是:
struct SDL_Vout {SDL_mutex *mutex;SDL_Class *opaque_class;SDL_Vout_Opaque *opaque;SDL_VoutOverlay *(*create_overlay)(int width, int height, int frame_format, SDL_Vout *vout);void (*free_l)(SDL_Vout *vout);int (*display_overlay)(SDL_Vout *vout, SDL_VoutOverlay *overlay);Uint32 overlay_output_format;
};
其中SDL_VoutOverlay的定义是:
struct SDL_VoutOverlay {int w; /**< Read-only */int h; /**< Read-only */Uint32 format; /**< Read-only */int planes; /**< Read-only */Uint16 *pitches; /**< in bytes, Read-only */Uint8 **pixels; /**< Read-write */int is_private;int sar_num;int sar_den;SDL_Class *opaque_class;SDL_VoutOverlay_Opaque *opaque;void (*free_l)(SDL_VoutOverlay *overlay);int (*lock)(SDL_VoutOverlay *overlay);int (*unlock)(SDL_VoutOverlay *overlay);void (*unref)(SDL_VoutOverlay *overlay);int (*func_fill_frame)(SDL_VoutOverlay *overlay, const AVFrame *frame);
};
该抽象实现了mediacodec解码器接口surface渲染和opengl方式渲染的统一接入接口。
(3)把从av_read_frame接口返回的packet进行解码,并queue_picture放置到渲染帧队列里去这个过程进行抽象,形成IJKFF_Pipenode:
struct IJKFF_Pipenode {SDL_mutex *mutex;void *opaque;void (*func_destroy) (IJKFF_Pipenode *node);int (*func_run_sync)(IJKFF_Pipenode *node);int (*func_flush) (IJKFF_Pipenode *node); // optional
};
IJK播放器经过以上三点抽象后,形成与ffplay不同的整体架构:
1,IJK基于mediacodec硬解码的渲染流程
IJK播放器如果是使用mediacodec硬解码,则是用mediacodec的config接口设置进来的surface直接渲染,实际上并没有将Frame传递给其他模块,若想通过OpenGL方式渲染,走软解渲染一样的流程,则必须进行定制开发。
2,IJK基于软解的渲染流程
IJK基于软解的渲染是通过OpenGL方式渲染的。