Newer
Older
1001
1002
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
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
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_video_filters(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;
oldtty = tty;
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
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
# 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;
if (output_streams[i]->output_frame) {
AVFrame *frame = output_streams[i]->output_frame;
if (frame->extended_data != frame->data)
av_freep(&frame->extended_data);
av_freep(&frame);
}
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();
av_freep(&audio_buf);
allocated_audio_buf_size = 0;
av_freep(&async_buf);
allocated_async_buf_size = 0;
avformat_network_deinit();
if (received_sigterm) {
av_log(NULL, AV_LOG_INFO, "Received signal %d: terminating.\n",
(int) received_sigterm);
exit (255);
}
exit(ret); /* not all OS-es handle main() return value */
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
}
}
Michael Niedermayer
committed
static void choose_sample_rate(AVStream *st, AVCodec *codec)
{
if (codec && codec->supported_samplerates) {
const int *p = codec->supported_samplerates;
int best = 0;
int best_dist = INT_MAX;
for (; *p; p++) {
int dist = abs(st->codec->sample_rate - *p);
if (dist < best_dist) {
best_dist = dist;
best = *p;
Michael Niedermayer
committed
}
}
int i;
const int *sample_rates = codec->supported_samplerates;
av_log(st->codec, AV_LOG_WARNING,
"Requested sampling rate (%dHz) unsupported, using %dHz instead\n"
"Available sampling rates for %s:",
st->codec->sample_rate, best, codec->name);
for (i = 0; sample_rates[i]; i++) {
if (!sample_rates[i + 1]) av_log(st->codec, AV_LOG_WARNING, " and");
else if (i) av_log(st->codec, AV_LOG_WARNING, ",");
av_log(st->codec, AV_LOG_WARNING, " %d", sample_rates[i]);
}
av_log(st->codec, AV_LOG_WARNING, ".\n");
st->codec->sample_rate = best;
Michael Niedermayer
committed
}
}
static double
get_sync_ipts(const OutputStream *ost, int64_t pts)
{
OutputFile *of = output_files[ost->file_index];
return (double)(pts - of->start_time) / AV_TIME_BASE;
}
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;
/*
* 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
}
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
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
static void get_default_channel_layouts(OutputStream *ost, InputStream *ist)
{
char layout_name[256];
AVCodecContext *enc = ost->st->codec;
AVCodecContext *dec = ist->st->codec;
if (dec->channel_layout &&
av_get_channel_layout_nb_channels(dec->channel_layout) != dec->channels) {
av_get_channel_layout_string(layout_name, sizeof(layout_name),
dec->channels, dec->channel_layout);
av_log(NULL, AV_LOG_ERROR, "New channel layout (%s) is invalid\n",
layout_name);
dec->channel_layout = 0;
}
if (!dec->channel_layout) {
if (enc->channel_layout && dec->channels == enc->channels) {
dec->channel_layout = enc->channel_layout;
} else {
dec->channel_layout = av_get_default_channel_layout(dec->channels);
if (!dec->channel_layout) {
av_log(NULL, AV_LOG_FATAL, "Unable to find default channel "
"layout for Input Stream #%d.%d\n", ist->file_index,
ist->st->index);
exit_program(1);
}
}
av_get_channel_layout_string(layout_name, sizeof(layout_name),
dec->channels, dec->channel_layout);
av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream "
"#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name);
}
if (!enc->channel_layout) {
if (dec->channels == enc->channels) {
enc->channel_layout = dec->channel_layout;
return;
} else {
enc->channel_layout = av_get_default_channel_layout(enc->channels);
}
if (!enc->channel_layout) {
av_log(NULL, AV_LOG_FATAL, "Unable to find default channel layout "
"for Output Stream #%d.%d\n", ost->file_index,
ost->st->index);
exit_program(1);
}
av_get_channel_layout_string(layout_name, sizeof(layout_name),
enc->channels, enc->channel_layout);
av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Output Stream "
"#%d.%d : %s\n", ost->file_index, ost->st->index, layout_name);
}
}
static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_t size)
{
int fill_char = 0x00;
if (sample_fmt == AV_SAMPLE_FMT_U8)
fill_char = 0x80;
memset(buf, fill_char, size);
}
static int encode_audio_frame(AVFormatContext *s, OutputStream *ost,
const uint8_t *buf, int buf_size)
{
AVCodecContext *enc = ost->st->codec;
AVFrame *frame = NULL;
AVPacket pkt;
int ret, got_packet;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
if (buf && buf_size) {
if (!ost->output_frame) {
ost->output_frame = avcodec_alloc_frame();
if (!ost->output_frame) {
av_log(NULL, AV_LOG_FATAL, "out-of-memory in encode_audio_frame()\n");
exit_program(1);
}
}
frame = ost->output_frame;
if (frame->extended_data != frame->data)
av_freep(&frame->extended_data);
avcodec_get_frame_defaults(frame);
frame->nb_samples = buf_size /
(enc->channels * av_get_bytes_per_sample(enc->sample_fmt));
if ((ret = avcodec_fill_audio_frame(frame, enc->channels, enc->sample_fmt,
buf, buf_size, 1)) < 0) {
Michael Niedermayer
committed
av_log(NULL, AV_LOG_FATAL, "Audio encoding failed (avcodec_fill_audio_frame)\n");
Michael Niedermayer
committed
}
frame->pts = ost->sync_opts;
ost->sync_opts += frame->nb_samples;
Michael Niedermayer
committed
}
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);
if (pkt.dts != AV_NOPTS_VALUE) {
int64_t max = ost->st->cur_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT);
pkt.dts = av_rescale_q(pkt.dts, enc->time_base, ost->st->time_base);
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;
}
}
if (pkt.duration > 0)
pkt.duration = av_rescale_q(pkt.duration, enc->time_base, ost->st->time_base);
write_frame(s, &pkt, ost);
audio_size += pkt.size;
av_free_packet(&pkt);
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));
}
static int alloc_audio_output_buf(AVCodecContext *dec, AVCodecContext *enc,
{
int64_t audio_buf_samples;
int audio_buf_size;
/* calculate required number of samples to allocate */
audio_buf_samples = ((int64_t)nb_samples * enc->sample_rate + dec->sample_rate) /
dec->sample_rate;
audio_buf_samples = 4 * audio_buf_samples + 10000; // safety factors for resampling
audio_buf_samples = FFMAX(audio_buf_samples, enc->frame_size);
if (audio_buf_samples > INT_MAX)
return AVERROR(EINVAL);
audio_buf_size = av_samples_get_buffer_size(buf_linesize, enc->channels,
audio_buf_samples,
if (audio_buf_size < 0)
return audio_buf_size;
av_fast_malloc(&audio_buf, &allocated_audio_buf_size, audio_buf_size);
if (!audio_buf)
return AVERROR(ENOMEM);
return 0;
}
static void do_audio_out(AVFormatContext *s, OutputStream *ost,
InputStream *ist, AVFrame *decoded_frame)
Sylvain Corré
committed
int frame_bytes, resample_changed, ret;
AVCodecContext *enc = ost->st->codec;
AVCodecContext *dec = ist->st->codec;
Justin Ruggles
committed
int osize = av_get_bytes_per_sample(enc->sample_fmt);
int isize = av_get_bytes_per_sample(dec->sample_fmt);
uint8_t *buf[AV_NUM_DATA_POINTERS];
int size = decoded_frame->nb_samples * dec->channels * isize;
int planes = av_sample_fmt_is_planar(dec->sample_fmt) ? dec->channels : 1;
int i;
int out_linesize = 0;
int buf_linesize = decoded_frame->linesize[0];
av_assert0(planes <= AV_NUM_DATA_POINTERS);
for(i=0; i<planes; i++)
buf[i]= decoded_frame->data[i];
Michael Niedermayer
committed
get_default_channel_layouts(ost, ist);
if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples, &out_linesize) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
Sylvain Corré
committed
if (audio_sync_method > 1 ||
enc->channels != dec->channels ||
enc->channel_layout != dec->channel_layout ||
enc->sample_rate != dec->sample_rate ||
dec->sample_fmt != enc->sample_fmt)
ost->audio_resample = 1;
resample_changed = ost->resample_sample_fmt != dec->sample_fmt ||
ost->resample_channels != dec->channels ||
ost->resample_channel_layout != dec->channel_layout ||
ost->resample_sample_rate != dec->sample_rate;
if ((ost->audio_resample && !ost->swr) || resample_changed || ost->audio_channels_mapped) {
if (resample_changed) {
av_log(NULL, AV_LOG_INFO, "Input stream #%d:%d frame changed from rate:%d fmt:%s ch:%d chl:0x%"PRIx64" to rate:%d fmt:%s ch:%d chl:0x%"PRIx64"\n",
ist->file_index, ist->st->index,
ost->resample_sample_rate, av_get_sample_fmt_name(ost->resample_sample_fmt),
ost->resample_channels, ost->resample_channel_layout,
dec->sample_rate, av_get_sample_fmt_name(dec->sample_fmt),
dec->channels, dec->channel_layout);
ost->resample_sample_fmt = dec->sample_fmt;
ost->resample_channels = dec->channels;
ost->resample_channel_layout = dec->channel_layout;
ost->resample_sample_rate = dec->sample_rate;
}
/* if audio_sync_method is >1 the resampler is needed for audio drift compensation */
if (audio_sync_method <= 1 && !ost->audio_channels_mapped &&
ost->resample_sample_fmt == enc->sample_fmt &&
ost->resample_channels == enc->channels &&
ost->resample_channel_layout == enc->channel_layout &&
ost->resample_sample_rate == enc->sample_rate) {
ost->audio_resample = 0;
} else {
ost->swr = swr_alloc_set_opts(ost->swr,
enc->channel_layout, enc->sample_fmt, enc->sample_rate,
dec->channel_layout, dec->sample_fmt, dec->sample_rate,
0, NULL);
av_opt_set_int(ost->swr, "dither_method", ost->swr_dither_method,0);
av_opt_set_double(ost->swr, "dither_scale", ost->swr_dither_scale,0);
if (ost->audio_channels_mapped)
swr_set_channel_mapping(ost->swr, ost->audio_channels_map);
av_opt_set_double(ost->swr, "rmvol", ost->rematrix_volume, 0);
av_opt_set_int(ost->swr, "icl", av_get_default_channel_layout(ost->audio_channels_mapped), 0);
av_opt_set_int(ost->swr, "uch", ost->audio_channels_mapped, 0);
if (av_opt_set_int(ost->swr, "ich", dec->channels, 0) < 0) {
av_log(NULL, AV_LOG_FATAL, "Unsupported number of input channels\n");
exit_program(1);
}
if (av_opt_set_int(ost->swr, "och", enc->channels, 0) < 0) {
av_log(NULL, AV_LOG_FATAL, "Unsupported number of output channels\n");
exit_program(1);
}
if(audio_sync_method>1) av_opt_set_int(ost->swr, "flags", SWR_FLAG_RESAMPLE, 0);
av_log(NULL, AV_LOG_FATAL, "swr_init() failed\n");
swr_free(&ost->swr);
}
if (!ost->swr) {
av_log(NULL, AV_LOG_FATAL, "Can not resample %d channels @ %d Hz to %d channels @ %d Hz\n",
dec->channels, dec->sample_rate,
enc->channels, enc->sample_rate);
}
av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt);
if (audio_sync_method > 0) {
double delta = get_sync_ipts(ost, ist->pts) * enc->sample_rate - ost->sync_opts -
av_fifo_size(ost->fifo) / (enc->channels * osize);
int idelta = delta * dec->sample_rate / enc->sample_rate;
int byte_delta = idelta * isize * dec->channels;
// FIXME resample delay
if (fabs(delta) > 50) {
if (ist->is_start || fabs(delta) > audio_drift_threshold*enc->sample_rate) {
if (byte_delta < 0) {
byte_delta = FFMAX(byte_delta, -size);
for (i=0; i<planes; i++)
buf[i] -= byte_delta/planes;
av_log(NULL, AV_LOG_VERBOSE, "discarding %d audio samples\n",
-byte_delta / (isize * dec->channels));
ist->is_start = 0;
} else {
av_fast_malloc(&async_buf, &allocated_async_buf_size,
byte_delta + size);
if (!async_buf) {
av_log(NULL, AV_LOG_FATAL, "Out of memory in do_audio_out\n");
exit_program(1);
}
if (alloc_audio_output_buf(dec, enc, decoded_frame->nb_samples + idelta, &out_linesize) < 0) {
av_log(NULL, AV_LOG_FATAL, "Error allocating audio buffer\n");
exit_program(1);
uint8_t *t = async_buf + i*((byte_delta + size)/planes);
generate_silence(t, dec->sample_fmt, byte_delta/planes);
memcpy(t + byte_delta/planes, buf[i], size/planes);
buf[i] = t;
}
av_log(NULL, AV_LOG_VERBOSE, "adding %d audio samples of silence\n", idelta);
} else if (audio_sync_method > 1) {
int comp = av_clip(delta, -audio_sync_method, audio_sync_method);
av_log(NULL, AV_LOG_VERBOSE, "compensating audio timestamp drift:%f compensation:%d in:%d\n",
delta, comp, enc->sample_rate);
Michael Niedermayer
committed
// fprintf(stderr, "drift:%f len:%d opts:%"PRId64" ipts:%"PRId64" fifo:%d\n", delta, -1, ost->sync_opts, (int64_t)(get_sync_ipts(ost) * enc->sample_rate), av_fifo_size(ost->fifo)/(ost->st->codec->channels * 2));
Marton Balint
committed
swr_set_compensation(ost->swr, comp, enc->sample_rate);
} else if (audio_sync_method == 0)
ost->sync_opts = lrintf(get_sync_ipts(ost, ist->pts) * enc->sample_rate) -
av_fifo_size(ost->fifo) / (enc->channels * osize); // FIXME wrong
if (ost->audio_resample || ost->audio_channels_mapped) {
size_out = swr_convert(ost->swr, ( uint8_t*[]){buftmp},
allocated_audio_buf_size / (enc->channels * osize),
buf,
if (size_out < 0) {
av_log(NULL, AV_LOG_FATAL, "swr_convert failed\n");
exit_program(1);
}
size_out = size_out * enc->channels * osize;
av_assert0(ost->audio_resample || dec->sample_fmt==enc->sample_fmt);
if (!(enc->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)) {
Michael Niedermayer
committed
if (av_fifo_realloc2(ost->fifo, av_fifo_size(ost->fifo) + size_out) < 0) {
av_log(NULL, AV_LOG_FATAL, "av_fifo_realloc2() failed\n");
Michael Niedermayer
committed
av_fifo_generic_write(ost->fifo, buftmp, size_out, NULL);
frame_bytes = enc->frame_size * osize * enc->channels;
Michael Niedermayer
committed
while (av_fifo_size(ost->fifo) >= frame_bytes) {
av_fifo_generic_read(ost->fifo, audio_buf, frame_bytes, NULL);
encode_audio_frame(s, ost, audio_buf, frame_bytes);
encode_audio_frame(s, ost, buftmp, size_out);
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
}
}
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
static double psnr(double d)
{
return -10.0 * log(d) / log(10.0);
}
static void do_video_stats(AVFormatContext *os, OutputStream *ost,
int frame_size)
{
AVCodecContext *enc;
int frame_number;
double ti1, bitrate, avg_bitrate;
/* this is executed just the first time do_video_stats is called */
if (!vstats_file) {
vstats_file = fopen(vstats_filename, "w");
if (!vstats_file) {
perror("fopen");
exit_program(1);
}
}
enc = ost->st->codec;
if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {
frame_number = ost->frame_number;
fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, enc->coded_frame->quality / (float)FF_QP2LAMBDA);
if (enc->flags&CODEC_FLAG_PSNR)
fprintf(vstats_file, "PSNR= %6.2f ", psnr(enc->coded_frame->error[0] / (enc->width * enc->height * 255.0 * 255.0)));
fprintf(vstats_file,"f_size= %6d ", frame_size);
/* compute pts value */
ti1 = ost->sync_opts * av_q2d(enc->time_base);
if (ti1 < 0.01)
ti1 = 0.01;
bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0;
avg_bitrate = (double)(video_size * 8) / ti1 / 1000.0;
fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
(double)video_size / 1024, ti1, bitrate, avg_bitrate);
fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(enc->coded_frame->pict_type));
}
}
static void do_video_out(AVFormatContext *s, OutputStream *ost,
AVFrame *in_picture, float quality)
int nb_frames, i, ret, format_video_sync;
AVCodecContext *enc;
Michael Niedermayer
committed
double duration = 0;
InputStream *ist = NULL;
if (ost->source_index >= 0)
ist = input_streams[ost->source_index];
Michael Niedermayer
committed
enc = ost->st->codec;
if (ist && ist->st->start_time != AV_NOPTS_VALUE && ist->st->first_dts != AV_NOPTS_VALUE) {
Michael Niedermayer
committed
duration = FFMAX(av_q2d(ist->st->time_base), av_q2d(ist->st->codec->time_base));
if(ist->st->r_frame_rate.num)
duration= FFMAX(duration, 1/av_q2d(ist->st->r_frame_rate));
if(ist->st->avg_frame_rate.num && 0)
Michael Niedermayer
committed
duration= FFMAX(duration, 1/av_q2d(ist->st->avg_frame_rate));
duration /= av_q2d(enc->time_base);
}
sync_ipts = get_sync_ipts(ost, in_picture->pts) / av_q2d(enc->time_base);
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 = lrintf(sync_ipts);
break;
ost->sync_opts = lrintf(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);
}
for (i = 0; i < nb_frames; i++) {
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
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(ost->sync_opts, enc->time_base, ost->st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;
write_frame(s, &pkt, ost);
} else {
Michael Niedermayer
committed
/* 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;