diff options
Diffstat (limited to 'libavformat/avisynth.c')
-rw-r--r-- | libavformat/avisynth.c | 247 |
1 files changed, 203 insertions, 44 deletions
diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c index fe71a427a6..514cb99f49 100644 --- a/libavformat/avisynth.c +++ b/libavformat/avisynth.c @@ -2,20 +2,19 @@ * AviSynth/AvxSynth support * Copyright (c) 2012 AvxSynth Team * - * This file is part of Libav. - * - * Libav is free software; you can redistribute it and/or + * This file is part of FFmpeg + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -30,20 +29,16 @@ /* Platform-specific directives for AviSynth vs AvxSynth. */ #ifdef _WIN32 - #include <windows.h> + #include "compat/w32dlfcn.h" #undef EXTERN_C - #include <avisynth/avisynth_c.h> + #include "compat/avisynth/avisynth_c.h" #define AVISYNTH_LIB "avisynth" #define USING_AVISYNTH #else #include <dlfcn.h> - #include <avxsynth/avxsynth_c.h> + #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 { @@ -69,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; @@ -100,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. */ @@ -113,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; @@ -143,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 @@ -154,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; } @@ -222,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; } @@ -231,23 +230,152 @@ 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; st->codecpar->width = avs->vi->width; st->codecpar->height = avs->vi->height; - st->time_base = (AVRational) { avs->vi->fps_denominator, - avs->vi->fps_numerator }; st->avg_frame_rate = (AVRational) { avs->vi->fps_numerator, avs->vi->fps_denominator }; st->start_time = 0; st->duration = avs->vi->num_frames; st->nb_frames = avs->vi->num_frames; + avpriv_set_pts_info(st, 32, avs->vi->fps_denominator, avs->vi->fps_numerator); 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; @@ -264,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; @@ -290,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; @@ -312,9 +462,8 @@ static int avisynth_create_stream_audio(AVFormatContext *s, AVStream *st) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->sample_rate = avs->vi->audio_samples_per_second; st->codecpar->channels = avs->vi->nchannels; - st->time_base = (AVRational) { 1, - avs->vi->audio_samples_per_second }; - st->duration = avs->vi->num_audio_samples; + st->duration = avs->vi->num_audio_samples; + avpriv_set_pts_info(st, 64, 1, avs->vi->audio_samples_per_second); switch (avs->vi->sample_type) { case AVS_SAMPLE_INT8: @@ -405,7 +554,7 @@ static int avisynth_open_file(AVFormatContext *s) avs->vi = avs_library.avs_get_video_info(avs->clip); #ifdef USING_AVISYNTH - /* On Windows, libav supports AviSynth interface version 6 or higher. + /* On Windows, FFmpeg supports AviSynth interface version 6 or higher. * This includes AviSynth 2.6 RC1 or higher, and AviSynth+ r1718 or higher, * and excludes 2.5 and the 2.6 alphas. Since AvxSynth identifies itself * as interface version 3 like 2.5.8, this needs to be special-cased. */ @@ -468,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 @@ -533,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; |