Newer
Older
}
}
}
}
if (pkt.dts != AV_NOPTS_VALUE)
ifile->last_ts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q);
if (debug_ts) {
Stefano Sabatini
committed
av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n",
Michael Niedermayer
committed
ifile->ist_index + pkt.stream_index, av_get_media_type_string(ist->dec_ctx->codec_type),
av_ts2str(pkt.pts), av_ts2timestr(pkt.pts, &ist->st->time_base),
av_ts2str(pkt.dts), av_ts2timestr(pkt.dts, &ist->st->time_base),
av_ts2str(input_files[ist->file_index]->ts_offset),
av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q));
sub2video_heartbeat(ist, pkt.pts);
process_input_packet(ist, &pkt, 0);
av_packet_unref(&pkt);
/**
* Perform a step of transcoding for the specified filter graph.
*
* @param[in] graph filter graph to consider
* @param[out] best_ist input stream where a frame would allow to continue
* @return 0 for success, <0 for error
*/
static int transcode_from_filter(FilterGraph *graph, InputStream **best_ist)
{
int i, ret;
int nb_requests, nb_requests_max = 0;
InputFilter *ifilter;
InputStream *ist;
*best_ist = NULL;
ret = avfilter_graph_request_oldest(graph->graph);
if (ret >= 0)
if (ret == AVERROR_EOF) {
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
for (i = 0; i < graph->nb_outputs; i++)
close_output_stream(graph->outputs[i]->ost);
return ret;
}
if (ret != AVERROR(EAGAIN))
return ret;
for (i = 0; i < graph->nb_inputs; i++) {
ifilter = graph->inputs[i];
ist = ifilter->ist;
if (input_files[ist->file_index]->eagain ||
input_files[ist->file_index]->eof_reached)
continue;
nb_requests = av_buffersrc_get_nb_failed_requests(ifilter->filter);
if (nb_requests > nb_requests_max) {
nb_requests_max = nb_requests;
*best_ist = ist;
}
}
if (!*best_ist)
for (i = 0; i < graph->nb_outputs; i++)
graph->outputs[i]->ost->unavailable = 1;
return 0;
}
/**
* Run a single step of transcoding.
*
* @return 0 for success, <0 for error
*/
static int transcode_step(void)
{
OutputStream *ost;
InputStream *ist;
int ret;
ost = choose_output();
if (!ost) {
if (got_eagain()) {
reset_eagain();
av_usleep(10000);
return 0;
}
av_log(NULL, AV_LOG_VERBOSE, "No more inputs to read from, finishing.\n");
return AVERROR_EOF;
}
if (ost->filter) {
if ((ret = transcode_from_filter(ost->filter->graph, &ist)) < 0)
return ret;
if (!ist)
return 0;
} else {
av_assert0(ost->source_index >= 0);
ist = input_streams[ost->source_index];
}
ret = process_input(ist->file_index);
if (ret == AVERROR(EAGAIN)) {
if (input_files[ist->file_index]->eagain)
ost->unavailable = 1;
return 0;
}
if (ret < 0)
return ret == AVERROR_EOF ? 0 : ret;
/*
* The following code is the main loop of the file converter
*/
static int transcode(void)
Fabrice Bellard
committed
{
int ret, i;
InputStream *ist;
int64_t timer_start;
int64_t total_packets_written = 0;
ret = transcode_init();
if (ret < 0)
goto fail;
if (stdin_interaction) {
av_log(NULL, AV_LOG_INFO, "Press [q] to stop, [?] for help\n");
timer_start = av_gettime_relative();
if ((ret = init_input_threads()) < 0)
goto fail;
#endif
int64_t cur_time= av_gettime_relative();
/* if 'q' pressed, exits */
if (stdin_interaction)
if (check_keyboard_interaction(cur_time) < 0)
break;
/* check if there's any stream where output is still needed */
if (!need_output()) {
av_log(NULL, AV_LOG_VERBOSE, "No more output streams to write to, finishing.\n");
ret = transcode_step();
if (ret < 0 && ret != AVERROR_EOF) {
char errbuf[128];
av_strerror(ret, errbuf, sizeof(errbuf));
av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", errbuf);
break;
Michael Niedermayer
committed
}
/* dump report by using the output first video and audio streams */
print_report(0, timer_start, cur_time);
/* at the end of stream, we must flush the decoder buffers */
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
if (!input_files[ist->file_index]->eof_reached && ist->decoding_needed) {
process_input_packet(ist, NULL, 0);
Fabrice Bellard
committed
}
flush_encoders();
Fabrice Bellard
committed
/* write the trailer if needed and close file */
os = output_files[i]->ctx;
if ((ret = av_write_trailer(os)) < 0) {
av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s", os->filename, av_err2str(ret));
if (exit_on_error)
exit_program(1);
/* dump report by using the first video and audio streams */
print_report(1, timer_start, av_gettime_relative());
/* close each encoder */
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
if (ost->encoding_needed) {
av_freep(&ost->enc_ctx->stats_in);
total_packets_written += ost->packets_written;
}
if (!total_packets_written && (abort_on_flags & ABORT_ON_FLAG_EMPTY_OUTPUT)) {
av_log(NULL, AV_LOG_FATAL, "Empty output\n");
exit_program(1);
/* close each decoder */
for (i = 0; i < nb_input_streams; i++) {
ist = input_streams[i];
if (ist->decoding_needed) {
avcodec_close(ist->dec_ctx);
ist->hwaccel_uninit(ist->dec_ctx);
av_buffer_unref(&hw_device_ctx);
/* finished ! */
ret = 0;
fail:
if (output_streams) {
for (i = 0; i < nb_output_streams; i++) {
ost = output_streams[i];
if (ost) {
if (ost->logfile) {
if (fclose(ost->logfile))
av_log(NULL, AV_LOG_ERROR,
"Error closing logfile, loss of information possible: %s\n",
av_err2str(AVERROR(errno)));
av_freep(&ost->forced_kf_pts);
Michael Niedermayer
committed
av_freep(&ost->apad);
av_freep(&ost->disposition);
av_dict_free(&ost->encoder_opts);
Michael Niedermayer
committed
av_dict_free(&ost->sws_dict);
Michael Niedermayer
committed
av_dict_free(&ost->swr_opts);
av_dict_free(&ost->resample_opts);
static int64_t getutime(void)
#if HAVE_GETRUSAGE
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return (rusage.ru_utime.tv_sec * 1000000LL) + rusage.ru_utime.tv_usec;
#elif HAVE_GETPROCESSTIMES
HANDLE proc;
FILETIME c, e, k, u;
proc = GetCurrentProcess();
GetProcessTimes(proc, &c, &e, &k, &u);
return ((int64_t) u.dwHighDateTime << 32 | u.dwLowDateTime) / 10;
#else
return av_gettime_relative();
static int64_t getmaxrss(void)
{
#if HAVE_GETRUSAGE && HAVE_STRUCT_RUSAGE_RU_MAXRSS
struct rusage rusage;
getrusage(RUSAGE_SELF, &rusage);
return (int64_t)rusage.ru_maxrss * 1024;
#elif HAVE_GETPROCESSMEMORYINFO
HANDLE proc;
PROCESS_MEMORY_COUNTERS memcounters;
proc = GetCurrentProcess();
memcounters.cb = sizeof(memcounters);
GetProcessMemoryInfo(proc, &memcounters, sizeof(memcounters));
return memcounters.PeakPagefileUsage;
#else
return 0;
#endif
}
static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl)
{
}
Hendrik Leppkes
committed
init_dynload();
register_exit(ffmpeg_cleanup);
setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */
av_log_set_flags(AV_LOG_SKIP_REPEATED);
parse_loglevel(argc, argv, options);
if(argc>1 && !strcmp(argv[1], "-d")){
run_as_daemon=1;
av_log_set_callback(log_callback_null);
argc--;
argv++;
}
#if CONFIG_AVDEVICE
avformat_network_init();
show_banner(argc, argv, options);
/* parse options and open all input/output files */
ret = ffmpeg_parse_options(argc, argv);
if (nb_output_files <= 0 && nb_input_files == 0) {
av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
/* file converter / grab */
if (nb_output_files <= 0) {
av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
// if (nb_input_files == 0) {
// av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n");
// exit_program(1);
if (transcode() < 0)
ti = getutime() - ti;
if (do_benchmark) {
av_log(NULL, AV_LOG_INFO, "bench: utime=%0.3fs\n", ti / 1000000.0);
av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",
decode_error_stat[0], decode_error_stat[1]);
Michael Niedermayer
committed
if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1])
Michael Niedermayer
committed
exit_program(received_nb_signals ? 255 : main_return_code);
return main_return_code;