summaryrefslogtreecommitdiff
path: root/libavformat/avisynth.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/avisynth.c')
-rw-r--r--libavformat/avisynth.c247
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;