avisynth: Simplify the pix_fmt check for the newer AviSynth API
[libav.git] / libavformat / avisynth.c
CommitLineData
9dc5607b 1/*
f0b234ab 2 * AviSynth/AvxSynth support
41ed7ab4 3 * Copyright (c) 2012 AvxSynth Team
9dc5607b 4 *
2912e87a 5 * This file is part of Libav.
b78e7197 6 *
2912e87a 7 * Libav is free software; you can redistribute it and/or
9dc5607b
GP
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
b78e7197 10 * version 2.1 of the License, or (at your option) any later version.
9dc5607b 11 *
2912e87a 12 * Libav is distributed in the hope that it will be useful,
9dc5607b
GP
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
2912e87a 18 * License along with Libav; if not, write to the Free Software
9dc5607b
GP
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
97b052e5 22#include "libavutil/internal.h"
f0b234ab 23#include "libavcodec/internal.h"
9dc5607b 24#include "avformat.h"
c3f9ebf7 25#include "internal.h"
247aa7af 26#include "config.h"
f0b234ab 27
28/* Enable function pointer definitions for runtime loading. */
29#define AVSC_NO_DECLSPEC
30
11881196 31/* Platform-specific directives for AviSynth vs AvxSynth. */
f0b234ab 32#ifdef _WIN32
33 #include <windows.h>
34 #undef EXTERN_C
35 #include <avisynth/avisynth_c.h>
36 #define AVISYNTH_LIB "avisynth"
37 #define USING_AVISYNTH
38#else
39 #include <dlfcn.h>
40 #include <avxsynth/avxsynth_c.h>
247aa7af
DB
41 #define AVISYNTH_NAME "libavxsynth"
42 #define AVISYNTH_LIB AVISYNTH_NAME SLIBSUF
f0b234ab 43
f2ad1495 44 #define LoadLibrary(x) dlopen(x, RTLD_NOW | RTLD_LOCAL)
f0b234ab 45 #define GetProcAddress dlsym
46 #define FreeLibrary dlclose
47#endif
48
49typedef struct AviSynthLibrary {
50 void *library;
51#define AVSC_DECLARE_FUNC(name) name ## _func name
52 AVSC_DECLARE_FUNC(avs_bit_blt);
53 AVSC_DECLARE_FUNC(avs_clip_get_error);
54 AVSC_DECLARE_FUNC(avs_create_script_environment);
55 AVSC_DECLARE_FUNC(avs_delete_script_environment);
56 AVSC_DECLARE_FUNC(avs_get_audio);
57 AVSC_DECLARE_FUNC(avs_get_error);
58 AVSC_DECLARE_FUNC(avs_get_frame);
59 AVSC_DECLARE_FUNC(avs_get_version);
60 AVSC_DECLARE_FUNC(avs_get_video_info);
61 AVSC_DECLARE_FUNC(avs_invoke);
62 AVSC_DECLARE_FUNC(avs_release_clip);
63 AVSC_DECLARE_FUNC(avs_release_value);
64 AVSC_DECLARE_FUNC(avs_release_video_frame);
65 AVSC_DECLARE_FUNC(avs_take_clip);
a8c99205
SH
66#ifdef USING_AVISYNTH
67 AVSC_DECLARE_FUNC(avs_bits_per_pixel);
68 AVSC_DECLARE_FUNC(avs_get_height_p);
69 AVSC_DECLARE_FUNC(avs_get_pitch_p);
70 AVSC_DECLARE_FUNC(avs_get_read_ptr_p);
71 AVSC_DECLARE_FUNC(avs_get_row_size_p);
a8c99205 72#endif
f0b234ab 73#undef AVSC_DECLARE_FUNC
74} AviSynthLibrary;
75
76typedef struct AviSynthContext {
77 AVS_ScriptEnvironment *env;
78 AVS_Clip *clip;
79 const AVS_VideoInfo *vi;
80
81 /* avisynth_read_packet_video() iterates over this. */
82 int n_planes;
83 const int *planes;
84
85 int curr_stream;
86 int curr_frame;
87 int64_t curr_sample;
88
89 int error;
90
91 /* Linked list pointers. */
92 struct AviSynthContext *next;
03039f4c 93} AviSynthContext;
9dc5607b 94
f0b234ab 95static const int avs_planes_packed[1] = { 0 };
96static const int avs_planes_grey[1] = { AVS_PLANAR_Y };
97static const int avs_planes_yuv[3] = { AVS_PLANAR_Y, AVS_PLANAR_U,
98 AVS_PLANAR_V };
99
100/* A conflict between C++ global objects, atexit, and dynamic loading requires
101 * us to register our own atexit handler to prevent double freeing. */
102static AviSynthLibrary avs_library;
103static int avs_atexit_called = 0;
104
105/* Linked list of AviSynthContexts. An atexit handler destroys this list. */
106static AviSynthContext *avs_ctx_list = NULL;
107
108static av_cold void avisynth_atexit_handler(void);
109
110static av_cold int avisynth_load_library(void)
111{
112 avs_library.library = LoadLibrary(AVISYNTH_LIB);
113 if (!avs_library.library)
114 return AVERROR_UNKNOWN;
115
116#define LOAD_AVS_FUNC(name, continue_on_fail) \
800d91d3 117 avs_library.name = GetProcAddress(avs_library.library, #name); \
f0b234ab 118 if (!continue_on_fail && !avs_library.name) \
119 goto fail;
120
121 LOAD_AVS_FUNC(avs_bit_blt, 0);
122 LOAD_AVS_FUNC(avs_clip_get_error, 0);
123 LOAD_AVS_FUNC(avs_create_script_environment, 0);
124 LOAD_AVS_FUNC(avs_delete_script_environment, 0);
125 LOAD_AVS_FUNC(avs_get_audio, 0);
126 LOAD_AVS_FUNC(avs_get_error, 1); // New to AviSynth 2.6
127 LOAD_AVS_FUNC(avs_get_frame, 0);
128 LOAD_AVS_FUNC(avs_get_version, 0);
129 LOAD_AVS_FUNC(avs_get_video_info, 0);
130 LOAD_AVS_FUNC(avs_invoke, 0);
131 LOAD_AVS_FUNC(avs_release_clip, 0);
132 LOAD_AVS_FUNC(avs_release_value, 0);
133 LOAD_AVS_FUNC(avs_release_video_frame, 0);
134 LOAD_AVS_FUNC(avs_take_clip, 0);
a8c99205 135#ifdef USING_AVISYNTH
a6a45e5a
SH
136 LOAD_AVS_FUNC(avs_bits_per_pixel, 1);
137 LOAD_AVS_FUNC(avs_get_height_p, 1);
138 LOAD_AVS_FUNC(avs_get_pitch_p, 1);
139 LOAD_AVS_FUNC(avs_get_read_ptr_p, 1);
140 LOAD_AVS_FUNC(avs_get_row_size_p, 1);
a8c99205 141#endif
f0b234ab 142#undef LOAD_AVS_FUNC
143
144 atexit(avisynth_atexit_handler);
145 return 0;
146
147fail:
148 FreeLibrary(avs_library.library);
149 return AVERROR_UNKNOWN;
150}
151
152/* Note that avisynth_context_create and avisynth_context_destroy
153 * do not allocate or free the actual context! That is taken care of
154 * by libavformat. */
155static av_cold int avisynth_context_create(AVFormatContext *s)
9dc5607b 156{
c16ddcc9 157 AviSynthContext *avs = s->priv_data;
f0b234ab 158 int ret;
159
160 if (!avs_library.library)
161 if (ret = avisynth_load_library())
162 return ret;
163
164 avs->env = avs_library.avs_create_script_environment(3);
165 if (avs_library.avs_get_error) {
166 const char *error = avs_library.avs_get_error(avs->env);
167 if (error) {
168 av_log(s, AV_LOG_ERROR, "%s\n", error);
169 return AVERROR_UNKNOWN;
9dc5607b
GP
170 }
171 }
172
f0b234ab 173 if (!avs_ctx_list) {
174 avs_ctx_list = avs;
175 } else {
176 avs->next = avs_ctx_list;
177 avs_ctx_list = avs;
178 }
179
c16ddcc9 180 return 0;
9dc5607b
GP
181}
182
f0b234ab 183static av_cold void avisynth_context_destroy(AviSynthContext *avs)
184{
185 if (avs_atexit_called)
186 return;
187
188 if (avs == avs_ctx_list) {
189 avs_ctx_list = avs->next;
190 } else {
191 AviSynthContext *prev = avs_ctx_list;
192 while (prev->next != avs)
193 prev = prev->next;
194 prev->next = avs->next;
195 }
196
197 if (avs->clip) {
198 avs_library.avs_release_clip(avs->clip);
199 avs->clip = NULL;
200 }
201 if (avs->env) {
202 avs_library.avs_delete_script_environment(avs->env);
203 avs->env = NULL;
204 }
205}
206
207static av_cold void avisynth_atexit_handler(void)
208{
209 AviSynthContext *avs = avs_ctx_list;
210
211 while (avs) {
212 AviSynthContext *next = avs->next;
213 avisynth_context_destroy(avs);
214 avs = next;
215 }
216 FreeLibrary(avs_library.library);
217
218 avs_atexit_called = 1;
219}
220
221/* Create AVStream from audio and video data. */
222static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st)
223{
224 AviSynthContext *avs = s->priv_data;
225 int planar = 0; // 0: packed, 1: YUV, 2: Y8
226
9200514a
AK
227 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
228 st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO;
229 st->codecpar->width = avs->vi->width;
230 st->codecpar->height = avs->vi->height;
f0b234ab 231
f0b234ab 232 st->avg_frame_rate = (AVRational) { avs->vi->fps_numerator,
233 avs->vi->fps_denominator };
234 st->start_time = 0;
235 st->duration = avs->vi->num_frames;
236 st->nb_frames = avs->vi->num_frames;
bcefafa2 237 avpriv_set_pts_info(st, 32, avs->vi->fps_denominator, avs->vi->fps_numerator);
f0b234ab 238
239 switch (avs->vi->pixel_type) {
240#ifdef USING_AVISYNTH
241 case AVS_CS_YV24:
9200514a
AK
242 st->codecpar->format = AV_PIX_FMT_YUV444P;
243 planar = 1;
f0b234ab 244 break;
245 case AVS_CS_YV16:
9200514a
AK
246 st->codecpar->format = AV_PIX_FMT_YUV422P;
247 planar = 1;
f0b234ab 248 break;
249 case AVS_CS_YV411:
9200514a
AK
250 st->codecpar->format = AV_PIX_FMT_YUV411P;
251 planar = 1;
f0b234ab 252 break;
253 case AVS_CS_Y8:
9200514a
AK
254 st->codecpar->format = AV_PIX_FMT_GRAY8;
255 planar = 2;
f0b234ab 256 break;
257#endif
258 case AVS_CS_BGR24:
9200514a 259 st->codecpar->format = AV_PIX_FMT_BGR24;
f0b234ab 260 break;
261 case AVS_CS_BGR32:
9200514a 262 st->codecpar->format = AV_PIX_FMT_RGB32;
f0b234ab 263 break;
264 case AVS_CS_YUY2:
9200514a 265 st->codecpar->format = AV_PIX_FMT_YUYV422;
f0b234ab 266 break;
267 case AVS_CS_YV12:
9200514a
AK
268 st->codecpar->format = AV_PIX_FMT_YUV420P;
269 planar = 1;
f0b234ab 270 break;
271 case AVS_CS_I420: // Is this even used anywhere?
9200514a
AK
272 st->codecpar->format = AV_PIX_FMT_YUV420P;
273 planar = 1;
f0b234ab 274 break;
275 default:
276 av_log(s, AV_LOG_ERROR,
277 "unknown AviSynth colorspace %d\n", avs->vi->pixel_type);
278 avs->error = 1;
279 return AVERROR_UNKNOWN;
280 }
281
282 switch (planar) {
283 case 2: // Y8
284 avs->n_planes = 1;
285 avs->planes = avs_planes_grey;
286 break;
287 case 1: // YUV
288 avs->n_planes = 3;
289 avs->planes = avs_planes_yuv;
290 break;
291 default:
292 avs->n_planes = 1;
293 avs->planes = avs_planes_packed;
294 }
295 return 0;
296}
297
298static int avisynth_create_stream_audio(AVFormatContext *s, AVStream *st)
299{
300 AviSynthContext *avs = s->priv_data;
301
9200514a
AK
302 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
303 st->codecpar->sample_rate = avs->vi->audio_samples_per_second;
304 st->codecpar->channels = avs->vi->nchannels;
bcefafa2
MB
305 st->duration = avs->vi->num_audio_samples;
306 avpriv_set_pts_info(st, 64, 1, avs->vi->audio_samples_per_second);
f0b234ab 307
308 switch (avs->vi->sample_type) {
309 case AVS_SAMPLE_INT8:
9200514a 310 st->codecpar->codec_id = AV_CODEC_ID_PCM_U8;
f0b234ab 311 break;
312 case AVS_SAMPLE_INT16:
9200514a 313 st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE;
f0b234ab 314 break;
315 case AVS_SAMPLE_INT24:
9200514a 316 st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE;
f0b234ab 317 break;
318 case AVS_SAMPLE_INT32:
9200514a 319 st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE;
f0b234ab 320 break;
321 case AVS_SAMPLE_FLOAT:
9200514a 322 st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE;
f0b234ab 323 break;
324 default:
325 av_log(s, AV_LOG_ERROR,
326 "unknown AviSynth sample type %d\n", avs->vi->sample_type);
327 avs->error = 1;
328 return AVERROR_UNKNOWN;
329 }
330 return 0;
331}
332
333static int avisynth_create_stream(AVFormatContext *s)
334{
335 AviSynthContext *avs = s->priv_data;
336 AVStream *st;
337 int ret;
338 int id = 0;
339
340 if (avs_has_video(avs->vi)) {
341 st = avformat_new_stream(s, NULL);
342 if (!st)
343 return AVERROR_UNKNOWN;
344 st->id = id++;
345 if (ret = avisynth_create_stream_video(s, st))
346 return ret;
347 }
348 if (avs_has_audio(avs->vi)) {
349 st = avformat_new_stream(s, NULL);
350 if (!st)
351 return AVERROR_UNKNOWN;
352 st->id = id++;
353 if (ret = avisynth_create_stream_audio(s, st))
354 return ret;
355 }
356 return 0;
357}
358
359static int avisynth_open_file(AVFormatContext *s)
9dc5607b 360{
c16ddcc9 361 AviSynthContext *avs = s->priv_data;
f0b234ab 362 AVS_Value arg, val;
363 int ret;
364#ifdef USING_AVISYNTH
365 char filename_ansi[MAX_PATH * 4];
366 wchar_t filename_wc[MAX_PATH * 4];
367#endif
368
369 if (ret = avisynth_context_create(s))
370 return ret;
371
372#ifdef USING_AVISYNTH
373 /* Convert UTF-8 to ANSI code page */
374 MultiByteToWideChar(CP_UTF8, 0, s->filename, -1, filename_wc, MAX_PATH * 4);
375 WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi,
376 MAX_PATH * 4, NULL, NULL);
377 arg = avs_new_value_string(filename_ansi);
378#else
379 arg = avs_new_value_string(s->filename);
380#endif
381 val = avs_library.avs_invoke(avs->env, "Import", arg, 0);
382 if (avs_is_error(val)) {
383 av_log(s, AV_LOG_ERROR, "%s\n", avs_as_error(val));
384 ret = AVERROR_UNKNOWN;
385 goto fail;
386 }
387 if (!avs_is_clip(val)) {
388 av_log(s, AV_LOG_ERROR, "AviSynth script did not return a clip\n");
389 ret = AVERROR_UNKNOWN;
390 goto fail;
391 }
9dc5607b 392
f0b234ab 393 avs->clip = avs_library.avs_take_clip(val, avs->env);
394 avs->vi = avs_library.avs_get_video_info(avs->clip);
9dc5607b 395
f0b234ab 396#ifdef USING_AVISYNTH
7a5f4447
SH
397 /* On Windows, libav supports AviSynth interface version 6 or higher.
398 * This includes AviSynth 2.6 RC1 or higher, and AviSynth+ r1718 or higher,
399 * and excludes 2.5 and the 2.6 alphas. Since AvxSynth identifies itself
400 * as interface version 3 like 2.5.8, this needs to be special-cased. */
f0b234ab 401
7a5f4447 402 if (avs_library.avs_get_version(avs->clip) < 6) {
f0b234ab 403 av_log(s, AV_LOG_ERROR,
7a5f4447 404 "AviSynth version is too old. Please upgrade to either AviSynth 2.6 >= RC1 or AviSynth+ >= r1718.\n");
f0b234ab 405 ret = AVERROR_UNKNOWN;
406 goto fail;
407 }
408#endif
9dc5607b 409
f0b234ab 410 /* Release the AVS_Value as it will go out of scope. */
411 avs_library.avs_release_value(val);
412
413 if (ret = avisynth_create_stream(s))
414 goto fail;
415
416 return 0;
9dc5607b 417
f0b234ab 418fail:
419 avisynth_context_destroy(avs);
420 return ret;
421}
9dc5607b 422
f0b234ab 423static void avisynth_next_stream(AVFormatContext *s, AVStream **st,
424 AVPacket *pkt, int *discard)
425{
426 AviSynthContext *avs = s->priv_data;
9dc5607b 427
c9db8694 428 avs->curr_stream++;
f0b234ab 429 avs->curr_stream %= s->nb_streams;
9dc5607b 430
c9db8694 431 *st = s->streams[avs->curr_stream];
f0b234ab 432 if ((*st)->discard == AVDISCARD_ALL)
433 *discard = 1;
434 else
435 *discard = 0;
9dc5607b 436
f0b234ab 437 return;
9dc5607b
GP
438}
439
f0b234ab 440/* Copy AviSynth clip data into an AVPacket. */
441static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt,
442 int discard)
9dc5607b 443{
c16ddcc9 444 AviSynthContext *avs = s->priv_data;
f0b234ab 445 AVS_VideoFrame *frame;
446 unsigned char *dst_p;
447 const unsigned char *src_p;
448 int n, i, plane, rowsize, planeheight, pitch, bits;
449 const char *error;
450
451 if (avs->curr_frame >= avs->vi->num_frames)
452 return AVERROR_EOF;
453
454 /* This must happen even if the stream is discarded to prevent desync. */
455 n = avs->curr_frame++;
456 if (discard)
457 return 0;
458
f0b234ab 459#ifdef USING_AVISYNTH
aaae5970
SH
460 /* avs_bits_per_pixel changed to AVSC_API with AviSynth 2.6, which
461 * requires going through avs_library, while AvxSynth has it under
462 * the older AVSC_INLINE type, so special-case this. */
463
464 bits = avs_library.avs_bits_per_pixel(avs->vi);
a8c99205
SH
465#else
466 bits = avs_bits_per_pixel(avs->vi);
f0b234ab 467#endif
f0b234ab 468
469 /* Without the cast to int64_t, calculation overflows at about 9k x 9k
470 * resolution. */
471 pkt->size = (((int64_t)avs->vi->width *
472 (int64_t)avs->vi->height) * bits) / 8;
473 if (!pkt->size)
474 return AVERROR_UNKNOWN;
475
476 if (av_new_packet(pkt, pkt->size) < 0)
477 return AVERROR(ENOMEM);
478
c9db8694
MN
479 pkt->pts = n;
480 pkt->dts = n;
481 pkt->duration = 1;
482 pkt->stream_index = avs->curr_stream;
483
f0b234ab 484 frame = avs_library.avs_get_frame(avs->clip, n);
485 error = avs_library.avs_clip_get_error(avs->clip);
486 if (error) {
487 av_log(s, AV_LOG_ERROR, "%s\n", error);
488 avs->error = 1;
489 av_packet_unref(pkt);
490 return AVERROR_UNKNOWN;
491 }
9dc5607b 492
f0b234ab 493 dst_p = pkt->data;
494 for (i = 0; i < avs->n_planes; i++) {
495 plane = avs->planes[i];
a8c99205
SH
496#ifdef USING_AVISYNTH
497 src_p = avs_library.avs_get_read_ptr_p(frame, plane);
498 pitch = avs_library.avs_get_pitch_p(frame, plane);
499
500 rowsize = avs_library.avs_get_row_size_p(frame, plane);
501 planeheight = avs_library.avs_get_height_p(frame, plane);
502#else
f0b234ab 503 src_p = avs_get_read_ptr_p(frame, plane);
504 pitch = avs_get_pitch_p(frame, plane);
505
506 rowsize = avs_get_row_size_p(frame, plane);
507 planeheight = avs_get_height_p(frame, plane);
a8c99205 508#endif
f0b234ab 509
510 /* Flip RGB video. */
511 if (avs_is_rgb24(avs->vi) || avs_is_rgb(avs->vi)) {
512 src_p = src_p + (planeheight - 1) * pitch;
513 pitch = -pitch;
514 }
9dc5607b 515
f0b234ab 516 avs_library.avs_bit_blt(avs->env, dst_p, rowsize, src_p, pitch,
517 rowsize, planeheight);
518 dst_p += rowsize * planeheight;
519 }
520
521 avs_library.avs_release_video_frame(frame);
c16ddcc9 522 return 0;
9dc5607b
GP
523}
524
f0b234ab 525static int avisynth_read_packet_audio(AVFormatContext *s, AVPacket *pkt,
526 int discard)
9dc5607b 527{
c16ddcc9 528 AviSynthContext *avs = s->priv_data;
f0b234ab 529 AVRational fps, samplerate;
530 int samples;
531 int64_t n;
532 const char *error;
533
534 if (avs->curr_sample >= avs->vi->num_audio_samples)
535 return AVERROR_EOF;
536
537 fps.num = avs->vi->fps_numerator;
538 fps.den = avs->vi->fps_denominator;
539 samplerate.num = avs->vi->audio_samples_per_second;
540 samplerate.den = 1;
541
542 if (avs_has_video(avs->vi)) {
543 if (avs->curr_frame < avs->vi->num_frames)
544 samples = av_rescale_q(avs->curr_frame, samplerate, fps) -
545 avs->curr_sample;
546 else
547 samples = av_rescale_q(1, samplerate, fps);
548 } else {
549 samples = 1000;
550 }
551
552 /* After seeking, audio may catch up with video. */
553 if (samples <= 0) {
554 pkt->size = 0;
555 pkt->data = NULL;
556 return 0;
557 }
558
559 if (avs->curr_sample + samples > avs->vi->num_audio_samples)
560 samples = avs->vi->num_audio_samples - avs->curr_sample;
561
562 /* This must happen even if the stream is discarded to prevent desync. */
563 n = avs->curr_sample;
564 avs->curr_sample += samples;
565 if (discard)
566 return 0;
567
f0b234ab 568 pkt->size = avs_bytes_per_channel_sample(avs->vi) *
569 samples * avs->vi->nchannels;
570 if (!pkt->size)
571 return AVERROR_UNKNOWN;
572
573 if (av_new_packet(pkt, pkt->size) < 0)
574 return AVERROR(ENOMEM);
575
c9db8694
MN
576 pkt->pts = n;
577 pkt->dts = n;
578 pkt->duration = samples;
579 pkt->stream_index = avs->curr_stream;
580
f0b234ab 581 avs_library.avs_get_audio(avs->clip, pkt->data, n, samples);
582 error = avs_library.avs_clip_get_error(avs->clip);
583 if (error) {
584 av_log(s, AV_LOG_ERROR, "%s\n", error);
585 avs->error = 1;
586 av_packet_unref(pkt);
587 return AVERROR_UNKNOWN;
588 }
589 return 0;
590}
591
592static av_cold int avisynth_read_header(AVFormatContext *s)
593{
594 int ret;
595
596 // Calling library must implement a lock for thread-safe opens.
597 if (ret = avpriv_lock_avformat())
598 return ret;
9dc5607b 599
f0b234ab 600 if (ret = avisynth_open_file(s)) {
601 avpriv_unlock_avformat();
602 return ret;
603 }
604
605 avpriv_unlock_avformat();
606 return 0;
607}
608
609static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt)
610{
611 AviSynthContext *avs = s->priv_data;
612 AVStream *st;
613 int discard = 0;
614 int ret;
615
616 if (avs->error)
617 return AVERROR_UNKNOWN;
618
619 /* If either stream reaches EOF, try to read the other one before
620 * giving up. */
621 avisynth_next_stream(s, &st, pkt, &discard);
9200514a 622 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
f0b234ab 623 ret = avisynth_read_packet_video(s, pkt, discard);
624 if (ret == AVERROR_EOF && avs_has_audio(avs->vi)) {
625 avisynth_next_stream(s, &st, pkt, &discard);
626 return avisynth_read_packet_audio(s, pkt, discard);
627 }
628 } else {
629 ret = avisynth_read_packet_audio(s, pkt, discard);
630 if (ret == AVERROR_EOF && avs_has_video(avs->vi)) {
631 avisynth_next_stream(s, &st, pkt, &discard);
632 return avisynth_read_packet_video(s, pkt, discard);
633 }
634 }
635
636 return ret;
637}
638
639static av_cold int avisynth_read_close(AVFormatContext *s)
640{
641 if (avpriv_lock_avformat())
642 return AVERROR_UNKNOWN;
643
644 avisynth_context_destroy(s->priv_data);
645 avpriv_unlock_avformat();
646 return 0;
647}
648
649static int avisynth_read_seek(AVFormatContext *s, int stream_index,
650 int64_t timestamp, int flags)
651{
652 AviSynthContext *avs = s->priv_data;
653 AVStream *st;
654 AVRational fps, samplerate;
655
656 if (avs->error)
657 return AVERROR_UNKNOWN;
658
659 fps = (AVRational) { avs->vi->fps_numerator,
660 avs->vi->fps_denominator };
661 samplerate = (AVRational) { avs->vi->audio_samples_per_second, 1 };
662
663 st = s->streams[stream_index];
9200514a 664 if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
f0b234ab 665 /* AviSynth frame counts are signed int. */
666 if ((timestamp >= avs->vi->num_frames) ||
667 (timestamp > INT_MAX) ||
668 (timestamp < 0))
669 return AVERROR_EOF;
670 avs->curr_frame = timestamp;
671 if (avs_has_audio(avs->vi))
672 avs->curr_sample = av_rescale_q(timestamp, samplerate, fps);
673 } else {
674 if ((timestamp >= avs->vi->num_audio_samples) || (timestamp < 0))
675 return AVERROR_EOF;
676 /* Force frame granularity for seeking. */
677 if (avs_has_video(avs->vi)) {
678 avs->curr_frame = av_rescale_q(timestamp, fps, samplerate);
679 avs->curr_sample = av_rescale_q(avs->curr_frame, samplerate, fps);
680 } else {
681 avs->curr_sample = timestamp;
682 }
683 }
9dc5607b 684
c16ddcc9 685 return 0;
9dc5607b
GP
686}
687
c6610a21 688AVInputFormat ff_avisynth_demuxer = {
0f5b0b41 689 .name = "avisynth",
f0b234ab 690 .long_name = NULL_IF_CONFIG_SMALL("AviSynth script"),
03039f4c 691 .priv_data_size = sizeof(AviSynthContext),
dfc2c4d9
AK
692 .read_header = avisynth_read_header,
693 .read_packet = avisynth_read_packet,
694 .read_close = avisynth_read_close,
695 .read_seek = avisynth_read_seek,
696 .extensions = "avs",
9dc5607b 697};