From 3cc3463f306f425f76bd962755df1132eeac6dfa Mon Sep 17 00:00:00 2001 From: Stephen Hutchinson Date: Wed, 26 Oct 2016 22:54:18 -0400 Subject: [PATCH] avisynth: Support pix_fmts added to AviSynth+ A number of new pix_fmts* have been added to AviSynth+: 16-bit packed RGB and RGBA 10-, 12-, 14, and 16-bit YUV 4:2:0, 4:2:2, and 4:4:4 8-, 10-, 12-, 14-, and 16-bit Planar RGB 8-, 10-, 12-, 14-, and 16-bit Planar YUVA and Planar RGBA 10-, 12-, 14-, and 16-bit GRAY variants 32-bit floating point Planar YUV(A), Planar RGB(A), and GRAY *some of which are not currently available pix_fmts here and were not added to the demuxer due to this Signed-off-by: Diego Biurrun --- libavformat/avisynth.c | 166 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c index b919801316..fd5f323e13 100644 --- a/libavformat/avisynth.c +++ b/libavformat/avisynth.c @@ -19,8 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/attributes.h" #include "libavutil/internal.h" + #include "libavcodec/internal.h" + #include "avformat.h" #include "internal.h" #include "config.h" @@ -69,6 +72,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_planar_rgb); + AVSC_DECLARE_FUNC(avs_is_planar_rgba); #endif #undef AVSC_DECLARE_FUNC } AviSynthLibrary; @@ -96,6 +101,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. */ @@ -138,6 +151,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_planar_rgb, 1); + LOAD_AVS_FUNC(avs_is_planar_rgba, 1); #endif #undef LOAD_AVS_FUNC @@ -222,7 +237,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; @@ -238,6 +253,116 @@ 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_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_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_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; @@ -254,7 +379,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; @@ -280,6 +413,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; @@ -447,6 +594,7 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt, const unsigned char *src_p; int n, i, plane, rowsize, planeheight, pitch, bits; const char *error; + int avsplus av_unused; if (avs->curr_frame >= avs->vi->num_frames) return AVERROR_EOF; @@ -457,6 +605,13 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt, return 0; #ifdef USING_AVISYNTH + /* Detect whether we're using AviSynth 2.6 or AviSynth+ by + * looking for whether avs_is_planar_rgb exists. */ + if (GetProcAddress(avs_library.library, "avs_is_planar_rgb") == NULL) + avsplus = 0; + else + 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. */ @@ -513,6 +668,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;