X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Favisynth.c;h=514cb99f49a767d548ee0505ba8ce1ee4c48ab42;hb=9bbdf5d921ef57e1698f64981e4ea04db7c56fb5;hp=d6167fac928ac6f26484a67ccdb14566080deecf;hpb=ecf65c30cf7545c72c0e27b32283fc9c55b03544;p=ffmpeg diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c index d6167fac928..514cb99f49a 100644 --- a/libavformat/avisynth.c +++ b/libavformat/avisynth.c @@ -29,7 +29,7 @@ /* Platform-specific directives for AviSynth vs AvxSynth. */ #ifdef _WIN32 - #include + #include "compat/w32dlfcn.h" #undef EXTERN_C #include "compat/avisynth/avisynth_c.h" #define AVISYNTH_LIB "avisynth" @@ -39,10 +39,6 @@ #include "compat/avisynth/avxsynth_c.h" #define AVISYNTH_NAME "libavxsynth" #define AVISYNTH_LIB AVISYNTH_NAME SLIBSUF - - #define LoadLibrary(x) dlopen(x, RTLD_NOW | RTLD_LOCAL) - #define GetProcAddress dlsym - #define FreeLibrary dlclose #endif typedef struct AviSynthLibrary { @@ -68,10 +64,8 @@ typedef struct AviSynthLibrary { AVSC_DECLARE_FUNC(avs_get_pitch_p); AVSC_DECLARE_FUNC(avs_get_read_ptr_p); AVSC_DECLARE_FUNC(avs_get_row_size_p); - AVSC_DECLARE_FUNC(avs_is_yv24); - AVSC_DECLARE_FUNC(avs_is_yv16); - AVSC_DECLARE_FUNC(avs_is_yv411); - AVSC_DECLARE_FUNC(avs_is_y8); + AVSC_DECLARE_FUNC(avs_is_planar_rgb); + AVSC_DECLARE_FUNC(avs_is_planar_rgba); #endif #undef AVSC_DECLARE_FUNC } AviSynthLibrary; @@ -99,6 +93,14 @@ static const int avs_planes_packed[1] = { 0 }; static const int avs_planes_grey[1] = { AVS_PLANAR_Y }; static const int avs_planes_yuv[3] = { AVS_PLANAR_Y, AVS_PLANAR_U, AVS_PLANAR_V }; +#ifdef USING_AVISYNTH +static const int avs_planes_rgb[3] = { AVS_PLANAR_G, AVS_PLANAR_B, + AVS_PLANAR_R }; +static const int avs_planes_yuva[4] = { AVS_PLANAR_Y, AVS_PLANAR_U, + AVS_PLANAR_V, AVS_PLANAR_A }; +static const int avs_planes_rgba[4] = { AVS_PLANAR_G, AVS_PLANAR_B, + AVS_PLANAR_R, AVS_PLANAR_A }; +#endif /* A conflict between C++ global objects, atexit, and dynamic loading requires * us to register our own atexit handler to prevent double freeing. */ @@ -112,13 +114,13 @@ static av_cold void avisynth_atexit_handler(void); static av_cold int avisynth_load_library(void) { - avs_library.library = LoadLibrary(AVISYNTH_LIB); + avs_library.library = dlopen(AVISYNTH_LIB, RTLD_NOW | RTLD_LOCAL); if (!avs_library.library) return AVERROR_UNKNOWN; #define LOAD_AVS_FUNC(name, continue_on_fail) \ avs_library.name = \ - (void *)GetProcAddress(avs_library.library, #name); \ + (void *)dlsym(avs_library.library, #name); \ if (!continue_on_fail && !avs_library.name) \ goto fail; @@ -142,10 +144,8 @@ static av_cold int avisynth_load_library(void) LOAD_AVS_FUNC(avs_get_pitch_p, 1); LOAD_AVS_FUNC(avs_get_read_ptr_p, 1); LOAD_AVS_FUNC(avs_get_row_size_p, 1); - LOAD_AVS_FUNC(avs_is_yv24, 1); - LOAD_AVS_FUNC(avs_is_yv16, 1); - LOAD_AVS_FUNC(avs_is_yv411, 1); - LOAD_AVS_FUNC(avs_is_y8, 1); + LOAD_AVS_FUNC(avs_is_planar_rgb, 1); + LOAD_AVS_FUNC(avs_is_planar_rgba, 1); #endif #undef LOAD_AVS_FUNC @@ -153,7 +153,7 @@ static av_cold int avisynth_load_library(void) return 0; fail: - FreeLibrary(avs_library.library); + dlclose(avs_library.library); return AVERROR_UNKNOWN; } @@ -221,7 +221,7 @@ static av_cold void avisynth_atexit_handler(void) avisynth_context_destroy(avs); avs = next; } - FreeLibrary(avs_library.library); + dlclose(avs_library.library); avs_atexit_called = 1; } @@ -230,7 +230,7 @@ static av_cold void avisynth_atexit_handler(void) static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) { AviSynthContext *avs = s->priv_data; - int planar = 0; // 0: packed, 1: YUV, 2: Y8 + int planar = 0; // 0: packed, 1: YUV, 2: Y8, 3: Planar RGB, 4: YUVA, 5: Planar RGBA st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; @@ -246,6 +246,136 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) switch (avs->vi->pixel_type) { #ifdef USING_AVISYNTH +/* 10~16-bit YUV pix_fmts (AviSynth+) */ + case AVS_CS_YUV444P10: + st->codecpar->format = AV_PIX_FMT_YUV444P10; + planar = 1; + break; + case AVS_CS_YUV422P10: + st->codecpar->format = AV_PIX_FMT_YUV422P10; + planar = 1; + break; + case AVS_CS_YUV420P10: + st->codecpar->format = AV_PIX_FMT_YUV420P10; + planar = 1; + break; + case AVS_CS_YUV444P12: + st->codecpar->format = AV_PIX_FMT_YUV444P12; + planar = 1; + break; + case AVS_CS_YUV422P12: + st->codecpar->format = AV_PIX_FMT_YUV422P12; + planar = 1; + break; + case AVS_CS_YUV420P12: + st->codecpar->format = AV_PIX_FMT_YUV420P12; + planar = 1; + break; + case AVS_CS_YUV444P14: + st->codecpar->format = AV_PIX_FMT_YUV444P14; + planar = 1; + break; + case AVS_CS_YUV422P14: + st->codecpar->format = AV_PIX_FMT_YUV422P14; + planar = 1; + break; + case AVS_CS_YUV420P14: + st->codecpar->format = AV_PIX_FMT_YUV420P14; + planar = 1; + break; + case AVS_CS_YUV444P16: + st->codecpar->format = AV_PIX_FMT_YUV444P16; + planar = 1; + break; + case AVS_CS_YUV422P16: + st->codecpar->format = AV_PIX_FMT_YUV422P16; + planar = 1; + break; + case AVS_CS_YUV420P16: + st->codecpar->format = AV_PIX_FMT_YUV420P16; + planar = 1; + break; +/* 8~16-bit YUV pix_fmts with Alpha (AviSynth+) */ + case AVS_CS_YUVA444: + st->codecpar->format = AV_PIX_FMT_YUVA444P; + planar = 4; + break; + case AVS_CS_YUVA422: + st->codecpar->format = AV_PIX_FMT_YUVA422P; + planar = 4; + break; + case AVS_CS_YUVA420: + st->codecpar->format = AV_PIX_FMT_YUVA420P; + planar = 4; + break; + case AVS_CS_YUVA444P10: + st->codecpar->format = AV_PIX_FMT_YUVA444P10; + planar = 4; + break; + case AVS_CS_YUVA422P10: + st->codecpar->format = AV_PIX_FMT_YUVA422P10; + planar = 4; + break; + case AVS_CS_YUVA420P10: + st->codecpar->format = AV_PIX_FMT_YUVA420P10; + planar = 4; + break; + case AVS_CS_YUVA444P16: + st->codecpar->format = AV_PIX_FMT_YUVA444P16; + planar = 4; + break; + case AVS_CS_YUVA422P16: + st->codecpar->format = AV_PIX_FMT_YUVA422P16; + planar = 4; + break; + case AVS_CS_YUVA420P16: + st->codecpar->format = AV_PIX_FMT_YUVA420P16; + planar = 4; + break; +/* Planar RGB pix_fmts (AviSynth+) */ + case AVS_CS_RGBP: + st->codecpar->format = AV_PIX_FMT_GBRP; + planar = 3; + break; + case AVS_CS_RGBP10: + st->codecpar->format = AV_PIX_FMT_GBRP10; + planar = 3; + break; + case AVS_CS_RGBP12: + st->codecpar->format = AV_PIX_FMT_GBRP12; + planar = 3; + break; + case AVS_CS_RGBP14: + st->codecpar->format = AV_PIX_FMT_GBRP14; + planar = 3; + break; + case AVS_CS_RGBP16: + st->codecpar->format = AV_PIX_FMT_GBRP16; + planar = 3; + break; +/* Planar RGB pix_fmts with Alpha (AviSynth+) */ + case AVS_CS_RGBAP: + st->codecpar->format = AV_PIX_FMT_GBRAP; + planar = 5; + break; + case AVS_CS_RGBAP10: + st->codecpar->format = AV_PIX_FMT_GBRAP10; + planar = 5; + break; + case AVS_CS_RGBAP12: + st->codecpar->format = AV_PIX_FMT_GBRAP12; + planar = 5; + break; + case AVS_CS_RGBAP16: + st->codecpar->format = AV_PIX_FMT_GBRAP16; + planar = 5; + break; +/* GRAY16 (AviSynth+) */ + case AVS_CS_Y16: + st->codecpar->format = AV_PIX_FMT_GRAY16; + planar = 2; + break; +/* pix_fmts added in AviSynth 2.6 */ case AVS_CS_YV24: st->codecpar->format = AV_PIX_FMT_YUV444P; planar = 1; @@ -262,7 +392,15 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) st->codecpar->format = AV_PIX_FMT_GRAY8; planar = 2; break; +/* 16-bit packed RGB pix_fmts (AviSynth+) */ + case AVS_CS_BGR48: + st->codecpar->format = AV_PIX_FMT_BGR48; + break; + case AVS_CS_BGR64: + st->codecpar->format = AV_PIX_FMT_BGRA64; + break; #endif +/* AviSynth 2.5 and AvxSynth pix_fmts */ case AVS_CS_BGR24: st->codecpar->format = AV_PIX_FMT_BGR24; break; @@ -288,6 +426,20 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) } switch (planar) { +#ifdef USING_AVISYNTH + case 5: // Planar RGB + Alpha + avs->n_planes = 4; + avs->planes = avs_planes_rgba; + break; + case 4: // YUV + Alpha + avs->n_planes = 4; + avs->planes = avs_planes_yuva; + break; + case 3: // Planar RGB + avs->n_planes = 3; + avs->planes = avs_planes_rgb; + break; +#endif case 2: // Y8 avs->n_planes = 1; avs->planes = avs_planes_grey; @@ -465,20 +617,21 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt, return 0; #ifdef USING_AVISYNTH - /* Define the bpp values for the new AviSynth 2.6 colorspaces. - * Since AvxSynth doesn't have these functions, special-case - * it in order to avoid implicit declaration errors. */ - - if (avs_library.avs_is_yv24(avs->vi)) - bits = 24; - else if (avs_library.avs_is_yv16(avs->vi)) - bits = 16; - else if (avs_library.avs_is_yv411(avs->vi)) - bits = 12; - else if (avs_library.avs_is_y8(avs->vi)) - bits = 8; + /* Detect whether we're using AviSynth 2.6 or AviSynth+ by + * looking for whether avs_is_planar_rgb exists. */ + + int avsplus; + + if (GetProcAddress(avs_library.library, "avs_is_planar_rgb") == NULL) + avsplus = 0; else - bits = avs_library.avs_bits_per_pixel(avs->vi); + avsplus = 1; + + /* avs_bits_per_pixel changed to AVSC_API with AviSynth 2.6, which + * requires going through avs_library, while AvxSynth has it under + * the older AVSC_INLINE type, so special-case this. */ + + bits = avs_library.avs_bits_per_pixel(avs->vi); #else bits = avs_bits_per_pixel(avs->vi); #endif @@ -530,6 +683,15 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt, pitch = -pitch; } +#ifdef USING_AVISYNTH + /* Flip Planar RGB video. */ + if (avsplus && (avs_library.avs_is_planar_rgb(avs->vi) || + avs_library.avs_is_planar_rgba(avs->vi))) { + src_p = src_p + (planeheight - 1) * pitch; + pitch = -pitch; + } +#endif + avs_library.avs_bit_blt(avs->env, dst_p, rowsize, src_p, pitch, rowsize, planeheight); dst_p += rowsize * planeheight;