GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavfilter/src_movie.c Lines: 182 331 55.0 %
Date: 2021-01-27 11:56:10 Branches: 89 207 43.0 %

Line Branch Exec Source
1
/*
2
 * Copyright (c) 2010 Stefano Sabatini
3
 * Copyright (c) 2008 Victor Paesa
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg 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
 * FFmpeg 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 FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
/**
23
 * @file
24
 * movie video source
25
 *
26
 * @todo use direct rendering (no allocation of a new frame)
27
 * @todo support a PTS correction mechanism
28
 */
29
30
#include <float.h>
31
#include <stdint.h>
32
33
#include "libavutil/attributes.h"
34
#include "libavutil/avstring.h"
35
#include "libavutil/avassert.h"
36
#include "libavutil/opt.h"
37
#include "libavutil/imgutils.h"
38
#include "libavutil/internal.h"
39
#include "libavutil/timestamp.h"
40
41
#include "libavcodec/avcodec.h"
42
43
#include "libavformat/avformat.h"
44
45
#include "audio.h"
46
#include "avfilter.h"
47
#include "formats.h"
48
#include "internal.h"
49
#include "video.h"
50
51
typedef struct MovieStream {
52
    AVStream *st;
53
    AVCodecContext *codec_ctx;
54
    int64_t discontinuity_threshold;
55
    int64_t last_pts;
56
} MovieStream;
57
58
typedef struct MovieContext {
59
    /* common A/V fields */
60
    const AVClass *class;
61
    int64_t seek_point;   ///< seekpoint in microseconds
62
    double seek_point_d;
63
    char *format_name;
64
    char *file_name;
65
    char *stream_specs; /**< user-provided list of streams, separated by + */
66
    int stream_index; /**< for compatibility */
67
    int loop_count;
68
    int64_t discontinuity_threshold;
69
    int64_t ts_offset;
70
71
    AVFormatContext *format_ctx;
72
73
    int max_stream_index; /**< max stream # actually used for output */
74
    MovieStream *st; /**< array of all streams, one per output */
75
    int *out_index; /**< stream number -> output number map, or -1 */
76
} MovieContext;
77
78
#define OFFSET(x) offsetof(MovieContext, x)
79
#define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM
80
81
static const AVOption movie_options[]= {
82
    { "filename",     NULL,                      OFFSET(file_name),    AV_OPT_TYPE_STRING,                                    .flags = FLAGS },
83
    { "format_name",  "set format name",         OFFSET(format_name),  AV_OPT_TYPE_STRING,                                    .flags = FLAGS },
84
    { "f",            "set format name",         OFFSET(format_name),  AV_OPT_TYPE_STRING,                                    .flags = FLAGS },
85
    { "stream_index", "set stream index",        OFFSET(stream_index), AV_OPT_TYPE_INT,    { .i64 = -1 }, -1, INT_MAX,                 FLAGS  },
86
    { "si",           "set stream index",        OFFSET(stream_index), AV_OPT_TYPE_INT,    { .i64 = -1 }, -1, INT_MAX,                 FLAGS  },
87
    { "seek_point",   "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, { .dbl =  0 },  0, (INT64_MAX-1) / 1000000, FLAGS },
88
    { "sp",           "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, { .dbl =  0 },  0, (INT64_MAX-1) / 1000000, FLAGS },
89
    { "streams",      "set streams",             OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str =  0},  0, 0, FLAGS },
90
    { "s",            "set streams",             OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str =  0},  0, 0, FLAGS },
91
    { "loop",         "set loop count",          OFFSET(loop_count),   AV_OPT_TYPE_INT,    {.i64 =  1},  0,        INT_MAX, FLAGS },
92
    { "discontinuity", "set discontinuity threshold", OFFSET(discontinuity_threshold), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, FLAGS },
93
    { NULL },
94
};
95
96
static int movie_config_output_props(AVFilterLink *outlink);
97
static int movie_request_frame(AVFilterLink *outlink);
98
99
11
static AVStream *find_stream(void *log, AVFormatContext *avf, const char *spec)
100
{
101
11
    int i, ret, already = 0, stream_id = -1;
102
    char type_char[2], dummy;
103
11
    AVStream *found = NULL;
104
    enum AVMediaType type;
105
106
11
    ret = sscanf(spec, "d%1[av]%d%c", type_char, &stream_id, &dummy);
107

11
    if (ret >= 1 && ret <= 2) {
108
11
        type = type_char[0] == 'v' ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
109
11
        ret = av_find_best_stream(avf, type, stream_id, -1, NULL, 0);
110
11
        if (ret < 0) {
111
            av_log(log, AV_LOG_ERROR, "No %s stream with index '%d' found\n",
112
                   av_get_media_type_string(type), stream_id);
113
            return NULL;
114
        }
115
11
        return avf->streams[ret];
116
    }
117
    for (i = 0; i < avf->nb_streams; i++) {
118
        ret = avformat_match_stream_specifier(avf, avf->streams[i], spec);
119
        if (ret < 0) {
120
            av_log(log, AV_LOG_ERROR,
121
                   "Invalid stream specifier \"%s\"\n", spec);
122
            return NULL;
123
        }
124
        if (!ret)
125
            continue;
126
        if (avf->streams[i]->discard != AVDISCARD_ALL) {
127
            already++;
128
            continue;
129
        }
130
        if (found) {
131
            av_log(log, AV_LOG_WARNING,
132
                   "Ambiguous stream specifier \"%s\", using #%d\n", spec, i);
133
            break;
134
        }
135
        found = avf->streams[i];
136
    }
137
    if (!found) {
138
        av_log(log, AV_LOG_WARNING, "Stream specifier \"%s\" %s\n", spec,
139
               already ? "matched only already used streams" :
140
                         "did not match any stream");
141
        return NULL;
142
    }
143
    if (found->codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
144
        found->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) {
145
        av_log(log, AV_LOG_ERROR, "Stream specifier \"%s\" matched a %s stream,"
146
               "currently unsupported by libavfilter\n", spec,
147
               av_get_media_type_string(found->codecpar->codec_type));
148
        return NULL;
149
    }
150
    return found;
151
}
152
153
11
static int open_stream(AVFilterContext *ctx, MovieStream *st)
154
{
155
    const AVCodec *codec;
156
    int ret;
157
158
11
    codec = avcodec_find_decoder(st->st->codecpar->codec_id);
159
11
    if (!codec) {
160
        av_log(ctx, AV_LOG_ERROR, "Failed to find any codec\n");
161
        return AVERROR(EINVAL);
162
    }
163
164
11
    st->codec_ctx = avcodec_alloc_context3(codec);
165
11
    if (!st->codec_ctx)
166
        return AVERROR(ENOMEM);
167
168
11
    ret = avcodec_parameters_to_context(st->codec_ctx, st->st->codecpar);
169
11
    if (ret < 0)
170
        return ret;
171
172
11
    st->codec_ctx->thread_count = ff_filter_get_nb_threads(ctx);
173
174
11
    if ((ret = avcodec_open2(st->codec_ctx, codec, NULL)) < 0) {
175
        av_log(ctx, AV_LOG_ERROR, "Failed to open codec\n");
176
        return ret;
177
    }
178
179
11
    return 0;
180
}
181
182
static int guess_channel_layout(MovieStream *st, int st_index, void *log_ctx)
183
{
184
    AVCodecParameters *dec_par = st->st->codecpar;
185
    char buf[256];
186
    int64_t chl = av_get_default_channel_layout(dec_par->channels);
187
188
    if (!chl) {
189
        av_log(log_ctx, AV_LOG_ERROR,
190
               "Channel layout is not set in stream %d, and could not "
191
               "be guessed from the number of channels (%d)\n",
192
               st_index, dec_par->channels);
193
        return AVERROR(EINVAL);
194
    }
195
196
    av_get_channel_layout_string(buf, sizeof(buf), dec_par->channels, chl);
197
    av_log(log_ctx, AV_LOG_WARNING,
198
           "Channel layout is not set in output stream %d, "
199
           "guessed channel layout is '%s'\n",
200
           st_index, buf);
201
    dec_par->channel_layout = chl;
202
    return 0;
203
}
204
205
11
static av_cold int movie_common_init(AVFilterContext *ctx)
206
{
207
11
    MovieContext *movie = ctx->priv;
208
11
    AVInputFormat *iformat = NULL;
209
    int64_t timestamp;
210
11
    int nb_streams = 1, ret, i;
211
    char default_streams[16], *stream_specs, *spec, *cursor;
212
    AVStream *st;
213
214
11
    if (!movie->file_name) {
215
        av_log(ctx, AV_LOG_ERROR, "No filename provided!\n");
216
        return AVERROR(EINVAL);
217
    }
218
219
11
    movie->seek_point = movie->seek_point_d * 1000000 + 0.5;
220
221
11
    stream_specs = movie->stream_specs;
222
11
    if (!stream_specs) {
223
11
        snprintf(default_streams, sizeof(default_streams), "d%c%d",
224
11
                 !strcmp(ctx->filter->name, "amovie") ? 'a' : 'v',
225
                 movie->stream_index);
226
11
        stream_specs = default_streams;
227
    }
228
55
    for (cursor = stream_specs; *cursor; cursor++)
229
44
        if (*cursor == '+')
230
            nb_streams++;
231
232

11
    if (movie->loop_count != 1 && nb_streams != 1) {
233
        av_log(ctx, AV_LOG_ERROR,
234
               "Loop with several streams is currently unsupported\n");
235
        return AVERROR_PATCHWELCOME;
236
    }
237
238
    // Try to find the movie format (container)
239
11
    iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL;
240
241
11
    movie->format_ctx = NULL;
242
11
    if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, NULL)) < 0) {
243
        av_log(ctx, AV_LOG_ERROR,
244
               "Failed to avformat_open_input '%s'\n", movie->file_name);
245
        return ret;
246
    }
247
11
    if ((ret = avformat_find_stream_info(movie->format_ctx, NULL)) < 0)
248
        av_log(ctx, AV_LOG_WARNING, "Failed to find stream info\n");
249
250
    // if seeking requested, we execute it
251
11
    if (movie->seek_point > 0) {
252
        timestamp = movie->seek_point;
253
        // add the stream start time, should it exist
254
        if (movie->format_ctx->start_time != AV_NOPTS_VALUE) {
255
            if (timestamp > 0 && movie->format_ctx->start_time > INT64_MAX - timestamp) {
256
                av_log(ctx, AV_LOG_ERROR,
257
                       "%s: seek value overflow with start_time:%"PRId64" seek_point:%"PRId64"\n",
258
                       movie->file_name, movie->format_ctx->start_time, movie->seek_point);
259
                return AVERROR(EINVAL);
260
            }
261
            timestamp += movie->format_ctx->start_time;
262
        }
263
        if ((ret = av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD)) < 0) {
264
            av_log(ctx, AV_LOG_ERROR, "%s: could not seek to position %"PRId64"\n",
265
                   movie->file_name, timestamp);
266
            return ret;
267
        }
268
    }
269
270
25
    for (i = 0; i < movie->format_ctx->nb_streams; i++)
271
14
        movie->format_ctx->streams[i]->discard = AVDISCARD_ALL;
272
273
11
    movie->st = av_calloc(nb_streams, sizeof(*movie->st));
274
11
    if (!movie->st)
275
        return AVERROR(ENOMEM);
276
277
22
    for (i = 0; i < nb_streams; i++) {
278
11
        spec = av_strtok(stream_specs, "+", &cursor);
279
11
        if (!spec)
280
            return AVERROR_BUG;
281
11
        stream_specs = NULL; /* for next strtok */
282
11
        st = find_stream(ctx, movie->format_ctx, spec);
283
11
        if (!st)
284
            return AVERROR(EINVAL);
285
11
        st->discard = AVDISCARD_DEFAULT;
286
11
        movie->st[i].st = st;
287
11
        movie->max_stream_index = FFMAX(movie->max_stream_index, st->index);
288
11
        movie->st[i].discontinuity_threshold =
289
11
            av_rescale_q(movie->discontinuity_threshold, AV_TIME_BASE_Q, st->time_base);
290
    }
291
11
    if (av_strtok(NULL, "+", &cursor))
292
        return AVERROR_BUG;
293
294
11
    movie->out_index = av_calloc(movie->max_stream_index + 1,
295
                                 sizeof(*movie->out_index));
296
11
    if (!movie->out_index)
297
        return AVERROR(ENOMEM);
298
22
    for (i = 0; i <= movie->max_stream_index; i++)
299
11
        movie->out_index[i] = -1;
300
22
    for (i = 0; i < nb_streams; i++) {
301
11
        AVFilterPad pad = { 0 };
302
11
        movie->out_index[movie->st[i].st->index] = i;
303
11
        pad.type          = movie->st[i].st->codecpar->codec_type;
304
11
        pad.name          = av_asprintf("out%d", i);
305
11
        if (!pad.name)
306
            return AVERROR(ENOMEM);
307
11
        pad.config_props  = movie_config_output_props;
308
11
        pad.request_frame = movie_request_frame;
309
11
        if ((ret = ff_insert_outpad(ctx, i, &pad)) < 0) {
310
            av_freep(&pad.name);
311
            return ret;
312
        }
313
11
        if ( movie->st[i].st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
314
3
            !movie->st[i].st->codecpar->channel_layout) {
315
            ret = guess_channel_layout(&movie->st[i], i, ctx);
316
            if (ret < 0)
317
                return ret;
318
        }
319
11
        ret = open_stream(ctx, &movie->st[i]);
320
11
        if (ret < 0)
321
            return ret;
322
    }
323
324
11
    av_log(ctx, AV_LOG_VERBOSE, "seek_point:%"PRIi64" format_name:%s file_name:%s stream_index:%d\n",
325
           movie->seek_point, movie->format_name, movie->file_name,
326
           movie->stream_index);
327
328
11
    return 0;
329
}
330
331
11
static av_cold void movie_uninit(AVFilterContext *ctx)
332
{
333
11
    MovieContext *movie = ctx->priv;
334
    int i;
335
336
22
    for (i = 0; i < ctx->nb_outputs; i++) {
337
11
        av_freep(&ctx->output_pads[i].name);
338
11
        if (movie->st[i].st)
339
11
            avcodec_free_context(&movie->st[i].codec_ctx);
340
    }
341
11
    av_freep(&movie->st);
342
11
    av_freep(&movie->out_index);
343
11
    if (movie->format_ctx)
344
11
        avformat_close_input(&movie->format_ctx);
345
11
}
346
347
11
static int movie_query_formats(AVFilterContext *ctx)
348
{
349
11
    MovieContext *movie = ctx->priv;
350
11
    int list[] = { 0, -1 };
351
11
    int64_t list64[] = { 0, -1 };
352
    int i, ret;
353
354
22
    for (i = 0; i < ctx->nb_outputs; i++) {
355
11
        MovieStream *st = &movie->st[i];
356
11
        AVCodecParameters *c = st->st->codecpar;
357
11
        AVFilterLink *outlink = ctx->outputs[i];
358
359
11
        switch (c->codec_type) {
360
8
        case AVMEDIA_TYPE_VIDEO:
361
8
            list[0] = c->format;
362
8
            if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->incfg.formats)) < 0)
363
                return ret;
364
8
            break;
365
3
        case AVMEDIA_TYPE_AUDIO:
366
3
            list[0] = c->format;
367
3
            if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->incfg.formats)) < 0)
368
                return ret;
369
3
            list[0] = c->sample_rate;
370
3
            if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->incfg.samplerates)) < 0)
371
                return ret;
372
3
            list64[0] = c->channel_layout;
373
3
            if ((ret = ff_channel_layouts_ref(ff_make_format64_list(list64),
374
                                   &outlink->incfg.channel_layouts)) < 0)
375
                return ret;
376
3
            break;
377
        }
378
11
    }
379
380
11
    return 0;
381
}
382
383
11
static int movie_config_output_props(AVFilterLink *outlink)
384
{
385
11
    AVFilterContext *ctx = outlink->src;
386
11
    MovieContext *movie  = ctx->priv;
387
11
    unsigned out_id = FF_OUTLINK_IDX(outlink);
388
11
    MovieStream *st = &movie->st[out_id];
389
11
    AVCodecParameters *c = st->st->codecpar;
390
391
11
    outlink->time_base = st->st->time_base;
392
393
11
    switch (c->codec_type) {
394
8
    case AVMEDIA_TYPE_VIDEO:
395
8
        outlink->w          = c->width;
396
8
        outlink->h          = c->height;
397
8
        outlink->frame_rate = st->st->r_frame_rate;
398
8
        break;
399
3
    case AVMEDIA_TYPE_AUDIO:
400
3
        break;
401
    }
402
403
11
    return 0;
404
}
405
406
static char *describe_frame_to_str(char *dst, size_t dst_size,
407
                                   AVFrame *frame, enum AVMediaType frame_type,
408
                                   AVFilterLink *link)
409
{
410
    switch (frame_type) {
411
    case AVMEDIA_TYPE_VIDEO:
412
        snprintf(dst, dst_size,
413
                 "video pts:%s time:%s size:%dx%d aspect:%d/%d",
414
                 av_ts2str(frame->pts), av_ts2timestr(frame->pts, &link->time_base),
415
                 frame->width, frame->height,
416
                 frame->sample_aspect_ratio.num,
417
                 frame->sample_aspect_ratio.den);
418
                 break;
419
    case AVMEDIA_TYPE_AUDIO:
420
        snprintf(dst, dst_size,
421
                 "audio pts:%s time:%s samples:%d",
422
                 av_ts2str(frame->pts), av_ts2timestr(frame->pts, &link->time_base),
423
                 frame->nb_samples);
424
                 break;
425
    default:
426
        snprintf(dst, dst_size, "%s BUG", av_get_media_type_string(frame_type));
427
        break;
428
    }
429
    return dst;
430
}
431
432
static int rewind_file(AVFilterContext *ctx)
433
{
434
    MovieContext *movie = ctx->priv;
435
    int64_t timestamp = movie->seek_point;
436
    int ret, i;
437
438
    if (movie->format_ctx->start_time != AV_NOPTS_VALUE)
439
        timestamp += movie->format_ctx->start_time;
440
    ret = av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD);
441
    if (ret < 0) {
442
        av_log(ctx, AV_LOG_ERROR, "Unable to loop: %s\n", av_err2str(ret));
443
        movie->loop_count = 1; /* do not try again */
444
        return ret;
445
    }
446
447
    for (i = 0; i < ctx->nb_outputs; i++) {
448
        avcodec_flush_buffers(movie->st[i].codec_ctx);
449
    }
450
    return 0;
451
}
452
453
3683
static int movie_decode_packet(AVFilterContext *ctx)
454
{
455
3683
    MovieContext *movie = ctx->priv;
456
3683
    AVPacket pkt = { 0 };
457
    int pkt_out_id, ret;
458
459
    /* read a new packet from input stream */
460
3683
    ret = av_read_frame(movie->format_ctx, &pkt);
461
3683
    if (ret == AVERROR_EOF) {
462
        /* EOF -> set all decoders for flushing */
463
22
        for (int i = 0; i < ctx->nb_outputs; i++) {
464
11
            ret = avcodec_send_packet(movie->st[i].codec_ctx, NULL);
465

11
            if (ret < 0 && ret != AVERROR_EOF)
466
                return ret;
467
        }
468
469
11
        return 0;
470
3672
    } else if (ret < 0)
471
        return ret;
472
473
    /* send the packet to its decoder, if any */
474
3672
    pkt_out_id = pkt.stream_index > movie->max_stream_index ? -1 :
475
3451
                 movie->out_index[pkt.stream_index];
476
3672
    if (pkt_out_id >= 0)
477
3451
        ret = avcodec_send_packet(movie->st[pkt_out_id].codec_ctx, &pkt);
478
3672
    av_packet_unref(&pkt);
479
480
3672
    return ret;
481
}
482
483
/**
484
 * Try to push a frame to the requested output.
485
 *
486
 * @param ctx     filter context
487
 * @param out_id  number of output where a frame is wanted;
488
 * @return  0 if a frame was pushed on the requested output,
489
 *         AVERROR(EAGAIN) if the decoder requires more input
490
 *         AVERROR(EOF) if the decoder has been completely flushed
491
 *         <0 AVERROR code
492
 */
493
7139
static int movie_push_frame(AVFilterContext *ctx, unsigned out_id)
494
{
495
7139
    MovieContext   *movie = ctx->priv;
496
7139
    MovieStream       *st = &movie->st[out_id];
497
7139
    AVFilterLink *outlink = ctx->outputs[out_id];
498
    AVFrame *frame;
499
    int ret;
500
501
7139
    frame = av_frame_alloc();
502
7139
    if (!frame)
503
        return AVERROR(ENOMEM);
504
505
7139
    ret = avcodec_receive_frame(st->codec_ctx, frame);
506
7139
    if (ret < 0) {
507

3694
        if (ret != AVERROR_EOF && ret != AVERROR(EAGAIN))
508
            av_log(ctx, AV_LOG_WARNING, "Decode error: %s\n", av_err2str(ret));
509
510
3694
        av_frame_free(&frame);
511
3694
        return ret;
512
    }
513
514
3445
    frame->pts = frame->best_effort_timestamp;
515
3445
    if (frame->pts != AV_NOPTS_VALUE) {
516
3443
        if (movie->ts_offset)
517
            frame->pts += av_rescale_q_rnd(movie->ts_offset, AV_TIME_BASE_Q, outlink->time_base, AV_ROUND_UP);
518
3443
        if (st->discontinuity_threshold) {
519
            if (st->last_pts != AV_NOPTS_VALUE) {
520
                int64_t diff = frame->pts - st->last_pts;
521
                if (diff < 0 || diff > st->discontinuity_threshold) {
522
                    av_log(ctx, AV_LOG_VERBOSE, "Discontinuity in stream:%d diff:%"PRId64"\n", out_id, diff);
523
                    movie->ts_offset += av_rescale_q_rnd(-diff, outlink->time_base, AV_TIME_BASE_Q, AV_ROUND_UP);
524
                    frame->pts -= diff;
525
                }
526
            }
527
        }
528
3443
        st->last_pts = frame->pts;
529
    }
530
    ff_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name,
531
            describe_frame_to_str((char[1024]){0}, 1024, frame,
532
                                  st->st->codecpar->codec_type, outlink));
533
534
3445
    if (st->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
535
3130
        if (frame->format != outlink->format) {
536
            av_log(ctx, AV_LOG_ERROR, "Format changed %s -> %s, discarding frame\n",
537
                av_get_pix_fmt_name(outlink->format),
538
                av_get_pix_fmt_name(frame->format)
539
                );
540
            av_frame_free(&frame);
541
            return 0;
542
        }
543
    }
544
3445
    ret = ff_filter_frame(outlink, frame);
545
546
3445
    if (ret < 0)
547
        return ret;
548
3445
    return 0;
549
}
550
551
3456
static int movie_request_frame(AVFilterLink *outlink)
552
{
553
3456
    AVFilterContext *ctx = outlink->src;
554
3456
    MovieContext  *movie = ctx->priv;
555
3456
    unsigned out_id = FF_OUTLINK_IDX(outlink);
556
557
3683
    while (1) {
558
7139
        int got_eagain = 0, got_eof = 0;
559
7139
        int ret = 0;
560
561
        /* check all decoders for available output */
562
10833
        for (int i = 0; i < ctx->nb_outputs; i++) {
563
7139
            ret = movie_push_frame(ctx, i);
564
7139
            if (ret == AVERROR(EAGAIN))
565
3683
                got_eagain++;
566
3456
            else if (ret == AVERROR_EOF)
567
11
                got_eof++;
568
3445
            else if (ret < 0)
569
                return ret;
570
3445
            else if (i == out_id)
571
3445
                return 0;
572
        }
573
574
3694
        if (got_eagain) {
575
            /* all decoders require more input -> read a new packet */
576
3683
            ret = movie_decode_packet(ctx);
577
3683
            if (ret < 0)
578
                return ret;
579
11
        } else if (got_eof) {
580
            /* all decoders flushed */
581
11
            if (movie->loop_count != 1) {
582
                ret = rewind_file(ctx);
583
                if (ret < 0)
584
                    return ret;
585
                movie->loop_count -= movie->loop_count > 1;
586
                av_log(ctx, AV_LOG_VERBOSE, "Stream finished, looping.\n");
587
                continue;
588
            }
589
11
            return AVERROR_EOF;
590
        }
591
    }
592
}
593
594
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
595
                           char *res, int res_len, int flags)
596
{
597
    MovieContext *movie = ctx->priv;
598
    int ret = AVERROR(ENOSYS);
599
600
    if (!strcmp(cmd, "seek")) {
601
        int idx, flags, i;
602
        int64_t ts;
603
        char tail[2];
604
605
        if (sscanf(args, "%i|%"SCNi64"|%i %1s", &idx, &ts, &flags, tail) != 3)
606
            return AVERROR(EINVAL);
607
608
        ret = av_seek_frame(movie->format_ctx, idx, ts, flags);
609
        if (ret < 0)
610
            return ret;
611
612
        for (i = 0; i < ctx->nb_outputs; i++) {
613
            avcodec_flush_buffers(movie->st[i].codec_ctx);
614
        }
615
        return ret;
616
    } else if (!strcmp(cmd, "get_duration")) {
617
        int print_len;
618
        char tail[2];
619
620
        if (!res || res_len <= 0)
621
            return AVERROR(EINVAL);
622
623
        if (args && sscanf(args, "%1s", tail) == 1)
624
            return AVERROR(EINVAL);
625
626
        print_len = snprintf(res, res_len, "%"PRId64, movie->format_ctx->duration);
627
        if (print_len < 0 || print_len >= res_len)
628
            return AVERROR(EINVAL);
629
630
        return 0;
631
    }
632
633
    return ret;
634
}
635
636
#if CONFIG_MOVIE_FILTER
637
638
AVFILTER_DEFINE_CLASS(movie);
639
640
AVFilter ff_avsrc_movie = {
641
    .name          = "movie",
642
    .description   = NULL_IF_CONFIG_SMALL("Read from a movie source."),
643
    .priv_size     = sizeof(MovieContext),
644
    .priv_class    = &movie_class,
645
    .init          = movie_common_init,
646
    .uninit        = movie_uninit,
647
    .query_formats = movie_query_formats,
648
649
    .inputs    = NULL,
650
    .outputs   = NULL,
651
    .flags     = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
652
    .process_command = process_command
653
};
654
655
#endif  /* CONFIG_MOVIE_FILTER */
656
657
#if CONFIG_AMOVIE_FILTER
658
659
#define amovie_options movie_options
660
AVFILTER_DEFINE_CLASS(amovie);
661
662
AVFilter ff_avsrc_amovie = {
663
    .name          = "amovie",
664
    .description   = NULL_IF_CONFIG_SMALL("Read audio from a movie source."),
665
    .priv_size     = sizeof(MovieContext),
666
    .init          = movie_common_init,
667
    .uninit        = movie_uninit,
668
    .query_formats = movie_query_formats,
669
670
    .inputs     = NULL,
671
    .outputs    = NULL,
672
    .priv_class = &amovie_class,
673
    .flags      = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
674
    .process_command = process_command,
675
};
676
677
#endif /* CONFIG_AMOVIE_FILTER */