00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ffmpeg.h"
00022
00023 #include "libavfilter/avfilter.h"
00024 #include "libavfilter/avfiltergraph.h"
00025 #include "libavfilter/buffersink.h"
00026
00027 #include "libavutil/audioconvert.h"
00028 #include "libavutil/avassert.h"
00029 #include "libavutil/avstring.h"
00030 #include "libavutil/bprint.h"
00031 #include "libavutil/pixdesc.h"
00032 #include "libavutil/pixfmt.h"
00033 #include "libavutil/imgutils.h"
00034 #include "libavutil/samplefmt.h"
00035
00036 enum PixelFormat choose_pixel_fmt(AVStream *st, AVCodec *codec, enum PixelFormat target)
00037 {
00038 if (codec && codec->pix_fmts) {
00039 const enum PixelFormat *p = codec->pix_fmts;
00040 int has_alpha= av_pix_fmt_descriptors[target].nb_components % 2 == 0;
00041 enum PixelFormat best= PIX_FMT_NONE;
00042 if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
00043 if (st->codec->codec_id == AV_CODEC_ID_MJPEG) {
00044 p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE };
00045 } else if (st->codec->codec_id == AV_CODEC_ID_LJPEG) {
00046 p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P,
00047 PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE };
00048 }
00049 }
00050 for (; *p != PIX_FMT_NONE; p++) {
00051 best= avcodec_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL);
00052 if (*p == target)
00053 break;
00054 }
00055 if (*p == PIX_FMT_NONE) {
00056 if (target != PIX_FMT_NONE)
00057 av_log(NULL, AV_LOG_WARNING,
00058 "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
00059 av_pix_fmt_descriptors[target].name,
00060 codec->name,
00061 av_pix_fmt_descriptors[best].name);
00062 return best;
00063 }
00064 }
00065 return target;
00066 }
00067
00068 void choose_sample_fmt(AVStream *st, AVCodec *codec)
00069 {
00070 if (codec && codec->sample_fmts) {
00071 const enum AVSampleFormat *p = codec->sample_fmts;
00072 for (; *p != -1; p++) {
00073 if (*p == st->codec->sample_fmt)
00074 break;
00075 }
00076 if (*p == -1) {
00077 if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
00078 av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n");
00079 if(av_get_sample_fmt_name(st->codec->sample_fmt))
00080 av_log(NULL, AV_LOG_WARNING,
00081 "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
00082 av_get_sample_fmt_name(st->codec->sample_fmt),
00083 codec->name,
00084 av_get_sample_fmt_name(codec->sample_fmts[0]));
00085 st->codec->sample_fmt = codec->sample_fmts[0];
00086 }
00087 }
00088 }
00089
00090 static char *choose_pix_fmts(OutputStream *ost)
00091 {
00092 if (ost->keep_pix_fmt) {
00093 if (ost->filter)
00094 avfilter_graph_set_auto_convert(ost->filter->graph->graph,
00095 AVFILTER_AUTO_CONVERT_NONE);
00096 if (ost->st->codec->pix_fmt == PIX_FMT_NONE)
00097 return NULL;
00098 return av_strdup(av_get_pix_fmt_name(ost->st->codec->pix_fmt));
00099 }
00100 if (ost->st->codec->pix_fmt != PIX_FMT_NONE) {
00101 return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc, ost->st->codec->pix_fmt)));
00102 } else if (ost->enc && ost->enc->pix_fmts) {
00103 const enum PixelFormat *p;
00104 AVIOContext *s = NULL;
00105 uint8_t *ret;
00106 int len;
00107
00108 if (avio_open_dyn_buf(&s) < 0)
00109 exit_program(1);
00110
00111 p = ost->enc->pix_fmts;
00112 if (ost->st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
00113 if (ost->st->codec->codec_id == AV_CODEC_ID_MJPEG) {
00114 p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_NONE };
00115 } else if (ost->st->codec->codec_id == AV_CODEC_ID_LJPEG) {
00116 p = (const enum PixelFormat[]) { PIX_FMT_YUVJ420P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ444P, PIX_FMT_YUV420P,
00117 PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_BGRA, PIX_FMT_NONE };
00118 }
00119 }
00120
00121 for (; *p != PIX_FMT_NONE; p++) {
00122 const char *name = av_get_pix_fmt_name(*p);
00123 avio_printf(s, "%s:", name);
00124 }
00125 len = avio_close_dyn_buf(s, &ret);
00126 ret[len - 1] = 0;
00127 return ret;
00128 } else
00129 return NULL;
00130 }
00131
00136 #define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name, separator)\
00137 static char *choose_ ## var ## s(OutputStream *ost) \
00138 { \
00139 if (ost->st->codec->var != none) { \
00140 get_name(ost->st->codec->var); \
00141 return av_strdup(name); \
00142 } else if (ost->enc->supported_list) { \
00143 const type *p; \
00144 AVIOContext *s = NULL; \
00145 uint8_t *ret; \
00146 int len; \
00147 \
00148 if (avio_open_dyn_buf(&s) < 0) \
00149 exit_program(1); \
00150 \
00151 for (p = ost->enc->supported_list; *p != none; p++) { \
00152 get_name(*p); \
00153 avio_printf(s, "%s" separator, name); \
00154 } \
00155 len = avio_close_dyn_buf(s, &ret); \
00156 ret[len - 1] = 0; \
00157 return ret; \
00158 } else \
00159 return NULL; \
00160 }
00161
00162
00163
00164
00165 DEF_CHOOSE_FORMAT(enum AVSampleFormat, sample_fmt, sample_fmts,
00166 AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME, ",")
00167
00168 DEF_CHOOSE_FORMAT(int, sample_rate, supported_samplerates, 0,
00169 GET_SAMPLE_RATE_NAME, ",")
00170
00171 DEF_CHOOSE_FORMAT(uint64_t, channel_layout, channel_layouts, 0,
00172 GET_CH_LAYOUT_NAME, ",")
00173
00174 FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost)
00175 {
00176 FilterGraph *fg = av_mallocz(sizeof(*fg));
00177
00178 if (!fg)
00179 exit_program(1);
00180 fg->index = nb_filtergraphs;
00181
00182 fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs), &fg->nb_outputs,
00183 fg->nb_outputs + 1);
00184 if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0]))))
00185 exit_program(1);
00186 fg->outputs[0]->ost = ost;
00187 fg->outputs[0]->graph = fg;
00188
00189 ost->filter = fg->outputs[0];
00190
00191 fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs), &fg->nb_inputs,
00192 fg->nb_inputs + 1);
00193 if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0]))))
00194 exit_program(1);
00195 fg->inputs[0]->ist = ist;
00196 fg->inputs[0]->graph = fg;
00197
00198 ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
00199 &ist->nb_filters, ist->nb_filters + 1);
00200 ist->filters[ist->nb_filters - 1] = fg->inputs[0];
00201
00202 filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs),
00203 &nb_filtergraphs, nb_filtergraphs + 1);
00204 filtergraphs[nb_filtergraphs - 1] = fg;
00205
00206 return fg;
00207 }
00208
00209 static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
00210 {
00211 InputStream *ist = NULL;
00212 enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx);
00213 int i;
00214
00215
00216 if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
00217 av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported "
00218 "currently.\n");
00219 exit_program(1);
00220 }
00221
00222 if (in->name) {
00223 AVFormatContext *s;
00224 AVStream *st = NULL;
00225 char *p;
00226 int file_idx = strtol(in->name, &p, 0);
00227
00228 if (file_idx < 0 || file_idx >= nb_input_files) {
00229 av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n",
00230 file_idx, fg->graph_desc);
00231 exit_program(1);
00232 }
00233 s = input_files[file_idx]->ctx;
00234
00235 for (i = 0; i < s->nb_streams; i++) {
00236 enum AVMediaType stream_type = s->streams[i]->codec->codec_type;
00237 if (stream_type != type &&
00238 !(stream_type == AVMEDIA_TYPE_SUBTITLE &&
00239 type == AVMEDIA_TYPE_VIDEO ))
00240 continue;
00241 if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) {
00242 st = s->streams[i];
00243 break;
00244 }
00245 }
00246 if (!st) {
00247 av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
00248 "matches no streams.\n", p, fg->graph_desc);
00249 exit_program(1);
00250 }
00251 ist = input_streams[input_files[file_idx]->ist_index + st->index];
00252 } else {
00253
00254 for (i = 0; i < nb_input_streams; i++) {
00255 ist = input_streams[i];
00256 if (ist->st->codec->codec_type == type && ist->discard)
00257 break;
00258 }
00259 if (i == nb_input_streams) {
00260 av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
00261 "unlabeled input pad %d on filter %s\n", in->pad_idx,
00262 in->filter_ctx->name);
00263 exit_program(1);
00264 }
00265 }
00266 av_assert0(ist);
00267
00268 ist->discard = 0;
00269 ist->decoding_needed++;
00270 ist->st->discard = AVDISCARD_NONE;
00271
00272 fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs),
00273 &fg->nb_inputs, fg->nb_inputs + 1);
00274 if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0]))))
00275 exit_program(1);
00276 fg->inputs[fg->nb_inputs - 1]->ist = ist;
00277 fg->inputs[fg->nb_inputs - 1]->graph = fg;
00278
00279 ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
00280 &ist->nb_filters, ist->nb_filters + 1);
00281 ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
00282 }
00283
00284 static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
00285 {
00286 char *pix_fmts;
00287 OutputStream *ost = ofilter->ost;
00288 AVCodecContext *codec = ost->st->codec;
00289 AVFilterContext *last_filter = out->filter_ctx;
00290 int pad_idx = out->pad_idx;
00291 int ret;
00292 char name[255];
00293 AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
00294
00295 snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index);
00296 ret = avfilter_graph_create_filter(&ofilter->filter,
00297 avfilter_get_by_name("ffbuffersink"),
00298 name, NULL, NULL, fg->graph);
00299 av_freep(&buffersink_params);
00300
00301 if (ret < 0)
00302 return ret;
00303
00304 if (codec->width || codec->height) {
00305 char args[255];
00306 AVFilterContext *filter;
00307
00308 snprintf(args, sizeof(args), "%d:%d:flags=0x%X",
00309 codec->width,
00310 codec->height,
00311 (unsigned)ost->sws_flags);
00312 snprintf(name, sizeof(name), "scaler for output stream %d:%d",
00313 ost->file_index, ost->index);
00314 if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
00315 name, args, NULL, fg->graph)) < 0)
00316 return ret;
00317 if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
00318 return ret;
00319
00320 last_filter = filter;
00321 pad_idx = 0;
00322 }
00323
00324 if ((pix_fmts = choose_pix_fmts(ost))) {
00325 AVFilterContext *filter;
00326 snprintf(name, sizeof(name), "pixel format for output stream %d:%d",
00327 ost->file_index, ost->index);
00328 if ((ret = avfilter_graph_create_filter(&filter,
00329 avfilter_get_by_name("format"),
00330 "format", pix_fmts, NULL,
00331 fg->graph)) < 0)
00332 return ret;
00333 if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
00334 return ret;
00335
00336 last_filter = filter;
00337 pad_idx = 0;
00338 av_freep(&pix_fmts);
00339 }
00340
00341 if (ost->frame_rate.num && 0) {
00342 AVFilterContext *fps;
00343 char args[255];
00344
00345 snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num,
00346 ost->frame_rate.den);
00347 snprintf(name, sizeof(name), "fps for output stream %d:%d",
00348 ost->file_index, ost->index);
00349 ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"),
00350 name, args, NULL, fg->graph);
00351 if (ret < 0)
00352 return ret;
00353
00354 ret = avfilter_link(last_filter, pad_idx, fps, 0);
00355 if (ret < 0)
00356 return ret;
00357 last_filter = fps;
00358 pad_idx = 0;
00359 }
00360
00361 if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
00362 return ret;
00363
00364 return 0;
00365 }
00366
00367 static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
00368 {
00369 OutputStream *ost = ofilter->ost;
00370 AVCodecContext *codec = ost->st->codec;
00371 AVFilterContext *last_filter = out->filter_ctx;
00372 int pad_idx = out->pad_idx;
00373 char *sample_fmts, *sample_rates, *channel_layouts;
00374 char name[255];
00375 int ret;
00376
00377
00378 snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index);
00379 ret = avfilter_graph_create_filter(&ofilter->filter,
00380 avfilter_get_by_name("ffabuffersink"),
00381 name, NULL, NULL, fg->graph);
00382 if (ret < 0)
00383 return ret;
00384
00385 #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \
00386 AVFilterContext *filt_ctx; \
00387 \
00388 av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \
00389 "similarly to -af " filter_name "=%s.\n", arg); \
00390 \
00391 ret = avfilter_graph_create_filter(&filt_ctx, \
00392 avfilter_get_by_name(filter_name), \
00393 filter_name, arg, NULL, fg->graph); \
00394 if (ret < 0) \
00395 return ret; \
00396 \
00397 ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0); \
00398 if (ret < 0) \
00399 return ret; \
00400 \
00401 last_filter = filt_ctx; \
00402 pad_idx = 0; \
00403 } while (0)
00404 if (ost->audio_channels_mapped) {
00405 int i;
00406 AVBPrint pan_buf;
00407 av_bprint_init(&pan_buf, 256, 8192);
00408 av_bprintf(&pan_buf, "0x%"PRIx64,
00409 av_get_default_channel_layout(ost->audio_channels_mapped));
00410 for (i = 0; i < ost->audio_channels_mapped; i++)
00411 if (ost->audio_channels_map[i] != -1)
00412 av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]);
00413
00414 AUTO_INSERT_FILTER("-map_channel", "pan", pan_buf.str);
00415 av_bprint_finalize(&pan_buf, NULL);
00416 }
00417
00418 if (codec->channels && !codec->channel_layout)
00419 codec->channel_layout = av_get_default_channel_layout(codec->channels);
00420
00421 sample_fmts = choose_sample_fmts(ost);
00422 sample_rates = choose_sample_rates(ost);
00423 channel_layouts = choose_channel_layouts(ost);
00424 if (sample_fmts || sample_rates || channel_layouts) {
00425 AVFilterContext *format;
00426 char args[256];
00427 args[0] = 0;
00428
00429 if (sample_fmts)
00430 av_strlcatf(args, sizeof(args), "sample_fmts=%s:",
00431 sample_fmts);
00432 if (sample_rates)
00433 av_strlcatf(args, sizeof(args), "sample_rates=%s:",
00434 sample_rates);
00435 if (channel_layouts)
00436 av_strlcatf(args, sizeof(args), "channel_layouts=%s:",
00437 channel_layouts);
00438
00439 av_freep(&sample_fmts);
00440 av_freep(&sample_rates);
00441 av_freep(&channel_layouts);
00442
00443 snprintf(name, sizeof(name), "audio format for output stream %d:%d",
00444 ost->file_index, ost->index);
00445 ret = avfilter_graph_create_filter(&format,
00446 avfilter_get_by_name("aformat"),
00447 name, args, NULL, fg->graph);
00448 if (ret < 0)
00449 return ret;
00450
00451 ret = avfilter_link(last_filter, pad_idx, format, 0);
00452 if (ret < 0)
00453 return ret;
00454
00455 last_filter = format;
00456 pad_idx = 0;
00457 }
00458
00459 if (audio_volume != 256 && 0) {
00460 char args[256];
00461
00462 snprintf(args, sizeof(args), "%f", audio_volume / 256.);
00463 AUTO_INSERT_FILTER("-vol", "volume", args);
00464 }
00465
00466 if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
00467 return ret;
00468
00469 return 0;
00470 }
00471
00472 #define DESCRIBE_FILTER_LINK(f, inout, in) \
00473 { \
00474 AVFilterContext *ctx = inout->filter_ctx; \
00475 AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; \
00476 int nb_pads = in ? ctx->input_count : ctx->output_count; \
00477 AVIOContext *pb; \
00478 \
00479 if (avio_open_dyn_buf(&pb) < 0) \
00480 exit_program(1); \
00481 \
00482 avio_printf(pb, "%s", ctx->filter->name); \
00483 if (nb_pads > 1) \
00484 avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
00485 avio_w8(pb, 0); \
00486 avio_close_dyn_buf(pb, &f->name); \
00487 }
00488
00489 int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
00490 {
00491 av_freep(&ofilter->name);
00492 DESCRIBE_FILTER_LINK(ofilter, out, 0);
00493
00494 switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) {
00495 case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out);
00496 case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out);
00497 default: av_assert0(0);
00498 }
00499 }
00500
00501 static int sub2video_prepare(InputStream *ist)
00502 {
00503 AVFormatContext *avf = input_files[ist->file_index]->ctx;
00504 int i, ret, w, h;
00505 uint8_t *image[4];
00506 int linesize[4];
00507
00508
00509
00510
00511 w = ist->st->codec->width;
00512 h = ist->st->codec->height;
00513 if (!(w && h)) {
00514 for (i = 0; i < avf->nb_streams; i++) {
00515 if (avf->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00516 w = FFMAX(w, avf->streams[i]->codec->width);
00517 h = FFMAX(h, avf->streams[i]->codec->height);
00518 }
00519 }
00520 if (!(w && h)) {
00521 w = FFMAX(w, 720);
00522 h = FFMAX(h, 576);
00523 }
00524 av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h);
00525 }
00526 ist->sub2video.w = ist->st->codec->width = w;
00527 ist->sub2video.h = ist->st->codec->height = h;
00528
00529
00530
00531 ist->st->codec->pix_fmt = PIX_FMT_RGB32;
00532
00533 ret = av_image_alloc(image, linesize, w, h, PIX_FMT_RGB32, 32);
00534 if (ret < 0)
00535 return ret;
00536 memset(image[0], 0, h * linesize[0]);
00537 ist->sub2video.ref = avfilter_get_video_buffer_ref_from_arrays(
00538 image, linesize, AV_PERM_READ | AV_PERM_PRESERVE,
00539 w, h, PIX_FMT_RGB32);
00540 if (!ist->sub2video.ref) {
00541 av_free(image[0]);
00542 return AVERROR(ENOMEM);
00543 }
00544 return 0;
00545 }
00546
00547 static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
00548 AVFilterInOut *in)
00549 {
00550 AVFilterContext *first_filter = in->filter_ctx;
00551 AVFilter *filter = avfilter_get_by_name("buffer");
00552 InputStream *ist = ifilter->ist;
00553 AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) :
00554 ist->st->time_base;
00555 AVRational fr = ist->framerate.num ? ist->framerate :
00556 ist->st->r_frame_rate;
00557 AVRational sar;
00558 AVBPrint args;
00559 char name[255];
00560 int pad_idx = in->pad_idx;
00561 int ret;
00562
00563 if (ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
00564 ret = sub2video_prepare(ist);
00565 if (ret < 0)
00566 return ret;
00567 }
00568
00569 sar = ist->st->sample_aspect_ratio.num ?
00570 ist->st->sample_aspect_ratio :
00571 ist->st->codec->sample_aspect_ratio;
00572 if(!sar.den)
00573 sar = (AVRational){0,1};
00574 av_bprint_init(&args, 0, 1);
00575 av_bprintf(&args,
00576 "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:"
00577 "pixel_aspect=%d/%d:sws_param=flags=%d", ist->st->codec->width,
00578 ist->st->codec->height, ist->st->codec->pix_fmt,
00579 tb.num, tb.den, sar.num, sar.den,
00580 SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
00581 if (fr.num && fr.den)
00582 av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den);
00583 snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
00584 ist->file_index, ist->st->index);
00585
00586 if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, name,
00587 args.str, NULL, fg->graph)) < 0)
00588 return ret;
00589
00590 if (ist->framerate.num) {
00591 AVFilterContext *setpts;
00592
00593 snprintf(name, sizeof(name), "force CFR for input from stream %d:%d",
00594 ist->file_index, ist->st->index);
00595 if ((ret = avfilter_graph_create_filter(&setpts,
00596 avfilter_get_by_name("setpts"),
00597 name, "N", NULL,
00598 fg->graph)) < 0)
00599 return ret;
00600
00601 if ((ret = avfilter_link(setpts, 0, first_filter, pad_idx)) < 0)
00602 return ret;
00603
00604 first_filter = setpts;
00605 pad_idx = 0;
00606 }
00607
00608 if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0)
00609 return ret;
00610 return 0;
00611 }
00612
00613 static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
00614 AVFilterInOut *in)
00615 {
00616 AVFilterContext *first_filter = in->filter_ctx;
00617 AVFilter *filter = avfilter_get_by_name("abuffer");
00618 InputStream *ist = ifilter->ist;
00619 int pad_idx = in->pad_idx;
00620 char args[255], name[255];
00621 int ret;
00622
00623 snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s"
00624 ":channel_layout=0x%"PRIx64,
00625 1, ist->st->codec->sample_rate,
00626 ist->st->codec->sample_rate,
00627 av_get_sample_fmt_name(ist->st->codec->sample_fmt),
00628 ist->st->codec->channel_layout);
00629 snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
00630 ist->file_index, ist->st->index);
00631
00632 if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter,
00633 name, args, NULL,
00634 fg->graph)) < 0)
00635 return ret;
00636
00637 #define AUTO_INSERT_FILTER_INPUT(opt_name, filter_name, arg) do { \
00638 AVFilterContext *filt_ctx; \
00639 \
00640 av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi " \
00641 "similarly to -af " filter_name "=%s.\n", arg); \
00642 \
00643 snprintf(name, sizeof(name), "graph %d %s for input stream %d:%d", \
00644 fg->index, filter_name, ist->file_index, ist->st->index); \
00645 ret = avfilter_graph_create_filter(&filt_ctx, \
00646 avfilter_get_by_name(filter_name), \
00647 name, arg, NULL, fg->graph); \
00648 if (ret < 0) \
00649 return ret; \
00650 \
00651 ret = avfilter_link(filt_ctx, 0, first_filter, pad_idx); \
00652 if (ret < 0) \
00653 return ret; \
00654 \
00655 first_filter = filt_ctx; \
00656 } while (0)
00657
00658 if (audio_sync_method > 0) {
00659 char args[256] = {0};
00660
00661 av_strlcatf(args, sizeof(args), "min_comp=0.001:min_hard_comp=%f", audio_drift_threshold);
00662 if (audio_sync_method > 1)
00663 av_strlcatf(args, sizeof(args), ":max_soft_comp=%f", audio_sync_method/(double)ist->st->codec->sample_rate);
00664 AUTO_INSERT_FILTER_INPUT("-async", "aresample", args);
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 if (audio_volume != 256) {
00681 char args[256];
00682
00683 snprintf(args, sizeof(args), "%f", audio_volume / 256.);
00684 AUTO_INSERT_FILTER_INPUT("-vol", "volume", args);
00685 }
00686 if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0)
00687 return ret;
00688
00689 return 0;
00690 }
00691
00692 static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter,
00693 AVFilterInOut *in)
00694 {
00695 av_freep(&ifilter->name);
00696 DESCRIBE_FILTER_LINK(ifilter, in, 1);
00697
00698 switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) {
00699 case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in);
00700 case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in);
00701 default: av_assert0(0);
00702 }
00703 }
00704
00705 int configure_filtergraph(FilterGraph *fg)
00706 {
00707 AVFilterInOut *inputs, *outputs, *cur;
00708 int ret, i, init = !fg->graph, simple = !fg->graph_desc;
00709 const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter :
00710 fg->graph_desc;
00711
00712 avfilter_graph_free(&fg->graph);
00713 if (!(fg->graph = avfilter_graph_alloc()))
00714 return AVERROR(ENOMEM);
00715
00716 if (simple) {
00717 OutputStream *ost = fg->outputs[0]->ost;
00718 char args[255];
00719 snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags);
00720 fg->graph->scale_sws_opts = av_strdup(args);
00721 }
00722
00723 if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0)
00724 return ret;
00725
00726 if (simple && (!inputs || inputs->next || !outputs || outputs->next)) {
00727 av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have "
00728 "exactly one input and output.\n", graph_desc);
00729 return AVERROR(EINVAL);
00730 }
00731
00732 for (cur = inputs; !simple && init && cur; cur = cur->next)
00733 init_input_filter(fg, cur);
00734
00735 for (cur = inputs, i = 0; cur; cur = cur->next, i++)
00736 if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0)
00737 return ret;
00738 avfilter_inout_free(&inputs);
00739
00740 if (!init || simple) {
00741
00742
00743 for (cur = outputs, i = 0; cur; cur = cur->next, i++)
00744 configure_output_filter(fg, fg->outputs[i], cur);
00745 avfilter_inout_free(&outputs);
00746
00747 if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
00748 return ret;
00749 } else {
00750
00751 for (cur = outputs; cur;) {
00752 fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs),
00753 &fg->nb_outputs, fg->nb_outputs + 1);
00754 if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0]))))
00755 exit_program(1);
00756 fg->outputs[fg->nb_outputs - 1]->graph = fg;
00757 fg->outputs[fg->nb_outputs - 1]->out_tmp = cur;
00758 cur = cur->next;
00759 fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL;
00760 }
00761 }
00762
00763 return 0;
00764 }
00765
00766 int ist_in_filtergraph(FilterGraph *fg, InputStream *ist)
00767 {
00768 int i;
00769 for (i = 0; i < fg->nb_inputs; i++)
00770 if (fg->inputs[i]->ist == ist)
00771 return 1;
00772 return 0;
00773 }
00774