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
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 FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM
74
86 { NULL },
87 };
88
91
93 {
94 int i,
ret, already = 0, stream_id = -1;
95 char type_char[2],
dummy;
98
99 ret = sscanf(spec, "d%1[av]%d%c", type_char, &stream_id, &dummy);
100 if (ret >= 1 && ret <= 2) {
103 if (ret < 0) {
106 return NULL;
107 }
109 }
112 if (ret < 0) {
114 "Invalid stream specifier \"%s\"\n", spec);
115 return NULL;
116 }
117 if (!ret)
118 continue;
120 already++;
121 continue;
122 }
123 if (found) {
125 "Ambiguous stream specifier \"%s\", using #%d\n", spec, i);
126 break;
127 }
129 }
130 if (!found) {
132 already ? "matched only already used streams" :
133 "did not match any stream");
134 return NULL;
135 }
139 "currently unsupported by libavfilter\n", spec,
141 return NULL;
142 }
143 return found;
144 }
145
147 {
150
152 if (!codec) {
155 }
156
158
162 }
163
164 return 0;
165 }
166
168 {
172
173 if (!chl) {
175 "Channel layout is not set in stream %d, and could not "
176 "be guessed from the number of channels (%d)\n",
179 }
180
183 "Channel layout is not set in output stream %d, "
184 "guessed channel layout is '%s'\n",
185 st_index, buf);
187 return 0;
188 }
189
191 {
194 int64_t timestamp;
195 int nb_streams,
ret, i;
196 char default_streams[16], *stream_specs, *spec, *cursor;
199
203 }
204
206
208 if (!stream_specs) {
209 snprintf(default_streams,
sizeof(default_streams),
"d%c%d",
210 !strcmp(ctx->
filter->
name,
"amovie") ?
'a' :
'v',
212 stream_specs = default_streams;
213 }
214 for (cursor = stream_specs, nb_streams = 1; *cursor; cursor++)
215 if (*cursor == '+')
216 nb_streams++;
217
218 if (movie->
loop_count != 1 && nb_streams != 1) {
220 "Loop with several streams is currently unsupported\n");
222 }
223
225
226 // Try to find the movie format (container)
228
232 "Failed to avformat_open_input '%s'\n", movie->
file_name);
234 }
237
238 // if seeking requested, we execute it
241 // add the stream start time, should it exist
245 "%s: seek value overflow with start_time:%"PRId64" seek_point:%"PRId64"\n",
248 }
250 }
255 }
256 }
257
260
264
265 for (i = 0; i < nb_streams; i++) {
266 spec =
av_strtok(stream_specs,
"+", &cursor);
267 if (!spec)
269 stream_specs = NULL; /* for next strtok */
271 if (!st)
274 movie->
st[i].
st = st;
276 }
279
286 for (i = 0; i < nb_streams; i++)
288
289 for (i = 0; i < nb_streams; i++) {
291 snprintf(name,
sizeof(name),
"out%d", i);
298 if (ret < 0)
303 if (ret < 0)
305 }
306 }
307
308 av_log(ctx,
AV_LOG_VERBOSE,
"seek_point:%"PRIi64
" format_name:%s file_name:%s stream_index:%d\n",
311
312 return 0;
313 }
314
316 {
318 int i;
319
324 }
330 }
331
333 {
335 int list[] = { 0, -1 };
336 int64_t list64[] = { 0, -1 };
337 int i;
338
343
348 break;
357 break;
358 }
359 }
360
361 return 0;
362 }
363
365 {
371
373
379 break;
381 break;
382 }
383
384 return 0;
385 }
386
390 {
391 switch (frame->
type) {
394 "video pts:%s time:%s size:%dx%d aspect:%d/%d",
399 break;
402 "audio pts:%s time:%s samples:%d",
405 break;
406 default:
408 break;
409 }
410 return dst;
411 }
412
413 #define describe_frameref(f, link) \
414 describe_frame_to_str((char[1024]){0}, 1024, f, link)
415
417 {
421
425 if (ret < 0) {
429 }
430
434 }
436 return 0;
437 }
438
439 /**
440 * Try to push a frame to the requested output.
441 *
442 * @param ctx filter context
443 * @param out_id number of output where a frame is wanted;
444 * if the frame is read from file, used to set the return value;
445 * if the codec is being flushed, flush the corresponding stream
446 * @return 1 if a frame was pushed on the requested output,
447 * 0 if another attempt is possible,
448 * <0 AVERROR code
449 */
451 {
455 int ret, got_frame = 0, pkt_out_id;
457
460 if (movie->
st[out_id].
done) {
463 if (ret < 0)
467 return 0; /* retry */
468 }
470 }
472 /* packet is already ready for flushing */
473 } else {
475 if (ret < 0) {
480 return 0; /* start flushing */
481 }
483 }
485 }
486 }
487
490 if (pkt_out_id < 0) {
492 pkt->
size = 0;
/* ready for next run */
494 return 0;
495 }
496 st = &movie->
st[pkt_out_id];
497 outlink = ctx->
outputs[pkt_out_id];
498
502
506 break;
509 break;
510 default:
512 break;
513 }
514 if (ret < 0) {
520 return 0;
521 }
524
527 if (pkt->
size <= 0) {
529 pkt->
size = 0;
/* ready for next run */
531 }
532 if (!got_frame) {
533 if (!ret)
536 return 0;
537 }
538
541
545
546 if (ret < 0)
548 return pkt_out_id == out_id;
549 }
550
552 {
556
557 while (1) {
559 if (ret)
560 return FFMIN(ret, 0);
561 }
562 }
563
564 #if CONFIG_MOVIE_FILTER
565
567
572 .priv_class = &movie_class,
576
580 };
581
582 #endif /* CONFIG_MOVIE_FILTER */
583
584 #if CONFIG_AMOVIE_FILTER
585
586 #define amovie_options movie_options
588
596
599 .priv_class = &amovie_class,
601 };
602
603 #endif /* CONFIG_AMOVIE_FILTER */