Newer
Older
fg->graph->scale_sws_opts = av_strdup(args);
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
return 0;
}
static int configure_simple_filtergraph(FilterGraph *fg)
{
OutputStream *ost = fg->outputs[0]->ost;
AVFilterContext *in_filter, *out_filter;
int ret;
avfilter_graph_free(&fg->graph);
fg->graph = avfilter_graph_alloc();
if (!fg->graph)
return AVERROR(ENOMEM);
switch (ost->st->codec->codec_type) {
case AVMEDIA_TYPE_VIDEO:
ret = configure_video_filters(fg, &in_filter, &out_filter);
break;
case AVMEDIA_TYPE_AUDIO:
ret = configure_audio_filters(fg, &in_filter, &out_filter);
break;
default: av_assert0(0);
}
if (ret < 0)
return ret;
if (ost->avfilter) {
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs = avfilter_inout_alloc();
outputs->name = av_strdup("in");
outputs->filter_ctx = in_filter;
outputs->pad_idx = 0;
outputs->next = NULL;
inputs->name = av_strdup("out");
inputs->filter_ctx = out_filter;
inputs->pad_idx = 0;
inputs->next = NULL;
if ((ret = avfilter_graph_parse(fg->graph, ost->avfilter, &inputs, &outputs, NULL)) < 0)
return ret;
av_freep(&ost->avfilter);
if ((ret = avfilter_link(in_filter, 0, out_filter, 0)) < 0)
return ret;
Nicolas George
committed
if (ost->keep_pix_fmt)
avfilter_graph_set_auto_convert(fg->graph,
AVFILTER_AUTO_CONVERT_NONE);
if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
return ret;
static FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost)
{
FilterGraph *fg = av_mallocz(sizeof(*fg));
if (!fg)
exit_program(1);
fg->index = nb_filtergraphs;
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs), &fg->nb_outputs,
fg->nb_outputs + 1);
if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0]))))
exit_program(1);
fg->outputs[0]->ost = ost;
fg->outputs[0]->graph = fg;
fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs), &fg->nb_inputs,
fg->nb_inputs + 1);
if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0]))))
exit_program(1);
fg->inputs[0]->ist = ist;
fg->inputs[0]->graph = fg;
ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
&ist->nb_filters, ist->nb_filters + 1);
ist->filters[ist->nb_filters - 1] = fg->inputs[0];
filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs),
&nb_filtergraphs, nb_filtergraphs + 1);
filtergraphs[nb_filtergraphs - 1] = fg;
return fg;
}
static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
{
InputStream *ist = NULL;
enum AVMediaType type = in->filter_ctx->input_pads[in->pad_idx].type;
int i;
// TODO: support other filter types
if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported "
"currently.\n");
exit_program(1);
}
if (in->name) {
AVFormatContext *s;
AVStream *st = NULL;
char *p;
int file_idx = strtol(in->name, &p, 0);
if (file_idx < 0 || file_idx >= nb_input_files) {
av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n",
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
file_idx, fg->graph_desc);
exit_program(1);
}
s = input_files[file_idx]->ctx;
for (i = 0; i < s->nb_streams; i++) {
if (s->streams[i]->codec->codec_type != type)
continue;
if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) {
st = s->streams[i];
break;
}
}
if (!st) {
av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
"matches no streams.\n", p, fg->graph_desc);
exit_program(1);
}
ist = input_streams[input_files[file_idx]->ist_index + st->index];
} else {
/* find the first unused stream of corresponding type */
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
if (ist->st->codec->codec_type == type && ist->discard)
break;
}
if (i == nb_input_streams) {
av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
"unlabeled input pad %d on filter %s", in->pad_idx,
in->filter_ctx->name);
exit_program(1);
}
}
ist->discard = 0;
ist->decoding_needed = 1;
ist->st->discard = AVDISCARD_NONE;
fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs),
&fg->nb_inputs, fg->nb_inputs + 1);
if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0]))))
exit_program(1);
fg->inputs[fg->nb_inputs - 1]->ist = ist;
fg->inputs[fg->nb_inputs - 1]->graph = fg;
ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
&ist->nb_filters, ist->nb_filters + 1);
ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
}
static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
AVCodecContext *codec = ofilter->ost->st->codec;
AVFilterContext *last_filter = out->filter_ctx;
int pad_idx = out->pad_idx;
int ret;
AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
#if FF_API_OLD_VSINK_API
ret = avfilter_graph_create_filter(&ofilter->filter,
avfilter_get_by_name("buffersink"),
"out", NULL, NULL, fg->graph);
ret = avfilter_graph_create_filter(&ofilter->filter,
avfilter_get_by_name("buffersink"),
"out", NULL, buffersink_params, fg->graph);
#endif
av_freep(&buffersink_params);
if (ret < 0)
return ret;
if (codec->width || codec->height) {
char args[255];
AVFilterContext *filter;
snprintf(args, sizeof(args), "%d:%d:flags=0x%X",
codec->width,
codec->height,
(unsigned)ofilter->ost->sws_flags);
if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
NULL, args, NULL, fg->graph)) < 0)
return ret;
if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
last_filter = filter;
if ((pix_fmts = choose_pix_fmts(ofilter->ost))) {
AVFilterContext *filter;
if ((ret = avfilter_graph_create_filter(&filter,
avfilter_get_by_name("format"),
"format", pix_fmts, NULL,
fg->graph)) < 0)
return ret;
if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
return ret;
last_filter = filter;
pad_idx = 0;
av_freep(&pix_fmts);
}
if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
return ret;
return 0;
}
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
{
OutputStream *ost = ofilter->ost;
AVCodecContext *codec = ost->st->codec;
AVFilterContext *last_filter = out->filter_ctx;
int pad_idx = out->pad_idx;
char *sample_fmts, *sample_rates, *channel_layouts;
int ret;
ret = avfilter_graph_create_filter(&ofilter->filter,
avfilter_get_by_name("abuffersink"),
"out", NULL, NULL, fg->graph);
if (ret < 0)
return ret;
if (codec->channels && !codec->channel_layout)
codec->channel_layout = av_get_default_channel_layout(codec->channels);
sample_fmts = choose_sample_fmts(ost);
sample_rates = choose_sample_rates(ost);
channel_layouts = choose_channel_layouts(ost);
if (sample_fmts || sample_rates || channel_layouts) {
AVFilterContext *format;
char args[256];
int len = 0;
if (sample_fmts)
len += snprintf(args + len, sizeof(args) - len, "sample_fmts=%s:",
sample_fmts);
if (sample_rates)
len += snprintf(args + len, sizeof(args) - len, "sample_rates=%s:",
sample_rates);
if (channel_layouts)
len += snprintf(args + len, sizeof(args) - len, "channel_layouts=%s:",
channel_layouts);
args[len - 1] = 0;
av_freep(&sample_fmts);
av_freep(&sample_rates);
av_freep(&channel_layouts);
ret = avfilter_graph_create_filter(&format,
avfilter_get_by_name("aformat"),
"aformat", args, NULL, fg->graph);
if (ret < 0)
return ret;
ret = avfilter_link(last_filter, pad_idx, format, 0);
if (ret < 0)
return ret;
last_filter = format;
pad_idx = 0;
}
if (audio_sync_method > 0) {
AVFilterContext *async;
char args[256];
int len = 0;
av_log(NULL, AV_LOG_WARNING, "-async has been deprecated. Used the "
"asyncts audio filter instead.\n");
if (audio_sync_method > 1)
len += snprintf(args + len, sizeof(args) - len, "compensate=1:"
"max_comp=%d:", audio_sync_method);
snprintf(args + len, sizeof(args) - len, "min_delta=%f",
audio_drift_threshold);
ret = avfilter_graph_create_filter(&async,
avfilter_get_by_name("asyncts"),
"async", args, NULL, fg->graph);
if (ret < 0)
return ret;
ret = avfilter_link(last_filter, pad_idx, async, 0);
if (ret < 0)
return ret;
last_filter = async;
pad_idx = 0;
}
if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
return ret;
return 0;
}
static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
{
switch (out->filter_ctx->output_pads[out->pad_idx].type) {
case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out);
case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out);
default: av_assert0(0);
}
}
static int configure_complex_filter(FilterGraph *fg)
{
AVFilterInOut *inputs, *outputs, *cur;
int ret, i, init = !fg->graph;
avfilter_graph_free(&fg->graph);
if (!(fg->graph = avfilter_graph_alloc()))
return AVERROR(ENOMEM);
if ((ret = avfilter_graph_parse2(fg->graph, fg->graph_desc, &inputs, &outputs)) < 0)
return ret;
for (cur = inputs; init && cur; cur = cur->next)
init_input_filter(fg, cur);
for (cur = inputs, i = 0; cur; cur = cur->next, i++) {
InputFilter *ifilter = fg->inputs[i];
InputStream *ist = ifilter->ist;
AVRational sar;
AVFilter *filter;
switch (cur->filter_ctx->input_pads[cur->pad_idx].type) {
case AVMEDIA_TYPE_VIDEO:
sar = ist->st->sample_aspect_ratio.num ?
ist->st->sample_aspect_ratio :
ist->st->codec->sample_aspect_ratio;
snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d", ist->st->codec->width,
ist->st->codec->height, ist->st->codec->pix_fmt,
ist->st->time_base.num, ist->st->time_base.den,
sar.num, sar.den);
filter = avfilter_get_by_name("buffer");
break;
case AVMEDIA_TYPE_AUDIO:
snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:"
"sample_fmt=%s:channel_layout=0x%"PRIx64,
ist->st->time_base.num, ist->st->time_base.den,
ist->st->codec->sample_rate,
av_get_sample_fmt_name(ist->st->codec->sample_fmt),
ist->st->codec->channel_layout);
filter = avfilter_get_by_name("abuffer");
break;
default:
av_assert0(0);
}
if ((ret = avfilter_graph_create_filter(&ifilter->filter,
filter, cur->name,
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
args, NULL, fg->graph)) < 0)
return ret;
if ((ret = avfilter_link(ifilter->filter, 0,
cur->filter_ctx, cur->pad_idx)) < 0)
return ret;
}
avfilter_inout_free(&inputs);
if (!init) {
/* we already know the mappings between lavfi outputs and output streams,
* so we can finish the setup */
for (cur = outputs, i = 0; cur; cur = cur->next, i++)
configure_output_filter(fg, fg->outputs[i], cur);
avfilter_inout_free(&outputs);
if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
return ret;
} else {
/* wait until output mappings are processed */
for (cur = outputs; cur;) {
fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs),
&fg->nb_outputs, fg->nb_outputs + 1);
if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0]))))
exit_program(1);
fg->outputs[fg->nb_outputs - 1]->graph = fg;
fg->outputs[fg->nb_outputs - 1]->out_tmp = cur;
cur = cur->next;
fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL;
}
}
return 0;
}
static int configure_complex_filters(void)
{
int i, ret = 0;
for (i = 0; i < nb_filtergraphs; i++)
if (!filtergraphs[i]->graph &&
(ret = configure_complex_filter(filtergraphs[i])) < 0)
return ret;
return 0;
}
static int configure_filtergraph(FilterGraph *fg)
{
return fg->graph_desc ? configure_complex_filter(fg) :
configure_simple_filtergraph(fg);
}
static int ist_in_filtergraph(FilterGraph *fg, InputStream *ist)
{
int i;
for (i = 0; i < fg->nb_inputs; i++)
if (fg->inputs[i]->ist == ist)
return 1;
return 0;
}
av_log(NULL, AV_LOG_QUIET, "%s", "");
#if HAVE_TERMIOS_H
tcsetattr (0, TCSANOW, &oldtty);
static volatile int received_sigterm = 0;
Roumen Petrov
committed
static void sigterm_handler(int sig)
Roumen Petrov
committed
{
received_sigterm = sig;
received_nb_signals++;
Roumen Petrov
committed
term_exit();
if(received_nb_signals > 3)
exit(123);
Roumen Petrov
committed
}
#if HAVE_TERMIOS_H
if(!run_as_daemon){
struct termios tty;
if (tcgetattr (0, &tty) == 0) {
oldtty = tty;
restore_tty = 1;
atexit(term_exit);
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
tty.c_oflag |= OPOST;
tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
tty.c_cflag &= ~(CSIZE|PARENB);
tty.c_cflag |= CS8;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 0;
tcsetattr (0, TCSANOW, &tty);
}
signal(SIGQUIT, sigterm_handler); /* Quit (POSIX). */
avformat_network_deinit();
signal(SIGINT , sigterm_handler); /* Interrupt (ANSI). */
Roumen Petrov
committed
signal(SIGTERM, sigterm_handler); /* Termination (ANSI). */
#ifdef SIGXCPU
signal(SIGXCPU, sigterm_handler);
#endif
}
/* read a key without blocking */
static int read_key(void)
{
#if HAVE_TERMIOS_H
int n = 1;
struct timeval tv;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
n = select(1, &rfds, NULL, NULL, &tv);
if (n > 0) {
n = read(0, &ch, 1);
if (n == 1)
return ch;
return n;
}
#elif HAVE_KBHIT
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
# if HAVE_PEEKNAMEDPIPE
static int is_pipe;
static HANDLE input_handle;
DWORD dw, nchars;
if(!input_handle){
input_handle = GetStdHandle(STD_INPUT_HANDLE);
is_pipe = !GetConsoleMode(input_handle, &dw);
}
if (stdin->_cnt > 0) {
read(0, &ch, 1);
return ch;
}
if (is_pipe) {
/* When running under a GUI, you will end here. */
if (!PeekNamedPipe(input_handle, NULL, 0, NULL, &nchars, NULL))
return -1;
//Read it
if(nchars != 0) {
read(0, &ch, 1);
return ch;
}else{
return -1;
}
}
# endif
static int decode_interrupt_cb(void *ctx)
Leon van Stuivenberg
committed
{
return received_nb_signals > 1;
Leon van Stuivenberg
committed
}
static const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
int i, j;
for (i = 0; i < nb_filtergraphs; i++) {
avfilter_graph_free(&filtergraphs[i]->graph);
for (j = 0; j < filtergraphs[i]->nb_inputs; j++)
av_freep(&filtergraphs[i]->inputs[j]);
av_freep(&filtergraphs[i]->inputs);
for (j = 0; j < filtergraphs[i]->nb_outputs; j++)
av_freep(&filtergraphs[i]->outputs[j]);
av_freep(&filtergraphs[i]->outputs);
av_freep(&filtergraphs[i]);
}
av_freep(&filtergraphs);
/* close files */
for (i = 0; i < nb_output_files; i++) {
AVFormatContext *s = output_files[i]->ctx;
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
avformat_free_context(s);
av_dict_free(&output_files[i]->opts);
av_freep(&output_files[i]);
for (i = 0; i < nb_output_streams; i++) {
AVBitStreamFilterContext *bsfc = output_streams[i]->bitstream_filters;
while (bsfc) {
AVBitStreamFilterContext *next = bsfc->next;
av_bitstream_filter_close(bsfc);
bsfc = next;
}
output_streams[i]->bitstream_filters = NULL;
av_freep(&output_streams[i]->filtered_frame);
av_freep(&output_streams[i]);
for (i = 0; i < nb_input_files; i++) {
avformat_close_input(&input_files[i]->ctx);
av_freep(&input_files[i]);
for (i = 0; i < nb_input_streams; i++) {
av_freep(&input_streams[i]->decoded_frame);
av_dict_free(&input_streams[i]->opts);
free_buffer_pool(input_streams[i]);
av_freep(&input_streams[i]->filters);
av_freep(&input_streams[i]);
if (vstats_file)
fclose(vstats_file);
av_free(vstats_filename);
av_freep(&input_streams);
av_freep(&input_files);
av_freep(&output_streams);
Anton Khirnov
committed
av_freep(&output_files);
uninit_opts();
avformat_network_deinit();
if (received_sigterm) {
av_log(NULL, AV_LOG_INFO, "Received signal %d: terminating.\n",
(int) received_sigterm);
exit (255);
}
static void assert_avoptions(AVDictionary *m)
{
AVDictionaryEntry *t;
if ((t = av_dict_get(m, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key);
static void assert_codec_experimental(AVCodecContext *c, int encoder)
{
const char *codec_string = encoder ? "encoder" : "decoder";
AVCodec *codec;
if (c->codec->capabilities & CODEC_CAP_EXPERIMENTAL &&
c->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
av_log(NULL, AV_LOG_FATAL, "%s '%s' is experimental and might produce bad "
"results.\nAdd '-strict experimental' if you want to use it.\n",
codec_string, c->codec->name);
codec = encoder ? avcodec_find_encoder(c->codec->id) : avcodec_find_decoder(c->codec->id);
if (!(codec->capabilities & CODEC_CAP_EXPERIMENTAL))
av_log(NULL, AV_LOG_FATAL, "Or use the non experimental %s '%s'.\n",
codec_string, codec->name);
Ronald S. Bultje
committed
static void choose_sample_fmt(AVStream *st, AVCodec *codec)
{
if (codec && codec->sample_fmts) {
const enum AVSampleFormat *p = codec->sample_fmts;
for (; *p != -1; p++) {
if (*p == st->codec->sample_fmt)
Ronald S. Bultje
committed
break;
}
if (*p == -1) {
Michael Niedermayer
committed
if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n");
if(av_get_sample_fmt_name(st->codec->sample_fmt))
av_log(NULL, AV_LOG_WARNING,
"Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
av_get_sample_fmt_name(st->codec->sample_fmt),
codec->name,
av_get_sample_fmt_name(codec->sample_fmts[0]));
Ronald S. Bultje
committed
st->codec->sample_fmt = codec->sample_fmts[0];
}
Ronald S. Bultje
committed
}
}
static void write_frame(AVFormatContext *s, AVPacket *pkt, OutputStream *ost)
AVBitStreamFilterContext *bsfc = ost->bitstream_filters;
AVCodecContext *avctx = ost->st->codec;
if ((avctx->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) ||
(avctx->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
pkt->pts = pkt->dts = AV_NOPTS_VALUE;
if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && pkt->dts != AV_NOPTS_VALUE) {
int64_t max = ost->st->cur_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
if (ost->st->cur_dts && ost->st->cur_dts != AV_NOPTS_VALUE && max > pkt->dts) {
av_log(s, max - pkt->dts > 2 ? AV_LOG_WARNING : AV_LOG_DEBUG, "Audio timestamp %"PRId64" < %"PRId64" invalid, cliping\n", pkt->dts, max);
pkt->pts = pkt->dts = max;
}
}
/*
* Audio encoders may split the packets -- #frames in != #packets out.
* But there is no reordering, so we can limit the number of output packets
* by simply dropping them here.
* Counting encoded video frames needs to be done separately because of
* reordering, see do_video_out()
*/
if (!(avctx->codec_type == AVMEDIA_TYPE_VIDEO && avctx->codec)) {
Justin Ruggles
committed
if (ost->frame_number >= ost->max_frames) {
av_free_packet(pkt);
Justin Ruggles
committed
}
ost->frame_number++;
}
while (bsfc) {
AVPacket new_pkt = *pkt;
int a = av_bitstream_filter_filter(bsfc, avctx, NULL,
&new_pkt.data, &new_pkt.size,
pkt->data, pkt->size,
pkt->flags & AV_PKT_FLAG_KEY);
if (a > 0) {
Michael Niedermayer
committed
av_free_packet(pkt);
new_pkt.destruct = av_destruct_packet;
} else if (a < 0) {
Stefano Sabatini
committed
av_log(NULL, AV_LOG_ERROR, "Failed to open bitstream filter %s for stream %d with codec %s",
bsfc->filter->name, pkt->stream_index,
avctx->codec ? avctx->codec->name : "copy");
if (exit_on_error)
Michael Niedermayer
committed
}
Michael Niedermayer
committed
Michael Niedermayer
committed
}
pkt->stream_index = ost->index;
ret = av_interleaved_write_frame(s, pkt);
if (ret < 0) {
print_error("av_interleaved_write_frame()", ret);
Michael Niedermayer
committed
}
static int check_recording_time(OutputStream *ost)
{
OutputFile *of = output_files[ost->file_index];
if (of->recording_time != INT64_MAX &&
av_compare_ts(ost->sync_opts - ost->first_pts, ost->st->codec->time_base, of->recording_time,
AV_TIME_BASE_Q) >= 0) {
ost->is_past_recording_time = 1;
return 0;
}
return 1;
}
static void do_audio_out(AVFormatContext *s, OutputStream *ost,
AVFrame *frame)
{
AVCodecContext *enc = ost->st->codec;
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
#if 0
if (!check_recording_time(ost))
return;
#endif
if (frame->pts == AV_NOPTS_VALUE || audio_sync_method < 0)
frame->pts = ost->sync_opts;
ost->sync_opts = frame->pts + frame->nb_samples;
Michael Niedermayer
committed
av_assert0(pkt.size || !pkt.data);
if (avcodec_encode_audio2(enc, &pkt, frame, &got_packet) < 0) {
Michael Niedermayer
committed
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed (avcodec_encode_audio2)\n");
exit_program(1);
update_benchmark("encode_audio %d.%d", ost->file_index, ost->index);
Michael Niedermayer
committed
if (got_packet) {
if (pkt.pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(pkt.pts, enc->time_base, ost->st->time_base);
pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base);
if (pkt.duration > 0)
pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base);
if (debug_ts) {
av_log(NULL, AV_LOG_INFO, "encoder -> type:audio "
"pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n",
av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ost->st->time_base),
av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ost->st->time_base));
}
write_frame(s, &pkt, ost);
audio_size += pkt.size;
av_free_packet(&pkt);
static void pre_process_video_frame(InputStream *ist, AVPicture *picture, void **bufp)
{
AVCodecContext *dec;
AVPicture *picture2;
AVPicture picture_tmp;
Michael Niedermayer
committed
dec = ist->st->codec;
/* deinterlace : must be done before any resize */
int size;
/* create temporary picture */
size = avpicture_get_size(dec->pix_fmt, dec->width, dec->height);
buf = av_malloc(size);
if (!buf)
return;
picture2 = &picture_tmp;
avpicture_fill(picture2, buf, dec->pix_fmt, dec->width, dec->height);
if (avpicture_deinterlace(picture2, picture,
dec->pix_fmt, dec->width, dec->height) < 0) {
/* if error, do not deinterlace */
av_log(NULL, AV_LOG_WARNING, "Deinterlacing failed\n");
} else {
picture2 = picture;
}
if (picture != picture2)
*picture = *picture2;
*bufp = buf;
}
static void do_subtitle_out(AVFormatContext *s,
OutputStream *ost,
InputStream *ist,
Fabrice Bellard
committed
AVSubtitle *sub,
int64_t pts)
{
static uint8_t *subtitle_out = NULL;
int subtitle_out_max_size = 1024 * 1024;
Fabrice Bellard
committed
int subtitle_out_size, nb, i;
AVCodecContext *enc;
AVPacket pkt;
if (pts == AV_NOPTS_VALUE) {
av_log(NULL, AV_LOG_ERROR, "Subtitle packets must have a pts\n");
if (exit_on_error)
Fabrice Bellard
committed
return;
}
Michael Niedermayer
committed
enc = ost->st->codec;
Fabrice Bellard
committed
if (!subtitle_out) {
subtitle_out = av_malloc(subtitle_out_max_size);
}
/* Note: DVB subtitle need one packet to draw them and one other
packet to clear them */
/* XXX: signal it in the codec context ? */
if (enc->codec_id == CODEC_ID_DVB_SUBTITLE)
nb = 2;
else
nb = 1;
for (i = 0; i < nb; i++) {
ost->sync_opts = av_rescale_q(pts, ist->st->time_base, enc->time_base);
Reimar Döffinger
committed
sub->pts = av_rescale_q(pts, ist->st->time_base, AV_TIME_BASE_Q);
// start_display_time is required to be 0
sub->pts += av_rescale_q(sub->start_display_time, (AVRational){ 1, 1000 }, AV_TIME_BASE_Q);
sub->end_display_time -= sub->start_display_time;
sub->start_display_time = 0;
subtitle_out_size = avcodec_encode_subtitle(enc, subtitle_out,
Fabrice Bellard
committed
subtitle_out_max_size, sub);
Reimar Döffinger
committed
if (subtitle_out_size < 0) {
av_log(NULL, AV_LOG_FATAL, "Subtitle encoding failed\n");
Reimar Döffinger
committed
}
Fabrice Bellard
committed
av_init_packet(&pkt);
pkt.data = subtitle_out;
pkt.size = subtitle_out_size;
pkt.pts = av_rescale_q(sub->pts, AV_TIME_BASE_Q, ost->st->time_base);
Fabrice Bellard
committed
if (enc->codec_id == CODEC_ID_DVB_SUBTITLE) {
/* XXX: the pts correction is handled here. Maybe handling
it in the codec would be better */
if (i == 0)
pkt.pts += 90 * sub->start_display_time;
else
pkt.pts += 90 * sub->end_display_time;
}
write_frame(s, &pkt, ost);
Fabrice Bellard
committed
}
}
static void do_video_out(AVFormatContext *s,
OutputStream *ost,
AVFrame *in_picture,
float quality)
int ret, format_video_sync;
AVPacket pkt;
AVCodecContext *enc = ost->st->codec;
int nb_frames, i;
Michael Niedermayer
committed
double duration = 0;
InputStream *ist = NULL;
if (ost->source_index >= 0)
ist = input_streams[ost->source_index];
if(ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE && ost->frame_rate.num)
duration = 1/(av_q2d(ost->frame_rate) * av_q2d(enc->time_base));
Michael Niedermayer
committed
sync_ipts = in_picture->pts;
delta = sync_ipts - ost->sync_opts + duration;
Fabrice Bellard
committed
/* by default, we output a single frame */
nb_frames = 1;
format_video_sync = video_sync_method;
if (format_video_sync == VSYNC_AUTO)
format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : 1;
switch (format_video_sync) {
case VSYNC_CFR:
// FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c
else if (delta > 1.1)
nb_frames = lrintf(delta);
break;
case VSYNC_VFR:
if (delta <= -0.6)
nb_frames = 0;
else if (delta > 0.6)
ost->sync_opts = lrint(sync_ipts);
ost->sync_opts = lrint(sync_ipts);
break;
default:
av_assert0(0);
}
nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number);
if (nb_frames == 0) {
nb_frames_drop++;
av_log(NULL, AV_LOG_VERBOSE, "*** drop!\n");
} else if (nb_frames > 1) {
nb_frames_dup += nb_frames - 1;
av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1);
}
duplicate_frame:
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
in_picture->pts = ost->sync_opts;
if (s->oformat->flags & AVFMT_RAWPICTURE &&
enc->codec->id == CODEC_ID_RAWVIDEO) {
/* raw pictures are written as AVPicture structure to
avoid any copies. We support temporarily the older
method. */
enc->coded_frame->interlaced_frame = in_picture->interlaced_frame;
enc->coded_frame->top_field_first = in_picture->top_field_first;
pkt.data = (uint8_t *)in_picture;
pkt.size = sizeof(AVPicture);
pkt.pts = av_rescale_q(in_picture->pts, enc->time_base, ost->st->time_base);
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
pkt.flags |= AV_PKT_FLAG_KEY;
write_frame(s, &pkt, ost);
} else {
int got_packet;
AVFrame big_picture;
big_picture = *in_picture;
/* better than nothing: use input picture interlaced
settings */
big_picture.interlaced_frame = in_picture->interlaced_frame;
if (ost->st->codec->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)) {
if (ost->top_field_first == -1)
big_picture.top_field_first = in_picture->top_field_first;
else
big_picture.top_field_first = !!ost->top_field_first;
}
/* handles same_quant here. This is not correct because it may
not be a global option */
big_picture.quality = quality;
if (!enc->me_threshold)
big_picture.pict_type = 0;
if (ost->forced_kf_index < ost->forced_kf_count &&
big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) {