avisynth: fix setting packet properties
[ffmpeg.git] / 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
307     switch (avs->vi->sample_type) {
308     case AVS_SAMPLE_INT8:
309         st->codec->codec_id = AV_CODEC_ID_PCM_U8;
310         break;
311     case AVS_SAMPLE_INT16:
312         st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
313         break;
314     case AVS_SAMPLE_INT24:
315         st->codec->codec_id = AV_CODEC_ID_PCM_S24LE;
316         break;
317     case AVS_SAMPLE_INT32:
318         st->codec->codec_id = AV_CODEC_ID_PCM_S32LE;
319         break;
320     case AVS_SAMPLE_FLOAT:
321         st->codec->codec_id = AV_CODEC_ID_PCM_F32LE;
322         break;
323     default:
324         av_log(s, AV_LOG_ERROR,
325                "unknown AviSynth sample type %d\n", avs->vi->sample_type);
326         avs->error = 1;
327         return AVERROR_UNKNOWN;
328     }
329     return 0;
330 }
331
332 static int avisynth_create_stream(AVFormatContext *s)
333 {
334     AviSynthContext *avs = s->priv_data;
335     AVStream *st;
336     int ret;
337     int id = 0;
338
339     if (avs_has_video(avs->vi)) {
340         st = avformat_new_stream(s, NULL);
341         if (!st)
342             return AVERROR_UNKNOWN;
343         st->id = id++;
344         if (ret = avisynth_create_stream_video(s, st))
345             return ret;
346     }
347     if (avs_has_audio(avs->vi)) {
348         st = avformat_new_stream(s, NULL);
349         if (!st)
350             return AVERROR_UNKNOWN;
351         st->id = id++;
352         if (ret = avisynth_create_stream_audio(s, st))
353             return ret;
354     }
355     return 0;
356 }
357
358 static int avisynth_open_file(AVFormatContext *s)
359 {
360     AviSynthContext *avs = s->priv_data;
361     AVS_Value arg, val;
362     int ret;
363 #ifdef USING_AVISYNTH
364     char filename_ansi[MAX_PATH * 4];
365     wchar_t filename_wc[MAX_PATH * 4];
366 #endif
367
368     if (ret = avisynth_context_create(s))
369         return ret;
370
371 #ifdef USING_AVISYNTH
372     /* Convert UTF-8 to ANSI code page */
373     MultiByteToWideChar(CP_UTF8, 0, s->filename, -1, filename_wc, MAX_PATH * 4);
374     WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi,
375                         MAX_PATH * 4, NULL, NULL);
376     arg = avs_new_value_string(filename_ansi);
377 #else
378     arg = avs_new_value_string(s->filename);
379 #endif
380     val = avs_library.avs_invoke(avs->env, "Import", arg, 0);
381     if (avs_is_error(val)) {
382         av_log(s, AV_LOG_ERROR, "%s\n", avs_as_error(val));
383         ret = AVERROR_UNKNOWN;
384         goto fail;
385     }
386     if (!avs_is_clip(val)) {
387         av_log(s, AV_LOG_ERROR, "AviSynth script did not return a clip\n");
388         ret = AVERROR_UNKNOWN;
389         goto fail;
390     }
391
392     avs->clip = avs_library.avs_take_clip(val, avs->env);
393     avs->vi   = avs_library.avs_get_video_info(avs->clip);
394
395 #ifdef USING_AVISYNTH
396     /* libav only supports AviSynth 2.6 on Windows. Since AvxSynth
397      * identifies itself as interface version 3 like 2.5.8, this
398      * needs to be special-cased. */
399
400     if (avs_library.avs_get_version(avs->clip) == 3) {
401         av_log(s, AV_LOG_ERROR,
402                "AviSynth 2.5.8 not supported. Please upgrade to 2.6.\n");
403         ret = AVERROR_UNKNOWN;
404         goto fail;
405     }
406 #endif
407
408     /* Release the AVS_Value as it will go out of scope. */
409     avs_library.avs_release_value(val);
410
411     if (ret = avisynth_create_stream(s))
412         goto fail;
413
414     return 0;
415
416 fail:
417     avisynth_context_destroy(avs);
418     return ret;
419 }
420
421 static void avisynth_next_stream(AVFormatContext *s, AVStream **st,
422                                  AVPacket *pkt, int *discard)
423 {
424     AviSynthContext *avs = s->priv_data;
425
426     avs->curr_stream++;
427     avs->curr_stream %= s->nb_streams;
428
429     *st = s->streams[avs->curr_stream];
430     if ((*st)->discard == AVDISCARD_ALL)
431         *discard = 1;
432     else
433         *discard = 0;
434
435     return;
436 }
437
438 /* Copy AviSynth clip data into an AVPacket. */
439 static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt,
440                                       int discard)
441 {
442     AviSynthContext *avs = s->priv_data;
443     AVS_VideoFrame *frame;
444     unsigned char *dst_p;
445     const unsigned char *src_p;
446     int n, i, plane, rowsize, planeheight, pitch, bits;
447     const char *error;
448
449     if (avs->curr_frame >= avs->vi->num_frames)
450         return AVERROR_EOF;
451
452     /* This must happen even if the stream is discarded to prevent desync. */
453     n = avs->curr_frame++;
454     if (discard)
455         return 0;
456
457 #ifdef USING_AVISYNTH
458     /* Define the bpp values for the new AviSynth 2.6 colorspaces.
459      * Since AvxSynth doesn't have these functions, special-case
460      * it in order to avoid implicit declaration errors. */
461
462     if (avs_is_yv24(avs->vi))
463         bits = 24;
464     else if (avs_is_yv16(avs->vi))
465         bits = 16;
466     else if (avs_is_yv411(avs->vi))
467         bits = 12;
468     else if (avs_is_y8(avs->vi))
469         bits = 8;
470     else
471 #endif
472         bits = avs_bits_per_pixel(avs->vi);
473
474     /* Without the cast to int64_t, calculation overflows at about 9k x 9k
475      * resolution. */
476     pkt->size = (((int64_t)avs->vi->width *
477                   (int64_t)avs->vi->height) * bits) / 8;
478     if (!pkt->size)
479         return AVERROR_UNKNOWN;
480
481     if (av_new_packet(pkt, pkt->size) < 0)
482         return AVERROR(ENOMEM);
483
484     pkt->pts      = n;
485     pkt->dts      = n;
486     pkt->duration = 1;
487     pkt->stream_index = avs->curr_stream;
488
489     frame = avs_library.avs_get_frame(avs->clip, n);
490     error = avs_library.avs_clip_get_error(avs->clip);
491     if (error) {
492         av_log(s, AV_LOG_ERROR, "%s\n", error);
493         avs->error = 1;
494         av_packet_unref(pkt);
495         return AVERROR_UNKNOWN;
496     }
497
498     dst_p = pkt->data;
499     for (i = 0; i < avs->n_planes; i++) {
500         plane = avs->planes[i];
501         src_p = avs_get_read_ptr_p(frame, plane);
502         pitch = avs_get_pitch_p(frame, plane);
503
504         rowsize     = avs_get_row_size_p(frame, plane);
505         planeheight = avs_get_height_p(frame, plane);
506
507         /* Flip RGB video. */
508         if (avs_is_rgb24(avs->vi) || avs_is_rgb(avs->vi)) {
509             src_p = src_p + (planeheight - 1) * pitch;
510             pitch = -pitch;
511         }
512
513         avs_library.avs_bit_blt(avs->env, dst_p, rowsize, src_p, pitch,
514                                  rowsize, planeheight);
515         dst_p += rowsize * planeheight;
516     }
517
518     avs_library.avs_release_video_frame(frame);
519     return 0;
520 }
521
522 static int avisynth_read_packet_audio(AVFormatContext *s, AVPacket *pkt,
523                                       int discard)
524 {
525     AviSynthContext *avs = s->priv_data;
526     AVRational fps, samplerate;
527     int samples;
528     int64_t n;
529     const char *error;
530
531     if (avs->curr_sample >= avs->vi->num_audio_samples)
532         return AVERROR_EOF;
533
534     fps.num        = avs->vi->fps_numerator;
535     fps.den        = avs->vi->fps_denominator;
536     samplerate.num = avs->vi->audio_samples_per_second;
537     samplerate.den = 1;
538
539     if (avs_has_video(avs->vi)) {
540         if (avs->curr_frame < avs->vi->num_frames)
541             samples = av_rescale_q(avs->curr_frame, samplerate, fps) -
542                       avs->curr_sample;
543         else
544             samples = av_rescale_q(1, samplerate, fps);
545     } else {
546         samples = 1000;
547     }
548
549     /* After seeking, audio may catch up with video. */
550     if (samples <= 0) {
551         pkt->size = 0;
552         pkt->data = NULL;
553         return 0;
554     }
555
556     if (avs->curr_sample + samples > avs->vi->num_audio_samples)
557         samples = avs->vi->num_audio_samples - avs->curr_sample;
558
559     /* This must happen even if the stream is discarded to prevent desync. */
560     n                 = avs->curr_sample;
561     avs->curr_sample += samples;
562     if (discard)
563         return 0;
564
565     pkt->size = avs_bytes_per_channel_sample(avs->vi) *
566                 samples * avs->vi->nchannels;
567     if (!pkt->size)
568         return AVERROR_UNKNOWN;
569
570     if (av_new_packet(pkt, pkt->size) < 0)
571         return AVERROR(ENOMEM);
572
573     pkt->pts      = n;
574     pkt->dts      = n;
575     pkt->duration = samples;
576     pkt->stream_index = avs->curr_stream;
577
578     avs_library.avs_get_audio(avs->clip, pkt->data, n, samples);
579     error = avs_library.avs_clip_get_error(avs->clip);
580     if (error) {
581         av_log(s, AV_LOG_ERROR, "%s\n", error);
582         avs->error = 1;
583         av_packet_unref(pkt);
584         return AVERROR_UNKNOWN;
585     }
586     return 0;
587 }
588
589 static av_cold int avisynth_read_header(AVFormatContext *s)
590 {
591     int ret;
592
593     // Calling library must implement a lock for thread-safe opens.
594     if (ret = avpriv_lock_avformat())
595         return ret;
596
597     if (ret = avisynth_open_file(s)) {
598         avpriv_unlock_avformat();
599         return ret;
600     }
601
602     avpriv_unlock_avformat();
603     return 0;
604 }
605
606 static int avisynth_read_packet(AVFormatContext *s, AVPacket *pkt)
607 {
608     AviSynthContext *avs = s->priv_data;
609     AVStream *st;
610     int discard = 0;
611     int ret;
612
613     if (avs->error)
614         return AVERROR_UNKNOWN;
615
616     /* If either stream reaches EOF, try to read the other one before
617      * giving up. */
618     avisynth_next_stream(s, &st, pkt, &discard);
619     if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
620         ret = avisynth_read_packet_video(s, pkt, discard);
621         if (ret == AVERROR_EOF && avs_has_audio(avs->vi)) {
622             avisynth_next_stream(s, &st, pkt, &discard);
623             return avisynth_read_packet_audio(s, pkt, discard);
624         }
625     } else {
626         ret = avisynth_read_packet_audio(s, pkt, discard);
627         if (ret == AVERROR_EOF && avs_has_video(avs->vi)) {
628             avisynth_next_stream(s, &st, pkt, &discard);
629             return avisynth_read_packet_video(s, pkt, discard);
630         }
631     }
632
633     return ret;
634 }
635
636 static av_cold int avisynth_read_close(AVFormatContext *s)
637 {
638     if (avpriv_lock_avformat())
639         return AVERROR_UNKNOWN;
640
641     avisynth_context_destroy(s->priv_data);
642     avpriv_unlock_avformat();
643     return 0;
644 }
645
646 static int avisynth_read_seek(AVFormatContext *s, int stream_index,
647                               int64_t timestamp, int flags)
648 {
649     AviSynthContext *avs = s->priv_data;
650     AVStream *st;
651     AVRational fps, samplerate;
652
653     if (avs->error)
654         return AVERROR_UNKNOWN;
655
656     fps        = (AVRational) { avs->vi->fps_numerator,
657                                 avs->vi->fps_denominator };
658     samplerate = (AVRational) { avs->vi->audio_samples_per_second, 1 };
659
660     st = s->streams[stream_index];
661     if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
662         /* AviSynth frame counts are signed int. */
663         if ((timestamp >= avs->vi->num_frames) ||
664             (timestamp > INT_MAX)              ||
665             (timestamp < 0))
666             return AVERROR_EOF;
667         avs->curr_frame = timestamp;
668         if (avs_has_audio(avs->vi))
669             avs->curr_sample = av_rescale_q(timestamp, samplerate, fps);
670     } else {
671         if ((timestamp >= avs->vi->num_audio_samples) || (timestamp < 0))
672             return AVERROR_EOF;
673         /* Force frame granularity for seeking. */
674         if (avs_has_video(avs->vi)) {
675             avs->curr_frame  = av_rescale_q(timestamp, fps, samplerate);
676             avs->curr_sample = av_rescale_q(avs->curr_frame, samplerate, fps);
677         } else {
678             avs->curr_sample = timestamp;
679         }
680     }
681
682     return 0;
683 }
684
685 AVInputFormat ff_avisynth_demuxer = {
686     .name           = "avisynth",
687     .long_name      = NULL_IF_CONFIG_SMALL("AviSynth script"),
688     .priv_data_size = sizeof(AviSynthContext),
689     .read_header    = avisynth_read_header,
690     .read_packet    = avisynth_read_packet,
691     .read_close     = avisynth_read_close,
692     .read_seek      = avisynth_read_seek,
693     .extensions     = "avs",
694 };