1160 lines · 39.2 KB · C
RawDownload
/* * AviSynth(+) support * Copyright (c) 2012 AvxSynth Team * * 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. * * 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 FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "libavutil/attributes.h"#include "libavutil/internal.h"#include "libavutil/mem.h"#include "libavutil/opt.h"#include "libavutil/thread.h" #include "avformat.h"#include "demux.h"#include "internal.h"#include "config.h" /* Enable function pointer definitions for runtime loading. */#define AVSC_NO_DECLSPEC /* Platform-specific directives. */#ifdef _WIN32  #include "compat/w32dlfcn.h"  #include "libavutil/wchar_filename.h"  #undef EXTERN_C  #define AVISYNTH_LIB "avisynth"#else  #include <dlfcn.h>  #define AVISYNTH_NAME "libavisynth"  #define AVISYNTH_LIB AVISYNTH_NAME SLIBSUF#endif /* Endianness guards for audio */#if HAVE_BIGENDIAN    #define PCM(format) (AV_CODEC_ID_PCM_ ## format ## BE)#else    #define PCM(format) (AV_CODEC_ID_PCM_ ## format ## LE)#endif #include <avisynth/avisynth_c.h> typedef struct AviSynthLibrary {    void *library;#define AVSC_DECLARE_FUNC(name) name ## _func name    AVSC_DECLARE_FUNC(avs_bit_blt);    AVSC_DECLARE_FUNC(avs_clip_get_error);    AVSC_DECLARE_FUNC(avs_check_version);    AVSC_DECLARE_FUNC(avs_create_script_environment);    AVSC_DECLARE_FUNC(avs_delete_script_environment);    AVSC_DECLARE_FUNC(avs_get_audio);    AVSC_DECLARE_FUNC(avs_get_channel_mask);    AVSC_DECLARE_FUNC(avs_get_error);    AVSC_DECLARE_FUNC(avs_get_frame);    AVSC_DECLARE_FUNC(avs_get_version);    AVSC_DECLARE_FUNC(avs_get_video_info);    AVSC_DECLARE_FUNC(avs_invoke);    AVSC_DECLARE_FUNC(avs_is_color_space);    AVSC_DECLARE_FUNC(avs_release_clip);    AVSC_DECLARE_FUNC(avs_release_value);    AVSC_DECLARE_FUNC(avs_release_video_frame);    AVSC_DECLARE_FUNC(avs_take_clip);    AVSC_DECLARE_FUNC(avs_bits_per_pixel);    AVSC_DECLARE_FUNC(avs_get_height_p);    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);    AVSC_DECLARE_FUNC(avs_get_frame_props_ro);    AVSC_DECLARE_FUNC(avs_prop_get_int);    AVSC_DECLARE_FUNC(avs_prop_get_type);    AVSC_DECLARE_FUNC(avs_get_env_property);#undef AVSC_DECLARE_FUNC} AviSynthLibrary; typedef enum AviSynthFlags {    AVISYNTH_FRAMEPROP_FIELD_ORDER = (1 << 0),    AVISYNTH_FRAMEPROP_RANGE = (1 << 1),    AVISYNTH_FRAMEPROP_PRIMARIES = (1 << 2),    AVISYNTH_FRAMEPROP_TRANSFER = (1 << 3),    AVISYNTH_FRAMEPROP_MATRIX = (1 << 4),    AVISYNTH_FRAMEPROP_CHROMA_LOCATION = (1 << 5),    AVISYNTH_FRAMEPROP_SAR = (1 << 6),} AviSynthFlags; typedef struct AviSynthContext {    const AVClass *class;    AVS_ScriptEnvironment *env;    AVS_Clip *clip;    const AVS_VideoInfo *vi;     /* avisynth_read_packet_video() iterates over this. */    int n_planes;    const int *planes;     int curr_stream;    int curr_frame;    int64_t curr_sample;     int error;     uint32_t flags;    struct AviSynthLibrary avs_library;} AviSynthContext; static av_cold int avisynth_load_library(AviSynthContext *avs){    avs->avs_library.library = dlopen(AVISYNTH_LIB, RTLD_NOW | RTLD_LOCAL);    if (!avs->avs_library.library)        return AVERROR_UNKNOWN; #define LOAD_AVS_FUNC(name, continue_on_fail)                          \        avs->avs_library.name = (name ## _func)                             \                           dlsym(avs->avs_library.library, #name);          \        if (!continue_on_fail && !avs->avs_library.name)                    \            goto fail;     LOAD_AVS_FUNC(avs_bit_blt, 0);    LOAD_AVS_FUNC(avs_clip_get_error, 0);    LOAD_AVS_FUNC(avs_check_version, 0);    LOAD_AVS_FUNC(avs_create_script_environment, 0);    LOAD_AVS_FUNC(avs_delete_script_environment, 0);    LOAD_AVS_FUNC(avs_get_audio, 0);    LOAD_AVS_FUNC(avs_get_channel_mask, 1);    LOAD_AVS_FUNC(avs_get_error, 1); // New to AviSynth 2.6    LOAD_AVS_FUNC(avs_get_frame, 0);    LOAD_AVS_FUNC(avs_get_version, 0);    LOAD_AVS_FUNC(avs_get_video_info, 0);    LOAD_AVS_FUNC(avs_invoke, 0);    LOAD_AVS_FUNC(avs_is_color_space, 1);    LOAD_AVS_FUNC(avs_release_clip, 0);    LOAD_AVS_FUNC(avs_release_value, 0);    LOAD_AVS_FUNC(avs_release_video_frame, 0);    LOAD_AVS_FUNC(avs_take_clip, 0);    LOAD_AVS_FUNC(avs_bits_per_pixel, 1);    LOAD_AVS_FUNC(avs_get_height_p, 1);    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);    LOAD_AVS_FUNC(avs_get_frame_props_ro, 1);    LOAD_AVS_FUNC(avs_prop_get_int, 1);    LOAD_AVS_FUNC(avs_prop_get_type, 1);    LOAD_AVS_FUNC(avs_get_env_property, 1);#undef LOAD_AVS_FUNC     return 0; fail:    dlclose(avs->avs_library.library);    return AVERROR_UNKNOWN;} /* Note that avisynth_context_create and avisynth_context_destroy * do not allocate or free the actual context! That is taken care of * by libavformat. */static av_cold int avisynth_context_create(AVFormatContext *s){    AviSynthContext *avs = s->priv_data;    int ret;     if (!avs->avs_library.library)        if (ret = avisynth_load_library(avs))            return ret;     avs->env = avs->avs_library.avs_create_script_environment(3);    if (avs->avs_library.avs_get_error) {        const char *error = avs->avs_library.avs_get_error(avs->env);        if (error) {            av_log(s, AV_LOG_ERROR, "%s\n", error);            return AVERROR_UNKNOWN;        }    }     return 0;} static av_cold void avisynth_context_destroy(AviSynthContext *avs){    if (avs->clip) {        avs->avs_library.avs_release_clip(avs->clip);        avs->clip = NULL;    }    if (avs->env) {        avs->avs_library.avs_delete_script_environment(avs->env);        avs->env = NULL;    }} /* Create AVStream from audio and video data. */static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st){    AviSynthContext *avs = s->priv_data;    const AVS_Map *avsmap;    AVS_VideoFrame *frame;    int error;    int planar = 0; // 0: packed, 1: YUV, 2: Y8, 3: Planar RGB, 4: YUVA, 5: Planar RGBA    int sar_num = 1;    int sar_den = 1;     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 };    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 };     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->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) {    /* 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_YUVA422P12:        st->codecpar->format = AV_PIX_FMT_YUVA422P12;        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;    /* Single precision floating point Planar RGB (AviSynth+) */    case AVS_CS_RGBPS:        st->codecpar->format = AV_PIX_FMT_GBRPF32;        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;    /* Single precision floating point Planar RGB with Alpha (AviSynth+) */    case AVS_CS_RGBAPS:        st->codecpar->format = AV_PIX_FMT_GBRAPF32;        planar               = 5;        break;    /* 10~16-bit gray pix_fmts (AviSynth+) */    case AVS_CS_Y10:        st->codecpar->format = AV_PIX_FMT_GRAY10;        planar               = 2;        break;    case AVS_CS_Y12:        st->codecpar->format = AV_PIX_FMT_GRAY12;        planar               = 2;        break;    case AVS_CS_Y14:        st->codecpar->format = AV_PIX_FMT_GRAY14;        planar               = 2;        break;    case AVS_CS_Y16:        st->codecpar->format = AV_PIX_FMT_GRAY16;        planar               = 2;        break;    /* Single precision floating point gray (AviSynth+) */    case AVS_CS_Y32:        st->codecpar->format = AV_PIX_FMT_GRAYF32;        planar               = 2;        break;    /* pix_fmts added in AviSynth 2.6 */    case AVS_CS_YV24:        st->codecpar->format = AV_PIX_FMT_YUV444P;        planar               = 1;        break;    case AVS_CS_YV16:        st->codecpar->format = AV_PIX_FMT_YUV422P;        planar               = 1;        break;    case AVS_CS_YV411:        st->codecpar->format = AV_PIX_FMT_YUV411P;        planar               = 1;        break;    case AVS_CS_Y8:        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;    /* AviSynth 2.5 pix_fmts */    case AVS_CS_BGR24:        st->codecpar->format = AV_PIX_FMT_BGR24;        break;    case AVS_CS_BGR32:        st->codecpar->format = AV_PIX_FMT_RGB32;        break;    case AVS_CS_YUY2:        st->codecpar->format = AV_PIX_FMT_YUYV422;        break;    case AVS_CS_YV12:        st->codecpar->format = AV_PIX_FMT_YUV420P;        planar               = 1;        break;    case AVS_CS_I420: // Is this even used anywhere?        st->codecpar->format = AV_PIX_FMT_YUV420P;        planar               = 1;        break;    default:        av_log(s, AV_LOG_ERROR,               "unknown AviSynth colorspace %d\n", avs->vi->pixel_type);        avs->error = 1;        return AVERROR_UNKNOWN;    }     switch (planar) {    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;    case 2: // Y8        avs->n_planes = 1;        avs->planes   = avs_planes_grey;        break;    case 1: // YUV        avs->n_planes = 3;        avs->planes   = avs_planes_yuv;        break;    default:        avs->n_planes = 1;        avs->planes   = avs_planes_packed;    }     /* Read AviSynth+'s frame properties to set additional info.     *     * Due to a bug preventing the C interface from accessing frame     * properties in earlier versions of interface version 8, and     * previous attempts at being clever resulting in pre-8 versions     * of AviSynth+ segfaulting, only enable this if we detect     * version 9 at the minimum.  Technically, 8.1 works, but the time     * distance between 8.1 and 9 is very small, so just restrict it to 9. */     if (avs->avs_library.avs_get_version(avs->clip) >= 9) {         frame  = avs->avs_library.avs_get_frame(avs->clip, 0);        avsmap = avs->avs_library.avs_get_frame_props_ro(avs->env, frame);         /* Field order */        if(avs->flags & AVISYNTH_FRAMEPROP_FIELD_ORDER) {            if(avs->avs_library.avs_prop_get_type(avs->env, avsmap, "_FieldBased") == AVS_PROPTYPE_UNSET) {                st->codecpar->field_order = AV_FIELD_UNKNOWN;            } else {                switch (avs->avs_library.avs_prop_get_int(avs->env, avsmap, "_FieldBased", 0, &error)) {                case 0:                    st->codecpar->field_order = AV_FIELD_PROGRESSIVE;                    break;                case 1:

Lines 1–500 of 1160.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t