00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030
00031
00032 #include <float.h>
00033 #include "libavutil/avstring.h"
00034 #include "libavutil/avassert.h"
00035 #include "libavutil/opt.h"
00036 #include "libavutil/imgutils.h"
00037 #include "libavutil/timestamp.h"
00038 #include "libavformat/avformat.h"
00039 #include "audio.h"
00040 #include "avcodec.h"
00041 #include "avfilter.h"
00042 #include "formats.h"
00043 #include "internal.h"
00044 #include "video.h"
00045
00046 typedef struct {
00047 AVStream *st;
00048 int done;
00049 } MovieStream;
00050
00051 typedef struct {
00052
00053 const AVClass *class;
00054 int64_t seek_point;
00055 double seek_point_d;
00056 char *format_name;
00057 char *file_name;
00058 char *stream_specs;
00059 int stream_index;
00060 int loop_count;
00061
00062 AVFormatContext *format_ctx;
00063 int eof;
00064 AVPacket pkt, pkt0;
00065 AVFrame *frame;
00066
00067 int max_stream_index;
00068 MovieStream *st;
00069 int *out_index;
00070 } MovieContext;
00071
00072 #define OFFSET(x) offsetof(MovieContext, x)
00073 #define F AV_OPT_FLAG_FILTERING_PARAM
00074
00075 static const AVOption movie_options[]= {
00076 {"format_name", "set format name", OFFSET(format_name), AV_OPT_TYPE_STRING, {.str = 0}, CHAR_MIN, CHAR_MAX, F },
00077 {"f", "set format name", OFFSET(format_name), AV_OPT_TYPE_STRING, {.str = 0}, CHAR_MIN, CHAR_MAX, F },
00078 {"streams", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, CHAR_MAX, CHAR_MAX, F },
00079 {"s", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, CHAR_MAX, CHAR_MAX, F },
00080 {"si", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, F },
00081 {"stream_index", "set stream index", OFFSET(stream_index), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, F },
00082 {"seek_point", "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, 0, (INT64_MAX-1) / 1000000, F },
00083 {"sp", "set seekpoint (seconds)", OFFSET(seek_point_d), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, 0, (INT64_MAX-1) / 1000000, F },
00084 {"loop", "set loop count", OFFSET(loop_count), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, F },
00085 {NULL},
00086 };
00087
00088 static int movie_config_output_props(AVFilterLink *outlink);
00089 static int movie_request_frame(AVFilterLink *outlink);
00090
00091 static AVStream *find_stream(void *log, AVFormatContext *avf, const char *spec)
00092 {
00093 int i, ret, already = 0, stream_id = -1;
00094 char type_char, dummy;
00095 AVStream *found = NULL;
00096 enum AVMediaType type;
00097
00098 ret = sscanf(spec, "d%[av]%d%c", &type_char, &stream_id, &dummy);
00099 if (ret >= 1 && ret <= 2) {
00100 type = type_char == 'v' ? AVMEDIA_TYPE_VIDEO : AVMEDIA_TYPE_AUDIO;
00101 ret = av_find_best_stream(avf, type, stream_id, -1, NULL, 0);
00102 if (ret < 0) {
00103 av_log(log, AV_LOG_ERROR, "No %s stream with index '%d' found\n",
00104 av_get_media_type_string(type), stream_id);
00105 return NULL;
00106 }
00107 return avf->streams[ret];
00108 }
00109 for (i = 0; i < avf->nb_streams; i++) {
00110 ret = avformat_match_stream_specifier(avf, avf->streams[i], spec);
00111 if (ret < 0) {
00112 av_log(log, AV_LOG_ERROR,
00113 "Invalid stream specifier \"%s\"\n", spec);
00114 return NULL;
00115 }
00116 if (!ret)
00117 continue;
00118 if (avf->streams[i]->discard != AVDISCARD_ALL) {
00119 already++;
00120 continue;
00121 }
00122 if (found) {
00123 av_log(log, AV_LOG_WARNING,
00124 "Ambiguous stream specifier \"%s\", using #%d\n", spec, i);
00125 break;
00126 }
00127 found = avf->streams[i];
00128 }
00129 if (!found) {
00130 av_log(log, AV_LOG_WARNING, "Stream specifier \"%s\" %s\n", spec,
00131 already ? "matched only already used streams" :
00132 "did not match any stream");
00133 return NULL;
00134 }
00135 if (found->codec->codec_type != AVMEDIA_TYPE_VIDEO &&
00136 found->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
00137 av_log(log, AV_LOG_ERROR, "Stream specifier \"%s\" matched a %s stream,"
00138 "currently unsupported by libavfilter\n", spec,
00139 av_get_media_type_string(found->codec->codec_type));
00140 return NULL;
00141 }
00142 return found;
00143 }
00144
00145 static int open_stream(void *log, MovieStream *st)
00146 {
00147 AVCodec *codec;
00148 int ret;
00149
00150 codec = avcodec_find_decoder(st->st->codec->codec_id);
00151 if (!codec) {
00152 av_log(log, AV_LOG_ERROR, "Failed to find any codec\n");
00153 return AVERROR(EINVAL);
00154 }
00155
00156 if ((ret = avcodec_open2(st->st->codec, codec, NULL)) < 0) {
00157 av_log(log, AV_LOG_ERROR, "Failed to open codec\n");
00158 return ret;
00159 }
00160
00161 return 0;
00162 }
00163
00164 static int guess_channel_layout(MovieStream *st, int st_index, void *log_ctx)
00165 {
00166 AVCodecContext *dec_ctx = st->st->codec;
00167 char buf[256];
00168 int64_t chl = av_get_default_channel_layout(dec_ctx->channels);
00169
00170 if (!chl) {
00171 av_log(log_ctx, AV_LOG_ERROR,
00172 "Channel layout is not set in stream %d, and could not "
00173 "be guessed from the number of channels (%d)\n",
00174 st_index, dec_ctx->channels);
00175 return AVERROR(EINVAL);
00176 }
00177
00178 av_get_channel_layout_string(buf, sizeof(buf), dec_ctx->channels, chl);
00179 av_log(log_ctx, AV_LOG_WARNING,
00180 "Channel layout is not set in output stream %d, "
00181 "guessed channel layout is '%s'\n",
00182 st_index, buf);
00183 dec_ctx->channel_layout = chl;
00184 return 0;
00185 }
00186
00187 static av_cold int movie_common_init(AVFilterContext *ctx, const char *args, const AVClass *class)
00188 {
00189 MovieContext *movie = ctx->priv;
00190 AVInputFormat *iformat = NULL;
00191 int64_t timestamp;
00192 int nb_streams, ret, i;
00193 char default_streams[16], *stream_specs, *spec, *cursor;
00194 char name[16];
00195 AVStream *st;
00196
00197 movie->class = class;
00198 av_opt_set_defaults(movie);
00199
00200 if (args)
00201 movie->file_name = av_get_token(&args, ":");
00202 if (!movie->file_name || !*movie->file_name) {
00203 av_log(ctx, AV_LOG_ERROR, "No filename provided!\n");
00204 return AVERROR(EINVAL);
00205 }
00206
00207 if (*args++ == ':' && (ret = av_set_options_string(movie, args, "=", ":")) < 0)
00208 return ret;
00209
00210 movie->seek_point = movie->seek_point_d * 1000000 + 0.5;
00211
00212 stream_specs = movie->stream_specs;
00213 if (!stream_specs) {
00214 snprintf(default_streams, sizeof(default_streams), "d%c%d",
00215 !strcmp(ctx->filter->name, "amovie") ? 'a' : 'v',
00216 movie->stream_index);
00217 stream_specs = default_streams;
00218 }
00219 for (cursor = stream_specs, nb_streams = 1; *cursor; cursor++)
00220 if (*cursor == '+')
00221 nb_streams++;
00222
00223 if (movie->loop_count != 1 && nb_streams != 1) {
00224 av_log(ctx, AV_LOG_ERROR,
00225 "Loop with several streams is currently unsupported\n");
00226 return AVERROR_PATCHWELCOME;
00227 }
00228
00229 av_register_all();
00230
00231
00232 iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL;
00233
00234 movie->format_ctx = NULL;
00235 if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, NULL)) < 0) {
00236 av_log(ctx, AV_LOG_ERROR,
00237 "Failed to avformat_open_input '%s'\n", movie->file_name);
00238 return ret;
00239 }
00240 if ((ret = avformat_find_stream_info(movie->format_ctx, NULL)) < 0)
00241 av_log(ctx, AV_LOG_WARNING, "Failed to find stream info\n");
00242
00243
00244 if (movie->seek_point > 0) {
00245 timestamp = movie->seek_point;
00246
00247 if (movie->format_ctx->start_time != AV_NOPTS_VALUE) {
00248 if (timestamp > INT64_MAX - movie->format_ctx->start_time) {
00249 av_log(ctx, AV_LOG_ERROR,
00250 "%s: seek value overflow with start_time:%"PRId64" seek_point:%"PRId64"\n",
00251 movie->file_name, movie->format_ctx->start_time, movie->seek_point);
00252 return AVERROR(EINVAL);
00253 }
00254 timestamp += movie->format_ctx->start_time;
00255 }
00256 if ((ret = av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD)) < 0) {
00257 av_log(ctx, AV_LOG_ERROR, "%s: could not seek to position %"PRId64"\n",
00258 movie->file_name, timestamp);
00259 return ret;
00260 }
00261 }
00262
00263 for (i = 0; i < movie->format_ctx->nb_streams; i++)
00264 movie->format_ctx->streams[i]->discard = AVDISCARD_ALL;
00265
00266 movie->st = av_calloc(nb_streams, sizeof(*movie->st));
00267 if (!movie->st)
00268 return AVERROR(ENOMEM);
00269
00270 for (i = 0; i < nb_streams; i++) {
00271 spec = av_strtok(stream_specs, "+", &cursor);
00272 if (!spec)
00273 return AVERROR_BUG;
00274 stream_specs = NULL;
00275 st = find_stream(ctx, movie->format_ctx, spec);
00276 if (!st)
00277 return AVERROR(EINVAL);
00278 st->discard = AVDISCARD_DEFAULT;
00279 movie->st[i].st = st;
00280 movie->max_stream_index = FFMAX(movie->max_stream_index, st->index);
00281 }
00282 if (av_strtok(NULL, "+", &cursor))
00283 return AVERROR_BUG;
00284
00285 movie->out_index = av_calloc(movie->max_stream_index + 1,
00286 sizeof(*movie->out_index));
00287 if (!movie->out_index)
00288 return AVERROR(ENOMEM);
00289 for (i = 0; i <= movie->max_stream_index; i++)
00290 movie->out_index[i] = -1;
00291 for (i = 0; i < nb_streams; i++)
00292 movie->out_index[movie->st[i].st->index] = i;
00293
00294 for (i = 0; i < nb_streams; i++) {
00295 AVFilterPad pad = { 0 };
00296 snprintf(name, sizeof(name), "out%d", i);
00297 pad.type = movie->st[i].st->codec->codec_type;
00298 pad.name = av_strdup(name);
00299 pad.config_props = movie_config_output_props;
00300 pad.request_frame = movie_request_frame;
00301 ff_insert_outpad(ctx, i, &pad);
00302 ret = open_stream(ctx, &movie->st[i]);
00303 if (ret < 0)
00304 return ret;
00305 if ( movie->st[i].st->codec->codec->type == AVMEDIA_TYPE_AUDIO &&
00306 !movie->st[i].st->codec->channel_layout) {
00307 ret = guess_channel_layout(&movie->st[i], i, ctx);
00308 if (ret < 0)
00309 return ret;
00310 }
00311 }
00312
00313 if (!(movie->frame = avcodec_alloc_frame()) ) {
00314 av_log(log, AV_LOG_ERROR, "Failed to alloc frame\n");
00315 return AVERROR(ENOMEM);
00316 }
00317
00318 av_log(ctx, AV_LOG_VERBOSE, "seek_point:%"PRIi64" format_name:%s file_name:%s stream_index:%d\n",
00319 movie->seek_point, movie->format_name, movie->file_name,
00320 movie->stream_index);
00321
00322 return 0;
00323 }
00324
00325 static av_cold void movie_uninit(AVFilterContext *ctx)
00326 {
00327 MovieContext *movie = ctx->priv;
00328 int i;
00329
00330 for (i = 0; i < ctx->nb_outputs; i++) {
00331 av_freep(&ctx->output_pads[i].name);
00332 if (movie->st[i].st)
00333 avcodec_close(movie->st[i].st->codec);
00334 }
00335 av_opt_free(movie);
00336 av_freep(&movie->file_name);
00337 av_freep(&movie->st);
00338 av_freep(&movie->out_index);
00339 avcodec_free_frame(&movie->frame);
00340 if (movie->format_ctx)
00341 avformat_close_input(&movie->format_ctx);
00342 }
00343
00344 static int movie_query_formats(AVFilterContext *ctx)
00345 {
00346 MovieContext *movie = ctx->priv;
00347 int list[] = { 0, -1 };
00348 int64_t list64[] = { 0, -1 };
00349 int i;
00350
00351 for (i = 0; i < ctx->nb_outputs; i++) {
00352 MovieStream *st = &movie->st[i];
00353 AVCodecContext *c = st->st->codec;
00354 AVFilterLink *outlink = ctx->outputs[i];
00355
00356 switch (c->codec_type) {
00357 case AVMEDIA_TYPE_VIDEO:
00358 list[0] = c->pix_fmt;
00359 ff_formats_ref(ff_make_format_list(list), &outlink->in_formats);
00360 break;
00361 case AVMEDIA_TYPE_AUDIO:
00362 list[0] = c->sample_fmt;
00363 ff_formats_ref(ff_make_format_list(list), &outlink->in_formats);
00364 list[0] = c->sample_rate;
00365 ff_formats_ref(ff_make_format_list(list), &outlink->in_samplerates);
00366 list64[0] = c->channel_layout;
00367 ff_channel_layouts_ref(avfilter_make_format64_list(list64),
00368 &outlink->in_channel_layouts);
00369 break;
00370 }
00371 }
00372
00373 return 0;
00374 }
00375
00376 static int movie_config_output_props(AVFilterLink *outlink)
00377 {
00378 AVFilterContext *ctx = outlink->src;
00379 MovieContext *movie = ctx->priv;
00380 unsigned out_id = FF_OUTLINK_IDX(outlink);
00381 MovieStream *st = &movie->st[out_id];
00382 AVCodecContext *c = st->st->codec;
00383
00384 outlink->time_base = st->st->time_base;
00385
00386 switch (c->codec_type) {
00387 case AVMEDIA_TYPE_VIDEO:
00388 outlink->w = c->width;
00389 outlink->h = c->height;
00390 outlink->frame_rate = st->st->r_frame_rate;
00391 break;
00392 case AVMEDIA_TYPE_AUDIO:
00393 break;
00394 }
00395
00396 return 0;
00397 }
00398
00399 static AVFilterBufferRef *frame_to_buf(enum AVMediaType type, AVFrame *frame,
00400 AVFilterLink *outlink)
00401 {
00402 AVFilterBufferRef *buf, *copy;
00403
00404 buf = avfilter_get_buffer_ref_from_frame(type, frame,
00405 AV_PERM_WRITE |
00406 AV_PERM_PRESERVE |
00407 AV_PERM_REUSE2);
00408 if (!buf)
00409 return NULL;
00410 buf->pts = av_frame_get_best_effort_timestamp(frame);
00411 copy = ff_copy_buffer_ref(outlink, buf);
00412 if (!copy)
00413 return NULL;
00414 buf->buf->data[0] = NULL;
00415 avfilter_unref_buffer(buf);
00416 return copy;
00417 }
00418
00419 static char *describe_bufref_to_str(char *dst, size_t dst_size,
00420 AVFilterBufferRef *buf,
00421 AVFilterLink *link)
00422 {
00423 switch (buf->type) {
00424 case AVMEDIA_TYPE_VIDEO:
00425 snprintf(dst, dst_size,
00426 "video pts:%s time:%s pos:%"PRId64" size:%dx%d aspect:%d/%d",
00427 av_ts2str(buf->pts), av_ts2timestr(buf->pts, &link->time_base),
00428 buf->pos, buf->video->w, buf->video->h,
00429 buf->video->sample_aspect_ratio.num,
00430 buf->video->sample_aspect_ratio.den);
00431 break;
00432 case AVMEDIA_TYPE_AUDIO:
00433 snprintf(dst, dst_size,
00434 "audio pts:%s time:%s pos:%"PRId64" samples:%d",
00435 av_ts2str(buf->pts), av_ts2timestr(buf->pts, &link->time_base),
00436 buf->pos, buf->audio->nb_samples);
00437 break;
00438 default:
00439 snprintf(dst, dst_size, "%s BUG", av_get_media_type_string(buf->type));
00440 break;
00441 }
00442 return dst;
00443 }
00444
00445 #define describe_bufref(buf, link) \
00446 describe_bufref_to_str((char[1024]){0}, 1024, buf, link)
00447
00448 static int rewind_file(AVFilterContext *ctx)
00449 {
00450 MovieContext *movie = ctx->priv;
00451 int64_t timestamp = movie->seek_point;
00452 int ret, i;
00453
00454 if (movie->format_ctx->start_time != AV_NOPTS_VALUE)
00455 timestamp += movie->format_ctx->start_time;
00456 ret = av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD);
00457 if (ret < 0) {
00458 av_log(ctx, AV_LOG_ERROR, "Unable to loop: %s\n", av_err2str(ret));
00459 movie->loop_count = 1;
00460 return ret;
00461 }
00462
00463 for (i = 0; i < ctx->nb_outputs; i++) {
00464 avcodec_flush_buffers(movie->st[i].st->codec);
00465 movie->st[i].done = 0;
00466 }
00467 movie->eof = 0;
00468 return 0;
00469 }
00470
00482 static int movie_push_frame(AVFilterContext *ctx, unsigned out_id)
00483 {
00484 MovieContext *movie = ctx->priv;
00485 AVPacket *pkt = &movie->pkt;
00486 MovieStream *st;
00487 int ret, got_frame = 0, pkt_out_id;
00488 AVFilterLink *outlink;
00489 AVFilterBufferRef *buf;
00490
00491 if (!pkt->size) {
00492 if (movie->eof) {
00493 if (movie->st[out_id].done) {
00494 if (movie->loop_count != 1) {
00495 ret = rewind_file(ctx);
00496 if (ret < 0)
00497 return ret;
00498 movie->loop_count -= movie->loop_count > 1;
00499 av_log(ctx, AV_LOG_VERBOSE, "Stream finished, looping.\n");
00500 return 0;
00501 }
00502 return AVERROR_EOF;
00503 }
00504 pkt->stream_index = movie->st[out_id].st->index;
00505
00506 } else {
00507 ret = av_read_frame(movie->format_ctx, &movie->pkt0);
00508 if (ret < 0) {
00509 av_init_packet(&movie->pkt0);
00510 *pkt = movie->pkt0;
00511 if (ret == AVERROR_EOF) {
00512 movie->eof = 1;
00513 return 0;
00514 }
00515 return ret;
00516 }
00517 *pkt = movie->pkt0;
00518 }
00519 }
00520
00521 pkt_out_id = pkt->stream_index > movie->max_stream_index ? -1 :
00522 movie->out_index[pkt->stream_index];
00523 if (pkt_out_id < 0) {
00524 av_free_packet(&movie->pkt0);
00525 pkt->size = 0;
00526 pkt->data = NULL;
00527 return 0;
00528 }
00529 st = &movie->st[pkt_out_id];
00530 outlink = ctx->outputs[pkt_out_id];
00531
00532 switch (st->st->codec->codec_type) {
00533 case AVMEDIA_TYPE_VIDEO:
00534 ret = avcodec_decode_video2(st->st->codec, movie->frame, &got_frame, pkt);
00535 break;
00536 case AVMEDIA_TYPE_AUDIO:
00537 ret = avcodec_decode_audio4(st->st->codec, movie->frame, &got_frame, pkt);
00538 break;
00539 default:
00540 ret = AVERROR(ENOSYS);
00541 break;
00542 }
00543 if (ret < 0) {
00544 av_log(ctx, AV_LOG_WARNING, "Decode error: %s\n", av_err2str(ret));
00545 return 0;
00546 }
00547 if (!ret)
00548 ret = pkt->size;
00549
00550 pkt->data += ret;
00551 pkt->size -= ret;
00552 if (pkt->size <= 0) {
00553 av_free_packet(&movie->pkt0);
00554 pkt->size = 0;
00555 pkt->data = NULL;
00556 }
00557 if (!got_frame) {
00558 if (!ret)
00559 st->done = 1;
00560 return 0;
00561 }
00562
00563 buf = frame_to_buf(st->st->codec->codec_type, movie->frame, outlink);
00564 if (!buf)
00565 return AVERROR(ENOMEM);
00566 av_dlog(ctx, "movie_push_frame(): file:'%s' %s\n", movie->file_name,
00567 describe_bufref(buf, outlink));
00568 switch (st->st->codec->codec_type) {
00569 case AVMEDIA_TYPE_VIDEO:
00570 if (!movie->frame->sample_aspect_ratio.num)
00571 buf->video->sample_aspect_ratio = st->st->sample_aspect_ratio;
00572 ff_start_frame(outlink, buf);
00573 ff_draw_slice(outlink, 0, outlink->h, 1);
00574 ff_end_frame(outlink);
00575 break;
00576 case AVMEDIA_TYPE_AUDIO:
00577 ff_filter_samples(outlink, buf);
00578 break;
00579 }
00580
00581 return pkt_out_id == out_id;
00582 }
00583
00584 static int movie_request_frame(AVFilterLink *outlink)
00585 {
00586 AVFilterContext *ctx = outlink->src;
00587 unsigned out_id = FF_OUTLINK_IDX(outlink);
00588 int ret;
00589
00590 while (1) {
00591 ret = movie_push_frame(ctx, out_id);
00592 if (ret)
00593 return FFMIN(ret, 0);
00594 }
00595 }
00596
00597 #if CONFIG_MOVIE_FILTER
00598
00599 AVFILTER_DEFINE_CLASS(movie);
00600
00601 static av_cold int movie_init(AVFilterContext *ctx, const char *args)
00602 {
00603 return movie_common_init(ctx, args, &movie_class);
00604 }
00605
00606 AVFilter avfilter_avsrc_movie = {
00607 .name = "movie",
00608 .description = NULL_IF_CONFIG_SMALL("Read from a movie source."),
00609 .priv_size = sizeof(MovieContext),
00610 .init = movie_init,
00611 .uninit = movie_uninit,
00612 .query_formats = movie_query_formats,
00613
00614 .inputs = NULL,
00615 .outputs = (const AVFilterPad[]) {{ .name = NULL }},
00616 .priv_class = &movie_class,
00617 };
00618
00619 #endif
00620
00621 #if CONFIG_AMOVIE_FILTER
00622
00623 #define amovie_options movie_options
00624 AVFILTER_DEFINE_CLASS(amovie);
00625
00626 static av_cold int amovie_init(AVFilterContext *ctx, const char *args)
00627 {
00628 return movie_common_init(ctx, args, &amovie_class);
00629 }
00630
00631 AVFilter avfilter_avsrc_amovie = {
00632 .name = "amovie",
00633 .description = NULL_IF_CONFIG_SMALL("Read audio from a movie source."),
00634 .priv_size = sizeof(MovieContext),
00635 .init = amovie_init,
00636 .uninit = movie_uninit,
00637 .query_formats = movie_query_formats,
00638
00639 .inputs = (const AVFilterPad[]) {{ .name = NULL }},
00640 .outputs = (const AVFilterPad[]) {{ .name = NULL }},
00641 .priv_class = &amovie_class,
00642 };
00643
00644 #endif