Advertisement
Guest User

Untitled

a guest
May 15th, 2019
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 21.28 KB | None | 0 0
  1. --- a/libavformat/vapoursynth.c
  2. +++ b/libavformat/vapoursynth.c
  3. @@ -23,243 +23,157 @@
  4.  * Synthesizes vapour (?)
  5.  */
  6.  
  7. -#include <limits.h>
  8. +#include <stdatomic.h>
  9.  
  10.  #include <VapourSynth.h>
  11.  #include <VSScript.h>
  12. +#include <VSHelper.h>
  13.  
  14. -#include "libavutil/avassert.h"
  15. -#include "libavutil/avstring.h"
  16. -#include "libavutil/eval.h"
  17. -#include "libavutil/imgutils.h"
  18. +#include "libavcodec/internal.h"
  19. +#include "libavutil/internal.h"
  20.  #include "libavutil/opt.h"
  21.  #include "libavutil/pixdesc.h"
  22. +#include "libavutil/time.h"
  23.  #include "avformat.h"
  24.  #include "internal.h"
  25.  
  26. -struct VSState {
  27. -    VSScript *vss;
  28. -};
  29. -
  30.  typedef struct VSContext {
  31.      const AVClass *class;
  32. -
  33. -    AVBufferRef *vss_state;
  34. -
  35.      const VSAPI *vsapi;
  36. -    VSCore *vscore;
  37. -
  38.      VSNodeRef *outnode;
  39. +    VSScript *script;
  40. +    int ncpu;
  41.      int is_cfr;
  42.      int current_frame;
  43. -
  44. -    int c_order[4];
  45. -
  46. -    /* options */
  47. -    int64_t max_script_size;
  48. +    int async_pending;
  49.  } VSContext;
  50.  
  51. -#define OFFSET(x) offsetof(VSContext, x)
  52. -#define A AV_OPT_FLAG_AUDIO_PARAM
  53. -#define D AV_OPT_FLAG_DECODING_PARAM
  54.  static const AVOption options[] = {
  55. -    {"max_script_size",    "set max file size supported (in bytes)", OFFSET(max_script_size),    AV_OPT_TYPE_INT64, {.i64 = 1 * 1024 * 1024}, 0,    SIZE_MAX - 1, A|D},
  56.      {NULL}
  57.  };
  58.  
  59. -static void free_vss_state(void *opaque, uint8_t *data)
  60. +static void async_callback(void *user_data, const VSFrameRef *f, int n, VSNodeRef *outnode, const char *error_msg)
  61.  {
  62. -    struct VSState *vss = opaque;
  63. +    AVFormatContext *s = user_data;
  64. +    VSContext *vs = s->priv_data;
  65.  
  66. -    if (vss->vss) {
  67. -        vsscript_freeScript(vss->vss);
  68. -        vsscript_finalize();
  69. -    }
  70. +    if (!f)
  71. +        av_log(s, AV_LOG_WARNING, "Async frame request failed: %s\n", error_msg);
  72. +
  73. +    vs->vsapi->freeFrame(f);
  74. +    atomic_fetch_sub(&vs->async_pending, 1);
  75.  }
  76.  
  77.  static av_cold int read_close_vs(AVFormatContext *s)
  78.  {
  79.      VSContext *vs = s->priv_data;
  80.  
  81. -    if (vs->outnode)
  82. -        vs->vsapi->freeNode(vs->outnode);
  83. -
  84. -    av_buffer_unref(&vs->vss_state);
  85. -
  86. -    vs->vsapi = NULL;
  87. -    vs->vscore = NULL;
  88. -    vs->outnode = NULL;
  89. -
  90. +    /* Wait for any async requests to complete. */
  91. +    while (atomic_load(&vs->async_pending))
  92. +        av_usleep(1000);
  93. +
  94. +    vs->vsapi->freeNode(vs->outnode);
  95. +    vsscript_freeScript(vs->script);
  96. +    vsscript_finalize();
  97.      return 0;
  98.  }
  99.  
  100. -static av_cold int is_native_endian(enum AVPixelFormat pixfmt)
  101. +static av_cold int map_vsformat(AVFormatContext *s, AVStream *st, const VSFormat *vsformat)
  102.  {
  103. -    enum AVPixelFormat other = av_pix_fmt_swap_endianness(pixfmt);
  104. -    const AVPixFmtDescriptor *pd;
  105. -    if (other == AV_PIX_FMT_NONE || other == pixfmt)
  106. -        return 1; // not affected by byte order
  107. -    pd = av_pix_fmt_desc_get(pixfmt);
  108. -    return pd && (!!HAVE_BIGENDIAN == !!(pd->flags & AV_PIX_FMT_FLAG_BE));
  109. -}
  110. +    if (vsformat->subSamplingW > 2 || vsformat->subSamplingH > 2)
  111. +        return AV_PIX_FMT_NONE;
  112.  
  113. -static av_cold enum AVPixelFormat match_pixfmt(const VSFormat *vsf, int c_order[4])
  114. -{
  115. -    static const int yuv_order[4] = {0, 1, 2, 0};
  116. -    static const int rgb_order[4] = {1, 2, 0, 0};
  117. -    const AVPixFmtDescriptor *pd;
  118. -
  119. -    for (pd = av_pix_fmt_desc_next(NULL); pd; pd = av_pix_fmt_desc_next(pd)) {
  120. -        int is_rgb, is_yuv, i;
  121. -        const int *order;
  122. -        enum AVPixelFormat pixfmt;
  123. -
  124. -        pixfmt = av_pix_fmt_desc_get_id(pd);
  125. -
  126. -        if (pd->flags & (AV_PIX_FMT_FLAG_BAYER | AV_PIX_FMT_FLAG_ALPHA |
  127. -                         AV_PIX_FMT_FLAG_HWACCEL | AV_PIX_FMT_FLAG_BITSTREAM))
  128. -            continue;
  129. -
  130. -        if (pd->log2_chroma_w != vsf->subSamplingW ||
  131. -            pd->log2_chroma_h != vsf->subSamplingH)
  132. -            continue;
  133. -
  134. -        is_rgb = vsf->colorFamily == cmRGB;
  135. -        if (is_rgb != !!(pd->flags & AV_PIX_FMT_FLAG_RGB))
  136. -            continue;
  137. -
  138. -        is_yuv = vsf->colorFamily == cmYUV ||
  139. -                 vsf->colorFamily == cmYCoCg ||
  140. -                 vsf->colorFamily == cmGray;
  141. -        if (!is_rgb && !is_yuv)
  142. -            continue;
  143. -
  144. -        if (vsf->sampleType != ((pd->flags & AV_PIX_FMT_FLAG_FLOAT) ? stFloat : stInteger))
  145. -            continue;
  146. -
  147. -        if (av_pix_fmt_count_planes(pixfmt) != vsf->numPlanes)
  148. -            continue;
  149. -
  150. -        if (strncmp(pd->name, "xyz", 3) == 0)
  151. -            continue;
  152. -
  153. -        if (!is_native_endian(pixfmt))
  154. -            continue;
  155. -
  156. -        order = is_yuv ? yuv_order : rgb_order;
  157. -
  158. -        for (i = 0; i < pd->nb_components; i++) {
  159. -            const AVComponentDescriptor *c = &pd->comp[i];
  160. -            if (order[c->plane] != i ||
  161. -                c->offset != 0 || c->shift != 0 ||
  162. -                c->step != vsf->bytesPerSample ||
  163. -                c->depth != vsf->bitsPerSample)
  164. -                goto cont;
  165. +    switch (vsformat->colorFamily) {
  166. +    case cmYUV:
  167. +    case cmYCoCg:
  168. +        switch ((vsformat->subSamplingW << 2) | vsformat->subSamplingH) {
  169. +        case ((1 << 2) | 1): /* 4:2:0 */
  170. +            switch (vsformat->bitsPerSample) {
  171. +            case 8: return AV_PIX_FMT_YUV420P;
  172. +            case 9: return AV_PIX_FMT_YUV420P9;
  173. +            case 10: return AV_PIX_FMT_YUV420P10;
  174. +            case 12: return AV_PIX_FMT_YUV420P12;
  175. +            case 14: return AV_PIX_FMT_YUV420P14;
  176. +            case 16: return AV_PIX_FMT_YUV420P16;
  177. +            default: return AV_PIX_FMT_NONE;
  178. +            }
  179. +        case ((0 << 2) | 0): /* 4:4:4 */
  180. +            switch (vsformat->bitsPerSample) {
  181. +            case 8: return AV_PIX_FMT_YUV444P;
  182. +            case 9: return AV_PIX_FMT_YUV444P9;
  183. +            case 10: return AV_PIX_FMT_YUV444P10;
  184. +            case 12: return AV_PIX_FMT_YUV444P12;
  185. +            case 14: return AV_PIX_FMT_YUV444P14;
  186. +            case 16: return AV_PIX_FMT_YUV444P16;
  187. +            default: return AV_PIX_FMT_NONE;
  188. +            }
  189. +        case ((1 << 2) | 0): /* 4:2:2 */
  190. +            switch (vsformat->bitsPerSample) {
  191. +            case 8: return AV_PIX_FMT_YUV422P;
  192. +            case 9: return AV_PIX_FMT_YUV422P9;
  193. +            case 10: return AV_PIX_FMT_YUV422P10;
  194. +            case 12: return AV_PIX_FMT_YUV422P12;
  195. +            case 14: return AV_PIX_FMT_YUV422P14;
  196. +            case 16: return AV_PIX_FMT_YUV422P16;
  197. +            default: return AV_PIX_FMT_NONE;
  198. +            }
  199. +        case ((0 << 2) | 1): /* 4:4:0 */
  200. +            switch (vsformat->bitsPerSample) {
  201. +            case 8: return AV_PIX_FMT_YUV440P;
  202. +            case 10: return AV_PIX_FMT_YUV440P10;
  203. +            case 12: return AV_PIX_FMT_YUV440P12;
  204. +            default: return AV_PIX_FMT_NONE;
  205. +            }
  206. +        case ((2 << 2) | 0): /* 4:1:1 */
  207. +            return vsformat->bitsPerSample == 8 ? AV_PIX_FMT_YUV411P : AV_PIX_FMT_NONE;
  208. +        case ((2 << 2) | 2): /* 4:1:0 */
  209. +            return vsformat->bitsPerSample == 8 ? AV_PIX_FMT_YUV410P : AV_PIX_FMT_NONE;
  210.          }
  211. -
  212. -        // Use it.
  213. -        memcpy(c_order, order, sizeof(int[4]));
  214. -        return pixfmt;
  215. -
  216. -    cont: ;
  217. +    case cmRGB:
  218. +        switch (vsformat->bitsPerSample) {
  219. +        case 8: return AV_PIX_FMT_GBRP;
  220. +        case 9: return AV_PIX_FMT_GBRP9;
  221. +        case 10: return AV_PIX_FMT_GBRP10;
  222. +        case 12: return AV_PIX_FMT_GBRP12;
  223. +        case 14: return AV_PIX_FMT_GBRP14;
  224. +        case 16: return AV_PIX_FMT_GBRP16;
  225. +        case 32: return AV_PIX_FMT_GBRPF32;
  226. +        default: return AV_PIX_FMT_NONE;
  227. +        }
  228. +    case cmGray:
  229. +        switch (vsformat->bitsPerSample) {
  230. +        case 8: return AV_PIX_FMT_GRAY8;
  231. +        case 9: return AV_PIX_FMT_GRAY9;
  232. +        case 10: return AV_PIX_FMT_GRAY10;
  233. +        case 12: return AV_PIX_FMT_GRAY12;
  234. +        case 14: return AV_PIX_FMT_GRAY14;
  235. +        case 16: return AV_PIX_FMT_GRAY16;
  236. +        case 32: return AV_PIX_FMT_GRAYF32;
  237. +        default: return AV_PIX_FMT_NONE;
  238. +        }
  239. +    case cmCompat:
  240. +        switch (vsformat->id) {
  241. +        case pfCompatBGR32: return AV_PIX_FMT_RGB32;
  242. +        case pfCompatYUY2: return AV_PIX_FMT_YUYV422;
  243. +        default: return AV_PIX_FMT_NONE;
  244. +        }
  245. +    default:
  246. +        return AV_PIX_FMT_NONE;
  247.      }
  248. -
  249. -    return AV_PIX_FMT_NONE;
  250.  }
  251.  
  252. -static av_cold int read_header_vs(AVFormatContext *s)
  253. +static av_cold int create_video_stream(AVFormatContext *s)
  254.  {
  255.      AVStream *st;
  256. -    AVIOContext *pb = s->pb;
  257.      VSContext *vs = s->priv_data;
  258. -    int64_t sz = avio_size(pb);
  259. -    char *buf = NULL;
  260. -    char dummy;
  261.      const VSVideoInfo *info;
  262. -    struct VSState *vss_state;
  263.      int err = 0;
  264.  
  265. -    vss_state = av_mallocz(sizeof(*vss_state));
  266. -    if (!vss_state) {
  267. -        err = AVERROR(ENOMEM);
  268. -        goto done;
  269. -    }
  270. -
  271. -    vs->vss_state = av_buffer_create(NULL, 0, free_vss_state, vss_state, 0);
  272. -    if (!vs->vss_state) {
  273. -        err = AVERROR(ENOMEM);
  274. -        av_free(vss_state);
  275. -        goto done;
  276. -    }
  277. -
  278. -    if (!vsscript_init()) {
  279. -        av_log(s, AV_LOG_ERROR, "Failed to initialize VSScript (possibly PYTHONPATH not set).\n");
  280. -        err = AVERROR_EXTERNAL;
  281. -        goto done;
  282. -    }
  283. -
  284. -    if (vsscript_createScript(&vss_state->vss)) {
  285. -        av_log(s, AV_LOG_ERROR, "Failed to create script instance.\n");
  286. -        err = AVERROR_EXTERNAL;
  287. -        vsscript_finalize();
  288. -        goto done;
  289. -    }
  290. -
  291. -    if (sz < 0 || sz > vs->max_script_size) {
  292. -        if (sz < 0)
  293. -            av_log(s, AV_LOG_WARNING, "Could not determine file size\n");
  294. -        sz = vs->max_script_size;
  295. -    }
  296. -
  297. -    buf = av_malloc(sz + 1);
  298. -    if (!buf) {
  299. -        err = AVERROR(ENOMEM);
  300. -        goto done;
  301. -    }
  302. -    sz = avio_read(pb, buf, sz);
  303. -
  304. -    if (sz < 0) {
  305. -        av_log(s, AV_LOG_ERROR, "Could not read script.\n");
  306. -        err = sz;
  307. -        goto done;
  308. -    }
  309. -
  310. -    // Data left means our buffer (the max_script_size option) is too small
  311. -    if (avio_read(pb, &dummy, 1) == 1) {
  312. -        av_log(s, AV_LOG_ERROR, "File size is larger than max_script_size option "
  313. -               "value %"PRIi64", consider increasing the max_script_size option\n",
  314. -               vs->max_script_size);
  315. -        err = AVERROR_BUFFER_TOO_SMALL;
  316. -        goto done;
  317. -    }
  318. -
  319. -    buf[sz] = '\0';
  320. -    if (vsscript_evaluateScript(&vss_state->vss, buf, s->url, 0)) {
  321. -        const char *msg = vsscript_getError(vss_state->vss);
  322. -        av_log(s, AV_LOG_ERROR, "Failed to parse script: %s\n", msg ? msg : "(unknown)");
  323. -        err = AVERROR_EXTERNAL;
  324. -        goto done;
  325. -    }
  326. -
  327. -    vs->vsapi = vsscript_getVSApi();
  328. -    vs->vscore = vsscript_getCore(vss_state->vss);
  329. -
  330. -    vs->outnode = vsscript_getOutput(vss_state->vss, 0);
  331. -    if (!vs->outnode) {
  332. -        av_log(s, AV_LOG_ERROR, "Could not get script output node.\n");
  333. -        err = AVERROR_EXTERNAL;
  334. -        goto done;
  335. -    }
  336. -
  337. -    st = avformat_new_stream(s, NULL);
  338. -    if (!st) {
  339. -        err = AVERROR(ENOMEM);
  340. -        goto done;
  341. -    }
  342. -
  343.      info = vs->vsapi->getVideoInfo(vs->outnode);
  344. +    if (!(st = avformat_new_stream(s, NULL)))
  345. +        return AVERROR_UNKNOWN;
  346.  
  347. -    if (!info->format || !info->width || !info->height) {
  348. +    if (!isConstantFormat(info)) {
  349.          av_log(s, AV_LOG_ERROR, "Non-constant input format not supported.\n");
  350.          err = AVERROR_PATCHWELCOME;
  351.          goto done;
  352. @@ -267,8 +181,11 @@ static av_cold int read_header_vs(AVForm
  353.  
  354.      if (info->fpsDen) {
  355.          vs->is_cfr = 1;
  356. +        st->avg_frame_rate   = (AVRational) { info->fpsNum, info->fpsDen };
  357. +        st->duration         = info->numFrames;
  358. +        st->nb_frames        = info->numFrames;
  359. +        st->start_time       = 0;
  360.          avpriv_set_pts_info(st, 64, info->fpsDen, info->fpsNum);
  361. -        st->duration = info->numFrames;
  362.      } else {
  363.          // VFR. Just set "something".
  364.          avpriv_set_pts_info(st, 64, 1, AV_TIME_BASE);
  365. @@ -276,10 +193,10 @@ static av_cold int read_header_vs(AVForm
  366.      }
  367.  
  368.      st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
  369. -    st->codecpar->codec_id = AV_CODEC_ID_WRAPPED_AVFRAME;
  370. -    st->codecpar->width = info->width;
  371. -    st->codecpar->height = info->height;
  372. -    st->codecpar->format = match_pixfmt(info->format, vs->c_order);
  373. +    st->codecpar->codec_id   = AV_CODEC_ID_RAWVIDEO;
  374. +    st->codecpar->width      = info->width;
  375. +    st->codecpar->height     = info->height;
  376. +    st->codecpar->format     = map_vsformat(s, st, info->format);
  377.  
  378.      if (st->codecpar->format == AV_PIX_FMT_NONE) {
  379.          av_log(s, AV_LOG_ERROR, "Unsupported VS pixel format %s\n", info->format->name);
  380. @@ -292,78 +209,87 @@ static av_cold int read_header_vs(AVForm
  381.      if (info->format->colorFamily == cmYCoCg)
  382.          st->codecpar->color_space = AVCOL_SPC_YCGCO;
  383.  
  384. +    return 0;
  385.  done:
  386. -    av_free(buf);
  387.      if (err < 0)
  388.          read_close_vs(s);
  389.      return err;
  390.  }
  391.  
  392. -static void free_frame(void *opaque, uint8_t *data)
  393. -{
  394. -    AVFrame *frame = (AVFrame *)data;
  395. -
  396. -    av_frame_free(&frame);
  397. -}
  398. -
  399. -static int get_vs_prop_int(AVFormatContext *s, const VSMap *map, const char *name, int def)
  400. +static av_cold int open_script(AVFormatContext *s)
  401.  {
  402.      VSContext *vs = s->priv_data;
  403. -    int64_t res;
  404. -    int err = 1;
  405. -
  406. -    res = vs->vsapi->propGetInt(map, name, 0, &err);
  407. -    return err || res < INT_MIN || res > INT_MAX ? def : res;
  408. -}
  409. +    int err;
  410.  
  411. -struct vsframe_ref_data {
  412. -    const VSAPI *vsapi;
  413. -    const VSFrameRef *frame;
  414. -    AVBufferRef *vss_state;
  415. -};
  416. -
  417. -static void free_vsframe_ref(void *opaque, uint8_t *data)
  418. -{
  419. -    struct vsframe_ref_data *d = opaque;
  420. +    // Locking is required, because vsscript_evaluateScript changes the process directory internally.
  421. +    if (err = ff_lock_avformat())
  422. +        return err;
  423. +
  424. +    if (vsscript_evaluateFile(&vs->script, s->url, efSetWorkingDir)) {
  425. +        ff_unlock_avformat();
  426. +        av_log(s, AV_LOG_ERROR, "VapourSynth script evaluation failed\n");
  427. +        return AVERROR_EXTERNAL;
  428. +    }
  429. +    
  430. +    ff_unlock_avformat();
  431.  
  432. -    if (d->frame)
  433. -        d->vsapi->freeFrame(d->frame);
  434. +    if (!(vs->outnode = vsscript_getOutput(vs->script, 0))) {
  435. +        av_log(s, AV_LOG_ERROR, "Failed to get the script output node\n");
  436. +        err = AVERROR_EXTERNAL;
  437. +        goto end;
  438. +    }
  439.  
  440. -    av_buffer_unref(&d->vss_state);
  441. +    if (err = create_video_stream(s))
  442. +        goto end;
  443.  
  444. -    av_free(d);
  445. +    return 0;
  446. +end:
  447. +    vs->vsapi->freeNode(vs->outnode);
  448. +    vsscript_freeScript(vs->script);
  449. +    return err;
  450.  }
  451.  
  452.  static int read_packet_vs(AVFormatContext *s, AVPacket *pkt)
  453.  {
  454. +    static const int gbr_order[3] = { 1, 2, 0 };
  455. +
  456.      VSContext *vs = s->priv_data;
  457.      AVStream *st = s->streams[0];
  458. -    AVFrame *frame = NULL;
  459. -    char vserr[80];
  460.      const VSFrameRef *vsframe;
  461.      const VSVideoInfo *info = vs->vsapi->getVideoInfo(vs->outnode);
  462. -    const VSMap *props;
  463. -    const AVPixFmtDescriptor *desc;
  464. -    AVBufferRef *vsframe_ref = NULL;
  465. -    struct vsframe_ref_data *ref_data;
  466. -    int err = 0;
  467. +    int err, plane;
  468.      int i;
  469. +    uint8_t *dst_ptr;
  470. +    char vserr[256];
  471.  
  472.      if (vs->current_frame >= info->numFrames)
  473.          return AVERROR_EOF;
  474.  
  475. -    ref_data = av_mallocz(sizeof(*ref_data));
  476. -    if (!ref_data) {
  477. -        err = AVERROR(ENOMEM);
  478. -        goto end;
  479. +    vs->current_frame++;
  480. +    if (st->discard == AVDISCARD_ALL)
  481. +        return 0;
  482. +
  483. +    pkt->size = 0;
  484. +    for (plane = 0; plane < info->format->numPlanes; ++plane) {
  485. +        int width = info->width;
  486. +        int height = info->height;
  487. +
  488. +        if (plane == 1 || plane == 2) {
  489. +            width >>= info->format->subSamplingW;
  490. +            height >>= info->format->subSamplingH;
  491. +        }
  492. +
  493. +        pkt->size += (int64_t)width * height * info->format->bytesPerSample;
  494.      }
  495.  
  496. -    // (the READONLY flag is important because the ref is reused for plane data)
  497. -    vsframe_ref = av_buffer_create(NULL, 0, free_vsframe_ref, ref_data, AV_BUFFER_FLAG_READONLY);
  498. -    if (!vsframe_ref) {
  499. -        err = AVERROR(ENOMEM);
  500. -        av_free(ref_data);
  501. -        goto end;
  502. +    if ((err = av_new_packet(pkt, pkt->size)) < 0)
  503. +        return err;
  504. +
  505. +    if (vs->is_cfr) {
  506. +        pkt->pts = vs->current_frame;
  507. +        pkt->dts = vs->current_frame;
  508. +        pkt->duration = 1;
  509. +        pkt->stream_index = 0;
  510.      }
  511.  
  512.      vsframe = vs->vsapi->getFrame(vs->current_frame, vs->outnode, vserr, sizeof(vserr));
  513. @@ -373,88 +299,69 @@ static int read_packet_vs(AVFormatContex
  514.          goto end;
  515.      }
  516.  
  517. -    ref_data->vsapi = vs->vsapi;
  518. -    ref_data->frame = vsframe;
  519. +    /* Prefetch the subsequent frames. */
  520. +    for (i = 0; i < vs->ncpu; ++i) {
  521. +        if (i >= (info->numFrames - vs->current_frame))
  522. +            break;
  523. +        vs->vsapi->getFrameAsync(vs->current_frame + i, vs->outnode, async_callback, s);
  524. +        atomic_fetch_add(&vs->async_pending, 1);
  525. +    }
  526. +
  527. +    dst_ptr = pkt->data;
  528. +    for (plane = 0; plane < info->format->numPlanes; ++plane) {
  529. +        int src_plane = info->format->colorFamily == cmRGB ? gbr_order[plane] : plane;
  530. +        const uint8_t *src_ptr = vs->vsapi->getReadPtr(vsframe, src_plane);
  531. +        int width = vs->vsapi->getFrameWidth(vsframe, src_plane);
  532. +        int height = vs->vsapi->getFrameHeight(vsframe, src_plane);
  533. +        int stride = vs->vsapi->getStride(vsframe, src_plane);
  534. +        int row_size = width * info->format->bytesPerSample;
  535. +
  536. +        if (info->format->id == pfCompatBGR32) {
  537. +            src_ptr += (int64_t)(height - 1) * stride;
  538. +            stride = -stride;
  539. +        }
  540.  
  541. -    ref_data->vss_state = av_buffer_ref(vs->vss_state);
  542. -    if (!ref_data->vss_state) {
  543. -        err = AVERROR(ENOMEM);
  544. -        goto end;
  545. +        vs_bitblt(dst_ptr, row_size, src_ptr, stride, row_size, height);
  546. +        dst_ptr += (int64_t)row_size * height;
  547.      }
  548.  
  549. -    props = vs->vsapi->getFramePropsRO(vsframe);
  550. -
  551. -    frame = av_frame_alloc();
  552. -    if (!frame) {
  553. -        err = AVERROR(ENOMEM);
  554. -        goto end;
  555. -    }
  556. +    vs->vsapi->freeFrame(vsframe);
  557. +    return 0;
  558. +end:
  559. +    vs->vsapi->freeFrame(vsframe);
  560. +    av_packet_unref(pkt);
  561. +    return err;
  562. +}
  563.  
  564. -    frame->format       = st->codecpar->format;
  565. -    frame->width        = st->codecpar->width;
  566. -    frame->height       = st->codecpar->height;
  567. -    frame->colorspace   = st->codecpar->color_space;
  568. -
  569. -    // Values according to ISO/IEC 14496-10.
  570. -    frame->colorspace       = get_vs_prop_int(s, props, "_Matrix",      frame->colorspace);
  571. -    frame->color_primaries  = get_vs_prop_int(s, props, "_Primaries",   frame->color_primaries);
  572. -    frame->color_trc        = get_vs_prop_int(s, props, "_Transfer",    frame->color_trc);
  573. -
  574. -    if (get_vs_prop_int(s, props, "_ColorRange", 1) == 0)
  575. -        frame->color_range = AVCOL_RANGE_JPEG;
  576. -
  577. -    frame->sample_aspect_ratio.num = get_vs_prop_int(s, props, "_SARNum", 0);
  578. -    frame->sample_aspect_ratio.den = get_vs_prop_int(s, props, "_SARDen", 1);
  579. -
  580. -    av_assert0(vs->vsapi->getFrameWidth(vsframe, 0) == frame->width);
  581. -    av_assert0(vs->vsapi->getFrameHeight(vsframe, 0) == frame->height);
  582. -
  583. -    desc = av_pix_fmt_desc_get(frame->format);
  584. -
  585. -    for (i = 0; i < info->format->numPlanes; i++) {
  586. -        int p = vs->c_order[i];
  587. -        ptrdiff_t plane_h = frame->height;
  588. -
  589. -        frame->data[i] = (void *)vs->vsapi->getReadPtr(vsframe, p);
  590. -        frame->linesize[i] = vs->vsapi->getStride(vsframe, p);
  591. -
  592. -        frame->buf[i] = av_buffer_ref(vsframe_ref);
  593. -        if (!frame->buf[i]) {
  594. -            err = AVERROR(ENOMEM);
  595. -            goto end;
  596. -        }
  597. +static av_cold int read_header_vs(AVFormatContext *s)
  598. +{
  599. +    VSContext *vs = s->priv_data;
  600. +    int err;
  601.  
  602. -        // Each plane needs an AVBufferRef that indicates the correct plane
  603. -        // memory range. VapourSynth doesn't even give us the memory range,
  604. -        // so make up a bad guess to make FFmpeg happy (even if almost nothing
  605. -        // checks the memory range).
  606. -        if (i == 1 || i == 2)
  607. -            plane_h = AV_CEIL_RSHIFT(plane_h, desc->log2_chroma_h);
  608. -        frame->buf[i]->data = frame->data[i];
  609. -        frame->buf[i]->size = frame->linesize[i] * plane_h;
  610. +    if (!vsscript_init()) {
  611. +        av_log(s, AV_LOG_ERROR, "Failed to initialize VapourSynth environment\n");
  612. +        return AVERROR_EXTERNAL;
  613.      }
  614.  
  615. -    pkt->buf = av_buffer_create((uint8_t*)frame, sizeof(*frame),
  616. -                                free_frame, NULL, 0);
  617. -    if (!pkt->buf) {
  618. -        err = AVERROR(ENOMEM);
  619. +    if ((err = vsscript_getApiVersion()) < VSSCRIPT_API_VERSION) {
  620. +        av_log(s, AV_LOG_ERROR, "VSScript API too old: %d versus %d\n", err, VSSCRIPT_API_VERSION);
  621. +        err = AVERROR_EXTERNAL;
  622.          goto end;
  623.      }
  624.  
  625. -    frame = NULL; // pkt owns it now
  626. -
  627. -    pkt->data   = pkt->buf->data;
  628. -    pkt->size   = pkt->buf->size;
  629. -    pkt->flags |= AV_PKT_FLAG_TRUSTED;
  630. -
  631. -    if (vs->is_cfr)
  632. -        pkt->pts = vs->current_frame;
  633. +    if (!(vs->vsapi = vsscript_getVSApi2(VAPOURSYNTH_API_VERSION))) {
  634. +        av_log(s, AV_LOG_ERROR, "VapourSynth API too old: %d required\n", VAPOURSYNTH_API_VERSION);
  635. +        err = AVERROR_EXTERNAL;
  636. +        goto end;
  637. +    }
  638.  
  639. -    vs->current_frame++;
  640. +    if (err = open_script(s))
  641. +        goto end;
  642.  
  643. +    vs->ncpu = av_cpu_count();
  644. +    return 0;
  645.  end:
  646. -    av_frame_free(&frame);
  647. -    av_buffer_unref(&vsframe_ref);
  648. +    vsscript_finalize();
  649.      return err;
  650.  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement