]> git.sesse.net Git - ffmpeg/blob - libavformat/vapoursynth.c
avfilter/vf_identity: remove unnecessary check
[ffmpeg] / libavformat / vapoursynth.c
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 /**
20 * @file
21 * VapourSynth demuxer
22 *
23 * Synthesizes vapour (?)
24 */
25
26 #include <limits.h>
27
28 #include <VapourSynth.h>
29 #include <VSScript.h>
30
31 #include "libavutil/avassert.h"
32 #include "libavutil/avstring.h"
33 #include "libavutil/eval.h"
34 #include "libavutil/imgutils.h"
35 #include "libavutil/opt.h"
36 #include "libavutil/pixdesc.h"
37 #include "avformat.h"
38 #include "internal.h"
39
40 struct VSState {
41     VSScript *vss;
42 };
43
44 typedef struct VSContext {
45     const AVClass *class;
46
47     AVBufferRef *vss_state;
48
49     const VSAPI *vsapi;
50     VSCore *vscore;
51
52     VSNodeRef *outnode;
53     int is_cfr;
54     int current_frame;
55
56     int c_order[4];
57
58     /* options */
59     int64_t max_script_size;
60 } VSContext;
61
62 #define OFFSET(x) offsetof(VSContext, x)
63 #define A AV_OPT_FLAG_AUDIO_PARAM
64 #define D AV_OPT_FLAG_DECODING_PARAM
65 static const AVOption options[] = {
66     {"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},
67     {NULL}
68 };
69
70 static void free_vss_state(void *opaque, uint8_t *data)
71 {
72     struct VSState *vss = opaque;
73
74     if (vss->vss) {
75         vsscript_freeScript(vss->vss);
76         vsscript_finalize();
77     }
78 }
79
80 static av_cold int read_close_vs(AVFormatContext *s)
81 {
82     VSContext *vs = s->priv_data;
83
84     if (vs->outnode)
85         vs->vsapi->freeNode(vs->outnode);
86
87     av_buffer_unref(&vs->vss_state);
88
89     vs->vsapi = NULL;
90     vs->vscore = NULL;
91     vs->outnode = NULL;
92
93     return 0;
94 }
95
96 static av_cold int is_native_endian(enum AVPixelFormat pixfmt)
97 {
98     enum AVPixelFormat other = av_pix_fmt_swap_endianness(pixfmt);
99     const AVPixFmtDescriptor *pd;
100     if (other == AV_PIX_FMT_NONE || other == pixfmt)
101         return 1; // not affected by byte order
102     pd = av_pix_fmt_desc_get(pixfmt);
103     return pd && (!!HAVE_BIGENDIAN == !!(pd->flags & AV_PIX_FMT_FLAG_BE));
104 }
105
106 static av_cold enum AVPixelFormat match_pixfmt(const VSFormat *vsf, int c_order[4])
107 {
108     static const int yuv_order[4] = {0, 1, 2, 0};
109     static const int rgb_order[4] = {1, 2, 0, 0};
110     const AVPixFmtDescriptor *pd;
111
112     for (pd = av_pix_fmt_desc_next(NULL); pd; pd = av_pix_fmt_desc_next(pd)) {
113         int is_rgb, is_yuv, i;
114         const int *order;
115         enum AVPixelFormat pixfmt;
116
117         pixfmt = av_pix_fmt_desc_get_id(pd);
118
119         if (pd->flags & (AV_PIX_FMT_FLAG_BAYER | AV_PIX_FMT_FLAG_ALPHA |
120                          AV_PIX_FMT_FLAG_HWACCEL | AV_PIX_FMT_FLAG_BITSTREAM))
121             continue;
122
123         if (pd->log2_chroma_w != vsf->subSamplingW ||
124             pd->log2_chroma_h != vsf->subSamplingH)
125             continue;
126
127         is_rgb = vsf->colorFamily == cmRGB;
128         if (is_rgb != !!(pd->flags & AV_PIX_FMT_FLAG_RGB))
129             continue;
130
131         is_yuv = vsf->colorFamily == cmYUV ||
132                  vsf->colorFamily == cmYCoCg ||
133                  vsf->colorFamily == cmGray;
134         if (!is_rgb && !is_yuv)
135             continue;
136
137         if (vsf->sampleType != ((pd->flags & AV_PIX_FMT_FLAG_FLOAT) ? stFloat : stInteger))
138             continue;
139
140         if (av_pix_fmt_count_planes(pixfmt) != vsf->numPlanes)
141             continue;
142
143         if (strncmp(pd->name, "xyz", 3) == 0)
144             continue;
145
146         if (!is_native_endian(pixfmt))
147             continue;
148
149         order = is_yuv ? yuv_order : rgb_order;
150
151         for (i = 0; i < pd->nb_components; i++) {
152             const AVComponentDescriptor *c = &pd->comp[i];
153             if (order[c->plane] != i ||
154                 c->offset != 0 || c->shift != 0 ||
155                 c->step != vsf->bytesPerSample ||
156                 c->depth != vsf->bitsPerSample)
157                 goto cont;
158         }
159
160         // Use it.
161         memcpy(c_order, order, sizeof(int[4]));
162         return pixfmt;
163
164     cont: ;
165     }
166
167     return AV_PIX_FMT_NONE;
168 }
169
170 static av_cold int read_header_vs(AVFormatContext *s)
171 {
172     AVStream *st;
173     AVIOContext *pb = s->pb;
174     VSContext *vs = s->priv_data;
175     int64_t sz = avio_size(pb);
176     char *buf = NULL;
177     char dummy;
178     const VSVideoInfo *info;
179     struct VSState *vss_state;
180     int err = 0;
181
182     vss_state = av_mallocz(sizeof(*vss_state));
183     if (!vss_state) {
184         err = AVERROR(ENOMEM);
185         goto done;
186     }
187
188     vs->vss_state = av_buffer_create(NULL, 0, free_vss_state, vss_state, 0);
189     if (!vs->vss_state) {
190         err = AVERROR(ENOMEM);
191         av_free(vss_state);
192         goto done;
193     }
194
195     if (!vsscript_init()) {
196         av_log(s, AV_LOG_ERROR, "Failed to initialize VSScript (possibly PYTHONPATH not set).\n");
197         err = AVERROR_EXTERNAL;
198         goto done;
199     }
200
201     if (vsscript_createScript(&vss_state->vss)) {
202         av_log(s, AV_LOG_ERROR, "Failed to create script instance.\n");
203         err = AVERROR_EXTERNAL;
204         vsscript_finalize();
205         goto done;
206     }
207
208     if (sz < 0 || sz > vs->max_script_size) {
209         if (sz < 0)
210             av_log(s, AV_LOG_WARNING, "Could not determine file size\n");
211         sz = vs->max_script_size;
212     }
213
214     buf = av_malloc(sz + 1);
215     if (!buf) {
216         err = AVERROR(ENOMEM);
217         goto done;
218     }
219     sz = avio_read(pb, buf, sz);
220
221     if (sz < 0) {
222         av_log(s, AV_LOG_ERROR, "Could not read script.\n");
223         err = sz;
224         goto done;
225     }
226
227     // Data left means our buffer (the max_script_size option) is too small
228     if (avio_read(pb, &dummy, 1) == 1) {
229         av_log(s, AV_LOG_ERROR, "File size is larger than max_script_size option "
230                "value %"PRIi64", consider increasing the max_script_size option\n",
231                vs->max_script_size);
232         err = AVERROR_BUFFER_TOO_SMALL;
233         goto done;
234     }
235
236     buf[sz] = '\0';
237     if (vsscript_evaluateScript(&vss_state->vss, buf, s->url, 0)) {
238         const char *msg = vsscript_getError(vss_state->vss);
239         av_log(s, AV_LOG_ERROR, "Failed to parse script: %s\n", msg ? msg : "(unknown)");
240         err = AVERROR_EXTERNAL;
241         goto done;
242     }
243
244     vs->vsapi = vsscript_getVSApi();
245     vs->vscore = vsscript_getCore(vss_state->vss);
246
247     vs->outnode = vsscript_getOutput(vss_state->vss, 0);
248     if (!vs->outnode) {
249         av_log(s, AV_LOG_ERROR, "Could not get script output node.\n");
250         err = AVERROR_EXTERNAL;
251         goto done;
252     }
253
254     st = avformat_new_stream(s, NULL);
255     if (!st) {
256         err = AVERROR(ENOMEM);
257         goto done;
258     }
259
260     info = vs->vsapi->getVideoInfo(vs->outnode);
261
262     if (!info->format || !info->width || !info->height) {
263         av_log(s, AV_LOG_ERROR, "Non-constant input format not supported.\n");
264         err = AVERROR_PATCHWELCOME;
265         goto done;
266     }
267
268     if (info->fpsDen) {
269         vs->is_cfr = 1;
270         avpriv_set_pts_info(st, 64, info->fpsDen, info->fpsNum);
271         st->duration = info->numFrames;
272     } else {
273         // VFR. Just set "something".
274         avpriv_set_pts_info(st, 64, 1, AV_TIME_BASE);
275         s->ctx_flags |= AVFMTCTX_UNSEEKABLE;
276     }
277
278     st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
279     st->codecpar->codec_id = AV_CODEC_ID_WRAPPED_AVFRAME;
280     st->codecpar->width = info->width;
281     st->codecpar->height = info->height;
282     st->codecpar->format = match_pixfmt(info->format, vs->c_order);
283
284     if (st->codecpar->format == AV_PIX_FMT_NONE) {
285         av_log(s, AV_LOG_ERROR, "Unsupported VS pixel format %s\n", info->format->name);
286         err = AVERROR_EXTERNAL;
287         goto done;
288     }
289     av_log(s, AV_LOG_VERBOSE, "VS format %s -> pixfmt %s\n", info->format->name,
290            av_get_pix_fmt_name(st->codecpar->format));
291
292     if (info->format->colorFamily == cmYCoCg)
293         st->codecpar->color_space = AVCOL_SPC_YCGCO;
294
295 done:
296     av_free(buf);
297     if (err < 0)
298         read_close_vs(s);
299     return err;
300 }
301
302 static void free_frame(void *opaque, uint8_t *data)
303 {
304     AVFrame *frame = (AVFrame *)data;
305
306     av_frame_free(&frame);
307 }
308
309 static int get_vs_prop_int(AVFormatContext *s, const VSMap *map, const char *name, int def)
310 {
311     VSContext *vs = s->priv_data;
312     int64_t res;
313     int err = 1;
314
315     res = vs->vsapi->propGetInt(map, name, 0, &err);
316     return err || res < INT_MIN || res > INT_MAX ? def : res;
317 }
318
319 struct vsframe_ref_data {
320     const VSAPI *vsapi;
321     const VSFrameRef *frame;
322     AVBufferRef *vss_state;
323 };
324
325 static void free_vsframe_ref(void *opaque, uint8_t *data)
326 {
327     struct vsframe_ref_data *d = opaque;
328
329     if (d->frame)
330         d->vsapi->freeFrame(d->frame);
331
332     av_buffer_unref(&d->vss_state);
333
334     av_free(d);
335 }
336
337 static int read_packet_vs(AVFormatContext *s, AVPacket *pkt)
338 {
339     VSContext *vs = s->priv_data;
340     AVStream *st = s->streams[0];
341     AVFrame *frame = NULL;
342     char vserr[80];
343     const VSFrameRef *vsframe;
344     const VSVideoInfo *info = vs->vsapi->getVideoInfo(vs->outnode);
345     const VSMap *props;
346     const AVPixFmtDescriptor *desc;
347     AVBufferRef *vsframe_ref = NULL;
348     struct vsframe_ref_data *ref_data;
349     int err = 0;
350     int i;
351
352     if (vs->current_frame >= info->numFrames)
353         return AVERROR_EOF;
354
355     ref_data = av_mallocz(sizeof(*ref_data));
356     if (!ref_data) {
357         err = AVERROR(ENOMEM);
358         goto end;
359     }
360
361     // (the READONLY flag is important because the ref is reused for plane data)
362     vsframe_ref = av_buffer_create(NULL, 0, free_vsframe_ref, ref_data, AV_BUFFER_FLAG_READONLY);
363     if (!vsframe_ref) {
364         err = AVERROR(ENOMEM);
365         av_free(ref_data);
366         goto end;
367     }
368
369     vsframe = vs->vsapi->getFrame(vs->current_frame, vs->outnode, vserr, sizeof(vserr));
370     if (!vsframe) {
371         av_log(s, AV_LOG_ERROR, "Error getting frame: %s\n", vserr);
372         err = AVERROR_EXTERNAL;
373         goto end;
374     }
375
376     ref_data->vsapi = vs->vsapi;
377     ref_data->frame = vsframe;
378
379     ref_data->vss_state = av_buffer_ref(vs->vss_state);
380     if (!ref_data->vss_state) {
381         err = AVERROR(ENOMEM);
382         goto end;
383     }
384
385     props = vs->vsapi->getFramePropsRO(vsframe);
386
387     frame = av_frame_alloc();
388     if (!frame) {
389         err = AVERROR(ENOMEM);
390         goto end;
391     }
392
393     frame->format       = st->codecpar->format;
394     frame->width        = st->codecpar->width;
395     frame->height       = st->codecpar->height;
396     frame->colorspace   = st->codecpar->color_space;
397
398     // Values according to ISO/IEC 14496-10.
399     frame->colorspace       = get_vs_prop_int(s, props, "_Matrix",      frame->colorspace);
400     frame->color_primaries  = get_vs_prop_int(s, props, "_Primaries",   frame->color_primaries);
401     frame->color_trc        = get_vs_prop_int(s, props, "_Transfer",    frame->color_trc);
402
403     if (get_vs_prop_int(s, props, "_ColorRange", 1) == 0)
404         frame->color_range = AVCOL_RANGE_JPEG;
405
406     frame->sample_aspect_ratio.num = get_vs_prop_int(s, props, "_SARNum", 0);
407     frame->sample_aspect_ratio.den = get_vs_prop_int(s, props, "_SARDen", 1);
408
409     av_assert0(vs->vsapi->getFrameWidth(vsframe, 0) == frame->width);
410     av_assert0(vs->vsapi->getFrameHeight(vsframe, 0) == frame->height);
411
412     desc = av_pix_fmt_desc_get(frame->format);
413
414     for (i = 0; i < info->format->numPlanes; i++) {
415         int p = vs->c_order[i];
416         ptrdiff_t plane_h = frame->height;
417
418         frame->data[i] = (void *)vs->vsapi->getReadPtr(vsframe, p);
419         frame->linesize[i] = vs->vsapi->getStride(vsframe, p);
420
421         frame->buf[i] = av_buffer_ref(vsframe_ref);
422         if (!frame->buf[i]) {
423             err = AVERROR(ENOMEM);
424             goto end;
425         }
426
427         // Each plane needs an AVBufferRef that indicates the correct plane
428         // memory range. VapourSynth doesn't even give us the memory range,
429         // so make up a bad guess to make FFmpeg happy (even if almost nothing
430         // checks the memory range).
431         if (i == 1 || i == 2)
432             plane_h = AV_CEIL_RSHIFT(plane_h, desc->log2_chroma_h);
433         frame->buf[i]->data = frame->data[i];
434         frame->buf[i]->size = frame->linesize[i] * plane_h;
435     }
436
437     pkt->buf = av_buffer_create((uint8_t*)frame, sizeof(*frame),
438                                 free_frame, NULL, 0);
439     if (!pkt->buf) {
440         err = AVERROR(ENOMEM);
441         goto end;
442     }
443
444     frame = NULL; // pkt owns it now
445
446     pkt->data   = pkt->buf->data;
447     pkt->size   = pkt->buf->size;
448     pkt->flags |= AV_PKT_FLAG_TRUSTED;
449
450     if (vs->is_cfr)
451         pkt->pts = vs->current_frame;
452
453     vs->current_frame++;
454
455 end:
456     av_frame_free(&frame);
457     av_buffer_unref(&vsframe_ref);
458     return err;
459 }
460
461 static int read_seek_vs(AVFormatContext *s, int stream_idx, int64_t ts, int flags)
462 {
463     VSContext *vs = s->priv_data;
464
465     if (!vs->is_cfr)
466         return AVERROR(ENOSYS);
467
468     vs->current_frame = FFMIN(FFMAX(0, ts), s->streams[0]->duration);
469     return 0;
470 }
471
472 static av_cold int probe_vs(const AVProbeData *p)
473 {
474     // Explicitly do not support this. VS scripts are written in Python, and
475     // can run arbitrary code on the user's system.
476     return 0;
477 }
478
479 static const AVClass class_vs = {
480     .class_name = "VapourSynth demuxer",
481     .item_name  = av_default_item_name,
482     .option     = options,
483     .version    = LIBAVUTIL_VERSION_INT,
484 };
485
486 const AVInputFormat ff_vapoursynth_demuxer = {
487     .name           = "vapoursynth",
488     .long_name      = NULL_IF_CONFIG_SMALL("VapourSynth demuxer"),
489     .priv_data_size = sizeof(VSContext),
490     .read_probe     = probe_vs,
491     .read_header    = read_header_vs,
492     .read_packet    = read_packet_vs,
493     .read_close     = read_close_vs,
494     .read_seek      = read_seek_vs,
495     .priv_class     = &class_vs,
496 };