annotate ffmpeg/libavformat/avisynth.c @ 13:844d341cf643 tip

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