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 /* #define DEBUG */
31
32 #include <float.h>
45
50
52 /* common A/V fields */
58 char *
stream_specs;
/**< user-provided list of streams, separated by + */
61
66
69 int *
out_index;
/**< stream number -> output number map, or -1 */
71
72 #define OFFSET(x) offsetof(MovieContext, x)
73 #define F AV_OPT_FLAG_FILTERING_PARAM
74
82 {
"seek_point",
"set seekpoint (seconds)",
OFFSET(seek_point_d),
AV_OPT_TYPE_DOUBLE, {.dbl = 0}, 0, (INT64_MAX-1) / 1000000,
F },
86 };
87
90
92 {
93 int i, ret, already = 0, stream_id = -1;
94 char type_char[2],
dummy;
97
98 ret = sscanf(spec, "d%1[av]%d%c", type_char, &stream_id, &dummy);
99 if (ret >= 1 && ret <= 2) {
102 if (ret < 0) {
106 }
108 }
111 if (ret < 0) {
113 "Invalid stream specifier \"%s\"\n", spec);
115 }
116 if (!ret)
117 continue;
119 already++;
120 continue;
121 }
122 if (found) {
124 "Ambiguous stream specifier \"%s\", using #%d\n", spec, i);
125 break;
126 }
128 }
129 if (!found) {
131 already ? "matched only already used streams" :
132 "did not match any stream");
134 }
138 "currently unsupported by libavfilter\n", spec,
141 }
142 return found;
143 }
144
146 {
148 int ret;
149
151 if (!codec) {
154 }
155
158 return ret;
159 }
160
161 return 0;
162 }
163
165 {
167 char buf[256];
169
170 if (!chl) {
172 "Channel layout is not set in stream %d, and could not "
173 "be guessed from the number of channels (%d)\n",
176 }
177
180 "Channel layout is not set in output stream %d, "
181 "guessed channel layout is '%s'\n",
182 st_index, buf);
184 return 0;
185 }
186
188 {
191 int64_t timestamp;
192 int nb_streams, ret, i;
193 char default_streams[16], *stream_specs, *spec, *cursor;
196
197 movie->
class =
class;
199
200 if (args) {
204 }
208 }
209
211 return ret;
212
214
216 if (!stream_specs) {
217 snprintf(default_streams,
sizeof(default_streams),
"d%c%d",
218 !strcmp(ctx->
filter->
name,
"amovie") ?
'a' :
'v',
220 stream_specs = default_streams;
221 }
222 for (cursor = stream_specs, nb_streams = 1; *cursor; cursor++)
223 if (*cursor == '+')
224 nb_streams++;
225
226 if (movie->
loop_count != 1 && nb_streams != 1) {
228 "Loop with several streams is currently unsupported\n");
230 }
231
233
234 // Try to find the movie format (container)
236
240 "Failed to avformat_open_input '%s'\n", movie->
file_name);
241 return ret;
242 }
245
246 // if seeking requested, we execute it
249 // add the stream start time, should it exist
253 "%s: seek value overflow with start_time:%"PRId64" seek_point:%"PRId64"\n",
256 }
258 }
262 return ret;
263 }
264 }
265
268
272
273 for (i = 0; i < nb_streams; i++) {
274 spec =
av_strtok(stream_specs,
"+", &cursor);
275 if (!spec)
277 stream_specs =
NULL;
/* for next strtok */
279 if (!st)
282 movie->
st[i].
st = st;
284 }
287
294 for (i = 0; i < nb_streams; i++)
296
297 for (i = 0; i < nb_streams; i++) {
299 snprintf(name,
sizeof(name),
"out%d", i);
306 if (ret < 0)
307 return ret;
311 if (ret < 0)
312 return ret;
313 }
314 }
315
319 }
320
321 av_log(ctx,
AV_LOG_VERBOSE,
"seek_point:%"PRIi64
" format_name:%s file_name:%s stream_index:%d\n",
324
325 return 0;
326 }
327
329 {
331 int i;
332
337 }
345 }
346
348 {
350 int list[] = { 0, -1 };
351 int64_t list64[] = { 0, -1 };
352 int i;
353
358
363 break;
372 break;
373 }
374 }
375
376 return 0;
377 }
378
380 {
386
388
394 break;
396 break;
397 }
398
399 return 0;
400 }
401
404 {
406
411 if (!buf)
415 if (!copy)
417 buf->
buf->
data[0] =
NULL;
/* it belongs to the frame */
420 }
421
425 {
429 "video pts:%s time:%s pos:%"PRId64" size:%dx%d aspect:%d/%d",
434 break;
437 "audio pts:%s time:%s pos:%"PRId64" samples:%d",
440 break;
441 default:
443 break;
444 }
446 }
447
448 #define describe_bufref(buf, link) \
449 describe_bufref_to_str((char[1024]){0}, 1024, buf, link)
450
452 {
455 int ret, i;
456
460 if (ret < 0) {
463 return ret;
464 }
465
469 }
471 return 0;
472 }
473
474 /**
475 * Try to push a frame to the requested output.
476 *
477 * @param ctx filter context
478 * @param out_id number of output where a frame is wanted;
479 * if the frame is read from file, used to set the return value;
480 * if the codec is being flushed, flush the corresponding stream
481 * @return 1 if a frame was pushed on the requested output,
482 * 0 if another attempt is possible,
483 * <0 AVERROR code
484 */
486 {
490 int ret, got_frame = 0, pkt_out_id;
493
496 if (movie->
st[out_id].
done) {
499 if (ret < 0)
500 return ret;
503 return 0; /* retry */
504 }
506 }
508 /* packet is already ready for flushing */
509 } else {
511 if (ret < 0) {
516 return 0; /* start flushing */
517 }
518 return ret;
519 }
521 }
522 }
523
526 if (pkt_out_id < 0) {
528 pkt->
size = 0;
/* ready for next run */
530 return 0;
531 }
532 st = &movie->
st[pkt_out_id];
533 outlink = ctx->
outputs[pkt_out_id];
534
538 break;
541 break;
542 default:
544 break;
545 }
546 if (ret < 0) {
548 return 0;
549 }
550 if (!ret)
552
555 if (pkt->
size <= 0) {
557 pkt->
size = 0;
/* ready for next run */
559 }
560 if (!got_frame) {
561 if (!ret)
563 return 0;
564 }
565
567 if (!buf)
575 /* Fall through */
578 break;
579 }
580
581 return pkt_out_id == out_id;
582 }
583
585 {
588 int ret;
589
590 while (1) {
592 if (ret)
593 return FFMIN(ret, 0);
594 }
595 }
596
597 #if CONFIG_MOVIE_FILTER
598
600
602 {
604 }
605
613
616 .priv_class = &movie_class,
617 };
618
619 #endif /* CONFIG_MOVIE_FILTER */
620
621 #if CONFIG_AMOVIE_FILTER
622
623 #define amovie_options movie_options
625
627 {
629 }
630
638
641 .priv_class = &amovie_class,
642 };
643
644 #endif /* CONFIG_AMOVIE_FILTER */