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