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