SDL_Vout顾名思义应该和图像输出有关
SDL_Vout *vout;
我们看下vout那里进行的赋值
IjkMediaPlayer *ijkmp_android_create(int(*msg_loop)(void*))
{
。。。。。。。
mp->ffplayer->vout = SDL_VoutAndroid_CreateForAndroidSurface();
if (!mp->ffplayer->vout)
goto fail;
。。。。。。。。
}
我们看下SDL_Vout的定义
ijkmedia/ijksdl/ijksdl_vout.h
typedef struct SDL_Vout SDL_Vout;
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);
释放SDL_Vout
void (*free_l)(SDL_Vout *vout);
显示图层
int (*display_overlay)(SDL_Vout *vout, SDL_VoutOverlay *overlay);
图层格式
Uint32 overlay_format;
};
SDL_Class *opaque_class;
我们看到SDL_Class只有一个name
typedef struct SDL_Class {
const char *name;
} SDL_Class;
SDL_Vout_Opaque *opaque;
Opaque翻译为不透明的, 怎么赋值的呢?
我们进入
SDL_Vout *SDL_VoutAndroid_CreateForAndroidSurface()
{
return SDL_VoutAndroid_CreateForANativeWindow();
}
ijksdl/android/ijksdl_vout_android_nativewindow.c
SDL_Vout *SDL_VoutAndroid_CreateForANativeWindow()
{
SDL_Vout *vout = SDL_Vout_CreateInternal(sizeof(SDL_Vout_Opaque));
if (!vout)
return NULL;
SDL_Vout_Opaque *opaque = vout->opaque;
opaque->native_window = NULL;
if (ISDL_Array__init(&opaque->overlay_manager, 32))
goto fail;
if (ISDL_Array__init(&opaque->overlay_pool, 32))
goto fail;
opaque->egl = IJK_EGL_create();
if (!opaque->egl)
goto fail;
vout->opaque_class = &g_nativewindow_class;
vout->create_overlay = func_create_overlay;
vout->free_l = func_free_l;
vout->display_overlay = func_display_overlay;
return vout;
fail:
func_free_l(vout);
return NULL;
}
所以 SDL_Vout_Opaque的定义是在ijkmedia/ijksdl/android/ijksdl_vout_android_nativewindow.c
typedef struct SDL_Vout_Opaque {
ANativeWindow *native_window;
SDL_AMediaCodec *acodec;
int null_native_window_warned; // reduce log for null window
int next_buffer_id;
ISDL_Array overlay_manager;
ISDL_Array overlay_pool;
IJK_EGL *egl;
} SDL_Vout_Opaque;
SDL_VoutOverlay *(*create_overlay)(int width, int height, int frame_format, SDL_Vout *vout);
而这个函数指针在SDL_VoutAndroid_CreateForANativeWindow中进行了赋值
vout->create_overlay = func_create_overlay;
static SDL_VoutOverlay *func_create_overlay_l(int width, int height, int frame_format, SDL_Vout *vout)
{
switch (frame_format) {
case IJK_AV_PIX_FMT__ANDROID_MEDIACODEC:
return SDL_VoutAMediaCodec_CreateOverlay(width, height, vout);
default:
return SDL_VoutFFmpeg_CreateOverlay(width, height, frame_format, vout);
}
}
可以大致猜到一个硬解码一个软解吗
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);
};
其中有个变量SDL_VoutOverlay_Opaque *opaque;
硬解码的情况下走的是
SDL_VoutAMediaCodec_CreateOverlay(width, height, vout);
ijksdl/android/ijksdl_vout_overlay_android_mediacodec.c 中定义的SDL_VoutOverlay_Opaque
typedef struct SDL_VoutOverlay_Opaque {
SDL_mutex *mutex;
SDL_Vout *vout;
SDL_AMediaCodec *acodec;
SDL_AMediaCodecBufferProxy *buffer_proxy;
Uint16 pitches[AV_NUM_DATA_POINTERS];
Uint8 *pixels[AV_NUM_DATA_POINTERS];
} SDL_VoutOverlay_Opaque;
软解吗的情况下走
SDL_VoutFFmpeg_CreateOverlay
ijksdl/ffmpeg/ijksdl_vout_overlay_ffmpeg.c 中定义的SDL_VoutOverlay_Opaque
struct SDL_VoutOverlay_Opaque {
SDL_mutex *mutex;
AVFrame *managed_frame;
AVBufferRef *frame_buffer;
int planes;
AVFrame *linked_frame;
Uint16 pitches[AV_NUM_DATA_POINTERS];
Uint8 *pixels[AV_NUM_DATA_POINTERS];
int no_neon_warned;
struct SwsContext *img_convert_ctx;
int sws_flags;
};