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